Enhanced the 'Name this entry dialog'

- created the canvastextview in sugar/graphics
This commit is contained in:
Simon Schampijer 2009-01-18 16:30:53 +01:00
parent 5250117b81
commit 817a981288
5 changed files with 359 additions and 58 deletions

View File

@ -6,4 +6,5 @@ sugar_PYTHON = \
activityhandle.py \ activityhandle.py \
activityservice.py \ activityservice.py \
bundlebuilder.py \ bundlebuilder.py \
main.py main.py \
namingalert.py

View File

@ -30,7 +30,7 @@ will need for a real activity.
STABLE. STABLE.
""" """
# Copyright (C) 2006-2007 Red Hat, Inc. # Copyright (C) 2006-2007 Red Hat, Inc.
# Copyright (C) 2007-2008 One Laptop Per Child # Copyright (C) 2007-2009 One Laptop Per Child
# #
# This library is free software; you can redistribute it and/or # This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public # modify it under the terms of the GNU Lesser General Public
@ -55,7 +55,8 @@ from hashlib import sha1
import traceback import traceback
import gconf import gconf
import gtk, gobject import gtk
import gobject
import dbus import dbus
import dbus.service import dbus.service
import cjson import cjson
@ -63,6 +64,7 @@ import cjson
from sugar import util from sugar import util
from sugar.presence import presenceservice from sugar.presence import presenceservice
from sugar.activity.activityservice import ActivityService from sugar.activity.activityservice import ActivityService
from sugar.activity.namingalert import NamingAlert
from sugar.graphics import style from sugar.graphics import style
from sugar.graphics.window import Window from sugar.graphics.window import Window
from sugar.graphics.toolbox import Toolbox from sugar.graphics.toolbox import Toolbox
@ -74,7 +76,6 @@ from sugar.graphics.xocolor import XoColor
from sugar.datastore import datastore from sugar.datastore import datastore
from sugar.session import XSMPClient from sugar.session import XSMPClient
from sugar import wm from sugar import wm
from sugar import _sugarext
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg) _ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
@ -353,59 +354,6 @@ class _ActivitySession(gobject.GObject):
def __sm_quit_cb(self, client): def __sm_quit_cb(self, client):
self.emit('quit') self.emit('quit')
class TitleAlert(gtk.Window):
__gtype_name__ = 'SugarTitleAlert'
_BACKGROUND_COLOR = style.COLOR_BLACK.get_gdk_color()
def __init__(self, activity):
gtk.Window.__init__(self)
self.set_border_width(style.LINE_WIDTH)
offset = style.GRID_CELL_SIZE
width = gtk.gdk.screen_width() - offset * 2
height = gtk.gdk.screen_height() - offset * 2
self.set_size_request(width, height)
self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
self.set_decorated(False)
self.set_resizable(False)
self.set_modal(True)
self.connect('realize', self.__realize_cb)
self._activity = activity
alignment = gtk.Alignment(xalign=0.5, yalign=0.5)
self.add(alignment)
alignment.show()
vbox = gtk.VBox()
vbox.set_spacing(style.DEFAULT_PADDING)
alignment.add(vbox)
vbox.show()
self._entry = gtk.Entry()
self._entry.props.text=self._activity.metadata['title']
self._entry.modify_bg(gtk.STATE_INSENSITIVE, self._BACKGROUND_COLOR)
self._entry.modify_base(gtk.STATE_INSENSITIVE, self._BACKGROUND_COLOR)
vbox.pack_start(self._entry)
self._entry.show()
self._entry.connect('activate', self.__activate_cb)
button = gtk.Button(_('Keep'))
vbox.pack_start(button)
button.show()
button.connect('clicked', self.__activate_cb)
def __realize_cb(self, widget):
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
self.window.set_accept_focus(True)
self.modify_bg(gtk.STATE_NORMAL, self._BACKGROUND_COLOR)
def __activate_cb(self, widget):
self._activity.metadata['title'] = self._entry.props.text
self._activity.metadata['title_set_by_user'] = '1'
self._activity.close()
class Activity(Window, gtk.Container): class Activity(Window, gtk.Container):
"""This is the base Activity class that all other Activities derive from. """This is the base Activity class that all other Activities derive from.
This is where your activity starts. This is where your activity starts.
@ -1027,7 +975,7 @@ class Activity(Window, gtk.Container):
if not self._updating_jobject: if not self._updating_jobject:
self._complete_close() self._complete_close()
else: else:
title_alert = TitleAlert(self) title_alert = NamingAlert(self, get_bundle_path())
title_alert.set_transient_for(self.get_toplevel()) title_alert.set_transient_for(self.get_toplevel())
title_alert.show() title_alert.show()

View File

