Commit cc4fec8

mo khan <mo@mokhan.ca>
2010-02-07 02:41:28
hooked up the status bar and progress bar.
1 parent bfa369b
build/project.deploy.build
@@ -7,10 +7,12 @@
 		<property name="target" value="${log4net.config}" />
 		<call target="expand.template.file" />
 		<copy file="${build.config.dir}\log4net.config.xml" tofile="${product.dir}\client\boot\log4net.config.xml" />
+		<copy file="${build.config.dir}\log4net.config.xml" tofile="${product.dir}\client\presentation.windows\log4net.config.xml" />
     
 		<property name="target" value="${assembly.config}" />
 		<call target="expand.template.file" />
 		<copy file="${build.config.dir}\AssemblyInfo.cs" tofile="${product.dir}\client\boot\Properties\AssemblyInfo.cs" />
+		<copy file="${build.config.dir}\AssemblyInfo.cs" tofile="${product.dir}\client\presentation.windows\Properties\AssemblyInfo.cs" />
   </target>
 
 	<target name="deploy" depends="create.configs, app.compile" />
product/client/boot/boot/container/WireUpTheContainer.cs
@@ -1,14 +1,13 @@
 using Autofac.Builder;
 using Gorilla.Commons.Infrastructure.Container;
 using Gorilla.Commons.Infrastructure.Reflection;
-using gorilla.commons.infrastructure.thirdparty;
 using gorilla.commons.infrastructure.thirdparty.Autofac;
 using gorilla.commons.utility;
 using MoMoney.boot.container.registration;
 using momoney.database;
-using MoMoney.Domain.Accounting;
 using MoMoney.Presentation;
 using momoney.service.infrastructure;
+using Assembly = System.Reflection.Assembly;
 
 namespace MoMoney.boot.container
 {
@@ -30,14 +29,13 @@ namespace MoMoney.boot.container
                 .then(new WireUpTheViewsInToThe(registry))
                 .then(new WireUpTheReportsInToThe(registry))
                 .run_against(new ApplicationAssembly(
-                         System.Reflection.Assembly.GetExecutingAssembly(),
-                         typeof (DatabaseAssembly).Assembly,
-                         typeof (PresentationAssembly).Assembly,
-                         typeof (InfrastructureAssembly).Assembly
-                         ));
+                                 Assembly.GetExecutingAssembly(),
+                                 typeof (DatabaseAssembly).Assembly,
+                                 typeof (PresentationAssembly).Assembly,
+                                 typeof (InfrastructureAssembly).Assembly
+                                 ));
 
             Resolve.initialize_with(registry.build());
         }
     }
-
 }
\ No newline at end of file
product/client/presentation.windows/ComposeShell.cs → product/client/presentation.windows/bootstrappers/ComposeShell.cs
@@ -1,11 +1,8 @@
-using System.Threading;
-using System.Windows;
 using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
 using presentation.windows.presenters;
 using presentation.windows.views;
 
-namespace presentation.windows
+namespace presentation.windows.bootstrappers
 {
     public class ComposeShell : NeedStartup
     {
@@ -28,21 +25,15 @@ namespace presentation.windows
             region_manager.region<TabControl>(x => x.Items.Add(new TabItem {Header = "Liabilities"}));
             region_manager.region<TabControl>(x => x.Items.Add(new TabItem {Header = "Budget"}));
 
-            region_manager.region<StatusBar>(x => x.Items.Add(new Label {Content = Thread.CurrentPrincipal.Identity.Name}));
-            region_manager.region<StatusBar>(x => x.Items.Add(new Label {Content = "Software Developer"}));
-
             region_manager.region<MainMenu>(x =>
             {
-                x.add("_File").add("E_xit", () =>
-                {
-                    Application.Current.Shutdown();
-                });
-                x.add("F_amily").add("_Add Member", () =>
+                x.add("_Family").add("_Add Member", () =>
                 {
                     controller.launch_dialog<AddFamilyMemberPresenter, AddFamilyMemberDialog>();
-                    MessageBox.Show("Add Family");
                 });
             });
+
+            controller.load_region<StatusBarPresenter, StatusBarRegion>();
         }
     }
 }
\ No newline at end of file
product/client/presentation.windows/commands/AddMemberToFamily.cs → product/client/presentation.windows/commands/AddFamilyMember.cs
@@ -1,14 +1,16 @@
+using System.Threading;
 using Gorilla.Commons.Infrastructure.Logging;
 using gorilla.commons.utility;
 using presentation.windows.commands.dto;
 
 namespace presentation.windows.commands
 {
-    public class AddMemberToFamily : ArgCommand<FamilyMemberToAdd>
+    public class AddFamilyMember : ArgCommand<FamilyMemberToAdd>
     {
         public void run_against(FamilyMemberToAdd item)
         {
             this.log().debug("adding family member");
+            Thread.Sleep(5000);
         }
     }
 }
