gtk4 4.0.3 → 4.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1fd29b5c43f2bbf99765dd2b0a165351a55ba71244c10392eed5f443f7953f13
4
- data.tar.gz: 7ed521f6ebb50e85924f9a80c46c172540f8565f148d84d8d71f6940f17ea22c
3
+ metadata.gz: cd956d7d34f4285571a9afaf17f4b942f973de302868f8a6b854692467b4dc16
4
+ data.tar.gz: c171947ea6785c3b529f0b05f9251388c4edacbe3b1f8ff401252e5dc2cf5d63
5
5
  SHA512:
6
- metadata.gz: 7c3658a5a78e4bc7854ece88656989a8710b238f4f39199b6c737953c52eec2c284fd3dbdb6e7db149efbca8be35d47c15706e04301ae7b31cae7a25445d713f
7
- data.tar.gz: 2d96bbe7d280d461c2a0b67033619e88a57c4409dedabe56156b67099ba9f87dbd83253f3ba83069d6c6538198167b2ca2f18d6b0fd642b4336eacd75247c946
6
+ metadata.gz: 2ad4711c7b084a033c558d924029bdbd73190fd4fa805d6584d3d73429c89057689e7a9eaa9afa63bbc8466174c6718cf97a13c78ae696a85d52a25c84edb0c6
7
+ data.tar.gz: 151c10f1af8eed7f1144ce5a9a626872b51ca711055b90ff762df4d57135e0b4b0105c684f6951ebef3974197d12b8dbb706f310f068bf413ff096c617b9c338
data/ext/gtk4/extconf.rb CHANGED
@@ -80,6 +80,16 @@ end
80
80
  create_pkg_config_file("Ruby/GTK4", package_id)
81
81
 
82
82
  $defs << "-DRUBY_GTK4_COMPILATION"
83
+ case RUBY_PLATFORM
84
+ when /darwin/
85
+ symbols_in_external_bundles = [
86
+ "_rbgobj_gc_mark_instance",
87
+ "_rbgobj_register_mark_func",
88
+ ]
89
+ symbols_in_external_bundles.each do |symbol|
90
+ $DLDFLAGS << " -Wl,-U,#{symbol}"
91
+ end
92
+ end
83
93
  create_makefile(module_name)
84
94
 
85
95
  pkg_config_dir = with_config("pkg-config-dir")
@@ -0,0 +1,41 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright (C) 2015-2022 Ruby-GNOME Project Team
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ * MA 02110-1301 USA
19
+ */
20
+
21
+ #include "rb-gtk4-private.h"
22
+
23
+ static void
24
+ rb_gtk4_cell_layout_mark(gpointer object)
25
+ {
26
+ GtkCellLayout *cell_layout = object;
27
+
28
+ GList *renderers = gtk_cell_layout_get_cells(cell_layout);
29
+ GList *node;
30
+ for (node = renderers; node; node = g_list_next(node)) {
31
+ GtkCellRenderer *renderer = node->data;
32
+ rbgobj_gc_mark_instance(renderer);
33
+ }
34
+ g_list_free(renderers);
35
+ }
36
+
37
+ void
38
+ rb_gtk4_cell_layout_init(void)
39
+ {
40
+ rbgobj_register_mark_func(GTK_TYPE_CELL_LAYOUT, rb_gtk4_cell_layout_mark);
41
+ }
@@ -29,5 +29,7 @@
29
29
 
30
30
  #include "rb-gtk4.h"
31
31
 
32
+ G_GNUC_INTERNAL void rb_gtk4_cell_layout_init(void);
33
+ G_GNUC_INTERNAL void rb_gtk4_tree_view_init(void);
32
34
  G_GNUC_INTERNAL void rb_gtk4_widget_init(void);
33
35
  G_GNUC_INTERNAL void rb_gtk4_window_init(void);
