~kelemeng/software-center/bug953812

« back to all changes in this revision

Viewing changes to softwarecenter/ui/gtk3/widgets/containers.py

  • Committer: Anthony Lenton
  • Date: 2012-03-12 12:43:52 UTC
  • mto: This revision was merged to the branch mainline in revision 2844.
  • Revision ID: anthony.lenton@canonical.com-20120312124352-nib8p2kkvvnaqea0
Made the pep8 test pass on three more files in softwarecenter/ui/gtk3/widgets/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import cairo
2
2
import os
3
3
from math import pi as PI
4
 
PI_OVER_180 = PI/180
 
4
PI_OVER_180 = PI / 180
5
5
import softwarecenter.paths
6
6
 
7
7
from gi.repository import Gtk, Gdk
25
25
        self.n_rows = 0
26
26
        self.paint_grid_pattern = paint_grid_pattern
27
27
        self._cell_size = None
28
 
        return
29
28
 
30
29
    # private
31
30
    def _get_n_columns_for_width(self, width, cell_w, col_spacing):
33
32
        return n_cols
34
33
 
35
34
    def _layout_children(self, a):
36
 
        if not self.get_visible(): return
 
35
        if not self.get_visible():
 
36
            return
37
37
 
38
38
        children = self.get_children()
39
39
        width = a.width
45
45
        cell_w, cell_h = self.get_cell_size()
46
46
        n_cols = self._get_n_columns_for_width(width, cell_w, col_spacing)
47
47
 
48
 
        if n_cols == 0: return
 
48
        if n_cols == 0:
 
49
            return
49
50
        cell_w = width / n_cols
50
51
        self.n_columns = n_cols
51
52
 
54
55
            #~ xo = h_overhang / (n_cols-1)
55
56
        #~ else:
56
57
            #~ xo = h_overhang
57
 
        
 
58
 
58
59
        if len(children) % n_cols:
59
 
            self.n_rows = len(children)/n_cols + 1
 
60
            self.n_rows = len(children) / n_cols + 1
60
61
        else:
61
 
            self.n_rows = len(children)/n_cols
 
62
            self.n_rows = len(children) / n_cols
62
63
 
63
64
        y = 0
64
65
        for i, child in enumerate(children):
67
68
            #~ x = a.x + (i % n_cols) * (cell_w + col_spacing + xo)
68
69
            #~ if n_cols == 1:
69
70
                #~ x += xo/2
70
 
            if (i%n_cols) == 0:
 
71
            if (i % n_cols) == 0:
71
72
                y = a.y + (i / n_cols) * (cell_h + row_spacing)
72
73
 
73
74
            child_alloc = child.get_allocation()
76
77
            child_alloc.width = cell_w
77
78
            child_alloc.height = cell_h
78
79
            child.size_allocate(child_alloc)
79
 
        return
80
80
 
81
81
    # overrides
82
82
    def do_get_request_mode(self):
84
84
 
85
85
    def do_get_preferred_height_for_width(self, width):
86
86
        old = self.get_allocation()
87
 
        if width == old.width: old.height, old.height
 
87
        if width == old.width:
 
88
            old.height, old.height
88
89
 
89
90
        cell_w, cell_h = self.get_cell_size()
90
91
        n_cols = self._get_n_columns_for_width(
91
92
                        width, cell_w, self.column_spacing)
92
93
 
93
 
        if not n_cols: return self.MIN_HEIGHT, self.MIN_HEIGHT
 
94
        if not n_cols:
 
95
            return self.MIN_HEIGHT, self.MIN_HEIGHT
94
96
 
95
97
        children = self.get_children()
96
98
        n_rows = len(children) / n_cols
99
101
        if len(children) % n_cols:
100
102
            n_rows += 1
101
103
 
102
 
        pref_h = n_rows*cell_h + (n_rows-1)*self.row_spacing + 1
 
104
        pref_h = n_rows * cell_h + (n_rows - 1) * self.row_spacing + 1
103
105
        pref_h = max(self.MIN_HEIGHT, pref_h)
104
106
        return pref_h, pref_h
105
107
 
107
109
    def do_size_allocate(self, allocation):
108
110
        self.set_allocation(allocation)
109
111
        self._layout_children(allocation)
110
 
        return
111
112
 
112
113
    def do_draw(self, cr):
113
 
        if not (self.n_columns and self.n_rows): return
 
114
        if not (self.n_columns and self.n_rows):
 
115
            return
114
116
 
115
117
        if self.paint_grid_pattern:
116
118
            self.render_grid(cr)
117
119
 
118
 
        for child in self: self.propagate_draw(child, cr)
