Commit d22bdcb
Changed files (24)
product
desktop.ui
presenters
views
utility
product/desktop.ui/model/FederalTaxes.cs
@@ -1,4 +1,6 @@
-namespace solidware.financials.windows.ui.model
+using utility;
+
+namespace solidware.financials.windows.ui.model
{
public class FederalTaxes
{
@@ -7,7 +9,7 @@
var taxes = 0m;
if (totalIncome <= 41544.00m)
{
- taxes = ((totalIncome - 0m)*0.15m) + 0m;
+ taxes = totalIncome.subtract(0m).multiply_by(0.15m).add(0m);
}
if (totalIncome > 41544.00m && totalIncome <= 83088.00m)
{
product/desktop.ui/model/TaxesForIndividual.cs
@@ -4,7 +4,7 @@ using solidware.financials.windows.ui.presenters;
namespace solidware.financials.windows.ui.model
{
- public class TaxesForIndividual : Observable<TaxesForIndividual>
+ public class TaxesForIndividual : ObservablePresenter<TaxesForIndividual>
{
public TaxesForIndividual(Guid id, FederalTaxesViewModel federalTaxes)
{
product/desktop.ui/presenters/ButtonBarPresenter.cs
@@ -9,7 +9,7 @@ using solidware.financials.windows.ui.model;
namespace solidware.financials.windows.ui.presenters
{
- public class ButtonBarPresenter : Observable<ButtonBarPresenter>, Presenter, EventSubscriber<AddedNewFamilyMember>
+ public class ButtonBarPresenter : ObservablePresenter<ButtonBarPresenter>, Presenter, EventSubscriber<AddedNewFamilyMember>
{
PersonDetails selected_member;
EventAggregator event_aggregator;
product/desktop.ui/presenters/FederalTaxesViewModel.cs
@@ -1,30 +1,47 @@
using System;
-using System.Collections.Generic;
using solidware.financials.windows.ui.model;
+using solidware.financials.windows.ui.views.controls;
namespace solidware.financials.windows.ui.presenters
{
- public class FederalTaxesViewModel : Observable<FederalTaxesViewModel>
+ public class FederalTaxesViewModel : ObservablePresenter<FederalTaxesViewModel>
{
public FederalTaxesViewModel(Guid id)
{
Id = id;
- FederalTaxesGrid = new List<TaxRow>
- {
- new TaxRow {Name = "john doe", Tax = 23456.09m},
- new TaxRow {Name = "sally doe", Tax = 9456.09m},
- };
+ FederalTaxesGrid = CreateSampleTable();
}
public Guid Id { get; private set; }
public decimal FederalTaxes { get; set; }
public decimal FederalFamilyTaxes { get; private set; }
- public IEnumerable<TaxRow> FederalTaxesGrid { get; private set; }
+ public DataGridTable FederalTaxesGrid { get; private set; }
public void ChangeTotalIncomeTo(decimal totalIncome)
{
FederalTaxes = new FederalTaxes().CalculateFederalTaxesFor(totalIncome);
+ FederalTaxesGrid.AddRow(x =>
+ {
+ x.AddToCell(new Column<string>("Name"), "blah");
+ x.AddToCell(new Column<decimal>("Tax"), totalIncome);
+ });
update(x => x.FederalTaxes);
}
+
+ DataGridTable CreateSampleTable()
+ {
+ var table = new DataGridTable();
+ var nameColumn = table.CreateColumn<string>("Name");
+ var tax = table.CreateColumn<decimal>("Tax");
+
+ table.AddRow(x =>
+ {
+ x.AddToCell(nameColumn, "mo");
+ x.AddToCell(tax, 12345.67m);
+ });
+ table.AddRow(x => x.AddToCell(nameColumn, "allison"));
+ table.FindRowFor(nameColumn, "allison").AddToCell(tax, 98765.43m);
+ return table;
+ }
}
}
\ No newline at end of file
product/desktop.ui/presenters/StatusBarPresenter.cs
@@ -4,7 +4,7 @@ using solidware.financials.windows.ui.events;
namespace solidware.financials.windows.ui.presenters
{
- public class StatusBarPresenter : Observable<StatusBarPresenter>, Presenter, EventSubscriber<UpdateOnLongRunningProcess>
+ public class StatusBarPresenter : ObservablePresenter<StatusBarPresenter>, Presenter, EventSubscriber<UpdateOnLongRunningProcess>
{
public string progress_message { get; set; }
public bool is_progress_bar_on { get; set; }
product/desktop.ui/presenters/TaxSummaryPresenter.cs
@@ -8,7 +8,7 @@ using solidware.financials.windows.ui.model;
namespace solidware.financials.windows.ui.presenters
{
- public class TaxSummaryPresenter : Observable<TaxSummaryPresenter>, TabPresenter, EventSubscriber<IncomeMessage>, EventSubscriber<SelectedFamilyMember>
+ public class TaxSummaryPresenter : ObservablePresenter<TaxSummaryPresenter>, TabPresenter, EventSubscriber<IncomeMessage>, EventSubscriber<SelectedFamilyMember>
{
UICommandBuilder builder;
ServiceBus bus;
product/desktop.ui/views/controls/ClipboardHelper.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Windows;
+
+namespace solidware.financials.windows.ui.views.controls
+{
+ static public class ClipboardHelper
+ {
+ static public List<string[]> ParseClipboardData()
+ {
+ var dataObj = Clipboard.GetDataObject();
+ if (dataObj == null) return new List<string[]>();
+
+ var clipboardRawData = dataObj.GetData(DataFormats.Text);
+ if (clipboardRawData == null) return new List<string[]>();
+
+ var rawDataStr = clipboardRawData as string;
+ if (rawDataStr == null && clipboardRawData is MemoryStream)
+ {
+ var ms = clipboardRawData as MemoryStream;
+ var sr = new StreamReader(ms);
+ rawDataStr = sr.ReadToEnd();
+ }
+ Debug.Assert(rawDataStr != null, string.Format("clipboardRawData: {0}, could not be converted to a string or memorystream.", clipboardRawData));
+
+ var clipboardData = new List<string[]>();
+ var rows = rawDataStr.Split(new[] {"\r\n"}, StringSplitOptions.RemoveEmptyEntries);
+ if (rows.Length > 0)
+ {
+ clipboardData = rows.Select(row => ParseTextFormat(row)).ToList();
+ }
+ else
+ {
+ Debug.WriteLine("unable to parse row data. possibly null or contains zero rows.");
+ }
+
+ return clipboardData.Where(x => x != null && x.Count() > 0 && x.First() != "\0").ToList();
+ }
+
+ static string[] ParseTextFormat(string value)
+ {
+ var outputList = new List<string>();
+ const char separator = '\t';
+ var startIndex = 0;
+ var endIndex = 0;
+
+ for (var i = 0; i < value.Length; i++)
+ {
+ var ch = value[i];
+ if (ch == separator)
+ {
+ outputList.Add(value.Substring(startIndex, endIndex - startIndex));
+
+ startIndex = endIndex + 1;
+ endIndex = startIndex;
+ }
+ else if (i + 1 == value.Length)
+ {
+ // add the last value
+ outputList.Add(value.Substring(startIndex));
+ break;
+ }
+ else
+ {
+ endIndex++;
+ }
+ }
+
+ return outputList.ToArray();
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/views/controls/Column.cs
@@ -0,0 +1,59 @@
+using System;
+
+namespace solidware.financials.windows.ui.views.controls
+{
+ public class Column<T> : IEquatable<Column<T>>
+ {
+ public string Title { get; private set; }
+
+ public Column(string title)
+ {
+ Title = title;
+ }
+
+ public override string ToString()
+ {
+ return Title;
+ }
+
+ static public implicit operator Column<T>(string title)
+ {
+ return new Column<T>(title);
+ }
+
+ static public implicit operator string(Column<T> column)
+ {
+ return column.Title;
+ }
+
+ public bool Equals(Column<T> other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return Equals(other.Title, Title);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != typeof (Column<T>)) return false;
+ return Equals((Column<T>) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return (Title != null ? Title.GetHashCode() : 0);
+ }
+
+ public static bool operator ==(Column<T> left, Column<T> right)
+ {
+ return Equals(left, right);
+ }
+
+ public static bool operator !=(Column<T> left, Column<T> right)
+ {
+ return !Equals(left, right);
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/views/controls/DataGridTable.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Linq;
+using gorilla.utility;
+
+namespace solidware.financials.windows.ui.views.controls
+{
+ public class DataGridTable : SmartCollection<Row>
+ {
+ public virtual Row FindRowFor<ColumnType>(Column<ColumnType> column, ColumnType expectedValue)
+ {
+ return FindRowMatching(row => row.ValueStoredIn(column).Equals(expectedValue));
+ }
+
+ public virtual Row FindRowMatching(Func<Row, bool> condition)
+ {
+ return this.First(condition);
+ }
+
+ public virtual void AddRow(Action<Row> configureRow)
+ {
+ var row = new Row(this);
+ configureRow(row);
+ Add(row);
+ }
+
+ public virtual Column<T> CreateColumn<T>(string columnName)
+ {
+ var column = new Column<T>(columnName);
+ this.each(x => x.AddToCell(column, default(T)));
+ return column;
+ }
+
+ public virtual Column<T> FindColumn<T>(string columnName)
+ {
+ return this.Any() ? null : this.First().FindColumn<T>(columnName);
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/views/controls/IObservable.cs
@@ -0,0 +1,9 @@
+using System.ComponentModel;
+
+namespace solidware.financials.windows.ui.views.controls
+{
+ public interface IObservable : INotifyPropertyChanged
+ {
+ object Value { get; }
+ }
+}
\ No newline at end of file
product/desktop.ui/views/controls/ObjectExtensions.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace solidware.financials.windows.ui.views.controls
+{
+ static public class ObjectExtensions
+ {
+ static public bool IsNumeric(this object value)
+ {
+ return value.Is<short>() || value.Is<int>() || value.Is<long>() || value.Is<decimal>() || value.Is<float>() || value.Is<double>();
+ }
+
+ static public bool IsNull<T>(this T item) where T : class
+ {
+ return item == null;
+ }
+
+ static public bool Is<T>(this object value)
+ {
+ return value is T;
+ }
+ public static T As<T>(this object value)
+ {
+ if (value is T)
+ return (T)value;
+ if(value is IObservable)
+ {
+ return (T)((IObservable)value).Value;
+ }
+ return (T)Convert.ChangeType(value, typeof (T));
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/views/controls/Observable.cs
@@ -0,0 +1,39 @@
+using System.ComponentModel;
+
+namespace solidware.financials.windows.ui.views.controls
+{
+ public class Observable<T> : IObservable
+ {
+ private T value;
+
+ public Observable() { }
+
+ public Observable(T value)
+ {
+ this.value = value;
+ }
+
+ public T Value
+ {
+ get { return value; }
+ set
+ {
+ this.value = value;
+ PropertyChanged(this, new PropertyChangedEventArgs("Value"));
+ }
+ }
+
+ object IObservable.Value { get { return value; } }
+
+ public static implicit operator T(Observable<T> val)
+ {
+ return val.value;
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged = delegate { };
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/views/controls/Row.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+using System.Linq;
+using gorilla.utility;
+
+namespace solidware.financials.windows.ui.views.controls
+{
+ public class Row : Dictionary<string, IObservable>
+ {
+ DataGridTable table;
+
+ public Row(DataGridTable table)
+ {
+ this.table = table;
+ }
+
+ public virtual T ValueStoredIn<T>(Column<T> column)
+ {
+ return this[column].As<T>();
+ }
+
+ public virtual void AddToCell<T>(Column<T> column, T value)
+ {
+ AddToCell(column, (IObservable)new Observable<T>(value));
+ }
+
+ public virtual void AddToCell<T>(Column<T> column, IObservable value)
+ {
+ this[column] = value;
+ table.each(row =>
+ {
+ if (!row.HasValueStoredIn(column))
+ row[column] = new Observable<T>(default(T));
+ });
+ }
+
+ public virtual bool HasValueStoredIn<T>(Column<T> column)
+ {
+ return ContainsKey(column);
+ }
+
+ public virtual Column<T> FindColumn<T>(string name)
+ {
+ return Keys.FirstOrDefault(x => x == name);
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/views/controls/SmartCollection.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+
+namespace solidware.financials.windows.ui.views.controls
+{
+ public class SmartCollection<T> : ObservableCollection<T>
+ {
+ bool suspend;
+
+ public SmartCollection()
+ {
+ suspend = false;
+ }
+
+ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ {
+ if (!suspend) base.OnCollectionChanged(e);
+ }
+
+ public IDisposable BeginEdit()
+ {
+ return new SuspendNotifications<T>(this);
+ }
+
+ class SuspendNotifications<K> : IDisposable
+ {
+ readonly SmartCollection<K> items;
+
+ public SuspendNotifications(SmartCollection<K> items)
+ {
+ this.items = items;
+ items.suspend = true;
+ }
+
+ public void Dispose()
+ {
+ items.suspend = false;
+ items.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/views/controls/SmartGrid.cs
@@ -0,0 +1,233 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Input;
+using System.Windows.Media;
+using gorilla.utility;
+
+namespace solidware.financials.windows.ui.views.controls
+{
+ public class SmartGrid : DataGrid
+ {
+ static SmartGrid()
+ {
+ IsReadOnlyProperty.OverrideMetadata(typeof (SmartGrid), new FrameworkPropertyMetadata((o, e) => ((SmartGrid) o).ConfigureColumns()));
+ ValueConvertersProperty.OverrideMetadata(typeof (SmartGrid), new FrameworkPropertyMetadata((o, e) => ((SmartGrid) o).ConfigureColumns()));
+ CommandManager.RegisterClassCommandBinding(typeof (SmartGrid), new CommandBinding(ApplicationCommands.Paste, (o, e) => ((SmartGrid) o).OnExecutedPaste()));
+ }
+
+ static public readonly DependencyProperty ReadOnlyColumnsProperty = DependencyProperty.Register("ReadOnlyColumns", typeof (IEnumerable<string>), typeof (SmartGrid));
+ static public readonly DependencyProperty HeaderColumnsProperty = DependencyProperty.Register("HeaderColumns", typeof (IEnumerable<string>), typeof (SmartGrid));
+
+ static public readonly DependencyProperty ValueConvertersProperty = DependencyProperty.Register("ValueConverters", typeof (IEnumerable<KeyValuePair<string, IValueConverter>>),
+ typeof (SmartGrid));
+
+ static public readonly DependencyProperty ReadOnlyItemsProperty = DependencyProperty.Register("ReadOnlyItems", typeof (IEnumerable<IDictionary<string, object>>), typeof (SmartGrid));
+
+ static readonly SolidColorBrush HeaderColour = Brushes.LightGray;
+ static readonly SolidColorBrush ReadOnlyColour = Brushes.WhiteSmoke;
+
+ public SmartGrid()
+ {
+ SelectionUnit = DataGridSelectionUnit.CellOrRowHeader;
+ ContextMenu = new ContextMenu
+ {
+ Items =
+ {
+ new MenuItem {Command = ApplicationCommands.Copy},
+ new MenuItem {Command = ApplicationCommands.Paste}
+ }
+ };
+ }
+
+ public virtual IEnumerable<IDictionary<string, object>> ReadOnlyItems
+ {
+ get { return (IEnumerable<IDictionary<string, object>>) GetValue(ReadOnlyItemsProperty) ?? Enumerable.Empty<IDictionary<string, object>>(); }
+ set { SetValue(ReadOnlyItemsProperty, value); }
+ }
+
+ public IEnumerable<string> ReadOnlyColumns
+ {
+ get { return (IEnumerable<string>) GetValue(ReadOnlyColumnsProperty) ?? Enumerable.Empty<string>(); }
+ set
+ {
+ SetValue(ReadOnlyColumnsProperty, value);
+ if (Columns != null && Columns.Count > 0)
+ {
+ ConfigureColumns();
+ }
+ }
+ }
+
+ public IEnumerable<string> HeaderColumns
+ {
+ get { return (IEnumerable<string>) GetValue(HeaderColumnsProperty) ?? Enumerable.Empty<string>(); }
+ set
+ {
+ SetValue(HeaderColumnsProperty, value);
+ if (Columns != null && Columns.Count > 0)
+ {
+ ConfigureColumns();
+ }
+ }
+ }
+
+ public IEnumerable<KeyValuePair<string, IValueConverter>> ValueConverters
+ {
+ get { return (IEnumerable<KeyValuePair<string, IValueConverter>>) GetValue(ValueConvertersProperty) ?? Enumerable.Empty<KeyValuePair<string, IValueConverter>>(); }
+ set
+ {
+ SetValue(ValueConvertersProperty, value);
+ if (Columns != null && Columns.Count > 0)
+ {
+ ConfigureColumns();
+ }
+ }
+ }
+
+ void ConfigureColumns()
+ {
+ foreach (var column in Columns)
+ {
+ var header = column.Header.ToString();
+ column.IsReadOnly = IsReadOnly || ReadOnlyColumns.Contains(header);
+
+ Brush background = null;
+ if (HeaderColumns.Contains(header))
+ {
+ background = HeaderColour;
+ }
+ else if (ReadOnlyColumns.Contains(header))
+ {
+ background = ReadOnlyColour;
+ }
+ if (background != null)
+ {
+ if (column.CellStyle == null) column.CellStyle = new Style();
+ SetPropertyIfNotPresent(column, BackgroundProperty, background);
+ SetPropertyIfNotPresent(column, ForegroundProperty, Brushes.Black);
+ }
+
+ var textColumn = column as DataGridTextColumn;
+ if (textColumn == null) continue;
+ var binding = textColumn.Binding as Binding;
+ if (binding == null) continue;
+ if (binding.Converter != null) continue; // Converter has already been bound and cannot be changed.
+
+ var valueConverter = ValueConverters.SingleOrDefault(x => x.Key == header).Value;
+
+ if (valueConverter != null)
+ {
+ binding.Converter = valueConverter;
+ }
+ }
+ }
+
+ static void SetPropertyIfNotPresent(DataGridColumn column, DependencyProperty dependencyProperty, Brush brush)
+ {
+ var existing = column.CellStyle.Setters.OfType<Setter>().FirstOrDefault(x => x.Property == dependencyProperty);
+ if (existing == null)
+ {
+ column.CellStyle.Setters.Add(new Setter(dependencyProperty, brush));
+ }
+ }
+
+ protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
+ {
+ base.OnItemsSourceChanged(oldValue, newValue);
+ if (newValue == null) return;
+
+ var enumerator = newValue.GetEnumerator();
+ if (!enumerator.MoveNext()) return;
+
+ var firstRow = enumerator.Current as IDictionary<string, IObservable>;
+
+ if (firstRow == null) return;
+
+ AutoGenerateColumns = false;
+ Columns.Clear();
+ foreach (var pair in firstRow)
+ {
+ Columns.Add(new ExtendedTextColumn {Header = pair.Key, Binding = new Binding("[" + pair.Key + "].Value")});
+ }
+ ConfigureColumns();
+ }
+
+ protected override void OnLoadingRow(DataGridRowEventArgs e)
+ {
+ if (ReadOnlyItems != null)
+ {
+ e.Row.IsEnabled = !IsItemReadOnly(e.Row.Item);
+ if (!e.Row.IsEnabled)
+ {
+ e.Row.Background = HeaderColour;
+ }
+ }
+
+ base.OnLoadingRow(e);
+ }
+
+ protected virtual void OnExecutedPaste()
+ {
+ OnBeginningEdit(new DataGridBeginningEditEventArgs(Columns.First(), new DataGridRow(), new RoutedEventArgs()));
+ var rowData = ClipboardHelper.ParseClipboardData();
+
+ var minColumnDisplayIndex = SelectedCells.Min(x => x.Column.DisplayIndex);
+ var maxColumnDisplayIndex = SelectedCells.Max(x => x.Column.DisplayIndex);
+ var minRowIndex = SelectedCells.Min(y => Items.IndexOf(y.Item));
+ var maxRowIndex = SelectedCells.Max(y => Items.IndexOf(y.Item));
+
+ // If single cell select, then use as a starting cell rather than limiting the paste
+ if (minColumnDisplayIndex == maxColumnDisplayIndex && minRowIndex == maxRowIndex)
+ {
+ maxColumnDisplayIndex = Columns.Count - 1;
+ maxRowIndex = Items.Count - 1;
+ }
+
+ var rowDataIndex = 0;
+ for (var i = minRowIndex; i <= maxRowIndex && rowDataIndex <= rowData.Count() - 1; i++, rowDataIndex++)
+ {
+ var columnDataIndex = 0;
+ for (var j = minColumnDisplayIndex; j <= maxColumnDisplayIndex && columnDataIndex <= rowData[rowDataIndex].Length - 1; j++, columnDataIndex++)
+ {
+ var column = ColumnFromDisplayIndex(j);
+ if (column.IsReadOnly) continue;
+ if (IsItemReadOnly(Items[i])) continue;
+ column.OnPastingCellClipboardContent(Items[i], rowData[rowDataIndex][columnDataIndex]);
+ }
+ }
+ }
+
+ bool IsItemReadOnly(object item)
+ {
+ return ReadOnlyItems.Any(x => ReferenceEquals(x, item));
+ }
+
+ protected override void OnKeyUp(KeyEventArgs e)
+ {
+ switch (e.Key)
+ {
+ case Key.Delete:
+ foreach (var cell in SelectedCells.Where(x => !x.Column.IsReadOnly))
+ {
+ // N.B. Passing in an integer value of zero results in the Gas (MCF) column updating,
+ // but no other column updating. Using a string "0" results in all values
+ // updating properly. Very odd behaviour, but insufficient time to investigate why.
+ cell.Column.OnPastingCellClipboardContent(cell.Item, "0");
+ }
+ OnBeginningEdit(new DataGridBeginningEditEventArgs(Columns.First(), new DataGridRow(), new RoutedEventArgs()));
+ break;
+ case Key.Enter:
+ OnBeginningEdit(new DataGridBeginningEditEventArgs(Columns.First(), new DataGridRow(), new RoutedEventArgs()));
+ break;
+ default:
+ base.OnKeyUp(e);
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/views/ExtendedTextColumn.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace solidware.financials.windows.ui.views
+{
+ public class ExtendedTextColumn : DataGridTextColumn
+ {
+ public HorizontalAlignment HorizontalAlignment
+ {
+ get { return (HorizontalAlignment)GetValue(HorizontalAlignmentProperty); }
+ set { SetValue(HorizontalAlignmentProperty, value); }
+ }
+
+ public static readonly DependencyProperty HorizontalAlignmentProperty =
+ DependencyProperty.Register(
+ "HorizontalAlignment",
+ typeof(HorizontalAlignment),
+ typeof(ExtendedTextColumn),
+ new UIPropertyMetadata(HorizontalAlignment.Stretch));
+
+ public VerticalAlignment VerticalAlignment
+ {
+ get { return (VerticalAlignment)GetValue(VerticalAlignmentProperty); }
+ set { SetValue(VerticalAlignmentProperty, value); }
+ }
+
+ public static readonly DependencyProperty VerticalAlignmentProperty =
+ DependencyProperty.Register(
+ "VerticalAlignment",
+ typeof(VerticalAlignment),
+ typeof(ExtendedTextColumn),
+ new UIPropertyMetadata(VerticalAlignment.Stretch));
+
+ private TextAlignment GetTextAlignment()
+ {
+ switch (HorizontalAlignment)
+ {
+ case HorizontalAlignment.Center:
+ return TextAlignment.Center;
+ case HorizontalAlignment.Left:
+ return TextAlignment.Left;
+ case HorizontalAlignment.Right:
+ return TextAlignment.Right;
+ case HorizontalAlignment.Stretch:
+ return TextAlignment.Justify;
+ default:
+ throw new ArgumentOutOfRangeException("HorizontalAlignment", "Unsupported alignment type!");
+ }
+ }
+
+ protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
+ {
+ var element = base.GenerateElement(cell, dataItem);
+
+ element.HorizontalAlignment = HorizontalAlignment;
+ element.VerticalAlignment = VerticalAlignment;
+
+ return element;
+ }
+
+ protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
+ {
+ var textBox = (TextBox)base.GenerateEditingElement(cell, dataItem);
+
+ textBox.TextAlignment = GetTextAlignment();
+ textBox.VerticalContentAlignment = VerticalAlignment;
+
+ return textBox;
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/views/TaxSummaryTab.xaml
@@ -2,8 +2,7 @@
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"
- mc:Ignorable="d" >
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:controls="clr-namespace:solidware.financials.windows.ui.views.controls" mc:Ignorable="d" >
<DockPanel MinWidth="1024">
<StackPanel>
<StackPanel Margin="5,5,5,5">
@@ -18,7 +17,7 @@
</DockPanel>
</StackPanel>
<DockPanel LastChildFill="False" HorizontalAlignment="Stretch">
- <StackPanel Margin="5,5,5,5" Width="500">
+ <StackPanel Margin="5,5,5,5" Width="500" DataContext="{Binding Path=FederalTaxes}">
<Label FontWeight="Bold">Federal Taxes</Label>
<Expander Header="Tax Rates">
<StackPanel>
@@ -33,13 +32,13 @@
</Expander>
<DockPanel>
<Label Width="100">Individual:</Label>
- <Label Content="{Binding Path=FederalTaxes.FederalTaxes}" FontWeight="Bold"/>
+ <Label Content="{Binding Path=FederalTaxes}" FontWeight="Bold"/>
</DockPanel>
<DockPanel>
<Label Width="100">Family:</Label>
- <Label Content="{Binding Path=FederalTaxes.FederalFamilyTaxes}" FontWeight="Bold"/>
+ <Label Content="{Binding Path=FederalFamilyTaxes}" FontWeight="Bold"/>
</DockPanel>
- <DataGrid Margin="5,5,5,5" ItemsSource="{Binding FederalTaxes.FederalTaxesGrid, Mode=OneWay}" IsReadOnly="True"></DataGrid>
+ <controls:SmartGrid Margin="5,5,5,5" ItemsSource="{Binding FederalTaxesGrid, Mode=OneWay}" IsReadOnly="True"></controls:SmartGrid>
</StackPanel>
<StackPanel Margin="5,5,5,5" Width="500">
<Label FontWeight="Bold">Provincial Taxes</Label>
product/desktop.ui/views/TaxSummaryTab.xaml.cs
@@ -8,5 +8,10 @@ namespace solidware.financials.windows.ui.views
{
InitializeComponent();
}
+
+ public void bind_to(TaxSummaryPresenter presenter)
+ {
+ DataContext = presenter;
+ }
}
}
\ No newline at end of file
product/desktop.ui/Observable.cs → product/desktop.ui/ObservablePresenter.cs
@@ -5,7 +5,7 @@ using gorilla.utility;
namespace solidware.financials.windows.ui
{
- public abstract class Observable<T> : INotifyPropertyChanged
+ public abstract class ObservablePresenter<T> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = (o, e) => { };
product/desktop.ui/solidware.financials.csproj
@@ -126,7 +126,7 @@
<Compile Include="model\FederalTaxes.cs" />
<Compile Include="model\TaxesForIndividual.cs" />
<Compile Include="model\TaxRow.cs" />
- <Compile Include="Observable.cs" />
+ <Compile Include="ObservablePresenter.cs" />
<Compile Include="Presenter.cs" />
<Compile Include="PresenterFactory.cs" />
<Compile Include="presenters\AddFamilyMemberPresenter.cs" />
@@ -157,12 +157,21 @@
<DependentUpon>AddNewIncomeDialog.xaml</DependentUpon>
</Compile>
<Compile Include="views\ButtonExpression.cs" />
+ <Compile Include="views\controls\ClipboardHelper.cs" />
+ <Compile Include="views\controls\Column.cs" />
+ <Compile Include="views\controls\DataGridTable.cs" />
+ <Compile Include="views\controls\IObservable.cs" />
+ <Compile Include="views\controls\ObjectExtensions.cs" />
+ <Compile Include="views\controls\Observable.cs" />
+ <Compile Include="views\controls\Row.cs" />
+ <Compile Include="views\controls\SmartCollection.cs" />
<Compile Include="views\DisplayCanadianTaxInformationDialog.xaml.cs">
<DependentUpon>DisplayCanadianTaxInformationDialog.xaml</DependentUpon>
</Compile>
<Compile Include="views\ErrorWindow.xaml.cs">
<DependentUpon>ErrorWindow.xaml</DependentUpon>
</Compile>
+ <Compile Include="views\ExtendedTextColumn.cs" />
<Compile Include="views\icons\UIIcon.cs" />
<Compile Include="views\icons\IconMarker.cs" />
<Compile Include="views\ImageButton.cs" />
@@ -177,6 +186,7 @@
<Compile Include="views\ShellWIndow.xaml.cs">
<DependentUpon>ShellWIndow.xaml</DependentUpon>
</Compile>
+ <Compile Include="views\controls\SmartGrid.cs" />
<Compile Include="views\StatusBarRegion.xaml.cs">
<DependentUpon>StatusBarRegion.xaml</DependentUpon>
</Compile>
product/desktop.ui/Tab.cs
@@ -1,4 +1,7 @@
namespace solidware.financials.windows.ui
{
- public interface Tab<Presenter> : View<Presenter> where Presenter : TabPresenter {}
+ public interface Tab<Presenter> : View<Presenter> where Presenter : TabPresenter
+ {
+ void bind_to(Presenter presenter);
+ }
}
\ No newline at end of file
product/desktop.ui/WPFApplicationController.cs
@@ -19,19 +19,19 @@ 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 : FrameworkElement, Tab<Presenter>, new()
{
var presenter = open<Presenter>();
+ var view = new View();
+ view.bind_to(presenter);
configure_region<DocumentPane>(x => x.Items.Add(new DocumentContent
{
Title = presenter.Header,
- Content = new View {DataContext = presenter},
+ Content = view,
}));
}
- public void load_region<TPresenter, Region>() where TPresenter : Presenter
- where Region : FrameworkElement, View<TPresenter>, new()
+ public void load_region<TPresenter, Region>() where TPresenter : Presenter where Region : FrameworkElement, View<TPresenter>, new()
{
configure_region<Region>(x => { x.DataContext = open<TPresenter>(); });
}
product/utility/Mathematics.cs
@@ -0,0 +1,25 @@
+namespace utility
+{
+ static public class Mathematics
+ {
+ static public decimal subtract(this decimal right, decimal left)
+ {
+ return right - left;
+ }
+
+ static public decimal add(this decimal right, decimal left)
+ {
+ return right + left;
+ }
+
+ static public decimal multiply_by(this decimal right, decimal left)
+ {
+ return right*left;
+ }
+
+ static public decimal divided_by(this decimal right, decimal left)
+ {
+ return right/left;
+ }
+ }
+}
\ No newline at end of file
product/utility/utility.csproj
@@ -45,6 +45,7 @@
<ItemGroup>
<Compile Include="MapKey.cs" />
<Compile Include="MapperRegistery.cs" />
+ <Compile Include="Mathematics.cs" />
<Compile Include="NeedsShutdown.cs" />
<Compile Include="NeedStartup.cs" />
</ItemGroup>