예제 #1
0
    def __setattr__(self, name, val):
        if name == "tab_spacing":
            self.tabs_container.spacing = val
        else:
            if name == "current_page":
                val = self.find_page(val)

            if self.__dict__.get(name, "hamster_graphics_no_value_really") == val:
                return
            Box.__setattr__(self, name, val)

            if name == "tab_position" and hasattr(self, "tabs_container"):
                self.tabs_container.x = 0
                self._position_contents()

            elif name == "scroll_position":
                # reorder sprites based on scroll position
                if val == "start":
                    sprites = [self.before_tabs, self.tabs_back, self.tabs_forward, self._tabs_viewport, self.after_tabs]
                elif val == "end":
                    sprites = [self.before_tabs, self._tabs_viewport, self.tabs_back, self.tabs_forward, self.after_tabs]
                else:
                    sprites = [self.before_tabs, self.tabs_back, self._tabs_viewport, self.tabs_forward, self.after_tabs]
                self.tabbox.sprites = sprites
            elif name == "current_page":
                self._select_current_page()
예제 #2
0
    def resize_children(self):
        Box.resize_children(self)

        pos = self.tab_position
        horizontal = pos.startswith("right") or pos.startswith("left")
        if horizontal:
            self.tabbox.alloc_w, self.tabbox.alloc_h = self.tabbox.alloc_h, self.tabbox.alloc_w

        if pos.startswith("right"):
            self.tabbox.x += self.tabbox.height
        elif pos.startswith("left"):
            self.tabbox.y += self.tabbox.width

        # show/hide thes croll buttons
        # doing it here to avoid recursion as changing visibility calls parent resize
        self.tabs_back.visible = self.tabs_forward.visible = self.show_scroll in (
            True, "auto_invisible")
        self.tabbox.resize_children()
        self.tabs_container.resize_children()

        if self.show_scroll == "auto_invisible":
            self.tabs_back.visible = self.tabs_forward.visible = True
            if self.tabs_container.width < self._tabs_viewport.width:
                self.tabs_back.opacity = self.tabs_forward.opacity = 0
            else:
                self.tabs_back.opacity = self.tabs_forward.opacity = 1

        else:
            self.tabs_back.opacity = self.tabs_forward.opacity = 1
            self.tabs_back.visible = self.tabs_forward.visible = self.show_scroll is True or \
                                                                (self.show_scroll == "auto" and \
                                                                 self.tabs_container.width > self._tabs_viewport.width)

        self.tabbox.resize_children()
        self._position_tabs()
예제 #3
0
    def __init__(self, contents = None, padding = 1, horizontal = False, owner = None,
                 open_on_hover = None, spacing = 0, hide_on_leave = False, hide_on_interstitial = False,
                 disable_toggling = False, **kwargs):
        Box.__init__(self, contents = contents, padding = padding, horizontal = horizontal, spacing = spacing, **kwargs)
        self.expand, self.expand_vert = False, False
        self.x_align = 0

        #: in case of a sub menu - a menu item that this menu belongs to
        self.owner = owner

        #: if specified, will open submenus menu after cursor has been over the item for the specified seconds
        self.open_on_hover = open_on_hover

        #: if set, will hide the menu when mouse moves out. defaults to False
        self._hide_on_leave = hide_on_leave

        #: if set, will hide the menu when mouse moves between menuitems.  defaults to False
        self._hide_on_interstitial = hide_on_interstitial

        #: if set, clicking on menu items with submenus will only show them instead of toggling
        #: this way the menu becomes more persistent
        self.disable_toggling = disable_toggling

        self._toggled = False
        self._scene_mouse_down = None
        self._scene_mouse_move = None
        self._scene_key_press = None
        self._echo = False

        self._timeout = None
        self.connect("on-render", self.__on_render)
        self.connect("on-mouse-down", self.__on_mouse_down)
        self.interactive = True
예제 #4
0
 def add_child(self, *sprites):
     for sprite in sprites:
         Box.add_child(self, sprite)
         self.connect_child(sprite, "on-click", self.on_item_click)
         self.connect_child(sprite, "on-mouse-down", self.on_item_mouse_down)
         self.connect_child(sprite, "on-mouse-over", self.on_item_mouse_over)
         self.connect_child(sprite, "on-mouse-out", self.on_item_mouse_out)
     self.resize_children()
