Commit a0b5c11
Changed files (11)
product
desktop.ui
specs
unit
ui
product/desktop.ui/presenters/SingleStockPresenter.cs
@@ -24,14 +24,20 @@ namespace solidware.financials.windows.ui.presenters
get { return symbol_to_watch; }
}
- public void present()
- {
- }
+ public void present() {}
public void notify(CurrentStockPrice message)
{
if (symbol_to_watch.Equals(message.Symbol))
Chart.Add(new KeyValuePair<DateTime, decimal>(Clock.now(), message.Price));
}
+
+ public class Factory
+ {
+ public virtual SingleStockPresenter create_for(string symbol)
+ {
+ throw new NotImplementedException();
+ }
+ }
}
}
\ No newline at end of file
product/desktop.ui/presenters/StockViewModel.cs
@@ -1,26 +1,55 @@
-using solidware.financials.windows.ui.views.controls;
+using solidware.financials.windows.ui.views;
+using solidware.financials.windows.ui.views.controls;
namespace solidware.financials.windows.ui.presenters
{
- public class StockViewModel
+ public class StockViewModel : Presenter
{
- public StockViewModel(string symbol)
+ UICommandBuilder builder;
+
+ public StockViewModel(string symbol, UICommandBuilder builder)
{
+ this.builder = builder;
Symbol = symbol;
Price = Money.Null;
+ AdditionalInformation = new SimpleCommand(() => {});
}
- public string Symbol { get; set; }
+ public virtual string Symbol { get; set; }
public Observable<Money> Price { get; set; }
+ public ObservableCommand AdditionalInformation { get; set; }
- public bool IsFor(string symbol)
+ public void present()
+ {
+ AdditionalInformation = builder.build<MoreCommand>(this);
+ }
+
+ public bool is_for(string symbol)
{
return Symbol.Equals(symbol);
}
- public void ChangePriceTo(decimal price)
+ public void change_price_to(decimal price)
{
Price.Value = price;
}
+
+ public class MoreCommand : UICommand<StockViewModel>
+ {
+ readonly ApplicationController controller;
+ readonly SingleStockPresenter.Factory factory;
+
+ public MoreCommand(ApplicationController controller, SingleStockPresenter.Factory factory)
+ {
+ this.controller = controller;
+ this.factory = factory;
+ }
+
+ public override void run(StockViewModel presenter)
+ {
+ controller
+ .load_tab<SingleStockPresenter, SingleStockTab>(factory.create_for(presenter.Symbol));
+ }
+ }
}
}
\ No newline at end of file
product/desktop.ui/presenters/StockWatchPresenter.cs
@@ -41,12 +41,12 @@ namespace solidware.financials.windows.ui.presenters
public void notify(CurrentStockPrice message)
{
- Stocks.Single(x => x.IsFor(message.Symbol)).ChangePriceTo(message.Price);
+ Stocks.Single(x => x.is_for(message.Symbol)).change_price_to(message.Price);
}
public void notify(StartWatchingSymbol message)
{
- Stocks.Add(new StockViewModel(symbol: message.Symbol));
+ Stocks.Add(new StockViewModel(symbol: message.Symbol, builder: builder));
}
public class AddSymbolCommand : UICommand<StockWatchPresenter>
product/desktop.ui/views/SingleStockTab.xaml
@@ -1,4 +1,4 @@
-<UserControl x:Class="solidware.financials.windows.ui.views.SingleStockTab" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:Charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" mc:Ignorable="d"
+<UserControl x:Class="solidware.financials.windows.ui.views.SingleStockTab" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:Charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" mc:Ignorable="d">
<DockPanel>
<Label Content="{Binding Path=Header}"></Label>
<Charting:Chart>
product/desktop.ui/views/SingleStockTab.xaml.cs
@@ -2,11 +2,16 @@
namespace solidware.financials.windows.ui.views
{
- public partial class SingleStockTab : View<SingleStockPresenter>
+ public partial class SingleStockTab : Tab<SingleStockPresenter>
{
public SingleStockTab()
{
InitializeComponent();
}
+
+ public void bind_to(SingleStockPresenter presenter)
+ {
+ DataContext = presenter;
+ }
}
}
\ No newline at end of file
product/desktop.ui/views/StockWatch.xaml
@@ -8,8 +8,9 @@
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel>
- <Label Content="{Binding Path=Symbol}" DockPanel.Dock="Left" Width="90"></Label>
+ <Label Content="{Binding Path=Symbol}" DockPanel.Dock="Left" Width="90" ></Label>
<Label Content="{Binding Path=Price.Value}" DockPanel.Dock="Right" HorizontalAlignment="Right" HorizontalContentAlignment="Right"></Label>
+ <Button Command="{Binding Path=AdditionalInformation}">...</Button>
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
product/desktop.ui/ApplicationController.cs
@@ -4,10 +4,9 @@ namespace solidware.financials.windows.ui
{
public interface ApplicationController
{
- void add_tab<Presenter, Tab>() where Presenter : TabPresenter
- where Tab : FrameworkElement, Tab<Presenter>, new();
+ void add_tab<Presenter, Tab>() where Presenter : TabPresenter where Tab : Tab<Presenter>, new();
+ void load_tab<Presenter, Tab>(Presenter presenter) where Presenter : TabPresenter where Tab : Tab<Presenter>, new();
- void load_region<Presenter, Region>() where Presenter : ui.Presenter
- where Region : FrameworkElement, View<Presenter>, new();
+ void load_region<Presenter, Region>() where Presenter : ui.Presenter where Region : FrameworkElement, View<Presenter>, new();
}
}
\ No newline at end of file
product/desktop.ui/WPFApplicationController.cs
@@ -1,5 +1,6 @@
using System;
using System.Windows;
+using gorilla.utility;
using solidware.financials.infrastructure.eventing;
namespace solidware.financials.windows.ui
@@ -17,12 +18,17 @@ namespace solidware.financials.windows.ui
this.factory = factory;
}
- public void add_tab<Presenter, View>() where Presenter : TabPresenter where View : FrameworkElement, Tab<Presenter>, new()
+ public void add_tab<Presenter, View>() where Presenter : TabPresenter where View : Tab<Presenter>, new()
{
var presenter = open<Presenter>();
var view = new View();
view.bind_to(presenter);
- region_manager.region(new TabRegionConfiguration(presenter,view));
+ region_manager.region(new TabRegionConfiguration(presenter,view.downcast_to<FrameworkElement>()));
+ }
+
+ public void load_tab<Presenter, View>(Presenter presenter) where Presenter : TabPresenter where View : Tab<Presenter>, new()
+ {
+ throw new NotImplementedException();
}
public void load_region<TPresenter, Region>() where TPresenter : Presenter where Region : FrameworkElement, View<TPresenter>, new()
product/specs/unit/ui/presenters/StockViewModelSpecs.cs
@@ -0,0 +1,85 @@
+using Machine.Specifications;
+using solidware.financials.windows.ui;
+using solidware.financials.windows.ui.presenters;
+using solidware.financials.windows.ui.views;
+
+namespace specs.unit.ui.presenters
+{
+ public class StockViewModelSpecs
+ {
+ public abstract class concern
+ {
+ Establish context = () =>
+ {
+ builder = Create.dependency<UICommandBuilder>();
+ sut = new StockViewModel("ARX.TO", builder);
+ };
+
+ static protected StockViewModel sut;
+ static protected UICommandBuilder builder;
+ }
+
+ public class when_someone_clicks_on_the_additional_info_button : concern
+ {
+ Establish context = () =>
+ {
+ more_command = Create.an<ObservableCommand>();
+ builder.is_told_to(x => x.build<StockViewModel.MoreCommand>(sut)).it_will_return(more_command);
+ };
+
+ Because of = () =>
+ {
+ sut.present();
+ };
+
+ It should_execute_the_additional_info_command = () =>
+ {
+ sut.AdditionalInformation.should_be_equal_to(more_command);
+ };
+
+ static ObservableCommand more_command;
+ }
+
+ public class MoreCommandSpecs
+ {
+ public abstract class concern_for_more_command
+ {
+ Establish context = () =>
+ {
+ controller = Create.dependency<ApplicationController>();
+ factory = Create.dependency<SingleStockPresenter.Factory>();
+ sut = new StockViewModel.MoreCommand(controller, factory);
+ };
+
+ static protected StockViewModel.MoreCommand sut;
+ static protected ApplicationController controller;
+ static protected SingleStockPresenter.Factory factory;
+ }
+
+ public class when_wanting_to_see_more_info_on_a_stock : concern_for_more_command
+ {
+ Establish context = () =>
+ {
+ presenter = Create.an<StockViewModel>();
+ tab = Create.an<SingleStockPresenter>();
+
+ presenter.is_told_to(x => x.Symbol).it_will_return("ARX.TO");
+ factory.is_told_to(x => x.create_for("ARX.TO")).it_will_return(tab);
+ };
+
+ Because of = () =>
+ {
+ sut.run(presenter);
+ };
+
+ It should_display_a_tab_for_the_stock = () =>
+ {
+ controller.received(x => x.load_tab<SingleStockPresenter, SingleStockTab>(tab));
+ };
+
+ static StockViewModel presenter;
+ static SingleStockPresenter tab;
+ }
+ }
+ }
+}
\ No newline at end of file
product/specs/unit/ui/presenters/StockWatchPresenterSpecs.cs
@@ -80,7 +80,7 @@ namespace specs.unit.ui.presenters
{
Establish context = () =>
{
- sut.Stocks.Add(new StockViewModel(symbol:"ARX.TO")
+ sut.Stocks.Add(new StockViewModel(symbol:"ARX.TO", builder: null)
{
Price = new Money(20.00m).ToObservable(),
});
@@ -157,7 +157,7 @@ namespace specs.unit.ui.presenters
Establish context = () =>
{
presenter = Create.an<StockWatchPresenter>();
- presenter.is_told_to(x => x.Stocks).it_will_return(new StockViewModel (symbol : "ARX.TO"));
+ presenter.is_told_to(x => x.Stocks).it_will_return(new StockViewModel (symbol : "ARX.TO", builder: null));
};
Because of = () =>
product/specs/specs.csproj
@@ -112,6 +112,7 @@
<Compile Include="IllegalExtensions.cs" />
<Compile Include="unit\ui\presenters\specifications\IfFamilyMemberIsSelectedSpecs.cs" />
<Compile Include="unit\ui\presenters\SingleStockPresenterSpecs.cs" />
+ <Compile Include="unit\ui\presenters\StockViewModelSpecs.cs" />
<Compile Include="unit\ui\presenters\StockWatchPresenterSpecs.cs" />
<Compile Include="unit\ui\RunInBackgroundInterceptorSpecs.cs" />
</ItemGroup>