// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Markup; using System.Xml; using ICSharpCode.Core.Presentation; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Workbench; using ICSharpCode.WpfDesign.Designer; using ICSharpCode.WpfDesign.Designer.OutlineView; using ICSharpCode.WpfDesign.Designer.PropertyGrid; using ICSharpCode.WpfDesign.Designer.Services; using ICSharpCode.WpfDesign.Designer.Xaml; namespace ICSharpCode.WpfDesign.AddIn { /// /// IViewContent implementation that hosts the WPF designer. /// public class WpfViewContent : AbstractViewContentHandlingLoadErrors, IHasPropertyContainer, IToolsHost, IOutlineContentHost { public WpfViewContent(OpenedFile file) : base(file) { BasicMetadata.Register(); this.TabPageText = "${res:FormsDesigner.DesignTabPages.DesignTabPage}"; this.IsActiveViewContentChanged += OnIsActiveViewContentChanged; } static WpfViewContent() { DragDropExceptionHandler.UnhandledException += delegate(object sender, ThreadExceptionEventArgs e) { ICSharpCode.Core.MessageService.ShowException(e.Exception); }; } DesignSurface designer; List tasks = new List(); public DesignSurface DesignSurface { get { return designer; } } public DesignContext DesignContext { get { return designer.DesignContext; } } protected override void LoadInternal(OpenedFile file, System.IO.Stream stream) { wasChangedInDesigner = false; Debug.Assert(file == this.PrimaryFile); _stream = new MemoryStream(); stream.CopyTo(_stream); stream.Position = 0; if (designer == null) { // initialize designer on first load designer = new DesignSurface(); this.UserContent = designer; InitPropertyEditor(); } this.UserContent = designer; 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 SharpDevelopEventHandlerService(this)); context.Services.AddService(typeof(ITopLevelWindowService), new WpfAndWinFormsTopLevelWindowService()); context.Services.AddService(typeof(ChooseClassServiceBase), new IdeChooseClassService()); }); settings.TypeFinder = MyTypeFinder.Create(this.PrimaryFile); try { settings.ReportErrors = UpdateTasks; designer.LoadDesigner(r, settings); designer.ContextMenuOpening += (sender, e) => MenuService.ShowContextMenu(e.OriginalSource as UIElement, designer, "/AddIns/WpfDesign/Designer/ContextMenu"); 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; } catch (Exception e) { this.UserContent = new WpfDocumentError(e); } } } private MemoryStream _stream; bool wasChangedInDesigner; protected override void SaveInternal(OpenedFile file, System.IO.Stream stream) { if (wasChangedInDesigner && designer.DesignContext != null) { XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = SD.EditorControlService.GlobalOptions.IndentationString; settings.NewLineOnAttributes = true; using (XmlWriter xmlWriter = XmlWriter.Create(stream, settings)) { designer.SaveDesigner(xmlWriter); } } else { _stream.Position = 0; using (var reader = new StreamReader(new UnclosableStream(_stream))) { using (var writer = new StreamWriter(stream)) { writer.Write(reader.ReadToEnd()); } } } } void UpdateTasks(XamlErrorService xamlErrorService) { Debug.Assert(xamlErrorService != null); foreach (SDTask task in tasks) { TaskService.Remove(task); } tasks.Clear(); foreach (XamlError error in xamlErrorService.Errors) { var task = new SDTask(PrimaryFile.FileName, error.Message, error.Column - 1, error.Line - 1, TaskType.Error); tasks.Add(task); TaskService.Add(task); } if (xamlErrorService.Errors.Count != 0) { WorkbenchSingleton.Workbench.GetPad(typeof(ErrorListPad)).BringPadToFront(); } } void OnUndoStackChanged(object sender, EventArgs e) { wasChangedInDesigner = true; this.PrimaryFile.MakeDirty(); } #region Property editor / SelectionChanged PropertyGridView propertyGridView; void InitPropertyEditor() { propertyGridView = new PropertyGridView(); propertyContainer.PropertyGridReplacementContent = propertyGridView; propertyGridView.PropertyGrid.PropertyChanged += OnPropertyGridPropertyChanged; } void OnSelectionChanged(object sender, DesignItemCollectionEventArgs e) { propertyGridView.PropertyGrid.SelectedItems = DesignContext.Services.Selection.SelectedItems; } void OnPropertyGridPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Name") { if (!propertyGridView.PropertyGrid.IsNameCorrect) return; // get the XAML file OpenedFile fileName = this.Files.FirstOrDefault(f => f.FileName.ToString().EndsWith(".xaml", StringComparison.OrdinalIgnoreCase)); if (fileName == null) return; // parse the XAML file ParseInformation info = SD.ParserService.Parse(fileName.FileName); if (info == null) return; // rename the member #warning reimplement rename! /* IMember member = info.CompilationUnit.Classes [0].AllMembers.FirstOrDefault(m => m.Name == propertyGridView.PropertyGrid.OldName); if (member != null) { FindReferencesAndRenameHelper.RenameMember(member, propertyGridView.PropertyGrid.Name); }*/ } } 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 object ToolsContent { 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); } // see 3522 outline.AddCommandHandler(ApplicationCommands.Delete, () => ApplicationCommands.Delete.Execute(null, designer)); } return outline; } } public object OutlineContent { get { return this.Outline; } } } }