From a0e0103f12ce14d6882ce9d2acdb606cc5a07e62 Mon Sep 17 00:00:00 2001 From: Christian Hornung Date: Sat, 6 Sep 2008 19:34:21 +0000 Subject: [PATCH] Windows.Forms designer cleanup: Support "warm" reloading of designer (without full Unload/Load in view content). Happens automatically on language change -> removed own PropertyValueChanged handler. Fixed the designer not reloading after a load error on the primary file. Show a "please wait" label while loading. Moved DefaultMemberRelationshipService to its own file. Removed unused TypeDescriptorFilterService (that service is in the framework already). Simplified IDEContainer and do actually add the grid to the container. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3508 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/FormsDesigner.csproj | 4 +- .../AbstractCodeDomDesignerLoader.cs | 22 +-- .../NRefactoryDesignerLoader.cs | 13 -- .../Project/Src/DesignerViewContent.cs | 156 +++++++++++------- .../DefaultMemberRelationshipService.cs | 46 ++++++ .../Services/TypeDescriptorFilterService.cs | 63 ------- .../AbstractViewContentHandlingLoadErrors.cs | 18 +- .../Src/Gui/Pads/PropertyPad/IDEContainer.cs | 81 ++++----- .../Src/Gui/Pads/PropertyPad/PropertyPad.cs | 10 +- 9 files changed, 206 insertions(+), 207 deletions(-) create mode 100644 src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DefaultMemberRelationshipService.cs delete mode 100644 src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeDescriptorFilterService.cs diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/FormsDesigner.csproj b/src/AddIns/DisplayBindings/FormsDesigner/Project/FormsDesigner.csproj index b47fbb65b6..5d527db1cf 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/FormsDesigner.csproj +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/FormsDesigner.csproj @@ -79,6 +79,7 @@ + @@ -88,7 +89,6 @@ - @@ -151,4 +151,4 @@ - \ No newline at end of file + diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/AbstractCodeDomDesignerLoader.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/AbstractCodeDomDesignerLoader.cs index 3915c777e6..2d8834f5f8 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/AbstractCodeDomDesignerLoader.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/AbstractCodeDomDesignerLoader.cs @@ -76,14 +76,6 @@ namespace ICSharpCode.FormsDesigner this.typeResolutionService = (ITypeResolutionService)host.GetService(typeof(ITypeResolutionService)); this.designerLoaderHost = host; - IComponentChangeService componentChangeService = (IComponentChangeService)host.GetService(typeof(IComponentChangeService)); - if (componentChangeService != null) { - LoggingService.Debug("Forms designer: Adding ComponentAdded handler for nested container setup"); - componentChangeService.ComponentAdded += ComponentContainerSetUp; - } else { - LoggingService.Warn("Forms designer: Cannot add ComponentAdded handler for nested container setup because IComponentChangeService is unavailable"); - } - base.BeginLoad(host); } @@ -132,6 +124,14 @@ namespace ICSharpCode.FormsDesigner IDesignerSerializationManager manager = (IDesignerSerializationManager)designerLoaderHost.GetService(typeof(IDesignerSerializationManager)); manager.AddSerializationProvider(localizationProvider); base.Initialize(); + + IComponentChangeService componentChangeService = (IComponentChangeService)this.GetService(typeof(IComponentChangeService)); + if (componentChangeService != null) { + LoggingService.Debug("Forms designer: Adding ComponentAdded handler for nested container setup"); + componentChangeService.ComponentAdded += ComponentContainerSetUp; + } else { + LoggingService.Warn("Forms designer: Cannot add ComponentAdded handler for nested container setup because IComponentChangeService is unavailable"); + } } /// @@ -153,13 +153,13 @@ namespace ICSharpCode.FormsDesigner try { base.OnEndLoad(successful, errors); } catch(ExceptionCollection e) { - LoggingService.Error("DesignerLoader.OnEndLoad error" + e.Message); + LoggingService.Error("DesignerLoader.OnEndLoad error " + e.Message, e); foreach(Exception ine in e.Exceptions) { - LoggingService.Error("DesignerLoader.OnEndLoad error" + ine.Message); + LoggingService.Error("DesignerLoader.OnEndLoad error " + ine.Message, ine); } throw; } catch(Exception e) { - LoggingService.Error("DesignerLoader.OnEndLoad error" + e.Message); + LoggingService.Error("DesignerLoader.OnEndLoad error " + e.Message, e); throw; } } diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs index d67fdfac9c..c47c8794a1 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs @@ -19,22 +19,9 @@ using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Visitors; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Dom; -using ICSharpCode.TextEditor; namespace ICSharpCode.FormsDesigner { - public class DefaultMemberRelationshipService : MemberRelationshipService - { - public override bool SupportsRelationship(MemberRelationship source, MemberRelationship relationship) - { - return true; - } - protected override MemberRelationship GetRelationship(MemberRelationship source) - { - return base.GetRelationship(source); - } - } - public class NRefactoryDesignerLoader : AbstractCodeDomDesignerLoader { SupportedLanguage language; diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs index f0f6c66c91..e4bab2334a 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs @@ -28,13 +28,13 @@ namespace ICSharpCode.FormsDesigner { public class FormsDesignerViewContent : AbstractViewContentHandlingLoadErrors, IClipboardHandler, IUndoHandler, IHasPropertyContainer, IContextHelpProvider, IToolsHost { - Panel p = new Panel(); + readonly Control pleaseWaitLabel = new Label() {Text=StringParser.Parse("${res:Global.PleaseWait}"), TextAlign=ContentAlignment.MiddleCenter}; DesignSurface designSurface; bool disposing; - bool loadingDesigner; readonly IViewContent primaryViewContent; readonly IDesignerLoaderProvider loaderProvider; + DesignerLoader loader; readonly IDesignerGenerator generator; readonly ResourceStore resourceStore; FormsDesignerUndoEngine undoEngine; @@ -93,6 +93,10 @@ namespace ICSharpCode.FormsDesigner get { return this.primaryViewContent; } } + protected override string LoadErrorHeaderText { + get { return StringParser.Parse("${res:ICSharpCode.SharpDevelop.FormDesigner.LoadErrorCheckSourceCodeForErrors}") + Environment.NewLine + Environment.NewLine; } + } + FormsDesignerViewContent(IViewContent primaryViewContent) : base() { @@ -104,13 +108,13 @@ namespace ICSharpCode.FormsDesigner this.primaryViewContent = primaryViewContent; - p.BackColor = Color.White; - p.RightToLeft = RightToLeft.No; + this.Control.BackColor = Color.White; + this.Control.RightToLeft = RightToLeft.No; // Make sure auto-scaling is based on the correct font. // This is required on Vista, I don't know why it works correctly in XP - p.Font = Control.DefaultFont; + this.Control.Font = Control.DefaultFont; - this.UserControl = this.p; + this.UserControl = this.pleaseWaitLabel; this.resourceStore = new ResourceStore(this); @@ -179,6 +183,9 @@ namespace ICSharpCode.FormsDesigner } else if (!this.Files.Contains(this.designerCodeFile)) { LoggingService.Debug("Forms designer: Adding designer code file " + this.designerCodeFile.FileName); this.Files.Insert(1, this.designerCodeFile); + } else if (this.HasLoadError || this.designSurface == null || !this.designSurface.IsLoaded) { + LoggingService.Debug("Forms designer: Having a load error. Reloading designer."); + this.ReloadDesignerFromMemory(); } } else if (file == this.DesignerCodeFile) { @@ -196,7 +203,7 @@ namespace ICSharpCode.FormsDesigner // Loading a resource file bool mustReload; - if (this.designSurface != null && !this.loadingDesigner) { + if (this.loader != null && !this.loader.Loading) { LoggingService.Debug("Forms designer: Reloading designer because of LoadInternal on resource file"); this.UnloadDesigner(); mustReload = true; @@ -260,13 +267,19 @@ namespace ICSharpCode.FormsDesigner } designSurface = CreateDesignSurface(serviceContainer); + designSurface.Loaded += this.DesignerLoaded; + designSurface.Flushed += this.DesignerFlushed; - serviceContainer.AddService(typeof(System.ComponentModel.Design.IMenuCommandService), new ICSharpCode.FormsDesigner.Services.MenuCommandService(p, designSurface)); + serviceContainer.AddService(typeof(System.ComponentModel.Design.IMenuCommandService), new ICSharpCode.FormsDesigner.Services.MenuCommandService(this.Control, designSurface)); ICSharpCode.FormsDesigner.Services.EventBindingService eventBindingService = new ICSharpCode.FormsDesigner.Services.EventBindingService(this, designSurface); serviceContainer.AddService(typeof(System.ComponentModel.Design.IEventBindingService), eventBindingService); - DesignerLoader designerLoader = loaderProvider.CreateLoader(generator); - designSurface.BeginLoad(designerLoader); + this.loader = loaderProvider.CreateLoader(generator); + designSurface.BeginLoad(this.loader); + + if (!designSurface.IsLoaded) { + throw new FormsDesignerLoadException(FormatLoadErrors(designSurface)); + } undoEngine = new FormsDesignerUndoEngine(Host); serviceContainer.AddService(typeof(UndoEngine), undoEngine); @@ -287,7 +300,6 @@ namespace ICSharpCode.FormsDesigner } UpdatePropertyPad(); - PropertyPad.PropertyValueChanged += PropertyValueChanged; hasUnmergedChanges = false; @@ -310,7 +322,7 @@ namespace ICSharpCode.FormsDesigner if (shouldUpdateSelectableObjects) { // update the property pad after the transaction is *really* finished // (including updating the selection) - p.BeginInvoke(new MethodInvoker(UpdatePropertyPad)); + this.Control.BeginInvoke(new MethodInvoker(UpdatePropertyPad)); shouldUpdateSelectableObjects = false; } } @@ -324,9 +336,10 @@ namespace ICSharpCode.FormsDesigner { LoggingService.Debug("FormsDesigner unloading, setting ActiveDesignSurface to null"); designSurfaceManager.ActiveDesignSurface = null; - PropertyPad.PropertyValueChanged -= PropertyValueChanged; + bool savedIsDirty = (this.DesignerCodeFile == null) ? false : this.DesignerCodeFile.IsDirty; - p.Controls.Clear(); + this.UserControl = this.pleaseWaitLabel; + Application.DoEvents(); if (this.DesignerCodeFile != null) { this.DesignerCodeFile.IsDirty = savedIsDirty; } @@ -337,13 +350,34 @@ namespace ICSharpCode.FormsDesigner // at design time" is thrown. // This is solved by calling dispose after the double-click event has been processed. if (designSurface != null) { + designSurface.Loaded -= this.DesignerLoaded; + designSurface.Flushed -= this.DesignerFlushed; + + IComponentChangeService componentChangeService = designSurface.GetService(typeof(IComponentChangeService)) as IComponentChangeService; + if (componentChangeService != null) { + componentChangeService.ComponentChanged -= MakeDirty; + componentChangeService.ComponentAdded -= ComponentListChanged; + componentChangeService.ComponentRemoved -= ComponentListChanged; + componentChangeService.ComponentRename -= ComponentListChanged; + } + if (this.Host != null) { + this.Host.TransactionClosed -= TransactionClose; + } + + ISelectionService selectionService = designSurface.GetService(typeof(ISelectionService)) as ISelectionService; + if (selectionService != null) { + selectionService.SelectionChanged -= SelectionChangedHandler; + } + if (disposing) { designSurface.Dispose(); } else { - p.BeginInvoke(new MethodInvoker(designSurface.Dispose)); + this.Control.BeginInvoke(new MethodInvoker(designSurface.Dispose)); } designSurface = null; } + + this.loader = null; } readonly PropertyContainer propertyContainer = new PropertyContainer(); @@ -373,44 +407,62 @@ namespace ICSharpCode.FormsDesigner { try { - this.loadingDesigner = true; - LoadDesigner(); - bool savedIsDirty = this.DesignerCodeFile.IsDirty; - if (designSurface != null && p.Controls.Count == 0) { - Control designer = designSurface.View as Control; - designer.Dock = DockStyle.Fill; - p.Controls.Add(designer); - LoggingService.Debug("FormsDesigner loaded, setting ActiveDesignSurface to " + this.designSurface.ToString()); - designSurfaceManager.ActiveDesignSurface = this.designSurface; - } - this.DesignerCodeFile.IsDirty = savedIsDirty; - } catch (Exception e) { - string mainErrorMessage; if (e.InnerException is FormsDesignerLoadException) { - mainErrorMessage = e.InnerException.Message; + throw new FormsDesignerLoadException(e.InnerException.Message, e); } else if (e is FormsDesignerLoadException) { - mainErrorMessage = e.Message; + throw; } else if (designSurface != null && !designSurface.IsLoaded && designSurface.LoadErrors != null) { - mainErrorMessage = StringParser.Parse("${res:ICSharpCode.SharpDevelop.FormDesigner.ErrorLoadingDesigner}\r\n\r\n"); - foreach(Exception le in designSurface.LoadErrors) { - mainErrorMessage += le.ToString(); - mainErrorMessage += "\r\n"; - } + throw new FormsDesignerLoadException(FormatLoadErrors(designSurface), e); } else { - mainErrorMessage = e.ToString(); + throw; } - throw new FormsDesignerLoadException(StringParser.Parse("${res:ICSharpCode.SharpDevelop.FormDesigner.LoadErrorCheckSourceCodeForErrors}") + Environment.NewLine + mainErrorMessage + Environment.NewLine, e); - - } finally { - this.loadingDesigner = false; } } + void DesignerLoaded(object sender, LoadedEventArgs e) + { + // This method is called when the designer has loaded. + + if (e.HasSucceeded) { + // Display the designer on the view content + bool savedIsDirty = this.DesignerCodeFile.IsDirty; + this.UserControl = (Control)this.designSurface.View; + LoggingService.Debug("FormsDesigner loaded, setting ActiveDesignSurface to " + this.designSurface.ToString()); + designSurfaceManager.ActiveDesignSurface = this.designSurface; + this.DesignerCodeFile.IsDirty = savedIsDirty; + } else { + // This method can not only be called during initialization, + // but also when the designer reloads itself because of + // a language change. + // When a load error occurs there, we are not somewhere + // below the Load method which handles load errors. + // That is why we create an error text box here anyway. + TextBox errorTextBox = new TextBox() { Multiline=true, ScrollBars=ScrollBars.Both, ReadOnly=true, BackColor=SystemColors.Window, Dock=DockStyle.Fill }; + errorTextBox.Text = String.Concat(this.LoadErrorHeaderText, FormatLoadErrors(designSurface)); + this.UserControl = errorTextBox; + } + } + + void DesignerFlushed(object sender, EventArgs e) + { + this.resourceStore.CommitAllResourceChanges(); + } + + static string FormatLoadErrors(DesignSurface designSurface) + { + StringBuilder sb = new StringBuilder(); + foreach(Exception le in designSurface.LoadErrors) { + sb.AppendLine(le.ToString()); + sb.AppendLine(); + } + return sb.ToString(); + } + public virtual void MergeFormChanges() { if (this.HasLoadError) { @@ -491,8 +543,8 @@ namespace ICSharpCode.FormsDesigner this.resourceStore.Dispose(); - p.Dispose(); - p = null; + this.UserControl = null; + this.pleaseWaitLabel.Dispose(); } } @@ -664,26 +716,6 @@ namespace ICSharpCode.FormsDesigner } #endregion - /// - /// Reloads the form designer if the language property has changed. - /// - void PropertyValueChanged(object source, PropertyValueChangedEventArgs e) - { - if (e.ChangedItem == null || e.OldValue == null) - return; - if (!propertyContainer.IsActivePropertyContainer) - return; - if (e.ChangedItem.GridItemType == GridItemType.Property) { - if (e.ChangedItem.PropertyDescriptor.Name == "Language") { - if (!e.OldValue.Equals(e.ChangedItem.Value)) { - LoggingService.Debug("Reloading designer due to language change."); - this.MergeAndUnloadDesigner(); - this.ReloadDesignerFromMemory(); - } - } - } - } - protected void MergeAndUnloadDesigner() { propertyContainer.Clear(); diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DefaultMemberRelationshipService.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DefaultMemberRelationshipService.cs new file mode 100644 index 0000000000..4a8e242f33 --- /dev/null +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DefaultMemberRelationshipService.cs @@ -0,0 +1,46 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.ComponentModel.Design.Serialization; + +using ICSharpCode.Core; + +//#define WFDESIGN_LOG_MEMBERRELATIONSHIPSERVICE + +namespace ICSharpCode.FormsDesigner.Services +{ + public class DefaultMemberRelationshipService : MemberRelationshipService + { + public DefaultMemberRelationshipService() + { + } + + public override bool SupportsRelationship(MemberRelationship source, MemberRelationship relationship) + { + #if WFDESIGN_LOG_MEMBERRELATIONSHIPSERVICE + LoggingService.Debug("MemberRelationshipService: SupportsRelationship called, source=" + ToString(source) + ", relationship=" + ToString(relationship)); + #endif + return true; + } + + #if WFDESIGN_LOG_MEMBERRELATIONSHIPSERVICE + protected override MemberRelationship GetRelationship(MemberRelationship source) + { + LoggingService.Debug("MemberRelationshipService: GetRelationship called, source=" + ToString(source)); + var mrs = base.GetRelationship(source); + LoggingService.Debug("MemberRelationshipService: -> returning " + ToString(mrs)); + return mrs; + } + + static string ToString(MemberRelationship mrs) + { + return "[MR: IsEmpty=" + mrs.IsEmpty + ", Owner=[" + (mrs.Owner == null ? "" : mrs.Owner.ToString()) + "], Member=[" + (mrs.Member == null ? "" : mrs.Member.Name) + "]]"; + } + #endif + } +} diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeDescriptorFilterService.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeDescriptorFilterService.cs deleted file mode 100644 index f4b8867160..0000000000 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeDescriptorFilterService.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// -// -// -// $Revision$ -// - -using System; -using System.ComponentModel; -using System.ComponentModel.Design; - -namespace ICSharpCode.FormsDesigner.Services -{ - public class TypeDescriptorFilterService : ITypeDescriptorFilterService - { - IDesignerFilter GetDesignerFilter(IComponent component) - { - ISite site = component.Site; - - if (site == null) { - return null; - } - - IDesignerHost host = (IDesignerHost)site.GetService(typeof(IDesignerHost)); - if (host == null) - return null; - return host.GetDesigner(component) as IDesignerFilter; - } - - -#region System.ComponentModel.Design.ITypeDescriptorFilterService interface implementation - public bool FilterProperties(System.ComponentModel.IComponent component, System.Collections.IDictionary properties) - { - IDesignerFilter designerFilter = GetDesignerFilter(component); - if (designerFilter != null) { - designerFilter.PreFilterProperties(properties); - designerFilter.PostFilterProperties(properties); - } - return false; - } - - public bool FilterEvents(System.ComponentModel.IComponent component, System.Collections.IDictionary events) - { - IDesignerFilter designerFilter = GetDesignerFilter(component); - if (designerFilter != null) { - designerFilter.PreFilterEvents(events); - designerFilter.PostFilterEvents(events); - } - return false; - } - - public bool FilterAttributes(System.ComponentModel.IComponent component, System.Collections.IDictionary attributes) - { - IDesignerFilter designerFilter = GetDesignerFilter(component); - if (designerFilter != null) { - designerFilter.PreFilterAttributes(attributes); - designerFilter.PostFilterAttributes(attributes); - } - return false; - } -#endregion - } -} diff --git a/src/Main/Base/Project/Src/Gui/AbstractViewContentHandlingLoadErrors.cs b/src/Main/Base/Project/Src/Gui/AbstractViewContentHandlingLoadErrors.cs index 1656d00729..f85ac6fb2f 100644 --- a/src/Main/Base/Project/Src/Gui/AbstractViewContentHandlingLoadErrors.cs +++ b/src/Main/Base/Project/Src/Gui/AbstractViewContentHandlingLoadErrors.cs @@ -51,9 +51,11 @@ namespace ICSharpCode.SharpDevelop.Gui panel.Controls.Remove(userControl); } userControl = value; - userControl.Dock = DockStyle.Fill; - if (errorList.Count == 0 && userControl != null) { - panel.Controls.Add(userControl); + if (userControl != null) { + userControl.Dock = DockStyle.Fill; + if (errorList.Count == 0) { + panel.Controls.Add(userControl); + } } } } @@ -96,13 +98,21 @@ namespace ICSharpCode.SharpDevelop.Gui errorTextBox.BackColor = SystemColors.Window; errorTextBox.Dock = DockStyle.Fill; } - errorTextBox.Text = ex.ToString(); + errorTextBox.Text = String.Concat(this.LoadErrorHeaderText, ex.ToString()); panel.Controls.Clear(); panel.Controls.Add(errorTextBox); } Dictionary errorList = new Dictionary(); + /// + /// Gets a text to be shown above the exception when a load error occurs. + /// The default is an empty string. + /// + protected virtual string LoadErrorHeaderText { + get { return String.Empty; } + } + public override sealed void Load(OpenedFile file, Stream stream) { try { diff --git a/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/IDEContainer.cs b/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/IDEContainer.cs index e771a7d9bf..0c9bee3340 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/IDEContainer.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/IDEContainer.cs @@ -5,75 +5,58 @@ // $Revision$ // +//#define IDECONTAINER_LOG_SERVICE_REQUESTS + using System; using System.ComponentModel; +using ICSharpCode.Core; + namespace ICSharpCode.SharpDevelop.Gui { class IDEContainer : Container { - class IDESite : ISite - { - private string name = ""; - private IComponent component; - private IDEContainer container; - - public IDESite(IComponent sitedComponent, IDEContainer site, string aName) - { - component = sitedComponent; - container = site; - name = aName; - } - - public IComponent Component{ - get{ return component;} - } - public IContainer Container{ - get{return container;} - } - - public bool DesignMode{ - get{return false;} - } - - public string Name { - get{ return name;} - set{name=value;} - } - - public object GetService(Type serviceType) - { - return container.GetService(serviceType); - } - } - - public IDEContainer (IServiceProvider sp) + IServiceProvider serviceProvider; + IComponent grid; + + public IDEContainer() { - serviceProvider = sp; } - + protected override object GetService(Type serviceType) { object service = base.GetService(serviceType); - if (service == null) { + if (service == null && serviceProvider != null) { service = serviceProvider.GetService(serviceType); } + #if IDECONTAINER_LOG_SERVICE_REQUESTS + if (service == null) { + LoggingService.Info("IDEContainer: request missing service: " + serviceType.AssemblyQualifiedName); + } else { + LoggingService.Debug("IDEContainer: get service: " + serviceType.AssemblyQualifiedName + " -> is: " + service.ToString()); + } + #endif return service; } - - public ISite CreateSite(IComponent component) - { - return CreateSite(component, "UNKNOWN_SITE"); - } - protected override ISite CreateSite(IComponent component,string name) + internal void ConnectGridAndHost(IComponent grid, IServiceProvider host) { - ISite site = base.CreateSite(component,name); - if (site == null) { + if (this.grid != null || this.serviceProvider != null) { + throw new InvalidOperationException("Grid must be disconnected first."); } - return new IDESite(component,this,name); + LoggingService.Debug("IDEContainer: Connecting property grid to service provider"); + this.serviceProvider = host; + this.grid = grid; + this.Add(grid); } - private IServiceProvider serviceProvider; + internal void Disconnect() + { + if (this.Components.Count == 0) return; + LoggingService.Debug("IDEContainer: Disconnecting property grid from service provider"); + this.Remove(grid); + this.grid = null; + this.serviceProvider = null; + } } } diff --git a/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs b/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs index 72415e86ec..c88fc7aa0c 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs @@ -26,6 +26,9 @@ namespace ICSharpCode.SharpDevelop.Gui // an empty container used to reset the property grid readonly PropertyContainer emptyContainer = new PropertyContainer(false); + // The IDE container used to connect the grid to a designer host + readonly IDEContainer ideContainer = new IDEContainer(); + PropertyContainer activeContainer; internal static PropertyContainer ActiveContainer { @@ -302,6 +305,7 @@ namespace ICSharpCode.SharpDevelop.Gui { base.Dispose(); if (grid != null) { + this.ideContainer.Disconnect(); ProjectService.SolutionClosed -= SolutionClosedEvent; try { grid.SelectedObjects = null; @@ -344,17 +348,17 @@ namespace ICSharpCode.SharpDevelop.Gui void RemoveHost(IDesignerHost host) { this.host = null; - grid.Site = null; + this.ideContainer.Disconnect(); } void SetDesignerHost(IDesignerHost host) { this.host = host; if (host != null) { - grid.Site = (new IDEContainer(host)).CreateSite(grid); + this.ideContainer.ConnectGridAndHost(grid, host); grid.PropertyTabs.AddTabType(typeof(System.Windows.Forms.Design.EventsTab), PropertyTabScope.Document); } else { - grid.Site = null; + this.ideContainer.Disconnect(); } }