Merge branch 'master' of git+ssh://guillaume@dev.laptop.org/git/sugar

This commit is contained in:
Guillaume Desmottes 2007-02-28 17:02:52 +01:00
commit 31fa414e42
15 changed files with 251 additions and 99 deletions

View File

@ -19,19 +19,71 @@
#include <stdlib.h> #include <stdlib.h>
#include <gdk/gdkx.h> #include <gdk/gdkx.h>
#include <gdk/gdkscreen.h>
#include <gtk/gtksettings.h>
#include "sugar-utils.h" #include "sugar-utils.h"
/* Ported from mozilla nsDeviceContextGTK.cpp */
static gint
get_gtk_settings_dpi(void)
{
GtkSettings *settings = gtk_settings_get_default();
GParamSpec *spec;
gint dpi = 0;
spec = g_object_class_find_property(
G_OBJECT_GET_CLASS(G_OBJECT(settings)), "gtk-xft-dpi");
if (spec) {
g_object_get(G_OBJECT(settings),
"gtk-xft-dpi", &dpi,
NULL);
}
return (int)(dpi / 1024.0 + 0.5);
}
static gint
get_xft_dpi(void)
{
char *val = XGetDefault(GDK_DISPLAY(), "Xft", "dpi");
if (val) {
char *e;
double d = strtod(val, &e);
if (e != val)
return (int)(d + 0.5);
}
return 0;
}
static int
get_dpi_from_physical_resolution(void)
{
float screen_width_in;
screen_width_in = (float)(gdk_screen_width_mm()) / 25.4f;
return (int)((float)(gdk_screen_width()) / screen_width_in + 0.5);
}
gint gint
sugar_get_screen_dpi(void) sugar_get_screen_dpi(void)
{ {
char *val = XGetDefault (GDK_DISPLAY(), "Xft", "dpi"); int dpi;
if (val) {
char *e; dpi = get_gtk_settings_dpi();
double d = strtod(val, &e);
if (d > 0.0) if (dpi == 0) {
return (int)(d+0.5); dpi = get_xft_dpi();
} }
return 96; if (dpi == 0) {
dpi = get_dpi_from_physical_resolution();
}
return dpi;
} }

View File

@ -48,23 +48,13 @@ class ClipboardIcon(CanvasIcon):
else: else:
self.props.xo_color = XoColor("#000000,#FFFFFF") self.props.xo_color = XoColor("#000000,#FFFFFF")
def _activity_create_success_cb(self, handler, activity):
activity.start(util.unique_id())
activity.execute("open_document", [self._object_id])
def _activity_create_error_cb(self, handler, err):
pass
def _open_file(self): def _open_file(self):
if self._percent < 100 or not self._activity: if self._percent < 100 or not self._activity:
return return
logging.debug("_icon_activated_cb: " + self._object_id) logging.debug("_icon_activated_cb: " + self._object_id)
# Launch the activity to handle this item activityfactory.create_with_uri(self._activity, self._object_id)
handler = activityfactory.create(self._activity)
handler.connect('success', self._activity_create_success_cb)
handler.connect('error', self._activity_create_error_cb)
def _icon_activated_cb(self, icon): def _icon_activated_cb(self, icon):
self._open_file() self._open_file()

View File

@ -1,6 +1,11 @@
from view.devices import deviceview from sugar.graphics import canvasicon
class DeviceView(deviceview.DeviceView): _ICON_NAME = 'device-battery'
class DeviceView(canvasicon.CanvasIcon):
def __init__(self, model): def __init__(self, model):
deviceview.DeviceView.__init__(self, model) canvasicon.CanvasIcon.__init__(self)
self.props.icon_name = 'theme:stock-close' self._model = model
icon_name = canvasicon.get_icon_state(_ICON_NAME, 60)
self.props.icon_name = icon_name

View File

@ -1,10 +1,5 @@
from sugar.graphics.canvasicon import CanvasIcon from sugar.graphics.canvasicon import CanvasIcon
class DeviceView(CanvasIcon):
def __init__(self, model):
CanvasIcon.__init__(self)
self.model = model
def create(model): def create(model):
name = 'view.devices.' + model.get_type() name = 'view.devices.' + model.get_type()

View File

