Ejemplo n.º 1
0
    def create_grid(self):
        """
        Setup the grid. After this function has has been called no modifications
        to the grid are possible.

        @todo: make it possible to change the layout during runtime
        """
        # do some calculations
        padding_x, padding_y = self.item_padding
        if padding_x is None:
            # no padding is given. Get the number fitting items
            # and devide the remaining space as paddingand border
            self.num_items_x = int(self.width / self.cell_size[0])
            padding_x = self.width / self.num_items_x - self.cell_size[0]
            self.item_width = self.cell_size[0] + padding_x
        else:
            self.item_width = self.cell_size[0] + padding_x
            # now that we know the sizes check how much items fit
            self.num_items_x = int(self.width / self.item_width)
        if padding_y is None:
            # no padding is given. Get the number fitting items
            # and devide the remaining space as padding and border
            self.num_items_y = int(self.height / self.cell_size[1])
            padding_y = self.height / self.num_items_y - self.cell_size[1]
            self.item_height = self.cell_size[1] + padding_y
        else:
            self.item_height = self.cell_size[1] + padding_y
            # now that we know the sizes check how much items fit
            self.num_items_y = int(self.height / self.item_height)
        self.item_padding = padding_x, padding_y
        # we now center the grid by default
        x0 = (self.width - self.num_items_x * self.item_width + padding_x) / 2
        y0 = (self.height - self.num_items_y * self.item_height +
              padding_y) / 2
        self.clip = (x0 - padding_x, y0 - padding_y), \
            (self.num_items_x * self.item_width + padding_x, self.num_items_y * self.item_height + padding_y)
        self.location = (0, 0)
        # list of rendered items
        self.item_widgets = {}
        # group of items
        self.item_group = AbstractGroup((x0, y0))
        self.add(self.item_group)
        self.create_grid = None
Ejemplo n.º 2
0
    def create_grid(self):
        """
        Setup the grid. After this function has has been called no modifications
        to the grid are possible.

        @todo: make it possible to change the layout during runtime
        """
        # do some calculations
        padding_x, padding_y = self.item_padding
        if padding_x is None:
            # no padding is given. Get the number fitting items
            # and devide the remaining space as paddingand border
            self.num_items_x = int(self.width / self.cell_size[0])
            padding_x = self.width / self.num_items_x - self.cell_size[0]
            self.item_width = self.cell_size[0] + padding_x
        else:
            self.item_width = self.cell_size[0] + padding_x
            # now that we know the sizes check how much items fit
            self.num_items_x = int(self.width / self.item_width)
        if padding_y is None:
            # no padding is given. Get the number fitting items
            # and devide the remaining space as padding and border
            self.num_items_y = int(self.height / self.cell_size[1])
            padding_y = self.height / self.num_items_y - self.cell_size[1]
            self.item_height = self.cell_size[1] + padding_y
        else:
            self.item_height = self.cell_size[1] + padding_y
            # now that we know the sizes check how much items fit
            self.num_items_y = int(self.height / self.item_height)
        self.item_padding = padding_x, padding_y
        # we now center the grid by default
        x0 = (self.width - self.num_items_x * self.item_width + padding_x) / 2
        y0 = (self.height - self.num_items_y * self.item_height + padding_y) / 2
        self.clip = (x0 - padding_x, y0 - padding_y), \
            (self.num_items_x * self.item_width + padding_x, self.num_items_y * self.item_height + padding_y)
        self.location = (0, 0)
        # list of rendered items
        self.item_widgets = {}
        # group of items
        self.item_group = AbstractGroup((x0, y0))
        self.add(self.item_group)
        self.create_grid = None
