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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/ext/gtk3/rb-gtk3-private.h +1 -0
  3. data/ext/gtk3/rb-gtk3-spin-button.c +85 -0
  4. data/ext/gtk3/rb-gtk3.c +3 -0
  5. data/lib/2.2/gtk3.so +0 -0
  6. data/lib/2.3/gtk3.so +0 -0
  7. data/lib/gtk3/deprecated.rb +0 -8
  8. data/lib/gtk3/loader.rb +1 -7
  9. data/lib/gtk3/tree-model.rb +2 -0
  10. data/sample/gtk-demo/TODO +10 -10
  11. data/sample/gtk-demo/assistant.rb +44 -39
  12. data/sample/gtk-demo/builder.rb +71 -50
  13. data/sample/gtk-demo/button_box.rb +39 -28
  14. data/sample/gtk-demo/clipboard.rb +139 -46
  15. data/sample/gtk-demo/colorsel.rb +50 -36
  16. data/sample/gtk-demo/css_accordion.rb +18 -17
  17. data/sample/gtk-demo/css_basics.rb +60 -47
  18. data/sample/gtk-demo/css_multiplebgs.rb +92 -71
  19. data/sample/gtk-demo/css_pixbufs.rb +61 -48
  20. data/sample/gtk-demo/css_shadows.rb +63 -50
  21. data/sample/gtk-demo/cursors.rb +95 -64
  22. data/sample/gtk-demo/dialog.rb +95 -78
  23. data/sample/gtk-demo/drawingarea.rb +138 -171
  24. data/sample/gtk-demo/editable_cells.rb +169 -130
  25. data/sample/gtk-demo/entry_buffer.rb +15 -13
  26. data/sample/gtk-demo/entry_completion.rb +22 -17
  27. data/sample/gtk-demo/expander.rb +39 -31
  28. data/sample/gtk-demo/filtermodel.rb +67 -63
  29. data/sample/gtk-demo/font_features.rb +91 -60
  30. data/sample/gtk-demo/glarea.rb +277 -0
  31. data/sample/gtk-demo/headerbar.rb +17 -15
  32. data/sample/gtk-demo/hypertext.rb +146 -167
  33. data/sample/gtk-demo/iconview.rb +132 -91
  34. data/sample/gtk-demo/iconview_edit.rb +49 -38
  35. data/sample/gtk-demo/infobar.rb +81 -62
  36. data/sample/gtk-demo/links.rb +35 -30
  37. data/sample/gtk-demo/list_store.rb +169 -114
  38. data/sample/gtk-demo/listbox.rb +183 -0
  39. data/sample/gtk-demo/main.rb +32 -21
  40. data/sample/gtk-demo/markup.rb +65 -52
  41. data/sample/gtk-demo/menus.rb +57 -58
  42. data/sample/gtk-demo/modelbutton.rb +11 -9
  43. data/sample/gtk-demo/modelbutton.ui +3 -0
  44. data/sample/gtk-demo/overlay.rb +39 -32
  45. data/sample/gtk-demo/overlay2.rb +68 -54
  46. data/sample/gtk-demo/panes.rb +56 -68
  47. data/sample/gtk-demo/pickers.rb +46 -45
  48. data/sample/gtk-demo/pixbufs.rb +27 -25
  49. data/sample/gtk-demo/popover.rb +70 -63
  50. data/sample/gtk-demo/printing.rb +94 -69
  51. data/sample/gtk-demo/revealer.rb +46 -38
  52. data/sample/gtk-demo/rotated_text.rb +75 -54
  53. data/sample/gtk-demo/scale.rb +10 -8
  54. data/sample/gtk-demo/search_entry.rb +195 -0
  55. data/sample/gtk-demo/search_entry2.rb +71 -59
  56. data/sample/gtk-demo/sidebar.rb +20 -19
  57. data/sample/gtk-demo/sizegroup.rb +36 -35
  58. data/sample/gtk-demo/spinbutton.rb +128 -0
  59. data/sample/gtk-demo/spinner.rb +55 -40
  60. data/sample/gtk-demo/stack.rb +11 -8
  61. data/sample/gtk-demo/textmask.rb +14 -13
  62. data/sample/gtk-demo/textscroll.rb +16 -12
  63. data/sample/gtk-demo/theming_style_classes.rb +14 -12
  64. data/sample/gtk-demo/transparent.rb +17 -13
  65. data/sample/misc/treemodelfilter.rb +1 -1
  66. metadata +24 -19
@@ -0,0 +1,277 @@
1
+ # Copyright (c) 2016 Ruby-GNOME2 Project Team
2
+ # This program is licenced under the same licence as Ruby-GNOME2.
3
+ #
4
+ =begin
5
+ = OpenGL Area
6
+
7
+ GtkGLArea is a widget that allows custom drawing using OpenGL calls.
8
+ =end
9
+ require "opengl"
10
+ OpenGL.load_lib
11
+ include OpenGL
12
+
13
+ class GlareaDemo
14
+ X_AXIS, Y_AXIS, Z_AXIS = (0..2).to_a
15
+ # The object we are drawing
16
+ VERTEX_DATA = [0.0, 0.5, 0.0, 1.0,
17
+ 0.5, -0.366, 0.0, 1.0,
18
+ -0.5, -0.366, 0.0, 1.0].freeze
19
+
20
+ def initialize(main_window)
21
+ # Rotation angles on each axis
22
+ @rotation_angles = [0.0, 0.0, 0.0]
23
+ @window = Gtk::Window.new(:toplevel)
24
+ @window.screen = main_window.screen
25
+ @window.title = "OpenGL Area"
26
+ @window.set_default_size(400, 600)
27
+ @window.border_width = 12
28
+
29
+ box = Gtk::Box.new(:vertical, false)
30
+ box.spacing = 6
31
+ @window.add(box)
32
+
33
+ @gl_area = Gtk::GLArea.new
34
+ @gl_area.hexpand = true
35
+ @gl_area.vexpand = true
36
+ box.add(@gl_area)
37
+
38
+ # We need to initialize and free GL resources, so we use
39
+ # the realize and unrealize signals on the widget
40
+ @gl_area.signal_connect "realize" do |widget|
41
+ # We need to set up our state when we realize the GtkGLArea widget
42
+ widget.make_current
43
+ unless widget.error
44
+ init_buffers
45
+ @program, @mvp_location = init_shaders
46
+ end
47
+ end
48
+
49
+ @gl_area.signal_connect "unrealize" do |widget|
50
+ widget.make_current
51
+ unless widget.error
52
+ # We should tear down the state when unrealizing
53
+ glDeleteProgram(@program)
54
+ end
55
+ end
56
+
57
+ # The main "draw" call for GtkGLArea
58
+ @gl_area.signal_connect "render" do |area, _context|
59
+ return false if area.error
60
+
61
+ # Clear the viewport
62
+ glClearColor(0.5, 0.5, 0.5, 1.0)
63
+ glClear(GL_COLOR_BUFFER_BIT)
64
+ draw_triangle
65
+ glFlush
66
+ true
67
+ end
68
+
69
+ controls = Gtk::Box.new(:vertical, false)
70
+ box.add(controls)
71
+ controls.hexpand = true
72
+ (0..2).each do |i|
73
+ controls.add(create_axis_slider(i))
74
+ end
75
+
76
+ button = Gtk::Button.new(:label => "Quit")
77
+ button.hexpand = true
78
+ box.add(button)
79
+ button.signal_connect "clicked" do
80
+ @window.destroy
81
+ end
82
+ end
83
+
84
+ def run
85
+ if !@window.visible?
86
+ @window.show_all
87
+ else
88
+ @window.destroy
89
+ end
90
+ @window
91
+ end
92
+
93
+ private
94
+
95
+ def init_buffers
96
+ vao = " "
97
+ glGenVertexArrays(1, vao)
98
+ gl_vao = vao.unpack("L")[0]
99
+ @position_buffer = gl_vao
100
+ glBindVertexArray(gl_vao)
101
+
102
+ # This is the buffer that holds the vertices
103
+ buffer = " "
104
+ glGenBuffers(1, buffer)
105
+ gl_vbo = buffer.unpack("L")[0]
106
+ glBindBuffer(GL_ARRAY_BUFFER, gl_vbo)
107
+ glBufferData(GL_ARRAY_BUFFER, 3 * 4 * Fiddle::SIZEOF_FLOAT,
108
+ VERTEX_DATA.pack("F*"), GL_STATIC_DRAW)
109
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
110
+ end
111
+
112
+ # Initialize shaders and link them into a programm
113
+ def init_shaders
114
+ src_vertex = Gio::Resources.lookup_data("/glarea/glarea-vertex.glsl", 0)
115
+ src_fragment = Gio::Resources.lookup_data("/glarea/glarea-fragment.glsl", 0)
116
+ vertex = create_shader(GL_VERTEX_SHADER, src_vertex)
117
+ return [0, nil] if vertex.zero?
118
+ fragment = create_shader(GL_FRAGMENT_SHADER, src_fragment)
119
+ return [0, nil] if fragment.zero?
120
+
121
+ program = glCreateProgram
122
+ glAttachShader(program, vertex)
123
+ glAttachShader(program, fragment)
124
+ glLinkProgram(program)
125
+ # Check if the program is valid
126
+ linked_buf = " "
127
+ glGetProgramiv(program, GL_LINK_STATUS, linked_buf)
128
+ status = linked_buf.unpack("L")[0]
129
+ if status.zero?
130
+ log_len = " "
131
+ glGetShaderiv(program, GL_INFO_LOG_LENGTH, log_len)
132
+ len = log_len.unpack("L")[0]
133
+ info_log = " " * (len + 1)
134
+ glGetProgramInfoLog(program, len, nil, info_log)
135
+ STDERR.puts "Linking failure:\n#{info_log}\n"
136
+ glDeleteProgram(program)
137
+ glDeleteShader(vertex)
138
+ glDeleteShader(fragment)
139
+ program = 0
140
+ end
141
+ mvp = glGetUniformLocation(program, "mvp")
142
+ [program, mvp]
143
+ end
144
+
145
+ def create_shader(type, source)
146
+ # Load the shaders sources
147
+ shader = glCreateShader(type)
148
+
149
+ glShaderSource(shader, 1, [source].pack("p"), [source.bytesize].pack("I"))
150
+ # Compile the vertex shader
151
+ glCompileShader(shader)
152
+ # Check the vertex shader compilation
153
+ compiled_buf = " "
154
+ glGetShaderiv(shader, GL_COMPILE_STATUS, compiled_buf)
155
+ status = compiled_buf.unpack("L")[0]
156
+ if status.zero?
157
+ log_len = " "
158
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, log_len)
159
+ len = log_len.unpack("L")[0]
160
+ info_log = " " * (len + 1)
161
+ glGetShaderInfoLog(shader, len, nil, info_log)
162
+ type_name = type == GL_VERTEX_SHADER ? "vertex" : "fragment"
163
+ STDERR.puts "Compile failure in #{type_name}:\n#{info_log}\n"
164
+ return 0
165
+ end
166
+ shader
167
+ end
168
+
169
+ def draw_triangle
170
+ # Compute the model view projection matrix using the rotation angles
171
+ # specified through the GtkRange widgets
172
+ mvp = compute_mvp
173
+ # Use our program
174
+ glUseProgram(@program)
175
+ # Update the "mvp" matrix we use in the shader
176
+ glUniformMatrix4fv(@mvp_location, 1, GL_FALSE, mvp.pack("F16"))
177
+ # Use the vertices in our buffer
178
+ glBindBuffer(GL_ARRAY_BUFFER, @position_buffer)
179
+ glEnableVertexAttribArray(0)
180
+ glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0)
181
+
182
+ # Draw the three vertices as a triangle
183
+ glDrawArrays(GL_TRIANGLES, 0, 3)
184
+
185
+ # We finished using the buffers and program
186
+ glDisableVertexAttribArray(0)
187
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
188
+ glUseProgram(0)
189
+ end
190
+
191
+ def compute_mvp
192
+ phi = @rotation_angles[X_AXIS]
193
+ theta = @rotation_angles[Y_AXIS]
194
+ psi = @rotation_angles[Z_AXIS]
195
+ res = Array.new(16, 0.0)
196
+ x = phi * (Math::PI / 180.0)
197
+ y = theta * (Math::PI / 180.0)
198
+ z = psi * (Math::PI / 180.0)
199
+ c1 = Math.cos(x)
200
+ c2 = Math.cos(y)
201
+ c3 = Math.cos(z)
202
+ s1 = Math.sin(x)
203
+ s2 = Math.sin(y)
204
+ s3 = Math.sin(z)
205
+ c3c2 = c3 * c2
206
+ s3c1 = s3 * c1
207
+ c3s2s1 = c3 * s2 * s1
208
+ s3s1 = s3 * s1
209
+ c3s2c1 = c3 * s2 * c1
210
+ s3c2 = s3 * c2
211
+ c3c1 = c3 * c1
212
+ s3s2s1 = s3 * s2 * s1
213
+ c3s1 = c3 * s1
214
+ s3s2c1 = s3 * s2 * c1
215
+ c2s1 = c2 * s1
216
+ c2c1 = c2 * c1
217
+
218
+ # initialize to the identity matrix
219
+ res[0] = 1.0
220
+ res[5] = 1.0
221
+ res[10] = 1.0
222
+ res[15] = 1.0
223
+
224
+ # apply all three rotations using the three matrices:
225
+ #
226
+ # ⎡ c3 s3 0 ⎤ ⎡ c2 0 -s2 ⎤ ⎡ 1 0 0 ⎤
227
+ # ⎢ -s3 c3 0 ⎥ ⎢ 0 1 0 ⎥ ⎢ 0 c1 s1 ⎥
228
+ # ⎣ 0 0 1 ⎦ ⎣ s2 0 c2 ⎦ ⎣ 0 -s1 c1 ⎦
229
+
230
+ res[0] = c3c2
231
+ res[1] = -s3c2
232
+ res[2] = s2
233
+ res[3] = 0.0
234
+ res[4] = s3c1 + c3s2s1
235
+ res[5] = c3c1 - s3s2s1
236
+ res[6] = -c2s1
237
+ res[7] = 0.0
238
+ res[8] = s3s1 - c3s2c1
239
+ res[9] = c3s1 + s3s2c1
240
+ res[10] = c2c1
241
+ res[11] = 0.0
242
+ res[12] = 0.0
243
+ res[13] = 0.0
244
+ res[14] = 0.0
245
+ res[15] = 1.0
246
+ res
247
+ end
248
+
249
+ def create_axis_slider(axis)
250
+ box = Gtk::Box.new(:horizontal, 0)
251
+ text = case axis
252
+ when X_AXIS
253
+ "X axis"
254
+ when Y_AXIS
255
+ "Y axis"
256
+ when Z_AXIS
257
+ "Z axis"
258
+ end
259
+ label = Gtk::Label.new(text)
260
+ box.add(label)
261
+ label.show
262
+
263
+ adj = Gtk::Adjustment.new(0.0, 0.0, 360.0, 1.0, 12.0, 0.0)
264
+ adj.signal_connect "value-changed" do |widget|
265
+ # Updte the rotation angle
266
+ @rotation_angles[axis] = widget.value
267
+ # Update the contents of the GL drawing area
268
+ @gl_area.queue_draw
269
+ end
270
+ slider = Gtk::Scale.new(:horizontal, adj)
271
+ box.add(slider)
272
+ slider.hexpand = true
273
+ slider.show
274
+ box.show
275
+ box
276
+ end
277
+ end
@@ -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
@@ -12,18 +12,18 @@ or right.
12
12
 
