Commit a1005c4

mo <email@solidware.ca>
2011-04-05 02:09:04
hook up tooltip error when no symbol is specified when adding a new stock symbol to watch.
1 parent 27f8b3c
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 = () =>