\ No newline at end of file
product/client/presentation.windows/commands/ContainerAwareParameterizedCommandBuilder.cs
@@ -1,6 +1,7 @@
 using System;
 using Gorilla.Commons.Infrastructure.Container;
 using gorilla.commons.utility;
+using MoMoney.Service.Infrastructure.Eventing;
 
 namespace presentation.windows.commands
 {
@@ -8,18 +9,28 @@ namespace presentation.windows.commands
     {
         readonly T data;
         Action action;
-        string message;
-        public ContainerAwareParameterizedCommandBuilder(T data)
+        EventAggregator event_broker;
+
+        public ContainerAwareParameterizedCommandBuilder(T data, EventAggregator event_broker)
         {
             this.data = data;
+            this.event_broker = event_broker;
         }
 
         public Command build<TCommand>(string message) where TCommand : ArgCommand<T>
         {
-            this.message = message;
             action = () =>
             {
+                event_broker.publish(new UpdateOnLongRunningProcess
+                                     {
+                                         message = message,
+                                         percent_complete = 0,
+                                     });
                 Resolve.the<TCommand>().run_against(data);
+                event_broker.publish(new UpdateOnLongRunningProcess
+                                     {
+                                         percent_complete = 100,
+                                     });
             };
 
             return this;
@@ -29,10 +40,5 @@ namespace presentation.windows.commands
         {
             action();
         }
-
-        public override string ToString()
-        {
-            return message;
-        }
     }
 }
\ No newline at end of file
product/client/presentation.windows/commands/ContainerCommandBuilder.cs
@@ -1,13 +1,21 @@
 using Gorilla.Commons.Infrastructure.Container;
 using gorilla.commons.utility;
+using MoMoney.Service.Infrastructure.Eventing;
 
 namespace presentation.windows.commands
 {
     public class ContainerCommandBuilder : CommandBuilder
     {
+        EventAggregator event_aggregator;
+
+        public ContainerCommandBuilder(EventAggregator event_aggregator)
+        {
+            this.event_aggregator = event_aggregator;
+        }
+
         public ParameterizedCommandBuilder<T> prepare<T>(T data)
         {
-            return new ContainerAwareParameterizedCommandBuilder<T>(data);
+            return new ContainerAwareParameterizedCommandBuilder<T>(data, event_aggregator);
         }
 
         public Command build<T>(string message) where T : Command
product/client/presentation.windows/commands/UpdateOnLongRunningProcess.cs
@@ -0,0 +1,10 @@
+using MoMoney.Service.Infrastructure.Eventing;
+
+namespace presentation.windows.commands
+{
+    public class UpdateOnLongRunningProcess : IEvent
+    {
+        public string message { get; set; }
+        public int percent_complete { get; set; }
+    }
+}
\ No newline at end of file
product/client/presentation.windows/presenters/AddFamilyMemberPresenter.cs
@@ -2,7 +2,6 @@ using System;
 using MoMoney.Service.Infrastructure.Threading;
 using presentation.windows.commands;
 using presentation.windows.commands.dto;
-using presentation.windows.views;
 
 namespace presentation.windows.presenters
 {
@@ -28,7 +27,7 @@ namespace presentation.windows.presenters
                                                last_name = last_name,
                                                date_of_birth = date_of_birth
                                            })
-                                  .build<AddMemberToFamily>("Adding Family Member")
+                                  .build<AddFamilyMember>("Adding Family Member")
                     );
                 close();
             });