13
13
  It is commonly used with gtk_window_set_titlebar()
14
14
  =end
15
- module HeaderbarDemo
16
- def self.run_demo(main_window)
17
- window = Gtk::Window.new(:toplevel)
18
- window.screen = main_window.screen
19
- window.set_default_size(600, 400)
15
+ class HeaderbarDemo
16
+ def initialize(main_window)
17
+ @window = Gtk::Window.new(:toplevel)
18
+ @window.screen = main_window.screen
19
+ @window.set_default_size(600, 400)
20
20
 
21
21
  header = Gtk::HeaderBar.new
22
- header.set_show_close_button(true)
23
- header.set_title("Welcome to Facebook - Log in, sign up or learn more")
24
- header.set_has_subtitle(false)
22
+ header.show_close_button = true
23
+ header.title = "Welcome to Facebook - Log in, sign up or learn more"
24
+ header.has_subtitle = false
25
25
 
26
- button = Gtk::Button.new()
26
+ button = Gtk::Button.new
27
27
 
28
28
  icon = Gio::ThemedIcon.new("mail-send-receive-symbolic")
29
29
  image = Gtk::Image.new(:icon => icon, :size => :button)
@@ -45,13 +45,15 @@ module HeaderbarDemo
45
45
  box.add(button)
46
46
 
