1
0

feat: add FrameCell widget

This commit is contained in:
2026-04-12 10:25:21 +08:00
parent 8b42af42cc
commit 6a451c846d
8 changed files with 131 additions and 11 deletions

View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
namespace BallanceTasEditor.Frontend.Converters {
[ValueConversion(typeof(bool), typeof(Brush))]
public class CellIsSelectedToColorConverter : IValueConverter {
public static readonly CellIsSelectedToColorConverter Instance = new CellIsSelectedToColorConverter();
private static readonly SolidColorBrush SELECTED_BRUSH = new(Color.FromRgb(255, 152, 0));
private static readonly SolidColorBrush DESELECTED_BRUSH = new(Color.FromRgb(158, 158, 158));
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
var isSelected = value as bool?;
if (isSelected is null) {
return Binding.DoNothing;
} else {
if (isSelected.Value) {
return SELECTED_BRUSH;
} else {
return DESELECTED_BRUSH;
}
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
return Binding.DoNothing;
}
}
[ValueConversion(typeof(bool), typeof(Brush))]
public class CellIsSetToColorConverter : IValueConverter {
public static readonly CellIsSetToColorConverter Instance = new CellIsSetToColorConverter();
private static readonly SolidColorBrush SET_BRUSH = new(Color.FromRgb(30, 144, 255));
private static readonly SolidColorBrush UNSET_BRUSH = new(Color.FromRgb(255, 255, 255));
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
var isSet = value as bool?;
if (isSet is null) {
return Binding.DoNothing;
} else {
if (isSet.Value) {
return SET_BRUSH;
} else {
return UNSET_BRUSH;
}
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
return Binding.DoNothing;
}
}
}

View File

@@ -14,10 +14,10 @@ namespace BallanceTasEditor.Frontend.Converters {
public static readonly StringifiedDeltaTimeConverter Instance = new StringifiedDeltaTimeConverter();
public StringifiedDeltaTimeConverter() {
m_Validator = new Validator.FpsValidator();
m_Validator = new Validators.FpsValidator();
}
private Validator.FpsValidator m_Validator;
private Validators.FpsValidator m_Validator;
private static readonly string INVALID_DELTA_TIME = "N/A";
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {

View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BallanceTasEditor.Frontend.Validator {
namespace BallanceTasEditor.Frontend.Validators {
public interface IValidator<TIn, TOut> {
OneOf<TOut, string> Validate(TIn value);

View File

@@ -7,7 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BallanceTasEditor.Frontend.Validator {
namespace BallanceTasEditor.Frontend.Validators {
public sealed class ValidatorAdapter<TIn, TOut, V> where V: IValidator<TIn, TOut> {
public ValidatorAdapter(IValidator<TIn, TOut> validator) {

View File

@@ -28,15 +28,15 @@ namespace BallanceTasEditor.Frontend.ViewModels {
#region Validators
private static readonly Validator.ValidatorAdapter<string, int, Validator.CountValidator> g_CountValidator =
new Validator.ValidatorAdapter<string, int, Validator.CountValidator>(new Validator.CountValidator());
private static readonly Validators.ValidatorAdapter<string, int, Validators.CountValidator> g_CountValidator =
new Validators.ValidatorAdapter<string, int, Validators.CountValidator>(new Validators.CountValidator());
public static ValidationResult? ValidateCount(string value, ValidationContext context) {
return g_CountValidator.Validate(value, context);
}
private static readonly Validator.ValidatorAdapter<string, uint, Validator.FpsValidator> g_FpsValidator =
new Validator.ValidatorAdapter<string, uint, Validator.FpsValidator>(new Validator.FpsValidator());
private static readonly Validators.ValidatorAdapter<string, uint, Validators.FpsValidator> g_FpsValidator =
new Validators.ValidatorAdapter<string, uint, Validators.FpsValidator>(new Validators.FpsValidator());
public static ValidationResult? ValidateFps(string value, ValidationContext context) {
return g_FpsValidator.Validate(value, context);

View File

@@ -67,9 +67,9 @@
<MenuItem Header="Next Item" Icon="{StaticResource IconNextItem}" InputGestureText="F"/>
<MenuItem Header="Goto Item" Icon="{StaticResource IconGoto}" InputGestureText="G"/>
<Separator/>
<MenuItem Header="Select Mode" Icon="{StaticResource IconSelectMode}"/>
<MenuItem Header="Fill Mode" Icon="{StaticResource IconFillMode}"/>
<MenuItem Header="Draw Mode" Icon="{StaticResource IconDrawMode}"/>
<MenuItem Header="Select Mode" Icon="{StaticResource IconSelectMode}" InputGestureText="Q"/>
<MenuItem Header="Fill Mode" Icon="{StaticResource IconFillMode}" InputGestureText="W"/>
<MenuItem Header="Draw Mode" Icon="{StaticResource IconDrawMode}" InputGestureText="E"/>
<Separator/>
<MenuItem Header="Clear Keys" Icon="{StaticResource IconClearKeys}"/>
<MenuItem Header="Uniform FPS" Icon="{StaticResource IconUniformFps}"/>

View File

@@ -0,0 +1,13 @@
<UserControl x:Class="BallanceTasEditor.Frontend.Widgets.FrameCell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BallanceTasEditor.Frontend.Widgets"
xmlns:conveter="clr-namespace:BallanceTasEditor.Frontend.Converters"
mc:Ignorable="d"
x:Name="Root"
d:DesignHeight="60" d:DesignWidth="120">
<Rectangle Stroke="{Binding ElementName=Root, Path=IsSelected, Mode=OneWay, Converter={x:Static conveter:CellIsSelectedToColorConverter.Instance}}" StrokeThickness="3"
Fill="{Binding ElementName=Root, Path=IsSet, Mode=OneWay, Converter={x:Static conveter:CellIsSetToColorConverter.Instance}}"/>
</UserControl>

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BallanceTasEditor.Frontend.Widgets {
/// <summary>
/// Interaction logic for FrameCell.xaml
/// </summary>
public partial class FrameCell : UserControl {
public FrameCell() {
InitializeComponent();
}
public bool IsSelected {
get { return (bool)GetValue(IsSelectedProperty); }
set { SetValue(IsSelectedProperty, value); }
}
// Using a DependencyProperty as the backing store for IsSelected. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsSelectedProperty =
DependencyProperty.Register("IsSelected", typeof(bool), typeof(FrameCell), new PropertyMetadata(false));
public bool IsSet {
get { return (bool)GetValue(IsSetProperty); }
set { SetValue(IsSetProperty, value); }
}
// Using a DependencyProperty as the backing store for IsSet. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsSetProperty =
DependencyProperty.Register("IsSet", typeof(bool), typeof(FrameCell), new PropertyMetadata(false));
}
}