From dc4c33b9dcfadf7d93ad0e563fa528e250ebcb25 Mon Sep 17 00:00:00 2001 From: Ivan Ivon Date: Sun, 24 Nov 2024 04:15:25 +0200 Subject: [PATCH 1/3] Use C# preview --- Hourglass.NAudio/Hourglass.NAudio.csproj | 2 +- Hourglass.Test/Hourglass.Test.csproj | 2 +- Hourglass/Hourglass.csproj | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Hourglass.NAudio/Hourglass.NAudio.csproj b/Hourglass.NAudio/Hourglass.NAudio.csproj index fb50320..85e398a 100644 --- a/Hourglass.NAudio/Hourglass.NAudio.csproj +++ b/Hourglass.NAudio/Hourglass.NAudio.csproj @@ -2,7 +2,7 @@ net48 Library - latest + preview enable diff --git a/Hourglass.Test/Hourglass.Test.csproj b/Hourglass.Test/Hourglass.Test.csproj index b835284..d8dab92 100644 --- a/Hourglass.Test/Hourglass.Test.csproj +++ b/Hourglass.Test/Hourglass.Test.csproj @@ -3,7 +3,7 @@ {CBE74854-0344-4606-A854-BFA719896A98} net48 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - latest + preview enable bin\$(Configuration)\ diff --git a/Hourglass/Hourglass.csproj b/Hourglass/Hourglass.csproj index 6cf6e4a..b441651 100644 --- a/Hourglass/Hourglass.csproj +++ b/Hourglass/Hourglass.csproj @@ -4,9 +4,8 @@ {4E327D2C-9171-4596-82C5-A9C3CF5028E4} WinExe {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - latest true - latest + preview enable true Debug;Release;Release Portable;Debug Portable From e6dd82483330c661f1bd596845606dd314269ea6 Mon Sep 17 00:00:00 2001 From: Ivan Ivon Date: Sun, 24 Nov 2024 04:18:33 +0200 Subject: [PATCH 2/3] Use field keyword --- Hourglass/Managers/TimerManager.cs | 6 +- Hourglass/Timing/Theme.cs | 224 ++++------- Hourglass/Timing/TimerOptions.cs | 387 +++++++------------ Hourglass/Windows/ThemeManagerWindow.xaml.cs | 63 +-- Hourglass/Windows/TimerWindow.xaml.cs | 83 ++-- 5 files changed, 272 insertions(+), 491 deletions(-) diff --git a/Hourglass/Managers/TimerManager.cs b/Hourglass/Managers/TimerManager.cs index bb8b482..7f5146e 100644 --- a/Hourglass/Managers/TimerManager.cs +++ b/Hourglass/Managers/TimerManager.cs @@ -42,15 +42,13 @@ private TimerManager() { } - private bool _silentMode; - /// /// Gets the silent mode when all the timers notifications are postponed. /// public bool SilentMode { - get => _silentMode && Settings.Default.ShowInNotificationArea; - private set => _silentMode = value; + get => field && Settings.Default.ShowInNotificationArea; + private set; } /// diff --git a/Hourglass/Timing/Theme.cs b/Hourglass/Timing/Theme.cs index 0ad5970..713fb8f 100644 --- a/Hourglass/Timing/Theme.cs +++ b/Hourglass/Timing/Theme.cs @@ -42,116 +42,56 @@ public sealed class Theme : INotifyPropertyChanged { #region Private Members - /// - /// The friendly name for this theme, or null if no friendly name is specified. - /// - private string _name; - - /// - /// The background color of the window. - /// - private Color _backgroundColor; - /// /// The brush used to paint the background color of the window. /// private Brush? _backgroundBrush; - /// - /// The color of the progress bar. - /// - private Color _progressBarColor; - /// /// The brush used to paint the color of the progress bar. /// private Brush? _progressBarBrush; - /// - /// The background color of the progress bar. - /// - private Color _progressBackgroundColor; - /// /// The brush used to paint the background color of the progress bar. /// private Brush? _progressBackgroundBrush; - /// - /// The color that is flashed on expiration. - /// - private Color _expirationFlashColor; - /// /// The brush used to paint the color that is flashed on expiration. /// private Brush? _expirationFlashBrush; - /// - /// The color of the primary text. - /// - private Color _primaryTextColor; - /// /// The brush used to paint the color of the primary text. /// private Brush? _primaryTextBrush; - /// - /// The color of the watermark in the primary text box. - /// - private Color _primaryHintColor; - /// /// The brush used to paint the color of the watermark in the primary text box. /// private Brush? _primaryHintBrush; - /// - /// The color of any secondary text. - /// - private Color _secondaryTextColor; - /// /// The brush used to paint the color of any secondary text. /// private Brush? _secondaryTextBrush; - /// - /// The color of the watermark in any secondary text box. - /// - private Color _secondaryHintColor; - /// /// The brush used to paint the color of the watermark in any secondary text box. /// private Brush? _secondaryHintBrush; - /// - /// The color of the button text. - /// - private Color _buttonColor; - /// /// The brush used to paint the color of the button text. /// private Brush? _buttonBrush; - /// - /// The color of the button text when the user hovers over the button. - /// - private Color _buttonHoverColor; - /// /// The brush used to paint the color of the button text when the user hovers over the button. /// private Brush? _buttonHoverBrush; - /// - /// Is the user theme the dark one. - /// - private bool _isUserThemeDark; - #endregion #region Constructors @@ -191,19 +131,19 @@ public Theme( { Type = type; Identifier = identifier; - _name = name; - - _backgroundColor = backgroundColor; - _progressBarColor = progressBarColor; - _progressBackgroundColor = progressBackgroundColor; - _expirationFlashColor = expirationFlashColor; - _primaryTextColor = primaryTextColor; - _primaryHintColor = primaryHintColor; - _secondaryTextColor = secondaryTextColor; - _secondaryHintColor = secondaryHintColor; - _buttonColor = buttonColor; - _buttonHoverColor = buttonHoverColor; - _isUserThemeDark = isUserThemeDark; + Name = name; + + BackgroundColor = backgroundColor; + ProgressBarColor = progressBarColor; + ProgressBackgroundColor = progressBackgroundColor; + ExpirationFlashColor = expirationFlashColor; + PrimaryTextColor = primaryTextColor; + PrimaryHintColor = primaryHintColor; + SecondaryTextColor = secondaryTextColor; + SecondaryHintColor = secondaryHintColor; + ButtonColor = buttonColor; + ButtonHoverColor = buttonHoverColor; + IsUserThemeDark = isUserThemeDark; } /// @@ -265,17 +205,17 @@ public Theme(ThemeType type, string identifier, string name, Theme theme) type, identifier, name, - theme._backgroundColor, - theme._progressBarColor, - theme._progressBackgroundColor, - theme._expirationFlashColor, - theme._primaryTextColor, - theme._primaryHintColor, - theme._secondaryTextColor, - theme._secondaryHintColor, - theme._buttonColor, - theme._buttonHoverColor, - theme.Type == ThemeType.BuiltInDark || theme._isUserThemeDark) + theme.BackgroundColor, + theme.ProgressBarColor, + theme.ProgressBackgroundColor, + theme.ExpirationFlashColor, + theme.PrimaryTextColor, + theme.PrimaryHintColor, + theme.SecondaryTextColor, + theme.SecondaryHintColor, + theme.ButtonColor, + theme.ButtonHoverColor, + theme.Type == ThemeType.BuiltInDark || theme.IsUserThemeDark) { } @@ -331,16 +271,16 @@ public Theme(ThemeInfo info) /// public string Name { - get => _name; + get; set { - if (_name == value) + if (field == value) { return; } - _name = value; + field = value; PropertyChanged.Notify(this); } } @@ -350,16 +290,16 @@ public string Name /// public Color BackgroundColor { - get => _backgroundColor; + get; set { - if (_backgroundColor == value) + if (field == value) { return; } - _backgroundColor = value; + field = value; _backgroundBrush = null; PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(BackgroundBrush)); @@ -369,23 +309,23 @@ public Color BackgroundColor /// /// Gets the brush used to paint the background color of the window. /// - public Brush BackgroundBrush => _backgroundBrush ??= new SolidColorBrush(_backgroundColor); + public Brush BackgroundBrush => _backgroundBrush ??= new SolidColorBrush(BackgroundColor); /// /// Gets or sets the color of the progress bar. /// public Color ProgressBarColor { - get => _progressBarColor; + get; set { - if (_progressBarColor == value) + if (field == value) { return; } - _progressBarColor = value; + field = value; _progressBarBrush = null; PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(ProgressBarBrush)); @@ -395,23 +335,23 @@ public Color ProgressBarColor /// /// Gets the brush used to paint the color of the progress bar. /// - public Brush ProgressBarBrush => _progressBarBrush ??= new SolidColorBrush(_progressBarColor); + public Brush ProgressBarBrush => _progressBarBrush ??= new SolidColorBrush(ProgressBarColor); /// /// Gets or sets the background color of the progress bar. /// public Color ProgressBackgroundColor { - get => _progressBackgroundColor; + get; set { - if (_progressBackgroundColor == value) + if (field == value) { return; } - _progressBackgroundColor = value; + field = value; _progressBackgroundBrush = null; PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(ProgressBackgroundBrush)); @@ -421,23 +361,23 @@ public Color ProgressBackgroundColor /// /// Gets the brush used to paint the background color of the progress bar. /// - public Brush ProgressBackgroundBrush => _progressBackgroundBrush ??= new SolidColorBrush(_progressBackgroundColor); + public Brush ProgressBackgroundBrush => _progressBackgroundBrush ??= new SolidColorBrush(ProgressBackgroundColor); /// /// Gets or sets the color that is flashed on expiration. /// public Color ExpirationFlashColor { - get => _expirationFlashColor; + get; set { - if (_expirationFlashColor == value) + if (field == value) { return; } - _expirationFlashColor = value; + field = value; _expirationFlashBrush = null; PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(ExpirationFlashBrush)); @@ -447,23 +387,23 @@ public Color ExpirationFlashColor /// /// Gets the brush used to paint the color that is flashed on expiration. /// - public Brush ExpirationFlashBrush => _expirationFlashBrush ??= new SolidColorBrush(_expirationFlashColor); + public Brush ExpirationFlashBrush => _expirationFlashBrush ??= new SolidColorBrush(ExpirationFlashColor); /// /// Gets or sets the color of the primary text. /// public Color PrimaryTextColor { - get => _primaryTextColor; + get; set { - if (_primaryTextColor == value) + if (field == value) { return; } - _primaryTextColor = value; + field = value; _primaryTextBrush = null; PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(PrimaryTextBrush)); @@ -473,23 +413,23 @@ public Color PrimaryTextColor /// /// Gets the brush used to paint the color of the primary text. /// - public Brush PrimaryTextBrush => _primaryTextBrush ??= new SolidColorBrush(_primaryTextColor); + public Brush PrimaryTextBrush => _primaryTextBrush ??= new SolidColorBrush(PrimaryTextColor); /// /// Gets or sets the color of the watermark in the primary text box. /// public Color PrimaryHintColor { - get => _primaryHintColor; + get; set { - if (_primaryHintColor == value) + if (field == value) { return; } - _primaryHintColor = value; + field = value; _primaryHintBrush = null; PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(PrimaryHintBrush)); @@ -499,23 +439,23 @@ public Color PrimaryHintColor /// /// Gets the brush used to paint the color of the watermark in the primary text box. /// - public Brush PrimaryHintBrush => _primaryHintBrush ??= new SolidColorBrush(_primaryHintColor); + public Brush PrimaryHintBrush => _primaryHintBrush ??= new SolidColorBrush(PrimaryHintColor); /// /// Gets or sets the color of any secondary text. /// public Color SecondaryTextColor { - get => _secondaryTextColor; + get; set { - if (_secondaryTextColor == value) + if (field == value) { return; } - _secondaryTextColor = value; + field = value; _secondaryTextBrush = null; PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(SecondaryTextBrush)); @@ -525,23 +465,23 @@ public Color SecondaryTextColor /// /// Gets the brush used to paint the color of any secondary text. /// - public Brush SecondaryTextBrush => _secondaryTextBrush ??= new SolidColorBrush(_secondaryTextColor); + public Brush SecondaryTextBrush => _secondaryTextBrush ??= new SolidColorBrush(SecondaryTextColor); /// /// Gets or sets the color of the watermark in any secondary text box. /// public Color SecondaryHintColor { - get => _secondaryHintColor; + get; set { - if (_secondaryHintColor == value) + if (field == value) { return; } - _secondaryHintColor = value; + field = value; _secondaryHintBrush = null; PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(SecondaryHintBrush)); @@ -551,23 +491,23 @@ public Color SecondaryHintColor /// /// Gets the brush used to paint the color of the watermark in any secondary text box. /// - public Brush SecondaryHintBrush => _secondaryHintBrush ??= new SolidColorBrush(_secondaryHintColor); + public Brush SecondaryHintBrush => _secondaryHintBrush ??= new SolidColorBrush(SecondaryHintColor); /// /// Gets or sets the color of the button text. /// public Color ButtonColor { - get => _buttonColor; + get; set { - if (_buttonColor == value) + if (field == value) { return; } - _buttonColor = value; + field = value; _buttonBrush = null; PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(ButtonBrush)); @@ -577,23 +517,23 @@ public Color ButtonColor /// /// Gets the brush used to paint the color of the button text. /// - public Brush ButtonBrush => _buttonBrush ??= new SolidColorBrush(_buttonColor); + public Brush ButtonBrush => _buttonBrush ??= new SolidColorBrush(ButtonColor); /// /// Gets or sets the color of the button text when the user hovers over the button. /// public Color ButtonHoverColor { - get => _buttonHoverColor; + get; set { - if (_buttonHoverColor == value) + if (field == value) { return; } - _buttonHoverColor = value; + field = value; _buttonHoverBrush = null; PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(ButtonHoverBrush)); @@ -605,16 +545,16 @@ public Color ButtonHoverColor /// public bool IsUserThemeDark { - get => _isUserThemeDark; + get; set { - if (_isUserThemeDark == value) + if (field == value) { return; } - _isUserThemeDark = value; + field = value; PropertyChanged.Notify(this); } } @@ -622,7 +562,7 @@ public bool IsUserThemeDark /// /// Gets the brush used to paint the color of the button text when the user hovers over the button. /// - public Brush ButtonHoverBrush => _buttonHoverBrush ??= new SolidColorBrush(_buttonHoverColor); + public Brush ButtonHoverBrush => _buttonHoverBrush ??= new SolidColorBrush(ButtonHoverColor); /// /// Gets the light variant of this theme. @@ -730,18 +670,18 @@ public ThemeInfo ToThemeInfo() return new() { Identifier = Identifier, - Name = _name, - BackgroundColor = _backgroundColor, - ProgressBarColor = _progressBarColor, - ProgressBackgroundColor = _progressBackgroundColor, - ExpirationFlashColor = _expirationFlashColor, - PrimaryTextColor = _primaryTextColor, - PrimaryHintColor = _primaryHintColor, - SecondaryTextColor = _secondaryTextColor, - SecondaryHintColor = _secondaryHintColor, - ButtonColor = _buttonColor, - ButtonHoverColor = _buttonHoverColor, - IsUserThemeDark = _isUserThemeDark + Name = Name, + BackgroundColor = BackgroundColor, + ProgressBarColor = ProgressBarColor, + ProgressBackgroundColor = ProgressBackgroundColor, + ExpirationFlashColor = ExpirationFlashColor, + PrimaryTextColor = PrimaryTextColor, + PrimaryHintColor = PrimaryHintColor, + SecondaryTextColor = SecondaryTextColor, + SecondaryHintColor = SecondaryHintColor, + ButtonColor = ButtonColor, + ButtonHoverColor = ButtonHoverColor, + IsUserThemeDark = IsUserThemeDark }; } diff --git a/Hourglass/Timing/TimerOptions.cs b/Hourglass/Timing/TimerOptions.cs index ae682b2..1973bad 100644 --- a/Hourglass/Timing/TimerOptions.cs +++ b/Hourglass/Timing/TimerOptions.cs @@ -70,113 +70,6 @@ public enum WindowTitleMode /// public sealed class TimerOptions : INotifyPropertyChanged { - #region Private Members - - /// - /// A user-specified title for the timer. - /// - private string? _title; - - /// - /// A value indicating whether the timer window should always be displayed on top of other windows. - /// - private bool _alwaysOnTop; - - /// - /// A value indicating whether to prompt the user before closing the timer window if the timer is running. - /// - private bool _promptOnExit; - - /// - /// A value indicating whether to show progress in the taskbar. - /// - private bool _showProgressInTaskbar; - - /// - /// A value indicating whether to keep the computer awake while the timer is running. - /// - private bool _doNotKeepComputerAwake; - - /// - /// A value indicating whether to reverse the progress bar (count backwards). - /// - private bool _reverseProgressBar; - - /// - /// A value indicating whether to show the time elapsed rather than the time left. - /// - private bool _showTimeElapsed; - - /// - /// A value indicating whether to show the trigger time. - /// - private bool _showTriggerTime; - - /// - /// A value indicating whether to loop the timer continuously. - /// - private bool _loopTimer; - - /// - /// A value indicating whether to pause before loop the timer continuously. - /// - private bool _pauseBeforeLoopTimer; - - /// - /// A value indicating whether the timer window should be brought to the top of other windows when the timer - /// expires. - /// - private bool _popUpWhenExpired; - - /// - /// A value indicating whether the timer window should be closed when the timer expires. - /// - private bool _closeWhenExpired; - - /// - /// A value indicating whether Windows should be shut down when the timer expires. - /// - private bool _shutDownWhenExpired; - - /// - /// The sound to play when the timer expires, or null if no sound is to be played. - /// - private Sound? _sound; - - /// - /// A value indicating whether the sound that plays when the timer expires should be looped until stopped by - /// the user. - /// - private bool _loopSound; - - /// - /// The theme of the timer window. - /// - private Theme? _theme; - - /// - /// A value indicating what information to display in the timer window title. - /// - private WindowTitleMode _windowTitleMode; - - /// - /// The size, position, and state of the timer window. - /// - private WindowSize? _windowSize; - - /// - /// A value indicating whether the user interface should be locked, preventing the user from taking any action - /// until the timer expires. - /// - private bool _lockInterface; - - /// - /// A value indicating whether to display time in the digital clock format. - /// - private bool _digitalClockTime; - - #endregion - #region Constructors /// @@ -184,30 +77,30 @@ public sealed class TimerOptions : INotifyPropertyChanged /// public TimerOptions() { - _title = string.Empty; - _alwaysOnTop = false; - _promptOnExit = true; - _showProgressInTaskbar = true; - _doNotKeepComputerAwake = false; - _reverseProgressBar = false; - _digitalClockTime = false; - _showTimeElapsed = false; - _showTriggerTime = false; - _loopTimer = false; - _pauseBeforeLoopTimer = false; - _popUpWhenExpired = true; - _closeWhenExpired = false; - _shutDownWhenExpired = false; - _theme = Theme.DefaultTheme; - _sound = Sound.DefaultSound; - _loopSound = false; - _windowTitleMode = WindowTitleMode.ApplicationName; - _windowSize = new( + Title = string.Empty; + AlwaysOnTop = false; + PromptOnExit = true; + ShowProgressInTaskbar = true; + DoNotKeepComputerAwake = false; + ReverseProgressBar = false; + DigitalClockTime = false; + ShowTimeElapsed = false; + ShowTriggerTime = false; + LoopTimer = false; + PauseBeforeLoopTimer = false; + PopUpWhenExpired = true; + CloseWhenExpired = false; + ShutDownWhenExpired = false; + Theme = Theme.DefaultTheme; + Sound = Sound.DefaultSound; + LoopSound = false; + WindowTitleMode = WindowTitleMode.ApplicationName; + WindowSize = new( new(double.PositiveInfinity, double.PositiveInfinity, InterfaceScaler.BaseWindowWidth, InterfaceScaler.BaseWindowHeight), WindowState.Normal, WindowState.Normal, false /* isFullScreen */); - _lockInterface = false; + LockInterface = false; } /// @@ -243,16 +136,16 @@ public TimerOptions(TimerOptionsInfo info) /// public string? Title { - get => _title; + get; set { - if (_title == value) + if (field == value) { return; } - _title = value; + field = value; PropertyChanged.Notify(this); } } @@ -262,16 +155,16 @@ public string? Title /// public bool AlwaysOnTop { - get => _alwaysOnTop; + get; set { - if (_alwaysOnTop == value) + if (field == value) { return; } - _alwaysOnTop = value; + field = value; PropertyChanged.Notify(this); } } @@ -282,16 +175,16 @@ public bool AlwaysOnTop /// public bool PromptOnExit { - get => _promptOnExit; + get; set { - if (_promptOnExit == value) + if (field == value) { return; } - _promptOnExit = value; + field = value; PropertyChanged.Notify(this); } } @@ -301,16 +194,16 @@ public bool PromptOnExit /// public bool ShowProgressInTaskbar { - get => _showProgressInTaskbar; + get; set { - if (_showProgressInTaskbar == value) + if (field == value) { return; } - _showProgressInTaskbar = value; + field = value; PropertyChanged.Notify(this); } } @@ -320,16 +213,16 @@ public bool ShowProgressInTaskbar /// public bool DoNotKeepComputerAwake { - get => _doNotKeepComputerAwake; + get; set { - if (_doNotKeepComputerAwake == value) + if (field == value) { return; } - _doNotKeepComputerAwake = value; + field = value; PropertyChanged.Notify(this); } } @@ -339,16 +232,16 @@ public bool DoNotKeepComputerAwake /// public bool ReverseProgressBar { - get => _reverseProgressBar; + get; set { - if (_reverseProgressBar == value) + if (field == value) { return; } - _reverseProgressBar = value; + field = value; PropertyChanged.Notify(this); } } @@ -358,16 +251,16 @@ public bool ReverseProgressBar /// public bool DigitalClockTime { - get => _digitalClockTime; + get; set { - if (_digitalClockTime == value) + if (field == value) { return; } - _digitalClockTime = value; + field = value; PropertyChanged.Notify(this); } } @@ -377,16 +270,16 @@ public bool DigitalClockTime /// public bool ShowTimeElapsed { - get => _showTimeElapsed; + get; set { - if (_showTimeElapsed == value) + if (field == value) { return; } - _showTimeElapsed = value; + field = value; PropertyChanged.Notify(this); } } @@ -396,16 +289,16 @@ public bool ShowTimeElapsed /// public bool ShowTriggerTime { - get => _showTriggerTime; + get; set { - if (_showTriggerTime == value) + if (field == value) { return; } - _showTriggerTime = value; + field = value; PropertyChanged.Notify(this); } } @@ -415,16 +308,16 @@ public bool ShowTriggerTime /// public bool LoopTimer { - get => _loopTimer; + get; set { - if (_loopTimer == value) + if (field == value) { return; } - _loopTimer = value; + field = value; PropertyChanged.Notify(this); } } @@ -434,16 +327,16 @@ public bool LoopTimer /// public bool PauseBeforeLoopTimer { - get => _pauseBeforeLoopTimer; + get; set { - if (_pauseBeforeLoopTimer == value) + if (field == value) { return; } - _pauseBeforeLoopTimer = value; + field = value; PropertyChanged.Notify(this); } } @@ -454,16 +347,16 @@ public bool PauseBeforeLoopTimer /// public bool PopUpWhenExpired { - get => _popUpWhenExpired; + get; set { - if (_popUpWhenExpired == value) + if (field == value) { return; } - _popUpWhenExpired = value; + field = value; PropertyChanged.Notify(this); } } @@ -473,16 +366,16 @@ public bool PopUpWhenExpired /// public bool CloseWhenExpired { - get => _closeWhenExpired; + get; set { - if (_closeWhenExpired == value) + if (field == value) { return; } - _closeWhenExpired = value; + field = value; PropertyChanged.Notify(this); } } @@ -492,16 +385,16 @@ public bool CloseWhenExpired /// public bool ShutDownWhenExpired { - get => _shutDownWhenExpired; + get; set { - if (_shutDownWhenExpired == value) + if (field == value) { return; } - _shutDownWhenExpired = value; + field = value; PropertyChanged.Notify(this); } } @@ -511,16 +404,16 @@ public bool ShutDownWhenExpired /// public Theme? Theme { - get => _theme; + get; set { - if (ReferenceEquals(_theme, value)) + if (field == value) { return; } - _theme = value; + field = value; PropertyChanged.Notify(this); } } @@ -530,16 +423,16 @@ public Theme? Theme /// public Sound? Sound { - get => _sound; + get; set { - if (_sound == value) + if (field == value) { return; } - _sound = value; + field = value; PropertyChanged.Notify(this); } } @@ -550,16 +443,16 @@ public Sound? Sound /// public bool LoopSound { - get => _loopSound; + get; set { - if (_loopSound == value) + if (field == value) { return; } - _loopSound = value; + field = value; PropertyChanged.Notify(this); } } @@ -569,16 +462,16 @@ public bool LoopSound /// public WindowTitleMode WindowTitleMode { - get => _windowTitleMode; + get; set { - if (_windowTitleMode == value) + if (field == value) { return; } - _windowTitleMode = value; + field = value; PropertyChanged.Notify(this); } } @@ -588,16 +481,16 @@ public WindowTitleMode WindowTitleMode /// public WindowSize? WindowSize { - get => _windowSize; + get; set { - if (_windowSize == value) + if (field == value) { return; } - _windowSize = value; + field = value; PropertyChanged.Notify(this); } } @@ -608,16 +501,16 @@ public WindowSize? WindowSize /// public bool LockInterface { - get => _lockInterface; + get; set { - if (_lockInterface == value) + if (field == value) { return; } - _lockInterface = value; + field = value; PropertyChanged.Notify(this); } } @@ -660,26 +553,26 @@ public void Set(TimerOptions options) throw new ArgumentNullException(nameof(options)); } - _title = options._title; - _alwaysOnTop = options._alwaysOnTop; - _promptOnExit = options._promptOnExit; - _showProgressInTaskbar = options._showProgressInTaskbar; - _doNotKeepComputerAwake = options._doNotKeepComputerAwake; - _reverseProgressBar = options._reverseProgressBar; - _digitalClockTime = options._digitalClockTime; - _showTimeElapsed = options._showTimeElapsed; - _showTriggerTime = options._showTriggerTime; - _loopTimer = options._loopTimer; - _pauseBeforeLoopTimer = options._pauseBeforeLoopTimer; - _popUpWhenExpired = options._popUpWhenExpired; - _closeWhenExpired = options._closeWhenExpired; - _shutDownWhenExpired = options._shutDownWhenExpired; - _theme = options._theme; - _sound = options._sound; - _loopSound = options._loopSound; - _windowTitleMode = options._windowTitleMode; - _windowSize = WindowSize.FromWindowSize(options.WindowSize); - _lockInterface = options._lockInterface; + Title = options.Title; + AlwaysOnTop = options.AlwaysOnTop; + PromptOnExit = options.PromptOnExit; + ShowProgressInTaskbar = options.ShowProgressInTaskbar; + DoNotKeepComputerAwake = options.DoNotKeepComputerAwake; + ReverseProgressBar = options.ReverseProgressBar; + DigitalClockTime = options.DigitalClockTime; + ShowTimeElapsed = options.ShowTimeElapsed; + ShowTriggerTime = options.ShowTriggerTime; + LoopTimer = options.LoopTimer; + PauseBeforeLoopTimer = options.PauseBeforeLoopTimer; + PopUpWhenExpired = options.PopUpWhenExpired; + CloseWhenExpired = options.CloseWhenExpired; + ShutDownWhenExpired = options.ShutDownWhenExpired; + Theme = options.Theme; + Sound = options.Sound; + LoopSound = options.LoopSound; + WindowTitleMode = options.WindowTitleMode; + WindowSize = WindowSize.FromWindowSize(options.WindowSize); + LockInterface = options.LockInterface; PropertyChanged.Notify(this, nameof(WindowTitleMode), @@ -715,26 +608,26 @@ private void Set(TimerOptionsInfo info) throw new ArgumentNullException(nameof(info)); } - _title = info.Title; - _alwaysOnTop = info.AlwaysOnTop; - _promptOnExit = info.PromptOnExit; - _showProgressInTaskbar = info.ShowProgressInTaskbar; - _doNotKeepComputerAwake = info.DoNotKeepComputerAwake; - _reverseProgressBar = info.ReverseProgressBar; - _digitalClockTime = info.DigitalClockTime; - _showTimeElapsed = info.ShowTimeElapsed; - _showTriggerTime = info.ShowTriggerTime; - _loopTimer = info.LoopTimer; - _pauseBeforeLoopTimer = info.PauseBeforeLoopTimer; - _popUpWhenExpired = info.PopUpWhenExpired; - _closeWhenExpired = info.CloseWhenExpired; - _shutDownWhenExpired = info.ShutDownWhenExpired; - _theme = Theme.FromIdentifier(info.ThemeIdentifier); - _sound = Sound.FromIdentifier(info.SoundIdentifier); - _loopSound = info.LoopSound; - _windowTitleMode = info.WindowTitleMode; - _windowSize = WindowSize.FromWindowSizeInfo(info.WindowSize); - _lockInterface = info.LockInterface; + Title = info.Title; + AlwaysOnTop = info.AlwaysOnTop; + PromptOnExit = info.PromptOnExit; + ShowProgressInTaskbar = info.ShowProgressInTaskbar; + DoNotKeepComputerAwake = info.DoNotKeepComputerAwake; + ReverseProgressBar = info.ReverseProgressBar; + DigitalClockTime = info.DigitalClockTime; + ShowTimeElapsed = info.ShowTimeElapsed; + ShowTriggerTime = info.ShowTriggerTime; + LoopTimer = info.LoopTimer; + PauseBeforeLoopTimer = info.PauseBeforeLoopTimer; + PopUpWhenExpired = info.PopUpWhenExpired; + CloseWhenExpired = info.CloseWhenExpired; + ShutDownWhenExpired = info.ShutDownWhenExpired; + Theme = Theme.FromIdentifier(info.ThemeIdentifier); + Sound = Sound.FromIdentifier(info.SoundIdentifier); + LoopSound = info.LoopSound; + WindowTitleMode = info.WindowTitleMode; + WindowSize = WindowSize.FromWindowSizeInfo(info.WindowSize); + LockInterface = info.LockInterface; PropertyChanged.Notify(this, nameof(WindowTitleMode), @@ -766,26 +659,26 @@ public TimerOptionsInfo ToTimerOptionsInfo() { return new() { - Title = _title, - AlwaysOnTop = _alwaysOnTop, - PromptOnExit = _promptOnExit, - ShowProgressInTaskbar = _showProgressInTaskbar, - DoNotKeepComputerAwake = _doNotKeepComputerAwake, - ReverseProgressBar = _reverseProgressBar, - DigitalClockTime = _digitalClockTime, - ShowTimeElapsed = _showTimeElapsed, - ShowTriggerTime = _showTriggerTime, - LoopTimer = _loopTimer, - PauseBeforeLoopTimer = _pauseBeforeLoopTimer, - PopUpWhenExpired = _popUpWhenExpired, - CloseWhenExpired = _closeWhenExpired, - ShutDownWhenExpired = _shutDownWhenExpired, - ThemeIdentifier = _theme?.Identifier, - SoundIdentifier = _sound?.Identifier, - LoopSound = _loopSound, - WindowTitleMode = _windowTitleMode, - WindowSize = WindowSizeInfo.FromWindowSize(_windowSize)!, - LockInterface = _lockInterface + Title = Title, + AlwaysOnTop = AlwaysOnTop, + PromptOnExit = PromptOnExit, + ShowProgressInTaskbar = ShowProgressInTaskbar, + DoNotKeepComputerAwake = DoNotKeepComputerAwake, + ReverseProgressBar = ReverseProgressBar, + DigitalClockTime = DigitalClockTime, + ShowTimeElapsed = ShowTimeElapsed, + ShowTriggerTime = ShowTriggerTime, + LoopTimer = LoopTimer, + PauseBeforeLoopTimer = PauseBeforeLoopTimer, + PopUpWhenExpired = PopUpWhenExpired, + CloseWhenExpired = CloseWhenExpired, + ShutDownWhenExpired = ShutDownWhenExpired, + ThemeIdentifier = Theme?.Identifier, + SoundIdentifier = Sound?.Identifier, + LoopSound = LoopSound, + WindowTitleMode = WindowTitleMode, + WindowSize = WindowSizeInfo.FromWindowSize(WindowSize)!, + LockInterface = LockInterface }; } diff --git a/Hourglass/Windows/ThemeManagerWindow.xaml.cs b/Hourglass/Windows/ThemeManagerWindow.xaml.cs index db7e202..6769f72 100644 --- a/Hourglass/Windows/ThemeManagerWindow.xaml.cs +++ b/Hourglass/Windows/ThemeManagerWindow.xaml.cs @@ -45,27 +45,6 @@ public enum ThemeManagerWindowState /// public sealed partial class ThemeManagerWindow { - /// - /// The state of the window. - /// - private ThemeManagerWindowState _state; - - /// - /// The that will be updated when a theme is selected in this window. - /// - private TimerWindow _timerWindow = null!; - - /// - /// The currently selected theme. - /// - private Theme _selectedTheme = null!; - - /// - /// A copy of the currently selected theme. The changes to this copy are applied to the selected theme when the - /// user saves their changes. - /// - private Theme _editedTheme = null!; - /// /// Initializes a new instance of the class. /// @@ -83,11 +62,11 @@ public ThemeManagerWindow(TimerWindow timerWindow) /// public ThemeManagerWindowState State { - get => _state; + get; private set { - _state = value; + field = value; BindState(); } } @@ -97,11 +76,11 @@ private set /// public TimerWindow TimerWindow { - get => _timerWindow; + get; private set { - _timerWindow = value; + field = value; BindTimerWindow(); } } @@ -111,14 +90,14 @@ private set /// public Theme SelectedTheme { - get => _selectedTheme; + get; private set { - _selectedTheme = value; + field = value; BindSelectedTheme(); } - } + } = null!; /// /// Gets or sets a copy of the currently selected theme. The changes to this copy are applied to the selected @@ -126,14 +105,14 @@ private set /// private Theme EditedTheme { - get => _editedTheme; + get; set { - _editedTheme = value; - DataContext = _editedTheme; + field = value; + DataContext = field; } - } + } = null!; /// /// Brings the window to the front. @@ -189,16 +168,16 @@ private void UnfocusAll() /// private void BindTimerWindow() { - if (_timerWindow.Theme?.Type == ThemeType.UserProvided) + if (TimerWindow.Theme?.Type == ThemeType.UserProvided) { - EditedTheme = CloneThemeForEditing(_timerWindow.Theme); - SelectedTheme = _timerWindow.Theme; + EditedTheme = CloneThemeForEditing(TimerWindow.Theme); + SelectedTheme = TimerWindow.Theme; State = ThemeManagerWindowState.UserThemeUnedited; } else { - EditedTheme = _timerWindow.Theme!; - SelectedTheme = _timerWindow.Theme!; + EditedTheme = TimerWindow.Theme!; + SelectedTheme = TimerWindow.Theme!; State = ThemeManagerWindowState.BuiltInTheme; } } @@ -225,7 +204,7 @@ private void BindSelectedTheme() /// private void BindState() { - switch (_state) + switch (State) { case ThemeManagerWindowState.BuiltInTheme: NameTextBox.IsEnabled = false; @@ -416,20 +395,20 @@ private void ThemesComboBoxSelectionChanged(object sender, SelectionChangedEvent } Theme newSelectedTheme = (Theme)selectedItem.Tag; - if (newSelectedTheme.Identifier == _selectedTheme.Identifier) + if (newSelectedTheme.Identifier == SelectedTheme.Identifier) { return; } // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - if (_timerWindow.Options is null || !PromptToSaveIfRequired()) + if (TimerWindow.Options is null || !PromptToSaveIfRequired()) { // Revert the selection BindSelectedTheme(); return; } - _timerWindow.Options.Theme = newSelectedTheme; + TimerWindow.Options.Theme = newSelectedTheme; BindTimerWindow(); } @@ -445,7 +424,7 @@ private void NewButtonClick(object sender, RoutedEventArgs e) return; } - _timerWindow.Options.Theme = ThemeManager.Instance.AddThemeBasedOnTheme(SelectedTheme); + TimerWindow.Options.Theme = ThemeManager.Instance.AddThemeBasedOnTheme(SelectedTheme); BindThemesComboBox(); BindTimerWindow(); } diff --git a/Hourglass/Windows/TimerWindow.xaml.cs b/Hourglass/Windows/TimerWindow.xaml.cs index 2ebd682..ef59233 100644 --- a/Hourglass/Windows/TimerWindow.xaml.cs +++ b/Hourglass/Windows/TimerWindow.xaml.cs @@ -172,16 +172,6 @@ public sealed partial class TimerWindow : INotifyPropertyChanged, IRestorableWin /// private readonly ContextMenu _menu = new(); - /// - /// The of the window. - /// - private TimerWindowMode _mode; - - /// - /// The timer backing the window. - /// - private Timer _timer = new(TimerOptionsManager.Instance.MostRecentOptions); - /// /// The timer to resume when the window loads, or null if no timer is to be resumed. /// @@ -193,11 +183,6 @@ public sealed partial class TimerWindow : INotifyPropertyChanged, IRestorableWin /// private TimerStart? _timerStartToStartOnLoad; - /// - /// The last used to start a timer in the window. - /// - private TimerStart _lastTimerStart = TimerStartManager.Instance.LastTimerStart; - /// /// The currently loaded theme. /// @@ -223,16 +208,6 @@ public sealed partial class TimerWindow : INotifyPropertyChanged, IRestorableWin /// private Storyboard _validationErrorStoryboard = null!; - /// - /// A value indicating whether the window is in full-screen mode. - /// - private bool _isFullScreen; - - /// - /// The before the window was minimized. - /// - private WindowState _restoreWindowState = WindowState.Normal; - #endregion public IEnumerable Commands { get; private set; } = []; @@ -288,16 +263,16 @@ public TimerWindow(TimerStart? timerStart) /// public TimerWindowMode Mode { - get => _mode; + get; private set { - if (_mode == value) + if (field == value) { return; } - _mode = value; + field = value; PropertyChanged.Notify(this); } } @@ -312,22 +287,22 @@ private set /// public Timer Timer { - get => _timer; + get; private set { - if (_timer == value) + if (field == value) { return; } UnbindTimer(); - _timer = value; + field = value; BindTimer(); PropertyChanged.Notify(this); PropertyChanged.Notify(this, nameof(Options)); } - } + } = new(TimerOptionsManager.Instance.MostRecentOptions); /// /// Gets the for the timer backing the window. @@ -339,19 +314,19 @@ private set /// public TimerStart LastTimerStart { - get => _lastTimerStart; + get; private set { - if (_lastTimerStart == value) + if (field == value) { return; } - _lastTimerStart = value; + field = value; PropertyChanged.Notify(this); } - } + } = TimerStartManager.Instance.LastTimerStart; /// /// Gets the currently loaded theme. @@ -363,20 +338,20 @@ private set /// public bool IsFullScreen { - get => _isFullScreen; + get; set { - if (_isFullScreen == value) + if (field == value) { return; } - _isFullScreen = value; + field = value; PropertyChanged.Notify(this); - if (_isFullScreen) + if (field) { WindowState = WindowState.Normal; // Needed to put the window on top of the taskbar WindowState = WindowState.Maximized; @@ -384,7 +359,7 @@ public bool IsFullScreen } else { - WindowState restoreWindowState = _restoreWindowState; + WindowState restoreWindowState = RestoreWindowState; if (restoreWindowState != WindowState.Normal && WindowStyle == WindowStyle.None) { WindowState = WindowState.Normal; @@ -401,19 +376,19 @@ public bool IsFullScreen /// public WindowState RestoreWindowState { - get => _restoreWindowState; + get; set { - if (_restoreWindowState == value) + if (field == value) { return; } - _restoreWindowState = value; + field = value; PropertyChanged.Notify(this); } - } + } = WindowState.Normal; public bool DoNotPromptOnExit { get; set; } @@ -421,19 +396,17 @@ public WindowState RestoreWindowState public bool ForceClose { get; set; } - private bool _showTimeToolTip; - public bool ShowTimeToolTip { - get => _showTimeToolTip; + get; set { - if (_showTimeToolTip == value) + if (field == value) { return; } - _showTimeToolTip = value; + field = value; UpdateTimeToolTip(); @@ -441,19 +414,17 @@ public bool ShowTimeToolTip } } - private string? _timeToolTip; - public string? TimeToolTip { - get => _timeToolTip; + get; set { - if (_timeToolTip == value) + if (field == value) { return; } - _timeToolTip = value; + field = value; PropertyChanged.Notify(this); } @@ -975,7 +946,7 @@ private void FlashExpirationStoryboardCompleted(object sender, EventArgs e) break; case TimerWindowMode.Status: - if (Options.LoopTimer && _timer.SupportsLooping) + if (Options.LoopTimer && Timer.SupportsLooping) { // Flash three times, or flash indefinitely if the sound is looped if (_flashExpirationCount < 3 || Options.LoopSound) From 9d6ee10d22ca0b1d6f160a06c869e017ec979d70 Mon Sep 17 00:00:00 2001 From: Ivan Ivon Date: Sat, 28 Dec 2024 01:23:23 +0200 Subject: [PATCH 3/3] Save on closing option --- FAQ.md | 15 +++++++++++++-- Hourglass/App.config | 3 +++ Hourglass/AppEntry.cs | 1 + Hourglass/CommandLineArguments.cs | 21 +++++++++++++++++++++ Hourglass/Managers/TimerManager.cs | 4 ++-- Hourglass/Properties/Resources.Designer.cs | 18 ++++++++++++++++++ Hourglass/Properties/Resources.resx | 8 ++++++++ Hourglass/Properties/Settings.Designer.cs | 14 +++++++++++++- Hourglass/Properties/Settings.settings | 3 +++ Hourglass/Resources/Usage.txt | 8 ++++++++ Hourglass/Timing/TimerBase.cs | 5 +++++ Hourglass/Windows/ContextMenu.cs | 19 +++++++++++++++++++ Hourglass/Windows/TimerWindow.xaml.cs | 11 ++++++++++- README.md | 4 ++++ 14 files changed, 128 insertions(+), 6 deletions(-) diff --git a/FAQ.md b/FAQ.md index 7b46b10..2d38b7b 100644 --- a/FAQ.md +++ b/FAQ.md @@ -22,6 +22,7 @@ The original **Hourglass** FAQ can be found [here](https://chris.dziemborowicz.c - [How do I save a timer?](#how-do-i-save-a-timer) - [How do I clear saved timers?](#how-do-i-clear-saved-timers) - [How do I set a title for a timer?](#how-do-i-set-a-title-for-a-timer) +- [How do I set a time for a timer?](#how-do-i-set-a-time-for-a-timer) - [How do I change what is displayed in the timer window title?](#how-do-i-change-what-is-displayed-in-the-timer-window-title) - [How do I change the timer window color theme?](#how-do-i-change-the-timer-window-color-theme) - [Is there a dark color theme available?](#is-there-a-dark-color-theme-available) @@ -291,7 +292,13 @@ And you can set the **Hourglass** to automatically open saved timers when it sta ## How do I save a timer? -A not expired yet timer is saved automatically when closed. See also [How do I resume a timer that I accidentally closed?](#how-do-i-resume-a-timer-that-i-accidentally-closed) +A not expired yet timer is saved automatically when closed if **Save timer on closing** option in the **Advanced options** submenu is checked. +You can change it in the close confirmation dialog shown if the **Prompt on close** in the timer window options menu is checked. + +See also [How do I resume a timer that I accidentally closed?](#how-do-i-resume-a-timer-that-i-accidentally-closed) + +> [!IMPORTANT] +> All the not expired yet timers are always saved on exit. ## How do I clear saved timers? @@ -299,10 +306,14 @@ A not expired yet timer is saved automatically when closed. See also [How do I r ## How do I set a title for a timer? -Click in the text field that says **Click to enter title**, enter a title and press `Enter`. +Click in the text field that says **Click to enter title** or press `F2`, enter a title and press `Enter`. To clear a title that you entered, click the title text field, delete the title text and press `Enter`. +## How do I set a time for a timer? + +Click in the time field or press `F4`, enter a time and press `Enter` to accept the new time or `Esc` to revert it back. In case of an error the red border will blink for a some time. + ## How do I change what is displayed in the timer window title? By default, the timer window title displays the application name **Hourglass**. You can change it to display the time left, the time elapsed or the timer title instead. diff --git a/Hourglass/App.config b/Hourglass/App.config index 703ed03..9c5b410 100644 --- a/Hourglass/App.config +++ b/Hourglass/App.config @@ -34,6 +34,9 @@ False + + True + diff --git a/Hourglass/AppEntry.cs b/Hourglass/AppEntry.cs index 93f59e5..2fd5420 100644 --- a/Hourglass/AppEntry.cs +++ b/Hourglass/AppEntry.cs @@ -203,6 +203,7 @@ private static void SetGlobalSettingsFromArguments(CommandLineArguments argument { Settings.Default.ShowInNotificationArea = arguments.ShowInNotificationArea; Settings.Default.OpenSavedTimersOnStartup = arguments.OpenSavedTimers; + Settings.Default.SaveTimerOnClosing = arguments.SaveTimerOnClosing; Settings.Default.Prefer24HourTime = arguments.Prefer24HourTime; Settings.Default.ActivateNextWindow = arguments.ActivateNextWindow; Settings.Default.OrderByTitleFirst = arguments.OrderByTitleFirst; diff --git a/Hourglass/CommandLineArguments.cs b/Hourglass/CommandLineArguments.cs index a01b34d..d38952e 100644 --- a/Hourglass/CommandLineArguments.cs +++ b/Hourglass/CommandLineArguments.cs @@ -163,6 +163,11 @@ public static string Usage /// public bool OpenSavedTimers { get; private set; } + /// + /// Gets a value indicating whether a timer should be saved on closing. + /// + public bool SaveTimerOnClosing { get; private set; } + /// /// Gets a value indicating whether to prefer interpreting time of day values as 24-hour time. /// @@ -332,6 +337,7 @@ private static CommandLineArguments GetArgumentsFromMostRecentOptions() Sound = options.Sound, LoopSound = options.LoopSound, OpenSavedTimers = Settings.Default.OpenSavedTimersOnStartup, + SaveTimerOnClosing = Settings.Default.SaveTimerOnClosing, Prefer24HourTime = Settings.Default.Prefer24HourTime, ActivateNextWindow = Settings.Default.ActivateNextWindow, OrderByTitleFirst = Settings.Default.OrderByTitleFirst, @@ -377,6 +383,7 @@ private static CommandLineArguments GetArgumentsFromFactoryDefaults() Sound = defaultOptions.Sound, LoopSound = defaultOptions.LoopSound, OpenSavedTimers = false, + SaveTimerOnClosing = true, Prefer24HourTime = false, ActivateNextWindow = true, OrderByTitleFirst = false, @@ -717,6 +724,20 @@ private static CommandLineArguments GetCommandLineArguments(IEnumerable argumentsBasedOnFactoryDefaults.OpenSavedTimers = openSavedTimers; break; + case "--save-timer-on-closing": + case "-sc": + case "/sc": + ThrowIfDuplicateSwitch(specifiedSwitches, "--save-timer-on-closing"); + + bool saveTimerOnClosing = GetBoolValue( + arg, + remainingArgs, + argumentsBasedOnMostRecentOptions.SaveTimerOnClosing); + + argumentsBasedOnMostRecentOptions.SaveTimerOnClosing = saveTimerOnClosing; + argumentsBasedOnFactoryDefaults.SaveTimerOnClosing = saveTimerOnClosing; + break; + case "--prefer-24h-time": case "-j": case "/j": diff --git a/Hourglass/Managers/TimerManager.cs b/Hourglass/Managers/TimerManager.cs index 8c5049c..29c8769 100644 --- a/Hourglass/Managers/TimerManager.cs +++ b/Hourglass/Managers/TimerManager.cs @@ -61,7 +61,7 @@ public bool SilentMode /// . /// #pragma warning disable S2365 - public IReadOnlyCollection ResumableTimers => _timers.Where(static t => t.State != TimerState.Stopped && !IsBoundToWindow(t)).ToArray(); + public IReadOnlyCollection ResumableTimers => _timers.Where(static t => t is { ShouldBeSaved: true, State: not TimerState.Stopped } && !IsBoundToWindow(t)).ToArray(); #pragma warning restore S2365 /// @@ -87,7 +87,7 @@ public override void Initialize() public override void Persist() { Settings.Default.Timers = _timers - .Where(static t => t.State != TimerState.Stopped && t.State != TimerState.Expired) + .Where(static t => t is { ShouldBeSaved: true, State: not TimerState.Stopped and not TimerState.Expired }) .Where(static t => !t.Options.LockInterface) .Take(MaxSavedTimers) .ToList(); diff --git a/Hourglass/Properties/Resources.Designer.cs b/Hourglass/Properties/Resources.Designer.cs index 0004581..1cf6416 100644 --- a/Hourglass/Properties/Resources.Designer.cs +++ b/Hourglass/Properties/Resources.Designer.cs @@ -583,6 +583,15 @@ public static string ContextMenuSavedTimersMenuItem { } } + /// + /// Looks up a localized string similar to Sa_ve timer on closing. + /// + public static string ContextMenuSaveTimerOnClosingMenuItem { + get { + return ResourceManager.GetString("ContextMenuSaveTimerOnClosingMenuItem", resourceCulture); + } + } + /// /// Looks up a localized string similar to _Show elapsed time instead of time left. /// @@ -1633,6 +1642,15 @@ public static string RelativeDateTokenTomorrowPattern { } } + /// + /// Looks up a localized string similar to &Save this timer. + /// + public static string SaveTimerTaskDialogText { + get { + return ResourceManager.GetString("SaveTimerTaskDialogText", resourceCulture); + } + } + /// /// Looks up a localized string similar to Lo_ud beep. /// diff --git a/Hourglass/Properties/Resources.resx b/Hourglass/Properties/Resources.resx index 4742aef..b80516d 100644 --- a/Hourglass/Properties/Resources.resx +++ b/Hourglass/Properties/Resources.resx @@ -1093,6 +1093,10 @@ $ &Close Close task dialog command + + Sa&ve this timer + Save this timer task dialog text + Mi&nimize Minimize task dialog command @@ -1128,6 +1132,10 @@ $ _Open saved timers on startup The text for the open saved timers on startup menu item, where the character following the optional underscore (_) is the access key + + Sa_ve timer on closing + The text for the save timer on closing menu item, where the character following the optional underscore (_) is the access key + _Show elapsed time instead of time left The text for the show elapsed time menu item, where the character following the optional underscore (_) is the access key diff --git a/Hourglass/Properties/Settings.Designer.cs b/Hourglass/Properties/Settings.Designer.cs index 08b021a..2768f14 100644 --- a/Hourglass/Properties/Settings.Designer.cs +++ b/Hourglass/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace Hourglass.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.12.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.13.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -173,5 +173,17 @@ public bool OrderByTitleFirst { this["OrderByTitleFirst"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool SaveTimerOnClosing { + get { + return ((bool)(this["SaveTimerOnClosing"])); + } + set { + this["SaveTimerOnClosing"] = value; + } + } } } diff --git a/Hourglass/Properties/Settings.settings b/Hourglass/Properties/Settings.settings index 99a9e45..8d174b4 100644 --- a/Hourglass/Properties/Settings.settings +++ b/Hourglass/Properties/Settings.settings @@ -41,5 +41,8 @@ False + + True + \ No newline at end of file diff --git a/Hourglass/Resources/Usage.txt b/Hourglass/Resources/Usage.txt index df947ea..e3af4c4 100644 --- a/Hourglass/Resources/Usage.txt +++ b/Hourglass/Resources/Usage.txt @@ -246,6 +246,13 @@ Options: Default value last Alias -v, /v + --save-timer-on-closing on|off|last + Saves the timer on closing. + + Required no + Default value last + Alias -sc, /sc + --prefer-24h-time on|off|last When the input used to start the timer contains a time of day that does not explicitly specify "am" or "pm", prefer interpreting the input as a @@ -351,6 +358,7 @@ Options: --sound -s normal beep --loop-sound -r off --open-saved-timers -v off + --save-timer-on-closing -sc on --prefer-24h-time -j off --window-title -i app --window-state -w normal diff --git a/Hourglass/Timing/TimerBase.cs b/Hourglass/Timing/TimerBase.cs index 504a3f9..73c6692 100644 --- a/Hourglass/Timing/TimerBase.cs +++ b/Hourglass/Timing/TimerBase.cs @@ -137,6 +137,11 @@ protected TimerBase(TimerInfo timerInfo) /// public TimerState State { get; private set; } = TimerState.Stopped; + /// + /// Gets or sets value indicating whether this timer should be saved on closing. + /// + public bool ShouldBeSaved { get; set; } = true; + /// /// Gets the that this timer was started if the is or , or null otherwise. diff --git a/Hourglass/Windows/ContextMenu.cs b/Hourglass/Windows/ContextMenu.cs index b24ec17..3113b1a 100644 --- a/Hourglass/Windows/ContextMenu.cs +++ b/Hourglass/Windows/ContextMenu.cs @@ -173,6 +173,11 @@ public sealed class ContextMenu : System.Windows.Controls.ContextMenu /// private MenuItem _openSavedTimersOnStartupMenuItem = null!; + /// + /// The "Save timer on closing" . + /// + private MenuItem _saveTimerOnClosingMenuItem = null!; + /// /// The "Display time in the digital clock format" . /// @@ -431,6 +436,9 @@ private void UpdateMenuFromOptions() // Open saved timers on startup _openSavedTimersOnStartupMenuItem.IsChecked = Settings.Default.OpenSavedTimersOnStartup; + // Save timer on closing + _saveTimerOnClosingMenuItem.IsChecked = Settings.Default.SaveTimerOnClosing; + // Prefer 24-hour time when parsing _prefer24HourTimeMenuItem.IsChecked = Settings.Default.Prefer24HourTime; @@ -536,6 +544,9 @@ private void UpdateOptionsFromMenu() // Open saved timers on startup Settings.Default.OpenSavedTimersOnStartup = _openSavedTimersOnStartupMenuItem.IsChecked; + // Save timer on closing + Settings.Default.SaveTimerOnClosing = _saveTimerOnClosingMenuItem.IsChecked; + // Prefer 24-hour time when parsing Settings.Default.Prefer24HourTime = _prefer24HourTimeMenuItem.IsChecked; @@ -923,6 +934,14 @@ private void BuildMenu() _openSavedTimersOnStartupMenuItem.Click += CheckableMenuItemClick; advancedOptionsMenuItem.Items.Add(_openSavedTimersOnStartupMenuItem); + // Save timer on closing + _saveTimerOnClosingMenuItem = new CheckableMenuItem + { + Header = Properties.Resources.ContextMenuSaveTimerOnClosingMenuItem + }; + _saveTimerOnClosingMenuItem.Click += CheckableMenuItemClick; + advancedOptionsMenuItem.Items.Add(_saveTimerOnClosingMenuItem); + // Prefer 24-hour time when parsing _prefer24HourTimeMenuItem = new CheckableMenuItem { diff --git a/Hourglass/Windows/TimerWindow.xaml.cs b/Hourglass/Windows/TimerWindow.xaml.cs index 9d5046c..cecd1fd 100644 --- a/Hourglass/Windows/TimerWindow.xaml.cs +++ b/Hourglass/Windows/TimerWindow.xaml.cs @@ -18,6 +18,8 @@ namespace Hourglass.Windows; using System.Windows.Media.Animation; using System.Windows.Shell; +using KPreisser.UI; + using Extensions; using Managers; using Properties; @@ -2078,15 +2080,22 @@ private void ConfirmClose() { BringToFrontAndActivate(); + var saveTimerOnClosingTaskDialogCheckBox = new TaskDialogCheckBox(Properties.Resources.SaveTimerTaskDialogText) + { + Checked = Settings.Default.SaveTimerOnClosing + }; + MessageBoxResult result = this.ShowTaskDialog( Properties.Resources.TimerWindowCloseTaskDialogInstruction, Properties.Resources.CloseWindowCloseTaskDialogCommand, - Properties.Resources.MinimizeWindowCloseTaskDialogCommand); + Properties.Resources.MinimizeWindowCloseTaskDialogCommand, + saveTimerOnClosingTaskDialogCheckBox); switch (result) { case MessageBoxResult.Yes: ForceClose = true; + Timer.ShouldBeSaved = saveTimerOnClosingTaskDialogCheckBox.Checked; Close(); return; case MessageBoxResult.No: diff --git a/README.md b/README.md index cdfa324..692b63a 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ ngen-Hourglass.bat uninstall - New option `--pause-after-loop-timer`, `-pl`, `/pl` - New option `--order-by-title`, `-ot`, `/ot` - Renamed option `--prompt-on-exit` to `--prompt-on-close` +- New option `--save-timer-on-closing`, `-sc`, `/sc` See [command-line usage](https://github.com/i2van/hourglass/blob/develop/Hourglass/Resources/Usage.txt) for details. @@ -105,6 +106,8 @@ See [command-line usage](https://github.com/i2van/hourglass/blob/develop/Hourgla - The `Esc` shortcut minimizes the timer window. - The `F11` shortcut makes the timer window full screen and back. - The `Ctrl`+`N` shortcut creates a new timer window. +- The `F2` shortcut edits a timer window title. +- The `F4` shortcut edits a timer window time. #### Context Menu @@ -117,6 +120,7 @@ See [command-line usage](https://github.com/i2van/hourglass/blob/develop/Hourgla - The **Advanced options** / **Show trigger time** timer window context menu option shows the trigger time in the timer window and in the notification area context menu. The command-line option is `--show-trigger-time`, `-st`, `/st` - The **Advanced options** / **Activate next window when minimized or closed** timer window context menu option enables the next timer window activation when the current timer window is minimized or closed. The command-line option is `--activate-next`, `-an`, `/an` - The **Advanced options** / **Order timers by title first then by time left** timer window context menu option orders the timers by the title first then by the time left. The command-line option is `--order-by-title`, `-ot`, `/ot` +- The **Advanced options** / **Save timer on closing** timer window context menu option enables timer window save on closing. The command-line option is `--save-timer-on-closing`, `-sc`, `/sc` - The **Pause all** timer window context menu command pauses all the running timers. Command-line command is `pause` - The **Resume all** timer window context menu command resumes all the paused timers. Command-line command is `resume` - The **Pause after each loop** timer window context menu command pauses the loop timer when it expires. Command-line command is `--pause-after-loop-timer`, `-pl`, `/pl`