gtk3 3.0.7-x86-mingw32 → 3.0.8-x86-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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/ext/gtk3/extconf.rb +1 -0
  3. data/ext/gtk3/rb-gtk3-tree-view.c +4 -0
  4. data/ext/gtk3/rb-gtk3.c +245 -60
  5. data/lib/2.2/gtk3.so +0 -0
  6. data/lib/2.3/gtk3.so +0 -0
  7. data/lib/gtk3/box.rb +22 -0
  8. data/lib/gtk3/builder.rb +50 -29
  9. data/lib/gtk3/deprecated.rb +7 -0
  10. data/lib/gtk3/entry-buffer.rb +28 -0
  11. data/lib/gtk3/list-store.rb +2 -20
  12. data/lib/gtk3/loader.rb +6 -0
  13. data/lib/gtk3/menu-item.rb +8 -7
  14. data/lib/gtk3/tree-iter.rb +25 -1
  15. data/lib/gtk3/tree-model.rb +41 -0
  16. data/lib/gtk3/tree-store.rb +7 -6
  17. data/lib/gtk3/widget.rb +18 -1
  18. data/sample/gtk-demo/TODO +45 -39
  19. data/sample/gtk-demo/assistant.rb +123 -0
  20. data/sample/gtk-demo/builder.rb +75 -38
  21. data/sample/gtk-demo/button_box.rb +100 -0
  22. data/sample/gtk-demo/colorsel.rb +49 -65
  23. data/sample/gtk-demo/css_accordion.rb +33 -55
  24. data/sample/gtk-demo/css_basics.rb +55 -80
  25. data/sample/gtk-demo/css_multiplebgs.rb +112 -0
  26. data/sample/gtk-demo/css_pixbufs.rb +84 -0
  27. data/sample/gtk-demo/css_shadows.rb +101 -0
  28. data/sample/gtk-demo/cursors.rb +114 -0
  29. data/sample/gtk-demo/dialog.rb +105 -115
  30. data/sample/gtk-demo/entry_buffer.rb +44 -0
  31. data/sample/gtk-demo/entry_completion.rb +40 -52
  32. data/sample/gtk-demo/expander.rb +60 -26
  33. data/sample/gtk-demo/filtermodel.rb +119 -0
  34. data/sample/gtk-demo/font_features.rb +117 -0
  35. data/sample/gtk-demo/headerbar.rb +57 -0
  36. data/sample/gtk-demo/iconview_edit.rb +79 -0
  37. data/sample/gtk-demo/infobar.rb +75 -59
  38. data/sample/gtk-demo/links.rb +53 -40
  39. data/sample/gtk-demo/main.rb +353 -43
  40. data/sample/gtk-demo/main.ui +9 -9
  41. data/sample/gtk-demo/markup.rb +46 -0
  42. data/sample/gtk-demo/menus.rb +111 -162
  43. data/sample/gtk-demo/modelbutton.rb +47 -0
  44. data/sample/gtk-demo/overlay.rb +61 -0
  45. data/sample/gtk-demo/overlay2.rb +75 -0
  46. data/sample/gtk-demo/panes.rb +114 -133
  47. data/sample/gtk-demo/pickers.rb +70 -0
  48. data/sample/gtk-demo/popover.rb +110 -0
  49. data/sample/gtk-demo/printing.rb +68 -83
  50. data/sample/gtk-demo/revealer.rb +53 -0
  51. data/sample/gtk-demo/scale.rb +26 -0
  52. data/sample/gtk-demo/search_entry2.rb +107 -0
  53. data/sample/gtk-demo/sidebar.rb +68 -0
  54. data/sample/gtk-demo/sizegroup.rb +93 -105
  55. data/sample/gtk-demo/spinner.rb +53 -50
  56. data/sample/gtk-demo/stack.rb +28 -0
  57. data/sample/gtk-demo/test_mod.rb +22 -0
  58. data/sample/gtk-demo/textmask.rb +61 -0
  59. data/sample/gtk-demo/theming_style_classes.rb +16 -12
  60. data/sample/misc/app-menu.ui +19 -0
  61. data/sample/misc/button-menu.ui +19 -0
  62. data/sample/misc/icons-theme-viewer.rb +65 -0
  63. data/sample/misc/menu.rb +3 -3
  64. data/sample/misc/menus_from_resources.gresource.xml +8 -0
  65. data/sample/misc/menus_from_resources.rb +91 -0
  66. data/sample/misc/statusicon.rb +1 -1
  67. data/sample/misc/toolbar-menu.ui +23 -0
  68. data/sample/misc/treestore.rb +63 -0
  69. data/sample/tutorial/README.md +368 -6
  70. data/test/test-gtk-box.rb +13 -0
  71. data/test/test-gtk-builder.rb +1 -1
  72. data/test/test-gtk-clipboard.rb +124 -0
  73. data/test/test-gtk-container.rb +3 -3
  74. data/test/test-gtk-entry-buffer.rb +32 -0
  75. data/test/test-gtk-list-store.rb +30 -12
  76. data/test/test-gtk-menu.rb +32 -0
  77. data/test/test-gtk-tree-iter.rb +61 -5
  78. data/test/test-gtk-tree-path.rb +26 -1
  79. data/test/test-gtk-tree-sortable.rb +35 -0
  80. data/test/test-gtk-tree-store.rb +34 -0
  81. data/test/test-gtk-widget.rb +33 -2
  82. metadata +57 -22
  83. data/lib/2.0/gtk3.so +0 -0
  84. data/lib/2.1/gtk3.so +0 -0
  85. data/sample/gtk-demo/button-box.rb +0 -82