@ -15,20 +15,16 @@
# 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
from view.devices import deviceview from sugar.graphics import canvasicon
from sugar.graphics import color
from model.devices import wirelessnetwork from model.devices import wirelessnetwork
from view.pulsingicon import PulsingIcon
_strength_to_icon = { _ICON_NAME = 'device-network-wireless'
(0, 20) : 'stock-net-wireless-00',
(21, 40) : 'stock-net-wireless-21-40',
(41, 60) : 'stock-net-wireless-41-60',
(61, 80) : 'stock-net-wireless-61-80',
(81, 100) : 'stock-net-wireless-81-100'
}
class DeviceView(deviceview.DeviceView): class DeviceView(PulsingIcon):
def __init__(self, model): def __init__(self, model):
deviceview.DeviceView.__init__(self, model) PulsingIcon.__init__(self)
self._model = model self._model = model
model.connect('notify::name', self._name_changed_cb) model.connect('notify::name', self._name_changed_cb)
@ -52,18 +48,20 @@ class DeviceView(deviceview.DeviceView):
self.props.tooltip = self._model.props.name self.props.tooltip = self._model.props.name
def _update_icon(self): def _update_icon(self):
strength = self._model.props.strength icon_name = canvasicon.get_icon_state(
for interval in _strength_to_icon.keys(): _ICON_NAME, self._model.props.strength)
if strength >= interval[0] and strength <= interval[1]: if icon_name:
stock_name = _strength_to_icon[interval] self.props.icon_name = icon_name
self.props.icon_name = 'theme:' + stock_name
def _update_state(self): def _update_state(self):
# FIXME Change icon colors once we have real icons # FIXME Change icon colors once we have real icons
state = self._model.props.state state = self._model.props.state
if state == wirelessnetwork.STATE_ACTIVATING: if state == wirelessnetwork.STATE_ACTIVATING:
self.props.background_color = 0xFF0000FF self.props.fill_color = color.ICON_FILL_INACTIVE
self.props.stroke_color = color.ICON_STROKE_INACTIVE
elif state == wirelessnetwork.STATE_ACTIVATED: elif state == wirelessnetwork.STATE_ACTIVATED:
self.props.background_color = 0x00FF00FF self.props.fill_color = None
self.props.stroke_color = None
elif state == wirelessnetwork.STATE_INACTIVE: elif state == wirelessnetwork.STATE_INACTIVE:
self.props.background_color = 0x00000000 self.props.fill_color = color.ICON_FILL_INACTIVE
self.props.stroke_color = color.ICON_STROKE_INACTIVE

View File

@ -22,21 +22,18 @@ import gobject
from sugar.graphics.spreadbox import SpreadBox from sugar.graphics.spreadbox import SpreadBox
from sugar.graphics.snowflakebox import SnowflakeBox from sugar.graphics.snowflakebox import SnowflakeBox
from sugar.graphics.canvasicon import CanvasIcon from sugar.graphics.canvasicon import CanvasIcon
from sugar.graphics import color
from sugar.graphics import canvasicon
from model import accesspointmodel from model import accesspointmodel
from hardware import hardwaremanager from hardware import hardwaremanager
from view.BuddyIcon import BuddyIcon from view.BuddyIcon import BuddyIcon
from view.pulsingicon import PulsingIcon
_strength_to_icon = { _ICON_NAME = 'device-network-wireless'
(0, 20) : 'stock-net-wireless-00',
(21, 40) : 'stock-net-wireless-21-40',
(41, 60) : 'stock-net-wireless-41-60',
(61, 80) : 'stock-net-wireless-61-80',
(81, 100) : 'stock-net-wireless-81-100'
}
class AccessPointView(CanvasIcon): class AccessPointView(PulsingIcon):
def __init__(self, model): def __init__(self, model):
CanvasIcon.__init__(self) PulsingIcon.__init__(self)
self._model = model self._model = model
self.connect('activated', self._activate_cb) self.connect('activated', self._activate_cb)
@ -45,6 +42,11 @@ class AccessPointView(CanvasIcon):
model.connect('notify::name', self._name_changed_cb) model.connect('notify::name', self._name_changed_cb)
model.connect('notify::state', self._state_changed_cb) model.connect('notify::state', self._state_changed_cb)
self.props.colors = [
[ None, None ],
[ color.ICON_FILL_INACTIVE, color.ICON_STROKE_INACTIVE ]
]
self._update_icon() self._update_icon()
self._update_name() self._update_name()
self._update_state() self._update_state()
@ -69,20 +71,22 @@ class AccessPointView(CanvasIcon):
self.props.tooltip = self._model.props.name self.props.tooltip = self._model.props.name
def _update_icon(self): def _update_icon(self):
strength = self._model.props.strength icon_name = canvasicon.get_icon_state(
for interval in _strength_to_icon.keys(): _ICON_NAME, self._model.props.strength)
if strength >= interval[0] and strength <= interval[1]: if icon_name:
stock_name = _strength_to_icon[interval] self.props.icon_name = icon_name
self.props.icon_name = 'theme:' + stock_name
def _update_state(self): def _update_state(self):
# FIXME Change icon colors once we have real icons
if self._model.props.state == accesspointmodel.STATE_CONNECTING: if self._model.props.state == accesspointmodel.STATE_CONNECTING:
self.props.background_color = 0xFF0000FF self.props.pulsing = True
elif self._model.props.state == accesspointmodel.STATE_CONNECTED: elif self._model.props.state == accesspointmodel.STATE_CONNECTED:
self.props.background_color = 0x00FF00FF self.props.pulsing = False
self.props.fill_color = None
self.props.stroke_color = None
elif self._model.props.state == accesspointmodel.STATE_NOTCONNECTED: elif self._model.props.state == accesspointmodel.STATE_NOTCONNECTED:
self.props.background_color = 0x00000000 self.props.pulsing = False
self.props.fill_color = color.ICON_FILL_INACTIVE
self.props.stroke_color = color.ICON_STROKE_INACTIVE
class ActivityView(SnowflakeBox): class ActivityView(SnowflakeBox):
def __init__(self, shell, menu_shell, model): def __init__(self, shell, menu_shell, model):