47
47
  header.pack_start(box)
48
- window.set_titlebar(header)
49
- window.add(Gtk::TextView.new())
48
+ @window.titlebar = header
49
+ @window.add(Gtk::TextView.new)
50
+ end
50
51
 
51
- if !window.visible?
52
- window.show_all
52
+ def run
53
+ if !@window.visible?
54
+ @window.show_all
53
55
  else
54
- window.destroy
56
+ @window.destroy
55
57
  end
56
58
  end
57
59
  end
@@ -1,205 +1,184 @@
1
- # Copyright (c) 2003-2005 Ruby-GNOME2 Project Team
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: hypertext.rb,v 1.2 2005/12/01 09:27:01 ktou Exp $
5
4
  =begin
6
- = Text Widget/Hypertext
5
+ = Text View/Hypertext
7
6
 
8
- Usually, tags modify the appearance of text in the view, e.g. making it
9
- bold or colored or underlined. But tags are not restricted to appearance.
10
- They can also affect the behavior of mouse and key presses, as this demo
11
- shows.
7
+ Usually, tags modify the appearance of text in the view, e.g. making it
8
+ bold or colored or underlined. But tags are not restricted to appearance.
9
+ They can also affect the behavior of mouse and key presses, as this demo
10
+ shows.
12
11
  =end
