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

[Core] Settings improvements: Grouping w/labels, support for doubles (#137)

* [Core] Settings improvements: Grouping w/labels, support for doubles

Layout improvements:
* Plugins can set `[SettingSuggestedColumnWidth(123)]` on a settings class to adjust the settings view column width to make it wider or narrower to fit things nicely.
* Plugins can set `[SettingNewGroup("label")]` on any setting property to force a "new paragraph", or group, of settings. If "label" is also provided, a grouping header with that text will also be created.
* A double precision up/down numeric control has been added. In support of this, there is now a precision value on the existing `[SettingNumericBounds]` attribute to specify the number of digits of precision the control displays/allows.

Plugins:
* The above have been applied/demonstrated on the Botanist and Explorer plugin settings.
This commit is contained in:
F K 2024-01-29 15:37:00 -05:00 committed by GitHub
parent a555c86083
commit 351dcdb732
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 227 additions and 28 deletions

View File

@ -7,11 +7,12 @@ using System.Threading.Tasks;
namespace Observatory.Botanist
{
[SettingSuggestedColumnWidth(450)]
class BotanistSettings
{
[SettingDisplayName("Enable Sampler Status Overlay")]
public bool OverlayEnabled { get; set; }
[SettingDisplayName("Sampler Status Overlay is sticky until sampling complete (if enabled)")]
[SettingDisplayName("Status Overlay is sticky until sampling is complete")]
public bool OverlayIsSticky { get; set; }
}
}

View File

@ -26,6 +26,12 @@ namespace Observatory.UI
_plugin = plugin;
// Filtered to only settings without SettingIgnore attribute
var attrib = _plugin.Settings.GetType().GetCustomAttribute<SettingSuggestedColumnWidth>();
if (attrib != null && attrib.Width > 0)
{
int minScreenWidth = Screen.AllScreens.Min(s => s.Bounds.Width);
_colWidth = Math.Min(attrib.Width, minScreenWidth / 2);
}
var settings = PluginManagement.PluginManager.GetSettingDisplayNames(plugin.Settings).Where(s => !Attribute.IsDefined(s.Key, typeof(SettingIgnore)));
CreateControls(settings);
@ -51,12 +57,30 @@ namespace Observatory.UI
foreach (var setting in settings)
{
// Reset the column tracking for checkboxes if this isn't a checkbox
// Reset the column tracking for checkboxes if this isn't a checkbox or explicitly requested
// to start a new grouping of settings.
int addedHeight = 35;
if (setting.Key.PropertyType.Name != "Boolean")
var newGroup = Attribute.GetCustomAttribute(setting.Key, typeof(SettingNewGroup)) as SettingNewGroup;
if (setting.Key.PropertyType.Name != "Boolean" || newGroup != null)
{
if (recentHalfCol) _colHeight.Add(addedHeight);
recentHalfCol = false;
if (newGroup != null)
{
if (!string.IsNullOrEmpty(newGroup.Label))
{
var label = CreateGroupLabel(newGroup.Label);
label.Location = GetSettingPosition();
Controls.Add(label);
trackBottomEdge(label);
_colHeight.Add(label.Height);
}
else
_colHeight.Add(10);
}
}
switch (setting.Key.GetValue(_plugin.Settings))
@ -98,7 +122,7 @@ namespace Observatory.UI
break;
case int:
// We have two options for integer values:
// 1) A slider (explicit by way of the SettingIntegerUseSlider attribute and bounded to 0..100 by default)
// 1) A slider (explicit by way of the SettingNumericUseSlider attribute and bounded to 0..100 by default)
// 2) A numeric up/down (default otherwise, and is unbounded by default).
// Bounds for both can be set via the SettingNumericBounds attribute, only the up/down uses Increment.
var intLabel = CreateSettingLabel(setting.Value);
@ -109,7 +133,7 @@ namespace Observatory.UI
}
else
{
intControl = CreateSettingNumericUpDown(setting.Key);
intControl = CreateSettingNumericUpDownForInt(setting.Key);
}
intLabel.Location = GetSettingPosition();
intControl.Location = GetSettingPosition(true);
@ -122,6 +146,23 @@ namespace Observatory.UI
Controls.Add(intControl);
trackBottomEdge(intControl);
break;
case double:
// We have one options for double values:
// 1) A numeric up/down (default otherwise, and is unbounded by default).
// Bounds can be set via the SettingNumericBounds attribute.
var doubleLabel = CreateSettingLabel(setting.Value);
Control doubleControl = CreateSettingNumericUpDownForDouble(setting.Key);
doubleLabel.Location = GetSettingPosition();
doubleControl.Location = GetSettingPosition(true);
addedHeight = doubleControl.Height + 2;
doubleLabel.Height = doubleControl.Height;
doubleLabel.TextAlign = ContentAlignment.MiddleRight;
Controls.Add(doubleLabel);
Controls.Add(doubleControl);
trackBottomEdge(doubleControl);
break;
case Action action:
var button = CreateSettingButton(setting.Value, action);
@ -152,8 +193,7 @@ namespace Observatory.UI
private Point GetSettingPosition(bool secondCol = false)
{
//return new Point(10 + (secondCol ? 200 : 0), -26 + _colHeight.Sum());
return new Point(10 + (secondCol ? _colWidth : 0), 15 + _colHeight.Sum());
return new Point(20 + (secondCol ? _colWidth + 20 : 0), 15 + _colHeight.Sum());
}
@ -170,6 +210,20 @@ namespace Observatory.UI
return label;
}
private Label CreateGroupLabel(string groupLabel)
{
Label label = new()
{
Text = groupLabel,
TextAlign = System.Drawing.ContentAlignment.MiddleLeft,
Width = _colWidth * 2,
ForeColor = Color.LightGray,
};
label.Font = new Font(label.Font.FontFamily, label.Font.Size + 1, FontStyle.Bold);
label.Height += 10; // Add spacing.
return label;
}
private ComboBox CreateSettingDropdown(PropertyInfo setting, Dictionary<string, object> dropdownItems)
{
var backingValueName = (SettingBackingValue?)Attribute.GetCustomAttribute(setting, typeof(SettingBackingValue));
@ -225,7 +279,7 @@ namespace Observatory.UI
private TrackBar CreateSettingTrackbar(PropertyInfo setting)
{
SettingNumericBounds? bounds = (SettingNumericBounds?)System.Attribute.GetCustomAttribute(setting, typeof(SettingNumericBounds));
SettingNumericBounds? bounds = (SettingNumericBounds?)Attribute.GetCustomAttribute(setting, typeof(SettingNumericBounds));
var minBound = Convert.ToInt32(bounds?.Minimum ?? 0);
var maxBound = Convert.ToInt32(bounds?.Maximum ?? 100);
@ -246,16 +300,16 @@ namespace Observatory.UI
trackBar.ValueChanged += (sender, e) =>
{
setting.SetValue(_plugin.Settings, Convert.ToInt32(trackBar.Value));
setting.SetValue(_plugin.Settings, trackBar.Value);
SaveSettings();
};
return trackBar;
}
private NumericUpDown CreateSettingNumericUpDown(PropertyInfo setting)
private NumericUpDown CreateSettingNumericUpDownForInt(PropertyInfo setting)
{
SettingNumericBounds? bounds = (SettingNumericBounds?)System.Attribute.GetCustomAttribute(setting, typeof(SettingNumericBounds));
SettingNumericBounds? bounds = (SettingNumericBounds?)Attribute.GetCustomAttribute(setting, typeof(SettingNumericBounds));
NumericUpDown numericUpDown = new()
{
Width = _colWidth,
@ -265,7 +319,6 @@ namespace Observatory.UI
};
numericUpDown.Value = (int?)setting.GetValue(_plugin.Settings) ?? 0;
numericUpDown.ValueChanged += (sender, e) =>
{
setting.SetValue(_plugin.Settings, Convert.ToInt32(numericUpDown.Value));
@ -275,6 +328,28 @@ namespace Observatory.UI
return numericUpDown;
}
private NumericUpDown CreateSettingNumericUpDownForDouble(PropertyInfo setting)
{
SettingNumericBounds? bounds = (SettingNumericBounds?)Attribute.GetCustomAttribute(setting, typeof(SettingNumericBounds));
NumericUpDown numericUpDown = new()
{
Width = _colWidth,
Minimum = Convert.ToDecimal(bounds?.Minimum ?? Double.MinValue),
Maximum = Convert.ToDecimal(bounds?.Maximum ?? Double.MaxValue),
Increment = Convert.ToDecimal(bounds?.Increment ?? 1.0),
DecimalPlaces = bounds?.Precision ?? 1,
};
numericUpDown.Value = Convert.ToDecimal(setting.GetValue(_plugin.Settings) ?? 0);
numericUpDown.ValueChanged += (sender, e) =>
{
setting.SetValue(_plugin.Settings, Convert.ToDouble(numericUpDown.Value));
SaveSettings();
};
return numericUpDown;
}
private CheckBox CreateBoolSetting(KeyValuePair<PropertyInfo, string> setting)
{
CheckBox checkBox = new()

View File

@ -1,12 +1,14 @@
using Observatory.Framework;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Observatory.Explorer
{
[SettingSuggestedColumnWidth(300)]
public class ExplorerSettings
{
public ExplorerSettings()
@ -14,6 +16,12 @@ namespace Observatory.Explorer
CustomCriteriaFile = $"{Environment.GetFolderPath(Environment.SpecialFolder.Personal)}{System.IO.Path.DirectorySeparatorChar}ObservatoryCriteria.lua";
}
[SettingNewGroup("Display")]
[SettingDisplayName("Only Show Current System")]
public bool OnlyShowCurrentSystem { get; set; }
[SettingNewGroup("Built-in Criteria")]
[SettingDisplayName("Landable & Terraformable")]
public bool LandableTerraformable { get; set; }
@ -83,12 +91,9 @@ namespace Observatory.Explorer
[SettingDisplayName("High-Value Body")]
public bool HighValueMappable { get; set; }
[SettingNewGroup("Custom Criteria")]
[SettingDisplayName("Enable Custom Criteria")]
public bool EnableCustomCriteria { get; set; }
[SettingDisplayName("Only Show Current System")]
public bool OnlyShowCurrentSystem { get; set; }
[SettingDisplayName("Custom Criteria File")]
[System.Text.Json.Serialization.JsonIgnore]
public System.IO.FileInfo CustomCriteria {get => new System.IO.FileInfo(CustomCriteriaFile); set => CustomCriteriaFile = value.FullName;}

View File

@ -6,6 +6,32 @@ using System.Threading.Tasks;
namespace Observatory.Framework
{
#region Settings class attributes
/// <summary>
/// Specifies the width of a settings column in the settings view. There are two columns.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class SettingSuggestedColumnWidth : Attribute
{
/// <summary>
/// Specifies the width of a settings column in the settings view. There are two columns.
/// </summary>
/// <param name="width">Provides a hint of the width of a settings column.</param>
public SettingSuggestedColumnWidth(int width)
{
Width = width;
}
/// <summary>
/// Provides a hint of the width of a settings column.
/// </summary>
public int Width { get; }
}
#endregion
#region Setting property attributes
/// <summary>
/// Specifies text to display as the name of the setting in the UI instead of the property name.
/// </summary>
@ -34,17 +60,24 @@ namespace Observatory.Framework
}
/// <summary>
/// Suggests default column width when building basic UI
/// Starts a new visual group of settings beginning with the current setting with an optional label.
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class ColumnSuggestedWidth : Attribute
{
public ColumnSuggestedWidth(int width)
public class SettingNewGroup : Attribute
{
/// <summary>
/// Starts a new visual group of settings beginning with the current setting with an optional label.
/// </summary>
/// <param name="label">An optional label describing the group.</param>
public SettingNewGroup(string label = "")
{
Width = width;
Label = label;
}
public int Width { get; }
/// <summary>
/// An optional label describing the group.
/// </summary>
public string Label { get; }
}
/// <summary>
@ -97,6 +130,7 @@ namespace Observatory.Framework
private double minimum;
private double maximum;
private double increment;
private int precision;
/// <summary>
/// Specify bounds for numeric inputs.
@ -104,11 +138,13 @@ namespace Observatory.Framework
/// <param name="minimum">Minimum allowed value.</param>
/// <param name="maximum">Maximum allowed value.</param>
/// <param name="increment">Increment between allowed values in slider/roller inputs.</param>
public SettingNumericBounds(double minimum, double maximum, double increment = 1.0)
/// <param name="precision">The number of digits to display for non integer values.</param>
public SettingNumericBounds(double minimum, double maximum, double increment = 1.0, int precision = 1)
{
this.minimum = minimum;
this.maximum = maximum;
this.increment = increment;
this.precision = precision;
}
/// <summary>
@ -121,7 +157,7 @@ namespace Observatory.Framework
}
/// <summary>
/// Maxunyn allowed value.
/// Maximum allowed value.
/// </summary>
public double Maximum
{
@ -137,5 +173,38 @@ namespace Observatory.Framework
get => increment;
set => increment = value;
}
/// <summary>
/// The number of digits to display for non integer values.
/// </summary>
public int Precision
{
get => precision;
set => precision = value;
}
}
#endregion
#region BasicUI attributes
/// <summary>
/// Suggests default column width when building basic plugin grid UI.
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class ColumnSuggestedWidth : Attribute
{
/// <summary>
/// Suggests default column width when building basic plugin grid UI.
/// </summary>
/// <param name="width">The suggested width of the annotated column.</param>
public ColumnSuggestedWidth(int width)
{
Width = width;
}
/// <summary>
/// The suggested width of the annotated column.
/// </summary>
public int Width { get; }
}
#endregion
}

View File

@ -4,6 +4,22 @@
<name>ObservatoryFramework</name>
</assembly>
<members>
<member name="T:Observatory.Framework.SettingSuggestedColumnWidth">
<summary>
Specifies the width of a settings column in the settings view. There are two columns.
</summary>
</member>
<member name="M:Observatory.Framework.SettingSuggestedColumnWidth.#ctor(System.Int32)">
<summary>
Specifies the width of a settings column in the settings view. There are two columns.
</summary>
<param name="width">Provides a hint of the width of a settings column.</param>
</member>
<member name="P:Observatory.Framework.SettingSuggestedColumnWidth.Width">
<summary>
Provides a hint of the width of a settings column.
</summary>
</member>
<member name="T:Observatory.Framework.SettingDisplayName">
<summary>
Specifies text to display as the name of the setting in the UI instead of the property name.
@ -20,9 +36,20 @@
Accessor to get/set displayed name.
</summary>
</member>
<member name="T:Observatory.Framework.ColumnSuggestedWidth">
<member name="T:Observatory.Framework.SettingNewGroup">
<summary>
Suggests default column width when building basic UI
Starts a new visual group of settings beginning with the current setting with an optional label.
</summary>
</member>
<member name="M:Observatory.Framework.SettingNewGroup.#ctor(System.String)">
<summary>
Starts a new visual group of settings beginning with the current setting with an optional label.
</summary>
<param name="label">An optional label describing the group.</param>
</member>
<member name="P:Observatory.Framework.SettingNewGroup.Label">
<summary>
An optional label describing the group.
</summary>
</member>
<member name="T:Observatory.Framework.SettingIgnore">
@ -56,13 +83,14 @@
Specify bounds for numeric inputs.
</summary>
</member>
<member name="M:Observatory.Framework.SettingNumericBounds.#ctor(System.Double,System.Double,System.Double)">
<member name="M:Observatory.Framework.SettingNumericBounds.#ctor(System.Double,System.Double,System.Double,System.Int32)">
<summary>
Specify bounds for numeric inputs.
</summary>
<param name="minimum">Minimum allowed value.</param>
<param name="maximum">Maximum allowed value.</param>
<param name="increment">Increment between allowed values in slider/roller inputs.</param>
<param name="precision">The number of digits to display for non integer values.</param>
</member>
<member name="P:Observatory.Framework.SettingNumericBounds.Minimum">
<summary>
@ -71,7 +99,7 @@
</member>
<member name="P:Observatory.Framework.SettingNumericBounds.Maximum">
<summary>
Maxunyn allowed value.
Maximum allowed value.
</summary>
</member>
<member name="P:Observatory.Framework.SettingNumericBounds.Increment">
@ -79,6 +107,27 @@
Increment between allowed values in slider/roller inputs.
</summary>
</member>
<member name="P:Observatory.Framework.SettingNumericBounds.Precision">
<summary>
The number of digits to display for non integer values.
</summary>
</member>
<member name="T:Observatory.Framework.ColumnSuggestedWidth">
<summary>
Suggests default column width when building basic plugin grid UI.
</summary>
</member>
<member name="M:Observatory.Framework.ColumnSuggestedWidth.#ctor(System.Int32)">
<summary>
Suggests default column width when building basic plugin grid UI.
</summary>
<param name="width">The suggested width of the annotated column.</param>
</member>
<member name="P:Observatory.Framework.ColumnSuggestedWidth.Width">
<summary>
The suggested width of the annotated column.
</summary>
</member>
<member name="T:Observatory.Framework.JournalEventArgs">
<summary>
Provides data for Elite Dangerous journal events.