~glitter-team/glitter/trunk

1 by Jan Jokela
Hi, Glitter here
1
# !/usr/bin/python
2
# -*- coding: utf-8 -*-
3
4
# Glitter Toolkit
5
6
__authors__ = ["Jan Jokela <janjokela@gmail.com>"]
7
__licenses__ = ["LICENSE.LGPL"]
8
__description__ = "Horizontal and vertical box widgets" 
9
10
import gobject
11
import pango
12
import clutter
13
14
from container import Container
15
16
class Box(Container):
17
    """ 
18
    A box is a special type of container for displaying multiple children in 
19
    an horizontal or vertical layout.
20
    
7.1.14 by Jan Jokela
(glitter/box.py) API changes to the box widget
21
    The 'Box' base widgets offers a common interface to all box widgets
22
    
1 by Jan Jokela
Hi, Glitter here
23
    """
24
    
7.1.13 by Jan Jokela
(Commit FIX)
25
    def __init__(self):
1 by Jan Jokela
Hi, Glitter here
26
        """ Initialize box """
27
        
28
        super(Box, self).__init__()
29
        
7.1.13 by Jan Jokela
(Commit FIX)
30
        self._spacing = 0.0
1 by Jan Jokela
Hi, Glitter here
31
        self._alignment = 1
32
        self.packed_children = []
33
        
34
        self._update_style(self.style)
35
        
36
    def _update_style(self, props=None):
37
        """ Updates style """
38
        
39
        super(Box, self)._update_style(props)
40
        
41
        for key, value in props:
42
            if key == 'spacing':
