Skip to content

Commit

Permalink
Merge pull request #18 from oldtimerza/timers
Browse files Browse the repository at this point in the history
Added initial setup for starting and stopping timers for active todos
Closes #14
  • Loading branch information
oldtimerza authored Feb 27, 2021
2 parents e6b19ca + a1b999e commit 879853b
Show file tree
Hide file tree
Showing 13 changed files with 186 additions and 36 deletions.
15 changes: 14 additions & 1 deletion Meerkat/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<SolidColorBrush x:Key="FontLight" Color="GhostWhite" />
<SolidColorBrush x:Key="CompleteGreen" Color="#19F9D8" />
<SolidColorBrush x:Key="IncompleteRed" Color="#FF2C6D" />
<SolidColorBrush x:Key="ActiveOrange" Color="#EDBC34"/>
<Style x:Key="MainWindow" TargetType="{x:Type Window}">
<Setter Property="MinWidth" Value="100"/>
<Setter Property="MinHeight" Value="46"/>
Expand Down Expand Up @@ -40,7 +41,7 @@
<Setter Property="Padding" Value="30, 0, 0, 0"/>
<Setter Property="Height" Value="40"/>
<Setter Property="MinWidth" Value="75"/>
<Setter Property="Width" Value="600"/>
<Setter Property="Width" Value="450"/>
<Setter Property="FontSize" Value="25"/>
</Style>
<Style x:Key="TodoListItemCheckbox" TargetType="{x:Type CheckBox}">
Expand Down Expand Up @@ -71,5 +72,17 @@
<Setter Property="Height" Value="40"/>
<Setter Property="Background" Value="{StaticResource MainDark}"/>
</Style>
<Style x:Key="TodoListItemTime" TargetType="{x:Type TextBlock}">
<Setter Property="Padding" Value="30, 0, 0, 0"/>
<Setter Property="Height" Value="40"/>
<Setter Property="MinWidth" Value="75"/>
<Setter Property="Width" Value="150"/>
<Setter Property="FontSize" Value="25"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Active}" Value="True">
<Setter Property="Foreground" Value="{StaticResource ActiveOrange}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Application.Resources>
</Application>
12 changes: 9 additions & 3 deletions Meerkat/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using Ninject;
using Stateless;
using System.Windows;
using System.Windows.Threading;
using System;

namespace Meerkat
{
Expand All @@ -21,6 +23,9 @@ protected override void OnStartup(StartupEventArgs e)
ConfigureContainer();
ComposeObjects();
Current.MainWindow.Show();
DispatcherTimer dispatcherTimer = container.Get<DispatcherTimer>();
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();
}

private void ConfigureContainer()
Expand All @@ -29,15 +34,16 @@ private void ConfigureContainer()
container.Bind<IRepository<Todo>>().To<TodoRepository>();
container.Bind<StateMachine<State, Models.Trigger>>().ToMethod<StateMachine<State, Models.Trigger>>(context => new StateMachine<State, Models.Trigger>(State.NAVIGATION));
container.Bind<IStateTracker, ITodoTracker>().To<MeerkatApp>().InSingletonScope();
container.Bind<ViewModelBase>().To<TodosViewModel>();
container.Bind<ViewModelBase>().To<MeerkatAppViewModel>();
container.Bind<DispatcherTimer>().To<DispatcherTimer>().InSingletonScope();
}

private void ComposeObjects()
{
ViewModelBase todosViewModel = container.Get<ViewModelBase>();
ViewModelBase meerkatAppViewModel = container.Get<ViewModelBase>();
Current.MainWindow = container.Get<MainWindow>();
Current.MainWindow.Title = "Meerkat";
Current.MainWindow.DataContext = todosViewModel;
Current.MainWindow.DataContext = meerkatAppViewModel;
}
}
}
37 changes: 34 additions & 3 deletions Meerkat/Models/Domain/Todo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Meerkat.Models
using System;

namespace Meerkat.Models
{
/// <summary>
/// Represents a basic todo item with a done state and message
Expand All @@ -11,8 +13,37 @@ public Todo(bool done, string message)
Message = message;
}

public bool Done { get; set; }
public string Message { get; set; }
public bool Done { get; private set; }
public string Message { get; private set; }

public bool Active { get; private set; }