@@ -0,0 +1,57 @@
1
+ # Copyright (c) 2015 Ruby-GNOME2 Project Team
2
+ # This program is licenced under the same licence as Ruby-GNOME2.
3
+ #
4
+ =begin
5
+ = Header Bar
6
+
7
+ GtkHeaderBar is a container that is suitable for implementing
8
+ window titlebars. One of its features is that it can position
9
+ a title (and optional subtitle) centered with regard to the
10
+ full width, regardless of variable-width content at the left
11
+ or right.
12
+
13
+ It is commonly used with gtk_window_set_titlebar()
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)
20
+
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)
25
+
26
+ button = Gtk::Button.new()
27
+
28
+ icon = Gio::ThemedIcon.new("mail-send-receive-symbolic")
29
+ image = Gtk::Image.new(:icon => icon, :size => :button)
30
+
31
+ button.add(image)
32
+ header.pack_end(button)
33
+
34
+ box = Gtk::Box.new(:horizontal, 0)
35
+ box.style_context.add_class("linked")
36
+
37
+ button = Gtk::Button.new
38
+ image = Gtk::Image.new(:icon_name => "pan-start-symbolic", :size => :button)
39
+ button.add(image)
40
+ box.add(button)
41
+
42
+ button = Gtk::Button.new
43
+ image = Gtk::Image.new(:icon_name => "pan-end-symbolic", :size => :button)
44
+ button.add(image)
45
+ box.add(button)
46
+
47
+ header.pack_start(box)
48
+ window.set_titlebar(header)
49
+ window.add(Gtk::TextView.new())
50
+
51
+ if !window.visible?
52
+ window.show_all
53
+ else
54
+ window.destroy
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,79 @@
1
+ # Copyright (c) 2015 Ruby-GNOME2 Project Team
2
+ # This program is licenced under the same licence as Ruby-GNOME2.
3
+ #
4
+ =begin
5
+ = Icon View/Editing and Drag-and-Drop
6
+
7
+ The GtkIconView widget supports Editing and Drag-and-Drop.
8
+ This example also demonstrates using the generic GtkCellLayout
9
+ interface to set up cell renderers in an icon view.
10
+ =end
11
+ module IconviewEditDemo
12
+ COL_TEXT = 0
13
+ NUM_COLS = 1
14
+ def self.run_demo(main_window)
15
+ window = Gtk::Window.new(:toplevel)
16
+ window.screen = main_window.screen
17
+ window.set_title("Editing and Drag-and-drop")
18
+
19
+ store = create_store
20
+ fill_store(store)
21
+
22
+ icon_view = Gtk::IconView.new(:model => store)
23
+ icon_view.set_selection_mode(:single)
24
+ icon_view.set_item_orientation(:horizontal)
25
+ icon_view.set_columns(2)
26
+ icon_view.set_reorderable(true)
27
+
28
+ renderer = Gtk::CellRendererPixbuf.new
29
+ icon_view.pack_start(renderer, true)
30
+
31
+ icon_view.set_cell_data_func(renderer) do |_layout, cell_renderer, model, iter|
32
+ text = model.get_value(iter, COL_TEXT)
33
+ if text
34
+ color = Gdk::RGBA.parse(text)
35
+ pixel = nil
36
+ if color
37
+ pixel = (color.red * 255).to_i << 24 |
38
+ (color.green * 255).to_i << 16 |
39
+ (color.blue * 255).to_i << 8 |
40
+ (color.alpha * 255).to_i
41
+ end
42
+ pixbuf = Gdk::Pixbuf.new(Gdk::Pixbuf::COLORSPACE_RGB, true, 8, 24, 24)
43
+ pixbuf.fill!(pixel) if pixel
44
+ cell_renderer.set_property("pixbuf", pixbuf)
45
+ end
46
+ end
47
+
48
+ renderer = Gtk::CellRendererText.new
49
+ icon_view.pack_start(renderer, true)
50
+ renderer.set_property("editable", true)
51
+ renderer.signal_connect("edited") do |_cell, path_string, text|
52
+ model = icon_view.model
53
+ path = Gtk::TreePath.new(path_string)
54
+ iter = model.get_iter(path)
55
+ iter[COL_TEXT] = text
56
+ end
57
+
58
+ icon_view.set_attributes(renderer, "text" => COL_TEXT)
59
+ window.add(icon_view)
60
+
61
+ if !window.visible?
62
+ window.show_all
63
+ else
64
+ window.destroy
65
+ end
66
+ window
67
+ end
68
+
69
+ def self.create_store
70
+ store = Gtk::ListStore.new(String)
71
+ store
72
+ end
73
+
74
+ def self.fill_store(store)
75
+ %w(Red Green Blue Yellow).each do |color|
76
+ store.append.set_values([color])
77
+ end
78
+ end
79
+ end
@@ -1,78 +1,94 @@
1
- # Copyright (c) 2013 Ruby-GNOME2 Project Team
1
+ # Copyright (c) 2015 Ruby-GNOME2 Project Team
2
2
  # This program is licenced under the same licence as Ruby-GNOME2.