12
+ class HypertextDemo
13
+ def initialize(main_window)
14
+ initialize_window(main_window)
15
+ initialize_cursors(main_window)
16
+ initialize_view
13
17
 
14
- require 'common'
15
-
16
- module Demo
17
- class Hypertext < BasicWindow
18
- def initialize
19
- super('Hypertext')
20
-
21
- @hand_cursor = Gdk::Cursor.new(Gdk::Cursor::HAND2)
22
- @regular_cursor = Gdk::Cursor.new(Gdk::Cursor::XTERM)
23
- @hovering = false
24
-
25
- set_default_size(450, 450)
26
- self.border_width = 0
27
-
28
- view = Gtk::TextView.new
29
-
30
- view.wrap_mode = :word
31
-
32
- view.signal_connect('key-press-event') do |*args|
33
- key_press_event(*args)
34
- end
35
- view.signal_connect('event-after') do |*args|
36
- event_after(*args)
37
- end
38
- view.signal_connect('motion-notify-event') do |*args|
39
- motion_notify_event(*args)
40
- end
41
- view.signal_connect('visibility-notify-event') do |*args|
42
- visibility_notify_event(*args)
18
+ @view.signal_connect "key-press-event" do |_widget, event|
19
+ case event.keyval
20
+ when Gdk::Keyval::KEY_Return, Gdk::Keyval::KEY_KP_Enter
21
+ iter = @buffer.get_iter_at_mark(@buffer.get_mark("insert"))
22
+ follow_if_link(iter) if iter
43
23
  end
