gtk4 4.1.2 → 4.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/sample/examples/application1/exampleapp.rb +2 -2
  3. data/sample/examples/application2/README.md +10 -0
  4. data/sample/examples/application2/exampleapp.rb +80 -0
  5. data/sample/examples/application3/README.md +1 -0
  6. data/sample/examples/application3/exampleapp.rb +108 -0
  7. data/sample/examples/application4/README.md +13 -0
  8. data/sample/examples/application4/exampleapp.rb +158 -0
  9. data/sample/examples/application5/README.md +30 -0
  10. data/sample/examples/application5/Rakefile +27 -0
  11. data/sample/examples/application5/exampleapp.rb +171 -0
  12. data/sample/examples/application5/org.gtk.exampleapp.gschema.xml +20 -0
  13. data/sample/examples/application6/README.md +15 -0
  14. data/sample/examples/application6/Rakefile +27 -0
  15. data/sample/examples/application6/exampleapp.rb +265 -0
  16. data/sample/examples/application6/org.gtk.exampleapp.gschema.xml +20 -0
  17. data/sample/examples/application7/README.md +15 -0
  18. data/sample/examples/application7/Rakefile +27 -0
  19. data/sample/examples/application7/exampleapp.rb +307 -0
  20. data/sample/examples/application7/org.gtk.exampleapp.gschema.xml +20 -0
  21. data/sample/examples/application8/README.md +15 -0
  22. data/sample/examples/application8/Rakefile +27 -0
  23. data/sample/examples/application8/exampleapp.rb +357 -0
  24. data/sample/examples/application8/org.gtk.exampleapp.gschema.xml +25 -0
  25. data/sample/examples/application9/README.md +15 -0
  26. data/sample/examples/application9/Rakefile +27 -0
  27. data/sample/examples/application9/exampleapp.rb +387 -0
  28. data/sample/examples/application9/org.gtk.exampleapp.gschema.xml +25 -0
  29. metadata +32 -6