@@ -0,0 +1,44 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright (C) 2015-2022 Ruby-GNOME Project Team
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ * MA 02110-1301 USA
19
+ */
20
+
21
+ #include "rb-gtk4-private.h"
22
+
23
+ static void
24
+ rb_gtk4_tree_view_mark(gpointer object)
25
+ {
26
+ GtkTreeView *tree_view = object;
27
+
28
+ GList *columns = gtk_tree_view_get_columns(tree_view);
29
+ GList *node;
30
+ for (node = columns; node; node = g_list_next(node)) {
31
+ GtkTreeViewColumn *column = node->data;
32
+ rbgobj_gc_mark_instance(column);
33
+ }
34
+ g_list_free(columns);
35
+
36
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
37
+ rbgobj_gc_mark_instance(selection);
38
+ }
39
+
40
+ void
41
+ rb_gtk4_tree_view_init(void)
42
+ {
43
+ rbgobj_register_mark_func(GTK_TYPE_TREE_VIEW, rb_gtk4_tree_view_mark);
44
+ }
data/ext/gtk4/rb-gtk4.c CHANGED
@@ -23,6 +23,8 @@
23
23
  void
24
24
  Init_gtk4(void)
25
25
  {
26
+ rb_gtk4_cell_layout_init();
27
+ rb_gtk4_tree_view_init();
26
28
  rb_gtk4_widget_init();
27
29
  rb_gtk4_window_init();
28
30
  }
@@ -629,7 +629,7 @@ module Gtk
629
629
  [{file: image}]
630
630
  end
631
631
  when Symbol
632
- [{icon_name: iamge}]
632
+ [{icon_name: image}]
633
633
  when GdkPixbuf::Pixbuf
634
634
  [{:pixbuf => image}]
635
635
  when Gio::Icon
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014 Ruby-GNOME2 Project Team
1
+ # Copyright (C) 2014-2022 Ruby-GNOME Project Team
2
2
  #
3
3
  # This library is free software; you can redistribute it and/or
4
4
  # modify it under the terms of the GNU Lesser General Public
@@ -18,7 +18,9 @@ module Gtk
18
18
  class ScrolledWindow
19
19
  alias_method :initialize_raw, :initialize
20
20
  def initialize(hadjustment=nil, vadjustment=nil)
21
- initialize_raw(hadjustment, vadjustment)
21
+ initialize_raw
22
+ set_hadjustment(hadjustment) if hadjustment
23
+ set_vadjustment(vadjustment) if vadjustment
22
24
  end
23
25
  end
24
26
  end
data/lib/gtk4/widget.rb CHANGED
@@ -106,6 +106,10 @@ module Gtk
106
106
 
107
107
  private
108
108
  def initialize_post
109
+ super
110
+
111
+ GObjectIntrospection::Loader.reference_gobject(self, sink: true)
112
+
109
113
  klass = self.class
110
114
  return unless klass.have_template?
111
115
  return unless respond_to?(:init_template)
@@ -123,7 +123,7 @@ application.signal_connect "activate" do |app|
123
123
  button.menu_model = buttonmenu
124
124
  button.halign = :center
125
125
  button.valign = :start
126
- win.add(button)
126
+ win.set_child(button)
127
127
  win.show
128
128
  end
129
129
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  #
3
- # Copyright (C) 2013-2018 Ruby-GNOME2 Project Team
3
+ # Copyright (C) 2013-2022 Ruby-GNOME Project Team
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -16,26 +16,33 @@
16
16
  # License along with this library; if not, write to the Free Software
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
- # example from https://github.com/GNOME/gtk/blob/master/examples/builder.c
19
+ # example from https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/builder.c
20
20
 
21
21
  require_relative "utils"
22
22
 
23
23
  require_gtk4
24
24
 
25
- # Construct a GtkBuilder instance and load our UI description
26
- builder = Gtk::Builder.new(:file => "#{path}/builder.ui")
25
+ app = Gtk::Application.new("org.gtk.example", :flags_none)
27
26
 
28
- # Connect signal handlers to the constructed widgets.
29
- window = builder["window"]
30
- window.signal_connect("destroy") { Gtk.main_quit }
27
+ app.signal_connect "activate" do
28
+ # Construct a GtkBuilder instance and load our UI description
29
+ builder = Gtk::Builder.new(file: File.join(__dir__, "builder.ui"))
31
30
 
32
- button = builder["button1"]
33
- button.signal_connect("clicked") { puts "Hello World!" }
31
+ # Connect signal handlers to the constructed widgets.
32
+ window = builder["window"]
33
+ window.set_application(app)
34
34
 
35
- button = builder["button2"]
36
- button.signal_connect("clicked") { puts "Hello World!" }
35
+ button = builder["button1"]
36
+ button.signal_connect("clicked") { puts "Hello World!" }
37
37
 