3
3
  #
4
4
  =begin
5
- = Info bar
5
+ = Info Bars
6
6
 
7
- Info bar widgets are used to report important messages to the user.
7
+ Info bar widgets are used to report important messages to the user.
8
8
  =end
9
- require 'common'
10
-
11
- module Demo
12
- class InfoBar < BasicWindow
13
- def initialize
14
- super('Info Bars')
15
-
16
- self.border_width = 8
9
+ module InfobarDemo
10
+ def self.run_demo(main_window)
11
+ actions = Gtk::Box.new(:horizontal, 0)
12
+
13
+ window = Gtk::Window.new(:toplevel)
14
+ window.screen = main_window.screen
15
+ window.set_title("Info Bars")
16
+ window.set_border_width(8)
17
+
18
+ vbox = Gtk::Box.new(:vertical, 0)
19
+ window.add(vbox)
20
+
21
+ generate_simple_infobar_and_button("info", vbox, actions)
22
+ generate_simple_infobar_and_button("warning", vbox, actions)
23
+
24
+ bar = Gtk::InfoBar.new
25
+ bar.add_button("_OK", Gtk::ResponseType::OK)
26
+ bar.set_show_close_button(true)
27
+ bar.signal_connect "response" do |info_bar, response_id|
28
+ info_bar.hide if response_id == Gtk::ResponseType::CLOSE
29
+ dialog = Gtk::MessageDialog.new(:parent => info_bar.toplevel,
30
+ :flags => [:modal, :destroy_with_parent],
31
+ :type => :info,
32
+ :buttons => :ok,
33
+ :message => "You clicked a button on an info bar")
34
+ dialog.secondary_text = "Your response has id #{response_id}"
35
+ dialog.signal_connect("response") { |widget| widget.destroy }
36
+ dialog.show_all
37
+ end
17
38
 
39
+ vbox.pack_start(bar,
40
+ :expand => false,
41
+ :fill => false,
42
+ :padding => 0)
18
43
 
19
- vbox = Gtk::Box.new :vertical
20
- self.add vbox
44
+ bar.set_message_type(:question)
45
+ label = Gtk::Label.new("This is an info bar with message type Gtk::MessageType::QUESTION")
46
+ label.set_line_wrap(true)
47
+ label.set_xalign(0)
21
48
 
22
- bar = Gtk::InfoBar.new
23
- vbox.pack_start bar, :expand => false, :fill => false, :padding => 0
24
- bar.message_type = :info
25
- label = Gtk::Label.new 'This is an info bar with message type GTK_MESSAGE_INFO'
26
- bar.content_area.pack_start label, :expand => false, :fill => false, :padding => 0
49
+ bar.content_area.pack_start(label, :expand => false, :fill => false, :padding => 0)
27
50
 
28
- bar = Gtk::InfoBar.new
29
- vbox.pack_start bar, :expand => false, :fill => false, :padding => 0
30
- bar.message_type = :warning
31
- label = Gtk::Label.new 'This is an info bar with message type GTK_MESSAGE_WARNING'
32
- bar.content_area.pack_start label, :expand => false, :fill => false, :padding => 0
51
+ button = Gtk::ToggleButton.new(:label => "Question")
52
+ button.bind_property("active", bar, "visible", :bidirectional)
53
+ actions.add(button)
54
+ button.set_active(false)
33
55
 
34
- bar = Gtk::InfoBar.new [:ok, :ok]
35
- bar.signal_connect(:response) {|widget, response_id| on_bar_response widget, response_id}
36
- vbox.pack_start bar, :expand => false, :fill => false, :padding => 0
37
- bar.message_type = :question
38
- label = Gtk::Label.new 'This is an info bar with message type GTK_MESSAGE_QUESTION'
39
- bar.content_area.pack_start label, :expand => false, :fill => false, :padding => 0
56
+ generate_simple_infobar_and_button("error", vbox, actions)
57
+ generate_simple_infobar_and_button("other", vbox, actions)
40
58
 