예제 #5
0
    def __init__(self,
                 horizontal=False,
                 thickness=None,
                 size=0,
                 offset=0,
                 **kwargs):
        Box.__init__(self, **kwargs)
        self.interactive, self.cursor = True, False

        self.spacing = 0

        self.thickness = thickness if thickness else self.thickness

        #: whether the scroll bar is vertical or horizontal
        self.orient_horizontal = horizontal

        #: width of the bar in pixels
        self.size = size

        #: scroll position in range 0..1
        self.offset = offset

        if horizontal:
            self.expand_vert = False
            self.min_height = thickness
        else:
            self.expand = False
            self.min_width = thickness

        #: slider container
        self.slider_zone = Widget()

        #: slider widget
        self.slider = ScrollBarSlider()
        self.slider_zone.add_child(self.slider)

        #: the scroll up button
        self.up = ScrollBarButton(
            direction="left" if self.orient_horizontal else "up")

        #: the scroll down button
        self.down = ScrollBarButton(
            direction="right" if self.orient_horizontal else "down")

        self.add_child(self.up, self.slider_zone, self.down)

        self._timeout = None

        for button in (self.up, self.down):
            self.connect_child(button, "on-mouse-down",
                               self.on_scrollbutton_pressed)
            self.connect_child(button, "on-mouse-up",
                               self.on_scrollbutton_released)
            self.connect_child(button, "on-mouse-out",
                               self.on_scrollbutton_released)

        self.connect_child(self.slider, "on-drag", self.on_slider_drag)
        self.connect("on-click", self.on_click)
예제 #6
0
 def add_child(self, *sprites):
     for sprite in sprites:
         Box.add_child(self, sprite)
         self.connect_child(sprite, "on-click", self.on_item_click)
         self.connect_child(sprite, "on-mouse-down",
                            self.on_item_mouse_down)
         self.connect_child(sprite, "on-mouse-over",
                            self.on_item_mouse_over)
         self.connect_child(sprite, "on-mouse-out", self.on_item_mouse_out)
     self.resize_children()
예제 #7
0
    def __setattr__(self, name, val):
        if self.__dict__.get(name, "hamster_graphics_no_value_really") == val:
            return

        Box.__setattr__(self, name, val)

        if name == "orient_horizontal" and hasattr(self, "up"):
            self.up.direction = "left" if val else "up"
            self.down.direction = "right" if val else "down"
        elif name == "size" and hasattr(self, "slider"):
            self._size_slider()
        elif name == "offset" and hasattr(self, "slider_zone"):
            self._position_slider()
예제 #8
0
    def __setattr__(self, name, val):
        if self.__dict__.get(name, "hamster_graphics_no_value_really") == val:
            return

        Box.__setattr__(self, name, val)

        if name == "orient_horizontal" and hasattr(self, "up"):
            self.up.direction="left" if val else "up"
            self.down.direction="right" if val else "down"
        elif name == "size" and hasattr(self, "slider"):
            self._size_slider()
        elif name == "offset" and hasattr(self, "slider_zone"):
            self._position_slider()
예제 #9
0
    def __init__(self,
                 text="",
                 markup="",
                 spacing=5,
                 image=None,
                 image_position=None,
                 size=None,
                 font_desc=None,
                 overflow=False,
                 color="#000",
                 background_color=None,
                 **kwargs):

        # TODO - am initiating table with fill = false but that yields suboptimal label placement and the 0,0 points to whatever parent gave us
        Bin.__init__(self, **kwargs)

        #: image to put next to the label
        self.image = image

        # the actual container that contains the label and/or image
        self.container = Box(spacing=spacing,
                             fill=False,
                             x_align=self.x_align,
                             y_align=self.y_align)

        if image_position is not None:
            self.image_position = image_position

        self.display_label = _DisplayLabel(text=text,
                                           markup=markup,
                                           color=color,
                                           size=size)
        self.display_label.x_align = 0  # the default is 0.5 which makes label align incorrectly on wrapping

        if font_desc or self.font_desc:
            self.display_label.font_desc = font_desc or self.font_desc

        self.display_label.size = size or self.size

        self.background_color = background_color

        #: either the pango `wrap <http://www.pygtk.org/pygtk2reference/pango-constants.html#pango-wrap-mode-constants>`_
        #: or `ellipsize <http://www.pygtk.org/pygtk2reference/pango-constants.html#pango-ellipsize-mode-constants>`_ constant.
        #: if set to False will refuse to become smaller
        self.overflow = overflow

        self.add_child(self.container)

        self._position_contents()
        self.connect_after("on-render", self.__on_render)
