forked from aparoksha/adwaita-swift
Add support for AdwBreakpointBin
This commit is contained in:
parent
016425e329
commit
963a02b1e1
@ -267,4 +267,36 @@ extension AnyView {
|
|||||||
.action(button: button, handler: handler)
|
.action(button: button, handler: handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a breakpoint.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - maxWidth: The maximum width.
|
||||||
|
/// - matches: Whether the content view matches the breakpoint.
|
||||||
|
public func breakpoint(maxWidth: Int, matches: Binding<Bool>) -> AnyView {
|
||||||
|
BreakpointBin(condition: .maxWidth(maxWidth), matches: matches) { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a breakpoint.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - minWidth: The minimum width.
|
||||||
|
/// - matches: Whether the content view matches the breakpoint.
|
||||||
|
public func breakpoint(minWidth: Int, matches: Binding<Bool>) -> AnyView {
|
||||||
|
BreakpointBin(condition: .minWidth(minWidth), matches: matches) { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a breakpoint.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - maxHeight: The maximum height.
|
||||||
|
/// - matches: Whether the content view matches the breakpoint.
|
||||||
|
public func breakpoint(maxHeight: Int, matches: Binding<Bool>) -> AnyView {
|
||||||
|
BreakpointBin(condition: .maxHeight(maxHeight), matches: matches) { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a breakpoint.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - minHeight: The minimum height.
|
||||||
|
/// - matches: Whether the content view matches the breakpoint.
|
||||||
|
public func breakpoint(minHeight: Int, matches: Binding<Bool>) -> AnyView {
|
||||||
|
BreakpointBin(condition: .minHeight(minHeight), matches: matches) { self }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,3 +52,11 @@ gtui_alertdialog_choose (uint64_t dialog, uint64_t data, uint64_t parent)
|
|||||||
adw_alert_dialog_choose (dialog, parent, NULL, gtui_alertdialog_cb, data);
|
adw_alert_dialog_choose (dialog, parent, NULL, gtui_alertdialog_cb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GValue
|
||||||
|
gtui_initialize_boolean (gboolean boolean)
|
||||||
|
{
|
||||||
|
GValue val = G_VALUE_INIT;
|
||||||
|
g_value_init(&val, G_TYPE_BOOLEAN);
|
||||||
|
g_value_set_boolean(&val, boolean);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
// Created by david-swift on 15.01.24.
|
// Created by david-swift on 15.01.24.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import CAdw
|
||||||
|
|
||||||
extension Bool {
|
extension Bool {
|
||||||
|
|
||||||
/// Get the gboolean for C.
|
/// Get the gboolean for C.
|
||||||
@ -12,4 +14,11 @@ extension Bool {
|
|||||||
self ? 1 : 0
|
self ? 1 : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The gboolean as a GValue.
|
||||||
|
public var gValue: UnsafePointer<GValue> {
|
||||||
|
let pointer = UnsafeMutablePointer<GValue>.allocate(capacity: 1)
|
||||||
|
pointer.initialize(to: gtui_initialize_boolean(cBool))
|
||||||
|
return .init(pointer)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
115
Sources/Core/View/BreakpointBin.swift
Normal file
115
Sources/Core/View/BreakpointBin.swift
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
//
|
||||||
|
// BreakpointBin.swift
|
||||||
|
// Adwaita
|
||||||
|
//
|
||||||
|
// Created by david-swift on 21.10.24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import CAdw
|
||||||
|
import Meta
|
||||||
|
|
||||||
|
/// Bind a dimension's to observe whether the child view matches a condition.
|
||||||
|
public struct BreakpointBin: AdwaitaWidget {
|
||||||
|
|
||||||
|
/// The child view.
|
||||||
|
@ViewProperty(
|
||||||
|
set: { bin, view in
|
||||||
|
var width: Int32 = 0
|
||||||
|
var height: Int32 = 0
|
||||||
|
gtk_widget_measure(view.cast(), GTK_ORIENTATION_VERTICAL, -1, &height, nil, nil, nil)
|
||||||
|
gtk_widget_measure(view.cast(), GTK_ORIENTATION_HORIZONTAL, -1, &width, nil, nil, nil)
|
||||||
|
gtk_widget_set_size_request(bin.cast(), width, height)
|
||||||
|
adw_breakpoint_bin_set_child(bin.cast(), view.cast())
|
||||||
|
},
|
||||||
|
pointer: OpaquePointer.self,
|
||||||
|
subview: OpaquePointer.self,
|
||||||
|
context: AdwaitaMainView.self
|
||||||
|
)
|
||||||
|
var content
|
||||||
|
|
||||||
|
/// The condition.
|
||||||
|
@Property(
|
||||||
|
set: { bin, condition, storage in
|
||||||
|
let condition = 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)
|
||||||
|
} else {
|
||||||
|
let breakpoint = adw_breakpoint_new(condition)
|
||||||
|
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(
|
||||||
|
breakpoint,
|
||||||
|
bin.opaquePointer?.cast(),
|
||||||
|
"visible",
|
||||||
|
false.gValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pointer: OpaquePointer.self
|
||||||
|
)
|
||||||
|
var condition: BreakpointCondition = .maxWidth(0)
|
||||||
|
|
||||||
|
/// Whether the child view does not match the condition.
|
||||||
|
@BindingProperty(
|
||||||
|
observe: { bin, matches, storage in
|
||||||
|
storage.notify(name: "current-breakpoint") {
|
||||||
|
matches.wrappedValue = adw_breakpoint_bin_get_current_breakpoint(bin.cast()) != nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set: { _, _, _ in },
|
||||||
|
pointer: OpaquePointer.self
|
||||||
|
)
|
||||||
|
var matches: Binding<Bool> = .constant(false)
|
||||||
|
|
||||||
|
/// Initialize a breakpoint bin.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - condition: The condition.
|
||||||
|
/// - matches: Whether the content matches the condition.
|
||||||
|
/// - content: The content.
|
||||||
|
public init(
|
||||||
|
condition: BreakpointCondition,
|
||||||
|
matches: Binding<Bool>,
|
||||||
|
@ViewBuilder content: () -> Body
|
||||||
|
) {
|
||||||
|
self.condition = condition
|
||||||
|
self.matches = matches
|
||||||
|
self.content = content()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize the widget.
|
||||||
|
public func initializeWidget() -> Any {
|
||||||
|
adw_breakpoint_bin_new()?.opaque() as Any
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A breakpoint condition.
|
||||||
|
public enum BreakpointCondition: Equatable {
|
||||||
|
|
||||||
|
/// Define a maximum width.
|
||||||
|
case maxWidth(_ width: Int)
|
||||||
|
/// Define a maximum height.
|
||||||
|
case maxHeight(_ height: Int)
|
||||||
|
/// Define a minimum width.
|
||||||
|
case minWidth(_ width: Int)
|
||||||
|
/// Define a minimum height.
|
||||||
|
case minHeight(_ height: Int)
|
||||||
|
|
||||||
|
/// The condition to parse.
|
||||||
|
var condition: String {
|
||||||
|
switch self {
|
||||||
|
case let .maxWidth(width):
|
||||||
|
"max-width: \(width)sp"
|
||||||
|
case let .maxHeight(height):
|
||||||
|
"max-height: \(height)sp"
|
||||||
|
case let .minWidth(width):
|
||||||
|
"min-width: \(width)sp"
|
||||||
|
case let .minHeight(height):
|
||||||
|
"min-height: \(height)sp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -43,7 +43,6 @@ struct Demo: App {
|
|||||||
}
|
}
|
||||||
.closeShortcut()
|
.closeShortcut()
|
||||||
.defaultSize(width: 600, height: 400)
|
.defaultSize(width: 600, height: 400)
|
||||||
.resizable(false)
|
|
||||||
.title("View Switcher Demo")
|
.title("View Switcher Demo")
|
||||||
Window(id: "form-demo", open: 0) { _ in
|
Window(id: "form-demo", open: 0) { _ in
|
||||||
FormDemo.WindowContent()
|
FormDemo.WindowContent()
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
// swiftlint:disable missing_docs
|
// swiftlint:disable missing_docs
|
||||||
|
|
||||||
import Adwaita
|
import Adwaita
|
||||||
|
import CAdw
|
||||||
|
|
||||||
struct ViewSwitcherDemo: View {
|
struct ViewSwitcherDemo: View {
|
||||||
|
|
||||||
@ -33,10 +34,6 @@ struct ViewSwitcherDemo: View {
|
|||||||
VStack {
|
VStack {
|
||||||
Text(selection.title)
|
Text(selection.title)
|
||||||
.padding()
|
.padding()
|
||||||
Button(bottom ? "Show Top Bar" : "Show Bottom Bar") {
|
|
||||||
bottom.toggle()
|
|
||||||
}
|
|
||||||
.halign(.center)
|
|
||||||
}
|
}
|
||||||
.valign(.center)
|
.valign(.center)
|
||||||
.topToolbar {
|
.topToolbar {
|
||||||
@ -44,15 +41,16 @@ struct ViewSwitcherDemo: View {
|
|||||||
HeaderBar
|
HeaderBar
|
||||||
.empty()
|
.empty()
|
||||||
} else {
|
} else {
|
||||||
toolbar
|
toolbar(bottom: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.bottomToolbar(visible: bottom) {
|
.bottomToolbar(visible: bottom) {
|
||||||
toolbar
|
toolbar(bottom: true)
|
||||||
}
|
}
|
||||||
|
.breakpoint(maxWidth: 600, matches: $bottom)
|
||||||
}
|
}
|
||||||
|
|
||||||
var toolbar: AnyView {
|
func toolbar(bottom: Bool) -> AnyView {
|
||||||
HeaderBar(titleButtons: !bottom) { } end: { }
|
HeaderBar(titleButtons: !bottom) { } end: { }
|
||||||
.headerBarTitle {
|
.headerBarTitle {
|
||||||
ViewSwitcher(selectedElement: $selection)
|
ViewSwitcher(selectedElement: $selection)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user