diff options
author | Marco Pesenti Gritti <marco@localhost.localdomain> | 2008-04-29 12:58:34 (GMT) |
---|---|---|
committer | Marco Pesenti Gritti <marco@localhost.localdomain> | 2008-04-29 12:58:34 (GMT) |
commit | 72c2a1d770aac5af9df899cbfd25a15cbc2956ea (patch) | |
tree | 8909999bda47a3dfe9abc7befcd38e5278d6716f /sugar/graphics | |
parent | 6efdf259b62d7af47b1e06601eaee17b74dbeb58 (diff) |
Use a src directory consistently with base and shell.
Diffstat (limited to 'sugar/graphics')
-rw-r--r-- | sugar/graphics/Makefile.am | 25 | ||||
-rw-r--r-- | sugar/graphics/__init__.py | 18 | ||||
-rw-r--r-- | sugar/graphics/alert.py | 257 | ||||
-rw-r--r-- | sugar/graphics/animator.py | 95 | ||||
-rw-r--r-- | sugar/graphics/combobox.py | 112 | ||||
-rw-r--r-- | sugar/graphics/entry.py | 25 | ||||
-rw-r--r-- | sugar/graphics/icon.py | 560 | ||||
-rw-r--r-- | sugar/graphics/iconentry.py | 106 | ||||
-rw-r--r-- | sugar/graphics/menuitem.py | 34 | ||||
-rw-r--r-- | sugar/graphics/notebook.py | 116 | ||||
-rw-r--r-- | sugar/graphics/objectchooser.py | 118 | ||||
-rw-r--r-- | sugar/graphics/palette.py | 1000 | ||||
-rw-r--r-- | sugar/graphics/palettegroup.py | 91 | ||||
-rw-r--r-- | sugar/graphics/panel.py | 23 | ||||
-rw-r--r-- | sugar/graphics/radiotoolbutton.py | 104 | ||||
-rw-r--r-- | sugar/graphics/roundbox.py | 66 | ||||
-rw-r--r-- | sugar/graphics/style.py | 147 | ||||
-rw-r--r-- | sugar/graphics/toggletoolbutton.py | 64 | ||||
-rw-r--r-- | sugar/graphics/toolbox.py | 97 | ||||
-rw-r--r-- | sugar/graphics/toolbutton.py | 130 | ||||
-rw-r--r-- | sugar/graphics/toolcombobox.py | 59 | ||||
-rw-r--r-- | sugar/graphics/tray.py | 308 | ||||
-rw-r--r-- | sugar/graphics/window.py | 212 | ||||
-rw-r--r-- | sugar/graphics/xocolor.py | 255 |
24 files changed, 0 insertions, 4022 deletions
diff --git a/sugar/graphics/Makefile.am b/sugar/graphics/Makefile.am deleted file mode 100644 index 0a3a846..0000000 --- a/sugar/graphics/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -sugardir = $(pythondir)/sugar/graphics -sugar_PYTHON = \ - __init__.py \ - alert.py \ - animator.py \ - combobox.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 diff --git a/sugar/graphics/__init__.py b/sugar/graphics/__init__.py deleted file mode 100644 index 1e7e0f9..0000000 --- a/sugar/graphics/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Graphics/controls for use in Sugar""" - -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# 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/sugar/graphics/alert.py b/sugar/graphics/alert.py deleted file mode 100644 index cab3c3b..0000000 --- a/sugar/graphics/alert.py +++ /dev/null @@ -1,257 +0,0 @@ -# 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 gettext - -import gtk -import gobject -import hippo -import math - -from sugar.graphics import style -from sugar.graphics.icon import Icon - -_ = lambda msg: gettext.dgettext('sugar', msg) - -class Alert(gtk.EventBox): - """UI interface for Alerts - - Alerts are used inside the activity window instead of being a - separate popup window. They do not hide canvas content. You can - use add_alert(widget) and remove_alert(widget) inside your activity - to add and remove the alert. The position of the alert is below the - toolbox or top in fullscreen mode. - - Properties: - 'title': the title of the alert, - 'message': the message of the alert, - 'icon': the icon that appears at the far left - See __gproperties__ - """ - - __gtype_name__ = 'SugarAlert' - - __gsignals__ = { - 'response': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])) - } - - __gproperties__ = { - 'title' : (str, None, None, None, - gobject.PARAM_READWRITE), - 'msg' : (str, None, None, None, - gobject.PARAM_READWRITE), - 'icon' : (object, None, None, - gobject.PARAM_WRITABLE) - } - - def __init__(self, **kwargs): - - self._title = None - self._msg = None - self._icon = None - self._buttons = {} - - self._hbox = gtk.HBox() - self._hbox.set_border_width(style.DEFAULT_SPACING) - self._hbox.set_spacing(style.DEFAULT_SPACING) - - self._msg_box = gtk.VBox() - self._title_label = gtk.Label() - self._title_label.set_alignment(0, 0.5) - self._msg_box.pack_start(self._title_label, False) - - self._msg_label = gtk.Label() - self._msg_label.set_alignment(0, 0.5) - self._msg_box.pack_start(self._msg_label, False) - self._hbox.pack_start(self._msg_box, False) - - self._buttons_box = gtk.HButtonBox() - self._buttons_box.set_layout(gtk.BUTTONBOX_END) - self._buttons_box.set_spacing(style.DEFAULT_SPACING) - self._hbox.pack_start(self._buttons_box) - - gtk.EventBox.__init__(self, **kwargs) - - self.set_visible_window(True) - self.add(self._hbox) - self._title_label.show() - self._msg_label.show() - self._buttons_box.show() - self._msg_box.show() - self._hbox.show() - self.show() - - def do_set_property(self, pspec, value): - if pspec.name == 'title': - if self._title != value: - self._title = value - self._title_label.set_markup("<b>" + self._title + "</b>") - elif pspec.name == 'msg': - if self._msg != value: - self._msg = value - self._msg_label.set_markup(self._msg) - elif pspec.name == 'icon': - if self._icon != value: - self._icon = value - self._hbox.pack_start(self._icon, False) - self._hbox.reorder_child(self._icon, 0) - - def do_get_property(self, pspec): - if pspec.name == 'title': - return self._title - elif pspec.name == 'msg': - return self._msg - - def add_button(self, response_id, label, icon=None, position=-1): - """Add a button to the alert - - response_id: will be emitted with the response signal - a response ID should one of the pre-defined - GTK Response Type Constants or a positive number - label: that will occure right to the buttom - icon: this can be a SugarIcon or a gtk.Image - position: the position of the button in the box (optional) - """ - button = gtk.Button() - self._buttons[response_id] = button - if icon is not None: - button.set_image(icon) - button.set_label(label) - self._buttons_box.pack_start(button) - button.show() - button.connect('clicked', self.__button_clicked_cb, response_id) - if position != -1: - self._buttons_box.reorder_child(button, position) - return button - - def remove_button(self, response_id): - """Remove a button from the alert by the given response id""" - self._buttons_box.remove(self._buttons[response_id]) - - def _response(self, response_id): - """Emitting response when we have a result - - A result can be that a user has clicked a button or - a timeout has occured, the id identifies the button - that has been clicked and -1 for a timeout - """ - self.emit('response', response_id) - - def __button_clicked_cb(self, button, response_id): - self._response(response_id) - - -class ConfirmationAlert(Alert): - """This is a ready-made two button (Cancel,Ok) alert""" - - def __init__(self, **kwargs): - Alert.__init__(self, **kwargs) - - icon = Icon(icon_name='dialog-cancel') - self.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), icon) - icon.show() - - icon = Icon(icon_name='dialog-ok') - self.add_button(gtk.RESPONSE_OK, _('Ok'), icon) - icon.show() - - -class _TimeoutIcon(hippo.CanvasText, hippo.CanvasItem): - """An icon with a round border""" - __gtype_name__ = 'AlertTimeoutIcon' - - def __init__(self, **kwargs): - hippo.CanvasText.__init__(self, **kwargs) - - self.props.orientation = hippo.ORIENTATION_HORIZONTAL - self.props.border_left = style.DEFAULT_SPACING - self.props.border_right = style.DEFAULT_SPACING - - def do_paint_background(self, cr, damaged_box): - [width, height] = self.get_allocation() - - xval = width * 0.5 - yval = height * 0.5 - radius = min(width * 0.5, height * 0.5) - - hippo.cairo_set_source_rgba32(cr, self.props.background_color) - cr.arc(xval, yval, radius, 0, 2*math.pi) - cr.fill_preserve() - - -class TimeoutAlert(Alert): - """This is a ready-made two button (Cancel,Continue) alert - - It times out with a positive reponse after the given amount of seconds. - """ - - def __init__(self, timeout=5, **kwargs): - Alert.__init__(self, **kwargs) - - self._timeout = timeout - - icon = Icon(icon_name='dialog-cancel') - self.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), icon) - icon.show() - - self._timeout_text = _TimeoutIcon( - text=self._timeout, - color=style.COLOR_BUTTON_GREY.get_int(), - background_color=style.COLOR_WHITE.get_int()) - canvas = hippo.Canvas() - canvas.set_root(self._timeout_text) - canvas.show() - self.add_button(gtk.RESPONSE_OK, _('Continue'), canvas) - - gobject.timeout_add(1000, self.__timeout) - - def __timeout(self): - self._timeout -= 1 - self._timeout_text.props.text = self._timeout - if self._timeout == 0: - self._response(gtk.RESPONSE_OK) - return False - return True - - -class NotifyAlert(Alert): - """Timeout alert with only an "OK" button - just for notifications""" - - def __init__(self, timeout=5, **kwargs): - Alert.__init__(self, **kwargs) - - self._timeout = timeout - - self._timeout_text = _TimeoutIcon( - text=self._timeout, - color=style.COLOR_BUTTON_GREY.get_int(), - background_color=style.COLOR_WHITE.get_int()) - canvas = hippo.Canvas() - canvas.set_root(self._timeout_text) - canvas.show() - self.add_button(gtk.RESPONSE_OK, _('Ok'), canvas) - - gobject.timeout_add(1000, self.__timeout) - - def __timeout(self): - self._timeout -= 1 - self._timeout_text.props.text = self._timeout - if self._timeout == 0: - self._response(gtk.RESPONSE_OK) - return False - return True diff --git a/sugar/graphics/animator.py b/sugar/graphics/animator.py deleted file mode 100644 index 85b9852..0000000 --- a/sugar/graphics/animator.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# 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 time - -import gobject - -EASE_OUT_EXPO = 0 -EASE_IN_EXPO = 1 - -class Animator(gobject.GObject): - __gsignals__ = { - 'completed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), - } - - def __init__(self, duration, fps=20, easing=EASE_OUT_EXPO): - gobject.GObject.__init__(self) - self._animations = [] - self._duration = duration - self._interval = 1.0 / fps - self._easing = easing - self._timeout_sid = 0 - self._start_time = None - - def add(self, animation): - self._animations.append(animation) - - def remove_all(self): - self.stop() - self._animations = [] - - def start(self): - if self._timeout_sid: - self.stop() - - self._start_time = time.time() - self._timeout_sid = gobject.timeout_add( - int(self._interval * 1000), self._next_frame_cb) - - def stop(self): - if self._timeout_sid: - gobject.source_remove(self._timeout_sid) - self._timeout_sid = 0 - self.emit('completed') - - def _next_frame_cb(self): - current_time = min(self._duration, time.time() - self._start_time) - current_time = max(current_time, 0.0) - - for animation in self._animations: - animation.do_frame(current_time, self._duration, self._easing) - - if current_time == self._duration: - self.stop() - return False - else: - return True - -class Animation(object): - def __init__(self, start, end): - self.start = start - self.end = end - - def do_frame(self, t, duration, easing): - start = self.start - change = self.end - self.start - - if t == duration: - # last frame - frame = self.end - else: - if easing == EASE_OUT_EXPO: - frame = change * (-pow(2, -10 * t / duration) + 1) + start - elif easing == EASE_IN_EXPO: - frame = change * pow(2, 10 * (t / duration - 1)) + start - - self.next_frame(frame) - - def next_frame(self, frame): - pass diff --git a/sugar/graphics/combobox.py b/sugar/graphics/combobox.py deleted file mode 100644 index 2924fb3..0000000 --- a/sugar/graphics/combobox.py +++ /dev/null @@ -1,112 +0,0 @@ -# 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 gobject -import gtk - -class ComboBox(gtk.ComboBox): - __gtype_name__ = 'SugarComboBox' - - __gproperties__ = { - 'value' : (object, None, None, - gobject.PARAM_READABLE) - } - def __init__(self): - gtk.ComboBox.__init__(self) - - self._text_renderer = None - self._icon_renderer = None - - self._model = gtk.ListStore(gobject.TYPE_PYOBJECT, - gobject.TYPE_STRING, - gtk.gdk.Pixbuf, - gobject.TYPE_BOOLEAN) - self.set_model(self._model) - - self.set_row_separator_func(self._is_separator) - - def do_get_property(self, pspec): - if pspec.name == 'value': - row = self.get_active_item() - if not row: - return None - return row[0] - else: - return gtk.ComboBox.do_get_property(self, pspec) - - def _get_real_name_from_theme(self, name, size): - icon_theme = gtk.icon_theme_get_default() - width, height = gtk.icon_size_lookup(size) - info = icon_theme.lookup_icon(name, max(width, height), 0) - if not info: - raise ValueError("Icon '" + name + "' not found.") - fname = info.get_filename() - del info - return fname - - def append_item(self, action_id, text, icon_name=None, file_name=None): - if not self._icon_renderer and (icon_name or file_name): - self._icon_renderer = gtk.CellRendererPixbuf() - - settings = self.get_settings() - w, h = gtk.icon_size_lookup_for_settings( - settings, gtk.ICON_SIZE_MENU) - self._icon_renderer.props.stock_size = max(w, h) - - self.pack_start(self._icon_renderer, False) - self.add_attribute(self._icon_renderer, 'pixbuf', 2) - - if not self._text_renderer and text: - self._text_renderer = gtk.CellRendererText() - self.pack_end(self._text_renderer, True) - self.add_attribute(self._text_renderer, 'text', 1) - - if icon_name or file_name: - if text: - size = gtk.ICON_SIZE_MENU - else: - size = gtk.ICON_SIZE_LARGE_TOOLBAR - width, height = gtk.icon_size_lookup(size) - - if icon_name: - file_name = self._get_real_name_from_theme(icon_name, size) - - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( - file_name, width, height) - else: - pixbuf = None - - self._model.append([action_id, text, pixbuf, False]) - - def append_separator(self): - self._model.append([0, None, None, True]) - - def get_active_item(self): - index = self.get_active() - if index == -1: - index = 0 - - row = self._model.iter_nth_child(None, index) - if not row: - return None - return self._model[row] - - def remove_all(self): - self._model.clear() - - def _is_separator(self, model, row): - return model[row][3] diff --git a/sugar/graphics/entry.py b/sugar/graphics/entry.py deleted file mode 100644 index 95510e5..0000000 --- a/sugar/graphics/entry.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# 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 hippo - -class CanvasEntry(hippo.CanvasEntry): - def set_background(self, color_spec): - color = gtk.gdk.color_parse(color_spec) - self.props.widget.modify_bg(gtk.STATE_INSENSITIVE, color) - self.props.widget.modify_base(gtk.STATE_INSENSITIVE, color) diff --git a/sugar/graphics/icon.py b/sugar/graphics/icon.py deleted file mode 100644 index 2bd73c8..0000000 --- a/sugar/graphics/icon.py +++ /dev/null @@ -1,560 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# 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 re -import math -import logging - -import gobject -import gtk -import hippo -import cairo - -from sugar.graphics.xocolor import XoColor -from sugar.util import LRU - -_BADGE_SIZE = 0.45 - -class _SVGLoader(object): - def __init__(self): - self._cache = LRU(50) - - def load(self, file_name, entities, cache): - if file_name in self._cache: - icon = self._cache[file_name] - else: - icon_file = open(file_name, 'r') - icon = icon_file.read() - icon_file.close() - - if cache: - self._cache[file_name] = icon - - for entity, value in entities.items(): - if isinstance(value, basestring): - xml = '<!ENTITY %s "%s">' % (entity, value) - icon = re.sub('<!ENTITY %s .*>' % entity, xml, icon) - else: - logging.error( - 'Icon %s, entity %s is invalid.', file_name, entity) - - import rsvg # XXX this is very slow! why? - return rsvg.Handle(data=icon) - -class _IconInfo(object): - def __init__(self): - self.file_name = None - self.attach_x = 0 - self.attach_y = 0 - -class _BadgeInfo(object): - def __init__(self): - self.attach_x = 0 - self.attach_y = 0 - self.size = 0 - self.icon_padding = 0 - -class _IconBuffer(object): - _surface_cache = LRU(50) - _loader = _SVGLoader() - - def __init__(self): - self.icon_name = None - self.icon_size = None - self.file_name = None - self.fill_color = None - self.stroke_color = None - self.badge_name = None - self.width = None - self.height = None - self.cache = False - self.scale = 1.0 - - def _get_cache_key(self, sensitive): - return (self.icon_name, self.file_name, self.fill_color, - self.stroke_color, self.badge_name, self.width, self.height, - sensitive) - - def _load_svg(self, file_name): - entities = {} - if self.fill_color: - entities['fill_color'] = self.fill_color - if self.stroke_color: - entities['stroke_color'] = self.stroke_color - - return self._loader.load(file_name, entities, self.cache) - - def _get_attach_points(self, info, size_request): - attach_points = info.get_attach_points() - - if attach_points: - attach_x = float(attach_points[0][0]) / size_request - attach_y = float(attach_points[0][1]) / size_request - else: - attach_x = attach_y = 0 - - return attach_x, attach_y - - def _get_icon_info(self): - icon_info = _IconInfo() - - if self.file_name: - icon_info.file_name = self.file_name - elif self.icon_name: - theme = gtk.icon_theme_get_default() - - size = 50 - if self.width != None: - size = self.width - - info = theme.lookup_icon(self.icon_name, size, 0) - if info: - attach_x, attach_y = self._get_attach_points(info, size) - - icon_info.file_name = info.get_filename() - icon_info.attach_x = attach_x - icon_info.attach_y = attach_y - - del info - else: - logging.warning('No icon with the name %s ' - 'was found in the theme.' % self.icon_name) - - return icon_info - - def _draw_badge(self, context, size, sensitive, widget): - theme = gtk.icon_theme_get_default() - badge_info = theme.lookup_icon(self.badge_name, size, 0) - if badge_info: - badge_file_name = badge_info.get_filename() - if badge_file_name.endswith('.svg'): - handle = self._loader.load(badge_file_name, {}, self.cache) - - dimensions = handle.get_dimension_data() - icon_width = int(dimensions[0]) - icon_height = int(dimensions[1]) - - pixbuf = handle.get_pixbuf() - else: - pixbuf = gtk.gdk.pixbuf_new_from_file(badge_file_name) - - icon_width = pixbuf.get_width() - icon_height = pixbuf.get_height() - - context.scale(float(size) / icon_width, - float(size) / icon_height) - - if not sensitive: - pixbuf = self._get_insensitive_pixbuf(pixbuf, widget) - surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf) - context.set_source_surface(surface, 0, 0) - context.paint() - - def _get_size(self, icon_width, icon_height, padding): - if self.width is not None and self.height is not None: - width = self.width + padding - height = self.height + padding - else: - width = icon_width + padding - height = icon_height + padding - - return width, height - - def _get_badge_info(self, icon_info, icon_width, icon_height): - info = _BadgeInfo() - if self.badge_name is None: - return info - - info.size = int(_BADGE_SIZE * icon_width) - info.attach_x = int(icon_info.attach_x * icon_width - info.size / 2) - info.attach_y = int(icon_info.attach_y * icon_height - info.size / 2) - - if info.attach_x < 0 or info.attach_y < 0: - info.icon_padding = max(-info.attach_x, -info.attach_y) - elif info.attach_x + info.size > icon_width or \ - info.attach_y + info.size > icon_height: - x_padding = info.attach_x + info.size - icon_width - y_padding = info.attach_y + info.size - icon_height - info.icon_padding = max(x_padding, y_padding) - - return info - - def _get_xo_color(self): - if self.stroke_color and self.fill_color: - return XoColor('%s,%s' % (self.stroke_color, self.fill_color)) - else: - return None - - def _set_xo_color(self, xo_color): - if xo_color: - self.stroke_color = xo_color.get_stroke_color() - self.fill_color = xo_color.get_fill_color() - else: - self.stroke_color = None - self.fill_color = None - - def _get_insensitive_pixbuf (self, pixbuf, widget): - if not (widget and widget.style): - return pixbuf - - icon_source = gtk.IconSource() - # Special size meaning "don't touch" - icon_source.set_size(-1) - icon_source.set_pixbuf(pixbuf) - icon_source.set_state(gtk.STATE_INSENSITIVE) - icon_source.set_direction_wildcarded(False) - icon_source.set_size_wildcarded(False) - - # Please note that the pixbuf returned by this function is leaked - # with current stable versions of pygtk. The relevant bug is - # http://bugzilla.gnome.org/show_bug.cgi?id=502871 - # -- 2007-12-14 Benjamin Berg - pixbuf = widget.style.render_icon(icon_source, widget.get_direction(), - gtk.STATE_INSENSITIVE, -1, widget, - "sugar-icon") - - return pixbuf - - def get_surface(self, sensitive=True, widget=None): - cache_key = self._get_cache_key(sensitive) - if cache_key in self._surface_cache: - return self._surface_cache[cache_key] - - icon_info = self._get_icon_info() - if icon_info.file_name is None: - return None - - is_svg = icon_info.file_name.endswith('.svg') - - if is_svg: - handle = self._load_svg(icon_info.file_name) - dimensions = handle.get_dimension_data() - icon_width = int(dimensions[0]) - icon_height = int(dimensions[1]) - else: - pixbuf = gtk.gdk.pixbuf_new_from_file(icon_info.file_name) - icon_width = pixbuf.get_width() - icon_height = pixbuf.get_height() - - badge_info = self._get_badge_info(icon_info, icon_width, icon_height) - - padding = badge_info.icon_padding - width, height = self._get_size(icon_width, icon_height, padding) - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - - context = cairo.Context(surface) - context.scale(float(width) / (icon_width + padding * 2), - float(height) / (icon_height + padding * 2)) - context.save() - - context.translate(padding, padding) - if is_svg: - if sensitive: - handle.render_cairo(context) - else: - pixbuf = handle.get_pixbuf() - pixbuf = self._get_insensitive_pixbuf(pixbuf, widget) - - pixbuf_surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf) - context.set_source_surface(pixbuf_surface, 0, 0) - context.paint() - else: - if not sensitive: - pixbuf = self._get_insensitive_pixbuf(pixbuf, widget) - pixbuf_surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf) - context.set_source_surface(pixbuf_surface, 0, 0) - context.paint() - - if self.badge_name: - context.restore() - context.translate(badge_info.attach_x, badge_info.attach_y) - self._draw_badge(context, badge_info.size, sensitive, widget) - - self._surface_cache[cache_key] = surface - - return surface - - xo_color = property(_get_xo_color, _set_xo_color) - -class Icon(gtk.Image): - __gtype_name__ = 'SugarIcon' - - __gproperties__ = { - 'xo-color' : (object, None, None, - gobject.PARAM_WRITABLE), - 'fill-color' : (object, None, None, - gobject.PARAM_READWRITE), - 'stroke-color' : (object, None, None, - gobject.PARAM_READWRITE), - 'badge-name' : (str, None, None, None, - gobject.PARAM_READWRITE) - } - - def __init__(self, **kwargs): - self._buffer = _IconBuffer() - - gobject.GObject.__init__(self, **kwargs) - - def _sync_image_properties(self): - if self._buffer.icon_name != self.props.icon_name: - self._buffer.icon_name = self.props.icon_name - - if self._buffer.file_name != self.props.file: - self._buffer.file_name = self.props.file - - if self.props.pixel_size == -1: - width, height = gtk.icon_size_lookup(self.props.icon_size) - else: - width = height = self.props.pixel_size - if self._buffer.width != width or self._buffer.height != height: - self._buffer.width = width - self._buffer.height = height - - def _icon_size_changed_cb(self, image, pspec): - self._buffer.icon_size = self.props.icon_size - - def _icon_name_changed_cb(self, image, pspec): - self._buffer.icon_name = self.props.icon_name - - def _file_changed_cb(self, image, pspec): - self._buffer.file_name = self.props.file - - def do_size_request(self, requisition): - self._sync_image_properties() - surface = self._buffer.get_surface() - if surface: - requisition[0] = surface.get_width() - requisition[1] = surface.get_height() - elif self._buffer.width and self._buffer.height: - requisition[0] = self._buffer.width - requisition[1] = self._buffer.width - else: - requisition[0] = requisition[1] = 0 - - def do_expose_event(self, event): - self._sync_image_properties() - sensitive = (self.state != gtk.STATE_INSENSITIVE) - surface = self._buffer.get_surface(sensitive, self) - if surface is None: - return - - xpad, ypad = self.get_padding() - xalign, yalign = self.get_alignment() - requisition = self.get_child_requisition() - if self.get_direction() != gtk.TEXT_DIR_LTR: - xalign = 1.0 - xalign - - allocation = self.get_allocation() - x = math.floor(allocation.x + xpad + - (allocation.width - requisition[0]) * xalign) - y = math.floor(allocation.y + ypad + - (allocation.height - requisition[1]) * yalign) - - cr = self.window.cairo_create() - cr.set_source_surface(surface, x, y) - cr.paint() - - def do_set_property(self, pspec, value): - if pspec.name == 'xo-color': - if self._buffer.xo_color != value: - self._buffer.xo_color = value - self.queue_draw() - elif pspec.name == 'fill-color': - if self._buffer.fill_color != value: - self._buffer.fill_color = value - self.queue_draw() - elif pspec.name == 'stroke-color': - if self._buffer.stroke_color != value: - self._buffer.stroke_color = value - self.queue_draw() - elif pspec.name == 'badge-name': - if self._buffer.badge_name != value: - self._buffer.badge_name = value - self.queue_resize() - else: - gtk.Image.do_set_property(self, pspec, value) - - def do_get_property(self, pspec): - if pspec.name == 'fill-color': - return self._buffer.fill_color - elif pspec.name == 'stroke-color': - return self._buffer.stroke_color - elif pspec.name == 'badge-name': - return self._buffer.badge_name - else: - return gtk.Image.do_get_property(self, pspec) - -class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem): - __gtype_name__ = 'CanvasIcon' - - __gproperties__ = { - 'file-name' : (str, None, None, None, - gobject.PARAM_READWRITE), - 'icon-name' : (str, None, None, None, - gobject.PARAM_READWRITE), - 'xo-color' : (object, None, None, - gobject.PARAM_WRITABLE), - 'fill-color' : (object, None, None, - gobject.PARAM_READWRITE), - 'stroke-color' : (object, None, None, - gobject.PARAM_READWRITE), - 'size' : (int, None, None, 0, 1024, 0, - gobject.PARAM_READWRITE), - 'scale' : (float, None, None, -1024.0, 1024.0, 1.0, - gobject.PARAM_READWRITE), - 'cache' : (bool, None, None, False, - gobject.PARAM_READWRITE), - 'badge-name' : (str, None, None, None, - gobject.PARAM_READWRITE) - } - - def __init__(self, **kwargs): - self._buffer = _IconBuffer() - - hippo.CanvasBox.__init__(self, **kwargs) - - self._palette = None - self.connect('destroy', self.__destroy_cb) - - def __destroy_cb(self, icon): - if self._palette is not None: - self._palette.destroy() - - def do_set_property(self, pspec, value): - if pspec.name == 'file-name': - if self._buffer.file_name != value: - self._buffer.file_name = value - self.emit_paint_needed(0, 0, -1, -1) - elif pspec.name == 'icon-name': - if self._buffer.icon_name != value: - self._buffer.icon_name = value - self.emit_paint_needed(0, 0, -1, -1) - elif pspec.name == 'xo-color': - if self._buffer.xo_color != value: - self._buffer.xo_color = value - self.emit_paint_needed(0, 0, -1, -1) - elif pspec.name == 'fill-color': - if self._buffer.fill_color != value: - self._buffer.fill_color = value - self.emit_paint_needed(0, 0, -1, -1) - elif pspec.name == 'stroke-color': - if self._buffer.stroke_color != value: - self._buffer.stroke_color = value - self.emit_paint_needed(0, 0, -1, -1) - elif pspec.name == 'size': - if self._buffer.width != value: - self._buffer.width = value - self._buffer.height = value - self.emit_request_changed() - elif pspec.name == 'scale': - logging.warning( - 'CanvasIcon: the scale parameter is currently unsupported') - if self._buffer.scale != value: - self._buffer.scale = value - self.emit_request_changed() - elif pspec.name == 'cache': - self._buffer.cache = value - elif pspec.name == 'badge-name': - if self._buffer.badge_name != value: - self._buffer.badge_name = value - self.emit_paint_needed(0, 0, -1, -1) - - def do_get_property(self, pspec): - if pspec.name == 'size': - return self._buffer.width - elif pspec.name == 'file-name': - return self._buffer.file_name - elif pspec.name == 'icon-name': - return self._buffer.icon_name - elif pspec.name == 'fill-color': - return self._buffer.fill_color - elif pspec.name == 'stroke-color': - return self._buffer.stroke_color - elif pspec.name == 'cache': - return self._buffer.cache - elif pspec.name == 'badge-name': - return self._buffer.badge_name - elif pspec.name == 'scale': - return self._buffer.scale - - def do_paint_below_children(self, cr, damaged_box): - surface = self._buffer.get_surface() - if surface: - width, height = self.get_allocation() - - x = (width - surface.get_width()) / 2 - y = (height - surface.get_height()) / 2 - - cr.set_source_surface(surface, x, y) - cr.paint() - - def do_get_content_width_request(self): - surface = self._buffer.get_surface() - if surface: - size = surface.get_width() - elif self._buffer.width: - size = self._buffer.width - else: - size = 0 - - return size, size - - def do_get_content_height_request(self, for_width): - surface = self._buffer.get_surface() - if surface: - size = surface.get_height() - elif self._buffer.height: - size = self._buffer.height - else: - size = 0 - - return size, size - - def do_button_press_event(self, event): - self.emit_activated() - return True - - def get_palette(self): - return self._palette - - def set_palette(self, palette): - from sugar.graphics.palette import CanvasInvoker - - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - if not self._palette.props.invoker: - self._palette.props.invoker = CanvasInvoker(self) - - def set_tooltip(self, text): - from sugar.graphics.palette import Palette - - self.set_palette(Palette(text)) - - palette = property(get_palette, set_palette) - -def get_icon_state(base_name, perc): - step = 5 - strength = round(perc / step) * step - icon_theme = gtk.icon_theme_get_default() - - while strength <= 100: - icon_name = '%s-%03d' % (base_name, strength) - if icon_theme.has_icon(icon_name): - return icon_name - - strength = strength + step diff --git a/sugar/graphics/iconentry.py b/sugar/graphics/iconentry.py deleted file mode 100644 index df38b9e..0000000 --- a/sugar/graphics/iconentry.py +++ /dev/null @@ -1,106 +0,0 @@ -# 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 gtk - -from sugar import _sugarext - -from sugar.graphics import style -from sugar.graphics.icon import _SVGLoader - -ICON_ENTRY_PRIMARY = _sugarext.ICON_ENTRY_PRIMARY -ICON_ENTRY_SECONDARY = _sugarext.ICON_ENTRY_SECONDARY - -class IconEntry(_sugarext.IconEntry): - - def __init__(self): - _sugarext.IconEntry.__init__(self) - - self._clear_icon = None - self._clear_shown = False - - self.connect('key_press_event', self._keypress_event_cb) - - def set_icon_from_name(self, position, name): - icon_theme = gtk.icon_theme_get_default() - icon_info = icon_theme.lookup_icon(name, - gtk.ICON_SIZE_SMALL_TOOLBAR, - 0) - - if icon_info.get_filename().endswith('.svg'): - loader = _SVGLoader() - entities = {'fill_color': style.COLOR_TOOLBAR_GREY.get_svg(), - 'stroke_color': style.COLOR_TOOLBAR_GREY.get_svg()} - handle = loader.load(icon_info.get_filename(), entities, None) - pixbuf = handle.get_pixbuf() - else: - pixbuf = gtk.gdk.pixbuf_new_from_file(icon_info.get_filename()) - del icon_info - - image = gtk.Image() - image.set_from_pixbuf(pixbuf) - image.show() - - self.set_icon(position, image) - - def set_icon(self, position, image): - if image.get_storage_type() not in [gtk.IMAGE_PIXBUF, gtk.IMAGE_STOCK]: - raise ValueError('Image must have a storage type of pixbuf or ' + - 'stock, not %r.' % image.get_storage_type()) - _sugarext.IconEntry.set_icon(self, position, image) - - def remove_icon(self, position): - _sugarext.IconEntry.set_icon(self, position, None) - - def add_clear_button(self): - if self.props.text != "": - self.show_clear_button() - else: - self.hide_clear_button() - - self.connect('icon-pressed', self._icon_pressed_cb) - self.connect('changed', self._changed_cb) - - def show_clear_button(self): - if not self._clear_shown: - self.set_icon_from_name(ICON_ENTRY_SECONDARY, - 'dialog-cancel') - self._clear_shown = True - - def hide_clear_button(self): - if self._clear_shown: - self.remove_icon(ICON_ENTRY_SECONDARY) - self._clear_shown = False - - def _keypress_event_cb(self, widget, event): - keyval = gtk.gdk.keyval_name(event.keyval) - if keyval == 'Escape': - self.props.text = '' - return True - return False - - def _icon_pressed_cb(self, entru, icon_pos, button): - if icon_pos == ICON_ENTRY_SECONDARY: - self.set_text('') - self.hide_clear_button() - - def _changed_cb(self, icon_entry): - if not self.props.text: - self.hide_clear_button() - else: - self.show_clear_button() - diff --git a/sugar/graphics/menuitem.py b/sugar/graphics/menuitem.py deleted file mode 100644 index 3d6764b..0000000 --- a/sugar/graphics/menuitem.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (C) 2007, Eduardo Silva <edsiper@gmail.com> -# -# 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 -from sugar.graphics.icon import Icon - -import pango - -class MenuItem(gtk.ImageMenuItem): - def __init__(self, text_label=None, icon_name=None, text_maxlen=0): - gtk.ImageMenuItem.__init__(self, text_label) - if icon_name: - icon = Icon(icon_name=icon_name, icon_size=gtk.ICON_SIZE_MENU) - self.set_image(icon) - icon.show() - - if text_maxlen > 0: - child = self.get_child() - child.set_ellipsize(pango.ELLIPSIZE_MIDDLE) - child.set_max_width_chars(text_maxlen) diff --git a/sugar/graphics/notebook.py b/sugar/graphics/notebook.py deleted file mode 100644 index bc6bab5..0000000 --- a/sugar/graphics/notebook.py +++ /dev/null @@ -1,116 +0,0 @@ -"""Notebook class - -This class create a gtk.Notebook() widget supporting -a close button in every tab when the 'can-close-tabs' gproperty -is enabled (True) -""" - -# Copyright (C) 2007, Eduardo Silva (edsiper@gmail.com) -# -# 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 - -class Notebook(gtk.Notebook): - __gtype_name__ = 'SugarNotebook' - - __gproperties__ = { - 'can-close-tabs': (bool, None, None, False, - gobject.PARAM_READWRITE | - gobject.PARAM_CONSTRUCT_ONLY) - } - - def __init__(self, **kwargs): - # Initialise the Widget - # - # Side effects: - # Set the 'can-close-tabs' property using **kwargs - # Set True the scrollable notebook property - - gobject.GObject.__init__(self, **kwargs) - - self._can_close_tabs = None - - self.set_scrollable(True) - self.show() - - def do_set_property(self, pspec, value): - if pspec.name == 'can-close-tabs': - self._can_close_tabs = value - else: - raise AssertionError - - def _add_icon_to_button(self, button): - icon_box = gtk.HBox() - image = gtk.Image() - image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU) - gtk.Button.set_relief(button, gtk.RELIEF_NONE) - - settings = gtk.Widget.get_settings(button) - w, h = gtk.icon_size_lookup_for_settings(settings, gtk.ICON_SIZE_MENU) - gtk.Widget.set_size_request(button, w + 4, h + 4) - image.show() - icon_box.pack_start(image, True, False, 0) - button.add(icon_box) - icon_box.show() - - def _create_custom_tab(self, text, child): - event_box = gtk.EventBox() - - tab_box = gtk.HBox(False, 2) - tab_label = gtk.Label(text) - - tab_button = gtk.Button() - tab_button.connect('clicked', self._close_page, child) - - # Add a picture on a button - self._add_icon_to_button(tab_button) - - event_box.show() - tab_button.show() - tab_label.show() - - tab_box.pack_start(tab_label, True) - tab_box.pack_start(tab_button, True) - - tab_box.show_all() - event_box.add(tab_box) - - return event_box - - def add_page(self, text_label, widget): - # Add a new page to the notebook - if self._can_close_tabs: - eventbox = self._create_custom_tab(text_label, widget) - self.append_page(widget, eventbox) - else: - self.append_page(widget, gtk.Label(text_label)) - - pages = self.get_n_pages() - - # Set the new page - self.set_current_page(pages - 1) - self.show_all() - - return True - - def _close_page(self, button, child): - # Remove a page from the notebook - page = self.page_num(child) - - if page != -1: - self.remove_page(page) diff --git a/sugar/graphics/objectchooser.py b/sugar/graphics/objectchooser.py deleted file mode 100644 index 51fa3a7..0000000 --- a/sugar/graphics/objectchooser.py +++ /dev/null @@ -1,118 +0,0 @@ -# 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 logging - -import gobject -import gtk -import dbus - -from sugar.datastore import datastore - -J_DBUS_SERVICE = 'org.laptop.Journal' -J_DBUS_INTERFACE = 'org.laptop.Journal' -J_DBUS_PATH = '/org/laptop/Journal' - -class ObjectChooser(object): - def __init__(self, title=None, parent=None, flags=None, buttons=None): - # For backwards compatibility: - # - We ignore title, flags and buttons. - # - 'parent' can be a xid or a gtk.gdk.Window - - if title is not None or flags is not None or buttons is not None: - logging.warning('Invocation of ObjectChooser() has deprecated ' - 'parameters.') - - if parent is None: - parent_xid = 0 - elif hasattr(parent, 'window') and hasattr(parent.window, 'xid'): - parent_xid = parent.window.xid - else: - parent_xid = parent - - self._parent_xid = parent_xid - self._main_loop = None - self._object_id = None - self._bus = None - self._chooser_id = None - self._response_code = gtk.RESPONSE_NONE - - def run(self): - self._object_id = None - - self._main_loop = gobject.MainLoop() - - self._bus = dbus.SessionBus(mainloop=self._main_loop) - self._bus.add_signal_receiver( - self.__name_owner_changed_cb, - signal_name="NameOwnerChanged", - dbus_interface="org.freedesktop.DBus", - arg0=J_DBUS_SERVICE) - - obj = self._bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH) - journal = dbus.Interface(obj, J_DBUS_INTERFACE) - journal.connect_to_signal('ObjectChooserResponse', - self.__chooser_response_cb) - journal.connect_to_signal('ObjectChooserCancelled', - self.__chooser_cancelled_cb) - self._chooser_id = journal.ChooseObject(self._parent_xid) - - gtk.gdk.threads_leave() - try: - self._main_loop.run() - finally: - gtk.gdk.threads_enter() - self._main_loop = None - - return self._response_code - - def get_selected_object(self): - if self._object_id is None: - return None - else: - return datastore.get(self._object_id) - - def destroy(self): - self._cleanup() - - def _cleanup(self): - if self._main_loop is not None: - self._main_loop.quit() - self._main_loop = None - self._bus = None - - def __chooser_response_cb(self, chooser_id, object_id): - if chooser_id != self._chooser_id: - return - logging.debug('ObjectChooser.__chooser_response_cb: %r' % object_id) - self._response_code = gtk.RESPONSE_ACCEPT - self._object_id = object_id - self._cleanup() - - def __chooser_cancelled_cb(self, chooser_id): - if chooser_id != self._chooser_id: - return - logging.debug('ObjectChooser.__chooser_cancelled_cb: %r' % chooser_id) - self._response_code = gtk.RESPONSE_CANCEL - self._cleanup() - - def __name_owner_changed_cb(self, name, old, new): - logging.debug('ObjectChooser.__name_owner_changed_cb') - # Journal service disappeared from the bus - self._response_code = gtk.RESPONSE_CANCEL - self._cleanup() - diff --git a/sugar/graphics/palette.py b/sugar/graphics/palette.py deleted file mode 100644 index 19a7249..0000000 --- a/sugar/graphics/palette.py +++ /dev/null @@ -1,1000 +0,0 @@ -# Copyright (C) 2007, Eduardo Silva <edsiper@gmail.com> -# Copyright (C) 2008, 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 logging - -import gtk -import gobject -import hippo -import pango - -from sugar.graphics import palettegroup -from sugar.graphics import animator -from sugar.graphics import style -from sugar.graphics.icon import Icon -from sugar import _sugarext - -# Helper function to find the gap position and size of widget a -def _calculate_gap(a, b): - # Test for each side if the palette and invoker are - # adjacent to each other. - gap = True - - if a.y + a.height == b.y: - gap_side = gtk.POS_BOTTOM - elif a.x + a.width == b.x: - gap_side = gtk.POS_RIGHT - elif a.x == b.x + b.width: - gap_side = gtk.POS_LEFT - elif a.y == b.y + b.height: - gap_side = gtk.POS_TOP - else: - gap = False - - if gap: - if gap_side == gtk.POS_BOTTOM or gap_side == gtk.POS_TOP: - gap_start = min(a.width, max(0, b.x - a.x)) - gap_size = max(0, min(a.width, - (b.x + b.width) - a.x) - gap_start) - elif gap_side == gtk.POS_RIGHT or gap_side == gtk.POS_LEFT: - gap_start = min(a.height, max(0, b.y - a.y)) - gap_size = max(0, min(a.height, - (b.y + b.height) - a.y) - gap_start) - - if gap and gap_size > 0: - return (gap_side, gap_start, gap_size) - else: - return False - -class MouseSpeedDetector(gobject.GObject): - - __gsignals__ = { - 'motion-slow': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), - 'motion-fast': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), - } - - _MOTION_SLOW = 1 - _MOTION_FAST = 2 - - def __init__(self, parent, delay, thresh): - """Create MouseSpeedDetector object, - delay in msec - threshold in pixels (per tick of 'delay' msec)""" - - gobject.GObject.__init__(self) - - self._threshold = thresh - self._parent = parent - self._delay = delay - self._state = None - self._timeout_hid = None - self._mouse_pos = None - - def start(self): - self._state = None - self._mouse_pos = self._get_mouse_position() - - self._timeout_hid = gobject.timeout_add(self._delay, self._timer_cb) - - def stop(self): - if self._timeout_hid is not None: - gobject.source_remove(self._timeout_hid) - self._state = None - - def _get_mouse_position(self): - display = gtk.gdk.display_get_default() - screen_, x, y, mask_ = display.get_pointer() - return (x, y) - - def _detect_motion(self): - oldx, oldy = self._mouse_pos - (x, y) = self._get_mouse_position() - self._mouse_pos = (x, y) - - dist2 = (oldx - x)**2 + (oldy - y)**2 - if dist2 > self._threshold**2: - return True - else: - return False - - def _timer_cb(self): - motion = self._detect_motion() - if motion and self._state != self._MOTION_FAST: - self.emit('motion-fast') - self._state = self._MOTION_FAST - elif not motion and self._state != self._MOTION_SLOW: - self.emit('motion-slow') - self._state = self._MOTION_SLOW - - return True - -class Palette(gtk.Window): - PRIMARY = 0 - SECONDARY = 1 - - __gtype_name__ = 'SugarPalette' - - __gproperties__ = { - 'invoker' : (object, None, None, - gobject.PARAM_READWRITE), - 'primary-text' : (str, None, None, None, - gobject.PARAM_READWRITE), - 'secondary-text' : (str, None, None, None, - gobject.PARAM_READWRITE), - 'icon' : (object, None, None, - gobject.PARAM_READWRITE), - 'icon-visible' : (bool, None, None, True, - gobject.PARAM_READWRITE), - 'group-id' : (str, None, None, None, - gobject.PARAM_READWRITE) - } - - __gsignals__ = { - 'popup' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), - 'popdown' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])) - } - - # 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, - text_maxlen=0, **kwargs): - - self.palette_state = self.PRIMARY - - self._primary_text = None - self._secondary_text = None - self._icon = None - self._icon_visible = True - self._group_id = None - - palette_box = gtk.VBox() - - primary_box = gtk.HBox() - palette_box.pack_start(primary_box, expand=False) - primary_box.show() - - self._icon_box = gtk.HBox() - self._icon_box.set_size_request(style.zoom(style.GRID_CELL_SIZE), -1) - primary_box.pack_start(self._icon_box, expand=False) - - labels_box = gtk.VBox() - self._label_alignment = gtk.Alignment(xalign=0, yalign=0.5, - xscale=1, yscale=0.33) - self._label_alignment.set_padding(0, 0, style.DEFAULT_SPACING, - style.DEFAULT_SPACING) - self._label_alignment.add(labels_box) - self._label_alignment.show() - primary_box.pack_start(self._label_alignment, expand=True) - labels_box.show() - - self._label = gtk.AccelLabel('') - self._label.set_alignment(0, 0.5) - - if text_maxlen > 0: - self._label.set_max_width_chars(text_maxlen) - self._label.set_ellipsize(pango.ELLIPSIZE_MIDDLE) - labels_box.pack_start(self._label, expand=True) - - self._secondary_label = gtk.Label() - self._secondary_label.set_alignment(0, 0.5) - - if text_maxlen > 0: - self._secondary_label.set_max_width_chars(text_maxlen) - self._secondary_label.set_ellipsize(pango.ELLIPSIZE_MIDDLE) - - labels_box.pack_start(self._secondary_label, expand=True) - - self._secondary_box = gtk.VBox() - palette_box.pack_start(self._secondary_box) - - self._separator = gtk.HSeparator() - self._secondary_box.pack_start(self._separator) - - self._menu_content_separator = gtk.HSeparator() - - self._popup_anim = animator.Animator(0.3, 10) - self._popup_anim.add(_PopupAnimation(self)) - - self._secondary_anim = animator.Animator(1.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) - - primary_box.set_size_request(-1, style.zoom(style.GRID_CELL_SIZE) - - 2 * self.get_border_width()) - - self.connect('realize', self._realize_cb) - self.connect('destroy', self.__destroy_cb) - self.connect('map-event', self.__map_event_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._palette_popup_sid = None - self._enter_invoker_hid = None - self._leave_invoker_hid = None - - # we set these for backward compatibility - if label is not None: - self.props.primary_text = label - - self._add_menu() - self._secondary_box.pack_start(self._menu_content_separator) - self._add_content() - - self.action_bar = PaletteActionBar() - self._secondary_box.pack_start(self.action_bar) - self.action_bar.show() - - self.add(palette_box) - palette_box.show() - - # The menu is not shown here until an item is added - self.menu = _Menu(self) - - 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) - - if self._palette_popup_sid is not None: - _palette_observer.disconnect(self._palette_popup_sid) - - def _add_menu(self): - self._menu_box = gtk.VBox() - self._secondary_box.pack_start(self._menu_box) - self._menu_box.show() - - def _add_content(self): - # The content is not shown until a widget is added - self._content = gtk.VBox() - 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): - if self._invoker is not None: - self._invoker.disconnect(self._enter_invoker_hid) - self._invoker.disconnect(self._leave_invoker_hid) - - self._invoker = invoker - if invoker is not None: - self._enter_invoker_hid = self._invoker.connect( - 'mouse-enter', self._invoker_mouse_enter_cb) - self._leave_invoker_hid = self._invoker.connect( - 'mouse-leave', self._invoker_mouse_leave_cb) - if hasattr(invoker.props, 'widget'): - self._label.props.accel_widget = invoker.props.widget - - def set_primary_text(self, label, accel_path=None): - self._primary_text = label - - if label is not None: - self._label.set_markup('<b>%s</b>' % label) - self._label.show() - - def _set_secondary_text(self, label): - self._secondary_text = label - - if label is None: - self._secondary_label.hide() - else: - self._secondary_label.set_text(label) - self._secondary_label.show() - - def _show_icon(self): - self._label_alignment.set_padding(0, 0, 0, style.DEFAULT_SPACING) - self._icon_box.show() - - def _hide_icon(self): - self._icon_box.hide() - self._label_alignment.set_padding(0, 0, style.DEFAULT_SPACING, - style.DEFAULT_SPACING) - - def _set_icon(self, icon): - if icon is None: - self._icon = None - self._hide_icon() - else: - if self._icon: - self._icon_box.remove(self._icon) - - self._icon = icon - self._icon.props.icon_size = gtk.ICON_SIZE_LARGE_TOOLBAR - self._icon_box.pack_start(self._icon) - self._icon.show() - self._show_icon() - - def _set_icon_visible(self, visible): - self._icon_visible = visible - - if visible and self._icon is not None: - self._show_icon() - else: - self._hide_icon() - - def set_content(self, widget): - if len(self._content.get_children()) > 0: - self._content.remove(self._content.get_children()[0]) - - if widget is not None: - self._content.add(widget) - self._content.show() - else: - self._content.hide() - - 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 do_set_property(self, pspec, value): - if pspec.name == 'invoker': - self._set_invoker(value) - elif pspec.name == 'primary-text': - self.set_primary_text(value, None) - elif pspec.name == 'secondary-text': - self._set_secondary_text(value) - elif pspec.name == 'icon': - self._set_icon(value) - elif pspec.name == 'icon-visible': - self._set_icon_visible(value) - elif pspec.name == 'group-id': - self.set_group_id(value) - else: - raise AssertionError - - def do_get_property(self, pspec): - if pspec.name == 'invoker': - return self._invoker - elif pspec.name == 'primary-text': - return self._primary_text - elif pspec.name == 'secondary-text': - return self._secondary_text - elif pspec.name == 'icon': - return self._icon - elif pspec.name == 'icon-visible': - return self._icon_visible - elif pspec.name == 'group-id': - return self._group_id - else: - raise AssertionError - - def do_size_request(self, requisition): - gtk.Window.do_size_request(self, requisition) - - # gtk.AccelLabel request doesn't include the accelerator. - label_width = self._label_alignment.size_request()[0] + \ - self._label.get_accel_width() + \ - 2 * self.get_border_width() - - requisition.width = max(requisition.width, - style.zoom(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 - self._separator.props.visible = visible - - visible = len(self.menu.get_children()) > 0 and \ - len(self._content.get_children()) > 0 - self._menu_content_separator.props.visible = visible - - def _update_accept_focus(self): - accept_focus = len(self._content.get_children()) - if self.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): - state = self.palette_state - - self._set_state(self.SECONDARY) - self._full_request = self.size_request() - - self._set_state(state) - - 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 _show(self): - if self._up: - return - - self._palette_popup_sid = _palette_observer.connect( - 'popup', self._palette_observer_popup_cb) - - 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.menu.set_active(True) - self.show() - - def _hide(self): - self._secondary_anim.stop() - - if not self._palette_popup_sid is None: - _palette_observer.disconnect(self._palette_popup_sid) - self._palette_popup_sid = None - - self.menu.set_active(False) - self.hide() - - if self._invoker: - self._invoker.notify_popdown() - - self._up = False - self.emit('popdown') - - def popup(self, immediate=False): - self._popdown_anim.stop() - - if not immediate: - self._popup_anim.start() - else: - self._show() - - self._secondary_anim.start() - - def popdown(self, immediate=False): - 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 - - if state == self.PRIMARY: - self.menu.unembed() - self._secondary_box.hide() - elif state == self.SECONDARY: - self.menu.embed(self._menu_box) - self._secondary_box.show() - - self.palette_state = state - - def _invoker_mouse_enter_cb(self, invoker): - self._mouse_detector.start() - - 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(): - self._set_state(self.PRIMARY) - - immediate = True - group.popdown() - - self.popup(immediate=immediate) - - def _invoker_mouse_leave_cb(self, invoker): - self._mouse_detector.stop() - self.popdown() - - def _enter_notify_event_cb(self, widget, event): - if event.detail != gtk.gdk.NOTIFY_INFERIOR: - self._popdown_anim.stop() - self._secondary_anim.start() - - def _leave_notify_event_cb(self, widget, event): - if event.detail != gtk.gdk.NOTIFY_INFERIOR: - self.popdown() - - def _palette_observer_popup_cb(self, observer, palette): - if self != palette: - self._hide() - - def __map_event_cb(self, widget, event): - self._invoker.notify_popup() - - self._up = True - _palette_observer.emit('popup', self) - self.emit('popup') - -class PaletteActionBar(gtk.HButtonBox): - def add_action(self, label, icon_name=None): - button = gtk.Button(label) - - if icon_name: - icon = Icon(icon_name) - button.set_image(icon) - icon.show() - - self.pack_start(button) - button.show() - -class _Menu(_sugarext.Menu): - __gtype_name__ = 'SugarPaletteMenu' - - def __init__(self, palette): - _sugarext.Menu.__init__(self) - self._palette = palette - - def do_insert(self, item, position): - _sugarext.Menu.do_insert(self, item, position) - self._palette._update_separators() - self.show() - - def do_expose_event(self, event): - # Ignore the Menu expose, just do the MenuShell expose to prevent any - # border from being drawn here. A border is drawn by the palette object - # around everything. - gtk.MenuShell.do_expose_event(self, event) - - def do_grab_notify(self, was_grabbed): - # Ignore grab_notify as the menu would close otherwise - pass - - def do_deactivate(self): - self._palette._hide() - -class _PopupAnimation(animator.Animation): - def __init__(self, palette): - animator.Animation.__init__(self, 0.0, 1.0) - self._palette = palette - - def next_frame(self, current): - if current == 1.0: - self._palette._set_state(Palette.PRIMARY) - self._palette._show() - -class _SecondaryAnimation(animator.Animation): - def __init__(self, palette): - animator.Animation.__init__(self, 0.0, 1.0) - self._palette = palette - - def next_frame(self, current): - if current == 1.0: - self._palette._set_state(Palette.SECONDARY) - self._palette._update_position() - -class _PopdownAnimation(animator.Animation): - def __init__(self, palette): - animator.Animation.__init__(self, 0.0, 1.0) - self._palette = palette - - def next_frame(self, current): - if current == 1.0: - self._palette._hide() - -class Invoker(gobject.GObject): - __gtype_name__ = 'SugarPaletteInvoker' - - __gsignals__ = { - 'mouse-enter': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), - 'mouse-leave': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), - 'focus-out': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])) - } - - ANCHORED = 0 - AT_CURSOR = 1 - - BOTTOM = [(0.0, 0.0, 0.0, 1.0), - (-1.0, 0.0, 1.0, 1.0)] - RIGHT = [(0.0, 0.0, 1.0, 0.0), - (0.0, -1.0, 1.0, 1.0)] - TOP = [(0.0, -1.0, 0.0, 0.0), - (-1.0, -1.0, 1.0, 0.0)] - LEFT = [(-1.0, 0.0, 0.0, 0.0), - (-1.0, -1.0, 0.0, 1.0)] - - def __init__(self): - gobject.GObject.__init__(self) - - self._screen_area = gtk.gdk.Rectangle(0, 0, gtk.gdk.screen_width(), - gtk.gdk.screen_height()) - self._position_hint = self.ANCHORED - self._cursor_x = -1 - self._cursor_y = -1 - - def _get_position_for_alignment(self, alignment, palette_dim): - palette_halign = alignment[0] - palette_valign = alignment[1] - invoker_halign = alignment[2] - invoker_valign = alignment[3] - - if self._cursor_x == -1 or self._cursor_y == -1: - display = gtk.gdk.display_get_default() - screen_, x, y, mask_ = display.get_pointer() - self._cursor_x = x - self._cursor_y = y - - if self._position_hint is self.ANCHORED: - rect = self.get_rect() - else: - dist = style.PALETTE_CURSOR_DISTANCE - rect = gtk.gdk.Rectangle(self._cursor_x - dist, - self._cursor_y - dist, - dist * 2, dist * 2) - - palette_width, palette_height = palette_dim - - x = rect.x + rect.width * invoker_halign + \ - palette_width * palette_halign - - y = rect.y + rect.height * invoker_valign + \ - palette_height * palette_valign - - return gtk.gdk.Rectangle(int(x), int(y), - palette_width, palette_height) - - def _in_screen(self, rect): - return rect.x >= self._screen_area.x and \ - rect.y >= self._screen_area.y and \ - rect.x + rect.width <= self._screen_area.width and \ - rect.y + rect.height <= self._screen_area.height - - def _get_area_in_screen(self, rect): - """Return area of rectangle visible in the screen""" - - x1 = max(rect.x, self._screen_area.x) - y1 = max(rect.y, self._screen_area.y) - x2 = min(rect.x + rect.width, - self._screen_area.x + self._screen_area.width) - y2 = min(rect.y + rect.height, - self._screen_area.y + self._screen_area.height) - - return (x2 - x1) * (y2 - y1) - - def _get_alignments(self): - if self._position_hint is self.AT_CURSOR: - return [(0.0, 0.0, 1.0, 1.0), - (0.0, -1.0, 1.0, 0.0), - (-1.0, -1.0, 0.0, 0.0), - (-1.0, 0.0, 0.0, 1.0)] - else: - return self.BOTTOM + self.RIGHT + self.TOP + self.LEFT - - def get_position_for_alignment(self, alignment, palette_dim): - rect = self._get_position_for_alignment(alignment, palette_dim) - if self._in_screen(rect): - return rect - else: - return None - - def get_position(self, palette_dim): - alignment = self.get_alignment(palette_dim) - return self._get_position_for_alignment(alignment, palette_dim) - - def get_alignment(self, palette_dim): - best_alignment = None - best_area = -1 - for alignment in self._get_alignments(): - pos = self._get_position_for_alignment(alignment, palette_dim) - if self._in_screen(pos): - return alignment - - area = self._get_area_in_screen(pos) - if area > best_area: - best_alignment = alignment - best_area = area - - # Palette horiz/vert alignment - ph = best_alignment[0] - pv = best_alignment[1] - - # Invoker horiz/vert alignment - ih = best_alignment[2] - iv = best_alignment[3] - - rect = self.get_rect() - screen_area = self._screen_area - - if best_alignment in self.LEFT or best_alignment in self.RIGHT: - dtop = rect.y - screen_area.y - dbottom = screen_area.y + screen_area.height - rect.y - rect.width - - iv = 0 - - # Set palette_valign to align to screen on the top - if dtop > dbottom: - pv = -float(dtop) / palette_dim[1] - - # Set palette_valign to align to screen on the bottom - else: - pv = -float(palette_dim[1] - dbottom - rect.height) \ - / palette_dim[1] - - else: - dleft = rect.x - screen_area.x - dright = screen_area.x + screen_area.width - rect.x - rect.width - - ih = 0 - - # Set palette_halign to align to screen on left - if dleft > dright: - ph = -float(dleft) / palette_dim[0] - - # Set palette_halign to align to screen on right - else: - ph = -float(palette_dim[0] - dright - rect.width) \ - / palette_dim[0] - - return (ph, pv, ih, iv) - - def has_rectangle_gap(self): - return False - - def draw_rectangle(self, event, palette): - pass - - def notify_popup(self): - pass - - def notify_popdown(self): - self._cursor_x = -1 - self._cursor_y = -1 - -class WidgetInvoker(Invoker): - def __init__(self, widget): - Invoker.__init__(self) - self._widget = widget - - widget.connect('enter-notify-event', self._enter_notify_event_cb) - widget.connect('leave-notify-event', self._leave_notify_event_cb) - - def get_rect(self): - allocation = self._widget.get_allocation() - if self._widget.window is not None: - x, y = self._widget.window.get_origin() - else: - logging.warning( - "Trying to position palette with invoker that's not realized.") - x = 0 - y = 0 - - if self._widget.flags() & gtk.NO_WINDOW: - x += allocation.x - y += allocation.y - - width = allocation.width - height = allocation.height - - return gtk.gdk.Rectangle(x, y, width, height) - - def has_rectangle_gap(self): - return True - - def draw_rectangle(self, event, palette): - wstyle = self._widget.get_style() - gap = _calculate_gap(self.get_rect(), palette.get_rect()) - if gap: - wstyle.paint_box_gap(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_IN, event.area, self._widget, - "palette-invoker", - self._widget.allocation.x, - self._widget.allocation.y, - self._widget.allocation.width, - self._widget.allocation.height, - gap[0], gap[1], gap[2]) - else: - wstyle.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_IN, event.area, self._widget, - "palette-invoker", - self._widget.allocation.x, - self._widget.allocation.y, - self._widget.allocation.width, - self._widget.allocation.height) - - def _enter_notify_event_cb(self, widget, event): - self.emit('mouse-enter') - - def _leave_notify_event_cb(self, widget, event): - self.emit('mouse-leave') - - def get_toplevel(self): - return self._widget.get_toplevel() - - def notify_popup(self): - Invoker.notify_popup(self) - self._widget.queue_draw() - - def notify_popdown(self): - Invoker.notify_popdown(self) - self._widget.queue_draw() - - def _get_widget(self): - return self._widget - widget = gobject.property(type=object, getter=_get_widget, setter=None) - -class CanvasInvoker(Invoker): - def __init__(self, item): - Invoker.__init__(self) - - self._item = item - self._position_hint = self.AT_CURSOR - - item.connect('motion-notify-event', - self._motion_notify_event_cb) - - def get_default_position(self): - return self.AT_CURSOR - - def get_rect(self): - context = self._item.get_context() - if context: - x, y = context.translate_to_screen(self._item) - width, height = self._item.get_allocation() - return gtk.gdk.Rectangle(x, y, width, height) - else: - return gtk.gdk.Rectangle() - - def _motion_notify_event_cb(self, button, event): - if event.detail == hippo.MOTION_DETAIL_ENTER: - self.emit('mouse-enter') - elif event.detail == hippo.MOTION_DETAIL_LEAVE: - self.emit('mouse-leave') - - return False - - def get_toplevel(self): - return hippo.get_canvas_for_item(self._item).get_toplevel() - -class ToolInvoker(WidgetInvoker): - def __init__(self, widget): - WidgetInvoker.__init__(self, widget.child) - - def _get_alignments(self): - parent = self._widget.get_parent() - if parent is None: - return WidgetInvoker.get_alignments() - - if parent.get_orientation() is gtk.ORIENTATION_HORIZONTAL: - return self.BOTTOM + self.TOP - else: - return self.LEFT + self.RIGHT - -class _PaletteObserver(gobject.GObject): - __gtype_name__ = 'SugarPaletteObserver' - - __gsignals__ = { - 'popup': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])) - } - - def __init__(self): - gobject.GObject.__init__(self) - -_palette_observer = _PaletteObserver() diff --git a/sugar/graphics/palettegroup.py b/sugar/graphics/palettegroup.py deleted file mode 100644 index bdae76b..0000000 --- a/sugar/graphics/palettegroup.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (C) 2007 Red Hat, Inc. -# -# 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 gobject - -_groups = {} - -def get_group(group_id): - if _groups.has_key(group_id): - group = _groups[group_id] - else: - group = Group() - _groups[group_id] = group - - return group - -class Group(gobject.GObject): - __gsignals__ = { - 'popup' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), - 'popdown' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])) - } - def __init__(self): - gobject.GObject.__init__(self) - self._up = False - self._palettes = [] - self._sig_ids = {} - - def is_up(self): - return self._up - - def get_state(self): - for palette in self._palettes: - if palette.is_up(): - return palette.palette_state - - return None - - def add(self, palette): - self._palettes.append(palette) - - self._sig_ids[palette] = [] - - sid = palette.connect('popup', self._palette_popup_cb) - self._sig_ids[palette].append(sid) - - sid = palette.connect('popdown', self._palette_popdown_cb) - self._sig_ids[palette].append(sid) - - def remove(self, palette): - sig_ids = self._sig_ids[palette] - for sid in sig_ids: - palette.disconnect(sid) - - self._palettes.remove(palette) - del self._sig_ids[palette] - - def popdown(self): - for palette in self._palettes: - if palette.is_up(): - palette.popdown(immediate=True) - - def _palette_popup_cb(self, palette): - if not self._up: - self.emit('popup') - self._up = True - - def _palette_popdown_cb(self, palette): - down = True - for palette in self._palettes: - if palette.is_up(): - down = False - - if down: - self._up = False - self.emit('popdown') diff --git a/sugar/graphics/panel.py b/sugar/graphics/panel.py deleted file mode 100644 index bf3ed24..0000000 --- a/sugar/graphics/panel.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# 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 - -class Panel(gtk.VBox): - __gtype_name__ = 'SugarPanel' - def __init__(self): - gtk.VBox.__init__(self) diff --git a/sugar/graphics/radiotoolbutton.py b/sugar/graphics/radiotoolbutton.py deleted file mode 100644 index 3fc815b..0000000 --- a/sugar/graphics/radiotoolbutton.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# Copyright (C) 2007-2008, 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 gtk -import gobject - -from sugar.graphics.icon import Icon -from sugar.graphics.palette import Palette, ToolInvoker -from sugar.graphics import toolbutton - -class RadioToolButton(gtk.RadioToolButton): - __gtype_name__ = "SugarRadioToolButton" - - def __init__(self, named_icon=None, group=None, xo_color=None, **kwargs): - self._accelerator = None - self._tooltip = None - self._palette = None - self._xo_color = xo_color - - gobject.GObject.__init__(self, **kwargs) - - if named_icon: - self.set_named_icon(named_icon) - if group: - self.props.group = group - - def set_tooltip(self, tooltip): - """ Set a simple palette with just a single label. - """ - if self.palette is None or self._tooltip is None: - self.palette = Palette(tooltip) - elif self.palette is not None: - self.palette.set_primary_text(tooltip) - - self._tooltip = tooltip - - # Set label, shows up when toolbar overflows - gtk.RadioToolButton.set_label(self, tooltip) - - def get_tooltip(self): - return self._tooltip - - tooltip = gobject.property(type=str, setter=set_tooltip, getter=get_tooltip) - - def set_accelerator(self, accelerator): - self._accelerator = accelerator - toolbutton.setup_accelerator(self) - - def get_accelerator(self): - return self._accelerator - - accelerator = gobject.property(type=str, setter=set_accelerator, - getter=get_accelerator) - - def set_named_icon(self, named_icon): - icon = Icon(icon_name=named_icon, - xo_color=self._xo_color, - icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) - self.set_icon_widget(icon) - icon.show() - - def get_palette(self): - return self._palette - - def set_palette(self, palette): - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - self._palette.props.invoker = ToolInvoker(self) - - palette = gobject.property( - type=object, setter=set_palette, getter=get_palette) - - def do_expose_event(self, event): - child = self.get_child() - allocation = self.get_allocation() - - if self._palette and self._palette.is_up(): - invoker = self._palette.props.invoker - invoker.draw_rectangle(event, self._palette) - elif child.state == gtk.STATE_PRELIGHT: - child.style.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_NONE, event.area, - child, "toolbutton-prelight", - allocation.x, allocation.y, - allocation.width, allocation.height) - - gtk.RadioToolButton.do_expose_event(self, event) - diff --git a/sugar/graphics/roundbox.py b/sugar/graphics/roundbox.py deleted file mode 100644 index 573344e..0000000 --- a/sugar/graphics/roundbox.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# 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 math - -import hippo - -from sugar.graphics import style - -class CanvasRoundBox(hippo.CanvasBox, hippo.CanvasItem): - __gtype_name__ = 'SugarRoundBox' - - _BORDER_DEFAULT = style.LINE_WIDTH - - def __init__(self, **kwargs): - hippo.CanvasBox.__init__(self, **kwargs) - - # TODO: we should calculate radius depending on the height of the box. - self._radius = style.zoom(10) - - self.props.orientation = hippo.ORIENTATION_HORIZONTAL - self.props.border = self._BORDER_DEFAULT - self.props.border_left = self._radius - self.props.border_right = self._radius - self.props.border_color = style.COLOR_BLACK.get_int() - - def do_paint_background(self, cr, damaged_box): - [width, height] = self.get_allocation() - - x = self._BORDER_DEFAULT / 2 - y = self._BORDER_DEFAULT / 2 - width -= self._BORDER_DEFAULT - height -= self._BORDER_DEFAULT - - cr.move_to(x + self._radius, y) - cr.arc(x + width - self._radius, y + self._radius, - self._radius, math.pi * 1.5, math.pi * 2) - cr.arc(x + width - self._radius, x + height - self._radius, - self._radius, 0, math.pi * 0.5) - cr.arc(x + self._radius, y + height - self._radius, - self._radius, math.pi * 0.5, math.pi) - cr.arc(x + self._radius, y + self._radius, self._radius, - math.pi, math.pi * 1.5) - - hippo.cairo_set_source_rgba32(cr, self.props.background_color) - cr.fill_preserve() - - # TODO: we should be more consistent here with the border properties. - if self.props.border_color: - hippo.cairo_set_source_rgba32(cr, self.props.border_color) - cr.set_line_width(self.props.border_top) - cr.stroke() diff --git a/sugar/graphics/style.py b/sugar/graphics/style.py deleted file mode 100644 index 1b510d1..0000000 --- a/sugar/graphics/style.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# 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. - -""" -All the constants are expressed in pixels. They are defined for the XO screen -and are usually adapted to different resolution by applying a zoom factor. The -factor for traditional 96 dpi screen is currently 0.72 which is the inverse -of the one we are using to adapt web pages to the XO screen. It should be -considered a reference value rather then a scale constant which has to be -automatically applied and always respected. -""" - -import os - -import gtk -import pango - -_XO_DPI = 200.0 - -_FOCUS_LINE_WIDTH = 2 -_TAB_CURVATURE = 1 - -def _get_screen_dpi(): - xft_dpi = gtk.settings_get_default().get_property('gtk-xft-dpi') - return float(xft_dpi / 1024) - -def _compute_zoom_factor(): - if _get_screen_dpi() == 96.0: - if not os.environ.has_key('SUGAR_XO_STYLE') or \ - not os.environ['SUGAR_XO_STYLE'] == 'yes': - return 0.72 - - return 1.0 - -def _compute_font_height(font): - widget = gtk.Label('') - - context = widget.get_pango_context() - pango_font = context.load_font(font.get_pango_desc()) - metrics = pango_font.get_metrics() - - return pango.PIXELS(metrics.get_ascent() + metrics.get_descent()) - -class Font(object): - def __init__(self, desc): - self._desc = desc - - def __str__(self): - return self._desc - - def get_pango_desc(self): - return pango.FontDescription(self._desc) - -class Color(object): - def __init__(self, color, alpha=1.0): - self._r, self._g, self._b = self._html_to_rgb(color) - self._a = alpha - - def get_rgba(self): - return (self._r, self._g, self._b, self._a) - - def get_int(self): - return int(self._a * 255) + (int(self._b * 255) << 8) + \ - (int(self._g * 255) << 16) + (int(self._r * 255) << 24) - - def get_gdk_color(self): - return gtk.gdk.Color(int(self._r * 65535), int(self._g * 65535), - int(self._b * 65535)) - - def get_html(self): - return '#%02x%02x%02x' % (self._r * 255, self._g * 255, self._b * 255) - - def _html_to_rgb(self, html_color): - """ #RRGGBB -> (r, g, b) tuple (in float format) """ - - html_color = html_color.strip() - if html_color[0] == '#': - html_color = html_color[1:] - if len(html_color) != 6: - raise ValueError, "input #%s is not in #RRGGBB format" % html_color - - r, g, b = html_color[:2], html_color[2:4], html_color[4:] - r, g, b = [int(n, 16) for n in (r, g, b)] - r, g, b = (r / 255.0, g / 255.0, b / 255.0) - - return (r, g, b) - - def get_svg(self): - if self._a == 0.0: - return 'none' - else: - return self.get_html() - -def zoom(units): - return int(ZOOM_FACTOR * units) - -ZOOM_FACTOR = _compute_zoom_factor() - -DEFAULT_SPACING = zoom(15) -DEFAULT_PADDING = zoom(6) -GRID_CELL_SIZE = zoom(75) -LINE_WIDTH = zoom(2) - -STANDARD_ICON_SIZE = zoom(55) -SMALL_ICON_SIZE = zoom(55 * 0.5) -MEDIUM_ICON_SIZE = zoom(55 * 1.5) -LARGE_ICON_SIZE = zoom(55 * 2.0) -XLARGE_ICON_SIZE = zoom(55 * 2.75) - -FONT_SIZE = zoom(7 * _XO_DPI / _get_screen_dpi()) -FONT_NORMAL = Font('Bitstream Vera Sans %d' % FONT_SIZE) -FONT_BOLD = Font('Bitstream Vera Sans bold %d' % FONT_SIZE) -FONT_NORMAL_H = _compute_font_height(FONT_NORMAL) -FONT_BOLD_H = _compute_font_height(FONT_BOLD) - -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_LABEL_WIDTH = zoom(150 - 15 * 2) - -COLOR_BLACK = Color('#000000') -COLOR_WHITE = Color('#FFFFFF') -COLOR_TRANSPARENT = Color('#FFFFFF', alpha=0.0) -COLOR_PANEL_GREY = Color('#C0C0C0') -COLOR_SELECTION_GREY = Color('#A6A6A6') -COLOR_TOOLBAR_GREY = Color('#282828') -COLOR_BUTTON_GREY = Color('#808080') -COLOR_INACTIVE_FILL = Color('#9D9FA1') -COLOR_INACTIVE_STROKE = Color('#757575') -COLOR_TEXT_FIELD_GREY = Color('#E5E5E5') - -PALETTE_CURSOR_DISTANCE = zoom(10) diff --git a/sugar/graphics/toggletoolbutton.py b/sugar/graphics/toggletoolbutton.py deleted file mode 100644 index 4c59f80..0000000 --- a/sugar/graphics/toggletoolbutton.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# 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 - -from sugar.graphics.icon import Icon -from sugar.graphics.palette import Palette, ToolInvoker - -class ToggleToolButton(gtk.ToggleToolButton): - __gtype_name__ = "SugarToggleToolButton" - - def __init__(self, named_icon=None): - gtk.ToggleToolButton.__init__(self) - self._palette = None - self.set_named_icon(named_icon) - - def set_named_icon(self, named_icon): - icon = Icon(icon_name=named_icon) - self.set_icon_widget(icon) - icon.show() - - def get_palette(self): - return self._palette - - def set_palette(self, palette): - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - self._palette.props.invoker = ToolInvoker(self) - - def set_tooltip(self, text): - self.set_palette(Palette(text)) - - def do_expose_event(self, event): - allocation = self.get_allocation() - child = self.get_child() - - if self._palette and self._palette.is_up(): - invoker = self._palette.props.invoker - invoker.draw_rectangle(event, self._palette) - elif child.state == gtk.STATE_PRELIGHT: - child.style.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_NONE, event.area, - child, "toolbutton-prelight", - allocation.x, allocation.y, - allocation.width, allocation.height) - - gtk.ToggleToolButton.do_expose_event(self, event) - - palette = property(get_palette, set_palette) diff --git a/sugar/graphics/toolbox.py b/sugar/graphics/toolbox.py deleted file mode 100644 index f0889be..0000000 --- a/sugar/graphics/toolbox.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# 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 hippo - -from sugar.graphics import style - -class Toolbox(gtk.VBox): - __gtype_name__ = 'SugarToolbox' - - __gsignals__ = { - 'current-toolbar-changed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([int])) - } - - def __init__(self): - gtk.VBox.__init__(self) - - self._notebook = gtk.Notebook() - self._notebook.set_tab_pos(gtk.POS_BOTTOM) - self._notebook.set_show_border(False) - self._notebook.set_show_tabs(False) - self._notebook.props.tab_vborder = style.TOOLBOX_TAB_VBORDER - self._notebook.props.tab_hborder = style.TOOLBOX_TAB_HBORDER - self.pack_start(self._notebook) - self._notebook.show() - - # FIXME improve gtk.Notebook and do this in the theme - self._separator = hippo.Canvas() - box = hippo.CanvasBox( - border_color=style.COLOR_BUTTON_GREY.get_int(), - background_color=style.COLOR_PANEL_GREY.get_int(), - box_height=style.TOOLBOX_SEPARATOR_HEIGHT, - border_bottom=style.LINE_WIDTH) - self._separator.set_root(box) - self.pack_start(self._separator, False) - - self._notebook.connect('notify::page', self._notify_page_cb) - - def _notify_page_cb(self, notebook, pspec): - self.emit('current-toolbar-changed', notebook.props.page) - - def add_toolbar(self, name, toolbar): - label = gtk.Label(name) - width, height_ = label.size_request() - label.set_size_request(max(width, style.TOOLBOX_TAB_LABEL_WIDTH), -1) - label.set_alignment(0.0, 0.5) - - event_box = gtk.EventBox() - - alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0) - alignment.set_padding(0, 0, style.TOOLBOX_HORIZONTAL_PADDING, - style.TOOLBOX_HORIZONTAL_PADDING) - - alignment.add(toolbar) - event_box.add(alignment) - alignment.show() - event_box.show() - - self._notebook.append_page(event_box, label) - - if self._notebook.get_n_pages() > 1: - self._notebook.set_show_tabs(True) - self._separator.show() - - def remove_toolbar(self, index): - self._notebook.remove_page(index) - - if self._notebook.get_n_pages() < 2: - self._notebook.set_show_tabs(False) - self._separator.hide() - - def set_current_toolbar(self, index): - self._notebook.set_current_page(index) - - def get_current_toolbar(self): - return self._notebook.get_current_page() - - current_toolbar = property(get_current_toolbar, set_current_toolbar) - diff --git a/sugar/graphics/toolbutton.py b/sugar/graphics/toolbutton.py deleted file mode 100644 index 236d7ec..0000000 --- a/sugar/graphics/toolbutton.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# Copyright (C) 2008, 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 logging - -import gtk -import gobject - -from sugar.graphics.icon import Icon -from sugar.graphics.palette import Palette, ToolInvoker - -def _add_accelerator(tool_button): - if not tool_button.props.accelerator or not tool_button.get_toplevel() or \ - not tool_button.child: - return - - # TODO: should we remove the accelerator from the prev top level? - - accel_group = tool_button.get_toplevel().get_data('sugar-accel-group') - if not accel_group: - logging.warning('No gtk.AccelGroup in the top level window.') - return - - keyval, mask = gtk.accelerator_parse(tool_button.props.accelerator) - # the accelerator needs to be set at the child, so the gtk.AccelLabel - # in the palette can pick it up. - tool_button.child.add_accelerator('clicked', accel_group, keyval, mask, - gtk.ACCEL_LOCKED | gtk.ACCEL_VISIBLE) - -def _hierarchy_changed_cb(tool_button, previous_toplevel): - _add_accelerator(tool_button) - -def setup_accelerator(tool_button): - _add_accelerator(tool_button) - tool_button.connect('hierarchy-changed', _hierarchy_changed_cb) - -class ToolButton(gtk.ToolButton): - __gtype_name__ = "SugarToolButton" - - def __init__(self, icon_name=None, **kwargs): - self._accelerator = None - self._tooltip = None - self._palette = None - - gobject.GObject.__init__(self, **kwargs) - - if icon_name: - self.set_icon(icon_name) - - self.connect('clicked', self.__button_clicked_cb) - - def set_tooltip(self, tooltip): - """ Set a simple palette with just a single label. - """ - if self.palette is None or self._tooltip is None: - self.palette = Palette(tooltip) - elif self.palette is not None: - self.palette.set_primary_text(tooltip) - - self._tooltip = tooltip - - # Set label, shows up when toolbar overflows - gtk.ToolButton.set_label(self, tooltip) - - def get_tooltip(self): - return self._tooltip - - tooltip = gobject.property(type=str, setter=set_tooltip, getter=get_tooltip) - - def set_accelerator(self, accelerator): - self._accelerator = accelerator - setup_accelerator(self) - - def get_accelerator(self): - return self._accelerator - - accelerator = gobject.property(type=str, setter=set_accelerator, - getter=get_accelerator) - - def set_icon(self, icon_name): - icon = Icon(icon_name=icon_name) - self.set_icon_widget(icon) - icon.show() - - def get_palette(self): - return self._palette - - def set_palette(self, palette): - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - self._palette.props.invoker = ToolInvoker(self) - - palette = gobject.property( - type=object, setter=set_palette, getter=get_palette) - - def do_expose_event(self, event): - child = self.get_child() - allocation = self.get_allocation() - if self._palette and self._palette.is_up(): - invoker = self._palette.props.invoker - invoker.draw_rectangle(event, self._palette) - elif child.state == gtk.STATE_PRELIGHT: - child.style.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_NONE, event.area, - child, "toolbutton-prelight", - allocation.x, allocation.y, - allocation.width, allocation.height) - - gtk.ToolButton.do_expose_event(self, event) - - def __button_clicked_cb(self, widget): - if self._palette: - self._palette.popdown(True) - diff --git a/sugar/graphics/toolcombobox.py b/sugar/graphics/toolcombobox.py deleted file mode 100644 index 460dcee..0000000 --- a/sugar/graphics/toolcombobox.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# 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 - -from sugar.graphics.combobox import ComboBox -from sugar.graphics import style - -class ToolComboBox(gtk.ToolItem): - __gproperties__ = { - 'label-text' : (str, None, None, None, - gobject.PARAM_WRITABLE), - } - - def __init__(self, combo=None, **kwargs): - self.label = None - self._label_text = '' - - gobject.GObject.__init__(self, **kwargs) - - self.set_border_width(style.DEFAULT_PADDING) - - hbox = gtk.HBox(False, style.DEFAULT_SPACING) - - self.label = gtk.Label(self._label_text) - hbox.pack_start(self.label, False) - self.label.show() - - if combo: - self.combo = combo - else: - self.combo = ComboBox() - - hbox.pack_start(self.combo) - self.combo.show() - - self.add(hbox) - hbox.show() - - def do_set_property(self, pspec, value): - if pspec.name == 'label-text': - self._label_text = value - if self.label: - self.label.set_text(self._label_text) diff --git a/sugar/graphics/tray.py b/sugar/graphics/tray.py deleted file mode 100644 index abc8df3..0000000 --- a/sugar/graphics/tray.py +++ /dev/null @@ -1,308 +0,0 @@ -# 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 gobject -import gtk - -from sugar.graphics import style -from sugar.graphics.palette import Palette, ToolInvoker -from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.icon import Icon - -_PREVIOUS_PAGE = 0 -_NEXT_PAGE = 1 - -class _TrayViewport(gtk.Viewport): - __gproperties__ = { - 'scrollable' : (bool, None, None, False, - gobject.PARAM_READABLE), - 'can-scroll-prev' : (bool, None, None, False, - gobject.PARAM_READABLE), - 'can-scroll-next' : (bool, None, None, False, - gobject.PARAM_READABLE), - } - - def __init__(self, orientation): - self.orientation = orientation - self._scrollable = False - self._can_scroll_next = False - self._can_scroll_prev = False - - gobject.GObject.__init__(self) - - self.set_shadow_type(gtk.SHADOW_NONE) - - self.traybar = gtk.Toolbar() - self.traybar.set_orientation(orientation) - self.traybar.set_show_arrow(False) - self.add(self.traybar) - self.traybar.show() - - self.connect('size_allocate', self._size_allocate_cb) - - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - adj = self.get_hadjustment() - else: - adj = self.get_vadjustment() - adj.connect('changed', self._adjustment_changed_cb) - adj.connect('value-changed', self._adjustment_changed_cb) - - def scroll(self, direction): - if direction == _PREVIOUS_PAGE: - self._scroll_previous() - elif direction == _NEXT_PAGE: - self._scroll_next() - - def _scroll_next(self): - allocation = self.get_allocation() - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - adj = self.get_hadjustment() - new_value = adj.value + allocation.width - adj.value = min(new_value, adj.upper - allocation.width) - else: - adj = self.get_vadjustment() - new_value = adj.value + allocation.height - adj.value = min(new_value, adj.upper - allocation.height) - - def _scroll_previous(self): - allocation = self.get_allocation() - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - adj = self.get_hadjustment() - new_value = adj.value - allocation.width - adj.value = max(adj.lower, new_value) - else: - adj = self.get_vadjustment() - new_value = adj.value - allocation.height - adj.value = max(adj.lower, new_value) - - def do_size_request(self, requisition): - child_requisition = self.get_child().size_request() - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - requisition[0] = 0 - requisition[1] = child_requisition[1] - else: - requisition[0] = child_requisition[0] - requisition[1] = 0 - - def do_get_property(self, pspec): - if pspec.name == 'scrollable': - return self._scrollable - elif pspec.name == 'can-scroll-next': - return self._can_scroll_next - elif pspec.name == 'can-scroll-prev': - return self._can_scroll_prev - - def _size_allocate_cb(self, viewport, allocation): - bar_requisition = self.traybar.get_child_requisition() - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - scrollable = bar_requisition[0] > allocation.width - else: - scrollable = bar_requisition[1] > allocation.height - - if scrollable != self._scrollable: - self._scrollable = scrollable - self.notify('scrollable') - - def _adjustment_changed_cb(self, adjustment): - if adjustment.value <= adjustment.lower: - can_scroll_prev = False - else: - can_scroll_prev = True - - if adjustment.value + adjustment.page_size >= adjustment.upper: - can_scroll_next = False - else: - can_scroll_next = True - - if can_scroll_prev != self._can_scroll_prev: - self._can_scroll_prev = can_scroll_prev - self.notify('can-scroll-prev') - - if can_scroll_next != self._can_scroll_next: - self._can_scroll_next = can_scroll_next - self.notify('can-scroll-next') - - -class _TrayScrollButton(ToolButton): - def __init__(self, icon_name, scroll_direction): - ToolButton.__init__(self) - self._viewport = None - - self._scroll_direction = scroll_direction - - self.set_size_request(style.GRID_CELL_SIZE, style.GRID_CELL_SIZE) - - self.icon = Icon(icon_name = icon_name, - icon_size=gtk.ICON_SIZE_SMALL_TOOLBAR) - # The alignment is a hack to work around gtk.ToolButton code - # that sets the icon_size when the icon_widget is a gtk.Image - alignment = gtk.Alignment(0.5, 0.5) - alignment.add(self.icon) - self.set_icon_widget(alignment) - alignment.show_all() - - self.connect('clicked', self._clicked_cb) - - def set_viewport(self, viewport): - self._viewport = viewport - self._viewport.connect('notify::scrollable', - self._viewport_scrollable_changed_cb) - - if self._scroll_direction == _PREVIOUS_PAGE: - self._viewport.connect('notify::can-scroll-prev', - self._viewport_can_scroll_dir_changed_cb) - self.set_sensitive(self._viewport.props.can_scroll_prev) - else: - self._viewport.connect('notify::can-scroll-next', - self._viewport_can_scroll_dir_changed_cb) - self.set_sensitive(self._viewport.props.can_scroll_next) - - - def _viewport_scrollable_changed_cb(self, viewport, pspec): - self.props.visible = self._viewport.props.scrollable - - def _viewport_can_scroll_dir_changed_cb(self, viewport, pspec): - if self._scroll_direction == _PREVIOUS_PAGE: - sensitive = self._viewport.props.can_scroll_prev - else: - sensitive = self._viewport.props.can_scroll_next - - self.set_sensitive(sensitive) - - def _clicked_cb(self, button): - self._viewport.scroll(self._scroll_direction) - - viewport = property(fset=set_viewport) - -class HTray(gtk.HBox): - def __init__(self, **kwargs): - gobject.GObject.__init__(self, **kwargs) - self.set_direction(gtk.TEXT_DIR_LTR) - - scroll_left = _TrayScrollButton('go-left', _PREVIOUS_PAGE) - self.pack_start(scroll_left, False) - - self._viewport = _TrayViewport(gtk.ORIENTATION_HORIZONTAL) - self.pack_start(self._viewport) - self._viewport.show() - - scroll_right = _TrayScrollButton('go-right', _NEXT_PAGE) - self.pack_start(scroll_right, False) - - scroll_left.viewport = self._viewport - scroll_right.viewport = self._viewport - - def get_children(self): - return self._viewport.traybar.get_children() - - def add_item(self, item, index=-1): - self._viewport.traybar.insert(item, index) - - def remove_item(self, item): - self._viewport.traybar.remove(item) - - def get_item_index(self, item): - return self._viewport.traybar.get_item_index(item) - -class VTray(gtk.VBox): - def __init__(self, **kwargs): - gobject.GObject.__init__(self, **kwargs) - - # FIXME we need a go-up icon - scroll_left = _TrayScrollButton('go-left', _PREVIOUS_PAGE) - self.pack_start(scroll_left, False) - - self._viewport = _TrayViewport(gtk.ORIENTATION_VERTICAL) - self.pack_start(self._viewport) - self._viewport.show() - - # FIXME we need a go-down icon - scroll_right = _TrayScrollButton('go-right', _NEXT_PAGE) - self.pack_start(scroll_right, False) - - scroll_left.viewport = self._viewport - scroll_right.viewport = self._viewport - - def get_children(self): - return self._viewport.traybar.get_children() - - def add_item(self, item, index=-1): - self._viewport.traybar.insert(item, index) - - def remove_item(self, item): - self._viewport.traybar.remove(item) - - def get_item_index(self, item): - return self._viewport.traybar.get_item_index(item) - -class TrayButton(ToolButton): - def __init__(self, **kwargs): - ToolButton.__init__(self, **kwargs) - -class _IconWidget(gtk.EventBox): - __gtype_name__ = "SugarTrayIconWidget" - - def __init__(self, icon_name=None, xo_color=None): - gtk.EventBox.__init__(self) - - self._palette = None - - self.set_app_paintable(True) - - self._icon = Icon(icon_name=icon_name, xo_color=xo_color, - icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) - self.add(self._icon) - self._icon.show() - - def do_expose_event(self, event): - if self._palette and self._palette.is_up(): - invoker = self._palette.props.invoker - invoker.draw_rectangle(event, self._palette) - - gtk.EventBox.do_expose_event(self, event) - - def set_palette(self, palette): - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - self._palette.props.invoker = ToolInvoker(self) - - def get_icon(self): - return self._icon - -class TrayIcon(gtk.ToolItem): - __gtype_name__ = "SugarTrayIcon" - - def __init__(self, icon_name=None, xo_color=None): - gtk.ToolItem.__init__(self) - - self._icon_widget = _IconWidget(icon_name, xo_color) - self.add(self._icon_widget) - self._icon_widget.show() - - self.set_size_request(style.GRID_CELL_SIZE, style.GRID_CELL_SIZE) - - def set_palette(self, palette): - self._icon_widget.set_palette(palette) - - def set_tooltip(self, text): - self.set_palette(Palette(text)) - - def get_icon(self): - return self._icon_widget.get_icon() - icon = property(get_icon, None) - diff --git a/sugar/graphics/window.py b/sugar/graphics/window.py deleted file mode 100644 index ced5595..0000000 --- a/sugar/graphics/window.py +++ /dev/null @@ -1,212 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# 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 gobject -import gtk - -from sugar.graphics.icon import Icon - -class UnfullscreenButton(gtk.Window): - - def __init__(self): - gtk.Window.__init__(self) - - self.set_decorated(False) - self.set_resizable(False) - self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - - self.set_border_width(0) - - self.props.accept_focus = False - - #Setup estimate of width, height - w, h = gtk.icon_size_lookup(gtk.ICON_SIZE_LARGE_TOOLBAR) - self._width = w - self._height = h - - self.connect('size-request', self._size_request_cb) - - screen = self.get_screen() - screen.connect('size-changed', self._screen_size_changed_cb) - - self._button = gtk.Button() - self._button.set_relief(gtk.RELIEF_NONE) - - self._icon = Icon(icon_name='view-return', - icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) - self._icon.show() - self._button.add(self._icon) - - self._button.show() - self.add(self._button) - - def connect_button_press(self, cb): - self._button.connect('button-press-event', cb) - - def _reposition(self): - x = gtk.gdk.screen_width() - self._width - self.move(x, 0) - - def _size_request_cb(self, widget, req): - self._width = req.width - self._height = req.height - self._reposition() - - def _screen_size_changed_cb(self, screen): - self._reposition() - -class Window(gtk.Window): - def __init__(self, **args): - self._enable_fullscreen_mode = True - - gtk.Window.__init__(self, **args) - - self.connect('realize', self.__window_realize_cb) - self.connect('window-state-event', self.__window_state_event_cb) - self.connect('key-press-event', self.__key_press_cb) - - self.toolbox = None - self._alerts = [] - self.canvas = None - self.tray = None - - self._vbox = gtk.VBox() - self._hbox = gtk.HBox() - self._vbox.pack_start(self._hbox) - self._hbox.show() - - self._event_box = gtk.EventBox() - self._hbox.pack_start(self._event_box) - self._event_box.show() - - self.add(self._vbox) - self._vbox.show() - - self._is_fullscreen = False - self._unfullscreen_button = UnfullscreenButton() - self._unfullscreen_button.set_transient_for(self) - self._unfullscreen_button.connect_button_press( - self.__unfullscreen_button_pressed) - - def set_canvas(self, canvas): - if self.canvas: - self._event_box.remove(self.canvas) - - if canvas: - self._event_box.add(canvas) - - self.canvas = 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 set_tray(self, tray, position): - if self.tray: - box = self.tray.get_parent() - box.remove(self.tray) - - if position == gtk.POS_LEFT: - self._hbox.pack_start(tray, False) - elif position == gtk.POS_RIGHT: - self._hbox.pack_end(tray, False) - elif position == gtk.POS_BOTTOM: - self._vbox.pack_end(tray, False) - - self.tray = tray - - def add_alert(self, alert): - self._alerts.append(alert) - if len(self._alerts) == 1: - self._vbox.pack_start(alert, False) - if self.toolbox is not None: - self._vbox.reorder_child(alert, 1) - else: - self._vbox.reorder_child(alert, 0) - - def remove_alert(self, alert): - if alert in self._alerts: - self._alerts.remove(alert) - # if the alert is the visible one on top of the queue - if alert.get_parent() is not None: - self._vbox.remove(alert) - if len(self._alerts) >= 1: - self._vbox.pack_start(self._alerts[0], False) - if self.toolbox is not None: - self._vbox.reorder_child(self._alerts[0], 1) - else: - self._vbox.reorder_child(self._alert[0], 0) - - def __window_realize_cb(self, window): - group = gtk.Window() - group.realize() - window.window.set_group(group.window) - - def __window_state_event_cb(self, window, event): - if not (event.changed_mask & gtk.gdk.WINDOW_STATE_FULLSCREEN): - return False - - if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN: - if self.toolbox is not None: - self.toolbox.hide() - if self.tray is not None: - self.tray.hide() - - self._is_fullscreen = True - if self.props.enable_fullscreen_mode: - self._unfullscreen_button.show() - - else: - if self.toolbox is not None: - self.toolbox.show() - if self.tray is not None: - self.tray.show() - - self._is_fullscreen = False - if self.props.enable_fullscreen_mode: - self._unfullscreen_button.hide() - - def __key_press_cb(self, widget, event): - key = gtk.gdk.keyval_name(event.keyval) - if event.state & gtk.gdk.MOD1_MASK: - if key == 'space': - self.tray.props.visible = not self.tray.props.visible - return True - elif key == 'Escape' and self._is_fullscreen and \ - self.props.enable_fullscreen_mode: - self.unfullscreen() - return True - return False - - def __unfullscreen_button_pressed(self, widget, event): - self.unfullscreen() - - def set_enable_fullscreen_mode(self, enable_fullscreen_mode): - self._enable_fullscreen_mode = enable_fullscreen_mode - - def get_enable_fullscreen_mode(self): - return self._enable_fullscreen_mode - - enable_fullscreen_mode = gobject.property(type=object, - setter=set_enable_fullscreen_mode, - getter=get_enable_fullscreen_mode) - diff --git a/sugar/graphics/xocolor.py b/sugar/graphics/xocolor.py deleted file mode 100644 index d5e906f..0000000 --- a/sugar/graphics/xocolor.py +++ /dev/null @@ -1,255 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# 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 random - -colors = [ -['#B20008', '#FF2B34'], \ -['#FF2B34', '#B20008'], \ -['#E6000A', '#FF2B34'], \ -['#FF2B34', '#E6000A'], \ -['#FFADCE', '#FF2B34'], \ -['#9A5200', '#FF2B34'], \ -['#FF2B34', '#9A5200'], \ -['#FF8F00', '#FF2B34'], \ -['#FF2B34', '#FF8F00'], \ -['#FFC169', '#FF2B34'], \ -['#807500', '#FF2B34'], \ -['#FF2B34', '#807500'], \ -['#BE9E00', '#FF2B34'], \ -['#FF2B34', '#BE9E00'], \ -['#F8E800', '#FF2B34'], \ -['#008009', '#FF2B34'], \ -['#FF2B34', '#008009'], \ -['#00B20D', '#FF2B34'], \ -['#FF2B34', '#00B20D'], \ -['#8BFF7A', '#FF2B34'], \ -['#00588C', '#FF2B34'], \ -['#FF2B34', '#00588C'], \ -['#005FE4', '#FF2B34'], \ -['#FF2B34', '#005FE4'], \ -['#BCCDFF', '#FF2B34'], \ -['#5E008C', '#FF2B34'], \ -['#FF2B34', '#5E008C'], \ -['#7F00BF', '#FF2B34'], \ -['#FF2B34', '#7F00BF'], \ -['#D1A3FF', '#FF2B34'], \ -['#9A5200', '#FF8F00'], \ -['#FF8F00', '#9A5200'], \ -['#C97E00', '#FF8F00'], \ -['#FF8F00', '#C97E00'], \ -['#FFC169', '#FF8F00'], \ -['#807500', '#FF8F00'], \ -['#FF8F00', '#807500'], \ -['#BE9E00', '#FF8F00'], \ -['#FF8F00', '#BE9E00'], \ -['#F8E800', '#FF8F00'], \ -['#008009', '#FF8F00'], \ -['#FF8F00', '#008009'], \ -['#00B20D', '#FF8F00'], \ -['#FF8F00', '#00B20D'], \ -['#8BFF7A', '#FF8F00'], \ -['#00588C', '#FF8F00'], \ -['#FF8F00', '#00588C'], \ -['#005FE4', '#FF8F00'], \ -['#FF8F00', '#005FE4'], \ -['#BCCDFF', '#FF8F00'], \ -['#5E008C', '#FF8F00'], \ -['#FF8F00', '#5E008C'], \ -['#A700FF', '#FF8F00'], \ -['#FF8F00', '#A700FF'], \ -['#D1A3FF', '#FF8F00'], \ -['#B20008', '#FF8F00'], \ -['#FF8F00', '#B20008'], \ -['#FF2B34', '#FF8F00'], \ -['#FF8F00', '#FF2B34'], \ -['#FFADCE', '#FF8F00'], \ -['#807500', '#F8E800'], \ -['#F8E800', '#807500'], \ -['#BE9E00', '#F8E800'], \ -['#F8E800', '#BE9E00'], \ -['#FFFA00', '#EDDE00'], \ -['#008009', '#F8E800'], \ -['#F8E800', '#008009'], \ -['#00EA11', '#F8E800'], \ -['#F8E800', '#00EA11'], \ -['#8BFF7A', '#F8E800'], \ -['#00588C', '#F8E800'], \ -['#F8E800', '#00588C'], \ -['#00A0FF', '#F8E800'], \ -['#F8E800', '#00A0FF'], \ -['#BCCEFF', '#F8E800'], \ -['#5E008C', '#F8E800'], \ -['#F8E800', '#5E008C'], \ -['#AC32FF', '#F8E800'], \ -['#F8E800', '#AC32FF'], \ -['#D1A3FF', '#F8E800'], \ -['#B20008', '#F8E800'], \ -['#F8E800', '#B20008'], \ -['#FF2B34', '#F8E800'], \ -['#F8E800', '#FF2B34'], \ -['#FFADCE', '#F8E800'], \ -['#9A5200', '#F8E800'], \ -['#F8E800', '#9A5200'], \ -['#FF8F00', '#F8E800'], \ -['#F8E800', '#FF8F00'], \ -['#FFC169', '#F8E800'], \ -['#008009', '#00EA11'], \ -['#00EA11', '#008009'], \ -['#00B20D', '#00EA11'], \ -['#00EA11', '#00B20D'], \ -['#8BFF7A', '#00EA11'], \ -['#00588C', '#00EA11'], \ -['#00EA11', '#00588C'], \ -['#005FE4', '#00EA11'], \ -['#00EA11', '#005FE4'], \ -['#BCCDFF', '#00EA11'], \ -['#5E008C', '#00EA11'], \ -['#00EA11', '#5E008C'], \ -['#7F00BF', '#00EA11'], \ -['#00EA11', '#7F00BF'], \ -['#D1A3FF', '#00EA11'], \ -['#B20008', '#00EA11'], \ -['#00EA11', '#B20008'], \ -['#FF2B34', '#00EA11'], \ -['#00EA11', '#FF2B34'], \ -['#FFADCE', '#00EA11'], \ -['#9A5200', '#00EA11'], \ -['#00EA11', '#9A5200'], \ -['#FF8F00', '#00EA11'], \ -['#00EA11', '#FF8F00'], \ -['#FFC169', '#00EA11'], \ -['#807500', '#00EA11'], \ -['#00EA11', '#807500'], \ -['#BE9E00', '#00EA11'], \ -['#00EA11', '#BE9E00'], \ -['#F8E800', '#00EA11'], \ -['#00588C', '#00A0FF'], \ -['#00A0FF', '#00588C'], \ -['#005FE4', '#00A0FF'], \ -['#00A0FF', '#005FE4'], \ -['#BCCDFF', '#00A0FF'], \ -['#5E008C', '#00A0FF'], \ -['#00A0FF', '#5E008C'], \ -['#9900E6', '#00A0FF'], \ -['#00A0FF', '#9900E6'], \ -['#D1A3FF', '#00A0FF'], \ -['#B20008', '#00A0FF'], \ -['#00A0FF', '#B20008'], \ -['#FF2B34', '#00A0FF'], \ -['#00A0FF', '#FF2B34'], \ -['#FFADCE', '#00A0FF'], \ -['#9A5200', '#00A0FF'], \ -['#00A0FF', '#9A5200'], \ -['#FF8F00', '#00A0FF'], \ -['#00A0FF', '#FF8F00'], \ -['#FFC169', '#00A0FF'], \ -['#807500', '#00A0FF'], \ -['#00A0FF', '#807500'], \ -['#BE9E00', '#00A0FF'], \ -['#00A0FF', '#BE9E00'], \ -['#F8E800', '#00A0FF'], \ -['#008009', '#00A0FF'], \ -['#00A0FF', '#008009'], \ -['#00B20D', '#00A0FF'], \ -['#00A0FF', '#00B20D'], \ -['#8BFF7A', '#00A0FF'], \ -['#5E008C', '#AC32FF'], \ -['#AC32FF', '#5E008C'], \ -['#7F00BF', '#AC32FF'], \ -['#AC32FF', '#7F00BF'], \ -['#D1A3FF', '#AC32FF'], \ -['#B20008', '#AC32FF'], \ -['#AC32FF', '#B20008'], \ -['#FF2B34', '#AC32FF'], \ -['#AC32FF', '#FF2B34'], \ -['#FFADCE', '#AC32FF'], \ -['#9A5200', '#AC32FF'], \ -['#AC32FF', '#9A5200'], \ -['#FF8F00', '#AC32FF'], \ -['#AC32FF', '#FF8F00'], \ -['#FFC169', '#AC32FF'], \ -['#807500', '#AC32FF'], \ -['#AC32FF', '#807500'], \ -['#BE9E00', '#AC32FF'], \ -['#AC32FF', '#BE9E00'], \ -['#F8E800', '#AC32FF'], \ -['#008009', '#AC32FF'], \ -['#AC32FF', '#008009'], \ -['#00B20D', '#AC32FF'], \ -['#AC32FF', '#00B20D'], \ -['#8BFF7A', '#AC32FF'], \ -['#00588C', '#AC32FF'], \ -['#AC32FF', '#00588C'], \ -['#005FE4', '#AC32FF'], \ -['#AC32FF', '#005FE4'], \ -['#BCCDFF', '#AC32FF'], \ -] - -def _parse_string(color_string): - if color_string == 'white': - return ['#ffffff', '#414141'] - elif color_string == 'insensitive': - return ['#ffffff', '#e2e2e2'] - - splitted = color_string.split(',') - if len(splitted) == 2: - return [splitted[0], splitted[1]] - else: - return None - -def is_valid(color_string): - return (_parse_string(color_string) != None) - -class XoColor: - def __init__(self, color_string=None): - if color_string == None or not is_valid(color_string): - n = int(random.random() * (len(colors) - 1)) - [self.stroke, self.fill] = colors[n] - else: - [self.stroke, self.fill] = _parse_string(color_string) - - def __cmp__(self, other): - if isinstance(other, XoColor): - if self.stroke == other.stroke and self.fill == other.fill: - return 0 - return -1 - - def get_stroke_color(self): - return self.stroke - - def get_fill_color(self): - return self.fill - - def to_string(self): - return '%s,%s' % (self.stroke, self.fill) - -if __name__ == "__main__": - import sys - import re - - f = open(sys.argv[1], 'r') - - print 'colors = [' - - for line in f.readlines(): - match = re.match(r'fill: ([A-Z0-9]*) stroke: ([A-Z0-9]*)', line) - print "['#%s', '#%s'], \\" % (match.group(2), match.group(1)) - - print ']' - - f.close() |