product/client/presentation.windows/presenters/Observable.cs
@@ -0,0 +1,20 @@
+using System;
+using System.ComponentModel;
+using System.Linq.Expressions;
+using gorilla.commons.utility;
+
+namespace presentation.windows.presenters
+{
+    public abstract class Observable<T> : INotifyPropertyChanged
+    {
+        public event PropertyChangedEventHandler PropertyChanged = (o, e) => {};
+
+        protected void update(params Expression<Func<T, object>>[] properties)
+        {
+            properties.each(x =>
+            {
+                PropertyChanged(this, new PropertyChangedEventArgs(x.pick_property().Name));
+            });
+        }
+    }
+}
\ No newline at end of file
product/client/presentation.windows/presenters/StatusBarPresenter.cs
@@ -0,0 +1,27 @@
+using System.Threading;
+using MoMoney.Service.Infrastructure.Eventing;
+using presentation.windows.commands;
+
+namespace presentation.windows.presenters
+{
+    public class StatusBarPresenter : Observable<StatusBarPresenter>, Presenter, EventSubscriber<UpdateOnLongRunningProcess>
+    {
+        public string progress_message { get; set; }
+        public bool is_progress_bar_on { get; set; }
+        public string username { get; set; }
+        public string title { get; set; }
+
+        public void present()
+        {
+            username = Thread.CurrentPrincipal.Identity.Name;
+            title = "Software Developer";
+        }
+
+        public void notify(UpdateOnLongRunningProcess message)
+        {
+            progress_message = message.message;
+            is_progress_bar_on = message.percent_complete < 100;
+            update(x => x.progress_message, x => x.is_progress_bar_on);
+        }
+    }
+}
\ No newline at end of file
product/client/presentation.windows/views/ShellWIndow.xaml
@@ -4,16 +4,13 @@
     <DockPanel  VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
         <ui:MainMenu x:Name="Menu" DockPanel.Dock="Top">
         </ui:MainMenu>
-        <StatusBar Name="StatusBar" HorizontalAlignment="Right" DockPanel.Dock="Bottom">
-            <Label>Test</Label>
-        </StatusBar>
+        <ui:StatusBarRegion x:Name="StatusBar" DockPanel.Dock="Bottom"></ui:StatusBarRegion>
         <StackPanel>
             <Expander>
                 <Expander.Header>
                     <DockPanel>
                     <Label>Family Member:</Label>
                     <ComboBox Width="150"></ComboBox>
-                    <Button >Test</Button>
                     </DockPanel>
                 </Expander.Header>
                 <UniformGrid>
@@ -23,9 +20,7 @@
                     <Label>Khan</Label>
                 </UniformGrid>
             </Expander>
-        <TabControl Name="Tabs">
-            <TabItem Header="Test"></TabItem>
-        </TabControl>
+        <TabControl Name="Tabs"></TabControl>
         </StackPanel>
     </DockPanel>
 </Window>
