CI / Go Backend (push) Canceled after 0s
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
243 lines
7.7 KiB
C#
243 lines
7.7 KiB
C#
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Controls.Primitives;
|
||
using System.Windows.Input;
|
||
|
||
using PCL.Core.App.Localization;
|
||
namespace PCL;
|
||
|
||
public class MyComboBox : ComboBox
|
||
{
|
||
public delegate void TextChangedEventHandler(object sender, TextChangedEventArgs e);
|
||
|
||
public static readonly DependencyProperty HintTextProperty = DependencyProperty.Register("HintText", typeof(string),
|
||
typeof(MyComboBox), new PropertyMetadata("", (d, e) =>
|
||
{
|
||
var c = (MyComboBox)d;
|
||
if (c.textBox is not null)
|
||
c.textBox.HintText = (string)e.NewValue;
|
||
}));
|
||
|
||
private string _Text;
|
||
|
||
// 鼠标按下接口
|
||
private bool isMouseDown;
|
||
|
||
// 修复 WPF Bug:下拉框文本修改后,依然误认为还选择着此前的选项,导致再次点击该选项时内容不变
|
||
private bool isTextChanging;
|
||
private double realWidth; // 由于下拉框 Popup 宽度与 Width 一致,故不能为 NaN(Auto)
|
||
private MyTextBox textBox;
|
||
|
||
// 基础
|
||
public int Uuid = ModBase.GetUuid();
|
||
|
||
public MyComboBox()
|
||
{
|
||
_Text = SelectedItem?.ToString() ?? "";
|
||
PreviewMouseLeftButtonDown += MyComboBox_PreviewMouseLeftButtonDown;
|
||
PreviewMouseLeftButtonUp += MyComboBox_PreviewMouseLeftButtonUp;
|
||
MouseLeave += MyComboBox_PreviewMouseLeftButtonUp;
|
||
IsEnabledChanged += (_, _) => RefreshColor();
|
||
MouseEnter += (_, _) => RefreshColor();
|
||
MouseLeave += (_, _) => RefreshColor();
|
||
PreviewMouseLeftButtonDown += (_, _) => RefreshColor();
|
||
PreviewMouseLeftButtonUp += (_, _) => RefreshColor();
|
||
GotKeyboardFocus += (_, _) => RefreshColor();
|
||
DropDownOpened += MyComboBox_DropDownOpened;
|
||
DropDownClosed += MyComboBox_DropDownClosed;
|
||
TextChanged += MyComboBox_TextChanged;
|
||
}
|
||
|
||
public string HintText
|
||
{
|
||
get => (string)GetValue(HintTextProperty);
|
||
set => SetValue(HintTextProperty, value);
|
||
}
|
||
|
||
public new string Text
|
||
{
|
||
get
|
||
{
|
||
if (IsEditable)
|
||
{
|
||
if (textBox is null) return _Text ?? "";
|
||
return textBox.Text ?? "";
|
||
}
|
||
|
||
return (SelectedItem ?? "").ToString();
|
||
}
|
||
set
|
||
{
|
||
if (IsEditable)
|
||
{
|
||
if (textBox is null)
|
||
_Text = value;
|
||
else
|
||
textBox.Text = value;
|
||
}
|
||
else
|
||
{
|
||
throw new NotSupportedException("该 ComboBox 不支持修改文本。");
|
||
}
|
||
}
|
||
}
|
||
|
||
public bool DropDownWidthSync { get; set; } = true;
|
||
|
||
public ContentPresenter ContentPresenter => (ContentPresenter)Template.FindName("PART_Content", this);
|
||
public event TextChangedEventHandler? TextChanged;
|
||
|
||
public override void OnApplyTemplate()
|
||
{
|
||
base.OnApplyTemplate();
|
||
if (!IsEditable)
|
||
return;
|
||
try
|
||
{
|
||
textBox = (MyTextBox)Template.FindName("PART_EditableTextBox", this);
|
||
textBox.AddHandler(LostFocusEvent, new RoutedEventHandler((_, _) => RefreshColor()));
|
||
textBox.changedEventList.Add((sender, e) => TextChanged?.Invoke(sender, (TextChangedEventArgs)e));
|
||
textBox.Tag = Tag; // 有时需要用文本框的 Tag 来写入设置
|
||
if (string.IsNullOrEmpty(Text))
|
||
textBox.Text = _Text;
|
||
else
|
||
TextChanged?.Invoke(this, null);
|
||
if (HintText.Length > 0)
|
||
textBox.HintText = HintText;
|
||
textBox.SetResourceReference(TextBoxBase.CaretBrushProperty, "ColorBrushGray1");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ModBase.Log(
|
||
ex,
|
||
"初始化可编辑文本框失败(" + (Name ?? "") + ")",
|
||
ModBase.LogLevel.Feedback,
|
||
userSummary: Lang.Text("Application.Control.Error.OperationFailed"));
|
||
}
|
||
}
|
||
|
||
private void MyComboBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||
{
|
||
isMouseDown = true;
|
||
}
|
||
|
||
private void MyComboBox_PreviewMouseLeftButtonUp(object sender, EventArgs e)
|
||
{
|
||
isMouseDown = false;
|
||
}
|
||
|
||
// 指向动画
|
||
public void RefreshColor()
|
||
{
|
||
// 判断当前颜色
|
||
string foreColorName;
|
||
string backColorName;
|
||
int time;
|
||
if (IsEnabled)
|
||
{
|
||
if (isMouseDown || IsDropDownOpen ||
|
||
(IsEditable && ((MyTextBox)Template.FindName("PART_EditableTextBox", this)).IsFocused))
|
||
{
|
||
foreColorName = "ColorBrush3";
|
||
backColorName = "ColorBrush7";
|
||
time = 10;
|
||
}
|
||
else if (IsMouseOver)
|
||
{
|
||
foreColorName = "ColorBrush4";
|
||
backColorName = "ColorBrush7";
|
||
time = 100;
|
||
}
|
||
else
|
||
{
|
||
foreColorName = "ColorBrushBg0";
|
||
backColorName = "ColorBrushHalfWhite";
|
||
time = 100;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
foreColorName = "ColorBrushGray5";
|
||
backColorName = "ColorBrushGray6";
|
||
time = 200;
|
||
}
|
||
|
||
// 触发颜色动画
|
||
if (IsLoaded && ModAnimation.AniControlEnabled == 0) // 防止默认属性变更触发动画
|
||
{
|
||
// 有动画
|
||
ModAnimation.AniStart(
|
||
new[]
|
||
{
|
||
ModAnimation.AaColor(this, ForegroundProperty, foreColorName, time),
|
||
ModAnimation.AaColor(this, BackgroundProperty, backColorName, time)
|
||
}, "MyComboBox Color " + Uuid);
|
||
}
|
||
else
|
||
{
|
||
// 无动画
|
||
ModAnimation.AniStop("MyComboBox Color " + Uuid);
|
||
SetResourceReference(ForegroundProperty, foreColorName);
|
||
SetResourceReference(BackgroundProperty, backColorName);
|
||
}
|
||
}
|
||
|
||
private void MyComboBox_DropDownOpened(object sender, EventArgs e)
|
||
{
|
||
realWidth = Width;
|
||
if (DropDownWidthSync)
|
||
Width = ActualWidth;
|
||
try
|
||
{
|
||
var popup = (Grid)Template.FindName("PanPopup", this);
|
||
popup.Opacity = ModMain.frmMain.Opacity;
|
||
if (!DropDownWidthSync)
|
||
popup.MinWidth = ActualWidth;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ModBase.Log(
|
||
ex,
|
||
"设置下拉框属性失败",
|
||
ModBase.LogLevel.Feedback,
|
||
userSummary: Lang.Text("Application.Control.Error.OperationFailed"));
|
||
}
|
||
}
|
||
|
||
private void MyComboBox_DropDownClosed(object sender, EventArgs e)
|
||
{
|
||
Width = realWidth;
|
||
}
|
||
|
||
private void MyComboBox_TextChanged(object sender, TextChangedEventArgs e)
|
||
{
|
||
if (isTextChanging || !IsEditable)
|
||
return;
|
||
if (SelectedItem is null || Text == SelectedItem.ToString()) return;
|
||
{
|
||
var rawText = Text;
|
||
var rawSelectionStart = textBox.SelectionStart;
|
||
isTextChanging = true;
|
||
SelectedItem = null;
|
||
Text = rawText;
|
||
textBox.SelectionStart = rawSelectionStart;
|
||
isTextChanging = false;
|
||
}
|
||
}
|
||
|
||
// 用于 ItemsSource 的自定义容器
|
||
protected override DependencyObject GetContainerForItemOverride()
|
||
{
|
||
return new MyComboBoxItem();
|
||
}
|
||
|
||
private void MyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||
{
|
||
if (IsLoaded && ModAnimation.AniControlEnabled == 0) ModMain.RaiseCustomEvent(this);
|
||
}
|
||
|
||
protected override bool IsItemItsOwnContainerOverride(object item)
|
||
{
|
||
return item is MyComboBoxItem || base.IsItemItsOwnContainerOverride(item);
|
||
}
|
||
} |