41
- bar = Gtk::InfoBar.new
42
- vbox.pack_start bar, :expand => false, :fill => false, :padding => 0
43
- bar.message_type = :error
44
- label = Gtk::Label.new 'This is an info bar with message type GTK_MESSAGE_ERROR'
45
- bar.content_area.pack_start label, :expand => false, :fill => false, :padding => 0
59
+ frame = Gtk::Frame.new("Info bars")
60
+ vbox.pack_start(frame, :expand => false, :fill => false, :padding => 8)
46
61
 
47
- bar = Gtk::InfoBar.new
48
- vbox.pack_start bar, :expand => false, :fill => false, :padding => 0
49
- bar.message_type = :other
50
- label = Gtk::Label.new 'This is an info bar with message type GTK_MESSAGE_OTHER'
51
- bar.content_area.pack_start label, :expand => false, :fill => false, :padding => 0
62
+ vbox2 = Gtk::Box.new(:vertical, 8)
63
+ vbox2.set_border_width(8)
64
+ frame.add(vbox2)
52
65
 
66
+ label = Gtk::Label.new("An example of different info bars")
67
+ vbox2.pack_start(label, :expand => false, :fill => false, :padding => 0)
68
+ actions.show_all
69
+ vbox2.pack_start(actions, :expand => false, :fill => false, :padding => 0)
53
70
 
54
- frame = Gtk::Frame.new 'Info bars'
55
- vbox.pack_start frame, :expand => false, :fill => false, :padding => 8
71
+ if !window.visible?
72
+ window.show_all
73
+ else
74
+ window.destroy
75
+ end
76
+ window
77
+ end
56
78
 
57
- vbox2 = Gtk::Box.new :vertical, 8
58
- vbox2.border_width = 8
59
- frame.add vbox2
79
+ def self.generate_simple_infobar_and_button(message_type, bar_parent, button_parent)
80
+ bar = Gtk::InfoBar.new
81
+ bar_parent.pack_start(bar, :expand => false, :fill => false, :padding => 0)
82
+ bar.set_message_type(message_type.to_sym)
60
83
 
61
- # Standard message dialog
62
- label = Gtk::Label.new 'An example of different info bars'
63
- vbox2.pack_start label, :expand => false, :fill => false, :padding => 0
64
- end
84
+ label = Gtk::Label.new("This is an info bar with message type Gtk::MessageType::#{message_type.upcase}")
85
+ label.set_line_wrap(true)
86
+ label.set_xalign(0)
65
87
 
66
- def on_bar_response info_bar, response_id
67
- dialog = Gtk::MessageDialog.new :parent => self,
68
- :flags => [:modal, :destroy_with_parent],
69
- :type => :info,
70
- :buttons_type => :ok,
71
- :message => 'You clicked a button on an info bar'
88
+ bar.content_area.pack_start(label, :expand => false, :fill => false, :padding => 0)
72
89
 
73
- dialog.set_secondary_text "Your response has id %d" % response_id
74
- dialog.signal_connect(:response) {dialog.destroy}
75
- dialog.show_all
76
- end
90
+ button = Gtk::ToggleButton.new(:label => "Message")
91
+ button.bind_property("active", bar, "visible", :bidirectional)
92
+ button_parent.add(button)
77
93
  end
78
- end
94
+ end
@@ -1,53 +1,66 @@
1
- # Copyright (c) 2013 Ruby-GNOME2 Project Team
1
+ # Copyright (c) 2015 Ruby-GNOME2 Project Team
2
2
  # This program is licenced under the same licence as Ruby-GNOME2.
3
3
  #
4
4
  =begin
5
5
  = Links
6
6
 
7
- GtkLabel can show hyperlinks. The default action is to call gtk_show_uri() on their URI, but it is possible to override this with a custom handler.
7
+ GtkLabel can show hyperlinks. The default action is to call
8
+ gtk_show_uri() on their URI, but it is possible to override
9
+ this with a custom handler.
8
10
  =end
9
- require 'common'
11
+ module LinksDemo
12
+ def self.run_demo(main_window)
13
+ window = Gtk::Window.new(:toplevel)
14
+ window.screen = main_window.screen
15
+ window.set_title("Links")
16
+ window.set_border_width(12)
10
17
 