78
shell/view/pulsingicon.py Normal file
View File

@ -0,0 +1,78 @@
# Copyright (C) 2006, Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import gobject
from sugar.graphics.canvasicon import CanvasIcon
class PulsingIcon(CanvasIcon):
__gproperties__ = {
'colors' : (object, None, None,
gobject.PARAM_READWRITE),
'pulsing' : (bool, None, None, False,
gobject.PARAM_READWRITE)
}
def __init__(self, **kwargs):
self._pulsing = False
self._colors = None
self._pulse_sid = 0
self._pos = 0
CanvasIcon.__init__(self, **kwargs)
def do_set_property(self, pspec, value):
CanvasIcon.do_set_property(self, pspec, value)
if pspec.name == 'pulsing':
self._pulsing = value
if self._pulsing:
self._start()
else:
self._stop()
elif pspec.name == 'colors':
self._colors = value
self._pos = 0
def do_get_property(self, pspec):
CanvasIcon.do_get_property(self, pspec, value)
if pspec.name == 'pulsing':
return self._pulsing
elif pspec.name == 'colors':
return self._colors
def _pulse_timeout(self):
if not self._colors:
return
self.props.stroke_color = self._colors[self._pos][0]
self.props.fill_color = self._colors[self._pos][1]
self._pos += 1
if self._pos == len(self._colors):
self._pos = 0
return True
def _start(self):
if self._pulse_sid == 0:
self._pulse_sid = gobject.timeout_add(1000, self._pulse_timeout)
def _stop(self):
if self._pulse_sid:
gobject.source_remove(self._pulse_sid)
self._pulse_sid = 0

View File

@ -36,6 +36,7 @@ else:
from sugar import env from sugar import env
from sugar import util from sugar import util
from sugar.emulator import Emulator from sugar.emulator import Emulator
import _sugar
if len(sys.argv) == 1: if len(sys.argv) == 1:
program = 'sugar-shell' program = 'sugar-shell'
@ -51,7 +52,9 @@ else:
width = 1200 width = 1200
height = 900 height = 900
emulator = Emulator(width, height, fullscreen) dpi = min(_sugar.get_screen_dpi(), 96)
emulator = Emulator(width, height, fullscreen, dpi)
emulator.start() emulator.start()
if sourcedir: if sourcedir:

View File

@ -78,7 +78,7 @@ class MatchboxProcess(Process):
return 'Matchbox' return 'Matchbox'
class XephyrProcess(Process): class XephyrProcess(Process):
def __init__(self, width, height, fullscreen): def __init__(self, width, height, fullscreen, dpi):
self._display = get_display_number() self._display = get_display_number()
cmd = 'Xephyr :%d -ac ' % (self._display) cmd = 'Xephyr :%d -ac ' % (self._display)
@ -88,6 +88,9 @@ class XephyrProcess(Process):
if width > 0 and height > 0: if width > 0 and height > 0:
cmd += ' -screen %dx%d' % (width, height) cmd += ' -screen %dx%d' % (width, height)
if dpi > 0:
cmd += ' -dpi %d' % (dpi)
Process.__init__(self, cmd) Process.__init__(self, cmd)
def get_name(self): def get_name(self):
@ -100,15 +103,16 @@ class XephyrProcess(Process):
class Emulator(object): class Emulator(object):
"""The OLPC emulator""" """The OLPC emulator"""
def __init__(self, width, height, fullscreen): def __init__(self, width, height, fullscreen, dpi):
self._fullscreen = fullscreen self._fullscreen = fullscreen
self._width = width self._width = width
self._height = height self._height = height
self._dpi = dpi
def start(self): def start(self):
try: try:
process = XephyrProcess(self._width, self._height, process = XephyrProcess(self._width, self._height,
self._fullscreen) self._fullscreen, self._dpi)
process.start() process.start()
except: except:
print 'Cannot run the emulator. You need to install Xephyr' print 'Cannot run the emulator. You need to install Xephyr'

