2025-09-05 13:32:42 +08:00
|
|
|
|
using HFUTCourseSimulation.Dialog;
|
2025-09-06 18:20:43 +08:00
|
|
|
|
using HFUTCourseSimulation.Util;
|
2025-09-05 13:32:42 +08:00
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using System;
|
2018-12-22 23:44:18 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
2025-09-05 13:32:42 +08:00
|
|
|
|
using System.Linq;
|
2018-12-22 23:44:18 +08:00
|
|
|
|
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 HFUTCourseSimulation {
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// MainWindow.xaml 的交互逻辑
|
|
|
|
|
/// </summary>
|
|
|
|
|
public partial class MainWindow : Window {
|
|
|
|
|
public MainWindow() {
|
|
|
|
|
InitializeComponent();
|
2025-09-04 21:56:31 +08:00
|
|
|
|
UpdateUiLayout();
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
#region Context and Assistant Functions
|
|
|
|
|
|
2025-09-06 18:20:43 +08:00
|
|
|
|
private Kernel.Data.Ui.Semester CurrentSemester { get; set; }
|
2025-09-05 13:32:42 +08:00
|
|
|
|
private string CurrentFilePath { get; set; }
|
2025-09-04 21:56:31 +08:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 返回当前是否有文件被加载。
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private bool IsFileLoaded() {
|
2025-09-05 13:32:42 +08:00
|
|
|
|
return !(CurrentSemester is null);
|
2025-09-04 21:56:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 检查当前加载的文件是否是关联到某个本地文件上的。
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private bool HasAssocFile() {
|
2025-09-05 13:32:42 +08:00
|
|
|
|
return !(CurrentFilePath is null);
|
2025-09-04 21:56:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 更新整个界面的UI状态(包括启用与否等)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private void UpdateUiLayout() {
|
|
|
|
|
bool isFileLoaded = this.IsFileLoaded();
|
|
|
|
|
bool hasAssocFile = this.HasAssocFile();
|
|
|
|
|
|
|
|
|
|
// Menus
|
|
|
|
|
uiMenuNew.IsEnabled = !isFileLoaded;
|
|
|
|
|
uiMenuOpen.IsEnabled = !isFileLoaded;
|
|
|
|
|
uiMenuOpenOld.IsEnabled = !isFileLoaded;
|
|
|
|
|
uiMenuOpenV1.IsEnabled = uiMenuOpenOld.IsEnabled;
|
|
|
|
|
|
|
|
|
|
uiMenuSave.IsEnabled = isFileLoaded;
|
|
|
|
|
uiMenuSaveAs.IsEnabled = isFileLoaded;
|
|
|
|
|
|
|
|
|
|
uiMenuClose.IsEnabled = isFileLoaded;
|
|
|
|
|
uiMenuQuit.IsEnabled = true;
|
|
|
|
|
|
|
|
|
|
uiMenuSimulator.IsEnabled = isFileLoaded;
|
|
|
|
|
uiMenuRender.IsEnabled = isFileLoaded;
|
|
|
|
|
|
|
|
|
|
// Main Area
|
|
|
|
|
uiMainTab.Visibility = isFileLoaded ? Visibility.Visible : Visibility.Collapsed;
|
|
|
|
|
|
|
|
|
|
// Window Caption
|
|
|
|
|
if (isFileLoaded) {
|
|
|
|
|
if (hasAssocFile) {
|
2025-09-05 13:32:42 +08:00
|
|
|
|
this.Title = $"HFUT课表模拟 - {CurrentFilePath}";
|
2025-09-04 21:56:31 +08:00
|
|
|
|
} else {
|
|
|
|
|
this.Title = "HFUT课表模拟 - [未命名]";
|
|
|
|
|
}
|
2018-12-22 23:44:18 +08:00
|
|
|
|
} else {
|
2025-09-04 21:56:31 +08:00
|
|
|
|
this.Title = "HFUT课表模拟";
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-12-26 15:55:33 +08:00
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 更新界面的数据源
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void UpdateDataSource() {
|
|
|
|
|
if (this.IsFileLoaded()) {
|
2025-09-05 13:32:42 +08:00
|
|
|
|
this.DataContext = CurrentSemester;
|
2025-09-04 21:56:31 +08:00
|
|
|
|
} else {
|
|
|
|
|
this.DataContext = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-12-22 23:44:18 +08:00
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
#endregion
|
2018-12-22 23:44:18 +08:00
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
#region Menu Handlers
|
2018-12-22 23:44:18 +08:00
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
private void uiMenuNew_Click(object sender, RoutedEventArgs e) {
|
2025-09-06 18:20:43 +08:00
|
|
|
|
// Create new blank semester.
|
|
|
|
|
var new_obj = new Kernel.Data.Storage.Semester();
|
|
|
|
|
|
|
|
|
|
// Convert into struct for Ui and clean assoc file path.
|
|
|
|
|
CurrentSemester = new Kernel.Data.Ui.Semester(new_obj);
|
2025-09-05 13:32:42 +08:00
|
|
|
|
CurrentFilePath = null;
|
2025-09-06 18:20:43 +08:00
|
|
|
|
|
|
|
|
|
// Update UI and data source
|
2025-09-04 21:56:31 +08:00
|
|
|
|
UpdateUiLayout();
|
|
|
|
|
UpdateDataSource();
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void uiMenuOpen_Click(object sender, RoutedEventArgs e) {
|
2025-09-04 21:56:31 +08:00
|
|
|
|
// Fetch file path.
|
|
|
|
|
var filepath = Util.Win32Dialog.OpenSemester();
|
|
|
|
|
if (filepath is null) return;
|
2018-12-22 23:44:18 +08:00
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
// Try to read file.
|
|
|
|
|
try {
|
|
|
|
|
using (var fs = new StreamReader(filepath, Encoding.UTF8)) {
|
2025-09-06 18:20:43 +08:00
|
|
|
|
// Read semester object.
|
|
|
|
|
var obj = JsonConvert.DeserializeObject<Kernel.Data.Storage.Semester>(fs.ReadToEnd());
|
|
|
|
|
// Convert into struct for Ui and add assoc file path.
|
|
|
|
|
CurrentSemester = new Kernel.Data.Ui.Semester(obj);
|
2025-09-05 13:32:42 +08:00
|
|
|
|
CurrentFilePath = filepath;
|
2025-09-04 21:56:31 +08:00
|
|
|
|
}
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
Util.Win32Dialog.Error(ex.ToString(), "打开文件时出错");
|
2018-12-22 23:44:18 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
// Update UI and data source
|
|
|
|
|
UpdateUiLayout();
|
|
|
|
|
UpdateDataSource();
|
|
|
|
|
}
|
2018-12-22 23:44:18 +08:00
|
|
|
|
|
2025-09-06 18:20:43 +08:00
|
|
|
|
private void OpenLegacy<T>() where T : Kernel.Data.Storage.IFromLegacy {
|
2025-09-05 11:10:23 +08:00
|
|
|
|
// Fetch file path.
|
|
|
|
|
var filepath = Util.Win32Dialog.OpenSemester();
|
|
|
|
|
if (filepath is null) return;
|
|
|
|
|
|
|
|
|
|
// Try to read file.
|
|
|
|
|
try {
|
|
|
|
|
using (var fs = new StreamReader(filepath, Encoding.UTF8)) {
|
2025-09-06 18:20:43 +08:00
|
|
|
|
// Read legacy file and convert it into latest file.
|
|
|
|
|
var obj = JsonConvert.DeserializeObject<T>(fs.ReadToEnd());
|
|
|
|
|
var latest_obj = obj.ToLatest();
|
|
|
|
|
// Convert into struct for Ui and add assoc file path.
|
|
|
|
|
CurrentSemester = new Kernel.Data.Ui.Semester(latest_obj);
|
2025-09-05 13:32:42 +08:00
|
|
|
|
CurrentFilePath = filepath;
|
2025-09-05 11:10:23 +08:00
|
|
|
|
}
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
Util.Win32Dialog.Error(ex.ToString(), "打开文件时出错");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-12-22 23:44:18 +08:00
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
// Update UI and data source
|
|
|
|
|
UpdateUiLayout();
|
|
|
|
|
UpdateDataSource();
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-09-06 18:20:43 +08:00
|
|
|
|
private void uiMenuOpenV1_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
OpenLegacy<Kernel.Data.LegacyStorage.V1.Semester>();
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-22 23:44:18 +08:00
|
|
|
|
private void uiMenuSave_Click(object sender, RoutedEventArgs e) {
|
2025-09-04 21:56:31 +08:00
|
|
|
|
// Check whether there is associated file.
|
|
|
|
|
// If it not, order user select one.
|
2025-09-05 13:32:42 +08:00
|
|
|
|
if (CurrentFilePath is null) {
|
2025-09-04 21:56:31 +08:00
|
|
|
|
var filepath = Util.Win32Dialog.SaveSemester();
|
|
|
|
|
if (filepath is null) return;
|
2025-09-05 13:32:42 +08:00
|
|
|
|
CurrentFilePath = filepath;
|
2025-09-04 21:56:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Try to save file
|
|
|
|
|
try {
|
2025-09-05 13:32:42 +08:00
|
|
|
|
using (var fs = new StreamWriter(CurrentFilePath, false, Encoding.UTF8)) {
|
2025-09-06 18:20:43 +08:00
|
|
|
|
fs.Write(JsonConvert.SerializeObject(CurrentSemester.ToStorage()));
|
2025-09-04 21:56:31 +08:00
|
|
|
|
}
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
Util.Win32Dialog.Error(ex.ToString(), "保存文件时出错");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update UI
|
|
|
|
|
UpdateUiLayout();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void uiMenuSaveAs_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
// Always order user give a path
|
|
|
|
|
var filepath = Util.Win32Dialog.SaveSemester();
|
|
|
|
|
if (filepath is null) return;
|
|
|
|
|
|
|
|
|
|
// Update it to current path for following editing.
|
2025-09-05 13:32:42 +08:00
|
|
|
|
CurrentFilePath = filepath;
|
2025-09-04 21:56:31 +08:00
|
|
|
|
|
|
|
|
|
// Try to save file
|
|
|
|
|
try {
|
2025-09-05 13:32:42 +08:00
|
|
|
|
using (var fs = new StreamWriter(CurrentFilePath, false, Encoding.UTF8)) {
|
2025-09-06 18:20:43 +08:00
|
|
|
|
fs.Write(JsonConvert.SerializeObject(CurrentSemester.ToStorage()));
|
2025-09-04 21:56:31 +08:00
|
|
|
|
}
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
Util.Win32Dialog.Error(ex.ToString(), "保存文件时出错");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update UI
|
|
|
|
|
UpdateUiLayout();
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void uiMenuClose_Click(object sender, RoutedEventArgs e) {
|
2025-09-04 21:56:31 +08:00
|
|
|
|
// Confirm close
|
|
|
|
|
var rv = Util.Win32Dialog.Confirm("确认关闭吗?所有未保存的更改都将永久丢失!", "确认关闭");
|
|
|
|
|
if (!rv) return;
|
2018-12-22 23:44:18 +08:00
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
// Clear semester and assoc file
|
2025-09-05 13:32:42 +08:00
|
|
|
|
CurrentSemester = null;
|
|
|
|
|
CurrentFilePath = null;
|
2025-09-04 21:56:31 +08:00
|
|
|
|
|
|
|
|
|
// Update UI and data source
|
|
|
|
|
UpdateUiLayout();
|
|
|
|
|
UpdateDataSource();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void uiMenuQuit_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
// If there is an opened document, let we confirm it first
|
|
|
|
|
if (IsFileLoaded()) {
|
|
|
|
|
var rv = Util.Win32Dialog.Confirm("确认退出吗?所有未保存的更改都将永久丢失!", "确认退出");
|
|
|
|
|
if (!rv) return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Close window
|
|
|
|
|
this.Close();
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-09-07 16:31:07 +08:00
|
|
|
|
private void uiMenuCheck_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
var semester = CurrentSemester.ToStorage();
|
|
|
|
|
var reporter = new Kernel.Reporter();
|
|
|
|
|
var rv = Kernel.Arranger.Arrange(semester, reporter);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 15:26:57 +08:00
|
|
|
|
private void uiMenuSimulator_Click(object sender, RoutedEventArgs e) {
|
2025-09-07 17:31:13 +08:00
|
|
|
|
var semester = CurrentSemester.ToStorage();
|
|
|
|
|
var reporter = new Kernel.Reporter();
|
|
|
|
|
var rv = Kernel.Arranger.Arrange(semester, reporter);
|
|
|
|
|
if (rv is null) return;
|
|
|
|
|
|
|
|
|
|
var dialog = new Dialog.Simulator();
|
|
|
|
|
dialog.CurrentSemester = rv;
|
|
|
|
|
dialog.ShowDialog();
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 15:26:57 +08:00
|
|
|
|
private void uiMenuRender_Click(object sender, RoutedEventArgs e) {
|
2025-09-06 18:20:43 +08:00
|
|
|
|
////convert data
|
|
|
|
|
//int weekCount;
|
|
|
|
|
//DateTime originDate;
|
|
|
|
|
//try {
|
|
|
|
|
// originDate = DateTime.Parse(General.GeneralSheet.StartDate);
|
|
|
|
|
// weekCount = General.GeneralSheet.WeekCount;
|
|
|
|
|
//} catch (Exception) {
|
|
|
|
|
// MessageBox.Show("周数或日期转换错误,无法输出", "错误", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
|
|
|
|
|
// return;
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
////open file
|
|
|
|
|
//var sp = new Microsoft.Win32.SaveFileDialog();
|
|
|
|
|
//sp.RestoreDirectory = true;
|
|
|
|
|
//sp.Filter = "图片文件(*.png)|*.png|所有文件(*.*)|*.*";
|
|
|
|
|
//var status = sp.ShowDialog();
|
|
|
|
|
//if (!(status.HasValue && status.Value)) return;
|
|
|
|
|
//var getFile = sp.FileName;
|
|
|
|
|
|
|
|
|
|
////export
|
|
|
|
|
//var res = ImageExport.Export(originDate, weekCount, getFile);
|
|
|
|
|
//if (!res) MessageBox.Show("当前课程安排存在冲突,请通过实时预览消除所有错误后才能使用此功能来导出为图片", "错误", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
|
|
|
|
|
//else MessageBox.Show("导出成功", "关于", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
|
2018-12-26 15:55:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-22 23:44:18 +08:00
|
|
|
|
private void uiMenuAbout_Click(object sender, RoutedEventArgs e) {
|
2025-09-06 18:20:43 +08:00
|
|
|
|
Win32Dialog.Info(@"本程序为开源程序。
|
|
|
|
|
开源地址:https://gitee.com/yyc12345/HFUTCourseSimulation
|
|
|
|
|
本程序旨在为各位选课的同学提供一个用于查验课程冲突以及查看课表的功能。如果您想参与开发,提交PullRequest即可,欢迎您的加入。", "关于");
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
#region Main Area Handlers
|
2018-12-22 23:44:18 +08:00
|
|
|
|
|
|
|
|
|
private void uiCoursesList_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
|
2025-09-05 13:32:42 +08:00
|
|
|
|
// It just an alias to edit
|
|
|
|
|
uiCtxMenuEditCourse_Click(sender, e);
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
private void uiCtxMenuNewCourse_Click(object sender, RoutedEventArgs e) {
|
2025-09-05 13:32:42 +08:00
|
|
|
|
// Create new item and order user edit it
|
2025-09-06 18:20:43 +08:00
|
|
|
|
var item = new Kernel.Data.Storage.Course();
|
2025-09-05 13:32:42 +08:00
|
|
|
|
var dialog = new Dialog.EditCourse();
|
2025-09-06 18:20:43 +08:00
|
|
|
|
dialog.CurrentCourse = new Kernel.Data.Ui.Course(item);
|
2025-09-05 13:32:42 +08:00
|
|
|
|
dialog.ShowDialog();
|
|
|
|
|
|
|
|
|
|
// Then insert or append it into list
|
|
|
|
|
var idx = uiCoursesList.SelectedIndex;
|
|
|
|
|
if (idx < 0) {
|
|
|
|
|
// No selection, append.
|
2025-09-06 18:20:43 +08:00
|
|
|
|
CurrentSemester.Courses.Add(dialog.CurrentCourse);
|
2025-09-05 13:32:42 +08:00
|
|
|
|
} else {
|
|
|
|
|
// Has selection, insert
|
2025-09-06 18:20:43 +08:00
|
|
|
|
CurrentSemester.Courses.Insert(idx, dialog.CurrentCourse);
|
2025-09-05 13:32:42 +08:00
|
|
|
|
}
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
private void uiCtxMenuEditCourse_Click(object sender, RoutedEventArgs e) {
|
2025-09-05 13:32:42 +08:00
|
|
|
|
var idx = uiCoursesList.SelectedIndex;
|
|
|
|
|
if (idx < 0) return;
|
2018-12-26 15:55:33 +08:00
|
|
|
|
|
2025-09-05 13:32:42 +08:00
|
|
|
|
var dialog = new Dialog.EditCourse();
|
|
|
|
|
dialog.CurrentCourse = CurrentSemester.Courses[idx];
|
|
|
|
|
dialog.ShowDialog();
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 21:56:31 +08:00
|
|
|
|
private void uiCtxMenuDeleteCourse_Click(object sender, RoutedEventArgs e) {
|
2025-09-05 13:32:42 +08:00
|
|
|
|
// Check whether there is item can be deleted
|
|
|
|
|
var idx = uiCoursesList.SelectedIndex;
|
|
|
|
|
if (idx < 0) return;
|
|
|
|
|
|
|
|
|
|
// Order a confirm
|
|
|
|
|
var rv = Util.Win32Dialog.Confirm("确认删除选中的课程吗?该操作不可撤销!", "确认删除");
|
|
|
|
|
if (!rv) return;
|
|
|
|
|
|
|
|
|
|
// Remove it
|
|
|
|
|
CurrentSemester.Courses.RemoveAt(idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void uiCtxMenuClearCourse_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
// Order a confirm
|
|
|
|
|
var rv = Util.Win32Dialog.Confirm("确认删除所有课程吗?该操作不可撤销!", "确认清空");
|
|
|
|
|
if (!rv) return;
|
2018-12-22 23:44:18 +08:00
|
|
|
|
|
2025-09-05 13:32:42 +08:00
|
|
|
|
// Clear all schedules
|
|
|
|
|
CurrentSemester.Courses.Clear();
|
2018-12-22 23:44:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|