119
 
        return
 
120
        for child in self:
 
121
            self.propagate_draw(child, cr)
120
122
 
121
123
    # public
122
124
    def render_grid(self, cr):
135
137
        w = a.width / self.n_columns
136
138
 
137
139
        for i in range(self.n_columns):
138
 
            cr.move_to(i*w+0.5, 0)
139
 
            cr.rel_line_to(0, a.height-3)
 
140
            cr.move_to(i * w + 0.5, 0)
 
141
            cr.rel_line_to(0, a.height - 3)
140
142
            cr.stroke()
141
143
 
142
144
        w = a.height / self.n_rows
143
145
 
144
146
        for i in range(self.n_rows):
145
 
            cr.move_to(2, i*w+0.5)
146
 
            cr.rel_line_to(a.width-4, 0)
 
147
            cr.move_to(2, i * w + 0.5)
 
148
            cr.rel_line_to(a.width - 4, 0)
147
149
            cr.stroke()
148
150
 
149
151
        cr.restore()
150
 
        return
151
152
 
152
153
    def add_child(self, child):
153
154
        self._cell_size = None
154
155
        self.put(child, 0, 0)
155
 
        return
156
156
 
157
157
    def get_cell_size(self):
158
158
        if self._cell_size is not None:
170
170
 
171
171
    def set_row_spacing(self, value):
172
172
        self.row_spacing = value
173
 
        return
174
173
 
175
174
    def set_column_spacing(self, value):
176
175
        self.column_spacing = value
177
176
        self._layout_children(self.get_allocation())
178
 
        return
179
177
 
180
178
    def remove_all(self):
181
179
        self._cell_size = None
182
180
        for child in self:
183
181
            self.remove(child)
184
 
        return
 
182
 
185
183
 
186
184
# first tier of caching, cache component assets from which frames are
187
185
# rendered
188
186
_frame_asset_cache = {}
 
187
 
 
188
 
189
189
class Frame(Gtk.Alignment):
190
190
 
191
191
    BORDER_RADIUS = 8
200
200
        # set padding + some additional padding in the bottom, left and
201
201
        # right edges to factor in the dropshadow width, and ensure even
202
202
        # visual border
203
 
        self.set_padding(padding, padding+2, padding+1, padding+1)
 
203
        self.set_padding(padding, padding + 2, padding + 1, padding + 1)
204
204
 
205
205
        # corner lable jazz
206
206
        #~ self.show_corner_label = False
218
218
        self._allocation = Gdk.Rectangle()
219
219
        self.connect("size-allocate", self.on_size_allocate)
220
220
        self.connect("style-updated", self.on_style_updated)
221
 
        return
222
221
 
223
222
    def on_style_updated(self, widget):
224
223
        self._frame_surface_cache = None
225
 
        return
226
224
 
227
225
    def on_size_allocate(self, *args):
228
226
        old = self._allocation
237
235
        global _frame_asset_cache
238
236
        at = self.ASSET_TAG
239
237
        assets = _frame_asset_cache
240
 
        if at in assets: return assets
 
238
        if at in assets:
 
239
            return assets
241
240
 
242
241
        def cache_corner_surface(tag, xo, yo):
243
242
            sw = sh = cnr_slice
247
246
            cr.paint()
248
247
            assets[tag] = surf
249
248
            del cr
250
 
            return
251
249
 
252
250
        def cache_edge_pattern(tag, xo, yo, sw, sh):
253
251
            surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, sw, sh)
258
256
            ptrn.set_extend(cairo.EXTEND_REPEAT)
259
257
            assets[tag] = ptrn
260
258
            del cr
261
 
            return
262
259
 
263
260
        # register the asset tag within the asset_cache
264
261
        assets[at] = 'loaded'
275
272
        # northern edge pattern
276
273
        cache_edge_pattern("%s-n" % at,
277
274
                           -cnr_slice, 0,
278
 
                           w-2*cnr_slice, cnr_slice)
 
275
                           w - 2 * cnr_slice, cnr_slice)
279
276
        # north-east corner
280
 
        cache_corner_surface("%s-ne" % at, -(w-cnr_slice), 0)
 
277
        cache_corner_surface("%s-ne" % at, -(w - cnr_slice), 0)
281
278
        # eastern edge pattern
282
279
        cache_edge_pattern("%s-e" % at,
283
 
                           -(w-cnr_slice), -cnr_slice,
284
 
                           cnr_slice, h-2*cnr_slice)
 
280
                           -(w - cnr_slice), -cnr_slice,
 
281
                           cnr_slice, h - 2 * cnr_slice)
285
282
        # south-east corner
