Index: Core/Common/src/Core.Common.Controls.TreeView/TreeViewController.cs =================================================================== diff -u -r2750ecd900b9e34ba54bb96d233c464b82d7684c -r83e8ea6f186faad530933f5620faa91f1920d1e1 --- Core/Common/src/Core.Common.Controls.TreeView/TreeViewController.cs (.../TreeViewController.cs) (revision 2750ecd900b9e34ba54bb96d233c464b82d7684c) +++ Core/Common/src/Core.Common.Controls.TreeView/TreeViewController.cs (.../TreeViewController.cs) (revision 83e8ea6f186faad530933f5620faa91f1920d1e1) @@ -62,7 +62,6 @@ this.treeView = treeView; - // Ensure tree nodes are correctly aligned treeView.ImageList = new ImageList { ColorDepth = ColorDepth.Depth32Bit Index: Core/Common/src/Core.Common.Gui/IGui.cs =================================================================== diff -u -r0c64d8a6c718c0aa67403a16c94dd0c10f862455 -r83e8ea6f186faad530933f5620faa91f1920d1e1 --- Core/Common/src/Core.Common.Gui/IGui.cs (.../IGui.cs) (revision 0c64d8a6c718c0aa67403a16c94dd0c10f862455) +++ Core/Common/src/Core.Common.Gui/IGui.cs (.../IGui.cs) (revision 83e8ea6f186faad530933f5620faa91f1920d1e1) @@ -20,7 +20,6 @@ // All rights reserved. using System; - using Core.Common.Base.Plugin; using Core.Common.Base.Storage; using Core.Common.Gui.Commands; Index: Core/Common/src/Core.Common.Gui/IGuiPluginsHost.cs =================================================================== diff -u -r0c64d8a6c718c0aa67403a16c94dd0c10f862455 -r83e8ea6f186faad530933f5620faa91f1920d1e1 --- Core/Common/src/Core.Common.Gui/IGuiPluginsHost.cs (.../IGuiPluginsHost.cs) (revision 0c64d8a6c718c0aa67403a16c94dd0c10f862455) +++ Core/Common/src/Core.Common.Gui/IGuiPluginsHost.cs (.../IGuiPluginsHost.cs) (revision 83e8ea6f186faad530933f5620faa91f1920d1e1) @@ -22,7 +22,7 @@ using System; using System.Collections; using System.Collections.Generic; - +using Core.Common.Controls.TreeView; using Core.Common.Gui.Plugin; namespace Core.Common.Gui @@ -53,5 +53,11 @@ /// The root data object. /// An enumeration of all (child)data that have view definitions declared. IEnumerable GetAllDataWithViewDefinitionsRecursively(object rootDataObject); + + /// + /// Retrieves all the defined on the configured plugins. + /// + /// An of which are configured in . + IEnumerable GetTreeNodeInfos(); } } \ No newline at end of file Index: Core/Common/src/Core.Common.Gui/RingtoetsGui.cs =================================================================== diff -u -r08d98d14b1c258721219d118317758eabfd3fc51 -r83e8ea6f186faad530933f5620faa91f1920d1e1 --- Core/Common/src/Core.Common.Gui/RingtoetsGui.cs (.../RingtoetsGui.cs) (revision 08d98d14b1c258721219d118317758eabfd3fc51) +++ Core/Common/src/Core.Common.Gui/RingtoetsGui.cs (.../RingtoetsGui.cs) (revision 83e8ea6f186faad530933f5620faa91f1920d1e1) @@ -199,6 +199,11 @@ } } + public IEnumerable GetTreeNodeInfos() + { + return Plugins.SelectMany(pluginGui => pluginGui.GetTreeNodeInfos()); + } + protected virtual void Dispose(bool disposing) { if (disposing) Index: Core/Common/test/Core.Common.Test/Core.Common.Test.csproj =================================================================== diff -u -r5933051dfa1dbc40dbf7552852e6ca85ae7b0811 -r83e8ea6f186faad530933f5620faa91f1920d1e1 --- Core/Common/test/Core.Common.Test/Core.Common.Test.csproj (.../Core.Common.Test.csproj) (revision 5933051dfa1dbc40dbf7552852e6ca85ae7b0811) +++ Core/Common/test/Core.Common.Test/Core.Common.Test.csproj (.../Core.Common.Test.csproj) (revision 83e8ea6f186faad530933f5620faa91f1920d1e1) @@ -179,6 +179,10 @@ {F49BD8B2-332A-4C91-A196-8CCE0A2C7D98} Core.Common.Utils + + {1d27f91f-4e62-4eaf-a0a8-a32708b9a9b1} + Core.Common.Controls.TreeView + Index: Core/Common/test/Core.Common.Test/Gui/RingtoetsGuiTests.cs =================================================================== diff -u -r0c64d8a6c718c0aa67403a16c94dd0c10f862455 -r83e8ea6f186faad530933f5620faa91f1920d1e1 --- Core/Common/test/Core.Common.Test/Gui/RingtoetsGuiTests.cs (.../RingtoetsGuiTests.cs) (revision 0c64d8a6c718c0aa67403a16c94dd0c10f862455) +++ Core/Common/test/Core.Common.Test/Gui/RingtoetsGuiTests.cs (.../RingtoetsGuiTests.cs) (revision 83e8ea6f186faad530933f5620faa91f1920d1e1) @@ -3,6 +3,7 @@ using Core.Common.Base.Plugin; using Core.Common.Base.Storage; +using Core.Common.Controls.TreeView; using Core.Common.Gui; using Core.Common.Gui.Forms.MainWindow; using Core.Common.Gui.Plugin; @@ -200,5 +201,63 @@ } mocks.VerifyAll(); } + + [Test] + [RequiresSTA] + public void GetTreeNodeInfos_NoPluginsConfigured_EmptyList() + { + // Setup + var mocks = new MockRepository(); + var projectStore = mocks.Stub(); + mocks.ReplayAll(); + + using (var gui = new RingtoetsGui(new MainWindow(), projectStore)) + { + // Call + var result = gui.GetTreeNodeInfos(); + + // Assert + CollectionAssert.IsEmpty(result); + } + } + + [Test] + [RequiresSTA] + public void GetTreeNodeInfos_MultiplePluginsConfigured_RetrievesTreeNodeInfosFromPlugins() + { + // Setup + var mocks = new MockRepository(); + var projectStore = mocks.Stub(); + + var pluginA = mocks.Stub(); + pluginA.Expect(p => p.GetTreeNodeInfos()).Return(Enumerable.Empty()); + pluginA.Expect(p => p.Deactivate()); + pluginA.Expect(p => p.Dispose()); + var pluginB = mocks.Stub(); + pluginB.Expect(p => p.GetTreeNodeInfos()).Return(Enumerable.Empty()); + pluginB.Expect(p => p.Deactivate()); + pluginB.Expect(p => p.Dispose()); + var pluginC = mocks.Stub(); + pluginC.Expect(p => p.GetTreeNodeInfos()).Return(Enumerable.Empty()); + pluginC.Expect(p => p.Deactivate()); + pluginC.Expect(p => p.Dispose()); + + mocks.ReplayAll(); + + using (var gui = new RingtoetsGui(new MainWindow(), projectStore)) + { + gui.Plugins.Add(pluginA); + gui.Plugins.Add(pluginB); + gui.Plugins.Add(pluginC); + + // Call + var result = gui.GetTreeNodeInfos(); + + // Assert + CollectionAssert.IsEmpty(result); + } + + mocks.VerifyAll(); + } } } \ No newline at end of file Index: Core/Plugins/src/Core.Plugins.ProjectExplorer/ProjectExplorer.cs =================================================================== diff -u -ra5cdc407e4483b4f0e55e37550a91477be094469 -r83e8ea6f186faad530933f5620faa91f1920d1e1 --- Core/Plugins/src/Core.Plugins.ProjectExplorer/ProjectExplorer.cs (.../ProjectExplorer.cs) (revision a5cdc407e4483b4f0e55e37550a91477be094469) +++ Core/Plugins/src/Core.Plugins.ProjectExplorer/ProjectExplorer.cs (.../ProjectExplorer.cs) (revision 83e8ea6f186faad530933f5620faa91f1920d1e1) @@ -20,23 +20,32 @@ // All rights reserved. using System; +using System.Collections.Generic; using System.Windows.Forms; using Core.Common.Controls.TreeView; using Core.Common.Gui.Commands; using Core.Common.Gui.Forms; using Core.Common.Gui.Selection; +using Core.Plugins.ProjectExplorer.Properties; using TreeView = Core.Common.Controls.TreeView.TreeView; namespace Core.Plugins.ProjectExplorer { - public partial class ProjectExplorer : UserControl, IProjectExplorer + public sealed partial class ProjectExplorer : UserControl, IProjectExplorer { - public ProjectExplorer(IApplicationSelection applicationSelection, IViewCommands viewCommands) + public ProjectExplorer(IApplicationSelection applicationSelection, IViewCommands viewCommands, IEnumerable treeNodeInfos) { + Text = Resources.ProjectExplorerPluginGui_InitializeProjectTreeView_Project_Explorer; + InitializeComponent(); ApplicationSelection = applicationSelection; ViewCommands = viewCommands; + foreach (TreeNodeInfo info in treeNodeInfos) + { + TreeView.TreeViewController.RegisterTreeNodeInfo(info); + } + TreeView.TreeViewController.TreeNodeDoubleClick += TreeViewDoubleClick; TreeView.TreeViewController.NodeDataDeleted += ProjectDataDeleted; TreeView.AfterSelect += TreeViewSelectedNodeChanged; @@ -77,6 +86,8 @@ components.Dispose(); } + Data = null; + TreeView.Dispose(); ApplicationSelection.SelectionChanged -= GuiSelectionChanged; base.Dispose(disposing); Index: Core/Plugins/src/Core.Plugins.ProjectExplorer/ProjectExplorerGuiPlugin.cs =================================================================== diff -u -ra5cdc407e4483b4f0e55e37550a91477be094469 -r83e8ea6f186faad530933f5620faa91f1920d1e1 --- Core/Plugins/src/Core.Plugins.ProjectExplorer/ProjectExplorerGuiPlugin.cs (.../ProjectExplorerGuiPlugin.cs) (revision a5cdc407e4483b4f0e55e37550a91477be094469) +++ Core/Plugins/src/Core.Plugins.ProjectExplorer/ProjectExplorerGuiPlugin.cs (.../ProjectExplorerGuiPlugin.cs) (revision 83e8ea6f186faad530933f5620faa91f1920d1e1) @@ -27,10 +27,8 @@ using Core.Common.Gui.Commands; using Core.Common.Gui.ContextMenu; using Core.Common.Gui.Forms; -using Core.Common.Gui.Forms.ViewManager; using Core.Common.Gui.Plugin; using Core.Common.Gui.Selection; -using Core.Common.Utils.Extensions; using Core.Plugins.ProjectExplorer.Commands; using ProjectExplorerResources = Core.Plugins.ProjectExplorer.Properties.Resources; @@ -39,6 +37,7 @@ public class ProjectExplorerGuiPlugin : GuiPlugin { private IToolViewController toolViewController; + private ProjectExplorerViewController projectExplorerViewController; private IDocumentViewController documentViewController; private IViewCommands viewCommands; private IProjectOwner projectOwner; @@ -70,10 +69,6 @@ applicationSelection = value; documentViewController = value; viewCommands = value.ViewCommands; - ribbonCommandHandler = new Ribbon - { - ShowProjectExplorerCommand = new ToggleProjectExplorerCommand(new ProjectExplorerViewController(this, toolViewController)) - }; } else { @@ -83,7 +78,6 @@ documentViewController = null; viewCommands = null; } - } } @@ -129,63 +123,44 @@ } } - public ProjectExplorer ProjectExplorer { get; private set; } - - public void InitializeProjectTreeView() - { - if (ProjectExplorer == null || ProjectExplorer.IsDisposed) - { - ProjectExplorer = new ProjectExplorer(applicationSelection, viewCommands); - - Gui.Plugins - .SelectMany(pluginGui => pluginGui.GetTreeNodeInfos()) - .ForEachElementDo(tni => ProjectExplorer.TreeView.TreeViewController.RegisterTreeNodeInfo(tni)); - - ProjectExplorer.TreeView.TreeViewController.Data = projectOwner.Project; - ProjectExplorer.TreeView.TreeViewController.NodeUpdated += (s, e) => documentViewController.UpdateToolTips(); - ProjectExplorer.Text = Properties.Resources.ProjectExplorerPluginGui_InitializeProjectTreeView_Project_Explorer; - } - - toolViewController.ToolWindowViews.Add(ProjectExplorer, ViewLocation.Left | ViewLocation.Top); - } - public override void Activate() { base.Activate(); - InitializeProjectTreeView(); + projectExplorerViewController = new ProjectExplorerViewController(documentViewController, viewCommands, applicationSelection, toolViewController, Gui.GetTreeNodeInfos()); + ribbonCommandHandler = new Ribbon + { + ShowProjectExplorerCommand = new ToggleProjectExplorerCommand(projectExplorerViewController) + }; + projectExplorerViewController.OnOpenView += (s,e) => UpdateProject(); + projectExplorerViewController.OpenView(); + projectOwner.ProjectOpened += ApplicationProjectOpened; - projectOwner.ProjectClosing += ApplicationProjectClosed; } public override void Dispose() { - if (ProjectExplorer != null) + if (projectExplorerViewController != null) { - ProjectExplorer.Dispose(); - ProjectExplorer = null; + projectExplorerViewController.Dispose(); } - - base.Dispose(); } public override void Deactivate() { base.Deactivate(); projectOwner.ProjectOpened -= ApplicationProjectOpened; - projectOwner.ProjectClosing -= ApplicationProjectClosed; - toolViewController.ToolWindowViews.Remove(ProjectExplorer); } - private void ApplicationProjectClosed(Project project) + private void ApplicationProjectOpened(Project project) { - ProjectExplorer.TreeView.TreeViewController.Data = null; + UpdateProject(); } - private void ApplicationProjectOpened(Project project) + private void UpdateProject() { - ProjectExplorer.TreeView.TreeViewController.Data = project; + projectExplorerViewController.Update(projectOwner.Project); } } } \ No newline at end of file Index: Core/Plugins/src/Core.Plugins.ProjectExplorer/ProjectExplorerViewController.cs =================================================================== diff -u -ra5cdc407e4483b4f0e55e37550a91477be094469 -r83e8ea6f186faad530933f5620faa91f1920d1e1 --- Core/Plugins/src/Core.Plugins.ProjectExplorer/ProjectExplorerViewController.cs (.../ProjectExplorerViewController.cs) (revision a5cdc407e4483b4f0e55e37550a91477be094469) +++ Core/Plugins/src/Core.Plugins.ProjectExplorer/ProjectExplorerViewController.cs (.../ProjectExplorerViewController.cs) (revision 83e8ea6f186faad530933f5620faa91f1920d1e1) @@ -1,36 +1,84 @@ -using Core.Common.Gui; +using System; +using System.Collections.Generic; +using Core.Common.Base.Data; +using Core.Common.Controls.TreeView; +using Core.Common.Gui; +using Core.Common.Gui.Commands; +using Core.Common.Gui.Forms.ViewManager; +using Core.Common.Gui.Selection; namespace Core.Plugins.ProjectExplorer { - public class ProjectExplorerViewController + public class ProjectExplorerViewController : IDisposable { - private readonly IToolViewController controller; - private readonly ProjectExplorerGuiPlugin plugin; + private readonly IToolViewController toolViewController; + private ProjectExplorer projectExplorer; + private readonly IEnumerable treeNodeInfos; + private readonly IApplicationSelection applicationSelection; + private readonly IViewCommands viewCommands; + private readonly IDocumentViewController documentViewController; - public ProjectExplorerViewController(ProjectExplorerGuiPlugin plugin, IToolViewController controller) + public EventHandler OnOpenView; + + public ProjectExplorerViewController(IDocumentViewController documentViewController, IViewCommands viewCommands, IApplicationSelection applicationSelection, IToolViewController toolViewController, IEnumerable treeNodeInfos) { - this.controller = controller; - this.plugin = plugin; + this.toolViewController = toolViewController; + this.applicationSelection = applicationSelection; + this.treeNodeInfos = treeNodeInfos; + this.viewCommands = viewCommands; + this.documentViewController = documentViewController; } public void ToggleView() { - var view = plugin.ProjectExplorer; - var active = controller.ToolWindowViews.Contains(view); - - if (active) + if (IsViewActive()) { - controller.ToolWindowViews.Remove(view); + CloseView(); } else { - plugin.InitializeProjectTreeView(); + OpenView(); } } + public void OpenView() + { + projectExplorer = new ProjectExplorer(applicationSelection, viewCommands, treeNodeInfos); + projectExplorer.TreeView.TreeViewController.NodeUpdated += (s, e) => documentViewController.UpdateToolTips(); + + toolViewController.ToolWindowViews.Add(projectExplorer, ViewLocation.Left | ViewLocation.Top); + + if (OnOpenView != null) + { + OnOpenView(this, EventArgs.Empty); + } + } + + private void CloseView() + { + toolViewController.ToolWindowViews.Remove(projectExplorer); // Disposes the view. + projectExplorer = null; + } + public bool IsViewActive() { - return controller.ToolWindowViews.Contains(plugin.ProjectExplorer); + return toolViewController.IsToolWindowOpen(); } + + public void Update(Project project) + { + if (IsViewActive()) + { + projectExplorer.Data = project; + } + } + + public void Dispose() + { + if (IsViewActive()) + { + CloseView(); + } + } } } \ No newline at end of file Index: Core/Plugins/test/Core.Plugins.ProjectExplorer.Test/ProjectExplorerGuiPluginTest.cs =================================================================== diff -u -rd262d2ed2c6937c2bb555429ae46dc40780720cb -r83e8ea6f186faad530933f5620faa91f1920d1e1 --- Core/Plugins/test/Core.Plugins.ProjectExplorer.Test/ProjectExplorerGuiPluginTest.cs (.../ProjectExplorerGuiPluginTest.cs) (revision d262d2ed2c6937c2bb555429ae46dc40780720cb) +++ Core/Plugins/test/Core.Plugins.ProjectExplorer.Test/ProjectExplorerGuiPluginTest.cs (.../ProjectExplorerGuiPluginTest.cs) (revision 83e8ea6f186faad530933f5620faa91f1920d1e1) @@ -31,7 +31,8 @@ guiStub.Stub(g => g.ApplicationCommands).Return(mocks.Stub()); guiStub.Stub(g => g.ProjectCommands).Return(mocks.Stub()); guiStub.Stub(g => g.ViewCommands).Return(mocks.Stub()); - otherGuiPlugin.Expect(g => g.GetTreeNodeInfos()).Return(new List { new TreeNodeInfo { TagType = typeof(int) } }); + guiStub.Stub(g => g.IsToolWindowOpen()).Return(false); + guiStub.Expect(g => g.GetTreeNodeInfos()).Return(Enumerable.Empty()); Expect.Call(guiStub.ApplicationCore).Return(applicationCore).Repeat.Any(); @@ -60,74 +61,14 @@ // Call projectExplorerGuiPlugin.Activate(); - - // Assert - TreeNodeInfo[] treeNodeInfos = projectExplorerGuiPlugin.ProjectExplorer.TreeView.TreeViewController.TreeNodeInfos.ToArray(); - Assert.AreEqual(2, treeNodeInfos.Length); - Assert.IsTrue(treeNodeInfos.Any(tni => tni.TagType == typeof(Project))); - Assert.IsTrue(treeNodeInfos.Any(tni => tni.TagType == typeof(int))); } + // Assert mocks.VerifyAll(); } [Test] [RequiresSTA] - public void ReopeningProjectExplorerKeepsCustomNodePresenter() - { - // Setup - var mocks = new MockRepository(); - var applicationCore = new ApplicationCore(); - var guiStub = mocks.Stub(); - var otherGuiPlugin = mocks.Stub(); - - guiStub.Stub(g => g.ApplicationCommands).Return(mocks.Stub()); - guiStub.Stub(g => g.ProjectCommands).Return(mocks.Stub()); - guiStub.Stub(g => g.ViewCommands).Return(mocks.Stub()); - otherGuiPlugin.Stub(g => g.GetTreeNodeInfos()).Return(new List { new TreeNodeInfo { TagType = typeof(int) } }); - - Expect.Call(guiStub.ApplicationCore).Return(applicationCore).Repeat.Any(); - - guiStub.Expect(g => g.SelectionChanged += Arg>.Is.Anything).Repeat.Any(); - guiStub.Expect(g => g.SelectionChanged -= Arg>.Is.Anything).Repeat.Any(); - guiStub.Expect(g => g.ProjectOpened += Arg>.Is.Anything).Repeat.Any(); - guiStub.Expect(g => g.ProjectOpened -= Arg>.Is.Anything).Repeat.Any(); - guiStub.Expect(g => g.ProjectClosing += Arg>.Is.Anything).Repeat.Any(); - guiStub.Expect(g => g.ProjectClosing -= Arg>.Is.Anything).Repeat.Any(); - guiStub.Expect(g => g.ToolWindowViews).Return(mocks.Stub()).Repeat.Any(); - guiStub.Expect(g => g.DocumentViews).Return(mocks.Stub()).Repeat.Any(); - - guiStub.Replay(); - - using (var projectExplorerGuiPlugin = new ProjectExplorerGuiPlugin - { - Gui = guiStub - }) - { - guiStub.Expect(g => g.Plugins).Return(new List - { - projectExplorerGuiPlugin, otherGuiPlugin - }).Repeat.Any(); - - mocks.ReplayAll(); - - // Call - projectExplorerGuiPlugin.Activate(); // This will create the project treeview - projectExplorerGuiPlugin.ProjectExplorer.Dispose(); // This is somewhat similar to closing the treeview - projectExplorerGuiPlugin.InitializeProjectTreeView(); // This is what the show command does - - // Assert - TreeNodeInfo[] treeNodeInfos = projectExplorerGuiPlugin.ProjectExplorer.TreeView.TreeViewController.TreeNodeInfos.ToArray(); - Assert.AreEqual(2, treeNodeInfos.Length); - Assert.IsTrue(treeNodeInfos.Any(tni => tni.TagType == typeof(Project))); - Assert.IsTrue(treeNodeInfos.Any(tni => tni.TagType == typeof(int))); - } - - mocks.VerifyAll(); - } - - [Test] - [RequiresSTA] public void GetTreeNodeInfos_ReturnsSupportedTreeNodeInfos() { // setup