44
24
 
45
- buffer = view.buffer
46
-
47
- sw = Gtk::ScrolledWindow.new
48
- sw.set_policy(:automatic,
49
- :automatic)
50
-
51
- add(sw)
52
- sw.add(view)
53
-
54
- show_page(buffer, 1)
25
+ false
55
26
  end
56
27
 
28
+ # Links can also be activated by clicking or tapping.
29
+ @view.signal_connect "event-after" do |widget, event|
30
+ if event.is_a?(Gdk::EventButton) && event.button == 1
31
+ buffer = widget.buffer
57
32
 
58
- # Inserts a piece of text into the buffer, giving it the usual
59
- # appearance of a hyperlink in a web browser: blue and underlined.
60
- # Additionally, attaches some data on the tag, to make it recognizable
61
- # as a link.
62
- def insert_link(buffer, iter, text, page)
63
- tag = buffer.create_tag(nil,
64
- {
65
- 'foreground' => 'blue',
66
- 'underline' => Pango::AttrUnderline::SINGLE,
67
- })
68
- tag.page = page
69
-
70
- buffer.insert(iter, text, tag)
71
- print("Insert #{tag}:#{page}\n")
72
- end
33
+ # we shouldn't follow a link if the user has selected something
34
+ range = buffer.selection_bounds
35
+ return false if range && range[0].offset != range[1].offset
73
36
 
74
- # Fills the buffer with text and interspersed links. In any real
75
- # hypertext app, this method would parse a file to identify the links.
76
- def show_page(buffer, page)
77
- puts
78
-
79
- buffer.text = ''
80
- iter = buffer.get_iter_at(:offset => 0)
81
-
82
- case page
83
- when 1
84
- buffer.insert(iter, 'Some text ot show that simple ')
85
- insert_link(buffer, iter, 'hypertext', 3)
86
- buffer.insert(iter, ' can easily be realized with ')
87
- insert_link(buffer, iter, 'tags', 2)
88
- buffer.insert(iter, '.')
89
- when 2
90
- buffer.insert(iter,
91
- %Q[A tag is an attribute that can be applied to some range of text. For example, a tag might be called "bold" and make the text insid the tag bold. However, the tag concept is more general than that; tags don't have to affect appearance. They can instead affect the behavior of mouse and key presses, "lock" a range of text so the user can't edit it, or countless other things.])
92
- buffer.insert(iter, "\n")
93
- insert_link(buffer, iter, 'Go back', 1)
94
- when 3
95
- tag = buffer.create_tag(nil,
96
- {
97
- 'weight' =>
98
- Pango::FontDescription::WEIGHT_BOLD
99
- })
100
- buffer.insert(iter, "hypertext:\n", tag);
101
- buffer.insert(iter, %Q[machine-readable text that is not sequential but is organized so that related items of information are connected.\n])
102
- insert_link(buffer, iter, 'Go back', 1)
37
+ x, y = widget.window_to_buffer_coords(:widget, event.x, event.y)
38
+ iter = widget.get_iter_at_location(x, y)
39
+ follow_if_link(iter) if iter
40
+ else
41
+ false
103
42
  end
104
43
  end
105
44
 
