mirror of
https://github.com/dscyrescotti/Memola.git
synced 2026-04-24 01:28:40 +02:00
193 lines
5.8 KiB
Swift
193 lines
5.8 KiB
Swift
//
|
|
// Toolbar.swift
|
|
// Memola
|
|
//
|
|
// Created by Dscyre Scotti on 5/19/24.
|
|
//
|
|
|
|
import SwiftUI
|
|
import Foundation
|
|
|
|
struct Toolbar: View {
|
|
@Environment(\.dismiss) private var dismiss
|
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
|
|
|
#if os(macOS)
|
|
@EnvironmentObject private var application: Application
|
|
#endif
|
|
|
|
@ObservedObject private var tool: Tool
|
|
@ObservedObject private var canvas: Canvas
|
|
@ObservedObject private var history: History
|
|
|
|
@State private var title: String
|
|
|
|
@FocusState private var textFieldState: Bool
|
|
|
|
private let size: CGFloat = 40
|
|
private let memo: MemoObject
|
|
|
|
init(memo: MemoObject, tool: Tool, canvas: Canvas, history: History) {
|
|
self.memo = memo
|
|
self.tool = tool
|
|
self.canvas = canvas
|
|
self.history = history
|
|
self.title = memo.title
|
|
}
|
|
|
|
var body: some View {
|
|
HStack(spacing: 5) {
|
|
HStack(spacing: 5) {
|
|
closeButton
|
|
titleField
|
|
.foregroundStyle(Color.primary)
|
|
}
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
#if os(macOS)
|
|
ElementToolbar(tool: tool, canvas: canvas)
|
|
#else
|
|
if horizontalSizeClass == .regular {
|
|
ElementToolbar(tool: tool, canvas: canvas)
|
|
}
|
|
#endif
|
|
HStack(spacing: 5) {
|
|
gridModeControl
|
|
historyControl
|
|
}
|
|
.frame(maxWidth: .infinity, alignment: .trailing)
|
|
}
|
|
.font(.subheadline)
|
|
.padding(10)
|
|
.foregroundStyle(Color.accentColor)
|
|
}
|
|
|
|
private var closeButton: some View {
|
|
Button {
|
|
closeMemo()
|
|
} label: {
|
|
Image(systemName: "xmark")
|
|
.frame(width: size, height: size)
|
|
.background(.regularMaterial)
|
|
.clipShape(.rect(cornerRadius: 8))
|
|
.contentShape(.rect(cornerRadius: 8))
|
|
}
|
|
#if os(iOS)
|
|
.hoverEffect(.lift)
|
|
#else
|
|
.buttonStyle(.plain)
|
|
#endif
|
|
.disabled(textFieldState)
|
|
.transition(.move(edge: .top).combined(with: .blurReplace))
|
|
}
|
|
|
|
private var titleField: some View {
|
|
TextField("", text: $title)
|
|
.focused($textFieldState)
|
|
.textFieldStyle(.plain)
|
|
.padding(.horizontal, size / 2.5)
|
|
.frame(width: horizontalSizeClass == .compact ? 100 : 140, height: size)
|
|
.background(.regularMaterial)
|
|
.clipShape(.rect(cornerRadius: 8))
|
|
.onChange(of: textFieldState) { oldValue, newValue in
|
|
if !newValue {
|
|
if !title.isEmpty {
|
|
memo.title = title
|
|
memo.updatedAt = .now
|
|
} else {
|
|
title = memo.title
|
|
}
|
|
withPersistence(\.viewContext) { context in
|
|
try context.saveIfNeeded()
|
|
}
|
|
}
|
|
}
|
|
.transition(.move(edge: .top).combined(with: .blurReplace))
|
|
}
|
|
|
|
private var historyControl: some View {
|
|
HStack(spacing: 0) {
|
|
Button {
|
|
history.historyPublisher.send(.undo)
|
|
} label: {
|
|
Image(systemName: "arrow.uturn.backward.circle")
|
|
.frame(width: size, height: size)
|
|
.contentShape(.rect(cornerRadius: 8))
|
|
}
|
|
#if os(iOS)
|
|
.hoverEffect(.lift)
|
|
#else
|
|
.buttonStyle(.plain)
|
|
#endif
|
|
.disabled(history.undoDisabled)
|
|
Button {
|
|
history.historyPublisher.send(.redo)
|
|
} label: {
|
|
Image(systemName: "arrow.uturn.forward.circle")
|
|
.frame(width: size, height: size)
|
|
.contentShape(.rect(cornerRadius: 8))
|
|
}
|
|
#if os(iOS)
|
|
.hoverEffect(.lift)
|
|
#else
|
|
.buttonStyle(.plain)
|
|
#endif
|
|
.disabled(history.redoDisabled)
|
|
}
|
|
.background(.regularMaterial)
|
|
.clipShape(.rect(cornerRadius: 8))
|
|
.disabled(textFieldState)
|
|
.transition(.move(edge: .top).combined(with: .blurReplace))
|
|
}
|
|
|
|
private var gridModeControl: some View {
|
|
#if os(macOS)
|
|
Button {
|
|
canvas.toggleGridMode()
|
|
} label: {
|
|
Image(systemName: canvas.gridMode.icon)
|
|
.frame(width: size, height: size)
|
|
.background(.regularMaterial)
|
|
.clipShape(.rect(cornerRadius: 8))
|
|
.contentShape(.rect(cornerRadius: 8))
|
|
}
|
|
.buttonStyle(.plain)
|
|
.contentTransition(.symbolEffect(.replace))
|
|
.transition(.move(edge: .top).combined(with: .blurReplace))
|
|
#else
|
|
Menu {
|
|
ForEach(GridMode.all, id: \.self) { mode in
|
|
Button {
|
|
canvas.setGridMode(mode)
|
|
} label: {
|
|
Label {
|
|
Text(mode.title)
|
|
} icon: {
|
|
Image(systemName: mode.icon)
|
|
}
|
|
.font(.headline)
|
|
}
|
|
}
|
|
} label: {
|
|
Image(systemName: canvas.gridMode.icon)
|
|
.frame(width: size, height: size)
|
|
.background(.regularMaterial)
|
|
.clipShape(.rect(cornerRadius: 8))
|
|
.contentShape(.rect(cornerRadius: 8))
|
|
}
|
|
.hoverEffect(.lift)
|
|
.contentTransition(.symbolEffect(.replace))
|
|
.transition(.move(edge: .top).combined(with: .blurReplace))
|
|
#endif
|
|
}
|
|
|
|
private func closeMemo() {
|
|
canvas.save(for: memo) {
|
|
#if os(macOS)
|
|
application.closeMemo()
|
|
#else
|
|
dismiss()
|
|
#endif
|
|
}
|
|
}
|
|
}
|