[Sugar-devel] [PATCH Terminal] The same tabs as browse

S. Daniel Francis francis at sugarlabs.org
Sun Jun 3 17:09:30 EDT 2012


Signed-off-by: Daniel Francis <francis at sugarlabs.org>
Signed-off-by: Agustin Zubiaga <aguz at sugarlabs.org>
---
 icons/close-tab.svg |   27 ++++++++++
 terminal.py         |   42 ++++++++++-----
 widgets.py          |  150 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 206 insertions(+), 13 deletions(-)
 create mode 100644 icons/close-tab.svg
 create mode 100644 widgets.py

diff --git a/icons/close-tab.svg b/icons/close-tab.svg
new file mode 100644
index 0000000..782ad24
--- /dev/null
+++ b/icons/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="browse-close-tab"
+   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>
diff --git a/terminal.py b/terminal.py
index 0ba2871..6918e3f 100644
--- a/terminal.py
+++ b/terminal.py
@@ -32,7 +32,6 @@ from gi.repository import Pango
 from sugar3.graphics.toolbutton import ToolButton
 from sugar3.graphics.toolbarbox import ToolbarBox
 from sugar3.graphics.toolbarbox import ToolbarButton
-from sugar3.graphics.notebook import Notebook

 from sugar3.activity.widgets import EditToolbar
 from sugar3.activity.widgets import ActivityToolbarButton
@@ -40,6 +39,9 @@ from sugar3.activity.widgets import StopButton
 from sugar3.activity import activity
 from sugar3 import env

+from widgets import BrowserNotebook
+from widgets import TabLabel
+
 MASKED_ENVIRONMENT = [
     'DBUS_SESSION_BUS_ADDRESS',
     'PPID']
@@ -118,7 +120,8 @@ class TerminalActivity(activity.Activity):
         toolbar_box.show()
         self._update_accelerators(toolbar_box)

-        self._notebook = Notebook()
+        self._notebook = BrowserNotebook()
+        self._notebook.connect("tab-added", self.__open_tab_cb)
         self._notebook.set_property("tab-pos", Gtk.PositionType.TOP)
         self._notebook.set_scrollable(True)
         self._notebook.show()
@@ -248,17 +251,24 @@ class TerminalActivity(activity.Activity):
         index = self._create_tab(None)
         self._notebook.page = index
         if self._notebook.get_n_pages() == 2:
+            self._notebook.get_tab_label(self._notebook.get_nth_page(0
+                                                    )).show_close_button()
             self._delete_tab_button.props.sensitive = True
             self._previous_tab_button.props.sensitive = True
             self._next_tab_button.props.sensitive = True

-    def __close_tab_cb(self, btn):
-        self._close_tab(self._notebook.props.page)
+    def __close_tab_cb(self, btn, child):
+        index = self._notebook.page_num(child)
+        self._close_tab(index)
         if self._notebook.get_n_pages() == 1:
+            self._notebook.get_tab_label(self._notebook.get_nth_page(0
+                                                    )).hide_close_button()
             self._delete_tab_button.props.sensitive = False
             self._previous_tab_button.props.sensitive = False
             self._next_tab_button.props.sensitive = False

+        self._notebook.update_tab_sizes()
+
     def __prev_tab_cb(self, btn):
         if self._notebook.props.page == 0:
             self._notebook.props.page = self._notebook.get_n_pages() - 1
@@ -305,9 +315,8 @@ class TerminalActivity(activity.Activity):
         vt.connect("window-title-changed", self.__tab_title_changed_cb)

         # FIXME have to resend motion events to parent, see #1402
-        vt.connect('motion-notify-event', self.__motion_notify_cb)
+        #vt.connect('motion-notify-event', self.__motion_notify_cb)

-        #FIXME Drag and drop not working SL#3655
         #vt.drag_dest_set(Gtk.DestDefaults.MOTION | Gtk.DestDefaults.DROP,
         #       [('text/plain', 0, 0), ('STRING', 0, 1)],
         #       Gdk.DragAction.DEFAULT |
@@ -318,25 +327,32 @@ class TerminalActivity(activity.Activity):

         vt.show()

-        label = Gtk.Label()
-
         scrollbar = Gtk.VScrollbar.new(vt.get_vadjustment())
-        scrollbar.show()

         box = Gtk.HBox()
         box.pack_start(vt, True, True, 0)
         box.pack_start(scrollbar, False, True, 0)

         box.vt = vt
-        box.label = label
+        box.show()
+
+        tablabel = TabLabel(box)
+        tablabel.connect('tab-close', self.__close_tab_cb)
+        tablabel.update_size(200)
+        box.label = tablabel
+
+        index = self._notebook.append_page(box, tablabel)
+        tablabel.show_all()