11
- module Demo
12
- class Links < BasicWindow
13
- def initialize
14
- super('Links')
18
+ label = Gtk::Label.new(<<-MESSAGE)
19
+ Some <a href="http://en.wikipedia.org/wiki/Text"
20
+ title="plain text">text</a> may be marked up
21
+ as hyperlinks, which can be clicked
22
+ or activated via <a href="keynav">keynav</a>
23
+ and they work fine with other markup, like when
24
+ searching on <a href="http://www.google.com/">
25
+ <span color="#0266C8">G</span><span color="#F90101">o</span>
26
+ <span color="#F2B50F">o</span><span color="#0266C8">g</span>
27
+ <span color="#00933B">l</span><span color="#F90101">e</span>
28
+ </a>.
29
+ MESSAGE
30
+ label.set_use_markup(true)
15
31
 
16
- title = 'Links'
17
- border_width = 12
18
- signal_connect(:destroy) {self.destroy}
19
-
20
- label = Gtk::Label.new "Some <a href=\"http://en.wikipedia.org/wiki/Text\"" +
21
- "title=\"plain text\">text</a> may be marked up\n" +
22
- "as hyperlinks, which can be clicked\n" +
23
- "or activated via <a href=\"keynav\">keynav</a>\n" +
24
- "and they work fine with other markup, like when\n" +
25
- "searching on <a href=\"http://www.google.com/\">" +
26
- "<span color=\"#0266C8\">G</span><span color=\"#F90101\">o</span>" +
27
- "<span color=\"#F2B50F\">o</span><span color=\"#0266C8\">g</span>" +
28
- "<span color=\"#00933B\">l</span><span color=\"#F90101\">e</span>" +
29
- "</a>."
30
- label.use_markup = true
31
- label.signal_connect(:activate_link) {|widget, uri| activate_link uri}
32
- add label
33
- label.show
32
+ label.signal_connect "activate-link" do |_widget, uri|
33
+ if uri == "keynav"
34
+ parent = label.toplevel
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
50
+ true
51
+ else
52
+ false
53
+ end
34
54
  end
35
55
 
36
- def activate_link uri
37
- if uri == 'keynav'
38
- dialog = Gtk::MessageDialog.new :parent => self,
39
- :flags => :destroy_with_parent,
40
- :type => :info,
41
- :buttons_type => :ok
56
+ window.add(label)
57
+ label.show
42
58
 
43
- dialog.markup = "The term <i>keynav</i> is a shorthand for " +
44
- "keyboard navigation and refers to the process of using " +
45
- "a program (exclusively) via keyboard input."
46
- dialog.present
47
- dialog.signal_connect(:response) {dialog.destroy}
48
- return true
49
- end
50
- false
59
+ if !window.visible?
60
+ window.show_all
61
+ else
62
+ window.destroy
51
63
  end
64
+ window
52
65
  end
53
- end
66
+ end
@@ -21,6 +21,7 @@ require "optparse"
21
21
  require "fileutils"
22
22
 
23
23
  current_path = File.expand_path(File.dirname(__FILE__))
24
+
24
25
  gresource_bin = "#{current_path}/demo.gresource"
25
26
  gresource_xml = "#{current_path}/demo.gresource.xml"
26
27
 
@@ -42,24 +43,205 @@ Gio::Resources.register(resource)
42
43
 
43
44
  ENV["GSETTINGS_SCHEMA_DIR"] = current_path
44
45
 
