From 71e6228ceba7a866d22be34607e14a1b4751fa47 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 10 Jul 2009 03:58:13 +0000 Subject: [PATCH 01/51] Initial implementation of toolbars mockup --- src/sugar/graphics/style.py | 4 + src/sugar/graphics/toolbar.py | 175 ++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 src/sugar/graphics/toolbar.py diff --git a/src/sugar/graphics/style.py b/src/sugar/graphics/style.py index 591957bf..ed229693 100644 --- a/src/sugar/graphics/style.py +++ b/src/sugar/graphics/style.py @@ -131,3 +131,7 @@ COLOR_INACTIVE_STROKE = Color('#757575') COLOR_TEXT_FIELD_GREY = Color('#E5E5E5') PALETTE_CURSOR_DISTANCE = zoom(10) + +#TOOLBAR_COLOR = COLOR_BLACK +TOOLBAR_COLOR = COLOR_TOOLBAR_GREY +TOOLBAR_ARROW_SIZE = 8 diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py new file mode 100644 index 00000000..9a7e396a --- /dev/null +++ b/src/sugar/graphics/toolbar.py @@ -0,0 +1,175 @@ +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import gtk +import gobject +import logging +from gobject import SIGNAL_RUN_FIRST, TYPE_NONE + +from sugar.graphics import style +from sugar.graphics.toolbutton import ToolButton + +class ToolbarButton(ToolButton): + def __init__(self, bar, page, **kwargs): + ToolButton.__init__(self, **kwargs) + + self.modify_bg(gtk.STATE_NORMAL, style.TOOLBAR_COLOR.get_gdk_color()) + + self._bar = bar + self._page = _align(_Box, page, style._FOCUS_LINE_WIDTH*3, + style.TOOLBAR_COLOR) + self._page._toolitem = self + page.show() + + bar._notebook.append_page(self._page) + + self.connect('clicked', + lambda widget: self.set_expanded(not self.expanded)) + self.connect('destroy', self.__destroy_cb) + + def __destroy_cb(self, widget): + self._bar._remove_page(self._page) + + def get_expanded(self): + return self._bar._expanded_page() == self._page + + def set_expanded(self, value): + if self.get_expanded() == value: + return + if value: + expanded = self._bar._expanded_page() + if expanded: + expanded._toolitem.window.invalidate_rect(None, True) + self._page._toolitem_alloc = self.allocation + self._bar._expand_page(self._page) + else: + self._bar._shrink_page() + + expanded = property(get_expanded, set_expanded) + + def do_expose_event(self, event): + child = self.get_child() + alloc = self.allocation + + if not self.expanded or self.palette and self.palette.is_up(): + ToolButton.do_expose_event(self, event) + _paint_arrow(self, event, gtk.ARROW_UP) + return + + self.get_style().paint_box(event.window, + gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, + 'palette-invoker', alloc.x, -style._FOCUS_LINE_WIDTH, + alloc.width, alloc.height + style._FOCUS_LINE_WIDTH*2) + + if child.state != gtk.STATE_PRELIGHT: + self.get_style().paint_box(event.window, + gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, None, + alloc.x + style._FOCUS_LINE_WIDTH, 0, + alloc.width - style._FOCUS_LINE_WIDTH*2, alloc.height) + + gtk.ToolButton.do_expose_event(self, event) + _paint_arrow(self, event, gtk.ARROW_DOWN) + +class Toolbar(gtk.VBox): + __gsignals__ = { + 'current-toolbar-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, ([int])) + } + + def __init__(self): + gtk.VBox.__init__(self) + + self._bar = gtk.Toolbar() + toolbar = _align(gtk.EventBox, self._bar, 0, style.COLOR_TOOLBAR_GREY) + self.pack_start(toolbar) + + self._notebook = gtk.Notebook() + self._notebook.set_show_border(False) + self._notebook.set_show_tabs(False) + self._notebook.show() + + self._notebook.connect('notify::page', lambda notebook, pspec: + self.emit('current-toolbar-changed', notebook.props.page)) + + top = property(lambda self: self._bar) + + def _remove_page(self, page): + page = self._notebook.page_num(page) + self._notebook.remove_page(page) + + def _expanded_page(self): + if self._notebook.parent is None: + return None + page_no = self._notebook.get_current_page() + return self._notebook.get_nth_page(page_no) + + def _shrink_page(self): + self.remove(self._notebook) + + def _expand_page(self, page): + page_no = self._notebook.page_num(page) + self._notebook.set_current_page(page_no) + + if self._notebook.parent is None: + self.pack_start(self._notebook) + +class _Box(gtk.EventBox): + def __init__(self): + gtk.EventBox.__init__(self) + + self._toolitem_alloc = gtk.gdk.Rectangle() + + self.modify_bg(gtk.STATE_PRELIGHT, style.TOOLBAR_COLOR.get_gdk_color()) + self.modify_bg(gtk.STATE_ACTIVE,style.COLOR_BUTTON_GREY.get_gdk_color()) + + self.connect('expose-event', self.do_expose_event) + self.set_app_paintable(True) + + def do_expose_event(self, widget, event): + self.get_style().paint_box(event.window, + gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, + 'palette-invoker', -style._FOCUS_LINE_WIDTH, 0, + self.allocation.width + style._FOCUS_LINE_WIDTH*2, + self.allocation.height + style._FOCUS_LINE_WIDTH) + self.get_style().paint_box(event.window, + gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, None, + self._toolitem_alloc.x + style._FOCUS_LINE_WIDTH, 0, + self._toolitem_alloc.width - style._FOCUS_LINE_WIDTH*2, + style._FOCUS_LINE_WIDTH) + +def _align(box_class, widget, vpad, color): + top_pad = vpad + bottom_pad = vpad and vpad - style._FOCUS_LINE_WIDTH + + alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0) + alignment.set_padding(top_pad, bottom_pad, style.TOOLBOX_HORIZONTAL_PADDING, + style.TOOLBOX_HORIZONTAL_PADDING) + alignment.add(widget) + alignment.show() + + box = box_class() + box.modify_bg(gtk.STATE_NORMAL, color.get_gdk_color()) + box.add(alignment) + box.show() + + return box + +def _paint_arrow(widget, event, type): + a = widget.allocation + widget.get_style().paint_arrow(event.window, + gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, widget, + None, type, True, + a.x + a.width/2 - style.TOOLBAR_ARROW_SIZE/2, + a.y + a.height - style.TOOLBAR_ARROW_SIZE - style._FOCUS_LINE_WIDTH, + style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) From 2fc1cab92dc8b6dfe3345b4c0adb2bdd527294e0 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 10 Jul 2009 04:07:10 +0000 Subject: [PATCH 02/51] Add simple toolbars example --- examples/sugar | 1 + examples/toolbar.py | 32 ++++++++++++++++++++++++++++++++ m4/.gitignore | 2 ++ src/sugar/__init__.py | 14 ++++++++++++++ src/sugar/_sugarext.so | 1 + 5 files changed, 50 insertions(+) create mode 120000 examples/sugar create mode 100644 examples/toolbar.py create mode 100644 src/sugar/__init__.py create mode 120000 src/sugar/_sugarext.so diff --git a/examples/sugar b/examples/sugar new file mode 120000 index 00000000..12f3164b --- /dev/null +++ b/examples/sugar @@ -0,0 +1 @@ +../src/sugar/ \ No newline at end of file diff --git a/examples/toolbar.py b/examples/toolbar.py new file mode 100644 index 00000000..e4d24dfd --- /dev/null +++ b/examples/toolbar.py @@ -0,0 +1,32 @@ +import gtk +from sugar.graphics.toolbar import Toolbar, ToolbarButton + +window = gtk.Window() + +box = gtk.VBox() +window.add(box) + +toolbar = Toolbar() +box.pack_start(toolbar, False) + +tollbarbutton_1 = ToolbarButton(toolbar, gtk.Button('1'), + icon_name='computer-xo', + tooltip='foo') +toolbar.top.insert(tollbarbutton_1, -1) + +toolbar.top.insert(gtk.SeparatorToolItem(), -1) + +tollbarbutton_2 = ToolbarButton(toolbar, gtk.Button('1'), + icon_name='button_cancel', + tooltip='foo') +toolbar.top.insert(tollbarbutton_2, -1) + +toolbar.top.insert(gtk.SeparatorToolItem(), -1) + +tollbarbutton_3 = ToolbarButton(toolbar, gtk.Button('3'), + icon_name='activity-journal', + tooltip='foo') +toolbar.top.insert(tollbarbutton_3, -1) + +window.show_all() +gtk.main() diff --git a/m4/.gitignore b/m4/.gitignore index 9f841b0a..e08c7c8f 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -1 +1,3 @@ intltool.m4 +libtool.m4 +lt*.m4 diff --git a/src/sugar/__init__.py b/src/sugar/__init__.py new file mode 100644 index 00000000..44acb4d7 --- /dev/null +++ b/src/sugar/__init__.py @@ -0,0 +1,14 @@ +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. diff --git a/src/sugar/_sugarext.so b/src/sugar/_sugarext.so new file mode 120000 index 00000000..c11ccc78 --- /dev/null +++ b/src/sugar/_sugarext.so @@ -0,0 +1 @@ +.libs/_sugarext.so \ No newline at end of file From 4c8c845e6c8b9b54a4661e3323f9a79808795fcb Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sat, 11 Jul 2009 13:22:02 +0000 Subject: [PATCH 03/51] Add hpad prop for Toolbar; add expand_bg for ToolbarButton --- src/sugar/graphics/toolbar.py | 40 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index 9a7e396a..eb267266 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -22,14 +22,14 @@ from sugar.graphics import style from sugar.graphics.toolbutton import ToolButton class ToolbarButton(ToolButton): - def __init__(self, bar, page, **kwargs): + def __init__(self, bar, page, expand_bg=style.TOOLBAR_COLOR, **kwargs): ToolButton.__init__(self, **kwargs) - self.modify_bg(gtk.STATE_NORMAL, style.TOOLBAR_COLOR.get_gdk_color()) + self.modify_bg(gtk.STATE_NORMAL, expand_bg.get_gdk_color()) self._bar = bar - self._page = _align(_Box, page, style._FOCUS_LINE_WIDTH*3, - style.TOOLBAR_COLOR) + self._page = _align(_Box, page, bar._hpad, style._FOCUS_LINE_WIDTH*3, + expand_bg) self._page._toolitem = self page.show() @@ -87,11 +87,13 @@ class Toolbar(gtk.VBox): 'current-toolbar-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, ([int])) } - def __init__(self): + def __init__(self, hpad=style.TOOLBOX_HORIZONTAL_PADDING): gtk.VBox.__init__(self) self._bar = gtk.Toolbar() - toolbar = _align(gtk.EventBox, self._bar, 0, style.COLOR_TOOLBAR_GREY) + self._hpad = hpad + toolbar = _align(gtk.EventBox, self._bar, hpad, 0, + style.COLOR_TOOLBAR_GREY) self.pack_start(toolbar) self._notebook = gtk.Notebook() @@ -127,12 +129,7 @@ class Toolbar(gtk.VBox): class _Box(gtk.EventBox): def __init__(self): gtk.EventBox.__init__(self) - self._toolitem_alloc = gtk.gdk.Rectangle() - - self.modify_bg(gtk.STATE_PRELIGHT, style.TOOLBAR_COLOR.get_gdk_color()) - self.modify_bg(gtk.STATE_ACTIVE,style.COLOR_BUTTON_GREY.get_gdk_color()) - self.connect('expose-event', self.do_expose_event) self.set_app_paintable(True) @@ -148,18 +145,23 @@ class _Box(gtk.EventBox): self._toolitem_alloc.width - style._FOCUS_LINE_WIDTH*2, style._FOCUS_LINE_WIDTH) -def _align(box_class, widget, vpad, color): - top_pad = vpad - bottom_pad = vpad and vpad - style._FOCUS_LINE_WIDTH +def _align(box_class, widget, hpad, vpad, color): + widget.modify_bg(gtk.STATE_NORMAL, color.get_gdk_color()) - alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0) - alignment.set_padding(top_pad, bottom_pad, style.TOOLBOX_HORIZONTAL_PADDING, - style.TOOLBOX_HORIZONTAL_PADDING) - alignment.add(widget) - alignment.show() + if hpad or vpad: + top_pad = vpad + bottom_pad = vpad and vpad - style._FOCUS_LINE_WIDTH + alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0) + alignment.set_padding(top_pad, bottom_pad, hpad, hpad) + alignment.add(widget) + alignment.show() + else: + alignment = widget box = box_class() box.modify_bg(gtk.STATE_NORMAL, color.get_gdk_color()) + box.modify_bg(gtk.STATE_PRELIGHT, color.get_gdk_color()) + box.modify_bg(gtk.STATE_ACTIVE, style.COLOR_BUTTON_GREY.get_gdk_color()) box.add(alignment) box.show() From f9de29f53906b7851fef37f11425649aca323d7d Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sat, 11 Jul 2009 14:22:05 +0000 Subject: [PATCH 04/51] Delete sub-widgets clearly --- examples/toolbar.py | 12 ++++++++---- src/sugar/graphics/toolbar.py | 9 ++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/examples/toolbar.py b/examples/toolbar.py index e4d24dfd..36624c03 100644 --- a/examples/toolbar.py +++ b/examples/toolbar.py @@ -9,23 +9,27 @@ window.add(box) toolbar = Toolbar() box.pack_start(toolbar, False) -tollbarbutton_1 = ToolbarButton(toolbar, gtk.Button('1'), +tollbarbutton_1 = ToolbarButton(toolbar, gtk.Button('sub-widget #1'), icon_name='computer-xo', tooltip='foo') toolbar.top.insert(tollbarbutton_1, -1) toolbar.top.insert(gtk.SeparatorToolItem(), -1) -tollbarbutton_2 = ToolbarButton(toolbar, gtk.Button('1'), +tollbarbutton_2 = ToolbarButton(toolbar, gtk.Button('sub-widget #2'), icon_name='button_cancel', tooltip='foo') toolbar.top.insert(tollbarbutton_2, -1) toolbar.top.insert(gtk.SeparatorToolItem(), -1) -tollbarbutton_3 = ToolbarButton(toolbar, gtk.Button('3'), +def del_cb(widget): + toolbar.top.remove(tollbarbutton_3) +del_b = gtk.Button('delete sub-widget #3') +del_b.connect('clicked', del_cb) +tollbarbutton_3 = ToolbarButton(toolbar, del_b, icon_name='activity-journal', - tooltip='foo') + tooltip='del') toolbar.top.insert(tollbarbutton_3, -1) window.show_all() diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index eb267266..6423fa12 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -50,7 +50,7 @@ class ToolbarButton(ToolButton): return if value: expanded = self._bar._expanded_page() - if expanded: + if expanded and expanded._toolitem.window: expanded._toolitem.window.invalidate_rect(None, True) self._page._toolitem_alloc = self.allocation self._bar._expand_page(self._page) @@ -104,8 +104,15 @@ class Toolbar(gtk.VBox): self._notebook.connect('notify::page', lambda notebook, pspec: self.emit('current-toolbar-changed', notebook.props.page)) + self._bar.connect('remove', self._remove_cb) + top = property(lambda self: self._bar) + def _remove_cb(self, sender, widget): + if not isinstance(widget, ToolbarButton): + return + widget.expanded = False + def _remove_page(self, page): page = self._notebook.page_num(page) self._notebook.remove_page(page) From e256b96366e7d7e5a327b8c6f675c899065cd710 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sun, 12 Jul 2009 01:42:23 +0000 Subject: [PATCH 05/51] Implement palette mode --- examples/toolbar.py | 21 +-- src/sugar/graphics/toolbar.py | 289 ++++++++++++++++++++++++++++------ 2 files changed, 250 insertions(+), 60 deletions(-) diff --git a/examples/toolbar.py b/examples/toolbar.py index 36624c03..ad07f370 100644 --- a/examples/toolbar.py +++ b/examples/toolbar.py @@ -1,5 +1,7 @@ import gtk + from sugar.graphics.toolbar import Toolbar, ToolbarButton +from sugar.graphics import style window = gtk.Window() @@ -9,16 +11,15 @@ window.add(box) toolbar = Toolbar() box.pack_start(toolbar, False) -tollbarbutton_1 = ToolbarButton(toolbar, gtk.Button('sub-widget #1'), - icon_name='computer-xo', - tooltip='foo') +tollbarbutton_1 = ToolbarButton( + page=gtk.Button('sub-widget #1'), + icon_name='computer-xo') toolbar.top.insert(tollbarbutton_1, -1) -toolbar.top.insert(gtk.SeparatorToolItem(), -1) - -tollbarbutton_2 = ToolbarButton(toolbar, gtk.Button('sub-widget #2'), +tollbarbutton_2 = ToolbarButton( + page=gtk.Button('sub-widget #2'), icon_name='button_cancel', - tooltip='foo') + tooltip='with custom palette instead of sub-widget') toolbar.top.insert(tollbarbutton_2, -1) toolbar.top.insert(gtk.SeparatorToolItem(), -1) @@ -27,9 +28,9 @@ def del_cb(widget): toolbar.top.remove(tollbarbutton_3) del_b = gtk.Button('delete sub-widget #3') del_b.connect('clicked', del_cb) -tollbarbutton_3 = ToolbarButton(toolbar, del_b, - icon_name='activity-journal', - tooltip='del') +tollbarbutton_3 = ToolbarButton( + page=del_b, + icon_name='activity-journal') toolbar.top.insert(tollbarbutton_3, -1) window.show_all() diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index 6423fa12..dd14ca48 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -20,42 +20,65 @@ from gobject import SIGNAL_RUN_FIRST, TYPE_NONE from sugar.graphics import style from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.palette import _PopupAnimation, _PopdownAnimation +from sugar.graphics.palette import MouseSpeedDetector, Invoker +from sugar.graphics import animator class ToolbarButton(ToolButton): - def __init__(self, bar, page, expand_bg=style.TOOLBAR_COLOR, **kwargs): + def __init__(self, **kwargs): + self._page = None + ToolButton.__init__(self, **kwargs) - self.modify_bg(gtk.STATE_NORMAL, expand_bg.get_gdk_color()) - - self._bar = bar - self._page = _align(_Box, page, bar._hpad, style._FOCUS_LINE_WIDTH*3, - expand_bg) - self._page._toolitem = self - page.show() - - bar._notebook.append_page(self._page) + if self.palette is None: + self.palette = _Palette(self) self.connect('clicked', lambda widget: self.set_expanded(not self.expanded)) - self.connect('destroy', self.__destroy_cb) - def __destroy_cb(self, widget): - self._bar._remove_page(self._page) + def get_toolbar(self): + if not hasattr(self.parent, 'owner'): + return None + return self.parent.owner + + toolbar = property(get_toolbar) + + def get_page(self): + return self._page.get_child() + + def set_page(self, page): + self._page = _align(_Box, page, 0, style._FOCUS_LINE_WIDTH*3) + self._page._toolitem = self + page.show() + + page = gobject.property(type=object, getter=get_page, setter=set_page) def get_expanded(self): - return self._bar._expanded_page() == self._page + return bool(self.toolbar) and bool(self._page) and \ + self.toolbar._expanded_page() == self._page def set_expanded(self, value): - if self.get_expanded() == value: + if not self.toolbar or not self._page or self.get_expanded() == value: return - if value: - expanded = self._bar._expanded_page() - if expanded and expanded._toolitem.window: - expanded._toolitem.window.invalidate_rect(None, True) - self._page._toolitem_alloc = self.allocation - self._bar._expand_page(self._page) - else: - self._bar._shrink_page() + + if isinstance(self.palette, _Palette) and self.palette.is_up(): + self.palette.popdown(immediate=True) + + if not value: + self.toolbar._shrink_page(self._page) + return + + expanded = self.toolbar._expanded_page() + if expanded and expanded._toolitem.window: + expanded._toolitem.window.invalidate_rect(None, True) + + if self._page.parent: + self.palette.remove(self._page) + + self.modify_bg(gtk.STATE_NORMAL, self.toolbar._bg) + + self._page._toolitem_alloc = self.allocation + self.toolbar._expand_page(self._page) expanded = property(get_expanded, set_expanded) @@ -65,18 +88,21 @@ class ToolbarButton(ToolButton): if not self.expanded or self.palette and self.palette.is_up(): ToolButton.do_expose_event(self, event) - _paint_arrow(self, event, gtk.ARROW_UP) + if self.palette and self.palette.is_up(): + _paint_arrow(self, event, gtk.ARROW_DOWN) + else: + _paint_arrow(self, event, gtk.ARROW_UP) return self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, - 'palette-invoker', alloc.x, -style._FOCUS_LINE_WIDTH, - alloc.width, alloc.height + style._FOCUS_LINE_WIDTH*2) + 'palette-invoker', alloc.x, 0, + alloc.width, alloc.height + style._FOCUS_LINE_WIDTH) if child.state != gtk.STATE_PRELIGHT: self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, None, - alloc.x + style._FOCUS_LINE_WIDTH, 0, + alloc.x + style._FOCUS_LINE_WIDTH, style._FOCUS_LINE_WIDTH, alloc.width - style._FOCUS_LINE_WIDTH*2, alloc.height) gtk.ToolButton.do_expose_event(self, event) @@ -90,11 +116,13 @@ class Toolbar(gtk.VBox): def __init__(self, hpad=style.TOOLBOX_HORIZONTAL_PADDING): gtk.VBox.__init__(self) - self._bar = gtk.Toolbar() - self._hpad = hpad - toolbar = _align(gtk.EventBox, self._bar, hpad, 0, - style.COLOR_TOOLBAR_GREY) - self.pack_start(toolbar) + self._top = gtk.Toolbar() + self._top.owner = self + self._top_widget = _align(gtk.EventBox, self._top, hpad, 0) + self.pack_start(self._top_widget) + + self.modify_bg(gtk.STATE_NORMAL, + style.COLOR_TOOLBAR_GREY.get_gdk_color()) self._notebook = gtk.Notebook() self._notebook.set_show_border(False) @@ -104,18 +132,22 @@ class Toolbar(gtk.VBox): self._notebook.connect('notify::page', lambda notebook, pspec: self.emit('current-toolbar-changed', notebook.props.page)) - self._bar.connect('remove', self._remove_cb) + self._top.connect('remove', self._remove_cb) - top = property(lambda self: self._bar) + top = property(lambda self: self._top) + + def modify_bg(self, state, color): + if state == gtk.STATE_NORMAL: + self._bg = color + self._top_widget.modify_bg(state, color) + self._top.modify_bg(state, color) def _remove_cb(self, sender, widget): if not isinstance(widget, ToolbarButton): return - widget.expanded = False - - def _remove_page(self, page): - page = self._notebook.page_num(page) - self._notebook.remove_page(page) + page_no = self._notebook.page_num(widget._page) + if page_no != -1: + self._notebook.remove_page(page_no) def _expanded_page(self): if self._notebook.parent is None: @@ -123,13 +155,18 @@ class Toolbar(gtk.VBox): page_no = self._notebook.get_current_page() return self._notebook.get_nth_page(page_no) - def _shrink_page(self): + def _shrink_page(self, page): + page_no = self._notebook.page_num(page) + if page_no == -1: + return + self._notebook.remove_page(page_no) self.remove(self._notebook) def _expand_page(self, page): - page_no = self._notebook.page_num(page) - self._notebook.set_current_page(page_no) - + for i in range(self._notebook.get_n_pages()): + self._notebook.remove_page(0) + _modify_bg(page, self._bg) + self._notebook.append_page(page) if self._notebook.parent is None: self.pack_start(self._notebook) @@ -152,9 +189,164 @@ class _Box(gtk.EventBox): self._toolitem_alloc.width - style._FOCUS_LINE_WIDTH*2, style._FOCUS_LINE_WIDTH) -def _align(box_class, widget, hpad, vpad, color): - widget.modify_bg(gtk.STATE_NORMAL, color.get_gdk_color()) +class _Palette(gtk.Window): + def __init__(self, toolitem, **kwargs): + gobject.GObject.__init__(self, **kwargs) + self.set_decorated(False) + self.set_resizable(False) + self.set_border_width(0) + + self._toolitem = toolitem + self._invoker = None + self._up = False + self._invoker_hids = [] + + self._popup_anim = animator.Animator(.5, 10) + self._popup_anim.add(_PopupAnimation(self)) + + self._popdown_anim = animator.Animator(0.6, 10) + self._popdown_anim.add(_PopdownAnimation(self)) + + accel_group = gtk.AccelGroup() + self.set_data('sugar-accel-group', accel_group) + self.add_accel_group(accel_group) + + self.connect('show', self.__show_cb) + self.connect('hide', self.__hide_cb) + self.connect('realize', self.__realize_cb) + self.connect('enter-notify-event', self.__enter_notify_event_cb) + self.connect('leave-notify-event', self.__leave_notify_event_cb) + + self._mouse_detector = MouseSpeedDetector(self, 200, 5) + self._mouse_detector.connect('motion-slow', self._mouse_slow_cb) + + def is_up(self): + return self._up + + def get_rect(self): + win_x, win_y = self.window.get_origin() + rectangle = self.get_allocation() + + x = win_x + rectangle.x + y = win_y + rectangle.y + width = rectangle.width + height = rectangle.height + + return gtk.gdk.Rectangle(x, y, width, height) + + def set_invoker(self, invoker): + for hid in self._invoker_hids[:]: + self._invoker.disconnect(hid) + self._invoker_hids.remove(hid) + + self._invoker = invoker + if invoker is not None: + self._invoker_hids.append(self._invoker.connect( + 'mouse-enter', self._invoker_mouse_enter_cb)) + self._invoker_hids.append(self._invoker.connect( + 'mouse-leave', self._invoker_mouse_leave_cb)) + self._invoker_hids.append(self._invoker.connect( + 'right-click', self._invoker_right_click_cb)) + + def get_invoker(self): + return self._invoker + + invoker = gobject.property(type=object, + getter=get_invoker, + setter=set_invoker) + + def do_size_request(self, requisition): + gtk.Window.do_size_request(self, requisition) + if self._toolitem.toolbar: + requisition.width = self._toolitem.toolbar.allocation.width + + def __realize_cb(self, widget): + self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) + #accept_focus = len(self._content.get_children()) + #if self.window: + # self.window.set_accept_focus(accept_focus) + + + def popup(self, immediate=False): + self._popdown_anim.stop() + + toolbar = self._toolitem.toolbar + page = self._toolitem._page + + if not self._invoker or self._toolitem.expanded or not toolbar: + return + + page._toolitem_alloc = self._toolitem.allocation + _modify_bg(page, style.COLOR_BLACK.get_gdk_color()) + if self.get_child() is None: + self.add(page) + + x, y = toolbar.window.get_origin() + self.move(x + toolbar.allocation.x, y + toolbar.top.allocation.height) + self.set_transient_for(self._invoker.get_toplevel()) + + if not immediate: + self._popup_anim.start() + else: + self.show() + + def popdown(self, immediate=False): + self._popup_anim.stop() + self._mouse_detector.stop() + + if not immediate: + self._popdown_anim.start() + else: + self.hide() + + def _mouse_slow_cb(self, widget): + self._mouse_detector.stop() + + if self.is_up(): + self._popdown_anim.stop() + return + + self.popup(immediate=False) + + def _invoker_mouse_enter_cb(self, invoker): + self._mouse_detector.start() + + def _invoker_mouse_leave_cb(self, invoker): + self._mouse_detector.stop() + self.popdown() + + def _invoker_right_click_cb(self, invoker): + self.popup(immediate=True) + + def __enter_notify_event_cb(self, widget, event): + if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ + event.mode == gtk.gdk.CROSSING_NORMAL: + self._popdown_anim.stop() + + def __leave_notify_event_cb(self, widget, event): + if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ + event.mode == gtk.gdk.CROSSING_NORMAL: + self.popdown() + + def __show_cb(self, widget): + self._invoker.notify_popup() + self._up = True + + def __hide_cb(self, widget): + if self._invoker: + self._invoker.notify_popdown() + self._up = False + +def _modify_bg(page, color): + child = page.get_child() + if isinstance(child, gtk.Alignment): + child = child.get_child() + child.modify_bg(gtk.STATE_NORMAL, color) + page.modify_bg(gtk.STATE_NORMAL, color) + page.modify_bg(gtk.STATE_PRELIGHT, color) + +def _align(box_class, widget, hpad, vpad): if hpad or vpad: top_pad = vpad bottom_pad = vpad and vpad - style._FOCUS_LINE_WIDTH @@ -162,14 +354,11 @@ def _align(box_class, widget, hpad, vpad, color): alignment.set_padding(top_pad, bottom_pad, hpad, hpad) alignment.add(widget) alignment.show() - else: - alignment = widget + widget = alignment box = box_class() - box.modify_bg(gtk.STATE_NORMAL, color.get_gdk_color()) - box.modify_bg(gtk.STATE_PRELIGHT, color.get_gdk_color()) box.modify_bg(gtk.STATE_ACTIVE, style.COLOR_BUTTON_GREY.get_gdk_color()) - box.add(alignment) + box.add(widget) box.show() return box From 82785558d4f40f8f5e6d978751203c218f59bae5 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sun, 12 Jul 2009 04:32:51 +0000 Subject: [PATCH 06/51] Use padding property for top toolbar and all sub-widgets --- src/sugar/graphics/toolbar.py | 75 ++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index dd14ca48..2bdd94b1 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -44,10 +44,10 @@ class ToolbarButton(ToolButton): toolbar = property(get_toolbar) def get_page(self): - return self._page.get_child() + return self._page.child.child def set_page(self, page): - self._page = _align(_Box, page, 0, style._FOCUS_LINE_WIDTH*3) + self._page = _align(_Box, page) self._page._toolitem = self page.show() @@ -77,15 +77,11 @@ class ToolbarButton(ToolButton): self.modify_bg(gtk.STATE_NORMAL, self.toolbar._bg) - self._page._toolitem_alloc = self.allocation self.toolbar._expand_page(self._page) expanded = property(get_expanded, set_expanded) def do_expose_event(self, event): - child = self.get_child() - alloc = self.allocation - if not self.expanded or self.palette and self.palette.is_up(): ToolButton.do_expose_event(self, event) if self.palette and self.palette.is_up(): @@ -94,12 +90,14 @@ class ToolbarButton(ToolButton): _paint_arrow(self, event, gtk.ARROW_UP) return + alloc = self.allocation + self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, 'palette-invoker', alloc.x, 0, alloc.width, alloc.height + style._FOCUS_LINE_WIDTH) - if child.state != gtk.STATE_PRELIGHT: + if self.child.state != gtk.STATE_PRELIGHT: self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, None, alloc.x + style._FOCUS_LINE_WIDTH, style._FOCUS_LINE_WIDTH, @@ -113,14 +111,16 @@ class Toolbar(gtk.VBox): 'current-toolbar-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, ([int])) } - def __init__(self, hpad=style.TOOLBOX_HORIZONTAL_PADDING): + def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING): gtk.VBox.__init__(self) self._top = gtk.Toolbar() self._top.owner = self - self._top_widget = _align(gtk.EventBox, self._top, hpad, 0) - self.pack_start(self._top_widget) + top_widget = _align(gtk.EventBox, self._top) + self.pack_start(top_widget) + + self.props.padding = padding self.modify_bg(gtk.STATE_NORMAL, style.COLOR_TOOLBAR_GREY.get_gdk_color()) @@ -136,10 +136,19 @@ class Toolbar(gtk.VBox): top = property(lambda self: self._top) + def get_padding(self): + return self._top.parent.props.left_padding + + def set_padding(self, pad): + self._top.parent.set_padding(0, 0, pad, pad) + + padding = gobject.property(type=object, + getter=get_padding, setter=set_padding) + def modify_bg(self, state, color): if state == gtk.STATE_NORMAL: self._bg = color - self._top_widget.modify_bg(state, color) + self._top.parent.parent.modify_bg(state, color) self._top.modify_bg(state, color) def _remove_cb(self, sender, widget): @@ -165,19 +174,21 @@ class Toolbar(gtk.VBox): def _expand_page(self, page): for i in range(self._notebook.get_n_pages()): self._notebook.remove_page(0) - _modify_bg(page, self._bg) + + _setup_page(page, self._bg, self.props.padding) self._notebook.append_page(page) + if self._notebook.parent is None: self.pack_start(self._notebook) class _Box(gtk.EventBox): def __init__(self): gtk.EventBox.__init__(self) - self._toolitem_alloc = gtk.gdk.Rectangle() self.connect('expose-event', self.do_expose_event) self.set_app_paintable(True) def do_expose_event(self, widget, event): + a = self._toolitem.allocation self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, 'palette-invoker', -style._FOCUS_LINE_WIDTH, 0, @@ -185,9 +196,8 @@ class _Box(gtk.EventBox): self.allocation.height + style._FOCUS_LINE_WIDTH) self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, None, - self._toolitem_alloc.x + style._FOCUS_LINE_WIDTH, 0, - self._toolitem_alloc.width - style._FOCUS_LINE_WIDTH*2, - style._FOCUS_LINE_WIDTH) + a.x + style._FOCUS_LINE_WIDTH, 0, + a.width - style._FOCUS_LINE_WIDTH*2, style._FOCUS_LINE_WIDTH) class _Palette(gtk.Window): def __init__(self, toolitem, **kwargs): @@ -277,9 +287,9 @@ class _Palette(gtk.Window): if not self._invoker or self._toolitem.expanded or not toolbar: return - page._toolitem_alloc = self._toolitem.allocation - _modify_bg(page, style.COLOR_BLACK.get_gdk_color()) - if self.get_child() is None: + _setup_page(page, style.COLOR_BLACK.get_gdk_color(), + toolbar.props.padding) + if self.child is None: self.add(page) x, y = toolbar.window.get_origin() @@ -338,29 +348,22 @@ class _Palette(gtk.Window): self._invoker.notify_popdown() self._up = False -def _modify_bg(page, color): - child = page.get_child() - if isinstance(child, gtk.Alignment): - child = child.get_child() - child.modify_bg(gtk.STATE_NORMAL, color) +def _setup_page(page, color, hpad): + vpad = style._FOCUS_LINE_WIDTH*3 + page.child.set_padding(vpad, vpad, hpad, hpad) + page.child.child.modify_bg(gtk.STATE_NORMAL, color) page.modify_bg(gtk.STATE_NORMAL, color) page.modify_bg(gtk.STATE_PRELIGHT, color) -def _align(box_class, widget, hpad, vpad): - if hpad or vpad: - top_pad = vpad - bottom_pad = vpad and vpad - style._FOCUS_LINE_WIDTH - alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0) - alignment.set_padding(top_pad, bottom_pad, hpad, hpad) - alignment.add(widget) - alignment.show() - widget = alignment - +def _align(box_class, widget): + widget.show() + alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0) + alignment.add(widget) + alignment.show() box = box_class() box.modify_bg(gtk.STATE_ACTIVE, style.COLOR_BUTTON_GREY.get_gdk_color()) - box.add(widget) + box.add(alignment) box.show() - return box def _paint_arrow(widget, event, type): From ff87ce76e5516e41c540c2b1000c73421746cd95 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sun, 12 Jul 2009 04:38:13 +0000 Subject: [PATCH 07/51] Close palette while removing ToolbarButton --- src/sugar/graphics/toolbar.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index 2bdd94b1..161de0bc 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -157,6 +157,8 @@ class Toolbar(gtk.VBox): page_no = self._notebook.page_num(widget._page) if page_no != -1: self._notebook.remove_page(page_no) + if widget.palette: + widget.palette.popdown(immediate=True) def _expanded_page(self): if self._notebook.parent is None: From 55609885de00509097af840427f1688bb68b136a Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Mon, 13 Jul 2009 00:32:26 +0000 Subject: [PATCH 08/51] Add radiopalette.py --- examples/radiopalette.py | 57 +++++++++++++ src/sugar/graphics/radiopalette.py | 128 +++++++++++++++++++++++++++++ src/sugar/graphics/toolbutton.py | 6 +- 3 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 examples/radiopalette.py create mode 100644 src/sugar/graphics/radiopalette.py diff --git a/examples/radiopalette.py b/examples/radiopalette.py new file mode 100644 index 00000000..eb868313 --- /dev/null +++ b/examples/radiopalette.py @@ -0,0 +1,57 @@ +import gtk + +from sugar.graphics.radiopalette import RadioPalette, RadioMenuButton, \ + RadioToolsButton +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics import style + +window = gtk.Window() + +box = gtk.VBox() +window.add(box) + +toolbar = gtk.Toolbar() +box.pack_start(toolbar, False) + +text_view = gtk.TextView() +box.pack_start(text_view) + +def echo(text): + text_view.props.buffer.props.text += "\n" + text + +palette = RadioPalette() +palette.append( + icon_name='document-open', + tooltip='menu.document-open', + toggled_cb=lambda: echo('menu.document-open')) +palette.append( + icon_name='document-save', + tooltip='menu.document-save', + toggled_cb=lambda: echo('menu.document-save')) +palette.append( + icon_name='document-send', + tooltip='menu.document-send', + toggled_cb=lambda: echo('menu.document-send')) + +button = RadioMenuButton(palette=palette) +toolbar.insert(button, -1) + +palette = RadioPalette() +palette.append( + icon_name='document-open', + tooltip='tools.document-open', + toggled_cb=lambda: echo('tools.document-open')) +palette.append( + icon_name='document-save', + tooltip='tools.document-save', + toggled_cb=lambda: echo('tools.document-save')) +palette.append( + icon_name='document-send', + tooltip='tools.document-send', + toggled_cb=lambda: echo('tools.document-send')) + +button = RadioToolsButton(palette=palette) +toolbar.insert(button, -1) + +window.show_all() +gtk.main() diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py new file mode 100644 index 00000000..2adaa0e8 --- /dev/null +++ b/src/sugar/graphics/radiopalette.py @@ -0,0 +1,128 @@ +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import gtk +import gobject +import logging +from gobject import SIGNAL_RUN_FIRST, TYPE_NONE + +from sugar.graphics import style +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.palette import Palette +from sugar.graphics.radiotoolbutton import RadioToolButton + +class RadioPaletteButton(ToolButton): + def __init__(self, **kwargs): + ToolButton.__init__(self, **kwargs) + + self._button_cb = None + + if self.props.palette: + self.__palette_cb(None, None) + + self.connect('notify::palette', self.__palette_cb) + + def __palette_cb(self, widget, pspec): + if not isinstance(self.props.palette, RadioPalette): + return + self.props.palette.update_button() + + def _set_current_button(self, button): + self.set_icon(button.rp_icon_name) + self._button_cb = button.rp_toggled_cb + +class RadioMenuButton(RadioPaletteButton): + def __init__(self, **kwargs): + RadioPaletteButton.__init__(self, **kwargs) + + def do_clicked(self): + if not self.palette: + return + if self.palette.is_up() and \ + self.palette.palette_state == Palette.SECONDARY: + self.palette.popdown(immediate=True) + else: + self.palette.popup(immediate=True, state=Palette.SECONDARY) + + def do_expose_event(self, event): + ToolButton.do_expose_event(self, event) + if not self.palette: + return + + if self.palette.is_up(): + type = gtk.ARROW_DOWN + else: + type = gtk.ARROW_UP + + a = self.allocation + self.get_style().paint_arrow(event.window, + gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, + None, type, True, + a.x + a.width/2 - style.TOOLBAR_ARROW_SIZE/2, + a.y + a.height - style.TOOLBAR_ARROW_SIZE - \ + style._FOCUS_LINE_WIDTH, + style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) + +class RadioToolsButton(RadioPaletteButton): + def __init__(self, **kwargs): + RadioPaletteButton.__init__(self, **kwargs) + + def do_clicked(self): + if not self._button_cb: + return + self._button_cb() + +class RadioPalette(Palette): + def __init__(self, **kwargs): + Palette.__init__(self, **kwargs) + + self.top = gtk.HBox() + self.top.show() + self.set_content(self.top) + + def append(self, icon_name, tooltip=None, toggled_cb=None): + children = self.top.get_children() + button = RadioToolButton(icon_name=icon_name, + group=children and children[0] or None) + button.show() + button.connect('toggled', self.__toggled_cb) + self.top.pack_start(button, fill=False) + + button.rp_icon_name = icon_name + button.rp_tooltip = tooltip + button.rp_toggled_cb = toggled_cb + + if not children: + self.__toggled_cb(button, True) + + def update_button(self): + for i in self.top.get_children(): + self.__toggled_cb(i, True) + + def __toggled_cb(self, button, quiet=False): + if not button.get_active(): + return + + self.set_primary_text(button.rp_tooltip) + if not quiet: + if button.rp_toggled_cb: + button.rp_toggled_cb() + self.popdown(immediate=True) + + if not self.invoker or \ + not isinstance(self.invoker.parent, RadioPaletteButton): + return + + self.invoker.parent._set_current_button(button) diff --git a/src/sugar/graphics/toolbutton.py b/src/sugar/graphics/toolbutton.py index 6205b8a4..047df067 100644 --- a/src/sugar/graphics/toolbutton.py +++ b/src/sugar/graphics/toolbutton.py @@ -68,7 +68,6 @@ class ToolButton(gtk.ToolButton): if icon_name: self.set_icon(icon_name) - self.connect('clicked', self.__button_clicked_cb) self.get_child().connect('can-activate-accel', self.__button_can_activate_accel_cb) @@ -151,8 +150,7 @@ class ToolButton(gtk.ToolButton): allocation.width, allocation.height) gtk.ToolButton.do_expose_event(self, event) - - def __button_clicked_cb(self, widget): + + def do_clicked(self): if self.palette: self.palette.popdown(True) - From 442034bb8b5deb9706d51f1343b3524737b3d4d4 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Mon, 13 Jul 2009 01:40:23 +0000 Subject: [PATCH 09/51] Support new toolbars widgets in activity.py --- src/sugar/activity/activity.py | 85 +++++++++++++++++++++--------- src/sugar/graphics/radiopalette.py | 2 + 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index 9809928a..fb523a90 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -73,6 +73,7 @@ from sugar.graphics.toolcombobox import ToolComboBox from sugar.graphics.alert import Alert from sugar.graphics.icon import Icon from sugar.graphics.xocolor import XoColor +from sugar.graphics.toolbar import Toolbar, ToolbarButton from sugar.datastore import datastore from sugar.session import XSMPClient from sugar import wm @@ -94,7 +95,7 @@ class ActivityToolbar(gtk.Toolbar): All activities should have this toolbar. It is easiest to add it to your Activity by using the ActivityToolbox. """ - def __init__(self, activity): + def __init__(self, activity, hide_stop=False): gtk.Toolbar.__init__(self) self._activity = activity @@ -141,11 +142,9 @@ class ActivityToolbar(gtk.Toolbar): self.insert(self.keep, -1) self.keep.show() - self.stop = ToolButton('activity-stop', tooltip=_('Stop')) - self.stop.props.accelerator = 'Q' - self.stop.connect('clicked', self.__stop_clicked_cb) - self.insert(self.stop, -1) - self.stop.show() + if not hide_stop: + stop = stop_button(activity) + self.insert(stop, -1) self._update_title_sid = None @@ -177,9 +176,6 @@ class ActivityToolbar(gtk.Toolbar): def __keep_clicked_cb(self, button): self._activity.copy() - def __stop_clicked_cb(self, button): - self._activity.close() - def __jobject_updated_cb(self, jobject): self.title.set_text(jobject['title']) @@ -254,30 +250,20 @@ class EditToolbar(gtk.Toolbar): def __init__(self): gtk.Toolbar.__init__(self) - self.undo = ToolButton('edit-undo') - self.undo.set_tooltip(_('Undo')) + self.undo = undo_button() self.insert(self.undo, -1) - self.undo.show() - self.redo = ToolButton('edit-redo') - self.redo.set_tooltip(_('Redo')) + self.redo = redo_button() self.insert(self.redo, -1) - self.redo.show() - self.separator = gtk.SeparatorToolItem() - self.separator.set_draw(True) + self.separator = separator() self.insert(self.separator, -1) - self.separator.show() - self.copy = ToolButton('edit-copy') - self.copy.set_tooltip(_('Copy')) + self.copy = copy_button() self.insert(self.copy, -1) - self.copy.show() - self.paste = ToolButton('edit-paste') - self.paste.set_tooltip(_('Paste')) + self.paste = paste_button() self.insert(self.paste, -1) - self.paste.show() class ActivityToolbox(Toolbox): """Creates the Toolbox for the Activity @@ -1061,3 +1047,54 @@ def show_object_in_journal(object_id): obj = bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH) journal = dbus.Interface(obj, J_DBUS_INTERFACE) journal.ShowObject(object_id) + +def toolbar(activity): + activity_button = ToolbarButton( + page=ActivityToolbar(activity, hide_stop=True), + icon_name='computer-xo') + activity_button.show() + return activity_button + +def expander(): + separator = gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + separator.show() + return separator + +def stop_button(activity, **kwargs): + stop = ToolButton('activity-stop', tooltip=_('Stop'), **kwargs) + stop.props.accelerator = 'Q' + stop.connect('clicked', lambda button: activity.close()) + stop.show() + return stop + +def undo_button(**kwargs): + undo = ToolButton('edit-undo', **kwargs) + undo.set_tooltip(_('Undo')) + undo.show() + return undo + +def redo_button(**kwargs): + redo = ToolButton('edit-redo', **kwargs) + redo.set_tooltip(_('Redo')) + redo.show() + return redo + +def separator(**kwargs): + separator = gtk.SeparatorToolItem(**kwargs) + separator.set_draw(True) + separator.show() + return separator + +def copy_button(**kwargs): + copy = ToolButton('edit-copy', **kwargs) + copy.set_tooltip(_('Copy')) + copy.show() + return copy + +def paste_button(**kwargs): + paste = ToolButton('edit-paste', **kwargs) + paste.set_tooltip(_('Paste')) + paste.show() + return paste diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index 2adaa0e8..c9387dd8 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -107,6 +107,8 @@ class RadioPalette(Palette): if not children: self.__toggled_cb(button, True) + return button + def update_button(self): for i in self.top.get_children(): self.__toggled_cb(i, True) From 44a8ecd8363960b16fa1fe522fc2fb539d939784 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Mon, 13 Jul 2009 01:57:27 +0000 Subject: [PATCH 10/51] Do not add extra vertical padding to sub-widgets --- src/sugar/graphics/toolbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index 161de0bc..131bd9d7 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -351,7 +351,7 @@ class _Palette(gtk.Window): self._up = False def _setup_page(page, color, hpad): - vpad = style._FOCUS_LINE_WIDTH*3 + vpad = style._FOCUS_LINE_WIDTH page.child.set_padding(vpad, vpad, hpad, hpad) page.child.child.modify_bg(gtk.STATE_NORMAL, color) page.modify_bg(gtk.STATE_NORMAL, color) From 5d2c5b98fff34eed18f7aede574fe2eeea8cd664 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Mon, 13 Jul 2009 02:58:49 +0000 Subject: [PATCH 11/51] Do not hide sub-widget when sub-palette was opened --- examples/toolbar.py | 13 ++++++++++++ src/sugar/graphics/toolbar.py | 37 +++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/examples/toolbar.py b/examples/toolbar.py index ad07f370..66c09f09 100644 --- a/examples/toolbar.py +++ b/examples/toolbar.py @@ -1,5 +1,6 @@ import gtk +from sugar.graphics.toolbutton import ToolButton from sugar.graphics.toolbar import Toolbar, ToolbarButton from sugar.graphics import style @@ -33,5 +34,17 @@ tollbarbutton_3 = ToolbarButton( icon_name='activity-journal') toolbar.top.insert(tollbarbutton_3, -1) +subbar = gtk.Toolbar() +subbutton = ToolButton( + icon_name='document-send', + tooltip='document-send') +subbar.insert(subbutton, -1) +subbar.show_all() + +tollbarbutton_4 = ToolbarButton( + page=subbar, + icon_name='document-save') +toolbar.top.insert(tollbarbutton_4, -1) + window.show_all() gtk.main() diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index 131bd9d7..c675bf92 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -23,6 +23,7 @@ from sugar.graphics.toolbutton import ToolButton from sugar.graphics.palette import _PopupAnimation, _PopdownAnimation from sugar.graphics.palette import MouseSpeedDetector, Invoker from sugar.graphics import animator +from sugar.graphics import palettegroup class ToolbarButton(ToolButton): def __init__(self, **kwargs): @@ -213,6 +214,7 @@ class _Palette(gtk.Window): self._invoker = None self._up = False self._invoker_hids = [] + self.__focus = 0 self._popup_anim = animator.Animator(.5, 10) self._popup_anim.add(_PopupAnimation(self)) @@ -233,6 +235,9 @@ class _Palette(gtk.Window): self._mouse_detector = MouseSpeedDetector(self, 200, 5) self._mouse_detector.connect('motion-slow', self._mouse_slow_cb) + group = palettegroup.get_group('default') + group.connect('popdown', self.__group_popdown_cb) + def is_up(self): return self._up @@ -255,11 +260,11 @@ class _Palette(gtk.Window): self._invoker = invoker if invoker is not None: self._invoker_hids.append(self._invoker.connect( - 'mouse-enter', self._invoker_mouse_enter_cb)) + 'mouse-enter', self.__invoker_mouse_enter_cb)) self._invoker_hids.append(self._invoker.connect( - 'mouse-leave', self._invoker_mouse_leave_cb)) + 'mouse-leave', self.__invoker_mouse_leave_cb)) self._invoker_hids.append(self._invoker.connect( - 'right-click', self._invoker_right_click_cb)) + 'right-click', self.__invoker_right_click_cb)) def get_invoker(self): return self._invoker @@ -321,25 +326,41 @@ class _Palette(gtk.Window): self.popup(immediate=False) - def _invoker_mouse_enter_cb(self, invoker): + def __handle_focus(self, delta): + self.__focus += delta + if self.__focus not in (0, 1): + logging.error('_Palette.__focus=%s not in (0, 1)' % self.__focus) + + if self.__focus == 0: + group = palettegroup.get_group('default') + if not group.is_up(): + self.popdown() + + def __group_popdown_cb(self, group): + if self.__focus == 0: + self.popdown(immediate=True) + + def __invoker_mouse_enter_cb(self, invoker): self._mouse_detector.start() + self.__handle_focus(+1) - def _invoker_mouse_leave_cb(self, invoker): + def __invoker_mouse_leave_cb(self, invoker): self._mouse_detector.stop() - self.popdown() + self.__handle_focus(-1) - def _invoker_right_click_cb(self, invoker): + def __invoker_right_click_cb(self, invoker): self.popup(immediate=True) def __enter_notify_event_cb(self, widget, event): if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ event.mode == gtk.gdk.CROSSING_NORMAL: self._popdown_anim.stop() + self.__handle_focus(+1) def __leave_notify_event_cb(self, widget, event): if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ event.mode == gtk.gdk.CROSSING_NORMAL: - self.popdown() + self.__handle_focus(-1) def __show_cb(self, widget): self._invoker.notify_popup() From 165b9e1e05a82a43dc077383979aedc24e474f28 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Mon, 13 Jul 2009 03:11:39 +0000 Subject: [PATCH 12/51] Provide fast access to all sub-widgets in Toolbar --- examples/toolbar.py | 2 ++ src/sugar/graphics/toolbar.py | 67 ++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/examples/toolbar.py b/examples/toolbar.py index 66c09f09..6150be36 100644 --- a/examples/toolbar.py +++ b/examples/toolbar.py @@ -46,5 +46,7 @@ tollbarbutton_4 = ToolbarButton( icon_name='document-save') toolbar.top.insert(tollbarbutton_4, -1) +print [i.props.page for i in toolbar.subs] + window.show_all() gtk.main() diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index c675bf92..3ae1bb29 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -115,74 +115,84 @@ class Toolbar(gtk.VBox): def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING): gtk.VBox.__init__(self) - self._top = gtk.Toolbar() - self._top.owner = self + self.__top = gtk.Toolbar() + self.__top.owner = self - top_widget = _align(gtk.EventBox, self._top) + top_widget = _align(gtk.EventBox, self.__top) self.pack_start(top_widget) self.props.padding = padding self.modify_bg(gtk.STATE_NORMAL, style.COLOR_TOOLBAR_GREY.get_gdk_color()) - self._notebook = gtk.Notebook() - self._notebook.set_show_border(False) - self._notebook.set_show_tabs(False) - self._notebook.show() + self.__notebook = gtk.Notebook() + self.__notebook.set_show_border(False) + self.__notebook.set_show_tabs(False) + self.__notebook.show() - self._notebook.connect('notify::page', lambda notebook, pspec: + self.__notebook.connect('notify::page', lambda notebook, pspec: self.emit('current-toolbar-changed', notebook.props.page)) - self._top.connect('remove', self._remove_cb) + self.__top.connect('remove', self.__remove_cb) - top = property(lambda self: self._top) + top = property(lambda self: self.__top) def get_padding(self): - return self._top.parent.props.left_padding + return self.__top.parent.props.left_padding def set_padding(self, pad): - self._top.parent.set_padding(0, 0, pad, pad) + self.__top.parent.set_padding(0, 0, pad, pad) padding = gobject.property(type=object, getter=get_padding, setter=set_padding) + def get_subs(self): + out = [] + for i in range(self.top.get_n_items()): + page = self.top.get_nth_item(i) + if isinstance(page, ToolbarButton): + out.append(page) + return out + + subs = property(get_subs) + def modify_bg(self, state, color): if state == gtk.STATE_NORMAL: self._bg = color - self._top.parent.parent.modify_bg(state, color) - self._top.modify_bg(state, color) + self.__top.parent.parent.modify_bg(state, color) + self.__top.modify_bg(state, color) - def _remove_cb(self, sender, widget): + def __remove_cb(self, sender, widget): if not isinstance(widget, ToolbarButton): return - page_no = self._notebook.page_num(widget._page) + page_no = self.__notebook.page_num(widget._page) if page_no != -1: - self._notebook.remove_page(page_no) + self.__notebook.remove_page(page_no) if widget.palette: widget.palette.popdown(immediate=True) def _expanded_page(self): - if self._notebook.parent is None: + if self.__notebook.parent is None: return None - page_no = self._notebook.get_current_page() - return self._notebook.get_nth_page(page_no) + page_no = self.__notebook.get_current_page() + return self.__notebook.get_nth_page(page_no) def _shrink_page(self, page): - page_no = self._notebook.page_num(page) + page_no = self.__notebook.page_num(page) if page_no == -1: return - self._notebook.remove_page(page_no) - self.remove(self._notebook) + self.__notebook.remove_page(page_no) + self.remove(self.__notebook) def _expand_page(self, page): - for i in range(self._notebook.get_n_pages()): - self._notebook.remove_page(0) + for i in range(self.__notebook.get_n_pages()): + self.__notebook.remove_page(0) _setup_page(page, self._bg, self.props.padding) - self._notebook.append_page(page) + self.__notebook.append_page(page) - if self._notebook.parent is None: - self.pack_start(self._notebook) + if self.__notebook.parent is None: + self.pack_start(self.__notebook) class _Box(gtk.EventBox): def __init__(self): @@ -284,7 +294,6 @@ class _Palette(gtk.Window): #if self.window: # self.window.set_accept_focus(accept_focus) - def popup(self, immediate=False): self._popdown_anim.stop() From b2fa922b01b758b92fbe0b4186e0498439758c42 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Mon, 13 Jul 2009 03:18:24 +0000 Subject: [PATCH 13/51] Do not fail in <0.86 environment --- src/sugar/graphics/radiopalette.py | 10 ++++++---- src/sugar/graphics/style.py | 2 -- src/sugar/graphics/toolbar.py | 9 ++++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index c9387dd8..d7f2d2a5 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -23,6 +23,9 @@ from sugar.graphics.toolbutton import ToolButton from sugar.graphics.palette import Palette from sugar.graphics.radiotoolbutton import RadioToolButton +ARROW_SIZE = hasattr(style, 'TOOLBAR_ARROW_SIZE') and style.TOOLBAR_ARROW_SIZE \ + or 8 + class RadioPaletteButton(ToolButton): def __init__(self, **kwargs): ToolButton.__init__(self, **kwargs) @@ -70,10 +73,9 @@ class RadioMenuButton(RadioPaletteButton): self.get_style().paint_arrow(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, None, type, True, - a.x + a.width/2 - style.TOOLBAR_ARROW_SIZE/2, - a.y + a.height - style.TOOLBAR_ARROW_SIZE - \ - style._FOCUS_LINE_WIDTH, - style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) + a.x + a.width/2 - ARROW_SIZE/2, + a.y + a.height - ARROW_SIZE - style._FOCUS_LINE_WIDTH, + ARROW_SIZE, ARROW_SIZE) class RadioToolsButton(RadioPaletteButton): def __init__(self, **kwargs): diff --git a/src/sugar/graphics/style.py b/src/sugar/graphics/style.py index ed229693..438aab79 100644 --- a/src/sugar/graphics/style.py +++ b/src/sugar/graphics/style.py @@ -132,6 +132,4 @@ COLOR_TEXT_FIELD_GREY = Color('#E5E5E5') PALETTE_CURSOR_DISTANCE = zoom(10) -#TOOLBAR_COLOR = COLOR_BLACK -TOOLBAR_COLOR = COLOR_TOOLBAR_GREY TOOLBAR_ARROW_SIZE = 8 diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index 3ae1bb29..b0ba0300 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -25,6 +25,9 @@ from sugar.graphics.palette import MouseSpeedDetector, Invoker from sugar.graphics import animator from sugar.graphics import palettegroup +ARROW_SIZE = hasattr(style, 'TOOLBAR_ARROW_SIZE') and style.TOOLBAR_ARROW_SIZE \ + or 8 + class ToolbarButton(ToolButton): def __init__(self, **kwargs): self._page = None @@ -403,6 +406,6 @@ def _paint_arrow(widget, event, type): widget.get_style().paint_arrow(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, widget, None, type, True, - a.x + a.width/2 - style.TOOLBAR_ARROW_SIZE/2, - a.y + a.height - style.TOOLBAR_ARROW_SIZE - style._FOCUS_LINE_WIDTH, - style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) + a.x + a.width/2 - ARROW_SIZE/2, + a.y + a.height - ARROW_SIZE - style._FOCUS_LINE_WIDTH, + ARROW_SIZE, ARROW_SIZE) From ad1f66f58a358cb79b577359d2104244ec3ab7dc Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Mon, 13 Jul 2009 18:14:10 +0000 Subject: [PATCH 14/51] Add toolbar.py and radiopalette.py to Makefile.am --- src/sugar/graphics/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sugar/graphics/Makefile.am b/src/sugar/graphics/Makefile.am index c4d5e61a..d1c6f09f 100644 --- a/src/sugar/graphics/Makefile.am +++ b/src/sugar/graphics/Makefile.am @@ -24,4 +24,6 @@ sugar_PYTHON = \ toolcombobox.py \ tray.py \ window.py \ - xocolor.py + xocolor.py \ + toolbar.py \ + radiopalette.py From d4cbd4150eef8f5e7be1866cb8c158c0621a7a0c Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Mon, 13 Jul 2009 18:34:02 +0000 Subject: [PATCH 15/51] Support legacy stop button in ActivityToolbar --- src/sugar/activity/activity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index fb523a90..692b537e 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -143,8 +143,8 @@ class ActivityToolbar(gtk.Toolbar): self.keep.show() if not hide_stop: - stop = stop_button(activity) - self.insert(stop, -1) + self.stop = stop_button(activity) + self.insert(self.stop, -1) self._update_title_sid = None From 095c732c9af0e756e1c2f1a69978b315c6961339 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Tue, 28 Jul 2009 11:50:36 +0000 Subject: [PATCH 16/51] Add activity.share_button --- src/sugar/activity/activity.py | 42 +++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index 692b537e..72691b17 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -61,7 +61,7 @@ import dbus import dbus.service import cjson -from sugar import util +from sugar import util from sugar.presence import presenceservice from sugar.activity.activityservice import ActivityService from sugar.activity.namingalert import NamingAlert @@ -74,6 +74,7 @@ from sugar.graphics.alert import Alert from sugar.graphics.icon import Icon from sugar.graphics.xocolor import XoColor from sugar.graphics.toolbar import Toolbar, ToolbarButton +from sugar.graphics.radiopalette import RadioPalette, RadioMenuButton from sugar.datastore import datastore from sugar.session import XSMPClient from sugar import wm @@ -1098,3 +1099,42 @@ def paste_button(**kwargs): paste.set_tooltip(_('Paste')) paste.show() return paste + +def share_button(activity, **kwargs): + quiet_trigger = [] + + def neighborhood_cb(): + if quiet_trigger: + return + activity.share() + + palette = RadioPalette() + private = palette.append( + icon_name='zoom-home', + tooltip=_('Private')) + neighborhood = palette.append( + icon_name='zoom-neighborhood', + tooltip=_('My Neighborhood'), + toggled_cb=neighborhood_cb) + + def update_share(): + quiet_trigger.append(True) + + logging.error(private.props.sensitive) + + if activity.get_shared(): + private.props.sensitive = False + neighborhood.props.sensitive = False + neighborhood.props.active = True + logging.error(private.props.sensitive) + else: + private.props.sensitive = True + neighborhood.props.sensitive = True + private.props.active = True + + quiet_trigger.pop() + + activity.connect('shared', lambda activity: update_share()) + activity.connect('joined', lambda activity: update_share()) + + return RadioMenuButton(palette=palette) From 2088bd5f2a86e2ef3f7d137654e94290679dff2b Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Tue, 28 Jul 2009 11:58:31 +0000 Subject: [PATCH 17/51] Add activity.keep_button --- src/sugar/activity/activity.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index 72691b17..e613d18a 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -132,16 +132,8 @@ class ActivityToolbar(gtk.Toolbar): self._update_share() - self.keep = ToolButton(tooltip=_('Keep')) - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - keep_icon = Icon(icon_name='document-save', xo_color=color) - self.keep.set_icon_widget(keep_icon) - keep_icon.show() - self.keep.props.accelerator = 'S' - self.keep.connect('clicked', self.__keep_clicked_cb) + self.keep = keep_button(activity) self.insert(self.keep, -1) - self.keep.show() if not hide_stop: self.stop = stop_button(activity) @@ -174,9 +166,6 @@ class ActivityToolbar(gtk.Toolbar): if scope == SCOPE_NEIGHBORHOOD: self._activity.share() - def __keep_clicked_cb(self, button): - self._activity.copy() - def __jobject_updated_cb(self, jobject): self.title.set_text(jobject['title']) @@ -1120,13 +1109,10 @@ def share_button(activity, **kwargs): def update_share(): quiet_trigger.append(True) - logging.error(private.props.sensitive) - if activity.get_shared(): private.props.sensitive = False neighborhood.props.sensitive = False neighborhood.props.active = True - logging.error(private.props.sensitive) else: private.props.sensitive = True neighborhood.props.sensitive = True @@ -1138,3 +1124,17 @@ def share_button(activity, **kwargs): activity.connect('joined', lambda activity: update_share()) return RadioMenuButton(palette=palette) + +def keep_button(activity, **kwargs): + client = gconf.client_get_default() + color = XoColor(client.get_string('/desktop/sugar/user/color')) + keep_icon = Icon(icon_name='document-save', xo_color=color) + keep_icon.show() + + keep = ToolButton(tooltip=_('Keep')) + keep.set_icon_widget(keep_icon) + keep.props.accelerator = 'S' + keep.connect('clicked', lambda button: activity.copy()) + keep.show() + + return keep From 9e9a22b2d521d2bbbe2d79019e4292e3dc793a66 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Tue, 28 Jul 2009 15:02:00 +0000 Subject: [PATCH 18/51] Use activity icon for activity.toolbar button --- src/sugar/activity/activity.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index e613d18a..600f86be 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -1019,7 +1019,7 @@ def _get_session(): def get_bundle_name(): """Return the bundle name for the current process' bundle""" return os.environ['SUGAR_BUNDLE_NAME'] - + def get_bundle_path(): """Return the bundle path for the current process' bundle""" return os.environ['SUGAR_BUNDLE_PATH'] @@ -1039,10 +1039,18 @@ def show_object_in_journal(object_id): journal.ShowObject(object_id) def toolbar(activity): + from jarabe.journal.misc import get_icon_name + activity_button = ToolbarButton( - page=ActivityToolbar(activity, hide_stop=True), - icon_name='computer-xo') + page=ActivityToolbar(activity, hide_stop=True)) activity_button.show() + + client = gconf.client_get_default() + color = XoColor(client.get_string('/desktop/sugar/user/color')) + icon = Icon(file=get_icon_name(activity.metadata), xo_color=color) + icon.show() + activity_button.set_icon_widget(icon) + return activity_button def expander(): @@ -1123,7 +1131,10 @@ def share_button(activity, **kwargs): activity.connect('shared', lambda activity: update_share()) activity.connect('joined', lambda activity: update_share()) - return RadioMenuButton(palette=palette) + share = RadioMenuButton(palette=palette) + share.show() + + return share def keep_button(activity, **kwargs): client = gconf.client_get_default() @@ -1131,7 +1142,7 @@ def keep_button(activity, **kwargs): keep_icon = Icon(icon_name='document-save', xo_color=color) keep_icon.show() - keep = ToolButton(tooltip=_('Keep')) + keep = ToolButton(tooltip=_('Keep'), **kwargs) keep.set_icon_widget(keep_icon) keep.props.accelerator = 'S' keep.connect('clicked', lambda button: activity.copy()) From ec474da5cc1e2fcbe7a55cb9dcc8ae223937ff34 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Wed, 29 Jul 2009 06:41:23 +0000 Subject: [PATCH 19/51] Replace share combo with new share button --- src/sugar/activity/activity.py | 48 ++-------------------------------- 1 file changed, 2 insertions(+), 46 deletions(-) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index 600f86be..fc452903 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -100,12 +100,6 @@ class ActivityToolbar(gtk.Toolbar): gtk.Toolbar.__init__(self) self._activity = activity - self._updating_share = False - - activity.connect('shared', self.__activity_shared_cb) - activity.connect('joined', self.__activity_shared_cb) - activity.connect('notify::max_participants', - self.__max_participants_changed_cb) if activity.metadata: self.title = gtk.Entry() @@ -122,15 +116,8 @@ class ActivityToolbar(gtk.Toolbar): self.insert(separator, -1) separator.show() - self.share = ToolComboBox(label_text=_('Share with:')) - self.share.combo.connect('changed', self.__share_changed_cb) - self.share.combo.append_item(SCOPE_PRIVATE, _('Private'), 'zoom-home') - self.share.combo.append_item(SCOPE_NEIGHBORHOOD, _('My Neighborhood'), - 'zoom-neighborhood') + self.share = share_button(activity) self.insert(self.share, -1) - self.share.show() - - self._update_share() self.keep = keep_button(activity) self.insert(self.keep, -1) @@ -141,31 +128,6 @@ class ActivityToolbar(gtk.Toolbar): self._update_title_sid = None - def _update_share(self): - self._updating_share = True - - if self._activity.props.max_participants == 1: - self.share.hide() - - if self._activity.get_shared(): - self.share.set_sensitive(False) - self.share.combo.set_active(1) - else: - self.share.set_sensitive(True) - self.share.combo.set_active(0) - - self._updating_share = False - - def __share_changed_cb(self, combo): - if self._updating_share: - return - - model = self.share.combo.get_model() - it = self.share.combo.get_active_iter() - (scope, ) = model.get(it, 0) - if scope == SCOPE_NEIGHBORHOOD: - self._activity.share() - def __jobject_updated_cb(self, jobject): self.title.set_text(jobject['title']) @@ -198,15 +160,9 @@ class ActivityToolbar(gtk.Toolbar): self.insert(tool_item, -1) tool_item.show() - def __activity_shared_cb(self, activity): - self._update_share() - - def __max_participants_changed_cb(self, activity, pspec): - self._update_share() - class EditToolbar(gtk.Toolbar): """Provides the standard edit toolbar for Activities. - + Members: undo -- the undo button redo -- the redo button From b5c950901403e6a593ccee9b27387f8dc7e85f15 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Wed, 29 Jul 2009 06:59:28 +0000 Subject: [PATCH 20/51] Remove redundant current-toolbar-changed signal from toolbar.Toolbar --- src/sugar/graphics/toolbar.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index b0ba0300..d9d3c98a 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -111,10 +111,6 @@ class ToolbarButton(ToolButton): _paint_arrow(self, event, gtk.ARROW_DOWN) class Toolbar(gtk.VBox): - __gsignals__ = { - 'current-toolbar-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, ([int])) - } - def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING): gtk.VBox.__init__(self) @@ -133,9 +129,6 @@ class Toolbar(gtk.VBox): self.__notebook.set_show_tabs(False) self.__notebook.show() - self.__notebook.connect('notify::page', lambda notebook, pspec: - self.emit('current-toolbar-changed', notebook.props.page)) - self.__top.connect('remove', self.__remove_cb) top = property(lambda self: self.__top) From 7f2488e505d1dd4f4ccc9e8aaf179e5150260aff Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Wed, 29 Jul 2009 12:42:43 +0000 Subject: [PATCH 21/51] Add Vasya Pupkin to copyright holders --- src/sugar/_sugarext.so | 1 - src/sugar/graphics/radiopalette.py | 2 ++ src/sugar/graphics/toolbar.py | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) delete mode 120000 src/sugar/_sugarext.so diff --git a/src/sugar/_sugarext.so b/src/sugar/_sugarext.so deleted file mode 120000 index c11ccc78..00000000 --- a/src/sugar/_sugarext.so +++ /dev/null @@ -1 +0,0 @@ -.libs/_sugarext.so \ No newline at end of file diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index d7f2d2a5..d510ed3b 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -1,3 +1,5 @@ +# Copyright (C) 2009, Aleksey Lim +# # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index d9d3c98a..35699e81 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -1,3 +1,5 @@ +# Copyright (C) 2009, Aleksey Lim +# # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either From 0cf445eb0faf941bc37141d972ff49b9269d8c4b Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Wed, 29 Jul 2009 13:02:41 +0000 Subject: [PATCH 22/51] Remove redundant ctor argument from activity.ActivityToolbar() --- src/sugar/activity/activity.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index fc452903..a4690e56 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -96,7 +96,7 @@ class ActivityToolbar(gtk.Toolbar): All activities should have this toolbar. It is easiest to add it to your Activity by using the ActivityToolbox. """ - def __init__(self, activity, hide_stop=False): + def __init__(self, activity): gtk.Toolbar.__init__(self) self._activity = activity @@ -122,9 +122,8 @@ class ActivityToolbar(gtk.Toolbar): self.keep = keep_button(activity) self.insert(self.keep, -1) - if not hide_stop: - self.stop = stop_button(activity) - self.insert(self.stop, -1) + self.stop = stop_button(activity) + self.insert(self.stop, -1) self._update_title_sid = None @@ -997,8 +996,9 @@ def show_object_in_journal(object_id): def toolbar(activity): from jarabe.journal.misc import get_icon_name - activity_button = ToolbarButton( - page=ActivityToolbar(activity, hide_stop=True)) + toolbar = ActivityToolbar(activity) + toolbar.stop.hide() + activity_button = ToolbarButton(page=toolbar) activity_button.show() client = gconf.client_get_default() From 872b18a103a43ce6b4d5d7de6287443864aa040c Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Wed, 29 Jul 2009 15:33:02 +0000 Subject: [PATCH 23/51] Fix review issues --- examples/radiopalette.py | 63 ++++++++++++++++++++---------- src/sugar/activity/activity.py | 44 +++++++++++---------- src/sugar/graphics/Makefile.am | 56 +++++++++++++------------- src/sugar/graphics/radiopalette.py | 54 +++++++++---------------- src/sugar/graphics/toolbar.py | 9 ++--- 5 files changed, 116 insertions(+), 110 deletions(-) diff --git a/examples/radiopalette.py b/examples/radiopalette.py index eb868313..8a47f987 100644 --- a/examples/radiopalette.py +++ b/examples/radiopalette.py @@ -2,6 +2,7 @@ import gtk from sugar.graphics.radiopalette import RadioPalette, RadioMenuButton, \ RadioToolsButton +from sugar.graphics.radiotoolbutton import RadioToolButton from sugar.graphics.toolbutton import ToolButton from sugar.graphics import style @@ -16,39 +17,61 @@ box.pack_start(toolbar, False) text_view = gtk.TextView() box.pack_start(text_view) -def echo(text): - text_view.props.buffer.props.text += "\n" + text +def echo(button): + if not button.props.active: + return + text_view.props.buffer.props.text += "\n" + button.props.tooltip + +# RadioMenuButton palette = RadioPalette() -palette.append( + +group = RadioToolButton( icon_name='document-open', - tooltip='menu.document-open', - toggled_cb=lambda: echo('menu.document-open')) -palette.append( + tooltip='menu.document-open') +group.connect('clicked', lambda button: echo(button)) +palette.append(group) + +button = RadioToolButton( icon_name='document-save', - tooltip='menu.document-save', - toggled_cb=lambda: echo('menu.document-save')) -palette.append( + group=group, + tooltip='menu.document-save') +button.connect('clicked', lambda button: echo(button)) +palette.append(button) + +button = RadioToolButton( icon_name='document-send', - tooltip='menu.document-send', - toggled_cb=lambda: echo('menu.document-send')) + group=group, + tooltip='menu.document-send') +button.connect('clicked', lambda button: echo(button)) +palette.append(button) button = RadioMenuButton(palette=palette) toolbar.insert(button, -1) +# RadioToolsButton + palette = RadioPalette() -palette.append( + +group = RadioToolButton( icon_name='document-open', - tooltip='tools.document-open', - toggled_cb=lambda: echo('tools.document-open')) -palette.append( + tooltip='menu.document-open') +group.connect('clicked', lambda button: echo(button)) +palette.append(group) + +button = RadioToolButton( icon_name='document-save', - tooltip='tools.document-save', - toggled_cb=lambda: echo('tools.document-save')) -palette.append( + group=group, + tooltip='menu.document-save') +button.connect('clicked', lambda button: echo(button)) +palette.append(button) + +button = RadioToolButton( icon_name='document-send', - tooltip='tools.document-send', - toggled_cb=lambda: echo('tools.document-send')) + group=group, + tooltip='menu.document-send') +button.connect('clicked', lambda button: echo(button)) +palette.append(button) button = RadioToolsButton(palette=palette) toolbar.insert(button, -1) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index a4690e56..76a349f3 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -75,6 +75,7 @@ from sugar.graphics.icon import Icon from sugar.graphics.xocolor import XoColor from sugar.graphics.toolbar import Toolbar, ToolbarButton from sugar.graphics.radiopalette import RadioPalette, RadioMenuButton +from sugar.graphics.radiotoolbutton import RadioToolButton from sugar.datastore import datastore from sugar.session import XSMPClient from sugar import wm @@ -1054,35 +1055,36 @@ def paste_button(**kwargs): return paste def share_button(activity, **kwargs): - quiet_trigger = [] - - def neighborhood_cb(): - if quiet_trigger: - return + def neighborhood_cb(button): activity.share() palette = RadioPalette() - private = palette.append( + + private = RadioToolButton( icon_name='zoom-home', tooltip=_('Private')) - neighborhood = palette.append( + palette.append(private) + + neighborhood = RadioToolButton( icon_name='zoom-neighborhood', - tooltip=_('My Neighborhood'), - toggled_cb=neighborhood_cb) + group=private, + tooltip=_('My Neighborhood')) + neighborhood.connect('clicked', neighborhood_cb) + palette.append(neighborhood) def update_share(): - quiet_trigger.append(True) - - if activity.get_shared(): - private.props.sensitive = False - neighborhood.props.sensitive = False - neighborhood.props.active = True - else: - private.props.sensitive = True - neighborhood.props.sensitive = True - private.props.active = True - - quiet_trigger.pop() + neighborhood.handler_block_by_func(neighborhood_cb) + try: + if activity.get_shared(): + private.props.sensitive = False + neighborhood.props.sensitive = False + neighborhood.props.active = True + else: + private.props.sensitive = True + neighborhood.props.sensitive = True + private.props.active = True + finally: + neighborhood.handler_unblock_by_func(neighborhood_cb) activity.connect('shared', lambda activity: update_share()) activity.connect('joined', lambda activity: update_share()) diff --git a/src/sugar/graphics/Makefile.am b/src/sugar/graphics/Makefile.am index d1c6f09f..6739a133 100644 --- a/src/sugar/graphics/Makefile.am +++ b/src/sugar/graphics/Makefile.am @@ -1,29 +1,29 @@ sugardir = $(pythondir)/sugar/graphics -sugar_PYTHON = \ - __init__.py \ - alert.py \ - animator.py \ - canvastextview.py \ - combobox.py \ - colorbutton.py \ - entry.py \ - icon.py \ - iconentry.py \ - menuitem.py \ - notebook.py \ - objectchooser.py \ - radiotoolbutton.py \ - palette.py \ - palettegroup.py \ - panel.py \ - roundbox.py \ - style.py \ - toggletoolbutton.py \ - toolbox.py \ - toolbutton.py \ - toolcombobox.py \ - tray.py \ - window.py \ - xocolor.py \ - toolbar.py \ - radiopalette.py +sugar_PYTHON = \ + alert.py \ + animator.py \ + canvastextview.py \ + colorbutton.py \ + combobox.py \ + entry.py \ + iconentry.py \ + icon.py \ + __init__.py \ + menuitem.py \ + notebook.py \ + objectchooser.py \ + palettegroup.py \ + palette.py \ + panel.py \ + radiopalette.py \ + radiotoolbutton.py \ + roundbox.py \ + style.py \ + toggletoolbutton.py \ + toolbar.py \ + toolbox.py \ + toolbutton.py \ + toolcombobox.py \ + tray.py \ + window.py \ + xocolor.py \ diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index d510ed3b..743a45f9 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -18,21 +18,16 @@ import gtk import gobject import logging -from gobject import SIGNAL_RUN_FIRST, TYPE_NONE +from gobject import SIGNAL_RUN_FIRST, TYPE_NONE, TYPE_PYOBJECT from sugar.graphics import style from sugar.graphics.toolbutton import ToolButton from sugar.graphics.palette import Palette -from sugar.graphics.radiotoolbutton import RadioToolButton - -ARROW_SIZE = hasattr(style, 'TOOLBAR_ARROW_SIZE') and style.TOOLBAR_ARROW_SIZE \ - or 8 class RadioPaletteButton(ToolButton): def __init__(self, **kwargs): ToolButton.__init__(self, **kwargs) - - self._button_cb = None + self.selected_button = None if self.props.palette: self.__palette_cb(None, None) @@ -44,10 +39,6 @@ class RadioPaletteButton(ToolButton): return self.props.palette.update_button() - def _set_current_button(self, button): - self.set_icon(button.rp_icon_name) - self._button_cb = button.rp_toggled_cb - class RadioMenuButton(RadioPaletteButton): def __init__(self, **kwargs): RadioPaletteButton.__init__(self, **kwargs) @@ -75,18 +66,19 @@ class RadioMenuButton(RadioPaletteButton): self.get_style().paint_arrow(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, None, type, True, - a.x + a.width/2 - ARROW_SIZE/2, - a.y + a.height - ARROW_SIZE - style._FOCUS_LINE_WIDTH, - ARROW_SIZE, ARROW_SIZE) + a.x + a.width/2 - style.TOOLBAR_ARROW_SIZE/2, + a.y + a.height - style.TOOLBAR_ARROW_SIZE - \ + style._FOCUS_LINE_WIDTH, + style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) class RadioToolsButton(RadioPaletteButton): def __init__(self, **kwargs): RadioPaletteButton.__init__(self, **kwargs) def do_clicked(self): - if not self._button_cb: + if not self.selected_button: return - self._button_cb() + self.selected_button.emit('clicked') class RadioPalette(Palette): def __init__(self, **kwargs): @@ -96,39 +88,31 @@ class RadioPalette(Palette): self.top.show() self.set_content(self.top) - def append(self, icon_name, tooltip=None, toggled_cb=None): + def append(self, button): children = self.top.get_children() - button = RadioToolButton(icon_name=icon_name, - group=children and children[0] or None) + button.show() - button.connect('toggled', self.__toggled_cb) + button.connect('clicked', self.__clicked_cb) self.top.pack_start(button, fill=False) - button.rp_icon_name = icon_name - button.rp_tooltip = tooltip - button.rp_toggled_cb = toggled_cb - if not children: - self.__toggled_cb(button, True) - - return button + self.__clicked_cb(button, True) def update_button(self): for i in self.top.get_children(): - self.__toggled_cb(i, True) + self.__clicked_cb(i, True) - def __toggled_cb(self, button, quiet=False): + def __clicked_cb(self, button, quiet=False): if not button.get_active(): return - self.set_primary_text(button.rp_tooltip) + self.set_primary_text(button.props.tooltip) if not quiet: - if button.rp_toggled_cb: - button.rp_toggled_cb() self.popdown(immediate=True) - if not self.invoker or \ - not isinstance(self.invoker.parent, RadioPaletteButton): + parent = self.invoker and self.invoker.parent + if not isinstance(parent, RadioPaletteButton): return - self.invoker.parent._set_current_button(button) + parent.set_icon(button.props.icon_name) + parent.selected_button = button diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index 35699e81..abeceee1 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -27,9 +27,6 @@ from sugar.graphics.palette import MouseSpeedDetector, Invoker from sugar.graphics import animator from sugar.graphics import palettegroup -ARROW_SIZE = hasattr(style, 'TOOLBAR_ARROW_SIZE') and style.TOOLBAR_ARROW_SIZE \ - or 8 - class ToolbarButton(ToolButton): def __init__(self, **kwargs): self._page = None @@ -401,6 +398,6 @@ def _paint_arrow(widget, event, type): widget.get_style().paint_arrow(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, widget, None, type, True, - a.x + a.width/2 - ARROW_SIZE/2, - a.y + a.height - ARROW_SIZE - style._FOCUS_LINE_WIDTH, - ARROW_SIZE, ARROW_SIZE) + a.x + a.width/2 - style.TOOLBAR_ARROW_SIZE/2, + a.y + a.height - style.TOOLBAR_ARROW_SIZE - style._FOCUS_LINE_WIDTH, + style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) From e5a701a1e644e7f465af5faf79904aa9cfdc7d30 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Wed, 29 Jul 2009 15:53:09 +0000 Subject: [PATCH 24/51] Fix Makefile.am file --- src/sugar/graphics/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sugar/graphics/Makefile.am b/src/sugar/graphics/Makefile.am index 6739a133..8f89a2cf 100644 --- a/src/sugar/graphics/Makefile.am +++ b/src/sugar/graphics/Makefile.am @@ -26,4 +26,4 @@ sugar_PYTHON = \ toolcombobox.py \ tray.py \ window.py \ - xocolor.py \ + xocolor.py From 2655a8ccada45beb1f78f2e5fbad13e88ba44447 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Wed, 29 Jul 2009 16:15:38 +0000 Subject: [PATCH 25/51] Suppress sub-palettes in radiopalette --- examples/radiopalette.py | 12 ++++++------ src/sugar/activity/activity.py | 10 ++++------ src/sugar/graphics/radiopalette.py | 8 ++++++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/examples/radiopalette.py b/examples/radiopalette.py index 8a47f987..a5538730 100644 --- a/examples/radiopalette.py +++ b/examples/radiopalette.py @@ -30,21 +30,21 @@ group = RadioToolButton( icon_name='document-open', tooltip='menu.document-open') group.connect('clicked', lambda button: echo(button)) -palette.append(group) +palette.append(group, 'menu.document-open') button = RadioToolButton( icon_name='document-save', group=group, tooltip='menu.document-save') button.connect('clicked', lambda button: echo(button)) -palette.append(button) +palette.append(button, 'menu.document-save') button = RadioToolButton( icon_name='document-send', group=group, tooltip='menu.document-send') button.connect('clicked', lambda button: echo(button)) -palette.append(button) +palette.append(button, 'menu.document-send') button = RadioMenuButton(palette=palette) toolbar.insert(button, -1) @@ -57,21 +57,21 @@ group = RadioToolButton( icon_name='document-open', tooltip='menu.document-open') group.connect('clicked', lambda button: echo(button)) -palette.append(group) +palette.append(group, 'menu.document-open') button = RadioToolButton( icon_name='document-save', group=group, tooltip='menu.document-save') button.connect('clicked', lambda button: echo(button)) -palette.append(button) +palette.append(button, 'menu.document-save') button = RadioToolButton( icon_name='document-send', group=group, tooltip='menu.document-send') button.connect('clicked', lambda button: echo(button)) -palette.append(button) +palette.append(button, 'menu.document-send') button = RadioToolsButton(palette=palette) toolbar.insert(button, -1) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index 76a349f3..30cd0a10 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -1061,16 +1061,14 @@ def share_button(activity, **kwargs): palette = RadioPalette() private = RadioToolButton( - icon_name='zoom-home', - tooltip=_('Private')) - palette.append(private) + icon_name='zoom-home') + palette.append(private, _('Private')) neighborhood = RadioToolButton( icon_name='zoom-neighborhood', - group=private, - tooltip=_('My Neighborhood')) + group=private) neighborhood.connect('clicked', neighborhood_cb) - palette.append(neighborhood) + palette.append(neighborhood, _('My Neighborhood')) def update_share(): neighborhood.handler_block_by_func(neighborhood_cb) diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index 743a45f9..b76ae4c4 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -88,12 +88,16 @@ class RadioPalette(Palette): self.top.show() self.set_content(self.top) - def append(self, button): + def append(self, button, label): children = self.top.get_children() + # palette's button should not have sub-palettes + button.palette = None + button.show() button.connect('clicked', self.__clicked_cb) self.top.pack_start(button, fill=False) + button.__palette_label = label if not children: self.__clicked_cb(button, True) @@ -106,7 +110,7 @@ class RadioPalette(Palette): if not button.get_active(): return - self.set_primary_text(button.props.tooltip) + self.set_primary_text(button.__palette_label) if not quiet: self.popdown(immediate=True) From e03fd4ddde95d8fcdf857f6cbdb0b05e9fd36471 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Thu, 30 Jul 2009 05:43:36 +0000 Subject: [PATCH 26/51] Minor tweaks --- src/sugar/activity/activity.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index 30cd0a10..7b6c0941 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -1055,9 +1055,6 @@ def paste_button(**kwargs): return paste def share_button(activity, **kwargs): - def neighborhood_cb(button): - activity.share() - palette = RadioPalette() private = RadioToolButton( @@ -1067,11 +1064,12 @@ def share_button(activity, **kwargs): neighborhood = RadioToolButton( icon_name='zoom-neighborhood', group=private) - neighborhood.connect('clicked', neighborhood_cb) + neighborhood_handle = neighborhood.connect('clicked', + lambda button: activity.share()) palette.append(neighborhood, _('My Neighborhood')) def update_share(): - neighborhood.handler_block_by_func(neighborhood_cb) + neighborhood.handler_block(neighborhood_handle) try: if activity.get_shared(): private.props.sensitive = False @@ -1082,7 +1080,7 @@ def share_button(activity, **kwargs): neighborhood.props.sensitive = True private.props.active = True finally: - neighborhood.handler_unblock_by_func(neighborhood_cb) + neighborhood.handler_unblock(neighborhood_handle) activity.connect('shared', lambda activity: update_share()) activity.connect('joined', lambda activity: update_share()) From a2f20f39ff359ecc3ea4430d0dfe7cb3d75dd320 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Thu, 30 Jul 2009 11:29:52 +0000 Subject: [PATCH 27/51] Fix review issues --- examples/radiopalette.py | 34 ++- src/sugar/activity/activity.py | 323 ++++++++++++++++++----------- src/sugar/graphics/radiopalette.py | 49 +++-- src/sugar/graphics/style.py | 2 +- src/sugar/graphics/toolbar.py | 17 +- 5 files changed, 250 insertions(+), 175 deletions(-) diff --git a/examples/radiopalette.py b/examples/radiopalette.py index a5538730..85b43cef 100644 --- a/examples/radiopalette.py +++ b/examples/radiopalette.py @@ -17,33 +17,30 @@ box.pack_start(toolbar, False) text_view = gtk.TextView() box.pack_start(text_view) -def echo(button): +def echo(button, label): if not button.props.active: return - text_view.props.buffer.props.text += "\n" + button.props.tooltip + text_view.props.buffer.props.text += "\n" + label # RadioMenuButton palette = RadioPalette() group = RadioToolButton( - icon_name='document-open', - tooltip='menu.document-open') -group.connect('clicked', lambda button: echo(button)) + icon_name='document-open') +group.connect('clicked', lambda button: echo(button, 'document-open')) palette.append(group, 'menu.document-open') button = RadioToolButton( icon_name='document-save', - group=group, - tooltip='menu.document-save') -button.connect('clicked', lambda button: echo(button)) + group=group) +button.connect('clicked', lambda button: echo(button, 'document-save')) palette.append(button, 'menu.document-save') button = RadioToolButton( icon_name='document-send', - group=group, - tooltip='menu.document-send') -button.connect('clicked', lambda button: echo(button)) + group=group) +button.connect('clicked', lambda button: echo(button, 'document-send')) palette.append(button, 'menu.document-send') button = RadioMenuButton(palette=palette) @@ -54,23 +51,20 @@ toolbar.insert(button, -1) palette = RadioPalette() group = RadioToolButton( - icon_name='document-open', - tooltip='menu.document-open') -group.connect('clicked', lambda button: echo(button)) + icon_name='document-open') +group.connect('clicked', lambda button: echo(button, 'document-open')) palette.append(group, 'menu.document-open') button = RadioToolButton( icon_name='document-save', - group=group, - tooltip='menu.document-save') -button.connect('clicked', lambda button: echo(button)) + group=group) +button.connect('clicked', lambda button: echo(button, 'document-save')) palette.append(button, 'menu.document-save') button = RadioToolButton( icon_name='document-send', - group=group, - tooltip='menu.document-send') -button.connect('clicked', lambda button: echo(button)) + group=group) +button.connect('clicked', lambda button: echo(button, 'document-send')) palette.append(button, 'menu.document-send') button = RadioToolsButton(palette=palette) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index 7b6c0941..28bb9353 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -61,7 +61,7 @@ import dbus import dbus.service import cjson -from sugar import util +from sugar import util from sugar.presence import presenceservice from sugar.activity.activityservice import ActivityService from sugar.activity.namingalert import NamingAlert @@ -101,6 +101,12 @@ class ActivityToolbar(gtk.Toolbar): gtk.Toolbar.__init__(self) self._activity = activity + self._updating_share = False + + activity.connect('shared', self.__activity_shared_cb) + activity.connect('joined', self.__activity_shared_cb) + activity.connect('notify::max_participants', + self.__max_participants_changed_cb) if activity.metadata: self.title = gtk.Entry() @@ -117,17 +123,66 @@ class ActivityToolbar(gtk.Toolbar): self.insert(separator, -1) separator.show() - self.share = share_button(activity) + self.share = ToolComboBox(label_text=_('Share with:')) + self.share.combo.connect('changed', self.__share_changed_cb) + self.share.combo.append_item(SCOPE_PRIVATE, _('Private'), 'zoom-home') + self.share.combo.append_item(SCOPE_NEIGHBORHOOD, _('My Neighborhood'), + 'zoom-neighborhood') self.insert(self.share, -1) + self.share.show() - self.keep = keep_button(activity) + self._update_share() + + self.keep = ToolButton(tooltip=_('Keep')) + client = gconf.client_get_default() + color = XoColor(client.get_string('/desktop/sugar/user/color')) + keep_icon = Icon(icon_name='document-save', xo_color=color) + self.keep.set_icon_widget(keep_icon) + keep_icon.show() + self.keep.props.accelerator = 'S' + self.keep.connect('clicked', self.__keep_clicked_cb) self.insert(self.keep, -1) + self.keep.show() - self.stop = stop_button(activity) + self.stop = ToolButton('activity-stop', tooltip=_('Stop')) + self.stop.props.accelerator = 'Q' + self.stop.connect('clicked', self.__stop_clicked_cb) self.insert(self.stop, -1) + self.stop.show() self._update_title_sid = None + def _update_share(self): + self._updating_share = True + + if self._activity.props.max_participants == 1: + self.share.hide() + + if self._activity.get_shared(): + self.share.set_sensitive(False) + self.share.combo.set_active(1) + else: + self.share.set_sensitive(True) + self.share.combo.set_active(0) + + self._updating_share = False + + def __share_changed_cb(self, combo): + if self._updating_share: + return + + model = self.share.combo.get_model() + it = self.share.combo.get_active_iter() + (scope, ) = model.get(it, 0) + if scope == SCOPE_NEIGHBORHOOD: + self._activity.share() + + def __keep_clicked_cb(self, button): + self._activity.copy() + + def __stop_clicked_cb(self, button): + self._activity.close() + def __jobject_updated_cb(self, jobject): self.title.set_text(jobject['title']) @@ -160,9 +215,15 @@ class ActivityToolbar(gtk.Toolbar): self.insert(tool_item, -1) tool_item.show() + def __activity_shared_cb(self, activity): + self._update_share() + + def __max_participants_changed_cb(self, activity, pspec): + self._update_share() + class EditToolbar(gtk.Toolbar): """Provides the standard edit toolbar for Activities. - + Members: undo -- the undo button redo -- the redo button @@ -196,20 +257,30 @@ class EditToolbar(gtk.Toolbar): def __init__(self): gtk.Toolbar.__init__(self) - self.undo = undo_button() + self.undo = ToolButton('edit-undo') + self.undo.set_tooltip(_('Undo')) self.insert(self.undo, -1) + self.undo.show() - self.redo = redo_button() + self.redo = ToolButton('edit-redo') + self.redo.set_tooltip(_('Redo')) self.insert(self.redo, -1) + self.redo.show() - self.separator = separator() + self.separator = gtk.SeparatorToolItem() + self.separator.set_draw(True) self.insert(self.separator, -1) + self.separator.show() - self.copy = copy_button() + self.copy = ToolButton('edit-copy') + self.copy.set_tooltip(_('Copy')) self.insert(self.copy, -1) + self.copy.show() - self.paste = paste_button() + self.paste = ToolButton('edit-paste') + self.paste.set_tooltip(_('Paste')) self.insert(self.paste, -1) + self.paste.show() class ActivityToolbox(Toolbox): """Creates the Toolbox for the Activity @@ -962,6 +1033,126 @@ class Activity(Window, gtk.Container): # DEPRECATED _shared_activity = property(lambda self: self.shared_activity, None) +class ActivityToolbarButton(ToolbarButton): + def __init__(self, activity, **kwargs): + from jarabe.journal.misc import get_icon_name + + toolbar = ActivityToolbar(activity) + toolbar.stop.hide() + + ToolbarButton.__init__(self, page=toolbar, **kwargs) + + self.activity = activity + + client = gconf.client_get_default() + color = XoColor(client.get_string('/desktop/sugar/user/color')) + icon = Icon(file=get_icon_name(activity.metadata), xo_color=color) + icon.show() + self.set_icon_widget(icon) + + def expander(self): + separator = gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + separator.show() + return separator + + def stop_button(self, **kwargs): + stop = ToolButton('activity-stop', tooltip=_('Stop'), **kwargs) + stop.props.accelerator = 'Q' + stop.connect('clicked', self.__stop_button_clicked_cb) + stop.show() + return stop + + def __stop_button_clicked_cb(self, button): + self.activity.close() + + def undo_button(self, **kwargs): + undo = ToolButton('edit-undo', **kwargs) + undo.set_tooltip(_('Undo')) + undo.show() + return undo + + def redo_button(self, **kwargs): + redo = ToolButton('edit-redo', **kwargs) + redo.set_tooltip(_('Redo')) + redo.show() + return redo + + def separator(self, **kwargs): + separator = gtk.SeparatorToolItem(**kwargs) + separator.set_draw(True) + separator.show() + return separator + + def copy_button(self, **kwargs): + copy = ToolButton('edit-copy', **kwargs) + copy.set_tooltip(_('Copy')) + copy.show() + return copy + + def paste_button(self, **kwargs): + paste = ToolButton('edit-paste', **kwargs) + paste.set_tooltip(_('Paste')) + paste.show() + return paste + + def share_button(self): + palette = RadioPalette() + + private = RadioToolButton( + icon_name='zoom-home') + palette.append(private, _('Private')) + + neighborhood = RadioToolButton( + icon_name='zoom-neighborhood', + group=private) + neighborhood_handle = neighborhood.connect('clicked', + self.__neighborhood_clicked_cb) + palette.append(neighborhood, _('My Neighborhood')) + + self.activity.connect('shared', self.__update_share) + self.activity.connect('joined', self.__update_share) + + share = RadioMenuButton(palette=palette) + share.show() + + return share + + def __neighborhood_clicked_cb(self, button): + self.activity.share() + + def __update_share(self, activity): + neighborhood.handler_block(neighborhood_handle) + try: + if self.activity.get_shared(): + private.props.sensitive = False + neighborhood.props.sensitive = False + neighborhood.props.active = True + else: + private.props.sensitive = True + neighborhood.props.sensitive = True + private.props.active = True + finally: + neighborhood.handler_unblock(neighborhood_handle) + + def keep_button(self, **kwargs): + client = gconf.client_get_default() + color = XoColor(client.get_string('/desktop/sugar/user/color')) + keep_icon = Icon(icon_name='document-save', xo_color=color) + keep_icon.show() + + keep = ToolButton(tooltip=_('Keep'), **kwargs) + keep.set_icon_widget(keep_icon) + keep.props.accelerator = 'S' + keep.connect('clicked', self.__keep_button_clicked) + keep.show() + + return keep + + def __keep_button_clicked(self, button): + self.activity.copy() + _session = None def _get_session(): @@ -975,7 +1166,7 @@ def _get_session(): def get_bundle_name(): """Return the bundle name for the current process' bundle""" return os.environ['SUGAR_BUNDLE_NAME'] - + def get_bundle_path(): """Return the bundle path for the current process' bundle""" return os.environ['SUGAR_BUNDLE_PATH'] @@ -993,113 +1184,3 @@ def show_object_in_journal(object_id): obj = bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH) journal = dbus.Interface(obj, J_DBUS_INTERFACE) journal.ShowObject(object_id) - -def toolbar(activity): - from jarabe.journal.misc import get_icon_name - - toolbar = ActivityToolbar(activity) - toolbar.stop.hide() - activity_button = ToolbarButton(page=toolbar) - activity_button.show() - - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - icon = Icon(file=get_icon_name(activity.metadata), xo_color=color) - icon.show() - activity_button.set_icon_widget(icon) - - return activity_button - -def expander(): - separator = gtk.SeparatorToolItem() - separator.props.draw = False - separator.set_expand(True) - separator.show() - return separator - -def stop_button(activity, **kwargs): - stop = ToolButton('activity-stop', tooltip=_('Stop'), **kwargs) - stop.props.accelerator = 'Q' - stop.connect('clicked', lambda button: activity.close()) - stop.show() - return stop - -def undo_button(**kwargs): - undo = ToolButton('edit-undo', **kwargs) - undo.set_tooltip(_('Undo')) - undo.show() - return undo - -def redo_button(**kwargs): - redo = ToolButton('edit-redo', **kwargs) - redo.set_tooltip(_('Redo')) - redo.show() - return redo - -def separator(**kwargs): - separator = gtk.SeparatorToolItem(**kwargs) - separator.set_draw(True) - separator.show() - return separator - -def copy_button(**kwargs): - copy = ToolButton('edit-copy', **kwargs) - copy.set_tooltip(_('Copy')) - copy.show() - return copy - -def paste_button(**kwargs): - paste = ToolButton('edit-paste', **kwargs) - paste.set_tooltip(_('Paste')) - paste.show() - return paste - -def share_button(activity, **kwargs): - palette = RadioPalette() - - private = RadioToolButton( - icon_name='zoom-home') - palette.append(private, _('Private')) - - neighborhood = RadioToolButton( - icon_name='zoom-neighborhood', - group=private) - neighborhood_handle = neighborhood.connect('clicked', - lambda button: activity.share()) - palette.append(neighborhood, _('My Neighborhood')) - - def update_share(): - neighborhood.handler_block(neighborhood_handle) - try: - if activity.get_shared(): - private.props.sensitive = False - neighborhood.props.sensitive = False - neighborhood.props.active = True - else: - private.props.sensitive = True - neighborhood.props.sensitive = True - private.props.active = True - finally: - neighborhood.handler_unblock(neighborhood_handle) - - activity.connect('shared', lambda activity: update_share()) - activity.connect('joined', lambda activity: update_share()) - - share = RadioMenuButton(palette=palette) - share.show() - - return share - -def keep_button(activity, **kwargs): - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - keep_icon = Icon(icon_name='document-save', xo_color=color) - keep_icon.show() - - keep = ToolButton(tooltip=_('Keep'), **kwargs) - keep.set_icon_widget(keep_icon) - keep.props.accelerator = 'S' - keep.connect('clicked', lambda button: activity.copy()) - keep.show() - - return keep diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index b76ae4c4..d9ca2895 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -24,7 +24,7 @@ from sugar.graphics import style from sugar.graphics.toolbutton import ToolButton from sugar.graphics.palette import Palette -class RadioPaletteButton(ToolButton): +class RadioMenuButton(ToolButton): def __init__(self, **kwargs): ToolButton.__init__(self, **kwargs) self.selected_button = None @@ -39,10 +39,7 @@ class RadioPaletteButton(ToolButton): return self.props.palette.update_button() -class RadioMenuButton(RadioPaletteButton): - def __init__(self, **kwargs): - RadioPaletteButton.__init__(self, **kwargs) - + # We use do_clicked to have a chance to override it in RadioToolsButton def do_clicked(self): if not self.palette: return @@ -58,22 +55,21 @@ class RadioMenuButton(RadioPaletteButton): return if self.palette.is_up(): - type = gtk.ARROW_DOWN - else: type = gtk.ARROW_UP + else: + type = gtk.ARROW_DOWN - a = self.allocation + alloc = self.allocation + x = alloc.x + alloc.width / 2 - style.TOOLBAR_ARROW_SIZE / 2 + y = alloc.y + alloc.height - int(style.TOOLBAR_ARROW_SIZE * .85) self.get_style().paint_arrow(event.window, - gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, + gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, None, type, True, - a.x + a.width/2 - style.TOOLBAR_ARROW_SIZE/2, - a.y + a.height - style.TOOLBAR_ARROW_SIZE - \ - style._FOCUS_LINE_WIDTH, - style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) + x, y, style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) -class RadioToolsButton(RadioPaletteButton): +class RadioToolsButton(RadioMenuButton): def __init__(self, **kwargs): - RadioPaletteButton.__init__(self, **kwargs) + RadioMenuButton.__init__(self, **kwargs) def do_clicked(self): if not self.selected_button: @@ -84,26 +80,26 @@ class RadioPalette(Palette): def __init__(self, **kwargs): Palette.__init__(self, **kwargs) - self.top = gtk.HBox() - self.top.show() - self.set_content(self.top) + self.button_box = gtk.HBox() + self.button_box.show() + self.set_content(self.button_box) def append(self, button, label): - children = self.top.get_children() + children = self.button_box.get_children() - # palette's button should not have sub-palettes - button.palette = None + if button.palette is not None: + raise RuntimeError("Palette's button should not have sub-palettes") button.show() button.connect('clicked', self.__clicked_cb) - self.top.pack_start(button, fill=False) + self.button_box.pack_start(button, fill=False) button.__palette_label = label if not children: self.__clicked_cb(button, True) def update_button(self): - for i in self.top.get_children(): + for i in self.button_box.get_children(): self.__clicked_cb(i, True) def __clicked_cb(self, button, quiet=False): @@ -114,8 +110,11 @@ class RadioPalette(Palette): if not quiet: self.popdown(immediate=True) - parent = self.invoker and self.invoker.parent - if not isinstance(parent, RadioPaletteButton): + if self.invoker is not None: + parent = self.invoker.parent + else: + parent = None + if not isinstance(parent, RadioMenuButton): return parent.set_icon(button.props.icon_name) diff --git a/src/sugar/graphics/style.py b/src/sugar/graphics/style.py index 438aab79..a37b745c 100644 --- a/src/sugar/graphics/style.py +++ b/src/sugar/graphics/style.py @@ -132,4 +132,4 @@ COLOR_TEXT_FIELD_GREY = Color('#E5E5E5') PALETTE_CURSOR_DISTANCE = zoom(10) -TOOLBAR_ARROW_SIZE = 8 +TOOLBAR_ARROW_SIZE = zoom(24) diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbar.py index abeceee1..6e3666e3 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbar.py @@ -88,9 +88,9 @@ class ToolbarButton(ToolButton): if not self.expanded or self.palette and self.palette.is_up(): ToolButton.do_expose_event(self, event) if self.palette and self.palette.is_up(): - _paint_arrow(self, event, gtk.ARROW_DOWN) - else: _paint_arrow(self, event, gtk.ARROW_UP) + else: + _paint_arrow(self, event, gtk.ARROW_DOWN) return alloc = self.allocation @@ -107,7 +107,7 @@ class ToolbarButton(ToolButton): alloc.width - style._FOCUS_LINE_WIDTH*2, alloc.height) gtk.ToolButton.do_expose_event(self, event) - _paint_arrow(self, event, gtk.ARROW_DOWN) + _paint_arrow(self, event, gtk.ARROW_UP) class Toolbar(gtk.VBox): def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING): @@ -394,10 +394,11 @@ def _align(box_class, widget): return box def _paint_arrow(widget, event, type): - a = widget.allocation + alloc = widget.allocation + x = alloc.x + alloc.width / 2 - style.TOOLBAR_ARROW_SIZE / 2 + y = alloc.y + alloc.height - int(style.TOOLBAR_ARROW_SIZE * .85) + widget.get_style().paint_arrow(event.window, - gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, widget, + gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, widget, None, type, True, - a.x + a.width/2 - style.TOOLBAR_ARROW_SIZE/2, - a.y + a.height - style.TOOLBAR_ARROW_SIZE - style._FOCUS_LINE_WIDTH, - style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) + x, y, style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) From 5ee1f2a3cbc814b8dc759df7c2a3b90de6964e75 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Thu, 30 Jul 2009 12:20:15 +0000 Subject: [PATCH 28/51] Do not use jarabe module --- src/sugar/activity/activity.py | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index 28bb9353..6e19c51e 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -76,6 +76,7 @@ from sugar.graphics.xocolor import XoColor from sugar.graphics.toolbar import Toolbar, ToolbarButton from sugar.graphics.radiopalette import RadioPalette, RadioMenuButton from sugar.graphics.radiotoolbutton import RadioToolButton +from sugar.bundle.activitybundle import ActivityBundle from sugar.datastore import datastore from sugar.session import XSMPClient from sugar import wm @@ -1035,28 +1036,19 @@ class Activity(Window, gtk.Container): class ActivityToolbarButton(ToolbarButton): def __init__(self, activity, **kwargs): - from jarabe.journal.misc import get_icon_name - toolbar = ActivityToolbar(activity) toolbar.stop.hide() ToolbarButton.__init__(self, page=toolbar, **kwargs) - self.activity = activity + bundle = ActivityBundle(get_bundle_path()) client = gconf.client_get_default() color = XoColor(client.get_string('/desktop/sugar/user/color')) - icon = Icon(file=get_icon_name(activity.metadata), xo_color=color) + icon = Icon(file=bundle.get_icon(), xo_color=color) icon.show() self.set_icon_widget(icon) - def expander(self): - separator = gtk.SeparatorToolItem() - separator.props.draw = False - separator.set_expand(True) - separator.show() - return separator - def stop_button(self, **kwargs): stop = ToolButton('activity-stop', tooltip=_('Stop'), **kwargs) stop.props.accelerator = 'Q' @@ -1079,12 +1071,6 @@ class ActivityToolbarButton(ToolbarButton): redo.show() return redo - def separator(self, **kwargs): - separator = gtk.SeparatorToolItem(**kwargs) - separator.set_draw(True) - separator.show() - return separator - def copy_button(self, **kwargs): copy = ToolButton('edit-copy', **kwargs) copy.set_tooltip(_('Copy')) From b43aa43114e329a467207dd3207c4c84f3aa8a26 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Thu, 30 Jul 2009 15:08:55 +0000 Subject: [PATCH 29/51] Move activity related widgets to sugar.activity.widgets --- src/sugar/activity/activity.py | 336 +-------------------------------- src/sugar/activity/widgets.py | 306 ++++++++++++++++++++++++++++++ 2 files changed, 309 insertions(+), 333 deletions(-) create mode 100644 src/sugar/activity/widgets.py diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index 6e19c51e..f20d402b 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -67,20 +67,15 @@ from sugar.activity.activityservice import ActivityService from sugar.activity.namingalert import NamingAlert from sugar.graphics import style from sugar.graphics.window import Window -from sugar.graphics.toolbox import Toolbox -from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.toolcombobox import ToolComboBox from sugar.graphics.alert import Alert from sugar.graphics.icon import Icon -from sugar.graphics.xocolor import XoColor -from sugar.graphics.toolbar import Toolbar, ToolbarButton -from sugar.graphics.radiopalette import RadioPalette, RadioMenuButton -from sugar.graphics.radiotoolbutton import RadioToolButton -from sugar.bundle.activitybundle import ActivityBundle from sugar.datastore import datastore from sugar.session import XSMPClient from sugar import wm +# support deprecated imports +from sugar.activity.widgets import ActivityToolbar, EditToolbar, ActivityToolbox + _ = lambda msg: gettext.dgettext('sugar-toolkit', msg) SCOPE_PRIVATE = "private" @@ -91,226 +86,6 @@ J_DBUS_SERVICE = 'org.laptop.Journal' J_DBUS_PATH = '/org/laptop/Journal' J_DBUS_INTERFACE = 'org.laptop.Journal' -class ActivityToolbar(gtk.Toolbar): - """The Activity toolbar with the Journal entry title, sharing, - Keep and Stop buttons - - All activities should have this toolbar. It is easiest to add it to your - Activity by using the ActivityToolbox. - """ - def __init__(self, activity): - gtk.Toolbar.__init__(self) - - self._activity = activity - self._updating_share = False - - activity.connect('shared', self.__activity_shared_cb) - activity.connect('joined', self.__activity_shared_cb) - activity.connect('notify::max_participants', - self.__max_participants_changed_cb) - - if activity.metadata: - self.title = gtk.Entry() - self.title.set_size_request(int(gtk.gdk.screen_width() / 3), -1) - self.title.set_text(activity.metadata['title']) - self.title.connect('changed', self.__title_changed_cb) - self._add_widget(self.title) - - activity.metadata.connect('updated', self.__jobject_updated_cb) - - separator = gtk.SeparatorToolItem() - separator.props.draw = False - separator.set_expand(True) - self.insert(separator, -1) - separator.show() - - self.share = ToolComboBox(label_text=_('Share with:')) - self.share.combo.connect('changed', self.__share_changed_cb) - self.share.combo.append_item(SCOPE_PRIVATE, _('Private'), 'zoom-home') - self.share.combo.append_item(SCOPE_NEIGHBORHOOD, _('My Neighborhood'), - 'zoom-neighborhood') - self.insert(self.share, -1) - self.share.show() - - self._update_share() - - self.keep = ToolButton(tooltip=_('Keep')) - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - keep_icon = Icon(icon_name='document-save', xo_color=color) - self.keep.set_icon_widget(keep_icon) - keep_icon.show() - self.keep.props.accelerator = 'S' - self.keep.connect('clicked', self.__keep_clicked_cb) - self.insert(self.keep, -1) - self.keep.show() - - self.stop = ToolButton('activity-stop', tooltip=_('Stop')) - self.stop.props.accelerator = 'Q' - self.stop.connect('clicked', self.__stop_clicked_cb) - self.insert(self.stop, -1) - self.stop.show() - - self._update_title_sid = None - - def _update_share(self): - self._updating_share = True - - if self._activity.props.max_participants == 1: - self.share.hide() - - if self._activity.get_shared(): - self.share.set_sensitive(False) - self.share.combo.set_active(1) - else: - self.share.set_sensitive(True) - self.share.combo.set_active(0) - - self._updating_share = False - - def __share_changed_cb(self, combo): - if self._updating_share: - return - - model = self.share.combo.get_model() - it = self.share.combo.get_active_iter() - (scope, ) = model.get(it, 0) - if scope == SCOPE_NEIGHBORHOOD: - self._activity.share() - - def __keep_clicked_cb(self, button): - self._activity.copy() - - def __stop_clicked_cb(self, button): - self._activity.close() - - def __jobject_updated_cb(self, jobject): - self.title.set_text(jobject['title']) - - def __title_changed_cb(self, entry): - if not self._update_title_sid: - self._update_title_sid = gobject.timeout_add_seconds( - 1, self.__update_title_cb) - - def __update_title_cb(self): - title = self.title.get_text() - - self._activity.metadata['title'] = title - self._activity.metadata['title_set_by_user'] = '1' - self._activity.save() - - shared_activity = self._activity.get_shared_activity() - if shared_activity: - shared_activity.props.name = title - - self._update_title_sid = None - return False - - def _add_widget(self, widget, expand=False): - tool_item = gtk.ToolItem() - tool_item.set_expand(expand) - - tool_item.add(widget) - widget.show() - - self.insert(tool_item, -1) - tool_item.show() - - def __activity_shared_cb(self, activity): - self._update_share() - - def __max_participants_changed_cb(self, activity, pspec): - self._update_share() - -class EditToolbar(gtk.Toolbar): - """Provides the standard edit toolbar for Activities. - - Members: - undo -- the undo button - redo -- the redo button - copy -- the copy button - paste -- the paste button - separator -- A separator between undo/redo and copy/paste - - This class only provides the 'edit' buttons in a standard layout, - your activity will need to either hide buttons which make no sense for your - Activity, or you need to connect the button events to your own callbacks: - - ## Example from Read.activity: - # Create the edit toolbar: - self._edit_toolbar = EditToolbar(self._view) - # Hide undo and redo, they're not needed - self._edit_toolbar.undo.props.visible = False - self._edit_toolbar.redo.props.visible = False - # Hide the separator too: - self._edit_toolbar.separator.props.visible = False - - # As long as nothing is selected, copy needs to be insensitive: - self._edit_toolbar.copy.set_sensitive(False) - # When the user clicks the button, call _edit_toolbar_copy_cb() - self._edit_toolbar.copy.connect('clicked', self._edit_toolbar_copy_cb) - - # Add the edit toolbar: - toolbox.add_toolbar(_('Edit'), self._edit_toolbar) - # And make it visible: - self._edit_toolbar.show() - """ - def __init__(self): - gtk.Toolbar.__init__(self) - - self.undo = ToolButton('edit-undo') - self.undo.set_tooltip(_('Undo')) - self.insert(self.undo, -1) - self.undo.show() - - self.redo = ToolButton('edit-redo') - self.redo.set_tooltip(_('Redo')) - self.insert(self.redo, -1) - self.redo.show() - - self.separator = gtk.SeparatorToolItem() - self.separator.set_draw(True) - self.insert(self.separator, -1) - self.separator.show() - - self.copy = ToolButton('edit-copy') - self.copy.set_tooltip(_('Copy')) - self.insert(self.copy, -1) - self.copy.show() - - self.paste = ToolButton('edit-paste') - self.paste.set_tooltip(_('Paste')) - self.insert(self.paste, -1) - self.paste.show() - -class ActivityToolbox(Toolbox): - """Creates the Toolbox for the Activity - - By default, the toolbox contains only the ActivityToolbar. After creating - the toolbox, you can add your activity specific toolbars, for example the - EditToolbar. - - To add the ActivityToolbox to your Activity in MyActivity.__init__() do: - - # Create the Toolbar with the ActivityToolbar: - toolbox = activity.ActivityToolbox(self) - ... your code, inserting all other toolbars you need, like EditToolbar - - # Add the toolbox to the activity frame: - self.set_toolbox(toolbox) - # And make it visible: - toolbox.show() - """ - def __init__(self, activity): - Toolbox.__init__(self) - - self._activity_toolbar = ActivityToolbar(activity) - self.add_toolbar(_('Activity'), self._activity_toolbar) - self._activity_toolbar.show() - - def get_activity_toolbar(self): - return self._activity_toolbar - class _ActivitySession(gobject.GObject): __gsignals__ = { 'quit-requested': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), @@ -1034,111 +809,6 @@ class Activity(Window, gtk.Container): # DEPRECATED _shared_activity = property(lambda self: self.shared_activity, None) -class ActivityToolbarButton(ToolbarButton): - def __init__(self, activity, **kwargs): - toolbar = ActivityToolbar(activity) - toolbar.stop.hide() - - ToolbarButton.__init__(self, page=toolbar, **kwargs) - self.activity = activity - - bundle = ActivityBundle(get_bundle_path()) - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - icon = Icon(file=bundle.get_icon(), xo_color=color) - icon.show() - self.set_icon_widget(icon) - - def stop_button(self, **kwargs): - stop = ToolButton('activity-stop', tooltip=_('Stop'), **kwargs) - stop.props.accelerator = 'Q' - stop.connect('clicked', self.__stop_button_clicked_cb) - stop.show() - return stop - - def __stop_button_clicked_cb(self, button): - self.activity.close() - - def undo_button(self, **kwargs): - undo = ToolButton('edit-undo', **kwargs) - undo.set_tooltip(_('Undo')) - undo.show() - return undo - - def redo_button(self, **kwargs): - redo = ToolButton('edit-redo', **kwargs) - redo.set_tooltip(_('Redo')) - redo.show() - return redo - - def copy_button(self, **kwargs): - copy = ToolButton('edit-copy', **kwargs) - copy.set_tooltip(_('Copy')) - copy.show() - return copy - - def paste_button(self, **kwargs): - paste = ToolButton('edit-paste', **kwargs) - paste.set_tooltip(_('Paste')) - paste.show() - return paste - - def share_button(self): - palette = RadioPalette() - - private = RadioToolButton( - icon_name='zoom-home') - palette.append(private, _('Private')) - - neighborhood = RadioToolButton( - icon_name='zoom-neighborhood', - group=private) - neighborhood_handle = neighborhood.connect('clicked', - self.__neighborhood_clicked_cb) - palette.append(neighborhood, _('My Neighborhood')) - - self.activity.connect('shared', self.__update_share) - self.activity.connect('joined', self.__update_share) - - share = RadioMenuButton(palette=palette) - share.show() - - return share - - def __neighborhood_clicked_cb(self, button): - self.activity.share() - - def __update_share(self, activity): - neighborhood.handler_block(neighborhood_handle) - try: - if self.activity.get_shared(): - private.props.sensitive = False - neighborhood.props.sensitive = False - neighborhood.props.active = True - else: - private.props.sensitive = True - neighborhood.props.sensitive = True - private.props.active = True - finally: - neighborhood.handler_unblock(neighborhood_handle) - - def keep_button(self, **kwargs): - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - keep_icon = Icon(icon_name='document-save', xo_color=color) - keep_icon.show() - - keep = ToolButton(tooltip=_('Keep'), **kwargs) - keep.set_icon_widget(keep_icon) - keep.props.accelerator = 'S' - keep.connect('clicked', self.__keep_button_clicked) - keep.show() - - return keep - - def __keep_button_clicked(self, button): - self.activity.copy() - _session = None def _get_session(): diff --git a/src/sugar/activity/widgets.py b/src/sugar/activity/widgets.py new file mode 100644 index 00000000..ca920aa6 --- /dev/null +++ b/src/sugar/activity/widgets.py @@ -0,0 +1,306 @@ +# Copyright (C) 2009, Aleksey Lim +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import gtk +import gobject +import logging +import gettext +import gconf + +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.toolbar import Toolbar, ToolbarButton +from sugar.graphics.radiopalette import RadioPalette, RadioMenuButton +from sugar.graphics.radiotoolbutton import RadioToolButton +from sugar.graphics.toolbox import Toolbox +from sugar.graphics.xocolor import XoColor +from sugar.graphics.icon import Icon +from sugar.bundle.activitybundle import ActivityBundle + +_ = lambda msg: gettext.dgettext('sugar-toolkit', msg) + +class ActivityToolbarButton(ToolbarButton): + def __init__(self, activity, **kwargs): + toolbar = ActivityToolbar(activity) + toolbar.stop.hide() + + ToolbarButton.__init__(self, page=toolbar, **kwargs) + + from sugar.activity.activity import get_bundle_path + bundle = ActivityBundle(get_bundle_path()) + + client = gconf.client_get_default() + color = XoColor(client.get_string('/desktop/sugar/user/color')) + icon = Icon(file=bundle.get_icon(), xo_color=color) + icon.show() + self.set_icon_widget(icon) + +class StopButton(ToolButton): + def __init__(self, activity, **kwargs): + ToolButton.__init__(self, 'activity-stop', + tooltip=_('Stop'), + accelerator='Q', + **kwargs) + self.connect('clicked', self.__stop_button_clicked_cb, activity) + + def __stop_button_clicked_cb(self, button, activity): + activity.close() + +class UndoButton(ToolButton): + def __init__(self, **kwargs): + ToolButton.__init__(self, 'edit-undo', + tooltip=_('Undo'), + accelerator='Q', + **kwargs) + +class RedoButton(ToolButton): + def __init__(self, **kwargs): + ToolButton.__init__(self, 'edit-redo', + tooltip=_('Redo'), + **kwargs) + +class CopyButton(ToolButton): + def __init__(self, **kwargs): + ToolButton.__init__(self, 'edit-copy', + tooltip=_('Copy'), + **kwargs) + +class PasteButton(ToolButton): + def __init__(self, **kwargs): + ToolButton.__init__(self, 'edit-paste', + tooltip=_('Paste'), + **kwargs) + +class ShareButton(RadioMenuButton): + def __init__(self, activity, **kwargs): + palette = RadioPalette() + + self.__private = RadioToolButton( + icon_name='zoom-home') + palette.append(self.__private, _('Private')) + + self.__neighborhood = RadioToolButton( + icon_name='zoom-neighborhood', + group=self.__private) + self.__neighborhood_handle = self.__neighborhood.connect( + 'clicked', self.__neighborhood_clicked_cb, activity) + palette.append(self.__neighborhood, _('My Neighborhood')) + + activity.connect('shared', self.__update_share) + activity.connect('joined', self.__update_share) + + RadioMenuButton.__init__(self, palette=palette, **kwargs) + + def __neighborhood_clicked_cb(self, button, activity): + activity.share() + + def __update_share(self, activity): + self.__neighborhood.handler_block(self.__neighborhood_handle) + try: + if activity.get_shared(): + self.__private.props.sensitive = False + self.__neighborhood.props.sensitive = False + self.__neighborhood.props.active = True + else: + self.__private.props.sensitive = True + self.__neighborhood.props.sensitive = True + self.__private.props.active = True + finally: + self.__neighborhood.handler_unblock(self.__neighborhood_handle) + +class KeepButton(ToolButton): + def __init__(self, activity, **kwargs): + ToolButton.__init__(self, + tooltip=_('Keep'), + accelerator='S', + **kwargs) + + client = gconf.client_get_default() + color = XoColor(client.get_string('/desktop/sugar/user/color')) + keep_icon = Icon(icon_name='document-save', xo_color=color) + keep_icon.show() + + self.set_icon_widget(keep_icon) + self.connect('clicked', self.__keep_button_clicked, activity) + + def __keep_button_clicked(self, button, activity): + activity.copy() + +class TitleEntry(gtk.Entry): + def __init__(self, activity, **kwargs): + gtk.Entry.__init__(self, **kwargs) + self.__update_title_sid = None + + self.set_size_request(int(gtk.gdk.screen_width() / 3), -1) + self.set_text(activity.metadata['title']) + self.connect('changed', self.__title_changed_cb, activity) + + activity.metadata.connect('updated', self.__jobject_updated_cb) + + def __jobject_updated_cb(self, jobject): + self.set_text(jobject['title']) + + def __title_changed_cb(self, entry, activity): + if not self.__update_title_sid: + self.__update_title_sid = gobject.timeout_add_seconds( + 1, self.__update_title_cb, activity) + + def __update_title_cb(self, activity): + title = self.get_text() + + activity.metadata['title'] = title + activity.metadata['title_set_by_user'] = '1' + activity.save() + + shared_activity = activity.get_shared_activity() + if shared_activity: + shared_activity.props.name = title + + self.__update_title_sid = None + return False + +class ActivityToolbar(gtk.Toolbar): + """The Activity toolbar with the Journal entry title, sharing, + Keep and Stop buttons + + All activities should have this toolbar. It is easiest to add it to your + Activity by using the ActivityToolbox. + """ + def __init__(self, activity): + gtk.Toolbar.__init__(self) + + self._activity = activity + + if activity.metadata: + self.title = TitleEntry(activity) + self._add_widget(self.title) + + separator = gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + self.insert(separator, -1) + separator.show() + + self.share = ShareButton(activity) + self.share.show() + self.insert(self.share, -1) + + self.keep = KeepButton(activity) + self.insert(self.keep, -1) + self.keep.show() + + self.stop = StopButton(activity) + self.insert(self.stop, -1) + self.stop.show() + + def _add_widget(self, widget, expand=False): + tool_item = gtk.ToolItem() + tool_item.set_expand(expand) + + tool_item.add(widget) + widget.show() + + self.insert(tool_item, -1) + tool_item.show() + +class EditToolbar(gtk.Toolbar): + """Provides the standard edit toolbar for Activities. + + Members: + undo -- the undo button + redo -- the redo button + copy -- the copy button + paste -- the paste button + separator -- A separator between undo/redo and copy/paste + + This class only provides the 'edit' buttons in a standard layout, + your activity will need to either hide buttons which make no sense for your + Activity, or you need to connect the button events to your own callbacks: + + ## Example from Read.activity: + # Create the edit toolbar: + self._edit_toolbar = EditToolbar(self._view) + # Hide undo and redo, they're not needed + self._edit_toolbar.undo.props.visible = False + self._edit_toolbar.redo.props.visible = False + # Hide the separator too: + self._edit_toolbar.separator.props.visible = False + + # As long as nothing is selected, copy needs to be insensitive: + self._edit_toolbar.copy.set_sensitive(False) + # When the user clicks the button, call _edit_toolbar_copy_cb() + self._edit_toolbar.copy.connect('clicked', self._edit_toolbar_copy_cb) + + # Add the edit toolbar: + toolbox.add_toolbar(_('Edit'), self._edit_toolbar) + # And make it visible: + self._edit_toolbar.show() + """ + def __init__(self): + gtk.Toolbar.__init__(self) + + self.undo = ToolButton('edit-undo') + self.undo.set_tooltip(_('Undo')) + self.insert(self.undo, -1) + self.undo.show() + + self.redo = ToolButton('edit-redo') + self.redo.set_tooltip(_('Redo')) + self.insert(self.redo, -1) + self.redo.show() + + self.separator = gtk.SeparatorToolItem() + self.separator.set_draw(True) + self.insert(self.separator, -1) + self.separator.show() + + self.copy = ToolButton('edit-copy') + self.copy.set_tooltip(_('Copy')) + self.insert(self.copy, -1) + self.copy.show() + + self.paste = ToolButton('edit-paste') + self.paste.set_tooltip(_('Paste')) + self.insert(self.paste, -1) + self.paste.show() + +class ActivityToolbox(Toolbox): + """Creates the Toolbox for the Activity + + By default, the toolbox contains only the ActivityToolbar. After creating + the toolbox, you can add your activity specific toolbars, for example the + EditToolbar. + + To add the ActivityToolbox to your Activity in MyActivity.__init__() do: + + # Create the Toolbar with the ActivityToolbar: + toolbox = activity.ActivityToolbox(self) + ... your code, inserting all other toolbars you need, like EditToolbar + + # Add the toolbox to the activity frame: + self.set_toolbox(toolbox) + # And make it visible: + toolbox.show() + """ + def __init__(self, activity): + Toolbox.__init__(self) + + self._activity_toolbar = ActivityToolbar(activity) + self.add_toolbar(_('Activity'), self._activity_toolbar) + self._activity_toolbar.show() + + def get_activity_toolbar(self): + return self._activity_toolbar From 61ab4110faec6032084ed9ec1423004407ff3fb8 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Thu, 30 Jul 2009 15:25:30 +0000 Subject: [PATCH 30/51] Rename toolbar.py to toolbarbox.py --- examples/toolbar.py | 4 ++-- src/sugar/activity/activity.py | 4 ++++ src/sugar/activity/widgets.py | 2 +- src/sugar/graphics/{toolbar.py => toolbarbox.py} | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) rename src/sugar/graphics/{toolbar.py => toolbarbox.py} (99%) diff --git a/examples/toolbar.py b/examples/toolbar.py index 6150be36..6a6c143d 100644 --- a/examples/toolbar.py +++ b/examples/toolbar.py @@ -1,7 +1,7 @@ import gtk from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.toolbar import Toolbar, ToolbarButton +from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton from sugar.graphics import style window = gtk.Window() @@ -9,7 +9,7 @@ window = gtk.Window() box = gtk.VBox() window.add(box) -toolbar = Toolbar() +toolbar = ToolbarBox() box.pack_start(toolbar, False) tollbarbutton_1 = ToolbarButton( diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index f20d402b..d94cdbec 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -806,6 +806,10 @@ class Activity(Window, gtk.Container): def get_document_path(self, async_cb, async_err_cb): async_err_cb(NotImplementedError()) + def set_toolbar_box(self, toolbar_box): + # make more consistent using ToolbarBox instead of Toolbox + self.set_toolbox(toolbar_box) + # DEPRECATED _shared_activity = property(lambda self: self.shared_activity, None) diff --git a/src/sugar/activity/widgets.py b/src/sugar/activity/widgets.py index ca920aa6..ae4abdf9 100644 --- a/src/sugar/activity/widgets.py +++ b/src/sugar/activity/widgets.py @@ -22,7 +22,7 @@ import gettext import gconf from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.toolbar import Toolbar, ToolbarButton +from sugar.graphics.toolbarbox import ToolbarButton from sugar.graphics.radiopalette import RadioPalette, RadioMenuButton from sugar.graphics.radiotoolbutton import RadioToolButton from sugar.graphics.toolbox import Toolbox diff --git a/src/sugar/graphics/toolbar.py b/src/sugar/graphics/toolbarbox.py similarity index 99% rename from src/sugar/graphics/toolbar.py rename to src/sugar/graphics/toolbarbox.py index 6e3666e3..3daca703 100644 --- a/src/sugar/graphics/toolbar.py +++ b/src/sugar/graphics/toolbarbox.py @@ -109,7 +109,7 @@ class ToolbarButton(ToolButton): gtk.ToolButton.do_expose_event(self, event) _paint_arrow(self, event, gtk.ARROW_UP) -class Toolbar(gtk.VBox): +class ToolbarBox(gtk.VBox): def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING): gtk.VBox.__init__(self) From b69d87520146291208c5e4e327f7b67cad46df1f Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Thu, 30 Jul 2009 15:38:16 +0000 Subject: [PATCH 31/51] Fix Makefile.am --- src/sugar/graphics/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sugar/graphics/Makefile.am b/src/sugar/graphics/Makefile.am index 8f89a2cf..a35fb4a0 100644 --- a/src/sugar/graphics/Makefile.am +++ b/src/sugar/graphics/Makefile.am @@ -20,7 +20,7 @@ sugar_PYTHON = \ roundbox.py \ style.py \ toggletoolbutton.py \ - toolbar.py \ + toolbarbox.py \ toolbox.py \ toolbutton.py \ toolcombobox.py \ From 7ca9574ca1232dd4f884befd33af02404592a036 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Thu, 30 Jul 2009 16:20:10 +0000 Subject: [PATCH 32/51] Rename ToolbarBox.top to ToolbarBox.bar --- examples/toolbar.py | 12 ++++++------ src/sugar/graphics/toolbarbox.py | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/toolbar.py b/examples/toolbar.py index 6a6c143d..8dde7a1c 100644 --- a/examples/toolbar.py +++ b/examples/toolbar.py @@ -15,24 +15,24 @@ box.pack_start(toolbar, False) tollbarbutton_1 = ToolbarButton( page=gtk.Button('sub-widget #1'), icon_name='computer-xo') -toolbar.top.insert(tollbarbutton_1, -1) +toolbar.bar.insert(tollbarbutton_1, -1) tollbarbutton_2 = ToolbarButton( page=gtk.Button('sub-widget #2'), icon_name='button_cancel', tooltip='with custom palette instead of sub-widget') -toolbar.top.insert(tollbarbutton_2, -1) +toolbar.bar.insert(tollbarbutton_2, -1) -toolbar.top.insert(gtk.SeparatorToolItem(), -1) +toolbar.bar.insert(gtk.SeparatorToolItem(), -1) def del_cb(widget): - toolbar.top.remove(tollbarbutton_3) + toolbar.bar.remove(tollbarbutton_3) del_b = gtk.Button('delete sub-widget #3') del_b.connect('clicked', del_cb) tollbarbutton_3 = ToolbarButton( page=del_b, icon_name='activity-journal') -toolbar.top.insert(tollbarbutton_3, -1) +toolbar.bar.insert(tollbarbutton_3, -1) subbar = gtk.Toolbar() subbutton = ToolButton( @@ -44,7 +44,7 @@ subbar.show_all() tollbarbutton_4 = ToolbarButton( page=subbar, icon_name='document-save') -toolbar.top.insert(tollbarbutton_4, -1) +toolbar.bar.insert(tollbarbutton_4, -1) print [i.props.page for i in toolbar.subs] diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index 3daca703..1e53dc3a 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -113,10 +113,10 @@ class ToolbarBox(gtk.VBox): def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING): gtk.VBox.__init__(self) - self.__top = gtk.Toolbar() - self.__top.owner = self + self.__bar = gtk.Toolbar() + self.__bar.owner = self - top_widget = _align(gtk.EventBox, self.__top) + top_widget = _align(gtk.EventBox, self.__bar) self.pack_start(top_widget) self.props.padding = padding @@ -128,23 +128,23 @@ class ToolbarBox(gtk.VBox): self.__notebook.set_show_tabs(False) self.__notebook.show() - self.__top.connect('remove', self.__remove_cb) + self.__bar.connect('remove', self.__remove_cb) - top = property(lambda self: self.__top) + bar = property(lambda self: self.__bar) def get_padding(self): - return self.__top.parent.props.left_padding + return self.bar.parent.props.left_padding def set_padding(self, pad): - self.__top.parent.set_padding(0, 0, pad, pad) + self.bar.parent.set_padding(0, 0, pad, pad) padding = gobject.property(type=object, getter=get_padding, setter=set_padding) def get_subs(self): out = [] - for i in range(self.top.get_n_items()): - page = self.top.get_nth_item(i) + for i in range(self.bar.get_n_items()): + page = self.bar.get_nth_item(i) if isinstance(page, ToolbarButton): out.append(page) return out @@ -154,8 +154,8 @@ class ToolbarBox(gtk.VBox): def modify_bg(self, state, color): if state == gtk.STATE_NORMAL: self._bg = color - self.__top.parent.parent.modify_bg(state, color) - self.__top.modify_bg(state, color) + self.bar.parent.parent.modify_bg(state, color) + self.bar.modify_bg(state, color) def __remove_cb(self, sender, widget): if not isinstance(widget, ToolbarButton): @@ -304,7 +304,7 @@ class _Palette(gtk.Window): self.add(page) x, y = toolbar.window.get_origin() - self.move(x + toolbar.allocation.x, y + toolbar.top.allocation.height) + self.move(x + toolbar.allocation.x, y + toolbar.bar.allocation.height) self.set_transient_for(self._invoker.get_toplevel()) if not immediate: From 3dd0ac8432e10a31ef6eddb11cf7c3dd062e629a Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Thu, 30 Jul 2009 16:25:04 +0000 Subject: [PATCH 33/51] Rename ToolbarBox.bar to ToolbarBox.toolbar --- examples/toolbar.py | 12 ++++++------ src/sugar/graphics/toolbarbox.py | 25 +++++++++++++------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/examples/toolbar.py b/examples/toolbar.py index 8dde7a1c..14ab3258 100644 --- a/examples/toolbar.py +++ b/examples/toolbar.py @@ -15,24 +15,24 @@ box.pack_start(toolbar, False) tollbarbutton_1 = ToolbarButton( page=gtk.Button('sub-widget #1'), icon_name='computer-xo') -toolbar.bar.insert(tollbarbutton_1, -1) +toolbar.toolbar.insert(tollbarbutton_1, -1) tollbarbutton_2 = ToolbarButton( page=gtk.Button('sub-widget #2'), icon_name='button_cancel', tooltip='with custom palette instead of sub-widget') -toolbar.bar.insert(tollbarbutton_2, -1) +toolbar.toolbar.insert(tollbarbutton_2, -1) -toolbar.bar.insert(gtk.SeparatorToolItem(), -1) +toolbar.toolbar.insert(gtk.SeparatorToolItem(), -1) def del_cb(widget): - toolbar.bar.remove(tollbarbutton_3) + toolbar.toolbar.remove(tollbarbutton_3) del_b = gtk.Button('delete sub-widget #3') del_b.connect('clicked', del_cb) tollbarbutton_3 = ToolbarButton( page=del_b, icon_name='activity-journal') -toolbar.bar.insert(tollbarbutton_3, -1) +toolbar.toolbar.insert(tollbarbutton_3, -1) subbar = gtk.Toolbar() subbutton = ToolButton( @@ -44,7 +44,7 @@ subbar.show_all() tollbarbutton_4 = ToolbarButton( page=subbar, icon_name='document-save') -toolbar.bar.insert(tollbarbutton_4, -1) +toolbar.toolbar.insert(tollbarbutton_4, -1) print [i.props.page for i in toolbar.subs] diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index 1e53dc3a..a985d7d3 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -113,10 +113,10 @@ class ToolbarBox(gtk.VBox): def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING): gtk.VBox.__init__(self) - self.__bar = gtk.Toolbar() - self.__bar.owner = self + self.__toolbar = gtk.Toolbar() + self.__toolbar.owner = self - top_widget = _align(gtk.EventBox, self.__bar) + top_widget = _align(gtk.EventBox, self.__toolbar) self.pack_start(top_widget) self.props.padding = padding @@ -128,23 +128,23 @@ class ToolbarBox(gtk.VBox): self.__notebook.set_show_tabs(False) self.__notebook.show() - self.__bar.connect('remove', self.__remove_cb) + self.__toolbar.connect('remove', self.__remove_cb) - bar = property(lambda self: self.__bar) + toolbar = property(lambda self: self.__toolbar) def get_padding(self): - return self.bar.parent.props.left_padding + return self.toolbar.parent.props.left_padding def set_padding(self, pad): - self.bar.parent.set_padding(0, 0, pad, pad) + self.toolbar.parent.set_padding(0, 0, pad, pad) padding = gobject.property(type=object, getter=get_padding, setter=set_padding) def get_subs(self): out = [] - for i in range(self.bar.get_n_items()): - page = self.bar.get_nth_item(i) + for i in range(self.toolbar.get_n_items()): + page = self.toolbar.get_nth_item(i) if isinstance(page, ToolbarButton): out.append(page) return out @@ -154,8 +154,8 @@ class ToolbarBox(gtk.VBox): def modify_bg(self, state, color): if state == gtk.STATE_NORMAL: self._bg = color - self.bar.parent.parent.modify_bg(state, color) - self.bar.modify_bg(state, color) + self.toolbar.parent.parent.modify_bg(state, color) + self.toolbar.modify_bg(state, color) def __remove_cb(self, sender, widget): if not isinstance(widget, ToolbarButton): @@ -304,7 +304,8 @@ class _Palette(gtk.Window): self.add(page) x, y = toolbar.window.get_origin() - self.move(x + toolbar.allocation.x, y + toolbar.bar.allocation.height) + self.move(x + toolbar.allocation.x, + y + toolbar.toolbar.allocation.height) self.set_transient_for(self._invoker.get_toplevel()) if not immediate: From 3b545cbcbb4610988dace897a972a231587e2818 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Thu, 30 Jul 2009 17:06:14 +0000 Subject: [PATCH 34/51] Remove redundant ToolbarBox props --- src/sugar/graphics/toolbarbox.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index a985d7d3..851884ac 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -141,16 +141,6 @@ class ToolbarBox(gtk.VBox): padding = gobject.property(type=object, getter=get_padding, setter=set_padding) - def get_subs(self): - out = [] - for i in range(self.toolbar.get_n_items()): - page = self.toolbar.get_nth_item(i) - if isinstance(page, ToolbarButton): - out.append(page) - return out - - subs = property(get_subs) - def modify_bg(self, state, color): if state == gtk.STATE_NORMAL: self._bg = color From 7bec8aba1b76d462b5d405862d64af71acb0589c Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Thu, 30 Jul 2009 17:13:36 +0000 Subject: [PATCH 35/51] Do not use do_clicked in RadioMenuButton --- src/sugar/graphics/radiopalette.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index d9ca2895..6d86ec43 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -33,14 +33,17 @@ class RadioMenuButton(ToolButton): self.__palette_cb(None, None) self.connect('notify::palette', self.__palette_cb) + self.connect('clicked', self.__clicked_cb) + + def __clicked_cb(self, button): + self._clicked() def __palette_cb(self, widget, pspec): if not isinstance(self.props.palette, RadioPalette): return self.props.palette.update_button() - # We use do_clicked to have a chance to override it in RadioToolsButton - def do_clicked(self): + def _clicked(self): if not self.palette: return if self.palette.is_up() and \ @@ -71,7 +74,7 @@ class RadioToolsButton(RadioMenuButton): def __init__(self, **kwargs): RadioMenuButton.__init__(self, **kwargs) - def do_clicked(self): + def _clicked(self): if not self.selected_button: return self.selected_button.emit('clicked') From 7bfb7704d747ef2a2877df81e05af0f5aad7e0bc Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 01:55:21 +0000 Subject: [PATCH 36/51] Fix Makefile.am --- src/sugar/activity/Makefile.am | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/sugar/activity/Makefile.am b/src/sugar/activity/Makefile.am index 91f6ea8f..e2e6fdce 100644 --- a/src/sugar/activity/Makefile.am +++ b/src/sugar/activity/Makefile.am @@ -1,10 +1,11 @@ sugardir = $(pythondir)/sugar/activity -sugar_PYTHON = \ - __init__.py \ - activity.py \ - activityfactory.py \ - activityhandle.py \ - activityservice.py \ - bundlebuilder.py \ - main.py \ - namingalert.py \ No newline at end of file +sugar_PYTHON = \ + __init__.py \ + activity.py \ + activityfactory.py \ + activityhandle.py \ + activityservice.py \ + bundlebuilder.py \ + main.py \ + namingalert.py \ + widgets.py From 353564f12c6e3aecfe0af19f85c3e09ed9692cf1 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 03:49:05 +0000 Subject: [PATCH 37/51] Fix review issues --- examples/toolbar.py | 2 - src/sugar/activity/activity.py | 4 -- src/sugar/activity/widgets.py | 87 ++++++++++++++---------------- src/sugar/graphics/radiopalette.py | 10 ++-- src/sugar/graphics/toolbarbox.py | 66 ++++++++++++++--------- src/sugar/graphics/window.py | 48 +++++++++++------ 6 files changed, 119 insertions(+), 98 deletions(-) diff --git a/examples/toolbar.py b/examples/toolbar.py index 14ab3258..2faea1f8 100644 --- a/examples/toolbar.py +++ b/examples/toolbar.py @@ -46,7 +46,5 @@ tollbarbutton_4 = ToolbarButton( icon_name='document-save') toolbar.toolbar.insert(tollbarbutton_4, -1) -print [i.props.page for i in toolbar.subs] - window.show_all() gtk.main() diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py index d94cdbec..f20d402b 100644 --- a/src/sugar/activity/activity.py +++ b/src/sugar/activity/activity.py @@ -806,10 +806,6 @@ class Activity(Window, gtk.Container): def get_document_path(self, async_cb, async_err_cb): async_err_cb(NotImplementedError()) - def set_toolbar_box(self, toolbar_box): - # make more consistent using ToolbarBox instead of Toolbox - self.set_toolbox(toolbar_box) - # DEPRECATED _shared_activity = property(lambda self: self.shared_activity, None) diff --git a/src/sugar/activity/widgets.py b/src/sugar/activity/widgets.py index ae4abdf9..52f39da8 100644 --- a/src/sugar/activity/widgets.py +++ b/src/sugar/activity/widgets.py @@ -50,10 +50,9 @@ class ActivityToolbarButton(ToolbarButton): class StopButton(ToolButton): def __init__(self, activity, **kwargs): - ToolButton.__init__(self, 'activity-stop', - tooltip=_('Stop'), - accelerator='Q', - **kwargs) + ToolButton.__init__(self, 'activity-stop', **kwargs) + self.props.tooltip = _('Stop') + self.props.accelerator = 'Q' self.connect('clicked', self.__stop_button_clicked_cb, activity) def __stop_button_clicked_cb(self, button, activity): @@ -61,72 +60,68 @@ class StopButton(ToolButton): class UndoButton(ToolButton): def __init__(self, **kwargs): - ToolButton.__init__(self, 'edit-undo', - tooltip=_('Undo'), - accelerator='Q', - **kwargs) + ToolButton.__init__(self, 'edit-undo', **kwargs) + self.props.tooltip = _('Undo') + self.props.accelerator = 'Q' class RedoButton(ToolButton): def __init__(self, **kwargs): - ToolButton.__init__(self, 'edit-redo', - tooltip=_('Redo'), - **kwargs) + ToolButton.__init__(self, 'edit-redo', **kwargs) + self.props.tooltip = _('Redo') class CopyButton(ToolButton): def __init__(self, **kwargs): - ToolButton.__init__(self, 'edit-copy', - tooltip=_('Copy'), - **kwargs) + ToolButton.__init__(self, 'edit-copy', **kwargs) + self.props.tooltip = _('Copy') class PasteButton(ToolButton): def __init__(self, **kwargs): - ToolButton.__init__(self, 'edit-paste', - tooltip=_('Paste'), - **kwargs) + ToolButton.__init__(self, 'edit-paste', **kwargs) + self.props.tooltip = _('Paste') class ShareButton(RadioMenuButton): def __init__(self, activity, **kwargs): palette = RadioPalette() - self.__private = RadioToolButton( + self.private = RadioToolButton( icon_name='zoom-home') - palette.append(self.__private, _('Private')) + palette.append(self.private, _('Private')) - self.__neighborhood = RadioToolButton( + self.neighborhood = RadioToolButton( icon_name='zoom-neighborhood', - group=self.__private) - self.__neighborhood_handle = self.__neighborhood.connect( + group=self.private) + self.__neighborhood_handle = self.neighborhood.connect( 'clicked', self.__neighborhood_clicked_cb, activity) - palette.append(self.__neighborhood, _('My Neighborhood')) + palette.append(self.neighborhood, _('My Neighborhood')) - activity.connect('shared', self.__update_share) - activity.connect('joined', self.__update_share) + activity.connect('shared', self.__update_share_cb) + activity.connect('joined', self.__update_share_cb) - RadioMenuButton.__init__(self, palette=palette, **kwargs) + RadioMenuButton.__init__(self, **kwargs) + self.props.palette = palette def __neighborhood_clicked_cb(self, button, activity): activity.share() - def __update_share(self, activity): - self.__neighborhood.handler_block(self.__neighborhood_handle) + def __update_share_cb(self, activity): + self.neighborhood.handler_block(self.__neighborhood_handle) try: if activity.get_shared(): - self.__private.props.sensitive = False - self.__neighborhood.props.sensitive = False - self.__neighborhood.props.active = True + self.private.props.sensitive = False + self.neighborhood.props.sensitive = False + self.neighborhood.props.active = True else: - self.__private.props.sensitive = True - self.__neighborhood.props.sensitive = True - self.__private.props.active = True + self.private.props.sensitive = True + self.neighborhood.props.sensitive = True + self.private.props.active = True finally: - self.__neighborhood.handler_unblock(self.__neighborhood_handle) + self.neighborhood.handler_unblock(self.__neighborhood_handle) class KeepButton(ToolButton): def __init__(self, activity, **kwargs): - ToolButton.__init__(self, - tooltip=_('Keep'), - accelerator='S', - **kwargs) + ToolButton.__init__(self, **kwargs) + self.props.tooltip = _('Keep') + self.props.accelerator = 'S' client = gconf.client_get_default() color = XoColor(client.get_string('/desktop/sugar/user/color')) @@ -166,7 +161,7 @@ class TitleEntry(gtk.Entry): activity.save() shared_activity = activity.get_shared_activity() - if shared_activity: + if shared_activity is None: shared_activity.props.name = title self.__update_title_sid = None @@ -252,13 +247,11 @@ class EditToolbar(gtk.Toolbar): def __init__(self): gtk.Toolbar.__init__(self) - self.undo = ToolButton('edit-undo') - self.undo.set_tooltip(_('Undo')) + self.undo = UndoButton() self.insert(self.undo, -1) self.undo.show() - self.redo = ToolButton('edit-redo') - self.redo.set_tooltip(_('Redo')) + self.redo = RedoButton() self.insert(self.redo, -1) self.redo.show() @@ -267,13 +260,11 @@ class EditToolbar(gtk.Toolbar): self.insert(self.separator, -1) self.separator.show() - self.copy = ToolButton('edit-copy') - self.copy.set_tooltip(_('Copy')) + self.copy = CopyButton() self.insert(self.copy, -1) self.copy.show() - self.paste = ToolButton('edit-paste') - self.paste.set_tooltip(_('Paste')) + self.paste = PasteButton() self.insert(self.paste, -1) self.paste.show() diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index 6d86ec43..e7d318dc 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -36,14 +36,14 @@ class RadioMenuButton(ToolButton): self.connect('clicked', self.__clicked_cb) def __clicked_cb(self, button): - self._clicked() + self.on_click() def __palette_cb(self, widget, pspec): if not isinstance(self.props.palette, RadioPalette): return self.props.palette.update_button() - def _clicked(self): + def on_click(self): if not self.palette: return if self.palette.is_up() and \ @@ -74,7 +74,7 @@ class RadioToolsButton(RadioMenuButton): def __init__(self, **kwargs): RadioMenuButton.__init__(self, **kwargs) - def _clicked(self): + def on_click(self): if not self.selected_button: return self.selected_button.emit('clicked') @@ -96,7 +96,7 @@ class RadioPalette(Palette): button.show() button.connect('clicked', self.__clicked_cb) self.button_box.pack_start(button, fill=False) - button.__palette_label = label + button.palette_label = label if not children: self.__clicked_cb(button, True) @@ -109,7 +109,7 @@ class RadioPalette(Palette): if not button.get_active(): return - self.set_primary_text(button.__palette_label) + self.set_primary_text(button.palette_label) if not quiet: self.popdown(immediate=True) diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index 851884ac..a9c04e8e 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -22,9 +22,8 @@ from gobject import SIGNAL_RUN_FIRST, TYPE_NONE from sugar.graphics import style from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.palette import _PopupAnimation, _PopdownAnimation from sugar.graphics.palette import MouseSpeedDetector, Invoker -from sugar.graphics import animator +from sugar.graphics.animator import Animator, Animation from sugar.graphics import palettegroup class ToolbarButton(ToolButton): @@ -37,55 +36,56 @@ class ToolbarButton(ToolButton): self.palette = _Palette(self) self.connect('clicked', - lambda widget: self.set_expanded(not self.expanded)) + lambda widget: self.set_expanded(not self.expanded_page)) - def get_toolbar(self): + def get_toolbar_box(self): if not hasattr(self.parent, 'owner'): return None return self.parent.owner - toolbar = property(get_toolbar) + toolbar_box = property(get_toolbar_box) def get_page(self): return self._page.child.child def set_page(self, page): - self._page = _align(_Box, page) + self._page = _embody_page(_Box, page) self._page._toolitem = self page.show() page = gobject.property(type=object, getter=get_page, setter=set_page) def get_expanded(self): - return bool(self.toolbar) and bool(self._page) and \ - self.toolbar._expanded_page() == self._page + return self.toolbar_box is not None and self._page is not None and \ + self.toolbar_box._expanded_page() == self._page def set_expanded(self, value): - if not self.toolbar or not self._page or self.get_expanded() == value: + if not self.toolbar_box or not self._page or \ + self.get_expanded() == value: return if isinstance(self.palette, _Palette) and self.palette.is_up(): self.palette.popdown(immediate=True) if not value: - self.toolbar._shrink_page(self._page) + self.toolbar_box.shrink_page(self._page) return - expanded = self.toolbar._expanded_page() + expanded = self.toolbar_box._expanded_page() if expanded and expanded._toolitem.window: expanded._toolitem.window.invalidate_rect(None, True) if self._page.parent: self.palette.remove(self._page) - self.modify_bg(gtk.STATE_NORMAL, self.toolbar._bg) + self.modify_bg(gtk.STATE_NORMAL, self.toolbar_box._bg) - self.toolbar._expand_page(self._page) + self.toolbar_box._expand_page(self._page) - expanded = property(get_expanded, set_expanded) + expanded_page = property(get_expanded, set_expanded) def do_expose_event(self, event): - if not self.expanded or self.palette and self.palette.is_up(): + if not self.expanded_page or self.palette and self.palette.is_up(): ToolButton.do_expose_event(self, event) if self.palette and self.palette.is_up(): _paint_arrow(self, event, gtk.ARROW_UP) @@ -116,7 +116,7 @@ class ToolbarBox(gtk.VBox): self.__toolbar = gtk.Toolbar() self.__toolbar.owner = self - top_widget = _align(gtk.EventBox, self.__toolbar) + top_widget = _embody_page(gtk.EventBox, self.__toolbar) self.pack_start(top_widget) self.props.padding = padding @@ -162,7 +162,7 @@ class ToolbarBox(gtk.VBox): page_no = self.__notebook.get_current_page() return self.__notebook.get_nth_page(page_no) - def _shrink_page(self, page): + def shrink_page(self, page): page_no = self.__notebook.page_num(page) if page_no == -1: return @@ -211,10 +211,10 @@ class _Palette(gtk.Window): self._invoker_hids = [] self.__focus = 0 - self._popup_anim = animator.Animator(.5, 10) + self._popup_anim = Animator(.5, 10) self._popup_anim.add(_PopupAnimation(self)) - self._popdown_anim = animator.Animator(0.6, 10) + self._popdown_anim = Animator(0.6, 10) self._popdown_anim.add(_PopdownAnimation(self)) accel_group = gtk.AccelGroup() @@ -270,8 +270,8 @@ class _Palette(gtk.Window): def do_size_request(self, requisition): gtk.Window.do_size_request(self, requisition) - if self._toolitem.toolbar: - requisition.width = self._toolitem.toolbar.allocation.width + if self._toolitem.toolbar_box: + requisition.width = self._toolitem.toolbar_box.allocation.width def __realize_cb(self, widget): self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) @@ -282,10 +282,10 @@ class _Palette(gtk.Window): def popup(self, immediate=False): self._popdown_anim.stop() - toolbar = self._toolitem.toolbar + toolbar = self._toolitem.toolbar_box page = self._toolitem._page - if not self._invoker or self._toolitem.expanded or not toolbar: + if not self._invoker or self._toolitem.expanded_page or not toolbar: return _setup_page(page, style.COLOR_BLACK.get_gdk_color(), @@ -366,6 +366,24 @@ class _Palette(gtk.Window): self._invoker.notify_popdown() self._up = False +class _PopupAnimation(Animation): + def __init__(self, palette): + Animation.__init__(self, 0.0, 1.0) + self._palette = palette + + def next_frame(self, current): + if current == 1.0: + self._palette.show() + +class _PopdownAnimation(Animation): + def __init__(self, palette): + Animation.__init__(self, 0.0, 1.0) + self._palette = palette + + def next_frame(self, current): + if current == 1.0: + self._palette.hide() + def _setup_page(page, color, hpad): vpad = style._FOCUS_LINE_WIDTH page.child.set_padding(vpad, vpad, hpad, hpad) @@ -373,7 +391,7 @@ def _setup_page(page, color, hpad): page.modify_bg(gtk.STATE_NORMAL, color) page.modify_bg(gtk.STATE_PRELIGHT, color) -def _align(box_class, widget): +def _embody_page(box_class, widget): widget.show() alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0) alignment.add(widget) diff --git a/src/sugar/graphics/window.py b/src/sugar/graphics/window.py index ea92e8b6..8cec11be 100644 --- a/src/sugar/graphics/window.py +++ b/src/sugar/graphics/window.py @@ -21,6 +21,8 @@ STABLE. import gobject import gtk +import logging +import warnings from sugar.graphics.icon import Icon @@ -83,7 +85,7 @@ class Window(gtk.Window): self.connect('window-state-event', self.__window_state_event_cb) self.connect('key-press-event', self.__key_press_cb) - self.toolbox = None + self.__toolbar_box = None self._alerts = [] self._canvas = None self.tray = None @@ -120,14 +122,19 @@ class Window(gtk.Window): canvas = property(get_canvas, set_canvas) - def set_toolbox(self, toolbox): - if self.toolbox: - self._vbox.remove(self.toolbox) - - self._vbox.pack_start(toolbox, False) - self._vbox.reorder_child(toolbox, 0) - - self.toolbox = toolbox + def get_toolbar_box(self): + return self.__toolbar_box + + def set_toolbar_box(self, toolbar_box): + if self.__toolbar_box: + self._vbox.remove(self.__toolbar_box) + + self._vbox.pack_start(toolbar_box, False) + self._vbox.reorder_child(toolbar_box, 0) + + self.__toolbar_box = toolbar_box + + toolbar_box = property(get_toolbar_box, set_toolbar_box) def set_tray(self, tray, position): if self.tray: @@ -147,7 +154,7 @@ class Window(gtk.Window): self._alerts.append(alert) if len(self._alerts) == 1: self._vbox.pack_start(alert, False) - if self.toolbox is not None: + if self.__toolbar_box is not None: self._vbox.reorder_child(alert, 1) else: self._vbox.reorder_child(alert, 0) @@ -160,7 +167,7 @@ class Window(gtk.Window): self._vbox.remove(alert) if len(self._alerts) >= 1: self._vbox.pack_start(self._alerts[0], False) - if self.toolbox is not None: + if self.__toolbar_box is not None: self._vbox.reorder_child(self._alerts[0], 1) else: self._vbox.reorder_child(self._alert[0], 0) @@ -175,8 +182,8 @@ class Window(gtk.Window): return False if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN: - if self.toolbox is not None: - self.toolbox.hide() + if self.__toolbar_box is not None: + self.__toolbar_box.hide() if self.tray is not None: self.tray.hide() @@ -185,8 +192,8 @@ class Window(gtk.Window): self._unfullscreen_button.show() else: - if self.toolbox is not None: - self.toolbox.show() + if self.__toolbar_box is not None: + self.__toolbar_box.show() if self.tray is not None: self.tray.show() @@ -219,3 +226,14 @@ class Window(gtk.Window): setter=set_enable_fullscreen_mode, getter=get_enable_fullscreen_mode) + # DEPRECATED + + def set_toolbox(self, toolbar_box): + warnings.warn('use toolbar_box instead of toolbox', DeprecationWarning) + self.set_toolbar_box(toolbar_box) + + def get_toolbox(self): + warnings.warn('use toolbar_box instead of toolbox', DeprecationWarning) + return self.__toolbar_box + + toolbox = property(get_toolbox, set_toolbox) From 3dde9b68a50325101fb1724ead71d706f0b79fae Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 03:58:52 +0000 Subject: [PATCH 38/51] Do not change arrow while opening palette in ToolbarBox --- src/sugar/graphics/toolbarbox.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index a9c04e8e..b6a14ed9 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -87,10 +87,7 @@ class ToolbarButton(ToolButton): def do_expose_event(self, event): if not self.expanded_page or self.palette and self.palette.is_up(): ToolButton.do_expose_event(self, event) - if self.palette and self.palette.is_up(): - _paint_arrow(self, event, gtk.ARROW_UP) - else: - _paint_arrow(self, event, gtk.ARROW_DOWN) + _paint_arrow(self, event, gtk.ARROW_DOWN) return alloc = self.allocation From d5c5ee88ec4e14388fb760b39da087f23a0c3c4d Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 07:10:17 +0000 Subject: [PATCH 39/51] Remove old design remains --- src/sugar/graphics/toolbarbox.py | 113 +++++++++++++------------------ 1 file changed, 46 insertions(+), 67 deletions(-) diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index b6a14ed9..57b98c1d 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -28,7 +28,7 @@ from sugar.graphics import palettegroup class ToolbarButton(ToolButton): def __init__(self, **kwargs): - self._page = None + self.page_widget = None ToolButton.__init__(self, **kwargs) @@ -36,7 +36,7 @@ class ToolbarButton(ToolButton): self.palette = _Palette(self) self.connect('clicked', - lambda widget: self.set_expanded(not self.expanded_page)) + lambda widget: self.set_expanded(not self.is_expanded())) def get_toolbar_box(self): if not hasattr(self.parent, 'owner'): @@ -46,46 +46,54 @@ class ToolbarButton(ToolButton): toolbar_box = property(get_toolbar_box) def get_page(self): - return self._page.child.child + if self.page_widget is None: + return None + return self.page_widget.child.child def set_page(self, page): - self._page = _embody_page(_Box, page) - self._page._toolitem = self + self.page_widget = _embody_page(_Box, page) + self.page_widget.toolbar_button = self page.show() page = gobject.property(type=object, getter=get_page, setter=set_page) - def get_expanded(self): - return self.toolbar_box is not None and self._page is not None and \ - self.toolbar_box._expanded_page() == self._page - - def set_expanded(self, value): - if not self.toolbar_box or not self._page or \ - self.get_expanded() == value: - return + def is_expanded(self): + return self.toolbar_box is not None and self.page_widget is not None \ + and self.toolbar_box.expanded_button == self + def popdown(self): if isinstance(self.palette, _Palette) and self.palette.is_up(): self.palette.popdown(immediate=True) - if not value: - self.toolbar_box.shrink_page(self._page) + def set_expanded(self, expanded): + self.popdown() + + box = self.toolbar_box + + if not box or not self.page_widget or self.is_expanded() == expanded: return - expanded = self.toolbar_box._expanded_page() - if expanded and expanded._toolitem.window: - expanded._toolitem.window.invalidate_rect(None, True) + if not expanded: + box.remove(self.page_widget) + box.expanded_button = None + return - if self._page.parent: - self.palette.remove(self._page) + if box.expanded_button is not None: + expanded_toolitem = box.expanded_button.page_widget.toolbar_button + if expanded_toolitem.window: + expanded_toolitem.window.invalidate_rect(None, True) + box.expanded_button.set_expanded(False) - self.modify_bg(gtk.STATE_NORMAL, self.toolbar_box._bg) + if self.page_widget.parent: + self.palette.remove(self.page_widget) - self.toolbar_box._expand_page(self._page) - - expanded_page = property(get_expanded, set_expanded) + self.modify_bg(gtk.STATE_NORMAL, box.background) + _setup_page(self.page_widget, box.background, box.props.padding) + box.pack_start(self.page_widget) + box.expanded_button = self def do_expose_event(self, event): - if not self.expanded_page or self.palette and self.palette.is_up(): + if not self.is_expanded() or self.palette and self.palette.is_up(): ToolButton.do_expose_event(self, event) _paint_arrow(self, event, gtk.ARROW_DOWN) return @@ -109,9 +117,11 @@ class ToolbarButton(ToolButton): class ToolbarBox(gtk.VBox): def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING): gtk.VBox.__init__(self) + self.expanded_button = None self.__toolbar = gtk.Toolbar() self.__toolbar.owner = self + self.__toolbar.connect('remove', self.__remove_cb) top_widget = _embody_page(gtk.EventBox, self.__toolbar) self.pack_start(top_widget) @@ -120,12 +130,13 @@ class ToolbarBox(gtk.VBox): self.modify_bg(gtk.STATE_NORMAL, style.COLOR_TOOLBAR_GREY.get_gdk_color()) - self.__notebook = gtk.Notebook() - self.__notebook.set_show_border(False) - self.__notebook.set_show_tabs(False) - self.__notebook.show() - - self.__toolbar.connect('remove', self.__remove_cb) + def __remove_cb(self, sender, button): + if not isinstance(button, ToolbarButton): + return + button.popdown() + if self.expanded_button == button: + self.remove(button.page_widget) + self.expanded_button = None toolbar = property(lambda self: self.__toolbar) @@ -140,42 +151,10 @@ class ToolbarBox(gtk.VBox): def modify_bg(self, state, color): if state == gtk.STATE_NORMAL: - self._bg = color + self.background = color self.toolbar.parent.parent.modify_bg(state, color) self.toolbar.modify_bg(state, color) - def __remove_cb(self, sender, widget): - if not isinstance(widget, ToolbarButton): - return - page_no = self.__notebook.page_num(widget._page) - if page_no != -1: - self.__notebook.remove_page(page_no) - if widget.palette: - widget.palette.popdown(immediate=True) - - def _expanded_page(self): - if self.__notebook.parent is None: - return None - page_no = self.__notebook.get_current_page() - return self.__notebook.get_nth_page(page_no) - - def shrink_page(self, page): - page_no = self.__notebook.page_num(page) - if page_no == -1: - return - self.__notebook.remove_page(page_no) - self.remove(self.__notebook) - - def _expand_page(self, page): - for i in range(self.__notebook.get_n_pages()): - self.__notebook.remove_page(0) - - _setup_page(page, self._bg, self.props.padding) - self.__notebook.append_page(page) - - if self.__notebook.parent is None: - self.pack_start(self.__notebook) - class _Box(gtk.EventBox): def __init__(self): gtk.EventBox.__init__(self) @@ -183,7 +162,7 @@ class _Box(gtk.EventBox): self.set_app_paintable(True) def do_expose_event(self, widget, event): - a = self._toolitem.allocation + a = self.toolbar_button.allocation self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, 'palette-invoker', -style._FOCUS_LINE_WIDTH, 0, @@ -280,9 +259,9 @@ class _Palette(gtk.Window): self._popdown_anim.stop() toolbar = self._toolitem.toolbar_box - page = self._toolitem._page + page = self._toolitem.page_widget - if not self._invoker or self._toolitem.expanded_page or not toolbar: + if not self._invoker or self._toolitem.is_expanded() or not toolbar: return _setup_page(page, style.COLOR_BLACK.get_gdk_color(), From 4d6a2cc9bdac24d126ea9a7514d396a7325a146a Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 10:25:01 +0000 Subject: [PATCH 40/51] Fix review issues --- src/sugar/activity/widgets.py | 18 +++++++-------- src/sugar/graphics/toolbarbox.py | 39 ++++++++++++++++---------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/sugar/activity/widgets.py b/src/sugar/activity/widgets.py index 52f39da8..8485605b 100644 --- a/src/sugar/activity/widgets.py +++ b/src/sugar/activity/widgets.py @@ -90,7 +90,7 @@ class ShareButton(RadioMenuButton): self.neighborhood = RadioToolButton( icon_name='zoom-neighborhood', group=self.private) - self.__neighborhood_handle = self.neighborhood.connect( + self._neighborhood_handle = self.neighborhood.connect( 'clicked', self.__neighborhood_clicked_cb, activity) palette.append(self.neighborhood, _('My Neighborhood')) @@ -104,7 +104,7 @@ class ShareButton(RadioMenuButton): activity.share() def __update_share_cb(self, activity): - self.neighborhood.handler_block(self.__neighborhood_handle) + self.neighborhood.handler_block(self._neighborhood_handle) try: if activity.get_shared(): self.private.props.sensitive = False @@ -115,7 +115,7 @@ class ShareButton(RadioMenuButton): self.neighborhood.props.sensitive = True self.private.props.active = True finally: - self.neighborhood.handler_unblock(self.__neighborhood_handle) + self.neighborhood.handler_unblock(self._neighborhood_handle) class KeepButton(ToolButton): def __init__(self, activity, **kwargs): @@ -129,15 +129,15 @@ class KeepButton(ToolButton): keep_icon.show() self.set_icon_widget(keep_icon) - self.connect('clicked', self.__keep_button_clicked, activity) + self.connect('clicked', self.__keep_button_clicked_cb, activity) - def __keep_button_clicked(self, button, activity): + def __keep_button_clicked_cb(self, button, activity): activity.copy() class TitleEntry(gtk.Entry): def __init__(self, activity, **kwargs): gtk.Entry.__init__(self, **kwargs) - self.__update_title_sid = None + self._update_title_sid = None self.set_size_request(int(gtk.gdk.screen_width() / 3), -1) self.set_text(activity.metadata['title']) @@ -149,8 +149,8 @@ class TitleEntry(gtk.Entry): self.set_text(jobject['title']) def __title_changed_cb(self, entry, activity): - if not self.__update_title_sid: - self.__update_title_sid = gobject.timeout_add_seconds( + if not self._update_title_sid: + self._update_title_sid = gobject.timeout_add_seconds( 1, self.__update_title_cb, activity) def __update_title_cb(self, activity): @@ -164,7 +164,7 @@ class TitleEntry(gtk.Entry): if shared_activity is None: shared_activity.props.name = title - self.__update_title_sid = None + self._update_title_sid = None return False class ActivityToolbar(gtk.Toolbar): diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index 57b98c1d..2e1d93be 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -119,11 +119,11 @@ class ToolbarBox(gtk.VBox): gtk.VBox.__init__(self) self.expanded_button = None - self.__toolbar = gtk.Toolbar() - self.__toolbar.owner = self - self.__toolbar.connect('remove', self.__remove_cb) + self._toolbar = gtk.Toolbar() + self._toolbar.owner = self + self._toolbar.connect('remove', self.__remove_cb) - top_widget = _embody_page(gtk.EventBox, self.__toolbar) + top_widget = _embody_page(gtk.EventBox, self._toolbar) self.pack_start(top_widget) self.props.padding = padding @@ -138,7 +138,7 @@ class ToolbarBox(gtk.VBox): self.remove(button.page_widget) self.expanded_button = None - toolbar = property(lambda self: self.__toolbar) + toolbar = property(lambda self: self._toolbar) def get_padding(self): return self.toolbar.parent.props.left_padding @@ -162,7 +162,7 @@ class _Box(gtk.EventBox): self.set_app_paintable(True) def do_expose_event(self, widget, event): - a = self.toolbar_button.allocation + alloc = self.toolbar_button.allocation self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, 'palette-invoker', -style._FOCUS_LINE_WIDTH, 0, @@ -170,8 +170,9 @@ class _Box(gtk.EventBox): self.allocation.height + style._FOCUS_LINE_WIDTH) self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, None, - a.x + style._FOCUS_LINE_WIDTH, 0, - a.width - style._FOCUS_LINE_WIDTH*2, style._FOCUS_LINE_WIDTH) + alloc.x + style._FOCUS_LINE_WIDTH, 0, + alloc.width - style._FOCUS_LINE_WIDTH*2, + style._FOCUS_LINE_WIDTH) class _Palette(gtk.Window): def __init__(self, toolitem, **kwargs): @@ -185,7 +186,7 @@ class _Palette(gtk.Window): self._invoker = None self._up = False self._invoker_hids = [] - self.__focus = 0 + self._focus = 0 self._popup_anim = Animator(.5, 10) self._popup_anim.add(_PopupAnimation(self)) @@ -297,27 +298,27 @@ class _Palette(gtk.Window): self.popup(immediate=False) - def __handle_focus(self, delta): - self.__focus += delta - if self.__focus not in (0, 1): - logging.error('_Palette.__focus=%s not in (0, 1)' % self.__focus) + def _handle_focus(self, delta): + self._focus += delta + if self._focus not in (0, 1): + logging.error('_Palette._focus=%s not in (0, 1)' % self._focus) - if self.__focus == 0: + if self._focus == 0: group = palettegroup.get_group('default') if not group.is_up(): self.popdown() def __group_popdown_cb(self, group): - if self.__focus == 0: + if self._focus == 0: self.popdown(immediate=True) def __invoker_mouse_enter_cb(self, invoker): self._mouse_detector.start() - self.__handle_focus(+1) + self._handle_focus(+1) def __invoker_mouse_leave_cb(self, invoker): self._mouse_detector.stop() - self.__handle_focus(-1) + self._handle_focus(-1) def __invoker_right_click_cb(self, invoker): self.popup(immediate=True) @@ -326,12 +327,12 @@ class _Palette(gtk.Window): if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ event.mode == gtk.gdk.CROSSING_NORMAL: self._popdown_anim.stop() - self.__handle_focus(+1) + self._handle_focus(+1) def __leave_notify_event_cb(self, widget, event): if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ event.mode == gtk.gdk.CROSSING_NORMAL: - self.__handle_focus(-1) + self._handle_focus(-1) def __show_cb(self, widget): self._invoker.notify_popup() From 3ee78747d4b3d2daf564a808189e88e4df70918f Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 10:55:58 +0000 Subject: [PATCH 41/51] Fix review issues --- src/sugar/graphics/toolbarbox.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index 2e1d93be..e8c1b359 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -70,7 +70,8 @@ class ToolbarButton(ToolButton): box = self.toolbar_box - if not box or not self.page_widget or self.is_expanded() == expanded: + if box is None or self.page_widget is None or \ + self.is_expanded() == expanded: return if not expanded: @@ -80,11 +81,11 @@ class ToolbarButton(ToolButton): if box.expanded_button is not None: expanded_toolitem = box.expanded_button.page_widget.toolbar_button - if expanded_toolitem.window: + if expanded_toolitem.window is not None: expanded_toolitem.window.invalidate_rect(None, True) box.expanded_button.set_expanded(False) - if self.page_widget.parent: + if self.page_widget.parent is not None: self.palette.remove(self.page_widget) self.modify_bg(gtk.STATE_NORMAL, box.background) @@ -93,7 +94,8 @@ class ToolbarButton(ToolButton): box.expanded_button = self def do_expose_event(self, event): - if not self.is_expanded() or self.palette and self.palette.is_up(): + if not self.is_expanded() or self.palette is not None and \ + self.palette.is_up(): ToolButton.do_expose_event(self, event) _paint_arrow(self, event, gtk.ARROW_DOWN) return @@ -247,7 +249,7 @@ class _Palette(gtk.Window): def do_size_request(self, requisition): gtk.Window.do_size_request(self, requisition) - if self._toolitem.toolbar_box: + if self._toolitem.toolbar_box is not None: requisition.width = self._toolitem.toolbar_box.allocation.width def __realize_cb(self, widget): From e0aedcd5c7657b18bdf864e302a820731126045d Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sat, 1 Aug 2009 11:23:06 +0000 Subject: [PATCH 42/51] Refactor Palette class (tomeu) --- src/sugar/graphics/palette.py | 572 +++++++++++++++++-------------- src/sugar/graphics/toolbarbox.py | 251 +++----------- 2 files changed, 357 insertions(+), 466 deletions(-) diff --git a/src/sugar/graphics/palette.py b/src/sugar/graphics/palette.py index 88145d24..a29a9412 100644 --- a/src/sugar/graphics/palette.py +++ b/src/sugar/graphics/palette.py @@ -127,11 +127,8 @@ class MouseSpeedDetector(gobject.GObject): return True -class Palette(gtk.Window): - PRIMARY = 0 - SECONDARY = 1 - - __gtype_name__ = 'SugarPalette' +class PaletteWindow(gtk.Window): + __gtype_name__ = 'SugarPaletteWindow' __gsignals__ = { 'popup' : (gobject.SIGNAL_RUN_FIRST, @@ -142,6 +139,261 @@ class Palette(gtk.Window): gobject.TYPE_NONE, ([])) } + def __init__(self, **kwargs): + self._group_id = None + self._invoker = None + self._invoker_hids = [] + self._cursor_x = 0 + self._cursor_y = 0 + self._alignment = None + self._up = False + self._old_alloc = None + + self._popup_anim = animator.Animator(.5, 10) + self._popup_anim.add(_PopupAnimation(self)) + + self._secondary_anim = animator.Animator(2.0, 10) + self._secondary_anim.add(_SecondaryAnimation(self)) + + self._popdown_anim = animator.Animator(0.6, 10) + self._popdown_anim.add(_PopdownAnimation(self)) + + gobject.GObject.__init__(self, **kwargs) + + self.set_decorated(False) + self.set_resizable(False) + # Just assume xthickness and ythickness are the same + self.set_border_width(self.get_style().xthickness) + + accel_group = gtk.AccelGroup() + self.set_data('sugar-accel-group', accel_group) + self.add_accel_group(accel_group) + + self.set_group_id("default") + + self.connect('show', self.__show_cb) + self.connect('hide', self.__hide_cb) + self.connect('realize', self.__realize_cb) + self.connect('destroy', self.__destroy_cb) + self.connect('enter-notify-event', self.__enter_notify_event_cb) + self.connect('leave-notify-event', self.__leave_notify_event_cb) + + self._mouse_detector = MouseSpeedDetector(self, 200, 5) + self._mouse_detector.connect('motion-slow', self._mouse_slow_cb) + + def __destroy_cb(self, palette): + self.set_group_id(None) + + def set_invoker(self, invoker): + for hid in self._invoker_hids[:]: + self._invoker.disconnect(hid) + self._invoker_hids.remove(hid) + + self._invoker = invoker + if invoker is not None: + self._invoker_hids.append(self._invoker.connect( + 'mouse-enter', self._invoker_mouse_enter_cb)) + self._invoker_hids.append(self._invoker.connect( + 'mouse-leave', self._invoker_mouse_leave_cb)) + self._invoker_hids.append(self._invoker.connect( + 'right-click', self._invoker_right_click_cb)) + + logging.debug(' Invoker set to %r' % self._invoker) + + def get_invoker(self): + return self._invoker + + invoker = gobject.property(type=object, + getter=get_invoker, + setter=set_invoker) + + def __realize_cb(self, widget): + self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) + + def _mouse_slow_cb(self, widget): + self._mouse_detector.stop() + self._palette_do_popup() + + def _palette_do_popup(self): + immediate = False + + if self.is_up(): + self._popdown_anim.stop() + return + + if self._group_id: + group = palettegroup.get_group(self._group_id) + if group and group.is_up(): + immediate = True + group.popdown() + + self.popup(immediate=immediate) + + def is_up(self): + return self._up + + def set_group_id(self, group_id): + if self._group_id: + group = palettegroup.get_group(self._group_id) + group.remove(self) + if group_id: + self._group_id = group_id + group = palettegroup.get_group(group_id) + group.add(self) + + def get_group_id(self): + return self._group_id + + group_id = gobject.property(type=str, + getter=get_group_id, + setter=set_group_id) + + def do_size_request(self, requisition): + gtk.Window.do_size_request(self, requisition) + requisition.width = max(requisition.width, style.GRID_CELL_SIZE * 2) + + def do_size_allocate(self, allocation): + gtk.Window.do_size_allocate(self, allocation) + + if self._old_alloc is None or \ + self._old_alloc.x != allocation.x or \ + self._old_alloc.y != allocation.y or \ + self._old_alloc.width != allocation.width or \ + self._old_alloc.height != allocation.height: + self.queue_draw() + + # We need to store old allocation because when size_allocate + # is called widget.allocation is already updated. + # gtk.Window resizing is different from normal containers: + # the X window is resized, widget.allocation is updated from + # the configure request handler and finally size_allocate is called. + self._old_alloc = allocation + + def do_expose_event(self, event): + # We want to draw a border with a beautiful gap + if self._invoker is not None and self._invoker.has_rectangle_gap(): + invoker = self._invoker.get_rect() + palette = self.get_rect() + + gap = _calculate_gap(palette, invoker) + else: + gap = False + + allocation = self.get_allocation() + wstyle = self.get_style() + + if gap: + wstyle.paint_box_gap(event.window, gtk.STATE_PRELIGHT, + gtk.SHADOW_IN, event.area, self, "palette", + 0, 0, allocation.width, allocation.height, + gap[0], gap[1], gap[2]) + else: + wstyle.paint_box(event.window, gtk.STATE_PRELIGHT, + gtk.SHADOW_IN, event.area, self, "palette", + 0, 0, allocation.width, allocation.height) + + # Fall trough to the container expose handler. + # (Leaving out the window expose handler which redraws everything) + gtk.Bin.do_expose_event(self, event) + + def update_position(self): + logging.debug(' update_position 1 %r %r' % (self._invoker, self._alignment)) + invoker = self._invoker + if invoker is None or self._alignment is None: + logging.error('Cannot update the palette position.') + return + + rect = self.size_request() + position = invoker.get_position_for_alignment(self._alignment, rect) + if position is None: + position = invoker.get_position(rect) + + logging.debug(' update_position %r %r' % (position.x, position.y)) + self.move(position.x, position.y) + + def get_full_size_request(self): + return self.size_request() + + def popup(self, immediate=False): + if self._invoker is not None: + full_size_request = self.get_full_size_request() + self._alignment = self._invoker.get_alignment(full_size_request) + + self.update_position() + self.set_transient_for(self._invoker.get_toplevel()) + + self._popdown_anim.stop() + + if not immediate: + self._popup_anim.start() + else: + self.show() + + def popdown(self, immediate=False): + logging.debug('Palette.popdown immediate %r' % immediate) + self._popup_anim.stop() + + self._mouse_detector.stop() + + if not immediate: + self._popdown_anim.start() + else: + self.hide() + + def _invoker_mouse_enter_cb(self, invoker): + self._mouse_detector.start() + + def _invoker_mouse_leave_cb(self, invoker): + self._mouse_detector.stop() + self.popdown() + + def _invoker_right_click_cb(self, invoker): + self.popup(immediate=True) + + def __enter_notify_event_cb(self, widget, event): + if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ + event.mode == gtk.gdk.CROSSING_NORMAL: + self._popdown_anim.stop() + self._secondary_anim.start() + + def __leave_notify_event_cb(self, widget, event): + if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ + event.mode == gtk.gdk.CROSSING_NORMAL: + self.popdown() + + def __show_cb(self, widget): + self._invoker.notify_popup() + + self._up = True + self.emit('popup') + + def __hide_cb(self, widget): + logging.debug('__hide_cb') + self._secondary_anim.stop() + + if self._invoker: + self._invoker.notify_popdown() + + self._up = False + self.emit('popdown') + + def get_rect(self): + win_x, win_y = self.window.get_origin() + rectangle = self.get_allocation() + + x = win_x + rectangle.x + y = win_y + rectangle.y + width = rectangle.width + height = rectangle.height + + return gtk.gdk.Rectangle(x, y, width, height) + +class Palette(PaletteWindow): + PRIMARY = 0 + SECONDARY = 1 + + __gtype_name__ = 'SugarPalette' + # DEPRECATED: label is passed with the primary-text property, accel_path # is set via the invoker property, and menu_after_content is not used def __init__(self, label=None, accel_path=None, menu_after_content=False, @@ -153,7 +405,6 @@ class Palette(gtk.Window): self._secondary_text = None self._icon = None self._icon_visible = True - self._group_id = None palette_box = gtk.VBox() @@ -200,49 +451,18 @@ class Palette(gtk.Window): self._menu_content_separator = gtk.HSeparator() - self._popup_anim = animator.Animator(.5, 10) - self._popup_anim.add(_PopupAnimation(self)) - self._secondary_anim = animator.Animator(2.0, 10) self._secondary_anim.add(_SecondaryAnimation(self)) - self._popdown_anim = animator.Animator(0.6, 10) - self._popdown_anim.add(_PopdownAnimation(self)) - # we init after initializing all of our containers - gobject.GObject.__init__(self, **kwargs) - - self.set_decorated(False) - self.set_resizable(False) - # Just assume xthickness and ythickness are the same - self.set_border_width(self.get_style().xthickness) - - accel_group = gtk.AccelGroup() - self.set_data('sugar-accel-group', accel_group) - self.add_accel_group(accel_group) + PaletteWindow.__init__(self, **kwargs) primary_box.set_size_request(-1, style.GRID_CELL_SIZE - 2 * self.get_border_width()) - - self.connect('show', self.__show_cb) - self.connect('hide', self.__hide_cb) - self.connect('realize', self.__realize_cb) - self.connect('destroy', self.__destroy_cb) - - self._alignment = None - self._old_alloc = None self._full_request = [0, 0] - self._cursor_x = 0 - self._cursor_y = 0 - self._invoker = None - self._group_id = None - self._up = False self._menu_box = None self._content = None - self._invoker_hids = [] - - self.set_group_id("default") # we set these for backward compatibility if label is not None: @@ -263,21 +483,63 @@ class Palette(gtk.Window): self.menu = _Menu(self) self.menu.connect('item-inserted', self.__menu_item_inserted_cb) - self.connect('enter-notify-event', self.__enter_notify_event_cb) - self.connect('leave-notify-event', self.__leave_notify_event_cb) + self.connect('realize', self.__realize_cb) + self.connect('show', self.__show_cb) + self.connect('hide', self.__hide_cb) + self.connect('notify::invoker', self.__notify_invoker_cb) + self.connect('destroy', self.__destroy_cb) - self._mouse_detector = MouseSpeedDetector(self, 200, 5) - self._mouse_detector.connect('motion-slow', self._mouse_slow_cb) + def _invoker_right_click_cb(self, invoker): + self.popup(immediate=True, state=self.SECONDARY) + + def do_style_set(self, previous_style): + # Prevent a warning from pygtk + if previous_style is not None: + gtk.Window.do_style_set(self, previous_style) + self.set_border_width(self.get_style().xthickness) def __menu_item_inserted_cb(self, menu): self._update_separators() def __destroy_cb(self, palette): - self.set_group_id(None) - # Break the reference cycle. It looks like the gc is not able to free # it, possibly because gtk.Menu memory handling is very special. self.menu = None + + def __show_cb(self, widget): + self.menu.set_active(True) + + def __hide_cb(self, widget): + logging.debug('__hide_cb') + self.menu.set_active(False) + + def __notify_invoker_cb(self, palette, pspec): + invoker = self.props.invoker + if invoker is not None and hasattr(invoker.props, 'widget'): + logging.debug(('Setup widget', invoker.props.widget)) + self._update_accel_widget() + self._invoker.connect('notify::widget', + self.__invoker_widget_changed_cb) + + def __invoker_widget_changed_cb(self, invoker, spec): + self._update_accel_widget() + + def get_full_size_request(self): + return self._full_request + + def popup(self, immediate=False, state=None): + logging.debug('Palette.popup immediate %r' % immediate) + + if self._invoker is not None: + self._update_full_request() + + PaletteWindow.popup(self, immediate) + + if state is None: + state = self.PRIMARY + self.set_state(state) + + self._secondary_anim.start() def _add_menu(self): self._menu_box = gtk.VBox() @@ -290,52 +552,6 @@ class Palette(gtk.Window): self._content.set_border_width(style.DEFAULT_SPACING) self._secondary_box.pack_start(self._content) - def do_style_set(self, previous_style): - # Prevent a warning from pygtk - if previous_style is not None: - gtk.Window.do_style_set(self, previous_style) - self.set_border_width(self.get_style().xthickness) - - def is_up(self): - return self._up - - def get_rect(self): - win_x, win_y = self.window.get_origin() - rectangle = self.get_allocation() - - x = win_x + rectangle.x - y = win_y + rectangle.y - width = rectangle.width - height = rectangle.height - - return gtk.gdk.Rectangle(x, y, width, height) - - def set_invoker(self, invoker): - for hid in self._invoker_hids[:]: - self._invoker.disconnect(hid) - self._invoker_hids.remove(hid) - - self._invoker = invoker - if invoker is not None: - self._invoker_hids.append(self._invoker.connect( - 'mouse-enter', self._invoker_mouse_enter_cb)) - self._invoker_hids.append(self._invoker.connect( - 'mouse-leave', self._invoker_mouse_leave_cb)) - self._invoker_hids.append(self._invoker.connect( - 'right-click', self._invoker_right_click_cb)) - if hasattr(invoker.props, 'widget'): - self._update_accel_widget() - logging.debug(('Setup widget', invoker.props.widget)) - self._invoker_hids.append(self._invoker.connect( - 'notify::widget', self._invoker_widget_changed_cb)) - - def get_invoker(self): - return self._invoker - - invoker = gobject.property(type=object, - getter=get_invoker, - setter=set_invoker) - def _update_accel_widget(self): assert self.props.invoker is not None self._label.props.accel_widget = self.props.invoker.props.widget @@ -438,24 +654,8 @@ class Palette(gtk.Window): self._update_accept_focus() self._update_separators() - def set_group_id(self, group_id): - if self._group_id: - group = palettegroup.get_group(self._group_id) - group.remove(self) - if group_id: - self._group_id = group_id - group = palettegroup.get_group(group_id) - group.add(self) - - def get_group_id(self): - return self._group_id - - group_id = gobject.property(type=str, - getter=get_group_id, - setter=set_group_id) - def do_size_request(self, requisition): - gtk.Window.do_size_request(self, requisition) + PaletteWindow.do_size_request(self, requisition) # gtk.AccelLabel request doesn't include the accelerator. label_width = self._label_alignment.size_request()[0] + \ @@ -463,54 +663,9 @@ class Palette(gtk.Window): 2 * self.get_border_width() requisition.width = max(requisition.width, - style.GRID_CELL_SIZE * 2, label_width, self._full_request[0]) - def do_size_allocate(self, allocation): - gtk.Window.do_size_allocate(self, allocation) - - if self._old_alloc is None or \ - self._old_alloc.x != allocation.x or \ - self._old_alloc.y != allocation.y or \ - self._old_alloc.width != allocation.width or \ - self._old_alloc.height != allocation.height: - self.queue_draw() - - # We need to store old allocation because when size_allocate - # is called widget.allocation is already updated. - # gtk.Window resizing is different from normal containers: - # the X window is resized, widget.allocation is updated from - # the configure request handler and finally size_allocate is called. - self._old_alloc = allocation - - def do_expose_event(self, event): - # We want to draw a border with a beautiful gap - if self._invoker is not None and self._invoker.has_rectangle_gap(): - invoker = self._invoker.get_rect() - palette = self.get_rect() - - gap = _calculate_gap(palette, invoker) - else: - gap = False - - allocation = self.get_allocation() - wstyle = self.get_style() - - if gap: - wstyle.paint_box_gap(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_IN, event.area, self, "palette", - 0, 0, allocation.width, allocation.height, - gap[0], gap[1], gap[2]) - else: - wstyle.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_IN, event.area, self, "palette", - 0, 0, allocation.width, allocation.height) - - # Fall trough to the container expose handler. - # (Leaving out the window expose handler which redraws everything) - gtk.Bin.do_expose_event(self, event) - def _update_separators(self): visible = len(self.menu.get_children()) > 0 or \ len(self._content.get_children()) > 0 @@ -526,7 +681,6 @@ class Palette(gtk.Window): self.window.set_accept_focus(accept_focus) def __realize_cb(self, widget): - self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) self._update_accept_focus() def _update_full_request(self): @@ -540,52 +694,6 @@ class Palette(gtk.Window): self.menu.unembed() self._secondary_box.hide() - def _update_position(self): - invoker = self._invoker - if invoker is None or self._alignment is None: - logging.error('Cannot update the palette position.') - return - - rect = self.size_request() - position = invoker.get_position_for_alignment(self._alignment, rect) - if position is None: - position = invoker.get_position(rect) - - self.move(position.x, position.y) - - def popup(self, immediate=False, state=None): - logging.debug('Palette.popup immediate %r' % immediate) - - if state is None: - state = self.PRIMARY - self.set_state(state) - - if self._invoker is not None: - self._update_full_request() - self._alignment = self._invoker.get_alignment(self._full_request) - self._update_position() - self.set_transient_for(self._invoker.get_toplevel()) - - self._popdown_anim.stop() - - if not immediate: - self._popup_anim.start() - else: - self.show() - - self._secondary_anim.start() - - def popdown(self, immediate=False): - logging.debug('Palette.popdown immediate %r' % immediate) - self._popup_anim.stop() - - self._mouse_detector.stop() - - if not immediate: - self._popdown_anim.start() - else: - self.hide() - def set_state(self, state): if self.palette_state == state: return @@ -596,74 +704,10 @@ class Palette(gtk.Window): elif state == self.SECONDARY: self.menu.embed(self._menu_box) self._secondary_box.show() - self._update_position() + self.update_position() self.palette_state = state - def _mouse_slow_cb(self, widget): - self._mouse_detector.stop() - self._palette_do_popup() - - def _palette_do_popup(self): - immediate = False - - if self.is_up(): - self._popdown_anim.stop() - return - - if self._group_id: - group = palettegroup.get_group(self._group_id) - if group and group.is_up(): - immediate = True - group.popdown() - - self.popup(immediate=immediate) - - def _invoker_widget_changed_cb(self, invoker, spec): - self._update_accel_widget() - - def _invoker_mouse_enter_cb(self, invoker): - self._mouse_detector.start() - - def _invoker_mouse_leave_cb(self, invoker): - self._mouse_detector.stop() - self.popdown() - - def _invoker_right_click_cb(self, invoker): - self.popup(immediate=True, state=self.SECONDARY) - - def __enter_notify_event_cb(self, widget, event): - if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ - event.mode == gtk.gdk.CROSSING_NORMAL: - self._popdown_anim.stop() - self._secondary_anim.start() - - def __leave_notify_event_cb(self, widget, event): - if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ - event.mode == gtk.gdk.CROSSING_NORMAL: - self.popdown() - - def __show_cb(self, widget): - self.menu.set_active(True) - - self._invoker.notify_popup() - - self._up = True - self.emit('popup') - - def __hide_cb(self, widget): - logging.debug('__hide_cb') - self.menu.set_active(False) - - self._secondary_anim.stop() - - if self._invoker: - self._invoker.notify_popdown() - - self._up = False - self.emit('popdown') - - class PaletteActionBar(gtk.HButtonBox): def add_action(self, label, icon_name=None): button = gtk.Button(label) diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index e8c1b359..f2f3ef8a 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -15,25 +15,21 @@ # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. -import gtk -import gobject import logging + +import gobject from gobject import SIGNAL_RUN_FIRST, TYPE_NONE +import gtk from sugar.graphics import style +from sugar.graphics.palette import PaletteWindow, ToolInvoker from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.palette import MouseSpeedDetector, Invoker -from sugar.graphics.animator import Animator, Animation -from sugar.graphics import palettegroup class ToolbarButton(ToolButton): - def __init__(self, **kwargs): - self.page_widget = None - + def __init__(self, page=None, **kwargs): ToolButton.__init__(self, **kwargs) - if self.palette is None: - self.palette = _Palette(self) + self.set_page(page) self.connect('clicked', lambda widget: self.set_expanded(not self.is_expanded())) @@ -51,19 +47,36 @@ class ToolbarButton(ToolButton): return self.page_widget.child.child def set_page(self, page): + if page is None: + self.page_widget = None + return self.page_widget = _embody_page(_Box, page) self.page_widget.toolbar_button = self page.show() + if self.props.palette is None: + self.props.palette = _ToolbarPalette(invoker=ToolInvoker(self)) + self.props.palette.toolbar_button = self + self._move_page_to_palette() page = gobject.property(type=object, getter=get_page, setter=set_page) + def _move_page_to_palette(self): + if self.page_widget is None: + return + + if self.toolbar_box is not None and \ + self.page_widget in self.toolbar_box.get_children(): + self.toolbar_box.remove(self.page_widget) + + if self.props.palette is not None: + self.props.palette.add(self.page_widget) + def is_expanded(self): return self.toolbar_box is not None and self.page_widget is not None \ and self.toolbar_box.expanded_button == self def popdown(self): - if isinstance(self.palette, _Palette) and self.palette.is_up(): - self.palette.popdown(immediate=True) + self.props.palette.popdown(immediate=True) def set_expanded(self, expanded): self.popdown() @@ -77,6 +90,7 @@ class ToolbarButton(ToolButton): if not expanded: box.remove(self.page_widget) box.expanded_button = None + self._move_page_to_palette() return if box.expanded_button is not None: @@ -86,7 +100,7 @@ class ToolbarButton(ToolButton): box.expanded_button.set_expanded(False) if self.page_widget.parent is not None: - self.palette.remove(self.page_widget) + self.props.palette.remove(self.page_widget) self.modify_bg(gtk.STATE_NORMAL, box.background) _setup_page(self.page_widget, box.background, box.props.padding) @@ -94,8 +108,8 @@ class ToolbarButton(ToolButton): box.expanded_button = self def do_expose_event(self, event): - if not self.is_expanded() or self.palette is not None and \ - self.palette.is_up(): + if not self.is_expanded() or self.props.palette is not None and \ + self.props.palette.is_up(): ToolButton.do_expose_event(self, event) _paint_arrow(self, event, gtk.ARROW_DOWN) return @@ -157,6 +171,26 @@ class ToolbarBox(gtk.VBox): self.toolbar.parent.parent.modify_bg(state, color) self.toolbar.modify_bg(state, color) +class _ToolbarPalette(PaletteWindow): + def __init__(self, **kwargs): + PaletteWindow.__init__(self, **kwargs) + self.toolbar_box = None + self.set_border_width(0) + + def do_size_request(self, requisition): + gtk.Window.do_size_request(self, requisition) + requisition.width = max(requisition.width, + gtk.gdk.screen_width()) + + def popup(self, immediate=False): + button = self.toolbar_button + if button.is_expanded(): + return + box = button.toolbar_box + _setup_page(button.page_widget, style.COLOR_BLACK.get_gdk_color(), + box.props.padding) + PaletteWindow.popup(self, immediate) + class _Box(gtk.EventBox): def __init__(self): gtk.EventBox.__init__(self) @@ -176,193 +210,6 @@ class _Box(gtk.EventBox): alloc.width - style._FOCUS_LINE_WIDTH*2, style._FOCUS_LINE_WIDTH) -class _Palette(gtk.Window): - def __init__(self, toolitem, **kwargs): - gobject.GObject.__init__(self, **kwargs) - - self.set_decorated(False) - self.set_resizable(False) - self.set_border_width(0) - - self._toolitem = toolitem - self._invoker = None - self._up = False - self._invoker_hids = [] - self._focus = 0 - - self._popup_anim = Animator(.5, 10) - self._popup_anim.add(_PopupAnimation(self)) - - self._popdown_anim = Animator(0.6, 10) - self._popdown_anim.add(_PopdownAnimation(self)) - - accel_group = gtk.AccelGroup() - self.set_data('sugar-accel-group', accel_group) - self.add_accel_group(accel_group) - - self.connect('show', self.__show_cb) - self.connect('hide', self.__hide_cb) - self.connect('realize', self.__realize_cb) - self.connect('enter-notify-event', self.__enter_notify_event_cb) - self.connect('leave-notify-event', self.__leave_notify_event_cb) - - self._mouse_detector = MouseSpeedDetector(self, 200, 5) - self._mouse_detector.connect('motion-slow', self._mouse_slow_cb) - - group = palettegroup.get_group('default') - group.connect('popdown', self.__group_popdown_cb) - - def is_up(self): - return self._up - - def get_rect(self): - win_x, win_y = self.window.get_origin() - rectangle = self.get_allocation() - - x = win_x + rectangle.x - y = win_y + rectangle.y - width = rectangle.width - height = rectangle.height - - return gtk.gdk.Rectangle(x, y, width, height) - - def set_invoker(self, invoker): - for hid in self._invoker_hids[:]: - self._invoker.disconnect(hid) - self._invoker_hids.remove(hid) - - self._invoker = invoker - if invoker is not None: - self._invoker_hids.append(self._invoker.connect( - 'mouse-enter', self.__invoker_mouse_enter_cb)) - self._invoker_hids.append(self._invoker.connect( - 'mouse-leave', self.__invoker_mouse_leave_cb)) - self._invoker_hids.append(self._invoker.connect( - 'right-click', self.__invoker_right_click_cb)) - - def get_invoker(self): - return self._invoker - - invoker = gobject.property(type=object, - getter=get_invoker, - setter=set_invoker) - - def do_size_request(self, requisition): - gtk.Window.do_size_request(self, requisition) - if self._toolitem.toolbar_box is not None: - requisition.width = self._toolitem.toolbar_box.allocation.width - - def __realize_cb(self, widget): - self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - #accept_focus = len(self._content.get_children()) - #if self.window: - # self.window.set_accept_focus(accept_focus) - - def popup(self, immediate=False): - self._popdown_anim.stop() - - toolbar = self._toolitem.toolbar_box - page = self._toolitem.page_widget - - if not self._invoker or self._toolitem.is_expanded() or not toolbar: - return - - _setup_page(page, style.COLOR_BLACK.get_gdk_color(), - toolbar.props.padding) - if self.child is None: - self.add(page) - - x, y = toolbar.window.get_origin() - self.move(x + toolbar.allocation.x, - y + toolbar.toolbar.allocation.height) - self.set_transient_for(self._invoker.get_toplevel()) - - if not immediate: - self._popup_anim.start() - else: - self.show() - - def popdown(self, immediate=False): - self._popup_anim.stop() - self._mouse_detector.stop() - - if not immediate: - self._popdown_anim.start() - else: - self.hide() - - def _mouse_slow_cb(self, widget): - self._mouse_detector.stop() - - if self.is_up(): - self._popdown_anim.stop() - return - - self.popup(immediate=False) - - def _handle_focus(self, delta): - self._focus += delta - if self._focus not in (0, 1): - logging.error('_Palette._focus=%s not in (0, 1)' % self._focus) - - if self._focus == 0: - group = palettegroup.get_group('default') - if not group.is_up(): - self.popdown() - - def __group_popdown_cb(self, group): - if self._focus == 0: - self.popdown(immediate=True) - - def __invoker_mouse_enter_cb(self, invoker): - self._mouse_detector.start() - self._handle_focus(+1) - - def __invoker_mouse_leave_cb(self, invoker): - self._mouse_detector.stop() - self._handle_focus(-1) - - def __invoker_right_click_cb(self, invoker): - self.popup(immediate=True) - - def __enter_notify_event_cb(self, widget, event): - if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ - event.mode == gtk.gdk.CROSSING_NORMAL: - self._popdown_anim.stop() - self._handle_focus(+1) - - def __leave_notify_event_cb(self, widget, event): - if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ - event.mode == gtk.gdk.CROSSING_NORMAL: - self._handle_focus(-1) - - def __show_cb(self, widget): - self._invoker.notify_popup() - self._up = True - - def __hide_cb(self, widget): - if self._invoker: - self._invoker.notify_popdown() - self._up = False - -class _PopupAnimation(Animation): - def __init__(self, palette): - Animation.__init__(self, 0.0, 1.0) - self._palette = palette - - def next_frame(self, current): - if current == 1.0: - self._palette.show() - -class _PopdownAnimation(Animation): - def __init__(self, palette): - Animation.__init__(self, 0.0, 1.0) - self._palette = palette - - def next_frame(self, current): - if current == 1.0: - self._palette.hide() - def _setup_page(page, color, hpad): vpad = style._FOCUS_LINE_WIDTH page.child.set_padding(vpad, vpad, hpad, hpad) From 2c7e2c393a1d0732f74dae9b95714586378d4286 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 19:56:43 +0000 Subject: [PATCH 43/51] Popdown RadioMenuButton's palette --- src/sugar/graphics/radiopalette.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index e7d318dc..803e556b 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -33,18 +33,14 @@ class RadioMenuButton(ToolButton): self.__palette_cb(None, None) self.connect('notify::palette', self.__palette_cb) - self.connect('clicked', self.__clicked_cb) - - def __clicked_cb(self, button): - self.on_click() def __palette_cb(self, widget, pspec): if not isinstance(self.props.palette, RadioPalette): return self.props.palette.update_button() - def on_click(self): - if not self.palette: + def do_clicked(self): + if self.palette is None: return if self.palette.is_up() and \ self.palette.palette_state == Palette.SECONDARY: @@ -74,7 +70,7 @@ class RadioToolsButton(RadioMenuButton): def __init__(self, **kwargs): RadioMenuButton.__init__(self, **kwargs) - def on_click(self): + def do_clicked(self): if not self.selected_button: return self.selected_button.emit('clicked') From 45a4ed104b40b47b5b04ddfa3bd9e36a72e0c960 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 19:57:13 +0000 Subject: [PATCH 44/51] Do not paint arrow in radiopalette --- src/sugar/graphics/radiopalette.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index 803e556b..87048f56 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -48,24 +48,6 @@ class RadioMenuButton(ToolButton): else: self.palette.popup(immediate=True, state=Palette.SECONDARY) - def do_expose_event(self, event): - ToolButton.do_expose_event(self, event) - if not self.palette: - return - - if self.palette.is_up(): - type = gtk.ARROW_UP - else: - type = gtk.ARROW_DOWN - - alloc = self.allocation - x = alloc.x + alloc.width / 2 - style.TOOLBAR_ARROW_SIZE / 2 - y = alloc.y + alloc.height - int(style.TOOLBAR_ARROW_SIZE * .85) - self.get_style().paint_arrow(event.window, - gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, - None, type, True, - x, y, style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) - class RadioToolsButton(RadioMenuButton): def __init__(self, **kwargs): RadioMenuButton.__init__(self, **kwargs) From 6e724c3d8d0ff7ce42b50a6459e523a0fbe39fa4 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 20:05:40 +0000 Subject: [PATCH 45/51] Set background color for activity.widgets.TitleEntry --- src/sugar/activity/widgets.py | 39 ++++++++++++++++---------------- src/sugar/graphics/toolbarbox.py | 14 ++++++++---- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/sugar/activity/widgets.py b/src/sugar/activity/widgets.py index 8485605b..123e6ecf 100644 --- a/src/sugar/activity/widgets.py +++ b/src/sugar/activity/widgets.py @@ -134,19 +134,28 @@ class KeepButton(ToolButton): def __keep_button_clicked_cb(self, button, activity): activity.copy() -class TitleEntry(gtk.Entry): +class TitleEntry(gtk.ToolItem): def __init__(self, activity, **kwargs): - gtk.Entry.__init__(self, **kwargs) + gtk.ToolItem.__init__(self) + self.set_expand(False) self._update_title_sid = None - self.set_size_request(int(gtk.gdk.screen_width() / 3), -1) - self.set_text(activity.metadata['title']) - self.connect('changed', self.__title_changed_cb, activity) + self.entry = gtk.Entry(**kwargs) + self.entry.set_size_request(int(gtk.gdk.screen_width() / 3), -1) + self.entry.set_text(activity.metadata['title']) + self.entry.connect('changed', self.__title_changed_cb, activity) + self.entry.show() + self.add(self.entry) activity.metadata.connect('updated', self.__jobject_updated_cb) + def modify_bg(self, state, color): + gtk.ToolItem.modify_bg(self, state, color) + if state == gtk.STATE_NORMAL: + self.entry.modify_bg(gtk.STATE_INSENSITIVE, color) + def __jobject_updated_cb(self, jobject): - self.set_text(jobject['title']) + self.entry.set_text(jobject['title']) def __title_changed_cb(self, entry, activity): if not self._update_title_sid: @@ -154,7 +163,7 @@ class TitleEntry(gtk.Entry): 1, self.__update_title_cb, activity) def __update_title_cb(self, activity): - title = self.get_text() + title = self.entry.get_text() activity.metadata['title'] = title activity.metadata['title_set_by_user'] = '1' @@ -180,8 +189,10 @@ class ActivityToolbar(gtk.Toolbar): self._activity = activity if activity.metadata: - self.title = TitleEntry(activity) - self._add_widget(self.title) + title_button = TitleEntry(activity) + title_button.show() + self.insert(title_button, -1) + self.title = title_button.entry separator = gtk.SeparatorToolItem() separator.props.draw = False @@ -201,16 +212,6 @@ class ActivityToolbar(gtk.Toolbar): self.insert(self.stop, -1) self.stop.show() - def _add_widget(self, widget, expand=False): - tool_item = gtk.ToolItem() - tool_item.set_expand(expand) - - tool_item.add(widget) - widget.show() - - self.insert(tool_item, -1) - tool_item.show() - class EditToolbar(gtk.Toolbar): """Provides the standard edit toolbar for Activities. diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index f2f3ef8a..2344b534 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -210,12 +210,18 @@ class _Box(gtk.EventBox): alloc.width - style._FOCUS_LINE_WIDTH*2, style._FOCUS_LINE_WIDTH) -def _setup_page(page, color, hpad): +def _setup_page(page_widget, color, hpad): vpad = style._FOCUS_LINE_WIDTH - page.child.set_padding(vpad, vpad, hpad, hpad) - page.child.child.modify_bg(gtk.STATE_NORMAL, color) + page_widget.child.set_padding(vpad, vpad, hpad, hpad) + + page = page_widget.child.child page.modify_bg(gtk.STATE_NORMAL, color) - page.modify_bg(gtk.STATE_PRELIGHT, color) + if isinstance(page, gtk.Container): + for i in page.get_children(): + i.modify_bg(gtk.STATE_NORMAL, color) + + page_widget.modify_bg(gtk.STATE_NORMAL, color) + page_widget.modify_bg(gtk.STATE_PRELIGHT, color) def _embody_page(box_class, widget): widget.show() From 35bbfe1d5015bb4f2792d10739ad90ba94fec410 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 20:43:35 +0000 Subject: [PATCH 46/51] Support palettes for sub-toolbar widgets --- src/sugar/graphics/palette.py | 24 +++++++++++++++----- src/sugar/graphics/toolbarbox.py | 38 +++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/sugar/graphics/palette.py b/src/sugar/graphics/palette.py index a29a9412..c681af9d 100644 --- a/src/sugar/graphics/palette.py +++ b/src/sugar/graphics/palette.py @@ -340,26 +340,38 @@ class PaletteWindow(gtk.Window): else: self.hide() - def _invoker_mouse_enter_cb(self, invoker): + def on_invoker_enter(self): self._mouse_detector.start() - def _invoker_mouse_leave_cb(self, invoker): + def on_invoker_leave(self): self._mouse_detector.stop() self.popdown() + def on_enter(self, event): + self._popdown_anim.stop() + self._secondary_anim.start() + + def on_leave(self, event): + self.popdown() + + def _invoker_mouse_enter_cb(self, invoker): + self.on_invoker_enter() + + def _invoker_mouse_leave_cb(self, invoker): + self.on_invoker_leave() + def _invoker_right_click_cb(self, invoker): self.popup(immediate=True) def __enter_notify_event_cb(self, widget, event): if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ event.mode == gtk.gdk.CROSSING_NORMAL: - self._popdown_anim.stop() - self._secondary_anim.start() + self.on_enter(event) def __leave_notify_event_cb(self, widget, event): if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ event.mode == gtk.gdk.CROSSING_NORMAL: - self.popdown() + self.on_leave(event) def __show_cb(self, widget): self._invoker.notify_popup() @@ -385,7 +397,7 @@ class PaletteWindow(gtk.Window): y = win_y + rectangle.y width = rectangle.width height = rectangle.height - + return gtk.gdk.Rectangle(x, y, width, height) class Palette(PaletteWindow): diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index 2344b534..91c5c2d8 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -24,6 +24,7 @@ import gtk from sugar.graphics import style from sugar.graphics.palette import PaletteWindow, ToolInvoker from sugar.graphics.toolbutton import ToolButton +from sugar.graphics import palettegroup class ToolbarButton(ToolButton): def __init__(self, page=None, **kwargs): @@ -68,7 +69,7 @@ class ToolbarButton(ToolButton): self.page_widget in self.toolbar_box.get_children(): self.toolbar_box.remove(self.page_widget) - if self.props.palette is not None: + if isinstance(self.props.palette, _ToolbarPalette): self.props.palette.add(self.page_widget) def is_expanded(self): @@ -176,6 +177,37 @@ class _ToolbarPalette(PaletteWindow): PaletteWindow.__init__(self, **kwargs) self.toolbar_box = None self.set_border_width(0) + self._focus = 0 + + group = palettegroup.get_group('default') + group.connect('popdown', self.__group_popdown_cb) + self.set_group_id('toolbar_box') + + def on_invoker_enter(self): + PaletteWindow.on_invoker_enter(self) + self._handle_focus(+1) + + def on_invoker_leave(self): + PaletteWindow.on_invoker_leave(self) + self._handle_focus(-1) + + def on_enter(self, event): + PaletteWindow.on_enter(self, event) + self._handle_focus(+1) + + def on_leave(self, event): + PaletteWindow.on_enter(self, event) + self._handle_focus(-1) + + def _handle_focus(self, delta): + self._focus += delta + if self._focus not in (0, 1): + logging.error('_Palette._focus=%s not in (0, 1)' % self._focus) + + if self._focus == 0: + group = palettegroup.get_group('default') + if not group.is_up(): + self.popdown() def do_size_request(self, requisition): gtk.Window.do_size_request(self, requisition) @@ -191,6 +223,10 @@ class _ToolbarPalette(PaletteWindow): box.props.padding) PaletteWindow.popup(self, immediate) + def __group_popdown_cb(self, group): + if self._focus == 0: + self.popdown(immediate=True) + class _Box(gtk.EventBox): def __init__(self): gtk.EventBox.__init__(self) From 68fa6bf0931039e4d3db893c0614ca9fda1be3fd Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 31 Jul 2009 22:04:28 +0000 Subject: [PATCH 47/51] Fix mess with gtk.Widget.set_state and Palette.set_state --- src/sugar/graphics/palette.py | 38 ++++++++++++++++++++------------ src/sugar/graphics/toolbarbox.py | 4 ++-- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/sugar/graphics/palette.py b/src/sugar/graphics/palette.py index c681af9d..2a3b6c6b 100644 --- a/src/sugar/graphics/palette.py +++ b/src/sugar/graphics/palette.py @@ -128,6 +128,9 @@ class MouseSpeedDetector(gobject.GObject): return True class PaletteWindow(gtk.Window): + PRIMARY = 0 + SECONDARY = 1 + __gtype_name__ = 'SugarPaletteWindow' __gsignals__ = { @@ -148,6 +151,7 @@ class PaletteWindow(gtk.Window): self._alignment = None self._up = False self._old_alloc = None + self._palette_state = self.PRIMARY self._popup_anim = animator.Animator(.5, 10) self._popup_anim.add(_PopupAnimation(self)) @@ -314,7 +318,7 @@ class PaletteWindow(gtk.Window): def get_full_size_request(self): return self.size_request() - def popup(self, immediate=False): + def popup(self, immediate=False, state=None): if self._invoker is not None: full_size_request = self.get_full_size_request() self._alignment = self._invoker.get_alignment(full_size_request) @@ -361,7 +365,7 @@ class PaletteWindow(gtk.Window): self.on_invoker_leave() def _invoker_right_click_cb(self, invoker): - self.popup(immediate=True) + self.popup(immediate=True, state=self.SECONDARY) def __enter_notify_event_cb(self, widget, event): if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ @@ -400,10 +404,18 @@ class PaletteWindow(gtk.Window): return gtk.gdk.Rectangle(x, y, width, height) -class Palette(PaletteWindow): - PRIMARY = 0 - SECONDARY = 1 + def get_palette_state(self): + return self._palette_state + def _set_palette_state(self, state): + self._palette_state = state + + def set_palette_state(self, state): + self._set_palette_state(state) + + palette_state = property(get_palette_state) + +class Palette(PaletteWindow): __gtype_name__ = 'SugarPalette' # DEPRECATED: label is passed with the primary-text property, accel_path @@ -411,8 +423,6 @@ class Palette(PaletteWindow): def __init__(self, label=None, accel_path=None, menu_after_content=False, text_maxlen=60, **kwargs): - self.palette_state = self.PRIMARY - self._primary_text = None self._secondary_text = None self._icon = None @@ -549,7 +559,7 @@ class Palette(PaletteWindow): if state is None: state = self.PRIMARY - self.set_state(state) + self.set_palette_state(state) self._secondary_anim.start() @@ -696,18 +706,18 @@ class Palette(PaletteWindow): self._update_accept_focus() def _update_full_request(self): - if self.palette_state == self.PRIMARY: + if self._palette_state == self.PRIMARY: self.menu.embed(self._menu_box) self._secondary_box.show() self._full_request = self.size_request() - if self.palette_state == self.PRIMARY: + if self._palette_state == self.PRIMARY: self.menu.unembed() self._secondary_box.hide() - def set_state(self, state): - if self.palette_state == state: + def _set_palette_state(self, state): + if self._palette_state == state: return if state == self.PRIMARY: @@ -718,7 +728,7 @@ class Palette(PaletteWindow): self._secondary_box.show() self.update_position() - self.palette_state = state + self._palette_state = state class PaletteActionBar(gtk.HButtonBox): def add_action(self, label, icon_name=None): @@ -784,7 +794,7 @@ class _SecondaryAnimation(animator.Animation): def next_frame(self, current): if current == 1.0: - self._palette.set_state(Palette.SECONDARY) + self._palette.set_palette_state(Palette.SECONDARY) class _PopdownAnimation(animator.Animation): def __init__(self, palette): diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index 91c5c2d8..fac92b9d 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -214,14 +214,14 @@ class _ToolbarPalette(PaletteWindow): requisition.width = max(requisition.width, gtk.gdk.screen_width()) - def popup(self, immediate=False): + def popup(self, immediate=False, state=None): button = self.toolbar_button if button.is_expanded(): return box = button.toolbar_box _setup_page(button.page_widget, style.COLOR_BLACK.get_gdk_color(), box.props.padding) - PaletteWindow.popup(self, immediate) + PaletteWindow.popup(self, immediate, state) def __group_popdown_cb(self, group): if self._focus == 0: From f5f8c807d3c4fc7cf6113996e77cea920598bfa4 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sat, 1 Aug 2009 11:27:56 +0000 Subject: [PATCH 48/51] Fix pylint/pep8 warnings --- src/sugar/activity/widgets.py | 25 ++++++++++++------------- src/sugar/graphics/radiopalette.py | 3 --- src/sugar/graphics/style.py | 6 +++--- src/sugar/graphics/toolbarbox.py | 22 ++++++++++++---------- 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/sugar/activity/widgets.py b/src/sugar/activity/widgets.py index 123e6ecf..e14c1f3f 100644 --- a/src/sugar/activity/widgets.py +++ b/src/sugar/activity/widgets.py @@ -17,7 +17,6 @@ import gtk import gobject -import logging import gettext import gconf @@ -179,7 +178,7 @@ class TitleEntry(gtk.ToolItem): class ActivityToolbar(gtk.Toolbar): """The Activity toolbar with the Journal entry title, sharing, Keep and Stop buttons - + All activities should have this toolbar. It is easiest to add it to your Activity by using the ActivityToolbox. """ @@ -214,18 +213,18 @@ class ActivityToolbar(gtk.Toolbar): class EditToolbar(gtk.Toolbar): """Provides the standard edit toolbar for Activities. - + Members: undo -- the undo button redo -- the redo button copy -- the copy button paste -- the paste button separator -- A separator between undo/redo and copy/paste - + This class only provides the 'edit' buttons in a standard layout, your activity will need to either hide buttons which make no sense for your Activity, or you need to connect the button events to your own callbacks: - + ## Example from Read.activity: # Create the edit toolbar: self._edit_toolbar = EditToolbar(self._view) @@ -234,12 +233,12 @@ class EditToolbar(gtk.Toolbar): self._edit_toolbar.redo.props.visible = False # Hide the separator too: self._edit_toolbar.separator.props.visible = False - + # As long as nothing is selected, copy needs to be insensitive: self._edit_toolbar.copy.set_sensitive(False) # When the user clicks the button, call _edit_toolbar_copy_cb() self._edit_toolbar.copy.connect('clicked', self._edit_toolbar_copy_cb) - + # Add the edit toolbar: toolbox.add_toolbar(_('Edit'), self._edit_toolbar) # And make it visible: @@ -271,17 +270,17 @@ class EditToolbar(gtk.Toolbar): class ActivityToolbox(Toolbox): """Creates the Toolbox for the Activity - + By default, the toolbox contains only the ActivityToolbar. After creating the toolbox, you can add your activity specific toolbars, for example the EditToolbar. - + To add the ActivityToolbox to your Activity in MyActivity.__init__() do: - - # Create the Toolbar with the ActivityToolbar: + + # Create the Toolbar with the ActivityToolbar: toolbox = activity.ActivityToolbox(self) ... your code, inserting all other toolbars you need, like EditToolbar - + # Add the toolbox to the activity frame: self.set_toolbox(toolbox) # And make it visible: @@ -289,7 +288,7 @@ class ActivityToolbox(Toolbox): """ def __init__(self, activity): Toolbox.__init__(self) - + self._activity_toolbar = ActivityToolbar(activity) self.add_toolbar(_('Activity'), self._activity_toolbar) self._activity_toolbar.show() diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index 87048f56..70ba2e09 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -16,9 +16,6 @@ # Boston, MA 02111-1307, USA. import gtk -import gobject -import logging -from gobject import SIGNAL_RUN_FIRST, TYPE_NONE, TYPE_PYOBJECT from sugar.graphics import style from sugar.graphics.toolbutton import ToolButton diff --git a/src/sugar/graphics/style.py b/src/sugar/graphics/style.py index a37b745c..e63e5caa 100644 --- a/src/sugar/graphics/style.py +++ b/src/sugar/graphics/style.py @@ -28,7 +28,7 @@ import logging import gtk import pango -_FOCUS_LINE_WIDTH = 2 +FOCUS_LINE_WIDTH = 2 _TAB_CURVATURE = 1 def _compute_zoom_factor(): @@ -115,8 +115,8 @@ FONT_BOLD_H = zoom(24) TOOLBOX_SEPARATOR_HEIGHT = zoom(9) TOOLBOX_HORIZONTAL_PADDING = zoom(75) -TOOLBOX_TAB_VBORDER = int((zoom(36) - FONT_NORMAL_H - _FOCUS_LINE_WIDTH) / 2) -TOOLBOX_TAB_HBORDER = zoom(15) - _FOCUS_LINE_WIDTH - _TAB_CURVATURE +TOOLBOX_TAB_VBORDER = int((zoom(36) - FONT_NORMAL_H - FOCUS_LINE_WIDTH) / 2) +TOOLBOX_TAB_HBORDER = zoom(15) - FOCUS_LINE_WIDTH - _TAB_CURVATURE TOOLBOX_TAB_LABEL_WIDTH = zoom(150 - 15 * 2) COLOR_BLACK = Color('#000000') diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index fac92b9d..f9fe73ed 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -15,11 +15,9 @@ # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. -import logging - -import gobject -from gobject import SIGNAL_RUN_FIRST, TYPE_NONE import gtk +import gobject +import logging from sugar.graphics import style from sugar.graphics.palette import PaletteWindow, ToolInvoker @@ -120,13 +118,13 @@ class ToolbarButton(ToolButton): self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, 'palette-invoker', alloc.x, 0, - alloc.width, alloc.height + style._FOCUS_LINE_WIDTH) + alloc.width, alloc.height + style.FOCUS_LINE_WIDTH) if self.child.state != gtk.STATE_PRELIGHT: self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, None, - alloc.x + style._FOCUS_LINE_WIDTH, style._FOCUS_LINE_WIDTH, - alloc.width - style._FOCUS_LINE_WIDTH*2, alloc.height) + alloc.x + style.FOCUS_LINE_WIDTH, style.FOCUS_LINE_WIDTH, + alloc.width - style.FOCUS_LINE_WIDTH*2, alloc.height) gtk.ToolButton.do_expose_event(self, event) _paint_arrow(self, event, gtk.ARROW_UP) @@ -135,6 +133,7 @@ class ToolbarBox(gtk.VBox): def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING): gtk.VBox.__init__(self) self.expanded_button = None + self.background = None self._toolbar = gtk.Toolbar() self._toolbar.owner = self @@ -155,7 +154,10 @@ class ToolbarBox(gtk.VBox): self.remove(button.page_widget) self.expanded_button = None - toolbar = property(lambda self: self._toolbar) + def get_toolbar(self): + return self._toolbar + + toolbar = property(get_toolbar) def get_padding(self): return self.toolbar.parent.props.left_padding @@ -270,12 +272,12 @@ def _embody_page(box_class, widget): box.show() return box -def _paint_arrow(widget, event, type): +def _paint_arrow(widget, event, arrow_type): alloc = widget.allocation x = alloc.x + alloc.width / 2 - style.TOOLBAR_ARROW_SIZE / 2 y = alloc.y + alloc.height - int(style.TOOLBAR_ARROW_SIZE * .85) widget.get_style().paint_arrow(event.window, gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, widget, - None, type, True, + None, arrow_type, True, x, y, style.TOOLBAR_ARROW_SIZE, style.TOOLBAR_ARROW_SIZE) From e799649f2ffbf1da08c9b89a30524c35b21a31e6 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sat, 1 Aug 2009 11:34:45 +0000 Subject: [PATCH 49/51] Fix merger artefacts --- src/sugar/graphics/toolbarbox.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index f9fe73ed..93c24960 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -124,7 +124,7 @@ class ToolbarButton(ToolButton): self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, None, alloc.x + style.FOCUS_LINE_WIDTH, style.FOCUS_LINE_WIDTH, - alloc.width - style.FOCUS_LINE_WIDTH*2, alloc.height) + alloc.width - style.FOCUS_LINE_WIDTH * 2, alloc.height) gtk.ToolButton.do_expose_event(self, event) _paint_arrow(self, event, gtk.ARROW_UP) @@ -239,17 +239,17 @@ class _Box(gtk.EventBox): alloc = self.toolbar_button.allocation self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_IN, event.area, self, - 'palette-invoker', -style._FOCUS_LINE_WIDTH, 0, - self.allocation.width + style._FOCUS_LINE_WIDTH*2, - self.allocation.height + style._FOCUS_LINE_WIDTH) + 'palette-invoker', -style.FOCUS_LINE_WIDTH, 0, + self.allocation.width + style.FOCUS_LINE_WIDTH * 2, + self.allocation.height + style.FOCUS_LINE_WIDTH) self.get_style().paint_box(event.window, gtk.STATE_NORMAL, gtk.SHADOW_NONE, event.area, self, None, - alloc.x + style._FOCUS_LINE_WIDTH, 0, - alloc.width - style._FOCUS_LINE_WIDTH*2, - style._FOCUS_LINE_WIDTH) + alloc.x + style.FOCUS_LINE_WIDTH, 0, + alloc.width - style.FOCUS_LINE_WIDTH * 2, + style.FOCUS_LINE_WIDTH) def _setup_page(page_widget, color, hpad): - vpad = style._FOCUS_LINE_WIDTH + vpad = style.FOCUS_LINE_WIDTH page_widget.child.set_padding(vpad, vpad, hpad, hpad) page = page_widget.child.child From 7d76f06ae1bf269a95e4246ae3cb6b3a18b24671 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sat, 1 Aug 2009 13:34:42 +0000 Subject: [PATCH 50/51] Remove redundant state argument from PaletteWindow.popup --- src/sugar/graphics/palette.py | 4 ++-- src/sugar/graphics/toolbarbox.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sugar/graphics/palette.py b/src/sugar/graphics/palette.py index 2a3b6c6b..92b04b65 100644 --- a/src/sugar/graphics/palette.py +++ b/src/sugar/graphics/palette.py @@ -318,7 +318,7 @@ class PaletteWindow(gtk.Window): def get_full_size_request(self): return self.size_request() - def popup(self, immediate=False, state=None): + def popup(self, immediate=False): if self._invoker is not None: full_size_request = self.get_full_size_request() self._alignment = self._invoker.get_alignment(full_size_request) @@ -365,7 +365,7 @@ class PaletteWindow(gtk.Window): self.on_invoker_leave() def _invoker_right_click_cb(self, invoker): - self.popup(immediate=True, state=self.SECONDARY) + self.popup(immediate=True) def __enter_notify_event_cb(self, widget, event): if event.detail != gtk.gdk.NOTIFY_INFERIOR and \ diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py index 93c24960..54de2bd4 100644 --- a/src/sugar/graphics/toolbarbox.py +++ b/src/sugar/graphics/toolbarbox.py @@ -93,6 +93,7 @@ class ToolbarButton(ToolButton): return if box.expanded_button is not None: + # need to redraw it to erase arrow expanded_toolitem = box.expanded_button.page_widget.toolbar_button if expanded_toolitem.window is not None: expanded_toolitem.window.invalidate_rect(None, True) @@ -216,14 +217,14 @@ class _ToolbarPalette(PaletteWindow): requisition.width = max(requisition.width, gtk.gdk.screen_width()) - def popup(self, immediate=False, state=None): + def popup(self, immediate=False): button = self.toolbar_button if button.is_expanded(): return box = button.toolbar_box _setup_page(button.page_widget, style.COLOR_BLACK.get_gdk_color(), box.props.padding) - PaletteWindow.popup(self, immediate, state) + PaletteWindow.popup(self, immediate) def __group_popdown_cb(self, group): if self._focus == 0: From 5c9020b18893d260f2007b469139a4284939ea18 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sat, 1 Aug 2009 13:35:18 +0000 Subject: [PATCH 51/51] Remove old design remains --- src/sugar/graphics/radiopalette.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sugar/graphics/radiopalette.py b/src/sugar/graphics/radiopalette.py index 70ba2e09..9a9476dc 100644 --- a/src/sugar/graphics/radiopalette.py +++ b/src/sugar/graphics/radiopalette.py @@ -74,19 +74,18 @@ class RadioPalette(Palette): button.palette_label = label if not children: - self.__clicked_cb(button, True) + self.__clicked_cb(button) def update_button(self): for i in self.button_box.get_children(): - self.__clicked_cb(i, True) + self.__clicked_cb(i) - def __clicked_cb(self, button, quiet=False): + def __clicked_cb(self, button): if not button.get_active(): return self.set_primary_text(button.palette_label) - if not quiet: - self.popdown(immediate=True) + self.popdown(immediate=True) if self.invoker is not None: parent = self.invoker.parent