/*
* MainWindow.xaml.cs - Better-Seewo 管理器主窗口逻辑
* 负责自定义标题栏拖动、窗口控制、页面导航、主题切换和动画效果
* 作者:雾启工作室
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace Better_Seewo.Manager
{
///
/// MainWindow 的交互逻辑 - Fluent Design 风格主窗口
///
public partial class MainWindow : Window
{
///
/// 导航指示条动画时长(毫秒)
///
private const int IndicatorAnimationDuration = 200;
///
/// 页面淡入淡出动画时长(毫秒)
///
private const int PageTransitionDuration = 300;
///
/// 指示条目标宽度
///
private const double IndicatorTargetWidth = 3;
///
/// 当前选中的导航按钮名称
///
private string _currentNavTag = "Install";
///
/// 构造函数,初始化窗口组件
///
public MainWindow()
{
InitializeComponent();
// 默认选中安装页面
SetActiveNavigation("BtnInstall", "IndicatorInstall");
}
///
/// 窗口加载完成事件处理 - 触发入场动画和初始页面加载
///
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// 入场动画已通过 XAML Trigger 触发
// 导航到默认页面
NavigateToPage("Install");
}
#region ===== 自定义标题栏拖动 =====
///
/// 标题栏鼠标左键按下 - 实现窗口拖动
///
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// 如果点击的是按钮区域则不触发拖动
if (e.Source is Button) return;
// 调用 DragMove 实现窗口拖动
if (e.LeftButton == MouseButtonState.Pressed)
{
DragMove();
}
}
///
/// 标题栏鼠标双击 - 切换最大化/还原
///
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
// 双击标题栏区域切换窗口状态
if (e.ClickCount == 2)
{
ToggleMaximize();
}
}
#endregion
#region ===== 窗口控制按钮 =====
///
/// 最小化按钮点击
///
private void BtnMinimize_Click(object sender, RoutedEventArgs e)
{
// 将窗口最小化到任务栏
WindowState = WindowState.Minimized;
}
///
/// 最大化/还原按钮点击
///
private void BtnMaximize_Click(object sender, RoutedEventArgs e)
{
ToggleMaximize();
}
///
/// 关闭按钮点击 - 关闭应用程序
///
private void BtnClose_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
///
/// 切换窗口最大化/还原状态
///
private void ToggleMaximize()
{
if (WindowState == WindowState.Maximized)
{
WindowState = WindowState.Normal;
// 更新按钮图标为最大化图标
BtnMaximize.Content = "\uE922";
}
else
{
WindowState = WindowState.Maximized;
// 更新按钮图标为还原图标
BtnMaximize.Content = "\uE923";
}
}
#endregion
#region ===== 导航按钮切换 =====
///
/// 导航按钮点击事件 - 切换Frame页面内容
///
private void NavButton_Click(object sender, RoutedEventArgs e)
{
if (sender is Button btn && btn.Tag is string tag)
{
// 如果点击的是当前已选中项,则忽略
if (tag == _currentNavTag) return;
// 更新当前选中项
_currentNavTag = tag;
// 根据按钮名称设置选中状态和指示条动画
SetActiveNavigation(btn.Name, GetIndicatorName(btn.Name));
// 导航到对应页面
NavigateToPage(tag);
}
}
///
/// 根据按钮名称获取对应的指示条名称
///
/// 按钮名称
/// 指示条名称
private string GetIndicatorName(string buttonName)
{
return buttonName switch
{
"BtnInstall" => "IndicatorInstall",
"BtnInk" => "IndicatorInk",
"BtnConvert" => "IndicatorConvert",
"BtnTouch" => "IndicatorTouch",
"BtnActivate" => "IndicatorActivate",
_ => "IndicatorInstall"
};
}
///
/// 设置当前选中的导航按钮,并触发指示条动画
///
/// 选中的按钮名称
/// 对应的指示条名称
private void SetActiveNavigation(string activeButtonName, string activeIndicatorName)
{
// 所有导航按钮列表
string[] buttonNames = { "BtnInstall", "BtnInk", "BtnConvert", "BtnTouch", "BtnActivate" };
// 所有指示条列表
string[] indicatorNames = { "IndicatorInstall", "IndicatorInk", "IndicatorConvert", "IndicatorTouch", "IndicatorActivate" };
for (int i = 0; i < buttonNames.Length; i++)
{
// 查找按钮
var btn = FindName(buttonNames[i]) as Button;
// 查找指示条
var indicator = FindName(indicatorNames[i]) as Border;
if (btn == null || indicator == null) continue;
if (buttonNames[i] == activeButtonName)
{
// 选中状态:高亮前景色,显示指示条
btn.Foreground = (Brush)FindResource("AccentBrush");
// 播放指示条展开动画(宽度从0到3px)
AnimateIndicatorWidth(indicator, IndicatorTargetWidth);
}
else
{
// 非选中状态:恢复默认前景色,隐藏指示条
btn.Foreground = (Brush)FindResource("TextSecondaryBrush");
// 播放指示条收缩动画(宽度从当前值到0)
AnimateIndicatorWidth(indicator, 0);
}
}
}
///
/// 为导航指示条播放宽度动画
///
/// 指示条控件
/// 目标宽度
private void AnimateIndicatorWidth(Border indicator, double targetWidth)
{
if (indicator == null) return;
// 创建宽度动画
var widthAnimation = new DoubleAnimation
{
From = indicator.Width,
To = targetWidth,
Duration = TimeSpan.FromMilliseconds(IndicatorAnimationDuration),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut }
};
// 应用动画到指示条的Width属性
indicator.BeginAnimation(WidthProperty, widthAnimation);
}
#endregion
#region ===== 页面导航 =====
///
/// 导航到指定页面,带淡入淡出动画效果
///
/// 页面标识(Install/Ink/Convert/Touch/Activate)
private void NavigateToPage(string pageTag)
{
// 创建淡出动画(当前页面)
var fadeOutAnimation = new DoubleAnimation
{
From = 1.0,
To = 0.0,
Duration = TimeSpan.FromMilliseconds(PageTransitionDuration / 2),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn }
};
// 淡出动画完成后切换页面
fadeOutAnimation.Completed += (s, e) =>
{
// 根据页面标识加载对应页面
// TODO: 创建各个功能页面后取消注释
// switch (pageTag)
// {
// case "Install":
// ContentFrame.Navigate(new Pages.InstallPage());
// break;
// case "Ink":
// ContentFrame.Navigate(new Pages.InkPage());
// break;
// case "Convert":
// ContentFrame.Navigate(new Pages.ConvertPage());
// break;
// case "Touch":
// ContentFrame.Navigate(new Pages.TouchPage());
// break;
// case "Activate":
// ContentFrame.Navigate(new Pages.ActivatePage());
// break;
// }
// 创建淡入动画(新页面)
var fadeInAnimation = new DoubleAnimation
{
From = 0.0,
To = 1.0,
Duration = TimeSpan.FromMilliseconds(PageTransitionDuration / 2),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }
};
// 应用淡入动画到Frame
ContentFrame.BeginAnimation(OpacityProperty, fadeInAnimation);
};
// 应用淡出动画到Frame
ContentFrame.BeginAnimation(OpacityProperty, fadeOutAnimation);
}
#endregion
#region ===== 主题切换 =====
///
/// 主题切换按钮点击事件
///
private void BtnThemeToggle_Click(object sender, RoutedEventArgs e)
{
// 切换到相反主题
bool newIsDark = !App.IsDarkTheme;
// 调用 App.SwitchTheme 切换主题资源
App.SwitchTheme(newIsDark);
// 更新主题图标
UpdateThemeIcon(newIsDark);
}
///
/// 根据当前主题更新切换按钮的图标
///
/// 当前是否为深色主题
private void UpdateThemeIcon(bool isDark)
{
if (ThemeIcon == null) return;
if (isDark)
{
// 深色主题时显示太阳图标(提示可以切换到浅色)
ThemeIcon.Data = Geometry.Parse(
"M12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,2L14.39,5.42C13.73,5.14 13,5 12,5C11,5 10.27,5.14 9.61,5.42L12,2M3.34,7L7.5,6.35C7,7 6.63,7.73 6.43,8.5L3.34,7M3.36,17L6.44,15.5C6.64,16.28 7,17 7.5,17.65L3.36,17M20.64,7L17.55,8.5C17.36,7.72 17,7 16.5,6.35L20.64,7M20.65,17L16.5,17.65C17,17 17.37,16.27 17.57,15.5L20.65,17M12,22L9.61,18.58C10.27,18.86 11,19 12,19C13,19 13.73,18.86 14.39,18.58L12,22Z"
);
}
else
{
// 浅色主题时显示月亮图标(提示可以切换到深色)
ThemeIcon.Data = Geometry.Parse(
"M17.75,4.09L15.22,6.03L16.13,9.09L13.5,7.28L10.87,9.09L11.78,6.03L9.25,4.09L12.44,4L13.5,1L14.56,4L17.75,4.09M21.25,11L19.61,12.25L20.2,14.23L18.5,13.06L16.8,14.23L17.39,12.25L15.75,11L17.81,10.95L18.5,9L19.19,10.95L21.25,11M18.97,15.95C19.8,15.87 20.69,17.05 20.16,17.8C19.84,18.25 19.38,18.57 18.97,18.95C16.73,21.04 14.04,22.5 11,22.5C7.96,22.5 5.27,21.04 3.03,18.95C2.62,18.57 2.16,18.25 1.84,17.8C1.31,17.05 2.2,15.87 3.03,15.95C7.33,16.37 10.17,12.37 11,9.42C11.83,12.37 14.67,16.37 18.97,15.95Z"
);
}
}
#endregion
}
}