Index: Core/Common/src/Core.Common.Gui/Core.Common.Gui.csproj =================================================================== diff -u -r791e86bf9004a55178386416eb6a9c545380bd1c -rf1e2ad82328ef2ef9a8079b79dc405c0a166188a --- Core/Common/src/Core.Common.Gui/Core.Common.Gui.csproj (.../Core.Common.Gui.csproj) (revision 791e86bf9004a55178386416eb6a9c545380bd1c) +++ Core/Common/src/Core.Common.Gui/Core.Common.Gui.csproj (.../Core.Common.Gui.csproj) (revision f1e2ad82328ef2ef9a8079b79dc405c0a166188a) @@ -135,7 +135,6 @@ - Form Index: Core/Common/src/Core.Common.Gui/Forms/MainWindow/IMainWindow.cs =================================================================== diff -u -r791e86bf9004a55178386416eb6a9c545380bd1c -rf1e2ad82328ef2ef9a8079b79dc405c0a166188a --- Core/Common/src/Core.Common.Gui/Forms/MainWindow/IMainWindow.cs (.../IMainWindow.cs) (revision 791e86bf9004a55178386416eb6a9c545380bd1c) +++ Core/Common/src/Core.Common.Gui/Forms/MainWindow/IMainWindow.cs (.../IMainWindow.cs) (revision f1e2ad82328ef2ef9a8079b79dc405c0a166188a) @@ -19,52 +19,70 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; using System.Windows.Forms; using Core.Common.Gui.Forms.MessageWindow; namespace Core.Common.Gui.Forms.MainWindow { /// - /// Main window of a shell application + /// Interface for the main user interface window of the application. /// public interface IMainWindow : IWin32Window { /// - /// Property grid tool window. See also . + /// Gets the property grid tool window. /// IPropertyGrid PropertyGrid { get; } /// - /// Tool window containing log messages. See also . + /// Gets the log messages tool window. /// IMessageWindow MessageWindow { get; } - //TODO: This is inconsistent with the form title which is called .Text /// - /// The window title + /// Gets or sets the title of the main user interface. /// string Title { get; set; } /// - /// Is the window visible? + /// Indicates if the main user interface is visible. /// bool Visible { get; } + /// + /// Gets or sets the status bar text. + /// string StatusBarMessage { get; set; } + /// + /// Shows main user interface. + /// void Show(); /// - /// Closes main window + /// Closes main user interface, shutting it down. /// void Close(); + /// + /// Updates the state of the child controls of the main user interface. + /// void ValidateItems(); + /// + /// Changes the cursor to display a 'waiting' or 'busy' state. + /// void SetWaitCursorOn(); + /// + /// Change the cursor to display the default cursor. + /// void SetWaitCursorOff(); + /// + /// Initializes and shows the property grid tool window. + /// void InitPropertiesWindowAndActivate(); } } \ No newline at end of file Fisheye: Tag f1e2ad82328ef2ef9a8079b79dc405c0a166188a refers to a dead (removed) revision in file `Core/Common/src/Core.Common.Gui/Forms/MainWindow/Interop/NativeWin32.cs'. Fisheye: No comparison available. Pass `N' to diff? Index: Core/Common/src/Core.Common.Gui/Forms/MainWindow/MainWindow.xaml =================================================================== diff -u -r791e86bf9004a55178386416eb6a9c545380bd1c -rf1e2ad82328ef2ef9a8079b79dc405c0a166188a --- Core/Common/src/Core.Common.Gui/Forms/MainWindow/MainWindow.xaml (.../MainWindow.xaml) (revision 791e86bf9004a55178386416eb6a9c545380bd1c) +++ Core/Common/src/Core.Common.Gui/Forms/MainWindow/MainWindow.xaml (.../MainWindow.xaml) (revision f1e2ad82328ef2ef9a8079b79dc405c0a166188a) @@ -42,32 +42,32 @@ - + - + @@ -76,7 +76,7 @@ - @@ -89,10 +89,10 @@ - - - - + + + + @@ -114,21 +114,21 @@ @@ -149,7 +149,7 @@ - + @@ -190,23 +190,9 @@ Grid.Row="2"> - + - - + Index: Core/Common/src/Core.Common.Gui/Forms/MainWindow/MainWindow.xaml.cs =================================================================== diff -u -r791e86bf9004a55178386416eb6a9c545380bd1c -rf1e2ad82328ef2ef9a8079b79dc405c0a166188a --- Core/Common/src/Core.Common.Gui/Forms/MainWindow/MainWindow.xaml.cs (.../MainWindow.xaml.cs) (revision 791e86bf9004a55178386416eb6a9c545380bd1c) +++ Core/Common/src/Core.Common.Gui/Forms/MainWindow/MainWindow.xaml.cs (.../MainWindow.xaml.cs) (revision f1e2ad82328ef2ef9a8079b79dc405c0a166188a) @@ -30,7 +30,6 @@ using System.IO; using System.Linq; using System.Reflection; -using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Forms; @@ -39,7 +38,6 @@ using System.Windows.Media.Imaging; using Core.Common.Gui.Commands; -using Core.Common.Gui.Forms.MainWindow.Interop; using Core.Common.Gui.Forms.MessageWindow; using Core.Common.Gui.Forms.Options; using Core.Common.Gui.Forms.ViewManager; @@ -64,7 +62,7 @@ namespace Core.Common.Gui.Forms.MainWindow { /// - /// Main windows of Ringtoets + /// Main user interface of the application. /// public partial class MainWindow : IMainWindow, IDisposable, ISynchronizeInvoke { @@ -86,64 +84,43 @@ private MessageWindow.MessageWindow messageWindow; private PropertyGridView.PropertyGridView propertyGrid; - private WindowInteropHelper windowInteropHelper; private IEnumerable ribbonCommandHandlers; /// - /// This is used when user selects non-contextual tab explicitly. Then we won't activate contextual tab on the next view activation. + /// This is used when user selects non-contextual tab explicitly. Then we won't + /// activate contextual tab on the next view activation. /// private bool activateContextualTab; /// - /// Used when contextual tab was activated and we switch back to view which does not support contextual tabs. + /// Used when contextual tab was activated and we switch back to view which does + /// not support contextual tabs. /// private string lastNonContextualTab; private IGui gui; + /// + /// Initializes a new instance of the class. + /// public MainWindow() { InitializeComponent(); - windowInteropHelper = new WindowInteropHelper(this); + Handle = new WindowInteropHelper(this).EnsureHandle(); log.Info(Properties.Resources.MainWindow_MainWindow_Main_window_created_); } - public IGui Gui - { - get - { - return gui; - } - set - { - gui = value; - - toolViewController = gui; - documentViewController = gui; - settings = gui; - commands = gui; - applicationSelection = gui; - } - } - + /// + /// Indicates whether this instance is disposed or not. + /// public bool IsWindowDisposed { get; private set; } - public bool Enabled - { - get - { - return IsEnabled; - } - set - { - IsEnabled = value; - NativeWin32.EnableWindow(new HandleRef(this, windowInteropHelper.Handle), value); // prevents resize etc - } - } - + /// + /// Gets the docking manager. + /// public DockingManager DockingManager { get @@ -160,6 +137,10 @@ } } + /// + /// Indicates if the main user interface is visible. + /// + /// When no gui has been set using . public bool Visible { get @@ -168,6 +149,11 @@ } set { + if (gui == null) + { + throw new InvalidOperationException("First call 'SetGui(IGui)' before settings a value on this property."); + } + if (value) { if (IsVisible) @@ -209,13 +195,7 @@ } } - public IntPtr Handle - { - get - { - return windowInteropHelper.Handle; - } - } + public IntPtr Handle { get; private set; } public bool InvokeRequired { @@ -225,6 +205,24 @@ } } + /// + /// Sets the GUI and dependencies. + /// + /// The GUI implementation. + public void SetGui(IGui value) + { + gui = value; + + toolViewController = gui; + documentViewController = gui; + settings = gui; + commands = gui; + applicationSelection = gui; + } + + /// + /// Subscribes the main user interface to the GUI provided by . + /// public void SubscribeToGui() { if (toolViewController != null && toolViewController.ToolWindowViews != null) @@ -238,6 +236,9 @@ } } + /// + /// Unsubscribes the main user interface from the GUI provided by . + /// public void UnsubscribeFromGui() { if (toolViewController != null && toolViewController.ToolWindowViews != null) @@ -251,30 +252,49 @@ } } + /// + /// Loads the layout of the main user interface from AppData. + /// public void LoadLayout() { LoadDockingLayout(); RestoreWindowAppearance(); } + /// + /// Saves the layout of the main user interface to AppData. + /// public void SaveLayout() { SaveWindowAppearance(); SaveDockingLayout(); } + /// + /// Initializes and shows all the tool windows. + /// + /// + /// When a gui hasn't been set with . + /// public void InitializeToolWindows() { InitMessagesWindowOrActivate(); InitPropertiesWindowAndActivate(); } - public void SuspendLayout() {} - - public void ResumeLayout() {} - + /// + /// Initializes and shows the property grid tool window. + /// + /// + /// When a gui hasn't been set with . + /// public void InitPropertiesWindowAndActivate() { + if (gui == null) + { + throw new InvalidOperationException("Must call 'SetGui(IGui)' before calling 'InitPropertiesWindowAndActivate'."); + } + if ((propertyGrid == null) || (propertyGrid.IsDisposed)) { propertyGrid = new PropertyGridView.PropertyGridView(applicationSelection, gui.PropertyResolver); @@ -289,24 +309,30 @@ toolViewController.ToolWindowViews.ActiveView = propertyGrid; } - public void ShowStartPage(bool checkUseSettings = true) + /// + /// Shows the welcome page. + /// + /// If set to true the user settings determine + /// if the start page should be shown. If set to false the welcome page will + /// be shown regardless of user settings. + public void ShowStartPage(bool useUserSettings = true) { - if (!checkUseSettings || Convert.ToBoolean(settings.UserSettings["showStartPage"], CultureInfo.InvariantCulture)) + if (!useUserSettings || Convert.ToBoolean(settings.UserSettings["showStartPage"], CultureInfo.InvariantCulture)) { log.Info(Properties.Resources.MainWindow_ShowStartPage_Adding_welcome_page_); OpenStartPage(); } } + /// + /// Closes all Document views. + /// public void ClearDocumentTabs() { - foreach (var contentToClose in dockingManager.Layout.Descendents().OfType().Where(d => (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).ToArray()) + foreach (var contentToClose in dockingManager.Layout.Descendents().OfType() + .Where(d => (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow) && d.CanClose) + .ToArray()) { - if (!contentToClose.CanClose) - { - continue; - } - if (contentToClose is LayoutDocument) { CloseContent(contentToClose as LayoutDocument); @@ -338,8 +364,6 @@ return; } - // TODO: add dispose code - IsWindowDisposed = true; if (dockingManager.AutoHideWindow != null) @@ -399,22 +423,18 @@ } ribbonCommandHandlers = null; - windowInteropHelper = null; - Gui = null; - - // Dispatcher.InvokeShutdown(); - //System.Windows.Threading.Dispatcher.CurrentDispatcher.InvokeShutdown(); + SetGui(null); } public void ValidateItems() { - if (Gui == null) + if (gui == null) { return; } - ValidateMainWindowRibbonItems(); + UpdateToolWindowButtonState(); if (ribbonCommandHandlers == null) { @@ -463,6 +483,8 @@ Mouse.OverrideCursor = null; } + #region Implementation: ISynchronizeInvoke + public IAsyncResult BeginInvoke(Delegate method, object[] args) { Dispatcher.BeginInvoke(method, args); @@ -479,6 +501,8 @@ return Dispatcher.Invoke(method, args); } + #endregion + private void ToolWindowViews_CollectionChanged(object sender, NotifyCollectionChangeEventArgs e) { if (e.Action != NotifyCollectionChangeAction.Remove) @@ -561,48 +585,36 @@ foreach (var recent in mruList) { - AddNewMruItem(recent, false); + AddNewMruItem(recent); } } - private void AddNewMruItem(string path, bool putOnTop = true) + private void AddNewMruItem(string path) { - var newItem = new TabItem + if (!RecentProjectsTabControl.Items.OfType().Any(i => Equals(i.Header, path))) { - Header = path - }; - newItem.MouseDoubleClick += (sender, args) => - { - try + var newItem = new TabItem { - commands.StorageCommands.OpenExistingProject(path); - RecentProjectsTabControl.Items.Remove(newItem); - RecentProjectsTabControl.Items.Insert(1, newItem); - } - catch (Exception) + Header = path + }; + newItem.MouseDoubleClick += (sender, args) => { - //remove item from the list if it cannot be retrieved from file - RecentProjectsTabControl.Items.Remove(newItem); - log.WarnFormat("{0} {1}", Properties.Resources.MainWindow_AddNewMruItem_Can_t_open_project, path); - } - finally - { + if (commands.StorageCommands.OpenExistingProject(path)) + { + RecentProjectsTabControl.Items.Remove(newItem); + RecentProjectsTabControl.Items.Insert(1, newItem); + } + else + { + //remove item from the list if it cannot be retrieved from file + RecentProjectsTabControl.Items.Remove(newItem); + log.WarnFormat("{0} {1}", Properties.Resources.MainWindow_AddNewMruItem_Can_t_open_project, path); + } + CommitMruToSettings(); ValidateItems(); Menu.IsOpen = false; - } - }; - if (RecentProjectsTabControl.Items.OfType().Any(i => Equals(i.Header, path))) - { - return; - } - - if (putOnTop) - { - RecentProjectsTabControl.Items.Insert(1, newItem); - } - else - { + }; RecentProjectsTabControl.Items.Add(newItem); } } @@ -626,7 +638,7 @@ private void OnLayoutRootPropertyChanged(object sender, PropertyChangedEventArgs e) {} - private void ValidateMainWindowRibbonItems() + private void UpdateToolWindowButtonState() { if (toolViewController.ToolWindowViews != null) { @@ -637,6 +649,11 @@ private void InitMessagesWindowOrActivate() { + if (gui == null) + { + throw new InvalidOperationException("Must call 'SetGui(IGui)' before calling 'InitMessagesWindowOrActivate'."); + } + if (messageWindow == null || messageWindow.IsDisposed) { messageWindow = new MessageWindow.MessageWindow(this) @@ -661,14 +678,14 @@ private void OnFileSaveClicked(object sender, RoutedEventArgs e) { - var saveProject = commands.StorageCommands.SaveProject(); - OnAfterProjectSaveOrOpen(saveProject); + var saveSuccesful = commands.StorageCommands.SaveProject(); + OnAfterProjectSaveOrOpen(saveSuccesful); } private void OnFileSaveAsClicked(object sender, RoutedEventArgs e) { - var saveProject = commands.StorageCommands.SaveProjectAs(); - OnAfterProjectSaveOrOpen(saveProject); + var saveSuccesful = commands.StorageCommands.SaveProjectAs(); + OnAfterProjectSaveOrOpen(saveSuccesful); } private void OnAfterProjectSaveOrOpen(bool actionSuccesful) @@ -701,7 +718,7 @@ private void OnFileExitClicked(object sender, RoutedEventArgs e) { - Gui.Exit(); + gui.Exit(); } private string GetLayoutFilePath() @@ -750,13 +767,13 @@ try { - var settings = File.ReadAllText(ribbonSettingsPath).Split('|'); - if (settings.Length != 2) + var tokenizedRibbonSettings = File.ReadAllText(ribbonSettingsPath).Split('|'); + if (tokenizedRibbonSettings.Length != 2) { return; } - var ribbonStateSettings = settings[0].Split(','); + var ribbonStateSettings = tokenizedRibbonSettings[0].Split(','); Ribbon.IsMinimized = bool.Parse(ribbonStateSettings[0]); Ribbon.ShowQuickAccessToolBarAboveRibbon = bool.Parse(ribbonStateSettings[1]); } Index: Core/Common/src/Core.Common.Gui/RingtoetsGui.cs =================================================================== diff -u -rd52ae535aea52b4e43aa6837305502e6cd911a92 -rf1e2ad82328ef2ef9a8079b79dc405c0a166188a --- Core/Common/src/Core.Common.Gui/RingtoetsGui.cs (.../RingtoetsGui.cs) (revision d52ae535aea52b4e43aa6837305502e6cd911a92) +++ Core/Common/src/Core.Common.Gui/RingtoetsGui.cs (.../RingtoetsGui.cs) (revision f1e2ad82328ef2ef9a8079b79dc405c0a166188a) @@ -667,21 +667,17 @@ private void InitializeMenusAndToolbars() { log.Info(Resources.RingtoetsGui_InitializeMenusAndToolbars_Setting_up_menus_and_toolbars); - mainWindow.SuspendLayout(); // Validate once when loading is completed mainWindow.ValidateItems(); - mainWindow.ResumeLayout(); log.Info(Resources.RingtoetsGui_InitializeMenusAndToolbars_Menus_and_toolbars_are_ready); } private void ActivatePlugins() { var problematicPlugins = new List(); - mainWindow.SuspendLayout(); - // Try to activate all plugins foreach (var plugin in Plugins) { @@ -700,8 +696,6 @@ { DeactivatePlugin(problematicPlugin); } - - mainWindow.ResumeLayout(); } private void CopyDefaultViewsFromUserSettings() @@ -1027,7 +1021,7 @@ private set { mainWindow = (MainWindow)value; - mainWindow.Gui = this; + mainWindow.SetGui(this); } } Index: Core/Common/test/Core.Common.Gui.Test/Core.Common.Gui.Test.csproj =================================================================== diff -u -rce50b65f662bcccb1849444e4d51549731131234 -rf1e2ad82328ef2ef9a8079b79dc405c0a166188a --- Core/Common/test/Core.Common.Gui.Test/Core.Common.Gui.Test.csproj (.../Core.Common.Gui.Test.csproj) (revision ce50b65f662bcccb1849444e4d51549731131234) +++ Core/Common/test/Core.Common.Gui.Test/Core.Common.Gui.Test.csproj (.../Core.Common.Gui.Test.csproj) (revision f1e2ad82328ef2ef9a8079b79dc405c0a166188a) @@ -33,10 +33,18 @@ pdbonly + + ..\..\..\..\packages\Fluent.Ribbon.3.4.0\lib\net40\Fluent.dll + True + ..\..\..\..\packages\log4net.2.0.4\lib\net40-full\log4net.dll True + + ..\..\..\..\packages\Fluent.Ribbon.3.4.0\lib\net40\Microsoft.Windows.Shell.dll + True + ..\..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll True @@ -52,8 +60,32 @@ + + ..\..\..\..\packages\Fluent.Ribbon.3.4.0\lib\net40\System.Windows.Interactivity.dll + True + + + ..\..\..\..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.dll + True + + + ..\..\..\..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.Aero.dll + True + + + ..\..\..\..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.Expression.dll + True + + + ..\..\..\..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.Metro.dll + True + + + ..\..\..\..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.VS2010.dll + True + @@ -78,6 +110,7 @@ + True True Index: Core/Common/test/Core.Common.Gui.Test/Forms/MainWindow/MainWindowTest.cs =================================================================== diff -u --- Core/Common/test/Core.Common.Gui.Test/Forms/MainWindow/MainWindowTest.cs (revision 0) +++ Core/Common/test/Core.Common.Gui.Test/Forms/MainWindow/MainWindowTest.cs (revision f1e2ad82328ef2ef9a8079b79dc405c0a166188a) @@ -0,0 +1,752 @@ +using System; +using System.ComponentModel; +using System.Configuration; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +using Core.Common.Gui.Commands; +using Core.Common.Gui.Forms; +using Core.Common.Gui.Forms.MainWindow; +using Core.Common.Gui.Forms.MessageWindow; +using Core.Common.Gui.Forms.PropertyGridView; +using Core.Common.Gui.Forms.ViewManager; +using Core.Common.Gui.Plugin; +using Core.Common.Gui.PropertyBag; +using Core.Common.Gui.Settings; +using Core.Common.Gui.Theme; +using Core.Common.Utils; +using Core.Common.Utils.Events; +using Core.Common.Utils.Reflection; + +using NUnit.Framework; + +using Rhino.Mocks; + +using FlowDirection = System.Windows.FlowDirection; + +namespace Core.Common.Gui.Test.Forms.MainWindow +{ + [TestFixture] + public class MainWindowTest + { + [Test] + [STAThread] + public void DefaultConstructor_ExpectedValues() + { + // Call + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + // Assert + Assert.IsInstanceOf(mainWindow); + Assert.IsInstanceOf(mainWindow); + Assert.IsInstanceOf(mainWindow); + + Assert.IsFalse(mainWindow.IsWindowDisposed); + Assert.IsFalse(mainWindow.Visible); + Assert.IsTrue(mainWindow.DockingManager.AllowMixedOrientation); + + Assert.IsNull(mainWindow.MessageWindow); + Assert.IsNull(mainWindow.PropertyGrid); + + Assert.AreEqual(string.Empty, mainWindow.StatusBarMessage); + + Assert.IsNotNull(mainWindow.Handle); + Assert.IsFalse(mainWindow.InvokeRequired, + "'mainWindow' instance on same thread as test, therefore invocation not required."); + + Assert.AreEqual("MainWindow", mainWindow.Title); + Assert.AreEqual(ResizeMode.CanResizeWithGrip, mainWindow.ResizeMode); + Assert.AreEqual(FlowDirection.LeftToRight, mainWindow.FlowDirection); + } + } + + [Test] + [STAThread] + public void Dispose_SetIsWindowDisposedTrue() + { + // Setup + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + // Call + mainWindow.Dispose(); + + // Assert + Assert.IsTrue(mainWindow.IsWindowDisposed); + } + } + + [Test] + [TestCase(true)] + [TestCase(false)] + [STAThread] + public void Visible_SettingValueWithoutHavingSetGui_ThrowInvalidOperationException(bool newVisibleValue) + { + // Setup + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + // Call + TestDelegate call = () => mainWindow.Visible = newVisibleValue; + + // Assert + Assert.Throws(call); + } + } + + [Test] + [STAThread] + public void Visible_SetToTrue_ShowMainForm() + { + // Setup + var mocks = new MockRepository(); + var settings = mocks.Stub(); + settings["colorTheme"] = ColorTheme.Generic; + + var toolViewsList = mocks.Stub(); + toolViewsList.Stub(l => l.Contains(Arg.Is.Anything)) + .Return(false); + toolViewsList.Stub(l => l.Contains(Arg.Is.Anything)) + .Return(false); + + var gui = mocks.Stub(); + gui.Stub(g => g.UserSettings).Return(settings); + gui.Stub(g => g.FixedSettings).Return(new GuiCoreSettings()); + gui.Stub(g => g.Plugins).Return(Enumerable.Empty().ToList()); + gui.Stub(g => g.ToolWindowViews).Return(toolViewsList); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + + // Call + mainWindow.Visible = true; + + // Assert + Assert.IsTrue(mainWindow.Visible); + Assert.IsTrue(mainWindow.IsVisible); + Assert.AreEqual(Visibility.Visible, mainWindow.Visibility); + } + mocks.VerifyAll(); + } + + [Test] + [STAThread] + public void Visible_SetToFalse_HideMainForm() + { + // Setup + var mocks = new MockRepository(); + var settings = mocks.Stub(); + settings["colorTheme"] = ColorTheme.Generic; + + var toolViewsList = mocks.Stub(); + toolViewsList.Stub(l => l.Contains(Arg.Is.Anything)) + .Return(false); + toolViewsList.Stub(l => l.Contains(Arg.Is.Anything)) + .Return(false); + + var gui = mocks.Stub(); + gui.Stub(g => g.UserSettings).Return(settings); + gui.Stub(g => g.FixedSettings).Return(new GuiCoreSettings()); + gui.Stub(g => g.Plugins).Return(Enumerable.Empty().ToList()); + gui.Stub(g => g.ToolWindowViews).Return(toolViewsList); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + mainWindow.Visible = true; + + // Call + mainWindow.Visible = false; + + // Assert + Assert.IsFalse(mainWindow.Visible); + Assert.IsFalse(mainWindow.IsVisible); + Assert.AreEqual(Visibility.Hidden, mainWindow.Visibility); + } + mocks.VerifyAll(); + } + + [Test] + [STAThread] + public void StatusBarMessage_SetValue_ReturnNewlySetValue() + { + // Setup + const string message = ""; + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + // Call + mainWindow.StatusBarMessage = message; + + // Assert + Assert.AreEqual(message, TypeUtils.GetField(mainWindow, "StatusMessageTextBlock").Text); + Assert.AreEqual(message, mainWindow.StatusBarMessage); + } + } + + [Test] + [STAThread] + public void SubscribeToGui_NoGuiSet_DoNothing() + { + // Setup + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + // Call + TestDelegate call = () => mainWindow.SubscribeToGui(); + + // Assert + Assert.DoesNotThrow(call); + } + } + + [Test] + [STAThread] + public void SubscribeToGui_GuiSet_AttachEvents() + { + // Setup + var mocks = new MockRepository(); + var toolWindowsList = mocks.Stub(); + toolWindowsList.Expect(l => l.CollectionChanged += null).IgnoreArguments(); + + var documentViewsList = mocks.Stub(); + documentViewsList.Expect(l => l.ActiveViewChanged += null).IgnoreArguments(); + documentViewsList.Expect(l => l.ActiveViewChanging += null).IgnoreArguments(); // Should happen during dispose + + var gui = mocks.Stub(); + gui.Stub(g => g.ToolWindowViews).Return(toolWindowsList); + gui.Stub(g => g.DocumentViews).Return(documentViewsList); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + + // Call + mainWindow.SubscribeToGui(); + } + // Assert + mocks.VerifyAll(); // Expect event subscription + } + + [Test] + [STAThread] + public void GivenSubscribedToGui_WhenPropertyGridRemovedEvent_ThenPropertyGridCleared() + { + // Setup + var mocks = new MockRepository(); + var toolWindowsList = mocks.Stub(); + toolWindowsList.Expect(l => l.CollectionChanged += null).IgnoreArguments(); + toolWindowsList.Stub(l => l.Contains(null)).IgnoreArguments() + .Return(false); + toolWindowsList.Stub(l => l.Add(null, ViewLocation.Right)).IgnoreArguments(); + + var documentViewsList = mocks.Stub(); + documentViewsList.Expect(l => l.ActiveViewChanged += null).IgnoreArguments(); + documentViewsList.Expect(l => l.ActiveViewChanging += null).IgnoreArguments(); // Should happen during dispose + + var propertyResolver = mocks.Stub(); + propertyResolver.Stub(r => r.GetObjectProperties(null)).IgnoreArguments().Return(null); + + var gui = mocks.Stub(); + gui.Stub(g => g.ToolWindowViews).Return(toolWindowsList); + gui.Stub(g => g.DocumentViews).Return(documentViewsList); + gui.Stub(g => g.PropertyResolver).Return(propertyResolver); + gui.Stub(g => g.SelectionChanged += null).IgnoreArguments(); + gui.Stub(g => g.SelectionChanged -= null).IgnoreArguments(); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + mainWindow.InitializeToolWindows(); + + // Precondition: + Assert.IsNotNull(mainWindow.PropertyGrid); + + // Call + mainWindow.SubscribeToGui(); + toolWindowsList.Raise(l => l.CollectionChanged += null, + toolWindowsList, + new NotifyCollectionChangeEventArgs(NotifyCollectionChangeAction.Remove, mainWindow.PropertyGrid, -1, 0)); + // Assert + Assert.IsNull(mainWindow.PropertyGrid); + } + mocks.VerifyAll(); + } + + [Test] + [STAThread] + public void GivenSubscribedToGui_WhenMessageWindowRemovedEvent_ThenMessageWindowCleared() + { + // Setup + var mocks = new MockRepository(); + var toolWindowsList = mocks.Stub(); + toolWindowsList.Expect(l => l.CollectionChanged += null).IgnoreArguments(); + toolWindowsList.Stub(l => l.Contains(null)).IgnoreArguments() + .Return(false); + toolWindowsList.Stub(l => l.Add(null, ViewLocation.Right)).IgnoreArguments(); + + var documentViewsList = mocks.Stub(); + documentViewsList.Expect(l => l.ActiveViewChanged += null).IgnoreArguments(); + documentViewsList.Expect(l => l.ActiveViewChanging += null).IgnoreArguments(); // Should happen during dispose + + var propertyResolver = mocks.Stub(); + propertyResolver.Stub(r => r.GetObjectProperties(null)).IgnoreArguments().Return(null); + + var gui = mocks.Stub(); + gui.Stub(g => g.ToolWindowViews).Return(toolWindowsList); + gui.Stub(g => g.DocumentViews).Return(documentViewsList); + gui.Stub(g => g.PropertyResolver).Return(propertyResolver); + gui.Stub(g => g.SelectionChanged += null).IgnoreArguments(); + gui.Stub(g => g.SelectionChanged -= null).IgnoreArguments(); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + mainWindow.InitializeToolWindows(); + + // Precondition: + Assert.IsNotNull(mainWindow.MessageWindow); + + // Call + mainWindow.SubscribeToGui(); + toolWindowsList.Raise(l => l.CollectionChanged += null, + toolWindowsList, + new NotifyCollectionChangeEventArgs(NotifyCollectionChangeAction.Remove, mainWindow.MessageWindow, -1, 0)); + // Assert + Assert.IsNull(mainWindow.MessageWindow); + } + mocks.VerifyAll(); + } + + [Test] + [STAThread] + public void UnsubscribeFromGui_NoGuiSet_DoNothing() + { + // Setup + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + // Call + TestDelegate call = () => mainWindow.UnsubscribeFromGui(); + + // Assert + Assert.DoesNotThrow(call); + } + } + + [Test] + [STAThread] + public void UnsubscribeFromGui_GuiSetAndSubscribed_DetachEvents() + { + // Setup + var mocks = new MockRepository(); + var toolWindowsList = mocks.Stub(); + toolWindowsList.Expect(l => l.CollectionChanged += null).IgnoreArguments(); + toolWindowsList.Expect(l => l.CollectionChanged -= null).IgnoreArguments(); + + var documentViewsList = mocks.Stub(); + documentViewsList.Expect(l => l.ActiveViewChanged += null).IgnoreArguments(); + documentViewsList.Expect(l => l.ActiveViewChanging += null).IgnoreArguments(); + documentViewsList.Expect(l => l.ActiveViewChanged -= null).IgnoreArguments(); + documentViewsList.Expect(l => l.ActiveViewChanging -= null).IgnoreArguments(); + + var gui = mocks.Stub(); + gui.Stub(g => g.ToolWindowViews).Return(toolWindowsList); + gui.Stub(g => g.DocumentViews).Return(documentViewsList); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + mainWindow.SubscribeToGui(); + + // Call + mainWindow.UnsubscribeFromGui(); + } + // Assert + mocks.VerifyAll(); // Expect event subscription and desubscription + } + + [Test] + [STAThread] + public void InitPropertiesWindowAndActivate_GuiNotSet_ThrowInvalidOperationException() + { + // Setup + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + // Call + TestDelegate call = () => mainWindow.InitPropertiesWindowAndActivate(); + + // Assert + Assert.Throws(call); + } + } + + [Test] + [STAThread] + public void InitPropertiesWindowAndActivate_GuiSet_InitializePropertyGridAndMakeActive() + { + // Setup + var selectedObject = new object(); + + var mocks = new MockRepository(); + var selectedObjectProperties = mocks.Stub(); + + var toolWindowList = mocks.Stub(); + toolWindowList.Expect(l => l.Add(Arg.Matches(grid => + grid.Text == "Eigenschappen" && + grid.Data == selectedObjectProperties), + Arg.Is.Equal(ViewLocation.Right | ViewLocation.Bottom))); + + var propertyResolver = mocks.Stub(); + propertyResolver.Expect(r => r.GetObjectProperties(selectedObject)) + .Return(selectedObjectProperties); + + var gui = mocks.Stub(); + gui.Stub(g => g.ToolWindowViews).Return(toolWindowList); + gui.Selection = selectedObject; + gui.Stub(g => g.PropertyResolver).Return(propertyResolver); + gui.Stub(g => g.SelectionChanged += null).IgnoreArguments(); + gui.Stub(g => g.SelectionChanged -= null).IgnoreArguments(); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + + // Call + mainWindow.InitPropertiesWindowAndActivate(); + + // Assert + Assert.IsInstanceOf(toolWindowList.ActiveView); + Assert.AreEqual("Eigenschappen", toolWindowList.ActiveView.Text); + Assert.AreEqual(selectedObjectProperties, toolWindowList.ActiveView.Data); + + Assert.AreSame(toolWindowList.ActiveView, mainWindow.PropertyGrid, + "PropertyGrid should now be initialized."); + } + mocks.VerifyAll(); + } + + [Test] + [STAThread] + public void InitPropertiesWindowAndActivate_GuiSetAndCalledTwice_UpdateAlreadyExistingPropertyGridViewInstance() + { + // Setup + var selectedObject = new object(); + + var mocks = new MockRepository(); + var selectedObjectProperties = mocks.Stub(); + + var toolWindowList = mocks.Stub(); + toolWindowList.Expect(l => l.Add(Arg.Matches(grid => + grid.Text == "Eigenschappen" && + grid.Data == selectedObjectProperties), + Arg.Is.Equal(ViewLocation.Right | ViewLocation.Bottom))); + + var propertyResolver = mocks.Stub(); + propertyResolver.Expect(r => r.GetObjectProperties(selectedObject)) + .Return(selectedObjectProperties) + .Repeat.Twice(); + + var gui = mocks.Stub(); + gui.Stub(g => g.ToolWindowViews).Return(toolWindowList); + gui.Selection = selectedObject; + gui.Stub(g => g.PropertyResolver).Return(propertyResolver); + gui.Stub(g => g.SelectionChanged += null).IgnoreArguments(); + gui.Stub(g => g.SelectionChanged -= null).IgnoreArguments(); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + + mainWindow.InitPropertiesWindowAndActivate(); + var originalPropertyGrid = mainWindow.PropertyGrid; + + // Call + mainWindow.InitPropertiesWindowAndActivate(); + + // Assert + Assert.AreSame(originalPropertyGrid, toolWindowList.ActiveView); + Assert.AreSame(originalPropertyGrid, mainWindow.PropertyGrid, + "PropertyGrid instance should remain the same."); + + Assert.AreEqual("Eigenschappen", mainWindow.PropertyGrid.Text); + Assert.AreEqual(selectedObjectProperties, mainWindow.PropertyGrid.Data); + } + mocks.VerifyAll(); + } + + [Test] + [STAThread] + public void InitializeToolWindows_GuiNotSet_ThrowInvalidOperationException() + { + // Setup + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + // Call + TestDelegate call = () => mainWindow.InitializeToolWindows(); + + // Assert + Assert.Throws(call); + } + } + + [Test] + [STAThread] + [TestCase(false)] + [TestCase(true)] + public void InitializeToolWindows_GuiSet_InitializePropertyGridAndMessageWindowAndMakeActive(bool messageWindowAddedToViewList) + { + // Setup + var selectedObject = new object(); + + var mocks = new MockRepository(); + var selectedObjectProperties = mocks.Stub(); + + var toolWindowList = mocks.Stub(); + toolWindowList.Expect(l => l.Add(Arg.Matches(grid => + grid.Text == "Eigenschappen" && + grid.Data == selectedObjectProperties), + Arg.Is.Equal(ViewLocation.Right | ViewLocation.Bottom))); + + toolWindowList.Stub(l => l.Contains(Arg.Matches(messages => messages.Text == "Berichten"))) + .Return(messageWindowAddedToViewList); + if (!messageWindowAddedToViewList) + { + toolWindowList.Expect(l => l.Add(Arg.Matches(messages => messages.Text == "Berichten"), + Arg.Is.Equal(ViewLocation.Bottom))); + } + + var propertyResolver = mocks.Stub(); + propertyResolver.Expect(r => r.GetObjectProperties(selectedObject)) + .Return(selectedObjectProperties); + + var gui = mocks.Stub(); + gui.Stub(g => g.ToolWindowViews).Return(toolWindowList); + gui.Selection = selectedObject; + gui.Stub(g => g.PropertyResolver).Return(propertyResolver); + gui.Stub(g => g.SelectionChanged += null).IgnoreArguments(); + gui.Stub(g => g.SelectionChanged -= null).IgnoreArguments(); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + + // Call + mainWindow.InitializeToolWindows(); + + // Assert + Assert.IsInstanceOf(mainWindow.PropertyGrid); + Assert.AreEqual("Eigenschappen", mainWindow.PropertyGrid.Text); + Assert.AreEqual(selectedObjectProperties, mainWindow.PropertyGrid.Data); + + Assert.IsInstanceOf(mainWindow.MessageWindow); + Assert.AreEqual("Berichten", mainWindow.MessageWindow.Text); + + Assert.AreSame(mainWindow.PropertyGrid, toolWindowList.ActiveView, + "PropertyGrid should be active view."); + } + mocks.VerifyAll(); + } + + [Test] + [STAThread] + public void ShowStartPage_IgnoreUserSettings_OpenViewForWebPage() + { + // Setup + const string pageName = ""; + var fixedSettings = new GuiCoreSettings + { + StartPageUrl = "http://www.google.nl" + }; + + var mocks = new MockRepository(); + + var userSettings = mocks.Stub(); + userSettings["startPageName"] = pageName; + + var viewCommands = mocks.Stub(); + viewCommands.Expect(c => c.OpenView(Arg.Matches(link => link.Name == pageName && + link.Path == new Uri(fixedSettings.StartPageUrl)))); + + var gui = mocks.Stub(); + gui.Stub(g => g.FixedSettings).Return(fixedSettings); + gui.Stub(g => g.UserSettings).Return(userSettings); + gui.Stub(g => g.ViewCommands).Return(viewCommands); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + + // Call + mainWindow.ShowStartPage(false); + } + // Assert + mocks.VerifyAll(); // Assert that expectancies are met + } + + [Test] + [STAThread] + [TestCase(null)] + [TestCase("")] + public void ShowStartPage_IgnoreUserSettingsAndNoStartPageUrl_OpenViewForAboutBlank(string startPageNameValue) + { + // Setup + var fixedSettings = new GuiCoreSettings + { + StartPageUrl = "about:blank" + }; + + var mocks = new MockRepository(); + + var userSettings = mocks.Stub(); + userSettings["startPageName"] = startPageNameValue; + + var viewCommands = mocks.Stub(); + viewCommands.Expect(c => c.OpenView(Arg.Matches(link => link.Name == startPageNameValue && + link.Path == new Uri(fixedSettings.StartPageUrl)))); + + var gui = mocks.Stub(); + gui.Stub(g => g.FixedSettings).Return(fixedSettings); + gui.Stub(g => g.UserSettings).Return(userSettings); + gui.Stub(g => g.ViewCommands).Return(viewCommands); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + + // Call + mainWindow.ShowStartPage(false); + } + // Assert + mocks.VerifyAll(); // Assert that expectancies are met + } + + [Test] + [STAThread] + public void ShowStartPage_FromUserSettings_OpenViewForWebPage() + { + // Setup + const string pageName = ""; + var fixedSettings = new GuiCoreSettings + { + StartPageUrl = "http://www.google.nl" + }; + + var mocks = new MockRepository(); + + var userSettings = mocks.Stub(); + userSettings["startPageName"] = pageName; + userSettings["showStartPage"] = true.ToString(); + + var viewCommands = mocks.Stub(); + viewCommands.Expect(c => c.OpenView(Arg.Matches(link => link.Name == pageName && + link.Path == new Uri(fixedSettings.StartPageUrl)))); + + var gui = mocks.Stub(); + gui.Stub(g => g.FixedSettings).Return(fixedSettings); + gui.Stub(g => g.UserSettings).Return(userSettings); + gui.Stub(g => g.ViewCommands).Return(viewCommands); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + + // Call + mainWindow.ShowStartPage(true); + } + // Assert + mocks.VerifyAll(); // Assert that expectancies are met + } + + [Test] + [STAThread] + public void ShowStartPage_FromUserSettingsWithShowStartPageFalse_DoNothing() + { + // Setup + var fixedSettings = new GuiCoreSettings(); + + var mocks = new MockRepository(); + + var userSettings = mocks.Stub(); + userSettings["showStartPage"] = false.ToString(); + + var viewCommands = mocks.StrictMock(); + + var gui = mocks.Stub(); + gui.Stub(g => g.FixedSettings).Return(fixedSettings); + gui.Stub(g => g.UserSettings).Return(userSettings); + gui.Stub(g => g.ViewCommands).Return(viewCommands); + mocks.ReplayAll(); + + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetGui(gui); + + // Call + mainWindow.ShowStartPage(); + } + // Assert + mocks.VerifyAll(); // Assert that expectancies are met + } + + [Test] + [STAThread] + public void SetWaitCursorOn_SetMouseOverrideToWait() + { + // Setup + Cursor originalValue = Mouse.OverrideCursor; + + try + { + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + // Call + mainWindow.SetWaitCursorOn(); + + // Assert + Assert.AreEqual(Cursors.Wait, Mouse.OverrideCursor); + } + } + finally + { + Mouse.OverrideCursor = originalValue; + } + } + + [Test] + [STAThread] + public void SetWaitCursorOff_SetMouseOverrideToNull() + { + // Setup + Cursor originalValue = Mouse.OverrideCursor; + + try + { + using (var mainWindow = new Gui.Forms.MainWindow.MainWindow()) + { + mainWindow.SetWaitCursorOn(); + + // Call + mainWindow.SetWaitCursorOff(); + + // Assert + Assert.IsNull(Mouse.OverrideCursor); + } + } + finally + { + Mouse.OverrideCursor = originalValue; + } + } + } +} \ No newline at end of file Index: Core/Common/test/Core.Common.Gui.Test/packages.config =================================================================== diff -u -r09e8f3d20ef762a75ac211870d3843b671516983 -rf1e2ad82328ef2ef9a8079b79dc405c0a166188a --- Core/Common/test/Core.Common.Gui.Test/packages.config (.../packages.config) (revision 09e8f3d20ef762a75ac211870d3843b671516983) +++ Core/Common/test/Core.Common.Gui.Test/packages.config (.../packages.config) (revision f1e2ad82328ef2ef9a8079b79dc405c0a166188a) @@ -1,5 +1,7 @@  + +