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 bin (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 | 151 ++++++++++++++++++------------ src/jarabe/frame/zoomtoolbar.py | 4 + 4 files changed, 103 insertions(+), 73 deletions(-) v2: Sascha pointed out that FrameContainer does not need to be windowed v3: implement FrameContainer as a Bin rather than as a Container as it only has one child element. Simplifies the code a little. 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..394ba00 100644 --- a/src/jarabe/frame/framewindow.py +++ b/src/jarabe/frame/framewindow.py @@ -15,11 +15,92 @@ # 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.Bin): + """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.Bin.__init__(self) + self._position = position + + if self.is_vertical(): + box = gtk.VBox() + else: + box = gtk.HBox() + self.add(box) + box.show() + + def is_vertical(self): + return self._position in (gtk.POS_LEFT, gtk.POS_RIGHT) + + def 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() + + gtk.Bin.do_expose_event(self, event) + 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.get_child().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.get_child().size_allocate(allocation) + + class FrameWindow(gtk.Window): __gtype_name__ = 'SugarFrameWindow' @@ -39,79 +120,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.get_child().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.4 _______________________________________________ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel