File: widgets.py

package info (click to toggle)
adesklets 0.6.1-4
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 2,044 kB
  • ctags: 1,325
  • sloc: ansic: 5,939; sh: 3,983; python: 2,344; perl: 333; makefile: 211; yacc: 80; lex: 42
file content (163 lines) | stat: -rw-r--r-- 5,611 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
"""
--------------------------------------------------------------------------------
widgets.py - S.Fourmanoit <syfou@users.sourceforge.net>, 2005

This shows a simple way to use Python object-orientedness to implement a
simple MVC (Model-View-Control) model, usable with adesklets to implements
easy to use widgets.

The beauty of this code is that, while being compact (the core Widget class
is seventeen lines of code), it gives a way to dynamically create and modify
an arbitrary tree of small graphical elements (widgets) embedding at the
same place all their data and the methods needed to display them.
--------------------------------------------------------------------------------
"""
#-------------------------------------------------------------------------------
class Widget(list):
    """
    Simple class creating a generic widget that can have any numbers
    of descendants, storable in a tree-like structure. It implements:

    - A breadth first iterator, usable to visit a complete widget tree
    or subtree in top to bottom, first to last child order (a widget can
    also contain non widget-derived objects -- they will simply be skipped
    by the irerator).

    - A 'static' config class attribute that can be used to store
    a configuration shared by all instances of Widget, or
    Widget derivated classes.

    - An 'execute' function, that can be used as a shortcut to __iter__
    to perform arbitrary code execution on a whole widget tree.

    Obviously, this is completely independent from adesklets...
    """
    __name = None
    config = {}

    def __init__(self,config=None):
        if not config is None:
            Widget.config=config

    def __iter__(self):
        yield self
        for elem in list.__iter__(self):
            if hasattr(elem,'_Widget__name'):
                for child in elem.__iter__():
                    yield child
                
    def execute(self, func, args=[]):
        for widget in self:
            widget.__getattribute__(func)(*args)
        
#-------------------------------------------------------------------------------
# Now, as a demonstration, let's create a few very simple classes derived
# from Widget able to specifically deal with adesklets.
#
# Here, we always create a 'draw' method in every one of them, that can be used
# later on to display the element using 'execute' from the root widget element.
# Real-life widgets would probably create at least two methods for this
# (one writing to foreground and the other one to background),
# that would be used appropriately (or arguments would be used).
#
import adesklets

class Box(Widget):
    """ Box widget"""
    def __init__(self,coords):
        Widget.__init__(self)
        self.coords=coords
    def draw(self):
        adesklets.context_set_color(0,0,0,0)
        adesklets.context_set_blend(False)
        adesklets.image_fill_rectangle(*self.coords)
        adesklets.context_set_blend(True)
        adesklets.context_set_color(*self.config['box_color'])
        adesklets.image_draw_rectangle(*self.coords)
        
class Text(Widget):
    """ Text label widget"""
    def __init__(self,coords, text):
        Widget.__init__(self)
        self.coords=coords
        self.text=text
    def draw(self):
        font=adesklets.load_font(self.config['text_font'])
        adesklets.context_set_font(font)
        adesklets.context_set_color(*self.config['text_color'])
        adesklets.text_draw(self.coords[0],self.coords[1],self.text)
        adesklets.free_font(font)
    def size(self):
        font=adesklets.load_font(self.config['text_font'])
        adesklets.context_set_font(font)
        result=adesklets.get_text_size(self.text)
        adesklets.free_font(font)
        return result
    def __str__(self):
        return "<Text label at %s, being '%s'>" % (self.coords, self.text)

class BoxedText(Widget):
    """Compound boxed text widget"""
    def __init__(self,coords,text):
        Widget.__init__(self)
        t=Text(coords,text)
        self.append(Box(coords + list(t.size())))
        self.append(t)
    def draw(self):
        pass

class Canva(Widget):
    """Root widget"""
    def draw(self):
        pass

#-------------------------------------------------------------------------------
# Utility functions
#
from signal import pause
from random import randint

def rcoords():
    """Iterator generating pseudo-random (x, y) coordinates in [0,100]"""
    while 1:
        yield [randint(0,100),randint(0,100)]

#-------------------------------------------------------------------------------
# Main routine
# ============

# Here is the configuration: of course, it could as well be an
# adesklets.ConfigFile class or anything else.
#
config = { 'text_font' : 'DejaVuSans/20', 'text_color' : [0,255,0,200] ,
           'box_color': [255,255,255,200] }

# Create dynamically a bunch of randomly positionned widgets
#
canva=Canva(config)
for coords, caption in zip(rcoords(),'Some text to put on screen'.split()):
    canva.append(BoxedText(coords,caption))

# Set up adesklets
#
adesklets.window_resize(150,150)
adesklets.window_set_transparency(True)
adesklets.window_reset(adesklets.WINDOW_MANAGED)
adesklets.window_show()

# Now let's draw everything once...
#
canva.execute('draw')

# ... Printout all existing Text widget properties descending from
# our root 'window' desklet, just to show off...
#
for widget in canva:
    if widget.__class__ is Text:
        print widget
        
# ... and finally, sleep forever.
#
pause()

#-------------------------------------------------------------------------------