2
0
mirror of https://github.com/9ParsonsB/Pulsar.git synced 2025-04-05 17:39:39 -04:00

[Core] Spit and polish on PluginList and tabs (#138)

Add checkboxes to the PluginList which allow you to enable/disable each plugin on-the-fly (it will no longer respond to events, but you can still configure it, etc.). These settings are preserved in a new Core setting. Also enabled full-row select for easier selection in the listview.

Also increased the height of the PluginList slightly. (Personally, I'd like it even taller.)

Also made slight sizing adjustments to the plugin tabs, which now show 3 letters when collapsed and has a bit of extra space so the longest one does not get cut-off when selected/bolded. Furthermore, the list of plugins is now sorted alphabetically.

Finally, set the plugin listview Dock = Fill (vs. Anchored). This seems to have fixed the listview resize problem I was experiencing.
This commit is contained in:
F K 2024-01-29 15:37:31 -05:00 committed by GitHub
parent 351dcdb732
commit 38b950cf37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 133 additions and 23 deletions

View File

@ -76,6 +76,9 @@
<setting name="ColumnSizing" serializeAs="String"> <setting name="ColumnSizing" serializeAs="String">
<value /> <value />
</setting> </setting>
<setting name="PluginsEnabled" serializeAs="String">
<value />
</setting>
</Observatory.Properties.Core> </Observatory.Properties.Core>
</userSettings> </userSettings>
</configuration> </configuration>

View File

@ -7,6 +7,7 @@ using System.Linq;
using Observatory.Framework.Files.Journal; using Observatory.Framework.Files.Journal;
using System.Timers; using System.Timers;
using Observatory.Utils; using Observatory.Utils;
using Observatory.Framework.Files.ParameterTypes;
namespace Observatory.PluginManagement namespace Observatory.PluginManagement
{ {
@ -14,6 +15,7 @@ namespace Observatory.PluginManagement
{ {
private IEnumerable<IObservatoryWorker> observatoryWorkers; private IEnumerable<IObservatoryWorker> observatoryWorkers;
private IEnumerable<IObservatoryNotifier> observatoryNotifiers; private IEnumerable<IObservatoryNotifier> observatoryNotifiers;
private HashSet<IObservatoryPlugin> disabledPlugins;
private List<(string error, string detail)> errorList; private List<(string error, string detail)> errorList;
private System.Timers.Timer timer; private System.Timers.Timer timer;
@ -21,6 +23,7 @@ namespace Observatory.PluginManagement
{ {
this.observatoryWorkers = observatoryWorkers; this.observatoryWorkers = observatoryWorkers;
this.observatoryNotifiers = observatoryNotifiers; this.observatoryNotifiers = observatoryNotifiers;
disabledPlugins = new();
errorList = new(); errorList = new();
InitializeTimer(); InitializeTimer();
@ -39,6 +42,7 @@ namespace Observatory.PluginManagement
{ {
foreach (var worker in observatoryWorkers) foreach (var worker in observatoryWorkers)
{ {
if (disabledPlugins.Contains(worker)) continue;
try try
{ {
worker.JournalEvent((JournalBase)journalEventArgs.journalEvent); worker.JournalEvent((JournalBase)journalEventArgs.journalEvent);
@ -59,6 +63,7 @@ namespace Observatory.PluginManagement
{ {
foreach (var worker in observatoryWorkers) foreach (var worker in observatoryWorkers)
{ {
if (disabledPlugins.Contains(worker)) continue;
try try
{ {
worker.StatusChange((Status)journalEventArgs.journalEvent); worker.StatusChange((Status)journalEventArgs.journalEvent);
@ -79,13 +84,14 @@ namespace Observatory.PluginManagement
{ {
foreach (var worker in observatoryWorkers) foreach (var worker in observatoryWorkers)
{ {
if (disabledPlugins.Contains(worker)) continue;
try try
{ {
worker.LogMonitorStateChanged(e); worker.LogMonitorStateChanged(e);
} }
catch (Exception ex) catch (Exception ex)
{ {
RecordError(ex, worker.Name, "LogMonitorStateChanged event", ex.StackTrace); RecordError(ex, worker.Name, "LogMonitorStateChanged event", ex.StackTrace ?? "");
} }
} }
} }
@ -94,6 +100,7 @@ namespace Observatory.PluginManagement
{ {
foreach (var notifier in observatoryNotifiers) foreach (var notifier in observatoryNotifiers)
{ {
if (disabledPlugins.Contains(notifier)) continue;
try try
{ {
notifier.OnNotificationEvent(notificationArgs); notifier.OnNotificationEvent(notificationArgs);
@ -114,10 +121,29 @@ namespace Observatory.PluginManagement
{ {
foreach (var plugin in observatoryNotifiers.Cast<IObservatoryPlugin>().Concat(observatoryWorkers)) foreach (var plugin in observatoryNotifiers.Cast<IObservatoryPlugin>().Concat(observatoryWorkers))
{ {
plugin.HandlePluginMessage(messageArgs.SourceName, messageArgs.SourceVersion, messageArgs.Message); if (disabledPlugins.Contains(plugin)) continue;
try
{
plugin.HandlePluginMessage(messageArgs.SourceName, messageArgs.SourceVersion, messageArgs.Message);
}
catch (PluginException ex)
{
RecordError(ex);
}
catch(Exception ex)
{
RecordError(ex, plugin.Name, "OnPluginMessageEvent event", "");
}
} }
} }
public void SetPluginEnabled(IObservatoryPlugin plugin, bool enabled)
{
if (enabled) disabledPlugins.Remove(plugin);
else disabledPlugins.Add(plugin);
}
private void ResetTimer() private void ResetTimer()
{ {
timer.Stop(); timer.Stop();
@ -136,7 +162,7 @@ namespace Observatory.PluginManagement
private void RecordError(PluginException ex) private void RecordError(PluginException ex)
{ {
errorList.Add(($"Error in {ex.PluginName}: {ex.Message}", ex.StackTrace)); errorList.Add(($"Error in {ex.PluginName}: {ex.Message}", ex.StackTrace ?? ""));
} }
private void RecordError(Exception ex, string plugin, string eventType, string eventDetail) private void RecordError(Exception ex, string plugin, string eventType, string eventDetail)

View File

@ -36,12 +36,13 @@ namespace Observatory.PluginManagement
public readonly List<(IObservatoryWorker plugin, PluginStatus signed)> workerPlugins; public readonly List<(IObservatoryWorker plugin, PluginStatus signed)> workerPlugins;
public readonly List<(IObservatoryNotifier plugin, PluginStatus signed)> notifyPlugins; public readonly List<(IObservatoryNotifier plugin, PluginStatus signed)> notifyPlugins;
private readonly PluginCore core; private readonly PluginCore core;
private readonly PluginEventHandler pluginHandler;
private PluginManager() private PluginManager()
{ {
errorList = LoadPlugins(out workerPlugins, out notifyPlugins); errorList = LoadPlugins(out workerPlugins, out notifyPlugins);
var pluginHandler = new PluginEventHandler(workerPlugins.Select(p => p.plugin), notifyPlugins.Select(p => p.plugin)); pluginHandler = new PluginEventHandler(workerPlugins.Select(p => p.plugin), notifyPlugins.Select(p => p.plugin));
var logMonitor = LogMonitor.GetInstance; var logMonitor = LogMonitor.GetInstance;
pluginPanels = new(); pluginPanels = new();
pluginTables = new(); pluginTables = new();
@ -196,6 +197,11 @@ namespace Observatory.PluginManagement
SettingsManager.Save(); SettingsManager.Save();
} }
public void SetPluginEnabled(IObservatoryPlugin plugin, bool enabled)
{
pluginHandler.SetPluginEnabled(plugin, enabled);
}
private static List<(string, string?)> LoadPlugins(out List<(IObservatoryWorker plugin, PluginStatus signed)> observatoryWorkers, out List<(IObservatoryNotifier plugin, PluginStatus signed)> observatoryNotifiers) private static List<(string, string?)> LoadPlugins(out List<(IObservatoryWorker plugin, PluginStatus signed)> observatoryWorkers, out List<(IObservatoryNotifier plugin, PluginStatus signed)> observatoryNotifiers)
{ {
observatoryWorkers = new(); observatoryWorkers = new();

View File

@ -309,5 +309,17 @@ namespace Observatory.Properties {
this["ColumnSizing"] = value; this["ColumnSizing"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string PluginsEnabled {
get {
return ((string)(this["PluginsEnabled"]));
}
set {
this["PluginsEnabled"] = value;
}
}
} }
} }

View File

@ -74,5 +74,8 @@
<Setting Name="ColumnSizing" Type="System.String" Scope="User"> <Setting Name="ColumnSizing" Type="System.String" Scope="User">
<Value Profile="(Default)" /> <Value Profile="(Default)" />
</Setting> </Setting>
<Setting Name="PluginsEnabled" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>

View File

@ -136,7 +136,7 @@
// //
ThemeLabel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; ThemeLabel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
ThemeLabel.BorderStyle = BorderStyle.FixedSingle; ThemeLabel.BorderStyle = BorderStyle.FixedSingle;
ThemeLabel.Location = new Point(3, 603); ThemeLabel.Location = new Point(3, 656);
ThemeLabel.Name = "ThemeLabel"; ThemeLabel.Name = "ThemeLabel";
ThemeLabel.Size = new Size(659, 23); ThemeLabel.Size = new Size(659, 23);
ThemeLabel.TabIndex = 7; ThemeLabel.TabIndex = 7;
@ -148,7 +148,7 @@
PluginSettingsButton.Anchor = AnchorStyles.Top | AnchorStyles.Right; PluginSettingsButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
PluginSettingsButton.FlatAppearance.BorderSize = 0; PluginSettingsButton.FlatAppearance.BorderSize = 0;
PluginSettingsButton.FlatStyle = FlatStyle.Flat; PluginSettingsButton.FlatStyle = FlatStyle.Flat;
PluginSettingsButton.Location = new Point(396, 140); PluginSettingsButton.Location = new Point(396, 193);
PluginSettingsButton.Name = "PluginSettingsButton"; PluginSettingsButton.Name = "PluginSettingsButton";
PluginSettingsButton.Size = new Size(130, 23); PluginSettingsButton.Size = new Size(130, 23);
PluginSettingsButton.TabIndex = 6; PluginSettingsButton.TabIndex = 6;
@ -167,7 +167,7 @@
VoiceSettingsPanel.Controls.Add(VoiceLabel); VoiceSettingsPanel.Controls.Add(VoiceLabel);
VoiceSettingsPanel.Controls.Add(VoiceSpeedLabel); VoiceSettingsPanel.Controls.Add(VoiceSpeedLabel);
VoiceSettingsPanel.Controls.Add(VoiceVolumeLabel); VoiceSettingsPanel.Controls.Add(VoiceVolumeLabel);
VoiceSettingsPanel.Location = new Point(3, 426); VoiceSettingsPanel.Location = new Point(3, 479);
VoiceSettingsPanel.Name = "VoiceSettingsPanel"; VoiceSettingsPanel.Name = "VoiceSettingsPanel";
VoiceSettingsPanel.Size = new Size(659, 177); VoiceSettingsPanel.Size = new Size(659, 177);
VoiceSettingsPanel.TabIndex = 5; VoiceSettingsPanel.TabIndex = 5;
@ -262,7 +262,7 @@
// //
VoiceNotificationLabel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; VoiceNotificationLabel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
VoiceNotificationLabel.BorderStyle = BorderStyle.FixedSingle; VoiceNotificationLabel.BorderStyle = BorderStyle.FixedSingle;
VoiceNotificationLabel.Location = new Point(3, 403); VoiceNotificationLabel.Location = new Point(3, 456);
VoiceNotificationLabel.Name = "VoiceNotificationLabel"; VoiceNotificationLabel.Name = "VoiceNotificationLabel";
VoiceNotificationLabel.Size = new Size(659, 23); VoiceNotificationLabel.Size = new Size(659, 23);
VoiceNotificationLabel.TabIndex = 4; VoiceNotificationLabel.TabIndex = 4;
@ -287,7 +287,7 @@
PopupSettingsPanel.Controls.Add(DisplayDropdown); PopupSettingsPanel.Controls.Add(DisplayDropdown);
PopupSettingsPanel.Controls.Add(CornerLabel); PopupSettingsPanel.Controls.Add(CornerLabel);
PopupSettingsPanel.Controls.Add(DisplayLabel); PopupSettingsPanel.Controls.Add(DisplayLabel);
PopupSettingsPanel.Location = new Point(3, 195); PopupSettingsPanel.Location = new Point(3, 248);
PopupSettingsPanel.Name = "PopupSettingsPanel"; PopupSettingsPanel.Name = "PopupSettingsPanel";
PopupSettingsPanel.Size = new Size(659, 208); PopupSettingsPanel.Size = new Size(659, 208);
PopupSettingsPanel.TabIndex = 3; PopupSettingsPanel.TabIndex = 3;
@ -440,7 +440,7 @@
// //
PopupNotificationLabel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; PopupNotificationLabel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
PopupNotificationLabel.BorderStyle = BorderStyle.FixedSingle; PopupNotificationLabel.BorderStyle = BorderStyle.FixedSingle;
PopupNotificationLabel.Location = new Point(3, 172); PopupNotificationLabel.Location = new Point(3, 225);
PopupNotificationLabel.Name = "PopupNotificationLabel"; PopupNotificationLabel.Name = "PopupNotificationLabel";
PopupNotificationLabel.Size = new Size(659, 23); PopupNotificationLabel.Size = new Size(659, 23);
PopupNotificationLabel.TabIndex = 2; PopupNotificationLabel.TabIndex = 2;
@ -453,7 +453,7 @@
PluginFolderButton.Anchor = AnchorStyles.Top | AnchorStyles.Right; PluginFolderButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
PluginFolderButton.FlatAppearance.BorderSize = 0; PluginFolderButton.FlatAppearance.BorderSize = 0;
PluginFolderButton.FlatStyle = FlatStyle.Flat; PluginFolderButton.FlatStyle = FlatStyle.Flat;
PluginFolderButton.Location = new Point(532, 140); PluginFolderButton.Location = new Point(532, 193);
PluginFolderButton.Name = "PluginFolderButton"; PluginFolderButton.Name = "PluginFolderButton";
PluginFolderButton.Size = new Size(130, 23); PluginFolderButton.Size = new Size(130, 23);
PluginFolderButton.TabIndex = 1; PluginFolderButton.TabIndex = 1;
@ -464,17 +464,20 @@
// //
PluginList.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; PluginList.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
PluginList.BorderStyle = BorderStyle.None; PluginList.BorderStyle = BorderStyle.None;
PluginList.CheckBoxes = true;
PluginList.Columns.AddRange(new ColumnHeader[] { NameColumn, TypeColumn, VersionColumn, StatusColumn }); PluginList.Columns.AddRange(new ColumnHeader[] { NameColumn, TypeColumn, VersionColumn, StatusColumn });
PluginList.FullRowSelect = true;
PluginList.HeaderStyle = ColumnHeaderStyle.Nonclickable; PluginList.HeaderStyle = ColumnHeaderStyle.Nonclickable;
PluginList.ImeMode = ImeMode.NoControl; PluginList.ImeMode = ImeMode.NoControl;
PluginList.Location = new Point(3, 3); PluginList.Location = new Point(3, 3);
PluginList.MultiSelect = false; PluginList.MultiSelect = false;
PluginList.Name = "PluginList"; PluginList.Name = "PluginList";
PluginList.OwnerDraw = true; PluginList.OwnerDraw = true;
PluginList.Size = new Size(659, 137); PluginList.Size = new Size(659, 184);
PluginList.TabIndex = 0; PluginList.TabIndex = 0;
PluginList.UseCompatibleStateImageBehavior = false; PluginList.UseCompatibleStateImageBehavior = false;
PluginList.View = View.Details; PluginList.View = View.Details;
PluginList.ItemChecked += PluginList_ItemChecked;
PluginList.Resize += PluginList_Resize; PluginList.Resize += PluginList_Resize;
// //
// NameColumn // NameColumn

View File

@ -1,12 +1,14 @@
using Observatory.PluginManagement; using Observatory.PluginManagement;
using Observatory.Framework.Interfaces; using Observatory.Framework.Interfaces;
using System.Linq; using System.Linq;
using System.Text.Json;
namespace Observatory.UI namespace Observatory.UI
{ {
partial class CoreForm partial class CoreForm
{ {
private Dictionary<ListViewItem, IObservatoryPlugin>? ListedPlugins; private Dictionary<ListViewItem, IObservatoryPlugin>? ListedPlugins;
private bool loading = true; // Suppress settings updates due to initializing the listview.
private void PopulatePluginList() private void PopulatePluginList()
{ {
@ -19,7 +21,8 @@ namespace Observatory.UI
ListViewItem item = new ListViewItem(new[] { plugin.Name, "Worker", plugin.Version, PluginStatusString(signed) }); ListViewItem item = new ListViewItem(new[] { plugin.Name, "Worker", plugin.Version, PluginStatusString(signed) });
ListedPlugins.Add(item, plugin); ListedPlugins.Add(item, plugin);
PluginList.Items.Add(item); var lvItem = PluginList.Items.Add(item);
lvItem.Checked = true; // Start with enabled, let settings disable things.
} }
} }
@ -29,12 +32,17 @@ namespace Observatory.UI
{ {
ListViewItem item = new ListViewItem(new[] { plugin.Name, "Notifier", plugin.Version, PluginStatusString(signed) }); ListViewItem item = new ListViewItem(new[] { plugin.Name, "Notifier", plugin.Version, PluginStatusString(signed) });
ListedPlugins.Add(item, plugin); ListedPlugins.Add(item, plugin);
PluginList.Items.Add(item); var lvItem = PluginList.Items.Add(item);
lvItem.Checked = true; // Start with enabled, let settings disable things.
} }
} }
PluginsEnabledStateFromSettings();
PluginList.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); PluginList.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
PluginList.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); PluginList.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
loading = false;
} }
private static string PluginStatusString(PluginManager.PluginStatus status) private static string PluginStatusString(PluginManager.PluginStatus status)
@ -136,7 +144,7 @@ namespace Observatory.UI
maxWidth = itemWidth.Width > maxWidth ? itemWidth.Width : maxWidth; maxWidth = itemWidth.Width > maxWidth ? itemWidth.Width : maxWidth;
} }
return maxWidth + 5; return maxWidth + 25;
} }
private void PluginSettingsButton_Click(object sender, EventArgs e) private void PluginSettingsButton_Click(object sender, EventArgs e)
@ -158,6 +166,56 @@ namespace Observatory.UI
} }
} }
private void PluginsEnabledStateFromSettings()
{
if (ListedPlugins == null) return;
string pluginsEnabledStr = Properties.Core.Default.PluginsEnabled;
Dictionary<string, bool>? pluginsEnabled = null;
if (!string.IsNullOrWhiteSpace(pluginsEnabledStr))
{
try
{
pluginsEnabled = JsonSerializer.Deserialize<Dictionary<string, bool>>(pluginsEnabledStr);
}
catch
{
// Failed deserialization means bad value, blow it away.
Properties.Core.Default.PluginsEnabled = string.Empty;
Properties.Core.Default.Save();
}
}
if (pluginsEnabled == null) return;
foreach (var p in ListedPlugins)
{
if (pluginsEnabled.ContainsKey(p.Value.Name) && !pluginsEnabled[p.Value.Name])
{
// Plugin is disabled.
p.Key.Checked = false; // This triggers the listview ItemChecked event.
}
}
}
private void PluginList_ItemChecked(object sender, ItemCheckedEventArgs e)
{
if (ListedPlugins == null) return;
var plugin = ListedPlugins[e.Item];
var enabled = e.Item.Checked;
PluginManager.GetInstance.SetPluginEnabled(plugin, enabled);
if (!loading)
{
Dictionary<string, bool> pluginsEnabled = ListedPlugins.ToDictionary(e => e.Value.Name, e => e.Key.Checked);
Properties.Core.Default.PluginsEnabled = JsonSerializer.Serialize(pluginsEnabled);
Properties.Core.Default.Save();
}
}
private Dictionary<IObservatoryPlugin, SettingsForm> SettingsForms = new(); private Dictionary<IObservatoryPlugin, SettingsForm> SettingsForms = new();
} }
} }

View File

@ -112,10 +112,10 @@ namespace Observatory.UI
if (menuItem.Value.Text == "<") if (menuItem.Value.Text == "<")
menuItem.Value.Text = ">"; menuItem.Value.Text = ">";
else else
menuItem.Value.Text = menuItem.Key[..1]; menuItem.Value.Text = menuItem.Key[..3];
} }
CoreMenu.Width = 40; CoreMenu.Width = 110;
ResizePanels(new Point(43, 12), 0); ResizePanels(new Point(CoreMenu.Width + 3, 12), 0);
} }
else if (e.ClickedItem.Text == ">") else if (e.ClickedItem.Text == ">")
{ {

View File

@ -17,7 +17,7 @@ namespace Observatory.UI
internal static List<string> CreatePluginTabs(MenuStrip menu, IEnumerable<(IObservatoryWorker plugin, PluginManagement.PluginManager.PluginStatus signed)> plugins, Dictionary<object, Panel> uiPanels) internal static List<string> CreatePluginTabs(MenuStrip menu, IEnumerable<(IObservatoryWorker plugin, PluginManagement.PluginManager.PluginStatus signed)> plugins, Dictionary<object, Panel> uiPanels)
{ {
List<string> pluginList = new List<string>(); List<string> pluginList = new List<string>();
foreach (var plugin in plugins) foreach (var plugin in plugins.OrderBy(p => p.plugin.ShortName))
{ {
AddPlugin(menu, plugin.plugin, plugin.signed, uiPanels); AddPlugin(menu, plugin.plugin, plugin.signed, uiPanels);
pluginList.Add(plugin.plugin.ShortName); pluginList.Add(plugin.plugin.ShortName);
@ -28,7 +28,7 @@ namespace Observatory.UI
internal static List<string> CreatePluginTabs(MenuStrip menu, IEnumerable<(IObservatoryNotifier plugin, PluginManagement.PluginManager.PluginStatus signed)> plugins, Dictionary<object, Panel> uiPanels) internal static List<string> CreatePluginTabs(MenuStrip menu, IEnumerable<(IObservatoryNotifier plugin, PluginManagement.PluginManager.PluginStatus signed)> plugins, Dictionary<object, Panel> uiPanels)
{ {
List<string> pluginList = new List<string>(); List<string> pluginList = new List<string>();
foreach (var plugin in plugins) foreach (var plugin in plugins.OrderBy(p => p.plugin.ShortName))
{ {
AddPlugin(menu, plugin.plugin, plugin.signed, uiPanels); AddPlugin(menu, plugin.plugin, plugin.signed, uiPanels);
pluginList.Add(plugin.plugin.ShortName); pluginList.Add(plugin.plugin.ShortName);
@ -73,12 +73,13 @@ namespace Observatory.UI
View = View.Details, View = View.Details,
Location = new Point(0, 0), Location = new Point(0, 0),
Size = panel.Size, Size = panel.Size,
Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom | AnchorStyles.Top, Dock = DockStyle.Fill,
BackColor = Color.FromArgb(64, 64, 64), BackColor = Color.FromArgb(64, 64, 64),
ForeColor = Color.LightGray, ForeColor = Color.LightGray,
ListViewItemSorter = columnSorter, ListViewItemSorter = columnSorter,
Font = new Font(new FontFamily("Segoe UI"), 10, FontStyle.Regular) Font = new Font(new FontFamily("Segoe UI"), 10, FontStyle.Regular)
}; };
panel.Controls.Add(listView);
string colSize = Properties.Core.Default.ColumnSizing; string colSize = Properties.Core.Default.ColumnSizing;
List<ColumnSizing>? columnSizing = null; List<ColumnSizing>? columnSizing = null;
@ -213,8 +214,6 @@ namespace Observatory.UI
listView.Sort(); listView.Sort();
}; };
panel.Controls.Add(listView);
plugin.PluginUI.DataGrid.CollectionChanged += (sender, e) => plugin.PluginUI.DataGrid.CollectionChanged += (sender, e) =>
{ {
var updateGrid = () => var updateGrid = () =>