46
+ TITLE_COLUMN = 0
47
+ FILENAME_COLUMN = 1
48
+ STYLE_COLUMN = 2
49
+
50
+ def script_info(path)
51
+ title = depend = nil
52
+ file = File.open(path)
53
+ file.each do |ln|
54
+ if !title && ln =~ /^=\s+(.*)$/
55
+ title = Regexp.last_match(1)
56
+ if title =~ /^(.*)\((.+?)\)$/
57
+ title = Regexp.last_match(1)
58
+ depend = Regexp.last_match(2)
59
+ end
60
+ end
61
+
62
+ break if title
63
+ end
64
+
65
+ [title, depend]
66
+ end
67
+
68
+ def generate_index
69
+ # Target scripts
70
+ scripts = Dir.glob(File.join(File.dirname(__FILE__), "*.rb"))
71
+ # Generate index tree
72
+ children = {}
73
+ index = []
74
+
75
+ scripts.each do |script|
76
+ next if ["common.rb", "main.rb"].include?(File.basename(script))
77
+ title, depend = script_info(script)
78
+
79
+ next if depend && !Gtk.const_defined?(depend)
80
+
81
+ if title =~ %r{^(.+?)/(.+)$}
82
+ parent = Regexp.last_match(1)
83
+ child = Regexp.last_match(2)
84
+
85
+ unless children[parent]
86
+ children[parent] = []
87
+ index += [[parent, nil, []]]
88
+ end
89
+ children[parent] += [[child, script]]
90
+ else
91
+ index += [[title, script]]
92
+ end
93
+ end
94
+
95
+ # Sort children
96
+ children.each_key do |parent|
97
+ children[parent].sort! do |a, b|
98
+ a[0] <=> b[0]
99
+ end
100
+ end
101
+
102
+ # Expand children
103
+ index.collect! do |row|
104
+ row[2] = children[row[0]] if row[2]
105
+
106
+ row
107
+ end
108
+
109
+ index.sort! do |a, b|
110
+ a[0] <=> b[0]
111
+ end
112
+
113
+ index
114
+ end
115
+
116
+ def append_children(model, source, parent = nil)
117
+ source.each do |title, filename, children|
118
+ iter = model.append(parent)
119
+ iter[TITLE_COLUMN] = title
120
+ iter[FILENAME_COLUMN] = filename
121
+ iter[STYLE_COLUMN] = Pango::FontDescription::STYLE_NORMAL
122
+
123
+ append_children(model, children, iter) if children
124
+ end
125
+ end
126
+
127
+ def get_demo_name_from_filename(filename)
128
+ File.basename(filename, ".rb").tr("-", "_")
129
+ end
130
+
131
+ def get_module_name_from_filename(filename)
132
+ pattern = get_demo_name_from_filename(filename)
133
+ module_name = pattern.split("_").map(&:capitalize).join
134
+ module_name << "Demo"
135
+ end
136
+
137
+ def list_demos(source, is_child = false)
138
+ source.each do |title, filename, children|
139
+ if is_child
140
+ printf("%-30.30s", "\t" + title)
141
+ printf("%-30.30s", get_demo_name_from_filename(filename))
142
+ puts ""
143
+ elsif filename
144
+ printf("%-38.38s", title)
145
+ printf("%-30.30s", get_demo_name_from_filename(filename))
146
+ puts ""
147
+ else
148
+ puts "#{title} : "
149
+ end
150
+
151
+ list_demos(children, true) if children
152
+ end
153
+ end
45
154
 
155
+ def find_demo_filename_from_name(source, name)
156
+ demo_filename = nil
157
+ source.each do |_title, filename, children|
158
+ if filename && name == get_demo_name_from_filename(filename)
159
+ demo_filename = filename
160
+ end
161
+ break if demo_filename
162
+ (demo_filename = find_demo_filename_from_name(children, name)) if children
163
+ end
164
+ demo_filename
165
+ end
166
+
167
+ def get_demo_filename_from_name(name)
168
+ index = generate_index
169
+ filename = find_demo_filename_from_name(index, name)
170
+ puts "Demo not found" unless filename
171
+
172
+ filename
173
+ end
174
+
175
+ def run_demo_from_file(filename, window)
176
+ module_name = get_module_name_from_filename(filename)
177
+
178
+ unless Module.const_defined?(module_name) == true
179
+ require filename
180
+ end
181
+
182
+ module_object = Module.const_get(module_name)
183
+ demo = module_object.send(:run_demo, window)
184
+
185
+ if demo && demo.class == Gtk::Window
186
+ demo.set_transient_for(window)
187
+ demo.modal = true
188
+ end
189
+ demo
190
+ end
46
191
 
47
192
  class Demo < Gtk::Application
48
193
  def initialize
49
194
  super("org.gtk.Demo", [:non_unique, :handles_command_line])
50
195
 
196
+ action = Gio::SimpleAction.new("quit")
197
+ action.signal_connect "activate" do |_action, _parameter|
198
+ quit
199
+ end
200
+ add_action(action)
201
+
202
+ action = Gio::SimpleAction.new("about")
203
+ action.signal_connect "activate" do |_action, _parameter|
204
+ Gtk::AboutDialog.show(active_window,
205
+ "program_name" => "GTK+ Demo",
206
+ "version" => Gtk::Version::STRING,
207
+ "copyright" => "(C) 1997-2013 The GTK+ Team",
208
+ "license_type" => Gtk::License::LGPL_2_1,
209
+ "website" => "http://www.gtk.org",
210
+ "comments" => "Program to demonstrate GTK+ widgets",
211
+ "authors" => ["The GTK+ Team"],
212
+ "logo_icon_name" => "gtk3-demo",
213
+ "title" => "About GTK+ Demo"
214
+ )
215
+ end
216
+
217
+ add_action(action)
51
218
  @options = {}
52
219
  @exit_status = 0
53
220
 
54
221
  signal_connect "startup" do |application|
55
- puts "startup"
56
222
  @builder = Gtk::Builder.new(:resource => "/ui/main.ui")
57
223
  appmenu = @builder["appmenu"]
58
224
  application.set_app_menu(appmenu)
225
+
226
+ @info_buffer = Gtk::TextBuffer.new
227
+ @source_buffer = Gtk::TextBuffer.new
228
+
229
+ @info_buffer.create_tag("title",
230
+ "font" => "Sans 18")
231
+
232
+ @source_buffer.create_tag("comment",
233
+ "foreground" => "red")
234
+ @source_buffer.create_tag("const",
235
+ "foreground" => "ForestGreen")
236
+ @source_buffer.create_tag("string",
237
+ "foreground" => "RosyBrown",
238
+ "weight" => Pango::FontDescription::WEIGHT_BOLD
239
+ )
240
+ @source_buffer.create_tag("reserved",
241
+ "foreground" => "purple")
59
242
  end
