gtk3 3.0.7 → 3.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/gtk3/extconf.rb +1 -0
- data/ext/gtk3/rb-gtk3-tree-view.c +4 -0
- data/ext/gtk3/rb-gtk3.c +245 -60
- data/lib/gtk3/box.rb +22 -0
- data/lib/gtk3/builder.rb +50 -29
- data/lib/gtk3/deprecated.rb +7 -0
- data/lib/gtk3/entry-buffer.rb +28 -0
- data/lib/gtk3/list-store.rb +2 -20
- data/lib/gtk3/loader.rb +6 -0
- data/lib/gtk3/menu-item.rb +8 -7
- data/lib/gtk3/tree-iter.rb +25 -1
- data/lib/gtk3/tree-model.rb +41 -0
- data/lib/gtk3/tree-store.rb +7 -6
- data/lib/gtk3/widget.rb +18 -1
- data/sample/gtk-demo/TODO +45 -39
- data/sample/gtk-demo/assistant.rb +123 -0
- data/sample/gtk-demo/builder.rb +75 -38
- data/sample/gtk-demo/button_box.rb +100 -0
- data/sample/gtk-demo/colorsel.rb +49 -65
- data/sample/gtk-demo/css_accordion.rb +33 -55
- data/sample/gtk-demo/css_basics.rb +55 -80
- data/sample/gtk-demo/css_multiplebgs.rb +112 -0
- data/sample/gtk-demo/css_pixbufs.rb +84 -0
- data/sample/gtk-demo/css_shadows.rb +101 -0
- data/sample/gtk-demo/cursors.rb +114 -0
- data/sample/gtk-demo/dialog.rb +105 -115
- data/sample/gtk-demo/entry_buffer.rb +44 -0
- data/sample/gtk-demo/entry_completion.rb +40 -52
- data/sample/gtk-demo/expander.rb +60 -26
- data/sample/gtk-demo/filtermodel.rb +119 -0
- data/sample/gtk-demo/font_features.rb +117 -0
- data/sample/gtk-demo/headerbar.rb +57 -0
- data/sample/gtk-demo/iconview_edit.rb +79 -0
- data/sample/gtk-demo/infobar.rb +75 -59
- data/sample/gtk-demo/links.rb +53 -40
- data/sample/gtk-demo/main.rb +353 -43
- data/sample/gtk-demo/main.ui +9 -9
- data/sample/gtk-demo/markup.rb +46 -0
- data/sample/gtk-demo/menus.rb +111 -162
- data/sample/gtk-demo/modelbutton.rb +47 -0
- data/sample/gtk-demo/overlay.rb +61 -0
- data/sample/gtk-demo/overlay2.rb +75 -0
- data/sample/gtk-demo/panes.rb +114 -133
- data/sample/gtk-demo/pickers.rb +70 -0
- data/sample/gtk-demo/popover.rb +110 -0
- data/sample/gtk-demo/printing.rb +68 -83
- data/sample/gtk-demo/revealer.rb +53 -0
- data/sample/gtk-demo/scale.rb +26 -0
- data/sample/gtk-demo/search_entry2.rb +107 -0
- data/sample/gtk-demo/sidebar.rb +68 -0
- data/sample/gtk-demo/sizegroup.rb +93 -105
- data/sample/gtk-demo/spinner.rb +53 -50
- data/sample/gtk-demo/stack.rb +28 -0
- data/sample/gtk-demo/test_mod.rb +22 -0
- data/sample/gtk-demo/textmask.rb +61 -0
- data/sample/gtk-demo/theming_style_classes.rb +16 -12
- data/sample/misc/app-menu.ui +19 -0
- data/sample/misc/button-menu.ui +19 -0
- data/sample/misc/icons-theme-viewer.rb +65 -0
- data/sample/misc/menu.rb +3 -3
- data/sample/misc/menus_from_resources.gresource.xml +8 -0
- data/sample/misc/menus_from_resources.rb +91 -0
- data/sample/misc/statusicon.rb +1 -1
- data/sample/misc/toolbar-menu.ui +23 -0
- data/sample/misc/treestore.rb +63 -0
- data/sample/tutorial/README.md +368 -6
- data/test/test-gtk-box.rb +13 -0
- data/test/test-gtk-builder.rb +1 -1
- data/test/test-gtk-clipboard.rb +124 -0
- data/test/test-gtk-container.rb +3 -3
- data/test/test-gtk-entry-buffer.rb +32 -0
- data/test/test-gtk-list-store.rb +30 -12
- data/test/test-gtk-menu.rb +32 -0
- data/test/test-gtk-tree-iter.rb +61 -5
- data/test/test-gtk-tree-path.rb +26 -1
- data/test/test-gtk-tree-sortable.rb +35 -0
- data/test/test-gtk-tree-store.rb +34 -0
- data/test/test-gtk-widget.rb +33 -2
- metadata +55 -19
- data/sample/gtk-demo/button-box.rb +0 -82
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<interface>
|
3
|
+
<!-- interface-requires gtk+ 3.0 -->
|
4
|
+
<menu id="appmenu">
|
5
|
+
<section>
|
6
|
+
<item>
|
7
|
+
<attribute name="label" translatable="yes">_About</attribute>
|
8
|
+
<attribute name="action">app.about</attribute>
|
9
|
+
</item>
|
10
|
+
</section>
|
11
|
+
|
12
|
+
<section>
|
13
|
+
<item>
|
14
|
+
<attribute name="label" translatable="yes">_Quit</attribute>
|
15
|
+
<attribute name="action">app.quit</attribute>
|
16
|
+
</item>
|
17
|
+
</section>
|
18
|
+
</menu>
|
19
|
+
</interface>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<interface>
|
3
|
+
<!-- interface-requires gtk+ 3.0 -->
|
4
|
+
<menu id="buttonmenu">
|
5
|
+
<section>
|
6
|
+
<attribute name="display-hint">horizontal-buttons</attribute>
|
7
|
+
<item>
|
8
|
+
<attribute name="label">Copy</attribute>
|
9
|
+
<attribute name="action">app.copy</attribute>
|
10
|
+
<attribute name="verb-icon">edit-copy-symbolic</attribute>
|
11
|
+
</item>
|
12
|
+
<item>
|
13
|
+
<attribute name="label">Paste</attribute>
|
14
|
+
<attribute name="action">app.paste</attribute>
|
15
|
+
<attribute name="verb-icon">edit-paste-symbolic</attribute>
|
16
|
+
</item>
|
17
|
+
</section>
|
18
|
+
</menu>
|
19
|
+
</interface>
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
icons-theme-viewer.rb - Ruby/GTK sample script.
|
4
|
+
|
5
|
+
Copyright (c) 2016 Ruby-GNOME2 Project Team
|
6
|
+
This program is licenced under the same licence as Ruby-GNOME2.
|
7
|
+
=end
|
8
|
+
|
9
|
+
require "gtk3"
|
10
|
+
|
11
|
+
def fill_model(icons)
|
12
|
+
model = Gtk::ListStore.new(String, Gdk::Pixbuf)
|
13
|
+
icons.each do |icon|
|
14
|
+
pixbuf = Gtk::IconTheme.default.load_icon(icon, 32, 0)
|
15
|
+
iter = model.append
|
16
|
+
iter[0] = icon
|
17
|
+
iter[1] = pixbuf
|
18
|
+
end
|
19
|
+
model
|
20
|
+
end
|
21
|
+
|
22
|
+
def gen_icon_view(pattern, context = nil)
|
23
|
+
icon_theme = Gtk::IconTheme.default
|
24
|
+
icons = icon_theme.icons(context).grep(/#{pattern}/)
|
25
|
+
model = fill_model(icons)
|
26
|
+
icon_view = Gtk::IconView.new(:model => model)
|
27
|
+
icon_view.text_column = 0
|
28
|
+
icon_view.pixbuf_column = 1
|
29
|
+
icon_view
|
30
|
+
end
|
31
|
+
|
32
|
+
window = Gtk::Window.new("View all your icons")
|
33
|
+
window.set_default_size(700, 700)
|
34
|
+
window.signal_connect("delete-event") { Gtk.main_quit }
|
35
|
+
|
36
|
+
icon_view = gen_icon_view("application")
|
37
|
+
sw = Gtk::ScrolledWindow.new(nil, nil)
|
38
|
+
sw.add(icon_view)
|
39
|
+
|
40
|
+
entry = Gtk::Entry.new
|
41
|
+
entry.buffer.text = "application"
|
42
|
+
entry.tooltip_text = "Use a pattern to filter icons"
|
43
|
+
entry.set_icon_from_icon_name(:secondary, "edit-clear")
|
44
|
+
entry.set_icon_tooltip_text(:secondary, "Reset pattern")
|
45
|
+
|
46
|
+
entry.signal_connect "icon-release" do |widget, position|
|
47
|
+
widget.buffer.text = "" if position == :secondary
|
48
|
+
end
|
49
|
+
|
50
|
+
entry.signal_connect "activate" do |widget|
|
51
|
+
sw.remove(icon_view)
|
52
|
+
pattern = widget.buffer.text
|
53
|
+
icon_view = gen_icon_view(pattern)
|
54
|
+
sw.add(icon_view)
|
55
|
+
window.show_all
|
56
|
+
end
|
57
|
+
|
58
|
+
box = Gtk::Box.new(:vertical, 0)
|
59
|
+
box.pack_start(entry)
|
60
|
+
box.pack_start(sw, :expand => true, :fill => true)
|
61
|
+
|
62
|
+
window.add(box)
|
63
|
+
window.show_all
|
64
|
+
|
65
|
+
Gtk.main
|
data/sample/misc/menu.rb
CHANGED
@@ -64,15 +64,15 @@ menubar = Gtk::MenuBar.new
|
|
64
64
|
box1.pack_start(menubar, :expand => false, :fill => true, :padding => 0)
|
65
65
|
|
66
66
|
menu = create_menu(2)
|
67
|
-
menuitem = Gtk::MenuItem.new("test\nline2")
|
67
|
+
menuitem = Gtk::MenuItem.new(:label => "test\nline2")
|
68
68
|
menuitem.set_submenu(menu)
|
69
69
|
menubar.append(menuitem)
|
70
70
|
|
71
|
-
menuitem = Gtk::MenuItem.new("foo")
|
71
|
+
menuitem = Gtk::MenuItem.new(:label => "foo")
|
72
72
|
menuitem.set_submenu(create_menu(3))
|
73
73
|
menubar.append(menuitem)
|
74
74
|
|
75
|
-
menuitem = Gtk::MenuItem.new("bar")
|
75
|
+
menuitem = Gtk::MenuItem.new(:label => "bar")
|
76
76
|
menuitem.set_submenu(create_menu(4))
|
77
77
|
menubar.append(menuitem)
|
78
78
|
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<gresources>
|
3
|
+
<gresource prefix="/org/gtk/menus_from_resources">
|
4
|
+
<file preprocess="xml-stripblanks">app-menu.ui</file>
|
5
|
+
<file preprocess="xml-stripblanks">toolbar-menu.ui</file>
|
6
|
+
<file preprocess="xml-stripblanks">button-menu.ui</file>
|
7
|
+
</gresource>
|
8
|
+
</gresources>
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
menus_from_resources.rb - Ruby/GTK sample script.
|
4
|
+
|
5
|
+
Copyright (c) 2016 Ruby-GNOME2 Project Team
|
6
|
+
This program is licenced under the same licence as Ruby-GNOME2.
|
7
|
+
=end
|
8
|
+
|
9
|
+
require "gtk3"
|
10
|
+
require "fileutils"
|
11
|
+
|
12
|
+
PATH = File.expand_path(File.dirname(__FILE__))
|
13
|
+
|
14
|
+
gresource_bin = "#{PATH}/menus_from_resources.gresource"
|
15
|
+
gresource_xml = "#{PATH}/menus_from_resources.gresource.xml"
|
16
|
+
|
17
|
+
system("glib-compile-resources",
|
18
|
+
"--target", gresource_bin,
|
19
|
+
"--sourcedir", File.dirname(gresource_xml),
|
20
|
+
gresource_xml)
|
21
|
+
|
22
|
+
at_exit do
|
23
|
+
FileUtils.rm_f(gresource_bin)
|
24
|
+
end
|
25
|
+
|
26
|
+
resource = Gio::Resource.load(gresource_bin)
|
27
|
+
Gio::Resources.register(resource)
|
28
|
+
|
29
|
+
application_instance = Gtk::Application.new("org.gtk.menus_from_resources",
|
30
|
+
:non_unique)
|
31
|
+
|
32
|
+
application_instance.signal_connect "startup" do |application|
|
33
|
+
%w(about preferences quit copy paste open save close).each do |label|
|
34
|
+
action = Gio::SimpleAction.new(label)
|
35
|
+
action.signal_connect("activate") do |_action, _parameter|
|
36
|
+
puts label
|
37
|
+
end
|
38
|
+
application.add_action(action)
|
39
|
+
end
|
40
|
+
builder = Gtk::Builder.new(:resource => "/org/gtk/menus_from_resources/app-menu.ui")
|
41
|
+
app_menu = builder["appmenu"]
|
42
|
+
application.set_app_menu(app_menu)
|
43
|
+
end
|
44
|
+
|
45
|
+
application_instance.signal_connect "activate" do |application|
|
46
|
+
window = Gtk::ApplicationWindow.new(application)
|
47
|
+
window.set_default_size(200, 200)
|
48
|
+
window.border_width = 20
|
49
|
+
|
50
|
+
toolbar = Gtk::Toolbar.new
|
51
|
+
toolbar.style = :both
|
52
|
+
toolbutton = Gtk::ToolButton.new(:label => "Open a Menu", :stock_id => Gtk::Stock::OPEN)
|
53
|
+
toolbutton.signal_connect "clicked" do |widget|
|
54
|
+
builder = Gtk::Builder.new(:resource => "/org/gtk/menus_from_resources/toolbar-menu.ui")
|
55
|
+
menu = Gtk::Menu.new(builder["toolbarmenu"])
|
56
|
+
# This method is important, it links the menu to the
|
57
|
+
# Gio::Actions of the Gtk::Application throught one of
|
58
|
+
# its children
|
59
|
+
menu.attach_to_widget(widget)
|
60
|
+
|
61
|
+
menu.show_all
|
62
|
+
event = Gtk.current_event
|
63
|
+
menu.popup(nil, nil, event.button, event.time)
|
64
|
+
end
|
65
|
+
toolbar.insert(toolbutton, 0)
|
66
|
+
|
67
|
+
button = Gtk::Button.new(:label => "Click me")
|
68
|
+
button.signal_connect "clicked" do |widget|
|
69
|
+
builder = Gtk::Builder.new(:resource => "/org/gtk/menus_from_resources/button-menu.ui")
|
70
|
+
menu = Gtk::Popover.new(widget, builder["buttonmenu"])
|
71
|
+
event = Gtk.current_event
|
72
|
+
x, y = event.window.coords_to_parent(event.x,
|
73
|
+
event.y)
|
74
|
+
rect = Gdk::Rectangle.new(x - widget.allocation.x,
|
75
|
+
y - widget.allocation.y,
|
76
|
+
1,
|
77
|
+
1)
|
78
|
+
menu.set_pointing_to(rect)
|
79
|
+
menu.show
|
80
|
+
end
|
81
|
+
hbox = Gtk::Box.new(:vertical, 0)
|
82
|
+
|
83
|
+
hbox.pack_start(toolbar, :expand => false, :fill => false)
|
84
|
+
hbox.pack_start(button, :expand => true, :fill => true)
|
85
|
+
window.add(hbox)
|
86
|
+
|
87
|
+
window.show_all
|
88
|
+
window.present
|
89
|
+
end
|
90
|
+
|
91
|
+
application_instance.run
|
data/sample/misc/statusicon.rb
CHANGED
@@ -28,7 +28,7 @@ class StatusIconSample < Gtk::StatusIcon
|
|
28
28
|
signal_connect("popup-menu") do |w, button, activate_time|
|
29
29
|
menu = Gtk::Menu.new
|
30
30
|
|
31
|
-
menuitem = Gtk::MenuItem.new("Quit")
|
31
|
+
menuitem = Gtk::MenuItem.new(:label => "Quit")
|
32
32
|
menuitem.signal_connect("activate") do
|
33
33
|
set_visible(false)
|
34
34
|
Gtk.main_quit
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<interface>
|
3
|
+
<!-- interface-requires gtk+ 3.0 -->
|
4
|
+
<menu id="toolbarmenu">
|
5
|
+
<section>
|
6
|
+
<item>
|
7
|
+
<attribute name="label" translatable="yes">_Open</attribute>
|
8
|
+
<attribute name="action">app.open</attribute>
|
9
|
+
</item>
|
10
|
+
<item>
|
11
|
+
<attribute name="label" translatable="yes">_Save</attribute>
|
12
|
+
<attribute name="action">app.save</attribute>
|
13
|
+
</item>
|
14
|
+
</section>
|
15
|
+
|
16
|
+
<section>
|
17
|
+
<item>
|
18
|
+
<attribute name="label" translatable="yes">_Close</attribute>
|
19
|
+
<attribute name="action">app.close</attribute>
|
20
|
+
</item>
|
21
|
+
</section>
|
22
|
+
</menu>
|
23
|
+
</interface>
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
treestore.rb - Gtk::TreeStore sample
|
4
|
+
|
5
|
+
Copyright (c) 2016 Ruby-GNOME2 Project Team
|
6
|
+
This program is licenced under the same licence as Ruby-GNOME2.
|
7
|
+
Based on https://developer.gnome.org/gtk3/stable/TreeWidget.html
|
8
|
+
=end
|
9
|
+
|
10
|
+
require "gtk3"
|
11
|
+
|
12
|
+
TITLE_COLUMN = 0
|
13
|
+
AUTHOR_COLUMN = 1
|
14
|
+
CHECKED_COLUMN = 2
|
15
|
+
|
16
|
+
model = Gtk::TreeStore.new(String, String, TrueClass)
|
17
|
+
iter = model.append(nil)
|
18
|
+
iter[TITLE_COLUMN] = "The Principle of Reason"
|
19
|
+
iter[AUTHOR_COLUMN] = "Martin Heidegger"
|
20
|
+
iter[CHECKED_COLUMN] = false
|
21
|
+
|
22
|
+
iter = model.append(nil)
|
23
|
+
iter.set_values(["The Art of Computer Programming", "Donald E. Knuth", true])
|
24
|
+
|
25
|
+
# append child
|
26
|
+
child_iter = model.append(iter)
|
27
|
+
child_iter[TITLE_COLUMN] = "Volume 1: Fundamental Algorithms"
|
28
|
+
|
29
|
+
# append another child
|
30
|
+
child_iter = model.append(iter)
|
31
|
+
child_iter.set_value(TITLE_COLUMN, "Volume 2: Seminumerical Algorithms")
|
32
|
+
child_iter.set_value(CHECKED_COLUMN, true)
|
33
|
+
|
34
|
+
# append another child
|
35
|
+
child_iter = model.append(iter)
|
36
|
+
child_iter.set_values(["Volume 3: Sorting and Searching",
|
37
|
+
"Donald E. Knuth",
|
38
|
+
true])
|
39
|
+
|
40
|
+
def treeview_widget_of(model)
|
41
|
+
treeview = Gtk::TreeView.new(model)
|
42
|
+
treeview.append_column(Gtk::TreeViewColumn.new("Title",
|
43
|
+
Gtk::CellRendererText.new,
|
44
|
+
:text => TITLE_COLUMN))
|
45
|
+
treeview.append_column(Gtk::TreeViewColumn.new("Author",
|
46
|
+
Gtk::CellRendererText.new,
|
47
|
+
:text => AUTHOR_COLUMN))
|
48
|
+
treeview.append_column(Gtk::TreeViewColumn.new("Author",
|
49
|
+
Gtk::CellRendererToggle.new,
|
50
|
+
:active => CHECKED_COLUMN))
|
51
|
+
treeview
|
52
|
+
end
|
53
|
+
|
54
|
+
def display_model(model)
|
55
|
+
win = Gtk::Window.new(:toplevel)
|
56
|
+
win.title = "Simple Gtk::TreeStore"
|
57
|
+
win.add(treeview_widget_of(model))
|
58
|
+
win.show_all
|
59
|
+
win.signal_connect("destroy") { Gtk.main_quit }
|
60
|
+
Gtk.main
|
61
|
+
end
|
62
|
+
|
63
|
+
display_model(model)
|
data/sample/tutorial/README.md
CHANGED
@@ -32,6 +32,28 @@ Gtk.main
|
|
32
32
|
```
|
33
33
|
This tutorial will mainly be focused on the use of Gtk::Application, which is the best way to create an application.
|
34
34
|
|
35
|
+
## Table of Contents
|
36
|
+
* [Basics](#basics)
|
37
|
+
* [Packing](#packing)
|
38
|
+
* [Building user interfaces](#building-user-interfaces)
|
39
|
+
* [Building Applications](#building-applications)
|
40
|
+
* [A trivial application](#a trivial application)
|
41
|
+
* [Populating the window](#populating-the-window)
|
42
|
+
* [Link a template to a custom class widget](#link-a-template-to-a-custom-class-widget)
|
43
|
+
* [Load a resource file](#load-a-resource-file)
|
44
|
+
* [Opening files](#opening-file)
|
45
|
+
* [An application menu](#an-application-menu)
|
46
|
+
* [Adding the menu interface](#adding-the-menu-interface)
|
47
|
+
* [Linking menu items to actions](#linking-menu-items-to-actions)
|
48
|
+
* [Add accelerators for an action](#add-accelerators-for-an-action)
|
49
|
+
* [A preference dialog](#a-preference-dialog)
|
50
|
+
* [Define and store settings for an application with gschemas](#define-and-store-settings-for-an-application-with-gschemas)
|
51
|
+
* [Configure the settings with a dialog window](#configure-the-settings-with-a-dialog-window)
|
52
|
+
* [Adding a search bar](#adding-a-search-bar)
|
53
|
+
* [Adding a sidebar](#adding-a-sidebar)
|
54
|
+
* [Properties](#properties)
|
55
|
+
* [Header Bar](#header-bar)
|
56
|
+
|
35
57
|
## Basics
|
36
58
|
https://developer.gnome.org/gtk3/stable/gtk-getting-started.html#id-1.2.3.5
|
37
59
|
|
@@ -54,7 +76,10 @@ puts app.run
|
|
54
76
|
|
55
77
|
```
|
56
78
|
When creating a Gtk::Application you need to pick an application identifier (a name) and input to `Gtk::Application#new` as parameter. For this example *org.gtk.example* is used but for choosing an identifier for your application see this [guide](https://wiki.gnome.org/HowDoI/ChooseApplicationID).
|
57
|
-
|
79
|
+
|
80
|
+
Lastly `Gtk::Application#new` takes a `Gio::ApplicationFlags` constants as input for your application, if your application would have special needs (those constants can be replaced by theirs respective symbol ie. `Gio::ApplicationFlags::NONE` == `:flags_none`). You must know that `GApplication` ignores arguments passed to `g_application_run()` on the Windows systems. It always uses command line arguments even when we pass an empty array to g_application_run().
|
81
|
+
|
82
|
+
If you plan to create a cross-platform application, it is recommanded to use the `:handles_command_line` flags and the *command-line* signal. (reference : https://github.com/ruby-gnome2/ruby-gnome2/issues/721 ).
|
58
83
|
|
59
84
|
Next we add instructions for the "activate" event of the `Gtk::Application` instance we created. The activate signal will be sent when your application is launched with the method `Gtk::Application#run` on the line below. This method also takes as arguments a ruby array of string. This allows GTK+ to parse specific command line arguments that control the behavior of GTK+ itself. The parsed arguments will be removed from the array, leaving the unrecognized ones for your application to parse.
|
60
85
|
|
@@ -516,7 +541,6 @@ stack.add_titled(scrolled, basename, basename)
|
|
516
541
|
|
517
542
|
In this line, given that `self` is `ExampleAppWindow` the usage of `stack` is a call to the method we have created previously. So here we add a tab with a `Gtk::ScrolledWindow` in the `Gtk::Stack` widget of our template and we display the file content.
|
518
543
|
|
519
|
-
|
520
544
|
### An application menu
|
521
545
|
https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.8
|
522
546
|
|
@@ -599,10 +623,10 @@ application.add_action(action)
|
|
599
623
|
application.set_accels_for_action("app.quit", quit_accels)
|
600
624
|
```
|
601
625
|
|
602
|
-
### A
|
626
|
+
### A preference dialog
|
603
627
|
https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.9
|
604
628
|
|
605
|
-
|
629
|
+
#### Define and store settings for an application with gschemas
|
606
630
|
* exampleapp5/exampleapp.rb
|
607
631
|
|
608
632
|
A typical application will have a some preferences that should be remembered from one run to the next. Even for our simple example application, we may want to change the font that is used for the content.
|
@@ -824,7 +848,7 @@ def open(file)
|
|
824
848
|
end
|
825
849
|
```
|
826
850
|
|
827
|
-
|
851
|
+
### Adding a search bar
|
828
852
|
https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.10
|
829
853
|
|
830
854
|
* exampleapp7/exampleapp.rb
|
@@ -934,5 +958,343 @@ In this part of code, the use of the method `set_connect_func` will allow us to
|
|
934
958
|
|
935
959
|
<signal name="search-changed" handler="search_text_changed"/>
|
936
960
|
|
937
|
-
Those pieces together mean that
|
961
|
+
Those pieces together mean that the signal *search-changed* of the `Gtk::SearchEntry`, trigger the private method of `ExampleAppWindow` that is called `search_text_changed`.
|
962
|
+
|
963
|
+
### Adding a sidebar
|
964
|
+
https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.11
|
965
|
+
|
966
|
+
* exampleapp8/exampleapp.rb
|
967
|
+
|
968
|
+
As another piece of functionality, we are adding a sidebar, which demonstrates `Gtk::MenuButton`, `Gtk::Revealer` and Gtk::ListBox`.
|
969
|
+
|
970
|
+
window.ui :
|
971
|
+
|
972
|
+
```xml
|
973
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
974
|
+
<interface>
|
975
|
+
<!-- interface-requires gtk+ 3.8 -->
|
976
|
+
<template class="ExampleAppWindow" parent="GtkApplicationWindow">
|
977
|
+
<property name="title" translatable="yes">Example Application</property>
|
978
|
+
<property name="default-width">600</property>
|
979
|
+
<property name="default-height">400</property>
|
980
|
+
<child>
|
981
|
+
<object class="GtkBox" id="content_box">
|
982
|
+
<property name="visible">True</property>
|
983
|
+
<property name="orientation">vertical</property>
|
984
|
+
<child>
|
985
|
+
<object class="GtkHeaderBar" id="header">
|
986
|
+
<property name="visible">True</property>
|
987
|
+
<child type="title">
|
988
|
+
<object class="GtkStackSwitcher" id="tabs">
|
989
|
+
<property name="visible">True</property>
|
990
|
+
<property name="margin">6</property>
|
991
|
+
<property name="stack">stack</property>
|
992
|
+
</object>
|
993
|
+
</child>
|
994
|
+
<child>
|
995
|
+
<object class="GtkToggleButton" id="search">
|
996
|
+
<property name="visible">True</property>
|
997
|
+
<property name="sensitive">False</property>
|
998
|
+
<style>
|
999
|
+
<class name="image-button"/>
|
1000
|
+
</style>
|
1001
|
+
<child>
|
1002
|
+
<object class="GtkImage" id="search-icon">
|
1003
|
+
<property name="visible">True</property>
|
1004
|
+
<property name="icon-name">edit-find-symbolic</property>
|
1005
|
+
<property name="icon-size">1</property>
|
1006
|
+
</object>
|
1007
|
+
</child>
|
1008
|
+
</object>
|
1009
|
+
<packing>
|
1010
|
+
<property name="pack-type">end</property>
|
1011
|
+
</packing>
|
1012
|
+
</child>
|
1013
|
+
<child>
|
1014
|
+
<object class="GtkMenuButton" id="gears">
|
1015
|
+
<property name="visible">True</property>
|
1016
|
+
<property name="direction">none</property>
|
1017
|
+
<property name="use-popover">True</property>
|
1018
|
+
<style>
|
1019
|
+
<class name="image-button"/>
|
1020
|
+
</style>
|
1021
|
+
</object>
|
1022
|
+
<packing>
|
1023
|
+
<property name="pack-type">end</property>
|
1024
|
+
</packing>
|
1025
|
+
</child>
|
1026
|
+
</object>
|
1027
|
+
</child>
|
1028
|
+
<child>
|
1029
|
+
<object class="GtkSearchBar" id="searchbar">
|
1030
|
+
<property name="visible">True</property>
|
1031
|
+
<child>
|
1032
|
+
<object class="GtkSearchEntry" id="searchentry">
|
1033
|
+
<signal name="search-changed" handler="search_text_changed"/>
|
1034
|
+
<property name="visible">True</property>
|
1035
|
+
</object>
|
1036
|
+
</child>
|
1037
|
+
</object>
|
1038
|
+
</child>
|
1039
|
+
<child>
|
1040
|
+
<object class="GtkBox" id="hbox">
|
1041
|
+
<property name="visible">True</property>
|
1042
|
+
<child>
|
1043
|
+
<object class="GtkRevealer" id="sidebar">
|
1044
|
+
<property name="visible">True</property>
|
1045
|
+
<property name="transition-type">slide-right</property>
|
1046
|
+
<child>
|
1047
|
+
<object class="GtkScrolledWindow" id="sidebar-sw">
|
1048
|
+
<property name="visible">True</property>
|
1049
|
+
<property name="hscrollbar-policy">never</property>
|
1050
|
+
<property name="vscrollbar-policy">automatic</property>
|
1051
|
+
<child>
|
1052
|
+
<object class="GtkListBox" id="words">
|
1053
|
+
<property name="visible">True</property>
|
1054
|
+
<property name="selection-mode">none</property>
|
1055
|
+
</object>
|
1056
|
+
</child>
|
1057
|
+
</object>
|
1058
|
+
</child>
|
1059
|
+
</object>
|
1060
|
+
</child>
|
1061
|
+
<child>
|
1062
|
+
<object class="GtkStack" id="stack">
|
1063
|
+
<signal name="notify::visible-child" handler="visible_child_changed"/>
|
1064
|
+
<property name="visible">True</property>
|
1065
|
+
</object>
|
1066
|
+
</child>
|
1067
|
+
</object>
|
1068
|
+
</child>
|
1069
|
+
</object>
|
1070
|
+
</child>
|
1071
|
+
</template>
|
1072
|
+
</interface>
|
1073
|
+
```
|
1074
|
+
|
1075
|
+
The code to populate the sidebar with buttons for the words found in each file is a little too involved to go into here. But we'll look at the code to add the gears menu.
|
1076
|
+
As expected by now, the gears menu is specified in a GtkBuilder ui file.
|
1077
|
+
|
1078
|
+
gears-menu.ui
|
1079
|
+
|
1080
|
+
```xml
|
1081
|
+
<?xml version="1.0"?>
|
1082
|
+
<interface>
|
1083
|
+
<!-- interface-requires gtk+ 3.0 -->
|
1084
|
+
<menu id="menu">
|
1085
|
+
<section>
|
1086
|
+
<item>
|
1087
|
+
<attribute name="label" translatable="yes">_Words</attribute>
|
1088
|
+
<attribute name="action">win.show-words</attribute>
|
1089
|
+
</item>
|
1090
|
+
</section>
|
1091
|
+
</menu>
|
1092
|
+
</interface>
|
1093
|
+
```
|
1094
|
+
To connect the menuitem to the show-words setting, we use a `Gio::SimpleAction` corresponding to the given `Gio::Settings` key.
|
1095
|
+
|
1096
|
+
```ruby
|
1097
|
+
class ExampleAppWindow < Gtk::ApplicationWindow
|
1098
|
+
# some code
|
1099
|
+
def initialize(application)
|
1100
|
+
super(:application => application)
|
1101
|
+
@settings = Gio::Settings.new("org.gtk.exampleapp")
|
1102
|
+
@settings.bind("transition",
|
1103
|
+
stack,
|
1104
|
+
"transition-type",
|
1105
|
+
Gio::SettingsBindFlags::DEFAULT)
|
1106
|
+
search.bind_property("active", searchbar, "search-mode-enabled", :bidirectional)
|
1107
|
+
@settings.bind("show-words",
|
1108
|
+
sidebar,
|
1109
|
+
"reveal-child",
|
1110
|
+
Gio::SettingsBindFlags::DEFAULT)
|
1111
|
+
sidebar.signal_connect "notify::reveal-child" do |_sidebar, _gparamspec|
|
1112
|
+
update_words(self)
|
1113
|
+
end
|
1114
|
+
builder = Gtk::Builder.new(:resource => "/org/gtk/exampleapp/gears-menu.ui")
|
1115
|
+
menu = builder.get_object("menu")
|
1116
|
+
gears.set_menu_model(menu)
|
1117
|
+
action = @settings.create_action("show-words")
|
1118
|
+
add_action(action)
|
1119
|
+
end
|
1120
|
+
|
1121
|
+
# some code
|
1122
|
+
end
|
1123
|
+
```
|
1124
|
+
|
1125
|
+
### Properties
|
1126
|
+
|
1127
|
+
https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.12
|
1128
|
+
|
1129
|
+
Widgets and other objects have many useful properties.
|
1130
|
+
|
1131
|
+
Here we show some ways to use them in new and flexible ways, by wrapping them in actions with `Gio::PropertyAction` or by binding them with `Gio::Binding`.
|
1132
|
+
To set this up, we add two labels to the header bar in our window template, named *lines_label* and *lines*, and bind them to struct members in the private struct, as we've seen a couple of times by now.
|
1133
|
+
We add a new "Lines" menu item to the gears menu, which triggers the show-lines action:
|
1134
|
+
|
1135
|
+
```xml
|
1136
|
+
<?xml version="1.0"?>
|
1137
|
+
<interface>
|
1138
|
+
<!-- interface-requires gtk+ 3.0 -->
|
1139
|
+
<menu id="menu">
|
1140
|
+
<section>
|
1141
|
+
<item>
|
1142
|
+
<attribute name="label" translatable="yes">_Words</attribute>
|
1143
|
+
<attribute name="action">win.show-words</attribute>
|
1144
|
+
</item>
|
1145
|
+
<item>
|
1146
|
+
<attribute name="label" translatable="yes">_Lines</attribute>
|
1147
|
+
<attribute name="action">win.show-lines</attribute>
|
1148
|
+
</item>
|
1149
|
+
</section>
|
1150
|
+
</menu>
|
1151
|
+
</interface>
|
1152
|
+
```
|
1153
|
+
|
1154
|
+
To make this menu item do something, we create a property action for the visible property of the lines label, and add it to the actions of the window. The effect of this is that the visibility of the label gets toggled every time the action is activated.
|
1155
|
+
Since we want both labels to appear and disappear together, we bind the visible property of the lines_label widget to the same property of the lines widget.
|
1156
|
+
|
1157
|
+
* exampleapp9/exampleapp.rb
|
1158
|
+
|
1159
|
+
```ruby
|
1160
|
+
# ...
|
1161
|
+
class ExampleAppWindow < Gtk::ApplicationWindow
|
1162
|
+
# ...
|
1163
|
+
def initialize(application)
|
1164
|
+
super(:application => application)
|
1165
|
+
# ...
|
1166
|
+
action = Gio::PropertyAction.new("show-lines", lines, "visible")
|
1167
|
+
add_action(action)
|
1168
|
+
lines.bind_property("visible", lines_label, "visible", :default)
|
1169
|
+
end
|
1170
|
+
```
|
1171
|
+
We also need a function that counts the lines of the currently active tab, and updates the lines label. See the full source if you are interested in the details.
|
1172
|
+
|
1173
|
+
### Header Bar
|
1174
|
+
|
1175
|
+
https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.13
|
1176
|
+
|
1177
|
+
Our application already uses a `Gtk::HeaderBar`, but so far it still gets a 'normal' window titlebar on top of that. This is a bit redundant, and we will now tell GTK+ to use the header bar as replacement for the titlebar. To do so, we move it around to be a direct child of the window, and set its type to be titlebar.
|
1178
|
+
|
1179
|
+
```xml
|
1180
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
1181
|
+
<interface>
|
1182
|
+
<!-- interface-requires gtk+ 3.8 -->
|
1183
|
+
<template class="ExampleAppWindow" parent="GtkApplicationWindow">
|
1184
|
+
<property name="title" translatable="yes">Example Application</property>
|
1185
|
+
<property name="default-width">600</property>
|
1186
|
+
<property name="default-height">400</property>
|
1187
|
+
<child type="titlebar">
|
1188
|
+
<object class="GtkHeaderBar" id="header">
|
1189
|
+
<property name="visible">True</property>
|
1190
|
+
<property name="show-close-button">True</property>
|
1191
|
+
<child>
|
1192
|
+
<object class="GtkLabel" id="lines_label">
|
1193
|
+
<property name="visible">False</property>
|
1194
|
+
<property name="label" translatable="yes">Lines:</property>
|
1195
|
+
</object>
|
1196
|
+
<packing>
|
1197
|
+
<property name="pack-type">start</property>
|
1198
|
+
</packing>
|
1199
|
+
</child>
|
1200
|
+
<child>
|
1201
|
+
<object class="GtkLabel" id="lines">
|
1202
|
+
<property name="visible">False</property>
|
1203
|
+
</object>
|
1204
|
+
<packing>
|
1205
|
+
<property name="pack-type">start</property>
|
1206
|
+
</packing>
|
1207
|
+
</child>
|
1208
|
+
<child type="title">
|
1209
|
+
<object class="GtkStackSwitcher" id="tabs">
|
1210
|
+
<property name="visible">True</property>
|
1211
|
+
<property name="margin">6</property>
|
1212
|
+
<property name="stack">stack</property>
|
1213
|
+
</object>
|
1214
|
+
</child>
|
1215
|
+
<child>
|
1216
|
+
<object class="GtkToggleButton" id="search">
|
1217
|
+
<property name="visible">True</property>
|
1218
|
+
<property name="sensitive">False</property>
|
1219
|
+
<style>
|
1220
|
+
<class name="image-button"/>
|
1221
|
+
</style>
|
1222
|
+
<child>
|
1223
|
+
<object class="GtkImage" id="search-icon">
|
1224
|
+
<property name="visible">True</property>
|
1225
|
+
<property name="icon-name">edit-find-symbolic</property>
|
1226
|
+
<property name="icon-size">1</property>
|
1227
|
+
</object>
|
1228
|
+
</child>
|
1229
|
+
</object>
|
1230
|
+
<packing>
|
1231
|
+
<property name="pack-type">end</property>
|
1232
|
+
</packing>
|
1233
|
+
</child>
|
1234
|
+
<child>
|
1235
|
+
<object class="GtkMenuButton" id="gears">
|
1236
|
+
<property name="visible">True</property>
|
1237
|
+
<property name="direction">none</property>
|
1238
|
+
<property name="use-popover">True</property>
|
1239
|
+
<style>
|
1240
|
+
<class name="image-button"/>
|
1241
|
+
</style>
|
1242
|
+
</object>
|
1243
|
+
<packing>
|
1244
|
+
<property name="pack-type">end</property>
|
1245
|
+
</packing>
|
1246
|
+
</child>
|
1247
|
+
</object>
|
1248
|
+
</child>
|
1249
|
+
<child>
|
1250
|
+
<object class="GtkBox" id="content_box">
|
1251
|
+
<property name="visible">True</property>
|
1252
|
+
<property name="orientation">vertical</property>
|
1253
|
+
<child>
|
1254
|
+
<object class="GtkSearchBar" id="searchbar">
|
1255
|
+
<property name="visible">True</property>
|
1256
|
+
<child>
|
1257
|
+
<object class="GtkSearchEntry" id="searchentry">
|
1258
|
+
<signal name="search-changed" handler="search_text_changed"/>
|
1259
|
+
<property name="visible">True</property>
|
1260
|
+
</object>
|
1261
|
+
</child>
|
1262
|
+
</object>
|
1263
|
+
</child>
|
1264
|
+
<child>
|
1265
|
+
<object class="GtkBox" id="hbox">
|
1266
|
+
<property name="visible">True</property>
|
1267
|
+
<child>
|
1268
|
+
<object class="GtkRevealer" id="sidebar">
|
1269
|
+
<property name="visible">True</property>
|
1270
|
+
<property name="transition-type">slide-right</property>
|
1271
|
+
<child>
|
1272
|
+
<object class="GtkScrolledWindow" id="sidebar-sw">
|
1273
|
+
<property name="visible">True</property>
|
1274
|
+
<property name="hscrollbar-policy">never</property>
|
1275
|
+
<property name="vscrollbar-policy">automatic</property>
|
1276
|
+
<child>
|
1277
|
+
<object class="GtkListBox" id="words">
|
1278
|
+
<property name="visible">True</property>
|
1279
|
+
<property name="selection-mode">none</property>
|
1280
|
+
</object>
|
1281
|
+
</child>
|
1282
|
+
</object>
|
1283
|
+
</child>
|
1284
|
+
</object>
|
1285
|
+
</child>
|
1286
|
+
<child>
|
1287
|
+
<object class="GtkStack" id="stack">
|
1288
|
+
<signal name="notify::visible-child" handler="visible_child_changed"/>
|
1289
|
+
<property name="visible">True</property>
|
1290
|
+
</object>
|
1291
|
+
</child>
|
1292
|
+
</object>
|
1293
|
+
</child>
|
1294
|
+
</object>
|
1295
|
+
</child>
|
1296
|
+
</template>
|
1297
|
+
</interface>
|
1298
|
+
```
|
938
1299
|
|
1300
|
+
A small extra bonus of using a header bar is that we get a fallback application menu for free.
|