diff --git a/OneMore/Helpers/Office/Office.cs b/OneMore/Helpers/Office/Office.cs index ae1c996008..5e1536f4b4 100644 --- a/OneMore/Helpers/Office/Office.cs +++ b/OneMore/Helpers/Office/Office.cs @@ -166,8 +166,11 @@ private static bool DarkModeLightsOn() /// /// Determines if Windows is set to dark mode /// - /// - private static bool SystemDefaultDarkMode() + /// True if the system default is dark mode + /// + /// Declared as public so it can be used by OneMoreCalendar + /// + public static bool SystemDefaultDarkMode() { using var key = Registry.CurrentUser.OpenSubKey( @"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize"); diff --git a/OneMoreCalendar/AboutDialog.Designer.cs b/OneMoreCalendar/AboutDialog.Designer.cs index e24244af58..1914dc6bd2 100644 --- a/OneMoreCalendar/AboutDialog.Designer.cs +++ b/OneMoreCalendar/AboutDialog.Designer.cs @@ -34,10 +34,10 @@ private void InitializeComponent () this.copyLabel = new System.Windows.Forms.Label(); this.okButton = new OneMoreCalendar.MoreButton(); this.pleaseLabel = new System.Windows.Forms.Label(); - this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.logoBox = new System.Windows.Forms.PictureBox(); this.sponsorButton = new River.OneMoreAddIn.UI.MoreButton(); this.homeLink = new River.OneMoreAddIn.UI.MoreLinkLabel(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.logoBox)).BeginInit(); this.SuspendLayout(); // // titleLabel @@ -96,15 +96,15 @@ private void InitializeComponent () this.pleaseLabel.TabIndex = 14; this.pleaseLabel.Text = "Please support future development of OneMore"; // - // pictureBox1 + // logoBox // - this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image"))); - this.pictureBox1.Location = new System.Drawing.Point(12, 12); - this.pictureBox1.Name = "pictureBox1"; - this.pictureBox1.Size = new System.Drawing.Size(124, 125); - this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; - this.pictureBox1.TabIndex = 0; - this.pictureBox1.TabStop = false; + this.logoBox.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image"))); + this.logoBox.Location = new System.Drawing.Point(12, 12); + this.logoBox.Name = "pictureBox1"; + this.logoBox.Size = new System.Drawing.Size(124, 125); + this.logoBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.logoBox.TabIndex = 0; + this.logoBox.TabStop = false; // // sponsorButton // @@ -154,7 +154,7 @@ private void InitializeComponent () this.Controls.Add(this.copyLabel); this.Controls.Add(this.versionLabel); this.Controls.Add(this.titleLabel); - this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.logoBox); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.MaximizeBox = false; this.MinimizeBox = false; @@ -163,7 +163,7 @@ private void InitializeComponent () this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "OneMore Calendar"; - ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.logoBox)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -171,11 +171,11 @@ private void InitializeComponent () #endregion - private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.PictureBox logoBox; private System.Windows.Forms.Label titleLabel; private System.Windows.Forms.Label versionLabel; private System.Windows.Forms.Label copyLabel; - private MoreButton okButton; + private OneMoreCalendar.MoreButton okButton; private River.OneMoreAddIn.UI.MoreLinkLabel homeLink; private River.OneMoreAddIn.UI.MoreButton sponsorButton; private System.Windows.Forms.Label pleaseLabel; diff --git a/OneMoreCalendar/AboutDialog.cs b/OneMoreCalendar/AboutDialog.cs index d0adb1bfb9..dd064dfccd 100644 --- a/OneMoreCalendar/AboutDialog.cs +++ b/OneMoreCalendar/AboutDialog.cs @@ -5,11 +5,10 @@ namespace OneMoreCalendar { using System; - using System.Drawing; using System.Windows.Forms; - internal partial class AboutDialog : Form + internal partial class AboutDialog : ThemedForm { public AboutDialog() @@ -19,11 +18,18 @@ public AboutDialog() sponsorButton.SetHandCursor(); // TODO: beta - versionLabel.Text = string.Format(versionLabel.Text, AssemblyInfo.Version) + " (BETA)"; + versionLabel.Text = string.Format(versionLabel.Text, AssemblyInfo.Version); copyLabel.Text = string.Format(copyLabel.Text, DateTime.Now.Year); } + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + BackColor = Theme.BackColor; + } + + private void OK(object sender, EventArgs e) { Close(); diff --git a/OneMoreCalendar/CalendarForm.cs b/OneMoreCalendar/CalendarForm.cs index 487c80263e..a4d20f2a60 100644 --- a/OneMoreCalendar/CalendarForm.cs +++ b/OneMoreCalendar/CalendarForm.cs @@ -4,8 +4,10 @@ namespace OneMoreCalendar { + using OneMoreCalendar.Properties; using River.OneMoreAddIn; using System; + using System.Drawing; using System.IO; using System.Threading.Tasks; using System.Windows.Forms; @@ -14,7 +16,7 @@ namespace OneMoreCalendar /// /// Main OneMoreCalendar form /// - public partial class CalendarForm : Form + internal partial class CalendarForm : ThemedForm { private DateTime date; private CalendarPages pages; @@ -35,9 +37,6 @@ public CalendarForm() Width = 1500; // TODO: save as settings? Height = 1000; - - // TODO: beta - Text = $"{Text} (BETA)"; } @@ -72,6 +71,32 @@ protected override async void OnLoad(EventArgs e) } + public override void OnThemeChange() + { + if (Theme.DarkMode) + { + var fromColor = ColorTranslator.FromHtml("#FF80397B"); + todayButton.Image = Resources.today_32.MapColor(fromColor, Color.MediumOrchid); + monthButton.Image = Resources.month_32.MapColor(fromColor, Color.MediumOrchid); + dayButton.Image = Resources.day_32.MapColor(fromColor, Color.MediumOrchid); + settingsButton.Image = Resources.settings_32.MapColor(fromColor, Color.MediumOrchid); + } + else + { + todayButton.Image = Resources.settings_32; + monthButton.Image = Resources.month_32; + dayButton.Image = Resources.day_32; + settingsButton.Image = Resources.settings_32; + } + + nextButton.PreferredFore = Theme.LinkColor; + nextButton.PreferredBack = Theme.BackColor; + prevButton.PreferredFore = Theme.LinkColor; + prevButton.PreferredBack = Theme.BackColor; + todayButton.PreferredBack = Theme.BackColor; + } + + private async Task SetMonth(int delta) { if (delta < 1000) @@ -166,6 +191,8 @@ await settings.GetNotebookIDs(), settings.Created, settings.Modified, settings.Deleted); detailView.SetRange(date, endDate, pages); + detailView.OnThemeChange(); + contentPanel.Controls.Add(detailView); } @@ -378,6 +405,7 @@ private async void ClosingSettings(object sender, FormClosingEventArgs e) if (settingsForm.DialogResult == DialogResult.OK) { + Theme.InitializeTheme(this); await SetMonth(date.Year); } } diff --git a/OneMoreCalendar/DetailView.cs b/OneMoreCalendar/DetailView.cs index a51e690e40..a1d39996eb 100644 --- a/OneMoreCalendar/DetailView.cs +++ b/OneMoreCalendar/DetailView.cs @@ -13,7 +13,7 @@ namespace OneMoreCalendar using System.Windows.Forms; - internal partial class DetailView : UserControl, ICalendarView + internal partial class DetailView : ThemedUserControl, ICalendarView { private sealed class DayItem { @@ -52,6 +52,12 @@ public DetailView() } + public override void OnThemeChange() + { + BackColor = Theme.BackColor; + } + + public event CalendarDayHandler ClickedDay; public event CalendarHoverHandler HoverPage; public event CalendarPageHandler ClickedPage; @@ -60,6 +66,7 @@ public DetailView() public void SetRange(DateTime startDate, DateTime endDate, CalendarPages pages) { + SuspendLayout(); listbox.Items.Clear(); var date = startDate; @@ -89,27 +96,26 @@ public void SetRange(DateTime startDate, DateTime endDate, CalendarPages pages) } Invalidate(); + ResumeLayout(); } private void HeaderPanelPaint(object sender, PaintEventArgs e) { - using (var font = new Font("Segoe UI Light", 10.0f, FontStyle.Regular)) - { - headerPanel.Height = font.Height + VPadding; - var y = (headerPanel.Height - font.Height) / 2; + using var font = new Font("Segoe UI Light", 10.0f, FontStyle.Regular); + headerPanel.Height = font.Height + VPadding; + var y = (headerPanel.Height - font.Height) / 2; - var size = e.Graphics.MeasureString("DATE", font); - e.Graphics.DrawString("DATE", font, Brushes.SlateGray, - (HeadWidth - size.Width) / 2, y); + var size = e.Graphics.MeasureString("DATE", font); + var width = e.ClipRectangle.Width - SystemInformation.VerticalScrollBarWidth; - var width = e.ClipRectangle.Width - SystemInformation.VerticalScrollBarWidth; + using var brush = new SolidBrush(Theme.MonthDayFore); - e.Graphics.DrawString("SECTION", font, Brushes.SlateGray, HeadWidth + 20, y); - e.Graphics.DrawString("PAGE", font, Brushes.SlateGray, HeadWidth + PathWidth + 40, y); - e.Graphics.DrawString("CREATED", font, Brushes.SlateGray, width - DateWidth * 2, y); - e.Graphics.DrawString("MODIFIED", font, Brushes.SlateGray, width - DateWidth, y); - } + e.Graphics.DrawString("DATE", font, brush, (HeadWidth - size.Width) / 2, y); + e.Graphics.DrawString("SECTION", font, brush, HeadWidth + 20, y); + e.Graphics.DrawString("PAGE", font, brush, HeadWidth + PathWidth + 40, y); + e.Graphics.DrawString("CREATED", font, brush, width - DateWidth * 2, y); + e.Graphics.DrawString("MODIFIED", font, brush, width - DateWidth, y); } @@ -138,9 +144,11 @@ private void ListBoxDrawItem(object sender, DrawItemEventArgs e) return; } - e.Graphics.FillRectangle(e.Index % 2 == 1 ? AppColors.RowBrush : Brushes.White, e.Bounds); + using var fill = new SolidBrush(e.Index % 2 == 1 ? Theme.DetailOddBack : Theme.DetailEvenBack); + e.Graphics.FillRectangle(fill, e.Bounds); - e.Graphics.DrawLine(Pens.LightGray, e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Top); + using var line = new Pen(Theme.MonthGrid); + e.Graphics.DrawLine(line, e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Top); //e.Graphics.DrawLine(Pens.LightGray, HeadWidth, e.Bounds.Top, HeadWidth, e.Bounds.Bottom); if (listbox.Items[e.Index] is DayItem day) @@ -151,7 +159,11 @@ private void ListBoxDrawItem(object sender, DrawItemEventArgs e) // header var head = day.Date.ToString("ddd, MMM d"); var size = e.Graphics.MeasureString(head, listbox.Font); - e.Graphics.DrawString(head, listbox.Font, Brushes.Black, + + using var fore = new SolidBrush(Theme.ForeColor); + using var gray = new SolidBrush(Color.Gray); + + e.Graphics.DrawString(head, listbox.Font, fore, (HeadWidth - size.Width) / 2, e.Bounds.Top + (e.Bounds.Height - size.Height) / 2); @@ -162,7 +174,7 @@ private void ListBoxDrawItem(object sender, DrawItemEventArgs e) // predict width of page title size = e.Graphics.MeasureString(page.Title, listbox.Font); - var color = page.IsDeleted ? Brushes.Gray : Brushes.Black; + var color = page.IsDeleted ? gray : fore; // section e.Graphics.DrawString(page.Path, @@ -239,11 +251,14 @@ private void ListBoxMouseMove(object sender, MouseEventArgs e) using (var g = listbox.CreateGraphics()) { var index = listbox.Items.IndexOf(hotday); - g.FillRectangle(index % 2 == 1 ? AppColors.RowBrush : Brushes.White, hotpage.Bounds); + using var fill = new SolidBrush(index % 2 == 1 ? Theme.DetailOddBack : Theme.DetailEvenBack); + g.FillRectangle(fill, hotpage.Bounds); + + using var fore = new SolidBrush(hotpage.IsDeleted ? Color.Gray : Theme.ForeColor); g.DrawString(hotpage.Title, hotpage.IsDeleted ? deletedFont : listbox.Font, - hotpage.IsDeleted ? Brushes.Gray : Brushes.Black, + fore, hotpage.Bounds, format); } @@ -258,11 +273,13 @@ private void ListBoxMouseMove(object sender, MouseEventArgs e) using (var g = listbox.CreateGraphics()) { var index = listbox.Items.IndexOf(day); - g.FillRectangle(index % 2 == 1 ? AppColors.RowBrush : Brushes.White, page.Bounds); + using var fill = new SolidBrush(index % 2 == 1 ? Theme.DetailOddBack : Theme.DetailEvenBack); + g.FillRectangle(fill, page.Bounds); + using var fore = new SolidBrush(Theme.Highlight); g.DrawString(page.Title, page.IsDeleted ? deletedFont : hotFont, - Brushes.DarkOrchid, page.Bounds, format); + fore, page.Bounds, format); } HoverPage?.Invoke(this, new CalendarPageEventArgs(page)); diff --git a/OneMoreCalendar/MonthView.cs b/OneMoreCalendar/MonthView.cs index aacfce86bf..e877d4ad84 100644 --- a/OneMoreCalendar/MonthView.cs +++ b/OneMoreCalendar/MonthView.cs @@ -13,7 +13,7 @@ namespace OneMoreCalendar using System.Windows.Forms; - internal partial class MonthView : UserControl, ICalendarView + internal partial class MonthView : ThemedUserControl, ICalendarView { private enum Hottype { Day, Page, Up, Down } @@ -208,10 +208,8 @@ private void ScrollDay(Hotspot spot) spot.Day.ScrollOffset = offset; - using (var g = CreateGraphics()) - { - PaintDay(g, spot.Day); - } + using var g = CreateGraphics(); + PaintDay(g, spot.Day); } @@ -241,9 +239,11 @@ protected override void OnMouseMove(MouseEventArgs e) { using (var g = CreateGraphics()) { - g.FillRectangle( - hotspot.Page.Modified.Month == date.Month ? Brushes.White : Brushes.WhiteSmoke, - hotspot.Bounds); + using var brush = hotspot.Page.Modified.Month == date.Month + ? new SolidBrush(Theme.MonthPrimary) + : new SolidBrush(Theme.MonthSecondary); + + g.FillRectangle(brush, hotspot.Bounds); if (hotspot.Page.IsDeleted) { @@ -253,8 +253,10 @@ protected override void OnMouseMove(MouseEventArgs e) } else { - var brush = hotspot.InMonth ? Brushes.Black : Brushes.Gray; - g.DrawString(hotspot.Page.Title, Font, brush, hotspot.Bounds, format); + var titleBrush = new SolidBrush(hotspot.InMonth + ? Theme.MonthTodayFore : Theme.MonthDayFore); + + g.DrawString(hotspot.Page.Title, Font, titleBrush, hotspot.Bounds, format); } } @@ -273,12 +275,12 @@ protected override void OnMouseMove(MouseEventArgs e) { using (var g = CreateGraphics()) { - var brush = spot.InMonth ? Brushes.White : Brushes.WhiteSmoke; - g.FillRectangle(brush, spot.Bounds); + using var fill = new SolidBrush(spot.InMonth ? Theme.MonthPrimary : Theme.MonthSecondary); + g.FillRectangle(fill, spot.Bounds); + using var fore = new SolidBrush(Theme.Highlight); g.DrawString(spot.Page.Title, - spot.Page.IsDeleted ? deletedFont : hotFont, - Brushes.DarkOrchid, + spot.Page.IsDeleted ? deletedFont : hotFont, fore, new Rectangle(spot.Bounds.X, spot.Bounds.Y, width, spot.Bounds.Height), format); } @@ -294,26 +296,30 @@ protected override void OnMouseMove(MouseEventArgs e) protected override void OnPaint(PaintEventArgs e) { + SuspendLayout(); + base.OnPaint(e); hotspots.Clear(); PaintGrid(e); PaintDays(e); + + ResumeLayout(); } private void PaintGrid(PaintEventArgs e) { - e.Graphics.Clear(Color.White); + e.Graphics.Clear(Theme.BackColor); // day of week names... - var dowFont = new Font("Segoe UI Light", 10.0f, FontStyle.Regular); + using var dowFont = new Font("Segoe UI Light", 10.0f, FontStyle.Regular); var culture = Thread.CurrentThread.CurrentUICulture.DateTimeFormat; - dowOffset = dowFont.Height + 2; + dowOffset = dowFont.Height; - var dowFormat = new StringFormat + using var dowFormat = new StringFormat { Alignment = StringAlignment.Center, FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.LineLimit, @@ -324,14 +330,15 @@ private void PaintGrid(PaintEventArgs e) // day names and vertical lines... - var pen = new Pen(Color.DarkGray, 0.1f); + using var pen = new Pen(Theme.MonthGrid, 0.1f); var dow = firstDow == DayOfWeek.Sunday ? 0 : 1; for (int i = 0; i < 7; i++, dow++) { var name = culture.GetDayName((DayOfWeek)(dow % 7)).ToUpper(); var clip = new Rectangle(dayWidth * i, 1, dayWidth, dowFont.Height + 2); - e.Graphics.DrawString(name, dowFont, Brushes.SlateGray, clip, dowFormat); + using var brush = new SolidBrush(Theme.MonthDayFore); + e.Graphics.DrawString(name, dowFont, brush, clip, dowFormat); if (i < 6) { @@ -350,10 +357,6 @@ private void PaintGrid(PaintEventArgs e) 0, i * dayHeight + dowOffset, e.ClipRectangle.Width, i * dayHeight + dowOffset); } - - dowFormat.Dispose(); - dowFont.Dispose(); - pen.Dispose(); } @@ -364,10 +367,13 @@ private void PaintDays(PaintEventArgs e) var row = 0; var col = 0; - var headFont = new Font("Segoe UI", 10.0f, FontStyle.Regular); - var headFore = new SolidBrush(ColorTranslator.FromHtml(TodayHeadColor)); - var headBack = new SolidBrush(ColorTranslator.FromHtml(HeadBackColor)); - var headPen = new Pen(Color.DarkGray, 0.1f); + using var headFont = new Font("Segoe UI", 10.0f, FontStyle.Regular); + using var headFore = new SolidBrush(Theme.MonthDayFore); + using var headBack = new SolidBrush(Theme.MonthDayBack); + using var todayBack = new SolidBrush(Theme.MonthTodayBack); + using var gridPen = new Pen(Theme.MonthGrid, 0.1f); + using var inbrush = new SolidBrush(Theme.MonthTodayFore); + using var outbrush = new SolidBrush(Theme.MonthDayFore); // how many lines fit in each day box maxItems = (((Height - dowOffset) / weeks) - headFont.Height - 2) / Font.Height; @@ -382,15 +388,17 @@ private void PaintDays(PaintEventArgs e) col * dayWidth, row * dayHeight + dowOffset, dayWidth, headFont.Height + 2); + var today = day.Date.Date.Equals(now.Date); + e.Graphics.FillRectangle( // compare only date part - day.Date.Date.Equals(now.Date) ? headFore : headBack, + today ? todayBack : headBack, box); - e.Graphics.DrawRectangle(headPen, box); + e.Graphics.DrawRectangle(gridPen, box); e.Graphics.DrawString(day.Date.Day.ToString(), headFont, - day.InMonth ? Brushes.Black : Brushes.Gray, + day.InMonth ? inbrush : outbrush, box.X + 3, box.Y + 1); // record day header box @@ -417,17 +425,13 @@ private void PaintDays(PaintEventArgs e) row++; } } - - headFore.Dispose(); - headFont.Dispose(); - headBack.Dispose(); - headPen.Dispose(); } private void PaintDay(Graphics g, CalendarDay day) { - g.FillRectangle(day.InMonth ? Brushes.White : Brushes.WhiteSmoke, day.Bounds); + using var backBrush = new SolidBrush(day.InMonth ? Theme.MonthPrimary : Theme.MonthSecondary); + g.FillRectangle(backBrush, day.Bounds); if (day.Pages.Count == 0) { @@ -461,8 +465,11 @@ private void PaintDay(Graphics g, CalendarDay day) width, Font.Height); var font = page.IsDeleted ? deletedFont : Font; - g.DrawString(page.Title, font, - page.IsDeleted || !day.InMonth ? Brushes.Gray : Brushes.Black, clip, format); + using var brush = new SolidBrush(page.IsDeleted || day.InMonth + ? Theme.MonthTodayFore + : Theme.MonthDayFore); + + g.DrawString(page.Title, font, brush, clip, format); // actual length of string for hyperlink hovering var size = g.MeasureString(page.Title, font, clip.Width, format).ToSize(); @@ -531,7 +538,8 @@ private void MakeScrollButton(Hottype type, CalendarDay day, Point location) var button = new MoreButton { Font = moreFont, - ForeColor = AppColors.ControlColor, + PreferredBack = Theme.MonthPrimary, + PreferredFore = Theme.LinkColor, Location = location, Text = type == Hottype.Up ? LessGlyph : MoreGlyph, Size = new Size(moreSize.Width + 4, moreSize.Height + 2), diff --git a/OneMoreCalendar/OneMoreCalendar.csproj b/OneMoreCalendar/OneMoreCalendar.csproj index de6d6ecb99..00ccfe7589 100644 --- a/OneMoreCalendar/OneMoreCalendar.csproj +++ b/OneMoreCalendar/OneMoreCalendar.csproj @@ -1,6 +1,9 @@  + + 9.0 + Debug AnyCPU @@ -63,7 +66,7 @@ DetailView.cs - + @@ -117,6 +120,12 @@ SnapshotForm.cs + + Form + + + UserControl + Form diff --git a/OneMoreCalendar/OneNoteProvider.cs b/OneMoreCalendar/OneNoteProvider.cs index 6d0d31132d..6656003719 100644 --- a/OneMoreCalendar/OneNoteProvider.cs +++ b/OneMoreCalendar/OneNoteProvider.cs @@ -197,12 +197,11 @@ public async Task NavigateTo(string pageID) using (one = new OneNote()) { var url = one.GetHyperlink(pageID, string.Empty); - if (url != null) + if (!string.IsNullOrEmpty(url)) { await one.NavigateTo(url); } } - } } } diff --git a/OneMoreCalendar/Properties/AssemblyInfo.cs b/OneMoreCalendar/Properties/AssemblyInfo.cs index 381100e113..97c495e96d 100644 Binary files a/OneMoreCalendar/Properties/AssemblyInfo.cs and b/OneMoreCalendar/Properties/AssemblyInfo.cs differ diff --git a/OneMoreCalendar/SettingsForm.Designer.cs b/OneMoreCalendar/SettingsForm.Designer.cs index b2fa2cd7be..b6a356f7db 100644 --- a/OneMoreCalendar/SettingsForm.Designer.cs +++ b/OneMoreCalendar/SettingsForm.Designer.cs @@ -1,4 +1,6 @@ -namespace OneMoreCalendar +using System.Drawing; + +namespace OneMoreCalendar { partial class SettingsForm { @@ -30,6 +32,7 @@ private void InitializeComponent() { this.optionsLabel = new System.Windows.Forms.Label(); this.notebooksLabel = new System.Windows.Forms.Label(); + this.themeLabel = new System.Windows.Forms.Label(); this.settingsPanel = new System.Windows.Forms.Panel(); this.emptyBox = new OneMoreCalendar.MoreCheckBox(); this.deletedBox = new OneMoreCalendar.MoreCheckBox(); @@ -38,6 +41,9 @@ private void InitializeComponent() this.notebooksBox = new OneMoreCalendar.MoreCheckedListBox(); this.createdBox = new OneMoreCalendar.MoreCheckBox(); this.modifiedBox = new OneMoreCalendar.MoreCheckBox(); + this.darkModeButton = new OneMoreCalendar.MoreRadioButton(); + this.lightModeButton = new OneMoreCalendar.MoreRadioButton(); + this.systemModeButton = new OneMoreCalendar.MoreRadioButton(); this.logLink = new River.OneMoreAddIn.UI.MoreLinkLabel(); this.aboutLink = new River.OneMoreAddIn.UI.MoreLinkLabel(); this.settingsPanel.SuspendLayout(); @@ -60,12 +66,23 @@ private void InitializeComponent() this.notebooksLabel.AutoSize = true; this.notebooksLabel.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.notebooksLabel.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(115)))), ((int)(((byte)(53)))), ((int)(((byte)(110))))); - this.notebooksLabel.Location = new System.Drawing.Point(23, 215); + this.notebooksLabel.Location = new System.Drawing.Point(23, 349); this.notebooksLabel.Name = "notebooksLabel"; this.notebooksLabel.Size = new System.Drawing.Size(131, 32); this.notebooksLabel.TabIndex = 1; this.notebooksLabel.Text = "Notebooks"; // + // themeLabel + // + this.themeLabel.AutoSize = true; + this.themeLabel.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.themeLabel.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(115)))), ((int)(((byte)(53)))), ((int)(((byte)(110))))); + this.themeLabel.Location = new System.Drawing.Point(22, 202); + this.themeLabel.Name = "themeLabel"; + this.themeLabel.Size = new System.Drawing.Size(88, 32); + this.themeLabel.TabIndex = 1; + this.themeLabel.Text = "Theme"; + // // settingsPanel // this.settingsPanel.BackColor = System.Drawing.Color.Transparent; @@ -78,14 +95,18 @@ private void InitializeComponent() this.settingsPanel.Controls.Add(this.modifiedBox); this.settingsPanel.Controls.Add(this.notebooksLabel); this.settingsPanel.Controls.Add(this.optionsLabel); + this.settingsPanel.Controls.Add(this.themeLabel); + this.settingsPanel.Controls.Add(this.darkModeButton); + this.settingsPanel.Controls.Add(this.lightModeButton); + this.settingsPanel.Controls.Add(this.systemModeButton); this.settingsPanel.Controls.Add(this.logLink); this.settingsPanel.Controls.Add(this.aboutLink); this.settingsPanel.Dock = System.Windows.Forms.DockStyle.Fill; - this.settingsPanel.Location = new System.Drawing.Point(0, 0); + this.settingsPanel.Location = new System.Drawing.Point(4, 4); this.settingsPanel.Margin = new System.Windows.Forms.Padding(0); this.settingsPanel.Name = "settingsPanel"; - this.settingsPanel.Padding = new System.Windows.Forms.Padding(20); - this.settingsPanel.Size = new System.Drawing.Size(518, 486); + this.settingsPanel.Padding = new System.Windows.Forms.Padding(20, 20, 10, 10); + this.settingsPanel.Size = new System.Drawing.Size(507, 598); this.settingsPanel.TabIndex = 2; // // emptyBox @@ -115,8 +136,10 @@ private void InitializeComponent() this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.okButton.BackColor = System.Drawing.SystemColors.Window; this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; - this.okButton.Location = new System.Drawing.Point(349, 439); + this.okButton.Location = new System.Drawing.Point(338, 551); this.okButton.Name = "okButton"; + this.okButton.PreferredBack = System.Drawing.Color.Empty; + this.okButton.PreferredFore = System.Drawing.Color.Empty; this.okButton.ShowBorder = true; this.okButton.Size = new System.Drawing.Size(75, 34); this.okButton.TabIndex = 9; @@ -129,8 +152,10 @@ private void InitializeComponent() this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.cancelButton.BackColor = System.Drawing.SystemColors.Window; this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(430, 439); + this.cancelButton.Location = new System.Drawing.Point(419, 551); this.cancelButton.Name = "cancelButton"; + this.cancelButton.PreferredBack = System.Drawing.Color.Empty; + this.cancelButton.PreferredFore = System.Drawing.Color.Empty; this.cancelButton.ShowBorder = true; this.cancelButton.Size = new System.Drawing.Size(75, 34); this.cancelButton.TabIndex = 8; @@ -146,9 +171,9 @@ private void InitializeComponent() this.notebooksBox.BorderStyle = System.Windows.Forms.BorderStyle.None; this.notebooksBox.CheckOnClick = true; this.notebooksBox.FormattingEnabled = true; - this.notebooksBox.Location = new System.Drawing.Point(48, 264); + this.notebooksBox.Location = new System.Drawing.Point(48, 398); this.notebooksBox.Name = "notebooksBox"; - this.notebooksBox.Size = new System.Drawing.Size(445, 138); + this.notebooksBox.Size = new System.Drawing.Size(446, 138); this.notebooksBox.TabIndex = 7; this.notebooksBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.ValidateCheckedItems); // @@ -178,14 +203,53 @@ private void InitializeComponent() this.modifiedBox.UseVisualStyleBackColor = false; this.modifiedBox.CheckedChanged += new System.EventHandler(this.ChangeFilter); // + // darkModeButton + // + this.darkModeButton.AutoSize = true; + this.darkModeButton.BackColor = System.Drawing.Color.White; + this.darkModeButton.Location = new System.Drawing.Point(48, 246); + this.darkModeButton.Name = "darkModeButton"; + this.darkModeButton.Round = true; + this.darkModeButton.Size = new System.Drawing.Size(68, 24); + this.darkModeButton.TabIndex = 12; + this.darkModeButton.Text = "Dark"; + this.darkModeButton.UseVisualStyleBackColor = false; + // + // lightModeButton + // + this.lightModeButton.AutoSize = true; + this.lightModeButton.BackColor = System.Drawing.Color.White; + this.lightModeButton.Location = new System.Drawing.Point(47, 276); + this.lightModeButton.Name = "lightModeButton"; + this.lightModeButton.Round = true; + this.lightModeButton.Size = new System.Drawing.Size(69, 24); + this.lightModeButton.TabIndex = 13; + this.lightModeButton.Text = "Light"; + this.lightModeButton.UseVisualStyleBackColor = false; + // + // systemModeButton + // + this.systemModeButton.AutoSize = true; + this.systemModeButton.BackColor = System.Drawing.Color.White; + this.systemModeButton.Checked = true; + this.systemModeButton.Location = new System.Drawing.Point(47, 306); + this.systemModeButton.Name = "systemModeButton"; + this.systemModeButton.Round = true; + this.systemModeButton.Size = new System.Drawing.Size(87, 24); + this.systemModeButton.TabIndex = 14; + this.systemModeButton.TabStop = true; + this.systemModeButton.Text = "System"; + this.systemModeButton.UseVisualStyleBackColor = false; + // // logLink // this.logLink.ActiveLinkColor = System.Drawing.Color.DarkOrchid; this.logLink.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.logLink.AutoSize = true; this.logLink.Cursor = System.Windows.Forms.Cursors.Hand; + this.logLink.HoverColor = System.Drawing.Color.MediumOrchid; this.logLink.LinkColor = System.Drawing.SystemColors.ControlDark; - this.logLink.Location = new System.Drawing.Point(15, 444); + this.logLink.Location = new System.Drawing.Point(24, 558); this.logLink.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.logLink.MaximumSize = new System.Drawing.Size(420, 0); this.logLink.Name = "logLink"; @@ -201,8 +265,9 @@ private void InitializeComponent() this.aboutLink.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.aboutLink.AutoSize = true; this.aboutLink.Cursor = System.Windows.Forms.Cursors.Hand; + this.aboutLink.HoverColor = System.Drawing.Color.MediumOrchid; this.aboutLink.LinkColor = System.Drawing.SystemColors.ControlDark; - this.aboutLink.Location = new System.Drawing.Point(135, 444); + this.aboutLink.Location = new System.Drawing.Point(144, 558); this.aboutLink.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.aboutLink.MaximumSize = new System.Drawing.Size(420, 0); this.aboutLink.Name = "aboutLink"; @@ -217,13 +282,15 @@ private void InitializeComponent() this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.White; - this.ClientSize = new System.Drawing.Size(518, 486); + this.ClientSize = new System.Drawing.Size(515, 606); this.Controls.Add(this.settingsPanel); + this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230))))); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.KeyPreview = true; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "SettingsForm"; + this.Padding = new System.Windows.Forms.Padding(4); this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; @@ -239,6 +306,7 @@ private void InitializeComponent() private System.Windows.Forms.Label optionsLabel; private System.Windows.Forms.Label notebooksLabel; + private System.Windows.Forms.Label themeLabel; private System.Windows.Forms.Panel settingsPanel; private MoreCheckBox createdBox; private MoreCheckBox modifiedBox; @@ -246,6 +314,9 @@ private void InitializeComponent() private MoreButton okButton; private MoreButton cancelButton; private MoreCheckBox deletedBox; + private MoreRadioButton lightModeButton; + private MoreRadioButton darkModeButton; + private MoreRadioButton systemModeButton; private River.OneMoreAddIn.UI.MoreLinkLabel logLink; private River.OneMoreAddIn.UI.MoreLinkLabel aboutLink; private MoreCheckBox emptyBox; diff --git a/OneMoreCalendar/SettingsForm.cs b/OneMoreCalendar/SettingsForm.cs index 196b781df0..983b81434a 100644 --- a/OneMoreCalendar/SettingsForm.cs +++ b/OneMoreCalendar/SettingsForm.cs @@ -40,6 +40,13 @@ protected override async void OnLoad(EventArgs e) deletedBox.Checked = provider.Deleted; emptyBox.Checked = !provider.Empty; + switch (provider.Theme) + { + case ThemeMode.Light: lightModeButton.Checked = true; break; + case ThemeMode.Dark: darkModeButton.Checked = true; break; + default: systemModeButton.Checked = true; break; + } + var notebooks = await provider.GetNotebooks(); notebooksBox.Items.Clear(); foreach (var notebook in notebooks) @@ -140,6 +147,11 @@ private void Apply(object sender, EventArgs e) createdBox.Checked, modifiedBox.Checked, deletedBox.Checked, !emptyBox.Checked); + provider.SetTheme( + lightModeButton.Checked + ? ThemeMode.Light + : darkModeButton.Checked ? ThemeMode.Dark : ThemeMode.System); + var ids = new List(); foreach (Notebook notebook in notebooksBox.CheckedItems) { diff --git a/OneMoreCalendar/SettingsProvider.cs b/OneMoreCalendar/SettingsProvider.cs index 482d862fb0..8fffc47362 100644 --- a/OneMoreCalendar/SettingsProvider.cs +++ b/OneMoreCalendar/SettingsProvider.cs @@ -11,7 +11,9 @@ namespace OneMoreCalendar using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; + using System.Windows.Forms.VisualStyles; using System.Xml.Linq; + using System.Xml.Serialization; /// @@ -43,10 +45,7 @@ public SettingsProvider() } } - if (root == null) - { - root = new XElement("settings"); - } + root ??= new XElement("settings"); var filters = root.Element("filters"); if (filters == null) @@ -65,6 +64,12 @@ public SettingsProvider() root.Add(notebooks); } } + + var theme = root.Elements("theme"); + if (theme == null) + { + root.Add(new XElement("theme", ThemeMode.System.ToString())); + } } @@ -91,6 +96,21 @@ public bool Empty root.Elements("filters").Elements("modified").Any(e => e.Value.Equals("true")); + public ThemeMode Theme + { + get + { + var element = root.Elements("theme").FirstOrDefault(); + if (element != null) + { + return (ThemeMode)Enum.Parse(typeof(ThemeMode), element.Value); + } + + return ThemeMode.System; + } + } + + public async Task> GetNotebookIDs() { var ids = root.Elements("notebooks").Elements("notebook").Select(e => e.Value); @@ -172,6 +192,20 @@ public void SetNotebookIDs(IEnumerable ids) } + public void SetTheme(ThemeMode mode) + { + var theme = root.Element("theme"); + if (theme == null) + { + root.Add(new XElement("theme", mode.ToString())); + } + else + { + theme.Value = mode.ToString(); + } + } + + public void Save() { PathHelper.EnsurePathExists(Path.GetDirectoryName(path)); diff --git a/OneMoreCalendar/SnapshotForm.cs b/OneMoreCalendar/SnapshotForm.cs index d60e4202d5..7f01562e84 100644 --- a/OneMoreCalendar/SnapshotForm.cs +++ b/OneMoreCalendar/SnapshotForm.cs @@ -24,6 +24,8 @@ public SnapshotForm() : base() { InitializeComponent(); + + StaticColors = true; } @@ -54,28 +56,25 @@ protected override void OnLoad(EventArgs e) if (!DesignMode && File.Exists(Path)) { - using (var source = new Metafile(Path)) - { - var target = new Bitmap(pictureBox.Width, pictureBox.Height); - using (var g = Graphics.FromImage(target)) - { - // resize the image 150% - g.DrawImage(source, - new Rectangle(0, 0, (int)(target.Width * 1.5), (int)(target.Height * 1.5)), - new Rectangle(0, 0, source.Width, source.Height), - GraphicsUnit.Pixel - ); - - //var path = System.IO.Path.Combine( - // System.IO.Path.GetTempPath(), - // System.IO.Path.GetRandomFileName() + ".png"); - - //target.Save(path, ImageFormat.Png); - //pictureBox.ImageLocation = path; - - pictureBox.Image = target; - } - } + using var source = new Metafile(Path); + var target = new Bitmap(pictureBox.Width, pictureBox.Height); + using var g = Graphics.FromImage(target); + + // resize the image 150% + g.DrawImage(source, + new Rectangle(0, 0, (int)(target.Width * 1.5), (int)(target.Height * 1.5)), + new Rectangle(0, 0, source.Width, source.Height), + GraphicsUnit.Pixel + ); + + //var path = System.IO.Path.Combine( + // System.IO.Path.GetTempPath(), + // System.IO.Path.GetRandomFileName() + ".png"); + + //target.Save(path, ImageFormat.Png); + //pictureBox.ImageLocation = path; + + pictureBox.Image = target; } } diff --git a/OneMoreCalendar/Things/AppColors.cs b/OneMoreCalendar/Things/AppColors.cs deleted file mode 100644 index d1011f27a9..0000000000 --- a/OneMoreCalendar/Things/AppColors.cs +++ /dev/null @@ -1,27 +0,0 @@ -//************************************************************************************************ -// Copyright © 2022 Steven M Cohn. All rights reserved. -//************************************************************************************************ - -namespace OneMoreCalendar -{ - using System.Drawing; - - - internal static class AppColors - { - - public static Color ControlColor => ColorTranslator.FromHtml("#FF73356E"); - - public static Brush HoverBrush => new SolidBrush(ColorTranslator.FromHtml("#FFF7EDF7")); - - public static Pen HoverPen => new Pen(ColorTranslator.FromHtml("#FFF0DAEE")); - - public static Brush RowBrush => new SolidBrush(ColorTranslator.FromHtml("#FFFDFAFE")); - - public static Brush PressedBrush => new SolidBrush(ColorTranslator.FromHtml("#FFF0DAEE")); - - public static Pen PressedPen => new Pen(ColorTranslator.FromHtml("#FF9E5499")); - - public static Brush TextBrush => new SolidBrush(Color.FromArgb(115, 53, 110)); - } -} diff --git a/OneMoreCalendar/Things/BitmapExtensions.cs b/OneMoreCalendar/Things/BitmapExtensions.cs index 06665acdea..3293226c57 100644 --- a/OneMoreCalendar/Things/BitmapExtensions.cs +++ b/OneMoreCalendar/Things/BitmapExtensions.cs @@ -28,17 +28,15 @@ public static Bitmap ConvertToGrayscale(this Bitmap original) new float[] { 0, 0, 0, 0, 1} }); - using (var attributes = new ImageAttributes()) - { - attributes.SetColorMatrix(colorMatrix); - - // redraw original image onto new image using grayscale color matrix - g.DrawImage(original, - new Rectangle(0, 0, original.Width, original.Height), - 0, 0, original.Width, original.Height, - GraphicsUnit.Pixel, - attributes); - } + using var attributes = new ImageAttributes(); + attributes.SetColorMatrix(colorMatrix); + + // redraw original image onto new image using grayscale color matrix + g.DrawImage(original, + new Rectangle(0, 0, original.Width, original.Height), + 0, 0, original.Width, original.Height, + GraphicsUnit.Pixel, + attributes); } return grayscale; diff --git a/OneMoreCalendar/Things/GraphicsExtensions.cs b/OneMoreCalendar/Things/GraphicsExtensions.cs index f95ff7031d..f27bd46a40 100644 --- a/OneMoreCalendar/Things/GraphicsExtensions.cs +++ b/OneMoreCalendar/Things/GraphicsExtensions.cs @@ -27,10 +27,8 @@ public static void DrawRoundedRectangle( if (pen == null) throw new ArgumentNullException(nameof(pen), "cannot be null"); - using (var path = CreateRoundedRectangle(bounds, cornerRadius)) - { - graphics.DrawPath(pen, path); - } + using var path = CreateRoundedRectangle(bounds, cornerRadius); + graphics.DrawPath(pen, path); } @@ -50,10 +48,8 @@ public static void FillRoundedRectangle( if (brush == null) throw new ArgumentNullException(nameof(brush), "cannot be null"); - using (var path = CreateRoundedRectangle(bounds, cornerRadius)) - { - graphics.FillPath(brush, path); - } + using var path = CreateRoundedRectangle(bounds, cornerRadius); + graphics.FillPath(brush, path); } diff --git a/OneMoreCalendar/Things/MoreButton.cs b/OneMoreCalendar/Things/MoreButton.cs index 6d5355728f..5cc4347343 100644 --- a/OneMoreCalendar/Things/MoreButton.cs +++ b/OneMoreCalendar/Things/MoreButton.cs @@ -4,6 +4,7 @@ namespace OneMoreCalendar { + using River.OneMoreAddIn; using System; using System.ComponentModel; using System.Drawing; @@ -23,7 +24,6 @@ namespace OneMoreCalendar internal class MoreButton : Button { private const int Radius = 4; - private IContainer components; private MouseEventArgs downArgs = null; private Image enabledImage; private Timer timer; @@ -48,7 +48,7 @@ public MoreButton() private void InitializeComponent() { - components = new Container(); + var components = new Container(); timer = new Timer(components); SuspendLayout(); timer.Tick += new EventHandler(Tick); @@ -69,6 +69,18 @@ private void InitializeComponent() public MouseState MouseState { get; private set; } + /// + /// Gets or sets the preferred background color + /// + public Color PreferredBack { get; set; } = Color.Empty; + + + /// + /// Gets or sets the preferred foreground color + /// + public Color PreferredFore { get; set; } = Color.Empty; + + /// /// Interval between repeat firings /// @@ -86,20 +98,21 @@ private void InitializeComponent() protected override void OnPaint(PaintEventArgs pevent) { var g = pevent.Graphics; - g.Clear(BackColor); + g.Clear(PreferredBack.IsEmpty ? Theme.BackColor : PreferredBack); if (Enabled && MouseState != MouseState.None) { - g.FillRoundedRectangle( - MouseState.HasFlag(MouseState.Pushed) ? AppColors.PressedBrush : AppColors.HoverBrush, - pevent.ClipRectangle, Radius); + using var brush = new SolidBrush(Theme.ButtonHotBack); + g.FillRoundedRectangle(brush, pevent.ClipRectangle, Radius); } if (ShowBorder || (Enabled && MouseState != MouseState.None)) { - g.DrawRoundedRectangle( - MouseState.HasFlag(MouseState.Pushed) ? AppColors.PressedPen : AppColors.HoverPen, - pevent.ClipRectangle, Radius); + using var pen = new Pen( + MouseState.HasFlag(MouseState.Pushed) ? Theme.ButtonPressBorder : + MouseState.HasFlag(MouseState.Hover) ? Theme.ButtonHotBorder : Theme.ButtonBorder); + + g.DrawRoundedRectangle(pen, pevent.ClipRectangle, Radius); } if (Image != null) @@ -113,17 +126,18 @@ protected override void OnPaint(PaintEventArgs pevent) if (!string.IsNullOrEmpty(Text)) { var size = g.MeasureString(Text, Font); - using (var brush = new SolidBrush(Enabled ? ForeColor : Color.Gray)) - { - g.DrawString(Text, Font, brush, - (pevent.ClipRectangle.Width - size.Width) / 2, - (pevent.ClipRectangle.Height - size.Height) / 2, - new StringFormat - { - Trimming = StringTrimming.EllipsisCharacter, - FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap - }); - } + using var brush = new SolidBrush(Enabled + ? PreferredFore.IsEmpty ? Theme.ButtonFore : PreferredFore + : Theme.ButtonDisabled); + + g.DrawString(Text, Font, brush, + (pevent.ClipRectangle.Width - size.Width) / 2, + (pevent.ClipRectangle.Height - size.Height) / 2, + new StringFormat + { + Trimming = StringTrimming.EllipsisCharacter, + FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap + }); } } diff --git a/OneMoreCalendar/Things/MoreCheckBox.cs b/OneMoreCalendar/Things/MoreCheckBox.cs index fbc7596ba1..ed0cae49ea 100644 --- a/OneMoreCalendar/Things/MoreCheckBox.cs +++ b/OneMoreCalendar/Things/MoreCheckBox.cs @@ -46,15 +46,17 @@ protected override void OnPaint(PaintEventArgs pevent) { if (Enabled && (MouseState != MouseState.None || Checked)) { - var brush = MouseState.HasFlag(MouseState.Pushed) || Checked - ? AppColors.PressedBrush - : AppColors.HoverBrush; + using var brush = new SolidBrush( + MouseState.HasFlag(MouseState.Pushed) || Checked + ? Theme.ButtonHotBack + : Theme.ButtonBack); g.FillRoundedRectangle(brush, pevent.ClipRectangle, Radius); - var pen = MouseState.HasFlag(MouseState.Pushed) || Checked - ? AppColors.PressedPen - : AppColors.HoverPen; + using var pen = new Pen( + MouseState.HasFlag(MouseState.Pushed) || Checked + ? Theme.ButtonPressBorder + : Theme.Border); g.DrawRoundedRectangle(pen, pevent.ClipRectangle, Radius); } @@ -66,33 +68,28 @@ protected override void OnPaint(PaintEventArgs pevent) } else { - using (var pen = new Pen(AppColors.ControlColor)) - { - g.DrawRectangle(pen, 0, 1, 14, 14); - } + using var pen = new Pen(Theme.Control); + g.DrawRectangle(pen, 0, 1, 14, 14); if (Checked) { - using (var brush = new SolidBrush(AppColors.ControlColor)) - { - g.FillRectangle(brush, 2, 3, 11, 11); - } + using var backBrush = new SolidBrush(Theme.Control); + g.FillRectangle(backBrush, 2, 3, 11, 11); } var size = g.MeasureString(Text, Font); - using (var brush = new SolidBrush(ForeColor)) - { - g.DrawString(Text, Font, brush, - new Rectangle(16, // standard icon size - (pevent.ClipRectangle.Height - (int)size.Height) / 2, - pevent.ClipRectangle.Width - 16, - (int)size.Height), - new StringFormat - { - Trimming = StringTrimming.EllipsisCharacter, - FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap - }); - } + using var brush = new SolidBrush(ForeColor); + + g.DrawString(Text, Font, brush, + new Rectangle(16, // standard icon size + (pevent.ClipRectangle.Height - (int)size.Height) / 2, + pevent.ClipRectangle.Width - 16, + (int)size.Height), + new StringFormat + { + Trimming = StringTrimming.EllipsisCharacter, + FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap + }); } } diff --git a/OneMoreCalendar/Things/MoreCheckedListBox.cs b/OneMoreCalendar/Things/MoreCheckedListBox.cs index dc381ce957..2301bb3cb2 100644 --- a/OneMoreCalendar/Things/MoreCheckedListBox.cs +++ b/OneMoreCalendar/Things/MoreCheckedListBox.cs @@ -10,8 +10,6 @@ namespace OneMoreCalendar internal class MoreCheckedListBox : CheckedListBox { - private const string BoxColor = "#FF73356E"; - public MoreCheckedListBox() : base() @@ -29,23 +27,16 @@ protected override void OnDrawItem(DrawItemEventArgs e) var g = e.Graphics; - using (var brush = new SolidBrush(BackColor)) - { - g.FillRectangle(brush, 0, e.Bounds.Y, e.Bounds.Width, 16); - } + using var fill = new SolidBrush(BackColor); + g.FillRectangle(fill, 0, e.Bounds.Y, e.Bounds.Width, 16); - var boxColor = ColorTranslator.FromHtml(BoxColor); - using (var pen = new Pen(boxColor)) - { - g.DrawRectangle(pen, 0, e.Bounds.Y + 1, 12, 12); - } + using var pen = new Pen(Theme.Control); + g.DrawRectangle(pen, 0, e.Bounds.Y + 1, 12, 12); if (CheckedIndices.Contains(e.Index)) { - using (var brush = new SolidBrush(boxColor)) - { - g.FillRectangle(brush, 2, e.Bounds.Y + 3, 9, 9); - } + using var brush = new SolidBrush(Theme.Control); + g.FillRectangle(brush, 2, e.Bounds.Y + 3, 9, 9); } var size = g.MeasureString(Text, Font); diff --git a/OneMoreCalendar/Things/MoreListBox.cs b/OneMoreCalendar/Things/MoreListBox.cs index 08c22945c6..72ee0d29cc 100644 --- a/OneMoreCalendar/Things/MoreListBox.cs +++ b/OneMoreCalendar/Things/MoreListBox.cs @@ -2,6 +2,7 @@ // Copyright © 2022 Steven M. Cohn. All Rights Reserved. //************************************************************************************************ +#pragma warning disable S1144 // Unused private types or members should be removed #pragma warning disable S4487 // Unread "private" fields should be removed #pragma warning disable S3459 // Unassigned members should be removed @@ -32,9 +33,9 @@ private struct ScrollInfo public int Mask; public int Min; public int Max; - public int Page; + public int Page; // unused but do not remove, S1144 public int Position; - public int TrackPosition; + public int TrackPosition; // unused but do not remove, S1144 } [DllImport("user32.dll")] @@ -87,9 +88,13 @@ private bool Scroll(int delta) private ScrollInfo GetScrollInfo() { - var info = new ScrollInfo(); - info.Mask = SIF_ALL; + var info = new ScrollInfo + { + Mask = SIF_ALL + }; + info.Size = Marshal.SizeOf(info); + GetScrollInfo(Handle, SB_VERT, ref info); return info; } @@ -97,8 +102,8 @@ private ScrollInfo GetScrollInfo() protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); - var info = GetScrollInfo(); - Logger.Current.WriteLine($"wheel delta:{e.Delta} pos:{info.Position} min:{info.Min} max:{info.Max}"); + //var info = GetScrollInfo(); + //Logger.Current.WriteLine($"wheel delta:{e.Delta} pos:{info.Position} min:{info.Min} max:{info.Max}"); } protected override void WndProc(ref Message m) @@ -108,7 +113,7 @@ protected override void WndProc(ref Message m) if (Scrolled != null) { var info = GetScrollInfo(); - Logger.Current.WriteLine($"wndproc pos:{info.Position} min:{info.Min} max:{info.Max}"); + //Logger.Current.WriteLine($"wndproc pos:{info.Position} min:{info.Min} max:{info.Max}"); if (m.WParam.ToInt32() == SB_ENDSCROLL) { diff --git a/OneMoreCalendar/Things/MoreRadioButton.cs b/OneMoreCalendar/Things/MoreRadioButton.cs index 212b4d26ed..217f1b6035 100644 --- a/OneMoreCalendar/Things/MoreRadioButton.cs +++ b/OneMoreCalendar/Things/MoreRadioButton.cs @@ -5,6 +5,7 @@ namespace OneMoreCalendar { using System; + using System.ComponentModel; using System.Drawing; using System.Windows.Forms; @@ -35,6 +36,10 @@ public MoreRadioButton() public MouseState MouseState { get; private set; } + [Description("Round radio if true")] + public bool Round { get; set; } + + protected override void OnPaint(PaintEventArgs pevent) { var g = pevent.Graphics; @@ -44,15 +49,17 @@ protected override void OnPaint(PaintEventArgs pevent) { if (Enabled && (MouseState != MouseState.None || Checked)) { - var brush = MouseState.HasFlag(MouseState.Pushed) || Checked - ? AppColors.PressedBrush - : AppColors.HoverBrush; + using var brush = new SolidBrush( + MouseState.HasFlag(MouseState.Pushed) || Checked + ? Theme.ButtonHotBack + : Theme.ButtonBack); g.FillRoundedRectangle(brush, pevent.ClipRectangle, Radius); - var pen = MouseState.HasFlag(MouseState.Pushed) || Checked - ? AppColors.PressedPen - : AppColors.HoverPen; + using var pen = new Pen( + MouseState.HasFlag(MouseState.Pushed) || Checked + ? Theme.ButtonPressBorder + : Theme.Border); g.DrawRoundedRectangle(pen, pevent.ClipRectangle, Radius); } @@ -64,14 +71,26 @@ protected override void OnPaint(PaintEventArgs pevent) } else { - using (var pen = new Pen(AppColors.ControlColor)) + using (var pen = new Pen(Theme.Control)) { - g.DrawRectangle(pen, 0, 1, 14, 14); + if (Round) + { + g.DrawArc(pen, 0, 1, 14, 14, 0, 360); + } + else + { + g.DrawRectangle(pen, 0, 1, 14, 14); + } } if (Checked) { - using (var brush = new SolidBrush(AppColors.ControlColor)) + using var brush = new SolidBrush(Theme.Control); + if (Round) + { + g.FillEllipse(brush, new Rectangle(2, 3, 10, 10)); + } + else { g.FillRectangle(brush, 2, 3, 11, 11); } diff --git a/OneMoreCalendar/Things/RoundedForm.cs b/OneMoreCalendar/Things/RoundedForm.cs index b3d6e040c3..acdde00bf0 100644 --- a/OneMoreCalendar/Things/RoundedForm.cs +++ b/OneMoreCalendar/Things/RoundedForm.cs @@ -10,7 +10,7 @@ namespace OneMoreCalendar using System.Windows.Forms; - internal partial class RoundedForm : Form + internal partial class RoundedForm : ThemedForm { [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")] @@ -36,25 +36,28 @@ public RoundedForm() protected override void OnLoad(EventArgs e) { base.OnLoad(e); - FormBorderStyle = FormBorderStyle.None; - Region = Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, Radius, Radius)); + + if (!DesignMode) + { + FormBorderStyle = FormBorderStyle.None; + Region = Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, Radius, Radius)); + } } protected override void OnPaintBackground(PaintEventArgs e) { //base.OnPaintBackground(e); - + Rectangle r; - using (var brush = new SolidBrush(BackColor)) - { - r = new Rectangle(0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height); - e.Graphics.FillRoundedRectangle(brush, r, Radius); - } + using var brush = new SolidBrush(BackColor); + r = new Rectangle(0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height); + e.Graphics.FillRoundedRectangle(brush, r, Radius); + using var pen = new Pen(Theme.Border); r = new Rectangle(0, 0, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1); - e.Graphics.DrawRoundedRectangle(AppColors.PressedPen, r, Radius); + e.Graphics.DrawRoundedRectangle(pen, r, Radius); } } } diff --git a/OneMoreCalendar/Things/Theme.cs b/OneMoreCalendar/Things/Theme.cs new file mode 100644 index 0000000000..5f0e9eb77c --- /dev/null +++ b/OneMoreCalendar/Things/Theme.cs @@ -0,0 +1,203 @@ +//************************************************************************************************ +// Copyright © 2022 Steven M Cohn. All rights reserved. +//************************************************************************************************ + +namespace OneMoreCalendar +{ + using River.OneMoreAddIn.Helpers.Office; + using System; + using System.Drawing; + using System.Runtime.InteropServices; + using System.Windows.Forms; + + + internal enum ThemeMode + { + System = 0, + Light = 1, + Dark = 2 + } + + internal static class Theme + { + #region Native + private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20; + + [DllImport("dwmapi.dll", PreserveSig = true)] + private static extern int DwmSetWindowAttribute( + IntPtr hwnd, int attr, ref bool attrValue, int attrSize); + #endregion Native + + + public static bool DarkMode { get; private set; } + + public static Color BackColor { get; private set; } + public static Color ForeColor { get; private set; } + public static Color Border { get; private set; } + public static Color Highlight { get; private set; } + public static Color Control { get; private set; } + + public static Color ButtonBack { get; private set; } + public static Color ButtonFore { get; private set; } + public static Color ButtonDisabled { get; private set; } + public static Color ButtonBorder { get; private set; } + public static Color ButtonHotBack { get; private set; } + public static Color ButtonHotBorder { get; private set; } + public static Color ButtonPressBorder { get; private set; } + + public static Color LinkColor { get; private set; } + public static Color HoverColor { get; private set; } + + public static Color DetailOddBack { get; private set; } + public static Color DetailEvenBack { get; private set; } + + public static Color MonthHeader { get; private set; } + public static Color MonthPrimary { get; private set; } + public static Color MonthSecondary { get; private set; } + public static Color MonthGrid { get; private set; } + public static Color MonthDayFore { get; private set; } + public static Color MonthDayBack { get; private set; } + public static Color MonthTodayFore { get; private set; } + public static Color MonthTodayBack { get; private set; } + + + public static void InitializeTheme(ContainerControl container) + { + var provider = new SettingsProvider(); + var theme = provider.Theme; + DarkMode = theme == ThemeMode.Dark || + (theme == ThemeMode.System && Office.SystemDefaultDarkMode()); + + SetColors(); + + // true=dark, false=normal + var value = DarkMode; + + DwmSetWindowAttribute( + container.Handle, DWMWA_USE_IMMERSIVE_DARK_MODE, ref value, Marshal.SizeOf(value)); + + // controls... + + if (container is ThemedForm form) + { + form.OnThemeChange(); + } + else if (container is ThemedUserControl control) + { + control.OnThemeChange(); + } + + container.BackColor = MonthHeader; + container.ForeColor = ForeColor; + + Colorize(container.Controls); + } + + + private static void SetColors() + { + if (DarkMode) + { + // primary-dark = 202020 / 1F1F1F + // medium-dark = 2B2B2B / 272727 + // light-dark = 363636 / 383838 + // light purple = D2A1DF / D6A6D3 + // dark purple = 73356E (DarkOrchid) + // --------------------------------------------------------- + + BackColor = ColorTranslator.FromHtml("#FF383838"); + ForeColor = ColorTranslator.FromHtml("#FFE6E6E6"); + Border = Color.DarkOrchid; + Control = Color.MediumOrchid; + + // light purple (pink) + Highlight = ColorTranslator.FromHtml("#FFD2A1DF"); + + ButtonBack = ColorTranslator.FromHtml("#FF363636"); + ButtonFore = ColorTranslator.FromHtml("#FFE6E6E6"); + ButtonDisabled = Color.Gray; + ButtonBorder = ColorTranslator.FromHtml("#FF555555"); + ButtonHotBack = ColorTranslator.FromHtml("#FF505050"); + ButtonHotBorder = ColorTranslator.FromHtml("#FF808080"); + ButtonPressBorder = Color.DarkOrchid; + + LinkColor = Color.MediumOrchid; + HoverColor = Color.Orchid; + + MonthHeader = ColorTranslator.FromHtml("#FF383838"); + MonthPrimary = ColorTranslator.FromHtml("#FF1F1F1F"); + MonthSecondary = ColorTranslator.FromHtml("#FF272727"); + MonthGrid = ColorTranslator.FromHtml("#FF676767"); + MonthDayFore = Color.LightGray; + MonthDayBack = ColorTranslator.FromHtml("#FF383838"); + MonthTodayFore = Color.LightGray; + MonthTodayBack = ColorTranslator.FromHtml("#FF73356E"); // dark purpose + + DetailOddBack = ColorTranslator.FromHtml("#FF1F1F1F"); + DetailEvenBack = ColorTranslator.FromHtml("#FF272727"); + } + else + { + BackColor = Color.White; + ForeColor = Color.Black; + Border = ColorTranslator.FromHtml("#FFD2A1DF"); + Control = ColorTranslator.FromHtml("#FF73356E"); // dark purple + + // light purple + Highlight = ColorTranslator.FromHtml("#FFBC58B6"); + + ButtonBack = ColorTranslator.FromHtml("#FFF7EDF7"); + ButtonFore = ColorTranslator.FromHtml("#FF73356E"); // dark purple + ButtonDisabled = Color.Gray; + ButtonBorder = ColorTranslator.FromHtml("#FFF0DAEE"); + ButtonHotBack = ColorTranslator.FromHtml("#FFF0DAEE"); + ButtonHotBorder = ColorTranslator.FromHtml("#FF9E5499"); + ButtonPressBorder = ColorTranslator.FromHtml("#FF9E5499"); + + LinkColor = ColorTranslator.FromHtml("#FF73356E"); // dark purple + HoverColor = Color.MediumOrchid; + + MonthHeader = SystemColors.Control; + MonthPrimary = Color.White; + MonthSecondary = Color.WhiteSmoke; + MonthGrid = Color.DarkGray; + MonthDayFore = Color.Gray; + MonthDayBack = ColorTranslator.FromHtml("#FFF4E8F3"); + MonthTodayFore = Color.Black; + MonthTodayBack = ColorTranslator.FromHtml("#FFD6A6D3"); + + DetailOddBack = ColorTranslator.FromHtml("#FFFDFAFE"); + DetailEvenBack = Color.White; + } + } + + + private static void Colorize(Control.ControlCollection controls) + { + foreach (Control control in controls) + { + control.BackColor = BackColor; + control.ForeColor = ForeColor; + + if (control.Controls.Count > 0) + { + Colorize(control.Controls); + } + + if (control is ListView view) + { + foreach (ListViewItem item in view.Items) + { + item.BackColor = MonthHeader; + item.ForeColor = ForeColor; + } + } + else if (control is River.OneMoreAddIn.UI.MoreLinkLabel label) + { + label.LinkColor= LinkColor; + label.HoverColor= HoverColor; + } + } + } + } +} diff --git a/OneMoreCalendar/Things/ThemedForm.cs b/OneMoreCalendar/Things/ThemedForm.cs new file mode 100644 index 0000000000..c3cfc33cd7 --- /dev/null +++ b/OneMoreCalendar/Things/ThemedForm.cs @@ -0,0 +1,36 @@ +//************************************************************************************************ +// Copyright © 2022 Steven M Cohn. All rights reserved. +//************************************************************************************************ + +namespace OneMoreCalendar +{ + using System; + using System.Windows.Forms; + + + /// + /// Changes the theme of the current Form instance to Dark mode if the Windows + /// system default theme is also Dark mode. + /// + internal class ThemedForm : Form + { + + protected bool StaticColors { get; set; } + + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + if (!StaticColors) + { + Theme.InitializeTheme(this); + } + } + + + public virtual void OnThemeChange() + { + } + } +} diff --git a/OneMoreCalendar/Things/ThemedUserControl.cs b/OneMoreCalendar/Things/ThemedUserControl.cs new file mode 100644 index 0000000000..444c18a717 --- /dev/null +++ b/OneMoreCalendar/Things/ThemedUserControl.cs @@ -0,0 +1,29 @@ +//************************************************************************************************ +// Copyright © 2022 Steven M Cohn. All rights reserved. +//************************************************************************************************ + +namespace OneMoreCalendar +{ + using System; + using System.Windows.Forms; + + + /// + /// Changes the theme of the current UserControl instance to Dark mode if the Windows + /// system default theme is also Dark mode. + /// + internal abstract class ThemedUserControl : UserControl + { + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + Theme.InitializeTheme(this); + } + + + public virtual void OnThemeChange() + { + } + } +} diff --git a/OneMoreCalendar/YearsForm.Designer.cs b/OneMoreCalendar/YearsForm.Designer.cs index 6adc22c302..d71fc3f811 100644 --- a/OneMoreCalendar/YearsForm.Designer.cs +++ b/OneMoreCalendar/YearsForm.Designer.cs @@ -40,12 +40,12 @@ private void InitializeComponent() this.listView.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(115)))), ((int)(((byte)(53)))), ((int)(((byte)(110))))); this.listView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; this.listView.HideSelection = false; - this.listView.Location = new System.Drawing.Point(7, 9); + this.listView.Location = new System.Drawing.Point(4, 4); this.listView.Margin = new System.Windows.Forms.Padding(0); this.listView.MultiSelect = false; this.listView.Name = "listView"; this.listView.OwnerDraw = true; - this.listView.Size = new System.Drawing.Size(370, 299); + this.listView.Size = new System.Drawing.Size(376, 309); this.listView.TabIndex = 0; this.listView.UseCompatibleStateImageBehavior = false; this.listView.View = System.Windows.Forms.View.List; @@ -68,7 +68,7 @@ private void InitializeComponent() this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "YearsForm"; - this.Padding = new System.Windows.Forms.Padding(7, 9, 7, 9); + this.Padding = new System.Windows.Forms.Padding(4); this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; diff --git a/OneMoreCalendar/YearsForm.cs b/OneMoreCalendar/YearsForm.cs index bfad0b7ff4..be3bc7cf79 100644 --- a/OneMoreCalendar/YearsForm.cs +++ b/OneMoreCalendar/YearsForm.cs @@ -19,7 +19,7 @@ internal partial class YearsForm : RoundedForm private const int ItemRadius = 4; - private int skipYear; // exclude currently displayed year + private readonly int skipYear; // exclude currently displayed year private ListViewItem hoveredItem; @@ -58,12 +58,9 @@ protected override async void OnLoad(EventArgs e) var years = await new OneNoteProvider() .GetYears(await new SettingsProvider().GetNotebookIDs()); - years.ToList().ForEach(y => + years.Where(y => y != skipYear).ToList().ForEach(y => { - if (y != skipYear) - { - listView.Items.Add(y.ToString()); - } + listView.Items.Add(y.ToString()); }); } } @@ -101,15 +98,20 @@ private void DrawItem(object sender, DrawListViewItemEventArgs e) var size = e.Graphics.MeasureString(e.Item.Text, listView.Font); var bounds = new Rectangle(e.Bounds.X, e.Bounds.Y, (int)size.Width + 8, e.Bounds.Height); - e.Graphics.FillRoundedRectangle(AppColors.HoverBrush, bounds, ItemRadius); - e.Graphics.DrawRoundedRectangle(AppColors.HoverPen, bounds, ItemRadius); + using var fill = new SolidBrush(Theme.ButtonBack); + e.Graphics.FillRoundedRectangle(fill, bounds, ItemRadius); + + using var fore = new Pen(Theme.ButtonFore); + e.Graphics.DrawRoundedRectangle(fore, bounds, ItemRadius); } else { - e.Graphics.FillRectangle(Brushes.White, e.Bounds); + using var backBrush = new SolidBrush(Theme.BackColor); + e.Graphics.FillRectangle(backBrush, e.Bounds); } - e.Graphics.DrawString(e.Item.Text, listView.Font, AppColors.TextBrush, e.Bounds); + using var brush = new SolidBrush(Theme.Highlight); + e.Graphics.DrawString(e.Item.Text, listView.Font, brush, e.Bounds); }