60
243
 
61
- signal_connect "activate" do |application|
62
- puts "activate"
244
+ signal_connect "activate" do |_application|
63
245
  begin
64
246
  run_application
65
247
  rescue => error
@@ -68,8 +250,7 @@ class Demo < Gtk::Application
68
250
  end
69
251
  end
70
252
 
71
- signal_connect "command-line" do |application, command_line|
72
- puts "cmd"
253
+ signal_connect "command-line" do |_application, command_line|
73
254
  begin
74
255
  parse_command_line(command_line.arguments)
75
256
  rescue SystemExit => error
@@ -85,9 +266,10 @@ class Demo < Gtk::Application
85
266
  @exit_status
86
267
  end
87
268
  end
88
- end
269
+ end
89
270
 
90
271
  private
272
+
91
273
  def parse_command_line(arguments)
92
274
  parser = OptionParser.new
93
275
  parser.on("-r", "--run EXAMPLE", "Run an example") do |example|
@@ -109,66 +291,194 @@ class Demo < Gtk::Application
109
291
 
110
292
  def run_application
111
293
  if @options[:list]
112
- puts "list"
113
- # list_demos
294
+ list_demos(generate_index)
114
295
  quit
115
296
  end
116
297
 
117
- if @options[:name]
118
- puts "name"
119
- # lookup_for_corresponding_demo
120
- # load_demo
121
- end
122
-
123
- if @options[:autoquit]
124
- puts "autoquit"
125
- GLib::Timeout.add(1) do
126
- #implement auto_quit
127
- end
128
- end
129
-
130
298
  window = @builder["window"]
131
299
  add_window(window)
132
-
133
300
  action = Gio::SimpleAction.new("run")
301
+
134
302
  action.signal_connect "activate" do |_action, _parameter|
135
- # activate_run
303
+ selection = @treeview.selection
304
+ iter = selection.selected
305
+ filename = iter[1]
306
+ run_demo_from_file(filename, windows.first) if filename
136
307
  end
137
- add_action(action)
308
+ window.add_action(action)
138
309
 
139
- notebook = @builder["notebook"]
140
- info_textwiew = @builder["info-textview"]
141
- source_textview = @builder["source-textview"]
310
+ @notebook = @builder["notebook"]
311
+ @info_view = @builder["info-textview"]
312
+ @source_view = @builder["source-textview"]
142
313
  headerbar = @builder["headerbar"]
143
- treeview = @builder["treeview"]
144
- model = treeview.model
314
+ @treeview = @builder["treeview"]
315
+ model = @treeview.model
316
+ append_children(model, generate_index)
145
317
 
146
- sw = @builder["source-scrolledwindow"]
147
- scrollbar = sw.vscrollbar
318
+ @source_sw = @builder["source-scrolledwindow"]
319
+ scrollbar = @source_sw.vscrollbar
148
320
 
149
- menu = Gtk::Menu.new
321
+ @menu = Gtk::Menu.new
150
322
 
151
- item = Gtk::MenuItem.new("Start")
152
- menu.append(item)
323
+ item = Gtk::MenuItem.new(:label => "Start")
324
+ @menu.append(item)
153
325
  item.signal_connect "activate" do
154
- adj = scrollbar.adjustement
155
- adj.value = adj.get_lower
326
+ adj = scrollbar.adjustment
327
+ adj.value = adj.lower
156
328
  end
157
329
 
158
- item = Gtk::MenuItem.new("End")
159
- menu.append(item)
330
+ item = Gtk::MenuItem.new(:label => "End")
331
+ @menu.append(item)
160
332
  item.signal_connect "activate" do
161
- adj = scrollbar.adjustement
162
- adj.value = adj.get_upper - adj.get_page_size
333
+ adj = scrollbar.adjustment
334
+ adj.value = adj.upper - adj.page_size
163
335
  end
164
336
 
165
- menu.show_all
337
+ @info_sw = @builder["info-scrolledwindow"]
338
+
339
+ @menu.show_all
166
340
 