Ejemplo n.º 3
0
class Grid(AbstractGroup):
    """
    Grid holding several widgets based on the given items. The grid
    supports scrolling.
    @note: see C{test/flickr.py} for an example
    """
    candyxml_name = 'grid'

    HORIZONTAL, VERTICAL = range(2)

    __items = None

    def __init__(self, pos, size, cell_size, cell_item, items, template,
                 orientation, xpadding=None, ypadding=None, context=None):
        """
        Simple grid widget to show the items based on the template.

        @param pos: (x,y) position of the widget or None
        @param size: (width,height) geometry of the widget.
        @param cell_size: (width,height) of each cell
        @param cell_item: string how the cell item should be added to the context
        @param items: list of objects or object name in the context
        @param template: child template for each cell
        @param orientation: how to arange the grid: Grid.HORIZONTAL or Grid.VERTICAL
        @param xpadding: x value of space between two items. If set to None
            the padding will be calculated based on cell size and widget size
        @param ypadding: y value of space between two items. If set to None
            the padding will be calculated based on cell size and widget size
        @param context: the context the widget is created in
        """
        super(Grid, self).__init__(pos, size, context=context)
        # store arguments for later public use
        self.cell_size = cell_size
        # store arguments for later private use
        self.__orientation = orientation
        if isinstance(items, (str, unicode)):
            # items is a string, get it from the context
            items = self.context.get(items)
        self.items = items
        self.cell_item = cell_item
        self.template = template
        self.item_padding = xpadding, ypadding

    def create_grid(self):
        """
        Setup the grid. After this function has has been called no modifications
        to the grid are possible.

        @todo: make it possible to change the layout during runtime
        """
        # do some calculations
        padding_x, padding_y = self.item_padding
        if padding_x is None:
            # no padding is given. Get the number fitting items
            # and devide the remaining space as paddingand border
            self.num_items_x = int(self.width / self.cell_size[0])
            padding_x = self.width / self.num_items_x - self.cell_size[0]
            self.item_width = self.cell_size[0] + padding_x
        else:
            self.item_width = self.cell_size[0] + padding_x
            # now that we know the sizes check how much items fit
            self.num_items_x = int(self.width / self.item_width)
        if padding_y is None:
            # no padding is given. Get the number fitting items
            # and devide the remaining space as padding and border
            self.num_items_y = int(self.height / self.cell_size[1])
            padding_y = self.height / self.num_items_y - self.cell_size[1]
            self.item_height = self.cell_size[1] + padding_y
        else:
            self.item_height = self.cell_size[1] + padding_y
            # now that we know the sizes check how much items fit
            self.num_items_y = int(self.height / self.item_height)
        self.item_padding = padding_x, padding_y
        # we now center the grid by default
        x0 = (self.width - self.num_items_x * self.item_width + padding_x) / 2
        y0 = (self.height - self.num_items_y * self.item_height + padding_y) / 2
        self.clip = (x0 - padding_x, y0 - padding_y), \
            (self.num_items_x * self.item_width + padding_x, self.num_items_y * self.item_height + padding_y)
        self.location = (0, 0)
        # list of rendered items
        self.item_widgets = {}
        # group of items
        self.item_group = AbstractGroup((x0, y0))
        self.add(self.item_group)
        self.create_grid = None

    def create_item(self, item_num, pos_x, pos_y):
        """
        Render one child
        """
        if item_num < 0 or item_num >= len(self.items):
            self.item_widgets[(pos_x, pos_y)] = None
            return
        # calculate the size where the child should be
        child_x = pos_x * self.item_width
        child_y = pos_y * self.item_height
        context = self.context.copy()
        context[self.cell_item] = self.items[item_num]
        child = self.template(context=context)
        child.x = child_x
        child.y = child_y
        child.width, child.height = self.cell_size
        self.item_group.add(child)
        self.item_widgets[(pos_x, pos_y)] = child
        return child

    def clear(self):
        """
        Clear the grid
        """
        self.item_group.clear()
        self.item_widgets = {}
        self.queue_rendering()

    def sync_prepare(self):
        """
        Prepare widget for the next sync with the backend
        """
        if self.create_grid:
            self.create_grid()
        if not super(Grid, self).sync_prepare():
            return False
        if self.__orientation == Grid.VERTICAL:
            max_x, max_y = self.location
            for y in range(0, max_y + self.num_items_y):
                for x in range(0, max_x + self.num_items_x):
                    item_num = x + y * self.num_items_x
                    if not (x, y) in self.item_widgets:
                        self.create_item(item_num, x, y)
        if self.__orientation == Grid.HORIZONTAL:
            max_x, max_y = self.location
            for x in range(0, max_x + self.num_items_x):
                for y in range(0, max_y + self.num_items_y):
                    item_num = x * self.num_items_y + y
                    if not (x, y) in self.item_widgets:
                        self.create_item(item_num, x, y)
        return super(Grid, self).sync_prepare()

    def sync_context(self):
        """
        Adjust to a new context. Note: the context of the children is
        not synced. If required the grid must be cleared first. This
        may be fixed in future versions of this widget.
        """
        self.items = self.__items_provided

    @property
    def items(self):
        """
        Get list of items
        """
        return self.__items

    @items.setter
    def items(self, items):
        """
        Set list of items
        """
        self.__items_provided = items
        if isinstance(items, (str, unicode)):
            # items is a string, get it from the context
            items = self.context.get(items)
        if self.__items != items:
            if self.__items:
                # we already had a valid list of items. Set the new
                # list of items before clearing in case an inherting
                # class already needs it on clear
                self.__items = items
                self.clear()
            self.__items = items

    @kaa.synchronized()
    def scroll_by(self, (x, y), secs, force=False):
