[Sugar-devel] [PATCH v2] Remove hippo from the frame
Daniel Drake
dsd at laptop.org
Tue Sep 27 13:41:32 EDT 2011
Based on earlier work by Raul Gutierrez and Walter Bender.
The tricky part here is not placing frame elements in the corners of the
screen, where grid-cell-sized squares are reserved, and also drawing
the little grey border around the inner edges of the frame.
Both of these issues are tackled with a custom container (FrameContainer)
class which provides the frame's child elements with a precisely defined
box to work in (which leaves the screen corners blank), and (like hippo)
uses cairo to draw the border on the appropriate edge.
---
src/jarabe/frame/clipboardpanelwindow.py | 5 +-
src/jarabe/frame/frame.py | 16 +--
src/jarabe/frame/framewindow.py | 168 +++++++++++++++++++----------
src/jarabe/frame/zoomtoolbar.py | 4 +
4 files changed, 120 insertions(+), 73 deletions(-)
v2: Sascha pointed out that FrameContainer does not need to be windowed
diff --git a/src/jarabe/frame/clipboardpanelwindow.py b/src/jarabe/frame/clipboardpanelwindow.py
index f5d537c..aefec7b 100644
--- a/src/jarabe/frame/clipboardpanelwindow.py
+++ b/src/jarabe/frame/clipboardpanelwindow.py
@@ -18,7 +18,6 @@ import logging
from urlparse import urlparse
import gtk
-import hippo
from jarabe.frame.framewindow import FrameWindow
from jarabe.frame.clipboardtray import ClipboardTray
@@ -39,8 +38,8 @@ class ClipboardPanelWindow(FrameWindow):
self._clipboard.connect('owner-change', self._owner_change_cb)
self._clipboard_tray = ClipboardTray()
- canvas_widget = hippo.CanvasWidget(widget=self._clipboard_tray)
- self.append(canvas_widget, hippo.PACK_EXPAND)
+ self._clipboard_tray.show()
+ self.append(self._clipboard_tray)
# Receiving dnd drops
self.drag_dest_set(0, [], 0)
diff --git a/src/jarabe/frame/frame.py b/src/jarabe/frame/frame.py
index 079eeeb..7407e18 100644
--- a/src/jarabe/frame/frame.py
+++ b/src/jarabe/frame/frame.py
@@ -18,7 +18,6 @@ import logging
import gtk
import gobject
-import hippo
from sugar.graphics import animator
from sugar.graphics import style
@@ -178,17 +177,12 @@ class Frame(object):
def _create_top_panel(self):
panel = self._create_panel(gtk.POS_TOP)
- # TODO: setting box_width and hippo.PACK_EXPAND looks like a hack to
- # me. Why hippo isn't respecting the request size of these controls?
-
zoom_toolbar = ZoomToolbar()
- panel.append(hippo.CanvasWidget(widget=zoom_toolbar,
- box_width=4 * style.GRID_CELL_SIZE))
+ panel.append(zoom_toolbar, expand=False)
zoom_toolbar.show()
activities_tray = ActivitiesTray()
- panel.append(hippo.CanvasWidget(widget=activities_tray),
- hippo.PACK_EXPAND)
+ panel.append(activities_tray)
activities_tray.show()
return panel
@@ -196,10 +190,8 @@ class Frame(object):
def _create_bottom_panel(self):
panel = self._create_panel(gtk.POS_BOTTOM)
- # TODO: same issue as in _create_top_panel()
devices_tray = DevicesTray()
- panel.append(hippo.CanvasWidget(widget=devices_tray),
- hippo.PACK_EXPAND)
+ panel.append(devices_tray)
devices_tray.show()
return panel
@@ -208,7 +200,7 @@ class Frame(object):
panel = self._create_panel(gtk.POS_RIGHT)
tray = FriendsTray()
- panel.append(hippo.CanvasWidget(widget=tray), hippo.PACK_EXPAND)
+ panel.append(tray)
tray.show()
return panel
diff --git a/src/jarabe/frame/framewindow.py b/src/jarabe/frame/framewindow.py
index c77e76c..e0256eb 100644
--- a/src/jarabe/frame/framewindow.py
+++ b/src/jarabe/frame/framewindow.py
@@ -15,11 +15,109 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import gtk
-import hippo
+from gtk import gdk
+import gobject
from sugar.graphics import style
+class FrameContainer(gtk.Container):
+ """A container class for frame panel rendering. Hosts a child 'box' where
+ frame elements can be added. Excludes grid-sized squares at each end
+ of the frame panel, and a space alongside the inside of the screen where
+ a border is drawn."""
+
+ __gtype_name__ = 'SugarFrameContainer'
+
+ def __init__(self, position):
+ gtk.Container.__init__(self)
+ self.set_has_window(False)
+ self._position = position
+
+ if self.is_vertical():
+ self._box = gtk.VBox()
+ else:
+ self._box = gtk.HBox()
+ self._box.set_parent(self)
+ self._box.show()
+
+ def is_vertical(self):
+ return self._position in (gtk.POS_LEFT, gtk.POS_RIGHT)
+
+ @gobject.property
+ def box(self):
+ return self._box
+
+ def do_realize(self):
+ self.set_flags(gtk.REALIZED)
+ self.set_window(self.get_parent_window())
+ self._box.set_parent_window(self.get_parent_window())
+ self.queue_resize()
+
+ def do_expose_event(self, event):
+ gtk.Container.do_expose_event(self, event)
+
+ # Draw the inner border as a rectangle
+ cr = self.get_parent_window().cairo_create()
+ r, g, b, a = style.COLOR_BUTTON_GREY.get_rgba()
+ cr.set_source_rgba (r, g, b, a)
+
+ if self.is_vertical():
+ x = style.GRID_CELL_SIZE if self._position == gtk.POS_LEFT else 0
+ y = style.GRID_CELL_SIZE
+ width = style.LINE_WIDTH
+ height = self.allocation.height - (style.GRID_CELL_SIZE * 2)
+ else:
+ x = style.GRID_CELL_SIZE
+ y = style.GRID_CELL_SIZE if self._position == gtk.POS_TOP else 0
+ height = style.LINE_WIDTH
+ width = self.allocation.width - (style.GRID_CELL_SIZE * 2)
+
+ cr.rectangle(x, y, width, height)
+ cr.fill()
+ return False
+
+ def do_size_request(self, req):
+ if self.is_vertical():
+ req.height = gdk.screen_height()
+ req.width = style.GRID_CELL_SIZE + style.LINE_WIDTH
+ else:
+ req.width = gdk.screen_width()
+ req.height = style.GRID_CELL_SIZE + style.LINE_WIDTH
+
+ self._box.size_request()
+
+ def do_size_allocate(self, allocation):
+ self.allocation = allocation
+
+ # exclude grid squares at two ends of the frame
+ # allocate remaining space to child box, minus the space needed for
+ # drawing the border
+ allocation = gdk.Rectangle()
+ if self.is_vertical():
+ allocation.x = 0 if self._position == gtk.POS_LEFT \
+ else style.LINE_WIDTH
+ allocation.y = style.GRID_CELL_SIZE
+ allocation.width = self.allocation.width - style.LINE_WIDTH
+ allocation.height = self.allocation.height \
+ - (style.GRID_CELL_SIZE * 2)
+ else:
+ allocation.x = style.GRID_CELL_SIZE
+ allocation.y = 0 if self._position == gtk.POS_TOP \
+ else style.LINE_WIDTH
+ allocation.width = self.allocation.width \
+ - (style.GRID_CELL_SIZE * 2)
+ allocation.height = self.allocation.height - style.LINE_WIDTH
+
+ self._box.size_allocate(allocation)
+
+ def do_forall(self, include_internals, callback, data):
+ callback(self._box, data)
+
+ def do_remove(self, child):
+ child.unparent()
+
+
class FrameWindow(gtk.Window):
__gtype_name__ = 'SugarFrameWindow'
@@ -39,79 +137,33 @@ class FrameWindow(gtk.Window):
self.connect('enter-notify-event', self._enter_notify_cb)
self.connect('leave-notify-event', self._leave_notify_cb)
- self._canvas = hippo.Canvas()
- self.add(self._canvas)
- self._canvas.show()
-
- box = hippo.CanvasBox()
- self._canvas.set_root(box)
-
- bg_box = hippo.CanvasBox(
- border_color=style.COLOR_BUTTON_GREY.get_int())
- box.append(bg_box, hippo.PACK_EXPAND)
-
- self._bg = hippo.CanvasBox()
- bg_box.append(self._bg, hippo.PACK_EXPAND)
-
- padding = style.GRID_CELL_SIZE
- border = style.LINE_WIDTH
-
- if position == gtk.POS_TOP or position == gtk.POS_BOTTOM:
- box.props.orientation = hippo.ORIENTATION_HORIZONTAL
- box.props.padding_left = padding
- box.props.padding_right = padding
- box.props.padding_top = 0
- box.props.padding_bottom = 0
- self._bg.props.orientation = hippo.ORIENTATION_HORIZONTAL
- self._bg.props.padding_left = border * 2
- self._bg.props.padding_right = border * 2
- else:
- box.props.orientation = hippo.ORIENTATION_VERTICAL
- box.props.padding_left = 0
- box.props.padding_right = 0
- box.props.padding_top = padding
- box.props.padding_bottom = padding
- self._bg.props.orientation = hippo.ORIENTATION_VERTICAL
- self._bg.props.padding_top = border * 2
- self._bg.props.padding_bottom = border * 2
-
- if position == gtk.POS_TOP:
- bg_box.props.orientation = hippo.ORIENTATION_HORIZONTAL
- bg_box.props.border_bottom = border
- elif position == gtk.POS_BOTTOM:
- bg_box.props.orientation = hippo.ORIENTATION_HORIZONTAL
- bg_box.props.border_top = border
- elif position == gtk.POS_LEFT:
- bg_box.props.orientation = hippo.ORIENTATION_VERTICAL
- bg_box.props.border_right = border
- elif position == gtk.POS_RIGHT:
- bg_box.props.orientation = hippo.ORIENTATION_VERTICAL
- bg_box.props.border_left = border
-
+ self._container = FrameContainer(position)
+ self.add(self._container)
+ self._container.show()
self._update_size()
- screen = gtk.gdk.screen_get_default()
+ screen = gdk.screen_get_default()
screen.connect('size-changed', self._size_changed_cb)
- def append(self, child, flags=0):
- self._bg.append(child, flags)
+ def append(self, child, expand=True, fill=True):
+ self._container.box.pack_start(child, expand=expand, fill=fill)
def _update_size(self):
if self._position == gtk.POS_TOP or self._position == gtk.POS_BOTTOM:
- self.resize(gtk.gdk.screen_width(), self.size)
+ self.resize(gdk.screen_width(), self.size)
else:
- self.resize(self.size, gtk.gdk.screen_height())
+ self.resize(self.size, gdk.screen_height())
def _realize_cb(self, widget):
- self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
+ self.window.set_type_hint(gdk.WINDOW_TYPE_HINT_DOCK)
self.window.set_accept_focus(False)
def _enter_notify_cb(self, window, event):
- if event.detail != gtk.gdk.NOTIFY_INFERIOR:
+ if event.detail != gdk.NOTIFY_INFERIOR:
self.hover = True
def _leave_notify_cb(self, window, event):
- if event.detail != gtk.gdk.NOTIFY_INFERIOR:
+ if event.detail != gdk.NOTIFY_INFERIOR:
self.hover = False
def _size_changed_cb(self, screen):
diff --git a/src/jarabe/frame/zoomtoolbar.py b/src/jarabe/frame/zoomtoolbar.py
index 2effea2..c28fe1c 100644
--- a/src/jarabe/frame/zoomtoolbar.py
+++ b/src/jarabe/frame/zoomtoolbar.py
@@ -21,6 +21,7 @@ import logging
import glib
import gtk
+from sugar.graphics import style
from sugar.graphics.palette import Palette
from sugar.graphics.radiotoolbutton import RadioToolButton
@@ -35,6 +36,9 @@ class ZoomToolbar(gtk.Toolbar):
# we shouldn't be mirrored in RTL locales
self.set_direction(gtk.TEXT_DIR_LTR)
+ # ask not to be collapsed if possible
+ self.set_size_request(4 * style.GRID_CELL_SIZE, -1)
+
self._mesh_button = self._add_button('zoom-neighborhood',
_('Neighborhood'), _('F1'), shell.ShellModel.ZOOM_MESH)
self._groups_button = self._add_button('zoom-groups',
--
1.7.6.2
More information about the Sugar-devel
mailing list