38
- button = builder["quit"]
39
- button.signal_connect("clicked") { Gtk.main_quit }
38
+ button = builder["button2"]
39
+ button.signal_connect("clicked") { puts "Hello World!" }
40
+
41
+ button = builder["quit"]
42
+ button.signal_connect("clicked") { window.close }
43
+
44
+ window.show
45
+ end
46
+
47
+ app.run
40
48
 
41
- Gtk.main
@@ -1,44 +1,39 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
1
2
  <interface>
2
3
  <object id="window" class="GtkWindow">
3
- <property name="visible">True</property>
4
4
  <property name="title">Grid</property>
5
5
  <child>
6
6
  <object id="grid" class="GtkGrid">
7
- <property name="visible">True</property>
8
7
  <child>
9
8
  <object id="button1" class="GtkButton">
10
- <property name="visible">True</property>
11
9
  <property name="label">Button 1</property>
10
+ <layout>
11
+ <property name="column">0</property>
12
+ <property name="row">0</property>
13
+ </layout>
12
14
  </object>
13
- <packing>
14
- <property name="left-attach">0</property>
15
- <property name="top-attach">0</property>
16
- </packing>
17
15
  </child>
18
16
  <child>
19
17
  <object id="button2" class="GtkButton">
20
- <property name="visible">True</property>
21
18
  <property name="label">Button 2</property>
19
+ <layout>
20
+ <property name="column">1</property>
21
+ <property name="row">0</property>
22
+ </layout>
22
23
  </object>
23
- <packing>
24
- <property name="left-attach">1</property>
25
- <property name="top-attach">0</property>
26
- </packing>
27
24
  </child>
28
25
  <child>
29
26
  <object id="quit" class="GtkButton">
30
- <property name="visible">True</property>
31
27
  <property name="label">Quit</property>
28
+ <layout>
29
+ <property name="column">0</property>
30
+ <property name="row">1</property>
31
+ <property name="column-span">2</property>
32
+ </layout>
32
33
  </object>
33
- <packing>
34
- <property name="left-attach">0</property>
35
- <property name="top-attach">1</property>
36
- <property name="width">2</property>
37
- </packing>
38
34
  </child>
39
35
  </object>
40
- <packing>
41
- </packing>
42
36
  </child>
43
37
  </object>
44
38
  </interface>
39
+
@@ -34,17 +34,13 @@ def draw_brush(widget, surface, x, y)
34
34
  cr = Cairo::Context.new(surface)
35
35
  cr.rectangle(x - 3, y - 3, 6, 6)
36
36
  cr.fill
37
- widget.queue_draw_area(x - 3, y - 3, 6, 6)
37
+ widget.queue_draw
38
38
  end
39
39
 
40
40
  def generate_surface_from_widget(widget)
41
- surface = nil
42
- if widget.window
43
- surface = widget.window.create_similar_surface(Cairo::CONTENT_COLOR,
44
- widget.allocated_width,
45
- widget.allocated_height)
46
- end
47
- surface
41
+ widget.native.surface.create_similar_surface(Cairo::CONTENT_COLOR,
42
+ widget.allocated_width,
43
+ widget.allocated_height)
48
44
  end
49
45
 
50
46
  myapp = Gtk::Application.new("org.gtk.example", :flags_none)
@@ -60,14 +56,10 @@ myapp.signal_connect "activate" do |app|
60
56
  win.destroy
61
57
  end
62
58
 
63
- frame = Gtk::Frame.new
64
- frame.shadow_type = Gtk::ShadowType::IN
65
- win.add(frame)
66
-
67
59
  drawing_area = Gtk::DrawingArea.new
68
60
  # Set a minimum size
69
61
  drawing_area.set_size_request(100, 100)
70
- frame.add(drawing_area)
62
+ win.set_child(drawing_area)
71
63
 
72
64
  drawing_area.set_draw_func do |da, cr|
73
65
  if surface.nil?
@@ -82,15 +74,16 @@ myapp.signal_connect "activate" do |app|
82
74
  cr.paint
83
75
  end
84
76
 
85
- drawing_area.signal_connect_after "size-allocate" do |da, alloc|
77
+ drawing_area.signal_connect_after "resize" do |da, alloc|
86
78
  surface.destroy if surface
87
79
  surface = generate_surface_from_widget(da)
88
80
  # Initialize the surface to white
89
81
  clear_surface(surface) if surface
90
82
  end
91
83
 