-        index = self._notebook.append_page(box, label)
+        self._notebook.update_tab_sizes()
         self._notebook.show_all()

         # Uncomment this to only show the tab bar when there is at least
         # one tab. I think it's useful to always see it, since it displays
         # the 'window title'.
         # self._notebook.props.show_tabs = self._notebook.get_n_pages() > 1
+        tablabel.hide_close_button() if self._notebook.get_n_pages() == 1\
+                                     else None

         # Launch the default shell in the HOME directory.
         os.chdir(os.environ["HOME"])
@@ -380,8 +396,8 @@ class TerminalActivity(activity.Activity):

         return index

-    def __motion_notify_cb(self, widget, event):
-        self.emit('motion-notify-event', event)
+#    def __motion_notify_cb(self, widget, event):
+#        self.emit('motion-notify-event', event)

     def __become_root_cb(self, button):
         vt = self._notebook.get_nth_page(self._notebook.get_current_page()).vt
diff --git a/widgets.py b/widgets.py
new file mode 100644
index 0000000..94eff64
--- /dev/null
+++ b/widgets.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2006, Red Hat, Inc.
+# Copyright (C) 2011, 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
+
+from gi.repository import GObject
+from gi.repository import Gtk
+from gi.repository import Pango
+
+from sugar3.graphics.icon import Icon
+
+
+class TabAdd(Gtk.Button):
+    __gtype_name__ = 'BrowseTabAdd'
+
+    __gsignals__ = {
+        'tab-added': (GObject.SignalFlags.RUN_FIRST,
+                      None,
+                      ([])),
+    }
+
+    def __init__(self):
+        GObject.GObject.__init__(self)
+
+        add_tab_icon = Icon(icon_name='add')
+        self.props.relief = Gtk.ReliefStyle.NONE
+        self.props.focus_on_click = False
+        icon_box = Gtk.HBox()
+        icon_box.pack_start(add_tab_icon, True, False, 0)
+        self.add(icon_box)
+        self.connect('clicked', self.__button_clicked_cb)
+        self.set_name('browse-tab-add')
+        add_tab_icon.show()
+        icon_box.show()
+        self.show()
+
+    def __button_clicked_cb(self, button):
+        self.emit('tab-added')
+
+
+class BrowserNotebook(Gtk.Notebook):
+    __gtype_name__ = 'BrowseNotebook'
+
+    __gsignals__ = {
+        'tab-added': (GObject.SignalFlags.RUN_FIRST,
+                      None,
+                      ([])),
+    }
+
+    """Handle an extra tab at the end with an Add Tab button."""
+
+    def __init__(self):
+        GObject.GObject.__init__(self)
+
+        self.first_expose = True
+        self.connect("draw", self._draw_cb)
+        self._tab_add = TabAdd()
+        self._tab_add.connect('tab-added', self.on_add_tab)
+        self.set_action_widget(self._tab_add, Gtk.PackType.END)
+        self._tab_add.show()
+
+    def _draw_cb(self, widget, event):
+        if self.first_expose:
+            self.update_tab_sizes()
+            self.first_expose = False
+
+    def on_add_tab(self, obj):
+        self.emit('tab-added')
+
+    def update_tab_sizes(self):
+        n_pages = self.get_n_pages()
+        canvas_size = self.get_allocation()
+
+        # FIXME
+        # overlap_size = self.style_get_property('tab-overlap') * n_pages - 1
+        overlap_size = 0
+        allowed_size = canvas_size.width - overlap_size
+
+        tab_new_size = int(float(allowed_size) / (n_pages) -\
+                           self._tab_add.get_allocation().width - 5)
+
+        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)
+
+
+class TabLabel(Gtk.HBox):
+    __gtype_name__ = 'BrowseTabLabel'
+
+    __gsignals__ = {
+        'tab-close': (GObject.SignalFlags.RUN_FIRST,
+                      None,
+                      ([GObject.TYPE_PYOBJECT])),
+    }
+
+    def __init__(self, child):
+        GObject.GObject.__init__(self)
+
+        self.child = child
+        self._label = Gtk.Label(label="")
+        self._label.set_ellipsize(Pango.EllipsizeMode.END)
+        self._label.set_alignment(0, 0.5)
+        self.pack_start(self._label, True, True, 0)
+        self._label.show()
+
+        close_tab_icon = Icon(icon_name='close-tab')
+        button = Gtk.Button()
+        button.props.relief = Gtk.ReliefStyle.NONE
+        button.props.focus_on_click = False
+        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, False, True, 0)
+        close_tab_icon.show()
+        icon_box.show()
+        button.show()
+        self._close_button = button
+
+    def set_text(self, title):
+        self._label.set_text(title)
+
+    def update_size(self, size):
+        self.set_size_request(size, -1)
+
+    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.child)
--
1.7.10.2


More information about the Sugar-devel mailing list