예제 #10
0
    def __init__(self, horizontal = False, thickness = None, size = 0, offset = 0, **kwargs):
        Box.__init__(self, **kwargs)
        self.interactive, self.cursor = True, False

        self.spacing = 0

        self.thickness = thickness if thickness else self.thickness

        #: whether the scroll bar is vertical or horizontal
        self.orient_horizontal = horizontal

        #: width of the bar in pixels
        self.size = size

        #: scroll position in range 0..1
        self.offset = offset

        if horizontal:
            self.expand_vert = False
            self.min_height = thickness
        else:
            self.expand = False
            self.min_width = thickness

        #: slider container
        self.slider_zone = Widget()

        #: slider widget
        self.slider = ScrollBarSlider()
        self.slider_zone.add_child(self.slider)

        #: the scroll up button
        self.up = ScrollBarButton(direction="left" if self.orient_horizontal else "up")

        #: the scroll down button
        self.down = ScrollBarButton(direction="right" if self.orient_horizontal else "down")

        self.add_child(self.up, self.slider_zone, self.down)

        self._timeout = None

        for button in (self.up, self.down):
            self.connect_child(button, "on-mouse-down", self.on_scrollbutton_pressed)
            self.connect_child(button, "on-mouse-up", self.on_scrollbutton_released)
            self.connect_child(button, "on-mouse-out", self.on_scrollbutton_released)

        self.connect_child(self.slider, "on-drag", self.on_slider_drag)
        self.connect("on-click", self.on_click)
예제 #11
0
 def get_min_size(self):
     w, h = Box.get_min_size(self)
     if self.orient_horizontal:
         return w, h
     else:
         # for vertical ones give place to the submenu indicator
         return w + 8, h
예제 #12
0
 def get_min_size(self):
     w, h = Box.get_min_size(self)
     if self.orient_horizontal:
         return w, h
     else:
         # for vertical ones give place to the submenu indicator
         return w + 8, h
예제 #13
0
    def __init__(self,
                 contents=None,
                 padding=1,
                 horizontal=False,
                 owner=None,
                 open_on_hover=None,
                 spacing=0,
                 hide_on_leave=False,
                 hide_on_interstitial=False,
                 disable_toggling=False,
                 **kwargs):
        Box.__init__(self,
                     contents=contents,
                     padding=padding,
                     horizontal=horizontal,
                     spacing=spacing,
                     **kwargs)
        self.expand, self.expand_vert = False, False
        self.x_align = 0

        #: in case of a sub menu - a menu item that this menu belongs to
        self.owner = owner

        #: if specified, will open submenus menu after cursor has been over the item for the specified seconds
        self.open_on_hover = open_on_hover

        #: if set, will hide the menu when mouse moves out. defaults to False
        self._hide_on_leave = hide_on_leave

        #: if set, will hide the menu when mouse moves between menuitems.  defaults to False
        self._hide_on_interstitial = hide_on_interstitial

        #: if set, clicking on menu items with submenus will only show them instead of toggling
        #: this way the menu becomes more persistent
        self.disable_toggling = disable_toggling

        self._toggled = False
        self._scene_mouse_down = None
        self._scene_mouse_move = None
        self._scene_key_press = None
        self._echo = False

        self._timeout = None
        self.connect("on-render", self.__on_render)
        self.connect("on-mouse-down", self.__on_mouse_down)
        self.interactive = True
