From ced07e429366daa800a8ae20f791d7f566ff3c3e Mon Sep 17 00:00:00 2001 From: david-swift Date: Fri, 25 Oct 2024 14:02:45 +0200 Subject: [PATCH] Add support for natural sizes for breakpoints --- Sources/Adwaita/AnyView+.swift | 12 +++++++++++ Sources/Core/View/BreakpointBin.swift | 29 ++++++++++++++++++++++----- Sources/Demo/ViewSwitcherDemo.swift | 2 +- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/Sources/Adwaita/AnyView+.swift b/Sources/Adwaita/AnyView+.swift index c8efdb2..d3eac6d 100644 --- a/Sources/Adwaita/AnyView+.swift +++ b/Sources/Adwaita/AnyView+.swift @@ -299,4 +299,16 @@ extension AnyView { BreakpointBin(condition: .minHeight(minHeight), matches: matches) { self } } + /// Whether the view has a width higher or equal to its natural width. + /// - Parameter matches: Whether the content view matches the breakpoint. + public func naturalWidth(matches: Binding) -> AnyView { + BreakpointBin(condition: .naturalWidth, matches: matches) { self } + } + + /// Whether the view has a height higher or equal to its natural height. + /// - Parameter matches: Whether the content view matches the breakpoint. + public func naturalHeight(matches: Binding) -> AnyView { + BreakpointBin(condition: .naturalHeight, matches: matches) { self } + } + } diff --git a/Sources/Core/View/BreakpointBin.swift b/Sources/Core/View/BreakpointBin.swift index b090971..91a6e39 100644 --- a/Sources/Core/View/BreakpointBin.swift +++ b/Sources/Core/View/BreakpointBin.swift @@ -30,13 +30,26 @@ public struct BreakpointBin: AdwaitaWidget { /// The condition. @Property( set: { bin, condition, storage in - let condition = adw_breakpoint_condition_parse(condition.condition) + let string: OpaquePointer + switch condition { + case .naturalWidth: + let child = adw_breakpoint_bin_get_child(bin.cast()) + var size: Int32 = 0 + gtk_widget_measure(child, GTK_ORIENTATION_HORIZONTAL, -1, nil, &size, nil, nil) + string = adw_breakpoint_condition_parse(BreakpointCondition.minWidth(.init(size)).condition) + case .naturalHeight: + let child = adw_breakpoint_bin_get_child(bin.cast()) + var size: Int32 = 0 + gtk_widget_measure(child, GTK_ORIENTATION_VERTICAL, -1, nil, &size, nil, nil) + string = adw_breakpoint_condition_parse(BreakpointCondition.minHeight(.init(size)).condition) + default: + string = adw_breakpoint_condition_parse(condition.condition) + } if let breakpoint = storage.fields["breakpoint"] as? OpaquePointer { g_object_unref(adw_breakpoint_get_condition(breakpoint)?.cast()) - adw_breakpoint_set_condition(breakpoint, condition) + adw_breakpoint_set_condition(breakpoint, string) } else { - let breakpoint = adw_breakpoint_new(condition) - adw_breakpoint_bin_add_breakpoint(bin.cast(), breakpoint) + let breakpoint = adw_breakpoint_new(string); adw_breakpoint_bin_add_breakpoint(bin.cast(), breakpoint) storage.fields["breakpoint"] = breakpoint if let bin = storage.content["_content"]?.first?.content["append"]?.first { adw_breakpoint_add_setter( @@ -97,9 +110,13 @@ public enum BreakpointCondition: Equatable { case minWidth(_ width: Int) /// Define a minimum height. case minHeight(_ height: Int) + /// The minimum width is the content's natural width. + case naturalWidth + /// The minimum height is the content's natural height. + case naturalHeight /// The condition to parse. - var condition: String { + var condition: String? { switch self { case let .maxWidth(width): "max-width: \(width)sp" @@ -109,6 +126,8 @@ public enum BreakpointCondition: Equatable { "min-width: \(width)sp" case let .minHeight(height): "min-height: \(height)sp" + default: + nil } } diff --git a/Sources/Demo/ViewSwitcherDemo.swift b/Sources/Demo/ViewSwitcherDemo.swift index 38b60a3..3f81755 100644 --- a/Sources/Demo/ViewSwitcherDemo.swift +++ b/Sources/Demo/ViewSwitcherDemo.swift @@ -47,7 +47,7 @@ struct ViewSwitcherDemo: View { .bottomToolbar(visible: bottom) { toolbar(bottom: true) } - .breakpoint(maxWidth: 600, matches: $bottom) + .naturalWidth(matches: .init { !bottom } set: { bottom = !$0 }) } func toolbar(bottom: Bool) -> AnyView {