286
 
        cache_corner_surface("%s-se" % at, -(w-cnr_slice), -(h-cnr_slice))
 
283
        cache_corner_surface("%s-se" % at, -(w - cnr_slice), -(h - cnr_slice))
287
284
        # southern edge pattern
288
285
        cache_edge_pattern("%s-s" % at,
289
 
                           -cnr_slice, -(h-cnr_slice),
290
 
                           w-2*cnr_slice, cnr_slice)
 
286
                           -cnr_slice, -(h - cnr_slice),
 
287
                           w - 2 * cnr_slice, cnr_slice)
291
288
        # south-west corner
292
 
        cache_corner_surface("%s-sw" % at, 0, -(h-cnr_slice))
 
289
        cache_corner_surface("%s-sw" % at, 0, -(h - cnr_slice))
293
290
        # western edge pattern
294
291
        cache_edge_pattern("%s-w" % at, 0, -cnr_slice,
295
 
                           cnr_slice, h-2*cnr_slice)
 
292
                           cnr_slice, h - 2 * cnr_slice)
296
293
        # all done!
297
294
        return assets
298
295
 
300
297
        cr.save()
301
298
        self.on_draw(cr)
302
299
        cr.restore()
303
 
        return
304
300
 
305
301
    def on_draw(self, cr):
306
302
        a = self.get_allocation()
307
303
        self.render_frame(cr, a, self.BORDER_RADIUS, _frame_asset_cache)
308
304
 
309
 
        for child in self: self.propagate_draw(child, cr)
310
 
        return
 
305
        for child in self:
 
306
            self.propagate_draw(child, cr)
311
307
 
312
308
    #~ def on_draw_after(self, widget, cr, assets, layout):
313
 
        #~ if not self.show_corner_label: return
 
309
        #~ if not self.show_corner_label:
 
310
        #~     return
314
311
        #~ cr.save()
315
312
        #~ surf = assets["corner-label"]
316
313
        #~ w = surf.get_width()
320
317
        #~ # corner-label.png image...
321
318
 
322
319
        #~ # alter the to allow drawing outside of the widget bounds
323
 
        #~ cr.rectangle(-10, -10, w+4, h+4)
 
320
        #~ cr.rectangle(-10, -10, w + 4, h + 4)
324
321
        #~ cr.clip()
325
322
        #~ cr.set_source_surface(surf, -7, -8)
326
323
        #~ cr.paint()
329
326
        #~ # transalate to the visual center of the corner-label
330
327
        #~ cr.translate(19, 18)
331
328
        #~ # rotate counter-clockwise
332
 
        #~ cr.rotate(-pi*0.25)
 
329
        #~ cr.rotate(-pi * 0.25)
333
330
        #~ # paint normal markup
334
331
        #~ Gtk.render_layout(widget.get_style_context(),
335
 
                          #~ cr, -ex.width/2, -ex.height/2, layout)
 
332
                          #~ cr, -ex.width / 2, -ex.height / 2, layout)
336
333
        #~ cr.restore()
337
 
        #~ return
338
334
 
339
335
    def set_show_corner_label(self, show_label):
340
336
        if (not self.layout.get_text() and
341
 
            self.show_corner_label == show_label): return
 
337
            self.show_corner_label == show_label):
 
338
                return
342
339
        global _frame_asset_cache
343
340
        assets = _frame_asset_cache
344
341
 
349
346
 
350
347
        self.show_corner_label = show_label
351
348
        self.queue_draw()
352
 
        return
353
349
 
354
350
    #~ def set_corner_label(self, markup):
355
 
        #~ markup = '<span font_desc="12" color="white"><b>%s</b></span>' % markup
 
351
        #~ markup = ('<span font_desc="12" color="white"><b>%s</b></span>' %
 
352
        #~     markup)
356
353
        #~ self.set_show_corner_label(True)
357
354
        #~ self.layout.set_markup(markup, -1)
358
355
        #~ self.queue_draw()
359
 
        #~ return
360
356
 
361
357
    def render_frame(self, cr, a, border_radius, assets):
362
358
        # we cache as much of the drawing as possible
379
375
            # paint north length
380
376
            _cr.save()
381
377
            _cr.set_source(assets["%s-n" % at])
382
 
            _cr.rectangle(cnr_slice, 0, width-2*cnr_slice, cnr_slice)
 
378
            _cr.rectangle(cnr_slice, 0, width - 2 * cnr_slice, cnr_slice)
383
379
            _cr.clip()
384
380
            _cr.paint()
385
381
            _cr.restore()
386
382
 
387
383
            # paint north-east corner
