Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions PCL.Core/App/Localization/Languages/en-US.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,7 @@
<sys:String x:Key="Download.Version.LoadingList">Getting version list...</sys:String>
<sys:String x:Key="Download.Version.Changelog">Changelog</sys:String>
<sys:String x:Key="Download.Version.SaveAs">Save as</sys:String>
<sys:String x:Key="Download.Version.Download">Download</sys:String>
<sys:String x:Key="Download.Version.DownloadServer">Download server</sys:String>
<sys:String x:Key="Download.Version.ViewAllVersions">Show all versions</sys:String>
<sys:String x:Key="Download.Version.SaveInstaller">Save installer</sys:String>
Expand Down Expand Up @@ -1057,6 +1058,11 @@
<sys:String x:Key="Download.Comp.Detail.FileList.Updated">Updated {0}</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.RequiredDependencies">Required dependencies</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.OptionalDependencies">Optional dependencies</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.Title">Version details</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.ButtonInstall">Install to current instance</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.ButtonSaveAs">Choose download location</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.NoInstance">Please select a Minecraft instance first</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.NoDeps">None</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.VersionList">Version list</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.ReleaseType.Release">Release</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.ReleaseType.Beta">Beta</sys:String>
Expand Down
6 changes: 6 additions & 0 deletions PCL.Core/App/Localization/Languages/zh-CN.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,7 @@
<sys:String x:Key="Download.Version.Fresh.Stable">最新稳定版</sys:String>
<sys:String x:Key="Download.Version.Fresh.Development">最新测试版</sys:String>
<sys:String x:Key="Download.Version.SelectSaveLocation">选择保存位置</sys:String>
<sys:String x:Key="Download.Version.Download">下载</sys:String>
<sys:String x:Key="Download.Version.Installer.Fabric.Filter">Fabric 安装器 (*.jar)|*.jar</sys:String>
<sys:String x:Key="Download.Version.Installer.LegacyFabric.Filter">LegacyFabric 安装器 (*.jar)|*.jar</sys:String>
<sys:String x:Key="Download.Version.Installer.Quilt.Filter">Quilt 安装器 (*.jar)|*.jar</sys:String>
Expand Down Expand Up @@ -1057,6 +1058,11 @@
<sys:String x:Key="Download.Comp.Detail.FileList.Updated">更新于 {0}</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.RequiredDependencies">必要前置资源</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.OptionalDependencies">可选前置资源</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.Title">版本详情</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.ButtonInstall">安装到当前实例</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.ButtonSaveAs">选择下载位置</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.NoInstance">请先选择一个 Minecraft 实例</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.NoDeps">无</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.VersionList">版本列表</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.ReleaseType.Release">正式版</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.ReleaseType.Beta">测试版</sys:String>
Expand Down
3 changes: 3 additions & 0 deletions Plain Craft Launcher 2/Controls/MyListItem.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public partial class MyListItem : IMyRadio
public event IMyRadio.ChangedEventHandler? Changed;

public event ClickEventHandler? Click;
public event ClickEventHandler? RightClick;
public event LogoClickEventHandler? LogoClick;