public TimeSpan TimeActive { get; set; }

public void ToggleDone()
{
Done = !Done;
if(Active)
{
Active = false;
}
}

public void ToggleActiveTimer()
{
if(!Done)
{
Active = !Active;
}
}

public void Tick()
{
if(Active)
{
TimeActive = TimeActive.Add(new TimeSpan(0, 0, 1));
}
}

public override bool Equals(object obj)
{
Expand Down
7 changes: 7 additions & 0 deletions Meerkat/Models/ITodoTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,12 @@ public interface ITodoTracker
/// </summary>
/// <param name="id">The id of the Todo item to remove</param>
void RemoveTodo(int id);

/// <summary>
/// Deactivate a Todo item's timer
/// </summary>
/// <param name="id">The id of the Todo item to deactivate</param>
void ToggleActiveTimerForTodo(int index);

}
}
39 changes: 32 additions & 7 deletions Meerkat/Models/MeerkatApp.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
using Stateless;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Threading;

namespace Meerkat.Models
{
public class MeerkatApp : IStateTracker, ITodoTracker
{
private StateMachine<State, Trigger> stateMachine;
private IList<Todo> todos;
private IRepository<Todo> repository;
private StateMachine<State, Trigger>.TriggerWithParameters<Todo> createTodoTrigger;
private double progress;

public MeerkatApp(StateMachine<State, Trigger> stateMachine, IRepository<Todo> repository)
public MeerkatApp(StateMachine<State, Trigger> stateMachine, IRepository<Todo> repository, DispatcherTimer dispatcherTimer)
{
this.stateMachine = stateMachine;
this.repository = repository;
this.todos = this.repository.Get().ToList();

this.stateMachine = stateMachine;
createTodoTrigger = this.stateMachine.SetTriggerParameters<Todo>(Trigger.CREATE_TODO);
stateMachine.Configure(State.INSERT).Permit(Trigger.EXIT_EDITOR, State.NAVIGATION);
stateMachine.Configure(State.INSERT).Permit(Trigger.CREATE_TODO, State.NAVIGATION);
stateMachine.Configure(State.NAVIGATION)
.OnEntryFrom(createTodoTrigger, todo => AddTodoItem(todo))
.Permit(Trigger.ENTER_EDITOR, State.INSERT);

dispatcherTimer.Tick += new EventHandler(Tick);
}

public virtual IReadOnlyCollection<Todo> Todos
{
get { return repository.Get().ToList<Todo>().AsReadOnly(); }
get { return new ReadOnlyCollection<Todo>(todos); }
}

public virtual State CurrentState
Expand Down Expand Up @@ -62,27 +70,44 @@ public void EnterInsert()
private void AddTodoItem(Todo item)
{
repository.Create(item);
todos.Add(item);
UpdateProgress();
}

public void ToggleTodo(int index)
{
Todo todo = repository.Get().ElementAt(index);
repository.Update(index, new Todo(!todo.Done, todo.Message));
Todo todo = todos.ElementAt(index);
todo.ToggleDone();
repository.Update(index, todo);
UpdateProgress();
}

public void RemoveTodo(int index)
{
todos.RemoveAt(index);
repository.Delete(index);
UpdateProgress();
}

private void UpdateProgress()
{
double doneTodosCount = repository.Get().Count(todo => todo.Done);
double totalCount = repository.Get().Count();
double doneTodosCount = todos.Count(todo => todo.Done);
double totalCount = todos.Count();
progress = doneTodosCount / totalCount;
}

private void Tick(object sender, EventArgs e)
{
foreach (Todo item in todos)
{
item.Tick();
}
}

public void ToggleActiveTimerForTodo(int index)
{
Todo todo = todos.ElementAt(index);
todo.ToggleActiveTimer();
}
}
}
5 changes: 2 additions & 3 deletions Meerkat/Models/Repositories/TodoRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ public IEnumerable<Todo> Get()

