Skip to content

Commit

Permalink
Merged release/1.7.0.0 into master
Browse files Browse the repository at this point in the history
  • Loading branch information
takuya-takeuchi committed Nov 11, 2016
2 parents 1d3b21c + 1d5adb8 commit a9865f5
Show file tree
Hide file tree
Showing 19 changed files with 741 additions and 65 deletions.
1 change: 1 addition & 0 deletions source/RedArmory/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@
IsHidden="False"
TriggerCount="1" />
<converters:TaskStateToStringConverter x:Key="TaskStateToStringConverter"/>
<converters:TaskToTriggerStringConverter x:Key="TaskToTriggerStringConverter"/>

<!-- Chart -->
<Style x:Key="MinimalChartStyle" TargetType="metroChart:ChartBase">
Expand Down
168 changes: 168 additions & 0 deletions source/RedArmory/Behaviors/NumericOnlyTextBoxBehaviors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace Ouranos.RedArmory.Behaviors
{

internal sealed class NumericOnlyTextBoxBehaviors : Behavior<TextBox>
{

#region 依存関係プロパティ

public static readonly DependencyProperty DefaultNumericProperty = DependencyProperty.RegisterAttached(
"DefaultNumeric",
typeof(int),
typeof(NumericOnlyTextBoxBehaviors),
new UIPropertyMetadata(0));

[AttachedPropertyBrowsableForType(typeof(TextBox))]
public static int GetDefaultNumeric(DependencyObject obj)
{
return (int)obj.GetValue(DefaultNumericProperty);
}

[AttachedPropertyBrowsableForType(typeof(TextBox))]
public static void SetDefaultNumeric(DependencyObject obj, int value)
{
obj.SetValue(DefaultNumericProperty, value);
}

public static readonly DependencyProperty IsNumericProperty = DependencyProperty.RegisterAttached(
"IsNumeric",
typeof(bool),
typeof(NumericOnlyTextBoxBehaviors),
new UIPropertyMetadata(false));

[AttachedPropertyBrowsableForType(typeof(TextBox))]
public static bool GetIsNumeric(DependencyObject obj)
{
return (bool)obj.GetValue(IsNumericProperty);
}

[AttachedPropertyBrowsableForType(typeof(TextBox))]
public static void SetIsNumeric(DependencyObject obj, bool value)
{
obj.SetValue(IsNumericProperty, value);
}

#endregion

#region メソッド

#region オーバーライド

protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.KeyDown += this.OnKeyDown;
this.AssociatedObject.TextChanged += this.OnTextChanged;
DataObject.AddPastingHandler(this.AssociatedObject, this.OnTextBoxPastingEventHandler);
}

protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.KeyDown -= this.OnKeyDown;
this.AssociatedObject.TextChanged -= this.OnTextChanged;
DataObject.RemovePastingHandler(this.AssociatedObject, this.OnTextBoxPastingEventHandler);
}

#endregion

#region イベントハンドラ

private void OnKeyDown(object sender, KeyEventArgs e)
{
if (!GetIsNumeric(this))
{
return;
}

var textBox = sender as TextBox;
if (textBox == null)
{
return;
}

if ((Key.D0 <= e.Key && e.Key <= Key.D9) ||
(Key.NumPad0 <= e.Key && e.Key <= Key.NumPad9) ||
(Key.Delete == e.Key) || (Key.Back == e.Key) || (Key.Tab == e.Key))
{
e.Handled = false;
}
else
{
e.Handled = true;
}
}

private void OnTextChanged(object sender, TextChangedEventArgs e)
{
if (!GetIsNumeric(this))
{
return;
}

var textBox = sender as TextBox;
if (textBox == null)
{
return;
}

if (string.IsNullOrEmpty(textBox.Text))
{
textBox.Text = GetDefaultNumeric(this).ToString();
}
}

private void OnTextBoxPastingEventHandler(object sender, DataObjectPastingEventArgs e)
{
if (!GetIsNumeric(this))
{
return;
}

var textBox = sender as TextBox;
var clipboard = e.DataObject.GetData(typeof(string)) as string;
clipboard = ValidateValue(clipboard);
if (textBox != null && !string.IsNullOrEmpty(clipboard))
{
textBox.Text = clipboard;
}

e.CancelCommand();
e.Handled = true;
}

#endregion

#region ヘルパーメソッド

private static string ValidateValue(string text)
{
var returntext = "";
foreach (var c in text)
{
if (Regex.Match(c.ToString(), "^[-0-9]$").Success)
{
returntext += c.ToString();
}
else if (c == '.')
{
returntext += c.ToString();
}
}

return returntext;
}