예제 #14
0
    def __setattr__(self, name, val):
        if name == "tab_spacing":
            self.tabs_container.spacing = val
        else:
            if name == "current_page":
                val = self.find_page(val)

            if self.__dict__.get(name,
                                 "hamster_graphics_no_value_really") == val:
                return
            Box.__setattr__(self, name, val)

            if name == "tab_position" and hasattr(self, "tabs_container"):
                self.tabs_container.x = 0
                self._position_contents()

            elif name == "scroll_position":
                # reorder sprites based on scroll position
                if val == "start":
                    sprites = [
                        self.before_tabs, self.tabs_back, self.tabs_forward,
                        self._tabs_viewport, self.after_tabs
                    ]
                elif val == "end":
                    sprites = [
                        self.before_tabs, self._tabs_viewport, self.tabs_back,
                        self.tabs_forward, self.after_tabs
                    ]
                else:
                    sprites = [
                        self.before_tabs, self.tabs_back, self._tabs_viewport,
                        self.tabs_forward, self.after_tabs
                    ]
                self.tabbox.sprites = sprites
            elif name == "current_page":
                self._select_current_page()
예제 #15
0
    def resize_children(self):
        Box.resize_children(self)

        pos = self.tab_position
        horizontal = pos.startswith("right") or pos.startswith("left")
        if horizontal:
            self.tabbox.alloc_w, self.tabbox.alloc_h = self.tabbox.alloc_h, self.tabbox.alloc_w

        if pos.startswith("right"):
            self.tabbox.x += self.tabbox.height
        elif pos.startswith("left"):
            self.tabbox.y += self.tabbox.width


        # show/hide thes croll buttons
        # doing it here to avoid recursion as changing visibility calls parent resize
        self.tabs_back.visible = self.tabs_forward.visible = self.show_scroll in (True, "auto_invisible")
        self.tabbox.resize_children()
        self.tabs_container.resize_children()


        if self.show_scroll == "auto_invisible":
            self.tabs_back.visible = self.tabs_forward.visible = True
            if self.tabs_container.width < self._tabs_viewport.width:
                self.tabs_back.opacity = self.tabs_forward.opacity = 0
            else:
                self.tabs_back.opacity = self.tabs_forward.opacity = 1

        else:
            self.tabs_back.opacity = self.tabs_forward.opacity = 1
            self.tabs_back.visible = self.tabs_forward.visible = self.show_scroll is True or \
                                                                (self.show_scroll == "auto" and \
                                                                 self.tabs_container.width > self._tabs_viewport.width)

        self.tabbox.resize_children()
        self._position_tabs()
예제 #16
0
    def __init__(self, text = "", markup = "", spacing = 5, image = None,
                 image_position = None, size = None, font_desc = None,
                 overflow = False,
                 color = "#000", background_color = None, **kwargs):

        # TODO - am initiating table with fill = false but that yields suboptimal label placement and the 0,0 points to whatever parent gave us
        Bin.__init__(self, **kwargs)

        #: image to put next to the label
        self.image = image

        # the actual container that contains the label and/or image
        self.container = Box(spacing = spacing, fill = False,
                             x_align = self.x_align, y_align = self.y_align)

        if image_position is not None:
            self.image_position = image_position

        self.display_label = _DisplayLabel(text = text, markup = markup, color=color, size = size)
        self.display_label.x_align = 0 # the default is 0.5 which makes label align incorrectly on wrapping

        if font_desc or self.font_desc:
            self.display_label.font_desc = font_desc or self.font_desc

        self.display_label.size = size or self.size

        self.background_color = background_color

        #: either the pango `wrap <http://www.pygtk.org/pygtk2reference/pango-constants.html#pango-wrap-mode-constants>`_
        #: or `ellipsize <http://www.pygtk.org/pygtk2reference/pango-constants.html#pango-ellipsize-mode-constants>`_ constant.
        #: if set to False will refuse to become smaller
        self.overflow = overflow

        self.add_child(self.container)

        self._position_contents()
        self.connect_after("on-render", self.__on_render)
