mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
commit
de6edaf565
@ -73,7 +73,9 @@
|
||||
MinWidth="95"
|
||||
MaxLength="9"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Stretch">
|
||||
HorizontalAlignment="Stretch"
|
||||
FontFamily="Consolas"
|
||||
CharacterCasing="Upper">
|
||||
<materialDesign:TextFieldAssist.CharacterCounterStyle>
|
||||
<Style TargetType="TextBlock" />
|
||||
</materialDesign:TextFieldAssist.CharacterCounterStyle>
|
||||
@ -82,7 +84,7 @@
|
||||
<Border Width="15"
|
||||
Height="15"
|
||||
CornerRadius="15"
|
||||
Margin="0 0 8 0"
|
||||
Margin="0 0 2 0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Background="{StaticResource Checkerboard}">
|
||||
|
||||
@ -32,6 +32,7 @@ namespace Artemis.UI.Shared.Screens.GradientEditor
|
||||
ColorStop.Position = (float) Math.Round(value / _gradientEditorViewModel.PreviewWidth, 3, MidpointRounding.AwayFromZero);
|
||||
NotifyOfPropertyChange(nameof(Offset));
|
||||
NotifyOfPropertyChange(nameof(OffsetPercent));
|
||||
NotifyOfPropertyChange(nameof(OffsetFloat));
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,6 +44,20 @@ namespace Artemis.UI.Shared.Screens.GradientEditor
|
||||
ColorStop.Position = Math.Min(100, Math.Max(0, value)) / 100f;
|
||||
NotifyOfPropertyChange(nameof(Offset));
|
||||
NotifyOfPropertyChange(nameof(OffsetPercent));
|
||||
NotifyOfPropertyChange(nameof(OffsetFloat));
|
||||
}
|
||||
}
|
||||
|
||||
// Functionally similar to Offset Percent, but doesn't round on get in order to prevent inconsistencies (and is 0 to 1)
|
||||
public float OffsetFloat
|
||||
{
|
||||
get => ColorStop.Position;
|
||||
set
|
||||
{
|
||||
ColorStop.Position = Math.Min(1, Math.Max(0, value));
|
||||
NotifyOfPropertyChange(nameof(Offset));
|
||||
NotifyOfPropertyChange(nameof(OffsetPercent));
|
||||
NotifyOfPropertyChange(nameof(OffsetFloat));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,9 +12,9 @@
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
|
||||
Width="400"
|
||||
Height="400"
|
||||
Height="450"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
d:DesignWidth="400"
|
||||
d:DataContext="{d:DesignInstance local:GradientEditorViewModel}">
|
||||
<UserControl.Resources>
|
||||
<shared:ColorGradientToGradientStopsConverter x:Key="ColorGradientToGradientStopsConverter" />
|
||||
@ -40,7 +40,7 @@
|
||||
</VisualBrush>
|
||||
</UserControl.Resources>
|
||||
<UserControl.InputBindings>
|
||||
<KeyBinding Key="Delete" Command="{s:Action RemoveColorStop}" CommandParameter="{Binding SelectedColorStopViewModel}"/>
|
||||
<KeyBinding Key="Delete" Command="{s:Action RemoveColorStop}" CommandParameter="{Binding SelectedColorStopViewModel}" />
|
||||
</UserControl.InputBindings>
|
||||
<Grid Margin="16">
|
||||
<Grid.RowDefinitions>
|
||||
@ -60,8 +60,83 @@
|
||||
</StackPanel>
|
||||
<Separator Grid.Row="1" Margin="0 5" />
|
||||
<StackPanel Grid.Row="2" Margin="0 5" ClipToBounds="False">
|
||||
<TextBlock Margin="0 5">Gradient</TextBlock>
|
||||
|
||||
<Grid Margin="0 0 0 5">
|
||||
<TextBlock Margin="0 5" VerticalAlignment="Center">Gradient</TextBlock>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
|
||||
<Button Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Margin="0 0 5 0"
|
||||
Padding="0"
|
||||
Command="{s:Action SpreadColorStops}"
|
||||
ToolTip="Spread Stops"
|
||||
IsEnabled="{Binding HasMoreThanOneStop}"
|
||||
HorizontalAlignment="Left"
|
||||
Height="25" Width="25">
|
||||
<materialDesign:PackIcon Kind="ArrowLeftRight" />
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Margin="0 0 5 0"
|
||||
Padding="0"
|
||||
Command="{s:Action ToggleSeam}"
|
||||
ToolTip="Toggle Seamless"
|
||||
IsEnabled="{Binding HasMoreThanOneStop}"
|
||||
HorizontalAlignment="Left"
|
||||
Height="25" Width="25">
|
||||
<materialDesign:PackIcon Kind="SineWave" />
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Margin="0 0 5 0"
|
||||
Padding="0"
|
||||
Command="{s:Action FlipColorStops}"
|
||||
ToolTip="Flip Stops"
|
||||
IsEnabled="{Binding HasMoreThanOneStop}"
|
||||
HorizontalAlignment="Left"
|
||||
Height="25" Width="25">
|
||||
<materialDesign:PackIcon Kind="FlipHorizontal" />
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Margin="0 0 5 0"
|
||||
Padding="0"
|
||||
Command="{s:Action RotateColorStops}"
|
||||
ToolTip="Rotate Stops (shift to invert)"
|
||||
IsEnabled="{Binding HasMoreThanOneStop}"
|
||||
HorizontalAlignment="Left"
|
||||
Height="25" Width="25">
|
||||
<materialDesign:PackIcon Kind="AxisZRotateCounterclockwise" />
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Padding="0"
|
||||
Command="{s:Action ShowClearGradientPopup}"
|
||||
ToolTip="Clear All Color Stops"
|
||||
IsEnabled="{Binding HasMoreThanOneStop}"
|
||||
HorizontalAlignment="Left"
|
||||
Height="25" Width="25"
|
||||
x:Name="ClearGradientButton">
|
||||
<StackPanel>
|
||||
<materialDesign:PackIcon Kind="DeleteSweep" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Popup
|
||||
AllowsTransparency="True"
|
||||
Placement="Right"
|
||||
VerticalOffset="-25"
|
||||
HorizontalOffset="-5"
|
||||
CustomPopupPlacementCallback="{x:Static materialDesign:CustomPopupPlacementCallbackHelper.LargePopupCallback}"
|
||||
PlacementTarget="{Binding ElementName=ClearGradientButton}"
|
||||
StaysOpen="False"
|
||||
PopupAnimation="Fade"
|
||||
IsOpen="{Binding ClearGradientPopupOpen, Mode=OneWay}">
|
||||
<materialDesign:Card Margin="30" Padding="12" materialDesign:ShadowAssist.ShadowDepth="Depth4">
|
||||
<StackPanel HorizontalAlignment="Center">
|
||||
<TextBlock Style="{StaticResource MaterialDesignSubtitle2TextBlock}" TextAlignment="Center" Margin="0 0 0 10">Clear Gradient?</TextBlock>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Command="{s:Action HideClearGradientPopup}" Style="{StaticResource MaterialDesignOutlinedButton}" Margin="0 0 10 0">No</Button>
|
||||
<Button Command="{s:Action ClearGradientAndHide}">Yes</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</materialDesign:Card>
|
||||
</Popup>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Border Background="{StaticResource Checkerboard}">
|
||||
<Rectangle x:Name="Preview" Height="40" shared:SizeObserver.Observe="True" shared:SizeObserver.ObservedWidth="{Binding PreviewWidth, Mode=OneWayToSource}">
|
||||
<Rectangle.Fill>
|
||||
@ -90,8 +165,7 @@
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBlock Margin="0 5">Selected stop</TextBlock>
|
||||
<TextBlock Margin="0 6 0 0" FontWeight="Bold">Selected stop:</TextBlock>
|
||||
|
||||
<Grid Margin="0 5">
|
||||
<Grid.ColumnDefinitions>
|
||||
@ -100,7 +174,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal">
|
||||
<Label HorizontalAlignment="Left" Margin="-5,0,0,0">Color:</Label>
|
||||
<Label HorizontalAlignment="Left" Margin="-5,1,0,0">Color:</Label>
|
||||
<shared:ColorPicker
|
||||
x:Name="CurrentColor"
|
||||
Width="85"
|
||||
@ -109,8 +183,8 @@
|
||||
IsEnabled="{Binding HasSelectedColorStopViewModel}" />
|
||||
|
||||
<Label HorizontalAlignment="Center">Location:</Label>
|
||||
<TextBox Width="40"
|
||||
Text="{Binding SelectedColorStopViewModel.OffsetPercent}"
|
||||
<TextBox Width="30"
|
||||
Text="{Binding SelectedColorStopViewModel.OffsetPercent, UpdateSourceTrigger=PropertyChanged}"
|
||||
IsEnabled="{Binding HasSelectedColorStopViewModel}"
|
||||
materialDesign:HintAssist.Hint="0"
|
||||
Margin="5 0 0 0" />
|
||||
@ -122,8 +196,15 @@
|
||||
Margin="8,0,0,0"
|
||||
IsEnabled="{Binding HasSelectedColorStopViewModel}"
|
||||
Command="{s:Action RemoveColorStop}"
|
||||
CommandParameter="{Binding SelectedColorStopViewModel}">
|
||||
DELETE
|
||||
CommandParameter="{Binding SelectedColorStopViewModel}"
|
||||
ToolTip="Delete Selected Stop">
|
||||
<Button.Resources>
|
||||
<SolidColorBrush x:Key="PrimaryHueMidBrush" Color="#c94848" />
|
||||
</Button.Resources>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Kind="Delete" />
|
||||
<TextBlock Margin="4 0 0 0">Delete</TextBlock>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
@ -27,19 +28,9 @@ namespace Artemis.UI.Shared.Screens.GradientEditor
|
||||
|
||||
PropertyChanged += UpdateColorStopViewModels;
|
||||
ColorGradient.CollectionChanged += ColorGradientOnCollectionChanged;
|
||||
ColorStopViewModels.CollectionChanged += ColorStopViewModelsOnCollectionChanged;
|
||||
}
|
||||
|
||||
#region Overrides of DialogViewModelBase
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDialogClosed(object sender, DialogClosingEventArgs e)
|
||||
{
|
||||
ColorGradient.CollectionChanged -= ColorGradientOnCollectionChanged;
|
||||
base.OnDialogClosed(sender, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public BindableCollection<ColorStopViewModel> ColorStopViewModels { get; }
|
||||
|
||||
public ColorStopViewModel? SelectedColorStopViewModel
|
||||
@ -53,6 +44,9 @@ namespace Artemis.UI.Shared.Screens.GradientEditor
|
||||
}
|
||||
|
||||
public bool HasSelectedColorStopViewModel => SelectedColorStopViewModel != null;
|
||||
public bool HasMoreThanOneStop => ColorStopViewModels.Count > 1;
|
||||
private bool popupOpen = false;
|
||||
public bool ClearGradientPopupOpen => popupOpen;
|
||||
|
||||
public ColorGradient ColorGradient { get; }
|
||||
|
||||
@ -62,11 +56,20 @@ namespace Artemis.UI.Shared.Screens.GradientEditor
|
||||
set => SetAndNotify(ref _previewWidth, value);
|
||||
}
|
||||
|
||||
public ColorGradient Stops
|
||||
public ColorGradient Stops => ColorGradient;
|
||||
|
||||
#region Overrides of DialogViewModelBase
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDialogClosed(object sender, DialogClosingEventArgs e)
|
||||
{
|
||||
get => ColorGradient;
|
||||
ColorGradient.CollectionChanged -= ColorGradientOnCollectionChanged;
|
||||
ColorStopViewModels.CollectionChanged -= ColorStopViewModelsOnCollectionChanged;
|
||||
base.OnDialogClosed(sender, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void AddColorStop(object sender, MouseEventArgs e)
|
||||
{
|
||||
Canvas? child = VisualTreeUtilities.FindChild<Canvas>((DependencyObject) sender, null);
|
||||
@ -79,19 +82,118 @@ namespace Artemis.UI.Shared.Screens.GradientEditor
|
||||
ColorStopViewModels.Insert(index, viewModel);
|
||||
|
||||
SelectColorStop(viewModel);
|
||||
NotifyOfPropertyChange(nameof(HasMoreThanOneStop));
|
||||
}
|
||||
|
||||
public void RemoveColorStop(ColorStopViewModel colorStopViewModel)
|
||||
{
|
||||
if (colorStopViewModel == null)
|
||||
return;
|
||||
|
||||
ColorStopViewModels.Remove(colorStopViewModel);
|
||||
ColorGradient.Remove(colorStopViewModel.ColorStop);
|
||||
|
||||
SelectColorStop(null);
|
||||
NotifyOfPropertyChange(nameof(HasMoreThanOneStop));
|
||||
}
|
||||
|
||||
#region Gradient Tools
|
||||
public void SpreadColorStops()
|
||||
{
|
||||
List<ColorStopViewModel> stops = ColorStopViewModels.OrderBy(x => x.OffsetFloat).ToList();
|
||||
int index = 0;
|
||||
foreach (ColorStopViewModel stop in stops)
|
||||
{
|
||||
stop.OffsetFloat = index / ((float) stops.Count - 1);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
public void RotateColorStops()
|
||||
{
|
||||
List<ColorStopViewModel> stops;
|
||||
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
|
||||
stops = ColorStopViewModels.OrderBy(x => x.OffsetFloat).ToList();
|
||||
else
|
||||
stops = ColorStopViewModels.OrderByDescending(x => x.OffsetFloat).ToList();
|
||||
|
||||
float lastStopPosition = stops.Last().OffsetFloat;
|
||||
foreach (ColorStopViewModel stop in stops)
|
||||
{
|
||||
float tempStop = stop.OffsetFloat;
|
||||
stop.OffsetFloat = lastStopPosition;
|
||||
lastStopPosition = tempStop;
|
||||
}
|
||||
}
|
||||
|
||||
public void FlipColorStops()
|
||||
{
|
||||
foreach (ColorStopViewModel stop in ColorStopViewModels) stop.OffsetFloat = 1 - stop.OffsetFloat;
|
||||
}
|
||||
|
||||
public void ToggleSeam()
|
||||
{
|
||||
if (ColorGradient.IsSeamless())
|
||||
{
|
||||
// Remove the last stop
|
||||
ColorStopViewModel? stopToRemove = ColorStopViewModels.OrderBy(x => x.OffsetFloat).Last();
|
||||
|
||||
if (stopToRemove == SelectedColorStopViewModel) SelectColorStop(null);
|
||||
|
||||
ColorStopViewModels.Remove(stopToRemove);
|
||||
ColorGradient.Remove(stopToRemove.ColorStop);
|
||||
|
||||
// Uncompress the stops if there is still more than one
|
||||
List<ColorStopViewModel> stops = ColorStopViewModels.OrderBy(x => x.OffsetFloat).ToList();
|
||||
|
||||
if (stops.Count >= 2)
|
||||
{
|
||||
float multiplier = stops.Count/(stops.Count - 1f);
|
||||
foreach (ColorStopViewModel stop in stops)
|
||||
stop.OffsetFloat = Math.Min(stop.OffsetFloat * multiplier, 100f);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compress existing stops to the left
|
||||
List<ColorStopViewModel> stops = ColorStopViewModels.OrderBy(x => x.OffsetFloat).ToList();
|
||||
|
||||
float multiplier = (stops.Count - 1f)/stops.Count;
|
||||
foreach (ColorStopViewModel stop in stops)
|
||||
stop.OffsetFloat *= multiplier;
|
||||
|
||||
// Add a stop to the end that is the same color as the first stop
|
||||
ColorGradientStop newStop = new(ColorGradient.First().Color, 1f);
|
||||
ColorGradient.Add(newStop);
|
||||
|
||||
int index = ColorGradient.IndexOf(newStop);
|
||||
ColorStopViewModel viewModel = new(this, newStop);
|
||||
ColorStopViewModels.Insert(index, viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowClearGradientPopup()
|
||||
{
|
||||
popupOpen = true;
|
||||
NotifyOfPropertyChange(nameof(ClearGradientPopupOpen));
|
||||
}
|
||||
public void HideClearGradientPopup()
|
||||
{
|
||||
popupOpen = false;
|
||||
NotifyOfPropertyChange(nameof(ClearGradientPopupOpen));
|
||||
}
|
||||
public void ClearGradientAndHide()
|
||||
{
|
||||
ClearGradient();
|
||||
HideClearGradientPopup();
|
||||
}
|
||||
public void ClearGradient()
|
||||
{
|
||||
ColorGradient.Clear();
|
||||
ColorStopViewModels.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public Point GetPositionInPreview(object sender, MouseEventArgs e)
|
||||
{
|
||||
Canvas? parent = VisualTreeUtilities.FindParent<Canvas>((DependencyObject) sender, null);
|
||||
@ -127,10 +229,15 @@ namespace Artemis.UI.Shared.Screens.GradientEditor
|
||||
foreach (ColorGradientStop colorStop in ColorGradient)
|
||||
ColorStopViewModels.Add(new ColorStopViewModel(this, colorStop));
|
||||
}
|
||||
|
||||
|
||||
private void ColorGradientOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
NotifyOfPropertyChange(nameof(ColorGradient));
|
||||
}
|
||||
|
||||
private void ColorStopViewModelsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
NotifyOfPropertyChange(nameof(HasMoreThanOneStop));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user