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
Easily highlight source code for your blog with our Syntax Highlighter. 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