106
- # Looks at all tags covering the position of iter in the text view,
107
- # and if one of them is a link, follow it by showing the page identified
108
- # by the data attached to it.
109
- def follow_if_link(text_view, iter)
110
- tags = iter.tags
111
- tags.each do |tag|
112
- print("Follow #{tag}:#{tag.page}\n")
113
- if tag.page
114
- show_page(text_view.buffer, tag.page)
115
- break
116
- end
117
- end
118
- end
119
-
120
- # Links can be activated by pressing Enter.
121
- def key_press_event(text_view, event)
122
- case event.keyval
123
- when Gdk::Keyval::KEY_Return, Gdk::Keyval::KEY_KP_Enter
124
- buffer = text_view.buffer
125
- iter = buffer.get_iter_at_mark(buffer.get_mark("insert"))
126
- follow_if_link(text_view, iter)
127
- end
45
+ @view.signal_connect "motion-notify-event" do |widget, event|
46
+ x, y = widget.window_to_buffer_coords(:widget, event.x, event.y)
47
+ set_cursor_if_appropriate(widget, x, y)
48
+ widget.window.pointer
128
49
 
129
50
  false
130
51
  end
131
52
 
132
- # Links can also be activated by clicking.
133
- def event_after(text_view, event)
134
- unless event.kind_of?(Gdk::EventButton) and event.button == 1
135
- return false
136
- end
53
+ sw = Gtk::ScrolledWindow.new
54
+ sw.set_policy(:automatic, :automatic)
55
+ @window.add(sw)
56
+ sw.add(@view)
57
+ show_page(1)
58
+ sw.show_all
59
+ end
137
60
 
138
- buffer = text_view.buffer
61
+ def run
62
+ if !@window.visible?
63
+ @window.show_all
64
+ else
65
+ @window.destroy
66
+ end
67
+ @window
68
+ end
139
69
 
140
- # we shouldn't follow a link if the user has selected something
141
- range = buffer.selection_bounds
142
- if range and range[0].offset != range[1].offset
143
- return false
144
- end
70
+ private
145
71
 
146
- x, y = text_view.window_to_buffer_coords(Gtk::TextView::WINDOW_WIDGET,
147
- event.x, event.y)
148
- iter = text_view.get_iter_at_location(x, y)
72
+ def initialize_window(main_window)
73
+ @window = Gtk::Window.new(:toplevel)
74
+ @window.screen = main_window.screen
75
+ @window.title = "Hypertext"
76
+ @window.set_default_size(450, 450)
77
+ @window.border_width = 0
78
+ end
149
79
 
150
- follow_if_link(text_view, iter)
151
- end
80
+ def initialize_cursors(main_window)
81
+ display = main_window.display
82
+ @hand_cursor = Gdk::Cursor.new("pointer", :display => display)
83
+ @regular_cursor = Gdk::Cursor.new("text", :display => display)
84
+ end
152
85
 
153
- # Looks at all tags covering the position (x, y) in the text view,
154
- # and if one of them is a link, change the cursor to the "hands" cursor
155
- # typically used by web browsers.
156
- def set_cursor_if_appropriate(text_view, x, y)
86
+ def initialize_view
87
+ @view = Gtk::TextView.new
88
+ @view.wrap_mode = :word
89
+ @view.left_margin = 20
90
+ @view.right_margin = 20
91
+ @buffer = @view.buffer
92
+ end
157
93
 
158
- buffer = text_view.buffer
159
- iter = text_view.get_iter_at_location(x, y)
94
+ # Fills the buffer with text and interspersed links. In any real
95
+ # hypertext app, this method would parse a file to identify the links.
96
+ def show_page(page)
97
+ @buffer.text = ""
98
+ case page
99
+ when 1
100
+ generate_page_1
101
+ when 2
102
+ generate_page_2
103
+ when 3
104
+ generate_page_3
105
+ end
106
+ end
160
107
 
161
- hovering = false
108
+ def generate_page_1
109
+ iter = @buffer.get_iter_at(:offset => 0)
110
+ @buffer.insert(iter, "Some text to show that simple")
111
+ insert_link(iter, "hyper text", 3)
112
+ @buffer.insert(iter, " can easily be realized with ")
113
+ insert_link(iter, "tags", 2)
114
+ @buffer.insert(iter, ".")
115
+ end
162
116
 
