diff --git a/src/sugar3/graphics/palettewindow.py b/src/sugar3/graphics/palettewindow.py index 760c99a5..7785d106 100644 --- a/src/sugar3/graphics/palettewindow.py +++ b/src/sugar3/graphics/palettewindow.py @@ -98,16 +98,15 @@ class _PaletteMenuWidget(Gtk.Menu): res_, x, y = self.get_toplevel().get_window().get_origin() return x, y - def do_size_request(self, requisition): - Gtk.Window.do_size_request(self, requisition) - requisition.width = max(requisition.width, style.GRID_CELL_SIZE * 2) - def move(self, x, y): self._popup_position = (x, y) def set_transient_for(self, window): pass + def set_invoker(self, invoker): + pass + def _position(self, widget, data): return self._popup_position[0], self._popup_position[1], False @@ -252,7 +251,7 @@ class _PaletteWindowWidget(Gtk.Window): self.add_accel_group(accel_group) self._old_alloc = None - + self._invoker = None self._should_accept_focus = True def set_accept_focus(self, focus): @@ -270,9 +269,13 @@ class _PaletteWindowWidget(Gtk.Window): self.get_window().set_accept_focus(self._should_accept_focus) self.set_type_hint(Gdk.WindowTypeHint.DIALOG) - def do_size_request(self, requisition): - Gtk.Window.do_size_request(self, requisition) - requisition.width = max(requisition.width, style.GRID_CELL_SIZE * 2) + def do_get_preferred_width(self): + size = 0 + child = self.get_child() + if child: + minimum_size, natural_size = child.get_preferred_width() + size = max(minimum_size, natural_size, style.GRID_CELL_SIZE * 2) + return size, size def do_size_allocate(self, allocation): Gtk.Window.do_size_allocate(self, allocation) @@ -291,6 +294,46 @@ class _PaletteWindowWidget(Gtk.Window): # the configure request handler and finally size_allocate is called. self._old_alloc = allocation + def set_invoker(self, invoker): + self._invoker = invoker + + def get_rect(self): + win_x, win_y = self.get_origin() + rectangle = self.get_allocation() + + x = win_x + rectangle.x + y = win_y + rectangle.y + minimum, natural = self.get_preferred_size() + rect = Gdk.Rectangle() + rect.x = x + rect.y = y + rect.width = minimum.width + rect.height = natural.height + + return rect + + def do_draw(self, cr): + # Fall trough to the container expose handler. + # (Leaving out the window expose handler which redraws everything) + Gtk.Window.do_draw(self, cr) + + if self._invoker is not None and self._invoker.has_rectangle_gap(): + invoker = self._invoker.get_rect() + palette = self.get_rect() + gap = _calculate_gap(palette, invoker) + else: + gap = False + + allocation = self.get_allocation() + context = self.get_style_context() + context.add_class('toolitem') + if gap: + Gtk.render_frame_gap(context, cr, 0, 0, allocation.width, allocation.height, + gap[0], gap[1], gap[2]) + else: + Gtk.render_frame(context, cr, 0, 0, allocation.width, allocation.height) + return False + def __enter_notify_event_cb(self, widget, event): if event.mode == Gdk.CrossingMode.NORMAL and \ event.detail != Gdk.NotifyType.INFERIOR: @@ -427,6 +470,7 @@ class PaletteWindow(GObject.GObject): self._widget.connect('leave-notify', self.__leave_notify_cb) self._set_effective_group_id(self._group_id) + self._widget.set_invoker(self._invoker) self._mouse_detector.connect('motion-slow', self._mouse_slow_cb) self._mouse_detector.parent = self._widget @@ -452,6 +496,7 @@ class PaletteWindow(GObject.GObject): self._invoker_hids.remove(hid) self._invoker = invoker + self._widget.set_invoker(self._invoker) if invoker is not None: self._invoker_hids.append(self._invoker.connect( 'mouse-enter', self._invoker_mouse_enter_cb)) @@ -599,17 +644,17 @@ class PaletteWindow(GObject.GObject): def get_rect(self): win_x, win_y = self._widget.get_origin() - rectangle = self.get_allocation() + rectangle = self._widget.get_allocation() x = win_x + rectangle.x y = win_y + rectangle.y - requisition = self._widget.size_request() + minimum, natural_ = self._widget.get_preferred_size() rect = Gdk.Rectangle() rect.x = x rect.y = y - rect.width = requisition.width - rect.height = requisition.height + rect.width = minimum.width + rect.height = minimum.height return rect @@ -967,25 +1012,18 @@ class WidgetInvoker(Invoker): def has_rectangle_gap(self): return True - def draw_rectangle(self, event, palette): - x, y = self._widget.allocation.x, self._widget.allocation.y + def draw_rectangle(self, cr, palette): + allocation = self.parent.get_allocation() - wstyle = self._widget.get_style() - gap = _calculate_gap(self.get_rect(), palette.get_rect()) + context = self.parent.get_style_context() + context.add_class('toolitem') + gap = _calculate_gap(self.get_rect(), palette.get_rect()) if gap: - wstyle.paint_box_gap(event.window, Gtk.StateType.PRELIGHT, - Gtk.ShadowType.IN, event.area, self._widget, - 'palette-invoker', x, y, - self._widget.allocation.width, - self._widget.allocation.height, + Gtk.render_frame_gap(context, cr, 0, 0, + allocation.width, + allocation.height, gap[0], gap[1], gap[2]) - else: - wstyle.paint_box(event.window, Gtk.StateType.PRELIGHT, - Gtk.ShadowType.IN, event.area, self._widget, - 'palette-invoker', x, y, - self._widget.allocation.width, - self._widget.allocation.height) def __enter_notify_event_cb(self, widget, event): self.notify_mouse_enter() diff --git a/src/sugar3/graphics/toolbarbox.py b/src/sugar3/graphics/toolbarbox.py index 5ec2db98..7e317f7d 100644 --- a/src/sugar3/graphics/toolbarbox.py +++ b/src/sugar3/graphics/toolbarbox.py @@ -38,7 +38,7 @@ class ToolbarButton(ToolButton): self.connect('clicked', lambda widget: self.set_expanded(not self.is_expanded())) - + self.connect_after('draw', self.__drawing_cb) self.connect('hierarchy-changed', self.__hierarchy_changed_cb) def __hierarchy_changed_cb(self, tool_button, previous_toplevel): @@ -66,7 +66,7 @@ class ToolbarButton(ToolButton): if page is None: self.page_widget = None return - self.page_widget, alignment_ = _embed_page(_Box, page) + self.page_widget, alignment_ = _embed_page(_Box(self), page) self.page_widget.set_size_request(-1, style.GRID_CELL_SIZE) page.show() if self.props.palette is None: @@ -125,22 +125,19 @@ class ToolbarButton(ToolButton): return page_parent.remove(self.page_widget) - def do_draw(self, cr): - if not self.is_expanded() or self.props.palette is not None and \ - self.props.palette.is_up(): - Gtk.ToolButton.do_draw(self, cr) - _paint_arrow(self, cr, math.pi) - return - + def __drawing_cb(self, button, cr): alloc = self.get_allocation() - context = self.get_style_context() context.add_class('toolitem') - + if not self.is_expanded() or self.props.palette is not None and \ + self.props.palette.is_up(): + ToolButton.do_draw(self, cr) + _paint_arrow(self, cr, math.pi) + return False Gtk.render_frame_gap(context, cr, 0, 0, alloc.width, alloc.height, Gtk.PositionType.BOTTOM, 0, alloc.width) - Gtk.ToolButton.do_draw(self, cr) _paint_arrow(self, cr, 0) + return False class ToolbarBox(Gtk.VBox): @@ -155,7 +152,7 @@ class ToolbarBox(Gtk.VBox): self._toolbar.connect('remove', self.__remove_cb) self._toolbar_widget, self._toolbar_alignment = \ - _embed_page(Gtk.EventBox, self._toolbar) + _embed_page(Gtk.EventBox(), self._toolbar) self.pack_start(self._toolbar_widget, True, True, 0) self.props.padding = padding @@ -269,26 +266,23 @@ class _ToolbarPalette(PaletteWindow): class _Box(Gtk.EventBox): - def __init__(self): + def __init__(self, toolbar_button): GObject.GObject.__init__(self) self.set_app_paintable(True) + self._toolbar_button = toolbar_button - def do_expose_event(self, widget, event): - # TODO: reimplement this in the theme - expanded_button = self.get_parent().expanded_button - if expanded_button is None: - return - alloc = expanded_button.allocation - self.get_style().paint_box(event.window, - Gtk.StateType.NORMAL, Gtk.ShadowType.IN, event.area, self, - 'palette-invoker', -style.FOCUS_LINE_WIDTH, 0, - self.allocation.width + style.FOCUS_LINE_WIDTH * 2, - self.allocation.height + style.FOCUS_LINE_WIDTH) - self.get_style().paint_box(event.window, - Gtk.StateType.NORMAL, Gtk.ShadowType.NONE, event.area, self, None, - alloc.x + style.FOCUS_LINE_WIDTH, 0, - alloc.width - style.FOCUS_LINE_WIDTH * 2, - style.FOCUS_LINE_WIDTH) + def do_draw(self, cr): + button_alloc = self._toolbar_button.get_allocation() + + cr.set_line_width(style.FOCUS_LINE_WIDTH * 2) + cr.set_source_rgba(*style.COLOR_BUTTON_GREY.get_rgba()) + cr.move_to(0, 0) + cr.line_to(button_alloc.x + style.FOCUS_LINE_WIDTH, 0) + cr.move_to(button_alloc.x + button_alloc.width - style.FOCUS_LINE_WIDTH, 0) + cr.line_to(self.get_allocation().width, 0) + cr.stroke() + + Gtk.EventBox.do_draw(self, cr) def _setup_page(page_widget, color, hpad): @@ -305,14 +299,13 @@ def _setup_page(page_widget, color, hpad): page_widget.modify_bg(Gtk.StateType.PRELIGHT, color) -def _embed_page(box_class, page): +def _embed_page(page_widget, page): page.show() alignment = Gtk.Alignment(xscale=1.0, yscale=1.0) alignment.add(page) alignment.show() - page_widget = box_class() page_widget.modify_bg(Gtk.StateType.ACTIVE, style.COLOR_BUTTON_GREY.get_gdk_color()) page_widget.add(alignment) diff --git a/src/sugar3/graphics/toolbutton.py b/src/sugar3/graphics/toolbutton.py index 7ca13d8b..a1ab8e4a 100644 --- a/src/sugar3/graphics/toolbutton.py +++ b/src/sugar3/graphics/toolbutton.py @@ -142,20 +142,22 @@ class ToolButton(Gtk.ToolButton): palette_invoker = GObject.property( type=object, setter=set_palette_invoker, getter=get_palette_invoker) - def do_expose_event(self, event): + def do_draw(self, cr): child = self.get_child() - allocation = self.get_allocation() + if self.palette and self.palette.is_up(): + allocation = self.get_allocation() + # draw a black background, has been done by the engine before + cr.set_source_rgb(0, 0, 0) + cr.rectangle(0, 0, allocation.width, allocation.height) + cr.paint() + + Gtk.ToolButton.do_draw(self, cr) + if self.palette and self.palette.is_up(): invoker = self.palette.props.invoker - invoker.draw_rectangle(event, self.palette) - elif child.state == Gtk.StateType.PRELIGHT: - child.style.paint_box(event.window, Gtk.StateType.PRELIGHT, - Gtk.ShadowType.NONE, event.area, - child, 'toolbutton-prelight', - allocation.x, allocation.y, - allocation.width, allocation.height) - - Gtk.ToolButton.do_expose_event(self, event) + invoker.draw_rectangle(cr, self.palette) + + return False def do_clicked(self): if self.palette: