Commit a1005c4
Changed files (11)
product
desktop.ui
presenters
views
dialogs
specs
unit
ui
presenters
product/desktop.ui/presenters/validation/AnonymousRule.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace solidware.financials.windows.ui.presenters.validation
+{
+ public class AnonymousRule<Severity> : Rule where Severity : validation.Severity, new()
+ {
+ readonly Func<bool> failCondition;
+ readonly Func<string> errorMessage;
+
+ public AnonymousRule(Func<bool> failCondition, Func<string> errorMessage)
+ {
+ this.failCondition = failCondition;
+ this.errorMessage = errorMessage;
+ }
+
+ public string ErrorMessage
+ {
+ get { return errorMessage(); }
+ }
+
+ public bool IsViolatedAndMoreSevereThan<OtherSeverity>() where OtherSeverity : validation.Severity, new()
+ {
+ return IsViolated() && new Severity().IsMoreSevereThan(new OtherSeverity());
+ }
+
+ public bool IsViolated()
+ {
+ return failCondition();
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/presenters/validation/Error.cs
@@ -0,0 +1,10 @@
+namespace solidware.financials.windows.ui.presenters.validation
+{
+ public class Error : Severity
+ {
+ public bool IsMoreSevereThan<OtherSeverity>(OtherSeverity otherSeverity) where OtherSeverity : Severity
+ {
+ return true;
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/presenters/validation/INotification.cs
@@ -0,0 +1,11 @@
+using System;
+using System.ComponentModel;
+using System.Linq.Expressions;
+
+namespace solidware.financials.windows.ui.presenters.validation
+{
+ public interface INotification<T> : IDataErrorInfo
+ {
+ string this[Expression<Func<T, object>> property] { get; }
+ }
+}
\ No newline at end of file
product/desktop.ui/presenters/validation/Notification.cs
@@ -1,28 +1,29 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using gorilla.utility;
namespace solidware.financials.windows.ui.presenters.validation
{
- public class Notification<T> : IDataErrorInfo
+ public class Notification<T> : INotification<T>
{
- IDictionary<string, IList<IRule>> validationRules = new Dictionary<string, IList<IRule>>();
-
- public void Register<Severity>(Expression<Func<T, object>> property, Func<bool> failCondition, Func<string> errorMessage) where Severity : ISeverity, new()
+ public void Register<Severity>(Expression<Func<T, object>> property, Func<bool> failCondition, Func<string> errorMessage) where Severity : validation.Severity, new()
{
Register(property, new AnonymousRule<Severity>(failCondition, errorMessage));
}
- public void Register(Expression<Func<T, object>> property, IRule rule)
+ public void Register(Expression<Func<T, object>> property, Rule rule)
{
EnsureRulesAreInitializeFor(property);
validationRules[property.pick_property().Name].Add(rule);
}
- public string this[Expression<Func<T, object>> property] { get { return this[property.pick_property().Name]; } }
+ public string this[Expression<Func<T, object>> property]
+ {
+ get { return this[property.pick_property().Name]; }
+ }
+
public string this[string propertyName]
{
get
@@ -40,7 +41,7 @@ namespace solidware.financials.windows.ui.presenters.validation
get { throw new NotImplementedException(); }
}
- public bool AreAnyRulesViolatedAndMoreSevereThan<Severity>() where Severity : ISeverity, new()
+ public bool AreAnyRulesViolatedAndMoreSevereThan<Severity>() where Severity : validation.Severity, new()
{
return validationRules.Any(validationRule => validationRule.Value.Any(x => x.IsViolatedAndMoreSevereThan<Severity>()));
}
@@ -48,10 +49,10 @@ namespace solidware.financials.windows.ui.presenters.validation
void EnsureRulesAreInitializeFor(Expression<Func<T, object>> property)
{
if (!validationRules.ContainsKey(property.pick_property().Name))
- validationRules[property.pick_property().Name] = new List<IRule>();
+ validationRules[property.pick_property().Name] = new List<Rule>();
}
- string BuildErrorsFor(IEnumerable<IRule> validationRulesForProperty)
+ string BuildErrorsFor(IEnumerable<Rule> validationRulesForProperty)
{
var errors = new List<string>();
validationRulesForProperty.each(x =>
@@ -60,55 +61,7 @@ namespace solidware.financials.windows.ui.presenters.validation
});
return string.Join(Environment.NewLine, errors.ToArray());
}
- }
- public interface IRule
- {
- bool IsViolated();
- string ErrorMessage { get; }
- bool IsViolatedAndMoreSevereThan<Severity>() where Severity : ISeverity, new();
- }
- public interface ISeverity
- {
- bool IsMoreSevereThan<OtherSeverity>(OtherSeverity otherSeverity) where OtherSeverity : ISeverity;
- }
- public class Warning : ISeverity
- {
- public bool IsMoreSevereThan<OtherSeverity>(OtherSeverity otherSeverity) where OtherSeverity : ISeverity
- {
- return !(otherSeverity is Error);
- }
- }
- public class Error : ISeverity
- {
- public bool IsMoreSevereThan<OtherSeverity>(OtherSeverity otherSeverity) where OtherSeverity : ISeverity
- {
- return true;
- }
- }
- public class AnonymousRule<Severity> : IRule where Severity : ISeverity, new()
- {
- readonly Func<bool> failCondition;
- readonly Func<string> errorMessage;
-
- public AnonymousRule(Func<bool> failCondition, Func<string> errorMessage)
- {
- this.failCondition = failCondition;
- this.errorMessage = errorMessage;
- }
-
- public string ErrorMessage
- {
- get { return errorMessage(); }
- }
- public bool IsViolatedAndMoreSevereThan<OtherSeverity>() where OtherSeverity : ISeverity, new()
- {
- return IsViolated() && new Severity().IsMoreSevereThan(new OtherSeverity());
- }
-
- public bool IsViolated()
- {
- return failCondition();
- }
+ IDictionary<string, IList<Rule>> validationRules = new Dictionary<string, IList<Rule>>();
}
}
\ No newline at end of file
product/desktop.ui/presenters/validation/Rule.cs
@@ -0,0 +1,9 @@
+namespace solidware.financials.windows.ui.presenters.validation
+{
+ public interface Rule
+ {
+ bool IsViolated();
+ string ErrorMessage { get; }
+ bool IsViolatedAndMoreSevereThan<Severity>() where Severity : validation.Severity, new();
+ }
+}
\ No newline at end of file
product/desktop.ui/presenters/validation/Severity.cs
@@ -0,0 +1,7 @@
+namespace solidware.financials.windows.ui.presenters.validation
+{
+ public interface Severity
+ {
+ bool IsMoreSevereThan<OtherSeverity>(OtherSeverity otherSeverity) where OtherSeverity : Severity;
+ }
+}
\ No newline at end of file
product/desktop.ui/presenters/validation/Warning.cs
@@ -0,0 +1,10 @@
+namespace solidware.financials.windows.ui.presenters.validation
+{
+ public class Warning : Severity
+ {
+ public bool IsMoreSevereThan<OtherSeverity>(OtherSeverity otherSeverity) where OtherSeverity : Severity
+ {
+ return !(otherSeverity is Error);
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/presenters/AddNewStockSymbolPresenter.cs
@@ -1,29 +1,51 @@
using System;
+using System.Linq.Expressions;
+using gorilla.utility;
using solidware.financials.infrastructure;
using solidware.financials.messages;
+using solidware.financials.windows.ui.presenters.validation;
namespace solidware.financials.windows.ui.presenters
{
- public class AddNewStockSymbolPresenter : DialogPresenter
+ public class AddNewStockSymbolPresenter : DialogPresenter, INotification<AddNewStockSymbolPresenter>
{
- UICommandBuilder builder;
-
public AddNewStockSymbolPresenter(UICommandBuilder builder)
{
this.builder = builder;
+ Notification = new Notification<AddNewStockSymbolPresenter>();
}
public ObservableCommand Add { get; set; }
public ObservableCommand Cancel { get; set; }
public virtual string Symbol { get; set; }
public virtual Action close { get; set; }
+ public Notification<AddNewStockSymbolPresenter> Notification { get; set; }
public void present()
{
Add = builder.build<AddCommand>(this);
Cancel = builder.build<CancelCommand>(this);
+
+ Notification.Register<Error>(x => x.Symbol, () => Symbol.is_blank(), () => "Please specify a symbol.");
+ }
+
+ public string this[string property]
+ {
+ get { return Notification[property]; }
+ }
+
+ public string this[Expression<Func<AddNewStockSymbolPresenter, object>> property]
+ {
+ get { return Notification[property]; }
}
+ public string Error
+ {
+ get { return Notification.Error; }
+ }
+
+ UICommandBuilder builder;
+
public class AddCommand : UICommand<AddNewStockSymbolPresenter>
{
ServiceBus bus;
product/desktop.ui/views/dialogs/AddNewStockSymbolDialog.xaml
@@ -1,12 +1,23 @@
<ui:WPFDialog x:Class="solidware.financials.windows.ui.views.dialogs.AddNewStockSymbolDialog" xmlns:ui="clr-namespace:solidware.financials.windows.ui" x:TypeArguments="presenters:AddNewStockSymbolPresenter" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:presenters="clr-namespace:solidware.financials.windows.ui.presenters" Title="Watch New Stock" Width="400" Height="90" WindowStartupLocation="CenterOwner">
- <StackPanel>
- <DockPanel>
- <Label Width="120px">Symbol:</Label>
- <TextBox Text="{Binding Path=Symbol, UpdateSourceTrigger=PropertyChanged}"></TextBox>
- </DockPanel>
- <DockPanel LastChildFill="False" HorizontalAlignment="Right">
- <Button IsDefault="True" Command="{Binding Path=Add}">_Add</Button>
- <Button IsCancel="True" Command="{Binding Path=Cancel}">_Cancel</Button>
- </DockPanel>
- </StackPanel>
+ <StackPanel>
+ <StackPanel.Resources>
+ <Style x:Key="Error">
+ <Style.Triggers>
+ <Trigger Property="Validation.HasError" Value="true">
+ <Setter Property="Control.ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}" />
+ <Setter Property="Control.BorderBrush" Value="Red" />
+ <Setter Property="Control.BorderThickness" Value="2" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </StackPanel.Resources>
+ <DockPanel>
+ <Label Width="120px">Symbol:</Label>
+ <TextBox Text="{Binding Path=Symbol, UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" Style="{StaticResource Error}"></TextBox>
+ </DockPanel>
+ <DockPanel LastChildFill="False" HorizontalAlignment="Right">
+ <Button IsDefault="True" Command="{Binding Path=Add}">_Add</Button>
+ <Button IsCancel="True" Command="{Binding Path=Cancel}">_Cancel</Button>
+ </DockPanel>
+ </StackPanel>
</ui:WPFDialog>
\ No newline at end of file
product/desktop.ui/solidware.financials.csproj
@@ -114,8 +114,14 @@
<Compile Include="bootstrappers\ComposeShell.cs" />
<Compile Include="bootstrappers\ConfigureMappings.cs" />
<Compile Include="bootstrappers\DefaultMapper.cs" />
+ <Compile Include="presenters\validation\AnonymousRule.cs" />
+ <Compile Include="presenters\validation\Error.cs" />
+ <Compile Include="presenters\validation\INotification.cs" />
<Compile Include="presenters\validation\Notification.cs" />
<Compile Include="presenters\SingleStockPresenter.cs" />
+ <Compile Include="presenters\validation\Rule.cs" />
+ <Compile Include="presenters\validation\Severity.cs" />
+ <Compile Include="presenters\validation\Warning.cs" />
<Compile Include="RunInBackgroundInterceptor.cs" />
<Compile Include="bootstrappers\StopEssentialServices.cs" />
<Compile Include="bootstrappers\WireUpSubscribers.cs" />
product/specs/unit/ui/presenters/AddNewStockSymbolPresenterSpecs.cs
@@ -50,6 +50,22 @@ namespace specs.unit.ui.presenters
static ObservableCommand cancel_command;
}
+ public class when_a_blank_symbol_is_entered : concern
+ {
+ Because of = () =>
+ {
+ sut.present();
+ result = sut[x => x.Symbol];
+ };
+
+ It should_display_an_error = () =>
+ {
+ result.should_be_equal_to("Please specify a symbol.");
+ };
+
+ static string result;
+ }
+
public class AddCommandSpecs
{
public abstract class concern_for_add_command
@@ -70,7 +86,10 @@ namespace specs.unit.ui.presenters
{
presenter = Create.an<AddNewStockSymbolPresenter>();
presenter.is_told_to(x => x.Symbol).it_will_return("TD.TO");
- presenter.Stub(x => x.close).Return(() => { closed = true; });
+ presenter.Stub(x => x.close).Return(() =>
+ {
+ closed = true;
+ });
};
Because of = () =>