diff --git a/ClassScheduler.Runner/App.xaml.cs b/ClassScheduler.Runner/App.xaml.cs
index f7fbc3a..d5d38f2 100644
--- a/ClassScheduler.Runner/App.xaml.cs
+++ b/ClassScheduler.Runner/App.xaml.cs
@@ -2,6 +2,7 @@
using System;
using System.ComponentModel.Composition.Hosting;
using System.IO;
+using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
@@ -30,6 +31,8 @@ private void Application_Startup(object sender, StartupEventArgs e)
try
{
+ AddDllResolveHandler(Path.GetFullPath("./"));
+
LoadPlugin("./ClassScheduler.WPF.dll");
}
catch (Exception o)
@@ -47,6 +50,23 @@ private void Application_Startup(object sender, StartupEventArgs e)
}
}
+ private static void AddDllResolveHandler(string appendPath)
+ {
+ var domain = AppDomain.CurrentDomain;
+
+ domain.AssemblyResolve += (sender, args) =>
+ {
+ var assemblyFolder = Path.GetFullPath(appendPath);
+ var assemblyPath = Path.Combine(assemblyFolder, new AssemblyName(args.Name).Name + ".dll");
+
+ if (!File.Exists(assemblyPath)) return null;
+
+ var assembly = Assembly.LoadFrom(assemblyPath);
+
+ return assembly;
+ };
+ }
+
private static void LoadPlugin(string path)
{
if (File.Exists(Path.GetFullPath(path)))
diff --git a/ClassScheduler.Runner/ClassScheduler.Runner.csproj b/ClassScheduler.Runner/ClassScheduler.Runner.csproj
index bb708fd..2ac7942 100644
--- a/ClassScheduler.Runner/ClassScheduler.Runner.csproj
+++ b/ClassScheduler.Runner/ClassScheduler.Runner.csproj
@@ -6,8 +6,13 @@
enable
true
AnyCPU;x64
+ icon.ico
+
+
+
+
diff --git a/ClassScheduler.Runner/icon.ico b/ClassScheduler.Runner/icon.ico
new file mode 100644
index 0000000..3549db7
Binary files /dev/null and b/ClassScheduler.Runner/icon.ico differ
diff --git a/ClassScheduler.WPF/Assets/ChartData.txt b/ClassScheduler.WPF/Assets/ChartData.txt
deleted file mode 100644
index a0e9aa3..0000000
--- a/ClassScheduler.WPF/Assets/ChartData.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-课表-从上至下:周日至周六-从左至右:第1~9节-直接写,无需空格,但只能用一个字表示课程-第9行(最后一行)为高考年份
-7周日课表缺失
-1生班物化-数语英-英英
-2物音生化-英数语-数数
-3数数语语-化生物-语语
-4生语英体-英物化-轮换
-5英英数数-物生化-轮换
-6数语英-化生物
-2023
\ No newline at end of file
diff --git a/ClassScheduler.WPF/Assets/icon.ico b/ClassScheduler.WPF/Assets/icon.ico
index 02f5e37..3549db7 100644
Binary files a/ClassScheduler.WPF/Assets/icon.ico and b/ClassScheduler.WPF/Assets/icon.ico differ
diff --git a/ClassScheduler.WPF/ClassScheduler.WPF.csproj b/ClassScheduler.WPF/ClassScheduler.WPF.csproj
index 19becf2..469efe7 100644
--- a/ClassScheduler.WPF/ClassScheduler.WPF.csproj
+++ b/ClassScheduler.WPF/ClassScheduler.WPF.csproj
@@ -16,6 +16,8 @@
+
+
@@ -26,9 +28,6 @@
-
- Always
-
Always
diff --git a/ClassScheduler.WPF/Converters/HorizontalAlignmentReverseConverter.cs b/ClassScheduler.WPF/Converters/HorizontalAlignmentReverseConverter.cs
new file mode 100644
index 0000000..fe25ffc
--- /dev/null
+++ b/ClassScheduler.WPF/Converters/HorizontalAlignmentReverseConverter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace ClassScheduler.WPF.Converters;
+
+public class HorizontalAlignmentReverseConverter : IValueConverter
+{
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var align = (HorizontalAlignment)value;
+ switch (align)
+ {
+ case HorizontalAlignment.Left:
+ return HorizontalAlignment.Right;
+ case HorizontalAlignment.Center:
+ return HorizontalAlignment.Stretch;
+ case HorizontalAlignment.Right:
+ return HorizontalAlignment.Left;
+ case HorizontalAlignment.Stretch:
+ return HorizontalAlignment.Center;
+ }
+
+ return align;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/ClassScheduler.WPF/Converters/RectConverter.cs b/ClassScheduler.WPF/Converters/RectConverter.cs
new file mode 100644
index 0000000..ab3c387
--- /dev/null
+++ b/ClassScheduler.WPF/Converters/RectConverter.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace ClassScheduler.WPF.Converters;
+
+public class RectConverter : IMultiValueConverter
+{
+ public object Convert(
+ object[] values,
+ Type targetType,
+ object parameter,
+ CultureInfo culture)
+ {
+ return new Rect(0, 0, (double)values[0], (double)values[1]);
+ }
+
+ public object[] ConvertBack(
+ object value,
+ Type[] targetTypes,
+ object parameter,
+ CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/ClassScheduler.WPF/Data/AppConfig.cs b/ClassScheduler.WPF/Data/AppConfig.cs
new file mode 100644
index 0000000..8655ee7
--- /dev/null
+++ b/ClassScheduler.WPF/Data/AppConfig.cs
@@ -0,0 +1,63 @@
+using ClassScheduler.WPF.Utils;
+using System;
+using System.IO;
+using System.Text.Json;
+
+namespace ClassScheduler.WPF.Data;
+
+public class AppConfig
+{
+ public TopmostEffectsSettings TopmostEffectsSettings { get; set; } = new();
+
+ public WallPaperSettings WallPaperSettings { get; set; } = new();
+}
+
+public class TopmostEffectsSettings
+{
+ public bool? IsDateTimeVisible { get; set; } = true;
+}
+
+public class WallPaperSettings
+{
+ public string? WallPapersPath { get; set; }
+
+ public int CurrentWallPaperIndex { get; set; } = 0;
+
+ public bool? WallPapersEnabled { get; set; } = false;
+
+ public WallPaperStyle? WallPaperStyle { get; set; } = Utils.WallPaperStyle.Stretched;
+}
+
+public static class AppConfigExtensions
+{
+ public static void Save(
+ this AppConfig config,
+ string path = "./Data/AppConfig.json",
+ Action? optionsProcessor = null)
+ {
+ var options = new JsonSerializerOptions()
+ {
+ IncludeFields = true,
+ WriteIndented = true,
+ };
+ optionsProcessor?.Invoke(options);
+
+ var json = JsonSerializer.Serialize(config, options);
+ File.WriteAllText(path, json);
+ }
+
+ public static AppConfig? LoadAsAppConfig(
+ this string path,
+ Action? optionsProcessor = null)
+ {
+ if (!Path.Exists(path)) return null;
+
+ var options = new JsonSerializerOptions();
+ optionsProcessor?.Invoke(options);
+
+ var json = File.ReadAllText(path);
+ var appConfig = JsonSerializer.Deserialize(json, options);
+
+ return appConfig;
+ }
+}
diff --git a/ClassScheduler.WPF/Data/Classes.cs b/ClassScheduler.WPF/Data/Classes.cs
index fc54c96..d07375e 100644
--- a/ClassScheduler.WPF/Data/Classes.cs
+++ b/ClassScheduler.WPF/Data/Classes.cs
@@ -10,25 +10,35 @@ public class Classes
{
public string? Name { get; set; }
- public List ClassesList { get; set; } = new();
+ public List ClassesList { get; set; } = new()
+ {
+ new()
+ {
+ Name = "name",
+ BeginTime = DateTime.Now,
+ EndTime = DateTime.Now + new TimeSpan(1,0,0),
+ WeekDay = 1,
+ }
+ };
public Classes Sort()
{
ClassesList.Sort(
- new Comparison(
- (x, y) =>
+ (x, y) =>
+ {
+ if (x.WeekDay == y.WeekDay)
{
- if (x.WeekDay == y.WeekDay)
- {
- if (x.BeginTime == y.BeginTime)
- return 0;
- else
- return x.BeginTime > y.BeginTime ? 1 : -1;
- }
- else
- return x.WeekDay > y.WeekDay ? 1 : -1;
+ var x_begin = DateTime.Parse(x.BeginTime?.ToString("HH:mm")!);
+ var y_begin = DateTime.Parse(y.BeginTime?.ToString("HH:mm")!);
+ var x_end = DateTime.Parse(x.EndTime?.ToString("HH:mm")!);
+ var y_end = DateTime.Parse(y.EndTime?.ToString("HH:mm")!);
+
+ if (x_begin == y_begin && x_end == y_end)
+ return x.Name!.CompareTo(y.Name);
+ else return x_begin.CompareTo(y_end);
}
- )
+ else return x.WeekDay > y.WeekDay ? 1 : -1;
+ }
);
return this;
@@ -39,7 +49,7 @@ public static class ClassesExtensions
{
public static void Save(
this Classes classes,
- string path,
+ string path = "./Data/Classes.json",
Action? optionsProcessor = null)
{
var options = new JsonSerializerOptions()
@@ -49,11 +59,11 @@ public static void Save(
};
optionsProcessor?.Invoke(options);
- var json = JsonSerializer.Serialize(classes);
+ var json = JsonSerializer.Serialize(classes, options);
File.WriteAllText(path, json);
}
- public static Classes? Load(
+ public static Classes? LoadAsClasses(
this string path,
Action? optionsProcessor = null)
{
@@ -63,7 +73,7 @@ public static void Save(
optionsProcessor?.Invoke(options);
var json = File.ReadAllText(path);
- var classes = JsonSerializer.Deserialize(json);
+ var classes = JsonSerializer.Deserialize(json, options);
return classes;
}
diff --git a/ClassScheduler.WPF/Identity.cs b/ClassScheduler.WPF/Identity.cs
index d2dba39..e52d410 100644
--- a/ClassScheduler.WPF/Identity.cs
+++ b/ClassScheduler.WPF/Identity.cs
@@ -1,6 +1,6 @@
using KitX.Contract.CSharp;
-using System.Collections.Generic;
using System;
+using System.Collections.Generic;
namespace ClassScheduler.WPF;
diff --git a/ClassScheduler.WPF/Instances.cs b/ClassScheduler.WPF/Instances.cs
index 411f97b..1387ad1 100644
--- a/ClassScheduler.WPF/Instances.cs
+++ b/ClassScheduler.WPF/Instances.cs
@@ -12,14 +12,22 @@ internal static void Init()
if (!Directory.Exists(Path.GetFullPath("./Data/")))
Directory.CreateDirectory(Path.GetFullPath("./Data/"));
- Classes = "./Data/Classes.json".Load();
+ AppConfig = "./Data/AppConfig.json".LoadAsAppConfig();
+ AppConfig ??= new();
+ AppConfig.Save();
+
+ Classes = "./Data/Classes.json".LoadAsClasses();
Classes ??= new();
- Classes.Save("./Data/Classes.json");
+ Classes.Sort();
+ Classes.Save();
MainWindow = new();
ScheduleWindow = new();
+ TopmostEffectsWindow = new();
+ TopmostEffectsWindow.Show();
+
Controller = new();
}
@@ -27,8 +35,12 @@ internal static void Init()
internal static ScheduleWindow? ScheduleWindow { get; set; }
+ internal static TopmostEffectsWindow? TopmostEffectsWindow { get; set; }
+
internal static Controller? Controller { get; set; }
+ internal static AppConfig? AppConfig { get; set; }
+
internal static Classes? Classes { get; set; }
internal static NotifyIcon? NotifyIcon { get; set; }
diff --git a/ClassScheduler.WPF/Models/ClassModel.cs b/ClassScheduler.WPF/Models/ClassModel.cs
index 6c703a9..f6bdc82 100644
--- a/ClassScheduler.WPF/Models/ClassModel.cs
+++ b/ClassScheduler.WPF/Models/ClassModel.cs
@@ -1,6 +1,5 @@
-using System;
-using System.IO;
-using ClassScheduler.WPF.Models.Types;
+using ClassScheduler.WPF.Models.Types;
+using System;
namespace ClassScheduler.WPF.Models;
@@ -33,7 +32,7 @@ public int? DayOfWeek
{
var weekDay = (int)WeekDay!;
var dividedCount = 0;
- while(weekDay != 1)
+ while (weekDay != 1)
{
weekDay /= 2;
++dividedCount;
diff --git a/ClassScheduler.WPF/Utils/Converter/DayOfWeekToInt.cs b/ClassScheduler.WPF/Utils/Converter/DayOfWeekToInt.cs
new file mode 100644
index 0000000..ece3c75
--- /dev/null
+++ b/ClassScheduler.WPF/Utils/Converter/DayOfWeekToInt.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace ClassScheduler.WPF.Utils.Converter;
+
+public static class DayOfWeekToInt
+{
+ public static int ToInt(this DayOfWeek day)
+ {
+ switch (day)
+ {
+ case DayOfWeek.Sunday:
+ return 7;
+ case DayOfWeek.Monday:
+ return 1;
+ case DayOfWeek.Tuesday:
+ return 2;
+ case DayOfWeek.Wednesday:
+ return 3;
+ case DayOfWeek.Thursday:
+ return 4;
+ case DayOfWeek.Friday:
+ return 5;
+ case DayOfWeek.Saturday:
+ return 6;
+ }
+
+ return -1;
+ }
+}
diff --git a/ClassScheduler.WPF/Utils/FixedSizedQueue.cs b/ClassScheduler.WPF/Utils/FixedSizedQueue.cs
new file mode 100644
index 0000000..b834ac5
--- /dev/null
+++ b/ClassScheduler.WPF/Utils/FixedSizedQueue.cs
@@ -0,0 +1,28 @@
+using System.Collections.Concurrent;
+
+namespace ClassScheduler.WPF.Utils;
+
+public class FixedSizedQueue : ConcurrentQueue
+{
+ private readonly object syncObject = new();
+
+ public int Size { get; private set; }
+
+ public FixedSizedQueue(int size)
+ {
+ Size = size;
+ }
+
+ public new void Enqueue(T obj)
+ {
+ base.Enqueue(obj);
+
+ lock (syncObject)
+ {
+ while (Count > Size)
+ {
+ TryDequeue(out T outObj);
+ }
+ }
+ }
+}
diff --git a/ClassScheduler.WPF/Utils/NotifyIconManager.cs b/ClassScheduler.WPF/Utils/NotifyIconManager.cs
new file mode 100644
index 0000000..f9da1f9
--- /dev/null
+++ b/ClassScheduler.WPF/Utils/NotifyIconManager.cs
@@ -0,0 +1,143 @@
+using ClassScheduler.WPF.Data;
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+
+namespace ClassScheduler.WPF.Utils;
+
+internal static class NotifyIconManager
+{
+ private static ToolStripMenuItem BuildItem(
+ string text = "",
+ Action