Ejemplo n.º 4
0
class Grid(AbstractGroup):
    """
    Grid holding several widgets based on the given items. The grid
    supports scrolling.
    @note: see C{test/flickr.py} for an example
    """
    candyxml_name = 'grid'

    HORIZONTAL, VERTICAL = range(2)

    __items = None

    def __init__(self,
                 pos,
                 size,
                 cell_size,
                 cell_item,
                 items,
                 template,
                 orientation,
                 xpadding=None,
                 ypadding=None,
                 context=None):
        """
        Simple grid widget to show the items based on the template.

        @param pos: (x,y) position of the widget or None
        @param size: (width,height) geometry of the widget.
        @param cell_size: (width,height) of each cell
        @param cell_item: string how the cell item should be added to the context
        @param items: list of objects or object name in the context
        @param template: child template for each cell
        @param orientation: how to arange the grid: Grid.HORIZONTAL or Grid.VERTICAL
        @param xpadding: x value of space between two items. If set to None
            the padding will be calculated based on cell size and widget size
        @param ypadding: y value of space between two items. If set to None
            the padding will be calculated based on cell size and widget size
        @param context: the context the widget is created in
        """
        super(Grid, self).__init__(pos, size, context=context)
        # store arguments for later public use
        self.cell_size = cell_size
        # store arguments for later private use
        self.__orientation = orientation
        if isinstance(items, (str, unicode)):
            # items is a string, get it from the context
            items = self.context.get(items)
        self.items = items
        self.cell_item = cell_item
        self.template = template
        self.item_padding = xpadding, ypadding

    def create_grid(self):
        """
        Setup the grid. After this function has has been called no modifications
        to the grid are possible.

        @todo: make it possible to change the layout during runtime
        """
        # do some calculations
        padding_x, padding_y = self.item_padding
        if padding_x is None:
            # no padding is given. Get the number fitting items
            # and devide the remaining space as paddingand border
            self.num_items_x = int(self.width / self.cell_size[0])
            padding_x = self.width / self.num_items_x - self.cell_size[0]
            self.item_width = self.cell_size[0] + padding_x
        else:
            self.item_width = self.cell_size[0] + padding_x
            # now that we know the sizes check how much items fit
            self.num_items_x = int(self.width / self.item_width)
        if padding_y is None:
            # no padding is given. Get the number fitting items
            # and devide the remaining space as padding and border
            self.num_items_y = int(self.height / self.cell_size[1])
            padding_y = self.height / self.num_items_y - self.cell_size[1]
            self.item_height = self.cell_size[1] + padding_y
        else:
            self.item_height = self.cell_size[1] + padding_y
            # now that we know the sizes check how much items fit
            self.num_items_y = int(self.height / self.item_height)
        self.item_padding = padding_x, padding_y
        # we now center the grid by default
        x0 = (self.width - self.num_items_x * self.item_width + padding_x) / 2
        y0 = (self.height - self.num_items_y * self.item_height +
              padding_y) / 2
        self.clip = (x0 - padding_x, y0 - padding_y), \
            (self.num_items_x * self.item_width + padding_x, self.num_items_y * self.item_height + padding_y)
        self.location = (0, 0)
        # list of rendered items
        self.item_widgets = {}
        # group of items
        self.item_group = AbstractGroup((x0, y0))
        self.add(self.item_group)
        self.create_grid = None

    def create_item(self, item_num, pos_x, pos_y):
        """
        Render one child
        """
        if item_num < 0 or item_num >= len(self.items):
            self.item_widgets[(pos_x, pos_y)] = None
            return
        # calculate the size where the child should be
        child_x = pos_x * self.item_width
        child_y = pos_y * self.item_height
        context = self.context.copy()
        context[self.cell_item] = self.items[item_num]
        child = self.template(context=context)
        child.x = child_x
        child.y = child_y
        child.width, child.height = self.cell_size
        self.item_group.add(child)
        self.item_widgets[(pos_x, pos_y)] = child
        return child

    def clear(self):
        """
        Clear the grid
        """
        self.item_group.clear()
        self.item_widgets = {}
        self.queue_rendering()

    def sync_prepare(self):
        """
        Prepare widget for the next sync with the backend
        """
        if self.create_grid:
            self.create_grid()
        if not super(Grid, self).sync_prepare():
            return False
        if self.__orientation == Grid.VERTICAL:
            max_x, max_y = self.location
            for y in range(0, max_y + self.num_items_y):
                for x in range(0, max_x + self.num_items_x):
                    item_num = x + y * self.num_items_x
                    if not (x, y) in self.item_widgets:
                        self.create_item(item_num, x, y)
        if self.__orientation == Grid.HORIZONTAL:
            max_x, max_y = self.location
            for x in range(0, max_x + self.num_items_x):
                for y in range(0, max_y + self.num_items_y):
                    item_num = x * self.num_items_y + y
                    if not (x, y) in self.item_widgets:
                        self.create_item(item_num, x, y)
        return super(Grid, self).sync_prepare()

    def sync_context(self):
        """
        Adjust to a new context. Note: the context of the children is
        not synced. If required the grid must be cleared first. This
        may be fixed in future versions of this widget.
        """
        self.items = self.__items_provided

    @property
    def items(self):
        """
        Get list of items
        """
        return self.__items

    @items.setter
    def items(self, items):
        """
        Set list of items
        """
        self.__items_provided = items
        if isinstance(items, (str, unicode)):
            # items is a string, get it from the context
            items = self.context.get(items)
        if self.__items != items:
            if self.__items:
                # we already had a valid list of items. Set the new
                # list of items before clearing in case an inherting
                # class already needs it on clear
                self.__items = items
                self.clear()
            self.__items = items

    @kaa.synchronized()
    def scroll_by(self, (x, y), secs, force=False):