From d264a108e98dc170ef952c5024dbdd5c04400f74 Mon Sep 17 00:00:00 2001 From: Alexis Date: Sat, 13 Mar 2021 13:07:10 +0100 Subject: [PATCH] - Added: Background color to YAPA 1.0 theme - Added: Design time model to YAPA 1.0 theme for design-time typing & validation - Misc: Cleaned up a little bit (e.g. unused declarations) --- YAPA.WPF.Themes/YAPA/YapaTheme.xaml | 754 +++++++------- YAPA.WPF.Themes/YAPA/YapaTheme.xaml.cs | 955 ++++++++++-------- .../YAPA/YapaThemeSettingWindow.xaml | 151 +-- YAPA.WPF.Themes/YAPA/YapaThemeSettings.cs | 16 + 4 files changed, 984 insertions(+), 892 deletions(-) diff --git a/YAPA.WPF.Themes/YAPA/YapaTheme.xaml b/YAPA.WPF.Themes/YAPA/YapaTheme.xaml index e18dd2b..be3d5b7 100644 --- a/YAPA.WPF.Themes/YAPA/YapaTheme.xaml +++ b/YAPA.WPF.Themes/YAPA/YapaTheme.xaml @@ -1,395 +1,395 @@  + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:shared="clr-namespace:YAPA.Shared;assembly=YAPA.WPF.Shared" + xmlns:yapa="clr-namespace:YAPA" + mc:Ignorable="d" + Height="60" + Width="130" + ShowInTaskbar="True" + ResizeMode="NoResize" + AllowsTransparency="True" + IsHitTestVisible="True" + WindowStartupLocation="Manual" + WindowStyle="None" + Topmost="True" + MouseLeftButtonDown="MainWindow_MouseLeftButtonDown" + MouseEnter="MainWindow_OnMouseEnter" + MouseLeave="MainWindow_OnMouseLeave" + MouseDoubleClick="Window_MouseDoubleClick" + Background="Transparent" + d:DataContext="{d:DesignInstance yapa:YapaTheme, IsDesignTimeCreatable=True}"> - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - + + + + + + + - - - - - + + + + + - + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - + - - - - + - + + + - + TextAlignment="Center" + Foreground="{Binding TextBrush}" + FontSize="10" + Opacity="{Binding ClockOpacity}" + FontFamily="Segoe UI" + FontStretch="UltraCondensed" /> + + + + + + + + + - - - + + - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/YAPA.WPF.Themes/YAPA/YapaTheme.xaml.cs b/YAPA.WPF.Themes/YAPA/YapaTheme.xaml.cs index 8d5efdd..7dc7391 100644 --- a/YAPA.WPF.Themes/YAPA/YapaTheme.xaml.cs +++ b/YAPA.WPF.Themes/YAPA/YapaTheme.xaml.cs @@ -1,517 +1,576 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Animation; -using YAPA.Shared; -using YAPA.Shared.Common; -using YAPA.Shared.Contracts; -using YAPA.WPF.Themes.YAPA; +#region License & Metadata + +// The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// Created On: 2021/03/13 08:53 +// Modified On: 2021/03/13 12:52 +// Modified By: Alexis + +#endregion + + + namespace YAPA { - public partial class YapaTheme : AbstractWindow, INotifyPropertyChanged - { + using System; + using System.ComponentModel; + using System.Linq; + using System.Runtime.CompilerServices; + using System.Threading; + using System.Threading.Tasks; + using System.Windows; + using System.Windows.Controls; + using System.Windows.Input; + using System.Windows.Media; + using System.Windows.Media.Animation; + using Shared; + using Shared.Common; + using Shared.Contracts; + using WPF.Themes.YAPA; - private readonly double _sizeRatio = 60 / 130.0; + public partial class YapaTheme : AbstractWindow, INotifyPropertyChanged + { + #region Properties & Fields - Non-Public - private YapaThemeSettings Settings { get; } - private readonly IPomodoroRepository _pomodoroRepository; - private readonly PomodoroEngineSettings _engineSettings; + private readonly double _sizeRatio = 60 / 130.0; + private readonly IPomodoroRepository _pomodoroRepository; + private readonly PomodoroEngineSettings _engineSettings; - public int PomodorosCompleted { get; set; } + private readonly Storyboard TimerFlush; + private readonly Storyboard AfterBreakTimerFlush; - private readonly Storyboard TimerFlush; - private readonly Storyboard AfterBreakTimerFlush; - public YapaTheme(IMainViewModel viewModel, YapaThemeSettings settings, IPomodoroEngine engine, ISettings globalSettings, IPomodoroRepository pomodoroRepository, PomodoroEngineSettings engineSettings) : base(viewModel) - { - ViewModel = viewModel; - Settings = settings; - _pomodoroRepository = pomodoroRepository; - _engineSettings = engineSettings; + private Visibility _secondsVisibility = Visibility.Visible; - InitializeComponent(); + private string _statusText; - TimerFlush = (Storyboard)TryFindResource("FlashTimer"); - AfterBreakTimerFlush = (Storyboard)TryFindResource("AfterBreakFlashTimer"); - PomodorosCompleted = 0; + //When mouse is no longer over app, wait 2s and if mouse don't come back over app hide minmax panel + //There has to be a better way to do it!! + private CancellationTokenSource cancelMinMaxPanelHide = new CancellationTokenSource(); - ViewModel.Engine.PropertyChanged += Engine_PropertyChanged; - ViewModel.Engine.OnPomodoroCompleted += Engine_OnPomodoroCompleted; - ViewModel.Engine.OnStarted += StopAnimation; - ViewModel.Engine.OnStopped += StopAnimation; - globalSettings.PropertyChanged += _globalSettings_PropertyChanged; + private YapaThemeSettings Settings { get; } - DataContext = this; + #endregion - UpdateAppSize(); - PhaseChanged(); - UpdateStatusText(); - UpdateCompletedPomodoroCount(); - PropertyChanged += YapaTheme_PropertyChanged; - UpdateDisplayedTime(); - UpdateSecondVisibility(); - } - private void UpdateDisplayedTime() - { - var minutes = CurrentTimeValue / 60; - var seconds = CurrentTimeValue % 60; - CurrentTimeMinutes.Text = $"{minutes / 10:0}"; - CurrentTimeMinutes2.Text = $"{minutes % 10:0}"; - CurrentTimeSeconds.Text = $"{seconds / 10:0}"; - CurrentTimeSeconds2.Text = $"{seconds % 10:0}"; - - if (SecondsVisible == Visibility.Collapsed && minutes == 0 && seconds > 0) - { - CurrentTimeMinutes.Text = "<"; - CurrentTimeMinutes2.Text = "1"; - } - } + #region Constructors - private void YapaTheme_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(CurrentTimeValue)) - { - UpdateDisplayedTime(); - } - } + public YapaTheme(IMainViewModel viewModel, + YapaThemeSettings settings, + IPomodoroEngine engine, + ISettings globalSettings, + IPomodoroRepository pomodoroRepository, + PomodoroEngineSettings engineSettings) : base(viewModel) + { + ViewModel = viewModel; + Settings = settings; + _pomodoroRepository = pomodoroRepository; + _engineSettings = engineSettings; - private void HideSeconds() - { - CurrentTime.ColumnDefinitions.Clear(); - CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); - CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); + InitializeComponent(); - SecondsVisible = Visibility.Collapsed; - RaisePropertyChanged(nameof(SecondsVisible)); - } + TimerFlush = (Storyboard)TryFindResource("FlashTimer"); + AfterBreakTimerFlush = (Storyboard)TryFindResource("AfterBreakFlashTimer"); - private void ShowSeconds() - { - CurrentTime.ColumnDefinitions.Clear(); - CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); - CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); - CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); - CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); - CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); - - SecondsVisible = Visibility.Visible; - RaisePropertyChanged(nameof(SecondsVisible)); - } + PomodorosCompleted = 0; + ViewModel.Engine.PropertyChanged += Engine_PropertyChanged; + ViewModel.Engine.OnPomodoroCompleted += Engine_OnPomodoroCompleted; + ViewModel.Engine.OnStarted += StopAnimation; + ViewModel.Engine.OnStopped += StopAnimation; + globalSettings.PropertyChanged += _globalSettings_PropertyChanged; - private Visibility _secondsVisibility = Visibility.Visible; - public Visibility SecondsVisible - { - get => _secondsVisibility; - set => _secondsVisibility = value; - } + DataContext = this; - public double ClockOpacity => Settings.ClockOpacity; - public double ShadowOpacity => Settings.ShadowOpacity; + UpdateAppSize(); + PhaseChanged(); + UpdateStatusText(); - private async void UpdateCompletedPomodoroCount() - { - await Task.Run(() => - { - var today = DateTime.Today.Date; - PomodorosCompleted = _pomodoroRepository.Pomodoros.Where(x => x.DateTime == today).Select(a => a.Count).DefaultIfEmpty(0).Sum(); - RaisePropertyChanged(nameof(PomodorosCompleted)); - }); - } + UpdateCompletedPomodoroCount(); - public SolidColorBrush FlashingColor - { - get - { - if (ViewModel.Engine.Phase == PomodoroPhase.WorkEnded) - { - return Brushes.Tomato; - } - else if (ViewModel.Engine.Phase == PomodoroPhase.BreakEnded) - { - return Brushes.MediumSeaGreen; - } - return Brushes.Transparent; - } - } + PropertyChanged += YapaTheme_PropertyChanged; + UpdateDisplayedTime(); + UpdateSecondVisibility(); + } - private void StopAnimation() - { - if (Settings.DisableFlashingAnimation == false) - { - TimerFlush.Stop(this); - AfterBreakTimerFlush.Stop(this); - } - else - { - CurrentTime.Background = Brushes.Transparent; - } - } + #endregion - private void StartAnimation() - { - Storyboard animationToStart = null; - - if (ViewModel.Engine.Phase == PomodoroPhase.WorkEnded) - { - animationToStart = TimerFlush; - } - else if (ViewModel.Engine.Phase == PomodoroPhase.BreakEnded) - { - animationToStart = AfterBreakTimerFlush; - } - if (animationToStart == null) - { - return; - } - - if (Settings.DisableFlashingAnimation == false) - { - animationToStart.Begin(this, true); - } - else - { - CurrentTime.Background = FlashingColor; - } - } - private void Engine_OnPomodoroCompleted() - { - PomodorosCompleted++; - RaisePropertyChanged(nameof(PomodorosCompleted)); - } - private void _globalSettings_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName.StartsWith($"{nameof(YapaTheme)}")) - { - RaisePropertyChanged(nameof(TextBrush)); - RaisePropertyChanged(nameof(TextShadowColor)); - RaisePropertyChanged(nameof(MouseOverBackgroundColor)); - RaisePropertyChanged(nameof(Settings.ClockOpacity)); - RaisePropertyChanged(nameof(Settings.ShadowOpacity)); - - if (e.PropertyName.StartsWith($"{nameof(YapaTheme)}.{nameof(YapaThemeSettings.Width)}")) - { - UpdateAppSize(); - } - - if (e.PropertyName.StartsWith($"{nameof(YapaTheme)}.{nameof(YapaThemeSettings.ShowStatusText)}")) - { - UpdateStatusText(); - } - - if (e.PropertyName.StartsWith($"{nameof(YapaTheme)}.{nameof(YapaThemeSettings.HideSeconds)}")) - { - UpdateSecondVisibility(); - } - - } - } + #region Properties & Fields - Public - private void UpdateSecondVisibility() - { - if (Settings.HideSeconds) - { - HideSeconds(); - } - else - { - ShowSeconds(); - } - } + public int PomodorosCompleted { get; set; } + public Visibility SecondsVisible + { + get => _secondsVisibility; + set => _secondsVisibility = value; + } - private void UpdateAppSize() - { - Width = Settings.Width; - Height = Settings.Width * _sizeRatio; - } + public SolidColorBrush FlashingColor + { + get + { + if (ViewModel.Engine.Phase == PomodoroPhase.WorkEnded) + return Brushes.Tomato; + else if (ViewModel.Engine.Phase == PomodoroPhase.BreakEnded) + return Brushes.MediumSeaGreen; + + return Brushes.Transparent; + } + } - private void Engine_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(ViewModel.Engine.Elapsed) || e.PropertyName == nameof(ViewModel.Engine.DisplayValue)) - { - RaisePropertyChanged(nameof(CurrentTimeValue)); - RaisePropertyChanged(nameof(ProgressValue)); - } - else if (e.PropertyName == nameof(ViewModel.Engine.Phase)) - { - PhaseChanged(); - RaisePropertyChanged(nameof(ProgressState)); - UpdateStatusText(); - StartAnimation(); - } - } + public string Status + { + get => _statusText; + set + { + _statusText = Settings.ShowStatusText ? value : string.Empty; - private string _statusText; + RaisePropertyChanged(nameof(Status)); + } + } - public string Status - { - get { return _statusText; } - set - { - if (Settings.ShowStatusText) - { - _statusText = value; - } - else - { - _statusText = String.Empty; - } - RaisePropertyChanged(nameof(Status)); - } - } + public double BackgroundOpacity => Settings.BackgroundOpacity; + public double ClockOpacity => Settings.ClockOpacity; + public double ShadowOpacity => Settings.ShadowOpacity; - private void UpdateStatusText() + public Brush BackgroundBrush + { + get + { + Color color; + switch (Settings.ThemeColors) { - switch (ViewModel.Engine.Phase) - { - case PomodoroPhase.NotStarted: - Status = "YAPA 2.0"; - break; - case PomodoroPhase.WorkEnded: - Status = "Work Ended"; - break; - case PomodoroPhase.BreakEnded: - Status = "Break Ended"; - break; - case PomodoroPhase.Work: - Status = "Work"; - break; - case PomodoroPhase.Break: - Status = "Break"; - break; - case PomodoroPhase.Pause: - Status = "Work Paused"; - break; - } + case ThemeColors.White: + color = Colors.White; + break; + case ThemeColors.Black: + color = Colors.Black; + break; + case ThemeColors.Custom: + color = Settings.BackgroundColor; + break; + default: + throw new ArgumentOutOfRangeException(); } + + return new SolidColorBrush(color); + } + } - private void PhaseChanged() + public Brush TextBrush + { + get + { + Color color; + switch (Settings.ThemeColors) { - switch (ViewModel.Engine.Phase) - { - case PomodoroPhase.NotStarted: - Start.Visibility = Visibility.Visible; - Stop.Visibility = Visibility.Collapsed; - Pause.Visibility = Visibility.Collapsed; - Skip.Visibility = Visibility.Collapsed; - break; - case PomodoroPhase.WorkEnded: - Start.Visibility = Visibility.Visible; - Stop.Visibility = Visibility.Collapsed; - Pause.Visibility = Visibility.Collapsed; - Skip.Visibility = Visibility.Visible; - break; - case PomodoroPhase.BreakEnded: - Start.Visibility = Visibility.Visible; - Stop.Visibility = Visibility.Collapsed; - Pause.Visibility = Visibility.Collapsed; - Skip.Visibility = Visibility.Collapsed; - break; - case PomodoroPhase.Work: - Start.Visibility = Visibility.Collapsed; - Stop.Visibility = Visibility.Visible; - Pause.Visibility = Visibility.Visible; - Skip.Visibility = Visibility.Collapsed; - break; - case PomodoroPhase.Break: - Start.Visibility = Visibility.Collapsed; - Stop.Visibility = Visibility.Visible; - Skip.Visibility = Visibility.Collapsed; - break; - case PomodoroPhase.Pause: - Start.Visibility = Visibility.Visible; - Stop.Visibility = Visibility.Visible; - Pause.Visibility = Visibility.Collapsed; - Skip.Visibility = Visibility.Collapsed; - break; - } + case ThemeColors.White: + color = Colors.White; + break; + case ThemeColors.Black: + color = Colors.Black; + break; + case ThemeColors.Custom: + color = Settings.TextColor; + break; + default: + throw new ArgumentOutOfRangeException(); } - public Brush TextBrush - { - get - { - Color color; - switch (Settings.ThemeColors) - { - case ThemeColors.White: - color = Colors.White; - break; - case ThemeColors.Black: - color = Colors.Black; - break; - case ThemeColors.Custom: - color = Settings.TextColor; - break; - default: - throw new ArgumentOutOfRangeException(); - } - return new SolidColorBrush(color); - } - } - //Settings.UseWhiteText ? Brushes.LightGray : Brushes.Black; + return new SolidColorBrush(color); + } + } + //Settings.UseWhiteText ? Brushes.LightGray : Brushes.Black; - public Color TextShadowColor + public Color TextShadowColor + { + get + { + Color color; + switch (Settings.ThemeColors) { - get - { - Color color; - switch (Settings.ThemeColors) - { - case ThemeColors.White: - color = Colors.Black; - break; - case ThemeColors.Black: - color = Colors.White; - break; - case ThemeColors.Custom: - color = Settings.ShadowColor; - break; - default: - throw new ArgumentOutOfRangeException(); - } - return color; - } + case ThemeColors.White: + color = Colors.Black; + break; + case ThemeColors.Black: + color = Colors.White; + break; + case ThemeColors.Custom: + color = Settings.ShadowColor; + break; + default: + throw new ArgumentOutOfRangeException(); } - public Brush MouseOverBackgroundColor => new SolidColorBrush(TextShadowColor); + return color; + } + } - public double ProgressValue - { - get - { - var elapsed = ViewModel.Engine.Elapsed; - var progress = 0d; - switch (ViewModel.Engine.Phase) - { - case PomodoroPhase.WorkEnded: - case PomodoroPhase.Work: - case PomodoroPhase.Pause: - progress = (double)elapsed / (ViewModel.Engine.WorkTime); - break; - case PomodoroPhase.Break: - case PomodoroPhase.BreakEnded: - progress = (double)elapsed / (ViewModel.Engine.BreakTime); - break; - } - return progress; - } - } + public Brush MouseOverBackgroundColor => new SolidColorBrush(TextShadowColor); - public string ProgressState + public double ProgressValue + { + get + { + var elapsed = ViewModel.Engine.Elapsed; + var progress = 0d; + switch (ViewModel.Engine.Phase) { - get - { - var progressState = ""; - switch (ViewModel.Engine.Phase) - { - case PomodoroPhase.NotStarted: - break; - case PomodoroPhase.Work: - case PomodoroPhase.Pause: - progressState = "Normal"; - break; - case PomodoroPhase.Break: - progressState = "Paused"; - break; - case PomodoroPhase.WorkEnded: - case PomodoroPhase.BreakEnded: - progressState = "Error"; - break; - } - return progressState; - } + case PomodoroPhase.WorkEnded: + case PomodoroPhase.Work: + case PomodoroPhase.Pause: + progress = (double)elapsed / ViewModel.Engine.WorkTime; + break; + case PomodoroPhase.Break: + case PomodoroPhase.BreakEnded: + progress = (double)elapsed / ViewModel.Engine.BreakTime; + break; } - public int CurrentTimeValue => ViewModel.Engine.DisplayValue; + return progress; + } + } - private void MainWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) + public string ProgressState + { + get + { + var progressState = ""; + switch (ViewModel.Engine.Phase) { - try - { - OnMouseLeftButtonDown(e); - DragMove(); - e.Handled = true; - } - catch - { - } + case PomodoroPhase.NotStarted: + break; + case PomodoroPhase.Work: + case PomodoroPhase.Pause: + progressState = "Normal"; + break; + case PomodoroPhase.Break: + progressState = "Paused"; + break; + case PomodoroPhase.WorkEnded: + case PomodoroPhase.BreakEnded: + progressState = "Error"; + break; } - private void Minimize_OnClick(object sender, RoutedEventArgs e) - { - WindowState = WindowState.Minimized; - } + return progressState; + } + } + public int CurrentTimeValue => ViewModel.Engine.DisplayValue; - //When mouse is no longer over app, wait 2s and if mouse don't come back over app hide minmax panel - //There has to be a better way to do it!! - CancellationTokenSource cancelMinMaxPanelHide = new CancellationTokenSource(); + #endregion - private void MainWindow_OnMouseEnter(object sender, MouseEventArgs e) - { - MinExitPanel.Visibility = Visibility.Visible; - ButtonPanel.Visibility = Visibility.Visible; - cancelMinMaxPanelHide.Cancel(); - cancelMinMaxPanelHide = new CancellationTokenSource(); - } - private async void MainWindow_OnMouseLeave(object sender, MouseEventArgs e) - { - await Task.Delay(TimeSpan.FromSeconds(2), cancelMinMaxPanelHide.Token).ContinueWith( - x => - { - if (x.IsCanceled) - { - return; - } - - Dispatcher.Invoke(() => - { - MinExitPanel.Visibility = Visibility.Hidden; - if (Settings.HideButtons) - { - ButtonPanel.Visibility = Visibility.Hidden; - } - - }); - cancelMinMaxPanelHide = new CancellationTokenSource(); - }); - } + #region Methods - private void Window_MouseDoubleClick(object sender, MouseButtonEventArgs e) - { - TimerFlush.Stop(this); - AfterBreakTimerFlush.Stop(this); - } + private void UpdateDisplayedTime() + { + var minutes = CurrentTimeValue / 60; + var seconds = CurrentTimeValue % 60; + CurrentTimeMinutes.Text = $"{minutes / 10:0}"; + CurrentTimeMinutes2.Text = $"{minutes % 10:0}"; + CurrentTimeSeconds.Text = $"{seconds / 10:0}"; + CurrentTimeSeconds2.Text = $"{seconds % 10:0}"; + + if (SecondsVisible == Visibility.Collapsed && minutes == 0 && seconds > 0) + { + CurrentTimeMinutes.Text = "<"; + CurrentTimeMinutes2.Text = "1"; + } + } - public event PropertyChangedEventHandler PropertyChanged; + private void YapaTheme_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(CurrentTimeValue)) + UpdateDisplayedTime(); + } - protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } + private void HideSeconds() + { + CurrentTime.ColumnDefinitions.Clear(); + CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); + CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); + + SecondsVisible = Visibility.Collapsed; + RaisePropertyChanged(nameof(SecondsVisible)); + } + + private void ShowSeconds() + { + CurrentTime.ColumnDefinitions.Clear(); + CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); + CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); + CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); + CurrentTime.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); + + SecondsVisible = Visibility.Visible; + RaisePropertyChanged(nameof(SecondsVisible)); + } + + private async void UpdateCompletedPomodoroCount() + { + await Task.Run(() => + { + var today = DateTime.Today.Date; + PomodorosCompleted = _pomodoroRepository.Pomodoros.Where(x => x.DateTime == today).Select(a => a.Count).DefaultIfEmpty(0).Sum(); + RaisePropertyChanged(nameof(PomodorosCompleted)); + }); + } + + private void StopAnimation() + { + if (Settings.DisableFlashingAnimation == false) + { + TimerFlush.Stop(this); + AfterBreakTimerFlush.Stop(this); + } + else + { + CurrentTime.Background = Brushes.Transparent; + } + } + + private void StartAnimation() + { + Storyboard animationToStart = null; + + if (ViewModel.Engine.Phase == PomodoroPhase.WorkEnded) + animationToStart = TimerFlush; + else if (ViewModel.Engine.Phase == PomodoroPhase.BreakEnded) + animationToStart = AfterBreakTimerFlush; + if (animationToStart == null) + return; + + if (Settings.DisableFlashingAnimation == false) + animationToStart.Begin(this, true); + else + CurrentTime.Background = FlashingColor; + } + + private void Engine_OnPomodoroCompleted() + { + PomodorosCompleted++; + RaisePropertyChanged(nameof(PomodorosCompleted)); + } + + private void _globalSettings_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName.StartsWith($"{nameof(YapaTheme)}")) + { + RaisePropertyChanged(nameof(BackgroundBrush)); + RaisePropertyChanged(nameof(TextBrush)); + RaisePropertyChanged(nameof(TextShadowColor)); + RaisePropertyChanged(nameof(MouseOverBackgroundColor)); + RaisePropertyChanged(nameof(Settings.BackgroundOpacity)); + RaisePropertyChanged(nameof(Settings.ClockOpacity)); + RaisePropertyChanged(nameof(Settings.ShadowOpacity)); + + if (e.PropertyName.StartsWith($"{nameof(YapaTheme)}.{nameof(YapaThemeSettings.Width)}")) + UpdateAppSize(); + + if (e.PropertyName.StartsWith($"{nameof(YapaTheme)}.{nameof(YapaThemeSettings.ShowStatusText)}")) + UpdateStatusText(); + + if (e.PropertyName.StartsWith($"{nameof(YapaTheme)}.{nameof(YapaThemeSettings.HideSeconds)}")) + UpdateSecondVisibility(); + } + } + + + private void UpdateSecondVisibility() + { + if (Settings.HideSeconds) + HideSeconds(); + else + ShowSeconds(); + } + + private void UpdateAppSize() + { + Width = Settings.Width; + Height = Settings.Width * _sizeRatio; + } + + private void Engine_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(ViewModel.Engine.Elapsed) || e.PropertyName == nameof(ViewModel.Engine.DisplayValue)) + { + RaisePropertyChanged(nameof(CurrentTimeValue)); + RaisePropertyChanged(nameof(ProgressValue)); + } + else if (e.PropertyName == nameof(ViewModel.Engine.Phase)) + { + PhaseChanged(); + RaisePropertyChanged(nameof(ProgressState)); + UpdateStatusText(); + StartAnimation(); + } + } - private void Exit_OnClick(object sender, RoutedEventArgs e) + private void UpdateStatusText() + { + switch (ViewModel.Engine.Phase) + { + case PomodoroPhase.NotStarted: + Status = "YAPA 2.0"; + break; + case PomodoroPhase.WorkEnded: + Status = "Work Ended"; + break; + case PomodoroPhase.BreakEnded: + Status = "Break Ended"; + break; + case PomodoroPhase.Work: + Status = "Work"; + break; + case PomodoroPhase.Break: + Status = "Break"; + break; + case PomodoroPhase.Pause: + Status = "Work Paused"; + break; + } + } + + private void PhaseChanged() + { + switch (ViewModel.Engine.Phase) + { + case PomodoroPhase.NotStarted: + Start.Visibility = Visibility.Visible; + Stop.Visibility = Visibility.Collapsed; + Pause.Visibility = Visibility.Collapsed; + Skip.Visibility = Visibility.Collapsed; + break; + case PomodoroPhase.WorkEnded: + Start.Visibility = Visibility.Visible; + Stop.Visibility = Visibility.Collapsed; + Pause.Visibility = Visibility.Collapsed; + Skip.Visibility = Visibility.Visible; + break; + case PomodoroPhase.BreakEnded: + Start.Visibility = Visibility.Visible; + Stop.Visibility = Visibility.Collapsed; + Pause.Visibility = Visibility.Collapsed; + Skip.Visibility = Visibility.Collapsed; + break; + case PomodoroPhase.Work: + Start.Visibility = Visibility.Collapsed; + Stop.Visibility = Visibility.Visible; + Pause.Visibility = Visibility.Visible; + Skip.Visibility = Visibility.Collapsed; + break; + case PomodoroPhase.Break: + Start.Visibility = Visibility.Collapsed; + Stop.Visibility = Visibility.Visible; + Skip.Visibility = Visibility.Collapsed; + break; + case PomodoroPhase.Pause: + Start.Visibility = Visibility.Visible; + Stop.Visibility = Visibility.Visible; + Pause.Visibility = Visibility.Collapsed; + Skip.Visibility = Visibility.Collapsed; + break; + } + } + + private void MainWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + try + { + OnMouseLeftButtonDown(e); + DragMove(); + e.Handled = true; + } + catch { } + } + + private void Minimize_OnClick(object sender, RoutedEventArgs e) + { + WindowState = WindowState.Minimized; + } + + private void MainWindow_OnMouseEnter(object sender, MouseEventArgs e) + { + MinExitPanel.Visibility = Visibility.Visible; + ButtonPanel.Visibility = Visibility.Visible; + + cancelMinMaxPanelHide.Cancel(); + cancelMinMaxPanelHide = new CancellationTokenSource(); + } + + private async void MainWindow_OnMouseLeave(object sender, MouseEventArgs e) + { + await Task.Delay(TimeSpan.FromSeconds(2), cancelMinMaxPanelHide.Token).ContinueWith( + x => { - CloseApp(); - } + if (x.IsCanceled) + return; + + Dispatcher.Invoke(() => + { + MinExitPanel.Visibility = Visibility.Hidden; + if (Settings.HideButtons) + ButtonPanel.Visibility = Visibility.Hidden; + }); + cancelMinMaxPanelHide = new CancellationTokenSource(); + }); } + + private void Window_MouseDoubleClick(object sender, MouseButtonEventArgs e) + { + TimerFlush.Stop(this); + AfterBreakTimerFlush.Stop(this); + } + + protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + private void Exit_OnClick(object sender, RoutedEventArgs e) + { + CloseApp(); + } + + #endregion + + + + + #region Events + + public event PropertyChangedEventHandler PropertyChanged; + + #endregion + } } diff --git a/YAPA.WPF.Themes/YAPA/YapaThemeSettingWindow.xaml b/YAPA.WPF.Themes/YAPA/YapaThemeSettingWindow.xaml index 72eb442..16a9553 100644 --- a/YAPA.WPF.Themes/YAPA/YapaThemeSettingWindow.xaml +++ b/YAPA.WPF.Themes/YAPA/YapaThemeSettingWindow.xaml @@ -1,80 +1,97 @@  - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - Disable flashing animation - Show pomodoro status - Hide seconds - Hide buttons - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + Disable flashing animation + Show pomodoro status + Hide seconds + Hide buttons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/YAPA.WPF.Themes/YAPA/YapaThemeSettings.cs b/YAPA.WPF.Themes/YAPA/YapaThemeSettings.cs index d2ba912..93c1314 100644 --- a/YAPA.WPF.Themes/YAPA/YapaThemeSettings.cs +++ b/YAPA.WPF.Themes/YAPA/YapaThemeSettings.cs @@ -33,6 +33,12 @@ public int Width set => _settings.Update(nameof(Width), value); } + public double BackgroundOpacity + { + get => _settings.Get(nameof(BackgroundOpacity), 0.0); + set => _settings.Update(nameof(BackgroundOpacity), value); + } + public double ClockOpacity { get => _settings.Get(nameof(ClockOpacity), 0.6); @@ -51,6 +57,16 @@ public ThemeColors ThemeColors set => _settings.Update(nameof(ThemeColors), value); } + public Color BackgroundColor + { + get + { + var color = _settings.Get(nameof(BackgroundColor), "White"); + return (Color)(ColorConverter.ConvertFromString(color) ?? Colors.White); + } + set => _settings.Update(nameof(BackgroundColor), value.ToString()); + } + public Color TextColor { get