예제 #17
0
class Label(Bin):
    """a widget that displays a limited amount of read-only text"""
    #: pango.FontDescription to use for the label
    font_desc = "Sans Serif 10"

    #: image attachment. one of top, right, bottom, left
    image_position = "left"

    #: font size
    size = None

    fill = False
    padding = 0
    x_align = 0

    def __init__(self, text = "", markup = "", spacing = 5, image = None,
                 image_position = None, size = None, font_desc = None,
                 overflow = False,
                 color = "#000", background_color = None, **kwargs):

        # TODO - am initiating table with fill = false but that yields suboptimal label placement and the 0,0 points to whatever parent gave us
        Bin.__init__(self, **kwargs)

        #: image to put next to the label
        self.image = image

        # the actual container that contains the label and/or image
        self.container = Box(spacing = spacing, fill = False,
                             x_align = self.x_align, y_align = self.y_align)

        if image_position is not None:
            self.image_position = image_position

        self.display_label = _DisplayLabel(text = text, markup = markup, color=color, size = size)
        self.display_label.x_align = 0 # the default is 0.5 which makes label align incorrectly on wrapping

        if font_desc or self.font_desc:
            self.display_label.font_desc = font_desc or self.font_desc

        self.display_label.size = size or self.size

        self.background_color = background_color

        #: either the pango `wrap <http://www.pygtk.org/pygtk2reference/pango-constants.html#pango-wrap-mode-constants>`_
        #: or `ellipsize <http://www.pygtk.org/pygtk2reference/pango-constants.html#pango-ellipsize-mode-constants>`_ constant.
        #: if set to False will refuse to become smaller
        self.overflow = overflow

        self.add_child(self.container)

        self._position_contents()
        self.connect_after("on-render", self.__on_render)

    def get_mouse_sprites(self):
        return None

    @property
    def text(self):
        """label text. This attribute and :attr:`markup` are mutually exclusive."""
        return self.display_label.text

    @property
    def markup(self):
        """pango markup to use in the label.
        This attribute and :attr:`text` are mutually exclusive."""
        return self.display_label.markup

    @property
    def color(self):
        """label color"""
        return self.display_label.color

    def __setattr__(self, name, val):
        if name in ("text", "markup", "color", "size"):
            if self.display_label.__dict__.get(name, "hamster_graphics_no_value_really") == val:
                return
            setattr(self.display_label, name, val)
        elif name in ("spacing"):
            setattr(self.container, name, val)
        else:
            if self.__dict__.get(name, "hamster_graphics_no_value_really") == val:
                return
            Bin.__setattr__(self, name, val)


        if name in ('x_align', 'y_align') and hasattr(self, "container"):
            setattr(self.container, name, val)

        elif name == "alloc_w" and hasattr(self, "display_label") and getattr(self, "overflow") is not False:
            self._update_max_width()

        elif name == "min_width" and hasattr(self, "display_label"):
            self.display_label.width = val - self.horizontal_padding

        elif name == "overflow" and hasattr(self, "display_label"):
            if val is False:
                self.display_label.wrap = None
                self.display_label.ellipsize = None
            elif isinstance(val, pango.WrapMode) and val in (pango.WrapMode.WORD, pango.WrapMode.WORD_CHAR, pango.WrapMode.CHAR):
                self.display_label.wrap = val
                self.display_label.ellipsize = None
            elif isinstance(val, pango.EllipsizeMode) and val in (pango.EllipsizeMode.START, pango.EllipsizeMode.MIDDLE, pango.EllipsizeMode.END):
                self.display_label.wrap = None
                self.display_label.ellipsize = val

            self._update_max_width()
        elif name in ("font_desc", "size"):
            setattr(self.display_label, name, val)

        if name in ("text", "markup", "image", "image_position", "overflow", "size"):
            if hasattr(self, "overflow"):
                self._position_contents()
                self.container.queue_resize()


    def _update_max_width(self):
        # updates labels max width, respecting image and spacing
        if self.overflow is False:
            self.display_label.max_width = -1
        else:
            w = (self.alloc_w or 0) - self.horizontal_padding - self.container.spacing
            if self.image and self.image_position in ("left", "right"):
                w -= self.image.width - self.container.spacing
            self.display_label.max_width = w

        self.container.queue_resize()


    def _position_contents(self):
        if self.image and (self.text or self.markup):
            self.image.expand = False
            self.container.orient_horizontal = self.image_position in ("left", "right")

            if self.image_position in ("top", "left"):
                if self.container.sprites != [self.image, self.display_label]:
                    self.container.clear()
                    self.container.add_child(self.image, self.display_label)
            else:
                if self.container.sprites != [self.display_label, self.image]:
                    self.container.clear()
                    self.container.add_child(self.display_label, self.image)
        elif self.image or (self.text or self.markup):
            sprite = self.image or self.display_label
            if self.container.sprites != [sprite]:
                self.container.clear()
                self.container.add_child(sprite)


    def __on_render(self, sprite):
        w, h = self.width, self.height
        w2, h2 = self.get_height_for_width_size()
        w, h = max(w, w2), max(h, h2)
        self.graphics.rectangle(0, 0, w, h)

        if self.background_color:
            self.graphics.fill(self.background_color)
        else:
            self.graphics.new_path()
