First go at the new intro screen, work in progress.

This commit is contained in:
Marco Pesenti Gritti 2007-07-11 11:45:27 +02:00
parent e4bce9271a
commit 9dab5fffaf
2 changed files with 163 additions and 283 deletions

View File

@ -14,281 +14,38 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import gtk, gobject import os
from ConfigParser import ConfigParser
from gettext import gettext as _
import gtk
import gobject
import dbus import dbus
import hippo import hippo
import logging import logging
from gettext import gettext as _
import os
from ConfigParser import ConfigParser
from sugar import env from sugar import env
from sugar.graphics import units
from sugar.graphics import style from sugar.graphics import style
from sugar.graphics import color from sugar.graphics.canvasentry import CanvasEntry
from sugar.graphics import iconbutton
import colorpicker import colorpicker
_VIDEO_WIDTH = units.points_to_pixels(160) class _NamePage(hippo.CanvasBox):
_VIDEO_HEIGHT = units.points_to_pixels(120)
class IntroImage(gtk.EventBox):
__gtype_name__ = "IntroImage"
def __init__(self, **kwargs): def __init__(self, **kwargs):
gtk.EventBox.__init__(self, **kwargs) hippo.CanvasBox.__init__(self, xalign=hippo.ALIGNMENT_CENTER,
self._image = gtk.Image() spacing=style.DEFAULT_SPACING,
self.add(self._image) orientation=hippo.ORIENTATION_HORIZONTAL,
**kwargs)
def set_pixbuf(self, pixbuf): label = hippo.CanvasText(text=_("Name:"))
if pixbuf: self.append(label)
self._image.set_from_pixbuf(pixbuf)
else:
self._image.clear()
self._entry = CanvasEntry(box_width=style.zoom(300))
self._entry.props.widget.set_max_length(45)
self.append(self._entry)
class IntroFallbackVideo(gtk.EventBox): def get_name(self):
__gtype_name__ = "IntroFallbackVideo" return self._check_nickname(self._entry.props.text)
__gsignals__ = {
'pixbuf': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
}
def __init__(self, **kwargs):
gtk.EventBox.__init__(self, **kwargs)
self._image = gtk.Image()
self._image.set_from_stock(gtk.STOCK_OPEN, -1)
self.add(self._image)
self._image.show()
self.connect('button-press-event', self._button_press_event_cb)
def play(self):
pass
def stop(self):
pass
def _button_press_event_cb(self, widget, event):
filt = gtk.FileFilter()
filt.add_pixbuf_formats()
chooser = gtk.FileChooserDialog(_("Pick a buddy picture"), \
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
chooser.set_filter(filt)
resp = chooser.run()
if resp == gtk.RESPONSE_ACCEPT:
fname = chooser.get_filename()
self.load_image(fname)
chooser.hide()
chooser.destroy()
return True
def load_image(self, path):
pixbuf = gtk.gdk.pixbuf_new_from_file(path)
self.emit('pixbuf', pixbuf)
class VideoBox(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = "SugarVideoBox"
def __init__(self, **kwargs):
hippo.CanvasBox.__init__(self, **kwargs)
self.props.orientation = hippo.ORIENTATION_HORIZONTAL
self._pixbuf = None
self._label = hippo.CanvasText(text=_("My Picture:"),
xalign=hippo.ALIGNMENT_START,
padding_right=units.grid_to_pixels(0.5))
self._label.props.color = color.LABEL_TEXT.get_int()
self._label.props.font_desc = style.FONT_NORMAL.get_pango_desc()
self.append(self._label)
# check for camera and if not generate a .jpg
has_webcam = False
try:
sys_bus = dbus.SystemBus()
hal_obj = sys_bus.get_object ('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
hal = dbus.Interface (hal_obj, 'org.freedesktop.Hal.Manager')
udis = hal.FindDeviceByCapability ('video4linux')
# check for the olpc specific camera
if not udis:
udis = hal.FindDeviceStringMatch('info.linux.driver','cafe1000-ccic')
if udis:
has_webcam = True
finally:
if has_webcam:
import glive
self._video = glive.LiveVideoSlot(_VIDEO_WIDTH, _VIDEO_HEIGHT)
else:
self._video = IntroFallbackVideo()
self._video.set_size_request(_VIDEO_WIDTH, _VIDEO_HEIGHT)
self._video.connect('pixbuf', self._new_pixbuf_cb)
self._video_widget = hippo.CanvasWidget()
self._video_widget.props.widget = self._video
self.append(self._video_widget)
gobject.idle_add(self._video.play)
self._img = IntroImage()
self._img.set_size_request(_VIDEO_WIDTH, _VIDEO_HEIGHT)
self._img.connect('button-press-event', self._clear_image_cb)
self._img_widget = hippo.CanvasWidget()
self._img_widget.props.widget = self._img
if not has_webcam:
path = os.path.join(os.path.dirname(__file__),
'default-picture.png')
self._video.load_image(path)
def _clear_image_cb(self, widget, event):
del self._pixbuf
self._pixbuf = None
self.remove(self._img_widget)
self._img.set_pixbuf(None)
self.append(self._video_widget)
self._video.play()
def _new_pixbuf_cb(self, widget, pixbuf):
if self._pixbuf:
del self._pixbuf
self._pixbuf = pixbuf
self._video.stop()
self.remove(self._video_widget)
scaled = pixbuf.scale_simple(_VIDEO_WIDTH, _VIDEO_HEIGHT, gtk.gdk.INTERP_BILINEAR)
self._img.set_pixbuf(scaled)
self._img.show_all()
self.append(self._img_widget)
def get_pixbuf(self):
return self._pixbuf
class EntryBox(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = "SugarEntryBox"
def __init__(self, **kwargs):
hippo.CanvasBox.__init__(self, **kwargs)
self.props.orientation = hippo.ORIENTATION_HORIZONTAL
self._label = hippo.CanvasText(text=_("My Name:"),
xalign=hippo.ALIGNMENT_START,
padding_right=units.grid_to_pixels(0.5))
self._label.props.color = color.LABEL_TEXT.get_int()
self._label.props.font_desc = style.FONT_NORMAL.get_pango_desc()
self.append(self._label)
self._entry = gtk.Entry()
self._entry.set_max_length(45)
entry_item = hippo.CanvasWidget(widget=self._entry)
self.append(entry_item)
def get_text(self):
return self._entry.props.text
def flash_label(self):
"""Briefly flashes the label to draw the user's attention to the
control"""
old_fg_color = color.LABEL_TEXT.get_int()
old_bg_color = 0x000000ff # background color set above
r,g,b,a = color.LABEL_TEXT.get_rgba()
fg_opposite = color.RGBColor(1 - r, 1 - g, 1 - b)
bg_opposite = color.RGBColor(1, 1, 1)
self._label.props.color = fg_opposite.get_int()
self._label.props.background_color = bg_opposite.get_int()
gobject.timeout_add(200, self._flash_reset, old_fg_color, old_bg_color)
def _flash_reset(self, old_fg_color, old_bg_color):
self._label.props.color = old_fg_color
self._label.props.background_color = old_bg_color
return False
class ColorBox(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = "SugarColorBox"
def __init__(self, **kwargs):
hippo.CanvasBox.__init__(self, **kwargs)
self.props.orientation = hippo.ORIENTATION_HORIZONTAL
self._color = None
self._label = hippo.CanvasText(text=_("My Color:"),
xalign=hippo.ALIGNMENT_START,
padding_right=units.grid_to_pixels(0.5))
self._label.props.color = color.LABEL_TEXT.get_int()
self._label.props.font_desc = style.FONT_NORMAL.get_pango_desc()
self.append(self._label)
self._cp = colorpicker.ColorPicker()
self._cp.connect('color', self._new_color_cb)
self.append(self._cp)
self._color = self._cp.get_color()
def _new_color_cb(self, widget, color):
self._color = color
def get_color(self):
return self._color
class IntroBox(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'SugarIntroBox'
__gsignals__ = {
'ok': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]))
}
def __init__(self, **kwargs):
hippo.CanvasBox.__init__(self, **kwargs)
self._pixbuf = None
#self._video_box = VideoBox(xalign=hippo.ALIGNMENT_CENTER,
# yalign=hippo.ALIGNMENT_START,
# padding_bottom=units.grid_to_pixels(0.5))
#self.append(self._video_box)
self._entry_box = EntryBox(xalign=hippo.ALIGNMENT_CENTER,
padding_bottom=units.grid_to_pixels(0.5))
self.append(self._entry_box)
self._color_box = ColorBox(xalign=hippo.ALIGNMENT_CENTER,
padding_bottom=units.grid_to_pixels(0.5))
self.append(self._color_box)
self._ok = iconbutton.IconButton(icon_name="theme:go-next",
padding_bottom=units.grid_to_pixels(0.5))
self._ok.connect('activated', self._ok_activated)
self.append(self._ok)
def _ok_activated(self, item):
#pixbuf = self._video_box.get_pixbuf()
path = os.path.join(os.path.dirname(__file__),
'default-picture.png')
pixbuf = gtk.gdk.pixbuf_new_from_file(path)
name = self._entry_box.get_text()
color = self._color_box.get_color()
name = self._check_nickname(name)
if name is None:
self._entry_box.flash_label()
return
if not pixbuf or not name or not color:
print "not one of pixbuf(%r), name(%r), or color(%r)"
return
self.emit('ok', pixbuf, name, color)
def _check_nickname(self, name): def _check_nickname(self, name):
"""Returns None if a bad nickname, returns the corrected nickname """Returns None if a bad nickname, returns the corrected nickname
@ -304,27 +61,112 @@ class IntroBox(hippo.CanvasBox, hippo.CanvasItem):
return name return name
class _ColorPage(hippo.CanvasBox):
def __init__(self, **kwargs):
hippo.CanvasBox.__init__(self, xalign=hippo.ALIGNMENT_CENTER,
spacing=style.DEFAULT_SPACING,
yalign=hippo.ALIGNMENT_CENTER,
**kwargs)
self._color = None
self._label = hippo.CanvasText(text=_("Click to change color:"),
xalign=hippo.ALIGNMENT_CENTER)
self.append(self._label)
self._cp = colorpicker.ColorPicker(xalign=hippo.ALIGNMENT_CENTER)
self._cp.connect('color', self._new_color_cb)
self.append(self._cp)
self._color = self._cp.get_color()
def _new_color_cb(self, widget, color):
self._color = color
def get_color(self):
return self._color
class _IntroBox(hippo.CanvasBox):
__gsignals__ = {
'done': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
gobject.TYPE_PYOBJECT]))
}
PAGE_NAME = 0
PAGE_COLOR = 1
PAGE_FIRST = PAGE_NAME
PAGE_LAST = PAGE_COLOR
def __init__(self):
hippo.CanvasBox.__init__(self, padding=style.zoom(30))
self._page = self.PAGE_NAME
page_color = style.COLOR_PANEL_GREY.get_int()
self._name_page = _NamePage(background_color=page_color)
self._color_page = _ColorPage(background_color=page_color)
self._setup_page()
def _setup_page(self):
self.remove_all()
if self._page == self.PAGE_NAME:
self.append(self._name_page, hippo.PACK_EXPAND)
elif self._page == self.PAGE_COLOR:
self.append(self._color_page, hippo.PACK_EXPAND)
button_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL)
if self._page != self.PAGE_FIRST:
back_button = hippo.CanvasButton(text=_('Back'))
back_button.connect('activated', self._done_activated_cb)
button_box.append(back_button)
spacer = hippo.CanvasBox()
button_box.append(spacer, hippo.PACK_EXPAND)
if self._page == self.PAGE_LAST:
done_button = hippo.CanvasButton(text=_('Done'))
done_button.connect('activated', self._done_activated_cb)
button_box.append(done_button)
else:
next_button = hippo.CanvasButton(text=_('Next'))
next_button.connect('activated', self._next_activated_cb)
button_box.append(next_button)
self.append(button_box)
def _back_activated_cb(self, item):
self._page -= 1
self._setup_page()
def _next_activated_cb(self, item):
self._page += 1
self._setup_page()
def _done_activated_cb(self, item):
path = os.path.join(os.path.dirname(__file__), 'default-picture.png')
pixbuf = gtk.gdk.pixbuf_new_from_file(path)
name = self._name_page.get_name()
color = self._color_page.get_color()
self.emit('done', pixbuf, name, color)
class IntroWindow(gtk.Window): class IntroWindow(gtk.Window):
def __init__(self): def __init__(self):
gtk.Window.__init__(self) gtk.Window.__init__(self)
self.set_default_size(gtk.gdk.screen_width(),
gtk.gdk.screen_height())
self.realize()
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DESKTOP)
self._canvas = hippo.Canvas() self._canvas = hippo.Canvas()
self._intro_box = IntroBox(background_color=0x000000ff, self._intro_box = _IntroBox()
yalign=hippo.ALIGNMENT_START, self._intro_box.connect('done', self._done_cb)
padding_top=units.grid_to_pixels(2),
padding_left=units.grid_to_pixels(3),
padding_right=units.grid_to_pixels(3))
self._intro_box.connect('ok', self._ok_cb)
self._canvas.set_root(self._intro_box) self._canvas.set_root(self._intro_box)
self.add(self._canvas)
self._canvas.show_all()
def _ok_cb(self, widget, pixbuf, name, color): self.add(self._canvas)
self._canvas.show()
def _done_cb(self, box, pixbuf, name, color):
self.hide() self.hide()
gobject.idle_add(self._create_profile, pixbuf, name, color) gobject.idle_add(self._create_profile, pixbuf, name, color)
@ -367,6 +209,6 @@ class IntroWindow(gtk.Window):
if __name__ == "__main__": if __name__ == "__main__":
w = IntroWindow() w = IntroWindow()
w.show_all() w.show()
w.connect('destroy', gtk.main_quit) w.connect('destroy', gtk.main_quit)
gtk.main() gtk.main()

View File

@ -25,7 +25,7 @@ def _get_screen_dpi():
def _compute_zoom_factor(): def _compute_zoom_factor():
return gtk.gdk.screen_width() / 1200.0 return gtk.gdk.screen_width() / 1200.0
def _zoom(units): def zoom(units):
return int(ZOOM_FACTOR * units) return int(ZOOM_FACTOR * units)
def _compute_font_height(font): def _compute_font_height(font):
@ -47,6 +47,40 @@ class Font(object):
def get_pango_desc(self): def get_pango_desc(self):
return pango.FontDescription(self._desc) return pango.FontDescription(self._desc)
class Color(object):
def __init__(self, color, alpha=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)
_XO_DPI = 200.0 _XO_DPI = 200.0
_FOCUS_LINE_WIDTH = 2 _FOCUS_LINE_WIDTH = 2
@ -54,14 +88,18 @@ _TAB_CURVATURE = 1
ZOOM_FACTOR = _compute_zoom_factor() ZOOM_FACTOR = _compute_zoom_factor()
FONT_SIZE = _zoom(7 * _XO_DPI / _get_screen_dpi()) DEFAULT_SPACING = zoom(6)
FONT_SIZE = zoom(7 * _XO_DPI / _get_screen_dpi())
FONT_NORMAL = Font('Bitstream Vera Sans %d' % FONT_SIZE) FONT_NORMAL = Font('Bitstream Vera Sans %d' % FONT_SIZE)
FONT_BOLD = Font('Bitstream Vera Sans bold %d' % FONT_SIZE) FONT_BOLD = Font('Bitstream Vera Sans bold %d' % FONT_SIZE)
FONT_NORMAL_H = _compute_font_height(FONT_NORMAL) FONT_NORMAL_H = _compute_font_height(FONT_NORMAL)
FONT_BOLD_H = _compute_font_height(FONT_BOLD) FONT_BOLD_H = _compute_font_height(FONT_BOLD)
TOOLBOX_SEPARATOR_HEIGHT = _zoom(9) TOOLBOX_SEPARATOR_HEIGHT = zoom(9)
TOOLBOX_HORIZONTAL_PADDING = _zoom(75) TOOLBOX_HORIZONTAL_PADDING = zoom(75)
TOOLBOX_TAB_VBORDER = int((_zoom(36) - FONT_NORMAL_H - _FOCUS_LINE_WIDTH) / 2) 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_HBORDER = zoom(15) - _FOCUS_LINE_WIDTH - _TAB_CURVATURE
TOOLBOX_TAB_LABEL_WIDTH = _zoom(150 - 15 * 2) TOOLBOX_TAB_LABEL_WIDTH = zoom(150 - 15 * 2)
COLOR_PANEL_GREY = Color('#C0C0C0')