View File

@ -415,3 +415,15 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
Override this method for adding prelighting behavior. Override this method for adding prelighting behavior.
""" """
pass pass
def get_icon_state(base_name, perc):
step = 5
strength = round(perc / step) * step
icon_theme = gtk.icon_theme_get_default()
while strength <= 100:
icon_name = '%s-%03d' % (base_name, strength)
if icon_theme.has_icon(icon_name):
return 'theme:' + icon_name
strength = strength + step

View File

@ -21,7 +21,9 @@ _system_colors = {
'button-hover' : '#808080', 'button-hover' : '#808080',
'button-background-hover' : '#000000', 'button-background-hover' : '#000000',
'button-inactive' : '#808080', 'button-inactive' : '#808080',
'button-background-inactive' : '#424242' 'button-background-inactive' : '#424242',
'icon-stroke-inactive' : '#757575',
'icon-fill-inactive' : '#9D9FA1'
} }
def _html_to_rgb(html_color): def _html_to_rgb(html_color):
@ -100,3 +102,5 @@ BUTTON_HOVER = SystemColor('button-hover')
BUTTON_BACKGROUND_HOVER = SystemColor('button-background-hover') BUTTON_BACKGROUND_HOVER = SystemColor('button-background-hover')
BUTTON_INACTIVE = SystemColor('button-inactive') BUTTON_INACTIVE = SystemColor('button-inactive')
BUTTON_BACKGROUND_INACTIVE = SystemColor('button-background-inactive') BUTTON_BACKGROUND_INACTIVE = SystemColor('button-background-inactive')
ICON_FILL_INACTIVE = SystemColor('icon-fill-inactive')
ICON_STROKE_INACTIVE = SystemColor('icon-stroke-inactive')

View File

@ -39,8 +39,19 @@ class Entry(hippo.CanvasBox, hippo.CanvasItem):
'button-activated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([int])) 'button-activated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([int]))
} }
def __init__(self, text=''): def __init__(self, **kwargs):
hippo.CanvasBox.__init__(self, orientation=hippo.ORIENTATION_HORIZONTAL) self._entry = self.create_entry()
self._entry.props.text = ''
self._entry.props.has_frame = False
self._entry.modify_text(gtk.STATE_SELECTED,
color.BLACK.get_gdk_color())
self._entry.connect('focus-in-event', self._entry_focus_in_event_cb)
self._entry.connect('focus-out-event', self._entry_focus_out_event_cb)
self._entry.connect('activate', self._entry_activate_cb)
self._entry.modify_font(font.DEFAULT.get_pango_desc())
hippo.CanvasBox.__init__(self, **kwargs)
self.props.orientation = hippo.ORIENTATION_HORIZONTAL
self.props.yalign = hippo.ALIGNMENT_CENTER self.props.yalign = hippo.ALIGNMENT_CENTER
self._buttons = {} self._buttons = {}
@ -49,21 +60,12 @@ class Entry(hippo.CanvasBox, hippo.CanvasItem):
self._round_box.props.border_color = color.FRAME_BORDER.get_int() self._round_box.props.border_color = color.FRAME_BORDER.get_int()
self.append(self._round_box, hippo.PACK_EXPAND) self.append(self._round_box, hippo.PACK_EXPAND)
self._entry = self.create_entry()
self._entry.props.has_frame = False
self._entry.props.text = text
self._update_colors(focused=False)
self._entry.modify_text(gtk.STATE_SELECTED,
color.BLACK.get_gdk_color())
self._entry.connect('focus-in-event', self._entry_focus_in_event_cb)
self._entry.connect('focus-out-event', self._entry_focus_out_event_cb)
self._entry.connect('activate', self._entry_activate_cb)
self._entry.modify_font(font.DEFAULT.get_pango_desc())
self._canvas_widget = hippo.CanvasWidget() self._canvas_widget = hippo.CanvasWidget()
self._canvas_widget.props.widget = self._entry self._canvas_widget.props.widget = self._entry
self._round_box.append(self._canvas_widget, hippo.PACK_EXPAND) self._round_box.append(self._canvas_widget, hippo.PACK_EXPAND)
self._update_colors(focused=False)
def create_entry(self): def create_entry(self):
""" """
Subclasses can override this method in order to provide a different Subclasses can override this method in order to provide a different
@ -84,10 +86,16 @@ class Entry(hippo.CanvasBox, hippo.CanvasItem):
self._buttons[button] = action_id self._buttons[button] = action_id
def do_set_property(self, pspec, value): def do_set_property(self, pspec, value):
self._entry.set_property(pspec.name, value) if pspec.name in [param.name for param in self._entry.props]:
self._entry.set_property(pspec.name, value)
else:
hippo.CanvasBox.set_property(self, pspec.name, value)
def do_get_property(self, pspec): def do_get_property(self, pspec):
return self._entry.get_property(pspec.name) if pspec.name in [param.name for param in self._entry.props]:
return self._entry.get_property(pspec.name)
else:
return hippo.CanvasBox.get_property(self, pspec.name)
def _entry_focus_in_event_cb(self, widget, event): def _entry_focus_in_event_cb(self, widget, event):
self._update_colors(focused=True) self._update_colors(focused=True)

