Convert to an ugly Hippo menu
This commit is contained in:
parent
4bf76960a0
commit
72832e0174
@ -2,7 +2,8 @@ sugardir = $(pkgdatadir)/services/nm
|
|||||||
sugar_PYTHON = \
|
sugar_PYTHON = \
|
||||||
__init__.py \
|
__init__.py \
|
||||||
nmclient.py \
|
nmclient.py \
|
||||||
nminfo.py
|
nminfo.py \
|
||||||
|
bubble.py
|
||||||
|
|
||||||
bin_SCRIPTS = sugar-nm-applet
|
bin_SCRIPTS = sugar-nm-applet
|
||||||
|
|
||||||
|
85
services/nm/bubble.py
Normal file
85
services/nm/bubble.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
# Copyright (C) 2006, Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# 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 math
|
||||||
|
|
||||||
|
import gobject
|
||||||
|
import gtk
|
||||||
|
import hippo
|
||||||
|
|
||||||
|
class Bubble(hippo.CanvasBox, hippo.CanvasItem):
|
||||||
|
__gtype_name__ = 'NetworkBubble'
|
||||||
|
|
||||||
|
__gproperties__ = {
|
||||||
|
'color' : (object, None, None,
|
||||||
|
gobject.PARAM_READWRITE),
|
||||||
|
'percent' : (object, None, None,
|
||||||
|
gobject.PARAM_READWRITE),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self._color = None
|
||||||
|
self._percent = 0
|
||||||
|
self._radius = 8
|
||||||
|
|
||||||
|
hippo.CanvasBox.__init__(self, **kwargs)
|
||||||
|
|
||||||
|
def do_set_property(self, pspec, value):
|
||||||
|
if pspec.name == 'color':
|
||||||
|
self._color = value
|
||||||
|
self.emit_paint_needed(0, 0, -1, -1)
|
||||||
|
elif pspec.name == 'percent':
|
||||||
|
self._percent = value
|
||||||
|
self.emit_paint_needed(0, 0, -1, -1)
|
||||||
|
|
||||||
|
def do_get_property(self, pspec):
|
||||||
|
if pspec.name == 'color':
|
||||||
|
return self._color
|
||||||
|
elif pspec.name == 'percent':
|
||||||
|
return self._percent
|
||||||
|
|
||||||
|
def _string_to_rgb(self, color_string):
|
||||||
|
col = gtk.gdk.color_parse(color_string)
|
||||||
|
return (col.red / 65535.0, col.green / 65535.0, col.blue / 65535.0)
|
||||||
|
|
||||||
|
def do_paint_below_children(self, cr, damaged_box):
|
||||||
|
[width, height] = self.get_allocation()
|
||||||
|
|
||||||
|
line_width = 3.0
|
||||||
|
x = line_width
|
||||||
|
y = line_width
|
||||||
|
width -= line_width * 2
|
||||||
|
height -= line_width * 2
|
||||||
|
|
||||||
|
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, x + 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);
|
||||||
|
|
||||||
|
color = self._string_to_rgb(self._color.get_fill_color())
|
||||||
|
cr.set_source_rgb(*color)
|
||||||
|
cr.fill_preserve();
|
||||||
|
|
||||||
|
color = self._string_to_rgb(self._color.get_stroke_color())
|
||||||
|
cr.set_source_rgb(*color)
|
||||||
|
cr.set_line_width(line_width)
|
||||||
|
cr.stroke();
|
@ -22,9 +22,15 @@ import dbus.decorators
|
|||||||
import gobject
|
import gobject
|
||||||
import gtk
|
import gtk
|
||||||
import logging
|
import logging
|
||||||
from sugar.graphics.menu import Menu
|
|
||||||
from gettext import gettext as _
|
|
||||||
import os
|
import os
|
||||||
|
from gettext import gettext as _
|
||||||
|
|
||||||
|
import hippo
|
||||||
|
from sugar.graphics.menu import Menu
|
||||||
|
from sugar.graphics import style
|
||||||
|
from sugar.graphics.iconcolor import IconColor
|
||||||
|
from sugar.graphics.timeline import Timeline
|
||||||
|
from bubble import Bubble
|
||||||
|
|
||||||
import nminfo
|
import nminfo
|
||||||
|
|
||||||
@ -106,18 +112,13 @@ class Network(gobject.GObject):
|
|||||||
return self._valid
|
return self._valid
|
||||||
|
|
||||||
def add_to_menu(self, menu):
|
def add_to_menu(self, menu):
|
||||||
item = gtk.CheckMenuItem()
|
|
||||||
strength = self._strength
|
strength = self._strength
|
||||||
if strength > 100:
|
if strength > 100:
|
||||||
strength = 100
|
strength = 100
|
||||||
elif strength < 0:
|
elif strength < 0:
|
||||||
strength = 0
|
strength = 0
|
||||||
label_str = "%s (%d%%)" % (self._ssid, strength)
|
item = NetworkMenuItem(text=self._ssid, percent=strength)
|
||||||
label = gtk.Label(label_str)
|
menu.add_item(item)
|
||||||
label.set_alignment(0.0, 0.5)
|
|
||||||
item.add(label)
|
|
||||||
item.show_all()
|
|
||||||
menu.add(item)
|
|
||||||
|
|
||||||
|
|
||||||
class Device(gobject.GObject):
|
class Device(gobject.GObject):
|
||||||
@ -188,14 +189,8 @@ class Device(gobject.GObject):
|
|||||||
del self._networks[net_op]
|
del self._networks[net_op]
|
||||||
|
|
||||||
def _add_to_menu_wired(self, menu):
|
def _add_to_menu_wired(self, menu):
|
||||||
item = gtk.CheckMenuItem()
|
item = NetworkMenuItem(_("Wired Network"))
|
||||||
label = gtk.Label(_("Wired Network"))
|
menu.add_item(item)
|
||||||
label.set_alignment(0.0, 0.5);
|
|
||||||
item.add(label)
|
|
||||||
if self._caps & NM_DEVICE_CAP_CARRIER_DETECT:
|
|
||||||
item.set_sensitive(self._link)
|
|
||||||
item.show_all()
|
|
||||||
menu.add(item)
|
|
||||||
|
|
||||||
def _add_to_menu_wireless(self, menu):
|
def _add_to_menu_wireless(self, menu):
|
||||||
for net in self._networks.values():
|
for net in self._networks.values():
|
||||||
@ -270,22 +265,42 @@ class Device(gobject.GObject):
|
|||||||
def set_carrier(self, on):
|
def set_carrier(self, on):
|
||||||
self._link = on
|
self._link = on
|
||||||
|
|
||||||
class ActivityMenu(Menu):
|
|
||||||
def __init__(self, activity_host):
|
|
||||||
Menu.__init__(self, activity_host.get_title())
|
|
||||||
|
|
||||||
if not activity_host.get_shared():
|
class NetworkMenuItem(Bubble):
|
||||||
self._add_mesh_action()
|
def __init__(self, text, percent=0):
|
||||||
|
color = IconColor("#646464,#646464")
|
||||||
|
Bubble.__init__(self, color=color, percent=percent)
|
||||||
|
|
||||||
self._add_close_action()
|
text_item = hippo.CanvasText(text=text)
|
||||||
|
style.apply_stylesheet(text_item, 'menu.Text')
|
||||||
|
self.append(text_item)
|
||||||
|
|
||||||
def _add_mesh_action(self):
|
|
||||||
icon = CanvasIcon(icon_name='stock-share-mesh')
|
|
||||||
self.add_action(icon, ActivityMenu.ACTION_SHARE)
|
|
||||||
|
|
||||||
def _add_close_action(self):
|
class NetworkMenu(gtk.Window):
|
||||||
icon = CanvasIcon(icon_name='stock-close')
|
__gsignals__ = {
|
||||||
self.add_action(icon, ActivityMenu.ACTION_CLOSE)
|
'action': (gobject.SIGNAL_RUN_FIRST,
|
||||||
|
gobject.TYPE_NONE, ([int])),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
gtk.Window.__init__(self, gtk.WINDOW_POPUP)
|
||||||
|
|
||||||
|
canvas = hippo.Canvas()
|
||||||
|
self.add(canvas)
|
||||||
|
canvas.show()
|
||||||
|
|
||||||
|
self._root = hippo.CanvasBox()
|
||||||
|
style.apply_stylesheet(self._root, 'menu')
|
||||||
|
canvas.set_root(self._root)
|
||||||
|
|
||||||
|
def add_separator(self):
|
||||||
|
separator = hippo.CanvasBox()
|
||||||
|
style.apply_stylesheet(separator, 'menu.Separator')
|
||||||
|
self._root.append(separator)
|
||||||
|
|
||||||
|
def add_item(self, item):
|
||||||
|
self._root.append(item)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NM_STATE_UNKNOWN = 0
|
NM_STATE_UNKNOWN = 0
|
||||||
@ -304,7 +319,6 @@ ICON_WIRELESS_81_100 = "stock-net-wireless-81-100"
|
|||||||
|
|
||||||
class NMClientApp:
|
class NMClientApp:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.menu = None
|
|
||||||
self.nminfo = None
|
self.nminfo = None
|
||||||
self._nm_present = False
|
self._nm_present = False
|
||||||
self._nm_state = NM_STATE_UNKNOWN
|
self._nm_state = NM_STATE_UNKNOWN
|
||||||
@ -313,6 +327,13 @@ class NMClientApp:
|
|||||||
self._active_device = None
|
self._active_device = None
|
||||||
self._devices = {}
|
self._devices = {}
|
||||||
|
|
||||||
|
self._menu = None
|
||||||
|
self._hover_menu = False
|
||||||
|
self._timeline = Timeline(self)
|
||||||
|
self._timeline.add_tag('popup', 6, 6)
|
||||||
|
self._timeline.add_tag('before_popdown', 7, 7)
|
||||||
|
self._timeline.add_tag('popdown', 8, 8)
|
||||||
|
|
||||||
self._icons = {}
|
self._icons = {}
|
||||||
self._cur_icon = None
|
self._cur_icon = None
|
||||||
|
|
||||||
@ -400,24 +421,61 @@ class NMClientApp:
|
|||||||
def _setup_trayicon(self):
|
def _setup_trayicon(self):
|
||||||
pixbuf = self._get_icon()
|
pixbuf = self._get_icon()
|
||||||
self._trayicon = gtk.status_icon_new_from_pixbuf(pixbuf)
|
self._trayicon = gtk.status_icon_new_from_pixbuf(pixbuf)
|
||||||
self._trayicon.connect("popup_menu", self._popup)
|
self._trayicon.connect("popup_menu", self._status_icon_clicked)
|
||||||
self._trayicon.connect("activate", self._popup)
|
self._trayicon.connect("activate", self._status_icon_clicked)
|
||||||
self._schedule_icon_update()
|
self._schedule_icon_update()
|
||||||
|
|
||||||
def _popup(self, status, button=0, time=None):
|
def _status_icon_clicked(self, button=0, time=None):
|
||||||
def menu_pos(menu):
|
self._timeline.play(None, 'popup')
|
||||||
return gtk.status_icon_position_menu(menu, self._trayicon)
|
|
||||||
|
|
||||||
if time is None:
|
def _get_menu_position(self, menu, item):
|
||||||
time = gtk.get_current_event_time()
|
(screen, rect, orientation) = item.get_geometry()
|
||||||
if self.menu:
|
[item_x, item_y, item_w, item_h] = rect
|
||||||
del self.menu
|
[menu_w, menu_h] = menu.size_request()
|
||||||
self.menu = self._construct_new_menu()
|
|
||||||
self.menu.popup(None, None, menu_pos, button, time)
|
|
||||||
self.menu.show_all()
|
|
||||||
|
|
||||||
def _construct_new_menu(self):
|
x = item_x + item_w - menu_w
|
||||||
menu = gtk.Menu()
|
y = item_y + item_h
|
||||||
|
|
||||||
|
x = min(x, screen.get_width() - menu_w)
|
||||||
|
x = max(0, x)
|
||||||
|
|
||||||
|
y = min(y, screen.get_height() - menu_h)
|
||||||
|
y = max(0, y)
|
||||||
|
|
||||||
|
return (x, y)
|
||||||
|
|
||||||
|
def do_popup(self, current, n_frames):
|
||||||
|
if self._menu:
|
||||||
|
self._popdown()
|
||||||
|
return
|
||||||
|
|
||||||
|
self._menu = self._create_menu()
|
||||||
|
self._menu.connect('enter-notify-event',
|
||||||
|
self._menu_enter_notify_event_cb)
|
||||||
|
self._menu.connect('leave-notify-event',
|
||||||
|
self._menu_leave_notify_event_cb)
|
||||||
|
(x, y) = self._get_menu_position(self._menu, self._trayicon)
|
||||||
|
self._menu.move(x, y)
|
||||||
|
self._menu.show_all()
|
||||||
|
|
||||||
|
def do_popdown(self, current, frame):
|
||||||
|
if self._menu:
|
||||||
|
self._menu.destroy()
|
||||||
|
self._menu = None
|
||||||
|
|
||||||
|
def _popdown(self):
|
||||||
|
self._timeline.play('popdown', 'popdown')
|
||||||
|
|
||||||
|
def _menu_enter_notify_event_cb(self, widget, event):
|
||||||
|
self._hover_menu = True
|
||||||
|
self._timeline.play('popup', 'popup')
|
||||||
|
|
||||||
|
def _menu_leave_notify_event_cb(self, widget, event):
|
||||||
|
self._hover_menu = False
|
||||||
|
self._popdown()
|
||||||
|
|
||||||
|
def _create_menu(self):
|
||||||
|
menu = NetworkMenu()
|
||||||
|
|
||||||
# Wired devices first
|
# Wired devices first
|
||||||
for dev in self._devices.values():
|
for dev in self._devices.values():
|
||||||
@ -427,6 +485,8 @@ class NMClientApp:
|
|||||||
continue
|
continue
|
||||||
dev.add_to_menu(menu)
|
dev.add_to_menu(menu)
|
||||||
|
|
||||||
|
menu.add_separator()
|
||||||
|
|
||||||
# Wireless devices second
|
# Wireless devices second
|
||||||
for dev in self._devices.values():
|
for dev in self._devices.values():
|
||||||
if not dev.is_valid():
|
if not dev.is_valid():
|
||||||
|
Loading…
Reference in New Issue
Block a user