product/client/presentation.windows/views/ShellWIndow.xaml.cs
@@ -5,7 +5,7 @@ using gorilla.commons.utility;
 
 namespace presentation.windows.views
 {
-    public partial class ShellWindow : Shell, RegionManager
+    public partial class ShellWindow : RegionManager
     {
         readonly IDictionary<Type, UIElement> regions;
 
product/client/presentation.windows/views/StatusBarRegion.xaml
@@ -0,0 +1,13 @@
+<UserControl x:Class="presentation.windows.views.StatusBarRegion"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+    <StatusBar HorizontalAlignment="Right">
+    	<StatusBar.Resources>
+    		<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
+    	</StatusBar.Resources>
+    	<Label Content="{Binding progress_message}"></Label>
+        <ProgressBar Width="200" Height="25" IsIndeterminate="True" Visibility="{Binding Path=is_progress_bar_on, Converter={StaticResource BooleanToVisibilityConverter}}"></ProgressBar>
+        <Label Content="{Binding username}"></Label>
+        <Label Content="{Binding title}"></Label>
+    </StatusBar>
+</UserControl>
product/client/presentation.windows/views/StatusBarRegion.xaml.cs
@@ -0,0 +1,12 @@
+using presentation.windows.presenters;
+
+namespace presentation.windows.views
+{
+    public partial class StatusBarRegion : View<StatusBarPresenter>
+    {
+        public StatusBarRegion()
+        {
+            InitializeComponent();
+        }
+    }
+}
\ No newline at end of file
product/client/presentation.windows/ApplicationController.cs
@@ -6,5 +6,6 @@ namespace presentation.windows
     {
         void add_tab<Presenter, Tab>() where Presenter : TabPresenter where Tab : FrameworkElement, Tab<Presenter>, new();
         void launch_dialog<Presenter, Dialog>() where Presenter : DialogPresenter where Dialog : FrameworkElement, Dialog<Presenter>, new();
+        void load_region<Presenter, Region>() where Presenter : windows.Presenter where Region : FrameworkElement, View<Presenter>, new();
     }
 }
\ No newline at end of file
product/client/presentation.windows/presentation.windows.csproj
@@ -76,6 +76,10 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="views\StatusBarRegion.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Compile Include="views\ShellWIndow.xaml.cs">
       <DependentUpon>ShellWIndow.xaml</DependentUpon>
       <SubType>Code</SubType>
@@ -84,16 +88,19 @@
   <ItemGroup>
     <Compile Include="ApplicationController.cs" />
     <Compile Include="commands\ParameterizedCommandBuilder.cs" />
+    <Compile Include="commands\UpdateOnLongRunningProcess.cs" />
     <Compile Include="Dialog.cs" />
     <Compile Include="DialogPresenter.cs" />
     <Compile Include="presenters\AddFamilyMemberPresenter.cs" />
     <Compile Include="commands\CommandBuilder.cs" />
-    <Compile Include="commands\AddMemberToFamily.cs" />
+    <Compile Include="commands\AddFamilyMember.cs" />
     <Compile Include="presenters\CompensationPresenter.cs" />
     <Compile Include="commands\dto\FamilyMemberToAdd.cs" />
     <Compile Include="commands\ContainerCommandBuilder.cs" />
     <Compile Include="commands\NamedCommand.cs" />
     <Compile Include="commands\ContainerAwareParameterizedCommandBuilder.cs" />
+    <Compile Include="presenters\StatusBarPresenter.cs" />
+    <Compile Include="presenters\Observable.cs" />
     <Compile Include="View.cs" />
     <Compile Include="views\AddFamilyMemberDialog.xaml.cs">
       <DependentUpon>AddFamilyMemberDialog.xaml</DependentUpon>
@@ -101,12 +108,11 @@
     <Compile Include="views\CompensationTab.xaml.cs">
       <DependentUpon>CompensationTab.xaml</DependentUpon>
     </Compile>
-    <Compile Include="ComposeShell.cs" />
+    <Compile Include="bootstrappers\ComposeShell.cs" />
     <Compile Include="NeedStartup.cs" />
     <Compile Include="Presenter.cs" />
     <Compile Include="PresenterFactory.cs" />
     <Compile Include="RegionManager.cs" />
-    <Compile Include="Shell.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs">
       <SubType>Code</SubType>
@@ -127,6 +133,9 @@
     <Compile Include="views\MainMenu.cs" />
     <Compile Include="views\MenuItemExtensions.cs" />
     <Compile Include="presenters\SimpleCommand.cs" />
+    <Compile Include="views\StatusBarRegion.xaml.cs">
+      <DependentUpon>StatusBarRegion.xaml</DependentUpon>
+    </Compile>
     <Compile Include="WpfApplicationController.cs" />
     <Compile Include="WpfPresenterFactory.cs" />
     <EmbeddedResource Include="Properties\Resources.resx">
@@ -140,6 +149,10 @@
     <AppDesigner Include="Properties\" />
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\commons\infrastructure.thirdparty.log4net\infrastructure.thirdparty.log4net.csproj">
+      <Project>{6BDCB0C1-51E1-435A-93D8-CA02BF8E409C}</Project>
+      <Name>infrastructure.thirdparty.log4net</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\commons\infrastructure.thirdparty\infrastructure.thirdparty.csproj">
       <Project>{04DC09B4-5DF9-44A6-8DD1-05941F0D0228}</Project>
       <Name>infrastructure.thirdparty</Name>
@@ -157,6 +170,9 @@
       <Name>service.infrastructure</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <Resource Include="log4net.config.xml" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
product/client/presentation.windows/Program.cs
@@ -1,12 +1,17 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Security.Principal;
 using System.Windows;
 using Autofac.Builder;
 using Gorilla.Commons.Infrastructure.Container;
+using Gorilla.Commons.Infrastructure.Logging;
 using gorilla.commons.infrastructure.thirdparty.Autofac;
+using gorilla.commons.infrastructure.thirdparty.Log4Net;
 using gorilla.commons.utility;
+using MoMoney.Service.Infrastructure.Eventing;
 using MoMoney.Service.Infrastructure.Threading;
+using presentation.windows.bootstrappers;
 using presentation.windows.commands;
 using presentation.windows.presenters;
 using presentation.windows.views;
@@ -32,21 +37,35 @@ namespace presentation.windows
         {
             var builder = new ContainerBuilder();
             var shell_window = new ShellWindow();
-            builder.Register(x => shell_window).As<RegionManager>();
+            builder.Register(x => shell_window).SingletonScoped();
+            builder.Register(x => shell_window).As<RegionManager>().SingletonScoped();
 
+            //needs startups
             builder.Register<ComposeShell>().As<NeedStartup>();
-            builder.Register<WpfApplicationController>().As<ApplicationController>();
-            builder.Register<WpfPresenterFactory>().As<PresenterFactory>();
 
+            // infrastructure
+            builder.Register<Log4NetLogFactory>().As<LogFactory>().SingletonScoped();
+
+            // presentation infrastructure
+            builder.Register<WpfApplicationController>().As<ApplicationController>().SingletonScoped();
+            builder.Register<WpfPresenterFactory>().As<PresenterFactory>().SingletonScoped();
+            builder.Register<SynchronizedEventAggregator>().As<EventAggregator>().SingletonScoped();
+            builder.Register(x => AsyncOperationManager.SynchronizationContext);
+
+            // presenters
+            builder.Register<StatusBarPresenter>().SingletonScoped();
             builder.Register<CompensationPresenter>();
             builder.Register<AddFamilyMemberPresenter>();
 
-            builder.Register<ContainerCommandBuilder>().As<CommandBuilder>();
-            builder.Register<SynchronousCommandProcessor>().As<CommandProcessor>();
-
+            // commanding
+            builder.Register<ContainerCommandBuilder>().As<CommandBuilder>().SingletonScoped();
+            builder.Register<AsynchronousCommandProcessor>().As<CommandProcessor>().SingletonScoped();
+            builder.Register<AddFamilyMember>();
 
             Resolve.initialize_with(new AutofacDependencyRegistryBuilder(builder).build());
             Resolve.the<IEnumerable<NeedStartup>>().each(x => x.run());
+            Resolve.the<CommandProcessor>().run();
+
             return shell_window;
         }
     }
