├── TomatoTimerWPF ├── Resource │ ├── work_icon.png │ ├── Roboto-Black.ttf │ ├── Roboto-Regular.ttf │ ├── work_bag-512.png │ ├── work_icon_alpha.png │ ├── work_bag-32_alpha.png │ ├── work_bag-512_alpha.png │ ├── Android_JellyBean │ │ ├── 9-av-move.png │ │ ├── 9-av-pause.ico │ │ ├── 9-av-pause.png │ │ ├── 9-av-play.ico │ │ ├── 9-av-play.png │ │ ├── 9-av-replay.ico │ │ ├── 9-av-replay.png │ │ ├── 9-av-stop.png │ │ ├── 2-action-help.png │ │ ├── 5-content-edit.png │ │ ├── 9-av-full-screen.png │ │ ├── 2-action-settings.png │ │ ├── 1-navigation-cancel.png │ │ ├── 10-device-access-time.png │ │ ├── 12-hardware-gamepad.ico │ │ ├── 12-hardware-gamepad.png │ │ ├── 10-device-access-alarms.png │ │ ├── 10-device-access-volume-on.png │ │ ├── 4-collections-collection.png │ │ ├── 4-collections-go-to-today.png │ │ ├── 4-collections-view-as-list.ico │ │ ├── 4-collections-view-as-list.png │ │ ├── 10-device-access-alarms_big.png │ │ ├── 9-av-make-available-offline.png │ │ ├── 10-device-access-alarms_big_wbg.ico │ │ ├── 10-device-access-alarms_big_wbg.pdn │ │ ├── 10-device-access-alarms_big_wbg.png │ │ ├── 10-device-access-alarms_shift.png │ │ ├── 10-device-access-volume-muted.png │ │ ├── 10-device-access-alarms_big_wbg__.ico │ │ ├── 10-device-access-volume-on_white.png │ │ ├── 10-device-access-alarms_big_wbg_wbloom.ico │ │ ├── 10-device-access-alarms_big_wbg_wbloom.pdn │ │ └── 10-device-access-alarms_big_wbg_wbloom.png │ └── TomatoTimerWPF_HowToGetCalenderID.gif ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── app.manifest │ ├── Resources.Designer.cs │ └── Resources.resx ├── App.xaml ├── merged64.bat ├── RectConverter.cs ├── Extensions.cs ├── App.xaml.cs ├── TimerSettings.settings ├── App.config ├── EmbeddedAssembly.cs ├── GifImage.cs ├── MainWindow.xaml ├── Pages │ ├── Page_Buttons.xaml │ ├── UIStyleResource.xaml │ ├── Page_Buttons.xaml.cs │ ├── Page_Settings.xaml │ ├── Page_Settings.xaml.cs │ ├── Page_SoundSettings.xaml │ └── Page_SoundSettings.xaml.cs ├── TimerSettings.Designer.cs ├── TomatoTimerWPF.csproj └── MainWindow.xaml.cs ├── Packages.dgml ├── TomatoTimerWPF.sln ├── README.md └── .gitignore /TomatoTimerWPF/Resource/work_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/work_icon.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Roboto-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Roboto-Black.ttf -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Roboto-Regular.ttf -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/work_bag-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/work_bag-512.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/work_icon_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/work_icon_alpha.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/work_bag-32_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/work_bag-32_alpha.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/work_bag-512_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/work_bag-512_alpha.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/9-av-move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/9-av-move.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/9-av-pause.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/9-av-pause.ico -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/9-av-pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/9-av-pause.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/9-av-play.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/9-av-play.ico -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/9-av-play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/9-av-play.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/9-av-replay.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/9-av-replay.ico -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/9-av-replay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/9-av-replay.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/9-av-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/9-av-stop.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/2-action-help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/2-action-help.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/5-content-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/5-content-edit.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/9-av-full-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/9-av-full-screen.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/TomatoTimerWPF_HowToGetCalenderID.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/TomatoTimerWPF_HowToGetCalenderID.gif -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/2-action-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/2-action-settings.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/1-navigation-cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/1-navigation-cancel.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-time.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/12-hardware-gamepad.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/12-hardware-gamepad.ico -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/12-hardware-gamepad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/12-hardware-gamepad.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-volume-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-volume-on.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/4-collections-collection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/4-collections-collection.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/4-collections-go-to-today.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/4-collections-go-to-today.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/4-collections-view-as-list.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/4-collections-view-as-list.ico -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/4-collections-view-as-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/4-collections-view-as-list.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/9-av-make-available-offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/9-av-make-available-offline.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg.ico -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg.pdn -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_shift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_shift.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-volume-muted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-volume-muted.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg__.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg__.ico -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-volume-on_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-volume-on_white.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg_wbloom.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg_wbloom.ico -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg_wbloom.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg_wbloom.pdn -------------------------------------------------------------------------------- /TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg_wbloom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Harpseal/TomatoTimerWPF/HEAD/TomatoTimerWPF/Resource/Android_JellyBean/10-device-access-alarms_big_wbg_wbloom.png -------------------------------------------------------------------------------- /TomatoTimerWPF/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /TomatoTimerWPF/App.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TomatoTimerWPF/merged64.bat: -------------------------------------------------------------------------------- 1 | "c:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe" /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319" /lib:"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\PublicAssemblies" /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\WPF" /targetplatform:v4,c:\Windows\Microsoft.NET\Framework64\v4.0.30319 /out:./merged/TomatoTimerWPF.exe TomatoTimerWPF.exe Microsoft.WindowsAPICodePack.dll Microsoft.WindowsAPICodePack.Shell.dll 2 | -------------------------------------------------------------------------------- /Packages.dgml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18408 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace TomatoTimerWPF.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TomatoTimerWPF/RectConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows.Data; 4 | using System.Windows; 5 | 6 | namespace TomatoTimerWPF 7 | { 8 | class RectConverter : IMultiValueConverter 9 | { 10 | public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 11 | { 12 | if (values != null && values[0] != null && values[1] != null && values[2] != null) 13 | { 14 | double progressBarFillPercentage = (double)values[0]; 15 | double textBlockActualyWidth = (double)values[1]; 16 | double textBlockHeight = (double)values[2]; 17 | return new Rect(0, 0, progressBarFillPercentage / 100.0 * textBlockActualyWidth, textBlockHeight); // ProgressBarFillWidth is calculated by multiplying Fill 18 | // percentage with actual width 19 | } 20 | return new Rect(0, 0, 0, 0); // Default Zero size rectangle 21 | } 22 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Windows; 6 | using System.Windows.Media.Imaging; 7 | 8 | namespace TomatoTimerWPF 9 | { 10 | public static class Extensions 11 | { 12 | public static Visibility ToVisibility(this bool visible) 13 | { 14 | return visible ? Visibility.Visible : Visibility.Collapsed; 15 | } 16 | 17 | public static string ToFormat(this string format, params object[] args) 18 | { 19 | return string.Format(format, args); 20 | } 21 | 22 | public static T Chain(this T target, Action action) 23 | { 24 | action(target); 25 | return target; 26 | } 27 | 28 | //public static BitmapFrame GetBitmapFrame(this Icon icon) 29 | //{ 30 | // return BitmapFrame.Create(icon.GetStream()); 31 | //} 32 | 33 | //public static Stream GetStream(this Icon icon) 34 | //{ 35 | // var stream = new MemoryStream(); 36 | // icon.Save(stream); 37 | // return stream; 38 | //} 39 | 40 | public static TimeSpan Milliseconds(this int ms) 41 | { 42 | return new TimeSpan(0, 0, 0, 0, ms); 43 | } 44 | 45 | public static TimeSpan Seconds(this int seconds) 46 | { 47 | return new TimeSpan(0, 0, seconds); 48 | } 49 | 50 | public static TimeSpan Minutes(this int minutes) 51 | { 52 | return new TimeSpan(0, minutes, 0); 53 | } 54 | 55 | public static bool IsNegativeOrZero(this TimeSpan span) 56 | { 57 | return span.TotalMilliseconds <= 0; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /TomatoTimerWPF.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2013 for Windows Desktop 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TomatoTimerWPF", "TomatoTimerWPF\TomatoTimerWPF.csproj", "{C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Debug|x64.ActiveCfg = Debug|x64 21 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Debug|x64.Build.0 = Debug|x64 22 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Debug|x86.ActiveCfg = Debug|x86 23 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Debug|x86.Build.0 = Debug|x86 24 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Release|x64.ActiveCfg = Release|x64 27 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Release|x64.Build.0 = Release|x64 28 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Release|x86.ActiveCfg = Release|x86 29 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472}.Release|x86.Build.0 = Release|x86 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TomatoTimerWPF 2 | 3 | Pomodoro timer for windows 7/8(Desktop) showing countdown on taskbar by using OverlayIcon and ProgressBar of the TaskbarManager. 4 | 5 | | Work | Rest | Timeout | 6 | |:----------:|:-----------:|:------------:| 7 | | ![Work](http://lh4.ggpht.com/-Ebb5l2m-PQ8/UqaxkbX4OeI/AAAAAAAABiY/jhwk-xTy48k/s144/TomatoTimerWPF_Work_2.png) ![Work_yellow](http://lh5.ggpht.com/-cJe0Wb_L-pI/UqaxkcANnJI/AAAAAAAABiQ/VA_mW--HglI/s144/TomatoTimerWPF_Work_3.png) | ![Rest](http://lh6.ggpht.com/-BFD8ov-DFbE/UqaxkW7COlI/AAAAAAAABiU/C0NnluU-xAo/s144/TomatoTimerWPF_Rest_2.png) ![Rest_yellow](http://lh6.ggpht.com/-2yPKb3rnt98/Uqa409OIwJI/AAAAAAAABi8/vXlG-hn0GlA/s144/TomatoTimerWPF_Rest_3.png) | ![Timeout](http://lh5.ggpht.com/-Sed_sHUqJV8/UqUzJmzliEI/AAAAAAAABgw/YBt531qFHKk/s144/TomatoTimerWPF_TimeOut.png) | 8 | 9 | 10 | | Windows 7 | Windows 8 | Windows 10 | 11 | |:---------:|:---------:|:----------:| 12 | | ![Taskbar Overlay Icons Win7](http://lh5.ggpht.com/-UgXA2tdtjCI/UqUzJoSJ78I/AAAAAAAABhE/e2SVe108bNM/s320/TomatoTimerWPF_OverlayIcon.png) | ![Taskbar Overlay Icons Win8](http://lh5.ggpht.com/-Muh0tDZiLv8/Urgbj_GV5iI/AAAAAAAABjU/F032XwfAJ5w/s320/TomatoTimerWPF_OverlayIcon_win8.png)| ![Taskbar Overlay Icons Win10](https://lh3.googleusercontent.com/bVdeguJCINUwJHBbN2qoRXL2x9DA8mYiU2dYh1ErXXjxJY62EdE0A3hpn0u3PGVTIzTD3PHnp04lj_w-bVsFEQyv2YUmgWxRDybSVNlldUFu2mupwtByIGlHDHFT-dt5ifDdVqosI0RblsCKKeq__HihO2ayXyhfTP6GaoxlCpuKY1hW1WP_YmJq-WShpK3pws6kUAttXCPx1B0a_yOALzQEPAenLxPp3goQ7fSv5-RbGhMnWB029vHVf-9bnHFjIUbDZy0SCz2NJLCmoJy5N3CzzLJLGbp0ZGILUZ8UhbloB_EJwyaKT4mVa398l6MgFeKvhuh0VVyUjt66YiCwVwqwIoZyC7KQmLedVUBW46mAiO9HWOtmewY-QbxlGZWlxjbJ6RYfEgFAjSYvVi_E708sIheEmuPclbc40ES7CpzCeYMLZLAdKBr3FR41dFMXJNoFwIeGlSfEw3fe7iGpBRjbQyvqPebUQ7VLvBzDO3FcibmO29vWZcGewPCkRUIBwCouymz42p3SVYJE4AT1IDhs3yN02O_13Dit0I3q8MGJXSg6-jXu4kERsYS0aB-7qxwZXlfevx5PU0m7-1uHKr3-Op79CoxTM4JyKg58zw=w300-h142-no-tmp.png)| 13 | 14 | 15 | 16 | ## Todo 17 | ``` 18 | ``` 19 | 20 | ## Buliding Prerequisites 21 | - [Microsoft Visual Studio](https://www.visualstudio.com/) (Community version is enough) 22 | 23 | ## Dependencies 24 | - [.NET Framework 4.5](https://www.microsoft.com/zh-tw/download/details.aspx?id=30653) 25 | 26 | ## Attribution 27 | 28 | All icons and sounds used in this project are made by android team and downloaded from [deviantart](http://palhaiz.deviantart.com/art/Android-4-1-Jelly-Bean-Icon-Set-311741892). Thanks for their hard work. :) 29 | 30 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("TomatoTimer")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("TomatoTimer")] 15 | [assembly: AssemblyCopyright("Copyright © 2014")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.*")] 55 | [assembly: AssemblyFileVersion("1.0.*")] 56 | -------------------------------------------------------------------------------- /TomatoTimerWPF/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Reflection; 9 | 10 | namespace TomatoTimerWPF 11 | { 12 | /// 13 | /// Interaction logic for App.xaml 14 | /// 15 | public partial class App : Application 16 | { 17 | //Custom main method 18 | [STAThread] 19 | public static void Main() 20 | { 21 | //EmbeddedAssembly.Load("TomatoTimerWPF.Microsoft.WindowsAPICodePack.dll", "Microsoft.WindowsAPICodePack.dll"); 22 | //EmbeddedAssembly.Load("TomatoTimerWPF.Microsoft.WindowsAPICodePack.Shell.dll", "Microsoft.WindowsAPICodePack.Shell.dll"); 23 | 24 | //AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => 25 | //{ 26 | // String resourceName = "TomatoTimerWPF.Microsoft.WindowsAPICodePack.Shell.dll"; 27 | // using (var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) 28 | // { 29 | // Byte[] assemblyData = new Byte[stream.Length]; 30 | // stream.Read(assemblyData, 0, assemblyData.Length); 31 | // return System.Reflection.Assembly.Load(assemblyData); 32 | // } 33 | //}; 34 | 35 | //AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => 36 | //{ 37 | // String resourceName = "TomatoTimerWPF.Microsoft.WindowsAPICodePack.dll"; 38 | // using (var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) 39 | // { 40 | // Byte[] assemblyData = new Byte[stream.Length]; 41 | // stream.Read(assemblyData, 0, assemblyData.Length); 42 | // return System.Reflection.Assembly.Load(assemblyData); 43 | // } 44 | //}; 45 | 46 | // Create new instance of application subclass 47 | App app = new App(); 48 | 49 | // Code to register events and set properties that were 50 | // defined in XAML in the application definition 51 | app.InitializeComponent(); 52 | 53 | // Start running the application 54 | app.Run(); 55 | 56 | } 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /TomatoTimerWPF/TimerSettings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 30 7 | 8 | 9 | 35 10 | 11 | 12 | 5 13 | 14 | 15 | 15 16 | 17 | 18 | 15 19 | 20 | 21 | 20 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | True 31 | 32 | 33 | True 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 0 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | False 58 | 59 | 60 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Properties/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 54 | -------------------------------------------------------------------------------- /TomatoTimerWPF/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 30 19 | 20 | 21 | 35 22 | 23 | 24 | 5 25 | 26 | 27 | 15 28 | 29 | 30 | 15 31 | 32 | 33 | 20 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | True 43 | 44 | 45 | True 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 0 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | False 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /TomatoTimerWPF/EmbeddedAssembly.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.IO; 5 | using System.Reflection; 6 | using System.Security.Cryptography; 7 | 8 | /// 9 | /// A class for loading Embedded Assembly 10 | /// 11 | public class EmbeddedAssembly 12 | { 13 | static Dictionary dic = null; 14 | 15 | public static void Load(string embeddedResource, string fileName,bool saveToLocal = false) 16 | { 17 | if (dic == null) 18 | dic = new Dictionary(); 19 | 20 | byte[] ba = null; 21 | Assembly asm = null; 22 | Assembly curAsm = Assembly.GetExecutingAssembly(); 23 | 24 | using (Stream stm = curAsm.GetManifestResourceStream(embeddedResource)) 25 | { 26 | // Either the file is not existed or it is not mark as embedded resource 27 | if (stm == null) 28 | throw new Exception(embeddedResource + " is not found in Embedded Resources."); 29 | 30 | // Get byte[] from the file from embedded resource 31 | ba = new byte[(int)stm.Length]; 32 | stm.Read(ba, 0, (int)stm.Length); 33 | try 34 | { 35 | asm = Assembly.Load(ba); 36 | 37 | // Add the assembly/dll into dictionary 38 | dic.Add(asm.FullName, asm); 39 | return; 40 | } 41 | catch 42 | { 43 | // Purposely do nothing 44 | // Unmanaged dll or assembly cannot be loaded directly from byte[] 45 | // Let the process fall through for next part 46 | } 47 | } 48 | 49 | bool fileOk = false; 50 | string tempFile = ""; 51 | 52 | using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) 53 | { 54 | string fileHash = BitConverter.ToString(sha1.ComputeHash(ba)).Replace("-", string.Empty); ; 55 | 56 | tempFile = Path.GetTempPath() + fileName; 57 | 58 | if (File.Exists(tempFile)) 59 | { 60 | byte[] bb = File.ReadAllBytes(tempFile); 61 | string fileHash2 = BitConverter.ToString(sha1.ComputeHash(bb)).Replace("-", string.Empty); 62 | 63 | if (fileHash == fileHash2) 64 | { 65 | fileOk = true; 66 | } 67 | else 68 | { 69 | fileOk = false; 70 | } 71 | } 72 | else 73 | { 74 | fileOk = false; 75 | } 76 | } 77 | 78 | if (!fileOk) 79 | { 80 | System.IO.File.WriteAllBytes(tempFile, ba); 81 | } 82 | 83 | asm = Assembly.LoadFile(tempFile); 84 | 85 | dic.Add(asm.FullName, asm); 86 | } 87 | 88 | public static Assembly Get(string assemblyFullName) 89 | { 90 | if (dic == null || dic.Count == 0) 91 | return null; 92 | 93 | if (dic.ContainsKey(assemblyFullName)) 94 | return dic[assemblyFullName]; 95 | 96 | return null; 97 | } 98 | } 99 | 100 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | # [Rr]elease/ 13 | x64/ 14 | build/ 15 | bld/ 16 | [Bb]in/ 17 | [Oo]bj/ 18 | 19 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 20 | !packages/*/build/ 21 | 22 | # MSTest test Results 23 | [Tt]est[Rr]esult*/ 24 | [Bb]uild[Ll]og.* 25 | 26 | #NUNIT 27 | *.VisualState.xml 28 | TestResult.xml 29 | 30 | *_i.c 31 | *_p.c 32 | *_i.h 33 | *.ilk 34 | *.meta 35 | *.obj 36 | *.pch 37 | *.pdb 38 | *.pgc 39 | *.pgd 40 | *.rsp 41 | *.sbr 42 | *.tlb 43 | *.tli 44 | *.tlh 45 | *.tmp 46 | *.tmp_proj 47 | *.log 48 | *.vspscc 49 | *.vssscc 50 | .builds 51 | *.pidb 52 | *.svclog 53 | *.scc 54 | 55 | # Chutzpah Test files 56 | _Chutzpah* 57 | 58 | # Visual C++ cache files 59 | ipch/ 60 | *.aps 61 | *.ncb 62 | *.opensdf 63 | *.sdf 64 | *.cachefile 65 | 66 | # Visual Studio profiler 67 | *.psess 68 | *.vsp 69 | *.vspx 70 | 71 | # TFS 2012 Local Workspace 72 | $tf/ 73 | 74 | # Guidance Automation Toolkit 75 | *.gpState 76 | 77 | # ReSharper is a .NET coding add-in 78 | _ReSharper*/ 79 | *.[Rr]e[Ss]harper 80 | *.DotSettings.user 81 | 82 | # JustCode is a .NET coding addin-in 83 | .JustCode 84 | 85 | # TeamCity is a build add-in 86 | _TeamCity* 87 | 88 | # DotCover is a Code Coverage Tool 89 | *.dotCover 90 | 91 | # NCrunch 92 | *.ncrunch* 93 | _NCrunch_* 94 | .*crunch*.local.xml 95 | 96 | # MightyMoose 97 | *.mm.* 98 | AutoTest.Net/ 99 | 100 | # Installshield output folder 101 | [Ee]xpress/ 102 | 103 | # DocProject is a documentation generator add-in 104 | DocProject/buildhelp/ 105 | DocProject/Help/*.HxT 106 | DocProject/Help/*.HxC 107 | DocProject/Help/*.hhc 108 | DocProject/Help/*.hhk 109 | DocProject/Help/*.hhp 110 | DocProject/Help/Html2 111 | DocProject/Help/html 112 | 113 | # Click-Once directory 114 | publish/ 115 | 116 | # Publish Web Output 117 | *.Publish.xml 118 | *.azurePubxml 119 | 120 | # NuGet Packages Directory 121 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 122 | #packages/ 123 | ## TODO: If the tool you use requires repositories.config, also uncomment the next line 124 | #!packages/repositories.config 125 | 126 | # Windows Azure Build Output 127 | csx/ 128 | *.build.csdef 129 | 130 | # Windows Store app package directory 131 | AppPackages/ 132 | 133 | # Others 134 | gif/ 135 | sql/ 136 | *.Cache 137 | ClientBin/ 138 | [Ss]tyle[Cc]op.* 139 | ~$* 140 | *~ 141 | *.dbmdl 142 | *.dbproj.schemaview 143 | *.[Pp]ublish.xml 144 | *.pfx 145 | *.publishsettings 146 | 147 | # RIA/Silverlight projects 148 | Generated_Code/ 149 | 150 | # Backup & report files from converting an old project file to a newer 151 | # Visual Studio version. Backup files are not needed, because we have git ;-) 152 | _UpgradeReport_Files/ 153 | Backup*/ 154 | UpgradeLog*.XML 155 | UpgradeLog*.htm 156 | 157 | # SQL Server files 158 | App_Data/*.mdf 159 | App_Data/*.ldf 160 | 161 | # Business Intelligence projects 162 | *.rdl.data 163 | *.bim.layout 164 | *.bim_*.settings 165 | 166 | # Microsoft Fakes 167 | FakesAssemblies/ 168 | 169 | # ========================= 170 | # Windows detritus 171 | # ========================= 172 | 173 | # Windows image file caches 174 | Thumbs.db 175 | ehthumbs.db 176 | 177 | # Folder config file 178 | Desktop.ini 179 | 180 | # Recycle Bin used on file shares 181 | $RECYCLE.BIN/ 182 | -------------------------------------------------------------------------------- /TomatoTimerWPF/GifImage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | using System.Windows.Media.Animation; 5 | using System.Windows.Media.Imaging; 6 | 7 | namespace TomatoTimerWPF 8 | { 9 | internal class GifImage : Image 10 | { 11 | public static readonly DependencyProperty FrameIndexProperty = 12 | DependencyProperty.Register( 13 | "FrameIndex", 14 | typeof(int), 15 | typeof(GifImage), 16 | new UIPropertyMetadata(0, FrameIndexChanged)); 17 | 18 | public static readonly DependencyProperty AutoStartProperty = 19 | DependencyProperty.Register( 20 | "AutoStart", 21 | typeof(bool), 22 | typeof(GifImage), 23 | new UIPropertyMetadata(true, AutoStartChanged)); 24 | 25 | public static readonly DependencyProperty GifSourceProperty = 26 | DependencyProperty.Register( 27 | "GifSource", 28 | typeof(string), 29 | typeof(GifImage), 30 | new UIPropertyMetadata(string.Empty, GifSourceChanged)); 31 | 32 | public static readonly DependencyProperty DurationPerFrameProperty = 33 | DependencyProperty.Register( 34 | "DurationPerFrameMS", 35 | typeof(int), 36 | typeof(GifImage), 37 | new UIPropertyMetadata(100, null)); 38 | 39 | private Int32Animation animation; 40 | private GifBitmapDecoder decoder; 41 | private bool isInitialized; 42 | 43 | static GifImage() 44 | { 45 | VisibilityProperty.OverrideMetadata( 46 | typeof(GifImage), 47 | new FrameworkPropertyMetadata(VisibilityChanged)); 48 | } 49 | 50 | public int FrameIndex 51 | { 52 | get { return (int)GetValue(FrameIndexProperty); } 53 | set { SetValue(FrameIndexProperty, value); } 54 | } 55 | 56 | public bool AutoStart 57 | { 58 | get { return (bool)GetValue(AutoStartProperty); } 59 | set { SetValue(AutoStartProperty, value); } 60 | } 61 | 62 | public string GifSource 63 | { 64 | get { return (string)GetValue(GifSourceProperty); } 65 | set { SetValue(GifSourceProperty, value); } 66 | } 67 | 68 | public int DurationPerFrameMS 69 | { 70 | get { return (int)GetValue(DurationPerFrameProperty); } 71 | set { SetValue(DurationPerFrameProperty, value); } 72 | } 73 | 74 | private void Initialize() 75 | { 76 | decoder = new GifBitmapDecoder( 77 | new Uri("pack://application:,,," + GifSource), 78 | BitmapCreateOptions.PreservePixelFormat, 79 | BitmapCacheOption.Default); 80 | int frameCount = decoder.Frames.Count; 81 | animation = new Int32Animation( 82 | 0, 83 | decoder.Frames.Count - 1, 84 | new Duration(new TimeSpan(0, 0, 0, 0, frameCount * 1000))) 85 | {RepeatBehavior = RepeatBehavior.Forever}; 86 | Source = decoder.Frames[0]; 87 | isInitialized = true; 88 | if (AutoStart && Visibility == Visibility.Visible) 89 | { 90 | StartAnimation(); 91 | } 92 | } 93 | 94 | private static void VisibilityChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 95 | { 96 | GifImage gifImage = sender as GifImage; 97 | if (gifImage == null) 98 | { 99 | return; 100 | } 101 | if ((Visibility)e.NewValue == Visibility.Visible) 102 | { 103 | gifImage.StartAnimation(); 104 | } 105 | else 106 | { 107 | gifImage.StopAnimation(); 108 | } 109 | } 110 | 111 | private static void FrameIndexChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 112 | { 113 | var gifImage = sender as GifImage; 114 | if (gifImage != null) 115 | { 116 | gifImage.Source = gifImage.decoder.Frames[(int)e.NewValue]; 117 | } 118 | } 119 | 120 | private static void AutoStartChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 121 | { 122 | if ((bool)e.NewValue) 123 | ((GifImage)sender).StartAnimation(); 124 | } 125 | 126 | private static void GifSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 127 | { 128 | ((GifImage)sender).Initialize(); 129 | } 130 | 131 | public void StartAnimation() 132 | { 133 | if (!isInitialized) 134 | Initialize(); 135 | BeginAnimation(FrameIndexProperty, animation); 136 | } 137 | 138 | public void StopAnimation() 139 | { 140 | BeginAnimation(FrameIndexProperty, null); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18408 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace TomatoTimerWPF.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TomatoTimerWPF.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 65 | /// 66 | internal static System.Drawing.Icon _12_hardware_gamepad { 67 | get { 68 | object obj = ResourceManager.GetObject("_12_hardware_gamepad", resourceCulture); 69 | return ((System.Drawing.Icon)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 75 | /// 76 | internal static System.Drawing.Icon _4_collections_view_as_list { 77 | get { 78 | object obj = ResourceManager.GetObject("_4_collections_view_as_list", resourceCulture); 79 | return ((System.Drawing.Icon)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 85 | /// 86 | internal static System.Drawing.Icon _9_av_pause { 87 | get { 88 | object obj = ResourceManager.GetObject("_9_av_pause", resourceCulture); 89 | return ((System.Drawing.Icon)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 95 | /// 96 | internal static System.Drawing.Icon _9_av_play { 97 | get { 98 | object obj = ResourceManager.GetObject("_9_av_play", resourceCulture); 99 | return ((System.Drawing.Icon)(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 105 | /// 106 | internal static System.Drawing.Icon _9_av_replay { 107 | get { 108 | object obj = ResourceManager.GetObject("_9_av_replay", resourceCulture); 109 | return ((System.Drawing.Icon)(obj)); 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /TomatoTimerWPF/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 18 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 44 | 45 | 46 | 47 | 48 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Pages/Page_Buttons.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 42 | 44 | 45 | 75 | 76 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Pages/UIStyleResource.xaml: -------------------------------------------------------------------------------- 1 | 4 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 119 | 120 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resource\Android_JellyBean\12-hardware-gamepad.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resource\Android_JellyBean\4-collections-view-as-list.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Resource\Android_JellyBean\9-av-pause.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Resource\Android_JellyBean\9-av-play.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | 134 | ..\Resource\Android_JellyBean\9-av-replay.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 135 | 136 | -------------------------------------------------------------------------------- /TomatoTimerWPF/TimerSettings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace TomatoTimerWPF { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")] 16 | internal sealed partial class TimerSettings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static TimerSettings defaultInstance = ((TimerSettings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new TimerSettings()))); 19 | 20 | public static TimerSettings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("30")] 29 | public int Work_Time { 30 | get { 31 | return ((int)(this["Work_Time"])); 32 | } 33 | set { 34 | this["Work_Time"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("35")] 41 | public int WorkTime_Uesr { 42 | get { 43 | return ((int)(this["WorkTime_Uesr"])); 44 | } 45 | set { 46 | this["WorkTime_Uesr"] = value; 47 | } 48 | } 49 | 50 | [global::System.Configuration.UserScopedSettingAttribute()] 51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 52 | [global::System.Configuration.DefaultSettingValueAttribute("5")] 53 | public int Relax_Time { 54 | get { 55 | return ((int)(this["Relax_Time"])); 56 | } 57 | set { 58 | this["Relax_Time"] = value; 59 | } 60 | } 61 | 62 | [global::System.Configuration.UserScopedSettingAttribute()] 63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 64 | [global::System.Configuration.DefaultSettingValueAttribute("15")] 65 | public int RelaxTime_Uesr { 66 | get { 67 | return ((int)(this["RelaxTime_Uesr"])); 68 | } 69 | set { 70 | this["RelaxTime_Uesr"] = value; 71 | } 72 | } 73 | 74 | [global::System.Configuration.UserScopedSettingAttribute()] 75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 76 | [global::System.Configuration.DefaultSettingValueAttribute("15")] 77 | public int Relax_Time_Long { 78 | get { 79 | return ((int)(this["Relax_Time_Long"])); 80 | } 81 | set { 82 | this["Relax_Time_Long"] = value; 83 | } 84 | } 85 | 86 | [global::System.Configuration.UserScopedSettingAttribute()] 87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 88 | [global::System.Configuration.DefaultSettingValueAttribute("20")] 89 | public int Relax_Time_Long_User { 90 | get { 91 | return ((int)(this["Relax_Time_Long_User"])); 92 | } 93 | set { 94 | this["Relax_Time_Long_User"] = value; 95 | } 96 | } 97 | 98 | [global::System.Configuration.UserScopedSettingAttribute()] 99 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 100 | [global::System.Configuration.DefaultSettingValueAttribute("")] 101 | public string GoogleCal_src { 102 | get { 103 | return ((string)(this["GoogleCal_src"])); 104 | } 105 | set { 106 | this["GoogleCal_src"] = value; 107 | } 108 | } 109 | 110 | [global::System.Configuration.UserScopedSettingAttribute()] 111 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 112 | [global::System.Configuration.DefaultSettingValueAttribute("")] 113 | public string GoogleCal_text { 114 | get { 115 | return ((string)(this["GoogleCal_text"])); 116 | } 117 | set { 118 | this["GoogleCal_text"] = value; 119 | } 120 | } 121 | 122 | [global::System.Configuration.UserScopedSettingAttribute()] 123 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 124 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 125 | public bool GoogleCal_EnableEvent { 126 | get { 127 | return ((bool)(this["GoogleCal_EnableEvent"])); 128 | } 129 | set { 130 | this["GoogleCal_EnableEvent"] = value; 131 | } 132 | } 133 | 134 | [global::System.Configuration.UserScopedSettingAttribute()] 135 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 136 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 137 | public bool AlwaysOnTop { 138 | get { 139 | return ((bool)(this["AlwaysOnTop"])); 140 | } 141 | set { 142 | this["AlwaysOnTop"] = value; 143 | } 144 | } 145 | 146 | [global::System.Configuration.UserScopedSettingAttribute()] 147 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 148 | [global::System.Configuration.DefaultSettingValueAttribute("")] 149 | public string WindowRestoreBounds { 150 | get { 151 | return ((string)(this["WindowRestoreBounds"])); 152 | } 153 | set { 154 | this["WindowRestoreBounds"] = value; 155 | } 156 | } 157 | 158 | [global::System.Configuration.UserScopedSettingAttribute()] 159 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 160 | [global::System.Configuration.DefaultSettingValueAttribute("")] 161 | public string TimerRestoreDateTime { 162 | get { 163 | return ((string)(this["TimerRestoreDateTime"])); 164 | } 165 | set { 166 | this["TimerRestoreDateTime"] = value; 167 | } 168 | } 169 | 170 | [global::System.Configuration.UserScopedSettingAttribute()] 171 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 172 | [global::System.Configuration.DefaultSettingValueAttribute("0")] 173 | public int TimerRestoreMode { 174 | get { 175 | return ((int)(this["TimerRestoreMode"])); 176 | } 177 | set { 178 | this["TimerRestoreMode"] = value; 179 | } 180 | } 181 | 182 | [global::System.Configuration.UserScopedSettingAttribute()] 183 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 184 | [global::System.Configuration.DefaultSettingValueAttribute("")] 185 | public string SoundPathTimeOutRest { 186 | get { 187 | return ((string)(this["SoundPathTimeOutRest"])); 188 | } 189 | set { 190 | this["SoundPathTimeOutRest"] = value; 191 | } 192 | } 193 | 194 | [global::System.Configuration.UserScopedSettingAttribute()] 195 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 196 | [global::System.Configuration.DefaultSettingValueAttribute("")] 197 | public string SoundPathTimeOutWork { 198 | get { 199 | return ((string)(this["SoundPathTimeOutWork"])); 200 | } 201 | set { 202 | this["SoundPathTimeOutWork"] = value; 203 | } 204 | } 205 | 206 | [global::System.Configuration.UserScopedSettingAttribute()] 207 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 208 | [global::System.Configuration.DefaultSettingValueAttribute("")] 209 | public string SoundPathPause { 210 | get { 211 | return ((string)(this["SoundPathPause"])); 212 | } 213 | set { 214 | this["SoundPathPause"] = value; 215 | } 216 | } 217 | 218 | [global::System.Configuration.UserScopedSettingAttribute()] 219 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 220 | [global::System.Configuration.DefaultSettingValueAttribute("")] 221 | public string SoundPathResume { 222 | get { 223 | return ((string)(this["SoundPathResume"])); 224 | } 225 | set { 226 | this["SoundPathResume"] = value; 227 | } 228 | } 229 | 230 | [global::System.Configuration.UserScopedSettingAttribute()] 231 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 232 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 233 | public bool GoogleCal_CopyToClipboard { 234 | get { 235 | return ((bool)(this["GoogleCal_CopyToClipboard"])); 236 | } 237 | set { 238 | this["GoogleCal_CopyToClipboard"] = value; 239 | } 240 | } 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Pages/Page_Buttons.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | using System.Windows.Media.Animation; 17 | using System.Windows.Interop; 18 | using System.Runtime.InteropServices; 19 | 20 | namespace TomatoTimerWPF 21 | { 22 | /// 23 | /// Interaction logic for Page_Buttons.xaml 24 | /// 25 | public partial class Page_Buttons : UserControl 26 | { 27 | 28 | [StructLayout(LayoutKind.Sequential)] 29 | public struct RECT 30 | { 31 | public int Left; 32 | public int Top; 33 | public int Right; 34 | public int Bottom; 35 | } 36 | 37 | [DllImport("user32.dll")] 38 | [return: MarshalAs(UnmanagedType.Bool)] 39 | public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); 40 | 41 | // Make sure RECT is actually OUR defined struct, not the windows rect. 42 | public static RECT GetWindowRectangle(Window window) 43 | { 44 | RECT rect; 45 | GetWindowRect((new WindowInteropHelper(window)).Handle, out rect); 46 | 47 | return rect; 48 | } 49 | 50 | private System.Windows.Point m_MousePosition; 51 | public DateTime m_MouseDownTime; 52 | public bool m_bIsMouseDown = false; 53 | 54 | private MainWindow m_window; 55 | public void SetMainWindow(MainWindow window) 56 | { 57 | m_window = window; 58 | } 59 | 60 | Storyboard m_sbAniOut; 61 | Storyboard m_sbAniIn; 62 | 63 | public Page_Buttons(MainWindow window) 64 | { 65 | InitializeComponent(); 66 | 67 | m_window = window; 68 | 69 | m_MousePosition.X = m_MousePosition.Y = 0; 70 | 71 | spButtonStackPanel.Opacity = 0; 72 | btnGotoSetting.Opacity = 0; 73 | 74 | labelTime_small.Opacity = 0; 75 | grLabelGrid.Opacity = 1; 76 | 77 | 78 | m_sbAniOut = new Storyboard(); 79 | DoubleAnimation daFadeOut = new DoubleAnimation(); 80 | daFadeOut.Duration = 200.Milliseconds(); 81 | daFadeOut.To = 0.0; 82 | 83 | m_sbAniOut.Children.Add(daFadeOut); 84 | Storyboard.SetTargetProperty(daFadeOut, new PropertyPath(UIElement.OpacityProperty)); 85 | 86 | m_sbAniIn = new Storyboard(); 87 | DoubleAnimation daFadeIn = new DoubleAnimation(); 88 | daFadeIn.Duration = 200.Milliseconds(); 89 | daFadeIn.From = 0.0; 90 | daFadeIn.To = 1.0; 91 | 92 | m_sbAniIn.Children.Add(daFadeIn); 93 | Storyboard.SetTargetProperty(daFadeIn, new PropertyPath(UIElement.OpacityProperty)); 94 | 95 | 96 | Version win8version = new Version(6, 2, 9200, 0); 97 | 98 | if (Environment.OSVersion.Platform == PlatformID.Win32NT && 99 | Environment.OSVersion.Version >= win8version) 100 | { 101 | labelTimeWhite.Visibility = Visibility.Visible; 102 | } 103 | else 104 | labelTimeWhite.Visibility = Visibility.Hidden; 105 | 106 | //labelTimeWhite.Visibility = Visibility.Visible; 107 | 108 | 109 | m_MouseDownTime = DateTime.Now; 110 | } 111 | 112 | #region ISwitchable Members 113 | //public void UtilizeState(object state) 114 | //{ 115 | // throw new NotImplementedException(); 116 | //} 117 | 118 | private void Button_GotoSettings_Click(object sender, System.Windows.RoutedEventArgs e) 119 | { 120 | //Switcher.Switch(new Page_Settings()); 121 | m_window.SwitchToSettings(); 122 | //m_window.SwitchToSoundSettings(); 123 | } 124 | #endregion 125 | 126 | private void Button_Close_Click(object sender, System.Windows.RoutedEventArgs e) 127 | { 128 | m_window.SavePropertiesAndClose(true); 129 | } 130 | 131 | private void OnButtonMove_MouseDown_1(object sender, MouseButtonEventArgs e) 132 | { 133 | Control uiCur = (sender as Control); 134 | if (uiCur == null) return; 135 | m_MousePosition = e.GetPosition(uiCur); 136 | m_MouseDownTime = DateTime.Now; 137 | m_bIsMouseDown = true; 138 | 139 | if (m_window.WindowState == WindowState.Maximized) 140 | { 141 | double borderWidth; 142 | double borderHeight; 143 | 144 | //The real border size is 7 in my windows 7, but ResizeFrameVerticalBorderWidth is 4 ??? 145 | //borderWidth = SystemParameters.ResizeFrameVerticalBorderWidth; 146 | //borderHeight = SystemParameters.ResizeFrameHorizontalBorderHeight; 147 | 148 | //use window api to get the real border size. 149 | var rectWindow = GetWindowRectangle(m_window); 150 | Point ptClient = m_window.PointToScreen(new Point(0, 0)); 151 | borderWidth = ptClient.X - rectWindow.Left; 152 | borderHeight = ptClient.Y - rectWindow.Top; 153 | 154 | m_window.WindowState = WindowState.Normal; 155 | 156 | System.Drawing.Point pointMouse = System.Windows.Forms.Control.MousePosition; 157 | Point relativePoint = uiCur.TransformToAncestor(m_window) 158 | .Transform(m_MousePosition); 159 | m_window.Left = (double)pointMouse.X - relativePoint.X - borderWidth; 160 | m_window.Top = (double)pointMouse.Y - relativePoint.Y - borderHeight; 161 | } 162 | } 163 | 164 | private void OnButtonMove_MouseMove_1(object sender, MouseEventArgs e) 165 | { 166 | 167 | //MessageBox.Show("MM"); 168 | //SystemParameters.MinimumHorizontalDragDistance 169 | Control uiCur = (sender as Control); 170 | if (uiCur == null) return; 171 | double minDragDis = Math.Min(Math.Min(uiCur.ActualWidth, uiCur.ActualHeight) * 0.25,15); 172 | var currentPoint = e.GetPosition(uiCur); 173 | 174 | if (e.LeftButton == MouseButtonState.Pressed 175 | && 176 | //uiCur.IsMouseCaptured && 177 | (Math.Abs(currentPoint.X - m_MousePosition.X) > minDragDis || 178 | Math.Abs(currentPoint.Y - m_MousePosition.Y) > minDragDis)) 179 | { 180 | // Prevent Click from firing 181 | uiCur.ReleaseMouseCapture(); 182 | //if (m_window.ResizeMode != System.Windows.ResizeMode.NoResize) 183 | //{ 184 | // m_window.ResizeMode = System.Windows.ResizeMode.NoResize; 185 | // m_window.UpdateLayout(); 186 | //} 187 | m_bIsMouseDown = false; 188 | 189 | try 190 | { 191 | m_window.DragMove(); 192 | } 193 | catch (System.InvalidOperationException) 194 | { 195 | 196 | } 197 | //Rect bounds = m_window.RestoreBounds; 198 | //Rect bounds = MainWindow.CheckBounds(m_window.RestoreBounds); 199 | //m_window.Top = bounds.Top; 200 | //m_window.Left = bounds.Left; 201 | //m_window.Width = bounds.Width; 202 | //m_window.Height = bounds.Height; 203 | 204 | 205 | } 206 | 207 | 208 | 209 | } 210 | 211 | private void Grid_MouseEnter_1(object sender, MouseEventArgs e) 212 | { 213 | //btnGotoSetting.Opacity = 1; 214 | //spWindowControlStackPanel.Opacity = 1; 215 | //spButtonStackPanel.Opacity = 1; 216 | //labelTime_small.Opacity = 1; 217 | //grLabelGrid.Opacity = 0; 218 | m_sbAniIn.Begin(btnGotoSetting); 219 | //m_sbAniIn.Begin(m_window.btnAlwaysOnTop);//m_sbAniIn.Begin(m_window.spWindowControlStackPanel); 220 | m_sbAniIn.Begin(spButtonStackPanel); 221 | m_sbAniIn.Begin(labelTime_small); 222 | m_sbAniOut.Begin(grLabelGrid); 223 | } 224 | 225 | private void Grid_MouseLeave_1(object sender, MouseEventArgs e) 226 | { 227 | m_sbAniOut.Begin(btnGotoSetting); 228 | //m_sbAniOut.Begin(m_window.btnAlwaysOnTop);// m_sbAniOut.Begin(m_window.spWindowControlStackPanel); 229 | m_sbAniOut.Begin(spButtonStackPanel); 230 | m_sbAniOut.Begin(labelTime_small); 231 | m_sbAniIn.Begin(grLabelGrid); 232 | 233 | //btnGotoSetting.Opacity = 0; 234 | //spWindowControlStackPanel.Opacity = 0; 235 | //spButtonStackPanel.Opacity = 0; 236 | //labelTime_small.Opacity = 0; 237 | //grLabelGrid.Opacity = 1; 238 | } 239 | 240 | private void Button_GotoWork_Click(object sender, System.Windows.RoutedEventArgs e) 241 | { 242 | //Switcher.GetBaseWindow().StartWork(); 243 | m_window.StartWork(); 244 | } 245 | 246 | private void Button_GotoRelax_Click(object sender, System.Windows.RoutedEventArgs e) 247 | { 248 | //Switcher.GetBaseWindow().StartRelax(); 249 | m_window.StartRelax(); 250 | m_bIsMouseDown = false; 251 | //TimeSpan downTime = DateTime.Now - m_MouseDownTime; 252 | //MessageBox.Show(downTime.ToString()); 253 | } 254 | 255 | private void Button_Pause_Click(object sender, System.Windows.RoutedEventArgs e) 256 | { 257 | 258 | m_window.Pause(); 259 | } 260 | 261 | private void Button_Resume_Click(object sender, System.Windows.RoutedEventArgs e) 262 | { 263 | m_window.Resume(); 264 | } 265 | 266 | private void Button_Reset_Click(object sender, System.Windows.RoutedEventArgs e) 267 | { 268 | m_window.Reset(); 269 | } 270 | 271 | private void Button_PreviewMouseDownTime(object sender, MouseButtonEventArgs e) 272 | { 273 | m_MouseDownTime = DateTime.Now; 274 | m_bIsMouseDown = true; 275 | } 276 | 277 | private void Button_MouseLeaveDownTime(object sender, MouseEventArgs e) 278 | { 279 | m_bIsMouseDown = false; 280 | //if (m_window.ResizeMode == System.Windows.ResizeMode.NoResize) 281 | //{ 282 | // // restore resize grips 283 | // m_window.ResizeMode = System.Windows.ResizeMode.CanResize; 284 | // m_window.UpdateLayout(); 285 | //} 286 | } 287 | 288 | 289 | public double GetLongMouseDownPercentage() 290 | { 291 | if (!m_bIsMouseDown) return 0; 292 | TimeSpan timeDown = DateTime.Now - m_MouseDownTime; 293 | double percentage = timeDown.TotalSeconds / 2.0 * 100; 294 | if (percentage > 100) percentage = 100; 295 | return percentage; 296 | } 297 | 298 | public bool GetIsMouseDown() 299 | { 300 | return m_bIsMouseDown; 301 | } 302 | 303 | public bool GetIsLongMouseDown() 304 | { 305 | return m_bIsMouseDown && !(DateTime.Now - m_MouseDownTime - 2.Seconds()).IsNegativeOrZero(); 306 | } 307 | 308 | 309 | } 310 | 311 | 312 | } 313 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Pages/Page_Settings.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 134 | 137 | 138 | 139 | 161 | 162 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Pages/Page_Settings.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | using System.Text.RegularExpressions; 17 | 18 | namespace TomatoTimerWPF 19 | { 20 | /// 21 | /// Interaction logic for Page_Settings.xaml 22 | /// 23 | public partial class Page_Settings : UserControl 24 | { 25 | private bool m_bVersionMode; 26 | private MainWindow m_window; 27 | public void SetMainWindow(MainWindow window) 28 | { 29 | m_window = window; 30 | } 31 | 32 | public Page_Settings(MainWindow window) 33 | { 34 | InitializeComponent(); 35 | 36 | m_bVersionMode = true; 37 | labelVersion_small.Content = "Version: " + System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString(); 38 | 39 | m_window = window; 40 | SyncSettingsToUIValue(); 41 | cbRelaxTimeComboBox.SelectionChanged += ComboBox_SelectionChanged; 42 | cbWorkTimeComboBox.SelectionChanged += ComboBox_SelectionChanged; 43 | cbLongRelaxTimeComboBox.SelectionChanged += ComboBox_SelectionChanged; 44 | } 45 | 46 | #region ISwitchable Members 47 | public void UtilizeState(object state) 48 | { 49 | throw new NotImplementedException(); 50 | } 51 | 52 | private void Button_GotoButtons_Click(object sender, System.Windows.RoutedEventArgs e) 53 | { 54 | SyncUIValueToSettings(); 55 | m_window.SwitchToButtons(); 56 | //Switcher.Switch(new Page_Buttons()); 57 | 58 | } 59 | #endregion 60 | 61 | private void SyncSettingsToUIValue() 62 | { 63 | TextBox tbox; 64 | 65 | tbox = cbWorkTimeComboBox.Items[2] as TextBox; 66 | if (tbox != null) 67 | tbox.Text = "" + TomatoTimerWPF.TimerSettings.Default.WorkTime_Uesr; 68 | 69 | tbox = cbRelaxTimeComboBox.Items[2] as TextBox; 70 | if (tbox != null) 71 | tbox.Text = "" + TomatoTimerWPF.TimerSettings.Default.RelaxTime_Uesr; 72 | 73 | tbox = cbLongRelaxTimeComboBox.Items[2] as TextBox; 74 | if (tbox != null) 75 | tbox.Text = "" + TomatoTimerWPF.TimerSettings.Default.Relax_Time_Long_User; 76 | 77 | 78 | if (TomatoTimerWPF.TimerSettings.Default.Work_Time == 30) 79 | cbWorkTimeComboBox.SelectedIndex = 0; 80 | else if (TomatoTimerWPF.TimerSettings.Default.Work_Time == 25) 81 | cbWorkTimeComboBox.SelectedIndex = 1; 82 | else 83 | { 84 | cbWorkTimeComboBox.SelectedIndex = 2; 85 | tbox = cbWorkTimeComboBox.Items[2] as TextBox; 86 | if (tbox != null) 87 | { 88 | tbox.Text = "" + TomatoTimerWPF.TimerSettings.Default.Work_Time; 89 | } 90 | } 91 | 92 | if (TomatoTimerWPF.TimerSettings.Default.Relax_Time == 10) 93 | cbRelaxTimeComboBox.SelectedIndex = 0; 94 | else if (TomatoTimerWPF.TimerSettings.Default.Relax_Time == 5) 95 | cbRelaxTimeComboBox.SelectedIndex = 1; 96 | else 97 | { 98 | cbRelaxTimeComboBox.SelectedIndex = 2; 99 | tbox = cbRelaxTimeComboBox.Items[2] as TextBox; 100 | if (tbox != null) 101 | { 102 | tbox.Text = "" + TomatoTimerWPF.TimerSettings.Default.Relax_Time; 103 | } 104 | } 105 | 106 | if (TomatoTimerWPF.TimerSettings.Default.Relax_Time_Long == 30) 107 | cbLongRelaxTimeComboBox.SelectedIndex = 0; 108 | else if (TomatoTimerWPF.TimerSettings.Default.Relax_Time_Long == 15) 109 | cbLongRelaxTimeComboBox.SelectedIndex = 1; 110 | else 111 | { 112 | cbLongRelaxTimeComboBox.SelectedIndex = 2; 113 | tbox = cbLongRelaxTimeComboBox.Items[2] as TextBox; 114 | if (tbox != null) 115 | { 116 | tbox.Text = "" + TomatoTimerWPF.TimerSettings.Default.Relax_Time_Long; 117 | } 118 | } 119 | 120 | tbGoogleCal_src.Text = TomatoTimerWPF.TimerSettings.Default.GoogleCal_src; 121 | tbGoogleCal_text.Text = TomatoTimerWPF.TimerSettings.Default.GoogleCal_text; 122 | cbEnableGCal.IsChecked = TomatoTimerWPF.TimerSettings.Default.GoogleCal_EnableEvent; 123 | 124 | if (cbEnableGCal.IsChecked == true) 125 | { 126 | spGoogleEventTitle.IsEnabled = true; 127 | spGoogleID.IsEnabled = true; 128 | menuTestGoogleCal.IsEnabled = true; 129 | } 130 | else 131 | { 132 | spGoogleEventTitle.IsEnabled = false; 133 | spGoogleID.IsEnabled = false; 134 | menuTestGoogleCal.IsEnabled = false; 135 | } 136 | } 137 | 138 | private void SyncUIValueToSettings() 139 | { 140 | TextBox tbox; 141 | if (cbRelaxTimeComboBox.SelectedIndex == 0) 142 | TomatoTimerWPF.TimerSettings.Default.Relax_Time = 10; 143 | else if (cbRelaxTimeComboBox.SelectedIndex == 1) 144 | TomatoTimerWPF.TimerSettings.Default.Relax_Time = 5; 145 | else 146 | { 147 | tbox = cbRelaxTimeComboBox.Items[2] as TextBox; 148 | if (tbox != null) 149 | { 150 | TomatoTimerWPF.TimerSettings.Default.Relax_Time = Int32.Parse(tbox.Text); 151 | } 152 | } 153 | 154 | 155 | if (cbLongRelaxTimeComboBox.SelectedIndex == 0) 156 | TomatoTimerWPF.TimerSettings.Default.Relax_Time_Long = 30; 157 | else if (cbLongRelaxTimeComboBox.SelectedIndex == 1) 158 | TomatoTimerWPF.TimerSettings.Default.Relax_Time_Long = 15; 159 | else 160 | { 161 | tbox = cbLongRelaxTimeComboBox.Items[2] as TextBox; 162 | if (tbox != null) 163 | { 164 | TomatoTimerWPF.TimerSettings.Default.Relax_Time_Long = Int32.Parse(tbox.Text); 165 | } 166 | } 167 | 168 | if (cbWorkTimeComboBox.SelectedIndex == 0) 169 | TomatoTimerWPF.TimerSettings.Default.Work_Time = 30; 170 | else if (cbWorkTimeComboBox.SelectedIndex == 1) 171 | TomatoTimerWPF.TimerSettings.Default.Work_Time = 25; 172 | else 173 | { 174 | tbox = cbWorkTimeComboBox.Items[2] as TextBox; 175 | if (tbox != null) 176 | { 177 | TomatoTimerWPF.TimerSettings.Default.Work_Time = Int32.Parse(tbox.Text); 178 | } 179 | } 180 | 181 | 182 | tbox = cbWorkTimeComboBox.Items[2] as TextBox; 183 | if (tbox != null) 184 | TomatoTimerWPF.TimerSettings.Default.WorkTime_Uesr = Int32.Parse(tbox.Text); 185 | 186 | tbox = cbRelaxTimeComboBox.Items[2] as TextBox; 187 | if (tbox != null) 188 | TomatoTimerWPF.TimerSettings.Default.RelaxTime_Uesr = Int32.Parse(tbox.Text); 189 | 190 | tbox = cbLongRelaxTimeComboBox.Items[2] as TextBox; 191 | if (tbox != null) 192 | TomatoTimerWPF.TimerSettings.Default.Relax_Time_Long_User = Int32.Parse(tbox.Text); 193 | 194 | 195 | TomatoTimerWPF.TimerSettings.Default.GoogleCal_src = tbGoogleCal_src.Text; 196 | TomatoTimerWPF.TimerSettings.Default.GoogleCal_text = tbGoogleCal_text.Text; 197 | TomatoTimerWPF.TimerSettings.Default.GoogleCal_EnableEvent = (cbEnableGCal.IsChecked == true); 198 | } 199 | 200 | private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 201 | { 202 | SyncUIValueToSettings(); 203 | 204 | } 205 | 206 | private void Button_Close_Click(object sender, System.Windows.RoutedEventArgs e) 207 | { 208 | //Switcher.Close(); 209 | m_window.Close(); 210 | } 211 | 212 | private void OnClick_Test_GoogleCalender(object sender, System.Windows.RoutedEventArgs e) 213 | { 214 | TomatoTimerWPF.TimerSettings.Default.GoogleCal_src = tbGoogleCal_src.Text; 215 | TomatoTimerWPF.TimerSettings.Default.GoogleCal_text = tbGoogleCal_text.Text; 216 | m_window.OpenGoogleCalender(DateTime.Now - TimeSpan.FromMinutes(TomatoTimerWPF.TimerSettings.Default.Work_Time), DateTime.Now); 217 | //Switcher.GetBaseWindow().OpenGoogleCalender(DateTime.Now - TimeSpan.FromMinutes(TomatoTimerWPF.TimerSettings.Default.Work_Time), DateTime.Now); 218 | } 219 | 220 | Regex NumEx = new Regex(@"^-?\d*\.?\d*$"); 221 | 222 | private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) 223 | { 224 | if (sender is TextBox) 225 | { 226 | string text = (sender as TextBox).Text + e.Text; 227 | 228 | e.Handled = !NumEx.IsMatch(text); 229 | } 230 | else 231 | throw new NotImplementedException("TextBox_PreviewTextInput Can only Handle TextBoxes"); 232 | } 233 | 234 | 235 | 236 | private void UserControl_Loaded(object sender, RoutedEventArgs e) 237 | { 238 | SyncSettingsToUIValue(); 239 | } 240 | 241 | private void myGif_MediaEnded(object sender, RoutedEventArgs e) 242 | { 243 | //myGif.Position = new TimeSpan(0, 0, 1); 244 | //myGif.Play(); 245 | } 246 | 247 | private void CheckBox_Checked(object sender, RoutedEventArgs e) 248 | { 249 | if (sender == cbEnableGCal) 250 | { 251 | if (cbEnableGCal.IsChecked == true) 252 | { 253 | spGoogleEventTitle.IsEnabled = true; 254 | spGoogleID.IsEnabled = true; 255 | menuTestGoogleCal.IsEnabled = true; 256 | } 257 | else 258 | { 259 | spGoogleEventTitle.IsEnabled = false; 260 | spGoogleID.IsEnabled = false; 261 | menuTestGoogleCal.IsEnabled = false; 262 | } 263 | TomatoTimerWPF.TimerSettings.Default.GoogleCal_EnableEvent = (cbEnableGCal.IsChecked == true); 264 | }// 265 | else if (sender == cbCopyLinkToClipBoard) 266 | { 267 | TomatoTimerWPF.TimerSettings.Default.GoogleCal_CopyToClipboard = (cbCopyLinkToClipBoard.IsChecked == true); 268 | } 269 | } 270 | 271 | private void MenuItem_SubmenuOpened(object sender, RoutedEventArgs e) 272 | { 273 | gifHowToDemo.FrameIndex = 0; 274 | gifHowToDemo.StopAnimation(); 275 | gifHowToDemo.StartAnimation(); 276 | } 277 | 278 | private void cbComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 279 | { 280 | SyncUIValueToSettings(); 281 | } 282 | 283 | private void menuClose_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 284 | { 285 | //MessageBox.Show("menuClose_MouseLeftButtonUp"); 286 | m_window.SavePropertiesAndClose(true); 287 | } 288 | 289 | private void menuCloseDontSave_Click(object sender, RoutedEventArgs e) 290 | { 291 | //MessageBox.Show("menuCloseDontSave_Click"); 292 | m_window.SavePropertiesAndClose(false); 293 | } 294 | 295 | private void menuCloseSave_Click(object sender, RoutedEventArgs e) 296 | { 297 | //MessageBox.Show("menuCloseSave_Click"); 298 | m_window.SavePropertiesAndClose(true); 299 | } 300 | 301 | private void btnGotoSoundSettings_Click(object sender, RoutedEventArgs e) 302 | { 303 | m_window.SwitchFromSettingToSound(); 304 | } 305 | 306 | private void labelVersion_small_MouseDown(object sender, MouseButtonEventArgs e) 307 | { 308 | m_bVersionMode = !m_bVersionMode; 309 | if (m_bVersionMode) 310 | labelVersion_small.Content = "Version: " + System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString(); 311 | else 312 | { 313 | Version ver = System.Reflection.Assembly.GetEntryAssembly().GetName().Version; 314 | var date = new DateTime( 2000, 01, 01 ).AddDays( ver.Build ).AddSeconds( ver.Revision * 2 ); 315 | labelVersion_small.Content = "Build date: " + date.ToString(); 316 | } 317 | 318 | } 319 | 320 | 321 | private void btnGCal_Click(object sender, RoutedEventArgs e) 322 | { 323 | Button btnSelf = (sender as Button); 324 | 325 | btnSelf.ContextMenu.IsEnabled = true; 326 | btnSelf.ContextMenu.PlacementTarget = btnSelf; 327 | btnSelf.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom; 328 | //btnSelf.ContextMenu.VerticalOffset = (btnSelf.ActualHeight); 329 | //btnSelf.ContextMenu.HorizontalOffset = (btnSelf.ContextMenu.ActualWidth / 2); 330 | btnSelf.ContextMenu.IsOpen = true; 331 | 332 | } 333 | } 334 | } 335 | -------------------------------------------------------------------------------- /TomatoTimerWPF/TomatoTimerWPF.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C6D3FC89-0EC1-485B-AF8D-57DDFD4CB472} 8 | WinExe 9 | Properties 10 | TomatoTimerWPF 11 | TomatoTimerWPF 12 | v4.5 13 | 512 14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 15 | 4 16 | false 17 | publish\ 18 | true 19 | Disk 20 | false 21 | Foreground 22 | 7 23 | Days 24 | false 25 | false 26 | true 27 | true 28 | 1 29 | 1.0.0.%2a 30 | false 31 | true 32 | true 33 | 34 | 35 | AnyCPU 36 | true 37 | full 38 | false 39 | bin\Debug\ 40 | DEBUG;TRACE 41 | prompt 42 | 4 43 | 44 | 45 | AnyCPU 46 | pdbonly 47 | true 48 | bin\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | false 53 | false 54 | 55 | 56 | Resource\Android_JellyBean\10-device-access-alarms_big_wbg_wbloom.ico 57 | 58 | 59 | 60 | 912366DAAE9B56D48FC2B4767EFDC57385296A24 61 | 62 | 63 | TomatoTimerWPF_TemporaryKey.pfx 64 | 65 | 66 | false 67 | 68 | 69 | LocalIntranet 70 | 71 | 72 | 73 | true 74 | 75 | 76 | false 77 | 78 | 79 | true 80 | bin\x64\Debug\ 81 | DEBUG;TRACE 82 | full 83 | x64 84 | prompt 85 | ManagedMinimumRules.ruleset 86 | true 87 | 88 | 89 | bin\x64\Release\ 90 | TRACE 91 | true 92 | none 93 | x64 94 | false 95 | prompt 96 | ManagedMinimumRules.ruleset 97 | true 98 | 99 | 100 | true 101 | bin\x86\Debug\ 102 | DEBUG;TRACE 103 | full 104 | x86 105 | prompt 106 | ManagedMinimumRules.ruleset 107 | true 108 | 109 | 110 | bin\x86\Release\ 111 | TRACE 112 | true 113 | none 114 | x86 115 | false 116 | prompt 117 | ManagedMinimumRules.ruleset 118 | false 119 | 120 | 121 | TomatoTimerWPF.App 122 | 123 | 124 | true 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 4.0 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | True 147 | True 148 | TimerSettings.settings 149 | 150 | 151 | MSBuild:Compile 152 | Designer 153 | 154 | 155 | 156 | 157 | 158 | Page_SoundSettings.xaml 159 | 160 | 161 | True 162 | True 163 | Resources.resx 164 | 165 | 166 | 167 | MSBuild:Compile 168 | Designer 169 | 170 | 171 | App.xaml 172 | Code 173 | 174 | 175 | MainWindow.xaml 176 | Code 177 | 178 | 179 | Designer 180 | MSBuild:Compile 181 | 182 | 183 | Designer 184 | MSBuild:Compile 185 | 186 | 187 | Designer 188 | MSBuild:Compile 189 | 190 | 191 | Designer 192 | MSBuild:Compile 193 | 194 | 195 | 196 | 197 | Page_Buttons.xaml 198 | 199 | 200 | Page_Settings.xaml 201 | 202 | 203 | Code 204 | 205 | 206 | True 207 | Settings.settings 208 | True 209 | 210 | 211 | ResXFileCodeGenerator 212 | Designer 213 | Resources.Designer.cs 214 | 215 | 216 | 217 | SettingsSingleFileGenerator 218 | Settings.Designer.cs 219 | 220 | 221 | 222 | SettingsSingleFileGenerator 223 | TimerSettings.Designer.cs 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | False 272 | Microsoft .NET Framework 4.5 %28x86 and x64%29 273 | true 274 | 275 | 276 | False 277 | .NET Framework 3.5 SP1 Client Profile 278 | false 279 | 280 | 281 | False 282 | .NET Framework 3.5 SP1 283 | false 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 312 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Pages/Page_SoundSettings.xaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 39 | 40 | 41 | 42 | 55 | 58 | 61 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 84 | 87 | 90 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 113 | 116 | 119 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 142 | 145 | 148 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /TomatoTimerWPF/Pages/Page_SoundSettings.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | //using WMPLib; 17 | 18 | namespace TomatoTimerWPF.Pages 19 | { 20 | using Res = Properties.Resources; 21 | /// 22 | /// Interaction logic for Page_SoundSettings.xaml 23 | /// 24 | public partial class Page_SoundSettings : UserControl 25 | { 26 | private MainWindow m_window; 27 | //private WindowsMediaPlayer m_wmplayer = null; 28 | //private System.Media.SoundPlayer[] m_ResourcePlayer; 29 | 30 | private MediaPlayer m_mediaPlayer = null; 31 | 32 | private Button[] m_aBtnPlay; 33 | private Button[] m_aBtnStop; 34 | private Button[] m_aBtnOpenFile; 35 | private Button[] m_aBtnMute; 36 | 37 | public enum SoundType : int 38 | { 39 | Resume = 0, 40 | Pause = 1, 41 | WorkDone = 2, 42 | RestTimeOut = 3 43 | } 44 | 45 | public enum SoundState : int 46 | { 47 | Resource = 0, 48 | Mute = 1, 49 | File = 2 50 | } 51 | 52 | private SoundState[] m_aSoundState; 53 | 54 | 55 | public Page_SoundSettings(MainWindow window) 56 | { 57 | InitializeComponent(); 58 | m_window = window; 59 | 60 | m_aBtnPlay = new Button[4] { btnSoundResumePlay, btnSoundPausePlay, btnSoundWorkPlay, btnSoundRestPlay }; 61 | m_aBtnStop = new Button[4] { btnSoundResumeStop, btnSoundPauseStop, btnSoundWorkStop, btnSoundRestStop }; 62 | m_aBtnOpenFile = new Button[4] { btnSoundResumeOpenFile, btnSoundPauseOpenFile, btnSoundWorkOpenFile, btnSoundRestOpenFile }; 63 | m_aBtnMute = new Button[4] { btnSoundResumeMute, btnSoundPauseMute, btnSoundWorkMute, btnSoundRestMute }; 64 | 65 | m_aSoundState = new SoundState[4]; 66 | //m_ResourcePlayer = new System.Media.SoundPlayer[4]; 67 | 68 | for (int i = 0; i < 4; i++) 69 | { 70 | //m_ResourcePlayer[i] = null; 71 | m_aSoundState[i] = getSoundState(getSoundPathProperties((SoundType)i)); 72 | SyncStateToPlayer((SoundType)i, m_aSoundState[i]); 73 | SyncStateToUI((SoundType)i, m_aSoundState[i]); 74 | } 75 | } 76 | 77 | private SoundState getSoundState(string path) 78 | { 79 | if (path.Length == 0) 80 | return SoundState.Mute; 81 | else 82 | { 83 | if (path == SoundState.Mute.ToString()) 84 | return SoundState.Mute; 85 | if (path == SoundState.Resource.ToString()) 86 | return SoundState.Mute; 87 | 88 | if (System.IO.File.Exists(path)) 89 | { 90 | return SoundState.File; 91 | } 92 | else 93 | return SoundState.Mute; 94 | } 95 | } 96 | 97 | private void SyncStateToUI(SoundType type, SoundState state) 98 | { 99 | switch (state) 100 | { 101 | case SoundState.Resource: 102 | case SoundState.File: 103 | m_aBtnPlay[(int)type].Visibility = Visibility.Visible; 104 | m_aBtnStop[(int)type].Visibility = Visibility.Collapsed; 105 | m_aBtnOpenFile[(int)type].Visibility = Visibility.Visible; 106 | m_aBtnMute[(int)type].Visibility = Visibility.Visible; 107 | break; 108 | case SoundState.Mute: 109 | m_aBtnPlay[(int)type].Visibility = Visibility.Collapsed; 110 | m_aBtnStop[(int)type].Visibility = Visibility.Collapsed; 111 | m_aBtnOpenFile[(int)type].Visibility = Visibility.Visible; 112 | m_aBtnMute[(int)type].Visibility = Visibility.Collapsed; 113 | break; 114 | } 115 | 116 | } 117 | 118 | private void SyncStateToPlayer(SoundType type, SoundState state) 119 | { 120 | switch (state) 121 | { 122 | case SoundState.Resource: 123 | //if (m_ResourcePlayer[(int)type]==null) 124 | //{ 125 | // switch (type) 126 | // { 127 | // case SoundType.Pause: 128 | // ;//m_ResourcePlayer[(int)type] = new System.Media.SoundPlayer(Res.Bellatrix_Pause); 129 | // break; 130 | // case SoundType.Resume: 131 | // ;//m_ResourcePlayer[(int)type] = new System.Media.SoundPlayer(Res.Pollux_Resume); 132 | // break; 133 | // case SoundType.WorkDone: 134 | // ;//m_ResourcePlayer[(int)type] = new System.Media.SoundPlayer(Res.CanisMajor_WorkDone); 135 | // break; 136 | // case SoundType.RestTimeOut: 137 | // ;//m_ResourcePlayer[(int)type] = new System.Media.SoundPlayer(Res.Fermium_RestTimeOut); 138 | // break; 139 | // } 140 | //} 141 | break; 142 | 143 | case SoundState.File: 144 | //if (m_wmplayer == null) 145 | //{ 146 | // m_wmplayer = new WMPLib.WindowsMediaPlayer(); 147 | // m_wmplayer.PlayStateChange += 148 | // new WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(Player_PlayStateChange); 149 | //} 150 | if (m_mediaPlayer == null) 151 | { 152 | m_mediaPlayer = new MediaPlayer(); 153 | m_mediaPlayer.MediaEnded += MediaPlayer_MediaEnded; 154 | } 155 | 156 | break; 157 | 158 | } 159 | 160 | } 161 | 162 | private void MediaPlayer_MediaEnded(object sender, EventArgs e) 163 | { 164 | for (int i = 0; i < 4; i++) 165 | { 166 | SyncStateToUI((SoundType)i, m_aSoundState[i]); 167 | } 168 | } 169 | 170 | private string getSoundPathProperties(SoundType type) 171 | { 172 | 173 | switch (type) 174 | { 175 | case SoundType.Resume: 176 | return TomatoTimerWPF.TimerSettings.Default.SoundPathResume; 177 | case SoundType.Pause: 178 | return TomatoTimerWPF.TimerSettings.Default.SoundPathPause; 179 | case SoundType.WorkDone: 180 | return TomatoTimerWPF.TimerSettings.Default.SoundPathTimeOutWork; 181 | case SoundType.RestTimeOut: 182 | return TomatoTimerWPF.TimerSettings.Default.SoundPathTimeOutRest; 183 | default: 184 | return ""; 185 | } 186 | } 187 | 188 | private void setSoundPathProperties(SoundType type,string stateString) 189 | { 190 | switch (type) 191 | { 192 | case SoundType.Resume: 193 | TomatoTimerWPF.TimerSettings.Default.SoundPathResume = stateString; 194 | break; 195 | case SoundType.Pause: 196 | TomatoTimerWPF.TimerSettings.Default.SoundPathPause = stateString; 197 | break; 198 | case SoundType.WorkDone: 199 | TomatoTimerWPF.TimerSettings.Default.SoundPathTimeOutWork = stateString; 200 | break;; 201 | case SoundType.RestTimeOut: 202 | TomatoTimerWPF.TimerSettings.Default.SoundPathTimeOutRest = stateString; 203 | break; 204 | } 205 | } 206 | 207 | //private void Player_PlayStateChange(int NewState) 208 | //{ 209 | // if ((WMPLib.WMPPlayState)NewState == WMPLib.WMPPlayState.wmppsStopped || 210 | // (WMPLib.WMPPlayState)NewState == WMPLib.WMPPlayState.wmppsMediaEnded) 211 | // { 212 | // for (int i = 0; i < 4; i++) 213 | // { 214 | // SyncStateToUI((SoundType)i, m_aSoundState[i]); 215 | // } 216 | // } 217 | // else if ((WMPLib.WMPPlayState)NewState == WMPLib.WMPPlayState.wmppsPlaying) 218 | // { 219 | // btnSoundPausePlay.Visibility = Visibility.Collapsed; 220 | // btnSoundResumePlay.Visibility = Visibility.Collapsed; 221 | // btnSoundWorkPlay.Visibility = Visibility.Collapsed; 222 | // btnSoundRestPlay.Visibility = Visibility.Collapsed; 223 | 224 | // btnSoundPauseStop.Visibility = Visibility.Visible; 225 | // btnSoundResumeStop.Visibility = Visibility.Visible; 226 | // btnSoundWorkStop.Visibility = Visibility.Visible; 227 | // btnSoundRestStop.Visibility = Visibility.Visible; 228 | // } 229 | //} 230 | 231 | public void playSound(SoundType type) 232 | { 233 | if ((int)type >= 4 || (int)type < 0) return; 234 | 235 | SyncStateToPlayer(type, m_aSoundState[(int)type]); 236 | switch (m_aSoundState[(int)type]) 237 | { 238 | case SoundState.File: 239 | //m_wmplayer.URL = getSoundPathProperties(type); 240 | //m_wmplayer.controls.play(); 241 | m_mediaPlayer.Open(new Uri(getSoundPathProperties(type))); 242 | m_mediaPlayer.Play(); 243 | 244 | btnSoundPausePlay.Visibility = Visibility.Collapsed; 245 | btnSoundResumePlay.Visibility = Visibility.Collapsed; 246 | btnSoundWorkPlay.Visibility = Visibility.Collapsed; 247 | btnSoundRestPlay.Visibility = Visibility.Collapsed; 248 | 249 | btnSoundPauseStop.Visibility = Visibility.Visible; 250 | btnSoundResumeStop.Visibility = Visibility.Visible; 251 | btnSoundWorkStop.Visibility = Visibility.Visible; 252 | btnSoundRestStop.Visibility = Visibility.Visible; 253 | 254 | break; 255 | case SoundState.Resource: 256 | //m_ResourcePlayer[(int)type].Play(); 257 | break; 258 | } 259 | 260 | } 261 | 262 | private void btnSound_Click(object sender, RoutedEventArgs e) 263 | { 264 | Button btnSelf = (sender as Button); 265 | 266 | btnSelf.ContextMenu.IsEnabled = true; 267 | btnSelf.ContextMenu.PlacementTarget = btnSelf; 268 | btnSelf.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Center; 269 | btnSelf.ContextMenu.VerticalOffset = (btnSelf.ActualHeight); 270 | //btnSelf.ContextMenu.HorizontalOffset = (btnSelf.ContextMenu.ActualWidth / 2); 271 | btnSelf.ContextMenu.IsOpen = true; 272 | 273 | } 274 | 275 | private void btnGotoSetting_Click(object sender, RoutedEventArgs e) 276 | { 277 | //if (m_wmplayer != null && m_wmplayer.playState == WMPLib.WMPPlayState.wmppsPlaying) 278 | // m_wmplayer.controls.stop(); 279 | if (m_mediaPlayer != null) 280 | m_mediaPlayer.Stop(); 281 | m_window.SwitchFromSoundToSetting(); 282 | } 283 | 284 | private void menuClose_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 285 | { 286 | //MessageBox.Show("menuClose_MouseLeftButtonUp"); 287 | m_window.SavePropertiesAndClose(true); 288 | } 289 | 290 | private void menuCloseDontSave_Click(object sender, RoutedEventArgs e) 291 | { 292 | //MessageBox.Show("menuCloseDontSave_Click"); 293 | m_window.SavePropertiesAndClose(false); 294 | } 295 | 296 | private void menuCloseSave_Click(object sender, RoutedEventArgs e) 297 | { 298 | //MessageBox.Show("menuCloseSave_Click"); 299 | m_window.SavePropertiesAndClose(true); 300 | } 301 | 302 | private void btnSoundPlay_Click(object sender, RoutedEventArgs e) 303 | { 304 | Button btnSelf = sender as Button; 305 | SoundType type; 306 | for (int i=0;i<4;i++) 307 | { 308 | if (btnSelf == m_aBtnPlay[i]) 309 | { 310 | type = (SoundType)i; 311 | playSound(type); 312 | return; 313 | } 314 | } 315 | } 316 | 317 | private void btnSoundStop_Click(object sender, RoutedEventArgs e) 318 | { 319 | //if (m_wmplayer == null) return; 320 | //m_wmplayer.controls.stop(); 321 | if (m_mediaPlayer == null) return; 322 | m_mediaPlayer.Stop(); 323 | for (int i = 0; i < 4; i++) 324 | { 325 | SyncStateToUI((SoundType)i, m_aSoundState[i]); 326 | } 327 | 328 | } 329 | 330 | private void btnSoundOpenFile_Click(object sender, RoutedEventArgs e) 331 | { 332 | Button btnSelf = sender as Button; 333 | SoundType type; 334 | 335 | System.Windows.Forms.OpenFileDialog dialog = new System.Windows.Forms.OpenFileDialog(); 336 | 337 | //dialog.Filter = "Sound files (*.wma;*.mp3;*.wav;*.ogg)|*.wma;*.mp3;*.wav;*.ogg"; 338 | dialog.Filter = "Sound files (*.wma;*.mp3;*.wav)|*.wma;*.mp3;*.wav"; 339 | //dialog.InitialDirectory = System.Windows.Forms.Application.StartupPath; 340 | dialog.Title = "Select a sound file"; 341 | 342 | if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) 343 | { 344 | for (int i = 0; i < 4; i++) 345 | { 346 | if (btnSelf == m_aBtnOpenFile[i]) 347 | { 348 | type = (SoundType)i; 349 | m_aSoundState[i] = SoundState.File; 350 | SyncStateToUI(type, SoundState.File); 351 | setSoundPathProperties(type, dialog.FileName); 352 | playSound(type); 353 | return; 354 | } 355 | } 356 | } 357 | //else 358 | //{ 359 | // for (int i = 0; i < 4; i++) 360 | // { 361 | // if (btnSelf == m_aBtnOpenFile[i]) 362 | // { 363 | // type = (SoundType)i; 364 | // m_aSoundState[i] = SoundState.Mute; 365 | // SyncStateToUI(type, SoundState.Resource); 366 | // setSoundPathProperties(type, SoundState.Resource.ToString()); 367 | // playSound(type); 368 | // return; 369 | // } 370 | // } 371 | //} 372 | } 373 | 374 | private void btnSoundMute_Click(object sender, RoutedEventArgs e) 375 | { 376 | if (m_mediaPlayer != null) 377 | m_mediaPlayer.Stop(); 378 | Button btnSelf = sender as Button; 379 | SoundType type; 380 | for (int i = 0; i < 4; i++) 381 | { 382 | if (btnSelf == m_aBtnMute[i]) 383 | { 384 | type = (SoundType)i; 385 | m_aSoundState[i] = SoundState.Mute; 386 | SyncStateToUI(type, SoundState.Mute); 387 | setSoundPathProperties(type, SoundState.Mute.ToString()); 388 | return; 389 | } 390 | } 391 | } 392 | 393 | } 394 | } 395 | -------------------------------------------------------------------------------- /TomatoTimerWPF/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | using System.Runtime.InteropServices; 17 | using System.Drawing; 18 | using System.Windows.Interop; 19 | using System.Windows.Media.Animation; 20 | using System.Configuration; 21 | 22 | using TomatoTimerWPF.Pages; 23 | 24 | namespace TomatoTimerWPF 25 | { 26 | using Res = Properties.Resources; 27 | //using Setting = Properties.Settings; 28 | /// 29 | /// Interaction logic for MainWindow.xaml 30 | /// 31 | public partial class MainWindow : Window 32 | { 33 | 34 | [DllImport("user32.dll")] 35 | static extern Int32 FlashWindowEx(ref FLASHWINFO pwfi); 36 | //static extern uint SetClassLong(HandleRef hWnd, int nIndex, uint dwNewLong); 37 | //static extern uint GetClassLong(HandleRef hWnd, int nIndex, uint dwNewLong); 38 | 39 | [//Obsolete("This method will crash on 64-bit operating systems. Use SetClassLongPtr instead"), 40 | DllImport("user32.dll", SetLastError = true)] 41 | static extern uint SetClassLong(HandleRef hWnd, int nIndex, uint dwNewLong); 42 | 43 | private const Int32 GWL_STYLE = -16; 44 | private const Int32 WS_MAXIMIZEBOX = 0x00010000; 45 | private const Int32 WS_MINIMIZEBOX = 0x00020000; 46 | 47 | [DllImport("User32.dll", EntryPoint = "GetWindowLong")] 48 | private extern static Int32 GetWindowLongPtr(IntPtr hWnd, Int32 nIndex); 49 | 50 | [DllImport("User32.dll", EntryPoint = "SetWindowLong")] 51 | private extern static Int32 SetWindowLongPtr(IntPtr hWnd, Int32 nIndex, Int32 dwNewLong); 52 | 53 | [StructLayout(LayoutKind.Sequential)] 54 | public struct FLASHWINFO 55 | { 56 | public UInt32 cbSize; 57 | public IntPtr hwnd; 58 | public Int32 dwFlags; 59 | public UInt32 uCount; 60 | public Int32 dwTimeout; 61 | } 62 | 63 | [System.Runtime.InteropServices.DllImport("gdi32.dll")] 64 | public static extern bool DeleteObject(IntPtr hObject); 65 | 66 | enum TimerMode{ 67 | MODE_WORK, 68 | MODE_RELAX, 69 | MODE_RELAX_LONG 70 | }; 71 | 72 | private System.Windows.Forms.Timer m_timer; 73 | private bool m_bIsPause = false; 74 | private DateTime m_TimeDateStart = DateTime.Now; 75 | private DateTime m_TimeDatePauseStart; 76 | private TimeSpan m_TimeSpan; 77 | private TimeSpan m_TimeSpanPause; 78 | private TimerMode m_mode = TimerMode.MODE_WORK; 79 | private int m_OverlayIconLastMin; 80 | private bool m_bIsSupportTaskbarManager = false; 81 | private bool m_bIsOverTime = false; 82 | 83 | public IntPtr m_hwnd; 84 | 85 | private Page_Buttons m_pageButtons; 86 | private Page_Settings m_pageSettings; 87 | private Page_SoundSettings m_pageSoundSettings; 88 | 89 | Storyboard m_sbAniOut; 90 | Storyboard m_sbAniIn; 91 | 92 | ThicknessAnimation m_taSlideOut; 93 | ThicknessAnimation m_taSlideIn; 94 | 95 | private bool m_isNormalClosingEvent; 96 | 97 | public MainWindow() 98 | { 99 | 100 | InitializeComponent(); 101 | 102 | //string path = System.Reflection.Assembly.GetExecutingAssembly().Location + ".config"; 103 | //if (!System.IO.File.Exists(path)) 104 | //{ 105 | // //TomatoTimerWPF.TimerSettings.Default.Save(); 106 | // Console.WriteLine("Save setting [" + path + "]"); 107 | //} 108 | //else 109 | // Console.WriteLine("Exists![" + path + "]"); 110 | 111 | m_OverlayIconLastMin = -99999; 112 | m_isNormalClosingEvent = false; 113 | 114 | //Initialize animations 115 | m_sbAniOut = new Storyboard(); 116 | DoubleAnimation daFadeOut = new DoubleAnimation(); 117 | daFadeOut.Duration = 200.Milliseconds(); 118 | daFadeOut.To = 0.0; 119 | 120 | ThicknessAnimation taSlideOut = new ThicknessAnimation(); 121 | taSlideOut.Duration = 200.Milliseconds(); 122 | taSlideOut.To = new Thickness(0, this.Height, 0, 0); 123 | taSlideOut.From = new Thickness(0, 0, 0, 0); 124 | 125 | m_sbAniOut.Completed += Storyboard_Completed; 126 | m_sbAniOut.Children.Add(daFadeOut); 127 | m_sbAniOut.Children.Add(taSlideOut); 128 | Storyboard.SetTargetProperty(daFadeOut, new PropertyPath(UIElement.OpacityProperty)); 129 | Storyboard.SetTargetProperty(taSlideOut, new PropertyPath(FrameworkElement.MarginProperty)); 130 | 131 | 132 | m_sbAniIn = new Storyboard(); 133 | DoubleAnimation daFadeIn = new DoubleAnimation(); 134 | daFadeIn.Duration = 200.Milliseconds(); 135 | daFadeIn.From = 0.0; 136 | daFadeIn.To = 1.0; 137 | 138 | ThicknessAnimation taSlideIn = new ThicknessAnimation(); 139 | taSlideIn.Duration = 200.Milliseconds(); 140 | taSlideIn.From = new Thickness(0, -this.Height, 0, 0); 141 | taSlideIn.To = new Thickness(0, 0, 0, 0); 142 | 143 | m_sbAniIn.Completed += Storyboard_Completed; 144 | m_sbAniIn.Children.Add(daFadeIn); 145 | m_sbAniIn.Children.Add(taSlideIn); 146 | Storyboard.SetTargetProperty(daFadeIn, new PropertyPath(UIElement.OpacityProperty)); 147 | Storyboard.SetTargetProperty(taSlideIn, new PropertyPath(FrameworkElement.MarginProperty)); 148 | 149 | m_taSlideOut = taSlideOut; 150 | m_taSlideIn = taSlideIn; 151 | 152 | try 153 | { 154 | Rect bounds = Rect.Parse(TomatoTimerWPF.TimerSettings.Default.WindowRestoreBounds); 155 | bounds = CheckBounds(bounds); 156 | this.Top = bounds.Top; 157 | this.Left = bounds.Left; 158 | this.Width = bounds.Width; 159 | this.Height = bounds.Height; 160 | } 161 | catch (Exception) 162 | { 163 | //MessageBox.Show(e.ToString()); 164 | //MessageBox.Show("[" + TomatoTimerWPF.TimerSettings.Default.WindowRestoreBounds + "]"); 165 | } 166 | } 167 | 168 | static public Rect CheckBounds(Rect bounds) 169 | { 170 | int iInsideLT, iInsideRB; 171 | iInsideLT = iInsideRB = -1; 172 | for (int s = 0; s < System.Windows.Forms.Screen.AllScreens.Length;s++ ) 173 | { 174 | System.Windows.Forms.Screen screen = System.Windows.Forms.Screen.AllScreens[s]; 175 | if (bounds.Left >= screen.Bounds.Left && bounds.Top >= screen.Bounds.Top && 176 | bounds.Left < screen.Bounds.Right && bounds.Top < screen.Bounds.Bottom) 177 | { 178 | iInsideLT = s; 179 | } 180 | 181 | if (bounds.Right >= screen.Bounds.Left && bounds.Bottom >= screen.Bounds.Top && 182 | bounds.Right < screen.Bounds.Right && bounds.Bottom < screen.Bounds.Bottom) 183 | { 184 | iInsideRB = s; 185 | } 186 | } 187 | 188 | //if (iInsideLT != -1 || iInsideRB != -1) 189 | { 190 | int recheckScreen = -1; 191 | 192 | if (iInsideLT == -1 && iInsideRB == -1) 193 | recheckScreen = 0; 194 | else if (iInsideLT == -1) 195 | recheckScreen = iInsideRB; 196 | else if (iInsideRB == -1) 197 | recheckScreen = iInsideLT; 198 | 199 | if (recheckScreen != -1) 200 | { 201 | System.Windows.Forms.Screen screen = System.Windows.Forms.Screen.AllScreens[recheckScreen]; 202 | 203 | if (bounds.X < screen.Bounds.Left) 204 | bounds.X = screen.Bounds.Left; 205 | if (bounds.Y < screen.Bounds.Top) 206 | bounds.Y = screen.Bounds.Top; 207 | if (bounds.Width > screen.Bounds.Width) 208 | bounds.Width = screen.Bounds.Width; 209 | if (bounds.Height > screen.Bounds.Height) 210 | bounds.Height = screen.Bounds.Height; 211 | 212 | if (bounds.Right > screen.Bounds.Right) 213 | bounds.X -= bounds.Right - screen.Bounds.Right; 214 | if (bounds.Bottom > screen.Bounds.Bottom) 215 | bounds.Y -= bounds.Bottom - screen.Bounds.Bottom; 216 | 217 | } 218 | } 219 | return bounds; 220 | } 221 | 222 | private void Window_Loaded_1(object sender, RoutedEventArgs e) 223 | { 224 | m_hwnd = new WindowInteropHelper(this).Handle; 225 | 226 | Int32 windowStyle = GetWindowLongPtr(m_hwnd, GWL_STYLE); 227 | SetWindowLongPtr(m_hwnd, GWL_STYLE, windowStyle & ~WS_MAXIMIZEBOX); 228 | 229 | m_bIsSupportTaskbarManager = true; 230 | this.TaskbarItemInfo.ThumbnailClipMargin = new Thickness(0, 0, 0, 0); 231 | 232 | try 233 | { 234 | DateTime restoreStart = DateTime.Parse(TomatoTimerWPF.TimerSettings.Default.TimerRestoreDateTime); 235 | m_TimeDateStart = restoreStart; 236 | m_TimeDatePauseStart = restoreStart; 237 | m_mode = (TimerMode)TomatoTimerWPF.TimerSettings.Default.TimerRestoreMode; 238 | } 239 | catch(Exception) 240 | { 241 | m_TimeDateStart = DateTime.Now; 242 | m_TimeDatePauseStart = DateTime.Now; 243 | } 244 | 245 | m_pageButtons = new Page_Buttons(this); 246 | m_pageSettings = new Page_Settings(this); 247 | m_pageSoundSettings = new Page_SoundSettings(this); 248 | 249 | btnAlwaysOnTop.IsChecked = TomatoTimerWPF.TimerSettings.Default.AlwaysOnTop; 250 | if (btnAlwaysOnTop.IsChecked == true) 251 | this.ToggleAlwaysOnTop(); 252 | 253 | spWindowControlStackPanel.Margin = new Thickness(0, -this.Height, 0, 0); 254 | m_sbAniOut.Begin(spWindowControlStackPanel); 255 | 256 | this.ucContent.Children.Add(m_pageButtons); 257 | UpdateUI(); 258 | 259 | m_timer = new System.Windows.Forms.Timer(); 260 | m_timer.Interval = 1000; 261 | m_timer.Tick += new EventHandler(Timer_Tick); 262 | m_timer.Start(); 263 | } 264 | 265 | void Timer_Tick(object sender, EventArgs e) 266 | { 267 | UpdateUI(); 268 | } 269 | 270 | public void SavePropertiesAndClose(bool isSaveTimerState) 271 | { 272 | if (isSaveTimerState && m_mode == TimerMode.MODE_WORK) 273 | { 274 | TomatoTimerWPF.TimerSettings.Default.TimerRestoreDateTime = m_TimeDateStart.ToString(); 275 | TomatoTimerWPF.TimerSettings.Default.TimerRestoreMode = (int)m_mode; 276 | } 277 | else 278 | { 279 | TomatoTimerWPF.TimerSettings.Default.TimerRestoreDateTime = ""; 280 | TomatoTimerWPF.TimerSettings.Default.TimerRestoreMode = (int)TimerMode.MODE_WORK; 281 | } 282 | TomatoTimerWPF.TimerSettings.Default.WindowRestoreBounds = this.RestoreBounds.ToString(); 283 | TomatoTimerWPF.TimerSettings.Default.Save(); 284 | 285 | m_isNormalClosingEvent = true; 286 | Close(); 287 | } 288 | 289 | private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 290 | { 291 | if (!m_isNormalClosingEvent) 292 | { 293 | if (m_mode == TimerMode.MODE_WORK) 294 | { 295 | TomatoTimerWPF.TimerSettings.Default.TimerRestoreDateTime = m_TimeDateStart.ToString(); 296 | TomatoTimerWPF.TimerSettings.Default.TimerRestoreMode = (int)m_mode; 297 | } 298 | else 299 | { 300 | TomatoTimerWPF.TimerSettings.Default.TimerRestoreDateTime = ""; 301 | TomatoTimerWPF.TimerSettings.Default.TimerRestoreMode = (int)TimerMode.MODE_WORK; 302 | } 303 | 304 | TomatoTimerWPF.TimerSettings.Default.WindowRestoreBounds = this.RestoreBounds.ToString(); 305 | TomatoTimerWPF.TimerSettings.Default.Save(); 306 | } 307 | } 308 | 309 | public void UpdateUI() 310 | { 311 | 312 | 313 | TimeSpan pauseSpan = m_TimeSpanPause; 314 | if (m_bIsPause) 315 | pauseSpan += DateTime.Now - m_TimeDatePauseStart; 316 | 317 | TimeSpan timerSpan, modeSpan; 318 | if (m_mode == TimerMode.MODE_WORK) 319 | modeSpan = TimeSpan.FromMinutes(TomatoTimerWPF.TimerSettings.Default.Work_Time) + 800.Milliseconds(); 320 | else if (m_mode == TimerMode.MODE_RELAX) 321 | modeSpan = TimeSpan.FromMinutes(TomatoTimerWPF.TimerSettings.Default.Relax_Time) + 800.Milliseconds(); 322 | else if (m_mode == TimerMode.MODE_RELAX_LONG) 323 | modeSpan = TimeSpan.FromMinutes(TomatoTimerWPF.TimerSettings.Default.Relax_Time_Long) + 800.Milliseconds(); 324 | else 325 | modeSpan = 1.Seconds(); 326 | 327 | if (m_bIsPause) 328 | timerSpan = modeSpan - m_TimeSpan; 329 | else 330 | timerSpan = modeSpan - (DateTime.Now - m_TimeDateStart); 331 | 332 | if (!m_bIsOverTime && timerSpan.IsNegativeOrZero()) 333 | { 334 | SetWindowFlash(true); 335 | 336 | if (m_mode == TimerMode.MODE_WORK) 337 | m_pageSoundSettings.playSound(Page_SoundSettings.SoundType.WorkDone); 338 | else 339 | m_pageSoundSettings.playSound(Page_SoundSettings.SoundType.RestTimeOut); 340 | 341 | } 342 | 343 | m_bIsOverTime = timerSpan.IsNegativeOrZero(); 344 | 345 | 346 | 347 | double progressValue = 100.0 - ((timerSpan.TotalMilliseconds * 100.0 / modeSpan.TotalMilliseconds)); 348 | if (progressValue < 0.0) 349 | progressValue = 0.0; 350 | else if (progressValue > 100.0) 351 | progressValue = 100.0; 352 | 353 | 354 | Page_Buttons pageButtons = m_pageButtons;//pageTransitionControl.CurrentPage as Page_Buttons; 355 | if (pageButtons != null) 356 | { 357 | if (m_mode == TimerMode.MODE_WORK) 358 | { 359 | pageButtons.btnWork.Visibility = false.ToVisibility(); 360 | pageButtons.btnWork.IsEnabled = false; 361 | 362 | pageButtons.btnRelax.Visibility = true.ToVisibility(); 363 | pageButtons.btnRelax.IsEnabled = true; 364 | 365 | if (m_bIsPause) 366 | { 367 | pageButtons.btnPause.Visibility = false.ToVisibility(); 368 | pageButtons.btnPause.IsEnabled = false; 369 | 370 | pageButtons.btnPlay.Visibility = true.ToVisibility(); 371 | pageButtons.btnPlay.IsEnabled = true; 372 | pageButtons.labelTime.Opacity = 0.5; 373 | } 374 | else 375 | { 376 | 377 | pageButtons.btnPause.Visibility = (!m_bIsPause).ToVisibility(); 378 | pageButtons.btnPause.IsEnabled = (!m_bIsPause); 379 | 380 | pageButtons.btnPlay.Visibility = false.ToVisibility(); 381 | pageButtons.btnPlay.IsEnabled = false; 382 | pageButtons.labelTime.Opacity = 1; 383 | } 384 | } 385 | else 386 | { 387 | pageButtons.btnWork.Visibility = true.ToVisibility(); 388 | pageButtons.btnWork.IsEnabled = true; 389 | 390 | pageButtons.btnRelax.Visibility = false.ToVisibility(); 391 | pageButtons.btnRelax.IsEnabled = false; 392 | 393 | pageButtons.btnPause.Visibility = false.ToVisibility(); 394 | pageButtons.btnPause.IsEnabled = false; 395 | 396 | pageButtons.btnPlay.Visibility = false.ToVisibility(); 397 | pageButtons.btnPlay.IsEnabled = false; 398 | pageButtons.labelTime.Opacity = 1; 399 | } 400 | 401 | String info, time; 402 | if (m_TimeDateStart.Day != DateTime.Now.Day || m_TimeDateStart.Month != DateTime.Now.Month) 403 | info = m_TimeDateStart.ToString("MM/dd H:mm"); 404 | else 405 | info = "Start @ " + m_TimeDateStart.ToString("H:mm"); 406 | 407 | if (!pauseSpan.IsNegativeOrZero()) 408 | { 409 | if (pauseSpan.Hours != 0 || pauseSpan.Days != 0) 410 | info += "\r\nPause: {0}:{1:00}:{2:00}".ToFormat(Math.Abs(pauseSpan.Hours + pauseSpan.Days * 24), Math.Abs(pauseSpan.Minutes), Math.Abs(pauseSpan.Seconds)); 411 | else 412 | info += "\r\nPause: {0}:{1:00}".ToFormat(Math.Abs(pauseSpan.Minutes), Math.Abs(pauseSpan.Seconds)); 413 | } 414 | 415 | pageButtons.labelInfo.Content = info; 416 | 417 | 418 | TextBlock timeText = new TextBlock(); 419 | if (m_mode == TimerMode.MODE_WORK) 420 | { 421 | time = "Work "; 422 | //timeText.Inlines.Add(new Bold(new Run("W"))); 423 | timeText.Inlines.Add("Work "); 424 | } 425 | else if (m_mode == TimerMode.MODE_RELAX || m_mode == TimerMode.MODE_RELAX_LONG) 426 | { 427 | time = "Rest "; 428 | //timeText.Inlines.Add(new Bold(new Run("R"))); 429 | timeText.Inlines.Add("Rest "); 430 | } 431 | else 432 | time = ""; 433 | 434 | 435 | if (timerSpan.Hours != 0 || timerSpan.Days != 0) 436 | { 437 | if ((timerSpan.Seconds & 0x1) == 0) 438 | time += "{0}:{1:00} {2:00}".ToFormat(Math.Abs(timerSpan.Hours + timerSpan.Days * 24), Math.Abs(timerSpan.Minutes), Math.Abs(timerSpan.Seconds)); 439 | else 440 | time += "{0}:{1:00}:{2:00}".ToFormat(Math.Abs(timerSpan.Hours + timerSpan.Days * 24), Math.Abs(timerSpan.Minutes), Math.Abs(timerSpan.Seconds)); 441 | 442 | timeText.Inlines.Add("{0}:{1:00}".ToFormat(Math.Abs(timerSpan.Hours + timerSpan.Days * 24), Math.Abs(timerSpan.Minutes))); 443 | //Run minText = new Run("{0:00}".ToFormat(Math.Abs(timerSpan.Minutes))); 444 | //minText.FontFamily = new System.Windows.Media.FontFamily("/TomatoTimerWPF;component/Resource/#Roboto"); 445 | //minText.FontWeight = FontWeights.Black; 446 | //timeText.Inlines.Add(new Bold(minText)); 447 | timeText.Inlines.Add((timerSpan.Seconds & 0x1) == 0 ? ":" : " "); 448 | timeText.Inlines.Add("{0:00}".ToFormat(Math.Abs(timerSpan.Seconds))); 449 | } 450 | else 451 | { 452 | if ((timerSpan.Seconds & 0x1)==0) 453 | time += "{0} {1:00}".ToFormat(Math.Abs(timerSpan.Minutes), Math.Abs(timerSpan.Seconds)); 454 | else 455 | time += "{0}:{1:00}".ToFormat(Math.Abs(timerSpan.Minutes), Math.Abs(timerSpan.Seconds)); 456 | 457 | Run minText= new Run("{0}".ToFormat(Math.Abs(timerSpan.Minutes))); 458 | minText.FontFamily = new System.Windows.Media.FontFamily("/TomatoTimerWPF;component/Resource/#Roboto"); 459 | minText.FontWeight = FontWeights.Black; 460 | timeText.Inlines.Add(new Bold(minText)); 461 | timeText.Inlines.Add((timerSpan.Seconds & 0x1)==0?":":" "); 462 | timeText.Inlines.Add("{0:00}".ToFormat(Math.Abs(timerSpan.Seconds))); 463 | } 464 | 465 | if (pageButtons.labelTimeWhite.Visibility == Visibility.Visible) 466 | { 467 | pageButtons.labelTimeWhite.Content = time; 468 | pageButtons.labelTime.Content = time; 469 | } 470 | else 471 | { 472 | pageButtons.labelTime.Content = timeText; 473 | } 474 | 475 | 476 | if (pageButtons.GetIsMouseDown()) 477 | { 478 | if (pageButtons.btnRelax.IsPressed) 479 | { 480 | progressValue = pageButtons.GetLongMouseDownPercentage(); 481 | pageButtons.labelTime_small.Content = progressValue >= 100 ? "Long rest" : time; 482 | } 483 | else if (pageButtons.btnReset.IsPressed && m_mode == TimerMode.MODE_WORK) 484 | { 485 | progressValue = pageButtons.GetLongMouseDownPercentage(); 486 | pageButtons.labelTime_small.Content = progressValue >= 100 ? "Skip GCal" : time; 487 | } 488 | else 489 | pageButtons.labelTime_small.Content = time; 490 | } 491 | else 492 | pageButtons.labelTime_small.Content = time; 493 | 494 | 495 | 496 | if (m_bIsPause) 497 | { 498 | pageButtons.pbarTimer.Foreground = System.Windows.Media.Brushes.Green; 499 | pageButtons.pbarTimer.IsIndeterminate = true; 500 | pageButtons.pbarTimer.Value = progressValue; 501 | pageButtons.labelTimeWhite.Opacity = 0; 502 | } 503 | else if (m_bIsOverTime) 504 | { 505 | pageButtons.pbarTimer.Foreground = System.Windows.Media.Brushes.Red; 506 | pageButtons.pbarTimer.IsIndeterminate = false; 507 | pageButtons.pbarTimer.Value = 100; 508 | pageButtons.labelTimeWhite.Opacity = 1; 509 | } 510 | else 511 | { 512 | if (progressValue > 80) 513 | { 514 | pageButtons.pbarTimer.Foreground = System.Windows.Media.Brushes.Yellow; 515 | pageButtons.labelTimeWhite.Opacity = 0; 516 | } 517 | else 518 | { 519 | pageButtons.pbarTimer.Foreground = System.Windows.Media.Brushes.Green; 520 | pageButtons.labelTimeWhite.Opacity = 1; 521 | } 522 | pageButtons.pbarTimer.IsIndeterminate = false; 523 | pageButtons.pbarTimer.Value = progressValue; 524 | } 525 | 526 | 527 | } 528 | 529 | 530 | int tMin = timerSpan.Hours * 24 + timerSpan.Minutes; 531 | 532 | if (m_bIsSupportTaskbarManager) 533 | { 534 | 535 | if (m_OverlayIconLastMin != (tMin == 0 ? timerSpan.Seconds : tMin) + (timerSpan.IsNegativeOrZero() ? 1 : 0) + (m_bIsPause ? 3 : 1)) 536 | { 537 | Bitmap bmp = new Bitmap(16, 16); 538 | 539 | 540 | using (Graphics g = Graphics.FromImage(bmp)) 541 | { 542 | g.FillRectangle(System.Drawing.Brushes.Black, 0, 0, 16, 16); 543 | if (m_bIsPause) 544 | g.FillRectangle(System.Drawing.Brushes.Gray, 1, 1, 14, 14); 545 | else if (timerSpan.IsNegativeOrZero()) 546 | g.FillRectangle(System.Drawing.Brushes.DarkRed, 1, 1, 14, 14); 547 | else if (m_mode == TimerMode.MODE_WORK) 548 | g.FillRectangle(System.Drawing.Brushes.BlueViolet, 1, 1, 14, 14); 549 | else 550 | g.FillRectangle(System.Drawing.Brushes.MediumSeaGreen, 1, 1, 14, 14); 551 | 552 | if (timerSpan.Hours != 0 || timerSpan.Days != 0) 553 | { 554 | if (Math.Abs(timerSpan.Hours + timerSpan.Days * 24) <= 99) 555 | { 556 | g.DrawString("{0:00}".ToFormat(Math.Abs(timerSpan.Hours + timerSpan.Days * 24)), new Font("Arial", 6), new SolidBrush(System.Drawing.Color.White), 2, -1); 557 | g.DrawString("{0:00}".ToFormat(Math.Abs(timerSpan.Minutes)), new Font("Arial", 6), new SolidBrush(System.Drawing.Color.White), 2, 6); 558 | } 559 | else 560 | { 561 | g.DrawString("99", new Font("Impact", 6), new SolidBrush(System.Drawing.Color.White), 2, -1); 562 | g.DrawString("59", new Font("Impact", 6), new SolidBrush(System.Drawing.Color.White), 2, 6); 563 | } 564 | } 565 | else if (tMin == 0 && !timerSpan.IsNegativeOrZero() && !m_bIsPause) 566 | g.DrawString("{0:00}".ToFormat(Math.Abs(timerSpan.Seconds)), new Font("Courier New", 9), new SolidBrush(timerSpan.Seconds % 2 == 0 ? System.Drawing.Color.White : System.Drawing.Color.Black), -1, 0); 567 | else 568 | g.DrawString("{0:00}".ToFormat(Math.Abs(timerSpan.Minutes)), new Font("Courier New", 9), new SolidBrush(System.Drawing.Color.White), -1, 0); 569 | 570 | IntPtr hBitmap = bmp.GetHbitmap(); 571 | this.TaskbarItemInfo.Overlay = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( 572 | hBitmap, 573 | IntPtr.Zero, 574 | System.Windows.Int32Rect.Empty, 575 | BitmapSizeOptions.FromWidthAndHeight(bmp.Width, bmp.Height)); 576 | 577 | DeleteObject(hBitmap); 578 | } 579 | m_OverlayIconLastMin = (tMin == 0 ? timerSpan.Seconds : tMin) + (timerSpan.IsNegativeOrZero() ? 1 : 0) + (m_bIsPause ? 3 : 1); 580 | } 581 | 582 | 583 | if (m_bIsPause) 584 | { 585 | this.TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Indeterminate; 586 | if (this.TaskbarItemInfo.ProgressValue != 1) 587 | this.TaskbarItemInfo.ProgressValue = 1; 588 | } 589 | else if (m_bIsOverTime) 590 | { 591 | if (m_mode == TimerMode.MODE_WORK) 592 | this.TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Paused; 593 | else 594 | this.TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Error; 595 | if (this.TaskbarItemInfo.ProgressValue != 1) 596 | this.TaskbarItemInfo.ProgressValue = 1; 597 | } 598 | else 599 | { 600 | if (progressValue > 80) 601 | this.TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Paused; 602 | else 603 | this.TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Normal; 604 | this.TaskbarItemInfo.ProgressValue = progressValue / 100; 605 | } 606 | 607 | 608 | if (m_mode == TimerMode.MODE_WORK) 609 | { 610 | 611 | ThumbButtonGoToWork.Visibility = Visibility.Collapsed; 612 | ThumbButtonTakeABreak.Visibility = Visibility.Visible; 613 | ThumbButtonPause.Visibility = !m_bIsPause ? Visibility.Visible : Visibility.Collapsed; 614 | ThumbButtonPlay.Visibility = m_bIsPause ? Visibility.Visible : Visibility.Collapsed; 615 | 616 | } 617 | else 618 | { 619 | ThumbButtonGoToWork.Visibility = Visibility.Visible; 620 | ThumbButtonTakeABreak.Visibility = Visibility.Collapsed; 621 | ThumbButtonPause.Visibility = Visibility.Collapsed; 622 | ThumbButtonPlay.Visibility = Visibility.Collapsed; 623 | } 624 | } 625 | } 626 | 627 | private int GetPercentageComplete(TimeSpan elapsed, TimeSpan total) 628 | { 629 | return (int)((elapsed.TotalMilliseconds * 100 / total.TotalMilliseconds)); 630 | } 631 | 632 | 633 | public void StartWork() 634 | { 635 | if (m_bIsOverTime && m_mode == TimerMode.MODE_WORK && 636 | TomatoTimerWPF.TimerSettings.Default.GoogleCal_EnableEvent) 637 | OpenGoogleCalender(m_TimeDateStart, DateTime.Now); 638 | 639 | SetWindowFlash(false); 640 | m_TimeDateStart = DateTime.Now; 641 | m_TimeDatePauseStart = DateTime.Now; 642 | m_TimeSpanPause = TimeSpan.FromMinutes(0); 643 | m_TimeSpan = TimeSpan.FromMinutes(0); 644 | m_mode = TimerMode.MODE_WORK; 645 | m_bIsPause = false; 646 | 647 | 648 | //if (menuClose.Visibility == System.Windows.Visibility.Collapsed) 649 | //{ 650 | // menuClose.Visibility = System.Windows.Visibility.Visible; 651 | // btnClose.Visibility = System.Windows.Visibility.Collapsed; 652 | //} 653 | 654 | UpdateUI(); 655 | 656 | } 657 | 658 | public void StartRelax() 659 | { 660 | if (m_bIsOverTime && m_mode == TimerMode.MODE_WORK && 661 | TomatoTimerWPF.TimerSettings.Default.GoogleCal_EnableEvent) 662 | OpenGoogleCalender(m_TimeDateStart, DateTime.Now); 663 | 664 | SetWindowFlash(false); 665 | m_TimeDateStart = DateTime.Now; 666 | m_TimeDatePauseStart = DateTime.Now; 667 | m_TimeSpanPause = TimeSpan.FromMinutes(0); 668 | m_TimeSpan = TimeSpan.FromMinutes(0); 669 | m_mode = TimerMode.MODE_RELAX; 670 | 671 | if (m_pageButtons != null) 672 | { 673 | if (m_pageButtons.GetIsLongMouseDown()) 674 | m_mode = TimerMode.MODE_RELAX_LONG; 675 | } 676 | m_bIsPause = false; 677 | 678 | //if (menuClose.Visibility == System.Windows.Visibility.Visible) 679 | //{ 680 | // menuClose.Visibility = System.Windows.Visibility.Collapsed; 681 | // btnClose.Visibility = System.Windows.Visibility.Visible; 682 | //} 683 | 684 | UpdateUI(); 685 | } 686 | 687 | public void Pause() 688 | { 689 | if (m_bIsPause) return; 690 | if (m_mode == TimerMode.MODE_RELAX_LONG || m_mode == TimerMode.MODE_RELAX) 691 | return; 692 | 693 | m_pageSoundSettings.playSound(Page_SoundSettings.SoundType.Pause); 694 | m_bIsPause = true; 695 | m_TimeSpan = DateTime.Now - m_TimeDateStart; 696 | m_TimeDatePauseStart = DateTime.Now; 697 | UpdateUI(); 698 | } 699 | 700 | public void Resume() 701 | { 702 | TimeSpan pauseSpan; 703 | if (!m_bIsPause) return; 704 | 705 | m_pageSoundSettings.playSound(Page_SoundSettings.SoundType.Resume); 706 | m_bIsPause = false; 707 | pauseSpan = DateTime.Now - m_TimeDatePauseStart; 708 | m_TimeDateStart += pauseSpan; 709 | m_TimeSpanPause += pauseSpan; 710 | 711 | UpdateUI(); 712 | } 713 | 714 | public void Reset() 715 | { 716 | if (m_bIsOverTime && m_mode == TimerMode.MODE_WORK && !m_pageButtons.GetIsLongMouseDown() && 717 | TomatoTimerWPF.TimerSettings.Default.GoogleCal_EnableEvent) 718 | OpenGoogleCalender(m_TimeDateStart, DateTime.Now); 719 | 720 | SetWindowFlash(false); 721 | m_bIsPause = false; 722 | m_TimeDateStart = DateTime.Now; 723 | m_TimeDatePauseStart = DateTime.Now; 724 | m_TimeSpanPause = TimeSpan.FromMinutes(0); 725 | m_TimeSpan = TimeSpan.FromMinutes(0); 726 | UpdateUI(); 727 | 728 | 729 | } 730 | 731 | private void SetWindowFlash(bool enable) 732 | { 733 | if (m_pageButtons.labelTimeWhite.Visibility == Visibility.Visible) 734 | return; 735 | 736 | FLASHWINFO fw = new FLASHWINFO(); 737 | 738 | fw.cbSize = Convert.ToUInt32(Marshal.SizeOf(typeof(FLASHWINFO))); 739 | fw.hwnd = m_hwnd;// new WindowInteropHelper(this).Handle; 740 | fw.dwFlags = enable ? 2 : 0; 741 | //fw.uCount = enable ? UInt32.MaxValue : 0; 742 | fw.uCount = enable ? (UInt32)(10*60) : 0; 743 | 744 | FlashWindowEx(ref fw); 745 | } 746 | 747 | public void OpenGoogleCalender(DateTime startTime, DateTime endTime) 748 | { 749 | 750 | String strTimeStart, strTimeEnd, gcalUrl; 751 | DateTime dateStartUTC, dateEndUTC; 752 | 753 | dateStartUTC = startTime.ToUniversalTime(); 754 | dateEndUTC = endTime.ToUniversalTime(); 755 | //dateEnd = DateTime.UtcNow; 756 | 757 | strTimeStart = String.Format("{0:yyyyMMdd}", dateStartUTC) + "T" + String.Format("{0:HHmmss}", dateStartUTC) + "Z"; 758 | strTimeEnd = String.Format("{0:yyyyMMdd}", dateEndUTC) + "T" + String.Format("{0:HHmmss}", dateEndUTC) + "Z"; 759 | 760 | //gcalUrl = "http://www.google.com/calendar/event?action=TEMPLATE"; 761 | gcalUrl = "https://calendar.google.com/calendar/r/eventedit?action=TEMPLATE"; 762 | if (TomatoTimerWPF.TimerSettings.Default.GoogleCal_text.Length != 0) 763 | { 764 | String textUrlEncode = System.Web.HttpUtility.UrlEncode(TomatoTimerWPF.TimerSettings.Default.GoogleCal_text); 765 | //MessageBox.Show("[" +TomatoTimerWPF.TimerSettings.Default.GoogleCal_text +"]->[" + textUrlEncode +"]"); 766 | gcalUrl += "&text=" + textUrlEncode; 767 | } 768 | if (TomatoTimerWPF.TimerSettings.Default.GoogleCal_src.Length != 0) 769 | { 770 | if (TomatoTimerWPF.TimerSettings.Default.GoogleCal_src.IndexOf("@")!=-1) 771 | { 772 | gcalUrl += "&src=" + System.Web.HttpUtility.UrlEncode(TomatoTimerWPF.TimerSettings.Default.GoogleCal_src); 773 | } 774 | else 775 | gcalUrl += "&src=" + TomatoTimerWPF.TimerSettings.Default.GoogleCal_src; 776 | } 777 | 778 | gcalUrl += "&dates=" + strTimeStart + "/" + strTimeEnd; 779 | //MessageBox.Show(gcalUrl); 780 | if (TomatoTimerWPF.TimerSettings.Default.GoogleCal_CopyToClipboard) 781 | { 782 | System.Windows.Clipboard.SetText(gcalUrl); 783 | } 784 | 785 | System.Diagnostics.Process.Start(gcalUrl); 786 | } 787 | 788 | 789 | public void SwitchToButtons() 790 | { 791 | if (ucContent.Children.Count == 0) 792 | return; 793 | m_taSlideOut.To = new Thickness(0, this.Height, 0, 0); 794 | m_taSlideIn.From = new Thickness(0, -this.Height, 0, 0); 795 | 796 | pages.Push(m_pageButtons); 797 | 798 | FrameworkElement ucCurrent = ucContent.Children[0] as FrameworkElement; 799 | m_sbAniOut.Begin(ucCurrent); 800 | 801 | 802 | } 803 | 804 | Stack pages = new Stack(); 805 | 806 | public void SwitchToSettings() 807 | { 808 | if (ucContent.Children.Count == 0) 809 | return; 810 | 811 | m_taSlideOut.To = new Thickness(0, -this.Height, 0, 0); 812 | m_taSlideIn.From = new Thickness(0, this.Height, 0, 0); 813 | 814 | pages.Push(m_pageSettings); 815 | 816 | FrameworkElement ucCurrent = ucContent.Children[0] as FrameworkElement; 817 | m_sbAniOut.Begin(ucCurrent); 818 | 819 | } 820 | 821 | public void SwitchFromSettingToSound() 822 | { 823 | if (ucContent.Children.Count == 0) 824 | return; 825 | 826 | m_taSlideOut.To = new Thickness(-this.Width, 0, 0, 0); 827 | m_taSlideIn.From = new Thickness(this.Width, 0, 0, 0); 828 | 829 | pages.Push(m_pageSoundSettings); 830 | FrameworkElement ucCurrent = ucContent.Children[0] as FrameworkElement; 831 | m_sbAniOut.Begin(ucCurrent); 832 | 833 | } 834 | 835 | 836 | public void SwitchFromSoundToSetting() 837 | { 838 | if (ucContent.Children.Count == 0) 839 | return; 840 | 841 | m_taSlideOut.To = new Thickness(this.Width, 0, 0, 0); 842 | m_taSlideIn.From = new Thickness(-this.Width, 0, 0, 0); 843 | 844 | pages.Push(m_pageSettings); 845 | UserControl ucCurrent = ucContent.Children[0] as UserControl; 846 | m_sbAniOut.Begin(ucCurrent); 847 | 848 | } 849 | 850 | private void Storyboard_Completed(object sender, EventArgs e) 851 | { 852 | if (pages.Count != 0) 853 | { 854 | UserControl page = pages.Pop(); 855 | 856 | Page_Buttons pageButtons = page as Page_Buttons; 857 | if (pageButtons != null) 858 | { 859 | UpdateUI(); 860 | btnAlwaysOnTop.Visibility = Visibility.Visible; 861 | } 862 | else 863 | btnAlwaysOnTop.Visibility = Visibility.Collapsed; 864 | ucContent.Children.Clear(); 865 | ucContent.Children.Add(page); 866 | 867 | m_sbAniIn.Begin(page); 868 | } 869 | } 870 | 871 | 872 | private void btnAlwaysOnTop_Click(object sender, RoutedEventArgs e) 873 | { 874 | this.ToggleAlwaysOnTop(); 875 | TomatoTimerWPF.TimerSettings.Default.AlwaysOnTop = this.Topmost; 876 | } 877 | 878 | private void ToggleAlwaysOnTop() 879 | { 880 | this.Topmost = btnAlwaysOnTop.IsChecked.HasValue && btnAlwaysOnTop.IsChecked.Value; 881 | } 882 | 883 | 884 | private void menuClose_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 885 | { 886 | //MessageBox.Show("menuClose_MouseLeftButtonUp"); 887 | this.SavePropertiesAndClose(true); 888 | } 889 | 890 | private void menuCloseDontSave_Click(object sender, RoutedEventArgs e) 891 | { 892 | //MessageBox.Show("menuCloseDontSave_Click"); 893 | this.SavePropertiesAndClose(false); 894 | } 895 | 896 | //private void menuCloseDontSave_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 897 | //{ 898 | // MessageBox.Show("menuCloseDontSave_MouseLeftButtonUp"); 899 | // m_window.SavePropertiesAndClose(false); 900 | //} 901 | 902 | //private void menuCloseDontSave_MouseEnter(object sender, MouseEventArgs e) 903 | //{ 904 | // //menuClose.ReleaseMouseCapture(); 905 | // //MessageBox.Show("menuCloseDontSave_MouseEnter"); 906 | //} 907 | 908 | private void menuCloseSave_Click(object sender, RoutedEventArgs e) 909 | { 910 | //MessageBox.Show("menuCloseSave_Click"); 911 | this.SavePropertiesAndClose(true); 912 | } 913 | 914 | private void Grid_MouseEnter(object sender, MouseEventArgs e) 915 | { 916 | m_timer.Interval = 50; 917 | m_taSlideIn.From = new Thickness(0, 0, 0, 0); 918 | m_sbAniIn.Begin(spWindowControlStackPanel); 919 | 920 | } 921 | 922 | private void Grid_MouseLeave(object sender, MouseEventArgs e) 923 | { 924 | m_timer.Interval = 1000; 925 | m_taSlideOut.To = new Thickness(0, 0, 0, 0); 926 | m_sbAniOut.Begin(spWindowControlStackPanel); 927 | } 928 | 929 | private void ThumbButtonPlay_Click(object sender, EventArgs e) 930 | { 931 | Resume(); 932 | } 933 | 934 | private void ThumbButtonPause_Click(object sender, EventArgs e) 935 | { 936 | Pause(); 937 | } 938 | 939 | private void ThumbButtonReset_Click(object sender, EventArgs e) 940 | { 941 | Reset(); 942 | } 943 | 944 | private void ThumbButtonGoToWork_Click(object sender, EventArgs e) 945 | { 946 | StartWork(); 947 | } 948 | 949 | private void ThumbButtonTakeABreak_Click(object sender, EventArgs e) 950 | { 951 | StartRelax(); 952 | } 953 | 954 | private void Window_Activated(object sender, EventArgs e) 955 | { 956 | if (m_bIsOverTime && m_mode == TimerMode.MODE_WORK) 957 | SetWindowFlash(false); 958 | } 959 | } 960 | } 961 | --------------------------------------------------------------------------------