add remove button

This commit is contained in:
2026-02-14 15:03:00 +01:00
parent 497795604e
commit 73711b9342
3 changed files with 146 additions and 45 deletions

View File

@@ -112,54 +112,71 @@ Padding="16,8"
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="0,0,0,12"> <DockPanel Grid.Row="0" Margin="0,0,0,12">
<ui:Button DockPanel.Dock="Right"
Content="Verlauf löschen"
Appearance="Secondary"
Icon="{ui:SymbolIcon Delete24}"
Command="{Binding ClearHistoryCommand}"
Padding="8,4"
VerticalAlignment="Center" />
<StackPanel>
<TextBlock Text="Farbverlauf" <TextBlock Text="Farbverlauf"
Style="{StaticResource HeaderText}" /> Style="{StaticResource HeaderText}" />
<TextBlock Text="Klicken zum Kopieren" <TextBlock Text="Klicken zum Kopieren"
Style="{StaticResource SubtleText}" Style="{StaticResource SubtleText}"
Margin="0,4,0,0" /> Margin="0,4,0,0" />
</StackPanel> </StackPanel>
</DockPanel>
<ScrollViewer Grid.Row="1" <ScrollViewer Grid.Row="1"
VerticalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"> HorizontalScrollBarVisibility="Disabled">
<ItemsControl ItemsSource="{Binding History}"> <ItemsControl ItemsSource="{Binding History}">
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate> <DataTemplate>
<ui:CardControl Margin="0,0,0,8" <ui:Card Margin="0,0,0,8"
Padding="8" Padding="12"
Cursor="Hand" Cursor="Hand"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch">
HorizontalContentAlignment="Left"> <ui:Card.InputBindings>
<ui:CardControl.InputBindings>
<MouseBinding MouseAction="LeftClick" <MouseBinding MouseAction="LeftClick"
Command="{Binding DataContext.CopyHexCommand, RelativeSource={RelativeSource AncestorType=ui:FluentWindow}}" Command="{Binding DataContext.CopyHexCommand, RelativeSource={RelativeSource AncestorType=ui:FluentWindow}}"
CommandParameter="{Binding}" /> CommandParameter="{Binding}" />
</ui:CardControl.InputBindings> </ui:Card.InputBindings>
<Grid HorizontalAlignment="Stretch"> <DockPanel LastChildFill="True">
<Grid.ColumnDefinitions> <!-- Delete button pinned to the right -->
<ColumnDefinition Width="Auto" /> <ui:Button DockPanel.Dock="Right"
<ColumnDefinition Width="*" /> Icon="{ui:SymbolIcon Dismiss24}"
</Grid.ColumnDefinitions> Appearance="Secondary"
ToolTip="Farbe entfernen"
Command="{Binding DataContext.RemoveColorCommand, RelativeSource={RelativeSource AncestorType=ui:FluentWindow}}"
CommandParameter="{Binding}"
Padding="6"
Margin="8,0,0,0"
VerticalAlignment="Center" />
<!-- Color preview on the left --> <!-- Color preview on the left -->
<Border Width="48" <Border DockPanel.Dock="Left"
Width="48"
Height="48" Height="48"
Background="{Binding Brush}" Background="{Binding Brush}"
CornerRadius="8" CornerRadius="8"
BorderBrush="{DynamicResource ControlStrokeColorDefaultBrush}" BorderBrush="{DynamicResource ControlStrokeColorDefaultBrush}"
BorderThickness="1" BorderThickness="1"
VerticalAlignment="Center" VerticalAlignment="Center" />
HorizontalAlignment="Left" />
<!-- Text info in the middle --> <!-- Text info fills the middle -->
<StackPanel Grid.Column="1" <StackPanel Margin="12,0,0,0"
Margin="12,0,0,0" VerticalAlignment="Center">
VerticalAlignment="Center"
HorizontalAlignment="Left">
<TextBlock Text="{Binding Hex}" <TextBlock Text="{Binding Hex}"
FontWeight="Medium" FontWeight="Medium"
FontSize="15" FontSize="15"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" /> Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="{Binding Rgb}" <TextBlock Text="{Binding Rgb}"
@@ -167,8 +184,8 @@ FontWeight="Medium"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Margin="0,2,0,0" /> Margin="0,2,0,0" />
</StackPanel> </StackPanel>
</Grid> </DockPanel>
</ui:CardControl> </ui:Card>
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ItemsControl> </ItemsControl>

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Windows.Input; using System.Windows.Input;
using MaxSlurper.Models; using MaxSlurper.Models;
@@ -10,11 +12,14 @@ namespace MaxSlurper.Services
{ {
AppSettings LoadSettings(); AppSettings LoadSettings();
void SaveSettings(AppSettings settings); void SaveSettings(AppSettings settings);
List<ColorItem> LoadHistory();
void SaveHistory(IEnumerable<ColorItem> history);
} }
public class SettingsService : ISettingsService public class SettingsService : ISettingsService
{ {
private readonly string _settingsPath; private readonly string _settingsPath;
private readonly string _historyPath;
public SettingsService() public SettingsService()
{ {
@@ -22,6 +27,7 @@ namespace MaxSlurper.Services
var appFolder = Path.Combine(appData, "MaxSlurper"); var appFolder = Path.Combine(appData, "MaxSlurper");
Directory.CreateDirectory(appFolder); Directory.CreateDirectory(appFolder);
_settingsPath = Path.Combine(appFolder, "settings.json"); _settingsPath = Path.Combine(appFolder, "settings.json");
_historyPath = Path.Combine(appFolder, "history.json");
} }
public AppSettings LoadSettings() public AppSettings LoadSettings()
@@ -94,10 +100,52 @@ var json = File.ReadAllText(_settingsPath);
catch { } catch { }
} }
public List<ColorItem> LoadHistory()
{
try
{
if (File.Exists(_historyPath))
{
var json = File.ReadAllText(_historyPath);
var items = JsonSerializer.Deserialize<List<HistoryEntry>>(json);
if (items != null)
{
return items.Select(e =>
{
var item = new ColorItem { R = e.R, G = e.G, B = e.B };
item.UpdateDerived();
return item;
}).ToList();
}
}
}
catch { }
return new List<ColorItem>();
}
public void SaveHistory(IEnumerable<ColorItem> history)
{
try
{
var entries = history.Select(c => new HistoryEntry { R = c.R, G = c.G, B = c.B }).ToList();
var json = JsonSerializer.Serialize(entries, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(_historyPath, json);
}
catch { }
}
private class SettingsData private class SettingsData
{ {
public string[]? HotkeyModifiers { get; set; } public string[]? HotkeyModifiers { get; set; }
public string? HotkeyKey { get; set; } public string? HotkeyKey { get; set; }
} }
private class HistoryEntry
{
public byte R { get; set; }
public byte G { get; set; }
public byte B { get; set; }
}
} }
} }

