using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; using TweetDuck.Core.Controls; using TweetDuck.Core.Handling.General; using TweetDuck.Core.Notification.Example; using TweetDuck.Core.Other.Analytics; using TweetDuck.Core.Other.Settings; using TweetDuck.Core.Other.Settings.Dialogs; using TweetDuck.Core.Utils; using TweetDuck.Plugins; using TweetDuck.Updates; namespace TweetDuck.Core.Other{ sealed partial class FormSettings : Form, FormManager.IAppDialog{ private readonly FormBrowser browser; private readonly PluginManager plugins; private readonly int buttonHeight; private readonly Dictionary<Type, SettingsTab> tabs = new Dictionary<Type, SettingsTab>(4); private SettingsTab currentTab; public bool ShouldReloadBrowser { get; private set; } public FormSettings(FormBrowser browser, PluginManager plugins, UpdateHandler updates, AnalyticsManager analytics, Type startTab){ InitializeComponent(); Text = Program.BrandName+" Options"; this.browser = browser; this.browser.PauseNotification(); this.plugins = plugins; this.buttonHeight = BrowserUtils.Scale(39, this.GetDPIScale()) | 1; AddButton("General", () => new TabSettingsGeneral(this.browser.ReloadColumns, updates)); AddButton("Locales", () => new TabSettingsLocales()); AddButton("System Tray", () => new TabSettingsTray()); AddButton("Notifications", () => new TabSettingsNotifications(new FormNotificationExample(this.browser, this.plugins))); AddButton("Sounds", () => new TabSettingsSounds(this.browser.PlaySoundNotification)); AddButton("Feedback", () => new TabSettingsFeedback(analytics, AnalyticsReportGenerator.ExternalInfo.From(this.browser), this.plugins)); AddButton("Advanced", () => new TabSettingsAdvanced(this.browser.ReinjectCustomCSS)); SelectTab(tabs[startTab ?? typeof(TabSettingsGeneral)]); } private void FormSettings_FormClosing(object sender, FormClosingEventArgs e){ currentTab.Control.OnClosing(); foreach(SettingsTab tab in tabs.Values){ if (tab.IsInitialized){ tab.Control.Dispose(); } } Program.UserConfig.Save(); browser.ResumeNotification(); } private void btnManageOptions_Click(object sender, EventArgs e){ currentTab.Control.OnClosing(); using(DialogSettingsManage dialog = new DialogSettingsManage(plugins)){ FormClosing -= FormSettings_FormClosing; if (dialog.ShowDialog() == DialogResult.OK){ if (!dialog.IsRestarting){ browser.ResumeNotification(); BrowserProcessHandler.UpdatePrefs(); ShouldReloadBrowser = dialog.ShouldReloadBrowser; } Close(); } else{ FormClosing += FormSettings_FormClosing; } } } private void btnClose_Click(object sender, EventArgs e){ Close(); } private void AddButton<T>(string title, Func<T> constructor) where T : BaseTabSettings{ FlatButton btn = new FlatButton{ BackColor = SystemColors.Control, FlatStyle = FlatStyle.Flat, Font = SystemFonts.MessageBoxFont, Location = new Point(0, (buttonHeight+1)*(panelButtons.Controls.Count/2)), Margin = new Padding(0), Size = new Size(panelButtons.Width, buttonHeight), Text = title, UseVisualStyleBackColor = true }; btn.FlatAppearance.BorderSize = 0; btn.FlatAppearance.MouseDownBackColor = Color.FromArgb(179, 213, 232); btn.FlatAppearance.MouseOverBackColor = Color.FromArgb(216, 230, 237); panelButtons.Controls.Add(btn); panelButtons.Controls.Add(new Panel{ BackColor = Color.DimGray, Location = new Point(0, panelButtons.Controls[panelButtons.Controls.Count-1].Location.Y+buttonHeight), Margin = new Padding(0), Size = new Size(panelButtons.Width, 1) }); tabs.Add(typeof(T), new SettingsTab(btn, constructor)); btn.Click += (sender, args) => SelectTab<T>(); } private void SelectTab<T>() where T : BaseTabSettings{ SelectTab(tabs[typeof(T)]); } private void SelectTab(SettingsTab tab){ if (currentTab != null){ currentTab.Button.BackColor = SystemColors.Control; currentTab.Control.OnClosing(); } tab.Button.BackColor = tab.Button.FlatAppearance.MouseDownBackColor; if (!tab.IsInitialized){ foreach(Control control in tab.Control.InteractiveControls){ if (control is ComboBox){ control.MouseLeave += control_MouseLeave; } else if (control is TrackBar){ control.MouseWheel += control_MouseWheel; } } tab.Control.OnReady(); } panelContents.VerticalScroll.Enabled = false; // required to stop animation that would otherwise break everything panelContents.PerformLayout(); panelContents.SuspendLayout(); panelContents.VerticalScroll.Value = 0; // https://gfycat.com/GrotesqueTastyAstarte panelContents.Controls.Clear(); panelContents.Controls.Add(tab.Control); panelContents.ResumeLayout(true); panelContents.VerticalScroll.Enabled = true; panelContents.Focus(); currentTab = tab; } private void control_MouseLeave(object sender, EventArgs e){ if (sender is ComboBox cb && cb.DroppedDown){ return; // prevents comboboxes from closing when MouseLeave event triggers during opening animation } panelContents.Focus(); } private void control_MouseWheel(object sender, MouseEventArgs e){ ((HandledMouseEventArgs)e).Handled = true; panelContents.Focus(); } private sealed class SettingsTab{ public Button Button { get; } public BaseTabSettings Control => control ?? (control = constructor()); public bool IsInitialized => control != null; private readonly Func<BaseTabSettings> constructor; private BaseTabSettings control; public SettingsTab(Button button, Func<BaseTabSettings> constructor){ this.Button = button; this.constructor = constructor; } } } }