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()
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()
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
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()
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)
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()
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()
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 __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)
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
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
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()
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()
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)
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()
def resize_children(self): Box.resize_children(self) self._size_slider()
def __setattr__(self, name, val): if name == "hide_on_leave": name = "_hide_on_leave" Box.__setattr__(self, name, val)
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
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()
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