product/client/presentation.windows/Shell.cs
@@ -1,4 +0,0 @@
-namespace presentation.windows
-{
-    public interface Shell {}
-}
\ No newline at end of file
product/client/presentation.windows/WpfApplicationController.cs
@@ -1,5 +1,6 @@
 using System.Windows;
 using System.Windows.Controls;
+using MoMoney.Service.Infrastructure.Eventing;
 using presentation.windows.views;
 
 namespace presentation.windows
@@ -8,16 +9,19 @@ namespace presentation.windows
     {
         RegionManager region_manager;
         PresenterFactory factory;
+        EventAggregator event_aggregator;
 
-        public WpfApplicationController(RegionManager region_manager, PresenterFactory factory)
+        public WpfApplicationController(RegionManager region_manager, PresenterFactory factory, EventAggregator event_aggregator)
         {
             this.region_manager = region_manager;
+            this.event_aggregator = event_aggregator;
             this.factory = factory;
         }
 
         public void add_tab<Presenter, View>() where Presenter : TabPresenter where View : FrameworkElement, Tab<Presenter>, new()
         {
             var presenter = factory.create<Presenter>();
+            event_aggregator.subscribe(presenter);
             presenter.present();
             region_manager.region<TabControl>(x => x.Items.Add(new TabItem
                                                                {
@@ -40,5 +44,16 @@ namespace presentation.windows
                 dialog.show_dialog(x);
             });
         }
+
+        public void load_region<Presenter, Region>() where Presenter : windows.Presenter where Region : FrameworkElement, View<Presenter>, new()
+        {
+            var presenter = factory.create<Presenter>();
+            event_aggregator.subscribe(presenter);
+            presenter.present();
+            region_manager.region<Region>(x =>
+            {
+                x.DataContext = presenter;
+            });
+        }
     }
 }
\ No newline at end of file
product/client/service.infrastructure/threading/AsynchronousCommandProcessor.cs
@@ -76,7 +76,6 @@ namespace MoMoney.Service.Infrastructure.Threading
                         });
             safely_invoke(() =>
                           {
-                              this.log().debug("running command: {0}", command);
                               command.run();
                           });
             reset_thread();
product/commons/utility/ExpressionExtensions.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace gorilla.commons.utility
+{
+    static public class ExpressionExtensions
+    {
+        static public PropertyInfo pick_property<T>(this Expression<Func<T, object>> expression)
+        {
+            return (PropertyInfo) member_expression(expression).Member;
+        }
+
+        static MemberExpression member_expression<T>(Expression<Func<T, object>> expression)
+        {
+            if (expression.Body.NodeType == ExpressionType.Convert)
+                return ((UnaryExpression) expression.Body).Operand as MemberExpression;
+            if (expression.Body.NodeType == ExpressionType.MemberAccess)
+                return expression.Body as MemberExpression;
+            throw new NotImplementedException();
+        }
+    }
+}
\ No newline at end of file
product/commons/utility/utility.csproj
@@ -58,6 +58,7 @@
     <Compile Include="EmptyCallback.cs" />
     <Compile Include="EmptyCommand.cs" />
     <Compile Include="DefaultConstructorFactory.cs" />
+    <Compile Include="ExpressionExtensions.cs" />
     <Compile Include="FactoryDelegate.cs" />
     <Compile Include="FilteredVisitor.cs" />
     <Compile Include="FuncSpecification.cs" />