예제 #18
0
 def resize_children(self):
     Box.resize_children(self)
     self._size_slider()
예제 #19
0
 def __setattr__(self, name, val):
     if name == "hide_on_leave":
         name = "_hide_on_leave"
     Box.__setattr__(self, name, val)
예제 #20
0
 def resize_children(self):
     Box.resize_children(self)
     self._size_slider()
예제 #21
0
    def __init__(self,
                 labels=None,
                 tab_position="top",
                 tab_spacing=0,
                 scroll_position=None,
                 show_scroll="auto",
                 scroll_selects_tab=True,
                 **kwargs):
        Box.__init__(self, horizontal=False, spacing=0, **kwargs)

        #: list of tabs in the order of appearance
        self.tabs = []

        #: list of pages in the order of appearance
        self.pages = []

        #: container of the pages
        self.pages_container = self.pages_container_class(padding=1)

        #: container of tabs. useful if you want to adjust padding/placement
        self.tabs_container = Group(fill=False, spacing=tab_spacing)
        self.tabs_container.on_mouse_over = lambda button: False  # ignore select-on-drag

        # viewport so that tabs don't go out of their area
        self._tabs_viewport = Viewport()
        self._tabs_viewport.get_min_size = self._tabs_viewport_get_min_size
        self._tabs_viewport.resize_children = self._tabs_viewport_resize_children
        self._tabs_viewport.add_child(self.tabs_container)

        #: wether scroll buttons should select next/previos tab or show the
        #: next/previos tab out of the view
        self.scroll_selects_tab = scroll_selects_tab

        #: container for custom content before tabs
        self.before_tabs = HBox(expand=False)

        #: container for custom content after tabs
        self.after_tabs = HBox(expand=False)

        #: button to scroll tabs back
        self.tabs_back = self.scroll_buttons_class("left",
                                                   expand=False,
                                                   visible=False,
                                                   enabled=False,
                                                   repeat_down_delay=150)
        self.tabs_back.connect("on-mouse-down", self.on_back_press)

        #: button to scroll tabs forward
        self.tabs_forward = self.scroll_buttons_class("right",
                                                      expand=False,
                                                      visible=False,
                                                      enabled=False,
                                                      repeat_down_delay=150)
        self.tabs_forward.connect("on-mouse-down", self.on_forward_press)

        #: the wrapping container that holds also the scroll buttons and everyting
        self.tabbox = self.tabbox_class(expand=False, expand_vert=False)
        self.tabbox.get_min_size = self.tabbox_get_min_size
        self.tabbox.get_height_for_width_size = self.tabbox_get_height_for_width_size

        self.tabbox.add_child(self.before_tabs, self.tabs_back,
                              self._tabs_viewport, self.tabs_forward,
                              self.after_tabs)

        #: current page
        self.current_page = 0

        #: tab position: top, right, bottom, left and combinations: "top-right", "left-bottom", etc.
        self.tab_position = tab_position

        for label in labels or []:
            self.add_page(label)

        #: where to place the scroll buttons on tab overflow. one of "start"
        #: (both at the start), "end" (both at the end) or "around" (on left
        #: and right of the tabs)
        self.scroll_position = scroll_position

        #: determines when to show scroll buttons. True for always, False for
        #: never, "auto" for auto appearing and disappearing, and
        #: "auto_invisible" for going transparent instead of disappearing
        #: (the latter avoids tab toggle)
        self.show_scroll = show_scroll
