bug: fix color picker clipped by frame

This commit is contained in:
dscyrescotti
2024-11-26 02:47:30 +07:00
parent ba684a3459
commit b5287c0552
2 changed files with 90 additions and 12 deletions

View File

@@ -9,6 +9,8 @@ import SwiftUI
import Foundation import Foundation
struct ColorPicker: View { struct ColorPicker: View {
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
@State private var hue: Double = 1 @State private var hue: Double = 1
@State private var saturation: Double = 0 @State private var saturation: Double = 0
@State private var brightness: Double = 1 @State private var brightness: Double = 1
@@ -16,16 +18,32 @@ struct ColorPicker: View {
@Binding private var color: Color @Binding private var color: Color
private let size: CGFloat = 20 private let isCompact: Bool
private let boundSize: CGFloat
private let size: CGFloat = 25
init(color: Binding<Color>) { init(color: Binding<Color>, boundSize: CGFloat, isCompact: Bool = false) {
self._color = color self._color = color
self.isCompact = isCompact
self.boundSize = boundSize
} }
var body: some View { var body: some View {
VStack(spacing: 10) { #if os(macOS)
colorPicker
#else
if horizontalSizeClass == .regular {
colorPicker colorPicker
.frame(width: 200, height: 200) } else {
compactColorPicker
}
#endif
}
private var colorPicker: some View {
VStack(spacing: 10) {
colorPalette
.frame(width: boundSize, height: boundSize)
HStack(spacing: 10) { HStack(spacing: 10) {
hueSlider hueSlider
alphaSlider alphaSlider
@@ -47,7 +65,29 @@ struct ColorPicker: View {
} }
@ViewBuilder @ViewBuilder
private var colorPicker: some View { private var compactColorPicker: some View {
let padding: CGFloat = 30 + (isCompact ? size * 2 + 10 : 0)
VStack(spacing: 10) {
colorPalette
.frame(width: boundSize - padding, height: boundSize - padding)
HStack(spacing: 10) {
hueSlider
alphaSlider
}
}
.padding(15)
.padding(.top, 10)
.onAppear {
let hsba = color.hsba
hue = hsba.hue
saturation = hsba.saturation
brightness = hsba.brightness
alpha = hsba.alpha * 1.43 - 0.43
}
}
@ViewBuilder
private var colorPalette: some View {
GeometryReader { proxy in GeometryReader { proxy in
ZStack { ZStack {
Color(hue: hue, saturation: 1, brightness: 1) Color(hue: hue, saturation: 1, brightness: 1)

View File

@@ -67,7 +67,7 @@ struct PenDock: View {
compactPenItemList compactPenItemList
.fixedSize(horizontal: false, vertical: true) .fixedSize(horizontal: false, vertical: true)
HStack(spacing: 0) { HStack(spacing: 0) {
compactPenPropertyTool compactPenPropertyTool(bounds: proxy.frame(in: .global).size)
Divider() Divider()
.padding(.vertical, 4) .padding(.vertical, 4)
.frame(height: size) .frame(height: size)
@@ -360,9 +360,10 @@ struct PenDock: View {
@ViewBuilder @ViewBuilder
private var penPropertyTool: some View { private var penPropertyTool: some View {
if let pen = tool.selectedPen { if let pen = tool.selectedPen {
let size: CGFloat = 250
VStack(spacing: 5) { VStack(spacing: 5) {
if pen.strokeStyle == .marker { if pen.strokeStyle == .marker {
penColorPicker(pen) penColorPicker(pen, bounds: .init(width: size, height: size))
} }
penThicknessPicker(pen) penThicknessPicker(pen)
} }
@@ -379,14 +380,14 @@ struct PenDock: View {
} }
@ViewBuilder @ViewBuilder
private var compactPenPropertyTool: some View { private func compactPenPropertyTool(bounds: CGSize) -> some View {
if let pen = tool.selectedPen { if let pen = tool.selectedPen {
HStack(spacing: 8) { HStack(spacing: 8) {
penThicknessPicker(pen) penThicknessPicker(pen)
.frame(width: penPropertySize) .frame(width: penPropertySize)
.rotationEffect(.degrees(-90)) .rotationEffect(.degrees(-90))
if pen.strokeStyle == .marker { if pen.strokeStyle == .marker {
penColorPicker(pen) penColorPicker(pen, bounds: bounds)
.frame(width: penPropertySize) .frame(width: penPropertySize)
.transition(.move(edge: .trailing).combined(with: .opacity)) .transition(.move(edge: .trailing).combined(with: .opacity))
} }
@@ -395,7 +396,7 @@ struct PenDock: View {
} }
} }
private func penColorPicker(_ pen: Pen) -> some View { private func penColorPicker(_ pen: Pen, bounds: CGSize) -> some View {
Button { Button {
opensColorPicker = true opensColorPicker = true
} label: { } label: {
@@ -437,8 +438,45 @@ struct PenDock: View {
tool.objectWillChange.send() tool.objectWillChange.send()
} }
) )
ColorPicker(color: color) #if os(macOS)
.presentationCompactAdaptation(.popover) ColorPicker(color: color, boundSize: min(bounds.height, bounds.width))
.onDisappear {
withPersistence(\.viewContext) { context in
try context.saveIfNeeded()
}
}
#else
if horizontalSizeClass == .regular {
ColorPicker(color: color, boundSize: min(bounds.height, bounds.width))
.onDisappear {
withPersistence(\.viewContext) { context in
try context.saveIfNeeded()
}
}
} else {
compactColorPicker(color: color, bounds: bounds)
}
#endif
}
}
@ViewBuilder
func compactColorPicker(color: Binding<Color>, bounds: CGSize) -> some View {
let size = min(bounds.height, bounds.width)
if bounds.height > bounds.width {
ColorPicker(color: color, boundSize: size)
.presentationDetents([.height(size + 40)])
.presentationDragIndicator(.visible)
.onDisappear {
withPersistence(\.viewContext) { context in
try context.saveIfNeeded()
}
}
} else {
ColorPicker(color: color, boundSize: size, isCompact: true)
.presentationCompactAdaptation(.sheet)
.presentationDetents([.large])
.presentationDragIndicator(.visible)
.onDisappear { .onDisappear {
withPersistence(\.viewContext) { context in withPersistence(\.viewContext) { context in
try context.saveIfNeeded() try context.saveIfNeeded()