diff --git a/Source/Menu/MainForm.cs b/Source/Menu/MainForm.cs index f9f138cd23..0c329c42fd 100644 --- a/Source/Menu/MainForm.cs +++ b/Source/Menu/MainForm.cs @@ -32,6 +32,7 @@ using System.Resources; using System.Runtime.InteropServices; using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; using static ORTS.Notification; using Path = ORTS.Menu.Path; @@ -307,11 +308,34 @@ void MainForm_FormClosing(object sender, FormClosingEventArgs e) File.Delete(file); } + //void CheckForUpdate() + //{ + // // This is known directly from the chosen channel so doesn't need to wait for the update check itself. + // linkLabelChangeLog.Visible = !string.IsNullOrEmpty(UpdateManager.ChangeLogLink); + + // new Task(this, () => + // { + // UpdateManager.Check(); + // return null; + // }, _ => + // { + // if (UpdateManager.LastCheckError != null) + // linkLabelUpdate.Text = catalog.GetString("Update check failed"); + //else if (UpdateManager.LastUpdate != null && UpdateManager.LastUpdate.Version != VersionInfo.Version) + // linkLabelUpdate.Text = catalog.GetStringFmt("Update to {0}", UpdateManager.LastUpdate.Version); + //else + // linkLabelUpdate.Text = ""; + //linkLabelUpdate.Enabled = true; + //linkLabelUpdate.Visible = linkLabelUpdate.Text.Length > 0; + //// Update link's elevation icon and size/position. + //if (UpdateManager.LastCheckError == null && UpdateManager.LastUpdate != null && UpdateManager.LastUpdate.Version != VersionInfo.Version && UpdateManager.UpdaterNeedsElevation) + // linkLabelUpdate.Image = ElevationIcon; + //else + // linkLabelUpdate.Image = null; + // }); + //} void CheckForUpdate() { - // This is known directly from the chosen channel so doesn't need to wait for the update check itself. - linkLabelChangeLog.Visible = !string.IsNullOrEmpty(UpdateManager.ChangeLogLink); - new Task(this, () => { UpdateManager.Check(); @@ -319,18 +343,14 @@ void CheckForUpdate() }, _ => { if (UpdateManager.LastCheckError != null) + { linkLabelUpdate.Text = catalog.GetString("Update check failed"); - else if (UpdateManager.LastUpdate != null && UpdateManager.LastUpdate.Version != VersionInfo.Version) - linkLabelUpdate.Text = catalog.GetStringFmt("Update to {0}", UpdateManager.LastUpdate.Version); - else - linkLabelUpdate.Text = ""; - linkLabelUpdate.Enabled = true; - linkLabelUpdate.Visible = linkLabelUpdate.Text.Length > 0; - // Update link's elevation icon and size/position. - if (UpdateManager.LastCheckError == null && UpdateManager.LastUpdate != null && UpdateManager.LastUpdate.Version != VersionInfo.Version && UpdateManager.UpdaterNeedsElevation) - linkLabelUpdate.Image = ElevationIcon; - else - linkLabelUpdate.Image = null; + linkLabelChangeLog.Visible = true; + } + if (UpdateManager.LastUpdate != null) + { + SetUpdateNotification(); + } }); } @@ -1479,6 +1499,9 @@ void comboBoxTimetable_EnabledChanged(object sender, EventArgs e) // Will probably move this region and the Details region into separate files. bool AreNotificationsVisible = false; + // New notifications are those with a date after the NotificationsReadDate. + // Notifications are listed in reverse date order, with the newest one at the front. + // We don't track the reading of each notification but set the NewNotificationCount = 0 after the last of the new ones has been read. int NewNotificationCount = 1; int LastNotificationViewed = 0; @@ -1501,19 +1524,25 @@ private void ToggleNotifications() { if (AreNotificationsVisible == false) { + AreNotificationsVisible = true; // Set before calling ShowNotifcations() ShowNotifications(); FiddleNewNotificationCount(); } else { + AreNotificationsVisible = false; ShowDetails(); } - AreNotificationsVisible = !AreNotificationsVisible; } private void FiddleNewNotificationCount() { LastNotificationViewed = 1; + UpdateNotificationAlert(); + } + + private void UpdateNotificationAlert() + { if (LastNotificationViewed >= NewNotificationCount) { pbNotificationsSome.Visible = false; @@ -1534,30 +1563,52 @@ void ShowNotifications() /// /// Populate the Notifications list /// + //private void PopulateNotificationList() + //{ + //NotificationList.Clear(); + //if (NotificationList.Count == 0) + //{ + // var newNotification = new Notification(); + // NotificationList.Add(newNotification); + //new NHeadingControl(panelDetails, "This is a dummy notification", Color.OrangeRed).Add(newNotification); + //new NTitleControl(panelDetails, DateTime.Now, "Update is available").Add(newNotification); + //new NRecordControl(panelDetails, "Update mode", 140, "Stable").Add(newNotification); + //new NRecordControl(panelDetails, "Installed version", 140, "1.3.1").Add(newNotification); + //new NRecordControl(panelDetails, "New version available", 140, "1.4").Add(newNotification); + //new NButtonControl(panelDetails, "What's new", 90, "Find out on-line what's new in this version.").Add(newNotification); + //new NButtonControl(panelDetails, "Install", 90, "Install the new version.").Add(newNotification); + //new NHeadingControl(panelDetails, "Warning", Color.OrangeRed).Add(newNotification); + //new NTextControl(panelDetails, "The update from your current version may affect the behaviour of some of your content.").Add(newNotification); + //new NButtonControl(panelDetails, "Issue details", 90, "More details about this issue are available on-line.").Add(newNotification); + + //new NTitleControl(panelDetails, new DateTime(2024, 8, 31, 0, 0, 0), "Update is available").Add(newNotification); + //new NRecordControl(panelDetails, "Update mode", 140, "Stable").Add(newNotification); + //new NRecordControl(panelDetails, "Installed version", 140, "1.6").Add(newNotification); + //new NRecordControl(panelDetails, "New version available", 140, "1.7").Add(newNotification); + //new NButtonControl(panelDetails, "What's new", 90, "Find out on-line what's new in this version.").Add(newNotification); + //new NHeadingControl(panelDetails, "Install Not Available", Color.OrangeRed).Add(newNotification); + //new NTextControl(panelDetails, "V1.7 cannot be installed on your system until the graphics card is upgraded.").Add(newNotification); + //new NButtonControl(panelDetails, "Graphics card", 90, "Find out on-line about graphics hardware needed.").Add(newNotification); + //new NHeadingControl(panelDetails, "More Realism", Color.Blue).Add(newNotification); + //new NTextControl(panelDetails, "This update supports graphics which are significantly more realistic.").Add(newNotification); + //new NButtonControl(panelDetails, "Enhancement", 90, "More details about this enhancement are available on-line.").Add(newNotification); + + //} + //else + //{ + //} + //var notification = NotificationList.LastOrDefault(); + //new NTextControl(panelDetails, "").Add(notification); + //new NTextControl(panelDetails, "(Toggle icon to hide notifications.)").Add(notification); + //} + private void PopulateNotificationList() { - NotificationList.Clear(); - if (NotificationList.Count == 0) - { - var newNotification = new Notification(); - NotificationList.Add(newNotification); - new NHeadingControl(panelDetails, "This is a dummy notification", Color.OrangeRed).Add(newNotification); - new NTitleControl(panelDetails, DateTime.Now, "Update is available").Add(newNotification); - new NRecordControl(panelDetails, "Update mode", 140, "Stable").Add(newNotification); - new NRecordControl(panelDetails, "Installed version", 140, "1.3.1").Add(newNotification); - new NRecordControl(panelDetails, "New version available", 140, "1.4").Add(newNotification); - new NButtonControl(panelDetails, "What's new", 90, "Find out on-line what's new in this version.").Add(newNotification); - new NButtonControl(panelDetails, "Install", 90, "Install the new version.").Add(newNotification); - new NHeadingControl(panelDetails, "Warning", Color.OrangeRed).Add(newNotification); - new NTextControl(panelDetails, "The update from your current version may affect the behaviour of some of your content.").Add(newNotification); - new NButtonControl(panelDetails, "Issue details", 90, "More details about this issue are available on-line.").Add(newNotification); - } - else - { - } + SetUpdateNotification(); + var notification = NotificationList.LastOrDefault(); - new NTextControl(panelDetails, "").Add(notification); - new NTextControl(panelDetails, "(Toggle icon to hide notifications.)").Add(notification); + new NTextControl(notification, "").Add(); + new NTextControl(notification, "(Toggle icon to hide notifications.)").Add(); } /// @@ -1569,6 +1620,63 @@ Notification GetCurrentNotification() return NotificationList[0]; } + /// + /// Ultimately there will be a list of notifications downloaded for openrails/content. + /// Until then, there is a single notification announcing either that a new update is available or the installation is up to date. + /// + void SetUpdateNotification() + { + NewNotificationCount = (IsUpdateAvailable()) ? 1 : 0; + UpdateNotificationAlert(); + NotificationList.Clear(); + var newNotification = new Notification(panelDetails); + if (IsUpdateAvailable()) + { + NewNotificationCount = 1; + if (AreNotificationsVisible) + { + new NTitleControl(newNotification, UpdateManager.LastUpdate.Date, "Update is available").Add(); + new NRecordControl(newNotification, "Update mode", 140, UpdateManager.ChannelName).Add(); + new NRecordControl(newNotification, "Installed version", 140, VersionInfo.VersionOrBuild).Add(); + new NRecordControl(newNotification, "New version available", 140, UpdateManager.LastUpdate.Version).Add(); + new NLinkControl(newNotification, "What's new", 90, "Find out on-line what's new in this version.", this, UpdateManager.ChangeLogLink).Add(); + new NUpdateControl(newNotification, "Install", 90, "Install the new version.", this).Add(); + } + } + else + { + NewNotificationCount = 0; + if (AreNotificationsVisible) + { + var channelName = UpdateManager.ChannelName == "" ? "None" : UpdateManager.ChannelName; + new NTitleControl(newNotification, DateTime.Now, "Installation is up to date").Add(); + new NRecordControl(newNotification, "Update mode", 140, channelName).Add(); + new NRecordControl(newNotification, "Installed version", 140, VersionInfo.VersionOrBuild).Add(); + new NRecordControl(newNotification, "New version available", 140, "none").Add(); + } + } + NotificationList.Add(newNotification); + } + + bool IsUpdateAvailable() + { + return UpdateManager.LastUpdate != null + && UpdateManager.LastUpdate.Version != VersionInfo.Version; + } + + // 3 should be enough, but is there a way to get unlimited buttons? + public void Button0_Click(object sender, EventArgs e) + { + GetCurrentNotification().DoButton(UpdateManager, 0); + } + public void Button1_Click(object sender, EventArgs e) + { + GetCurrentNotification().DoButton(UpdateManager, 1); + } + public void Button2_Click(object sender, EventArgs e) + { + GetCurrentNotification().DoButton(UpdateManager, 2); + } #endregion Notifications } } diff --git a/Source/Menu/Notification.cs b/Source/Menu/Notification.cs index 3474259625..bb6f6211c9 100644 --- a/Source/Menu/Notification.cs +++ b/Source/Menu/Notification.cs @@ -17,17 +17,24 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; +using ORTS.Updater; namespace ORTS { public class Notification { public List NDetailList = new List(); + public Dictionary ButtonDictionary = new Dictionary(); + public Panel Panel; + + public Notification(Panel panel) + { + Panel = panel; + NButtonControl.ButtonCount = 0; + } public class NDetail { @@ -42,11 +49,16 @@ public class NDetail public static readonly int RecordHeight = 15; public const int ScrollBarWidth = 20; + public Notification Notification { get; private set; } public Label Control; - public void Add(Notification notification) + public NDetail(Notification notification) { - notification.NDetailList.Add(this); + Notification = notification; + } + public void Add() + { + Notification.NDetailList.Add(this); } } @@ -55,7 +67,7 @@ public void Add(Notification notification) /// public class NTitleControl : NDetail { - public NTitleControl(Panel panelDetails, DateTime date, string text) + public NTitleControl(Notification notification, DateTime date, string text) : base(notification) { var title = $"Notification 1/1: {date:dd-MMM-yyyy} - {text}"; var left = LeftPadding; @@ -63,18 +75,18 @@ public NTitleControl(Panel panelDetails, DateTime date, string text) { Text = title, UseMnemonic = false, - Font = new Font(panelDetails.Font, FontStyle.Bold), + Font = new Font(Notification.Panel.Font, FontStyle.Bold), TextAlign = ContentAlignment.BottomLeft, Height = TitleHeight, - Width = panelDetails.Width - ScrollBarWidth - left, + Width = Notification.Panel.Width - ScrollBarWidth - left, Left = LeftPadding }; - panelDetails.Controls.Add(Control); + Notification.Panel.Controls.Add(Control); } } public class NHeadingControl : NDetail { - public NHeadingControl(Panel panelDetails, string text, Color color = default) + public NHeadingControl(Notification notification, string text, Color color = default) : base(notification) { var left = LeftPadding; Control = new Label @@ -82,46 +94,47 @@ public NHeadingControl(Panel panelDetails, string text, Color color = default) ForeColor = color, Text = text, UseMnemonic = false, - Font = new Font(panelDetails.Font, FontStyle.Bold), + Font = new Font(Notification.Panel.Font, FontStyle.Bold), TextAlign = ContentAlignment.BottomLeft, Height = HeadingHeight, - Width = panelDetails.Width - ScrollBarWidth - left, + Width = Notification.Panel.Width - ScrollBarWidth - left, Left = left, Top = TopPadding, }; - panelDetails.Controls.Add(Control); + Notification.Panel.Controls.Add(Control); } } public class NTextControl : NDetail { - public NTextControl(Panel panelDetails, string text) + public NTextControl(Notification notification, string text) : base(notification) { var left = LeftPaddingIndented; Control = new Label { Text = text, UseMnemonic = false, - Font = new Font(panelDetails.Font, FontStyle.Regular), + Font = new Font(Notification.Panel.Font, FontStyle.Regular), TextAlign = ContentAlignment.BottomLeft, Height = TextHeight, - Width = panelDetails.Width - ScrollBarWidth - left, + Width = Notification.Panel.Width - ScrollBarWidth - left, Left = left, }; - panelDetails.Controls.Add(Control); + Notification.Panel.Controls.Add(Control); } } public class NButtonControl : NDetail { + public static int ButtonCount = 0; public Button Button; - public NButtonControl(Panel panelDetails, string legend, int width, string description) - { + public NButtonControl(Notification notification, string legend, int width, string description, MainForm mainForm) : base(notification) + { var buttonLeft = LeftPaddingIndented; Button = new Button { Margin = new Padding(20), Text = legend, UseMnemonic = false, - Font = new Font(panelDetails.Font, FontStyle.Regular), + Font = new Font(Notification.Panel.Font, FontStyle.Regular), TextAlign = ContentAlignment.MiddleCenter, Height = ButtonHeight, Width = width, @@ -129,7 +142,24 @@ public NButtonControl(Panel panelDetails, string legend, int width, string descr Top = TopPadding, BackColor = SystemColors.ButtonFace }; - panelDetails.Controls.Add(Button); + Notification.Panel.Controls.Add(Button); + + // 3 should be enough, but is there a way to get unlimited buttons? + switch (ButtonCount) + { + case 0: + Button.Click += new EventHandler(mainForm.Button0_Click); + break; + case 1: + Button.Click += new EventHandler(mainForm.Button1_Click); + break; + case 2: + Button.Click += new EventHandler(mainForm.Button2_Click); + break; + default: + MessageBox.Show("Cannot add 4th button; only 3 buttons are supported.", "Add Notification Button"); + break; + } var labelLeft = Button.Left + Button.Width + LeftPaddingIndented; Control = new Label @@ -137,47 +167,76 @@ public NButtonControl(Panel panelDetails, string legend, int width, string descr Margin = new Padding(20), Text = description, UseMnemonic = false, - Font = new Font(panelDetails.Font, FontStyle.Regular), + Font = new Font(Notification.Panel.Font, FontStyle.Regular), TextAlign = ContentAlignment.MiddleLeft, Height = ButtonHeight, - Width = panelDetails.Width - ScrollBarWidth - labelLeft, + Width = Notification.Panel.Width - ScrollBarWidth - labelLeft, Top = TopPadding, Left = labelLeft }; - panelDetails.Controls.Add(Control); + Notification.Panel.Controls.Add(Control); + } + } + public class NLinkControl : NButtonControl + { + public string Url; + public NLinkControl(Notification notification, string legend, int width, string description, MainForm mainForm, string url) + : base(notification, legend, width, description, mainForm) + { + Url = url; + Notification.ButtonDictionary.Add(ButtonCount, this); + ButtonCount++; + } + } + public class NUpdateControl : NButtonControl + { + public NUpdateControl(Notification notification, string legend, int width, string description, MainForm mainForm) + : base(notification, legend, width, description, mainForm) + { + Notification.ButtonDictionary.Add(ButtonCount, this); + ButtonCount++; } } + public void DoButton(UpdateManager updateManager, int key) + { + var button = ButtonDictionary[key]; + if (button is NLinkControl) + Process.Start(((NLinkControl)button).Url); + else if (button is NUpdateControl) + updateManager.Update(); + } + public class NRecordControl : NDetail { public Label Field; - public NRecordControl(Panel panelDetails, string label, int width, string field) - { + public NRecordControl(Notification notification, string label, int width, string field) : base(notification) + { Control = new Label { Text = label + ":", UseMnemonic = false, - Font = new Font(panelDetails.Font, FontStyle.Bold), + Font = new Font(Notification.Panel.Font, FontStyle.Bold), TextAlign = ContentAlignment.BottomRight, Width = width, Height = RecordHeight, Left = LeftPadding, Top = TopPadding }; - panelDetails.Controls.Add(Control); + Notification.Panel.Controls.Add(Control); var left = width + LeftPadding; Field = new Label { Text = field, UseMnemonic = false, - Font = new Font(panelDetails.Font, FontStyle.Regular), + Font = new Font(Notification.Panel.Font, FontStyle.Regular), TextAlign = ContentAlignment.BottomLeft, - Width = panelDetails.Width - ScrollBarWidth - left, + Width = Notification.Panel.Width - ScrollBarWidth - left, Height = RecordHeight, Left = left, Top = TopPadding }; - panelDetails.Controls.Add(Field); + Notification.Panel.Controls.Add(Field); } } @@ -202,5 +261,4 @@ public void FlowNDetails() } } } - } diff --git a/Source/ORTS.Updater/UpdateManager.cs b/Source/ORTS.Updater/UpdateManager.cs index 768ff8d743..2839a147c8 100644 --- a/Source/ORTS.Updater/UpdateManager.cs +++ b/Source/ORTS.Updater/UpdateManager.cs @@ -55,7 +55,7 @@ public class UpdateManager readonly string ProductName; readonly string ProductVersion; readonly UpdateSettings Settings; - readonly UpdateState State; + public readonly UpdateState State; UpdateSettings Channel; bool Force;