[Sugar-devel] [PATCH] Browse: tabs usability improved
manuel quiñones
manuq at laptop.org
Mon Sep 5 14:47:04 EDT 2011
A screen grab here:
http://dev.laptop.org/~manuq/browse_design/tabs/new_tabs2.png
2011/9/5 Manuel Quiñones <manuq at laptop.org>:
> The Add Tab button has been relocated next to the tab labels, allowing
> more space for the URL entry.
>
> Tabs are always shown. There is at least one tab. In that case, it
> cannot be closed. We prevent the closing by hidding the 'X' button.
> Also, the close image was sugarized.
>
> There is now a fixed width for tabs. The label text does ellipsize.
> The width depends on the amount of tabs. There is a maximun size that
> is used when there is extra space. There is a minimun size to prevent
> hiding the information.
>
> When a new tab is opened, it now shows an empty page, not the default
> page. In the future, we will add a hint in this empty page, similar
> to what we have for an empty Journal.
>
> Added the option to "follow link in new tab" in the link's palette.
> Added an icon for this item, and also the icon for "follow link" is
> also updated.
>
> Signed-off-by: Manuel Quiñones <manuq at laptop.org>
> ---
> browser.py | 115 ++++++++++++++++++++++++++++------
> icons/browse-close-tab.svg | 27 ++++++++
> icons/browse-follow-link-new-tab.svg | 43 +++++++++++++
> icons/browse-follow-link.svg | 26 ++++++++
> palettes.py | 27 ++++++---
> webactivity.py | 31 +--------
> webtoolbar.py | 16 +-----
> widgets.py | 88 ++++++++++++++++++++++++++
> 8 files changed, 304 insertions(+), 69 deletions(-)
> create mode 100644 icons/browse-close-tab.svg
> create mode 100644 icons/browse-follow-link-new-tab.svg
> create mode 100644 icons/browse-follow-link.svg
> create mode 100644 widgets.py
>
> diff --git a/browser.py b/browser.py
> index 96e6fb1..0a32dd5 100644
> --- a/browser.py
> +++ b/browser.py
> @@ -21,6 +21,7 @@ import time
>
> import gobject
> import gtk
> +import pango
> import hulahop
> import xpcom
> from xpcom.nsError import *
> @@ -31,13 +32,16 @@ from hulahop.webview import WebView
> from sugar import env
> from sugar.activity import activity
> from sugar.graphics import style
> +from sugar.graphics.icon import Icon
>
> import sessionstore
> from palettes import ContentInvoker
> from sessionhistory import HistoryListener
> from progresslistener import ProgressListener
> +from widgets import BrowserNotebook
>
> _ZOOM_AMOUNT = 0.1
> +_LIBRARY_PATH = '/usr/share/library-common/index.html'
>
>
> class SaveListener(object):
> @@ -93,7 +97,7 @@ class CommandListener(object):
> cert_exception.showDialog(self._window)
>
>
> -class TabbedView(gtk.Notebook):
> +class TabbedView(BrowserNotebook):
> __gtype_name__ = 'TabbedView'
>
> _com_interfaces_ = interfaces.nsIWindowCreator
> @@ -104,7 +108,7 @@ class TabbedView(gtk.Notebook):
> 'user-stylesheet.css')
>
> def __init__(self):
> - gobject.GObject.__init__(self)
> + BrowserNotebook.__init__(self)
>
> self.props.show_border = False
> self.props.scrollable = True
> @@ -140,8 +144,13 @@ class TabbedView(gtk.Notebook):
> interfaces.nsIWindowCreator)
> window_watcher.setWindowCreator(window_creator)
>
> - browser = Browser()
> - self._append_tab(browser)
> + self.connect('size-allocate', self.__size_allocate_cb)
> + self.connect('page-added', self.__page_added_cb)
> + self.connect('page-removed', self.__page_removed_cb)
> +
> + self.new_tab()
> + self._update_closing_buttons()
> + self._update_tab_sizes()
>
> def createChromeWindow(self, parent, flags):
> if flags & interfaces.nsIWebBrowserChrome.CHROME_OPENAS_CHROME:
> @@ -160,25 +169,81 @@ class TabbedView(gtk.Notebook):
>
> return browser.containerWindow
> else:
> - browser = Browser()
> + browser = Browser(self)
> self._append_tab(browser)
>
> return browser.browser.containerWindow
>
> + def __size_allocate_cb(self, widget, allocation):
> + self._update_tab_sizes()
> +
> + def __page_added_cb(self, notebook, child, pagenum):
> + self._update_closing_buttons()
> + self._update_tab_sizes()
> +
> + def __page_removed_cb(self, notebook, child, pagenum):
> + self._update_closing_buttons()
> + self._update_tab_sizes()
> +
> + def new_tab(self):
> + browser = Browser(self)
> + self._append_tab(browser)
> + return browser
> +
> def _append_tab(self, browser):
> label = TabLabel(browser)
> label.connect('tab-close', self.__tab_close_cb)
>
> self.append_page(browser, label)
> browser.show()
> -
> self.set_current_page(-1)
> - self.props.show_tabs = self.get_n_pages() > 1
> +
> + def on_add_tab(self, gobject):
> + self.new_tab()
>
> def __tab_close_cb(self, label, browser):
> self.remove_page(self.page_num(browser))
> browser.destroy()
> - self.props.show_tabs = self.get_n_pages() > 1
> +
> + def _update_tab_sizes(self):
> + """Update ta widths based in the amount of tabs."""
> +
> + canvas_size = self.get_allocation()
> + allowed_size = canvas_size.width
> + n_pages = self.get_n_pages()
> + tab_new_size = int(allowed_size * 1.0 / (n_pages+1))
> + tab_max_size = int(allowed_size * 1.0 / (4+1))
> + tab_min_size = int(allowed_size * 1.0 / (8+1))
> +
> + if tab_new_size < tab_min_size:
> + tab_new_size = tab_min_size
> + elif tab_new_size > tab_max_size:
> + tab_new_size = tab_max_size
> +
> + for page_idx in range(n_pages):
> + page = self.get_nth_page(page_idx)
> + label = self.get_tab_label(page)
> + label.update_size(tab_new_size)
> +
> + def _update_closing_buttons(self):
> + """Prevent closing the last tab."""
> + first_page = self.get_nth_page(0)
> + first_label = self.get_tab_label(first_page)
> + if self.get_n_pages() == 1:
> + first_label.hide_close_button()
> + else:
> + first_label.show_close_button()
> +
> + def _load_homepage(self):
> + """If new_tab is True, open the homepage in a new tab."""
> + browser = self.current_browser
> +
> + if os.path.isfile(_LIBRARY_PATH):
> + browser.load_uri('file://' + _LIBRARY_PATH)
> + else:
> + default_page = os.path.join(activity.get_bundle_path(),
> + "data/index.html")
> + browser.load_uri(default_page)
>
> def _get_current_browser(self):
> return self.get_nth_page(self.get_current_page())
> @@ -202,7 +267,7 @@ class TabbedView(gtk.Notebook):
> self.remove_page(self.get_n_pages() - 1)
>
> for tab_session in tab_sessions:
> - browser = Browser()
> + browser = Browser(self)
> self._append_tab(browser)
> sessionstore.set_session(browser, tab_session)
>
> @@ -231,21 +296,32 @@ class TabLabel(gtk.HBox):
> self._browser.connect('is-setup', self.__browser_is_setup_cb)
>
> self._label = gtk.Label('')
> - self.pack_start(self._label)
> + self._label.set_ellipsize(pango.ELLIPSIZE_END)
> + self._label.set_alignment(0, 0.5)
> + self.pack_start(self._label, )
> self._label.show()
>
> + close_tab_icon = Icon(icon_name='browse-close-tab')
> button = gtk.Button()
> - button.connect('clicked', self.__button_clicked_cb)
> - button.set_name('browse-tab-close')
> button.props.relief = gtk.RELIEF_NONE
> button.props.focus_on_click = False
> - self.pack_start(button)
> - button.show()
> + icon_box = gtk.HBox()
> + icon_box.pack_start(close_tab_icon, True, False, 0)
> + button.add(icon_box)
> + button.connect('clicked', self.__button_clicked_cb)
> + button.set_name('browse-tab-close')
> + self.pack_start(button, expand=False)
> + button.show_all()
> + self._close_button = button
> +
> + def update_size(self, size):
> + self.set_size_request(size, -1)
>
> - close_image = gtk.image_new_from_stock(gtk.STOCK_CLOSE,
> - gtk.ICON_SIZE_MENU)
> - button.add(close_image)
> - close_image.show()
> + def hide_close_button(self):
> + self._close_button.hide()
> +
> + def show_close_button(self):
> + self._close_button.show()
>
> def __button_clicked_cb(self, button):
> self.emit('tab-close', self._browser)
> @@ -272,9 +348,10 @@ class Browser(WebView):
> ([])),
> }
>
> - def __init__(self):
> + def __init__(self, tabbed_view):
> WebView.__init__(self)
>
> + self.tabbed_view = tabbed_view
> self.history = HistoryListener()
> self.progress = ProgressListener()
>
> diff --git a/icons/browse-close-tab.svg b/icons/browse-close-tab.svg
> new file mode 100644
> index 0000000..7affd43
> --- /dev/null
> +++ b/icons/browse-close-tab.svg
> @@ -0,0 +1,27 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
> + <!ENTITY fill_color "#FFFFFF">
> + <!ENTITY stroke_color "#010101">
> +]>
> +<svg
> + xmlns="http://www.w3.org/2000/svg"
> + version="1.1"
> + width="22.16"
> + height="22.16"
> + viewBox="0 0 22.16 22.16"
> + id="svg2"
> + xml:space="preserve">
> + <g
> + transform="matrix(1.3,0,0,1.3,-3.2682282,-3.3351543)"
> + id="browse-dialog-cancel"
> + style="stroke:&fill_color;;stroke-width:2.69230771;stroke-miterlimit:4;stroke-dasharray:none">
> + <path
> + d="M 14.798121,7.2131543 6.9900671,15.021208"
> + id="path2986"
> + style="fill:none;stroke:&fill_color;;stroke-width:2.69230771;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
> + <path
> + d="M 6.9900671,7.2131543 14.798121,15.021208"
> + id="path3756"
> + style="fill:none;stroke:&fill_color;;stroke-width:2.69230771;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
> + </g>
> +</svg>
> \ No newline at end of file
> diff --git a/icons/browse-follow-link-new-tab.svg b/icons/browse-follow-link-new-tab.svg
> new file mode 100644
> index 0000000..8d9d644
> --- /dev/null
> +++ b/icons/browse-follow-link-new-tab.svg
> @@ -0,0 +1,43 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
> + <!ENTITY fill_color "#FFFFFF">
> + <!ENTITY stroke_color "#010101">
> +]>
> +<svg
> + xmlns="http://www.w3.org/2000/svg"
> + version="1.1"
> + width="55.125"
> + height="55"
> + viewBox="0 0 55.125 55"
> + id="svg2"
> + xml:space="preserve">
> +<g
> + transform="matrix(0.72828114,0,0,0.72828114,7.3907532,18.617266)"
> + id="tab-add"
> + style="display:block">
> + <g
> + transform="scale(0.8,0.8)"
> + id="g5">
> + <g
> + transform="translate(6.5,6.5)"
> + id="g7">
> + <path
> + d="m 0,50 55,0 0,-15 -5,0 0,-25 Q 50,5 45,5 L 10,5 Q 5,5 5,10 L 5,35 0,35 z M 30.768,38.767 c -0.002,1.774 -1.438,3.216 -3.214,3.214 -0.889,10e-4 -1.693,-0.359 -2.275,-0.941 -0.582,-0.581 -0.94,-1.385 -0.94,-2.27 l 0,-8.146 h -8.146 c -0.886,-10e-4 -1.689,-0.359 -2.271,-0.94 -0.582,-0.583 -0.942,-1.388 -0.942,-2.276 0,-1.773 1.439,-3.213 3.217,-3.211 h 8.143 v -8.143 c -0.003,-1.776 1.438,-3.217 3.212,-3.217 1.774,0 3.218,1.438 3.215,3.215 l 0.001,8.145 8.146,0.001 c 1.775,-0.005 3.212,1.438 3.213,3.213 0.002,1.775 -1.441,3.214 -3.215,3.215 h -8.143 v 8.141 z"
> + id="path9"
> + style="fill:&fill_color;" />
> + </g>
> + </g>
> +</g>
> +<g
> + transform="translate(0,0.55369128)"
> + id="g3868"><line
> + style="fill:none;stroke:&fill_color;;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round"
> + x1="36.448467"
> + x2="19.418867"
> + y1="11.934766"
> + y2="11.934766"
> + id="line15" /><polyline
> + transform="matrix(1.4,0,0,1.4,-2.8453325,2.1725664)"
> + style="fill:none;stroke:&fill_color;;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"
> + points=" 21.983,1.843 28.067,6.973 21.983,12.104 "
> + id="polyline17" /></g></svg>
> \ No newline at end of file
> diff --git a/icons/browse-follow-link.svg b/icons/browse-follow-link.svg
> new file mode 100644
> index 0000000..43da884
> --- /dev/null
> +++ b/icons/browse-follow-link.svg
> @@ -0,0 +1,26 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
> + <!ENTITY fill_color "#FFFFFF">
> + <!ENTITY stroke_color "#010101">
> +]>
> +<svg
> + xmlns="http://www.w3.org/2000/svg"
> + version="1.1"
> + width="55.125"
> + height="55"
> + viewBox="0 0 55.125 55"
> + id="svg2"
> + xml:space="preserve">
> +<g
> + transform="translate(-0.37116731,15.564534)"
> + id="g3868"><line
> + style="fill:none;stroke:&fill_color;;stroke-width:5.25;stroke-linecap:round;stroke-linejoin:round"
> + x1="40.705868"
> + x2="15.161467"
> + y1="11.934416"
> + y2="11.934416"
> + id="line15" /><polyline
> + transform="matrix(2.1,0,0,2.1,-18.234832,-2.7088836)"
> + style="fill:none;stroke:&fill_color;;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round"
> + points=" 21.983,1.843 28.067,6.973 21.983,12.104 "
> + id="polyline17" /></g></svg>
> \ No newline at end of file
> diff --git a/palettes.py b/palettes.py
> index 9fbc370..1197cf4 100644
> --- a/palettes.py
> +++ b/palettes.py
> @@ -140,6 +140,17 @@ class LinkPalette(Palette):
> else:
> self.props.primary_text = url
>
> + menu_item = MenuItem(_('Follow link'), 'browse-follow-link')
> + menu_item.connect('activate', self.__follow_activate_cb)
> + self.menu.append(menu_item)
> + menu_item.show()
> +
> + menu_item = MenuItem(_('Follow link in new tab'),
> + 'browse-follow-link-new-tab')
> + menu_item.connect('activate', self.__follow_activate_cb, True)
> + self.menu.append(menu_item)
> + menu_item.show()
> +
> menu_item = MenuItem(_('Keep link'))
> icon = Icon(icon_name='document-save', xo_color=profile.get_color(),
> icon_size=gtk.ICON_SIZE_MENU)
> @@ -156,14 +167,14 @@ class LinkPalette(Palette):
> self.menu.append(menu_item)
> menu_item.show()
>
> - menu_item = MenuItem(_('Follow link'), 'edit-copy')
> - menu_item.connect('activate', self.__follow_activate_cb)
> - self.menu.append(menu_item)
> - menu_item.show()
> -
> - def __follow_activate_cb(self, menu_item):
> - self._browser.load_uri(self._url)
> - self._browser.grab_focus()
> + def __follow_activate_cb(self, menu_item, new_tab=False):
> + if new_tab:
> + new_browser = self._browser.tabbed_view.new_tab()
> + new_browser.load_uri(self._url)
> + new_browser.grab_focus()
> + else:
> + self._browser.load_uri(self._url)
> + self._browser.grab_focus()
>
> def __copy_activate_cb(self, menu_item):
> clipboard = gtk.Clipboard()
> diff --git a/webactivity.py b/webactivity.py
> index fb1fec8..9999d95 100644
> --- a/webactivity.py
> +++ b/webactivity.py
> @@ -177,8 +177,6 @@ from edittoolbar import EditToolbar
> from viewtoolbar import ViewToolbar
> import downloadmanager
>
> -_LIBRARY_PATH = '/usr/share/library-common/index.html'
> -
> from model import Model
> from sugar.presence.tubeconn import TubeConnection
> from messenger import Messenger
> @@ -232,15 +230,12 @@ class WebActivity(activity.Activity):
> self.set_tray(self._tray, gtk.POS_BOTTOM)
> self._tray.show()
>
> - self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self,
> - self._disable_multiple_tabs)
> + self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self)
> self._edit_toolbar = EditToolbar(self)
> self._view_toolbar = ViewToolbar(self)
>
> self._primary_toolbar.connect('add-link', self._link_add_button_cb)
>
> - self._primary_toolbar.connect('add-tab', self._new_tab_cb)
> -
> self._primary_toolbar.connect('go-home', self._go_home_button_cb)
>
> if NEW_TOOLBARS:
> @@ -292,7 +287,7 @@ class WebActivity(activity.Activity):
> elif not self._jobject.file_path:
> # TODO: we need this hack until we extend the activity API for
> # opening URIs and default docs.
> - self._load_homepage()
> + self._tabbed_view._load_homepage()
>
> self.messenger = None
> self.connect('shared', self._shared_cb)
> @@ -321,9 +316,6 @@ class WebActivity(activity.Activity):
> else:
> _logger.debug('Created activity')
>
> - def _new_tab_cb(self, gobject):
> - self._load_homepage(new_tab=True)
> -
> def _shared_cb(self, activity_):
> _logger.debug('My activity was shared')
> self.initiating = True
> @@ -425,21 +417,6 @@ class WebActivity(activity.Activity):
> self.messenger = Messenger(self.tube_conn, self.initiating,
> self.model)
>
> - def _load_homepage(self, new_tab=False):
> - # If new_tab is True, open the homepage in a new tab.
> - if new_tab:
> - browser = Browser()
> - self._tabbed_view._append_tab(browser)
> - else:
> - browser = self._tabbed_view.current_browser
> -
> - if os.path.isfile(_LIBRARY_PATH):
> - browser.load_uri('file://' + _LIBRARY_PATH)
> - else:
> - default_page = os.path.join(activity.get_bundle_path(),
> - "data/index.html")
> - browser.load_uri(default_page)
> -
> def _get_data_from_file_path(self, file_path):
> fd = open(file_path, 'r')
> try:
> @@ -518,7 +495,7 @@ class WebActivity(activity.Activity):
> self._add_link()
>
> def _go_home_button_cb(self, button):
> - self._load_homepage()
> + self._tabbed_view._load_homepage()
>
> def _key_press_cb(self, widget, event):
> key_name = gtk.gdk.keyval_name(event.keyval)
> @@ -555,7 +532,7 @@ class WebActivity(activity.Activity):
> browser.web_navigation.reload(flags)
> elif gtk.gdk.keyval_name(event.keyval) == "t":
> if not self._disable_multiple_tabs:
> - self._load_homepage(new_tab=True)
> + self._tabbed_view._load_homepage(new_tab=True)
> else:
> return False
>
> diff --git a/webtoolbar.py b/webtoolbar.py
> index c0e097d..a4623be 100644
> --- a/webtoolbar.py
> +++ b/webtoolbar.py
> @@ -228,15 +228,12 @@ class PrimaryToolbar(ToolbarBase):
> 'add-link': (gobject.SIGNAL_RUN_FIRST,
> gobject.TYPE_NONE,
> ([])),
> - 'add-tab': (gobject.SIGNAL_RUN_FIRST,
> - gobject.TYPE_NONE,
> - ([])),
> 'go-home': (gobject.SIGNAL_RUN_FIRST,
> gobject.TYPE_NONE,
> ([])),
> }
>
> - def __init__(self, tabbed_view, act, disable_multiple_tabs):
> + def __init__(self, tabbed_view, act):
> ToolbarBase.__init__(self)
>
> self._activity = act
> @@ -286,14 +283,6 @@ class PrimaryToolbar(ToolbarBase):
> toolbar.insert(self._forward, -1)
> self._forward.show()
>
> - if not disable_multiple_tabs:
> - self._add_tab = ToolButton('tab-add')
> - self._add_tab.set_tooltip(_('Add a tab'))
> - self._add_tab.props.sensitive = True
> - self._add_tab.connect('clicked', self._add_tab_cb)
> - toolbar.insert(self._add_tab, -1)
> - self._add_tab.show()
> -
> self._link_add = ToolButton('emblem-favorite')
> self._link_add.set_tooltip(_('Bookmark'))
> self._link_add.connect('clicked', self._link_add_clicked_cb)
> @@ -417,9 +406,6 @@ class PrimaryToolbar(ToolbarBase):
> browser.load_uri(entry.props.text)
> browser.grab_focus()
>
> - def _add_tab_cb(self, button):
> - self.emit('add-tab')
> -
> def _go_home_cb(self, button):
> self.emit('go-home')
>
> diff --git a/widgets.py b/widgets.py
> new file mode 100644
> index 0000000..288ed1a
> --- /dev/null
> +++ b/widgets.py
> @@ -0,0 +1,88 @@
> +# Copyright (C) 2006, Red Hat, Inc.
> +# Copyright (C) 2007, One Laptop Per Child
> +# Copyright (C) 2009, Tomeu Vizoso, Simon Schampijer
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> +
> +import gobject
> +import gtk
> +
> +from sugar.graphics.notebook import Notebook
> +from sugar.graphics.icon import Icon
> +
> +
> +class TabAdd(gtk.HBox):
> + __gtype_name__ = 'TabAdd'
> +
> + __gsignals__ = {
> + 'tab-add': (gobject.SIGNAL_RUN_FIRST,
> + gobject.TYPE_NONE,
> + ([])),
> + }
> +
> + def __init__(self):
> + gtk.HBox.__init__(self)
> +
> + add_tab_icon = Icon(icon_name='add')
> + button = gtk.Button()
> + button.props.relief = gtk.RELIEF_NONE
> + button.props.focus_on_click = False
> + icon_box = gtk.HBox()
> + icon_box.pack_start(add_tab_icon, True, False, 0)
> + button.add(icon_box)
> + button.connect('clicked', self.__button_clicked_cb)
> + button.set_name('browse-tab-add')
> + self.pack_start(button)
> + button.show_all()
> +
> + def __button_clicked_cb(self, button):
> + self.emit('tab-add')
> +
> +
> +class BrowserNotebook(Notebook):
> + """Handle an extra tab at the end with an Add Tab button."""
> +
> + def __init__(self):
> + Notebook.__init__(self)
> + self.connect('switch-page', self.__on_switch_page)
> +
> + tab_add = TabAdd()
> + tab_add.connect('tab-add', self.on_add_tab)
> + empty_page = gtk.HBox()
> + self.append_page(empty_page, tab_add)
> + empty_page.show()
> +
> + def on_add_tab(self, gobject):
> + raise NotImplementedError, "implement this in the subclass"
> +
> + def __on_switch_page(self, notebook, page, page_num):
> + """Don't switch to the extra tab at the end."""
> + if page_num == Notebook.get_n_pages(self) - 1:
> + self.set_current_page(-1)
> + self.stop_emission("switch-page")
> +
> + def get_n_pages(self):
> + """Skip the extra tab at the end on the pages count."""
> + return Notebook.get_n_pages(self) - 1
> +
> + def append_page(self, page, label):
> + """Append keeping the extra tab at the end."""
> + return self.insert_page(page, label, self.get_n_pages())
> +
> + def set_current_page(self, number):
> + """If indexing from the end, skip the extra tab."""
> + if number < 0:
> + number = self.get_n_pages() - 1
> + return Notebook.set_current_page(self, number)
> --
> 1.7.4.4
>
>
--
.. manuq ..
More information about the Sugar-devel
mailing list