163
- tags = iter.tags
164
- tags.each do |t|
165
- if t.page
166
- hovering = true
167
- break
168
- end
169
- end
117
+ def generate_page_2
118
+ iter = @buffer.get_iter_at(:offset => 0)
119
+ @buffer.insert(iter, <<-EOF)
120
+ A tag is an attribute that can be applied to some range of text.
121
+ For example, a tag might be called "bold" and make the text inside
122
+ the tag bold. However, the tag concept is more general than that;
123
+ tags don't have to affect appearance. They can instead affect the
124
+ behavior of mouse and key presses, "lock" a range of text so the
125
+ user can't edit it, or countless other things.\n
126
+ EOF
127
+ insert_link(iter, "Goback", 1)
128
+ end
170
129
 
171
- if hovering != @hovering
172
- @hovering = hovering
130
+ def generate_page_3
131
+ iter = @buffer.get_iter_at(:offset => 0)
132
+ tag = @buffer.create_tag(nil,
133
+ "weight" => Pango::FontDescription::WEIGHT_BOLD)
134
+ @buffer.insert(iter, "hypertext:\n", :tags => [tag])
135
+ @buffer.insert(iter, <<-EOF)
136
+ machine-readable text that is not sequential but is organized
137
+ so that related items of information are connected
138
+ EOF
139
+ insert_link(iter, "Go back", 1)
140
+ end
173
141
 
174
- window = text_view.get_window(Gtk::TextView::WINDOW_TEXT)
142
+ def insert_link(iter, text, page)
143
+ tag = @buffer.create_tag(nil,
144
+ "foreground" => "blue",
145
+ "underline" => Pango::AttrUnderline::SINGLE)
146
+ tag.page = page
147
+ @buffer.insert(iter, text, :tags => [tag])
148
+ end
175
149
 
176
- window.cursor = if @hovering
177
- @hand_cursor
178
- else
179
- @regular_cursor
180
- end
150
+ # Looks at all tags covering the position of iter in the text view,
151
+ # and if one of them is a link, follow it by showing the page identified
152
+ # by the data attached to it.
153
+ def follow_if_link(iter)
154
+ tags = iter.tags
155
+ tags.each do |tag|
156
+ if tag.page
157
+ show_page(tag.page)
158
+ break
181
159
  end
182
160
  end
161
+ end
183
162
 
184
- # Update the cursor image if the pointer moved.
185
- def motion_notify_event(text_view, event)
186
- x, y = text_view.window_to_buffer_coords(Gtk::TextView::WINDOW_WIDGET,
187
- event.x, event.y)
188
- set_cursor_if_appropriate(text_view, x, y)
189
- text_view.window.pointer
190
-
191
- false
163
+ # Looks at all tags covering the position (x, y) in the text view,
164
+ # and if one of them is a link, change the cursor to the "hands" cursor
165
+ # typically used by web browsers.
166
+ def set_cursor_if_appropriate(text_view, x, y)
167
+ iter = text_view.get_iter_at_location(x, y)
168
+ return unless iter
169
+ hovering = false
170
+ tags = iter.tags
171
+ tags.each do |tag|
172
+ if tag.page
173
+ hovering = true
174
+ break
175
+ end
192
176
  end
193
177
 
194
- # Also update the cursor image if the window becomes visible
195
- # (e.g. when a window covering it got iconified).
196
- def visibility_notify_event (text_view, event)
197
- window, wx, wy = text_view.window.pointer
198
- bx, by = text_view.window_to_buffer_coords(Gtk::TextView::WINDOW_WIDGET,
199
- wx, wy)
200
- set_cursor_if_appropriate(text_view, bx, by)
201
-
202
- false
178
+ if hovering != @hovering
179
+ @hovering = hovering
180
+ window = text_view.get_window(:text)
181
+ window.cursor = @hovering ? @hand_cursor : @regular_cursor
203
182
  end
204
183
  end
205
184
  end