// // // // // $Revision$ // using ICSharpCode.WpfDesign.Designer.OutlineView; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using System.Windows.Forms; using System.Windows.Forms.Integration; using System.Windows.Markup; using System.Xml; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.WpfDesign.Designer; using ICSharpCode.WpfDesign.Designer.PropertyGrid; using ICSharpCode.WpfDesign.Designer.Services; using ICSharpCode.WpfDesign.Designer.Xaml; using ICSharpCode.WpfDesign.PropertyGrid; namespace ICSharpCode.WpfDesign.AddIn { /// /// IViewContent implementation that hosts the WPF designer. /// public class WpfViewContent : AbstractViewContentHandlingLoadErrors, IHasPropertyContainer, IToolsHost { public WpfViewContent(OpenedFile file) : base(file) { BasicMetadata.Register(); this.TabPageText = "${res:FormsDesigner.DesignTabPages.DesignTabPage}"; this.IsActiveViewContentChanged += OnIsActiveViewContentChanged; this.editor = file.RegisteredViewContents[0] as TextEditorDisplayBindingWrapper; } ElementHost wpfHost; DesignSurface designer; List tasks = new List(); // save text from editor when designer cannot be saved (e.g. invalid xml) TextEditorDisplayBindingWrapper editor; public DesignSurface DesignSurface { get { return designer; } } public DesignContext DesignContext { get { return designer.DesignContext; } } protected override void LoadInternal(OpenedFile file, System.IO.Stream stream) { Debug.Assert(file == this.PrimaryFile); if (designer == null) { // initialize designer on first load DragDropExceptionHandler.HandleException = ICSharpCode.Core.MessageService.ShowError; designer = new DesignSurface(); wpfHost = new SharpDevelopElementHost(this, designer); this.UserControl = wpfHost; InitPropertyEditor(); } if (outline != null) { outline.Root = null; } using (XmlTextReader r = new XmlTextReader(stream)) { XamlLoadSettings settings = new XamlLoadSettings(); settings.DesignerAssemblies.Add(typeof(WpfViewContent).Assembly); settings.CustomServiceRegisterFunctions.Add( delegate(XamlDesignContext context) { context.Services.AddService(typeof(IUriContext), new FileUriContext(this.PrimaryFile)); context.Services.AddService(typeof(IPropertyDescriptionService), new PropertyDescriptionService(this.PrimaryFile)); context.Services.AddService(typeof(IEventHandlerService), new CSharpEventHandlerService(this)); context.Services.AddService(typeof(ITopLevelWindowService), new WpfAndWinFormsTopLevelWindowService()); context.Services.AddService(typeof(ChooseClassServiceBase), new IdeChooseClassService()); }); settings.TypeFinder = MyTypeFinder.Create(this.PrimaryFile); designer.LoadDesigner(r, settings); UpdateTasks(); if (outline != null && designer.DesignContext != null && designer.DesignContext.RootItem != null) { outline.Root = OutlineNode.Create(designer.DesignContext.RootItem); } propertyGridView.PropertyGrid.SelectedItems = null; designer.DesignContext.Services.Selection.SelectionChanged += OnSelectionChanged; designer.DesignContext.Services.GetService().UndoStackChanged += OnUndoStackChanged; } } protected override void SaveInternal(OpenedFile file, System.IO.Stream stream) { if (designer.DesignContext.CanSave) { XmlWriterSettings settings = new XmlWriterSettings(); settings.Encoding = Encoding.UTF8; settings.Indent = true; settings.IndentChars = ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.SharpDevelopTextEditorProperties.Instance.IndentationString; settings.NewLineOnAttributes = true; using (XmlWriter xmlWriter = XmlTextWriter.Create(stream, settings)) { designer.SaveDesigner(xmlWriter); } } else { editor.Save(file, stream); } } public override bool SupportsSwitchFromThisWithoutSaveLoad(OpenedFile file, IViewContent newView) { return newView == editor && !designer.DesignContext.CanSave; } void UpdateTasks() { foreach (var task in tasks) { TaskService.Remove(task); } tasks.Clear(); var xamlErrorService = designer.DesignContext.Services.GetService(); foreach (var error in xamlErrorService.Errors) { var task = new Task(PrimaryFile.FileName, error.Message, error.Column - 1, error.Line - 1, TaskType.Error); tasks.Add(task); TaskService.Add(task); } } void OnUndoStackChanged(object sender, EventArgs e) { this.PrimaryFile.MakeDirty(); } #region Property editor / SelectionChanged ElementHost propertyEditorHost; PropertyGridView propertyGridView; void InitPropertyEditor() { propertyGridView = new PropertyGridView(); propertyEditorHost = new SharpDevelopElementHost(this, propertyGridView); propertyContainer.PropertyGridReplacementControl = propertyEditorHost; } ICollection oldItems = new DesignItem[0]; void OnSelectionChanged(object sender, DesignItemCollectionEventArgs e) { ISelectionService selectionService = designer.DesignContext.Services.Selection; ICollection items = selectionService.SelectedItems; if (!IsCollectionWithSameElements(items, oldItems)) { propertyGridView.PropertyGrid.SelectedItems = items; oldItems = items; } } static bool IsCollectionWithSameElements(ICollection a, ICollection b) { return ContainsAll(a, b) && ContainsAll(b, a); } static bool ContainsAll(ICollection a, ICollection b) { foreach (DesignItem item in a) { if (!b.Contains(item)) return false; } return true; } PropertyContainer propertyContainer = new PropertyContainer(); public PropertyContainer PropertyContainer { get { return propertyContainer; } } #endregion public Control ToolsControl { get { return WpfToolbox.Instance.ToolboxControl; } } public override void Dispose() { propertyContainer.Clear(); base.Dispose(); } void OnIsActiveViewContentChanged(object sender, EventArgs e) { if (IsActiveViewContent) { if (designer != null && designer.DesignContext != null) { WpfToolbox.Instance.ToolService = designer.DesignContext.Services.Tool; } } } Outline outline; public Outline Outline { get { if (outline == null) { outline = new Outline(); if (DesignSurface != null && DesignSurface.DesignContext != null && DesignSurface.DesignContext.RootItem != null) { outline.Root = OutlineNode.Create(DesignSurface.DesignContext.RootItem); } } return outline; } } } }