From 32c89a1fcb7a536455343b87dc799b800da66380 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Thu, 15 Feb 2007 18:23:52 +0100 Subject: [PATCH] New widget OptionMenu. --- sugar/graphics/Makefile.am | 3 +- sugar/graphics/entry.py | 7 +- sugar/graphics/label.py | 8 +- sugar/graphics/optionmenu.py | 155 +++++++++++++++++++++++++++++++++++ sugar/graphics/style.py | 8 +- tests/data/stock-close.svg | 15 ++++ tests/test-entry.py | 4 + tests/test-label.py | 4 + tests/test-option-menu.py | 68 +++++++++++++++ 9 files changed, 259 insertions(+), 13 deletions(-) create mode 100644 sugar/graphics/optionmenu.py create mode 100644 tests/data/stock-close.svg create mode 100755 tests/test-option-menu.py diff --git a/sugar/graphics/Makefile.am b/sugar/graphics/Makefile.am index d0d04aeb..04508325 100644 --- a/sugar/graphics/Makefile.am +++ b/sugar/graphics/Makefile.am @@ -13,7 +13,8 @@ sugar_PYTHON = \ menu.py \ menuicon.py \ menushell.py \ - roundbox.py \ + optionmenu.py \ + roundbox.py \ snowflakebox.py \ spreadbox.py \ style.py \ diff --git a/sugar/graphics/entry.py b/sugar/graphics/entry.py index 62c1551b..0af2f0df 100644 --- a/sugar/graphics/entry.py +++ b/sugar/graphics/entry.py @@ -20,10 +20,10 @@ import logging import gobject import gtk import hippo -import pango from sugar.graphics import style from sugar.graphics.style import Color +from sugar.graphics.style import Font from sugar.graphics.button import Button from sugar.graphics.roundbox import RoundBox @@ -57,10 +57,7 @@ class Entry(hippo.CanvasBox, hippo.CanvasItem): self._entry.connect('focus-in-event', self._entry_focus_in_event_cb) self._entry.connect('focus-out-event', self._entry_focus_out_event_cb) self._entry.connect('activate', self._entry_activate_cb) - - fd = pango.FontDescription() - fd.set_size(int(round(style.default_font_size * pango.SCALE))) - self._entry.modify_font(fd) + self._entry.modify_font(Font.DEFAULT.get_pango_desc()) self._canvas_widget = hippo.CanvasWidget() self._canvas_widget.props.widget = self._entry diff --git a/sugar/graphics/label.py b/sugar/graphics/label.py index deb3762a..69caa1be 100644 --- a/sugar/graphics/label.py +++ b/sugar/graphics/label.py @@ -20,12 +20,12 @@ import logging import gobject import gtk import hippo -import pango from sugar.graphics import style from sugar.graphics.roundbox import RoundBox from sugar.graphics.button import Button from sugar.graphics.style import Color +from sugar.graphics.font import Font class Label(hippo.CanvasBox, hippo.CanvasItem): __gtype_name__ = 'SugarLabel' @@ -48,11 +48,7 @@ class Label(hippo.CanvasBox, hippo.CanvasItem): self._canvas_text = hippo.CanvasText() self._canvas_text.props.text = self._text self._canvas_text.props.color = Color.LABEL_TEXT.get_int() - - fd = pango.FontDescription() - fd.set_size(int(round(style.default_font_size * pango.SCALE))) - self._canvas_text.props.font_desc = fd - + self._canvas_text.props.font_desc = Font.DEFAULT.get_pango_desc() self._round_box.append(self._canvas_text, hippo.PACK_EXPAND) def do_set_property(self, pspec, value): diff --git a/sugar/graphics/optionmenu.py b/sugar/graphics/optionmenu.py new file mode 100644 index 00000000..a8084388 --- /dev/null +++ b/sugar/graphics/optionmenu.py @@ -0,0 +1,155 @@ +# Copyright (C) 2007, One Laptop Per Child +# +# 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 sys +import logging +from gettext import gettext as _ + +import gobject +import gtk +import hippo + +from sugar.graphics import style +from sugar.graphics.roundbox import RoundBox +from sugar.graphics.button import Button +from sugar.graphics.style import Color +from sugar.graphics.style import Font +from sugar.graphics.canvasicon import CanvasIcon + +class Menu(hippo.CanvasBox, hippo.CanvasItem): + __gtype_name__ = 'SugarMenu' + + __gsignals__ = { + 'action': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([int])) + } + + def __init__(self): + hippo.CanvasBox.__init__(self) + self.props.background_color = Color.MENU_BACKGROUND.get_int() + self.props.border_color = Color.MENU_BORDER.get_int() + #TODO: how we should specify the border thickness? + self.props.border = style.separator_thickness + self._window = None + + def add_item(self, action_id, label, icon_name=None, icon_color=None): + box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL) + box.props.padding = 5 + box.props.spacing = 5 + if icon_name: + icon = CanvasIcon(icon_name=icon_name, scale=style.small_icon_scale) + if icon_color: + icon.props.color = icon_color + box.append(icon) + + canvas_text = hippo.CanvasText() + canvas_text.props.text = label + canvas_text.props.color = Color.LABEL_TEXT.get_int() + canvas_text.props.font_desc = Font.DEFAULT.get_pango_desc() + box.append(canvas_text) + + box.connect('button-press-event', self._button_press_event_cb, action_id) + self.append(box) + + def add_separator(self): + box = hippo.CanvasBox() + box.props.background_color = Color.MENU_SEPARATOR.get_int() + box.props.box_height = style.separator_thickness + self.append(box) + + def show(self, x, y): + if not self._window: + self._window = hippo.CanvasWindow(gtk.WINDOW_POPUP) + self._window.move(x, y) + self._window.set_root(self) + self._window.show() + + def hide(self): + if self._window: + self._window.destroy() + self._window = None + + def _button_press_event_cb(self, item, event, option_id): + self.emit('action', option_id) + self.hide() + + def is_visible(self): + return self._window != None + +class OptionMenu(hippo.CanvasBox, hippo.CanvasItem): + __gtype_name__ = 'SugarOptionMenu' + + __gproperties__ = { + 'value' : (int, None, None, 0, sys.maxint, 1, gobject.PARAM_READWRITE) + } + + __gsignals__ = { + 'changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])) + } + + def __init__(self): + hippo.CanvasBox.__init__(self, orientation=hippo.ORIENTATION_HORIZONTAL) + self.props.yalign = hippo.ALIGNMENT_CENTER + self._value = None + + self._round_box = RoundBox() + self._round_box.props.border_color = Color.FRAME_BORDER.get_int() + self.append(self._round_box, hippo.PACK_EXPAND) + + self._canvas_text = hippo.CanvasText() + self._canvas_text.props.text = _('No options') + self._canvas_text.props.color = Color.LABEL_TEXT.get_int() + self._canvas_text.props.font_desc = Font.DEFAULT.get_pango_desc() + self._round_box.append(self._canvas_text, hippo.PACK_EXPAND) + + # TODO: Substitute for the right icon. + button = Button(icon_name='theme:stock-close') + button.props.scale = style.small_icon_scale + button.props.yalign = hippo.ALIGNMENT_CENTER + button.props.xalign = hippo.ALIGNMENT_START + button.connect('activated', self._button_activated_cb) + self._round_box.append(button) + + self._menu = Menu() + self._menu.connect('action', self._menu_action_cb) + + def do_set_property(self, pspec, value): + if pspec.name == 'value': + self._value = value + + def do_get_property(self, pspec): + if pspec.name == 'value': + return self._value + + def add_option(self, action_id, label, icon_name=None, icon_color=None): + self._menu.add_item(action_id, label, icon_name, icon_color) + + def add_separator(self): + self._menu.add_separator() + + def _button_activated_cb(self, button): + if self._menu.is_visible(): + self._menu.hide() + else: + context = self._round_box.get_context() + [x, y] = context.translate_to_screen(self._round_box) + [width, height] = self._round_box.get_allocation() + self._menu.props.box_width = self.get_width_request() + self._menu.show(x, y + height) + + def _menu_action_cb(self, menu, option_id): + if option_id != self._value: + self._value = option_id + self.emit('changed') diff --git a/sugar/graphics/style.py b/sugar/graphics/style.py index ab1d0369..81f29616 100644 --- a/sugar/graphics/style.py +++ b/sugar/graphics/style.py @@ -39,7 +39,10 @@ _system_colors = { 'entry-text-unfocused' : '#FFFFFF', 'entry-border' : '#D1D1D2', 'label-text' : '#FFFFFF', - 'desktop-background' : '#E2E2E3' + 'desktop-background' : '#E2E2E3', + 'menu-background' : '#414141', + 'menu-separator' : '#D1D1D2', + 'menu-border' : '#D1D1D2' } def _html_to_rgb(html_color): @@ -102,6 +105,9 @@ class Color(object): ENTRY_BORDER = SystemColor('entry-border') LABEL_TEXT = SystemColor('label-text') DESKTOP_BACKGROUND = SystemColor('desktop-background') + MENU_BACKGROUND = SystemColor('menu-background') + MENU_SEPARATOR = SystemColor('menu-separator') + MENU_BORDER = SystemColor('menu-border') _system_fonts = { 'default' : 'Bitstream Vera Sans %d' % _default_font_size diff --git a/tests/data/stock-close.svg b/tests/data/stock-close.svg new file mode 100644 index 00000000..0354c634 --- /dev/null +++ b/tests/data/stock-close.svg @@ -0,0 +1,15 @@ + + + + + + +]> + + + + + diff --git a/tests/test-entry.py b/tests/test-entry.py index 7c4ac06c..c87a5ae2 100755 --- a/tests/test-entry.py +++ b/tests/test-entry.py @@ -31,6 +31,10 @@ def _entry_button_activated_cb(entry, action_id): print "_entry_button_activated_cb: " + str(action_id) entry.props.text = '' +import os +theme = gtk.icon_theme_get_default() +theme.prepend_search_path(os.path.join(os.path.dirname(__file__), 'data')) + window = gtk.Window() window.connect("destroy", lambda w: gtk.main_quit()) window.show() diff --git a/tests/test-label.py b/tests/test-label.py index 890a528a..0ddfc176 100755 --- a/tests/test-label.py +++ b/tests/test-label.py @@ -23,6 +23,10 @@ from sugar.graphics.label import Label from sugar.graphics.button import Button from sugar.graphics.style import Color +import os +theme = gtk.icon_theme_get_default() +theme.prepend_search_path(os.path.join(os.path.dirname(__file__), 'data')) + BUTTON_DELETE = 1 window = gtk.Window() diff --git a/tests/test-option-menu.py b/tests/test-option-menu.py new file mode 100755 index 00000000..856c0f5b --- /dev/null +++ b/tests/test-option-menu.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python + +# Copyright (C) 2007, One Laptop Per Child +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import sys +sys.path.insert(0, '/home/tomeu/sugar-jhbuild/source/sugar') +from gettext import gettext as _ + +import gtk +import hippo + +from sugar.graphics.toolbar import Toolbar +from sugar.graphics.optionmenu import OptionMenu +from sugar.graphics.style import Color +from sugar.graphics.button import Button + +def _option_menu_changed_cb(option_menu): + print '_option_menu_activated_cb: %i' % option_menu.props.value + +import os +theme = gtk.icon_theme_get_default() +theme.prepend_search_path(os.path.join(os.path.dirname(__file__), 'data')) + +window = gtk.Window() +window.connect("destroy", lambda w: gtk.main_quit()) +window.show() + +canvas = hippo.Canvas() +window.add(canvas) +canvas.show() + +vbox = hippo.CanvasBox() +canvas.set_root(vbox) + +toolbar = Toolbar() +vbox.append(toolbar) + +button = Button('theme:stock-close') +toolbar.append(button) + +OPTION_ANYTHING = 1 +OPTION_DRAW = 2 +OPTION_WRITE = 3 +OPTION_CHAT = 4 + +option_menu = OptionMenu() +option_menu.add_option(OPTION_ANYTHING, _('Anything')) +option_menu.add_separator() +option_menu.add_option(OPTION_DRAW, _('Draw'), 'theme:stock-close') +option_menu.add_option(OPTION_WRITE, _('Write')) +option_menu.add_option(OPTION_CHAT, _('Chat')) +option_menu.connect('changed', _option_menu_changed_cb) +toolbar.append(option_menu) + +gtk.main()