Ejemplo n.º 1
0
class WidgetPlaceholder(delegate_to_widget_mixin('_original_widget'),
                        WidgetDecoration):
    """
    This is a do-nothing decoration widget that can be used for swapping
    between widgets without modifying the container of this widget.

    This can be useful for making an interface with a number of distinct
    pages or for showing and hiding menu or status bars.

    The widget displayed is stored as a .original_widget property and
    can be changed by assigning a new widget to it.
    """
    pass
Ejemplo n.º 2
0
class PopUpLauncher(delegate_to_widget_mixin('_original_widget'),
                    WidgetDecoration):
    def __init__(self, original_widget):
        self.__super.__init__(original_widget)
        self._pop_up_widget = None

    def create_pop_up(self):
        """
        Subclass must override this method and have is return a widget
        to be used for the pop-up.  This method is called once each time
        the pop-up is opened.
        """
        raise NotImplementedError("Subclass must override this method")

    def get_pop_up_parameters(self):
        """
        Subclass must override this method and have it return a dict, eg:

        {'left':0, 'top':1, 'overlay_width':30, 'overlay_height':4}

        This method is called each time this widget is rendered.
        """
        raise NotImplementedError("Subclass must override this method")

    def open_pop_up(self):
        self._pop_up_widget = self.create_pop_up()
        self._invalidate()

    def close_pop_up(self):
        self._pop_up_widget = None
        self._invalidate()

    def render(self, size, focus=False):
        canv = self.__super.render(size, focus)
        if self._pop_up_widget:
            canv = CompositeCanvas(canv)
            canv.set_pop_up(self._pop_up_widget,
                            **self.get_pop_up_parameters())
        return canv
Ejemplo n.º 3
0
class AttrMap(delegate_to_widget_mixin('_original_widget'), WidgetDecoration):
    """
    AttrMap is a decoration that maps one set of attributes to another for
    a FlowWidget or BoxWidget
    """
    def __init__(self, w, attr_map, focus_map=None):
        """
        w -- widget to wrap (stored as self.original_widget)
        attr_map -- attribute to apply to w, or dictionary of attribute mappings
        focus_map -- attribute to apply when in focus or dictionary of
            attribute mappings, if None use attr

        This object will pass all function calls and variable references
        to the wrapped widget.

        >>> AttrMap(Divider(u"!"), 'bright')
        <AttrMap flow widget <Divider flow widget '!'> attr_map={None: 'bright'}>
        >>> AttrMap(Edit(), 'notfocus', 'focus')
        <AttrMap selectable flow widget <Edit selectable flow widget '' edit_pos=0> attr_map={None: 'notfocus'} focus_map={None: 'focus'}>
        >>> size = (5,)
        >>> am = AttrMap(Text(u"hi"), 'greeting', 'fgreet')
        >>> am.render(size, focus=False).content().next() # ... = b in Python 3
        [('greeting', None, ...'hi   ')]
        >>> am.render(size, focus=True).content().next()
        [('fgreet', None, ...'hi   ')]
        >>> am2 = AttrMap(Text(('word', u"hi")), {'word':'greeting', None:'bg'})
        >>> am2
        <AttrMap flow widget <Text flow widget 'hi'> attr_map={'word': 'greeting', None: 'bg'}>
        >>> am2.render(size).content().next()
        [('greeting', None, ...'hi'), ('bg', None, ...'   ')]
        """
        self.__super.__init__(w)

        if type(attr_map) != dict:
            self.set_attr_map({None: attr_map})
        else:
            self.set_attr_map(attr_map)

        if focus_map is not None and type(focus_map) != dict:
            self.set_focus_map({None: focus_map})
        else:
            self.set_focus_map(focus_map)

    def _repr_attrs(self):
        # only include the focus_attr when it takes effect (not None)
        d = dict(self.__super._repr_attrs(), attr_map=self._attr_map)
        if self._focus_map is not None:
            d['focus_map'] = self._focus_map
        return d

    def get_attr_map(self):
        # make a copy so ours is not accidentally modified
        # FIXME: a dictionary that detects modifications would be better
        return dict(self._attr_map)

    def set_attr_map(self, attr_map):
        """
        Set the attribute mapping dictionary {from_attr: to_attr, ...}

        Note this function does not accept a single attribute the way the
        constructor does.  You must specify {None: attribute} instead.

        >> w = AttrMap(Text("hi"), None)
        >> w.set_attr({'a':'b'})
        >> w
        <AttrMap flow widget <Text flow widget 'hi'> attr_map={'a': 'b'}>
        """
        for from_attr, to_attr in attr_map.items():
            if not from_attr.__hash__ or not to_attr.__hash__:
                raise AttrMapError("%r:%r attribute mapping is invalid.  "
                                   "Attributes must be hashable" %
                                   (from_attr, to_attr))
        self._attr_map = attr_map
        self._invalidate()

    attr_map = property(get_attr_map, set_attr_map)

    def get_focus_map(self):
        # make a copy so ours is not accidentally modified
        # FIXME: a dictionary that detects modifications would be better
        if self._focus_map:
            return dict(self._focus_map)

    def set_focus_map(self, focus_map):
        """
        Set the focus attribute mapping dictionary 
        {from_attr: to_attr, ...}
        
        If None this widget will use the attr mapping instead (no change 
        when in focus).
        
        Note this function does not accept a single attribute the way the
        constructor does.  You must specify {None: attribute} instead.

        >> w = AttrMap(Text("hi"), {})
        >> w.set_focus_map({'a':'b'})
        >> w
        <AttrMap flow widget <Text flow widget 'hi'> attr_map={} focus_map={'a': 'b'}>
        >> w.set_focus_map(None)
        >> w
        <AttrMap flow widget <Text flow widget 'hi'> attr_map={}>
        """
        if focus_map is not None:
            for from_attr, to_attr in focus_map.items():
                if not from_attr.__hash__ or not to_attr.__hash__:
                    raise AttrMapError("%r:%r attribute mapping is invalid.  "
                                       "Attributes must be hashable" %
                                       (from_attr, to_attr))
        self._focus_map = focus_map
        self._invalidate()

    focus_map = property(get_focus_map, set_focus_map)

    def render(self, size, focus=False):
        """
        Render wrapped widget and apply attribute. Return canvas.
        """
        attr_map = self._attr_map
        if focus and self._focus_map is not None:
            attr_map = self._focus_map
        canv = self._original_widget.render(size, focus=focus)
        canv = CompositeCanvas(canv)
        canv.fill_attr_apply(attr_map)
        return canv