[Sugar-devel] [PATCH Speak] Removing Hippo Canvas from chat mode
Rafael Ortiz
rafael at activitycentral.com
Tue Jul 10 13:05:53 EDT 2012
On Sat, Jul 7, 2012 at 7:01 PM, Daniel Francis <francis at sugarlabs.org>wrote:
> 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 <francis at sugarlabs.org>
> ---
> activity.py | 12 ++
> chat.py | 137 +++++++++++-----------
> chatbox.py | 364
> ++++++++++++++++++++++++++++++++++-------------------------
> roundbox.py | 100 ++++++++++++++++
> 4 files changed, 391 insertions(+), 222 deletions(-)
> create mode 100644 roundbox.py
>
> 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 = '<span foreground="%s">' % self._color.get_html() +\
> + text + '</span>'
> + 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()
> --
> 1.7.10.4
>
> _______________________________________________
> Sugar-devel mailing list
> Sugar-devel at lists.sugarlabs.org
> http://lists.sugarlabs.org/listinfo/sugar-devel
>
Daniel, your patch is in
http://git.sugarlabs.org/speak/mainline/commit/a5ca5dca316a30bd01d9e97bdcee567aa3460671
Y just had to make a little change.
http://git.sugarlabs.org/speak/mainline/commit/27ee0e4bd2ef993d26e02427170910ea09917a4a
Thanks, this is a great improvement btw!.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.sugarlabs.org/archive/sugar-devel/attachments/20120710/d672f9fc/attachment-0001.html>
More information about the Sugar-devel
mailing list