92
- drag = Gtk::GestureDrag.new(drawing_area)
84
+ drag = Gtk::GestureDrag.new
93
85
  drag.button = Gdk::BUTTON_PRIMARY
86
+ drawing_area.add_controller(drag)
94
87
 
95
88
  start_x = 0.0
96
89
  start_y = 0.0
@@ -109,8 +102,9 @@ myapp.signal_connect "activate" do |app|
109
102
  draw_brush(drawing_area, surface, start_x + x, start_y + y)
110
103
  end
111
104
 
112
- press = Gtk::GestureMultiPress.new(drawing_area)
105
+ press = Gtk::GestureClick.new
113
106
  press.button = Gdk::BUTTON_SECONDARY
107
+ drawing_area.add_controller(press)
114
108
  press.signal_connect "pressed" do |gesture, n_press, x, y|
115
109
  clear_surface(surface)
116
110
  drawing_area.queue_draw
@@ -33,7 +33,7 @@ application.signal_connect "activate" do |app|
33
33
  grid = Gtk::Grid.new
34
34
 
35
35
  # Pack the container in the window
36
- win.add(grid)
36
+ win.set_child(grid)
37
37
 
38
38
  button = Gtk::Button.new(:label => "Button 1")
39
39
  button.signal_connect("clicked") { puts "Hello World!" }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  #
3
- # Copyright (C) 2013-2018 Ruby-GNOME2 Project Team
3
+ # Copyright (C) 2013-2022 Ruby-GNOME Project Team
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -16,7 +16,7 @@
16
16
  # License along with this library; if not, write to the Free Software
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
- # example from https://github.com/GNOME/gtk/blob/master/examples/hello-world.c
19
+ # example from https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/hello/hello-world.c
20
20
 
21
21
  require_relative "utils"
22
22
 
@@ -25,22 +25,22 @@ require_gtk4
25
25
  application = Gtk::Application.new("org.gtk.example", :flags_none)
26
26
 
27
27
  application.signal_connect "activate" do |app|
28
- win = Gtk::ApplicationWindow.new(app)
29
- win.title = "window"
30
- win.set_default_size(200, 200)
28
+ window = Gtk::ApplicationWindow.new(app)
29
+ window.title = "Window"
30
+ window.set_default_size(200, 200)
31
31
 
32
- button_box = Gtk::ButtonBox.new(:horizontal)
33
- win.add(button_box)
32
+ button = Gtk::Button.new(label: "Hello World")
33
+ button.halign = :center
34
+ button.valign = :center
34
35
 
35
- button = Gtk::Button.new(:label => "Hello World")
36
36
  button.signal_connect "clicked" do
37
37
  puts "Hello World"
38
- win.destroy
38
+ window.destroy
39
39
  end
40
40
 
41
- button_box.add(button)
41
+ window.child = button
42
42
 
43
- win.show
43
+ window.show
44
44
  end
45
45
 
46
46
  application.run
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (C) 2022 Ruby-GNOME Project Team
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ # example from https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/window-default.c
20
+ #
21
+ # License: LGPL2.1+
22
+
23
+ require_relative "utils"
24
+
25
+ require_gtk4
26
+
27
+ application = Gtk::Application.new("org.gtk.example", :flags_none)
28
+
29
+ application.signal_connect "activate" do |app|
30
+ window = Gtk::ApplicationWindow.new(app)
31
+ window.title = "Window"
32
+ window.set_default_size(200, 200)
33
+ window.show
34
+ end
35
+
36
+ application.run
@@ -1,4 +1,357 @@
1
1
  # Ruby/GTK4 getting started
2
2
 