18.1.12 by Jan Jokela
(glitter/tests/*) Added and improved a bunch of tests; (glitter/data/themes/nublo/styles/label.json) Fixes in label widget style; (glitter/box.py) Layout code fixes
43
                self._spacing = value
1 by Jan Jokela
Hi, Glitter here
44
            elif key == 'alignment':
18.1.12 by Jan Jokela
(glitter/tests/*) Added and improved a bunch of tests; (glitter/data/themes/nublo/styles/label.json) Fixes in label widget style; (glitter/box.py) Layout code fixes
45
                self._alignment = value
1 by Jan Jokela
Hi, Glitter here
46
                
47
    def _update_layout(self):
48
        """ Update layout """
49
        
7.1.6 by Jan Jokela
(glitter/box.py) Added clipping to the box widgets
50
        super(Box, self)._update_layout() 
51
        
52
        self.set_clip(0, 0, self.get_width(), self.get_height())         
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
53
         
54
    def _update_fixed_widgets(self, child):
55
        """ Update list of fixed width/height children """
56
        
57
        pass
1 by Jan Jokela
Hi, Glitter here
58
                   
7.1.14 by Jan Jokela
(glitter/box.py) API changes to the box widget
59
    def pack(self, child, order='after'):
60
        """ Packs a child into the box after or before current items 
61
        
62
        child -- (glitter.Widget) A Glitter widget
63
        order -- (str) 'after' or 'before' currently packed items
64
        """
65
        
66
        if order == 'after': 
67
            self.packed_children.append(child)
68
        elif order == 'before':
69
            self.packed_children.insert(0, child)
1 by Jan Jokela
Hi, Glitter here
70
        self.add(child)
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
71
        self._update_fixed_widgets(child)
7.1.4 by Jan Jokela
(glitter/box.py) Fixed bug where packing a widget wouldn't refresh the layout
72
        self._update_layout()
5.1.1 by Jan Jokela
Added list widget, 'Scrollable' interface
73
        
7.1.14 by Jan Jokela
(glitter/box.py) API changes to the box widget
74
    def unpack(self, child):
75
        """ Unpacks a child from a box 
76
        
77
        child -- (glitter.Widget) A Glitter widget
78
        """
79
        
80
        self.packed_children.remove(child)
81
        self.remove(child)
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
82
        self._update_fixed_widgets(child)
7.1.14 by Jan Jokela
(glitter/box.py) API changes to the box widget
83
        self._update_layout()        
84
        
5.1.1 by Jan Jokela
Added list widget, 'Scrollable' interface
85
    def get_packed_children(self):
86
        """ Retrieve packed children """
87
        
88
        return self.packed_children
1 by Jan Jokela
Hi, Glitter here
89
                            
90
    def get_spacing(self):
91
        """ Retrieve child spacing """
92
        
93
        return self._spacing
94
        
95
    def set_spacing(self, value):
96
        """ Sets child spacing
97
        
98
        value -- (float) Spacing between children
99
        """
100
        
101
        self._spacing = value
18.1.12 by Jan Jokela
(glitter/tests/*) Added and improved a bunch of tests; (glitter/data/themes/nublo/styles/label.json) Fixes in label widget style; (glitter/box.py) Layout code fixes
102
        self._update_layout()
1 by Jan Jokela
Hi, Glitter here
103
                
104
    spacing = property(get_spacing, set_spacing)
105
        
106
    def get_alignment(self):
107
        """ Retrieve alignment """
108
        
109
        return self._alignment
110
        
111
    def set_alignment(self, value):
112
        """ Sets children alignment 
113
        
114
        value -- (str) [ALINGMENT.START, ALIGNMENT.END, ALIGNMENT.CENTER]
115
        """
116
        
117
        self._alignment = value
18.1.12 by Jan Jokela
(glitter/tests/*) Added and improved a bunch of tests; (glitter/data/themes/nublo/styles/label.json) Fixes in label widget style; (glitter/box.py) Layout code fixes
118
        self._update_layout()
1 by Jan Jokela
Hi, Glitter here
119
        
120
    alignment = property(get_alignment, set_alignment)
121
        
122
           
123
class HBox(Box):
7.1.14 by Jan Jokela
(glitter/box.py) API changes to the box widget
124
    """ A HBox layouts children in an horizontal fashion """
1 by Jan Jokela
Hi, Glitter here
125
    
7.1.13 by Jan Jokela
(Commit FIX)
126
    def __init__(self):
1 by Jan Jokela
Hi, Glitter here
127
        """ Initialize horizontal box """
128
        
7.1.13 by Jan Jokela
(Commit FIX)
129
        super(HBox, self).__init__()
1 by Jan Jokela
Hi, Glitter here
130
        
131
        self._update_style(self.style)
132
        
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
133
        self.fixed_width_children = []
134
        
1 by Jan Jokela
Hi, Glitter here
135
    def _update_style(self, props=None):
136
        """ Updates style """
7.1.12 by Jan Jokela
(glitter/box.py) Box widget spacing?
137
       
1 by Jan Jokela
Hi, Glitter here
138
        super(HBox, self)._update_style(props)
139
        
140
    def _update_layout(self):
141
        """ Updates layout """
142
        
143
        super(HBox, self)._update_layout()
144
        
18.1.4 by Jan Jokela
(/glitter/container.py) Minor fixes; (/glitter/box.py) Fixes in box layout algorithm; (glitter/test_hbox.py) n.a.; (glitter/test_image.py) Sanitized imports so no warnings appear now
145
        if len(self.packed_children) > 0:
26.1.4 by Jan Jokela
Minimum width buttons work again
146
            # Reserved width for spacing between widgets
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
147
            reserved_width = self.spacing * (len(self.packed_children) - 1) * \
148
              self.get_widthu()
149
        else:
150
            reserved_width = 0.0
151
        
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
152
        # Update the reserved width given our fixed width children
153
        for child in self.fixed_width_children:
154
            child._update_layout()
155
            # Increment reserved width by child height and horizontal 
156
            # offset
157
            reserved_width += child.get_widthu() + \
158
              child.h_offset * child.get_widthu() * 2.0
26.1.4 by Jan Jokela
Minimum width buttons work again
159
        self.minimum_width = reserved_width
160
        super(HBox, self)._update_layout()
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
161
        
162
        # Total width excluding reserved width        
163
        free_width = self.get_widthu() - reserved_width
164
        # Width for variable width children
165
        var_width_child_count = len(self.packed_children) - \
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
166
          len(self.fixed_width_children)
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
167
        var_child_width = free_width        
168
        if var_width_child_count > 0:
169
            var_child_width /= var_width_child_count        
170
        
171
        # Position all children
172
        current_x = 0.0
173
        for child in self.packed_children:
26.1.7 by Jan Jokela
(glitter/box.py) Improved code documentation
174
            # Calculate child offset width and add that to the current x pos
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
175
            if child not in self.fixed_width_children:
18.1.12 by Jan Jokela
(glitter/tests/*) Added and improved a bunch of tests; (glitter/data/themes/nublo/styles/label.json) Fixes in label widget style; (glitter/box.py) Layout code fixes
176
                offset_width = var_child_width * child.h_offset
177
            else:
178
                offset_width = child.h_offset * child.get_widthu()
179
            current_x += offset_width
26.1.7 by Jan Jokela
(glitter/box.py) Improved code documentation
180
            # Position children
18.1.6 by Jan Jokela
(glitter/data/themes/nublo/styles/button.json) @.@
181
            if self.get_widthu() > 0:
182
                child.natural_x = current_x / self.get_widthu()
26.1.7 by Jan Jokela
(glitter/box.py) Improved code documentation
183
                # Size variable width children
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
184
                if child not in self.fixed_width_children:
18.1.12 by Jan Jokela
(glitter/tests/*) Added and improved a bunch of tests; (glitter/data/themes/nublo/styles/label.json) Fixes in label widget style; (glitter/box.py) Layout code fixes
185
                    child.natural_width = (var_child_width - 2 * offset_width) \
186
                    / self.get_widthu()
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
187
            child._update_layout()
26.1.7 by Jan Jokela
(glitter/box.py) Improved code documentation
188
            # Add child width, horizontal offset and box spacing to current x
18.1.5 by Jan Jokela
(glitter/box.py) Huge improvements in horizontal box algorithm; (glitter/tests/test_hbox.py) Tests clean; (glitter/container.py) Position now set in device independent units, again
189
            current_x += child.get_widthu()
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
190
            current_x += child.get_widthu() * child.h_offset
191
            current_x += self.get_widthu() * self.spacing
26.1.9 by Jan Jokela
(glitter/button.py) Button layout code
192
        self.set_clipu(0, 0, self.get_widthu(), self.get_heightu())
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
193
194
    def _update_fixed_widgets(self, child):
195
        """ Updates fixed width children list """
196
197
        super(HBox, self)._update_fixed_widgets(child)
198
199
        if child in self.fixed_width_children:
200
            self.fixed_width_children.remove(child)    
201
        elif child.size_ratio > 0 or child.natural_width == 0:
202
            self.fixed_width_children.append(child)
203
5.1.1 by Jan Jokela
Added list widget, 'Scrollable' interface
204
class VBox(Box):
205
    """ A VBox layouts children in a vertical fashion """
206
    
207
    def __init__(self):
208
        """ Initialize vertical box """
209
        
210
        super(VBox, self).__init__()
211
        
212
        self._update_style(self.style)
213
        
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
214
        self.fixed_height_children = []
215
        
5.1.1 by Jan Jokela
Added list widget, 'Scrollable' interface
216
    def _update_style(self, props=None):
217
        """ Updates style """
218
        
219
        super(VBox, self)._update_style(props)
220
        
221
    def _update_layout(self):
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
222
        """ Updates layout 
223
        
224
        Fixed height children are flagged and will be offered the space they 
225
        need. Other children will share the remaining space.
226
        
227
        Children with minimum height and width->height size ratios qualify as 
228
        fixed height.
229
        """
5.1.1 by Jan Jokela
Added list widget, 'Scrollable' interface
230
        
231
        super(VBox, self)._update_layout()
232
        
18.1.7 by Jan Jokela
(glitter/box.py) Fixed vertical box; (glitter/tests/test_vbox.py) Sanitized imports and improved test
233
        if len(self.packed_children) > 0:
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
234
            # Reserved height for spacing between widgets
18.1.7 by Jan Jokela
(glitter/box.py) Fixed vertical box; (glitter/tests/test_vbox.py) Sanitized imports and improved test
235
            reserved_height = self.spacing * (len(self.packed_children) - 1) * \
236
              self.get_heightu()
237
        else:
238
            reserved_height = 0.0
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
239
        
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
240
        # Update the reserved height given our fixed height children
241
        for child in self.fixed_height_children:
242
            child._update_layout()
243
            # Increment reserved height by child height and horizontal 
244
            # offset
245
            reserved_height += child.get_heightu() + \
246
              child.v_offset * child.get_heightu() * 2.0
247
        self.minimum_height = reserved_height
248
        super(VBox, self)._update_layout()
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
249
        
250
        # Total height excluding reserved height        
251
        free_height = self.get_heightu() - reserved_height
18.1.7 by Jan Jokela
(glitter/box.py) Fixed vertical box; (glitter/tests/test_vbox.py) Sanitized imports and improved test
252
        # Height for variable width children
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
253
        var_height_child_count = len(self.packed_children) - \
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
254
          len(self.fixed_height_children)
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
255
        var_child_height = free_height        
256
        if var_height_child_count > 0:
257
            var_child_height /= var_height_child_count        
258
        
259
        # Position all children
260
        current_y = 0.0
261
        for child in self.packed_children:
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
262
            # Calculate child offset height and add that to the current y pos
263
            if child not in self.fixed_height_children:
18.1.12 by Jan Jokela
(glitter/tests/*) Added and improved a bunch of tests; (glitter/data/themes/nublo/styles/label.json) Fixes in label widget style; (glitter/box.py) Layout code fixes
264
                offset_height = var_child_height * child.v_offset
265
            else:
266
                offset_height = child.v_offset * child.get_heightu()
267
            current_y += offset_height
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
268
            # Position children
18.1.7 by Jan Jokela
(glitter/box.py) Fixed vertical box; (glitter/tests/test_vbox.py) Sanitized imports and improved test
269
            if self.get_heightu() > 0:
270
                child.natural_y = current_y / self.get_heightu()
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
271
                # Size variable height children
272
                if child not in self.fixed_height_children:
18.1.12 by Jan Jokela
(glitter/tests/*) Added and improved a bunch of tests; (glitter/data/themes/nublo/styles/label.json) Fixes in label widget style; (glitter/box.py) Layout code fixes
273
                    child.natural_height = (var_child_height - 2 * offset_height) \
274
                    / self.get_heightu()
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
275
            child._update_layout()
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
276
            # Add child height, vertical offset and box spacing to current y
18.1.7 by Jan Jokela
(glitter/box.py) Fixed vertical box; (glitter/tests/test_vbox.py) Sanitized imports and improved test
277
            current_y += child.get_heightu()
18.1.3 by Jan Jokela
(glitter/box.py) Algorithm improvements
278
            current_y += child.get_heightu() * child.v_offset
279
            current_y += self.get_heightu() * self.spacing
18.1.7 by Jan Jokela
(glitter/box.py) Fixed vertical box; (glitter/tests/test_vbox.py) Sanitized imports and improved test
280
          
5.1.1 by Jan Jokela
Added list widget, 'Scrollable' interface
281
    def get_item(self, i):
282
        """ Retrieve natural y for packed item i """
283
        
284
        if len(self.packed_children) > i:
285
            return self.packed_children[i]
286
        else:
287
            return None
288
289
    def get_item_natural_height(self, i):
290
        """ Retrieve natural height for packed item i """
291
        
292
        if len(self.packed_children) > i:
293
            return self.packed_children[i].natural_height
294
        else:
295
            return -1
26.1.8 by Jan Jokela
(glitter/box.py) Improved algorithms for box widgets; (glitter/test_vbox.py) Fix
296
            
297
    def _update_fixed_widgets(self, child):
298
        """ Updates fixed height children list """
299
300
        super(VBox, self)._update_fixed_widgets(child)
301
302
        if child in self.fixed_height_children:
303
            self.fixed_height_children.remove(child)    
304
        elif child.size_ratio < 0 or child.natural_height == 0:
305
            self.fixed_height_children.append(child) 
306
            
5.1.1 by Jan Jokela
Added list widget, 'Scrollable' interface
307