Compare commits

..

5 Commits

Author SHA1 Message Date
541135e063 add export 2025-05-03 16:26:07 +02:00
73711b9342 add remove button 2025-05-03 16:26:07 +02:00
497795604e Add autostart and update translations 2025-05-03 16:26:07 +02:00
bfd3581f26 Remove ThemeResources.xaml 2025-05-03 16:26:07 +02:00
5811421ca2 README.md aktualisiert 2025-10-23 19:07:04 +00:00
12 changed files with 314 additions and 74 deletions

View File

@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MaxSlurper" xmlns:local="clr-namespace:MaxSlurper"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
StartupUri="MainWindow.xaml"> >
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>

View File

@@ -1,5 +1,4 @@
using System.Configuration; using System.Linq;
using System.Data;
using Wpf.Ui.Appearance; using Wpf.Ui.Appearance;
namespace MaxSlurper namespace MaxSlurper
@@ -13,7 +12,22 @@ namespace MaxSlurper
{ {
base.OnStartup(e); base.OnStartup(e);
// The theme will be applied automatically when the window is shown bool startMinimized = e.Args.Contains("--minimized", System.StringComparer.OrdinalIgnoreCase);
var mainWindow = new MainWindow();
MainWindow = mainWindow;
if (startMinimized)
{
// Only show the tray icon, don't show the window
mainWindow.WindowState = System.Windows.WindowState.Minimized;
mainWindow.ShowInTaskbar = false;
mainWindow.Hide();
}
else
{
mainWindow.Show();
}
} }
} }
} }

View File

@@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Title="Farbe aussuche" Title="Farbe auswählen"
Height="500" Height="500"
Width="400" Width="400"
ResizeMode="NoResize" ResizeMode="NoResize"
@@ -26,7 +26,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<!-- Title bar --> <!-- Title bar -->
<ui:TitleBar Grid.Row="0" <ui:TitleBar Grid.Row="0"
Title="Farbe aussuche" Title="Farbe auswählen"
ShowMaximize="False" ShowMaximize="False"
ShowMinimize="False" ShowMinimize="False"
Icon="/logo.png" /> Icon="/logo.png" />
@@ -176,14 +176,14 @@ Height="20"
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<ui:Button Content="Lass ma" <ui:Button Content="Abbrechen"
Height="44" Height="44"
Margin="0,0,8,0" Margin="0,0,8,0"
Click="CancelButton_Click" Click="CancelButton_Click"
Appearance="Secondary"/> Appearance="Secondary"/>
<ui:Button Grid.Column="1" <ui:Button Grid.Column="1"
Content="Kopieren &amp; Tschüss" Content="Kopieren &amp; Schließen"
Height="44" Height="44"
Padding="24,0" Padding="24,0"
Click="OkButton_Click" Click="OkButton_Click"

View File