#endregion

#endregion

}

}
8 changes: 7 additions & 1 deletion source/RedArmory/Controls/DailyTriggerControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="clr-namespace:Ouranos.RedArmory.Models"
xmlns:viewModels="clr-namespace:Ouranos.RedArmory.ViewModels"
xmlns:behaviors="clr-namespace:Ouranos.RedArmory.Behaviors"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
d:DataContext="{d:DesignInstance {x:Type viewModels:DailyTriggerViewModel}}"
d:DesignHeight="300"
d:DesignWidth="300"
Expand Down Expand Up @@ -48,7 +50,11 @@
<TextBox MinWidth="20"
VerticalAlignment="Center"
Text="{Binding Interval,
StringFormat=d}" />
StringFormat=d, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Behaviors>
<behaviors:NumericOnlyTextBoxBehaviors IsNumeric="True" DefaultNumeric="1" />
</i:Interaction.Behaviors>
</TextBox>
<TextBlock Style="{StaticResource TriggerControlPropertyTextBlock}" Text="{Binding Source={x:Static models:ResourceService.Instance}, Path=Resources.Word_RecurEveryDays, Mode=OneWay}" />
</StackPanel>
<!--#endregion-->
Expand Down
4 changes: 2 additions & 2 deletions source/RedArmory/Controls/DateTimeControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ public DateTimeControl()

#region プロパティ

public WeeklyTriggerViewModel ViewModel
public TriggerViewModel ViewModel
{
get
{
return this.DataContext as WeeklyTriggerViewModel;
return this.DataContext as TriggerViewModel;
}
}

Expand Down
8 changes: 7 additions & 1 deletion source/RedArmory/Controls/WeeklyTriggerControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
xmlns:models="clr-namespace:Ouranos.RedArmory.Models"
xmlns:viewModels="clr-namespace:Ouranos.RedArmory.ViewModels"
xmlns:controls="clr-namespace:Ouranos.RedArmory.Controls"
xmlns:behaviors="clr-namespace:Ouranos.RedArmory.Behaviors"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
d:DataContext="{d:DesignInstance {x:Type viewModels:WeeklyTriggerViewModel}}"
d:DesignHeight="300"
d:DesignWidth="300"
Expand Down Expand Up @@ -49,7 +51,11 @@
<TextBox MinWidth="20"
VerticalAlignment="Center"
Text="{Binding Interval,
StringFormat=d}" />
StringFormat=d, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Behaviors>
<behaviors:NumericOnlyTextBoxBehaviors IsNumeric="True" DefaultNumeric="1" />
</i:Interaction.Behaviors>
</TextBox>
<TextBlock Style="{StaticResource TriggerControlPropertyTextBlock}" Text="{Binding Source={x:Static models:ResourceService.Instance}, Path=Resources.Word_RecurEveryWeeks, Mode=OneWay}" />
</StackPanel>
<!--#region Days-->
Expand Down
44 changes: 44 additions & 0 deletions source/RedArmory/Converters/TaskToTriggerStringConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Linq;
using System.Windows.Data;
using Microsoft.Win32.TaskScheduler;
using Ouranos.RedArmory.Extensions;

namespace Ouranos.RedArmory.Converters
{

/// <summary>
/// <see cref="Task"/> からトリガーを説明する文字列に変換します。このクラスは継承できません。
/// </summary>
internal sealed class TaskToTriggerStringConverter : IValueConverter
{

/// <summary>
/// 値を変換します。
/// </summary>
/// <param name="value">バインディング ソースによって生成された値。</param>
/// <param name="targetType">バインディング ターゲット プロパティの型。</param>
/// <param name="parameter">使用するコンバーター パラメーター。</param>
/// <param name="culture">コンバーターで使用するカルチャ。</param>
/// <returns>変換された値。メソッドが null を返す場合は、有効な null 値が使用されています。</returns>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// トリガーは一つだけという前提
var trigger = (value as Task)?.Definition?.Triggers?.FirstOrDefault();
return trigger?.ToDetailString();
}

/// <summary>
/// 値を変換します。
/// </summary>
/// <param name="value">バインディング ターゲットによって生成される値。</param>
/// <param name="targetType">変換後の型。</param>
/// <param name="parameter">使用するコンバーター パラメーター。</param>
/// <param name="culture">コンバーターで使用するカルチャ。</param>
/// <returns>変換された値。 メソッドが null を返す場合は、有効な null 値が使用されています。</returns>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
Loading

0 comments on commit a9865f5

Please sign in to comment.