public Todo Update(int id, Todo t)
{
//TODO: this needs to be cleaned up, perhaps a separate model for storage in future.
//For now It's being ignored.
Todo todo = todos.ElementAt(id);

todo.Done = t.Done;
todo.Message = t.Message;

return todo;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
using Meerkat.Models;
using Meerkat.ViewModels.Commands;
using System;
using System.Collections.Generic;
using System.Windows.Input;
using System.Windows.Threading;

namespace Meerkat.ViewModels
{
public class TodosViewModel : ViewModelBase
public class MeerkatAppViewModel : ViewModelBase
{
private IStateTracker stateTracker;
private ITodoTracker todoTracker;
private DispatcherTimer dispatcherTimer;
private bool focusInsertText;
private int selectedIndex;
private ICommand addTodo;
Expand All @@ -17,13 +20,20 @@ public class TodosViewModel : ViewModelBase
private ICommand previousTodoItem;
private ICommand toggleTodo;
private ICommand removeTodo;
private ICommand toggleTodoIsActive;

public TodosViewModel(IStateTracker stateTracker, ITodoTracker todoTracker)
public MeerkatAppViewModel(IStateTracker stateTracker, ITodoTracker todoTracker, DispatcherTimer dispatcherTimer)
{
this.stateTracker = stateTracker;
this.todoTracker = todoTracker;
this.dispatcherTimer = dispatcherTimer;
this.dispatcherTimer.Tick += new System.EventHandler(TimeChanged);
}

private void TimeChanged(object sender, EventArgs e)
{
OnPropertyChanged("Todos");
}

public IReadOnlyCollection<Todo> Todos
{
Expand Down Expand Up @@ -154,6 +164,23 @@ public ICommand RemoveTodo
}
}

public ICommand ToggleTodoIsActive
{
get
{
if(toggleTodoIsActive == null)
{
toggleTodoIsActive = new RelayCommand(p =>
{
todoTracker.ToggleActiveTimerForTodo(SelectedIndex);
OnPropertyChanged("Todos");
},
p => stateTracker.CurrentState == State.NAVIGATION);
}
return toggleTodoIsActive;
}
}

public bool FocusInsertText
{
get
Expand All @@ -168,6 +195,7 @@ public bool FocusInsertText
}
}

//TODO: this needs to be moved into the MeerkatApp Model, this shouldn't be handled by the ViewModel.
public int SelectedIndex
{
get
Expand All @@ -177,7 +205,7 @@ public int SelectedIndex

set
{
selectedIndex = value;
selectedIndex = value < 0 ? 0 : value;
OnPropertyChanged("SelectedIndex");
}
}
Expand Down
25 changes: 25 additions & 0 deletions Meerkat/ViewModels/TodoViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Meerkat.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace Meerkat.ViewModels
{
public class TodoViewModel
{
public bool Done { get; set; }
public string Message { get; private set; }

public bool Active { get; private set; }

public string TimeActive { get; private set; }

public TodoViewModel(Todo todo)
{
this.Done = todo.Done;
this.Message = todo.Message;
this.Active = todo.Active;
this.TimeActive = todo.TimeActive.ToString();
}
}
}
6 changes: 5 additions & 1 deletion Meerkat/Views/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Style="{StaticResource TodoItem}">
<CheckBox Style="{ StaticResource TodoListItemCheckbox }" IsChecked="{ Binding Done }"/>
<CheckBox Style="{ StaticResource TodoListItemCheckbox }" IsChecked="{ Binding Done, Mode=OneWay}" />
<TextBlock Style="{ StaticResource TodoListItemDescription }" Text="{ Binding Message }" />
<TextBlock Style="{ StaticResource TodoListItemTime}" Text="{Binding TimeActive}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Expand All @@ -55,6 +56,9 @@
<KeyBinding
Key="Space"
Command="{ Binding ToggleTodo }" />
<KeyBinding
Key="S"
Command="{Binding ToggleTodoIsActive}" />
<KeyBinding
Key="D"
Command="{ Binding RemoveTodo }" />
Expand Down
3 changes: 2 additions & 1 deletion Meerkat/Views/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ private void TodoMessageText_PreviewKeyDown(object sender, KeyEventArgs e)
new Tuple<Key, string>( Key.I, "i" ),
new Tuple<Key, string>( Key.J, "j" ),
new Tuple<Key, string>( Key.K, "k" ),
new Tuple<Key, string>( Key.D, "d" )
new Tuple<Key, string>( Key.D, "d" ),
new Tuple<Key, string>( Key.S, "s")
};
if(!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
{
Expand Down
Loading

0 comments on commit 879853b

Please sign in to comment.