public void RefreshColor(object sender, EventArgs e)
Expand Down Expand Up @@ -474,6 +475,8 @@ public MyListItem()
PreviewMouseLeftButtonDown += Button_MouseDown;
MouseLeave += Button_MouseLeave;
PreviewMouseLeftButtonUp += Button_MouseLeave;
// 右键事件(用于触发 RightClick,例如模组版本项右键直接另存为)
PreviewMouseRightButtonUp += (_, e) => RightClick?.Invoke(this, e);
MouseEnter += RefreshColor;
MouseLeave += RefreshColor;
MouseLeftButtonDown += RefreshColor;
Expand Down
62 changes: 62 additions & 0 deletions Plain Craft Launcher 2/Controls/MyMsg/ModDependencyMsgBox.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<Grid x:Class="PCL.ModDependencyMsgBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:PCL"
RenderTransformOrigin="0,0.5" UseLayoutRounding="True" SnapsToDevicePixels="True" MinWidth="420" MaxWidth="620"
HorizontalAlignment="Center" VerticalAlignment="Center" Margin="25">
<Grid.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="TransformRotate" Angle="-4" />
<TranslateTransform x:Name="TransformPos" X="0" Y="40" />
</TransformGroup>
</Grid.RenderTransform>
<Border Name="PanBorder" CornerRadius="7" Background="{DynamicResource ColorBrushBackground}">
<Border.Effect>
<DropShadowEffect Color="{DynamicResource ColorObjectMsgBoxShadow}" BlurRadius="20" ShadowDepth="2"
RenderingBias="Performance" Opacity="0.8" x:Name="EffectShadow" />
</Border.Effect>
<Grid Name="PanMain" VerticalAlignment="Top" Margin="22,22,22,23">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="2" />
<RowDefinition Height="13" />
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" FontSize="23" TextTrimming="None" Foreground="{DynamicResource ColorBrush2}"
HorizontalAlignment="Left" Name="LabTitle" Margin="7,-1,70,9" Text="版本详情"
VerticalAlignment="Top" SnapsToDevicePixels="False" UseLayoutRounding="False" />
<Rectangle x:Name="ShapeLine" Grid.Row="1" Height="2" Fill="{Binding Foreground, ElementName=LabTitle}" />
<my:MyScrollViewer Grid.Row="3" VerticalAlignment="Top" x:Name="PanCaption" Margin="0,0,0,17"
Padding="7,0,15,0" MaxHeight="460"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled"
DeltaMult="0.7">
<StackPanel Orientation="Vertical">
<StackPanel Margin="2,0,2,12">
<StackPanel Orientation="Horizontal">
<TextBlock Name="LabVersionInfo"
TextWrapping="NoWrap" TextTrimming="CharacterEllipsis"
VerticalAlignment="Center" />
<StackPanel Orientation="Horizontal"
Name="PanVersionTags" VerticalAlignment="Center" Margin="4,0,0,0" />
</StackPanel>
<TextBlock Name="LabDateInfo" TextWrapping="Wrap" Margin="0,4,0,0"/>
</StackPanel>
<TextBlock Name="LabReqTitle" FontSize="14" FontWeight="Bold" Margin="2,8,0,4" />
<StackPanel Name="PanReqDeps" Orientation="Vertical" />
<TextBlock Name="LabOptTitle" FontSize="14" FontWeight="Bold" Margin="2,8,0,4" />
<StackPanel Name="PanOptDeps" Orientation="Vertical" />
</StackPanel>
</my:MyScrollViewer>
<StackPanel Grid.Row="4" Name="PanBtn" VerticalAlignment="Top" HorizontalAlignment="Right"
Margin="150,0,8,0" Orientation="Horizontal">
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="安装到当前实例" x:Name="Btn1" Margin="12,0,0,0"
TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" UseLayoutRounding="False" />
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="选择下载位置" x:Name="Btn2" Margin="12,0,0,0"
TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" UseLayoutRounding="False" />
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="取消" x:Name="Btn3" Margin="12,0,0,0"
TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" UseLayoutRounding="False" />
</StackPanel>
</Grid>
</Border>
</Grid>
225 changes: 225 additions & 0 deletions Plain Craft Launcher 2/Controls/MyMsg/ModDependencyMsgBox.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using PCL.Core.App.Localization;
using PCL.Core.UI.Controls;

namespace PCL;

