Skip to content

Commit 03f29dd

Browse files
authored
Finish Adwaita and GTK 4 override
This should nicely finish up the overrides for Adw and GTK 4, while also making sure to test them. This commit removes old GTK 3 tests, which are necessary to test GTK 4. As GTK 3 is obsolete, this is an easy choice to make. This commit also updates the GTK documentation to note the overridden behaviour, with examples.
1 parent cf95952 commit 03f29dd

File tree

10 files changed

+436
-435
lines changed

10 files changed

+436
-435
lines changed

.github/install_deps.bash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
set -x
22
sudo apt-get update -qq
3-
sudo apt-get install -y libgirepository1.0-dev libgirepository-2.0-dev libcairo2-dev gir1.2-gtk-4.0 libffi-dev libglib2.0-dev
3+
sudo apt-get install -y libgirepository1.0-dev libgirepository-2.0-dev libcairo2-dev gir1.2-gtk-4.0 gir1.2-adw-1 libffi-dev libglib2.0-dev
44
sudo apt-get install -y xvfb dbus-x11 at-spi2-core

LuaGObject/override/Adw.lua

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,72 @@ local log = LuaGObject.log.domain "LuaGObject.Adw"
1010

1111
-- Constructor container support --
1212

13+
Adw.Carousel._container_add = Adw.Carousel.append
1314
Adw.PreferencesDialog._container_add = Adw.PreferencesDialog._method.add
1415
Adw.PreferencesPage._container_add = Adw.PreferencesPage._method.add
1516
Adw.PreferencesGroup._container_add = Adw.PreferencesGroup._method.add
1617
Adw.ExpanderRow._container_add = Adw.ExpanderRow.add_row
1718

1819
-- These classes were introduced in later versions of Adw, and thus may not always be available.
20+
-- Introduced in Adw 1.7
1921
if Adw.WrapBox then
2022
Adw.WrapBox._container_add = Adw.WrapBox._method.append
2123
end
24+
25+
--Introduced in Adw 1.8
2226
if Adw.ShortcutsDialog then
2327
Adw.ShortcutsDialog._container_add = Adw.ShortcutsDialog.add
2428
end
2529
if Adw.ShortcutsSection then
2630
Adw.ShortcutsSection._container_add = Adw.ShortcutsSection.add
2731
end
2832

33+
-- Adw.TabView overrides --
34+
35+
function Adw.TabView:_container_add(child)
36+
if Gtk.Widget:is_type_of(child) then
37+
child = { child }
38+
end
39+
if type(child) ~= "table" then
40+
error("%s: Child must be table or GTK Widget", self._type.name)
41+
end
42+
if #child ~= 1 or not Gtk.Widget:is_type_of(child[1]) then
43+
error("%s: Child must contain only a single GTK Widget.", self._type.name)
44+
end
45+
local page
46+
if child.pinned then
47+
page = self:append_pinned(child[1])
48+
else
49+
page = self:append(child[1])
50+
end
51+
if type(child.title) == "string" then
52+
page.title = child.title
53+
end
54+
end
55+
56+
-- Adw.ViewStack overrides --
57+
58+
function Adw.ViewStack:_container_add(child)
59+
if Gtk.Widget:is_type_of(child) then
60+
child = { child }
61+
end
62+
if type(child) ~= "table" then
63+
error("%s: Child must be table or GTK Widget", self._type.name)
64+
end
65+
if #child ~= 1 or not Gtk.Widget:is_type_of(child[1]) then
66+
error("%s: Child table must contain one GTK Widget.", self._type.name)
67+
end
68+
if type(child.icon_name) == "string" and type(child.title) == "string" and type(child.name) == "string" then
69+
self:add_titled_with_icon(child[1], child.name, child.title, child.icon_name)
70+
elseif type(child.title) == "string" and type(child.name) == "string" then
71+
self:add_titled(child[1], child.name, child.title)
72+
elseif type(child.name) == "string" then
73+
self:add_named(child[1], child.name)
74+
else
75+
self:add(child[1])
76+
end
77+
end
78+
2979
-- Adw.ActionRow overrides --
3080

