License Public Domain
Lines 177
Keywords
clutter (1) gtk (1) pyclutter (1) pygtk (2) python (33) toolkit (2)
Permissions
Owner: lethalman
Viewable by Everyone
Editable by All Siafoo Users
Hide
Siafoo is here to make coding less frustrating and to save you time. Join Siafoo Now or Learn More

Replace GTK+ with Clutter Atom Feed 0

In Brief Hello, lately I was having fun with Clutter and Python. I've started by creating some Gtk-like widgets (such as GtkWindow, GtkBox, and GtkButton) in Clutter. Well, this is the result... it's a simple example of a very poor toolkit, but it works.... more
# 's
  1import math
2import gobject
3import pango
4import clutter
5
6class Stage (clutter.Stage):
7 def __init__ (self):
8 self.__gobject_init__ ()
9 self.set_color (clutter.color_parse ('#000000ff'))
10
11 def get_child (self):
12 return self.get_children()[0]
13
14 def add (self, actor):
15 if self.get_children ():
16 raise RuntimeError ("A Stage can only hold one child")
17 clutter.Stage.add (self, actor)
18 actor.set_position (1, 1)
19 actor.set_size (self.get_width () - 2, self.get_height () - 2)
20
21class Box (clutter.Group):
22 HORIZONTAL = 0
23 VERTICAL = 1
24
25 def __init__ (self, orientation, spacing=0):
26 self.__gobject_init__ ()
27 self.order = []
28 self.orientation = orientation
29 self.spacing = spacing
30
31 def pack_end (self, actor):
32 clutter.Group.add (self, actor)
33 self.order.insert (0, actor)
34 self._reallocate ()
35
36 def pack_start (self, actor):
37 clutter.Group.add (self, actor)
38 self.order.append (actor)
39 self._reallocate ()
40
41 def _reallocate (self):
42 n = len (self.order)
43 x = 0
44 y = 0
45 eat = int (math.ceil (self.spacing * (n - 1) / float (n)))
46 if self.orientation == self.HORIZONTAL:
47 width = self.get_width () / n - eat
48 height = self.get_height ()
49 for child in self.order:
50 child.set_position (x, y)
51 child.set_size (width, height)
52 x += child.get_width () + self.spacing
53 else:
54 width = self.get_width ()
55 height = self.get_height () / n - eat
56 for child in self.order:
57 child.set_position (x, y)
58 child.set_size (width, height)
59 y += child.get_height () + self.spacing
60
61class Label (clutter.Label):
62 COLOR = clutter.color_parse ('#ffffffc0')
63
64 def __init__ (self):
65 self.__gobject_init__ ()
66 self.set_color (self.COLOR)
67 attr_list = pango.AttrList ()
68 attr = pango.AttrWeight (pango.WEIGHT_BOLD)
69 attr.end_index = -1
70 attr_list.insert (attr)
71 attr = pango.AttrSize (11*pango.SCALE)
72 attr.end_index = -1
73 attr_list.insert (attr)
74 self.set_attributes (attr_list)
75
76class Button (clutter.Group):
77 BORDER_WIDTH = 2
78 BORDER_COLOR = clutter.color_parse ('#a9a9a970')
79 NORMAL_COLOR = clutter.color_parse ('#5e7ea540')
80 HOVER_COLOR = clutter.color_parse ('#5e7ea580')
81 CLICKED_COLOR = clutter.color_parse ('#8bafdc80')
82
83 __gproperties__ = {
84 'label': (gobject.TYPE_STRING, 'Label', "The button's label",
85 '', gobject.PARAM_READWRITE),
86 'padding': (gobject.TYPE_INT, 'Padding', 'The padding of the button',
87 0, 100, 6, gobject.PARAM_READWRITE),
88 'width': (gobject.TYPE_INT, 'Width', 'The width of the button',
89 0, 100000, 0, gobject.PARAM_READWRITE),
90 'height': (gobject.TYPE_INT, 'Height', 'The height of the button',
91 0, 100000, 0, gobject.PARAM_READWRITE),
92 }
93
94 __gsignals__ = {
95 'button-press-event': 'override',
96 'button-release-event': 'override',
97 'enter-event': 'override',
98 'leave-event': 'override',
99 'clicked': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
100 ()),
101 }
102
103 def __init__ (self, label=''):
104 self.__gobject_init__ ()
105
106 self.set_reactive (True)
107 self.padding = 12
108 self.label = label
109
110 self.label_actor = Label ()
111 self.label_actor.set_text (self.label)
112
113 self.rectangle_actor = clutter.Rectangle ()
114 self.rectangle_actor.set_color (self.NORMAL_COLOR)
115 self.rectangle_actor.set_border_width (self.BORDER_WIDTH)
116 self.rectangle_actor.set_border_color (self.BORDER_COLOR)
117
118 self.set_size (0, 0)
119
120 self.add (self.rectangle_actor)
121 self.add (self.label_actor)
122
123 def get_min_width (self):
124 return self.label_actor.get_width () + self.padding * 2
125
126 def get_min_height (self):
127 return self.label_actor.get_height () + self.padding * 2
128
129 def _set_width (self, width):
130 min_width = self.get_min_width ()
131 if width > min_width:
132 self.width = width
133 else:
134 self.width = min_width
135
136 def _set_height (self, height):
137 min_height = self.get_min_height ()
138 if height > min_height:
139 self.height = height
140 else:
141 self.height = min_height
142
143 def set_size (self, width, height):
144 self._set_width (width)
145 self._set_height (height)
146 self._repaint ()
147
148 def set_width (self, width):
149 self._set_width (width)
150 self._repaint ()
151
152 def set_height (self, height):
153 self._set_height (height)
154 self._repaint ()
155
156 def _repaint (self):
157 # Recalculate geometry
158 self._set_width (self.width)
159 self._set_height (self.height)
160 l_width = self.label_actor.get_width ()
161 l_height = self.label_actor.get_height ()
162 self.label_actor.set_position (self.width/2-l_width/2, self.height/2-l_height/2)
163 self.rectangle_actor.set_size (self.width, self.height)
164
165 def do_set_property(self, pspec, value):
166 setattr (self, pspec.name, value)
167 if pspec.name == 'label':
168 self.label_actor.set_text (value)
169 self._repaint ()
170 elif pspec.name in ('padding', 'width', 'height'):
171 self._repaint ()
172 else:
173 raise AttributeError, 'unknown property %s' % pspec.name
174
175 def do_get_property(self, pspec):
176 if pspec.name in ('label', 'padding', 'width', 'height'):
177 return getattr (self, pspec.name)
178 else:
179 raise AttributeError, 'unknown property %s' % pspec.name
180
181 def do_button_press_event (self, event):
182 self.rectangle_actor.set_color (self.CLICKED_COLOR)
183
184 def do_button_release_event (self, event):
185 self.rectangle_actor.set_color (self.HOVER_COLOR)
186 self.emit ('clicked')
187
188 def do_enter_event (self, event):
189 self.rectangle_actor.set_color (self.HOVER_COLOR)
190
191 def do_leave_event (self, event):
192 self.rectangle_actor.set_color (self.NORMAL_COLOR)
193
194clutter.init ()
195
196stage = Stage ()
197stage.show ()
198stage.connect ('destroy', lambda *args: clutter.main_quit ()) # This looks like a self-kill for X
199
200box = Box (Box.VERTICAL, 10)
201stage.add (box)
202
203box1 = Box (Box.HORIZONTAL, 5)
204box.pack_start (box1)
205box2 = Box (Box.HORIZONTAL, 15)
206box.pack_end (box2)
207
208box1.pack_start (Button ("Button 1"))
209box1.pack_end (Button ("Button 2"))
210box1.pack_start (Button ("Button 3"))
211
212box2.pack_start (Button ("Button 1"))
213box2.pack_end (Button ("Button 2"))
214box2.pack_start (Button ("Button 3"))
215
216clutter.main ()

Hello, lately I was having fun with Clutter and Python. I've started by creating some Gtk-like widgets (such as GtkWindow, GtkBox, and GtkButton) in Clutter. Well, this is the result... it's a simple example of a very poor toolkit, but it works.

http://www.siafoo.net/image/127