View File

@ -3,8 +3,8 @@ import pango
from sugar.graphics import units from sugar.graphics import units
_system_fonts = { _system_fonts = {
'default' : 'Bitstream Vera Sans %d' % units.points_to_pixels(9), 'default' : 'Bitstream Vera Sans %dpx' % units.points_to_pixels(9),
'default-bold' : 'Bitstream Vera Sans bold %d' % units.points_to_pixels(9) 'default-bold' : 'Bitstream Vera Sans bold %dpx' % units.points_to_pixels(9)
} }
class Font(object): class Font(object):

View File

@ -43,15 +43,16 @@ class IconButton(CanvasIcon):
CanvasIcon.__init__(self, cache=True, **kwargs) CanvasIcon.__init__(self, cache=True, **kwargs)
if not self.props.fill_color: if self._active:
self.props.fill_color = color.BUTTON_BACKGROUND_NORMAL self.props.fill_color = color.BUTTON_BACKGROUND_NORMAL
if not self.props.stroke_color:
self.props.stroke_color = color.BUTTON_NORMAL self.props.stroke_color = color.BUTTON_NORMAL
self.props.background_color = color.BUTTON_BACKGROUND_NORMAL.get_int() self.props.background_color = \
color.BUTTON_BACKGROUND_NORMAL.get_int()
self._normal_fill_color = self.props.fill_color else:
self._normal_stroke_color = self.props.stroke_color self.props.fill_color = color.BUTTON_BACKGROUND_INACTIVE
self._normal_background_color = self.props.background_color self.props.stroke_color = color.BUTTON_INACTIVE
self.props.background_color = \
color.BUTTON_BACKGROUND_INACTIVE.get_int()
self._set_size(STANDARD_SIZE) self._set_size(STANDARD_SIZE)
@ -76,13 +77,11 @@ class IconButton(CanvasIcon):
elif pspec.name == 'active': elif pspec.name == 'active':
self._active = value self._active = value
if self._active: if self._active:
self.props.fill_color = self._normal_fill_color self.props.fill_color = color.BUTTON_BACKGROUND_NORMAL
self.props.stroke_color = self._normal_stroke_color self.props.stroke_color = color.BUTTON_NORMAL
self.props.background_color = self._normal_background_color
else: else:
self.props.fill_color = color.BUTTON_BACKGROUND_INACTIVE self.props.fill_color = color.BUTTON_BACKGROUND_INACTIVE
self.props.stroke_color = color.BUTTON_INACTIVE self.props.stroke_color = color.BUTTON_INACTIVE
self.props.background_color = color.BUTTON_BACKGROUND_INACTIVE.get_int()
else: else:
CanvasIcon.do_set_property(self, pspec, value) CanvasIcon.do_set_property(self, pspec, value)
@ -104,5 +103,5 @@ class IconButton(CanvasIcon):
if self._active: if self._active:
self.props.background_color = color.BLACK.get_int() self.props.background_color = color.BLACK.get_int()
else: else:
if self._active: self.props.background_color = \
self.props.background_color = self._normal_background_color color.BUTTON_BACKGROUND_NORMAL.get_int()

View File

@ -1,6 +1,6 @@
VERSION=0.63 VERSION=0.63
DATE=`date +%Y%m%d` DATE=`date +%Y%m%d`
RELEASE=2.23 RELEASE=2.25
TARBALL=sugar-$VERSION-$RELEASE.${DATE}git.tar.bz2 TARBALL=sugar-$VERSION-$RELEASE.${DATE}git.tar.bz2
rm sugar-$VERSION.tar.bz2 rm sugar-$VERSION.tar.bz2