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,282 +14,39 @@
# along with this program; if not, write to the Free Software
# 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 hippo
import logging
from gettext import gettext as _
import os
from ConfigParser import ConfigParser
from sugar import env
from sugar.graphics import units
from sugar.graphics import style
from sugar.graphics import color
from sugar.graphics import iconbutton
from sugar.graphics.canvasentry import CanvasEntry
import colorpicker
_VIDEO_WIDTH = units.points_to_pixels(160)
_VIDEO_HEIGHT = units.points_to_pixels(120)
class IntroImage(gtk.EventBox):
__gtype_name__ = "IntroImage"
class _NamePage(hippo.CanvasBox):
def __init__(self, **kwargs):
gtk.EventBox.__init__(self, **kwargs)
self._image = gtk.Image()
self.add(self._image)
hippo.CanvasBox.__init__(self, xalign=hippo.ALIGNMENT_CENTER,
spacing=style.DEFAULT_SPACING,
orientation=hippo.ORIENTATION_HORIZONTAL,
**kwargs)
def set_pixbuf(self, pixbuf):
if pixbuf:
self._image.set_from_pixbuf(pixbuf)
else:
self._image.clear()
label = hippo.CanvasText(text=_("Name:"))
self.append(label)
self._entry = CanvasEntry(box_width=style.zoom(300))
self._entry.props.widget.set_max_length(45)
self.append(self._entry)
class IntroFallbackVideo(gtk.EventBox):
__gtype_name__ = "IntroFallbackVideo"
def get_name(self):
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):
"""Returns None if a bad nickname, returns the corrected nickname
otherwise"""
@ -304,27 +61,112 @@ class IntroBox(hippo.CanvasBox, hippo.CanvasItem):
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):
def __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._intro_box = IntroBox(background_color=0x000000ff,
yalign=hippo.ALIGNMENT_START,
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._intro_box = _IntroBox()
self._intro_box.connect('done', self._done_cb)
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()
gobject.idle_add(self._create_profile, pixbuf, name, color)
@ -367,6 +209,6 @@ class IntroWindow(gtk.Window):
if __name__ == "__main__":
w = IntroWindow()
w.show_all()
w.show()
w.connect('destroy', gtk.main_quit)
gtk.main()

View File

@ -25,7 +25,7 @@ def _get_screen_dpi():
def _compute_zoom_factor():
return gtk.gdk.screen_width() / 1200.0
def _zoom(units):
def zoom(units):
return int(ZOOM_FACTOR * units)
def _compute_font_height(font):
@ -47,6 +47,40 @@ class Font(object):
def get_pango_desc(self):
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
_FOCUS_LINE_WIDTH = 2
@ -54,14 +88,18 @@ _TAB_CURVATURE = 1
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_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)
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_PANEL_GREY = Color('#C0C0C0')