@@ -58,7 +58,7 @@
TextWrapping="Wrap" TextWrapping="Wrap"
FontSize="12" FontSize="12"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Margin="0,2,0,0"><Run Language="de-de" Text="H"/><Run Text="otkey zum Farben schlürfen"/></TextBlock> Margin="0,2,0,0">Hotkey zum Farben aufnehmen</TextBlock>
</StackPanel> </StackPanel>
</Grid> </Grid>
@@ -99,6 +99,37 @@ Foreground="{DynamicResource TextFillColorSecondaryBrush}"
</StackPanel> </StackPanel>
</ui:Card> </ui:Card>
<!-- Autostart Card -->
<ui:Card Margin="0,0,0,16" Padding="20">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ui:SymbolIcon Symbol="Power24"
FontSize="24"
VerticalAlignment="Center"
Margin="0,0,12,0"/>
<StackPanel Grid.Column="1" VerticalAlignment="Center">
<TextBlock Text="Autostart"
FontSize="16"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"/>
<TextBlock Text="Beim Systemstart minimiert starten"
FontSize="12"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Margin="0,2,0,0"/>
</StackPanel>
<CheckBox Grid.Column="2"
IsChecked="{Binding IsAutostart}"
VerticalAlignment="Center"/>
</Grid>
</ui:Card>
<!-- About Card --> <!-- About Card -->
<ui:Card Padding="20"> <ui:Card Padding="20">
<StackPanel> <StackPanel>
@@ -121,7 +152,7 @@ FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"/> Foreground="{DynamicResource TextFillColorPrimaryBrush}"/>
</Grid> </Grid>
<TextBlock Text="DER ColorPicker für Max" <TextBlock Text="Der Farbwähler für Max"
TextWrapping="Wrap" TextWrapping="Wrap"
FontSize="13" FontSize="13"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" Foreground="{DynamicResource TextFillColorSecondaryBrush}"
@@ -129,7 +160,7 @@ TextWrapping="Wrap"
<TextBlock TextWrapping="Wrap" <TextBlock TextWrapping="Wrap"
FontSize="13" FontSize="13"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"> Foreground="{DynamicResource TextFillColorSecondaryBrush}">
<Run Text="Gemacht mit "/> <Run Text="Erstellt mit "/>
<Run Text="♥" Foreground="Red" FontSize="14"/> <Run Text="♥" Foreground="Red" FontSize="14"/>
<Run Text=" von Mathias"/> <Run Text=" von Mathias"/>
</TextBlock> </TextBlock>
@@ -151,13 +182,13 @@ BorderThickness="0,1,0,0"
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Text="Änderungen werden direkt jespeichert" <TextBlock Text="Änderungen werden automatisch gespeichert"
VerticalAlignment="Center" VerticalAlignment="Center"
FontSize="12" FontSize="12"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"/> Foreground="{DynamicResource TextFillColorSecondaryBrush}"/>
<ui:Button Grid.Column="1" <ui:Button Grid.Column="1"
Content="Zumachen" Content="Schließen"
Height="36" Height="36"
Padding="24,0" Padding="24,0"
Click="Close_Click" Click="Close_Click"

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@@ -7,6 +7,7 @@ using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using MaxSlurper.Models; using MaxSlurper.Models;
using MaxSlurper.Services; using MaxSlurper.Services;
using Microsoft.Win32;
using Wpf.Ui.Controls; using Wpf.Ui.Controls;
namespace MaxSlurper.Controls namespace MaxSlurper.Controls
@@ -31,6 +32,35 @@ public event PropertyChangedEventHandler? PropertyChanged;
} }
} }
private const string RegistryRunKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
private const string AppName = "MaxSlurper";
public bool IsAutostart
{
get
{
using var key = Registry.CurrentUser.OpenSubKey(RegistryRunKey, false);
return key?.GetValue(AppName) != null;
}
set
{
using var key = Registry.CurrentUser.OpenSubKey(RegistryRunKey, true);
if (key == null) return;
if (value)
{
var exePath = Environment.ProcessPath ?? System.Reflection.Assembly.GetEntryAssembly()!.Location;
key.SetValue(AppName, $"\"{exePath}\" --minimized");
}
else
{
key.DeleteValue(AppName, false);
}
OnPropertyChanged();
}
}
public SettingsWindow(AppSettings settings, ISettingsService settingsService, Action<AppSettings> onSettingsChanged) public SettingsWindow(AppSettings settings, ISettingsService settingsService, Action<AppSettings> onSettingsChanged)
{ {
InitializeComponent(); InitializeComponent();
@@ -54,7 +84,7 @@ public event PropertyChangedEventHandler? PropertyChanged;
return; return;
_isCapturingHotkey = true; _isCapturingHotkey = true;
CurrentHotkey = "Drück deine Tasten..."; CurrentHotkey = "Tastenkombination eingeben...";
var captureWindow = new HotkeyCapture(); var captureWindow = new HotkeyCapture();
captureWindow.Owner = this; captureWindow.Owner = this;
@@ -131,7 +161,7 @@ ExtendsContentIntoTitleBar = true;
var infoText = new System.Windows.Controls.TextBlock var infoText = new System.Windows.Controls.TextBlock
{ {
Text = "Drück die Tastenkombination, die de haben willst", Text = "Drücken Sie die gewünschte Tastenkombination",
FontSize = 14, FontSize = 14,
TextAlignment = TextAlignment.Center, TextAlignment = TextAlignment.Center,
Foreground = (System.Windows.Media.Brush)FindResource("TextFillColorSecondaryBrush"), Foreground = (System.Windows.Media.Brush)FindResource("TextFillColorSecondaryBrush"),
@@ -142,7 +172,7 @@ ExtendsContentIntoTitleBar = true;
var keyDisplay = new System.Windows.Controls.TextBlock var keyDisplay = new System.Windows.Controls.TextBlock
{ {
Text = "Warte uff Eingabe...", Text = "Warte auf Eingabe...",
FontSize = 18, FontSize = 18,
FontWeight = FontWeights.SemiBold, FontWeight = FontWeights.SemiBold,
TextAlignment = TextAlignment.Center, TextAlignment = TextAlignment.Center,
@@ -204,7 +234,7 @@ key == Key.LWin || key == Key.RWin)
// Require at least one modifier // Require at least one modifier
if (modifiers == ModifierKeys.None) if (modifiers == ModifierKeys.None)
{ {
keyDisplay.Text = "Mindestens ein Modifier (Strg, Alt, Shift, Win) musste drücken!"; keyDisplay.Text = "Mindestens eine Zusatztaste (Strg, Alt, Shift, Win) erforderlich!";
okButton.IsEnabled = false; okButton.IsEnabled = false;
return; return;
} }

View File

@@ -55,7 +55,7 @@
BorderBrush="{DynamicResource ControlStrokeColorDefaultBrush}" BorderBrush="{DynamicResource ControlStrokeColorDefaultBrush}"
BorderThickness="1" BorderThickness="1"
Cursor="Hand" Cursor="Hand"
ToolTip="Drück ma druff, dann kannste dir 'ne Farbe raussuche"> ToolTip="Klicken, um eine Farbe auszuwählen">
<Border.Effect> <Border.Effect>
<DropShadowEffect BlurRadius="8" <DropShadowEffect BlurRadius="8"
ShadowDepth="2" ShadowDepth="2"
@@ -72,7 +72,7 @@
<StackPanel Orientation="Vertical" <StackPanel Orientation="Vertical"
Margin="16,0,16,0" Margin="16,0,16,0"
VerticalAlignment="Center"> VerticalAlignment="Center">
<TextBlock Text="Zuletzt jeklaut" <TextBlock Text="Zuletzt aufgenommen"
Style="{StaticResource SubtleText}" Style="{StaticResource SubtleText}"
Margin="0,0,0,4" /> Margin="0,0,0,4" />
<TextBlock Text="{Binding SelectedHex}" <TextBlock Text="{Binding SelectedHex}"
@@ -87,7 +87,7 @@ Style="{StaticResource SubtleText}" />
<!-- Actions --> <!-- Actions -->
<StackPanel Orientation="Vertical" <StackPanel Orientation="Vertical"
DockPanel.Dock="Right"> DockPanel.Dock="Right">
<ui:Button Content="Farbe schlürfen" <ui:Button Content="Farbe aufnehmen"
Appearance="Primary" Appearance="Primary"
Icon="{ui:SymbolIcon Eyedropper24}" Icon="{ui:SymbolIcon Eyedropper24}"
Command="{Binding PickColorCommand}" Command="{Binding PickColorCommand}"
@@ -112,54 +112,79 @@ 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">
<TextBlock Text="Wat ick schon so jeklaut hab" <ui:Button DockPanel.Dock="Right"
Content="Verlauf löschen"
Appearance="Secondary"
Icon="{ui:SymbolIcon Delete24}"
Command="{Binding ClearHistoryCommand}"
Padding="8,4"
VerticalAlignment="Center" />
<ui:Button DockPanel.Dock="Right"
Content="Exportieren"
Appearance="Secondary"
Icon="{ui:SymbolIcon ArrowExportUp24}"
Command="{Binding ExportHistoryCommand}"
Padding="8,4"
Margin="0,0,8,0"
VerticalAlignment="Center" />
<StackPanel>
<TextBlock Text="Farbverlauf"
Style="{StaticResource HeaderText}" /> Style="{StaticResource HeaderText}" />
<TextBlock Text="Druff klicken und ab dafuer, wa" <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 +192,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

@@ -77,14 +77,14 @@ namespace MaxSlurper
_notifyIcon.Text = "MaxSlurper"; _notifyIcon.Text = "MaxSlurper";
var contextMenu = new ContextMenuStrip(); var contextMenu = new ContextMenuStrip();
var pickItem = new ToolStripMenuItem("Farbe schlürfen"); var pickItem = new ToolStripMenuItem("Farbe aufnehmen");
// Use BeginInvoke to avoid synchronous invocation while windows may be closing // Use BeginInvoke to avoid synchronous invocation while windows may be closing
pickItem.Click += (s, e) => { Dispatcher.BeginInvoke(new Action(() => _vm.PickColorCommand.Execute(null))); }; pickItem.Click += (s, e) => { Dispatcher.BeginInvoke(new Action(() => _vm.PickColorCommand.Execute(null))); };
var openItem = new ToolStripMenuItem("Fenster uffmachen"); var openItem = new ToolStripMenuItem("Fenster öffnen");
openItem.Click += (s, e) => { Dispatcher.BeginInvoke(new Action(() => { Show(); WindowState = WindowState.Normal; Activate(); })); }; openItem.Click += (s, e) => { Dispatcher.BeginInvoke(new Action(() => { Show(); WindowState = WindowState.Normal; Activate(); })); };
var settingsItem = new ToolStripMenuItem("Einstellungen"); var settingsItem = new ToolStripMenuItem("Einstellungen");
settingsItem.Click += (s, e) => { Dispatcher.BeginInvoke(new Action(() => { Show(); WindowState = WindowState.Normal; Activate(); _vm.OpenSettingsCommand.Execute(null); })); }; settingsItem.Click += (s, e) => { Dispatcher.BeginInvoke(new Action(() => { Show(); WindowState = WindowState.Normal; Activate(); _vm.OpenSettingsCommand.Execute(null); })); };
var exitItem = new ToolStripMenuItem("Tschüss"); var exitItem = new ToolStripMenuItem("Beenden");
exitItem.Click += (s, e) => { _notifyIcon.Visible = false; System.Windows.Application.Current.Shutdown(); }; exitItem.Click += (s, e) => { _notifyIcon.Visible = false; System.Windows.Application.Current.Shutdown(); };
contextMenu.Items.Add(pickItem); contextMenu.Items.Add(pickItem);
contextMenu.Items.Add(openItem); contextMenu.Items.Add(openItem);

View File

@@ -13,7 +13,7 @@
<Authors>Mathias Wagner</Authors> <Authors>Mathias Wagner</Authors>
<Company>MaxSlurper</Company> <Company>MaxSlurper</Company>
<Product>MaxSlurper</Product> <Product>MaxSlurper</Product>
<Description>Weil Max danach gefragt hat</Description> <Description>Farbwähler-Anwendung</Description>
<Copyright>Copyright © 2025</Copyright> <Copyright>Copyright © 2025</Copyright>
<ApplicationIcon>logo.ico</ApplicationIcon> <ApplicationIcon>logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>

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

@@ -1,6 +1,7 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using MaxSlurper.Models; using MaxSlurper.Models;
@@ -38,9 +39,11 @@ 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; }
public ICommand ExportHistoryCommand { get; }
public MainViewModel(IColorPickerService colorPicker, IAudioPlayer audioPlayer, ISettingsService settingsService) public MainViewModel(IColorPickerService colorPicker, IAudioPlayer audioPlayer, ISettingsService settingsService)
{ {
@@ -51,10 +54,19 @@ 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());
ExportHistoryCommand = new RelayCommand(_ => ExportHistory(), _ => History.Count > 0);
// 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 +91,9 @@ 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();
((RelayCommand)ExportHistoryCommand).RaiseCanExecuteChanged();
} }
private void OpenColorPicker() private void OpenColorPicker()
@@ -104,6 +119,9 @@ 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();
((RelayCommand)ExportHistoryCommand).RaiseCanExecuteChanged();
} }
} }
@@ -119,6 +137,25 @@ namespace MaxSlurper.ViewModels
private void ClearHistory() private void ClearHistory()
{ {
History.Clear(); History.Clear();
Selected = null;
_settingsService.SaveHistory(History);
((RelayCommand)ClearHistoryCommand).RaiseCanExecuteChanged();
((RelayCommand)ExportHistoryCommand).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();
((RelayCommand)ExportHistoryCommand).RaiseCanExecuteChanged();
} }
private void CopyHex(object? parameter) private void CopyHex(object? parameter)
@@ -134,9 +171,62 @@ namespace MaxSlurper.ViewModels
// Show a notification (optional - can add UI feedback) // Show a notification (optional - can add UI feedback)
} }
private void ExportHistory()
{
var dialog = new Microsoft.Win32.SaveFileDialog
{
Title = "Farbpalette exportieren",
Filter = "CSS-Datei (*.css)|*.css|JSON-Datei (*.json)|*.json|Textdatei (*.txt)|*.txt",
DefaultExt = ".css",
FileName = "palette"
};
if (dialog.ShowDialog() != true) return;
var sb = new StringBuilder();
var ext = System.IO.Path.GetExtension(dialog.FileName).ToLowerInvariant();
switch (ext)
{
case ".css":
sb.AppendLine(":root {");
for (int i = 0; i < History.Count; i++)
{
var c = History[i];
sb.AppendLine($" --color-{i + 1}: {c.Hex};");
}
sb.AppendLine("}");
break;
case ".json":
sb.AppendLine("[");
for (int i = 0; i < History.Count; i++)
{
var c = History[i];
var comma = i < History.Count - 1 ? "," : "";
sb.AppendLine($" {{ \"hex\": \"{c.Hex}\", \"rgb\": \"{c.Rgb}\" }}{comma}");
}
sb.AppendLine("]");
break;
default: // .txt
foreach (var c in History)
sb.AppendLine(c.Hex);
break;
}
System.IO.File.WriteAllText(dialog.FileName, sb.ToString());
}
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;

View File

@@ -1 +1,3 @@
# MaxSlurper # MaxSlurper
Der ColorPicker der einen Slurp-Sound macht