feat 使用SwiftUI的方式调整窗口大小
This commit is contained in:
parent
4c373b7e5e
commit
b10f99ac8a
@ -7,9 +7,23 @@
|
||||
|
||||
import SwiftUI
|
||||
import SwiftData
|
||||
#if os(macOS)
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
// Class to manage window title across the app
|
||||
class WindowTitleManager: ObservableObject {
|
||||
@Published var title: String = "TeachMate"
|
||||
|
||||
func updateTitle(_ newTitle: String) {
|
||||
self.title = newTitle
|
||||
}
|
||||
}
|
||||
|
||||
@main
|
||||
struct TeachMateApp: App {
|
||||
@StateObject private var windowTitleManager = WindowTitleManager()
|
||||
|
||||
var sharedModelContainer: ModelContainer = {
|
||||
let schema = Schema([
|
||||
Semester.self,
|
||||
@ -28,7 +42,17 @@ struct TeachMateApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
.environmentObject(windowTitleManager)
|
||||
.onReceive(windowTitleManager.$title) { newTitle in
|
||||
#if os(macOS)
|
||||
NSApp.windows.first?.title = newTitle
|
||||
#endif
|
||||
}
|
||||
}
|
||||
.modelContainer(sharedModelContainer)
|
||||
#if os(macOS)
|
||||
.windowResizability(.contentSize)
|
||||
.defaultSize(WindowSizeManager.WindowSizePreset.schedule.size)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
import SwiftUI
|
||||
|
||||
#if os(macOS)
|
||||
// 窗口尺寸管理器
|
||||
// 窗口尺寸预设
|
||||
struct WindowSizeManager {
|
||||
enum WindowSizePreset {
|
||||
case calendar // 教学历视图 - 竖长
|
||||
@ -17,52 +17,29 @@ struct WindowSizeManager {
|
||||
var size: CGSize {
|
||||
switch self {
|
||||
case .calendar:
|
||||
return CGSize(width: 500, height: 800) // 竖长窗口
|
||||
return CGSize(width: 500, height: 800)
|
||||
case .schedule:
|
||||
return CGSize(width: 1200, height: 680) // 横长窗口
|
||||
return CGSize(width: 1200, height: 680)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 调整窗口大小
|
||||
static func resizeWindow(to preset: WindowSizePreset) {
|
||||
guard let window = NSApplication.shared.windows.first else { return }
|
||||
|
||||
let newSize = preset.size
|
||||
let currentFrame = window.frame
|
||||
|
||||
// 计算新的窗口位置,保持窗口中心点不变
|
||||
let newOriginX = currentFrame.origin.x + (currentFrame.width - newSize.width) / 2
|
||||
let newOriginY = currentFrame.origin.y + (currentFrame.height - newSize.height) / 2
|
||||
|
||||
let newFrame = NSRect(
|
||||
x: newOriginX,
|
||||
y: newOriginY,
|
||||
width: newSize.width,
|
||||
height: newSize.height
|
||||
)
|
||||
|
||||
// 平滑动画调整窗口大小
|
||||
window.animator().setFrame(newFrame, display: true, animate: true)
|
||||
}
|
||||
|
||||
// 扩展Scene以便于使用
|
||||
extension Scene {
|
||||
func windowIdealSize(_ preset: WindowSizeManager.WindowSizePreset) -> some Scene {
|
||||
self.windowResizability(.contentSize)
|
||||
.defaultSize(preset.size)
|
||||
}
|
||||
}
|
||||
|
||||
// 视图修饰符,用于调整窗口大小
|
||||
struct WindowSizeModifier: ViewModifier {
|
||||
let preset: WindowSizeManager.WindowSizePreset
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.onAppear {
|
||||
WindowSizeManager.resizeWindow(to: preset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 扩展View以便于使用
|
||||
// 扩展View以便于在视图级别设置理想尺寸
|
||||
extension View {
|
||||
func adjustWindowSize(to preset: WindowSizeManager.WindowSizePreset) -> some View {
|
||||
modifier(WindowSizeModifier(preset: preset))
|
||||
func idealFrame(for preset: WindowSizeManager.WindowSizePreset) -> some View {
|
||||
self.frame(
|
||||
idealWidth: preset.size.width,
|
||||
idealHeight: preset.size.height
|
||||
)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -11,6 +11,7 @@ import SwiftData
|
||||
struct ContentView: View {
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
@Query private var semesters: [Semester]
|
||||
@EnvironmentObject private var windowTitleManager: WindowTitleManager
|
||||
|
||||
// Add a state to track the selected navigation item
|
||||
@State private var selectedNavItem: NavItem? = .schedule
|
||||
@ -120,14 +121,20 @@ struct ContentView: View {
|
||||
CourseScheduleView(semester: currentSemester)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
#if os(macOS)
|
||||
.adjustWindowSize(to: .schedule)
|
||||
.idealFrame(for: .schedule)
|
||||
#endif
|
||||
.onAppear {
|
||||
windowTitleManager.updateTitle(selectedNavItem.rawValue)
|
||||
}
|
||||
} else if !semesters.isEmpty {
|
||||
CourseScheduleView(semester: semesters[0])
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
#if os(macOS)
|
||||
.adjustWindowSize(to: .schedule)
|
||||
.idealFrame(for: .schedule)
|
||||
#endif
|
||||
.onAppear {
|
||||
windowTitleManager.updateTitle(selectedNavItem.rawValue)
|
||||
}
|
||||
} else {
|
||||
VStack {
|
||||
Text("请先添加学期")
|
||||
@ -135,20 +142,29 @@ struct ContentView: View {
|
||||
Text("在添加学期后,将自动显示课程表")
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.onAppear {
|
||||
windowTitleManager.updateTitle(selectedNavItem.rawValue)
|
||||
}
|
||||
}
|
||||
case .calendar:
|
||||
if let currentSemester = semesters.first(where: { $0.isCurrent }) {
|
||||
AcademicCalendarView(semester: currentSemester)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
#if os(macOS)
|
||||
.adjustWindowSize(to: .calendar)
|
||||
.idealFrame(for: .calendar)
|
||||
#endif
|
||||
.onAppear {
|
||||
windowTitleManager.updateTitle(selectedNavItem.rawValue)
|
||||
}
|
||||
} else if !semesters.isEmpty {
|
||||
AcademicCalendarView(semester: semesters[0])
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
#if os(macOS)
|
||||
.adjustWindowSize(to: .calendar)
|
||||
.idealFrame(for: .calendar)
|
||||
#endif
|
||||
.onAppear {
|
||||
windowTitleManager.updateTitle(selectedNavItem.rawValue)
|
||||
}
|
||||
} else {
|
||||
VStack {
|
||||
Text("请先添加学期")
|
||||
@ -156,11 +172,20 @@ struct ContentView: View {
|
||||
Text("在添加学期后,将自动显示教学日历")
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.onAppear {
|
||||
windowTitleManager.updateTitle(selectedNavItem.rawValue)
|
||||
}
|
||||
}
|
||||
case .reminders:
|
||||
Text("提醒事项内容")
|
||||
.onAppear {
|
||||
windowTitleManager.updateTitle(selectedNavItem.rawValue)
|
||||
}
|
||||
case .courseManager:
|
||||
CourseManagerView()
|
||||
.onAppear {
|
||||
windowTitleManager.updateTitle(selectedNavItem.rawValue)
|
||||
}
|
||||
}
|
||||
} else if let semester = selectedSemester {
|
||||
// Show semester detail
|
||||
@ -199,9 +224,14 @@ struct ContentView: View {
|
||||
Spacer()
|
||||
}
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.onAppear {
|
||||
windowTitleManager.updateTitle(semester.title)
|
||||
}
|
||||
} else {
|
||||
Text("请选择一个项目")
|
||||
Text("选择一个项目以查看详情")
|
||||
.onAppear {
|
||||
windowTitleManager.updateTitle("TeachMate")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -228,4 +258,5 @@ struct ContentView: View {
|
||||
#Preview {
|
||||
ContentView()
|
||||
.modelContainer(PreviewData.createSemesterContainer())
|
||||
.environmentObject(WindowTitleManager())
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ struct CourseFormView: View {
|
||||
setupInitialValues()
|
||||
}
|
||||
}
|
||||
.frame(idealWidth: 600, idealHeight: 400)
|
||||
}
|
||||
|
||||
// Main content view
|
||||
@ -78,7 +79,6 @@ struct CourseFormView: View {
|
||||
// Left side - Form content
|
||||
formFieldsSection
|
||||
}
|
||||
.frame(minWidth: 600, idealWidth: 700, maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ struct CourseManagerView: View {
|
||||
mode: .edit(course),
|
||||
onSave: { _ in }
|
||||
)
|
||||
.frame(width: 600)
|
||||
.frame(idealWidth: 600, idealHeight: 400)
|
||||
} else {
|
||||
CourseFormView(
|
||||
mode: .add,
|
||||
@ -96,7 +96,7 @@ struct CourseManagerView: View {
|
||||
selectedCourse = newCourse
|
||||
}
|
||||
)
|
||||
.frame(width: 600)
|
||||
.frame(idealWidth: 600, idealHeight: 400)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
|
@ -58,6 +58,7 @@ struct SessionFormView: View {
|
||||
setupInitialValues()
|
||||
}
|
||||
}
|
||||
.frame(idealWidth: 600, idealHeight: 400)
|
||||
}
|
||||
|
||||
// Main content view
|
||||
@ -76,7 +77,6 @@ struct SessionFormView: View {
|
||||
Divider()
|
||||
.padding(.vertical)
|
||||
}
|
||||
.frame(minWidth: 600, idealWidth: 700, maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user