From a5ca5dca316a30bd01d9e97bdcee567aa3460671 Mon Sep 17 00:00:00 2001 From: Daniel Francis Date: Sun, 08 Jul 2012 00:01:33 +0000 Subject: Removing Hippo Canvas from chat mode Now the activity hasn't got HippoCanvas and I'm ready to port it to Gtk3! A little comment, I added de _share function because I forgot it at the time to remove the early toolkit modules, and it appeared in the log when I tried to share the activity. Signed-off-by: Daniel Francis --- diff --git a/activity.py b/activity.py index a3f01ac..d4f0e2a 100644 --- a/activity.py +++ b/activity.py @@ -203,6 +203,18 @@ class SpeakActivity(SharedActivity): toolbox.show_all() self.toolbar_box = toolbox + def _share(self, tube_conn, initiator): + logging.debug('Activity._share state=%s' % self.__state) + + if self.__state == _NEW_INSTANCE: + self.__postponed_share.append((tube_conn, initiator)) + self.__state = _PRE_INSTANCE + elif self.__state == _PRE_INSTANCE: + self.__postponed_share.append((tube_conn, initiator)) + self.__instance() + elif self.__state == _POST_INSTANCE: + self.share_instance(tube_conn, initiator) + def set_cursor(self, cursor): if not isinstance(cursor, gtk.gdk.Cursor): cursor = CursorFactory().get_cursor(cursor) diff --git a/chat.py b/chat.py index 12d0075..a61822d 100644 --- a/chat.py +++ b/chat.py @@ -16,12 +16,11 @@ import gtk import pango -import hippo import logging from gettext import gettext as _ import sugar.graphics.style as style -from sugar.graphics.roundbox import CanvasRoundBox +from roundbox import RoundBox from sugar.graphics.toggletoolbutton import ToggleToolButton import eye @@ -45,9 +44,9 @@ ENTRY_XPAD = 0 ENTRY_YPAD = 7 -class View(hippo.Canvas): +class View(gtk.EventBox): def __init__(self): - hippo.Canvas.__init__(self) + gtk.EventBox.__init__(self) self.messenger = None self.me = None @@ -57,16 +56,18 @@ class View(hippo.Canvas): # buddies box - self._buddies_list = hippo.CanvasBox( - background_color=BUDDIES_COLOR.get_int(), - box_width=BUDDIES_WIDTH, - padding=ENTRY_YPAD, - spacing=ENTRY_YPAD) + self._buddies_list = gtk.VBox() + self._buddies_list.set_homogeneous(False) + self._buddies_list.props.spacing = ENTRY_YPAD - self._buddies_box = hippo.CanvasScrollbars() - self._buddies_box.set_policy(hippo.ORIENTATION_HORIZONTAL, - hippo.SCROLLBAR_NEVER) - self._buddies_box.set_root(self._buddies_list) + self._buddies_box = gtk.ScrolledWindow() + self._buddies_box.set_policy(gtk.POLICY_ALWAYS, + gtk.POLICY_NEVER) + evbox = gtk.EventBox() + evbox.modify_bg(gtk.STATE_NORMAL, BUDDIES_COLOR.get_gdk_color()) + evbox.add(self._buddies_list) + evbox.show() + self._buddies_box.add_with_viewport(evbox) # chat entry @@ -82,40 +83,37 @@ class View(hippo.Canvas): chat_post.connect('key-press-event', self._key_press_cb) chat_post.props.wrap_mode = gtk.WRAP_WORD_CHAR chat_post.set_size_request(-1, BUDDY_SIZE - ENTRY_YPAD * 2) - chat_post_box = CanvasRoundBox( - background_color=style.COLOR_WHITE.get_int(), - padding_left=ENTRY_XPAD, - padding_right=ENTRY_XPAD, - padding_top=ENTRY_YPAD, - padding_bottom=ENTRY_YPAD - ) - chat_post_box.props.border_color = ENTRY_COLOR.get_int() - chat_post_box.append(hippo.CanvasWidget(widget=chat_post), - hippo.PACK_EXPAND) - - chat_entry = CanvasRoundBox(background_color=ENTRY_COLOR.get_int(), - padding_left=ENTRY_XPAD, - padding_right=ENTRY_XPAD, - padding_top=ENTRY_YPAD, - padding_bottom=ENTRY_YPAD, - spacing=ENTRY_YPAD) - chat_entry.props.orientation = hippo.ORIENTATION_HORIZONTAL - chat_entry.props.border_color = style.COLOR_WHITE.get_int() - chat_entry.append(my_face_widget) - chat_entry.append(chat_post_box, hippo.PACK_EXPAND) - - chat_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL, - background_color=style.COLOR_WHITE.get_int()) - chat_box.append(self._chat, hippo.PACK_EXPAND) - chat_box.append(chat_entry) + chat_post_box = RoundBox() + chat_post_box.background_color = style.COLOR_WHITE + chat_post_box.border_color = ENTRY_COLOR + chat_post_box.pack_start(chat_post, True, True, ENTRY_XPAD) + + chat_entry = RoundBox() + chat_entry.set_border_width(ENTRY_YPAD) + chat_entry.background_color = ENTRY_COLOR + chat_entry.border_color = style.COLOR_WHITE + chat_entry.pack_start(my_face_widget, False, True, 0) + separator = gtk.EventBox() + separator.modify_bg(gtk.STATE_NORMAL, ENTRY_COLOR.get_gdk_color()) + separator.set_size_request(ENTRY_YPAD, -1) + separator.show() + chat_entry.pack_start(separator, False, False) + chat_entry.pack_start(chat_post_box, True, True, ENTRY_XPAD) + + evbox = gtk.EventBox() + evbox.modify_bg(gtk.STATE_NORMAL, style.COLOR_WHITE.get_gdk_color()) + chat_box = gtk.VBox() + chat_box.pack_start(self._chat, True, True) + chat_box.pack_start(chat_entry, False, True) + evbox.add(chat_box) # desk - self._desk = hippo.CanvasBox() - self._desk.props.orientation = hippo.ORIENTATION_HORIZONTAL - self._desk.append(chat_box, hippo.PACK_EXPAND) + self._desk = gtk.HBox() + self._desk.pack_start(evbox, True, True) + self._desk.show_all() - self.set_root(self._desk) + self.add(self._desk) def update(self, status): self.me.update(status) @@ -160,34 +158,30 @@ class View(hippo.Canvas): self.me.shut_up() def _add_buddy(self, buddy): - box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, - background_color=BUDDIES_COLOR.get_int(), - spacing=ENTRY_YPAD) + evbox = gtk.EventBox() + evbox.modify_bg(gtk.STATE_NORMAL, BUDDIES_COLOR.get_gdk_color()) + box = gtk.HBox() buddy_face, buddy_widget = self._new_face(buddy, BUDDIES_COLOR) - char_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL) - nick = hippo.CanvasText(text=buddy.props.nick, - xalign=hippo.ALIGNMENT_START, - yalign=hippo.ALIGNMENT_START) - lang = hippo.CanvasText(text='', - xalign=hippo.ALIGNMENT_START, - yalign=hippo.ALIGNMENT_START) - char_box.append(nick) - char_box.append(lang) + char_box = gtk.VBox() + nick = gtk.Label(buddy.props.nick) + lang = gtk.Label() + char_box.pack_start(nick) + char_box.pack_start(lang) - box.append(buddy_widget) - box.append(char_box, hippo.PACK_EXPAND) + box.pack_start(buddy_widget, False, False, ENTRY_YPAD) + box.pack_start(char_box, True, True, ENTRY_YPAD) self._buddies[buddy] = { 'box': box, 'face': buddy_face, 'lang': lang } - self._buddies_list.append(box) + self._buddies_list.pack_start(box) if len(self._buddies) == 1: - self._desk.append(self._buddies_box) + self._desk.pack_start(self._buddies_box) def _key_press_cb(self, widget, event): if event.keyval == gtk.keysyms.Return: @@ -213,17 +207,20 @@ class View(hippo.Canvas): buddy_face = face.View(fill_color) buddy_face.show_all() - inner = CanvasRoundBox(background_color=fill_color.get_int()) - inner.props.border_color = fill_color.get_int() - inner.append(hippo.CanvasWidget(widget=buddy_face), hippo.PACK_EXPAND) - inner.props.border = BUDDY_PAD - - outer = CanvasRoundBox(background_color=stroke_color.get_int(), - box_width=BUDDY_SIZE, - box_height=BUDDY_SIZE) - outer.props.border_color = stroke_color.get_int() - outer.append(inner, hippo.PACK_EXPAND) - outer.props.border = BUDDY_PAD + inner = RoundBox() + inner.set_border_width(BUDDY_PAD) + inner.background_color = fill_color + inner.border_color = fill_color + inner.pack_start(buddy_face, True, True, 0) + inner.border = BUDDY_PAD + + outer = RoundBox() + outer.set_border_width(BUDDY_PAD) + outer.background_color = stroke_color + outer.set_size_request(BUDDY_SIZE, BUDDY_SIZE) + outer.border_color = stroke_color + outer.pack_start(inner, True, True, 0) + outer.border = BUDDY_PAD return (buddy_face, outer) diff --git a/chatbox.py b/chatbox.py index 671ba09..58320b4 100644 --- a/chatbox.py +++ b/chatbox.py @@ -17,21 +17,20 @@ # This code is a stripped down version of the Chat import gtk -import hippo import logging import pango import re from datetime import datetime -from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT from gettext import gettext as _ -import sugar.graphics.style as style -from sugar.graphics.roundbox import CanvasRoundBox -from sugar.graphics.palette import Palette, CanvasInvoker +from sugar.graphics.style import style +from sugar.graphics.palette import Palette +from sugar.graphics.palette import CanvasInvoker +from sugar.graphics.palette import MouseSpeedDetector from sugar.presence import presenceservice -from sugar.graphics.style import (Color, COLOR_BLACK, COLOR_WHITE) from sugar.graphics.menuitem import MenuItem from sugar.activity.activity import get_activity_root +from roundbox import RoundBox logger = logging.getLogger('speak') @@ -40,9 +39,173 @@ URL_REGEXP = re.compile('((http|ftp)s?://)?' '(:[1-9][0-9]{0,4})?(/[-a-zA-Z0-9/%~@&_+=;:,.?#]*[a-zA-Z0-9/])?') -class ChatBox(hippo.CanvasScrollbars): +class TextBox(gtk.TextView): + + hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2) + + def __init__(self, color, bg_color, lang_rtl): + self._lang_rtl = lang_rtl + gtk.TextView.__init__(self) + self.set_editable(False) + self.set_cursor_visible(False) + self.set_wrap_mode(gtk.WRAP_WORD_CHAR) + self.get_buffer().set_text("", 0) + self.iter_text = self.get_buffer().get_iter_at_offset(0) + self.fg_tag = self.get_buffer().create_tag("foreground_color", + foreground=color.get_html()) + self._subscript_tag = self.get_buffer().create_tag('subscript', + rise=-7 * pango.SCALE) # in pixels + self._empty = True + self.palette = None + self._mouse_detector = MouseSpeedDetector(self, 200, 5) + self._mouse_detector.connect('motion-slow', self.__mouse_slow_cb) + self.modify_base(gtk.STATE_NORMAL, bg_color.get_gdk_color()) + + self.add_events(gtk.gdk.POINTER_MOTION_MASK | \ + gtk.gdk.BUTTON_PRESS_MASK | \ + gtk.gdk.BUTTON_RELEASE_MASK | \ + gtk.gdk.LEAVE_NOTIFY_MASK) + + self.connect('event-after', self.__event_after_cb) + self.connect('button-press-event', self.__button_press_cb) + self.motion_notify_id = self.connect('motion-notify-event', \ + self.__motion_notify_cb) + self.connect('visibility-notify-event', self.__visibility_notify_cb) + self.connect('leave-notify-event', self.__leave_notify_event_cb) + + def __leave_notify_event_cb(self, widget, event): + self._mouse_detector.stop() + + def __button_press_cb(self, widget, event): + if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: + # To disable the standard textview popup + return True + + # Links can be activated by clicking. + def __event_after_cb(self, widget, event): + if event.type != gtk.gdk.BUTTON_RELEASE: + return False + + x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, + int(event.x), int(event.y)) + iter_tags = self.get_iter_at_location(x, y) + + for tag in iter_tags.get_tags(): + url = tag.get_data('url') + if url is not None: + if event.button == 3: + palette = tag.get_data('palette') + xw, yw = self.get_toplevel().get_pointer() + palette.move(int(xw), int(yw)) + palette.popup() + else: + self._show_via_journal(url) + break + + return False + + def check_url_hovering(self, x, y): + # Looks at all tags covering the position (x, y) in the text view, + # and if one of them is a link return True + + hovering = False + # When check on_slow_mouse event, the position can be out + # of the widget and return negative values. + if x < 0 or y < 0: + return hovering + + self.palette = None + iter_tags = self.get_iter_at_location(x, y) + + tags = iter_tags.get_tags() + for tag in tags: + url = tag.get_data('url') + self.palette = tag.get_data('palette') + if url is not None: + hovering = True + break + return hovering + + def set_cursor_if_appropriate(self, x, y): + # Looks at all tags covering the position (x, y) in the text view, + # and if one of them is a link, change the cursor to the "hands" cursor + + hovering_over_link = self.check_url_hovering(x, y) + win = self.get_window(gtk.TEXT_WINDOW_TEXT) + if hovering_over_link: + win.set_cursor(self.hand_cursor) + self._mouse_detector.start() + else: + win.set_cursor(None) + self._mouse_detector.stop() + + def __mouse_slow_cb(self, widget): + x, y = self.get_pointer() + hovering_over_link = self.check_url_hovering(x, y) + if hovering_over_link: + if self.palette is not None: + xw, yw = self.get_toplevel().get_pointer() + self.palette.move(xw, yw) + self.palette.popup() + self._mouse_detector.stop() + else: + if self.palette is not None: + self.palette.popdown() + + # Update the cursor image if the pointer moved. + def __motion_notify_cb(self, widget, event): + x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, + int(event.x), int(event.y)) + self.set_cursor_if_appropriate(x, y) + self.window.get_pointer() + return False + + def __visibility_notify_cb(self, widget, event): + # Also update the cursor image if the window becomes visible + # (e.g. when a window covering it got iconified). + + wx, wy, __ = self.window.get_pointer() + bx, by = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, wx, wy) + self.set_cursor_if_appropriate(bx, by) + return False + + def __palette_mouse_enter_cb(self, widget, event): + self.handler_block(self.motion_notify_id) + + def __palette_mouse_leave_cb(self, widget, event): + self.handler_unblock(self.motion_notify_id) + + def add_text(self, text): + buf = self.get_buffer() + + if not self._empty: + buf.insert(self.iter_text, '\n') + + words = text.split() + for word in words: + buf.insert(self.iter_text, word) + buf.insert(self.iter_text, ' ') + + self._empty = False + + +class ColorLabel(gtk.Label): + + def __init__(self, text, color=None): + self._color = color + if self._color is not None: + text = '' % self._color.get_html() +\ + text + '' + gtk.Label.__init__(self) + self.set_use_markup(True) + self.set_markup(text) + self.props.selectable = True + + +class ChatBox(gtk.ScrolledWindow): + def __init__(self): - hippo.CanvasScrollbars.__init__(self) + gtk.ScrolledWindow.__init__(self) self.owner = presenceservice.get_instance().get_owner() @@ -54,15 +217,17 @@ class ChatBox(hippo.CanvasScrollbars): self._last_msg = None self._chat_log = '' - self._conversation = hippo.CanvasBox( - spacing=0, - background_color=COLOR_WHITE.get_int()) - - self.set_policy(hippo.ORIENTATION_HORIZONTAL, - hippo.SCROLLBAR_NEVER) - self.set_root(self._conversation) - - vadj = self.props.widget.get_vadjustment() + self._conversation = gtk.VBox() + self._conversation.set_homogeneous(False) + self._conversation.props.spacing = style.LINE_WIDTH + self._conversation.props.border_width = style.LINE_WIDTH + evbox = gtk.EventBox() + evbox.modify_bg(gtk.STATE_NORMAL, style.COLOR_WHITE.get_gdk_color()) + evbox.add(self._conversation) + + self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) + self.add_with_viewport(evbox) + vadj = self.get_vadjustment() vadj.connect('changed', self._scroll_changed_cb) vadj.connect('value-changed', self._scroll_value_changed_cb) @@ -80,17 +245,12 @@ class ChatBox(hippo.CanvasScrollbars): False: show what buddy said True: show what buddy did - hippo layout: .------------- rb ---------------. - | +name_vbox+ +----msg_vbox----+ | + | +name_vbox+ +----align-----+ | | | | | | | - | | nick: | | +--msg_hbox--+ | | - | | | | | text | | | + | | nick: | | +--message---+ | | + | | | | | text | | | | +---------+ | +------------+ | | - | | | | - | | +--msg_hbox--+ | | - | | | text | url | | | - | | +------------+ | | | +----------------+ | `--------------------------------' """ @@ -110,16 +270,15 @@ class ChatBox(hippo.CanvasScrollbars): color_stroke_html, color_fill_html = ('#000000', '#888888') # Select text color based on fill color: - color_fill_rgba = Color(color_fill_html).get_rgba() + color_fill_rgba = style.Color(color_fill_html).get_rgba() color_fill_gray = (color_fill_rgba[0] + color_fill_rgba[1] + color_fill_rgba[2]) / 3 - color_stroke = Color(color_stroke_html).get_int() - color_fill = Color(color_fill_html).get_int() - + color_stroke = style.Color(color_stroke_html) + color_fill = style.Color(color_fill_html) if color_fill_gray < 0.5: - text_color = COLOR_WHITE.get_int() + text_color = style.COLOR_WHITE else: - text_color = COLOR_BLACK.get_int() + text_color = style.COLOR_BLACK self._add_log(nick, color, text, status_message) @@ -139,82 +298,35 @@ class ChatBox(hippo.CanvasScrollbars): if not new_msg: rb = self._last_msg - msg_vbox = rb.get_children()[1] - msg_hbox = hippo.CanvasBox( - orientation=hippo.ORIENTATION_HORIZONTAL) - msg_vbox.append(msg_hbox) + self._last_msg.add_text(text) else: - rb = CanvasRoundBox(background_color=color_fill, - border_color=color_stroke, - padding=4) - rb.props.border_color = color_stroke # Bug #3742 - self._last_msg = rb + rb = RoundBox() + screen_width = gtk.gdk.screen_width() + # keep space to the scrollbar + rb.set_size_request(screen_width - 50, -1) + rb.props.border_width = style.DEFAULT_PADDING + rb.props.spacing = style.DEFAULT_SPACING + rb.background_color = color_fill + rb.border_color = color_stroke self._last_msg_sender = buddy + self._last_msg = rb if not status_message: - name = hippo.CanvasText(text=nick + ': ', - color=text_color) - name_vbox = hippo.CanvasBox( - orientation=hippo.ORIENTATION_VERTICAL) - name_vbox.append(name) - rb.append(name_vbox) - msg_vbox = hippo.CanvasBox( - orientation=hippo.ORIENTATION_VERTICAL) - rb.append(msg_vbox) - msg_hbox = hippo.CanvasBox( - orientation=hippo.ORIENTATION_HORIZONTAL) - msg_vbox.append(msg_hbox) + name = ColorLabel(text=nick + ':', color=text_color) + name_vbox = gtk.VBox() + name_vbox.pack_start(name, False, False) + rb.pack_start(name_vbox, False, False) + message = TextBox(text_color, color_fill, lang_rtl) + vbox = gtk.VBox() + vbox.pack_start(message, True, True) + rb.pack_start(vbox, True, True) + self._last_msg = message + self._conversation.pack_start(rb, False, False) + message.add_text(text) + self._conversation.show_all() if status_message: self._last_msg_sender = None - match = URL_REGEXP.match(text) - while match: - # there is a URL in the text - starttext = text[:match.start()] - if starttext: - message = hippo.CanvasText( - text=starttext, - size_mode=hippo.CANVAS_SIZE_WRAP_WORD, - color=text_color, - xalign=hippo.ALIGNMENT_START) - msg_hbox.append(message) - url = text[match.start():match.end()] - - message = CanvasLink( - text=url, - color=text_color) - attrs = pango.AttrList() - attrs.insert(pango.AttrUnderline(pango.UNDERLINE_SINGLE, 0, 32767)) - message.set_property("attributes", attrs) - message.connect('activated', self._link_activated_cb) - - # call interior magic which should mean just: - # CanvasInvoker().parent = message - CanvasInvoker(message) - - msg_hbox.append(message) - text = text[match.end():] - match = URL_REGEXP.search(text) - - if text: - message = hippo.CanvasText( - text=text, - size_mode=hippo.CANVAS_SIZE_WRAP_WORD, - color=text_color, - xalign=hippo.ALIGNMENT_START) - msg_hbox.append(message) - - # Order of boxes for RTL languages: - if lang_rtl: - msg_hbox.reverse() - if new_msg: - rb.reverse() - - if new_msg: - box = hippo.CanvasBox(padding=2) - box.append(rb) - self._conversation.append(box) - def _scroll_value_changed_cb(self, adj, scroll=None): """Turn auto scrolling on or off. If the user scrolled up, turn it off. @@ -282,58 +394,6 @@ class ChatBox(hippo.CanvasScrollbars): nick, color, status_message, text) -class CanvasLink(hippo.CanvasLink): - def __init__(self, **kwargs): - hippo.CanvasLink.__init__(self, **kwargs) - - def create_palette(self): - return URLMenu(self.props.text) - - -class URLMenu(Palette): - def __init__(self, url): - Palette.__init__(self, url) - - self.url = url_check_protocol(url) - - menu_item = MenuItem(_('Copy to Clipboard'), 'edit-copy') - menu_item.connect('activate', self._copy_to_clipboard_cb) - self.menu.append(menu_item) - menu_item.show() - - def create_palette(self): - pass - - def _copy_to_clipboard_cb(self, menuitem): - logger.debug('Copy %s to clipboard', self.url) - clipboard = gtk.clipboard_get() - targets = [("text/uri-list", 0, 0), - ("UTF8_STRING", 0, 1)] - - if not clipboard.set_with_data(targets, - self._clipboard_data_get_cb, - self._clipboard_clear_cb, - (self.url)): - logger.error('GtkClipboard.set_with_data failed!') - else: - self.owns_clipboard = True - - def _clipboard_data_get_cb(self, clipboard, selection, info, data): - logger.debug('_clipboard_data_get_cb data=%s target=%s', data, - selection.target) - if selection.target in ['text/uri-list']: - if not selection.set_uris([data]): - logger.debug('failed to set_uris') - else: - logger.debug('not uri') - if not selection.set_text(data): - logger.debug('failed to set_text') - - def _clipboard_clear_cb(self, clipboard, data): - logger.debug('clipboard_clear_cb') - self.owns_clipboard = False - - def url_check_protocol(url): """Check that the url has a protocol, otherwise prepend https:// diff --git a/roundbox.py b/roundbox.py new file mode 100644 index 0000000..35d5f7c --- /dev/null +++ b/roundbox.py @@ -0,0 +1,100 @@ +import math +import gtk +from sugar.graphics import style + + +class RoundBox(gtk.HBox): + __gtype_name__ = 'RoundBox' + + _BORDER_DEFAULT = style.LINE_WIDTH + + def __init__(self, **kwargs): + gtk.HBox.__init__(self, **kwargs) + + self._x = None + self._y = None + self._width = None + self._height = None + self._radius = style.zoom(10) + self.border = self._BORDER_DEFAULT + self.border_color = style.COLOR_BLACK + self.background_color = None + self.set_reallocate_redraws(True) + self.set_resize_mode(gtk.RESIZE_PARENT) + self.connect("expose_event", self.__expose_cb) + self.connect("add", self.__add_cb) + + def __add_cb(self, child, params): + child.set_border_width(style.zoom(5)) + + def __size_allocate_cb(self, widget, allocation): + self._x = allocation.x + self._y = allocation.y + self._width = allocation.width + self._height = allocation.height + + def __expose_cb(self, widget, event): + context = widget.window.cairo_create() + + # set a clip region for the expose event + context.rectangle(event.area.x, event.area.y, + event.area.width, event.area.height) + context.clip() + self.draw(context) + return False + + def draw(self, cr): + rect = self.get_allocation() + x = rect.x + self._BORDER_DEFAULT / 2 + y = rect.y + self._BORDER_DEFAULT / 2 + width = rect.width - self._BORDER_DEFAULT + height = rect.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, y + 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) + cr.close_path() + + if self.background_color is not None: + r, g, b, __ = self.background_color.get_rgba() + cr.set_source_rgb(r, g, b) + cr.fill_preserve() + + if self.border_color is not None: + r, g, b, __ = self.border_color.get_rgba() + cr.set_source_rgb(r, g, b) + cr.set_line_width(self.border) + cr.stroke() + +if __name__ == '__main__': + + win = gtk.Window() + win.connect('destroy', gtk.main_quit) + win.set_default_size(450, 550) + vbox = gtk.VBox() + + box1 = RoundBox() + vbox.add(box1) + label1 = gtk.Label("Test 1") + box1.add(label1) + + rbox = RoundBox() + rbox.background_color = style.Color('#FF0000') + vbox.add(rbox) + label2 = gtk.Label("Test 2") + rbox.add(label2) + + bbox = RoundBox() + bbox.background_color = style.Color('#aaff33') + bbox.border_color = style.Color('#ff3300') + vbox.add(bbox) + + win.add(vbox) + win.show_all() + gtk.main() -- cgit v0.9.1