388
384
            _cr.set_source_surface(assets["%s-ne" % at],
389
 
                                   width-cnr_slice, 0)
 
385
                                   width - cnr_slice, 0)
390
386
            _cr.paint()
391
387
 
392
388
            # paint east length
393
389
            _cr.save()
394
 
            _cr.translate(width-cnr_slice, cnr_slice)
 
390
            _cr.translate(width - cnr_slice, cnr_slice)
395
391
            _cr.set_source(assets["%s-e" % at])
396
 
            _cr.rectangle(0, 0, cnr_slice, height-2*cnr_slice)
 
392
            _cr.rectangle(0, 0, cnr_slice, height - 2 * cnr_slice)
397
393
            _cr.clip()
398
394
            _cr.paint()
399
395
            _cr.restore()
400
396
 
401
397
            # paint south-east corner
402
398
            _cr.set_source_surface(assets["%s-se" % at],
403
 
                                   width-cnr_slice,
404
 
                                   height-cnr_slice)
 
399
                                   width - cnr_slice,
 
400
                                   height - cnr_slice)
405
401
            _cr.paint()
406
402
 
407
403
            # paint south length
408
404
            _cr.save()
409
 
            _cr.translate(cnr_slice, height-cnr_slice)
 
405
            _cr.translate(cnr_slice, height - cnr_slice)
410
406
            _cr.set_source(assets["%s-s" % at])
411
 
            _cr.rectangle(0, 0, width-2*cnr_slice, cnr_slice)
 
407
            _cr.rectangle(0, 0, width - 2 * cnr_slice, cnr_slice)
412
408
            _cr.clip()
413
409
            _cr.paint()
414
410
            _cr.restore()
415
411
 
416
412
            # paint south-west corner
417
413
            _cr.set_source_surface(assets["%s-sw" % at],
418
 
                                   0, height-cnr_slice)
 
414
                                   0, height - cnr_slice)
419
415
            _cr.paint()
420
416
 
421
417
            # paint west length
422
418
            _cr.save()
423
419
            _cr.translate(0, cnr_slice)
424
420
            _cr.set_source(assets["%s-w" % at])
425
 
            _cr.rectangle(0, 0, cnr_slice, height-2*cnr_slice)
 
421
            _cr.rectangle(0, 0, cnr_slice, height - 2 * cnr_slice)
426
422
            _cr.clip()
427
423
            _cr.paint()
428
424
            _cr.restore()
429
425
 
430
426
            # fill interior
431
 
            rounded_rect(_cr, 3, 2, a.width-6, a.height-6, border_radius)
 
427
            rounded_rect(_cr, 3, 2, a.width - 6, a.height - 6, border_radius)
432
428
            context = self.get_style_context()
433
429
            bg = context.get_background_color(self.get_state_flags())
434
430
 
447
443
        # paint the cached surface and apply a rounded rect clip to
448
444
        # child draw ops
449
445
        A = self.get_allocation()
450
 
        xo, yo = a.x-A.x, a.y-A.y
 
446
        xo, yo = a.x - A.x, a.y - A.y
451
447
 
452
448
        cr.set_source_surface(self._frame_surface_cache, xo, yo)
453
449
        cr.paint()
454
450
 
455
451
        #~ rounded_rect(cr, xo+3, yo+2, a.width-6, a.height-6, border_radius)
456
452
        #~ cr.clip()
457
 
        return
458
453
 
459
454
 
460
455
class SmallBorderRadiusFrame(Frame):
462
457
    BORDER_RADIUS = 3
463
458
    ASSET_TAG = "small"
464
459
    BORDER_IMAGE = os.path.join(
465
 
        softwarecenter.paths.datadir, "ui/gtk3/art/frame-border-image-2px-border-radius.png")
 
460
        softwarecenter.paths.datadir,
 
461
        "ui/gtk3/art/frame-border-image-2px-border-radius.png")
466
462
 
467
463
    def __init__(self, padding=3):
468
464
        Frame.__init__(self, padding)
469
 
        return
470
465
 
471
466
 
472
467
class FramedBox(Frame):
473
468
 
474
 
    def __init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=0, padding=0):
 
469
    def __init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=0,
 
470
        padding=0):
475
471
        Frame.__init__(self, padding)
476
472
        self.box = Gtk.Box.new(orientation, spacing)
477
473
        Gtk.Alignment.add(self, self.box)
478
 
        return
479
474
 
480
475
    def add(self, *args, **kwargs):
481
476
        return self.box.add(*args, **kwargs)
496
491
class FramedHeaderBox(FramedBox):
497
492
 
498
493
    MARKUP = '<b>%s</b>'
