| 1 |
|
|---|
| 2 |
import gobject |
|---|
| 3 |
import gtk |
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
class Wrapbox(gtk.Table): |
|---|
| 7 |
""" |
|---|
| 8 |
A Wrapbox contains a set of items. A wrap box tries to optimize it's |
|---|
| 9 |
content by moving elements to a second row if the do not fit on the first. |
|---|
| 10 |
And a third and a fourth, depending on the given space. |
|---|
| 11 |
|
|---|
| 12 |
The width is given, the height is changed in order to fit all contained |
|---|
| 13 |
objects. |
|---|
| 14 |
""" |
|---|
| 15 |
|
|---|
| 16 |
def __init__(self): |
|---|
| 17 |
self.__gobject_init__() |
|---|
| 18 |
self.resize_idle_id = 0 |
|---|
| 19 |
self.rows = 1 |
|---|
| 20 |
self.cols = 1 |
|---|
| 21 |
|
|---|
| 22 |
self.resize(self.rows, self.cols) |
|---|
| 23 |
|
|---|
| 24 |
self.connect('size_allocate', self.on_size_allocate) |
|---|
| 25 |
self.children = [] |
|---|
| 26 |
|
|---|
| 27 |
def calculate_size(self, allocation): |
|---|
| 28 |
children = self.children |
|---|
| 29 |
max_width = 0 |
|---|
| 30 |
for c in children: |
|---|
| 31 |
size_request = c.size_request() |
|---|
| 32 |
|
|---|
| 33 |
max_width = max(max_width, size_request[0]) |
|---|
| 34 |
cols = allocation.width / (max_width or 1) |
|---|
| 35 |
if cols == 0: |
|---|
| 36 |
cols = 1 |
|---|
| 37 |
rows = len(children) / cols |
|---|
| 38 |
if len(children) % cols: |
|---|
| 39 |
rows += 1 |
|---|
| 40 |
return cols, rows |
|---|
| 41 |
|
|---|
| 42 |
def set_new_size(self): |
|---|
| 43 |
|
|---|
| 44 |
table = self |
|---|
| 45 |
children = self.children |
|---|
| 46 |
if not children: |
|---|
| 47 |
return |
|---|
| 48 |
rows = self.rows |
|---|
| 49 |
cols = self.cols |
|---|
| 50 |
for c in children: |
|---|
| 51 |
table.remove(c) |
|---|
| 52 |
table.resize(rows, cols) |
|---|
| 53 |
x = y = 0 |
|---|
| 54 |
for c in children: |
|---|
| 55 |
table.attach(c, left_attach=x, right_attach=x+1, top_attach=y, bottom_attach=y+1) |
|---|
| 56 |
x += 1 |
|---|
| 57 |
if x == rows: |
|---|
| 58 |
x = 0 |
|---|
| 59 |
y += 1 |
|---|
| 60 |
|
|---|
| 61 |
def _idle_handler(self): |
|---|
| 62 |
try: |
|---|
| 63 |
self.set_new_size() |
|---|
| 64 |
finally: |
|---|
| 65 |
self.resize_idle_id = 0 |
|---|
| 66 |
|
|---|
| 67 |
def on_size_allocate(self, table, allocation): |
|---|
| 68 |
rows, cols = self.calculate_size(allocation) |
|---|
| 69 |
|
|---|
| 70 |
if not self.resize_idle_id and (rows != self.rows or cols != self.cols): |
|---|
| 71 |
|
|---|
| 72 |
self.resize_idle_id = gobject.idle_add(self._idle_handler) |
|---|
| 73 |
self.rows = rows |
|---|
| 74 |
self.cols = cols |
|---|
| 75 |
|
|---|
| 76 |
def add(self, widget): |
|---|
| 77 |
assert widget, 'No widget supplied: %s' % widget |
|---|
| 78 |
self.cols += 1 |
|---|
| 79 |
row = self.rows |
|---|
| 80 |
col = self.cols |
|---|
| 81 |
|
|---|
| 82 |
self.attach(widget, left_attach=col-1, right_attach=col, |
|---|
| 83 |
top_attach=row-1, bottom_attach=row) |
|---|
| 84 |
self.children.append(widget) |
|---|
| 85 |
|
|---|
| 86 |
gobject.type_register(Wrapbox) |
|---|
| 87 |
|
|---|
| 88 |
|
|---|
| 89 |
|
|---|