Files
xyou f70b061d1a
CI / Go Backend (push) Canceled after 0s
feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块

Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
2026-08-08 14:07:56 +08:00

887 lines
32 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.VisualBasic;
using PCL.Core.App;
using PCL.Core.Utils;
using PCL.Core.Utils.Exts;
using PCL.Core.App.Localization;
namespace PCL;
public partial class MyLocalCompItem
{
private string GetUpdateCompareDescription()
{
var currentName = Entry.compFile.FileName.Replace(".jar", "");
var newestName = Entry.UpdateFile.FileName.Replace(".jar", "");
// 简化名称对比
var currentSegs = currentName.Split('-').ToList();
var newestSegs = newestName.Split('-').ToList();
var shortened = false;
foreach (var Seg in currentSegs.ToList())
{
if (!newestSegs.Contains(Seg))
continue;
currentSegs.Remove(Seg);
newestSegs.Remove(Seg);
shortened = true;
}
if (shortened && currentSegs.Any() && newestSegs.Any())
{
currentName = currentSegs.Join("-");
newestName = newestSegs.Join("-");
Entry._Version = currentName; // 使用网络信息作为显示的版本号
}
return
Lang.Text("Instance.Resource.Item.UpdateCompare", currentName, Lang.TimeSpan(Entry.compFile.ReleaseDate - DateTime.Now), newestName, Lang.TimeSpan(Entry.UpdateFile.ReleaseDate - DateTime.Now));
}
public void Refresh()
{
Dispatcher.BeginInvoke(new Func<Task>(async () =>
{
// 更新
if (Entry.CanUpdate)
{
BtnUpdate.Visibility = Visibility.Visible;
BtnUpdate.ToolTip = $"{GetUpdateCompareDescription()}\r\n{Lang.Text("Instance.Resource.Item.UpdateToolTip")}";
}
else
{
BtnUpdate.Visibility = Visibility.Collapsed;
}
// 标题与描述
string descFileName;
if (Entry.IsFolder)
// 文件夹项的特殊处理
descFileName = Entry.Name;
else
switch (Entry.State)
{
case ModLocalComp.LocalCompFile.LocalFileStatus.Fine:
{
descFileName = ModBase.GetFileNameWithoutExtentionFromPath(Entry.path);
break;
}
case ModLocalComp.LocalCompFile.LocalFileStatus.Disabled:
{
descFileName =
ModBase.GetFileNameWithoutExtentionFromPath(Entry.path.Replace(".disabled", "")
.Replace(".old", "")); // McMod.McModState.Unavailable
break;
}
default:
{
descFileName = ModBase.GetFileNameFromPath(Entry.path);
break;
}
}
string newDescription;
var compTemp = Entry.Comp;
if (Entry.IsFolder)
{
// 文件夹项的特殊显示
Title = Entry.Name;
newDescription = Entry.Description;
}
else if (Config.Download.Comp.UiCompNameSolution == 1)
{
// 标题显示文件名,详情显示译名
// 标题
Title = descFileName;
SubTitle = "";
// 描述
if (Entry.Comp is null)
{
newDescription = Entry.Name;
}
else
{
var titles = await Task.Run(() => compTemp.GetControlTitle(false));
newDescription = titles.Key + titles.Value;
}
newDescription = newDescription.Replace(" | ", " / ");
if (Entry.Version is not null)
newDescription += $" ({Entry.Version})";
}
else
{
// 标题显示译名,详情显示文件名
// 标题
if (Entry.Comp is null)
{
Title = Entry.Name;
SubTitle = Entry.Version is null ? "" : " | " + Entry.Version;
}
else
{
var titles = await Task.Run(() => compTemp.GetControlTitle(false));
Title = titles.Key;
SubTitle = titles.Value + (Entry.Version is null ? "" : " | " + Entry.Version);
}
// 描述
newDescription = descFileName;
}
if (Entry.Comp is not null)
newDescription += ": " + Entry.Comp.Description.Replace("\r", "").Replace("\n", "");
else if (Entry.Description is not null)
newDescription += ": " + Entry.Description.Replace("\r", "").Replace("\n", "");
else if (!Entry.IsFileAvailable) newDescription += ": " + Lang.Text("Instance.Resource.Item.InfoUnavailable");
Description = newDescription;
if (Checked)
LabTitle.SetResourceReference(TextBlock.ForegroundProperty,
Entry.State == ModLocalComp.LocalCompFile.LocalFileStatus.Fine ? "ColorBrush2" : "ColorBrush5");
else
LabTitle.SetResourceReference(TextBlock.ForegroundProperty,
Entry.State == ModLocalComp.LocalCompFile.LocalFileStatus.Fine ? "ColorBrush1" : "ColorBrushGray4");
// 主 Logo
Logo = Entry.GetLogo();
// 图标右下角的 Logo
if (Entry.State == ModLocalComp.LocalCompFile.LocalFileStatus.Fine)
{
if (imgState is not null)
{
Children.Remove(imgState);
imgState = null;
}
}
else
{
if (imgState is null)
{
imgState = new Image
{
Width = 20d,
Height = 20d,
Margin = new Thickness(0d, 0d, -5, -3),
IsHitTestVisible = false,
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Bottom
};
RenderOptions.SetBitmapScalingMode(imgState, BitmapScalingMode.HighQuality);
SetColumn(imgState, 1);
SetRow(imgState, 1);
SetRowSpan(imgState, 2);
Children.Add(imgState);
// <Image x:Name="ImgState" RenderOptions.BitmapScalingMode="HighQuality" Width="16" Height="16" Margin="0,0,-3,-1"
// Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" IsHitTestVisible="False"
// HorizontalAlignment="Right" VerticalAlignment="Bottom"
// Source="/Images/Icons/Unavailable.png" />
}
imgState.Source = new MyBitmap(ModBase.pathImage + $"Icons/{Entry.State}.png");
}
// 标签
if (Entry.IsFolder)
// 为文件夹添加标签
Tags = new List<string> { Lang.Text("Instance.Resource.Item.FolderTag") };
else if (Entry.Comp is not null) Tags = Entry.Comp.Tags;
}));
}
public void RefreshColor(object sender, EventArgs e)
{
InitLate(sender, e);
// 触发颜色动画
var time = IsMouseOver ? 120 : 180;
var ani = new List<ModAnimation.AniData>();
// ButtonStack
if (buttonStack is not null)
{
if (IsMouseOver)
{
ani.Add(ModAnimation.AaOpacity(buttonStack, 1d - buttonStack.Opacity, (int)Math.Round(time * 0.7d),
(int)Math.Round(time * 0.3d)));
ani.Add(ModAnimation.AaDouble(
i => ColumnPaddingRight.Width =
new GridLength(Math.Max(0, ColumnPaddingRight.Width.Value + (double)i)),
5 + Buttons.Count() * 25 - ColumnPaddingRight.Width.Value, (int)Math.Round(time * 0.3d),
(int)Math.Round(time * 0.7d)));
}
else
{
ani.Add(ModAnimation.AaOpacity(buttonStack, -buttonStack.Opacity, (int)Math.Round(time * 0.4d)));
ani.Add(ModAnimation.AaDouble(
i => ColumnPaddingRight.Width =
new GridLength(Math.Max(0, ColumnPaddingRight.Width.Value + (double)i)),
4d - ColumnPaddingRight.Width.Value, (int)Math.Round(time * 0.4d)));
}
}
// RectBack
if (IsMouseOver || Checked)
{
ani.AddRange(new[]
{
ModAnimation.AaColor(RectBack, Border.BackgroundProperty, isMouseDown ? "ColorBrush6" : "ColorBrushBg1",
time),
ModAnimation.AaOpacity(RectBack, 1d - RectBack.Opacity, time, ease: new ModAnimation.AniEaseOutFluent())
});
if (isMouseDown)
ani.Add(ModAnimation.AaScaleTransform(RectBack,
0.996d - ((ScaleTransform)RectBack.RenderTransform).ScaleX, (int)Math.Round(time * 1.2d),
ease: new ModAnimation.AniEaseOutFluent()));
else
ani.Add(ModAnimation.AaScaleTransform(RectBack, 1d - ((ScaleTransform)RectBack.RenderTransform).ScaleX,
(int)Math.Round(time * 1.2d), ease: new ModAnimation.AniEaseOutFluent()));
}
else
{
ani.AddRange(new[]
{
ModAnimation.AaOpacity(RectBack, -RectBack.Opacity, time),
ModAnimation.AaScaleTransform(RectBack, 0.996d - ((ScaleTransform)RectBack.RenderTransform).ScaleX,
time, ease: new ModAnimation.AniEaseOutFluent()),
ModAnimation.AaScaleTransform(RectBack, -0.196d, 1, after: true)
});
}
ModAnimation.AniStart(ani, "LocalModItem Color " + Uuid);
}
// 触发虚拟化内容
private void InitLate(object sender, EventArgs e)
{
if (buttonHandler is not null)
{
buttonHandler((MyLocalCompItem)sender, e);
buttonHandler = null;
}
}
// 显示更新日志
private void BtnUpdate_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
ShowUpdateLog();
}
private void ShowUpdateLog()
{
if (Entry.Comp is not null)
{
if (!Information.IsNumeric(Entry.Comp.Id))
{
var modrinthUrl = Entry.changelogUrls.FirstOrDefault(x => x.Contains("modrinth.com"));
if (modrinthUrl is not null)
{
ModBase.OpenWebsite(modrinthUrl);
return;
}
}
else
{
var curseForgeUrl = Entry.changelogUrls.FirstOrDefault(x => x.Contains("curseforge.com"));
if (curseForgeUrl is not null)
{
ModBase.OpenWebsite(curseForgeUrl);
return;
}
}
}
ModBase.Log(
Lang.Text("Instance.Resource.Item.OpenChangelogFailed"),
ModBase.LogLevel.Hint,
userSummary: Lang.Text("Instance.Resource.Item.OpenChangelogFailed"));
}
// 触发更新
private void BtnUpdate_Click(object sender, EventArgs e)
{
switch (ModMain.MyMsgBox(
$"{Lang.Text("Instance.Resource.Item.UpdateConfirm.Message", Entry.Name)}\r\n\r\n{GetUpdateCompareDescription()}",
Lang.Text("Instance.Resource.Item.UpdateConfirm.Title"),
Lang.Text("Instance.Resource.Item.Update"), Lang.Text("Instance.Resource.Item.ViewChangelog"), Lang.Text("Common.Action.Cancel")))
{
case 1: // 更新
{
switch (Entry.Comp.Type)
{
case ModComp.CompType.Mod:
{
ModMain.frmInstanceMod ??= new PageInstanceCompResource(ModComp.CompType.Mod);
ModMain.frmInstanceMod.UpdateResource(new[] { Entry });
break;
}
case ModComp.CompType.ResourcePack:
{
ModMain.frmInstanceResourcePack ??= new PageInstanceCompResource(ModComp.CompType.ResourcePack);
ModMain.frmInstanceResourcePack.UpdateResource(new[] { Entry });
break;
}
case ModComp.CompType.Shader:
{
ModMain.frmInstanceShader ??= new PageInstanceCompResource(ModComp.CompType.Shader);
ModMain.frmInstanceShader.UpdateResource(new[] { Entry });
break;
}
case ModComp.CompType.DataPack:
{
ModMain.frmInstanceSavesDatapack ??= new PageInstanceSavesDatapack();
ModMain.frmInstanceSavesDatapack.UpdateResource(new[] { Entry });
break;
}
}
break;
}
case 2: // 查看更新日志
{
ShowUpdateLog();
break;
}
case 3: // 取消
{
break;
}
}
}
// 自适应(#4465
private void PanTitle_SizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
{
// 0:全部舒展:Auto - Auto - (Auto) - 1*
// 1:压缩 SubtitleAuto - 1* - (Auto) - 0
// 2:继续压缩 Title1* - 0 - (Auto) - 0
var currentCompressLevel =
ColumnExtend.Width.IsStar ? 0 : ColumnTitle.Width.IsStar ? 2 : 1; // Subtitle 可能是 Collapsed
var newCompressLevel = default(int);
switch (currentCompressLevel)
{
case 0:
{
if (ColumnExtend.ActualWidth < 0.5d)
newCompressLevel = LabSubtitle.Visibility == Visibility.Collapsed ? 2 : 1;
else
return;
break;
}
case 1:
{
if (ColumnSubtitle.ActualWidth < 0.5d)
newCompressLevel = 2;
else if (!LabSubtitle.IsTextTrimmed())
newCompressLevel = 0;
else
return;
break;
}
case 2:
{
if (!LabTitle.IsTextTrimmed())
newCompressLevel = LabSubtitle.Visibility == Visibility.Collapsed ? 0 : 1;
else
return;
break;
}
}
switch (newCompressLevel)
{
case 0:
{
// 全部舒展:Auto - Auto - (Auto) - 1*
ColumnTitle.Width = GridLength.Auto;
ColumnSubtitle.Width = GridLength.Auto;
ColumnExtend.Width = new GridLength(1d, GridUnitType.Star);
break;
}
case 1:
{
// 压缩 SubtitleAuto - 1* - (Auto) - 0
ColumnTitle.Width = GridLength.Auto;
ColumnSubtitle.Width = new GridLength(1d, GridUnitType.Star);
ColumnExtend.Width = new GridLength(0d, GridUnitType.Pixel);
break;
}
case 2:
{
// 继续压缩 Title1* - 0 - (Auto) - 0
ColumnTitle.Width = new GridLength(1d, GridUnitType.Star);
ColumnSubtitle.Width = new GridLength(0d, GridUnitType.Pixel);
ColumnExtend.Width = new GridLength(0d, GridUnitType.Pixel);
break;
}
}
}
#region 基础属性
public int Uuid = ModBase.GetUuid();
// Logo
public string Logo
{
get => PathLogo.Source;
set => PathLogo.Source = value;
}
// 标题
public string Title
{
get => field;
set
{
var rawValue = value;
switch (Entry.State)
{
case ModLocalComp.LocalCompFile.LocalFileStatus.Fine:
{
LabTitle.TextDecorations = null;
break;
}
case ModLocalComp.LocalCompFile.LocalFileStatus.Disabled:
{
LabTitle.TextDecorations = TextDecorations.Strikethrough;
break;
}
case ModLocalComp.LocalCompFile.LocalFileStatus.Unavailable:
{
LabTitle.TextDecorations = TextDecorations.Strikethrough;
value += Lang.Text("Instance.Resource.Item.ErrorSuffix");
break;
}
}
if ((LabTitle.Text ?? "") == (value ?? ""))
return;
LabTitle.Text = value;
field = rawValue;
}
}
// 副标题
public string SubTitle
{
get => LabSubtitle?.Text ?? "";
set
{
if ((LabSubtitle.Text ?? "") == (value ?? ""))
return;
LabSubtitle.Text = value;
LabSubtitle.Visibility = string.IsNullOrEmpty(value) ? Visibility.Collapsed : Visibility.Visible;
}
}
// 描述
public string Description
{
get => LabInfo.Text;
set
{
if ((LabInfo.Text ?? "") == (value ?? ""))
return;
LabInfo.Text = value;
}
}
// Tag
public List<string> Tags
{
set
{
PanTags.Children.Clear();
PanTags.Visibility = value.Any() ? Visibility.Visible : Visibility.Collapsed;
foreach (var TagText in value)
{
var newTag = new Border
{
Background = new SolidColorBrush(Color.FromArgb(12, 0, 0, 0)),
Padding = new Thickness(3d, 1d, 3d, 1d),
CornerRadius = new CornerRadius(3d),
Margin = new Thickness(0d, 0d, 3d, 0d),
SnapsToDevicePixels = true,
UseLayoutRounding = false
};
var tagTextBlock = new TextBlock
{
Text = TagText,
Foreground = new SolidColorBrush(ThemeManager.IsDarkMode
? Color.FromArgb(88, 255, 255, 255)
: Color.FromArgb(88, 136, 136, 136)),
FontSize = 11d
};
newTag.Child = tagTextBlock;
PanTags.Children.Add(newTag);
}
}
}
// 相关联的 Mod
public ModLocalComp.LocalCompFile Entry
{
get => (ModLocalComp.LocalCompFile)Tag;
set => Tag = value;
}
#endregion
#region 点击与勾选
// 触发点击事件
public event ClickEventHandler? Click;
public delegate void ClickEventHandler(object sender, MouseButtonEventArgs e);
public MyLocalCompItem()
{
InitializeComponent();
PreviewMouseLeftButtonUp += Button_MouseUp;
PreviewMouseLeftButtonDown += Button_MouseDown;
MouseLeave += Button_MouseLeave;
PreviewMouseLeftButtonUp += Button_MouseLeave;
MouseLeftButtonDown += Button_MouseSwipeStart;
MouseEnter += Button_MouseSwipe;
MouseLeave += Button_MouseSwipe;
MouseLeftButtonUp += Button_MouseSwipe;
Loaded += (_, _) => Refresh();
MouseEnter += RefreshColor;
MouseLeave += RefreshColor;
MouseLeftButtonDown += RefreshColor;
MouseLeftButtonUp += RefreshColor;
Changed += RefreshColor;
// Handles
BtnUpdate.PreviewMouseRightButtonUp += BtnUpdate_PreviewMouseRightButtonUp;
BtnUpdate.Click += BtnUpdate_Click;
PanTitle.SizeChanged += PanTitle_SizeChanged;
}
private void Button_MouseUp(object sender, MouseButtonEventArgs e)
{
if (isMouseDown)
{
Click?.Invoke(sender, e);
if (e.Handled)
return;
ModBase.Log("[Control] 按下本地 Mod 列表项:" + LabTitle.Text);
}
}
// 鼠标点击判定
private bool isMouseDown;
private void Button_MouseDown(object sender, MouseButtonEventArgs e)
{
if (!IsMouseDirectlyOver)
return;
isMouseDown = true;
if (buttonStack is not null)
buttonStack.IsHitTestVisible = false;
}
private void Button_MouseLeave(object sender, object e)
{
isMouseDown = false;
if (buttonStack is not null)
buttonStack.IsHitTestVisible = true;
}
// 滑动选中
public class SwipeSelect
{
public int Start { get; set; }
public int End { get; set; }
public bool Swiping
{
get => field;
set
{
field = value;
if (TargetFrm is not null)
try
{
var cardSelect = Interaction.CallByName(TargetFrm, "CardSelect", CallType.Get);
Interaction.CallByName(cardSelect, "IsHitTestVisible", CallType.Set, !value);
}
catch
{
}
}
}
public bool SwipeToState { get; set; }
public object TargetFrm { get; set; }
}
public SwipeSelect CurrentSwipe { get; set; }
private void Button_MouseSwipeStart(object sender, object e)
{
if (Parent is null)
return; // Mod 可能已被删除(#3824
// 开始滑动
var index = ((StackPanel)Parent).Children.IndexOf(this);
CurrentSwipe.Start = index;
CurrentSwipe.End = index;
CurrentSwipe.Swiping = true;
CurrentSwipe.SwipeToState = !Checked;
}
private void Button_MouseSwipe(object sender, object e)
{
if (Parent is null)
return; // Mod 可能已被删除(#3824
// 结束滑动
if (Mouse.LeftButton != MouseButtonState.Pressed || !(Mouse.DirectlyOver is MyLocalCompItem)) // #5771
{
CurrentSwipe.Swiping = false;
return;
}
// 计算滑动范围
var elements = ((StackPanel)Parent).Children;
var index = elements.IndexOf(this);
CurrentSwipe.Start =
(int)Math.Round(ModBase.MathClamp(Math.Min(CurrentSwipe.Start, index), 0d, elements.Count - 1));
CurrentSwipe.End =
(int)Math.Round(ModBase.MathClamp(Math.Max(CurrentSwipe.End, index), 0d, elements.Count - 1));
// 勾选所有范围中的项
if (CurrentSwipe.Start == CurrentSwipe.End)
return;
for (int i = CurrentSwipe.Start, loopTo = CurrentSwipe.End; i <= loopTo; i++)
{
var item = (MyLocalCompItem)elements[i];
item.InitLate(item, (EventArgs)e);
item.Checked = CurrentSwipe.SwipeToState;
}
}
// 勾选状态
public event CheckEventHandler? Check;
public delegate void CheckEventHandler(object sender, ModBase.RouteEventArgs e);
public event ChangedEventHandler? Changed;
public delegate void ChangedEventHandler(object sender, ModBase.RouteEventArgs e);
public bool Checked
{
get => field;
set
{
try
{
// 触发属性值修改
var rawValue = field;
if (value == field)
return;
field = value;
var ChangedEventArgs = new ModBase.RouteEventArgs();
if (IsInitialized)
{
Changed?.Invoke(this, ChangedEventArgs);
if (ChangedEventArgs.handled)
{
field = rawValue;
return;
}
}
if (value)
{
var checkEventArgs = new ModBase.RouteEventArgs();
Check?.Invoke(this, checkEventArgs);
if (checkEventArgs.handled)
return;
}
// 更改动画
if (this.IsVisibleInWindow(ModMain.frmMain))
{
var anim = new List<ModAnimation.AniData>();
if (Checked)
{
// 由无变有
var delta = 32d - RectCheck.ActualHeight;
anim.Add(ModAnimation.AaHeight(RectCheck, delta * 0.4d, 200,
ease: new ModAnimation.AniEaseOutFluent(ModAnimation.AniEasePower.Weak)));
anim.Add(ModAnimation.AaHeight(RectCheck, delta * 0.6d, 300,
ease: new ModAnimation.AniEaseOutBack(ModAnimation.AniEasePower.Weak)));
anim.Add(ModAnimation.AaOpacity(RectCheck, 1d - RectCheck.Opacity, 30));
RectCheck.VerticalAlignment = VerticalAlignment.Center;
RectCheck.Margin = new Thickness(-3, 0d, 0d, 0d);
anim.Add(ModAnimation.AaColor(LabTitle, TextBlock.ForegroundProperty,
Entry.State == ModLocalComp.LocalCompFile.LocalFileStatus.Fine
? "ColorBrush2"
: "ColorBrush5", 200));
}
else
{
// 由有变无
anim.Add(ModAnimation.AaHeight(RectCheck, -RectCheck.ActualHeight, 120,
ease: new ModAnimation.AniEaseInFluent(ModAnimation.AniEasePower.Weak)));
anim.Add(ModAnimation.AaOpacity(RectCheck, -RectCheck.Opacity, 70, 40));
RectCheck.VerticalAlignment = VerticalAlignment.Center;
anim.Add(ModAnimation.AaColor(LabTitle, TextBlock.ForegroundProperty,
LabTitle.TextDecorations is null ? "ColorBrush1" : "ColorBrushGray4", 120));
}
ModAnimation.AniStart(anim, "MyLocalCompItem Checked " + Uuid);
}
else
{
// 不在窗口上时直接设置
RectCheck.VerticalAlignment = VerticalAlignment.Center;
RectCheck.Margin = new Thickness(-3, 0d, 0d, 0d);
if (Checked)
{
RectCheck.Height = 32d;
RectCheck.Opacity = 1d;
LabTitle.SetResourceReference(TextBlock.ForegroundProperty,
Entry.State == ModLocalComp.LocalCompFile.LocalFileStatus.Fine
? "ColorBrush2"
: "ColorBrush5");
}
else
{
RectCheck.Height = 0d;
RectCheck.Opacity = 0d;
LabTitle.SetResourceReference(TextBlock.ForegroundProperty,
Entry.State == ModLocalComp.LocalCompFile.LocalFileStatus.Fine
? "ColorBrush1"
: "ColorBrushGray4");
}
ModAnimation.AniStop("MyLocalCompItem Checked " + Uuid);
}
}
catch (Exception ex)
{
ModBase.Log(ex, "设置 Checked 失败");
}
}
}
#endregion
#region 后加载内容
// 右下角状态指示图标
private Image imgState;
// 指向背景
public Border RectBack
{
get
{
if (field is null)
{
var rect = new Border
{
Name = "RectBack",
CornerRadius = new CornerRadius(3d),
RenderTransform = new ScaleTransform(0.8d, 0.8d),
RenderTransformOrigin = new Point(0.5d, 0.5d),
BorderThickness = new Thickness(ModBase.GetWPFSize(1d)),
SnapsToDevicePixels = true,
IsHitTestVisible = false,
Opacity = 0d
};
rect.SetResourceReference(Border.BackgroundProperty, "ColorBrush7");
rect.SetResourceReference(Border.BorderBrushProperty, "ColorBrush6");
SetColumnSpan(rect, 999);
SetRowSpan(rect, 999);
Children.Insert(0, rect);
field = rect;
// <!--<corelocal:BlurBorder x:Name = "RectBack" CornerRadius="3" RenderTransformOrigin="0.5,0.5" SnapsToDevicePixels="True"
// IsHitTestVisible = "False" Opacity="0" BorderThickness="1"
// Grid.ColumnSpan = "4" Background="{DynamicResource ColorBrush7}" BorderBrush="{DynamicResource ColorBrush6}"/>-->
}
return field;
}
}
// 按钮
public Action<MyLocalCompItem, EventArgs> buttonHandler;
public FrameworkElement buttonStack;
public IEnumerable<MyIconButton> Buttons
{
get => field;
set
{
field = value;
// 移除原 Stack
if (buttonStack is not null)
{
Children.Remove(buttonStack);
buttonStack = null;
}
if (!value.Any())
return;
// 添加新 Stack
buttonStack = new StackPanel
{
Opacity = 0d,
Margin = new Thickness(0d, 0d, 5d, 0d),
SnapsToDevicePixels = false,
Orientation = (Orientation)System.Windows.Forms.Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Center,
UseLayoutRounding = false
};
SetColumnSpan(buttonStack, 10);
SetRowSpan(buttonStack, 10);
// 构造按钮
foreach (var Btn in value)
{
if (Btn.Height.Equals(double.NaN))
Btn.Height = 25d;
if (Btn.Width.Equals(double.NaN))
Btn.Width = 25d;
((StackPanel)buttonStack).Children.Add(Btn);
}
Children.Add(buttonStack);
}
}
// 勾选条
public Border RectCheck
{
get
{
if (field is null)
{
field = new Border
{
Width = 5d,
Height = Checked ? double.NaN : 0d,
CornerRadius = new CornerRadius(2d, 2d, 2d, 2d),
VerticalAlignment = Checked ? VerticalAlignment.Stretch : VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Left,
UseLayoutRounding = false,
SnapsToDevicePixels = false,
Margin = Checked ? new Thickness(-3, 6d, 0d, 6d) : new Thickness(-3, 0d, 0d, 0d)
};
field.SetResourceReference(Border.BackgroundProperty, "ColorBrush3");
SetRowSpan(field, 10);
Children.Add(field);
}
return field;
}
}
#endregion
}