diff --git a/src/DesktopMagic/Helpers/SettingElementGenerator.cs b/src/DesktopMagic/Helpers/SettingElementGenerator.cs
index c21acd7..dd236d6 100644
--- a/src/DesktopMagic/Helpers/SettingElementGenerator.cs
+++ b/src/DesktopMagic/Helpers/SettingElementGenerator.cs
@@ -1,14 +1,18 @@
-using DesktopMagic.Plugins;
+using DesktopMagic.Dialogs;
+using DesktopMagic.Plugins;
+
+using Microsoft.Win32;
using System;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Media;
namespace DesktopMagic.Helpers;
internal class SettingElementGenerator(uint pluginId)
{
- public Control? Generate(SettingElement settingElement, System.Windows.Controls.TextBlock textBlock)
+ public FrameworkElement? Generate(SettingElement settingElement, System.Windows.Controls.TextBlock textBlock)
{
if (settingElement.Input is DesktopMagic.Api.Settings.Label eLabel)
{
@@ -215,6 +219,148 @@ internal class SettingElementGenerator(uint pluginId)
return comboBox;
}
+ else if (settingElement.Input is DesktopMagic.Api.Settings.ColorPicker eColorPicker)
+ {
+ Grid panel = new()
+ {
+ HorizontalAlignment = HorizontalAlignment.Stretch
+ };
+ panel.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
+ panel.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
+
+ Border colorPreview = new()
+ {
+ Width = 30,
+ Height = 30,
+ CornerRadius = new CornerRadius(4),
+ Background = new SolidColorBrush(Color.FromArgb(eColorPicker.Value.A, eColorPicker.Value.R, eColorPicker.Value.G, eColorPicker.Value.B)),
+ Margin = new Thickness(0, 0, 10, 0),
+ BorderBrush = Application.Current.FindResource("ControlElevationBorderBrush") as Brush,
+ BorderThickness = new Thickness(1)
+ };
+ Grid.SetColumn(colorPreview, 0);
+
+ Wpf.Ui.Controls.Button browseButton = new()
+ {
+ Content = "Select Color",
+ VerticalAlignment = VerticalAlignment.Center,
+ HorizontalAlignment = HorizontalAlignment.Stretch
+ };
+ Grid.SetColumn(browseButton, 1);
+
+ browseButton.Click += (_s, _e) =>
+ {
+ try
+ {
+ ColorDialog colorDialog = new("Select a color", eColorPicker.Value)
+ {
+ Owner = Application.Current.MainWindow
+ };
+
+ if (colorDialog.ShowDialog() == true)
+ {
+ eColorPicker.Value = colorDialog.ResultColor;
+ colorPreview.Background = new SolidColorBrush(Color.FromArgb(eColorPicker.Value.A, eColorPicker.Value.R, eColorPicker.Value.G, eColorPicker.Value.B));
+ }
+ }
+ catch (Exception ex)
+ {
+ DisplayException(ex.Message);
+ }
+ };
+
+ eColorPicker.OnValueChanged += () =>
+ {
+ colorPreview.Dispatcher.Invoke(() =>
+ {
+ colorPreview.Background = new SolidColorBrush(Color.FromArgb(eColorPicker.Value.A, eColorPicker.Value.R, eColorPicker.Value.G, eColorPicker.Value.B));
+ });
+ };
+
+ _ = panel.Children.Add(colorPreview);
+ _ = panel.Children.Add(browseButton);
+
+ return panel;
+ }
+ else if (settingElement.Input is DesktopMagic.Api.Settings.FileSelector eFileSelector)
+ {
+ Grid grid = new()
+ {
+ HorizontalAlignment = HorizontalAlignment.Stretch
+ };
+ grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
+ grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
+
+ Wpf.Ui.Controls.TextBox pathTextBox = new()
+ {
+ Text = eFileSelector.Value,
+ IsReadOnly = true,
+ VerticalAlignment = VerticalAlignment.Center,
+ HorizontalAlignment = HorizontalAlignment.Stretch,
+ Margin = new Thickness(0, 0, 5, 0)
+ };
+ Grid.SetColumn(pathTextBox, 0);
+
+ Wpf.Ui.Controls.Button browseButton = new()
+ {
+ Content = "Browse",
+ VerticalAlignment = VerticalAlignment.Center
+ };
+ Grid.SetColumn(browseButton, 1);
+
+ browseButton.Click += (_s, _e) =>
+ {
+ try
+ {
+ if (eFileSelector.SelectFolder)
+ {
+ OpenFolderDialog folderDialog = new()
+ {
+ Title = eFileSelector.Title,
+ InitialDirectory = string.IsNullOrEmpty(eFileSelector.Value) ? Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) : System.IO.Path.GetDirectoryName(eFileSelector.Value)
+ };
+
+ if (folderDialog.ShowDialog() == true)
+ {
+ eFileSelector.Value = folderDialog.FolderName;
+ pathTextBox.Text = eFileSelector.Value;
+ }
+ }
+ else
+ {
+ OpenFileDialog fileDialog = new()
+ {
+ Title = eFileSelector.Title,
+ Filter = eFileSelector.Filter,
+ InitialDirectory = string.IsNullOrEmpty(eFileSelector.Value) ? Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) : System.IO.Path.GetDirectoryName(eFileSelector.Value)
+ };
+
+ if (fileDialog.ShowDialog() == true)
+ {
+ eFileSelector.Value = fileDialog.FileName;
+ pathTextBox.Text = eFileSelector.Value;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ DisplayException(ex.Message);
+ }
+ };
+
+ eFileSelector.OnValueChanged += () =>
+ {
+ pathTextBox.Dispatcher.Invoke(() =>
+ {
+ pathTextBox.Text = eFileSelector.Value;
+ });
+ };
+
+ _ = grid.Children.Add(pathTextBox);
+ _ = grid.Children.Add(browseButton);
+
+ return grid;
+ }
return null;
}
diff --git a/src/DesktopMagic/Pages/MainPage.xaml.cs b/src/DesktopMagic/Pages/MainPage.xaml.cs
index a199ceb..0b01fc9 100644
--- a/src/DesktopMagic/Pages/MainPage.xaml.cs
+++ b/src/DesktopMagic/Pages/MainPage.xaml.cs
@@ -267,7 +267,7 @@ public partial class MainPage : Page
_ = optionsPanel.Children.Add(card);
- Control? control = settingElementGenerator.Generate(settingElement, textBlock);
+ FrameworkElement? control = settingElementGenerator.Generate(settingElement, textBlock);
if (control is not null)
{
diff --git a/src/DesktopMagicPluginAPI/Settings/ColorPicker.cs b/src/DesktopMagicPluginAPI/Settings/ColorPicker.cs
new file mode 100644
index 0000000..ada24ee
--- /dev/null
+++ b/src/DesktopMagicPluginAPI/Settings/ColorPicker.cs
@@ -0,0 +1,62 @@
+using System.Drawing;
+using System.Globalization;
+
+namespace DesktopMagic.Api.Settings;
+
+///
+/// Represents a color picker control.
+///
+public sealed class ColorPicker : Setting
+{
+ private Color _value;
+
+ ///
+ /// Gets or sets the color value assigned to the element.
+ ///
+ public Color Value
+ {
+ get => _value;
+ set
+ {
+ if (_value != value)
+ {
+ _value = value;
+ ValueChanged();
+ }
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class with the provided .
+ ///
+ /// The default color value.
+ public ColorPicker(Color defaultColor)
+ {
+ _value = defaultColor;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a default color of White.
+ ///
+ public ColorPicker() : this(Color.White)
+ {
+ }
+
+ internal override string GetJsonValue()
+ {
+ return $"{Value.A},{Value.R},{Value.G},{Value.B}";
+ }
+
+ internal override void SetJsonValue(string value)
+ {
+ string[] parts = value.Split(',');
+ if (parts.Length == 4 &&
+ byte.TryParse(parts[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out byte a) &&
+ byte.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out byte r) &&
+ byte.TryParse(parts[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out byte g) &&
+ byte.TryParse(parts[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out byte b))
+ {
+ Value = Color.FromArgb(a, r, g, b);
+ }
+ }
+}
diff --git a/src/DesktopMagicPluginAPI/Settings/FileSelector.cs b/src/DesktopMagicPluginAPI/Settings/FileSelector.cs
new file mode 100644
index 0000000..0fde70a
--- /dev/null
+++ b/src/DesktopMagicPluginAPI/Settings/FileSelector.cs
@@ -0,0 +1,65 @@
+namespace DesktopMagic.Api.Settings;
+
+///
+/// Represents a file selector control that allows the user to browse for a file.
+///
+public sealed class FileSelector : Setting
+{
+ private string _value = string.Empty;
+
+ ///
+ /// Gets or sets the selected file path.
+ ///
+ public string Value
+ {
+ get => _value;
+ set
+ {
+ if (_value != value)
+ {
+ _value = value;
+ ValueChanged();
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the file filter for the file dialog (e.g., "Image Files|*.png;*.jpg|All Files|*.*").
+ ///
+ public string Filter { get; set; }
+
+ ///
+ /// Gets or sets the title of the file dialog.
+ ///
+ public string Title { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the file selector should select folders instead of files.
+ ///
+ public bool SelectFolder { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The default file path.
+ /// The file filter for the file dialog.
+ /// The title of the file dialog.
+ /// If true, selects folders instead of files.
+ public FileSelector(string defaultPath = "", string filter = "All Files|*.*", string title = "Select File", bool selectFolder = false)
+ {
+ _value = defaultPath;
+ Filter = filter;
+ Title = title;
+ SelectFolder = selectFolder;
+ }
+
+ internal override string GetJsonValue()
+ {
+ return Value;
+ }
+
+ internal override void SetJsonValue(string value)
+ {
+ Value = value;
+ }
+}