167
- scrollbar.signal_connect "popup-menu" do
168
- menu.popup(nil, nil, Gtk.current_event_time)
341
+ scrollbar.signal_connect "popup-menu" do |widget, button, activate_time|
342
+ @menu.popup(nil, nil, 0, Gtk.current_event_time)
343
+ end
344
+
345
+ @treeview.signal_connect "row-activated" do |_tree_view, path, _column|
346
+ iter = model.get_iter(path)
347
+ filename = iter[1]
348
+ iter[2] = Pango::FontDescription::STYLE_ITALIC
349
+ demo = run_demo_from_file(filename, windows.first)
350
+ demo.signal_connect "destroy" do
351
+ iter[2] = Pango::FontDescription::STYLE_NORMAL
352
+ end
353
+ end
354
+
355
+ treeview_selection = @builder["treeview-selection"]
356
+ treeview_selection.signal_connect "changed" do |selection, _model|
357
+ iter = selection.selected
358
+ filename = iter[1]
359
+ title = iter[0]
360
+ load_file(filename) if filename
361
+ headerbar.set_title(title)
169
362
  end
170
363
 
171
364
  window.show_all
365
+
366
+ if @options[:name]
367
+ filename = get_demo_filename_from_name(@options[:name])
368
+ run_demo_from_file(filename, windows.first)
369
+ end
370
+
371
+ if @options[:autoquit]
372
+ GLib::Timeout.add_seconds(1) do
373
+ quit
374
+ end
375
+ end
376
+ end
377
+
378
+ def fill_buffers_from(file)
379
+ start = @info_buffer.get_iter_at(:offset => 0)
380
+ state = :before_header
381
+
382
+ file.each do |line|
383
+ case state
384
+ when :before_header
385
+ state = :in_header if line =~ /^=begin$/
386
+ when :in_header
387
+ if line =~ /^=end$/
388
+ state = :body
389
+ start = @source_buffer.get_iter_at(:offset => 0)
390
+ elsif line =~ /^=\s+(.*)$/
391
+ title = Regexp.last_match(1)
392
+ title.gsub!(/\s*\(.*\)$/, "") # Delete depend field
393
+
394
+ last = start
395
+
396
+ @info_buffer.insert(last, title)
397
+ start = last.clone
398
+
399
+ start.backward_chars(title.length)
400
+ @info_buffer.apply_tag("title", start, last)
401
+
402
+ start = last
403
+ else
404
+ @info_buffer.insert(start, line)
405
+ end
406
+ when :body # Reading program body
407
+ @source_buffer.insert(start, line)
408
+ end
409
+ end
410
+ end
411
+
412
+ def load_file(filename)
413
+ return if filename == @current_file
414
+
415
+ # implement add_data_tab
416
+
417
+ @info_buffer.delete(*@info_buffer.bounds)
418
+
419
+ @source_buffer.delete(*@source_buffer.bounds)
420
+
421
+ file = begin
422
+ File.open(filename)
423
+ rescue
424
+ $stderr.puts "Cannot open: #{$ERROR_INFO}" if $DEBUG
425
+ return
426
+ end
427
+
428
+ fill_buffers_from(file)
429
+
430
+ fontify
431
+
432
+ @source_view.buffer = @source_buffer
433
+ @info_view.buffer = @info_buffer
434
+
435
+ @current_file = filename
436
+ end
437
+
438
+ def fontify(start_iter = @source_buffer.start_iter,
439
+ end_iter = @source_buffer.end_iter)
440
+ str = @source_buffer.get_text(start_iter, end_iter, true)
441
+ tokenizer = RubyTokonizer.new
442
+ tokenizer.tokenize(str, start_iter.offset) do |tag, start, last|
443
+ @source_buffer.apply_tag(tag.to_s,
444
+ @source_buffer.get_iter_at(:offset => start),
445
+ @source_buffer.get_iter_at(:offset => last))
446
+ end
447
+ end
448
+
449
+ class RubyTokonizer
450
+ RESERVED_WORDS = %w(begin end module class def if then else
451
+ while unless do case when require yield)
452
+ RESERVED_WORDS_PATTERN = Regexp.compile(/(^|\s+)(#{RESERVED_WORDS.collect do |pat| Regexp.quote(pat) end.join("|")})(\s+|$)/)
453
+
454
+ def tokenize(str, index = 0)
455
+ until str.empty?
456
+ tag = nil
457
+
458
+ case str
459
+ when /".+?"/, /'.+?'/
460
+ tag = :string
461
+ when /#.*$/
462
+ tag = :comment
463
+ when RESERVED_WORDS_PATTERN
464
+ tag = :reserved
465
+ when /[A-Z][A-Za-z0-9_]+/
466
+ tag = :const
467
+ end
468
+
469
+ if tag
470
+ tokenize($LAST_MATCH_INFO.pre_match, index) do |*args|
471
+ yield(*args)
472
+ end
473
+ yield(tag, index + $LAST_MATCH_INFO.begin(0), index + $LAST_MATCH_INFO.end(0))
474
+ index += (str.length - $LAST_MATCH_INFO.post_match.length)
475
+ str = $LAST_MATCH_INFO.post_match
476
+ else
477
+ index += str.length
478
+ str = ""
479
+ end
480
+ end
481
+ end
172
482
  end
173
483
  end
174
484