View File

@@ -38,6 +38,7 @@ namespace MaxSlurper.ViewModels
public ICommand PickColorCommand { get; } public ICommand PickColorCommand { get; }
public ICommand ClearHistoryCommand { get; } public ICommand ClearHistoryCommand { get; }
public ICommand RemoveColorCommand { get; }
public ICommand CopyHexCommand { get; } public ICommand CopyHexCommand { get; }
public ICommand OpenColorPickerCommand { get; } public ICommand OpenColorPickerCommand { get; }
public ICommand OpenSettingsCommand { get; } public ICommand OpenSettingsCommand { get; }
@@ -51,10 +52,18 @@ namespace MaxSlurper.ViewModels
Settings = _settingsService.LoadSettings(); Settings = _settingsService.LoadSettings();
PickColorCommand = new RelayCommand(async _ => await PickColor()); PickColorCommand = new RelayCommand(async _ => await PickColor());
ClearHistoryCommand = new RelayCommand(_ => ClearHistory()); ClearHistoryCommand = new RelayCommand(_ => ClearHistory(), _ => History.Count > 0);
RemoveColorCommand = new RelayCommand(RemoveColor, _ => _ is ColorItem);
CopyHexCommand = new RelayCommand(CopyHex, _ => Selected != null || _ is ColorItem); CopyHexCommand = new RelayCommand(CopyHex, _ => Selected != null || _ is ColorItem);
OpenColorPickerCommand = new RelayCommand(_ => OpenColorPicker()); OpenColorPickerCommand = new RelayCommand(_ => OpenColorPicker());
OpenSettingsCommand = new RelayCommand(_ => OpenSettings()); OpenSettingsCommand = new RelayCommand(_ => OpenSettings());
// Restore persisted history
foreach (var item in _settingsService.LoadHistory())
History.Add(item);
if (History.Count > 0)
Selected = History[0];
} }
public System.Action<AppSettings>? OnSettingsChanged { get; set; } public System.Action<AppSettings>? OnSettingsChanged { get; set; }
@@ -79,6 +88,8 @@ namespace MaxSlurper.ViewModels
Selected = item; Selected = item;
System.Windows.Clipboard.SetText(item.Hex); System.Windows.Clipboard.SetText(item.Hex);
_settingsService.SaveHistory(History);
((RelayCommand)ClearHistoryCommand).RaiseCanExecuteChanged();
} }
private void OpenColorPicker() private void OpenColorPicker()
@@ -104,6 +115,8 @@ namespace MaxSlurper.ViewModels
Selected = item; Selected = item;
System.Windows.Clipboard.SetText(item.Hex); System.Windows.Clipboard.SetText(item.Hex);
_settingsService.SaveHistory(History);
((RelayCommand)ClearHistoryCommand).RaiseCanExecuteChanged();
} }
} }
@@ -119,6 +132,23 @@ namespace MaxSlurper.ViewModels
private void ClearHistory() private void ClearHistory()
{ {
History.Clear(); History.Clear();
Selected = null;
_settingsService.SaveHistory(History);
((RelayCommand)ClearHistoryCommand).RaiseCanExecuteChanged();
}
private void RemoveColor(object? parameter)
{
if (parameter is not ColorItem item) return;
var wasSelected = item == Selected;
History.Remove(item);
if (wasSelected)
Selected = History.Count > 0 ? History[0] : null;
_settingsService.SaveHistory(History);
((RelayCommand)ClearHistoryCommand).RaiseCanExecuteChanged();
} }
private void CopyHex(object? parameter) private void CopyHex(object? parameter)
@@ -136,7 +166,13 @@ namespace MaxSlurper.ViewModels
private void UpdateSelected() private void UpdateSelected()
{ {
if (Selected == null) return; if (Selected == null)
{
SelectedColorBrush = System.Windows.Media.Brushes.White;
SelectedHex = "#FFFFFF";
SelectedRgb = "255,255,255";
return;
}
SelectedColorBrush = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(Selected.R, Selected.G, Selected.B)); SelectedColorBrush = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(Selected.R, Selected.G, Selected.B));
SelectedHex = Selected.Hex; SelectedHex = Selected.Hex;
SelectedRgb = Selected.Rgb; SelectedRgb = Selected.Rgb;