[pyclutter] examples: Add layout manager example
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pyclutter] examples: Add layout manager example
- Date: Tue, 14 Apr 2015 11:54:31 +0000 (UTC)
commit ceccf2b65a4646f00b9ee4b5fa5295528dc9863d
Author: Emmanuele Bassi <ebassi gnome org>
Date: Tue Apr 14 12:27:11 2015 +0100
examples: Add layout manager example
examples/Makefile.am | 1 +
examples/layout-manager.py | 234 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 235 insertions(+), 0 deletions(-)
---
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 163d1fa..241cb83 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -1,4 +1,5 @@
EXTRA_DIST = \
basic-actor.py \
constraints.py \
+ layout-manager.py \
rounded-rectangle.py
diff --git a/examples/layout-manager.py b/examples/layout-manager.py
new file mode 100644
index 0000000..79562f6
--- /dev/null
+++ b/examples/layout-manager.py
@@ -0,0 +1,234 @@
+import math
+
+from gi.repository import GObject
+from gi.repository import Clutter
+
+class MultiLayout(Clutter.LayoutManager):
+ GRID = 0
+ CIRCLE = 1
+
+ def __init__(self):
+ Clutter.LayoutManager.__init__(self)
+ self._state = MultiLayout.GRID
+ self._spacing = 0
+ self._cell_width = -1
+ self._cell_height = -1
+
+ @GObject.Property(type=int)
+ def state(self):
+ return self._state
+
+ @state.setter
+ def state(self, value):
+ if self._state != value:
+ self._state = value
+ self.layout_changed()
+
+ @GObject.Property(type=int)
+ def spacing(self):
+ return self._spacing
+
+ @spacing.setter
+ def spacing(self, value):
+ if self._spacing != value:
+ self._spacing = value
+ self.layout_changed()
+
+ def do_get_preferred_width(self, actor, for_height):
+ minimum = 0
+ natural = 0
+ max_natural = 0
+ n_children = 0
+
+ for child in actor:
+ if not child.props.visible:
+ continue
+
+ min_w, nat_w = child.get_preferred_width(-1)
+ max_natural = max(max_natural, nat_w)
+
+ if self._state == MultiLayout.GRID:
+ minimum += min_w
+ natural += nat_w
+ elif self._state == MultiLayout.CIRCLE:
+ minimum = max(minimum, min_w)
+ natural = max(natural, nat_w)
+
+ n_children += 1
+
+ self._cell_width = max_natural
+
+ minimum += (self._spacing * (n_children - 1))
+ natural += (self._spacing * (n_children - 1))
+
+ return (minimum, natural)
+
+ def do_get_preferred_height(self, actor, for_width):
+ minimum = 0
+ natural = 0
+ max_natural = 0
+ n_children = 0
+
+ for child in actor:
+ if not child.props.visible:
+ continue
+
+ min_h, nat_h = child.get_preferred_height(-1)
+ max_natural = max(max_natural, nat_h)
+
+ if self._state == MultiLayout.GRID:
+ minimum += min_h
+ natural += nat_h
+ elif self._state == MultiLayout.CIRCLE:
+ minimum = max(minimum, min_h)
+ natural = max(natural, nat_h)
+
+ n_children += 1
+
+ self._cell_height = max_natural
+
+ minimum += (self._spacing * (n_children - 1))
+ natural += (self._spacing * (n_children - 1))
+
+ return (minimum, natural)
+
+ def _get_items_per_row(self, for_width):
+ if for_width < 0:
+ return 1
+
+ if self._cell_width <= 0:
+ return 1
+
+ n_columns = int((for_width + self._spacing) / (self._cell_width + self._spacing))
+
+ return max(n_columns, 1)
+
+ def do_allocate(self, actor, allocation, flags):
+ def get_visible_children(actor):
+ n_visible_children = 0
+ for child in actor:
+ if not child.props.visible:
+ continue
+ n_visible_children += 1
+
+ return n_visible_children
+
+ n_items = get_visible_children(actor)
+ if n_items == 0:
+ return
+
+ x_offset, y_offset = allocation.get_origin()
+ avail_width, avail_height = allocation.get_size()
+
+ self.do_get_preferred_width(actor, avail_width)
+ self.do_get_preferred_height(actor, avail_height)
+
+ item_index = 0
+ n_items_per_row = 0
+ center = Clutter.Point()
+ radius = 0
+ if self._state == MultiLayout.GRID:
+ n_items_per_row = self._get_items_per_row(avail_width)
+ item_x = x_offset
+ item_y = y_offset
+ elif self._state == MultiLayout.CIRCLE:
+ radius = min((avail_width - self._cell_width) / 2, (avail_height - self._cell_height) / 2)
+ center.x = allocation.x2 / 2
+ center.y = allocation.y2 / 2
+
+ for child in actor:
+ child_alloc = Clutter.ActorBox()
+
+ if self._state == MultiLayout.GRID:
+ if item_index == n_items_per_row:
+ item_index = 0
+ item_x = x_offset
+ item_y += self._cell_height + self._spacing
+
+ child_alloc.x1 = item_x
+ child_alloc.y1 = item_y
+ item_x += self._cell_width + self._spacing
+ elif self._state == MultiLayout.CIRCLE:
+ theta = 2.0 * math.pi / n_items * item_index
+ child_alloc.x1 = center.x + radius * math.sin(theta) - (self._cell_width / 2)
+ child_alloc.y1 = center.y + radius * math.cos(theta) - (self._cell_height / 2)
+
+ child_alloc.x2 = child_alloc.x1 + self._cell_width
+ child_alloc.y2 = child_alloc.y1 + self._cell_height
+
+ child.allocate(child_alloc, flags)
+
+ item_index += 1
+
+def on_enter(actor, event):
+ actor.set_scale(1.2, 1.2)
+ return True
+
+def on_leave(actor, event):
+ actor.set_scale(1.0, 1.0)
+ return True
+
+def on_key_press(stage, event, layout):
+ key = event.keyval
+ if key == Clutter.KEY_q:
+ Clutter.main_quit()
+ return True
+
+ if key == Clutter.KEY_t:
+ if layout.state == MultiLayout.GRID:
+ layout.state = MultiLayout.CIRCLE
+ elif layout.state == MultiLayout.CIRCLE:
+ layout.state = MultiLayout.GRID
+ return True
+
+ return False
+
+if __name__ == '__main__':
+ stage = Clutter.Stage()
+ stage.props.title = 'Multi-layout'
+ stage.connect('destroy', Clutter.main_quit)
+ stage.show()
+
+ N_RECTS = 16
+ RECT_SIZE = 64
+ N_ROWS = 4
+ PADDING = 12
+ BOX_SIZE = (RECT_SIZE * (N_RECTS / N_ROWS) + PADDING * (N_RECTS / N_ROWS - 1))
+
+ layout = MultiLayout()
+ layout.spacing = PADDING
+ box = Clutter.Actor(layout_manager=layout, width=BOX_SIZE, height=BOX_SIZE)
+ box.set_margin(Clutter.Margin(PADDING))
+ box.add_constraint(Clutter.AlignConstraint(source=stage, align_axis=Clutter.AlignAxis.BOTH, factor=0.5))
+ stage.add_child(box)
+
+ for i in range(N_RECTS):
+ color = Clutter.Color.from_hls(360 / N_RECTS * i, 0.5, 0.8)
+ color.alpha = 128 + 128 / N_RECTS * i
+
+ rect = Clutter.Actor()
+ rect.props.background_color = color
+ rect.props.opacity = 0
+ rect.props.reactive = True
+ rect.set_size(RECT_SIZE, RECT_SIZE)
+ rect.set_pivot_point(0.5, 0.5)
+ rect.set_easing_duration(250)
+ rect.set_easing_mode(Clutter.AnimationMode.EASE_OUT_CUBIC)
+ box.add_child(rect)
+
+ transition = Clutter.PropertyTransition(property_name='opacity', duration=250, delay=i*50)
+ transition.set_from(0)
+ transition.set_to(color.alpha)
+ rect.add_transition('fadeIn', transition)
+
+ rect.connect('enter-event', on_enter)
+ rect.connect('leave-event', on_leave)
+
+ label = Clutter.Text(text="Press t → Toggle layout\nPress q → Quit")
+ label.add_constraint(Clutter.AlignConstraint(source=stage, align_axis=Clutter.AlignAxis.X_AXIS,
factor=0.50))
+ label.add_constraint(Clutter.AlignConstraint(source=stage, align_axis=Clutter.AlignAxis.Y_AXIS,
factor=0.95))
+ stage.add_child(label)
+
+ stage.connect('key-press-event', on_key_press, layout)
+
+ Clutter.main()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]