clutter-gtk 1.2.0

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.
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ # -*- ruby -*-
2
+ #
3
+ # Copyright (C) 2013 Ruby-GNOME2 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
+ $LOAD_PATH.unshift("./../glib2/lib")
20
+ require "gnome2-raketask"
21
+
22
+ package = GNOME2Package.new do |_package|
23
+ _package.summary = "Ruby/ClutterGTK is a Ruby binding of Clutter-GTK."
24
+ _package.description = "Ruby/ClutterGTK is a Ruby binding of Clutter-GTK."
25
+ _package.dependency.gem.runtime = ["clutter", "gtk3"]
26
+ _package.dependency.gem.development = ["test-unit-notify"]
27
+ _package.win32.packages = []
28
+ _package.win32.dependencies = []
29
+ _package.win32.build_dependencies = ["glib2", "gobject-introspection"]
30
+ _package.win32.build_packages = []
31
+ end
32
+ package.define_tasks
33
+
34
+ namespace :dependency do
35
+ desc "Install depenencies"
36
+ task :install do
37
+ # TODO: Install gir1.2-gtkclutter-1.0 on Debian.
38
+ end
39
+ end
40
+
41
+ task :build => "dependency:install"
@@ -0,0 +1,63 @@
1
+ # Copyright (C) 2013 Ruby-GNOME2 Project Team
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ require "clutter"
18
+ require "gtk3"
19
+
20
+ base_dir = Pathname.new(__FILE__).dirname.dirname.dirname.expand_path
21
+ vendor_dir = base_dir + "vendor" + "local"
22
+ vendor_bin_dir = vendor_dir + "bin"
23
+ GLib.prepend_environment_path(vendor_bin_dir)
24
+
25
+ module ClutterGtk
26
+ LOG_DOMAIN = "Clutter-Gtk"
27
+ GLib::Log.set_log_domain(LOG_DOMAIN)
28
+
29
+ class << self
30
+ @initialized = false
31
+ def init(argv=ARGV)
32
+ return if @initialized
33
+ @initialized = true
34
+ loader = Loader.new(self, argv)
35
+ loader.load("GtkClutter")
36
+ Clutter.init(argv)
37
+ end
38
+ end
39
+
40
+ class Loader < GObjectIntrospection::Loader
41
+ class InitError < StandardError
42
+ end
43
+
44
+ def initialize(base_module, init_arguments)
45
+ super(base_module)
46
+ @init_arguments = init_arguments
47
+ end
48
+
49
+ private
50
+ def pre_load(repository, namespace)
51
+ init = repository.find(namespace, "init")
52
+ error, argc, argv = init.invoke(1 + @init_arguments.size,
53
+ [$0] + @init_arguments)
54
+ @init_arguments.replace(argv)
55
+ if error.to_i <= 0
56
+ raise InitError, "failed to initialize Clutter: #{error.name}"
57
+ end
58
+ end
59
+
60
+ def post_load(repository, namespace)
61
+ end
62
+ end
63
+ end
data/sample/events.rb ADDED
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This sample code is a port of
4
+ # clutter-gtk/examples/gtk-clutter-events.c. The image file used in
5
+ # this sample code is copied from
6
+ # clutter-gtk/examples/redhand.png. They are licensed under the terms
7
+ # of the GNU Lesser General Public License, version 2.1 or (at your
8
+ # option) later.
9
+ #
10
+ # Copyright (C) 2013 Ruby-GNOME2 Project Team
11
+ #
12
+ # This library is free software; you can redistribute it and/or
13
+ # modify it under the terms of the GNU Lesser General Public
14
+ # License as published by the Free Software Foundation; either
15
+ # version 2.1 of the License, or (at your option) any later version.
16
+ #
17
+ # This library is distributed in the hope that it will be useful,
18
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
+ # Lesser General Public License for more details.
21
+ #
22
+ # You should have received a copy of the GNU Lesser General Public
23
+ # License along with this library; if not, write to the Free Software
24
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25
+
26
+ require "clutter-gtk"
27
+ require "gdk_pixbuf2"
28
+
29
+ ClutterGtk.init
30
+
31
+ window = Gtk::Window.new
32
+ window.title = "Gtk-Clutter Interaction demo"
33
+ window.set_default_size(800, 600)
34
+ window.resizable = false
35
+ window.border_width = 12
36
+ window.signal_connect("destroy") do
37
+ Gtk.main_quit
38
+ end
39
+
40
+ vbox = Gtk::Box.new(:vertical, 12)
41
+ window.add(vbox)
42
+
43
+ clutter_entry = nil
44
+ gtk_entry = Gtk::Entry.new
45
+ gtk_entry.text = "Enter some text"
46
+ vbox.pack_start(gtk_entry, :expand => false, :fill => false, :padding => 0)
47
+ gtk_entry.signal_connect("changed") do |editable|
48
+ clutter_entry.text = editable.text
49
+ end
50
+
51
+ hbox = Gtk::Box.new(:horizontal, 12)
52
+ vbox.pack_start(hbox, :expand => true, :fill => true, :padding => 0)
53
+
54
+ # Set up clutter & create our stage
55
+ clutter_embed = ClutterGtk::Embed.new
56
+ hbox.pack_start(clutter_embed, :expand => true, :fill => true, :padding => 0)
57
+ clutter_embed.grab_focus
58
+ stage = clutter_embed.stage
59
+ clutter_embed.set_size_request(640, 480)
60
+ stage.signal_connect("captured-event") do |_stage, event|
61
+ case event
62
+ when Clutter::ButtonEvent
63
+ puts("#{event.type.nick} captured at (#{event.x}, #{event.y})");
64
+ when Clutter::CrossingEvent
65
+ if event.source == _stage and not event.related.nil?
66
+ if event.type == Clutter::EventType::ENTER
67
+ stage_action = "Entering"
68
+ actor_action = "leaving"
69
+ else
70
+ stage_action = "Leaving"
71
+ actor_action = "entering"
72
+ end
73
+ puts("#{stage_action} the stage and #{actor_action} '#{event.related.name}'")
74
+ end
75
+ when Clutter::KeyEvent
76
+ if event.type == Clutter::EventType::KEY_PRESS
77
+ format = "the stage got a key press: '%s' (symbol: %d, unicode: 0x%x)"
78
+ unicode = [event.key_unicode].pack("U")
79
+ puts(format % [unicode, event.key_symbol, event.key_unicode])
80
+ end
81
+ end
82
+
83
+ not Clutter::Event::STOP
84
+ end
85
+
86
+ clutter_embed.signal_connect("enter-notify-event") do |widget|
87
+ puts("Entering widget '#{widget.class.name}'")
88
+ false
89
+ end
90
+ clutter_embed.signal_connect("leave-notify-event") do |widget|
91
+ puts("Leaving widget '#{widget.class.name}'")
92
+ end
93
+
94
+ # Create the main texture that the spin buttons manipulate
95
+ pixbuf = Gdk::Pixbuf.new(File.expand_path("redhand.png", File.dirname(__FILE__)));
96
+ hand = ClutterGtk::Texture.new
97
+ hand.from_pixbuf = pixbuf
98
+ stage.add_child(hand)
99
+ hand.anchor_point_from_gravity = :center
100
+ hand.set_position(stage.width / 2, stage.height / 2)
101
+ hand.reactive = true
102
+ hand.name = "Red Hand"
103
+ hand.signal_connect("button-press-event") do |actor, event|
104
+ puts("Button press on hand ('#{actor.class.name}')")
105
+ not Clutter::Event::STOP
106
+ end
107
+
108
+ # Setup the clutter entry
109
+ clutter_entry = Clutter::Text.new
110
+ clutter_entry.color = Clutter::Color.new(:black)
111
+ stage.add_child(clutter_entry)
112
+ clutter_entry.set_position(0, 0)
113
+ clutter_entry.set_size(500, 20)
114
+
115
+ # Create our adjustment widgets
116
+ vbox = Gtk::Box.new(:vertical, 6)
117
+ hbox.pack_start(vbox, :expand => false, :fill => false, :padding => 0)
118
+
119
+ box = Gtk::Box.new(:horizontal, 6)
120
+ vbox.pack_start(box, :expand => false, :fill => true, :padding => 0)
121
+ label = Gtk::Label.new("Rotate x-axis")
122
+ box.pack_start(label, :expand => true, :fill => true, :padding => 0)
123
+ button = Gtk::SpinButton.new(0, 360, 1)
124
+ box.pack_start(button, :expand => true, :fill => true, :padding => 0)
125
+ button.signal_connect("value-changed") do |_button|
126
+ hand.set_rotation(:x_axis,
127
+ _button.value,
128
+ 0,
129
+ hand.height / 2,
130
+ 0)
131
+ end
132
+
133
+ box = Gtk::Box.new(:horizontal, 6)
134
+ vbox.pack_start(box, :expand => false, :fill => true, :padding => 0)
135
+ label = Gtk::Label.new("Rotate y-axis")
136
+ box.pack_start(label, :expand => true, :fill => true, :padding => 0)
137
+ button = Gtk::SpinButton.new(0, 360, 1)
138
+ box.pack_start(button, :expand => true, :fill => true, :padding => 0)
139
+ button.signal_connect("value-changed") do |_button|
140
+ hand.set_rotation(:y_axis,
141
+ _button.value,
142
+ hand.width / 2,
143
+ 0,
144
+ 0)
145
+ end
146
+
147
+ box = Gtk::Box.new(:horizontal, 6)
148
+ vbox.pack_start(box, :expand => false, :fill => true, :padding => 0)
149
+ label = Gtk::Label.new("Rotate z-axis")
150
+ box.pack_start(label, :expand => true, :fill => true, :padding => 0)
151
+ button = Gtk::SpinButton.new(0, 360, 1)
152
+ box.pack_start(button, :expand => true, :fill => true, :padding => 0)
153
+ button.signal_connect("value-changed") do |_button|
154
+ hand.set_rotation(:z_axis,
155
+ _button.value,
156
+ hand.width / 2,
157
+ hand.height / 2,
158
+ 0)
159
+ end
160
+
161
+ box = Gtk::Box.new(:horizontal, 6)
162
+ vbox.pack_start(box, :expand => false, :fill => true, :padding => 0)
163
+ label = Gtk::Label.new("Adjust opacity")
164
+ box.pack_start(label, :expand => true, :fill => true, :padding => 0)
165
+ button = Gtk::SpinButton.new(0, 255, 1)
166
+ button.value = 255
167
+ box.pack_start(button, :expand => true, :fill => true, :padding => 0)
168
+ button.signal_connect("value-changed") do |_button|
169
+ hand.opacity = _button.value
170
+ end
171
+
172
+ window.show_all
173
+
174
+ # Only show/show_all the stage after parent show. widget_show will call
175
+ # show on the stage.
176
+ stage.show
177
+
178
+ Gtk.main
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This sample code is a port of clutter-gtk/examples/gtk-clutter-multistage.c.
4
+ # It is licensed under the terms of the GNU Lesser General Public
5
+ # License, version 2.1 or (at your option) later.
6
+ #
7
+ # Copyright (C) 2013 Ruby-GNOME2 Project Team
8
+ #
9
+ # This library is free software; you can redistribute it and/or
10
+ # modify it under the terms of the GNU Lesser General Public
11
+ # License as published by the Free Software Foundation; either
12
+ # version 2.1 of the License, or (at your option) any later version.
13
+ #
14
+ # This library is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ # Lesser General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public
20
+ # License along with this library; if not, write to the Free Software
21
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
+
23
+ require "clutter-gtk"
24
+ require "gdk_pixbuf2"
25
+
26
+ ClutterGtk.init
27
+
28
+ window = Gtk::Window.new
29
+ window.set_default_size(600, 400)
30
+ window.title = "Multiple GtkClutterEmbed"
31
+ window.signal_connect("destroy") do
32
+ Gtk.main_quit
33
+ end
34
+
35
+ notebook = Gtk::Notebook.new
36
+ window.add(notebook)
37
+
38
+ clutter0 = ClutterGtk::Embed.new
39
+ notebook.append_page(clutter0, Gtk::Label.new("One stage"))
40
+ stage0 = clutter0.stage
41
+ stage0.background_color = Clutter::Color.new(0xdd, 0xff, 0xdd, 0xff)
42
+
43
+ vbox = Gtk::Box.new(:vertical, 6)
44
+ notebook.append_page(vbox, Gtk::Label.new("Two stages"))
45
+
46
+ clutter1 = ClutterGtk::Embed.new
47
+ clutter1.set_size_request(320, 240)
48
+ stage1 = clutter1.stage
49
+ stage1.background_color = Clutter::Color.new(0xff, 0xff, 0xff, 0xff)
50
+ texture1 = ClutterGtk::Texture.new
51
+ texture1.set_from_stock(clutter1, Gtk::Stock::DIALOG_INFO.to_s, :dialog)
52
+ texture1.set_anchor_point(texture1.width / 2,
53
+ texture1.height / 2)
54
+ texture1.set_position(160, 120)
55
+ stage1.add_child(texture1)
56
+ texture1.show
57
+
58
+ vbox.add(clutter1)
59
+
60
+ clutter2 = ClutterGtk::Embed.new
61
+ clutter2.set_size_request(320, 120)
62
+ stage2 = clutter2.stage
63
+ stage2.background_color = Clutter::Color.new(0x00, 0x00, 0x00, 0xff)
64
+ texture2 = ClutterGtk::Texture.new
65
+ texture2.set_from_icon_name(clutter1, "user-info", :button)
66
+ texture2.set_anchor_point(texture2.width / 2,
67
+ texture2.height / 2)
68
+ texture2.set_position(160, 60)
69
+ stage2.add_child(texture2)
70
+
71
+ vbox.add(clutter2)
72
+
73
+ stage2.signal_connect("allocation-changed") do |actor, allocation, flags|
74
+ texture2.set_position((allocation.x2 - allocation.x1) / 2,
75
+ (allocation.y2 - allocation.y1) / 2)
76
+ end
77
+
78
+ window.show_all
79
+
80
+ Gtk.main
81
+
82
+ __END__
83
+ #include <gtk/gtk.h>
84
+ #include <clutter/clutter.h>
85
+
86
+ #include <clutter-gtk/clutter-gtk.h>
87
+
88
+ static void
89
+ on_stage2_allocation_changed (ClutterActor *stage_2,
90
+ const ClutterActorBox *allocation,
91
+ ClutterAllocationFlags flags,
92
+ ClutterActor *texture_2)
93
+ {
94
+ clutter_actor_set_position (texture_2,
95
+ (allocation->x2 - allocation->x1) / 2,
96
+ (allocation->y2 - allocation->y1) / 2);
97
+ }
98
+
99
+ int
100
+ main (int argc, char *argv[])
101
+ {
102
+ ClutterActor *stage0, *stage1, *stage2, *tex1, *tex2;
103
+ GtkWidget *window, *clutter0, *clutter1, *clutter2;
104
+ GtkWidget *notebook, *vbox;
105
+ ClutterColor col0 = { 0xdd, 0xff, 0xdd, 0xff };
106
+ ClutterColor col1 = { 0xff, 0xff, 0xff, 0xff };
107
+ ClutterColor col2 = { 0, 0, 0, 0xff };
108
+
109
+ if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
110
+ g_error ("Unable to initialize GtkClutter");
111
+
112
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
113
+ gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
114
+ gtk_window_set_title (GTK_WINDOW (window), "Multiple GtkClutterEmbed");
115
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
116
+
117
+ notebook = gtk_notebook_new ();
118
+ gtk_container_add (GTK_CONTAINER (window), notebook);
119
+
120
+ clutter0 = gtk_clutter_embed_new ();
121
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), clutter0,
122
+ gtk_label_new ("One stage"));
123
+ stage0 = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (clutter0));
124
+ clutter_actor_set_background_color (stage0, &col0);
125
+
126
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
127
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox,
128
+ gtk_label_new ("Two stages"));
129
+
130
+ clutter1 = gtk_clutter_embed_new ();
131
+ gtk_widget_set_size_request (clutter1, 320, 240);
132
+ stage1 = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (clutter1));
133
+ clutter_actor_set_background_color (stage1, &col1);
134
+ tex1 = gtk_clutter_texture_new ();
135
+ gtk_clutter_texture_set_from_stock (GTK_CLUTTER_TEXTURE (tex1),
136
+ clutter1,
137
+ GTK_STOCK_DIALOG_INFO,
138
+ GTK_ICON_SIZE_DIALOG,
139
+ NULL);
140
+ clutter_actor_set_anchor_point (tex1,
141
+ clutter_actor_get_width (tex1) / 2,
142
+ clutter_actor_get_height (tex1) / 2);
143
+ clutter_actor_set_position (tex1, 160, 120);
144
+ clutter_actor_add_child (stage1, tex1);
145
+ clutter_actor_show (tex1);
146
+
147
+ gtk_container_add (GTK_CONTAINER (vbox), clutter1);
148
+
149
+ clutter2 = gtk_clutter_embed_new ();
150
+ gtk_widget_set_size_request (clutter2, 320, 120);
151
+ stage2 = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (clutter2));
152
+ clutter_actor_set_background_color (stage2, &col2);
153
+ tex2 = gtk_clutter_texture_new ();
154
+ gtk_clutter_texture_set_from_icon_name (GTK_CLUTTER_TEXTURE (tex2),
155
+ clutter1,
156
+ "user-info",
157
+ GTK_ICON_SIZE_BUTTON,
158
+ NULL);
159
+ clutter_actor_set_anchor_point (tex2,
160
+ clutter_actor_get_width (tex2) / 2,
161
+ clutter_actor_get_height (tex2) / 2);
162
+ clutter_actor_set_position (tex2, 160, 60);
163
+ clutter_actor_add_child (stage2, tex2);
164
+
165
+ gtk_container_add (GTK_CONTAINER (vbox), clutter2);
166
+
167
+ g_signal_connect (stage2, "allocation-changed",
168
+ G_CALLBACK (on_stage2_allocation_changed),
169
+ tex2);
170
+
171
+ gtk_widget_show_all (window);
172
+
173
+ gtk_main();
174
+
175
+ return 0;
176
+ }
Binary file
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This sample code is a port of clutter-gtk/examples/gtk-clutter-test-actor.c.
4
+ # It is licensed under the terms of the GNU Lesser General Public
5
+ # License, version 2.1 or (at your option) later.
6
+ #
7
+ # Copyright (C) 2013 Ruby-GNOME2 Project Team
8
+ #
9
+ # This library is free software; you can redistribute it and/or
10
+ # modify it under the terms of the GNU Lesser General Public
11
+ # License as published by the Free Software Foundation; either
12
+ # version 2.1 of the License, or (at your option) any later version.
13
+ #
14
+ # This library is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ # Lesser General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public
20
+ # License along with this library; if not, write to the Free Software
21
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
+
23
+ require "clutter-gtk"
24
+
25
+ ClutterGtk.init
26
+
27
+ MAX_N_WIDGETS = 4
28
+ WINDOW_WIDTH = 400
29
+ WINDOW_HEIGHT = 400
30
+ RADIUS = 80
31
+
32
+ do_rotate_p = true
33
+
34
+ window = Gtk::Window.new
35
+ window.signal_connect("destroy") do
36
+ Gtk.main_quit
37
+ end
38
+
39
+ vbox = Gtk::Box.new(:vertical, 6)
40
+ window.add(vbox)
41
+
42
+ clutter = ClutterGtk::Embed.new
43
+ clutter.set_size_request(WINDOW_WIDTH, WINDOW_HEIGHT)
44
+
45
+ vbox.pack_start(clutter, :expand => true, :fill => true, :padding => 0)
46
+
47
+ stage = clutter.stage
48
+
49
+ button = Gtk::Button.new(:stock_id => Gtk::Stock::QUIT)
50
+ button.signal_connect("clicked") do |_button|
51
+ window.destroy
52
+ end
53
+ vbox.pack_end(button, :expand => false, :fill => false, :padding => 0)
54
+
55
+ stage.background_color = Clutter::Color.new(0x61, 0x64, 0x8c, 0xff)
56
+
57
+ widgets = []
58
+
59
+ # create a new group to hold multiple actors in a group
60
+ group = Clutter::Actor.new
61
+
62
+ create_gtk_actor = lambda do
63
+ gtk_actor = ClutterGtk::Actor.new
64
+ bin = gtk_actor.widget
65
+
66
+ vbox = Gtk::Box.new(:vertical, 6)
67
+ bin.add(vbox)
68
+
69
+ button = Gtk::Button.new(:label => "A Button")
70
+ vbox.pack_start(button, :expand => false, :fill => false, :padding => 0)
71
+
72
+ button.signal_connect("clicked") do |_button|
73
+ puts("button clicked")
74
+ label = Gtk::Label.new("A new label")
75
+ label.show
76
+ vbox.pack_start(label, :expand => false, :fill => false, :padding => 0)
77
+ end
78
+
79
+ button = Gtk::CheckButton.new("Another button")
80
+ vbox.pack_start(button, :expand => false, :fill => false, :padding => 0)
81
+
82
+ entry = Gtk::Entry.new
83
+ vbox.pack_start(entry, :expand => false, :fill => false, :padding => 0)
84
+
85
+ bin.show_all
86
+
87
+ gtk_actor
88
+ end
89
+
90
+ add_clutter_actor = lambda do |actor, container, i|
91
+ container.add_child(actor)
92
+
93
+ # Place around a circle
94
+ w = widgets.first.width
95
+ h = widgets.first.height
96
+
97
+ x = WINDOW_WIDTH / 2 +
98
+ RADIUS * Math.cos(i * 2 * Math::PI / (MAX_N_WIDGETS)) - w / 2
99
+ y = WINDOW_HEIGHT / 2 +
100
+ RADIUS * Math.sin(i * 2 * Math::PI / (MAX_N_WIDGETS)) - h / 2
101
+
102
+ actor.set_position(x, y)
103
+ end
104
+
105
+ MAX_N_WIDGETS.times do |i|
106
+ widget = create_gtk_actor.call
107
+ widgets[i] = widget
108
+ add_clutter_actor.call(widget, group, i)
109
+ end
110
+
111
+ # Add the group to the stage and center it
112
+ stage.add_child(group)
113
+ group.add_constraint(Clutter::AlignConstraint.new(stage, :x_axis, 0.5))
114
+ group.add_constraint(Clutter::AlignConstraint.new(stage, :y_axis, 0.5))
115
+
116
+ window.show_all
117
+
118
+ # Create a timeline to manage animation
119
+ timeline = Clutter::Timeline.new(6000)
120
+ timeline.repeat_count = -1
121
+
122
+ # fire a callback for frame change
123
+ timeline.signal_connect("new-frame") do |_timeline, m_secs|
124
+ rotation = _timeline.progress * 360.0
125
+ if do_rotate_p
126
+ # Rotate everything clockwise about stage center
127
+ group.set_rotation(:z_axis,
128
+ rotation,
129
+ WINDOW_WIDTH / 2,
130
+ WINDOW_HEIGHT / 2,
131
+ 0)
132
+
133
+ widgets.each do |widget|
134
+ # rotate each widget around its center
135
+ w = widget.width
136
+ h = widget.height
137
+
138
+ widget.set_rotation(:z_axis,
139
+ -(2 * rotation),
140
+ w / 2,
141
+ h / 2,
142
+ 0)
143
+ widget.opacity = 50 * Math.sin(2 * Math::PI * rotation / 360) + (255 - 50)
144
+ end
145
+ end
146
+ end
147
+
148
+ # and start it
149
+ timeline.start
150
+
151
+ GLib::Timeout.add_seconds(3) do
152
+ if MAX_N_WIDGETS == widgets.size
153
+ # Removing an item
154
+ group.remove_child(widgets.pop)
155
+ else
156
+ # Adding an item
157
+ widget = create_gtk_actor.call
158
+ widgets << widget
159
+ add_clutter_actor.call(widget, group, MAX_N_WIDGETS - 1)
160
+ end
161
+ keep_callback = true
162
+ keep_callback
163
+ end
164
+
165
+ Gtk.main