gtk3 3.0.9-x64-mingw32 → 3.1.0-x64-mingw32
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.
- checksums.yaml +4 -4
- data/ext/gtk3/rb-gtk3-private.h +1 -0
- data/ext/gtk3/rb-gtk3-spin-button.c +85 -0
- data/ext/gtk3/rb-gtk3.c +3 -0
- data/lib/2.2/gtk3.so +0 -0
- data/lib/2.3/gtk3.so +0 -0
- data/lib/gtk3/deprecated.rb +0 -8
- data/lib/gtk3/loader.rb +1 -7
- data/lib/gtk3/tree-model.rb +2 -0
- data/sample/gtk-demo/TODO +10 -10
- data/sample/gtk-demo/assistant.rb +44 -39
- data/sample/gtk-demo/builder.rb +71 -50
- data/sample/gtk-demo/button_box.rb +39 -28
- data/sample/gtk-demo/clipboard.rb +139 -46
- data/sample/gtk-demo/colorsel.rb +50 -36
- data/sample/gtk-demo/css_accordion.rb +18 -17
- data/sample/gtk-demo/css_basics.rb +60 -47
- data/sample/gtk-demo/css_multiplebgs.rb +92 -71
- data/sample/gtk-demo/css_pixbufs.rb +61 -48
- data/sample/gtk-demo/css_shadows.rb +63 -50
- data/sample/gtk-demo/cursors.rb +95 -64
- data/sample/gtk-demo/dialog.rb +95 -78
- data/sample/gtk-demo/drawingarea.rb +138 -171
- data/sample/gtk-demo/editable_cells.rb +169 -130
- data/sample/gtk-demo/entry_buffer.rb +15 -13
- data/sample/gtk-demo/entry_completion.rb +22 -17
- data/sample/gtk-demo/expander.rb +39 -31
- data/sample/gtk-demo/filtermodel.rb +67 -63
- data/sample/gtk-demo/font_features.rb +91 -60
- data/sample/gtk-demo/glarea.rb +277 -0
- data/sample/gtk-demo/headerbar.rb +17 -15
- data/sample/gtk-demo/hypertext.rb +146 -167
- data/sample/gtk-demo/iconview.rb +132 -91
- data/sample/gtk-demo/iconview_edit.rb +49 -38
- data/sample/gtk-demo/infobar.rb +81 -62
- data/sample/gtk-demo/links.rb +35 -30
- data/sample/gtk-demo/list_store.rb +169 -114
- data/sample/gtk-demo/listbox.rb +183 -0
- data/sample/gtk-demo/main.rb +32 -21
- data/sample/gtk-demo/markup.rb +65 -52
- data/sample/gtk-demo/menus.rb +57 -58
- data/sample/gtk-demo/modelbutton.rb +11 -9
- data/sample/gtk-demo/modelbutton.ui +3 -0
- data/sample/gtk-demo/overlay.rb +39 -32
- data/sample/gtk-demo/overlay2.rb +68 -54
- data/sample/gtk-demo/panes.rb +56 -68
- data/sample/gtk-demo/pickers.rb +46 -45
- data/sample/gtk-demo/pixbufs.rb +27 -25
- data/sample/gtk-demo/popover.rb +70 -63
- data/sample/gtk-demo/printing.rb +94 -69
- data/sample/gtk-demo/revealer.rb +46 -38
- data/sample/gtk-demo/rotated_text.rb +75 -54
- data/sample/gtk-demo/scale.rb +10 -8
- data/sample/gtk-demo/search_entry.rb +195 -0
- data/sample/gtk-demo/search_entry2.rb +71 -59
- data/sample/gtk-demo/sidebar.rb +20 -19
- data/sample/gtk-demo/sizegroup.rb +36 -35
- data/sample/gtk-demo/spinbutton.rb +128 -0
- data/sample/gtk-demo/spinner.rb +55 -40
- data/sample/gtk-demo/stack.rb +11 -8
- data/sample/gtk-demo/textmask.rb +14 -13
- data/sample/gtk-demo/textscroll.rb +16 -12
- data/sample/gtk-demo/theming_style_classes.rb +14 -12
- data/sample/gtk-demo/transparent.rb +17 -13
- data/sample/misc/treemodelfilter.rb +1 -1
- metadata +24 -19
data/sample/gtk-demo/links.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2015 Ruby-GNOME2 Project Team
|
1
|
+
# Copyright (c) 2015-2016 Ruby-GNOME2 Project Team
|
2
2
|
# This program is licenced under the same licence as Ruby-GNOME2.
|
3
3
|
#
|
4
4
|
=begin
|
@@ -8,12 +8,12 @@ GtkLabel can show hyperlinks. The default action is to call
|
|
8
8
|
gtk_show_uri() on their URI, but it is possible to override
|
9
9
|
this with a custom handler.
|
10
10
|
=end
|
11
|
-
|
12
|
-
def
|
13
|
-
window = Gtk::Window.new(:toplevel)
|
14
|
-
window.screen = main_window.screen
|
15
|
-
window.
|
16
|
-
window.
|
11
|
+
class LinksDemo
|
12
|
+
def initialize(main_window)
|
13
|
+
@window = Gtk::Window.new(:toplevel)
|
14
|
+
@window.screen = main_window.screen
|
15
|
+
@window.title = "Links"
|
16
|
+
@window.border_width = 12
|
17
17
|
|
18
18
|
label = Gtk::Label.new(<<-MESSAGE)
|
19
19
|
Some <a href="http://en.wikipedia.org/wiki/Text"
|
@@ -27,40 +27,45 @@ searching on <a href="http://www.google.com/">
|
|
27
27
|
<span color="#00933B">l</span><span color="#F90101">e</span>
|
28
28
|
</a>.
|
29
29
|
MESSAGE
|
30
|
-
label.
|
30
|
+
label.use_markup = true
|
31
31
|
|
32
|
-
label.signal_connect "activate-link" do |
|
32
|
+
label.signal_connect "activate-link" do |widget, uri|
|
33
33
|
if uri == "keynav"
|
34
|
-
|
35
|
-
dialog = Gtk::MessageDialog.new(:parent => parent,
|
36
|
-
:flags => :destroy_with_parent,
|
37
|
-
:type => :info,
|
38
|
-
:buttons => :ok,
|
39
|
-
:message => <<-MESSAGE)
|
40
|
-
The term <i>keynav</i> is a shorthand for
|
41
|
-
keyboard navigation and refers to the process of using
|
42
|
-
a program (exclusively) via keyboard input.
|
43
|
-
MESSAGE
|
44
|
-
dialog.set_use_markup(true)
|
45
|
-
dialog.set_modal(true)
|
46
|
-
dialog.present
|
47
|
-
dialog.signal_connect "response" do
|
48
|
-
dialog.destroy
|
49
|
-
end
|
34
|
+
generate_dialog(widget)
|
50
35
|
true
|
51
36
|
else
|
52
37
|
false
|
53
38
|
end
|
54
39
|
end
|
55
40
|
|
56
|
-
window.add(label)
|
41
|
+
@window.add(label)
|
57
42
|
label.show
|
43
|
+
end
|
58
44
|
|
59
|
-
|
60
|
-
|
45
|
+
def run
|
46
|
+
if !@window.visible?
|
47
|
+
@window.show_all
|
61
48
|
else
|
62
|
-
window.destroy
|
49
|
+
@window.destroy
|
63
50
|
end
|
64
|
-
window
|
51
|
+
@window
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def generate_dialog(widget)
|
57
|
+
dialog = Gtk::MessageDialog.new(:parent => widget.toplevel,
|
58
|
+
:flags => :destroy_with_parent,
|
59
|
+
:type => :info,
|
60
|
+
:buttons => :ok,
|
61
|
+
:message => <<-MESSAGE)
|
62
|
+
The term <i>keynav</i> is a shorthand for
|
63
|
+
keyboard navigation and refers to the process of using
|
64
|
+
a program (exclusively) via keyboard input.
|
65
|
+
MESSAGE
|
66
|
+
dialog.use_markup = true
|
67
|
+
dialog.modal = true
|
68
|
+
dialog.present
|
69
|
+
dialog.signal_connect("response", &:destroy)
|
65
70
|
end
|
66
71
|
end
|
@@ -1,138 +1,193 @@
|
|
1
|
-
# Copyright (c)
|
1
|
+
# Copyright (c) 2016 Ruby-GNOME2 Project Team
|
2
2
|
# This program is licenced under the same licence as Ruby-GNOME2.
|
3
3
|
#
|
4
|
-
# $Id: list_store.rb,v 1.5 2005/02/06 18:25:13 kzys Exp $
|
5
4
|
=begin
|
6
|
-
=
|
5
|
+
= Tree View/List Store
|
7
6
|
|
8
|
-
The
|
9
|
-
later on by a
|
10
|
-
simple
|
11
|
-
demo for a more advanced example.
|
12
|
-
=end
|
13
|
-
require 'common'
|
14
|
-
|
15
|
-
module Demo
|
16
|
-
class ListStore < BasicWindow
|
17
|
-
Bug = Struct.new('Bug', :fixed, :number, :severity, :description)
|
18
|
-
COLUMN_FIXED, COLUMN_NUMBER, COLUMN_SEVERITY, COLUMN_DESCRIPTION,
|
19
|
-
NUM_COLUMNS = *(0..5).to_a
|
20
|
-
DATA = [
|
21
|
-
[ false, 60482, 'Normal', 'scrollable notebooks and hidden tabs' ],
|
22
|
-
[ false, 60620, 'Critical', 'gdk_window_clear_area (gdkwindow-win32.c) is not thread-safe' ],
|
23
|
-
[ false, 50214, 'Major', 'Xft support does not clean up correctly' ],
|
24
|
-
[ true, 52877, 'Major', 'GtkFileSelection needs a refresh method. ' ],
|
25
|
-
[ false, 56070, 'Normal', "Can't click button after setting in sensitive" ],
|
26
|
-
[ true, 56355, 'Normal', 'GtkLabel - Not all changes propagate correctly' ],
|
27
|
-
[ false, 50055, 'Normal', 'Rework width/height computations for TreeView' ],
|
28
|
-
[ false, 58278, 'Normal', "gtk_dialog_set_response_sensitive doesn't work" ],
|
29
|
-
[ false, 55767, 'Normal', 'Getters for all setters' ],
|
30
|
-
[ false, 56925, 'Normal', 'Gtkcalender size' ],
|
31
|
-
[ false, 56221, 'Normal', 'Selectable label needs right-click copy menu' ],
|
32
|
-
[ true, 50939, 'Normal', 'Add shift clicking to GtkTextView' ],
|
33
|
-
[ false, 6112, 'Enhancement','netscape-like collapsable toolbars' ],
|
34
|
-
[ false, 1, 'Normal', 'First bug :=)' ],
|
35
|
-
].collect do |ary|
|
36
|
-
Bug.new(*ary)
|
37
|
-
end
|
38
|
-
def initialize
|
39
|
-
super('GtkListStore demo')
|
40
|
-
self.border_width = 8
|
7
|
+
The GtkListStore is used to store data in list form, to be used
|
8
|
+
later on by a GtkTreeView to display it. This demo builds a
|
9
|
+
simple GtkListStore and displays it.
|
41
10
|
|
42
|
-
|
43
|
-
|
11
|
+
=end
|
12
|
+
class ListStoreDemo
|
13
|
+
Bug = Struct.new("Bug", :fixed, :number, :severity, :description)
|
14
|
+
COLUMN_FIXED, COLUMN_NUMBER, COLUMN_SEVERITY, COLUMN_DESCRIPTION,
|
15
|
+
COLUMN_PULSE, COLUMN_ICON, COLUMN_ACTIVE, COLUMN_SENSITIVE, NUM_COLUMNS =
|
16
|
+
*(0..8).to_a
|
17
|
+
DATA = [
|
18
|
+
[false, 60_482, "Normal", "scrollable notebooks and hidden tabs" ],
|
19
|
+
[false, 60_620, "Critical", "gdk_window_clear_area (gdkwindow-win32.c) is not thread-safe" ],
|
20
|
+
[false, 50_214, "Major", "Xft support does not clean up correctly" ],
|
21
|
+
[true, 52_877, "Major", "GtkFileSelection needs a refresh method. " ],
|
22
|
+
[false, 56_070, "Normal", "Can't click button after setting in sensitive" ],
|
23
|
+
[true, 56_355, "Normal", "GtkLabel - Not all changes propagate correctly" ],
|
24
|
+
[false, 50_055, "Normal", "Rework width/height computations for TreeView" ],
|
25
|
+
[false, 58_278, "Normal", "gtk_dialog_set_response_sensitive doesn't work" ],
|
26
|
+
[false, 55_767, "Normal", "Getters for all setters" ],
|
27
|
+
[false, 56_925, "Normal", "Gtkcalender size" ],
|
28
|
+
[false, 56_221, "Normal", "Selectable label needs right-click copy menu" ],
|
29
|
+
[true, 50_939, "Normal", "Add shift clicking to GtkTextView" ],
|
30
|
+
[false, 6_112, "Enhancement","netscape-like collapsable toolbars" ],
|
31
|
+
[false, 1, "Normal", "First bug :=)" ],
|
32
|
+
].collect do |ary|
|
33
|
+
Bug.new(*ary)
|
34
|
+
end
|
44
35
|
|
45
|
-
|
46
|
-
|
36
|
+
def initialize(main_window)
|
37
|
+
@window = Gtk::Window.new(:toplevel)
|
38
|
+
@window.screen = main_window.screen
|
39
|
+
@window.title = "List Store"
|
40
|
+
@window.border_width = 8
|
41
|
+
@timeout = 0
|
42
|
+
@window.signal_connect "delete-event" do
|
43
|
+
@model = nil
|
44
|
+
GLib::Source.remove(@timeout) unless @timeout.zero?
|
45
|
+
@timeout = 0
|
46
|
+
false
|
47
|
+
end
|
48
|
+
vbox = Gtk::Box.new(:vertical, 8)
|
49
|
+
@window.add(vbox)
|
50
|
+
|
51
|
+
label = Gtk::Label.new(<<-EOF)
|
52
|
+
This is the bug list (note: not based on real data, it would be nice to
|
53
|
+
have a nice ODBC interface to bugzilla or so, though).
|
54
|
+
EOF
|
55
|
+
vbox.pack_start(label, :expand => false, :fill => false, :padding => 0)
|
56
|
+
sw = Gtk::ScrolledWindow.new(nil, nil)
|
57
|
+
sw.shadow_type = :etched_in
|
58
|
+
sw.set_policy(:never, :automatic)
|
59
|
+
vbox.pack_start(sw, :expand => true, :fill => true, :padding => 0)
|
60
|
+
|
61
|
+
# create tree model
|
62
|
+
create_model
|
63
|
+
|
64
|
+
# create tree view
|
65
|
+
treeview = Gtk::TreeView.new(@model)
|
66
|
+
treeview.search_column = COLUMN_DESCRIPTION
|
67
|
+
sw.add(treeview)
|
68
|
+
|
69
|
+
# add columns to the tree view
|
70
|
+
add_columns(treeview)
|
71
|
+
|
72
|
+
# finish and show
|
73
|
+
@window.set_default_size(280, 250)
|
74
|
+
end
|
47
75
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
76
|
+
def run
|
77
|
+
if !@window.visible?
|
78
|
+
@window.show_all
|
79
|
+
add_spinner
|
52
80
|
|
53
|
-
|
54
|
-
|
81
|
+
else
|
82
|
+
@window.destroy
|
83
|
+
GLib::Source.remove(@tiemout) unless @timeout.zero?
|
84
|
+
@timeout = 0
|
85
|
+
end
|
86
|
+
@window
|
87
|
+
end
|
55
88
|
|
56
|
-
|
57
|
-
treeview = Gtk::TreeView.new(model)
|
58
|
-
treeview.rules_hint = true
|
59
|
-
treeview.search_column = COLUMN_DESCRIPTION
|
89
|
+
private
|
60
90
|
|
61
|
-
|
91
|
+
def create_model
|
92
|
+
# create list store
|
93
|
+
@model = Gtk::ListStore.new(TrueClass, Integer, String, String, Integer,
|
94
|
+
String, TrueClass, TrueClass)
|
62
95
|
|
63
|
-
|
64
|
-
|
96
|
+
# add data to the list store
|
97
|
+
DATA.each_with_index do |bug, i|
|
98
|
+
icon_name = ""
|
99
|
+
icon_name = "battery-caution-charging-symbolic" if i == 1 || i == 3
|
100
|
+
sensitive = i == 3 ? false : true
|
65
101
|
|
66
|
-
|
102
|
+
iter = @model.append
|
103
|
+
iter.set_values([bug.fixed, bug.number, bug.severity, bug.description,
|
104
|
+
0, icon_name, false, sensitive])
|
67
105
|
end
|
106
|
+
end
|
68
107
|
|
69
|
-
|
70
|
-
|
71
|
-
|
108
|
+
def add_columns(treeview)
|
109
|
+
# column for fixed toggles
|
110
|
+
renderer = Gtk::CellRendererToggle.new
|
111
|
+
renderer.signal_connect("toggled") { |_cell, path| fixed_toggled(path) }
|
112
|
+
column = Gtk::TreeViewColumn.new("Fixed?",
|
113
|
+
renderer,
|
114
|
+
"active" => COLUMN_FIXED)
|
115
|
+
|
116
|
+
# set this column to a fixed sizing (of 50 pixels)
|
117
|
+
column.sizing = :fixed
|
118
|
+
column.fixed_width = 50
|
119
|
+
treeview.append_column(column)
|
120
|
+
|
121
|
+
# column for bug numbers
|
122
|
+
renderer = Gtk::CellRendererText.new
|
123
|
+
column = Gtk::TreeViewColumn.new("Bug number",
|
124
|
+
renderer,
|
125
|
+
"text" => COLUMN_NUMBER)
|
126
|
+
column.sort_column_id = COLUMN_NUMBER
|
127
|
+
treeview.append_column(column)
|
128
|
+
|
129
|
+
# column for severities
|
130
|
+
renderer = Gtk::CellRendererText.new
|
131
|
+
column = Gtk::TreeViewColumn.new("Severity",
|
132
|
+
renderer,
|
133
|
+
"text" => COLUMN_SEVERITY)
|
134
|
+
column.sort_column_id = COLUMN_SEVERITY
|
135
|
+
treeview.append_column(column)
|
136
|
+
|
137
|
+
# column for description
|
138
|
+
renderer = Gtk::CellRendererText.new
|
139
|
+
column = Gtk::TreeViewColumn.new("Description",
|
140
|
+
renderer,
|
141
|
+
"text" => COLUMN_DESCRIPTION)
|
142
|
+
column.sort_column_id = COLUMN_DESCRIPTION
|
143
|
+
treeview.append_column(column)
|
144
|
+
|
145
|
+
# column for spinner
|
146
|
+
renderer = Gtk::CellRendererSpinner.new
|
147
|
+
column = Gtk::TreeViewColumn.new("Spinning",
|
148
|
+
renderer,
|
149
|
+
"pulse" => COLUMN_PULSE,
|
150
|
+
"active" => COLUMN_ACTIVE)
|
151
|
+
column.sort_column_id = COLUMN_PULSE
|
152
|
+
treeview.append_column(column)
|
153
|
+
|
154
|
+
# column for symbolic icon
|
155
|
+
renderer = Gtk::CellRendererPixbuf.new
|
156
|
+
column = Gtk::TreeViewColumn.new("Symbolic icon",
|
157
|
+
renderer,
|
158
|
+
"icon-name" => COLUMN_ICON,
|
159
|
+
"sensitive" => COLUMN_SENSITIVE)
|
160
|
+
column.sort_column_id = COLUMN_ICON
|
161
|
+
treeview.append_column(column)
|
162
|
+
end
|
72
163
|
|
73
|
-
|
74
|
-
|
75
|
-
iter = store.append
|
76
|
-
bug.each_with_index do |value, index|
|
77
|
-
iter[index] = value
|
78
|
-
end
|
79
|
-
end
|
80
|
-
return store
|
81
|
-
end
|
164
|
+
def fixed_toggled(path_str)
|
165
|
+
path = Gtk::TreePath.new(path_str)
|
82
166
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
renderer.signal_connect('toggled') do |cell, path|
|
87
|
-
fixed_toggled(treeview.model, path)
|
88
|
-
end
|
167
|
+
# get toggled iter
|
168
|
+
iter = @model.get_iter(path)
|
169
|
+
fixed = iter[COLUMN_FIXED]
|
89
170
|
|
90
|
-
|
91
|
-
|
92
|
-
'active' => COLUMN_FIXED)
|
93
|
-
|
94
|
-
# set this column to a fixed sizing (of 50 pixels)
|
95
|
-
column.sizing = Gtk::TreeViewColumn::FIXED
|
96
|
-
column.fixed_width = 50
|
97
|
-
treeview.append_column(column)
|
98
|
-
|
99
|
-
# column for bug numbers
|
100
|
-
renderer = Gtk::CellRendererText.new
|
101
|
-
column = Gtk::TreeViewColumn.new('Bug number',
|
102
|
-
renderer,
|
103
|
-
'text' => COLUMN_NUMBER)
|
104
|
-
column.set_sort_column_id(COLUMN_NUMBER)
|
105
|
-
treeview.append_column(column)
|
106
|
-
|
107
|
-
# column for severities
|
108
|
-
renderer = Gtk::CellRendererText.new
|
109
|
-
column = Gtk::TreeViewColumn.new('Severity',
|
110
|
-
renderer,
|
111
|
-
'text' => COLUMN_SEVERITY)
|
112
|
-
column.set_sort_column_id(COLUMN_SEVERITY)
|
113
|
-
treeview.append_column(column)
|
114
|
-
|
115
|
-
# column for description
|
116
|
-
renderer = Gtk::CellRendererText.new
|
117
|
-
column = Gtk::TreeViewColumn.new('Description',
|
118
|
-
renderer,
|
119
|
-
'text' => COLUMN_DESCRIPTION)
|
120
|
-
column.set_sort_column_id(COLUMN_DESCRIPTION)
|
121
|
-
treeview.append_column(column)
|
122
|
-
end
|
171
|
+
# do something with the value
|
172
|
+
fixed ^= 1
|
123
173
|
|
124
|
-
|
125
|
-
|
174
|
+
# set new value
|
175
|
+
iter[COLUMN_FIXED] = fixed
|
176
|
+
end
|
126
177
|
|
127
|
-
|
128
|
-
|
129
|
-
|
178
|
+
def add_spinner
|
179
|
+
if @timeout.zero?
|
180
|
+
@timeout = GLib::Timeout.add(80) do
|
181
|
+
GLib::Source.remove(@timeout) unless @model
|
182
|
+
iter = @model.iter_first
|
183
|
+
pulse = iter[COLUMN_PULSE]
|
130
184
|
|
131
|
-
|
132
|
-
|
185
|
+
pulse = pulse == GLib::MAXUINT ? 0 : pulse + 1
|
186
|
+
iter[COLUMN_PULSE] = pulse
|
187
|
+
iter[COLUMN_ACTIVE] = true
|
133
188
|
|
134
|
-
|
135
|
-
|
189
|
+
true
|
190
|
+
end
|
136
191
|
end
|
137
192
|
end
|
138
193
|
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# Copyright (c) 2016 Ruby-GNOME2 Project Team
|
2
|
+
# This program is licenced under the same licence as Ruby-GNOME2.
|
3
|
+
#
|
4
|
+
=begin
|
5
|
+
= List Box
|
6
|
+
|
7
|
+
GtkListBox allows lists with complicated layouts, using
|
8
|
+
regular widgets supporting sorting and filtering.
|
9
|
+
|
10
|
+
=end
|
11
|
+
class ListboxDemo
|
12
|
+
def initialize(main_window)
|
13
|
+
@window = Gtk::Window.new(:toplevel)
|
14
|
+
@window.screen = main_window.screen
|
15
|
+
@window.title = "List Box"
|
16
|
+
@window.set_default_size(400, 600)
|
17
|
+
|
18
|
+
vbox = Gtk::Box.new(:vertical, 12)
|
19
|
+
@window.add(vbox)
|
20
|
+
label = Gtk::Label.new("Messages from Gtk+ and friends")
|
21
|
+
vbox.pack_start(label, :expand => false, :fill => false, :padding => 0)
|
22
|
+
scrolled = Gtk::ScrolledWindow.new
|
23
|
+
scrolled.set_policy(:never, :automatic)
|
24
|
+
vbox.pack_start(scrolled, :expand => true, :fill => true, :padding => 0)
|
25
|
+
|
26
|
+
listbox = Gtk::ListBox.new
|
27
|
+
scrolled.add(listbox)
|
28
|
+
|
29
|
+
listbox.set_sort_func do |a, b|
|
30
|
+
a.sort(b)
|
31
|
+
end
|
32
|
+
listbox.activate_on_single_click = false
|
33
|
+
listbox.signal_connect("row-activated", &:row_activated)
|
34
|
+
vbox.show_all
|
35
|
+
|
36
|
+
data = Gio::Resources.lookup_data("/listbox/messages.txt", 0)
|
37
|
+
data.each_line do |line|
|
38
|
+
message = Message.new(line)
|
39
|
+
row = GtkMessageRow.new(message)
|
40
|
+
row.show
|
41
|
+
listbox.add(row)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def run
|
46
|
+
if !@window.visible?
|
47
|
+
@window.show_all
|
48
|
+
else
|
49
|
+
@window.destroy
|
50
|
+
end
|
51
|
+
@window
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Message
|
56
|
+
attr_reader :id, :sender_name, :sender_nick, :message, :time, :reply_to,
|
57
|
+
:resent_by
|
58
|
+
attr_accessor :n_favorites, :n_reshares
|
59
|
+
|
60
|
+
def initialize(str)
|
61
|
+
strv = str.split("|")
|
62
|
+
parse(strv)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def parse(array_of_strings)
|
68
|
+
@id = array_of_strings[0].to_i
|
69
|
+
@sender_name = array_of_strings[1]
|
70
|
+
@sender_nick = array_of_strings[2]
|
71
|
+
@message = array_of_strings[3]
|
72
|
+
@time = array_of_strings[4].to_i
|
73
|
+
@reply_to = array_of_strings[5] || nil
|
74
|
+
@resent_by = array_of_strings[6] || nil
|
75
|
+
@n_favorites = array_of_strings[7] ? array_of_strings[7].to_i : nil
|
76
|
+
@n_reshares = array_of_strings[8] ? array_of_strings[8].to_i : nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class GtkMessageRow < Gtk::ListBoxRow
|
81
|
+
|
82
|
+
type_register
|
83
|
+
class << self
|
84
|
+
def init
|
85
|
+
set_template(:resource => "/listbox/listbox.ui")
|
86
|
+
bind_template_child("content_label")
|
87
|
+
bind_template_child("source_name")
|
88
|
+
bind_template_child("source_nick")
|
89
|
+
bind_template_child("short_time_label")
|
90
|
+
bind_template_child("detailed_time_label")
|
91
|
+
bind_template_child("extra_buttons_box")
|
92
|
+
bind_template_child("details_revealer")
|
93
|
+
bind_template_child("avatar_image")
|
94
|
+
bind_template_child("resent_box")
|
95
|
+
bind_template_child("resent_by_button")
|
96
|
+
bind_template_child("n_reshares_label")
|
97
|
+
bind_template_child("n_favorites_label")
|
98
|
+
bind_template_child("expand_button")
|
99
|
+
|
100
|
+
set_connect_func do |name|
|
101
|
+
method(name)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def favorite_clicked(button)
|
108
|
+
row = button.parent
|
109
|
+
row = row.parent while row.class != GtkMessageRow
|
110
|
+
row.message.n_favorites += 1
|
111
|
+
row.message_row_update
|
112
|
+
end
|
113
|
+
|
114
|
+
def expand_clicked(button)
|
115
|
+
row = button.parent
|
116
|
+
row = row.parent while row.class != GtkMessageRow
|
117
|
+
row.row_expand
|
118
|
+
end
|
119
|
+
|
120
|
+
def reshare_clicked(button)
|
121
|
+
row = button.parent
|
122
|
+
row = row.parent while row.class != GtkMessageRow
|
123
|
+
row.message.n_reshares += 1
|
124
|
+
row.message_row_update
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
attr_reader :message
|
129
|
+
|
130
|
+
def initialize(message)
|
131
|
+
super()
|
132
|
+
@message = message
|
133
|
+
@avatar_pixbuf_other = GdkPixbuf::Pixbuf.new(:resource => "/listbox/apple-red.png",
|
134
|
+
:width => 32, :height => 32,
|
135
|
+
:preserve_aspect_ratio => false)
|
136
|
+
message_row_update
|
137
|
+
extra_buttons_box.hide
|
138
|
+
extra_buttons_box.visible = false
|
139
|
+
extra_buttons_box.unset_state_flags([:prelight, :selected])
|
140
|
+
set_state_flags(Gtk::StateFlags::NORMAL, false)
|
141
|
+
|
142
|
+
signal_connect "state-flags-changed" do |widget, _previous_flags|
|
143
|
+
flags = widget.state_flags
|
144
|
+
|
145
|
+
is_prelight_or_selected = flags & (Gtk::StateFlags::PRELIGHT |
|
146
|
+
Gtk::StateFlags::SELECTED)
|
147
|
+
if is_prelight_or_selected.nonzero?
|
148
|
+
widget.extra_buttons_box.visible = true
|
149
|
+
else
|
150
|
+
widget.extra_buttons_box.visible = false
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def message_row_update
|
156
|
+
source_name.text = @message.sender_name
|
157
|
+
source_nick.text = @message.sender_nick
|
158
|
+
content_label.text = @message.message
|
159
|
+
short_time_label.text = Time.at(@message.time).utc.strftime("%e %b %y")
|
160
|
+
detailed_time_label.text = Time.at(@message.time).utc.strftime("%Y - %e %b %Y")
|
161
|
+
n_favorites_label.visible = @message.n_favorites.nonzero?
|
162
|
+
n_favorites_label.markup = "<b>#{@message.n_favorites}</b>\nFavorites"
|
163
|
+
n_reshares_label.visible = @message.n_reshares.nonzero?
|
164
|
+
n_reshares_label.markup = "<b>#{@message.n_reshares}</b>\nReshares"
|
165
|
+
resent_box.visible = !@message.resent_by.nil?
|
166
|
+
resent_by_button.label = @message.resent_by if @message.resent_by
|
167
|
+
if @message.sender_nick == "@GTKtoolkit"
|
168
|
+
avatar_image.set_from_icon_name("gtk3-demo", Gtk::IconSize::DND)
|
169
|
+
else
|
170
|
+
avatar_image.from_pixbuf = @avatar_pixbuf_other
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def sort(b)
|
175
|
+
@message.time - b.message.time
|
176
|
+
end
|
177
|
+
|
178
|
+
def row_expand
|
179
|
+
expand = !details_revealer.reveal_child?
|
180
|
+
details_revealer.reveal_child = expand
|
181
|
+
expand ? expand_button.label = "Hide" : expand_button.label = "Expand"
|
182
|
+
end
|
183
|
+
end
|