예제 #22
0
class Label(Bin):
    """a widget that displays a limited amount of read-only text"""
    #: pango.FontDescription to use for the label
    font_desc = "Sans Serif 10"

    #: image attachment. one of top, right, bottom, left
    image_position = "left"

    #: font size
    size = None

    fill = False
    padding = 0
    x_align = 0

    def __init__(self,
                 text="",
                 markup="",
                 spacing=5,
                 image=None,
                 image_position=None,
                 size=None,
                 font_desc=None,
                 overflow=False,
                 color="#000",
                 background_color=None,
                 **kwargs):

        # TODO - am initiating table with fill = false but that yields suboptimal label placement and the 0,0 points to whatever parent gave us
        Bin.__init__(self, **kwargs)

        #: image to put next to the label
        self.image = image

        # the actual container that contains the label and/or image
        self.container = Box(spacing=spacing,
                             fill=False,
                             x_align=self.x_align,
                             y_align=self.y_align)

        if image_position is not None:
            self.image_position = image_position

        self.display_label = _DisplayLabel(text=text,
                                           markup=markup,
                                           color=color,
                                           size=size)
        self.display_label.x_align = 0  # the default is 0.5 which makes label align incorrectly on wrapping

        if font_desc or self.font_desc:
            self.display_label.font_desc = font_desc or self.font_desc

        self.display_label.size = size or self.size

        self.background_color = background_color

        #: either the pango `wrap <http://www.pygtk.org/pygtk2reference/pango-constants.html#pango-wrap-mode-constants>`_
        #: or `ellipsize <http://www.pygtk.org/pygtk2reference/pango-constants.html#pango-ellipsize-mode-constants>`_ constant.
        #: if set to False will refuse to become smaller
        self.overflow = overflow

        self.add_child(self.container)

        self._position_contents()
        self.connect_after("on-render", self.__on_render)

    def get_mouse_sprites(self):
        return None

    @property
    def text(self):
        """label text. This attribute and :attr:`markup` are mutually exclusive."""
        return self.display_label.text

    @property
    def markup(self):
        """pango markup to use in the label.
        This attribute and :attr:`text` are mutually exclusive."""
        return self.display_label.markup

    @property
    def color(self):
        """label color"""
        return self.display_label.color

    def __setattr__(self, name, val):
        if name in ("text", "markup", "color", "size"):
            if self.display_label.__dict__.get(
                    name, "hamster_graphics_no_value_really") == val:
                return
            setattr(self.display_label, name, val)
        elif name in ("spacing"):
            setattr(self.container, name, val)
        else:
            if self.__dict__.get(name,
                                 "hamster_graphics_no_value_really") == val:
                return
            Bin.__setattr__(self, name, val)

        if name in ('x_align', 'y_align') and hasattr(self, "container"):
            setattr(self.container, name, val)

        elif name == "alloc_w" and hasattr(self, "display_label") and getattr(
                self, "overflow") is not False:
            self._update_max_width()

        elif name == "min_width" and hasattr(self, "display_label"):
            self.display_label.width = val - self.horizontal_padding

        elif name == "overflow" and hasattr(self, "display_label"):
            if val is False:
                self.display_label.wrap = None
                self.display_label.ellipsize = None
            elif isinstance(
                    val, pango.WrapMode) and val in (pango.WrapMode.WORD,
                                                     pango.WrapMode.WORD_CHAR,
                                                     pango.WrapMode.CHAR):
                self.display_label.wrap = val
                self.display_label.ellipsize = None
            elif isinstance(val, pango.EllipsizeMode) and val in (
                    pango.EllipsizeMode.START, pango.EllipsizeMode.MIDDLE,
                    pango.EllipsizeMode.END):
                self.display_label.wrap = None
                self.display_label.ellipsize = val

            self._update_max_width()
        elif name in ("font_desc", "size"):
            setattr(self.display_label, name, val)

        if name in ("text", "markup", "image", "image_position", "overflow",
                    "size"):
            if hasattr(self, "overflow"):
                self._position_contents()
                self.container.queue_resize()

    def _update_max_width(self):
        # updates labels max width, respecting image and spacing
        if self.overflow is False:
            self.display_label.max_width = -1
        else:
            w = (self.alloc_w
                 or 0) - self.horizontal_padding - self.container.spacing
            if self.image and self.image_position in ("left", "right"):
                w -= self.image.width - self.container.spacing
            self.display_label.max_width = w

        self.container.queue_resize()

    def _position_contents(self):
        if self.image and (self.text or self.markup):
            self.image.expand = False
            self.container.orient_horizontal = self.image_position in ("left",
                                                                       "right")

            if self.image_position in ("top", "left"):
                if self.container.sprites != [self.image, self.display_label]:
                    self.container.clear()
                    self.container.add_child(self.image, self.display_label)
            else:
                if self.container.sprites != [self.display_label, self.image]:
                    self.container.clear()
                    self.container.add_child(self.display_label, self.image)
        elif self.image or (self.text or self.markup):
            sprite = self.image or self.display_label
            if self.container.sprites != [sprite]:
                self.container.clear()
                self.container.add_child(sprite)

    def __on_render(self, sprite):
        w, h = self.width, self.height
        w2, h2 = self.get_height_for_width_size()
        w, h = max(w, w2), max(h, h2)
        self.graphics.rectangle(0, 0, w, h)

        if self.background_color:
            self.graphics.fill(self.background_color)
        else:
            self.graphics.new_path()
