mirror of
https://github.com/dscyrescotti/Memola.git
synced 2026-07-10 06:42:43 +02:00
feat: add duplicate and remove button
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
EC0D14212BF79C73009BFE5F /* ToolObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14202BF79C73009BFE5F /* ToolObject.swift */; };
|
EC0D14212BF79C73009BFE5F /* ToolObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14202BF79C73009BFE5F /* ToolObject.swift */; };
|
||||||
EC0D14242BF79C98009BFE5F /* MemolaModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14222BF79C98009BFE5F /* MemolaModel.xcdatamodeld */; };
|
EC0D14242BF79C98009BFE5F /* MemolaModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14222BF79C98009BFE5F /* MemolaModel.xcdatamodeld */; };
|
||||||
EC0D14262BF7A8C9009BFE5F /* PenObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14252BF7A8C9009BFE5F /* PenObject.swift */; };
|
EC0D14262BF7A8C9009BFE5F /* PenObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14252BF7A8C9009BFE5F /* PenObject.swift */; };
|
||||||
EC0D14282BF7BF20009BFE5F /* ContextMenuableViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14272BF7BF20009BFE5F /* ContextMenuableViewModifier.swift */; };
|
EC0D14282BF7BF20009BFE5F /* ContextMenuViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14272BF7BF20009BFE5F /* ContextMenuViewModifier.swift */; };
|
||||||
EC3565522BEFC65F00A4E0BF /* NSManagedObjectContext++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3565512BEFC65F00A4E0BF /* NSManagedObjectContext++.swift */; };
|
EC3565522BEFC65F00A4E0BF /* NSManagedObjectContext++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3565512BEFC65F00A4E0BF /* NSManagedObjectContext++.swift */; };
|
||||||
EC3565542BEFC6AD00A4E0BF /* View++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3565532BEFC6AD00A4E0BF /* View++.swift */; };
|
EC3565542BEFC6AD00A4E0BF /* View++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3565532BEFC6AD00A4E0BF /* View++.swift */; };
|
||||||
EC3565562BEFC7B300A4E0BF /* NSManagedObject++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3565552BEFC7B300A4E0BF /* NSManagedObject++.swift */; };
|
EC3565562BEFC7B300A4E0BF /* NSManagedObject++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3565552BEFC7B300A4E0BF /* NSManagedObject++.swift */; };
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
EC35655C2BF0712A00A4E0BF /* Float++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC35655B2BF0712A00A4E0BF /* Float++.swift */; };
|
EC35655C2BF0712A00A4E0BF /* Float++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC35655B2BF0712A00A4E0BF /* Float++.swift */; };
|
||||||
EC4538892BEBCAE000A86FEC /* Quad.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC4538882BEBCAE000A86FEC /* Quad.swift */; };
|
EC4538892BEBCAE000A86FEC /* Quad.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC4538882BEBCAE000A86FEC /* Quad.swift */; };
|
||||||
EC5050072BF65CED00B4D86E /* PenDropDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC5050062BF65CED00B4D86E /* PenDropDelegate.swift */; };
|
EC5050072BF65CED00B4D86E /* PenDropDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC5050062BF65CED00B4D86E /* PenDropDelegate.swift */; };
|
||||||
EC50500D2BF6674400B4D86E /* DraggableViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC50500C2BF6674400B4D86E /* DraggableViewModifier.swift */; };
|
EC50500D2BF6674400B4D86E /* OnDragViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC50500C2BF6674400B4D86E /* OnDragViewModifier.swift */; };
|
||||||
EC7F6BEC2BE5E6E300A34A7B /* MemolaApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7F6BEB2BE5E6E300A34A7B /* MemolaApp.swift */; };
|
EC7F6BEC2BE5E6E300A34A7B /* MemolaApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7F6BEB2BE5E6E300A34A7B /* MemolaApp.swift */; };
|
||||||
EC7F6BF02BE5E6E400A34A7B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC7F6BEF2BE5E6E400A34A7B /* Assets.xcassets */; };
|
EC7F6BF02BE5E6E400A34A7B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC7F6BEF2BE5E6E400A34A7B /* Assets.xcassets */; };
|
||||||
EC7F6BF32BE5E6E400A34A7B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC7F6BF22BE5E6E400A34A7B /* Preview Assets.xcassets */; };
|
EC7F6BF32BE5E6E400A34A7B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC7F6BF22BE5E6E400A34A7B /* Preview Assets.xcassets */; };
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
EC0D14202BF79C73009BFE5F /* ToolObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolObject.swift; sourceTree = "<group>"; };
|
EC0D14202BF79C73009BFE5F /* ToolObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolObject.swift; sourceTree = "<group>"; };
|
||||||
EC0D14232BF79C98009BFE5F /* MemolaModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MemolaModel.xcdatamodel; sourceTree = "<group>"; };
|
EC0D14232BF79C98009BFE5F /* MemolaModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MemolaModel.xcdatamodel; sourceTree = "<group>"; };
|
||||||
EC0D14252BF7A8C9009BFE5F /* PenObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenObject.swift; sourceTree = "<group>"; };
|
EC0D14252BF7A8C9009BFE5F /* PenObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenObject.swift; sourceTree = "<group>"; };
|
||||||
EC0D14272BF7BF20009BFE5F /* ContextMenuableViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuableViewModifier.swift; sourceTree = "<group>"; };
|
EC0D14272BF7BF20009BFE5F /* ContextMenuViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuViewModifier.swift; sourceTree = "<group>"; };
|
||||||
EC3565512BEFC65F00A4E0BF /* NSManagedObjectContext++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext++.swift"; sourceTree = "<group>"; };
|
EC3565512BEFC65F00A4E0BF /* NSManagedObjectContext++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext++.swift"; sourceTree = "<group>"; };
|
||||||
EC3565532BEFC6AD00A4E0BF /* View++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View++.swift"; sourceTree = "<group>"; };
|
EC3565532BEFC6AD00A4E0BF /* View++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View++.swift"; sourceTree = "<group>"; };
|
||||||
EC3565552BEFC7B300A4E0BF /* NSManagedObject++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObject++.swift"; sourceTree = "<group>"; };
|
EC3565552BEFC7B300A4E0BF /* NSManagedObject++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObject++.swift"; sourceTree = "<group>"; };
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
EC35655B2BF0712A00A4E0BF /* Float++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Float++.swift"; sourceTree = "<group>"; };
|
EC35655B2BF0712A00A4E0BF /* Float++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Float++.swift"; sourceTree = "<group>"; };
|
||||||
EC4538882BEBCAE000A86FEC /* Quad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Quad.swift; sourceTree = "<group>"; };
|
EC4538882BEBCAE000A86FEC /* Quad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Quad.swift; sourceTree = "<group>"; };
|
||||||
EC5050062BF65CED00B4D86E /* PenDropDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenDropDelegate.swift; sourceTree = "<group>"; };
|
EC5050062BF65CED00B4D86E /* PenDropDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenDropDelegate.swift; sourceTree = "<group>"; };
|
||||||
EC50500C2BF6674400B4D86E /* DraggableViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableViewModifier.swift; sourceTree = "<group>"; };
|
EC50500C2BF6674400B4D86E /* OnDragViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnDragViewModifier.swift; sourceTree = "<group>"; };
|
||||||
EC50500E2BF670EA00B4D86E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
EC50500E2BF670EA00B4D86E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
EC7F6BE82BE5E6E300A34A7B /* Memola.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Memola.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
EC7F6BE82BE5E6E300A34A7B /* Memola.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Memola.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EC7F6BEB2BE5E6E300A34A7B /* MemolaApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemolaApp.swift; sourceTree = "<group>"; };
|
EC7F6BEB2BE5E6E300A34A7B /* MemolaApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemolaApp.swift; sourceTree = "<group>"; };
|
||||||
@@ -233,8 +233,8 @@
|
|||||||
EC50500B2BF6673300B4D86E /* ViewModifiers */ = {
|
EC50500B2BF6673300B4D86E /* ViewModifiers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
EC50500C2BF6674400B4D86E /* DraggableViewModifier.swift */,
|
EC50500C2BF6674400B4D86E /* OnDragViewModifier.swift */,
|
||||||
EC0D14272BF7BF20009BFE5F /* ContextMenuableViewModifier.swift */,
|
EC0D14272BF7BF20009BFE5F /* ContextMenuViewModifier.swift */,
|
||||||
);
|
);
|
||||||
path = ViewModifiers;
|
path = ViewModifiers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -721,7 +721,7 @@
|
|||||||
ECA738C92BE60EF700A4542E /* GraphicContext.swift in Sources */,
|
ECA738C92BE60EF700A4542E /* GraphicContext.swift in Sources */,
|
||||||
ECA738F62BE612B700A4542E /* MTLDevice++.swift in Sources */,
|
ECA738F62BE612B700A4542E /* MTLDevice++.swift in Sources */,
|
||||||
EC0D14212BF79C73009BFE5F /* ToolObject.swift in Sources */,
|
EC0D14212BF79C73009BFE5F /* ToolObject.swift in Sources */,
|
||||||
EC50500D2BF6674400B4D86E /* DraggableViewModifier.swift in Sources */,
|
EC50500D2BF6674400B4D86E /* OnDragViewModifier.swift in Sources */,
|
||||||
ECA7389E2BE601CB00A4542E /* QuadVertex.swift in Sources */,
|
ECA7389E2BE601CB00A4542E /* QuadVertex.swift in Sources */,
|
||||||
ECA738B32BE60D9E00A4542E /* CanvasView.swift in Sources */,
|
ECA738B32BE60D9E00A4542E /* CanvasView.swift in Sources */,
|
||||||
ECA738C42BE60E8800A4542E /* MarkerPenStyle.swift in Sources */,
|
ECA738C42BE60E8800A4542E /* MarkerPenStyle.swift in Sources */,
|
||||||
@@ -737,7 +737,7 @@
|
|||||||
ECA738DE2BE610A000A4542E /* ViewPortRenderPass.swift in Sources */,
|
ECA738DE2BE610A000A4542E /* ViewPortRenderPass.swift in Sources */,
|
||||||
EC7F6BEC2BE5E6E300A34A7B /* MemolaApp.swift in Sources */,
|
EC7F6BEC2BE5E6E300A34A7B /* MemolaApp.swift in Sources */,
|
||||||
ECA738A02BE601E400A4542E /* ViewPortVertex.swift in Sources */,
|
ECA738A02BE601E400A4542E /* ViewPortVertex.swift in Sources */,
|
||||||
EC0D14282BF7BF20009BFE5F /* ContextMenuableViewModifier.swift in Sources */,
|
EC0D14282BF7BF20009BFE5F /* ContextMenuViewModifier.swift in Sources */,
|
||||||
ECA738BC2BE60E0300A4542E /* Tool.swift in Sources */,
|
ECA738BC2BE60E0300A4542E /* Tool.swift in Sources */,
|
||||||
ECA738972BE6014200A4542E /* Graphic.metal in Sources */,
|
ECA738972BE6014200A4542E /* Graphic.metal in Sources */,
|
||||||
ECA7388A2BE6006A00A4542E /* PipelineStates.swift in Sources */,
|
ECA7388A2BE6006A00A4542E /* PipelineStates.swift in Sources */,
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ public class Tool: NSObject, ObservableObject {
|
|||||||
@Published var pens: [Pen] = []
|
@Published var pens: [Pen] = []
|
||||||
@Published var selectedPen: Pen?
|
@Published var selectedPen: Pen?
|
||||||
@Published var draggedPen: Pen?
|
@Published var draggedPen: Pen?
|
||||||
@Published var isReordering: Bool = false
|
|
||||||
@Published var isShaking: Bool = false
|
|
||||||
@Published var shakingId: UUID = UUID()
|
|
||||||
|
|
||||||
let scrollPublisher = PassthroughSubject<String, Never>()
|
let scrollPublisher = PassthroughSubject<String, Never>()
|
||||||
|
|
||||||
@@ -47,6 +44,9 @@ public class Tool: NSObject, ObservableObject {
|
|||||||
selectedPen = pen
|
selectedPen = pen
|
||||||
}
|
}
|
||||||
selectedPen?.isSelected = true
|
selectedPen?.isSelected = true
|
||||||
|
withPersistence(\.viewContext) { context in
|
||||||
|
try context.saveIfNeeded()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func unselectPen(_ pen: Pen) {
|
func unselectPen(_ pen: Pen) {
|
||||||
@@ -54,6 +54,23 @@ public class Tool: NSObject, ObservableObject {
|
|||||||
withAnimation {
|
withAnimation {
|
||||||
selectedPen = nil
|
selectedPen = nil
|
||||||
}
|
}
|
||||||
|
withPersistence(\.viewContext) { context in
|
||||||
|
try context.saveIfNeeded()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func duplicatePen(_ pen: Pen, of originalPen: Pen) {
|
||||||
|
guard let index = pens.firstIndex(where: { originalPen === $0 }) else { return }
|
||||||
|
withAnimation {
|
||||||
|
pens.insert(pen, at: index + 1)
|
||||||
|
}
|
||||||
|
selectPen(pen)
|
||||||
|
withPersistence(\.viewContext) { [pens] context in
|
||||||
|
for (index, pen) in pens.enumerated() {
|
||||||
|
pen.object?.orderIndex = Int16(index)
|
||||||
|
}
|
||||||
|
try context.saveIfNeeded()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addPen(_ pen: Pen) {
|
func addPen(_ pen: Pen) {
|
||||||
@@ -65,6 +82,9 @@ public class Tool: NSObject, ObservableObject {
|
|||||||
object.pens.add(_pen)
|
object.pens.add(_pen)
|
||||||
}
|
}
|
||||||
scrollPublisher.send(pen.id)
|
scrollPublisher.send(pen.id)
|
||||||
|
withPersistence(\.viewContext) { context in
|
||||||
|
try context.saveIfNeeded()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removePen(_ pen: Pen) {
|
func removePen(_ pen: Pen) {
|
||||||
@@ -76,5 +96,8 @@ public class Tool: NSObject, ObservableObject {
|
|||||||
_pen.tool = nil
|
_pen.tool = nil
|
||||||
object.pens.remove(_pen)
|
object.pens.remove(_pen)
|
||||||
}
|
}
|
||||||
|
withPersistence(\.viewContext) { context in
|
||||||
|
try context.saveIfNeeded()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// ContextMenuableViewModifier.swift
|
// ContextMenuViewModifier.swift
|
||||||
// Memola
|
// Memola
|
||||||
//
|
//
|
||||||
// Created by Dscyre Scotti on 5/17/24.
|
// Created by Dscyre Scotti on 5/17/24.
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct ContextMenuableViewModifier<MenuContent: View>: ViewModifier {
|
struct ContextMenuViewModifier<MenuContent: View>: ViewModifier {
|
||||||
let condition: Bool
|
let condition: Bool
|
||||||
let menuItems: () -> MenuContent
|
let menuItems: () -> MenuContent
|
||||||
|
|
||||||
@@ -24,6 +24,6 @@ struct ContextMenuableViewModifier<MenuContent: View>: ViewModifier {
|
|||||||
|
|
||||||
public extension View {
|
public extension View {
|
||||||
func contextMenu<MenuContent: View>(if condition: Bool, @ViewBuilder menuItems: @escaping () -> MenuContent) -> some View {
|
func contextMenu<MenuContent: View>(if condition: Bool, @ViewBuilder menuItems: @escaping () -> MenuContent) -> some View {
|
||||||
modifier(ContextMenuableViewModifier(condition: condition, menuItems: menuItems))
|
modifier(ContextMenuViewModifier(condition: condition, menuItems: menuItems))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// DraggableViewModifier.swift
|
// OnDragViewModifier.swift
|
||||||
// Memola
|
// Memola
|
||||||
//
|
//
|
||||||
// Created by Dscyre Scotti on 5/16/24.
|
// Created by Dscyre Scotti on 5/16/24.
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct DraggableViewModifier<Preview: View>: ViewModifier {
|
struct OnDragViewModifier<Preview: View>: ViewModifier {
|
||||||
let condition: Bool
|
let condition: Bool
|
||||||
let data: () -> NSItemProvider
|
let data: () -> NSItemProvider
|
||||||
let preview: () -> Preview
|
let preview: () -> Preview
|
||||||
@@ -25,6 +25,6 @@ struct DraggableViewModifier<Preview: View>: ViewModifier {
|
|||||||
|
|
||||||
public extension View {
|
public extension View {
|
||||||
func onDrag<Preview: View>(if condition: Bool, data: @escaping () -> NSItemProvider, @ViewBuilder preview: @escaping () -> Preview) -> some View {
|
func onDrag<Preview: View>(if condition: Bool, data: @escaping () -> NSItemProvider, @ViewBuilder preview: @escaping () -> Preview) -> some View {
|
||||||
modifier(DraggableViewModifier(condition: condition, data: data, preview: preview))
|
modifier(OnDragViewModifier(condition: condition, data: data, preview: preview))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,11 +27,11 @@ struct PenDropDelegate: DropDelegate {
|
|||||||
tool.pens.move(fromOffsets: IndexSet(integer: fromIndex), toOffset: toIndex > fromIndex ? toIndex + 1 : toIndex)
|
tool.pens.move(fromOffsets: IndexSet(integer: fromIndex), toOffset: toIndex > fromIndex ? toIndex + 1 : toIndex)
|
||||||
tool.objectWillChange.send()
|
tool.objectWillChange.send()
|
||||||
}
|
}
|
||||||
tool.shakingId = UUID()
|
|
||||||
withPersistence(\.viewContext) { context in
|
withPersistence(\.viewContext) { context in
|
||||||
for (index, pen) in tool.pens.enumerated() {
|
for (index, pen) in tool.pens.enumerated() {
|
||||||
pen.object?.orderIndex = Int16(index)
|
pen.object?.orderIndex = Int16(index)
|
||||||
}
|
}
|
||||||
|
try context.saveIfNeeded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,37 +17,14 @@ struct PenToolView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollViewReader { proxy in
|
ScrollViewReader { proxy in
|
||||||
ScrollView(.vertical, showsIndicators: false) {
|
ScrollView(.vertical, showsIndicators: false) {
|
||||||
if tool.isReordering {
|
LazyVStack(spacing: 0) {
|
||||||
LazyVStack(spacing: 0) {
|
ForEach(tool.pens) { pen in
|
||||||
ForEach(tool.pens) { pen in
|
penView(pen)
|
||||||
if pen.strokeStyle == .marker {
|
.id(pen.id)
|
||||||
penView(pen)
|
|
||||||
.offset(y: tool.isShaking ? 1.5 : -1.5)
|
|
||||||
.id(pen.id)
|
|
||||||
} else {
|
|
||||||
penView(pen)
|
|
||||||
.id(pen.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.padding(.vertical, 10)
|
|
||||||
.padding(.leading, 40)
|
|
||||||
.onAppear {
|
|
||||||
withAnimation(.easeInOut.repeatForever().speed(5)) {
|
|
||||||
tool.isShaking.toggle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.id(tool.shakingId)
|
|
||||||
} else {
|
|
||||||
LazyVStack(spacing: 0) {
|
|
||||||
ForEach(tool.pens) { pen in
|
|
||||||
penView(pen)
|
|
||||||
.id(pen.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.vertical, 10)
|
|
||||||
.padding(.leading, 40)
|
|
||||||
}
|
}
|
||||||
|
.padding(.vertical, 10)
|
||||||
|
.padding(.leading, 40)
|
||||||
}
|
}
|
||||||
.onReceive(tool.scrollPublisher) { id in
|
.onReceive(tool.scrollPublisher) { id in
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||||
@@ -68,14 +45,8 @@ struct PenToolView: View {
|
|||||||
}
|
}
|
||||||
.clipShape(.rect(cornerRadii: .init(bottomTrailing: 20, topTrailing: 20)))
|
.clipShape(.rect(cornerRadii: .init(bottomTrailing: 20, topTrailing: 20)))
|
||||||
.overlay(alignment: .bottomLeading) {
|
.overlay(alignment: .bottomLeading) {
|
||||||
Group {
|
newPenButton
|
||||||
if tool.isReordering {
|
.offset(x: 60, y: 10)
|
||||||
doneButton
|
|
||||||
} else {
|
|
||||||
newPenButton
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.offset(x: 60, y: 10)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,20 +73,34 @@ struct PenToolView: View {
|
|||||||
tool.selectPen(pen)
|
tool.selectPen(pen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.disabled(tool.isReordering)
|
.contextMenu(if: pen.strokeStyle != .eraser) {
|
||||||
.contextMenu(if: pen.strokeStyle != .eraser && !tool.isReordering) {
|
ControlGroup {
|
||||||
Button {
|
Button {
|
||||||
tool.isReordering = true
|
let originalPen = pen
|
||||||
} label: {
|
let pen = PenObject.createObject(\.viewContext, penStyle: originalPen.style)
|
||||||
Label("Rearrange", systemImage: "arrow.up.arrow.down.circle")
|
pen.color = originalPen.color
|
||||||
}
|
pen.isSelected = true
|
||||||
Button(role: .destructive) {
|
pen.tool = tool.object
|
||||||
tool.removePen(pen)
|
let _pen = Pen(object: pen)
|
||||||
} label: {
|
tool.duplicatePen(_pen, of: originalPen)
|
||||||
Label("Delete", systemImage: "trash")
|
} label: {
|
||||||
|
Label(
|
||||||
|
title: { Text("Duplicate") },
|
||||||
|
icon: { Image(systemName: "plus.square.on.square") }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Button(role: .destructive) {
|
||||||
|
tool.removePen(pen)
|
||||||
|
} label: {
|
||||||
|
Label(
|
||||||
|
title: { Text("Remove") },
|
||||||
|
icon: { Image(systemName: "trash") }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.controlGroupStyle(.menu)
|
||||||
}
|
}
|
||||||
.onDrag(if: pen.strokeStyle != .eraser && tool.isReordering) {
|
.onDrag(if: pen.strokeStyle != .eraser) {
|
||||||
tool.draggedPen = pen
|
tool.draggedPen = pen
|
||||||
return NSItemProvider(contentsOf: URL(string: pen.id)) ?? NSItemProvider()
|
return NSItemProvider(contentsOf: URL(string: pen.id)) ?? NSItemProvider()
|
||||||
} preview: {
|
} preview: {
|
||||||
@@ -149,22 +134,6 @@ struct PenToolView: View {
|
|||||||
.hoverEffect(.lift)
|
.hoverEffect(.lift)
|
||||||
}
|
}
|
||||||
|
|
||||||
var doneButton: some View {
|
|
||||||
Button {
|
|
||||||
tool.isReordering = false
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "xmark.circle")
|
|
||||||
.font(.title2)
|
|
||||||
.padding(1)
|
|
||||||
.contentShape(.circle)
|
|
||||||
.background {
|
|
||||||
Circle()
|
|
||||||
.fill(.white)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.hoverEffect(.lift)
|
|
||||||
}
|
|
||||||
|
|
||||||
func penPreview(_ pen: Pen) -> some View {
|
func penPreview(_ pen: Pen) -> some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
if let tip = pen.style.icon.tip {
|
if let tip = pen.style.icon.tip {
|
||||||
|
|||||||
Reference in New Issue
Block a user