499
 
    
 
494
 
500
495
    # pages for the spinner notebook
501
496
    (CONTENT,
502
497
     SPINNER) = range(2)
517
512
        # finally, a notebook for the spinner and the content box to share
518
513
        self.spinner_notebook = SpinnerNotebook(self.content_box)
519
514
        self.box.add(self.spinner_notebook)
520
 
        return
521
515
 
522
516
    def on_draw(self, cr):
523
517
        a = self.get_allocation()
525
519
        a = self.header_alignment.get_allocation()
526
520
        self.render_header(cr, a, Frame.BORDER_RADIUS, _frame_asset_cache)
527
521
 
528
 
        for child in self: self.propagate_draw(child, cr)
529
 
        return
 
522
        for child in self:
 
523
            self.propagate_draw(child, cr)
530
524
 
531
525
    def add(self, *args, **kwargs):
532
526
        return self.content_box.add(*args, **kwargs)
536
530
 
537
531
    def pack_end(self, *args, **kwargs):
538
532
        return self.content_box.pack_end(*args, **kwargs)
539
 
        
 
533
 
540
534
    # XXX: non-functional with current code...
541
535
    #~ def set_header_expand(self, expand):
542
536
        #~ alignment = self.header_alignment
564
558
            self.title.show()
565
559
 
566
560
        self.title.set_markup(self.MARKUP % label)
567
 
        return
568
561
 
569
562
    def header_implements_more_button(self):
570
563
        if not hasattr(self, "more"):
571
564
            self.more = MoreLink()
572
565
            self.header.pack_end(self.more, False, False, 0)
573
 
        return
574
566
 
575
567
    def render_header(self, cr, a, border_radius, assets):
576
568
 
596
588
                w = ta.width + StockEms.MEDIUM
597
589
 
598
590
                cr.new_sub_path()
599
 
                cr.arc(r+x, r+y, r, PI, 270*PI_OVER_180)
600
 
                cr.line_to(x+w, y)
601
 
                cr.line_to(x+w - StockEms.MEDIUM, y + h/2)
602
 
                cr.line_to(x+w, y+h)
603
 
                cr.line_to(x, y+h)
 
591
                cr.arc(r + x, r + y, r, PI, 270 * PI_OVER_180)
 
592
                cr.line_to(x + w, y)
 
593
                cr.line_to(x + w - StockEms.MEDIUM, y + h / 2)
 
594
                cr.line_to(x + w, y + h)
 
595
                cr.line_to(x, y + h)
604
596
                cr.close_path()
605
597
 
606
598
                cr.fill()
607
599
 
608
 
                cr.move_to(x+w, y)
609
 
                cr.line_to(x+w - StockEms.MEDIUM, y + h/2)
610
 
                cr.line_to(x+w, y+h)
 
600
                cr.move_to(x + w, y)
 
601
                cr.line_to(x + w - StockEms.MEDIUM, y + h / 2)
 
602
                cr.line_to(x + w, y + h)
611
603
 
612
604
            else:
613
605
                x = ta.x - a.x - StockEms.MEDIUM
614
606
                w = ta.width + StockEms.MEDIUM - 1
615
607
 
616
608
                cr.move_to(x, y)
617
 
                cr.arc(x+w-r, y+r, r, 270*PI_OVER_180, 0)
618
 
                cr.line_to(x+w, y+h)
619
 
                cr.line_to(x, y+h)
620
 
                cr.line_to(x + StockEms.MEDIUM, y + h/2)
 
609
                cr.arc(x + w - r, y + r, r, 270 * PI_OVER_180, 0)
 
610
                cr.line_to(x + w, y + h)
 
611
                cr.line_to(x, y + h)
 
612
                cr.line_to(x + StockEms.MEDIUM, y + h / 2)
621
613
                cr.close_path()
622
614
 
623
615
                cr.fill()
624
616
 
625
617
                cr.move_to(x, y)
626
 
                cr.line_to(x + StockEms.MEDIUM, y + h/2)
627
 
                cr.line_to(x, y+h)
 
618
                cr.line_to(x + StockEms.MEDIUM, y + h / 2)
 
619
                cr.line_to(x, y + h)
628
620
 
629
621
            bc = context.get_border_color(self.get_state_flags())
630
622
            Gdk.cairo_set_source_rgba(cr, bc)
634
626
            cr.restore()
635
627
 
636
628
        # paint the containers children
637
 
        for child in self: self.propagate_draw(child, cr)
638
 
        return
 
629
        for child in self:
 
630
            self.propagate_draw(child, cr)
639
631
 
640
632
 
641
633
# this is used in the automatic tests