@@ -0,0 +1,27 @@
1
+ # Copyright (C) 2023 Ruby-GNOME Project Team
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ require "rake/clean"
18
+
19
+ task :default => "gschemas.compiled"
20
+
21
+ file "gschemas.compiled" => "org.gtk.exampleapp.gschema.xml" do
22
+ sh("glib-compile-schemas", ".")
23
+ end
24
+
25
+ CLEAN << "gschemas.compiled"
26
+
27
+ task :clean
@@ -0,0 +1,265 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (C) 2023 Ruby-GNOME Project Team
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ #
19
+ # Example from:
20
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application6/exampleapp.c
21
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application6/exampleappwin.c
22
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application6/exampleappprefs.c
23
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application6/window.ui
24
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application6/gears-menu.ui
25
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application6/prefs.ui
26
+ # License: LGPL2.1-or-later
27
+
28
+ # GSETTINGS_SCHEMA_DIR must be set before requiring "gtk4" gem because it is used in the GIO initialization.
29
+
30
+ if File.exist?(File.join(__dir__, "gschemas.compiled"))
31
+ ENV["GSETTINGS_SCHEMA_DIR"] = __dir__
32
+ else
33
+ raise %{gschemas.compiled doesn't exist. Run "rake" to generate it.}
34
+ end
35
+
36
+ require "gtk4"
37
+
38
+ class ExampleAppPrefs < Gtk::Dialog
39
+ type_register
40
+ class << self
41
+ def init
42
+ template = <<~TEMPLATE
43
+ <?xml version="1.0" encoding="UTF-8"?>
44
+ <interface>
45
+ <template class="ExampleAppPrefs" parent="GtkDialog">
46
+ <property name="title" translatable="yes">Preferences</property>
47
+ <property name="resizable">0</property>
48
+ <property name="modal">1</property>
49
+ <child internal-child="content_area">
50
+ <object class="GtkBox" id="content_area">
51
+ <child>
52
+ <object class="GtkGrid" id="grid">
53
+ <property name="margin-start">12</property>
54
+ <property name="margin-end">12</property>
55
+ <property name="margin-top">12</property>
56
+ <property name="margin-bottom">12</property>
57
+ <property name="row-spacing">12</property>
58
+ <property name="column-spacing">12</property>
59
+ <child>
60
+ <object class="GtkLabel" id="fontlabel">
61
+ <property name="label">_Font:</property>
62
+ <property name="use-underline">1</property>
63
+ <property name="mnemonic-widget">font</property>
64
+ <property name="xalign">1</property>
65
+ <layout>
66
+ <property name="column">0</property>
67
+ <property name="row">0</property>
68
+ </layout>
69
+ </object>
70
+ </child>
71
+ <child>
72
+ <object class="GtkFontButton" id="font">
73
+ <layout>
74
+ <property name="column">1</property>
75
+ <property name="row">0</property>
76
+ </layout>
77
+ </object>
78
+ </child>
79
+ <child>
80
+ <object class="GtkLabel" id="transitionlabel">
81
+ <property name="label">_Transition:</property>
82
+ <property name="use-underline">1</property>
83
+ <property name="mnemonic-widget">transition</property>
84
+ <property name="xalign">1</property>
85
+ <layout>
86
+ <property name="column">0</property>
87
+ <property name="row">1</property>
88
+ </layout>
89
+ </object>
90
+ </child>
91
+ <child>
92
+ <object class="GtkComboBoxText" id="transition">
93
+ <items>
94
+ <item translatable="yes" id="none">None</item>
95
+ <item translatable="yes" id="crossfade">Fade</item>
96
+ <item translatable="yes" id="slide-left-right">Slide</item>
97
+ </items>
98
+ <layout>
99
+ <property name="column">1</property>
100
+ <property name="row">1</property>
101
+ </layout>
102
+ </object>
103
+ </child>
104
+ </object>
105
+ </child>
106
+ </object>
107
+ </child>
108
+ </template>
109
+ </interface>
110
+ TEMPLATE
111
+ set_template(data: template)
112
+ bind_template_child("font")
113
+ bind_template_child("transition")
114
+ end
115
+ end
116
+
117
+ def initialize(win)
118
+ # The original C program sets use-header-bar property to TRUE instead of 1.
119
+ # But the property type is int, not gboolean.
120
+ # Therefore, the property value must be 1, not `true` here.
121
+ super('transient-for': win, 'use-header-bar': 1)
122
+ settings = Gio::Settings.new("org.gtk.exampleapp")
123
+ settings.bind("font", font, "font", :default)
124
+ settings.bind("transition", transition, "active-id", :default)
125
+ end
126
+ end
127
+
128
+ class ExampleAppWindow < Gtk::ApplicationWindow
129
+ type_register
130
+ class << self
131
+ def init
132
+ template = <<~TEMPLATE
133
+ <?xml version="1.0" encoding="UTF-8"?>
134
+ <interface>
135
+ <template class="ExampleAppWindow" parent="GtkApplicationWindow">
136
+ <property name="title" translatable="yes">Example Application</property>
137
+ <property name="default-width">600</property>
138
+ <property name="default-height">400</property>
139
+ <child type="titlebar">
140
+ <object class="GtkHeaderBar" id="header">
141
+ <child type="title">
142
+ <object class="GtkStackSwitcher" id="tabs">
143
+ <property name="stack">stack</property>
144
+ </object>
145
+ </child>
146
+ <child type="end">
147
+ <object class="GtkMenuButton" id="gears">
148
+ <property name="direction">none</property>
149
+ </object>
150
+ </child>
151
+ </object>
152
+ </child>
153
+ <child>
154
+ <object class="GtkBox" id="content_box">
155
+ <property name="orientation">vertical</property>
156
+ <child>
157
+ <object class="GtkStack" id="stack"/>
158
+ </child>
159
+ </object>
160
+ </child>
161
+ </template>
162
+ </interface>
163
+ TEMPLATE
164
+ set_template(data: template)
165
+ bind_template_child("stack")
166
+ bind_template_child("gears")
167
+ end
168
+ end
169
+
170
+ def initialize(application)
171
+ menu_ui = <<~MENU
172
+ <?xml version="1.0" encoding="UTF-8"?>
173
+ <interface>
174
+ <menu id="menu">
175
+ <section>
176
+ <item>
177
+ <attribute name="label" translatable="yes">_Preferences</attribute>
178
+ <attribute name="action">app.preferences</attribute>
179
+ </item>
180
+ </section>
181
+ <section>
182
+ <item>
183
+ <attribute name="label" translatable="yes">_Quit</attribute>
184
+ <attribute name="action">app.quit</attribute>
185
+ </item>
186
+ </section>
187
+ </menu>
188
+ </interface>
189
+ MENU
190
+ super(application: application)
191
+ builder = Gtk::Builder.new(string: menu_ui)
192
+ gears.menu_model = builder["menu"]
193
+ @settings = Gio::Settings.new("org.gtk.exampleapp")
194
+ @settings.bind("transition", stack, "transition-type", :default)
195
+ end
196
+
197
+ def open(file)
198
+ basename = file.basename
199
+ scrolled = Gtk::ScrolledWindow.new
200
+ scrolled.hexpand = true
201
+ scrolled.vexpand = true
202
+ view = Gtk::TextView.new
203
+ view.editable = false
204
+ view.cursor_visible = false
205
+ scrolled.child = view
206
+ stack.add_titled(scrolled, basename, basename)
207
+ buffer = view.buffer
208
+ file.read do |stream|
209
+ buffer.text = stream.read.force_encoding(Encoding::UTF_8)
210
+ end
211
+ tag = buffer.create_tag
212
+ @settings.bind("font", tag, "font", :default)
213
+ buffer.apply_tag(tag, buffer.start_iter, buffer.end_iter)
214
+ end
215
+ end
216
+
217
+ class ExampleApp < Gtk::Application
218
+ def initialize
219
+ super("org.gtk.exampleapp", :handles_open)
220
+
221
+ signal_connect "startup" do |application|
222
+ [
223
+ "preferences",
224
+ "quit"
225
+ ].each do |action_name|
226
+ action = Gio::SimpleAction.new(action_name)
227
+ action.signal_connect("activate") do |_action, _parameter|
228
+ __send__("#{action_name}_activated")
229
+ end
230
+ application.add_action(action)
231
+ end
232
+ application.set_accels_for_action("app.quit", ["<Control>Q"])
233
+ end
234
+ signal_connect "activate" do |application|
235
+ window = ExampleAppWindow.new(application)
236
+ window.present
237
+ end
238
+ signal_connect "open" do |application, files, hint|
239
+ window = application.windows[0] || ExampleAppWindow.new(application)
240
+ files.each do |file|
241
+ window.open(file)
242
+ end
243
+ window.present
244
+ end
245
+ end
246
+
247
+ private
248
+
249
+ def preferences_activated
250
+ prefs = ExampleAppPrefs.new(active_window)
251
+ prefs.present
252
+ end
253
+
254
+ def quit_activated
255
+ quit
256
+ end
257
+ end
258
+
259
+ app = ExampleApp.new
260
+
261
+ # Gtk::Application#run needs C style argv ([prog, arg1, arg2, ...,argn]).
262
+ # The ARGV ruby variable only contains the arguments ([arg1, arg2, ...,argb])
263
+ # and not the program name. We have to add it explicitly.
264
+
265
+ app.run([$PROGRAM_NAME] + ARGV)
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <schemalist>
3
+ <schema path="/org/gtk/exampleapp/" id="org.gtk.exampleapp">
4
+ <key name="font" type="s">
5
+ <default>'Monospace 12'</default>
6
+ <summary>Font</summary>
7
+ <description>The font to be used for content.</description>
8
+ </key>
9
+ <key name="transition" type="s">
10
+ <choices>
11
+ <choice value='none'/>
12
+ <choice value='crossfade'/>
13
+ <choice value='slide-left-right'/>
14
+ </choices>
15
+ <default>'none'</default>
16
+ <summary>Transition</summary>
17
+ <description>The transition to use when switching tabs.</description>
18
+ </key>
19
+ </schema>
20
+ </schemalist>
@@ -0,0 +1,15 @@
1
+ # Step 7: Add a search bar
2
+
3
+ The original files are located in the following directory.
4
+
5
+ - https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application7
6
+
7
+ The original schema file is [here](https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application7/org.gtk.exampleapp.gschema.xml) and the license is LGPL 2.1 or later.
8
+
9
+ Run `rake` before trying `exampleapp.rb`.
10
+
11
+ ```console
12
+ $ cd gtk4/sample/examples/application7
13
+ $ rake
14
+ $ ruby exampleapp.rb README.md Rakefile
15
+ ```
@@ -0,0 +1,27 @@
1
+ # Copyright (C) 2023 Ruby-GNOME Project Team
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ require "rake/clean"
18
+
19
+ task :default => "gschemas.compiled"
20
+
21
+ file "gschemas.compiled" => "org.gtk.exampleapp.gschema.xml" do
22
+ sh("glib-compile-schemas", ".")
23
+ end
24
+
25
+ CLEAN << "gschemas.compiled"
26
+
27
+ task :clean
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (C) 2023 Ruby-GNOME Project Team
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ #
19
+ # Example from:
20
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application7/exampleapp.c
21
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application7/exampleappwin.c
22
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application7/exampleappprefs.c
23
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application7/window.ui
24
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application7/gears-menu.ui
25
+ # * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/examples/application7/prefs.ui
26
+ # License: LGPL2.1-or-later
27
+
28
+ # GSETTINGS_SCHEMA_DIR must be set before requiring "gtk4" gem because it is used in the GIO initialization.
29
+
30
+ if File.exist?(File.join(__dir__, "gschemas.compiled"))
31
+ ENV["GSETTINGS_SCHEMA_DIR"] = __dir__
32
+ else
33
+ raise %{gschemas.compiled doesn't exist. Run "rake" to generate it.}
34
+ end
35
+
36
+ require "gtk4"
37
+
38
+ class ExampleAppPrefs < Gtk::Dialog
39
+ type_register
40
+ class << self
41
+ def init
42
+ template = <<~TEMPLATE
43
+ <?xml version="1.0" encoding="UTF-8"?>
44
+ <interface>
45
+ <template class="ExampleAppPrefs" parent="GtkDialog">
46
+ <property name="title" translatable="yes">Preferences</property>
47
+ <property name="resizable">0</property>
48
+ <property name="modal">1</property>
49
+ <child internal-child="content_area">
50
+ <object class="GtkBox" id="content_area">
51
+ <child>
52
+ <object class="GtkGrid" id="grid">
53
+ <property name="margin-start">12</property>
54
+ <property name="margin-end">12</property>
55
+ <property name="margin-top">12</property>
56
+ <property name="margin-bottom">12</property>
57
+ <property name="row-spacing">12</property>
58
+ <property name="column-spacing">12</property>
59
+ <child>
60
+ <object class="GtkLabel" id="fontlabel">
61
+ <property name="label">_Font:</property>
62
+ <property name="use-underline">1</property>
63
+ <property name="mnemonic-widget">font</property>
64
+ <property name="xalign">1</property>
65
+ <layout>
66
+ <property name="column">0</property>
67
+ <property name="row">0</property>
68
+ </layout>
69
+ </object>
70
+ </child>
71
+ <child>
72
+ <object class="GtkFontButton" id="font">
73
+ <layout>
74
+ <property name="column">1</property>
75
+ <property name="row">0</property>
76
+ </layout>
77
+ </object>
78
+ </child>
79
+ <child>
80
+ <object class="GtkLabel" id="transitionlabel">
81
+ <property name="label">_Transition:</property>
82
+ <property name="use-underline">1</property>
83
+ <property name="mnemonic-widget">transition</property>
84
+ <property name="xalign">1</property>
85
+ <layout>
86
+ <property name="column">0</property>
87
+ <property name="row">1</property>
88
+ </layout>
89
+ </object>
90
+ </child>
91
+ <child>
92
+ <object class="GtkComboBoxText" id="transition">
93
+ <items>
94
+ <item translatable="yes" id="none">None</item>
95
+ <item translatable="yes" id="crossfade">Fade</item>
96
+ <item translatable="yes" id="slide-left-right">Slide</item>
97
+ </items>
98
+ <layout>
99
+ <property name="column">1</property>
100
+ <property name="row">1</property>
101
+ </layout>
102
+ </object>
103
+ </child>
104
+ </object>
105
+ </child>
106
+ </object>
107
+ </child>
108
+ </template>
109
+ </interface>
110
+ TEMPLATE
111
+ set_template(data: template)
112
+ bind_template_child("font")
113
+ bind_template_child("transition")
114
+ end
115
+ end
116
+
117
+ def initialize(win)
118
+ # The original C program sets use-header-bar property to TRUE instead of 1.
119
+ # But the property type is int, not gboolean.
120
+ # Therefore, the property value must be 1, not `true` here.
121
+ super('transient-for': win, 'use-header-bar': 1)
122
+ settings = Gio::Settings.new("org.gtk.exampleapp")
123
+ settings.bind("font", font, "font", :default)
124
+ settings.bind("transition", transition, "active-id", :default)
125
+ end
126
+ end
127
+
128
+ class ExampleAppWindow < Gtk::ApplicationWindow
129
+ type_register
130
+ class << self
131
+ def init
132
+ template = <<~TEMPLATE
133
+ <?xml version="1.0" encoding="UTF-8"?>
134
+ <interface>
135
+ <template class="ExampleAppWindow" parent="GtkApplicationWindow">
136
+ <property name="title" translatable="yes">Example Application</property>
137
+ <property name="default-width">600</property>
138
+ <property name="default-height">400</property>
139
+ <child type="titlebar">
140
+ <object class="GtkHeaderBar" id="header">
141
+ <child type="title">
142
+ <object class="GtkStackSwitcher" id="tabs">
143
+ <property name="stack">stack</property>
144
+ </object>
145
+ </child>
146
+ <child type="end">
147
+ <object class="GtkMenuButton" id="gears">
148
+ <property name="direction">none</property>
149
+ </object>
150
+ </child>
151
+ <child type="end">
152
+ <object class="GtkToggleButton" id="search">
153
+ <property name="sensitive">0</property>
154
+ <property name="icon-name">edit-find-symbolic</property>
155
+ </object>
156
+ </child>
157
+ </object>
158
+ </child>
159
+ <child>
160
+ <object class="GtkBox" id="content_box">
161
+ <property name="orientation">vertical</property>
162
+ <child>
163
+ <object class="GtkSearchBar" id="searchbar">
164
+ <child>
165
+ <object class="GtkSearchEntry" id="searchentry">
166
+ <signal name="search-changed" handler="search_text_changed"/>
167
+ </object>
168
+ </child>
169
+ </object>
170
+ </child>
171
+ <child>
172
+ <object class="GtkStack" id="stack">
173
+ <signal name="notify::visible-child" handler="visible_child_changed"/>
174
+ </object>
175
+ </child>
176
+ </object>
177
+ </child>
178
+ </template>
179
+ </interface>
180
+ TEMPLATE
181
+ set_template(data: template)
182
+ bind_template_child("stack")
183
+ bind_template_child("gears")
184
+ bind_template_child("search")
185
+ bind_template_child("searchbar")
186
+ bind_template_callback_full("search_text_changed")
187
+ bind_template_callback_full("visible_child_changed")
188
+ end
189
+ end
190
+
191
+ def initialize(application)
192
+ menu_ui = <<~MENU
193
+ <?xml version="1.0" encoding="UTF-8"?>
194
+ <interface>
195
+ <menu id="menu">
196
+ <section>
197
+ <item>
198
+ <attribute name="label" translatable="yes">_Preferences</attribute>
199
+ <attribute name="action">app.preferences</attribute>
200
+ </item>
201
+ </section>
202
+ <section>
203
+ <item>
204
+ <attribute name="label" translatable="yes">_Quit</attribute>
205
+ <attribute name="action">app.quit</attribute>
206
+ </item>
207
+ </section>
208
+ </menu>
209
+ </interface>
210
+ MENU
211
+ super(application: application)
212
+ builder = Gtk::Builder.new(string: menu_ui)
213
+ gears.menu_model = builder["menu"]
214
+ @settings = Gio::Settings.new("org.gtk.exampleapp")
215
+ @settings.bind("transition", stack, "transition-type", :default)
216
+ search.bind_property("active", searchbar, "search-mode-enabled", :bidirectional)
217
+ end
218
+
219
+ def open(file)
220
+ basename = file.basename
221
+ scrolled = Gtk::ScrolledWindow.new
222
+ scrolled.hexpand = true
223
+ scrolled.vexpand = true
224
+ view = Gtk::TextView.new
225
+ view.editable = false
226
+ view.cursor_visible = false
227
+ scrolled.child = view
228
+ stack.add_titled(scrolled, basename, basename)
229
+ buffer = view.buffer
230
+ file.read do |stream|
231
+ buffer.text = stream.read.force_encoding(Encoding::UTF_8)
232
+ end
233
+ tag = buffer.create_tag
234
+ @settings.bind("font", tag, "font", :default)
235
+ buffer.apply_tag(tag, buffer.start_iter, buffer.end_iter)
236
+ search.sensitive = true
237
+ end
238
+
239
+ private
240
+
241
+ def search_text_changed(search_entry)
242
+ text = search_entry.text
243
+ return if text.empty?
244
+ tab = stack.visible_child
245
+ view = tab.child
246
+ buffer = view.buffer
247
+ range = buffer.start_iter.forward_search(text, :case_insensitive)
248
+ return unless range
249
+ buffer.select_range(range[0], range[1])
250
+ view.scroll_to_iter(range[0], 0.0, false, 0.0, 0.0)
251
+ end
252
+
253
+ def visible_child_changed(stack, params)
254
+ return if stack.in_destruction?
255
+ searchbar.search_mode = false
256
+ end
257
+ end
258
+
259
+ class ExampleApp < Gtk::Application
260
+ def initialize
261
+ super("org.gtk.exampleapp", :handles_open)
262
+
263
+ signal_connect "startup" do |application|
264
+ [
265
+ "preferences",
266
+ "quit"
267
+ ].each do |action_name|
268
+ action = Gio::SimpleAction.new(action_name)
269
+ action.signal_connect("activate") do |_action, _parameter|
270
+ __send__("#{action_name}_activated")
271
+ end
272
+ application.add_action(action)
273
+ end
274
+ application.set_accels_for_action("app.quit", ["<Control>Q"])
275
+ end
276
+ signal_connect "activate" do |application|
277
+ window = ExampleAppWindow.new(application)
278
+ window.present
279
+ end
280
+ signal_connect "open" do |application, files, hint|
281
+ window = application.windows[0] || ExampleAppWindow.new(application)
282
+ files.each do |file|
283
+ window.open(file)
284
+ end
285
+ window.present
286
+ end
287
+ end
288
+
289
+ private
290
+
291
+ def preferences_activated
292
+ prefs = ExampleAppPrefs.new(active_window)
293
+ prefs.present
294
+ end
295
+
296
+ def quit_activated
297
+ quit
298
+ end
299
+ end
300
+
301
+ app = ExampleApp.new
302
+
303
+ # Gtk::Application#run needs C style argv ([prog, arg1, arg2, ...,argn]).
304
+ # The ARGV ruby variable only contains the arguments ([arg1, arg2, ...,argb])
305
+ # and not the program name. We have to add it explicitly.
306
+
307
+ app.run([$PROGRAM_NAME] + ARGV)