@ -0,0 +1,312 @@
# Copyright (C) 2009 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 gconf
from sugar.graphics import style
from sugar.graphics.icon import Icon
from sugar.graphics.xocolor import XoColor
from sugar.graphics.icon import CanvasIcon
from sugar.graphics.entry import CanvasEntry
from sugar.graphics.toolbutton import ToolButton
from sugar.graphics.canvastextview import CanvasTextView
from sugar.bundle.activitybundle import ActivityBundle
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
class NamingToolbar(gtk.Toolbar):
""" Toolbar of the naming alert
"""
__gtype_name__ = 'SugarNamingToolbar'
__gsignals__ = {
'keep-clicked': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([]))
}
def __init__(self):
gtk.Toolbar.__init__(self)
client = gconf.client_get_default()
color = XoColor(client.get_string('/desktop/sugar/user/color'))
icon = Icon()
icon.set_from_icon_name('activity-journal',
gtk.ICON_SIZE_LARGE_TOOLBAR)
icon.props.xo_color = color
self._add_widget(icon)
self._add_separator()
self._title = gtk.Label(_('Name this entry'))
self._add_widget(self._title)
self._add_separator(True)
self._keep_button = ToolButton('dialog-ok')
self._keep_button.set_tooltip(_('Keep'))
self._keep_button.connect('clicked', self.__keep_button_clicked_cb)
self.insert(self._keep_button, -1)
self._keep_button.show()
def _add_separator(self, expand=False):
separator = gtk.SeparatorToolItem()
separator.props.draw = False
if expand:
separator.set_expand(True)
else:
separator.set_size_request(style.DEFAULT_SPACING, -1)
self.insert(separator, -1)
separator.show()
def _add_widget(self, widget, expand=False):
tool_item = gtk.ToolItem()
tool_item.set_expand(expand)
tool_item.add(widget)
widget.show()
self.insert(tool_item, -1)
tool_item.show()
def __keep_button_clicked_cb(self, widget, data=None):
self.emit('keep-clicked')
class FavoriteIcon(CanvasIcon):
def __init__(self, favorite):
CanvasIcon.__init__(self, icon_name='emblem-favorite',
box_width=style.GRID_CELL_SIZE * 3 / 5,
size=style.SMALL_ICON_SIZE)
self._favorite = None
self.set_favorite(favorite)
self.connect('button-release-event', self.__release_event_cb)
self.connect('motion-notify-event', self.__motion_notify_event_cb)
def set_favorite(self, favorite):
if favorite == self._favorite:
return
self._favorite = favorite
if favorite:
client = gconf.client_get_default()
color = XoColor(client.get_string('/desktop/sugar/user/color'))
self.props.xo_color = color
else:
self.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg()
self.props.fill_color = style.COLOR_WHITE.get_svg()
def get_favorite(self):
return self._favorite
favorite = gobject.property(
type=bool, default=False, getter=get_favorite, setter=set_favorite)
def __release_event_cb(self, icon, event):
self.props.favorite = not self.props.favorite
def __motion_notify_event_cb(self, icon, event):
if not self._favorite:
if event.detail == hippo.MOTION_DETAIL_ENTER:
icon.props.fill_color = style.COLOR_BUTTON_GREY.get_svg()
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg()
class NamingAlert(gtk.Window):
__gtype_name__ = 'SugarNamingAlert'
def __init__(self, activity, bundle_path):
gtk.Window.__init__(self)
self._bundle_path = bundle_path
self._favorite_icon = None
self._title = None
self._description = None
self._tags = None
self.set_border_width(style.LINE_WIDTH)
offset = style.GRID_CELL_SIZE
width = gtk.gdk.screen_width() - offset * 2
height = gtk.gdk.screen_height() - offset * 2
self.set_size_request(width, height)
self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
self.set_decorated(False)
self.set_resizable(False)
self.set_modal(True)
self.connect('realize', self.__realize_cb)
self._activity = activity
vbox = gtk.VBox()
self.add(vbox)
vbox.show()
toolbar = NamingToolbar()
toolbar.connect('keep-clicked', self.__keep_cb)
vbox.pack_start(toolbar, False)
toolbar.show()
canvas = hippo.Canvas()
self._root = hippo.CanvasBox()
self._root.props.background_color = style.COLOR_WHITE.get_int()
canvas.set_root(self._root)
vbox.pack_start(canvas)
canvas.show()
body = self._create_body()
self._root.append(body, hippo.PACK_EXPAND)
def _create_body(self):
body = hippo.CanvasBox()
body.props.orientation = hippo.ORIENTATION_VERTICAL
body.props.background_color = style.COLOR_WHITE.get_int()
body.props.padding_top = style.DEFAULT_SPACING * 3
header = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL,
padding=style.DEFAULT_PADDING,
padding_right=style.GRID_CELL_SIZE,
spacing=style.DEFAULT_SPACING)
body.append(header)
descriptions = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL,
spacing=style.DEFAULT_SPACING * 3,
padding_left=style.GRID_CELL_SIZE,
padding_right=style.GRID_CELL_SIZE,
padding_top=style.DEFAULT_SPACING * 3)
body.append(descriptions, hippo.PACK_EXPAND)
first_column = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL,
spacing=style.DEFAULT_SPACING)
descriptions.append(first_column)
second_column = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL,
spacing=style.DEFAULT_SPACING)
descriptions.append(second_column, hippo.PACK_EXPAND)
self._favorite_icon = self._create_favorite_icon()
header.append(self._favorite_icon)
activity_icon = self._create_activity_icon()
header.append(activity_icon)
self._title = self._create_title()
header.append(self._title, hippo.PACK_EXPAND)
if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
header.reverse()
description_box, self._description = self._create_description()
second_column.append(description_box)
tags_box, self._tags = self._create_tags()
second_column.append(tags_box)
return body
def _create_favorite_icon(self):
favorite_icon = FavoriteIcon(False)
return favorite_icon
def _create_activity_icon(self):
activity_bundle = ActivityBundle(self._bundle_path)
activity_icon = CanvasIcon(file_name=activity_bundle.get_icon())
if self._activity.metadata.has_key('icon-color') and \
self._activity.metadata['icon-color']:
activity_icon.props.xo_color = XoColor( \
self._activity.metadata['icon-color'])
return activity_icon
def _create_title(self):
title = CanvasEntry()
title.set_background(style.COLOR_WHITE.get_html())
title.props.text = self._activity.metadata.get('title', _('Untitled'))
return title
def _create_description(self):
vbox = hippo.CanvasBox()
vbox.props.spacing = style.DEFAULT_SPACING
text = hippo.CanvasText(text=_('Description:'),
font_desc=style.FONT_NORMAL.get_pango_desc())
text.props.color = style.COLOR_BUTTON_GREY.get_int()
if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
text.props.xalign = hippo.ALIGNMENT_END
else:
text.props.xalign = hippo.ALIGNMENT_START
vbox.append(text)
description = self._activity.metadata.get('description', '')
text_view = CanvasTextView(description,
box_height=style.GRID_CELL_SIZE * 2)
vbox.append(text_view, hippo.PACK_EXPAND)
text_view.text_view_widget.props.accepts_tab = False
return vbox, text_view
def _create_tags(self):
vbox = hippo.CanvasBox()
vbox.props.spacing = style.DEFAULT_SPACING
text = hippo.CanvasText(text=_('Tags:'),
font_desc=style.FONT_NORMAL.get_pango_desc())
text.props.color = style.COLOR_BUTTON_GREY.get_int()
if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
text.props.xalign = hippo.ALIGNMENT_END
else:
text.props.xalign = hippo.ALIGNMENT_START
vbox.append(text)
tags = self._activity.metadata.get('tags', '')
text_view = CanvasTextView(tags, box_height=style.GRID_CELL_SIZE * 2)
vbox.append(text_view, hippo.PACK_EXPAND)
text_view.text_view_widget.props.accepts_tab = False
return vbox, text_view
def __realize_cb(self, widget):
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
self.window.set_accept_focus(True)
def __keep_cb(self, widget):
is_favorite = self._favorite_icon.get_favorite()
if is_favorite:
self._activity.metadata['keep'] = 1
else:
self._activity.metadata['keep'] = 0
self._activity.metadata['title'] = self._title.props.text
new_tags = self._tags.text_view_widget.props.buffer.props.text
self._activity.metadata['tags'] = new_tags
new_description = \
self._description.text_view_widget.props.buffer.props.text
self._activity.metadata['description'] = new_description
self._activity.metadata['title_set_by_user'] = '1'
self._activity.close()

View File

@ -3,6 +3,7 @@ sugar_PYTHON = \
__init__.py \ __init__.py \
alert.py \ alert.py \
animator.py \ animator.py \
canvastextview.py \
combobox.py \ combobox.py \
colorbutton.py \ colorbutton.py \
entry.py \ entry.py \

View File

@ -0,0 +1,39 @@
# 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 gtk
import hippo
from sugar.graphics import style
class CanvasTextView(hippo.CanvasWidget):
def __init__(self, text, **kwargs):
hippo.CanvasWidget.__init__(self, **kwargs)
self.text_view_widget = gtk.TextView()
self.text_view_widget.props.buffer.props.text = text
self.text_view_widget.props.left_margin = style.DEFAULT_SPACING
self.text_view_widget.props.right_margin = style.DEFAULT_SPACING
self.text_view_widget.props.wrap_mode = gtk.WRAP_WORD
self.text_view_widget.show()
# TODO: These fields should expand vertically instead of scrolling
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_shadow_type(gtk.SHADOW_OUT)
scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
scrolled_window.add(self.text_view_widget)
self.props.widget = scrolled_window