mirror of
https://github.com/dscyrescotti/Memola.git
synced 2026-04-20 15:51:34 +02:00
bug: fix color picker clipped by frame
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user