3181
Adw.ActionRow._attribute = {
@@ -34,29 +84,29 @@ Adw.ActionRow._attribute = {
3484
}
3585

3686
function Adw.ActionRow._attribute.prefixes:get()
37-
error("%s: Cannot read prefixes; attribute is write-only.", self.type.name)
87+
error("%s: Cannot read prefixes; attribute is write-only.", self._type.name)
3888
end
3989
function Adw.ActionRow._attribute.prefixes:set(value)
4090
if Gtk.Widget:is_type_of(value) then
4191
value = { value }
4292
end
4393
if type(value) ~= "table" then
44-
error("%s: Can only write table or Gtk.Widget to add_prefixes.", self.type.name)
94+
error("%s: Can only write table or Gtk.Widget to add_prefixes.", self._type.name)
4595
end
4696
for _, c in ipairs(value) do
4797
self:add_prefix(c)
4898
end
4999
end
50100

51101
function Adw.ActionRow._attribute.suffixes:get()
52-
error("%s: Cannot read suffixes; attribute is write-only.", self.type.name)
102+
error("%s: Cannot read suffixes; attribute is write-only.", self._type.name)
53103
end
54104
function Adw.ActionRow._attribute.suffixes:set(value)
55105
if Gtk.Widget:is_type_of(value) then
56106
value = { value }
57107
end
58108
if type(value) ~= "table" then
59-
error("%s: Can only write table or Widget to add_suffixes.", self.type.name)
109+
error("%s: Can only write table or Widget to add_suffixes.", self._type.name)
60110
end
61111
for _, v in ipairs(value) do
62112
self:add_suffix(v)
@@ -71,29 +121,29 @@ Adw.HeaderBar._attribute = {
71121
}
72122

73123
function Adw.HeaderBar._attribute.end_packs:get()
74-
error("%s: Cannot read end_packs; attribute is write-only.", self.type.name)
124+
error("%s: Cannot read end_packs; attribute is write-only.", self._type.name)
75125
end
76126
function Adw.HeaderBar._attribute.end_packs:set(value)
77127
if Gtk.Widget:is_type_of(value) then
78128
value = { value }
79129
end
80130
if type(value) ~= "table" then
81-
error("%s: Can only write table or Widget to end_packs.", self.type.name)
131+
error("%s: Can only write table or Widget to end_packs.", self._type.name)
82132
end
83133
for _, v in ipairs(value) do
84134
self:pack_end(v)
85135
end
86136
end
87137

88138
function Adw.HeaderBar._attribute.start_packs:get()
89-
error("%s: Cannot read start_packs; attribute is write-only.", self.type.name)
139+
error("%s: Cannot read start_packs; attribute is write-only.", self._type.name)
90140
end
91141
function Adw.HeaderBar._attribute.start_packs:set(value)
92-
if Gtk.Widget:is_type_of(widget) then
142+
if Gtk.Widget:is_type_of(value) then
93143
value = { value }
94144
end
95145
if type(value) ~= "table" then
96-
error("%s: Can only write table or Widget to start_packs.", self.type.name)
146+
error("%s: Can only write table or Widget to start_packs.", self._type.name)
97147
end
98148
for _, v in ipairs(value) do
99149
self:pack_start(v)
@@ -102,37 +152,37 @@ end
102152

103153
-- Adw.ToolbarView overrides --
104154

105-
-- Adw.ToolbarView was introduced in Adw 1.4, and may not be available.
155+
-- Adw.ToolbarView was introduced in Adw 1.4. It should only be overridden if it exists.
106156
if Adw.ToolbarView then
107157
Adw.ToolbarView._attribute = {
108158
bottom_bars = {},
109159
top_bars = {},
110160
}
111161

112162
function Adw.ToolbarView._attribute.bottom_bars:get()
113-
error("%s: Cannot read bottom_bars; attribute is write-only.", self.type.name)
163+
error("%s: Cannot read bottom_bars; attribute is write-only.", self._type.name)
114164
end
115165
function Adw.ToolbarView._attribute.bottom_bars:set(value)
116166
if Gtk.Widget:is_type_of(value) then
117167
value = { value }
118168
end
119169
if type(value) ~= "table" then
120-
error("%s: Can only write table or Gtk.Widget to add_bottom_bars.", self.type.name)
170+
error("%s: Can only write table or Gtk.Widget to add_bottom_bars.", self._type.name)
121171
end
122172
for _, v in ipairs(values) do
123173
self:add_bottom_bar(v)
124174
end
125175
end
126176

127177
function Adw.ToolbarView._attribute.top_bars:get()
128-
error("%s: Cannot read top_bars; attribute is write-only.", self.type.name)
178+
error("%s: Cannot read top_bars; attribute is write-only.", self._type.name)
129179
end
130180
function Adw.ToolbarView._attribute.top_bars:set(value)
131181
if Gtk.Widget:is_type_of(value) then
132182
value = { value }
133183
end
134184
if type(value) ~= "table" then
135-
error("%s: Can only write table or Gtk.Widget to add_top_bars.", self.type.name)
185+
error("%s: Can only write table or Gtk.Widget to add_top_bars.", self._type.name)
136186
end
137187
for _, v in ipairs(value) do
138188
self:add_top_bar(v)

LuaGObject/override/Gtk3.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ local cairo = LuaGObject.cairo
1919

2020
local log = LuaGObject.log.domain('LuaGObject.Gtk3')
2121

22+
assert(Gtk.get_major_version() <= 3)
23+
2224
-- Initialize GTK.
2325
Gtk.disable_setlocale()
2426
if not Gtk.init_check() then

LuaGObject/override/Gtk4.lua

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,49 @@ function Gtk.Widget._attribute.children:get()
7070
return setmetatable({ _widget = self }, widget_children_mt)
7171
end
7272

73-
-- Constructor container support --
73+
-- Simple container support --
7474

7575
Gtk.Box._container_add = Gtk.Box._method.append
7676
Gtk.FlowBox._container_add = Gtk.FlowBox._method.append
7777
Gtk.ListBox._container_add = Gtk.ListBox._method.append
7878
Gtk.Stack._container_add = Gtk.Stack._method.add_child
79+
80+
-- Gtk.Grid container support --
81+
82+
function Gtk.Grid:_container_add(child)
83+
if type(child) ~= "table" then
84+
error("%s: Cannot add non-table child from constructor.", self._type.name)
85+
end
86+
if type(child.column) ~= "number" or type(child.row) ~= "number" then
87+
error("%s: Child column and/or row are unspecified.", self._type.name)
88+
end
89+
if #child ~= 1 or not Gtk.Widget:is_type_of(child[1]) then
90+
error("%s: Child table must contain only one widget.", self._type.name)
91+
end
92+
local column = child.column
93+
local row = child.row
94+
local width = child.width or 1
95+
local height = child.height or 1
96+
self:attach(child[1], column, row, width, height)
97+
end
98+
99+
-- Gtk.Notebook container support --
100+
101+
function Gtk.Notebook:_container_add(child)
102+
if type(child) ~= "table" then
103+
error("%s: Cannot add non-table child from constructor.", self._type.name)
104+
end
105+
if type(child.tab_label) == "string" then
106+
child.tab_label = Gtk.Label { label = child.tab_label }
107+
elseif not Gtk.Widget:is_type_of(child.tab_label) then
108+
error("%s: Child label is not a GTK Widget.", self._type.name)
109+
end
110+
if #child ~= 1 or not Gtk.Widget:is_type_of(child[1]) then
111+
error("%s: Child table must have only one widget.", self._type.name)
112+
end
113+
if Gtk.Widget:is_type_of(child.menu_label) then
114+
self:append_page_menu(child[1], child.tab_label, child.menu_label)
115+
else
116+
self:append_page(child[1], child.tab_label)
117+
end
118+
end

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
VERSION = 0.10.0
1010
MAKE ?= make
1111

12-
ROCK = LuaGObject-$(VERSION)-1.rockspec
12+
ROCK = luagobject-$(VERSION)-1.rockspec
1313

1414
.PHONY : rock all clean install check
1515

docs/gtk.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ GTK 4 gets rid of the Container class, making it somewhat more complicated to in
4949
- `Gtk.FlowBox`
5050
- `Gtk.ListBox`
5151
- `Gtk.Stack`
52+
- `Gtk.Notebook`
53+
- `Gtk.Grid`
5254

5355
An example of instantiating a `Gtk.Box` with its own children:
5456

@@ -62,6 +64,48 @@ An example of instantiating a `Gtk.Box` with its own children:
6264

6365
This creates a `Gtk.Box` containing four children. Note that `box`'s `orientation` property was set to `Gtk.Orientation.VERTICAL` as well in the same constructor. For specific container widgets, this creates a programmer experience not unlike using `Gtk.Builder` for creating widget hierarchies, but with a syntax ressembling Blueprint.
6466

67+
### `Gtk.Notebook` Children
68+
69+
To construct an instance of `Gtk.Notebook` with children, special consideration must be undertaken. Adding children to this widget requires a label to be provided. Additionally, an optional menu may be provided as well. To do this, each child in the constructor must be a table with a GTK widget in the first slot, a `.tab_label` item with a child widget, and optionally a `.menu_label` item with a child widget.
70+
71+
local notebook = Gtk.Notebook {
72+
{
73+
Gtk.TextView(),
74+
tab_label = Gtk.Label { label = "Tab 1" },
75+
},
76+
{
77+
Gtk.ScrolledWindow(),
78+
tab_label = Gtk.Label { label = "Tab 2" },
79+
menu_label = Gtk.MenuButton(),
80+
},
81+
}
82+
83+
This example creates a `Gtk.Notebook` containing two tabs, labelled "Tab 1" and "Tab 2". Tab 2 also has a menu widget.
84+
85+
For convenience, this override also allows a child's `.tab_label` item to be a string. In this case, LuaGObject automatically wraps this into a `Gtk.Label` with the `.label` property set the given value. Thus, the previous example can be rewritten as:
86+
87+
local notebook = Gtk.Notebook {
88+
{ Gtk.TextView(), tab_label = "Tab 1" },
89+
{
90+
Gtk.ScrolledWindow(),
91+
tab_label = "Tab 2",
92+
menu = Gtk.MenuButton(),
93+
},
94+
}
95+
96+
### `Gtk.Grid` Children
97+
98+
Like with `Gtk.Notebook`, the `Gtk.Grid` class also requires special consideration when adding children in its constructor. Each child added this way must be a table containing a widget in the array part, as well as integer values for `.column` and `.row`. A `.width` and/or `.height` may optionally be specified, and both will default to 1 if not given.
99+
100+
local grid = Gtk.Grid {
101+
{ Gtk.Button.new_with_label "1, 1", column = 1, row = 1 },
102+
{ Gtk.Button.new_with_label "2, 1", column = 2, row = 1 },
103+
{
104+
Gtk.Button.new_with_label "1–2, 2 (spans two columns)",
105+
column = 1, row = 2, width = 2,
106+
},
107+
}
108+
65109
### Advanced Example: Removing Children
66110

67111
Many container widgets implement a `:remove()` method which takes a child `Gtk.Widget` as its argument. Without the GTK 4 override, removing a child in this way can be somewhat tricky—one may need to call a function like `:get_child_at_index()`, including adjusting the index to account for 0-indexing.
@@ -89,6 +133,7 @@ Certain classes only exist in later versions of libadwaita. These version requir
89133

90134
Like `Gtk.Box` and related classes, LuaGObject overrides certain Adw classes to allow specifying children to be added in constructor tables. The following widgets are supported:
91135

136+
- `Adw.Carousel`
92137
- `Adw.PreferencesDialog`
93138
- Must only contain `Adw.PreferencesPage` children.
94139
- `Adw.PreferencesPage`
@@ -100,6 +145,8 @@ Like `Gtk.Box` and related classes, LuaGObject overrides certain Adw classes to
100145
- Must only contain `Adw.ShortcutsSection` children.
101146
- `Adw.ShortcutsSection` (Adw 1.8 and later)
102147
- Must only contain `Adw.ShortcutsItem` children.
148+
- `Adw.TabView`
149+
- `Adw.ViewStack`
103150

104151
As with GTK 4, these constructors may be nested. Here is a more complex example involving the creation of a preferences page:
105152

@@ -119,6 +166,33 @@ As with GTK 4, these constructors may be nested. Here is a more complex example
119166
},
120167
}
121168

