./configure --prefix support for perl
[adesklets.git] / test / widgets.py
blob8f2612832b92b116d85303d0256e42d68aeaf63f
1 """
2 --------------------------------------------------------------------------------
3 widgets.py - S.Fourmanoit <syfou@users.sourceforge.net>, 2005
5 This shows a simple way to use Python object-orientedness to implement a
6 simple MVC (Model-View-Control) model, usable with adesklets to implements
7 easy to use widgets.
9 The beauty of this code is that, while being compact (the core Widget class
10 is seventeen lines of code), it gives a way to dynamically create and modify
11 an arbitrary tree of small graphical elements (widgets) embedding at the
12 same place all their data and the methods needed to display them.
13 --------------------------------------------------------------------------------
14 """
15 #-------------------------------------------------------------------------------
16 class Widget(list):
17 """
18 Simple class creating a generic widget that can have any numbers
19 of descendants, storable in a tree-like structure. It implements:
21 - A breadth first iterator, usable to visit a complete widget tree
22 or subtree in top to bottom, first to last child order (a widget can
23 also contain non widget-derived objects -- they will simply be skipped
24 by the irerator).
26 - A 'static' config class attribute that can be used to store
27 a configuration shared by all instances of Widget, or
28 Widget derivated classes.
30 - An 'execute' function, that can be used as a shortcut to __iter__
31 to perform arbitrary code execution on a whole widget tree.
33 Obviously, this is completely independent from adesklets...
34 """
35 __name = None
36 config = {}
38 def __init__(self,config=None):
39 if not config is None:
40 Widget.config=config
42 def __iter__(self):
43 yield self
44 for elem in list.__iter__(self):
45 if hasattr(elem,'_Widget__name'):
46 for child in elem.__iter__():
47 yield child
49 def execute(self, func, args=[]):
50 for widget in self:
51 widget.__getattribute__(func)(*args)
53 #-------------------------------------------------------------------------------
54 # Now, as a demonstration, let's create a few very simple classes derived
55 # from Widget able to specifically deal with adesklets.
57 # Here, we always create a 'draw' method in every one of them, that can be used
58 # later on to display the element using 'execute' from the root widget element.
59 # Real-life widgets would probably create at least two methods for this
60 # (one writing to foreground and the other one to background),
61 # that would be used appropriately (or arguments would be used).
63 import adesklets
65 class Box(Widget):
66 """ Box widget"""
67 def __init__(self,coords):
68 Widget.__init__(self)
69 self.coords=coords
70 def draw(self):
71 adesklets.context_set_color(0,0,0,0)
72 adesklets.context_set_blend(False)
73 adesklets.image_fill_rectangle(*self.coords)
74 adesklets.context_set_blend(True)
75 adesklets.context_set_color(*self.config['box_color'])
76 adesklets.image_draw_rectangle(*self.coords)
78 class Text(Widget):
79 """ Text label widget"""
80 def __init__(self,coords, text):
81 Widget.__init__(self)
82 self.coords=coords
83 self.text=text
84 def draw(self):
85 font=adesklets.load_font(self.config['text_font'])
86 adesklets.context_set_font(font)
87 adesklets.context_set_color(*self.config['text_color'])
88 adesklets.text_draw(self.coords[0],self.coords[1],self.text)
89 adesklets.free_font(font)
90 def size(self):
91 font=adesklets.load_font(self.config['text_font'])
92 adesklets.context_set_font(font)
93 result=adesklets.get_text_size(self.text)
94 adesklets.free_font(font)
95 return result
96 def __str__(self):
97 return "<Text label at %s, being '%s'>" % (self.coords, self.text)
99 class BoxedText(Widget):
100 """Compound boxed text widget"""
101 def __init__(self,coords,text):
102 Widget.__init__(self)
103 t=Text(coords,text)
104 self.append(Box(coords + list(t.size())))
105 self.append(t)
106 def draw(self):
107 pass
109 class Canva(Widget):
110 """Root widget"""
111 def draw(self):
112 pass
114 #-------------------------------------------------------------------------------
115 # Utility functions
117 from signal import pause
118 from random import randint
120 def rcoords():
121 """Iterator generating pseudo-random (x, y) coordinates in [0,100]"""
122 while 1:
123 yield [randint(0,100),randint(0,100)]
125 #-------------------------------------------------------------------------------
126 # Main routine
127 # ============
129 # Here is the configuration: of course, it could as well be an
130 # adesklets.ConfigFile class or anything else.
132 config = { 'text_font' : 'Vera/20', 'text_color' : [0,255,0,200] ,
133 'box_color': [255,255,255,200] }
135 # Create dynamically a bunch of randomly positionned widgets
137 canva=Canva(config)
138 for coords, caption in zip(rcoords(),'Some text to put on screen'.split()):
139 canva.append(BoxedText(coords,caption))
141 # Set up adesklets
143 adesklets.window_resize(150,150)
144 adesklets.window_set_transparency(True)
145 adesklets.window_reset(adesklets.WINDOW_MANAGED)
146 adesklets.window_show()
148 # Now let's draw everything once...
150 canva.execute('draw')
152 # ... Printout all existing Text widget properties descending from
153 # our root 'window' desklet, just to show off...
155 for widget in canva:
156 if widget.__class__ is Text:
157 print widget
159 # ... and finally, sleep forever.
161 pause()
163 #-------------------------------------------------------------------------------