📄 abstractdesignergenerator.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision: 1431 $</version>
// </file>
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Reflection;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.CodeDom;
using System.CodeDom.Compiler;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
using ICSharpCode.Core;
using ICSharpCode.TextEditor.Document;
namespace ICSharpCode.FormsDesigner
{
public abstract class AbstractDesignerGenerator : IDesignerGenerator
{
/// <summary>The currently open part of the class being designed.</summary>
IClass c;
/// <summary>The complete class being designed.</summary>
IClass completeClass;
/// <summary>The class part containing the designer code.</summary>
IClass formClass;
IMethod initializeComponents;
FormsDesignerViewContent viewContent;
bool failedDesignerInitialize = false;
CodeDomProvider provider;
public CodeDomProvider CodeDomProvider {
get {
if (this.provider == null) {
this.provider = this.CreateCodeProvider();
}
return this.provider;
}
}
public void Attach(FormsDesignerViewContent viewContent)
{
this.viewContent = viewContent;
}
public void Detach()
{
this.viewContent = null;
}
/// <summary>
/// Removes the field declaration with the specified name from the source file.
/// </summary>
void RemoveField(string fieldName)
{
try {
LoggingService.Info("Remove field declaration: "+fieldName);
Reparse();
IField field = GetField(formClass, fieldName);
if (field != null) {
int startOffset = document.PositionToOffset(new Point(0, field.Region.BeginLine - 1));
int endOffset = document.PositionToOffset(new Point(0, field.Region.EndLine));
document.Remove(startOffset, endOffset - startOffset);
} else if ((field = GetField(completeClass, fieldName)) != null) {
// TODO: Remove the field in the part where it is declared
LoggingService.Warn("Removing field declaration in non-designer part currently not supported");
}
SaveDocument();
} catch (Exception ex) {
MessageService.ShowError(ex);
}
}
protected virtual string GenerateFieldDeclaration(CodeDOMGenerator domGenerator, CodeMemberField field)
{
StringWriter writer = new StringWriter();
domGenerator.ConvertContentDefinition(field, writer);
return writer.ToString().Trim();
}
/// <summary>
/// Contains the tabs in front of the InitializeComponents declaration.
/// Used to indent the fields and generated statements.
/// </summary>
protected string tabs;
/// <summary>
/// Adds the declaration for the specified field to the source file
/// or replaces the already present declaration for a field with the same name.
/// </summary>
/// <param name="domGenerator">The CodeDOMGenerator used to generate the field declaration.</param>
/// <param name="newField">The CodeDom field to be added or replaced.</param>
void AddOrReplaceField(CodeDOMGenerator domGenerator, CodeMemberField newField)
{
try {
Reparse();
IField oldField = GetField(formClass, newField.Name);
if (oldField != null) {
int startOffset = document.PositionToOffset(new Point(0, oldField.Region.BeginLine - 1));
int endOffset = document.PositionToOffset(new Point(0, oldField.Region.EndLine));
document.Replace(startOffset, endOffset - startOffset, tabs + GenerateFieldDeclaration(domGenerator, newField) + Environment.NewLine);
} else {
if ((oldField = GetField(completeClass, newField.Name)) != null) {
// TODO: Replace the field in the part where it is declared
LoggingService.Warn("Field declaration replacement in non-designer part currently not supported");
} else {
int endOffset = document.PositionToOffset(new Point(0, initializeComponents.BodyRegion.EndLine));
document.Insert(endOffset, tabs + GenerateFieldDeclaration(domGenerator, newField) + Environment.NewLine);
}
}
SaveDocument();
} catch (Exception ex) {
MessageService.ShowError(ex);
}
}
protected abstract System.CodeDom.Compiler.CodeDomProvider CreateCodeProvider();
protected abstract DomRegion GetReplaceRegion(ICSharpCode.TextEditor.Document.IDocument document, IMethod method);
protected virtual void FixGeneratedCode(IClass formClass, CodeMemberMethod code)
{
}
public void MergeFormChanges(CodeCompileUnit unit)
{
Reparse();
// find InitializeComponent method and the class it is declared in
CodeTypeDeclaration formClass = null;
CodeMemberMethod initializeComponent = null;
foreach (CodeNamespace n in unit.Namespaces) {
foreach (CodeTypeDeclaration typeDecl in n.Types) {
foreach (CodeTypeMember m in typeDecl.Members) {
if (m is CodeMemberMethod && m.Name == "InitializeComponent") {
formClass = typeDecl;
initializeComponent = (CodeMemberMethod)m;
break;
}
}
}
}
if (formClass == null || initializeComponent == null) {
throw new InvalidOperationException("InitializeComponent method not found in framework-generated CodeDom.");
}
if (this.formClass == null) {
MessageService.ShowMessage("Cannot save form: InitializeComponent method does not exist anymore. You should not modify the Designer.cs file while editing a form.");
return;
}
if (formClass.Name != this.formClass.Name) {
LoggingService.Info("Renaming form to " + formClass.Name);
ICSharpCode.SharpDevelop.DefaultEditor.Commands.ClassBookmarkMenuBuilder.RenameClass(this.formClass, formClass.Name);
Reparse();
}
FixGeneratedCode(this.formClass, initializeComponent);
// generate file and get initialize components string
StringWriter writer = new StringWriter();
CodeDOMGenerator domGenerator = new CodeDOMGenerator(this.CodeDomProvider, tabs + '\t');
domGenerator.ConvertContentDefinition(initializeComponent, writer);
string statements = writer.ToString();
// initializeComponents.BodyRegion.BeginLine + 1
DomRegion bodyRegion = GetReplaceRegion(document, initializeComponents);
if (bodyRegion.BeginColumn <= 0 || bodyRegion.EndColumn <= 0)
throw new InvalidOperationException("Column must be > 0");
int startOffset = document.PositionToOffset(new Point(bodyRegion.BeginColumn - 1, bodyRegion.BeginLine - 1));
int endOffset = document.PositionToOffset(new Point(bodyRegion.EndColumn - 1, bodyRegion.EndLine - 1));
document.Replace(startOffset, endOffset - startOffset, statements);
SaveDocument();
// apply changes the designer made to field declarations
// first loop looks for added and changed fields
foreach (CodeTypeMember m in formClass.Members) {
if (m is CodeMemberField) {
CodeMemberField newField = (CodeMemberField)m;
IField oldField = GetField(completeClass, newField.Name);
if (oldField == null || FieldChanged(oldField, newField)) {
AddOrReplaceField(domGenerator, newField);
}
}
}
// second loop looks for removed fields
List<string> removedFields = new List<string>();
foreach (IField field in completeClass.Fields) {
bool found = false;
foreach (CodeTypeMember m in formClass.Members) {
if (m is CodeMemberField && m.Name == field.Name) {
found = true;
break;
}
}
if (!found) {
removedFields.Add(field.Name);
}
}
// removing fields is done in two steps because
// we must not modify the c.Fields collection while it is enumerated
removedFields.ForEach(RemoveField);
ParserService.EnqueueForParsing(designerFile, document.TextContent);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -