<Compile Include="Clock.cs" />
<Compile Include="Clock.TizenMobile.cs" />
<Compile Include="Clock.Dependency.cs" />
+ <Compile Include="Controls\ExtendedEntry.cs" />
+ <Compile Include="Controls\ExtendedEntryRenderer.cs" />
<Compile Include="Controls\FloatingButtonRenderer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Controls\TimePickerRenderer.cs" />
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
-</Project>
\ No newline at end of file
+</Project>
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+
+namespace Clock.TizenMobile.Controls
+{
+ public class ExtendedEntry : Entry
+ {
+ public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create("IsSelected", typeof(bool), typeof(Entry), default(bool), BindingMode.TwoWay);
+ public static readonly BindableProperty MaxValueProperty = BindableProperty.Create("MaxValue", typeof(int), typeof(Entry), default(int), BindingMode.TwoWay);
+
+ public const int MaxLenght = 2;
+
+ public ExtendedEntry NextFocus
+ {
+ get;
+ set;
+ }
+
+ public ExtendedEntry()
+ {
+ TextChanged += OnEntryChanged;
+
+ Unfocused += OnEntryUnfocus;
+ Focused += OnEntryFocus;
+ }
+
+ public static bool Validate(ExtendedEntry entry)
+ {
+ int n;
+ var isNumeric = int.TryParse(entry.Text, out n);
+
+ if (string.IsNullOrWhiteSpace(entry.Text) || !isNumeric || n < 0)
+ {
+ entry.Text = "00";
+ return false;
+ }
+
+ if (n > entry.MaxValue)
+ {
+ entry.Text = entry.MaxValue.ToString("D2");
+ return false;
+ }
+
+ return true;
+ }
+
+ public int MaxValue
+ {
+ get
+ {
+ return (int)GetValue(MaxValueProperty);
+ }
+ set
+ {
+ SetValue(MaxValueProperty, value);
+ }
+ }
+
+ public bool IsSelected
+ {
+ get
+ {
+ return (bool)GetValue(IsSelectedProperty);
+ }
+ set
+ {
+ SetValue(IsSelectedProperty, value);
+ }
+ }
+
+ public void Increase()
+ {
+ int n;
+
+ if(!int.TryParse(Text, out n))
+ {
+ return;
+ }
+ ++n;
+
+ if (n > MaxValue)
+ {
+ n = 0;
+ }
+
+ Text = n.ToString("D2");
+ }
+
+ public void Decrease()
+ {
+ int n;
+
+ if(!int.TryParse(Text, out n))
+ {
+ return;
+ }
+ --n;
+
+ if (n < 0)
+ {
+ n = MaxValue;
+ }
+
+ Text = n.ToString("D2");
+ }
+
+ private static void OnEntryTextChanged(object sender, EventArgs e)
+ {
+ var entry = sender as ExtendedEntry;
+
+ if (entry.Text.Length >= 2)
+ {
+ EntryFocusNext(entry);
+ }
+ }
+
+ private static void EntryFocusNext(ExtendedEntry entry)
+ {
+ if (entry.NextFocus != null)
+ {
+ entry.NextFocus.Focus();
+ }
+ }
+
+ private static void OnEntryFocus(object sender, EventArgs e)
+ {
+ var entry = sender as ExtendedEntry;
+
+ entry.IsSelected = !entry.IsSelected;
+ }
+
+ private static void OnEntryUnfocus(object sender, FocusEventArgs e)
+ {
+ var entry = sender as ExtendedEntry;
+
+ int n;
+ var isNumeric = int.TryParse(entry.Text, out n);
+ if (n < 10)
+ {
+ var output = n.ToString().PadLeft(2, '0');
+
+ if (entry.Text != output)
+ {
+ entry.Text = output;
+ }
+
+ return;
+ }
+
+ entry.Text = n.ToString("D2");
+ }
+
+ private static void OnEntryChanged(object sender, TextChangedEventArgs e)
+ {
+ var entry = sender as ExtendedEntry;
+
+ if (!Validate(entry))
+ {
+ return;
+ }
+
+ int n;
+ var isNumeric = int.TryParse(entry.Text, out n);
+
+ if (entry.IsFocused && isNumeric && entry.Text.Length >= 2)
+ {
+ EntryFocusNext(entry);
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+using TNative = Xamarin.Forms.Platform.Tizen;
+
+[assembly: TNative.ExportRenderer(typeof(Clock.TizenMobile.Controls.ExtendedEntry), typeof(CustomRenderer.ExtendedEntryRenderer))]
+namespace CustomRenderer
+{
+ public class ExtendedEntryRenderer : TNative.EntryRenderer
+ {
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Clock.TizenMobile.Controls.ExtendedEntry.IsSelectedProperty.PropertyName)
+ {
+ Tizen.Log.Debug("CLOCK", "Entry selected!");
+ base.Control.SelectAll();
+ }
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+ }
+}
using Xamarin.Forms;
using ElmSharp;
-[assembly: ExportRenderer(typeof(Clock.TizenMobile.Controls.FloatingButton), typeof(CustomRenderer.Tizen.FloatingButtonRenderer))]
-namespace CustomRenderer.Tizen
+[assembly: ExportRenderer(typeof(Clock.TizenMobile.Controls.FloatingButton), typeof(CustomRenderer.FloatingButtonRenderer))]
+namespace CustomRenderer
{
public class FloatingButtonRenderer : ViewRenderer<Clock.TizenMobile.Controls.FloatingButton, ElmSharp.FloatingButton>
{
using Xamarin.Forms;
using Xamarin.Forms.Platform.Tizen;
-[assembly: ExportRenderer(typeof(Clock.TizenMobile.Controls.TimePicker), typeof(CustomRenderer.Tizen.TimePickerRenderer))]
-namespace CustomRenderer.Tizen {
+[assembly: ExportRenderer(typeof(Clock.TizenMobile.Controls.TimePicker), typeof(CustomRenderer.TimePickerRenderer))]
+namespace CustomRenderer {
class TimePickerRenderer : ViewRenderer<Xamarin.Forms.TimePicker, Xamarin.Forms.Platform.Tizen.Native.TimePicker>{
protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e) {
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:controls="clr-namespace:Clock.TizenMobile.Controls;assembly=Clock.TizenMobile"
x:Class="Clock.TizenMobile.Views.TimerView">
<ContentPage.Content>
<StackLayout Orientation="Horizontal" AbsoluteLayout.LayoutBounds=".5, .3, 620, 426" AbsoluteLayout.LayoutFlags="PositionProportional" >
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<Label Text="Hours" AbsoluteLayout.LayoutBounds=".235, .0, .2, .09" AbsoluteLayout.LayoutFlags="All" VerticalTextAlignment="End" HorizontalTextAlignment="Center" TextColor="White" />
- <Button BackgroundColor="Transparent" Image="images/alarm_picker_arrow_up.png" />
- <Entry x:Name="EntryHours" Text="00" TextChanged="OnEntryChanged" FontSize="80" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" HorizontalTextAlignment="Center" TextColor="White"/>
- <Button BackgroundColor="Transparent" Image="images/alarm_picker_arrow_down.png" />
+ <Button x:Name="ButtonHourIncrease" BackgroundColor="Transparent" Clicked="OnTimeButtonClicked" Image="images/alarm_picker_arrow_up.png" />
+ <controls:ExtendedEntry x:Name="EntryHours" Text="00" FontSize="80" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" HorizontalTextAlignment="Center" TextColor="White" MaxValue="99"/>
+ <Button x:Name="ButtonHourDecrease" BackgroundColor="Transparent" Clicked="OnTimeButtonClicked" Image="images/alarm_picker_arrow_down.png" />
</StackLayout>
- <Label Text=":" FontSize="80" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" VerticalTextAlignment="Center" TextColor="White"/>
+ <Label Text=":" FontSize="80" HorizontalOptions="FillAndExpand" VerticalOptions="Center" VerticalTextAlignment="Center" TextColor="White"/>
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<Label Text="Minutes" AbsoluteLayout.LayoutBounds=".5, .0, .2, .09" AbsoluteLayout.LayoutFlags="All" HorizontalTextAlignment="Center" TextColor="White" />
- <Button BackgroundColor="Transparent" Image="images/alarm_picker_arrow_up.png" />
- <Entry x:Name="EntryMinutes" Text="00" TextChanged="OnEntryChanged" FontSize="80" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" HorizontalTextAlignment="Center" TextColor="White"/>
- <Button BackgroundColor="Transparent" Image="images/alarm_picker_arrow_down.png" />
+ <Button x:Name="ButtonMinuteIncrease" BackgroundColor="Transparent" Clicked="OnTimeButtonClicked" Image="images/alarm_picker_arrow_up.png" />
+ <controls:ExtendedEntry x:Name="EntryMinutes" Text="00" FontSize="80" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" HorizontalTextAlignment="Center" TextColor="White" MaxValue="59"/>
+ <Button x:Name="ButtonMinuteDecrease" BackgroundColor="Transparent" Clicked="OnTimeButtonClicked" Image="images/alarm_picker_arrow_down.png" />
</StackLayout>
- <Label Text=":" FontSize="80" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" VerticalTextAlignment="Center" TextColor="White"/>
+ <Label Text=":" FontSize="80" HorizontalOptions="FillAndExpand" VerticalOptions="Center" VerticalTextAlignment="Center" TextColor="White"/>
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<Label Text="Seconds" AbsoluteLayout.LayoutBounds=".765, .0, .2, .09" AbsoluteLayout.LayoutFlags="All" HorizontalTextAlignment="Center" TextColor="White" />
- <Button BackgroundColor="Transparent" Image="images/alarm_picker_arrow_up.png" />
- <Entry x:Name="EntrySeconds" Text="00" TextChanged="OnEntryChanged" FontSize="80" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" HorizontalTextAlignment="Center" TextColor="White"/>
- <Button BackgroundColor="Transparent" Image="images/alarm_picker_arrow_down.png" />
+ <Button x:Name="ButtonSecondIncrease" BackgroundColor="Transparent" Clicked="OnTimeButtonClicked" Image="images/alarm_picker_arrow_up.png" />
+ <controls:ExtendedEntry x:Name="EntrySeconds" Text="00" FontSize="80" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" HorizontalTextAlignment="Center" TextColor="White" MaxValue="59"/>
+ <Button x:Name="ButtonSecondDecrease" BackgroundColor="Transparent" Clicked="OnTimeButtonClicked" Image="images/alarm_picker_arrow_down.png" />
</StackLayout>
</StackLayout>
<AbsoluteLayout AbsoluteLayout.LayoutBounds=".5, 1, 720, 120" AbsoluteLayout.LayoutFlags="PositionProportional">
<BoxView Color="White" AbsoluteLayout.LayoutBounds=".5, 1, 1, 1" AbsoluteLayout.LayoutFlags="All"/>
- <Button x:Name="StartButton" Text="Start" AbsoluteLayout.LayoutBounds=".5, .5, 0.7, 0.7" AbsoluteLayout.LayoutFlags="All" IsVisible="True"/>
- <Button x:Name="PauseButton" Text="Pause" AbsoluteLayout.LayoutBounds=".1, .5, 0.4, 0.7" AbsoluteLayout.LayoutFlags="All" IsVisible="False"/>
- <Button x:Name="CancelButton" Text="Cancel" AbsoluteLayout.LayoutBounds=".9, .5, 0.4, 0.7" AbsoluteLayout.LayoutFlags="All" IsVisible="False"/>
- <Button x:Name="ResumeButton" Text="Resume" AbsoluteLayout.LayoutBounds=".1, .5, 0.4, 0.7" AbsoluteLayout.LayoutFlags="All" IsVisible="False"/>
- <Button x:Name="ResetButton" Text="Reset" AbsoluteLayout.LayoutBounds=".9, .5, 0.4, 0.7" AbsoluteLayout.LayoutFlags="All" IsVisible="False"/>
+ <Button x:Name="StartButton" Text="Start" AbsoluteLayout.LayoutBounds=".5, .5, .7, .7" AbsoluteLayout.LayoutFlags="All" IsVisible="True"/>
+ <Button x:Name="PauseButton" Text="Pause" AbsoluteLayout.LayoutBounds=".1, .5, .4, .7" AbsoluteLayout.LayoutFlags="All" IsVisible="False"/>
+ <Button x:Name="CancelButton" Text="Cancel" AbsoluteLayout.LayoutBounds=".9, .5, .4, .7" AbsoluteLayout.LayoutFlags="All" IsVisible="False"/>
+ <Button x:Name="ResumeButton" Text="Resume" AbsoluteLayout.LayoutBounds=".1, .5, .4, .7" AbsoluteLayout.LayoutFlags="All" IsVisible="False"/>
+ <Button x:Name="ResetButton" Text="Reset" AbsoluteLayout.LayoutBounds=".9, .5, .4, .7" AbsoluteLayout.LayoutFlags="All" IsVisible="False"/>
</AbsoluteLayout>
</AbsoluteLayout>
using System.Threading.Tasks;
using Xamarin.Forms;
+using Clock.TizenMobile.Controls;
+using System.Windows.Input;
namespace Clock.TizenMobile.Views
{
public partial class TimerView : ContentPage
{
+ enum ButtonDirection {
+ INCREASE,
+ DECREASE,
+ }
+
+ enum ButtonType
+ {
+ HOUR,
+ MINUTE,
+ SECOND
+ }
+
public TimerView()
{
InitializeComponent();
+
+ EntryHours.NextFocus = EntryMinutes;
+ EntryMinutes.NextFocus = EntrySeconds;
+ EntrySeconds.NextFocus = EntryHours;
}
- private void OnEntryChanged(object sender, EventArgs e)
+ private void OnTimeButtonClicked(object sender, EventArgs e)
{
+ var button = sender as Button;
+ ButtonType bType = ButtonType.HOUR;
+ ButtonDirection bDirection = ButtonDirection.INCREASE;
+
+ if (button.Equals(ButtonHourIncrease))
+ {
+ bType = ButtonType.HOUR;
+ bDirection = ButtonDirection.INCREASE;
+ }
+ else if (button.Equals(ButtonHourDecrease))
+ {
+ bType = ButtonType.HOUR;
+ bDirection = ButtonDirection.DECREASE;
+ }
+ else if (button.Equals(ButtonMinuteIncrease))
+ {
+ bType = ButtonType.MINUTE;
+ bDirection = ButtonDirection.INCREASE;
+ }
+ else if (button.Equals(ButtonMinuteDecrease))
+ {
+ bType = ButtonType.MINUTE;
+ bDirection = ButtonDirection.DECREASE;
+ }
+ else if (button.Equals(ButtonSecondIncrease))
+ {
+ bType = ButtonType.SECOND;
+ bDirection = ButtonDirection.INCREASE;
+ }
+ else if (button.Equals(ButtonSecondDecrease))
+ {
+ bType = ButtonType.SECOND;
+ bDirection = ButtonDirection.DECREASE;
+ }
+ EntryUpdate(bType, bDirection);
+ }
+
+ private void EntryUpdate(ButtonType type, ButtonDirection direction)
+ {
+ switch (type)
+ {
+ case ButtonType.HOUR:
+ if (direction == ButtonDirection.INCREASE)
+ {
+ EntryHours.Increase();
+ }
+ else
+ {
+ EntryHours.Decrease();
+ }
+ break;
+ case ButtonType.MINUTE:
+ if (direction == ButtonDirection.INCREASE)
+ {
+ EntryMinutes.Increase();
+ }
+ else
+ {
+ EntryMinutes.Decrease();
+ }
+ break;
+ case ButtonType.SECOND:
+ if (direction == ButtonDirection.INCREASE)
+ {
+ EntrySeconds.Increase();
+ }
+ else
+ {
+ EntrySeconds.Decrease();
+ }
+ break;
+ default:
+ return;
+ }
}
}
}