diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/FormsDesignerBinding.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/FormsDesignerBinding.cs index 795fd9f561..7ad6e0ffaa 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/FormsDesignerBinding.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/FormsDesignerBinding.cs @@ -19,6 +19,16 @@ namespace Grunwald.BooBinding.Designer { public class FormsDesignerDisplayBinding : ISecondaryDisplayBinding { + /// + /// When you return true for this property, the CreateSecondaryViewContent method + /// is called again after the LoadSolutionProjects thread has finished. + /// + public bool ReattachWhenParserServiceIsReady { + get { + return true; + } + } + public bool CanAttachTo(IViewContent viewContent) { if (viewContent is ITextEditorControlProvider) { @@ -38,6 +48,10 @@ namespace Grunwald.BooBinding.Designer public ISecondaryViewContent[] CreateSecondaryViewContent(IViewContent viewContent) { + if (viewContent.SecondaryViewContents.Exists(delegate(ISecondaryViewContent c) { return c.GetType() == typeof(FormsDesignerViewContent); })) { + return new ISecondaryViewContent[0]; + } + IDesignerLoaderProvider loader = new BooDesignerLoaderProvider(((ITextEditorControlProvider)viewContent).TextEditorControl); IDesignerGenerator generator = new BooDesignerGenerator(); return new ISecondaryViewContent[] { new FormsDesignerViewContent(viewContent, loader, generator) }; diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/SecondaryDisplayBinding.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/SecondaryDisplayBinding.cs index 3e8d70990e..6055a437b6 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/SecondaryDisplayBinding.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/SecondaryDisplayBinding.cs @@ -20,6 +20,16 @@ namespace ICSharpCode.FormsDesigner { public class FormsDesignerSecondaryDisplayBinding : ISecondaryDisplayBinding { + /// + /// When you return true for this property, the CreateSecondaryViewContent method + /// is called again after the LoadSolutionProjects thread has finished. + /// + public bool ReattachWhenParserServiceIsReady { + get { + return true; + } + } + public static IMethod GetInitializeComponents(IClass c) { c = c.DefaultReturnType.GetUnderlyingClass(); @@ -99,6 +109,10 @@ namespace ICSharpCode.FormsDesigner public ISecondaryViewContent[] CreateSecondaryViewContent(IViewContent viewContent) { + if (viewContent.SecondaryViewContents.Exists(delegate(ISecondaryViewContent c) { return c.GetType() == typeof(FormsDesignerViewContent); })) { + return new ISecondaryViewContent[0]; + } + string fileExtension = String.Empty; string fileName = viewContent.IsUntitled ? viewContent.UntitledName : viewContent.FileName; diff --git a/src/AddIns/Misc/SubversionAddIn/Project/Src/Gui/HistoryViewDisplayBinding/HistoryViewDisplayBinding.cs b/src/AddIns/Misc/SubversionAddIn/Project/Src/Gui/HistoryViewDisplayBinding/HistoryViewDisplayBinding.cs index bcab08f077..159fcc1d72 100644 --- a/src/AddIns/Misc/SubversionAddIn/Project/Src/Gui/HistoryViewDisplayBinding/HistoryViewDisplayBinding.cs +++ b/src/AddIns/Misc/SubversionAddIn/Project/Src/Gui/HistoryViewDisplayBinding/HistoryViewDisplayBinding.cs @@ -40,6 +40,16 @@ namespace ICSharpCode.Svn { public class HistoryViewDisplayBinding : ISecondaryDisplayBinding { + /// + /// When you return true for this property, the CreateSecondaryViewContent method + /// is called again after the LoadSolutionProjects thread has finished. + /// + public bool ReattachWhenParserServiceIsReady { + get { + return false; + } + } + public ICSharpCode.SharpDevelop.Gui.ISecondaryViewContent[] CreateSecondaryViewContent(ICSharpCode.SharpDevelop.Gui.IViewContent viewContent) { return new ICSharpCode.SharpDevelop.Gui.ISecondaryViewContent[] { new HistoryView(viewContent) }; diff --git a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceWindow.cs b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceWindow.cs index ba3856a617..d2d5bf7159 100644 --- a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceWindow.cs +++ b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceWindow.cs @@ -98,6 +98,7 @@ namespace ICSharpCode.SharpDevelop.Gui protected override void Dispose(bool disposing) { if (disposing) { + ParserService.LoadSolutionProjectsThreadEnded -= LoadSolutionProjectsThreadEndedEvent; if (content != null) DetachContent(); if (this.TabPageContextMenu != null) { @@ -126,16 +127,22 @@ namespace ICSharpCode.SharpDevelop.Gui SetTitleEvent(this, EventArgs.Empty); this.TabPageContextMenu = MenuService.CreateContextMenu(this, contextMenuPath); InitControls(); + + ParserService.LoadSolutionProjectsThreadEnded += LoadSolutionProjectsThreadEndedEvent; + } + + private void CreateViewTabControl() + { + viewTabControl = new TabControl(); + viewTabControl.Alignment = TabAlignment.Bottom; + viewTabControl.Dock = DockStyle.Fill; + viewTabControl.SelectedIndexChanged += new EventHandler(viewTabControlIndexChanged); } internal void InitControls() { if (content.SecondaryViewContents.Count > 0) { - viewTabControl = new TabControl(); - viewTabControl.Alignment = TabAlignment.Bottom; - viewTabControl.Dock = DockStyle.Fill; - viewTabControl.SelectedIndexChanged += new EventHandler(viewTabControlIndexChanged); - + CreateViewTabControl(); AttachSecondaryViewContent(content); foreach (ISecondaryViewContent subContent in content.SecondaryViewContents) { AttachSecondaryViewContent(subContent); @@ -157,6 +164,41 @@ namespace ICSharpCode.SharpDevelop.Gui viewTabControl.TabPages.Add(newPage); } + /// + /// Ensures that all possible secondary view contents are attached. + /// This is primarily used to add the FormsDesigner view content for files + /// containing partial classes after the designer file has been parsed if + /// the view content has been created too early on startup. + /// + void RefreshSecondaryViewContents() + { + if (content == null) { + return; + } + int oldSvcCount = content.SecondaryViewContents.Count; + DisplayBindingService.AttachSubWindows(content, true); + if (content.SecondaryViewContents.Count > oldSvcCount) { + LoggingService.Debug("Attaching new secondary view contents to '"+this.Title+"'"); + if (viewTabControl == null) { + // The tab control needs to be created first. + Controls.Remove(content.Control); + CreateViewTabControl(); + AttachSecondaryViewContent(content); + Controls.Add(viewTabControl); + } + foreach (ISecondaryViewContent svc in content.SecondaryViewContents) { + if (svc.WorkbenchWindow == null) { + AttachSecondaryViewContent(svc); + } + } + } + } + + void LoadSolutionProjectsThreadEndedEvent(object sender, EventArgs e) + { + this.BeginInvoke(new MethodInvoker(this.RefreshSecondaryViewContents)); + } + void LeaveTabPage(object sender, EventArgs e) { OnWindowDeselected(EventArgs.Empty); diff --git a/src/Main/Base/Project/Src/Services/DisplayBinding/ISubDisplayBinding.cs b/src/Main/Base/Project/Src/Services/DisplayBinding/ISubDisplayBinding.cs index 8951896b73..f4a0a558ad 100644 --- a/src/Main/Base/Project/Src/Services/DisplayBinding/ISubDisplayBinding.cs +++ b/src/Main/Base/Project/Src/Services/DisplayBinding/ISubDisplayBinding.cs @@ -22,6 +22,17 @@ namespace ICSharpCode.Core { bool CanAttachTo(IViewContent content); + /// + /// When you return true for this property, the CreateSecondaryViewContent method + /// is called again after the LoadSolutionProjects thread has finished. + /// + bool ReattachWhenParserServiceIsReady { get; } + + /// + /// Creates the secondary view contents for the given view content. + /// If ReattachWhenParserServiceIsReady is used, the implementation is responsible + /// for checking that no duplicate secondary view contents are added. + /// ISecondaryViewContent [] CreateSecondaryViewContent(IViewContent viewContent); } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index d6d1ff3f57..df848c3aad 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -132,6 +132,7 @@ namespace ICSharpCode.Core } finally { LoggingService.Info("LoadSolutionProjects thread ended"); loadSolutionProjectsThread = null; + OnLoadSolutionProjectsThreadEnded(EventArgs.Empty); } } @@ -609,6 +610,14 @@ namespace ICSharpCode.Core } } + static void OnLoadSolutionProjectsThreadEnded(EventArgs e) + { + if (LoadSolutionProjectsThreadEnded != null) { + LoadSolutionProjectsThreadEnded(null, e); + } + } + public static event ParseInformationEventHandler ParseInformationUpdated; + public static event EventHandler LoadSolutionProjectsThreadEnded; } }