예제 #23
0
    def __init__(self, labels = None, tab_position="top", tab_spacing = 0,
                 scroll_position = None, show_scroll = "auto", scroll_selects_tab = True, **kwargs):
        Box.__init__(self, horizontal=False, spacing=0, **kwargs)

        #: list of tabs in the order of appearance
        self.tabs = []

        #: list of pages in the order of appearance
        self.pages = []

        #: container of the pages
        self.pages_container = self.pages_container_class(padding=1)

        #: container of tabs. useful if you want to adjust padding/placement
        self.tabs_container = Group(fill=False, spacing=tab_spacing)
        self.tabs_container.on_mouse_over = lambda button: False  # ignore select-on-drag

        # viewport so that tabs don't go out of their area
        self._tabs_viewport = Viewport()
        self._tabs_viewport.get_min_size = self._tabs_viewport_get_min_size
        self._tabs_viewport.resize_children = self._tabs_viewport_resize_children
        self._tabs_viewport.add_child(self.tabs_container)

        #: wether scroll buttons should select next/previos tab or show the
        #: next/previos tab out of the view
        self.scroll_selects_tab = scroll_selects_tab

        #: container for custom content before tabs
        self.before_tabs = HBox(expand=False)

        #: container for custom content after tabs
        self.after_tabs = HBox(expand=False)

        #: button to scroll tabs back
        self.tabs_back = self.scroll_buttons_class("left",
                                                   expand=False,
                                                   visible=False,
                                                   enabled=False,
                                                   repeat_down_delay = 150)
        self.tabs_back.connect("on-mouse-down", self.on_back_press)

        #: button to scroll tabs forward
        self.tabs_forward = self.scroll_buttons_class("right",
                                                      expand=False,
                                                      visible=False,
                                                      enabled=False,
                                                      repeat_down_delay = 150)
        self.tabs_forward.connect("on-mouse-down", self.on_forward_press)


        #: the wrapping container that holds also the scroll buttons and everyting
        self.tabbox = self.tabbox_class(expand = False, expand_vert = False)
        self.tabbox.get_min_size = self.tabbox_get_min_size
        self.tabbox.get_height_for_width_size = self.tabbox_get_height_for_width_size


        self.tabbox.add_child(self.before_tabs, self.tabs_back,
                              self._tabs_viewport,
                              self.tabs_forward, self.after_tabs)

        #: current page
        self.current_page = 0

        #: tab position: top, right, bottom, left and combinations: "top-right", "left-bottom", etc.
        self.tab_position = tab_position


        for label in labels or []:
            self.add_page(label)

        #: where to place the scroll buttons on tab overflow. one of "start"
        #: (both at the start), "end" (both at the end) or "around" (on left
        #: and right of the tabs)
        self.scroll_position = scroll_position

        #: determines when to show scroll buttons. True for always, False for
        #: never, "auto" for auto appearing and disappearing, and
        #: "auto_invisible" for going transparent instead of disappearing
        #: (the latter avoids tab toggle)
        self.show_scroll = show_scroll
예제 #24
0
 def __setattr__(self, name, val):
     if name == "hide_on_leave":
         name = "_hide_on_leave"
     Box.__setattr__(self, name, val)