clutter-gtk 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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