3
- There are scripts ported from
4
- https://docs.gtk.org/gtk4/getting_started.html .
3
+ This is a ruby adaptation of the [official tutorial](https://docs.gtk.org/gtk4/getting_started.html) for the C language.
4
+
5
+ The Gtk4 module of the ruby-gnome project is an implementation of the ruby bindings for GTK.
6
+
7
+ GTK is a [widget toolkit](http://en.wikipedia.org/wiki/Widget_toolkit). Each user interface created by GTK consists of widgets. Widgets are organized in a hierarchy. The window widget is the main container. The user interface is then built by adding buttons, drop-down menus, input fields, and other widgets to the window. If you are creating complex user interfaces it is recommended to use `Gtk::Builder` and its GTK-specific markup description language, instead of assembling the interface manually.
8
+
9
+ GTK is event-driven. The toolkit listens for events such as a click on a button, and passes the event to your application.
10
+
11
+ This chapter contains some tutorial information to get you started with GTK programming. It assumes that you have GTK, its dependencies and ruby with the gtk4 gem installed.
12
+
13
+ ## Basics
14
+ To begin our introduction to GTK, we’ll start with a very simple application. This program will create an empty 200 × 200 pixel window.
15
+
16
+ ![example-0](images/example-0.png)
17
+
18
+ ```ruby
19
+ # example-0.rb
20
+ require "gtk4"
21
+
22
+ application = Gtk::Application.new("org.gtk.example", :flags_none)
23
+
24
+ application.signal_connect "activate" do |app|
25
+ window = Gtk::ApplicationWindow.new(app)
26
+ window.title = "Window"
27
+ window.set_default_size(200, 200)
28
+ window.show
29
+ end
30
+
31
+ application.run
32
+ ```
33
+
34
+ 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).
35
+
36
+ Lastly `Gtk::Application#new` takes a `Gio::ApplicationFlags` constant as input for your application, if your application would have special needs (those constants can be replaced by theirs respective symbol ie. `Gio::ApplicationFlags::FLAGS_NONE` == `:flags_none`). You must know that `Gio:::Application` ignores arguments passed to `Gio::Application#run` on the Windows systems. It always uses command line arguments even when we pass an empty array to `Gio::Application#run`.
37
+
38
+ 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-gnome/ruby-gnome/issues/721 ).
39
+
40
+ 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. Your application can override the command line handling, e.g. to open files passed on the commandline.
41
+
42
+ A window title is set using `Gtk::ApplicationWindow#title=`. This setter function takes a string as input.
43
+
44
+ Finally the window size is set using `Gtk::ApplicationWindow#set_default_size` and the window is then shown by GTK via `Gtk::Widget#show`.
45
+
46
+ While the program is running, GTK is receiving *events*. These are typically input events caused by the user interacting with your program, but also things like messages from the window manager or other applications. GTK processes these and as a result, signals may be emitted on your widgets. Connecting handlers for these signals is how you normally make your program do something in response to user input.
47
+
48
+ The following example is slightly more complex, and tries to showcase some of the capabilities of GTK.
49
+
50
+ ## Hello, World
51
+
52
+ In the long tradition of programming languages and libraries, this example is called *Hello, World*.
53
+
54
+ ![example-1](images/example-1.png)
55
+
56
+ ```ruby
57
+ # example-1.rb
58
+ application = Gtk::Application.new("org.gtk.example", :flags_none)
59
+
60
+ application.signal_connect "activate" do |app|
61
+ window = Gtk::ApplicationWindow.new(app)
62
+ window.title = "Window"
63
+ window.set_default_size(200, 200)
64
+
65
+ button_box = Gtk::Box.new(:horizontal)
66
+ button_box.halign = :center
67
+ button_box.valign = :center
68
+ window.set_child(button_box)
69
+
70
+ button = Gtk::Button.new(label: "Hello World")
71
+
72
+ button.signal_connect "clicked" do
73
+ puts "Hello World"
74
+ window.destroy
75
+ end
76
+ button_box.append(button)
77
+
78
+ window.show
79
+ end
80
+
81
+ application.run
82
+ ```
83
+
84
+ As seen above, example-1.rb builds further upon example-0.rb by adding a button to our window, with the label “Hello World”.
85
+
86
+ The button_box variable stores a `Gtk::Box` object, which is GTK's way of controlling the size and layout of widgets. The `Gtk::Box` is created with the method `Gtk::Box#new` which takes a `Gtk::Orientation `constant as parameter or the related symbols (`:vertical` or `:horizontal`).
87
+
88
+ The buttons which this box will contain can either be stored horizontally or vertically but this does not matter in this particular case as we are dealing with only one button. After initializing button_box with horizontal orientation, the code adds the button_box widget to the window widget using `Gtk::Box#append`.
89
+
90
+ Next the button variable is initialized in similar manner. The method `Gtk::Button#new` is called which returns a `Gtk::Button` to be stored in button. A label is set using a ruby hash as argument: `label: "Hello World"`. Afterwards button is added to our button_box.
91
+
92
+ Using the method `Gtk::Button#signal_connect` we add instructions, so that when the button is clicked, a message will be displayed in the terminal if the GTK application was started from one.
93
+
94
+ After that, `Gtk::ApplicationWindow#destroy` is called. This method is inherited from `Gtk::Widget`. This has the effect that when the button is clicked, the whole GTK window is destroyed. More information about creating buttons can be found [here](https://wiki.gnome.org/HowDoI/Buttons).
95
+
96
+ The rest of the code in example-1.rb is identical to example-0.rb. Next section will elaborate further on how to add several GtkWidgets to your GTK application.
97
+
98
+ ## Packing
99
+
100
+ When creating an application, you’ll want to put more than one widget inside a window. When you do so, it becomes important to control how each widget is positioned and sized. This is where packing comes in.
101
+
102
+ GTK comes with a large variety of layout containers whose purpose it is to control the layout of the child widgets that are added to them, like:
103
+
104
+ * [Gtk::Box](https://docs.gtk.org/gtk4/class.Box.html)
105
+ * [Gtk::Grid](https://docs.gtk.org/gtk4/class.Grid.html)
106
+ * [Gtk::Revealer](https://docs.gtk.org/gtk4/class.Revealer.html)
107
+ * [Gtk::Stack](https://docs.gtk.org/gtk4/class.Stack.html)
108
+ * [Gtk::Overlay](https://docs.gtk.org/gtk4/class.Overlay.html)
109
+ * [Gtk::Paned](https://docs.gtk.org/gtk4/class.Paned.html)
110
+ * [Gtk::Expander](https://docs.gtk.org/gtk4/class.Expander.html)
111
+ * [Gtk::Fixed](https://docs.gtk.org/gtk4/class.Fixed.html)
112
+
113
+ The following example shows how the `Gtk::Grid` container lets you arrange several buttons:
114
+
115
+ ![example-2](images/example-2.png)
116
+
117
+ ```ruby
118
+ # example-2.rb
119
+ require "gtk4"
120
+
121
+ application = Gtk::Application.new("org.gtk.example", :flags_none)
122
+
123
+ application.signal_connect "activate" do |app|
124
+ # Create a new window and set its title
125
+ win = Gtk::ApplicationWindow.new(app)
126
+ win.title = "Window"
127
+
128
+ # Here we construct the container that is going to pack our buttons.
129
+ grid = Gtk::Grid.new
130
+
131
+ # Pack the container in the window
132
+ win.set_child(grid)
133
+
134
+ button = Gtk::Button.new(label: "Button 1")
135
+ button.signal_connect("clicked") { puts "Hello World!" }
136
+
137
+ # Place the first button in the grid cell (0, 0), and make it fill
138
+ # just 1 cell horizontally and vertically (ie no spanning)
139
+ grid.attach(button, 0, 0, 1, 1)
140
+
141
+ button = Gtk::Button.new(label: "Button 2")
142
+ button.signal_connect("clicked") { puts "Hello World!" }
143
+
144
+ # Place the second button in the grid cell (1, 0), and make it fill
145
+ # just 1 cell horizontally and vertically (ie no spanning)
146
+ grid.attach(button, 1, 0, 1, 1)
147
+
148
+ button = Gtk::Button.new(label: "Quit")
149
+ button.signal_connect("clicked") { win.destroy }
150
+
151
+ # Place the Quit button in the grid cell (0, 1), and make it
152
+ # span 2 columns.
153
+ grid.attach(button, 0, 1, 2, 1)
154
+
155
+ win.show
156
+ end
157
+
158
+ application.run
159
+ ```
160
+
161
+ ## Custom Drawing
162
+
163
+ Many widgets, like buttons, do all their drawing themselves. You just tell them the label you want to see, and they figure out what font to use, draw the button outline and focus rectangle, etc. Sometimes, it is necessary to do some custom drawing. In that case, a `Gtk::DrawingArea` might be the right widget to use. It offers a canvas on which you can draw by setting its draw function.
164
+
165
+ The contents of a widget often need to be partially or fully redrawn, e.g. when another window is moved and uncovers part of the widget, or when the window containing it is resized. It is also possible to explicitly cause a widget to be redrawn, by calling `Gtk::Widget#queue_draw`. GTK takes care of most of the details by providing a ready-to-use cairo context to the draw function.
166
+
167
+ The following example shows how to use a draw function with `Gtk::DrawingArea`. It is a bit more complicated than the previous examples, since it also demonstrates input event handling with event controllers.
168
+
169
+ ![example-3](images/example-3.png)
170
+
171
+ ### Drawing in response to input
172
+
173
+ ```ruby
174
+ # example-3.rb
175
+ require "gtk4"
176
+
177
+ def clear_surface(surface)
178
+ cr = Cairo::Context.new(surface)
179
+ cr.set_source_rgb(1, 1, 1)
180
+ cr.paint
181
+ cr.destroy
182
+ end
183
+
184
+ # Draw a rectangle on the surface at the given position
185
+ def draw_brush(widget, surface, x, y)
186
+ cr = Cairo::Context.new(surface)
187
+ cr.rectangle(x - 3, y - 3, 6, 6)
188
+ cr.fill
189
+ widget.queue_draw
190
+ end
191
+
192
+ def generate_surface_from_widget(widget)
193
+ widget.native.surface.create_similar_surface(Cairo::CONTENT_COLOR,
194
+ widget.allocated_width,
195
+ widget.allocated_height)
196
+ end
197
+
198
+ myapp = Gtk::Application.new("org.gtk.example", :flags_none)
199
+
200
+ myapp.signal_connect "activate" do |app|
201
+ win = Gtk::ApplicationWindow.new(app)
202
+ win.set_title("Drawing Area")
203
+
204
+ surface = nil
205
+
206
+ win.signal_connect "destroy" do
207
+ surface.destroy if surface
208
+ win.destroy
209
+ end
210
+
211
+ drawing_area = Gtk::DrawingArea.new
212
+ # Set a minimum size
213
+ drawing_area.set_size_request(100, 100)
214
+ win.set_child(drawing_area)
215
+
216
+ drawing_area.set_draw_func do |da, cr|
217
+ if surface.nil?
218
+ surface = generate_surface_from_widget(da)
219
+ ## Initialize the surface to white
220
+ clear_surface(surface)
221
+ end
222
+ # Redraw the screen from the surface. Note that the draw
223
+ # callback receives a ready-to-be-used cairo_t that is already
224
+ # clipped to only draw the exposed areas of the widget
225
+ cr.set_source(surface, 0, 0)
226
+ cr.paint
227
+ end
228
+
229
+ drawing_area.signal_connect_after "resize" do |da, alloc|
230
+ surface.destroy if surface
231
+ surface = generate_surface_from_widget(da)
232
+ # Initialize the surface to white
233
+ clear_surface(surface) if surface
234
+ end
235
+
236
+ drag = Gtk::GestureDrag.new
237
+ drag.button = Gdk::BUTTON_PRIMARY
238
+ drawing_area.add_controller(drag)
239
+
240
+ start_x = 0.0
241
+ start_y = 0.0
242
+
243
+ drag.signal_connect "drag-begin" do |gesture, x, y|
244
+ start_x = x
245
+ start_y = y
246
+ draw_brush(drawing_area, surface, x, y)
247
+ end
248
+
249
+ drag.signal_connect "drag-update" do |gesture, x, y|
250
+ draw_brush(drawing_area, surface, start_x + x, start_y + y)
251
+ end
252
+
253
+ drag.signal_connect "drag-end" do |gesture, x, y|
254
+ draw_brush(drawing_area, surface, start_x + x, start_y + y)
255
+ end
256
+
257
+ press = Gtk::GestureClick.new
258
+ press.button = Gdk::BUTTON_SECONDARY
259
+ drawing_area.add_controller(press)
260
+ press.signal_connect "pressed" do |gesture, n_press, x, y|
261
+ clear_surface(surface)
262
+ drawing_area.queue_draw
263
+ end
264
+ win.show
265
+ end
266
+
267
+ myapp.run
268
+ ```
269
+
270
+ ## Building user interfaces
271
+ When constructing a more complicated user interface, with dozens or hundreds of widgets, doing all the setup work in code is cumbersome, and making changes becomes next to impossible.
272
+
273
+ Thankfully, GTK supports the separation of user interface layout from your business logic, by using UI descriptions in an XML format that can be parsed by the `Gtk::Builder` class.
274
+
275
+ ### Packing buttons with GtkBuilder
276
+
277
+ Create a new file with the following content:
278
+
279
+ ```ruby
280
+ # example-4.rb
281
+ require "gtk4"
282
+
283
+ app = Gtk::Application.new("org.gtk.example", :flags_none)
284
+
285
+ app.signal_connect "activate" do
286
+ # Construct a GtkBuilder instance and load our UI description
287
+ builder = Gtk::Builder.new(file: File.join(__dir__, "builder.ui"))
288
+
289
+ # Connect signal handlers to the constructed widgets.
290
+ window = builder["window"]
291
+ window.set_application(app)
292
+
293
+ button = builder["button1"]
294
+ button.signal_connect("clicked") { puts "Hello World!" }
295
+
296
+ button = builder["button2"]
297
+ button.signal_connect("clicked") { puts "Hello World!" }
298
+
299
+ button = builder["quit"]
300
+ button.signal_connect("clicked") { window.close }
301
+
302
+ window.show
303
+ end
304
+
305
+ app.run
306
+ ```
307
+
308
+ Then, create a new file with the following content named `builder.ui`.
309
+
310
+ ```xml
311
+ <?xml version="1.0" encoding="UTF-8"?>
312
+ <interface>
313
+ <object id="window" class="GtkWindow">
314
+ <property name="title">Grid</property>
315
+ <child>
316
+ <object id="grid" class="GtkGrid">
317
+ <child>
318
+ <object id="button1" class="GtkButton">
319
+ <property name="label">Button 1</property>
320
+ <layout>
321
+ <property name="column">0</property>
322
+ <property name="row">0</property>
323
+ </layout>
324
+ </object>
325
+ </child>
326
+ <child>
327
+ <object id="button2" class="GtkButton">
328
+ <property name="label">Button 2</property>
329
+ <layout>
330
+ <property name="column">1</property>
331
+ <property name="row">0</property>
332
+ </layout>
333
+ </object>
334
+ </child>
335
+ <child>
336
+ <object id="quit" class="GtkButton">
337
+ <property name="label">Quit</property>
338
+ <layout>
339
+ <property name="column">0</property>
340
+ <property name="row">1</property>
341
+ <property name="column-span">2</property>
342
+ </layout>
343
+ </object>
344
+ </child>
345
+ </object>
346
+ </child>
347
+ </object>
348
+ </interface>
349
+ ```
350
+
351
+ The usage of the `Gtk::Builder` is easy, we just create an instance from the
352
+ file "builder.ui" with `Gtk::Builder.new(file: path/to/builder.ui)`. Then you can access every widget or part of the interface thanks to its name: `window = builder["window"]`. Note that `Gtk::Builder` can also be used to construct objects that are not widgets, such as tree models, adjustments, etc.
353
+
354
+ It is also possible to embed the UI description in the source code as a string and use `GtkBuilder::add_from_string` to load it. But keeping the UI description in a separate file has several advantages:
355
+
356
+ * it is easier to isolate the UI code from the business logic of your application
357
+ * it is easier to restructure your UI into separate classes using composite widget templates
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gtk4
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.3
4
+ version: 4.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Ruby-GNOME Project Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-13 00:00:00.000000000 Z
11
+ date: 2022-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: atk
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.3
19
+ version: 4.0.5
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 4.0.3
26
+ version: 4.0.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: gdk4
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 4.0.3
33
+ version: 4.0.5
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 4.0.3
40
+ version: 4.0.5
41
41
  description: Ruby/GTK4 is a Ruby binding of GTK+-4.x.
42
42
  email: ruby-gnome2-devel-en@lists.sourceforge.net
43
43
  executables: []
@@ -49,7 +49,9 @@ files:
49
49
  - README.md
50
50
  - Rakefile
51
51
  - ext/gtk4/extconf.rb
52
+ - ext/gtk4/rb-gtk4-cell-layout.c
52
53
  - ext/gtk4/rb-gtk4-private.h
54
+ - ext/gtk4/rb-gtk4-tree-view.c
53
55
  - ext/gtk4/rb-gtk4-widget.c
54
56
  - ext/gtk4/rb-gtk4-window.c
55
57
  - ext/gtk4/rb-gtk4.c
@@ -121,7 +123,12 @@ files:
121
123
  - sample/examples/grid_packing.rb
122
124
  - sample/examples/hello_world.rb
123
125
  - sample/examples/utils.rb
126
+ - sample/examples/window_default.rb
124
127
  - sample/getting-started/README.md
128
+ - sample/getting-started/images/example-0.png
129
+ - sample/getting-started/images/example-1.png
130
+ - sample/getting-started/images/example-2.png
131
+ - sample/getting-started/images/example-3.png
125
132
  homepage: https://ruby-gnome2.osdn.jp/
126
133
  licenses:
127
134
  - LGPL-2.1+