/// <summary>
/// 模组版本的「前置详情」弹窗:展示该版本的版本信息、必要前置 / 可选前置,
/// 并提供「安装到当前实例」/「选择下载位置」两个动作。点击某个前置项会关闭弹窗并返回该前置工程。
/// 布局由 XAML 定义,调用方只需传入 CompFile 数据(由 <see cref="ModMain.ModDependencyMsgBox" /> 触发)。
/// </summary>
public partial class ModDependencyMsgBox
{
private readonly ModMain.MyMsgBoxConverter myConverter;
private readonly int uuid = ModBase.GetUuid();

public ModDependencyMsgBox(ModMain.MyMsgBoxConverter converter)
{
try
{
InitializeComponent();
AppendUniqueNameSuffix(Btn1);
AppendUniqueNameSuffix(Btn2);
AppendUniqueNameSuffix(Btn3);
myConverter = converter;
LabTitle.Text = Lang.Text("Download.Comp.Detail.VersionPopup.Title");
Btn1.Text = Lang.Text("Download.Comp.Detail.VersionPopup.ButtonInstall");
Btn2.Text = Lang.Text("Download.Comp.Detail.VersionPopup.ButtonSaveAs");
Btn3.Text = Lang.Text("Common.Action.Cancel");
ShapeLine.StrokeThickness = ModBase.GetWPFSize(1d);
if (converter.Content is ModComp.CompFile file)
Populate(file);
}
catch (Exception ex)
{
ModBase.Log(ex, "前置弹窗初始化失败", ModBase.LogLevel.Hint);
}

Loaded += Load;
PreviewKeyDown += ModDependencyMsgBox_PreviewKeyDown;
Btn1.Click += Btn1_Click;
Btn2.Click += Btn2_Click;
Btn3.Click += Btn3_Click;
LabTitle.MouseLeftButtonDown += Drag;
PanBorder.MouseLeftButtonDown += Drag;
}

private void AppendUniqueNameSuffix(FrameworkElement element)
{
element.Name += ModBase.GetUuid();
}

/// <summary>
/// 填充版本信息与必要 / 可选前置项。
/// </summary>
private void Populate(ModComp.CompFile file)
{
// 1. 版本信息
LabVersionInfo.Text = file.DisplayName;
_AddTag(file.StatusDescription);
foreach (var loader in file.ModLoaders)
_AddTag(loader.ToString());
LabDateInfo.Text = Lang.Text("Download.Comp.Detail.FileList.Updated", file.ReleaseDate.ToString("G"));

// 2. 必要前置 / 可选前置
FillDependencySection(LabReqTitle, PanReqDeps, file.Dependencies,
Lang.Text("Download.Comp.Detail.FileList.RequiredDependencies"));
FillDependencySection(LabOptTitle, PanOptDeps, file.OptionalDependencies,
Lang.Text("Download.Comp.Detail.FileList.OptionalDependencies"));
}

private void _AddTag(string text)
{
var tag = new Border
{
Background = new SolidColorBrush(Color.FromArgb(17, 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
};
tag.Child = new TextBlock
{
Text = text,
Foreground = new SolidColorBrush(Color.FromRgb(134, 134, 134)),
FontSize = 11d
};
PanVersionTags.Children.Add(tag);
}

/// <summary>
/// 填充一个前置分区:标题 + 可点击的前置项(点击以该前置工程关闭弹窗)。
/// </summary>
private void FillDependencySection(TextBlock header, StackPanel panel, List<string> depIds, string title)
{
var projects = new List<ModComp.CompProject>();
foreach (var id in depIds)
if (ModComp.compProjectCache.TryGetValue(id, out var project))
projects.Add(project);

header.Text = $"{title}({projects.Count})";

if (!projects.Any())
{
header.Visibility = Visibility.Collapsed;
panel.Visibility = Visibility.Collapsed;
return;
}

foreach (var project in projects)
{
var captured = project;
// 复用「游戏资源 → 模组」搜索结果同款 MyCompItem 卡片样式;
// 关闭其内置跳转(AutoNavigate=false),改由弹窗统一「先关闭再跳转」
var item = project.ToCompItem(true, true).Init();
item.AutoNavigate = false;
item.Click += (_, _) => ReturnResult(captured);
panel.Children.Add(item);
}
}

/// <summary>
/// 以指定返回值关闭弹窗:按钮返回 1 / 2,前置项返回对应 CompProject。
/// </summary>
private void ReturnResult(object result)
{
if (myConverter.IsExited)
return;
myConverter.IsExited = true;
myConverter.Result = result;
Close();
}

private void Load(object sender, EventArgs e)
{
try
{
// UI 初始化
if (Btn2.IsVisible && !(Btn1.ColorType == MyButton.ColorState.Red))
Btn1.ColorType = MyButton.ColorState.Highlight;
Btn1.Focus();
// 动画
Opacity = 0d;
ModAnimation.AniStart(
ModAnimation.AaColor(ModMain.frmMain.PanMsgBackground, BlurBorder.BackgroundProperty,
new ModBase.MyColor(90d, 0d, 0d, 0d) - ModMain.frmMain.PanMsgBackground.Background, 200),
"PanMsgBackground Background");
ModAnimation.AniStart(
new[]
{
ModAnimation.AaOpacity(this, 1d, 120, 60),
ModAnimation.AaDouble(i => TransformPos.Y += (double)i,
-TransformPos.Y, 300, 60, new ModAnimation.AniEaseOutBack(ModAnimation.AniEasePower.Weak)),
ModAnimation.AaDouble(i => TransformRotate.Angle += (double)i,
-TransformRotate.Angle, 300, 60,
new ModAnimation.AniEaseOutFluent(ModAnimation.AniEasePower.Weak))
}, "MyMsgBox " + uuid);
ModBase.Log("[Control] 前置详情弹窗:" + LabTitle.Text);
}
catch (Exception ex)
{
ModBase.Log(ex, "前置详情弹窗加载失败", ModBase.LogLevel.Hint);
}
}

private void Close()
{
// 结束线程阻塞
myConverter.WaitFrame.Continue = false;
ComponentDispatcher.PopModal();
// 动画
ModAnimation.AniStart(new[]
{
ModAnimation.AaCode(() =>
{
if (!ModMain.WaitingMyMsgBox.Any())
ModAnimation.AniStart(ModAnimation.AaColor(ModMain.frmMain.PanMsgBackground,
BlurBorder.BackgroundProperty,
new ModBase.MyColor(0d, 0d, 0d, 0d) - ModMain.frmMain.PanMsgBackground.Background, 200,
ease: new ModAnimation.AniEaseOutFluent(ModAnimation.AniEasePower.Weak)));
}, 30),
ModAnimation.AaOpacity(this, -Opacity, 80, 20),
ModAnimation.AaDouble(i => TransformPos.Y += (double)i, 20d - TransformPos.Y,
150, 0, new ModAnimation.AniEaseOutFluent()),
ModAnimation.AaDouble(i => TransformRotate.Angle += (double)i,
6d - TransformRotate.Angle, 150, 0, new ModAnimation.AniEaseInFluent(ModAnimation.AniEasePower.Weak)),
ModAnimation.AaCode(() => ((Grid)Parent).Children.Remove(this), after: true)
}, "MyMsgBox " + uuid);
}

public void Btn1_Click(object sender, MouseButtonEventArgs e) => ReturnResult(1);

public void Btn2_Click(object sender, MouseButtonEventArgs e) => ReturnResult(2);

public void Btn3_Click(object sender, MouseButtonEventArgs e) => ReturnResult(null);

/// <summary>按 Esc 关闭弹窗(等同点击「取消」,返回 null)。</summary>
private void ModDependencyMsgBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
e.Handled = true;
ReturnResult(null);
}
}

private void Drag(object sender, MouseButtonEventArgs e)
{
try
{
if (e.LeftButton == MouseButtonState.Pressed)
if (e.GetPosition(ShapeLine).Y <= 2d)
ModMain.frmMain.DragMove();
}
catch (Exception ex)
{
ModBase.Log(ex, "拖拽移动失败", ModBase.LogLevel.Hint);
}
}
}
Loading
Loading