diff --git a/docs/assets/examples/action_bar.png b/docs/assets/examples/action_bar.png
new file mode 100644
index 00000000..601dce17
Binary files /dev/null and b/docs/assets/examples/action_bar.png differ
diff --git a/docs/widgets.md b/docs/widgets.md
index 37e6b7fa..a9e9f31d 100644
--- a/docs/widgets.md
+++ b/docs/widgets.md
@@ -143,6 +143,7 @@ renderable CenterBox of BaseWidget
- `endWidget: Widget`
- `baselinePosition: BaselinePosition = BaselineCenter`
- `shrinkCenterLast: bool = false` Requires GTK 4.12 or higher to work. Compile with `-d:gtkminor=12` to enable it
+- `orient: Orient = OrientX`
###### Adders
@@ -1625,6 +1626,30 @@ A progress bar widget to show progress being made on a long-lasting task
- `text: string = ""`
+## ActionBar
+
+```nim
+renderable ActionBar of BaseWidget
+```
+
+A Bar for actions to execute in a given context. Can be hidden with intro- and outro-animations.
+
+###### Fields
+
+- All fields from [BaseWidget](#BaseWidget)
+- `centerWidget: Widget`
+- `packStart: seq[Widget]` Widgets shown on the start of the ActionBar
+- `packEnd: seq[Widget]` Widgets shown on the end of the ActionBar
+- `revealed: bool`
+
+###### Adders
+
+- All adders from [BaseWidget](#BaseWidget)
+- `add`
+- `addStart`
+- `addEnd`
+
+
## ListView
```nim
diff --git a/examples/README.md b/examples/README.md
index 5e93dfbc..441a27c6 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -123,6 +123,10 @@ The `widgets` directory contains examples for how to use different widgets.
Name |
Image |
+
+ Action Bar |
+ |
+
Calendar |
|
diff --git a/examples/widgets/action_bar.nim b/examples/widgets/action_bar.nim
new file mode 100644
index 00000000..6d18ba65
--- /dev/null
+++ b/examples/widgets/action_bar.nim
@@ -0,0 +1,72 @@
+# MIT License
+#
+# Copyright (c) 2022 Can Joshua Lehmann
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import std/[sequtils]
+import owlkettle, owlkettle/[dataentries, playground, adw]
+
+viewable App:
+ revealed: bool = false
+ sensitive: bool = true
+ tooltip: string = ""
+ sizeRequest: tuple[x, y: int] = (-1, -1)
+
+ dummyText: string = "Some Data"
+
+method view(app: AppState): Widget =
+ result = gui:
+ Window():
+ title = "ActionBar Example"
+ defaultSize = (400, 200)
+ HeaderBar() {.addTitlebar.}:
+ insert(app.toAutoFormMenu(ignoreFields = @["dummyText"], sizeRequest = (400, 300))) {.addRight.}
+
+ Button(text = "Reset") {.addRight.}:
+ style = [ButtonFlat]
+ proc clicked() =
+ app.dummyText = "Some Data"
+
+ Box(orient = OrientY):
+ Button(text = app.dummyText):
+ style = [ButtonFlat]
+ proc clicked() = app.revealed = not app.revealed
+
+ Separator() {.expand: false.}
+ ActionBar {.expand: false.}:
+ revealed = app.revealed
+ sensitive = app.sensitive
+ tooltip = app.tooltip
+ sizeRequest = app.sizeRequest
+
+ Label(text = "Delete Dataset?")
+ Button(icon = "process-stop-symbolic") {.addEnd.}:
+ proc clicked() =
+ echo "Keep Dataset"
+ app.revealed = false
+
+ Button(icon = "user-trash-symbolic", style = [ButtonDestructive]) {.addEnd.}:
+ style = [ButtonDestructive]
+ proc clicked() =
+ echo "Delete Dataset"
+ app.dummyText = ""
+ app.revealed = false
+
+adw.brew(gui(App()))
diff --git a/examples/widgets/center_box.nim b/examples/widgets/center_box.nim
index 2948c637..24046b68 100644
--- a/examples/widgets/center_box.nim
+++ b/examples/widgets/center_box.nim
@@ -26,11 +26,13 @@ import owlkettle, owlkettle/[dataentries, playground, adw]
viewable App:
baselinePosition: BaselinePosition = BaselineCenter
shrinkCenterLast: bool = false
- addStartWidget: bool = true
- addEndWidget: bool = true
+ orient: Orient = OrientX
sensitive: bool = true
tooltip: string = ""
sizeRequest: tuple[x, y: int] = (-1, -1)
+
+ addStartWidget: bool = true
+ addEndWidget: bool = true
method view(app: AppState): Widget =
result = gui:
@@ -46,7 +48,7 @@ method view(app: AppState): Widget =
sensitive = app.sensitive
tooltip = app.tooltip
sizeRequest = app.sizeRequest
-
+ orient = app.orient
if app.addStartWidget:
Label(text = "Start of CenterBox") {.addStart.}
diff --git a/owlkettle/gtk.nim b/owlkettle/gtk.nim
index ff4307ea..980b1a03 100644
--- a/owlkettle/gtk.nim
+++ b/owlkettle/gtk.nim
@@ -667,6 +667,15 @@ proc gtk_window_close*(window: GtkWidget)
proc gtk_window_destroy*(window: GtkWidget)
proc gtk_window_set_icon_name*(window: GtkWidget, name: cstring)
+# Gtk.ActionBar
+proc gtk_action_bar_new*(): GtkWidget
+proc gtk_action_bar_get_revealed*(widget: GtkWidget): cbool
+proc gtk_action_bar_pack_end*(widget: GtkWidget, child: GtkWidget)
+proc gtk_action_bar_pack_start*(widget: GtkWidget, child: GtkWidget)
+proc gtk_action_bar_remove*(widget: GtkWidget, child: GtkWidget)
+proc gtk_action_bar_set_center_widget*(widget: GtkWidget, center_widget: GtkWidget)
+proc gtk_action_bar_set_revealed*(widget: GtkWidget, revealed: cbool)
+
# Gtk.Button
proc gtk_button_new*(): GtkWidget
proc gtk_button_new_with_label*(label: cstring): GtkWidget
diff --git a/owlkettle/widgets.nim b/owlkettle/widgets.nim
index 3340e017..b7822855 100644
--- a/owlkettle/widgets.nim
+++ b/owlkettle/widgets.nim
@@ -331,6 +331,7 @@ renderable CenterBox of BaseWidget:
endWidget: Widget
baselinePosition: BaselinePosition = BaselineCenter
shrinkCenterLast: bool = false ## Requires GTK 4.12 or higher to work. Compile with `-d:gtkminor=12` to enable it
+ orient: Orient = OrientX
hooks:
beforeBuild:
@@ -357,6 +358,10 @@ renderable CenterBox of BaseWidget:
when GtkMinor >= 12:
gtk_center_box_set_shrink_center_last(state.internalWidget, state.shrinkCenterLast.cbool)
+ hooks orient:
+ property:
+ gtk_orientable_set_orientation(state.internalWidget, state.orient.toGtk())
+
adder addStart:
if widget.hasStartWidget:
raise newException(ValueError, "Unable to add multiple children to the start of CenterBox.")
@@ -3985,6 +3990,46 @@ renderable ProgressBar of BaseWidget:
property:
gtk_progress_bar_set_text(state.internalWidget, state.text.cstring)
+renderable ActionBar of BaseWidget:
+ ## A Bar for actions to execute in a given context. Can be hidden with intro- and outro-animations.
+ centerWidget: Widget
+ packStart: seq[Widget] ## Widgets shown on the start of the ActionBar
+ packEnd: seq[Widget] ## Widgets shown on the end of the ActionBar
+ revealed: bool
+
+ hooks:
+ beforeBuild:
+ state.internalWidget = gtk_action_bar_new()
+
+ hooks centerWidget:
+ (build, update):
+ state.updateChild(state.centerWidget, widget.valCenterWidget, gtk_action_bar_set_center_widget)
+
+ hooks packStart:
+ (build, update):
+ state.updateChildren(state.packStart, widget.valPackStart, gtk_action_bar_pack_start, gtk_action_bar_remove)
+
+ hooks packEnd:
+ (build, update):
+ state.updateChildren(state.packEnd, widget.valPackEnd, gtk_action_bar_pack_end, gtk_action_bar_remove)
+
+ hooks revealed:
+ property:
+ gtk_action_bar_set_revealed(state.internalWidget, state.revealed.cbool)
+
+ adder add:
+ if widget.hasCenterWidget:
+ raise newException(ValueError, "Unable to add multiple children as center widget of ActionBar. Add them to the start or end via {.addStart.} or {.addEnd.}.")
+ widget.hasCenterWidget = true
+ widget.valCenterWidget = child
+
+ adder addStart:
+ widget.hasPackStart = true
+ widget.valPackStart.add(child)
+
+ adder addEnd:
+ widget.hasPackEnd = true
+ widget.valPackEnd.add(child)
const
ListViewRichList* = StyleClass("rich-list")
ListViewNavigationSidebar* = StyleClass("navigation-sidebar")
@@ -4166,3 +4211,4 @@ export EmojiChooser
export PasswordEntry
export CenterBox
export ListView
+export ActionBar
\ No newline at end of file