169+
### `Adw.TabView` Constructor Children
170+
171+
Like with other container widgets, `Adw.TabView` can accept an arbitrary number of child widgets in the constructor table's array part. Additionally, it can also accept an arbitrary number of tables, each containing one widget in the array part and optionally also a value at `.pinned`, which will add the child widget as a pinned tab, and `.title` which is a string to be used as the tab's title. This example illustrates multiple ways to add children to a Tab View:
172+
173+
local tabview = Adw.TabView {
174+
Gtk.TextView(), -- Title will be left blank
175+
{ Gtk.TextView(), title = "Tab 2" },
176+
{ Gtk.TextView(), title = "Tab 3", pinned = true },
177+
}
178+
179+
### `Adw.ViewStack` Constructor Children
180+
181+
As with `Adw.TabView`, `Adw.ViewStack` children may be included in the constructor table directly, or wrapped in tables with certain additional members. These are `.name`, `.title`, and `.icon_name`. For `.title`, a `.name` must be set or it won't be used. For `.icon_name`, both a `.title` and a `.name` must be set as well. For a complete example of all ways to add children to `Adw.ViewStack` in the constructor:
182+
183+
local viewstack = Adw.ViewStack {
184+
Gtk.TextView(),
185+
{ Gtk.TextView() },
186+
{ Gtk.TextView(), name = "Name" },
187+
{ Gtk.TextView(), name = "Name", title = "Title" },
188+
{
189+
Gtk.TextView(),
190+
name = "Name",
191+
title = "Title",
192+
icon_name = "icon-name",
193+
},
194+
}
195+
122196
## Constructing with Supplemental Widgets
123197

124198
Certain Adw classes have multiple different kinds of child widgets, preventing them from being arbitrarily added like with other container-type widgets. Widgets that work this way usually do so to distinguish between children coming before, and after, the main widget body. Each class supporting this pattern does so using class-specific methods. LuaGObject provides pseudo-properties for specific classes allowing these kinds of children to be added at construction time. Each pseudo-property is write-only and takes a value of either a single widget or a table array of widgets. Currently, these classes are:

0 commit comments

Comments
 (0)