Commit 345a4aa

mokhan <mokhan@ce5e1baf-6525-42e4-a1b2-857ea38da20a>
2009-03-28 19:14:43
refactoring to run commands via the asynchronous command processor.
git-svn-id: https://svn.xp-dev.com/svn/mokhan-mo.money@120 ce5e1baf-6525-42e4-a1b2-857ea38da20a
1 parent 7d3cf94
trunk/product/MyMoney/boot/container/registration/wire_up_the_presentation_modules.cs
@@ -1,5 +1,6 @@
 using System.Reflection;
 using MoMoney.Infrastructure.Container;
+using MoMoney.Infrastructure.reflection;
 using MoMoney.Presentation.Core;
 using MoMoney.Presentation.Model.Menu.File;
 using MoMoney.Presentation.Model.Menu.Help;
@@ -10,7 +11,7 @@ using MoMoney.Utility.Extensions;
 
 namespace MoMoney.boot.container.registration
 {
-    internal class wire_up_the_presentation_modules : ICommand
+    internal class wire_up_the_presentation_modules : ICommand, IParameterizedCommand<IAssembly>
     {
         readonly IDependencyRegistration registry;
 
@@ -20,22 +21,25 @@ namespace MoMoney.boot.container.registration
         }
 
         public void run()
+        {
+            run(new ApplicationAssembly(Assembly.GetExecutingAssembly()));
+        }
+
+        public void run(IAssembly item)
         {
             registry.transient(typeof (IRunThe<>), typeof (RunThe<>));
             registry.transient<IFileMenu, FileMenu>();
             registry.transient<IWindowMenu, WindowMenu>();
             registry.transient<IHelpMenu, HelpMenu>();
 
-            Assembly
-                .GetExecutingAssembly()
-                .GetTypes()
+            item
+                .all_types()
                 .where(x => typeof (IPresenter).IsAssignableFrom(x))
                 .where(x => !x.IsInterface)
                 .each(type => registry.transient(typeof (IPresenter), type));
 
-            Assembly
-                .GetExecutingAssembly()
-                .GetTypes()
+            item
+                .all_types()
                 .where(x => typeof (IPresentationModule).IsAssignableFrom(x))
                 .where(x => !x.IsInterface)
                 .each(type => registry.transient(typeof (IPresentationModule), type));
trunk/product/MyMoney/boot/start_the_application.cs
@@ -4,6 +4,7 @@ using MoMoney.Infrastructure.Container;
 using MoMoney.Infrastructure.eventing;
 using MoMoney.Infrastructure.Extensions;
 using MoMoney.Infrastructure.interceptors;
+using MoMoney.Infrastructure.Threading;
 using MoMoney.Presentation.Model.messages;
 using MoMoney.Presentation.Presenters.Commands;
 using MoMoney.Presentation.Views.Shell;
@@ -28,6 +29,7 @@ namespace MoMoney.boot
         {
             try
             {
+                resolve.dependency_for<ICommandProcessor>().run();
                 command.run();
                 Application.Run(resolve.dependency_for<ApplicationShell>());
             }
trunk/product/MyMoney/Infrastructure/System/application_environment.cs → trunk/product/MyMoney/Infrastructure/System/ApplicationEnvironment.cs
@@ -1,4 +1,5 @@
 using System.Windows.Forms;
+using MoMoney.Infrastructure.Threading;
 
 namespace MoMoney.Infrastructure.System
 {
@@ -8,16 +9,25 @@ namespace MoMoney.Infrastructure.System
         void restart();
     }
 
-    public class application_environment : IApplicationEnvironment
+    public class ApplicationEnvironment : IApplicationEnvironment
     {
+        readonly ICommandProcessor processor;
+
+        public ApplicationEnvironment(ICommandProcessor processor)
+        {
+            this.processor = processor;
+        }
+
         public void shut_down()
         {
+            processor.stop();
             Application.Exit();
             //Environment.Exit(Environment.ExitCode);
         }
 
         public void restart()
         {
+            processor.stop();
             Application.Restart();
         }
     }
trunk/product/MyMoney/Infrastructure/Threading/AsynchronousCommandProcessor.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Collections.Generic;
 using System.Threading;
 using MoMoney.Utility.Core;
@@ -8,6 +9,8 @@ namespace MoMoney.Infrastructure.Threading
     {
         readonly Queue<ICommand> queued_commands;
         readonly EventWaitHandle manual_reset;
+        Thread worker_thread;
+        bool keep_working;
 
         public AsynchronousCommandProcessor()
         {
@@ -15,10 +18,16 @@ namespace MoMoney.Infrastructure.Threading
             manual_reset = new ManualResetEvent(false);
         }
 
+        public void add(Action action_to_process)
+        {
+            add(new ActionCommand(action_to_process));
+        }
+
         public void add(ICommand command_to_process)
         {
             lock (queued_commands)
             {
+                if (queued_commands.Contains(command_to_process)) return;
                 queued_commands.Enqueue(command_to_process);
                 reset_thread();
             }
@@ -27,27 +36,44 @@ namespace MoMoney.Infrastructure.Threading
         public void run()
         {
             reset_thread();
-            new Thread(execute_commands).Start();
+            keep_working = true;
+            worker_thread = new Thread(run_commands);
+            worker_thread.SetApartmentState(ApartmentState.STA);
+            worker_thread.Start();
         }
 
-        void execute_commands()
+        public void stop()
         {
-            manual_reset.WaitOne();
-            next_command().run();
-            reset_thread();
+            keep_working = false;
+            manual_reset.Set();
+            worker_thread.Abort();
+            worker_thread = null;
+        }
+
+        [STAThread]
+        void run_commands()
+        {
+            while (keep_working)
+            {
+                manual_reset.WaitOne();
+                run_next_command();
+            }
         }
 
-        ICommand next_command()
+        void run_next_command()
         {
+            ICommand command;
             lock (queued_commands)
             {
                 if (queued_commands.Count == 0)
                 {
                     manual_reset.Reset();
-                    return new EmptyCommand();
+                    return;
                 }
-                return queued_commands.Dequeue();
+                command = queued_commands.Dequeue();
             }
+            command.run();
+            reset_thread();
         }
 
         void reset_thread()
trunk/product/MyMoney/Infrastructure/Threading/CommandProcessor.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Collections.Generic;
 using MoMoney.Utility.Core;
 
@@ -12,6 +13,11 @@ namespace MoMoney.Infrastructure.Threading
             queued_commands = new Queue<ICommand>();
         }
 
+        public void add(Action action_to_process)
+        {
+            add(new ActionCommand(action_to_process));
+        }
+
         public void add(ICommand command_to_process)
         {
             queued_commands.Enqueue(command_to_process);
@@ -24,5 +30,10 @@ namespace MoMoney.Infrastructure.Threading
                 queued_commands.Dequeue().run();
             }
         }
+
+        public void stop()
+        {
+            queued_commands.Clear();
+        }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/Threading/ICommandProcessor.cs
@@ -1,9 +1,12 @@
+using System;
 using MoMoney.Utility.Core;
 
 namespace MoMoney.Infrastructure.Threading
 {
     public interface ICommandProcessor : ICommand
     {
+        void add(Action action_to_process);
         void add(ICommand command_to_process);
+        void stop();
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/Threading/SynchronizedCommand.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Threading;
+using MoMoney.Infrastructure.Extensions;
+using MoMoney.Utility.Core;
+
+namespace MoMoney.Infrastructure.Threading
+{
+    public interface ISynchronizedCommand : IParameterizedCommand<Action>, IParameterizedCommand<ICommand>
+    {
+    }
+
+    public class SynchronizedCommand : ISynchronizedCommand
+    {
+        readonly SynchronizationContext context;
+
+        public SynchronizedCommand(SynchronizationContext context)
+        {
+            this.context = context;
+        }
+
+        public void run(Action item)
+        {
+            context.Post(x =>
+                             {
+                                 this.log().debug("posting action");
+                                 item();
+                             }, new object());
+        }
+
+        public void run(ICommand item)
+        {
+            run(item.run);
+        }
+    }
+}
\ No newline at end of file
trunk/product/MyMoney/Presentation/Model/Menu/Help/HelpMenu.cs
@@ -1,5 +1,4 @@
 using System.Collections.Generic;
-using MoMoney.Presentation.Model.Menu.File;
 using MoMoney.Presentation.Model.Menu.Help.commands;
 using MoMoney.Presentation.Presenters.Commands;
 using MoMoney.Presentation.Presenters.Shell;
trunk/product/MyMoney/Presentation/Model/Menu/window/WindowMenu.cs
@@ -1,5 +1,4 @@
 using System.Collections.Generic;
-using MoMoney.Presentation.Model.Menu.File;
 using MoMoney.Presentation.Model.Menu.File.Commands;
 
 namespace MoMoney.Presentation.Model.Menu.window
trunk/product/MyMoney/Presentation/Model/Menu/create.cs
@@ -7,7 +7,7 @@ namespace MoMoney.Presentation.Model.Menu
     {
         public static IMenuItemBuilder a_menu_item()
         {
-            return new MenuItemBuilder(resolve.dependency_for<IDependencyRegistry>());
+            return new MenuItemBuilder(resolve.dependency_for<IDependencyRegistry>(),resolve.dependency_for<IEventAggregator>());
         }
 
         public static IMenuItem a_menu_item_separator()
trunk/product/MyMoney/Presentation/Model/Menu/MenuItem.cs
@@ -9,45 +9,45 @@ namespace MoMoney.Presentation.Model.Menu
     {
         ToolStripItem build();
         System.Windows.Forms.MenuItem build_menu_item();
+        void refresh();
     }
 
     public class MenuItem : IMenuItem
     {
-        public MenuItem(string name, Action command, HybridIcon icon, ShortcutKey key,
-                        Func<bool> can_be_clicked)
+        readonly Func<bool> can_be_clicked;
+        readonly ToolStripMenuItem item;
+        readonly System.Windows.Forms.MenuItem task_tray_item;
+
+        public MenuItem(string name, Action command, HybridIcon icon, ShortcutKey key, Func<bool> can_be_clicked)
         {
-            this.name = name;
-            this.command = command;
-            this.icon = icon;
-            this.key = key;
             this.can_be_clicked = can_be_clicked;
-        }
 
-        string name { get; set; }
-        Action command { get; set; }
-        HybridIcon icon { get; set; }
-        ShortcutKey key { get; set; }
-        readonly Func<bool> can_be_clicked;
+            item = new ToolStripMenuItem(name)
+                       {
+                           Image = icon,
+                           ShortcutKeys = key,
+                           Enabled = can_be_clicked()
+                       };
+            item.Click += (o, e) => command();
+
+            task_tray_item = new System.Windows.Forms.MenuItem(name) {ShowShortcut = true, Enabled = can_be_clicked()};
+            task_tray_item.Click += (o, e) => command();
+        }
 
         public ToolStripItem build()
         {
-            var item = new ToolStripMenuItem(name)
-                           {
-                               Image = icon,
-                               ShortcutKeys = key,
-                               Enabled = can_be_clicked()
-                           };
-            item.Click += (o, e) => command();
             return item;
         }
 
         public System.Windows.Forms.MenuItem build_menu_item()
         {
-            var item = new System.Windows.Forms.MenuItem(name) {ShowShortcut = true, Enabled = can_be_clicked()};
-            item.Click += (sender, e) => command();
-            //item.Popup += (o,e)=> {}
-            item.DrawItem += (sender, args) => item.Enabled = can_be_clicked();
-            return item;
+            return task_tray_item;
+        }
+
+        public void refresh()
+        {
+            item.Enabled = can_be_clicked();
+            task_tray_item.Enabled = can_be_clicked();
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Model/Menu/MenuItemBuilder.cs
@@ -1,5 +1,6 @@
 using System;
 using MoMoney.Infrastructure.Container;
+using MoMoney.Infrastructure.eventing;
 using MoMoney.Presentation.Model.keyboard;
 using MoMoney.Presentation.Resources;
 using MoMoney.Utility.Core;
@@ -20,12 +21,14 @@ namespace MoMoney.Presentation.Model.Menu
     {
         readonly IDependencyRegistry registry;
         Func<bool> can_be_clicked = () => true;
+        IEventAggregator aggregator;
 
-        public MenuItemBuilder(IDependencyRegistry registry)
+        public MenuItemBuilder(IDependencyRegistry registry, IEventAggregator aggregator)
         {
             name_of_the_menu = "Unknown";
             command_to_execute = () => { };
             this.registry = registry;
+            this.aggregator = aggregator;
             icon = ApplicationIcons.Empty;
             key = ShortcutKeys.none;
         }
@@ -73,7 +76,9 @@ namespace MoMoney.Presentation.Model.Menu
 
         public IMenuItem build()
         {
-            return new MenuItem(name_of_the_menu, command_to_execute, icon, key, can_be_clicked);
+            var item = new MenuItem(name_of_the_menu, command_to_execute, icon, key, can_be_clicked);
+            aggregator.subscribe(item);
+            return item;
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Model/Menu/MenuItemSeparator.cs
@@ -13,5 +13,9 @@ namespace MoMoney.Presentation.Model.Menu
         {
             return new System.Windows.Forms.MenuItem("----------");
         }
+
+        public void refresh()
+        {
+        }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Model/Menu/File/SubMenu.cs → trunk/product/MyMoney/Presentation/Model/Menu/SubMenu.cs
@@ -2,7 +2,7 @@ using System.Collections.Generic;
 using System.Windows.Forms;
 using MoMoney.Utility.Extensions;
 
-namespace MoMoney.Presentation.Model.Menu.File
+namespace MoMoney.Presentation.Model.Menu
 {
     public abstract class SubMenu : ISubMenu
     {
trunk/product/MyMoney/Presentation/Presenters/Commands/LoadPresentationModulesCommand.cs
@@ -1,3 +1,4 @@
+using MoMoney.Infrastructure.Threading;
 using MoMoney.Presentation.Core;
 using MoMoney.Utility.Core;
 using MoMoney.Utility.Extensions;
@@ -11,15 +12,17 @@ namespace MoMoney.Presentation.Presenters.Commands
     public class LoadPresentationModulesCommand : ILoadPresentationModulesCommand
     {
         readonly IRegistry<IPresentationModule> registry;
+        readonly ICommandProcessor processor;
 
-        public LoadPresentationModulesCommand(IRegistry<IPresentationModule> registry)
+        public LoadPresentationModulesCommand(IRegistry<IPresentationModule> registry, ICommandProcessor processor)
         {
             this.registry = registry;
+            this.processor = processor;
         }
 
         public void run()
         {
-            registry.all().each(x => x.run());
+            registry.all().each(x => processor.add(x));
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Presenters/Commands/LoadPresentationModulesCommandSpecs.cs
@@ -1,4 +1,5 @@
 using developwithpassion.bdd.contexts;
+using MoMoney.Infrastructure.Threading;
 using MoMoney.Presentation.Core;
 using MoMoney.Testing.MetaData;
 using MoMoney.Testing.spechelpers.contexts;
@@ -10,11 +11,12 @@ namespace MoMoney.Presentation.Presenters.Commands
     [Concern(typeof (LoadPresentationModulesCommand))]
     public class when_loading_the_application_shell : concerns_for<ILoadPresentationModulesCommand, LoadPresentationModulesCommand>
     {
-        it should_initialize_all_the_presentation_modules = () => module.was_told_to(x => x.run());
+        it should_initialize_all_the_presentation_modules = () => processor.was_told_to(x => x.add(module));
 
         context c = () =>
                         {
                             registry = the_dependency<IRegistry<IPresentationModule>>();
+                            processor = the_dependency<ICommandProcessor>();
                             module = an<IPresentationModule>();
                             when_the(registry).is_told_to(r => r.all()).it_will_return(module);
                         };
@@ -23,5 +25,6 @@ namespace MoMoney.Presentation.Presenters.Commands
 
         static IRegistry<IPresentationModule> registry;
         static IPresentationModule module;
+        static ICommandProcessor processor;
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Presenters/Commands/RunPresenterCommand.cs
@@ -1,3 +1,4 @@
+using MoMoney.Infrastructure.Threading;
 using MoMoney.Presentation.Core;
 
 namespace MoMoney.Presentation.Presenters.Commands
@@ -9,16 +10,18 @@ namespace MoMoney.Presentation.Presenters.Commands
 
     public class RunPresenterCommand : IRunPresenterCommand
     {
-        private readonly IApplicationController application_controller;
+        readonly IApplicationController application_controller;
+        readonly ICommandProcessor processor;
 
-        public RunPresenterCommand(IApplicationController application_controller)
+        public RunPresenterCommand(IApplicationController application_controller, ICommandProcessor processor)
         {
             this.application_controller = application_controller;
+            this.processor = processor;
         }
 
         public void run<Presenter>() where Presenter : IPresenter
         {
-            application_controller.run<Presenter>();
+            processor.add(() => application_controller.run<Presenter>());
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Presenters/Menu/Help/AboutTheApplicationPresenter.cs
@@ -1,10 +1,10 @@
-using MoMoney.Infrastructure.Extensions;
 using MoMoney.Presentation.Core;
+using MoMoney.Presentation.Views.core;
 using MoMoney.Presentation.Views.Menu.Help;
 
 namespace MoMoney.Presentation.Presenters.Menu.Help
 {
-    public interface IAboutApplicationPresenter : IPresenter
+    public interface IAboutApplicationPresenter : IContentPresenter
     {
     }
 
@@ -19,8 +19,12 @@ namespace MoMoney.Presentation.Presenters.Menu.Help
 
         public void run()
         {
-            this.log().debug("about app");
             view.display();
         }
+
+        IDockedContentView IContentPresenter.View
+        {
+            get { return view; }
+        }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Presenters/Menu/ApplicationMenuModule.cs
@@ -1,16 +1,16 @@
 using MoMoney.Infrastructure.eventing;
-using MoMoney.Infrastructure.Extensions;
 using MoMoney.Presentation.Core;
+using MoMoney.Presentation.Model.Menu;
 using MoMoney.Presentation.Model.messages;
 using MoMoney.Presentation.Presenters.Commands;
 
 namespace MoMoney.Presentation.Presenters.Menu
 {
     public interface IApplicationMenuModule : IPresentationModule,
-                                       IEventSubscriber<NewProjectOpened>,
-                                       IEventSubscriber<ClosingProjectEvent>,
-                                       IEventSubscriber<SavedChangesEvent>,
-                                       IEventSubscriber<UnsavedChangesEvent>
+                                              IEventSubscriber<NewProjectOpened>,
+                                              IEventSubscriber<ClosingProjectEvent>,
+                                              IEventSubscriber<SavedChangesEvent>,
+                                              IEventSubscriber<UnsavedChangesEvent>
     {
     }
 
@@ -27,29 +27,28 @@ namespace MoMoney.Presentation.Presenters.Menu
 
         public void run()
         {
-            this.log().debug("hooking up the main menu");
             broker.subscribe(this);
             command.run<IApplicationMenuPresenter>();
         }
 
         public void notify(NewProjectOpened message)
         {
-            //command.run<IApplicationMenuPresenter>();
+            broker.publish<IMenuItem>(x => x.refresh());
         }
 
         public void notify(ClosingProjectEvent message)
         {
-            //command.run<IApplicationMenuPresenter>();
+            broker.publish<IMenuItem>(x => x.refresh());
         }
 
         public void notify(SavedChangesEvent message)
         {
-            //command.run<IApplicationMenuPresenter>();
+            broker.publish<IMenuItem>(x => x.refresh());
         }
 
         public void notify(UnsavedChangesEvent message)
         {
-            //command.run<IApplicationMenuPresenter>();
+            broker.publish<IMenuItem>(x => x.refresh());
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Presenters/Menu/ApplicationMenuPresenter.cs
@@ -23,11 +23,7 @@ namespace MoMoney.Presentation.Presenters.Menu
 
         public void run()
         {
-            shell.region<MenuStrip>(x =>
-                                        {
-                                            x.Items.Clear();
-                                            registry.all().each(y => y.add_to(x));
-                                        });
+            shell.region<MenuStrip>(x => registry.all().each(y => y.add_to(x)));
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Presenters/Navigation/ExpandoBuilder.cs
@@ -1,11 +1,9 @@
 using System.Collections.Generic;
 using System.ComponentModel;
-using System.Drawing;
 using System.Windows.Forms;
 using MoMoney.Utility.Core;
 using MoMoney.Utility.Extensions;
 using XPExplorerBar;
-using Padding=System.Windows.Forms.Padding;
 
 namespace MoMoney.Presentation.Presenters.Navigation
 {
trunk/product/MyMoney/Presentation/Presenters/Navigation/ExpandoItemBuilder.cs
@@ -45,12 +45,8 @@ namespace MoMoney.Presentation.Presenters.Navigation
                                Anchor = ((AnchorStyles.Top | AnchorStyles.Left) | AnchorStyles.Right),
                                BackColor = Color.Transparent,
                                Image = the_image,
-                               //Location = new Point(12, 33),
                                Name = "ux" + the_name,
-                               //Size = new Size(266, 19),
-                               //TabIndex = 0,
                                Text = the_name,
-                               //TextAlign = ContentAlignment.TopLeft,
                                UseVisualStyleBackColor = false,
                            };
             item.Click += (sender, e) => the_action();
trunk/product/MyMoney/Presentation/Presenters/Shell/ApplicationShellPresenter.cs
@@ -6,9 +6,7 @@ using MoMoney.Presentation.Views.Shell;
 
 namespace MoMoney.Presentation.Presenters.Shell
 {
-    public interface IApplicationShellPresenter : IPresentationModule,
-                                                  IEventSubscriber<NewProjectOpened>,
-                                                  IEventSubscriber<ClosingProjectEvent>
+    public interface IApplicationShellPresenter : IPresentationModule, IEventSubscriber<ClosingProjectEvent>
     {
         void shut_down();
     }
@@ -28,17 +26,10 @@ namespace MoMoney.Presentation.Presenters.Shell
 
         public void run()
         {
-            broker.subscribe_to<NewProjectOpened>(this);
-            broker.subscribe_to<ClosingProjectEvent>(this);
+            broker.subscribe(this);
             shell.attach_to(this);
         }
 
-        public void notify(NewProjectOpened message)
-        {
-            //shell.clear_menu_items();
-            //shell.close_all_windows();
-        }
-
         public void notify(ClosingProjectEvent message)
         {
             shell.close_all_windows();
trunk/product/MyMoney/Presentation/Views/core/ApplicationDockedWindow.cs
@@ -1,6 +1,8 @@
-using System.Linq;
+using System;
+using System.Linq;
 using System.Windows.Forms;
 using MoMoney.Presentation.Resources;
+using MoMoney.Presentation.Views.helpers;
 using MoMoney.Utility.Extensions;
 using WeifenLuo.WinFormsUI.Docking;
 
@@ -60,19 +62,22 @@ namespace MoMoney.Presentation.Views.core
 
         public void add_to(DockPanel panel)
         {
-            if (window_is_already_contained_in(panel))
+            using (new SuspendLayout(panel))
             {
-                remove_from(panel);
+                if (window_is_already_contained_in(panel)) remove_from(panel);
+                Show(panel);
+                DockState = dock_state;
             }
-            Show(panel);
-            DockState = dock_state;
         }
 
         public void remove_from(DockPanel panel)
         {
-            var panel_to_remove = get_window_from(panel);
-            panel_to_remove.DockHandler.Close();
-            panel_to_remove.DockHandler.Dispose();
+            using (new SuspendLayout(panel))
+            {
+                var panel_to_remove = get_window_from(panel);
+                panel_to_remove.DockHandler.Close();
+                panel_to_remove.DockHandler.Dispose();
+            }
         }
 
         IDockContent get_window_from(DockPanel panel)
@@ -89,5 +94,17 @@ namespace MoMoney.Presentation.Views.core
         {
             return x.DockHandler.TabText.Equals(TabText);
         }
+
+        protected void on_ui_thread(Action action)
+        {
+            if (InvokeRequired)
+            {
+                BeginInvoke(action);
+            }
+            else
+            {
+                action();
+            }
+        }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Views/core/ApplicationWindow.cs
@@ -62,16 +62,15 @@ namespace MoMoney.Presentation.Views.core
         {
             //context.Post(x => action(), new object());
             //context.Send(x => action(), new object());
-            action();
             //operation.Post(x => action(), new object());
-            //if (InvokeRequired)
-            //{
-            //    BeginInvoke(action);
-            //}
-            //else
-            //{
-            //    action();
-            //}
+            if (InvokeRequired)
+            {
+                BeginInvoke(action);
+            }
+            else
+            {
+                action();
+            }
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Views/helpers/SuspendLayout.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Windows.Forms;
+
+namespace MoMoney.Presentation.Views.helpers
+{
+    public class SuspendLayout : IDisposable
+    {
+        readonly Control control;
+
+        public SuspendLayout(Control control)
+        {
+            this.control = control;
+            control.SuspendLayout();
+        }
+
+        public void Dispose()
+        {
+            control.ResumeLayout();
+        }
+    }
+}
\ No newline at end of file
trunk/product/MyMoney/Presentation/Views/Menu/Help/AboutTheApplicationView.cs
@@ -1,5 +1,4 @@
 using System;
-using System.Linq;
 using System.Reflection;
 using MoMoney.Presentation.Resources;
 using MoMoney.Presentation.Views.core;
@@ -7,7 +6,7 @@ using MoMoney.Utility.Extensions;
 
 namespace MoMoney.Presentation.Views.Menu.Help
 {
-    public partial class AboutTheApplicationView : ApplicationWindow, IAboutApplicationView
+    public partial class AboutTheApplicationView : ApplicationDockedWindow, IAboutApplicationView
     {
         public AboutTheApplicationView()
         {
@@ -29,7 +28,7 @@ namespace MoMoney.Presentation.Views.Menu.Help
 
         public void display()
         {
-            on_ui_thread(() => ShowDialog());
+            //on_ui_thread(() => ShowDialog());
         }
 
         string AssemblyVersion
@@ -39,12 +38,7 @@ namespace MoMoney.Presentation.Views.Menu.Help
 
         Attribute get_attribute<Attribute>() where Attribute : System.Attribute
         {
-            return
-                GetType()
-                    .Assembly
-                    .GetCustomAttributes(typeof (Attribute), false)
-                    .Select(x => x.downcast_to<Attribute>())
-                    .First();
+            return GetType().Assembly.get_attribute<Attribute>();
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Presentation/Views/Menu/Help/IAboutApplicationView.cs
@@ -1,6 +1,8 @@
+using MoMoney.Presentation.Views.core;
+
 namespace MoMoney.Presentation.Views.Menu.Help
 {
-    public interface IAboutApplicationView
+    public interface IAboutApplicationView : IDockedContentView
     {
         void display();
     }
trunk/product/MyMoney/Presentation/Views/Menu/Mappers/SubMenuToToolStripMenuItemMapper.cs
@@ -1,21 +0,0 @@
-using System.Windows.Forms;
-using MoMoney.Presentation.Model.Menu;
-using MoMoney.Utility.Core;
-using MoMoney.Utility.Extensions;
-
-namespace MoMoney.Presentation.Views.Menu.Mappers
-{
-    //public interface ISubMenuToToolStripMenuItemMapper : IMapper<ISubMenu, ToolStripMenuItem>
-    //{
-    //}
-
-    //public class SubMenuToToolStripMenuItemMapper : ISubMenuToToolStripMenuItemMapper
-    //{
-    //    public ToolStripMenuItem map_from(ISubMenu item)
-    //    {
-    //        var menu_item = new ToolStripMenuItem(item.name);
-    //        item.all_menu_items().each(x => menu_item.DropDownItems.Add(x.build()));
-    //        return menu_item;
-    //    }
-    //}
-}
\ No newline at end of file
trunk/product/MyMoney/Presentation/Views/Navigation/MainMenuView.cs
@@ -25,7 +25,7 @@ namespace MoMoney.Presentation.Views.Navigation
 
         public void add(Expando expando)
         {
-            ux_system_task_pane.Expandos.Add(expando);
+            on_ui_thread(() => ux_system_task_pane.Expandos.Add(expando));
         }
 
         public void display()
trunk/product/MyMoney/Presentation/Views/Shell/ApplicationShell.cs
@@ -5,6 +5,7 @@ using System.ComponentModel.Composition;
 using System.Windows.Forms;
 using MoMoney.Presentation.Presenters.Shell;
 using MoMoney.Presentation.Views.core;
+using MoMoney.Presentation.Views.helpers;
 using MoMoney.Utility.Extensions;
 
 namespace MoMoney.Presentation.Views.Shell
@@ -20,7 +21,7 @@ namespace MoMoney.Presentation.Views.Shell
             regions = new Dictionary<string, IComponent>
                           {
                               {GetType().FullName, this},
-                              {typeof(Form).FullName, this},
+                              {typeof (Form).FullName, this},
                               {ux_main_menu_strip.GetType().FullName, ux_main_menu_strip},
                               {ux_dock_panel.GetType().FullName, ux_dock_panel},
                               {ux_tool_bar_strip.GetType().FullName, ux_tool_bar_strip},
@@ -32,7 +33,7 @@ namespace MoMoney.Presentation.Views.Shell
         protected override void OnLoad(EventArgs e)
         {
             try_to_reduce_flickering();
-                //.top_most();
+            //.top_most();
         }
 
         public void attach_to(IApplicationShellPresenter presenter)
@@ -60,9 +61,12 @@ namespace MoMoney.Presentation.Views.Shell
         {
             on_ui_thread(() =>
                              {
-                                 while (ux_dock_panel.Contents.Count > 0)
+                                 using (new SuspendLayout(ux_dock_panel))
                                  {
-                                     ux_dock_panel.Contents[0].DockHandler.Close();
+                                     while (ux_dock_panel.Contents.Count > 0)
+                                     {
+                                         ux_dock_panel.Contents[0].DockHandler.Close();
+                                     }
                                  }
                              });
         }
trunk/product/MyMoney/Utility/Core/AnonymousDisposable.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace MoMoney.Utility.Core
+{
+    public class AnonymousDisposable : IDisposable
+    {
+        readonly Action action;
+
+        public AnonymousDisposable(Action action)
+        {
+            this.action = action;
+        }
+
+        public void Dispose()
+        {
+            action();
+        }
+    }
+}
\ No newline at end of file
trunk/product/MyMoney/Utility/Extensions/CommandExtensions.cs
@@ -24,7 +24,7 @@ namespace MoMoney.Utility.Extensions
 
         public static ICommand as_command_chain(this IEnumerable<ICommand> commands)
         {
-            var processor = new AsynchronousCommandProcessor();
+            var processor = new CommandProcessor();
             commands.each(processor.add);
             return processor;
         }
trunk/product/MyMoney/Utility/Extensions/TypeExtensions.cs
@@ -1,28 +1,40 @@
 using System;
+using System.Linq;
+using System.Reflection;
 
 namespace MoMoney.Utility.Extensions
 {
-    static public class TypeExtensions
+    public static class TypeExtensions
     {
-        static public Type last_interface(this Type type)
+        public static Type last_interface(this Type type)
         {
             return type.GetInterfaces()[type.GetInterfaces().Length - 1];
         }
 
-        static public Type first_interface(this Type type)
+        public static Type first_interface(this Type type)
         {
             return type.GetInterfaces()[0];
         }
 
-        static public bool is_a_generic_type(this Type type)
+        public static bool is_a_generic_type(this Type type)
         {
             //return type.IsGenericType;
             return type.IsGenericTypeDefinition;
         }
 
-        static public object default_value(this Type type)
+        public static object default_value(this Type type)
         {
             return (type.IsValueType ? Activator.CreateInstance(type) : null);
         }
+
+        public static Attribute get_attribute<Attribute>(this ICustomAttributeProvider provider)
+            where Attribute : System.Attribute
+        {
+            return
+                provider
+                    .GetCustomAttributes(typeof (Attribute), false)
+                    .Select(x => x.downcast_to<Attribute>())
+                    .First();
+        }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/MyMoney.csproj
@@ -276,7 +276,7 @@
     <Compile Include="Domain\Core\Month.cs" />
     <Compile Include="Domain\Core\Months.cs" />
     <Compile Include="Infrastructure\Container\Windsor\configuration\ComponentRegistrationConfiguration.cs" />
-    <Compile Include="Infrastructure\System\application_environment.cs" />
+    <Compile Include="Infrastructure\System\ApplicationEnvironment.cs" />
     <Compile Include="Infrastructure\Threading\AsynchronousCommandProcessor.cs" />
     <Compile Include="Infrastructure\Threading\BackgroundThreadFactory.cs" />
     <Compile Include="Infrastructure\Threading\BackgroundThread.cs">
@@ -287,6 +287,7 @@
     <Compile Include="Infrastructure\Threading\Juval\Synchronizer.cs" />
     <Compile Include="Infrastructure\Threading\Juval\WorkItem.cs" />
     <Compile Include="Infrastructure\Threading\SynchronizationContextFactory.cs" />
+    <Compile Include="Infrastructure\Threading\SynchronizedCommand.cs" />
     <Compile Include="Infrastructure\Threading\SynchronizedContext.cs" />
     <Compile Include="Infrastructure\Threading\ThreadSafeInterceptor.cs" />
     <Compile Include="Infrastructure\Threading\TimerFactory.cs" />
@@ -318,7 +319,7 @@
     <Compile Include="Presentation\Model\Menu\File\Commands\SaveChangesCommand.cs" />
     <Compile Include="Presentation\Model\Menu\File\Commands\SaveAsCommandSpecs.cs" />
     <Compile Include="Presentation\Model\Menu\File\Commands\SaveCommandSpecs.cs" />
-    <Compile Include="Presentation\Model\Menu\File\SubMenu.cs" />
+    <Compile Include="Presentation\Model\Menu\SubMenu.cs" />
     <Compile Include="Presentation\Model\Menu\IToolbarButton.cs" />
     <Compile Include="Presentation\Model\Menu\IToolbarItemBuilder.cs" />
     <Compile Include="Presentation\Model\Menu\MenuItemSeparator.cs" />
@@ -461,6 +462,7 @@
     </Compile>
     <Compile Include="Presentation\Views\dialogs\SaveChangesViewSpecs.cs" />
     <Compile Include="Presentation\Views\helpers\EventTriggerExtensions.cs" />
+    <Compile Include="Presentation\Views\helpers\SuspendLayout.cs" />
     <Compile Include="Presentation\Views\IAddCompanyView.cs" />
     <Compile Include="Presentation\Views\billing\IViewAllBills.cs" />
     <Compile Include="Presentation\Views\billing\ViewAllBills.cs">
@@ -570,6 +572,7 @@
     <Compile Include="Presentation\Views\helpers\IEventTarget.cs" />
     <Compile Include="Presentation\Views\helpers\EventTriggerSpecs.cs" />
     <Compile Include="Utility\Core\ActionCommand.cs" />
+    <Compile Include="Utility\Core\AnonymousDisposable.cs" />
     <Compile Include="Utility\Core\ChainedConfiguration.cs" />
     <Compile Include="Utility\Core\chained_mapper.cs" />
     <Compile Include="Utility\Core\AndSpecification.cs" />
@@ -661,7 +664,6 @@
     <Compile Include="Presentation\Views\Shell\ApplicationShell.Designer.cs">
       <DependentUpon>ApplicationShell.cs</DependentUpon>
     </Compile>
-    <Compile Include="Presentation\Views\Menu\Mappers\SubMenuToToolStripMenuItemMapper.cs" />
     <Compile Include="Presentation\Views\Startup\ISplashScreenView.cs" />
     <Compile Include="Presentation\Views\Startup\SplashScreenView.cs">
       <SubType>Form</SubType>
@@ -793,6 +795,7 @@
   <ItemGroup>
     <Folder Include="DataAccess\sqlcompact\" />
     <Folder Include="Presentation\module\" />
+    <Folder Include="Presentation\Views\Menu\Mappers\" />
     <Folder Include="Tasks\domain\" />
     <Folder Include="Tasks\Stubs\" />
     <Folder Include="Testing\spechelpers\concerns\" />