def __init__(self, activity, **kwargs):
        self._activity = activity
        self.properties = self._activity.area.tool
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._palette = None
        self._selected_tool = None

        GObject.GObject.__init__(self, **kwargs)

        # The Gtk.ToolButton has already added a normal button.
        # Replace it with a ColorButton
        self.color_button = BrushButton(has_invoker=False)
        self.add(self.color_button)
        self.color_button.set_brush_size(self.properties['line size'])
        self.color_button.set_brush_shape(self.properties['line shape'])
        self.color_button.set_stamp_size(20)

        # The following is so that the behaviour on the toolbar is correct.
        self.color_button.set_relief(Gtk.ReliefStyle.NONE)

        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        # This widget just proxies the following properties to the colorbutton
        self.color_button.connect('notify::color', self.__notify_change)
        self.color_button.connect('notify::icon-name', self.__notify_change)
        self.color_button.connect('notify::icon-size', self.__notify_change)
        self.color_button.connect('notify::title', self.__notify_change)
        self.color_button.connect('can-activate-accel',
                                  self.__button_can_activate_accel_cb)

        self.create_palette()
    def __init__(self, icon_name='color-preview', **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._palette = None

        GObject.GObject.__init__(self, **kwargs)

        # The Gtk.ToolButton has already added a normal button.
        # Replace it with a ColorButton
        color_button = _ColorButton(icon_name=icon_name, has_invoker=False)
        self.add(color_button)
        color_button.show()

        # The following is so that the behaviour on the toolbar is correct.
        color_button.set_relief(Gtk.ReliefStyle.NONE)
        color_button.icon_size = Gtk.IconSize.LARGE_TOOLBAR

        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        # This widget just proxies the following properties to the colorbutton
        color_button.connect('notify::color', self.__notify_change)
        color_button.connect('notify::icon-name', self.__notify_change)
        color_button.connect('notify::icon-size', self.__notify_change)
        color_button.connect('notify::title', self.__notify_change)
        color_button.connect('color-set', self.__color_set_cb)
        color_button.connect('can-activate-accel',
                             self.__button_can_activate_accel_cb)
    def __init__(self, tagline, default_icon, default_label, palette_content):
        self._palette_invoker = ToolInvoker()
        Gtk.ToolButton.__init__(self)
        self._label = default_label

        self.set_is_important(False)
        self.set_size_request(style.GRID_CELL_SIZE, -1)

        self._label_widget = Gtk.Label()
        self._label_widget.set_alignment(0.0, 0.5)
        self._label_widget.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
        self._label_widget.set_max_width_chars(10)
        self._label_widget.set_use_markup(True)
        self._label_widget.set_markup(default_label)
        self.set_label_widget(self._label_widget)
        self._label_widget.show()

        self.set_widget_icon(icon_name=default_icon)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        self.palette = Palette(tagline)
        self.palette.set_invoker(self._palette_invoker)

        self.props.palette.set_content(palette_content)
Exemple #4
0
    def __init__(self, default_icon, default_label, palette_content):
        self._palette_invoker = ToolInvoker()
        Gtk.ToolButton.__init__(self)
        self._label = default_label

        self.set_is_important(False)
        self.set_size_request(style.GRID_CELL_SIZE, -1)

        self._label_widget = Gtk.Label()
        self._label_widget.set_alignment(0.0, 0.5)
        self._label_widget.set_ellipsize(style.ELLIPSIZE_MODE_DEFAULT)
        self._label_widget.set_max_width_chars(_LABEL_MAX_WIDTH)
        self._label_widget.set_use_markup(True)
        self._label_widget.set_markup(default_label)
        self.set_label_widget(self._label_widget)
        self._label_widget.show()

        self.set_widget_icon(icon_name=default_icon)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        self.palette = Palette(_('Select filter'))
        self.palette.set_invoker(self._palette_invoker)

        self.props.palette.set_content(palette_content)
    def __init__(self, default_icon, default_value, options):
        self._palette_invoker = ToolInvoker()
        self._options = options
        Gtk.ToolButton.__init__(self)
        logging.debug('filter options %s', options)
        self._value = default_value
        self._label = self._options[default_value]
        self.set_is_important(True)
        self.set_size_request(style.GRID_CELL_SIZE, -1)

        self._label_widget = Gtk.Label()
        self._label_widget.set_alignment(0.0, 0.5)
        self._label_widget.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
        self._label_widget.set_max_width_chars(self._LABEL_MAX_WIDTH)
        self._label_widget.set_use_markup(True)
        self._label_widget.set_markup(self._label)
        self.set_label_widget(self._label_widget)
        self._label_widget.show()

        self.set_widget_icon(icon_name=default_icon)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        self.palette = Palette(_('Select language'))
        self.palette.set_invoker(self._palette_invoker)

        self.props.palette.set_content(self.set_palette_list(options))
Exemple #6
0
class TrayIcon(Gtk.ToolItem):

    __gtype_name__ = 'SugarTrayIcon'

    def __init__(self, icon_name=None, xo_color=None):
        Gtk.ToolItem.__init__(self)

        self._icon_widget = _IconWidget(icon_name, xo_color)
        self.add(self._icon_widget)
        self._icon_widget.show()

        self._palette_invoker = ToolInvoker(self)

        self.set_size_request(style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def get_icon(self):
        return self._icon_widget.get_icon()
    icon = property(get_icon, None)
    def __init__(self, icon_name=None):
        GObject.GObject.__init__(self)

        self._palette_invoker = ToolInvoker(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.connect('destroy', self.__destroy_cb)
    def __init__(self):
        self._palette_invoker = ToolInvoker()
        Gtk.ToolItem.__init__(self)
        self._font_label = FontLabel()
        bt = Gtk.Button('')
        bt.set_can_focus(False)
        bt.remove(bt.get_children()[0])
        box = Gtk.HBox()
        bt.add(box)
        icon = Icon(icon_name='font-text')
        box.pack_start(icon, False, False, 10)
        box.pack_start(self._font_label, False, False, 10)
        self.add(bt)
        self.show_all()

        self._font_name = 'Sans'

        # theme the button, can be removed if add the style to the sugar css
        if style.zoom(100) == 100:
            subcell_size = 15
        else:
            subcell_size = 11
        radius = 2 * subcell_size
        theme = "GtkButton {border-radius: %dpx;}" % radius
        css_provider = Gtk.CssProvider()
        css_provider.load_from_data(theme)
        style_context = bt.get_style_context()
        style_context.add_provider(css_provider,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        # init palette
        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True

        self.palette = Palette(_('Select font'))
        self.palette.set_invoker(self._palette_invoker)

        # load the fonts in the palette menu
        self._menu_box = PaletteMenuBox()
        self.props.palette.set_content(self._menu_box)
        self._menu_box.show()

        context = self.get_pango_context()

        self._init_font_list()

        tmp_list = []
        for family in context.list_families():
            name = family.get_name()
            if name in self._font_white_list:
                tmp_list.append(name)
        for name in sorted(tmp_list):
            self._add_menu(name, self.__font_selected_cb)

        self._font_label.set_font(self._font_name)
Exemple #9
0
    def __init__(self, icon_name=None, xo_color=None):
        Gtk.ToolItem.__init__(self)

        self._icon_widget = _IconWidget(icon_name, xo_color)
        self.add(self._icon_widget)
        self._icon_widget.show()

        self._palette_invoker = ToolInvoker(self)

        self.set_size_request(style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)

        self.connect('destroy', self.__destroy_cb)
    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._xo_color = None
        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.connect('destroy', self.__destroy_cb)
Exemple #11
0
    def __init__(self, default, options):
        self._palette_invoker = ToolInvoker()
        Gtk.ToolItem.__init__(self)
        self._label = Gtk.Label()
        bt = Gtk.Button('')
        bt.set_can_focus(False)
        bt.remove(bt.get_children()[0])
        self._box = Gtk.HBox()
        bt.add(self._box)
        self._icon = Icon(icon_name='')
        self._box.pack_start(self._icon, False, False, 5)
        self._box.pack_end(self._label, False, False, 5)
        self.add(bt)
        self.show_all()

        # theme the button, can be removed if add the style to the sugar css
        if style.zoom(100) == 100:
            subcell_size = 15
        else:
            subcell_size = 11
        radius = 2 * subcell_size
        theme = "GtkButton {border-radius: %dpx;}" % radius
        css_provider = Gtk.CssProvider()
        css_provider.load_from_data(theme)
        style_context = bt.get_style_context()
        style_context.add_provider(css_provider,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        # init palette
        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True

        self.palette = Palette(_('Select option'))
        self.palette.set_invoker(self._palette_invoker)

        # load the fonts in the palette menu
        self._menu_box = PaletteMenuBox()
        self.props.palette.set_content(self._menu_box)
        self._menu_box.show()

        for option in options:
            if option.__class__ is str:
                self._add_menu(option, activate_cb=self.__option_selected_cb)
            else:
                self._add_menu(option[0], icon=option[1],
                               activate_cb=self.__option_selected_cb)

        self.set_value(default)
    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.get_child().connect('can-activate-accel',
                                 self.__button_can_activate_accel_cb)

        self.connect('destroy', self.__destroy_cb)
    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._xo_color = None
        self._hide_tooltip_on_click = True

        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        # HACK: stop Gtk from adding a label and expanding the size of
        # the button. This happen when set_icon_widget is called
        # if label_widget is None
        self.props.label_widget = Gtk.Box()

        self.connect('destroy', self.__destroy_cb)
    def __init__(self, icon_name=None, pixel_size=None,
                direction=Gtk.Orientation.VERTICAL, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._progress = 0.0
        self._icon_name = icon_name
        self._pixel_size = pixel_size
        self._direction = direction

        GObject.GObject.__init__(self, **kwargs)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)

        self._stroke = get_surface(
            icon_name=self._icon_name, width=self._pixel_size, height=self._pixel_size,
            stroke_color=style.COLOR_BUTTON_GREY.get_svg(),
            fill_color=style.COLOR_TRANSPARENT.get_svg())

        self._fill = get_surface(
            icon_name=self._icon_name, width=self._pixel_size, height=self._pixel_size,
            stroke_color=style.COLOR_TRANSPARENT.get_svg(),
            fill_color=style.COLOR_WHITE.get_svg())
Exemple #15
0
class IntensitySelector(Gtk.ToolItem):

    __gsignals__ = {
        'changed': (GObject.SignalFlags.RUN_LAST, None, ([])), }

    def __init__(self, value_range, default_value, default_image):

        Gtk.ToolItem.__init__(self)
        self._palette_invoker = ToolInvoker()

        self.palette = None
        self._values = value_range
        self._palette_invoker.attach_tool(self)

        # theme the buttons, can be removed if add the style to the sugar css
        # these are the same values used in gtk-widgets.css.em
        if style.zoom(100) == 100:
            subcell_size = 15
            default_padding = 6
        else:
            subcell_size = 11
            default_padding = 4

        hbox = Gtk.HBox()
        vbox = Gtk.VBox()
        self.add(vbox)
        # add a vbox to set the padding up and down
        vbox.pack_start(hbox, True, True, default_padding)

        self._size_down = ToolButton('go-previous-paired')
        self._palette_invoker.attach_tool(self._size_down)

        self._size_down.set_can_focus(False)
        self._size_down.connect('clicked', self.__value_changed_cb, False)
        hbox.pack_start(self._size_down, False, False, 5)

        # TODO: default?
        self._default_value = default_value
        self._value = self._default_value

        self.image_wrapper = Gtk.EventBox()
        self._intensityImage = Gtk.Image()
        self.image_wrapper.add(self._intensityImage)
        self.image_wrapper.show()
        self._intensityImage.set_from_file(default_image)
        self._intensityImage.show()
        self._palette_invoker.attach_widget(self.image_wrapper)

        hbox.pack_start(self.image_wrapper, False, False, 10)

        self._size_up = ToolButton('go-next-paired')

        self._palette_invoker.attach_tool(self._size_up)

        self._size_up.set_can_focus(False)
        self._size_up.connect('clicked', self.__value_changed_cb, True)
        hbox.pack_start(self._size_up, False, False, 5)

        radius = 2 * subcell_size
        theme_up = "GtkButton {border-radius:0px %dpx %dpx 0px;}" % (radius,
                                                                     radius)
        css_provider_up = Gtk.CssProvider()
        css_provider_up.load_from_data(theme_up)

        style_context = self._size_up.get_style_context()
        style_context.add_provider(css_provider_up,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        theme_down = "GtkButton {border-radius: %dpx 0px 0px %dpx;}" % (radius,
                                                                        radius)
        css_provider_down = Gtk.CssProvider()
        css_provider_down.load_from_data(theme_down)
        style_context = self._size_down.get_style_context()
        style_context.add_provider(css_provider_down,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        self.show_all()

    def __destroy_cb(self, **args):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def __value_changed_cb(self, button, increase):
        if self._value in self._values:
            i = self._values.index(self._value)
            if increase:
                if i < len(self._values) - 1:
                    i += 1
            else:
                if i > 0:
                    i -= 1
        else:
            i = self._values.index(self._default_value)

        self._value = self._values[i]
        self._size_down.set_sensitive(i != 0)
        self._size_up.set_sensitive(i < len(self._values) - 1)
        self.emit('changed')

    def set_value(self, val):
        if val not in self._values:
            # assure the val assigned is in the range
            # if not, assign one close.
            for v in self._values:
                if v > val:
                    val = v
                    break
            if val > self._values[-1]:
                size = self._values[-1]

        self._value = size
        self._size_label.set_text(str(self._value))

        # update the buttons states
        i = self._values.index(self._value)
        self._size_down.set_sensitive(i != 0)
        self._size_up.set_sensitive(i < len(self._value) - 1)
        self.emit('changed')

    def set_tooltip(self, tooltip):
        """ Set a simple palette with just a single label.
        """
        if self.palette is None or self._tooltip is None:
            self.palette = Palette(tooltip)
        elif self.palette is not None:
            self.palette.set_primary_text(tooltip)

        self._tooltip = tooltip

    def get_hide_tooltip_on_click(self):
        return self._hide_tooltip_on_click

    def set_hide_tooltip_on_click(self, hide_tooltip_on_click):
        if self._hide_tooltip_on_click != hide_tooltip_on_click:
            self._hide_tooltip_on_click = hide_tooltip_on_click

    hide_tooltip_on_click = GObject.Property(
        type=bool, default=True, getter=get_hide_tooltip_on_click,
        setter=set_hide_tooltip_on_click)

    def get_tooltip(self):
        return self._tooltip

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.Property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.Property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def do_draw(self, cr):
        Gtk.ToolButton.do_draw(self, cr)

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        return False

    def do_clicked(self):
        if self._hide_tooltip_on_click and self.palette:
            self.palette.popdown(True)

    def set_image(self, image):
        self._intensityImage.set_from_file(image)

    def get_value(self):
        return self._value
class RadioToolButton(Gtk.RadioToolButton):
    '''
    The RadioToolButton class manages a Gtk.RadioToolButton styled for
    Sugar.

    Args:
        icon_name (string): name of icon to be used.

    Keyword Args:

        accelerator (string): keyboard shortcut to be used to
            activate this button.

        tooltip (string): tooltip to be displayed when user hovers
            over button.

        xo_color (sugar3.graphics.xocolor.XoColor): XoColor of button.

        hide_tooltip_on_click (bool): Whether or not the tooltip
            is hidden when user clicks on button.
    '''

    __gtype_name__ = 'SugarRadioToolButton'

    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._xo_color = None
        self._hide_tooltip_on_click = True

        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        # HACK: stop Gtk from adding a label and expanding the size of
        # the button. This happen when set_icon_widget is called
        # if label_widget is None
        self.props.label_widget = Gtk.Box()

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def set_tooltip(self, tooltip):
        '''
        Set the tooltip.

        Args:
            tooltip (string): tooltip to be set.
        '''
        if self.palette is None or self._tooltip is None:
            self.palette = Palette(tooltip)
        elif self.palette is not None:
            self.palette.set_primary_text(tooltip)

        self._tooltip = tooltip

        # Set label, shows up when toolbar overflows
        Gtk.RadioToolButton.set_label(self, tooltip)

    def get_tooltip(self):
        '''
        Return the tooltip.
        '''
        return self._tooltip

    tooltip = GObject.Property(type=str, setter=set_tooltip,
                               getter=get_tooltip)

    def set_accelerator(self, accelerator):
        '''
        Set keyboard shortcut that activates this button.

        Args:
            accelerator (string): accelerator to be set. Should be in
            form <modifier>Letter.
        '''
        self._accelerator = accelerator
        toolbutton.setup_accelerator(self)

    def get_accelerator(self):
        '''
        Return accelerator string.
        '''
        return self._accelerator

    accelerator = GObject.Property(type=str, setter=set_accelerator,
                                   getter=get_accelerator)

    def set_icon_name(self, icon_name):
        '''
        Set name of icon.

        Args:
            icon_name (string): name of icon
        '''
        icon = Icon(icon_name=icon_name,
                    xo_color=self._xo_color)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        '''
        Return icon name, or None if there is no icon name.
        '''
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.Property(type=str, setter=set_icon_name,
                                 getter=get_icon_name)

    def set_xo_color(self, xo_color):
        '''
        Set XoColor of button icon.

        Args:
            xo_color (sugar3.graphics.xocolor.XoColor): xocolor to be set.
        '''
        if self._xo_color != xo_color:
            self._xo_color = xo_color
            if self.props.icon_widget is not None:
                self.props.icon_widget.props.xo_color = xo_color

    def get_xo_color(self):
        '''
        Return xocolor.
        '''
        return self._xo_color

    xo_color = GObject.Property(type=object, setter=set_xo_color,
                                getter=get_xo_color)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.Property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.Property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def do_draw(self, cr):
        '''
        Implementation method for drawing the button.
        '''
        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.RadioToolButton.do_draw(self, cr)

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        return False

    def get_hide_tooltip_on_click(self):
        '''
        Return True if the tooltip is hidden when a user
        clicks on the button, otherwise return False.
        '''
        return self._hide_tooltip_on_click

    def set_hide_tooltip_on_click(self, hide_tooltip_on_click):
        '''
        Set whether or not the tooltip is hidden when a user
        clicks on the button.

        Args:
            hide_tooltip_on_click (bool): True if the tooltip is
            hidden on click, and False otherwise.
        '''
        if self._hide_tooltip_on_click != hide_tooltip_on_click:
            self._hide_tooltip_on_click = hide_tooltip_on_click

    hide_tooltip_on_click = GObject.Property(
        type=bool, default=True, getter=get_hide_tooltip_on_click,
        setter=set_hide_tooltip_on_click)

    def do_clicked(self):
        '''
        Implementation method for hiding the tooltip when
        the button is clicked.
        '''
        if self._hide_tooltip_on_click and self.palette:
            self.palette.popdown(True)
class FontComboBox(Gtk.ToolItem):

    __gsignals__ = {
        'changed': (GObject.SignalFlags.RUN_LAST, None, ([])),
    }

    def __init__(self):
        self._palette_invoker = ToolInvoker()
        Gtk.ToolItem.__init__(self)
        self._font_label = FontLabel()
        bt = Gtk.Button('')
        bt.set_can_focus(False)
        bt.remove(bt.get_children()[0])
        box = Gtk.HBox()
        bt.add(box)
        icon = Icon(icon_name='font-text')
        box.pack_start(icon, False, False, 10)
        box.pack_start(self._font_label, False, False, 10)
        self.add(bt)
        self.show_all()

        self._font_name = 'Sans'

        # theme the button, can be removed if add the style to the sugar css
        if style.zoom(100) == 100:
            subcell_size = 15
        else:
            subcell_size = 11
        radius = 2 * subcell_size
        theme = b"GtkButton {border-radius: %dpx;}" % radius
        css_provider = Gtk.CssProvider()
        css_provider.load_from_data(theme)
        style_context = bt.get_style_context()
        style_context.add_provider(css_provider,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        # init palette
        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True

        self.palette = Palette(_('Select font'))
        self.palette.set_invoker(self._palette_invoker)

        # load the fonts in the palette menu
        self._menu_box = PaletteMenuBox()
        self.props.palette.set_content(self._menu_box)
        self._menu_box.show()

        context = self.get_pango_context()

        self._init_font_list()

        tmp_list = []
        for family in context.list_families():
            name = family.get_name()
            if name in self._font_white_list:
                tmp_list.append(name)
        for name in sorted(tmp_list):
            self._add_menu(name, self.__font_selected_cb)

        self._font_label.set_font(self._font_name)

    def _init_font_list(self):
        self._font_white_list = []
        self._font_white_list.extend(DEFAULT_FONTS)

        # check if there are a user configuration file
        if not os.path.exists(USER_FONTS_FILE_PATH):
            # verify if exists a file in /etc
            if os.path.exists(GLOBAL_FONTS_FILE_PATH):
                shutil.copy(GLOBAL_FONTS_FILE_PATH, USER_FONTS_FILE_PATH)

        if os.path.exists(USER_FONTS_FILE_PATH):
            # get the font names in the file to the white list
            fonts_file = open(USER_FONTS_FILE_PATH)
            # get the font names in the file to the white list
            for line in fonts_file:
                self._font_white_list.append(line.strip())
            # monitor changes in the file
            gio_fonts_file = Gio.File.new_for_path(USER_FONTS_FILE_PATH)
            self.monitor = gio_fonts_file.monitor_file(
                Gio.FileMonitorFlags.NONE, None)
            self.monitor.set_rate_limit(5000)
            self.monitor.connect('changed', self._reload_fonts)

    def _reload_fonts(self, monitor, gio_file, other_file, event):
        if event != Gio.FileMonitorEvent.CHANGES_DONE_HINT:
            return
        self._font_white_list = []
        self._font_white_list.extend(DEFAULT_FONTS)
        fonts_file = open(USER_FONTS_FILE_PATH)
        for line in fonts_file:
            self._font_white_list.append(line.strip())
        # update the menu
        for child in self._menu_box.get_children():
            self._menu_box.remove(child)
            child = None
        context = self.get_pango_context()
        tmp_list = []
        for family in context.list_families():
            name = family.get_name()
            if name in self._font_white_list:
                tmp_list.append(name)
        for name in sorted(tmp_list):
            self._add_menu(name, self.__font_selected_cb)
        return False

    def __font_selected_cb(self, menu, font_name):
        self._font_name = font_name
        self._font_label.set_font(font_name)
        self.emit('changed')

    def _add_menu(self, font_name, activate_cb):
        label = '<span font="%s">%s</span>' % (font_name, font_name)
        menu_item = PaletteMenuItem()
        menu_item.set_label(label)
        menu_item.connect('activate', activate_cb, font_name)
        self._menu_box.append_item(menu_item)
        menu_item.show()

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.Property(type=object,
                               setter=set_palette,
                               getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.Property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def set_font_name(self, font_name):
        self._font_label.set_font(font_name)

    def get_font_name(self):
        return self._font_name
Exemple #18
0
class RadioToolButton(Gtk.RadioToolButton):
    '''
    The RadioToolButton class manages a Gtk.RadioToolButton styled for
    Sugar.

    Args:
        icon_name (string): name of icon to be used.

    Keyword Args:

        accelerator (string): keyboard shortcut to be used to
            activate this button.

        tooltip (string): tooltip to be displayed when user hovers
            over button.

        xo_color (sugar3.graphics.xocolor.XoColor): XoColor of button.

        hide_tooltip_on_click (bool): Whether or not the tooltip
            is hidden when user clicks on button.
    '''

    __gtype_name__ = 'SugarRadioToolButton'

    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._xo_color = None
        self._hide_tooltip_on_click = True

        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        # HACK: stop Gtk from adding a label and expanding the size of
        # the button. This happen when set_icon_widget is called
        # if label_widget is None
        self.props.label_widget = Gtk.Box()

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def set_tooltip(self, tooltip):
        '''
        Set the tooltip.

        Args:
            tooltip (string): tooltip to be set.
        '''
        if self.palette is None or self._tooltip is None:
            self.palette = Palette(tooltip)
        elif self.palette is not None:
            self.palette.set_primary_text(tooltip)

        self._tooltip = tooltip

        # Set label, shows up when toolbar overflows
        Gtk.RadioToolButton.set_label(self, tooltip)

    def get_tooltip(self):
        '''
        Return the tooltip.
        '''
        return self._tooltip

    tooltip = GObject.property(type=str,
                               setter=set_tooltip,
                               getter=get_tooltip)

    def set_accelerator(self, accelerator):
        '''
        Set keyboard shortcut that activates this button.

        Args:
            accelerator (string): accelerator to be set. Should be in
            form <modifier>Letter.
        '''
        self._accelerator = accelerator
        toolbutton.setup_accelerator(self)

    def get_accelerator(self):
        '''
        Return accelerator string.
        '''
        return self._accelerator

    accelerator = GObject.property(type=str,
                                   setter=set_accelerator,
                                   getter=get_accelerator)

    def set_icon_name(self, icon_name):
        '''
        Set name of icon.

        Args:
            icon_name (string): name of icon
        '''
        icon = Icon(icon_name=icon_name, xo_color=self._xo_color)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        '''
        Return icon name, or None if there is no icon name.
        '''
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.property(type=str,
                                 setter=set_icon_name,
                                 getter=get_icon_name)

    def set_xo_color(self, xo_color):
        '''
        Set XoColor of button icon.

        Args:
            xo_color (sugar3.graphics.xocolor.XoColor): xocolor to be set.
        '''
        if self._xo_color != xo_color:
            self._xo_color = xo_color
            if self.props.icon_widget is not None:
                self.props.icon_widget.props.xo_color = xo_color

    def get_xo_color(self):
        '''
        Return xocolor.
        '''
        return self._xo_color

    xo_color = GObject.property(type=object,
                                setter=set_xo_color,
                                getter=get_xo_color)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(type=object,
                               setter=set_palette,
                               getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def do_draw(self, cr):
        '''
        Implementation method for drawing the button.
        '''
        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.RadioToolButton.do_draw(self, cr)

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        return False

    def get_hide_tooltip_on_click(self):
        '''
        Return True if the tooltip is hidden when a user
        clicks on the button, otherwise return False.
        '''
        return self._hide_tooltip_on_click

    def set_hide_tooltip_on_click(self, hide_tooltip_on_click):
        '''
        Set whether or not the tooltip is hidden when a user
        clicks on the button.

        Args:
            hide_tooltip_on_click (bool): True if the tooltip is
            hidden on click, and False otherwise.
        '''
        if self._hide_tooltip_on_click != hide_tooltip_on_click:
            self._hide_tooltip_on_click = hide_tooltip_on_click

    hide_tooltip_on_click = GObject.property(type=bool,
                                             default=True,
                                             getter=get_hide_tooltip_on_click,
                                             setter=set_hide_tooltip_on_click)

    def do_clicked(self):
        '''
        Implementation method for hiding the tooltip when
        the button is clicked.
        '''
        if self._hide_tooltip_on_click and self.palette:
            self.palette.popdown(True)
class ToolButton(Gtk.ToolButton):

    __gtype_name__ = 'SugarToolButton'

    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.get_child().connect('can-activate-accel',
                                 self.__button_can_activate_accel_cb)

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def __button_can_activate_accel_cb(self, button, signal_id):
        # Accept activation via accelerators regardless of this widget's state
        return True

    def set_tooltip(self, tooltip):
        """ Set a simple palette with just a single label.
        """
        if self.palette is None or self._tooltip is None:
            self.palette = Palette(tooltip)
        elif self.palette is not None:
            self.palette.set_primary_text(tooltip)

        self._tooltip = tooltip

        # Set label, shows up when toolbar overflows
        Gtk.ToolButton.set_label(self, tooltip)

    def get_tooltip(self):
        return self._tooltip

    tooltip = GObject.property(type=str,
                               setter=set_tooltip,
                               getter=get_tooltip)

    def get_hide_tooltip_on_click(self):
        return self._hide_tooltip_on_click

    def set_hide_tooltip_on_click(self, hide_tooltip_on_click):
        if self._hide_tooltip_on_click != hide_tooltip_on_click:
            self._hide_tooltip_on_click = hide_tooltip_on_click

    hide_tooltip_on_click = GObject.property(type=bool,
                                             default=True,
                                             getter=get_hide_tooltip_on_click,
                                             setter=set_hide_tooltip_on_click)

    def set_accelerator(self, accelerator):
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        return self._accelerator

    accelerator = GObject.property(type=str,
                                   setter=set_accelerator,
                                   getter=get_accelerator)

    def set_icon_name(self, icon_name):
        icon = Icon(icon_name=icon_name)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.property(type=str,
                                 setter=set_icon_name,
                                 getter=get_icon_name)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(type=object,
                               setter=set_palette,
                               getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def do_draw(self, cr):
        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(cr, self.palette)

        return False

    def do_clicked(self):
        if self._hide_tooltip_on_click and self.palette:
            self.palette.popdown(True)
    def __init__(self, value_range, default_value, default_image):

        Gtk.ToolItem.__init__(self)
        self._palette_invoker = ToolInvoker()

        self.palette = None
        self._values = value_range
        self._palette_invoker.attach_tool(self)

        # theme the buttons, can be removed if add the style to the sugar css
        # these are the same values used in gtk-widgets.css.em
        if style.zoom(100) == 100:
            subcell_size = 15
            default_padding = 6
        else:
            subcell_size = 11
            default_padding = 4

        hbox = Gtk.HBox()
        vbox = Gtk.VBox()
        self.add(vbox)
        # add a vbox to set the padding up and down
        vbox.pack_start(hbox, True, True, default_padding)

        self._size_down = ToolButton('go-previous-paired')
        self._palette_invoker.attach_tool(self._size_down)

        self._size_down.set_can_focus(False)
        self._size_down.connect('clicked', self.__value_changed_cb, False)
        hbox.pack_start(self._size_down, False, False, 5)

        # TODO: default?
        self._default_value = default_value
        self._value = self._default_value

        self.image_wrapper = Gtk.EventBox()
        self._intensityImage = Gtk.Image()
        self.image_wrapper.add(self._intensityImage)
        self.image_wrapper.show()
        self._intensityImage.set_from_file(default_image)
        self._intensityImage.show()
        self._palette_invoker.attach_widget(self.image_wrapper)

        hbox.pack_start(self.image_wrapper, False, False, 10)

        self._size_up = ToolButton('go-next-paired')

        self._palette_invoker.attach_tool(self._size_up)

        self._size_up.set_can_focus(False)
        self._size_up.connect('clicked', self.__value_changed_cb, True)
        hbox.pack_start(self._size_up, False, False, 5)

        radius = 2 * subcell_size
        theme_up = "GtkButton {border-radius:0px %dpx %dpx 0px;}" % (radius,
                                                                     radius)
        css_provider_up = Gtk.CssProvider()
        css_provider_up.load_from_data(theme_up)

        style_context = self._size_up.get_style_context()
        style_context.add_provider(css_provider_up,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        theme_down = "GtkButton {border-radius: %dpx 0px 0px %dpx;}" % (radius,
                                                                        radius)
        css_provider_down = Gtk.CssProvider()
        css_provider_down.load_from_data(theme_down)
        style_context = self._size_down.get_style_context()
        style_context.add_provider(css_provider_down,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        self.show_all()
class ProgressToolButton(ToolButton):
    """
    This class provides a simple wrapper based on the :class:`ToolButton`
    Displays the progress filling the ToolButton icon.

    Call update(progress) with the new progress to update the ToolButton icon.

    The direction defaults to 'vertical', in which case the icon is
    filled from bottom to top.  If direction is set to 'horizontal',
    it will be filled from right to left or from left to right,
    depending on the system's language RTL setting.
    """

    __gtype_name__ = 'SugarProgressToolButton'

    def __init__(self,
                 icon_name=None,
                 pixel_size=None,
                 direction=Gtk.Orientation.VERTICAL,
                 **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._progress = 0.0
        self._icon_name = icon_name
        self._pixel_size = pixel_size
        self._direction = direction

        GObject.GObject.__init__(self, **kwargs)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)

        self._stroke = get_surface(
            icon_name=self._icon_name,
            width=self._pixel_size,
            height=self._pixel_size,
            stroke_color=style.COLOR_BUTTON_GREY.get_svg(),
            fill_color=style.COLOR_TRANSPARENT.get_svg())

        self._fill = get_surface(
            icon_name=self._icon_name,
            width=self._pixel_size,
            height=self._pixel_size,
            stroke_color=style.COLOR_TRANSPARENT.get_svg(),
            fill_color=style.COLOR_WHITE.get_svg())

    def do_draw(self, cr):
        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()

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        # Changes the outline color of the progressicon on activation
        if self._progress > 0:
            self._stroke = get_surface(
                icon_name=self._icon_name,
                width=self._pixel_size,
                height=self._pixel_size,
                stroke_color=style.COLOR_WHITE.get_svg(),
                fill_color=style.COLOR_TRANSPARENT.get_svg())
        else:
            self._stroke = get_surface(
                icon_name=self._icon_name,
                width=self._pixel_size,
                height=self._pixel_size,
                stroke_color=style.COLOR_BUTTON_GREY.get_svg(),
                fill_color=style.COLOR_TRANSPARENT.get_svg())

        allocation = self.get_allocation()

        # Center the graphic in the allocated space.
        margin_x = (allocation.width - self._stroke.get_width()) / 2
        margin_y = (allocation.height - self._stroke.get_height()) / 2
        cr.translate(margin_x, margin_y)

        # Paint the fill, clipping it by the progress.
        x_, y_ = 0, 0
        width, height = self._stroke.get_width(), self._stroke.get_height()
        if self._direction == 'vertical':  # vertical direction, bottom to top
            y_ = self._stroke.get_height()
            height *= self._progress * -1
        else:
            rtl_direction = \
                Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL
            if rtl_direction:  # horizontal direction, right to left
                x_ = self._stroke.get_width()
                width *= self._progress * -1
            else:  # horizontal direction, left to right
                width *= self._progress

        cr.rectangle(x_, y_, width, height)
        cr.clip()
        cr.set_source_surface(self._fill, 0, 0)
        cr.paint()

        # Paint the stroke over the fill.
        cr.reset_clip()
        cr.set_source_surface(self._stroke, 0, 0)
        cr.paint()

        return False

    def update(self, progress):
        # Updates the progress
        self._progress = progress
        self.queue_draw()
class ToggleToolButton(Gtk.ToggleToolButton):
    '''
    UI for toggletoolbutton.
    A ToggleToolButton is a ToolItem that contains a toggle button,
    having an icon, a tooltip palette, and an accelerator.
    Use ToggleToolButton.new() to create a new ToggleToolButton.

    Args:
        accelerator (string): keyboard shortcut to be used to
        activate this button.
        Find about format here :
        https://developer.gnome.org/gtk3/stable/gtk3-Keyboard-Accelerators.html#gtk-accelerator-parse

        tooltip (string): tooltip to be displayed when user
        hovers over toggle button.

    Keyword Args:
        icon_name(string): name of themed icon which is to be used.
    '''

    __gtype_name__ = 'SugarToggleToolButton'

    def __init__(self, icon_name=None):
        GObject.GObject.__init__(self)

        self._palette_invoker = ToolInvoker(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def set_icon_name(self, icon_name):
        '''
        Sets the icon for the tool button from a named themed icon.
        If it is none then no icon will be shown.

        Args:
            icon_name(string): The name for a themed icon.
            It can be set as 'None' too.

        Example:
            set_icon_name('view-radial')
        '''
        icon = Icon(icon_name=icon_name)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        '''
        The get_icon_name() method returns the value of the icon_name
        property that contains the name of a themed icon or None.
        '''
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.property(type=str,
                                 setter=set_icon_name,
                                 getter=get_icon_name)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(type=object,
                               setter=set_palette,
                               getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def set_tooltip(self, text):
        '''
        Sets the tooltip of the toogle tool button. Displays when
        user hovers over the button with cursor.

        Args:
            tooltip (string): tooltip to be added to the button
        '''
        self.set_palette(Palette(text))

    def set_accelerator(self, accelerator):
        '''
        Sets keyboard shortcut that activates this button.

        Args:
            accelerator(string): accelerator to be set. Should be in
            form <modifier>Letter
            Find about format here :
            https://developer.gnome.org/gtk3/stable/gtk3-Keyboard-Accelerators.html#gtk-accelerator-parse

        Example:
            set_accelerator(self, 'accel')
        '''
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        '''
        Returns above accelerator string.
        '''
        return self._accelerator

    accelerator = GObject.property(type=str,
                                   setter=set_accelerator,
                                   getter=get_accelerator)

    def do_draw(self, cr):
        '''
        Implementation method for drawing the toogle tool button
        '''
        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.ToggleToolButton.do_draw(self, cr)

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        return False

    def do_clicked(self):
        '''
        Implementation method for hiding the tooltip when the
        toggle button is clicked
        '''
        if self.palette:
            self.palette.popdown(True)

    palette = property(get_palette, set_palette)
class ToggleToolButton(Gtk.ToggleToolButton):

    __gtype_name__ = 'SugarToggleToolButton'

    def __init__(self, icon_name=None):
        GObject.GObject.__init__(self)

        self._palette_invoker = ToolInvoker(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def set_icon_name(self, icon_name):
        icon = Icon(icon_name=icon_name)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.property(type=str, setter=set_icon_name,
                                 getter=get_icon_name)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def set_tooltip(self, text):
        self.set_palette(Palette(text))

    def set_accelerator(self, accelerator):
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        return self._accelerator

    accelerator = GObject.property(type=str, setter=set_accelerator,
                                   getter=get_accelerator)

    def do_draw(self, cr):
        allocation = self.get_allocation()
        child = self.get_child()

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

            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.ToggleToolButton.do_draw(self, cr)

    palette = property(get_palette, set_palette)
class ButtonStrokeColor(Gtk.ToolItem):
    """Class to manage the Stroke Color of a Button"""

    __gtype_name__ = 'BrushColorToolButton'
    __gsignals__ = {
        'color-set': (GObject.SignalFlags.RUN_FIRST, None, tuple())
    }

    def __init__(self, activity, **kwargs):
        self._activity = activity
        self.properties = self._activity.area.tool
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._palette = None
        self._selected_tool = None

        GObject.GObject.__init__(self, **kwargs)

        # The Gtk.ToolButton has already added a normal button.
        # Replace it with a ColorButton
        self.color_button = BrushButton(has_invoker=False)
        self.add(self.color_button)
        self.color_button.set_brush_size(self.properties['line size'])
        self.color_button.set_brush_shape(self.properties['line shape'])
        self.color_button.set_stamp_size(20)

        # The following is so that the behaviour on the toolbar is correct.
        self.color_button.set_relief(Gtk.ReliefStyle.NONE)

        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        # This widget just proxies the following properties to the colorbutton
        self.color_button.connect('notify::color', self.__notify_change)
        self.color_button.connect('notify::icon-name', self.__notify_change)
        self.color_button.connect('notify::icon-size', self.__notify_change)
        self.color_button.connect('notify::title', self.__notify_change)
        self.color_button.connect('can-activate-accel',
                                  self.__button_can_activate_accel_cb)

        self.create_palette()

    def __button_can_activate_accel_cb(self, button, signal_id):
        # Accept activation via accelerators regardless of this widget's state
        return True

    def __notify_change(self, widget, pspec):
        self.color_button.set_color(self.get_color())
        self.notify(pspec.name)

    def _color_button_cb(self, widget, pspec):
        color = self.get_color()
        self.set_stroke_color(color)

    def create_palette(self):
        self._palette = self.get_child().create_palette()

        color_palette_hbox = self._palette._picker_hbox
        self.custom_box = Gtk.VBox()

        self.vbox_brush_options = Gtk.VBox()

        # This is where we set restrictions for size:
        # Initial value, minimum value, maximum value, step

        adj = Gtk.Adjustment(self.properties['line size'], 1.0, 100.0, 1.0)
        self.size_scale = Gtk.HScale()
        self.size_scale.set_adjustment(adj)
        self.size_scale.set_draw_value(False)
        self.size_scale.set_size_request(style.zoom(200), -1)
        self.size_label = Gtk.Label(label=_('Size'))
        self.size_label.props.halign = Gtk.Align.START
        self.vbox_brush_options.pack_start(self.size_label, True, True, 0)
        self.vbox_brush_options.pack_start(self.size_scale, True, True, 0)

        self.size_scale.connect('value-changed', self._on_value_changed)

        # Control alpha
        alpha = self.properties['alpha'] * 100
        adj_alpha = Gtk.Adjustment(alpha, 10.0, 100.0, 1.0)
        self.alpha_scale = Gtk.HScale()
        self.alpha_scale.set_adjustment(adj_alpha)
        self.alpha_scale.set_draw_value(False)
        self.alpha_scale.set_size_request(style.zoom(200), -1)
        self.alpha_label = Gtk.Label(label=_('Opacity'))
        self.alpha_label.props.halign = Gtk.Align.START
        self.vbox_brush_options.pack_start(self.alpha_label, True, True, 0)
        self.vbox_brush_options.pack_start(self.alpha_scale, True, True, 0)

        self.alpha_scale.connect('value-changed', self._on_alpha_changed)

        # User is able to choose Shapes for 'Brush' and 'Eraser'
        self.shape_box = Gtk.HBox()
        self.custom_box.pack_start(self.vbox_brush_options, True, True, 0)
        item1 = RadioToolButton()
        item1.set_icon_name('tool-shape-ellipse')

        item2 = RadioToolButton()
        item2.set_icon_name('tool-shape-rectangle')
        item2.props.group = item1

        if self.properties['line shape'] == 'circle':
            item1.set_active(True)
        else:
            item2.set_active(True)

        item1.connect('toggled', self._on_toggled, self.properties, 'circle')
        item2.connect('toggled', self._on_toggled, self.properties, 'square')

        self.shape_box.pack_start(Gtk.Label(_('Shape')), True, True, 0)
        self.shape_box.pack_start(item1, True, True, 0)
        self.shape_box.pack_start(item2, True, True, 0)

        self.vbox_brush_options.pack_start(self.shape_box, True, True, 0)

        self.keep_aspect_checkbutton = Gtk.CheckButton(_('Keep aspect'))
        ratio = self._activity.area.keep_aspect_ratio
        self.keep_aspect_checkbutton.set_active(ratio)
        self.keep_aspect_checkbutton.connect(
            'toggled', self._keep_aspect_checkbutton_toggled)
        self.vbox_brush_options.pack_start(self.keep_aspect_checkbutton, True,
                                           True, 0)

        self.custom_separator = Gtk.VSeparator()
        color_palette_hbox.pack_start(self.custom_separator,
                                      True,
                                      True,
                                      padding=style.DEFAULT_SPACING)
        color_palette_hbox.pack_start(self.custom_box,
                                      True,
                                      True,
                                      padding=style.DEFAULT_SPACING)
        color_palette_hbox.show_all()
        self._update_palette()
        return self._palette

    def _keep_aspect_checkbutton_toggled(self, checkbutton):
        self._activity.area.keep_aspect_ratio = checkbutton.get_active()

    def _update_palette(self):
        tool_name = self._selected_tool
        show_controls = ()
        show_colors = False
        if tool_name == 'brush' or tool_name is None:
            title = _('Brush properties')
            show_colors = True
            show_controls = (self.size_label, self.size_scale, self.shape_box,
                             self.alpha_label, self.alpha_scale)
        elif tool_name in ('stamp', 'load-stamp'):
            show_controls = (self.size_label, self.size_scale)
            title = _('Stamp properties')
        elif tool_name == 'eraser':
            show_controls = (self.size_label, self.size_scale, self.shape_box)
            title = _('Eraser properties')
        elif tool_name == 'bucket':
            show_colors = True
            title = _('Bucket properties')
        elif tool_name == 'picker':
            title = _('Picker properties')
        elif tool_name == 'marquee-rectangular':
            title = _('Select Area')
            show_controls = (self.keep_aspect_checkbutton, )
        else:
            title = ''

        self._palette._picker_hbox.show_all()
        # Hide palette color widgets except size:
        if not show_colors:
            palette_children = self._palette._picker_hbox.get_children()
            for ch in palette_children:
                if ch != self.custom_box:
                    ch.hide()
        elif not show_controls:
            self.custom_separator.hide()

        self.vbox_brush_options.show_all()
        controls = self.vbox_brush_options.get_children()
        for control in controls:
            if control not in show_controls:
                control.hide()

        # Change title:
        self.set_title(title)

        self._palette._picker_hbox.resize_children()
        self._palette._picker_hbox.queue_draw()

    def update_stamping(self):
        if self.color_button.is_stamping():
            self.size_scale.set_value(self.color_button.stamp_size)
        else:
            self.size_scale.set_value(self.color_button.brush_size)
        self.size_scale.queue_draw()
        self._update_palette()

    def _on_alpha_changed(self, scale):
        alpha = scale.get_value() / 100.0
        self._activity.area.set_alpha(alpha)
        self.color_button.set_alpha(alpha)

    def _on_value_changed(self, scale):
        size = int(scale.get_value())
        if self.color_button.is_stamping():
            # avoid stamps too small
            if size > 5:
                self.properties['stamp size'] = size
                resized_stamp = self._activity.area.resize_stamp(size)
                self.color_button.set_resized_stamp(resized_stamp)
                self.color_button.set_stamp_size(self.properties['stamp size'])
        else:
            self.properties['line size'] = size
            self.color_button.set_brush_size(self.properties['line size'])
        self._activity.area.set_tool(self.properties)

    def _on_toggled(self, radiobutton, tool, shape):
        if radiobutton.get_active():
            self.properties['line shape'] = shape
            self.color_button.set_brush_shape(shape)
            self.color_button.set_brush_size(self.properties['line size'])

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def set_expanded(self, expanded):
        box = self.toolbar_box
        if not box:
            return

        if not expanded:
            self._palette_invoker.notify_popdown()
            return

        if box.expanded_button is not None:
            box.expanded_button.queue_draw()
            if box.expanded_button != self:
                box.expanded_button.set_expanded(False)
        box.expanded_button = self

    def get_toolbar_box(self):
        parent = self.get_parent()
        if not hasattr(parent, 'owner'):
            return None
        return parent.owner

    toolbar_box = property(get_toolbar_box)

    def set_color(self, color):
        self.color_button.set_color(color)

    def get_color(self):
        return self.get_child().props.color

    color = GObject.property(type=object, getter=get_color, setter=set_color)

    def set_title(self, title):
        self.get_child().props.title = title

    def get_title(self):
        return self.get_child().props.title

    title = GObject.property(type=str, getter=get_title, setter=set_title)

    def get_selected_tool(self):
        return self._selected_tool

    def set_selected_tool(self, tool_name):
        self._selected_tool = tool_name

    def do_draw(self, cr):
        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.ToolItem.do_draw(self, cr)

        if self._palette and self._palette.is_up():
            invoker = self._palette.props.invoker
            invoker.draw_rectangle(cr, self._palette)

        return False
Exemple #25
0
class PaletteBox(Gtk.ToolItem):

    __gsignals__ = {
        'changed': (GObject.SignalFlags.RUN_LAST, None, ([])), }

    def __init__(self, default, options):
        self._palette_invoker = ToolInvoker()
        Gtk.ToolItem.__init__(self)
        self._label = Gtk.Label()
        bt = Gtk.Button('')
        bt.set_can_focus(False)
        bt.remove(bt.get_children()[0])
        self._box = Gtk.HBox()
        bt.add(self._box)
        self._icon = Icon(icon_name='')
        self._box.pack_start(self._icon, False, False, 5)
        self._box.pack_end(self._label, False, False, 5)
        self.add(bt)
        self.show_all()

        # theme the button, can be removed if add the style to the sugar css
        if style.zoom(100) == 100:
            subcell_size = 15
        else:
            subcell_size = 11
        radius = 2 * subcell_size
        theme = "GtkButton {border-radius: %dpx;}" % radius
        css_provider = Gtk.CssProvider()
        css_provider.load_from_data(theme)
        style_context = bt.get_style_context()
        style_context.add_provider(css_provider,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        # init palette
        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True

        self.palette = Palette(_('Select option'))
        self.palette.set_invoker(self._palette_invoker)

        # load the fonts in the palette menu
        self._menu_box = PaletteMenuBox()
        self.props.palette.set_content(self._menu_box)
        self._menu_box.show()

        for option in options:
            if option.__class__ is str:
                self._add_menu(option, activate_cb=self.__option_selected_cb)
            else:
                self._add_menu(option[0], icon=option[1],
                               activate_cb=self.__option_selected_cb)

        self.set_value(default)

    def _set_icon(self, icon_name):
        self._box.remove(self._box.get_children()[0])
        self._icon = Icon(icon_name=icon_name,
                          pixel_size=style.STANDARD_ICON_SIZE)
        self._icon.show()
        self._box.pack_start(self._icon, False, False, 5)

    def __option_selected_cb(self, menu, option):
        self.set_value(option)
        self.emit('changed')

    def _add_menu(self, option, icon=None, activate_cb=None):
        if icon is not None:
            menu_item = PaletteMenuItem(icon_name=icon)
            if activate_cb is not None:
                menu_item.connect('activate', activate_cb, [option, icon])
        else:
            menu_item = PaletteMenuItem()
            if activate_cb is not None:
                menu_item.connect('activate', activate_cb, option)
        menu_item.set_label(option)
        self._menu_box.append_item(menu_item)
        menu_item.show()

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def set_value(self, value):
        self._value = value
        if value.__class__ is str:
            self._label.set_text(value)
        else:
            self._label.set_text(value[0])
            self._set_icon(value[1])

    def get_value(self):
        return self._value
Exemple #26
0
class FilterToolItem(Gtk.ToolButton):

    _LABEL_MAX_WIDTH = 18
    _MAXIMUM_PALETTE_COLUMNS = 4

    __gsignals__ = {
        'changed': (GObject.SignalFlags.RUN_LAST, None, ([str])),
    }

    def __init__(self, default_icon, default_value, options):
        self._palette_invoker = ToolInvoker()
        self._options = options
        Gtk.ToolButton.__init__(self)
        logging.debug('filter options %s', options)
        self._value = default_value
        self._label = self._options[default_value]
        self.set_is_important(True)
        self.set_size_request(style.GRID_CELL_SIZE, -1)

        self._label_widget = Gtk.Label()
        self._label_widget.set_alignment(0.0, 0.5)
        self._label_widget.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
        self._label_widget.set_max_width_chars(self._LABEL_MAX_WIDTH)
        self._label_widget.set_use_markup(True)
        self._label_widget.set_markup(self._label)
        self.set_label_widget(self._label_widget)
        self._label_widget.show()

        self.set_widget_icon(icon_name=default_icon)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        self.palette = Palette(_('Select language'))
        self.palette.set_invoker(self._palette_invoker)

        self.props.palette.set_content(self.set_palette_list(options))

    def set_options(self, options):
        self._options = options
        self.palette = Palette(_('Select language'))
        self.palette.set_invoker(self._palette_invoker)
        self.props.palette.set_content(self.set_palette_list(options))
        if self._value not in self._options.keys():
            new_value = self._options.keys()[0]
            self._value = new_value
            self._set_widget_label(self._options[new_value])
            self.emit('changed', new_value)

    def set_widget_icon(self, icon_name=None):
        icon = Icon(icon_name=icon_name, pixel_size=style.SMALL_ICON_SIZE)
        self.set_icon_widget(icon)
        icon.show()

    def _set_widget_label(self, label=None):
        # FIXME: Ellipsis is not working on these labels.
        if label is None:
            label = self._label
        if len(label) > self._LABEL_MAX_WIDTH:
            label = label[0:7] + '...' + label[-7:]
        self._label_widget.set_markup(label)
        self._label = label

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(type=object,
                               setter=set_palette,
                               getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def do_draw(self, cr):
        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(cr, self.palette)

        return False

    def set_palette_list(self, options):
        _menu_item = PaletteMenuItem(text_label=options[options.keys()[0]])
        req2 = _menu_item.get_preferred_size()[1]
        menuitem_width = req2.width
        menuitem_height = req2.height

        palette_width = Gdk.Screen.width() - style.GRID_CELL_SIZE
        palette_height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 3

        nx = min(self._MAXIMUM_PALETTE_COLUMNS,
                 int(palette_width / menuitem_width))
        ny = min(int(palette_height / menuitem_height), len(options) + 1)
        if ny >= len(options):
            nx = 1
            ny = len(options)

        grid = Gtk.Grid()
        grid.set_row_spacing(style.DEFAULT_PADDING)
        grid.set_column_spacing(0)
        grid.set_border_width(0)
        grid.show()

        x = 0
        y = 0

        for key in options.keys():
            menu_item = PaletteMenuItem()
            menu_item.set_label(options[key])

            menu_item.set_size_request(style.GRID_CELL_SIZE * 3, -1)

            menu_item.connect('button-release-event', self._option_selected,
                              key)
            grid.attach(menu_item, x, y, 1, 1)
            x += 1
            if x == nx:
                x = 0
                y += 1

            menu_item.show()

        if palette_height < (y * menuitem_height + style.GRID_CELL_SIZE):
            # if the grid is bigger than the palette, put in a scrolledwindow
            scrolled_window = Gtk.ScrolledWindow()
            scrolled_window.set_policy(Gtk.PolicyType.NEVER,
                                       Gtk.PolicyType.AUTOMATIC)
            scrolled_window.set_size_request(nx * menuitem_width,
                                             (ny + 1) * menuitem_height)
            scrolled_window.add_with_viewport(grid)
            return scrolled_window
        else:
            return grid

    def _option_selected(self, menu_item, event, key):
        self._set_widget_label(self._options[key])
        self._value = key
        self.emit('changed', key)
Exemple #27
0
    def __init__(self, value_range, default_value, default_image):

        Gtk.ToolItem.__init__(self)
        self._palette_invoker = ToolInvoker()

        self.palette = None
        self._values = value_range
        self._palette_invoker.attach_tool(self)

        # theme the buttons, can be removed if add the style to the sugar css
        # these are the same values used in gtk-widgets.css.em
        if style.zoom(100) == 100:
            subcell_size = 15
            default_padding = 6
        else:
            subcell_size = 11
            default_padding = 4

        hbox = Gtk.HBox()
        vbox = Gtk.VBox()
        self.add(vbox)
        # add a vbox to set the padding up and down
        vbox.pack_start(hbox, True, True, default_padding)

        self._size_down = ToolButton('go-previous-paired')
        self._palette_invoker.attach_tool(self._size_down)

        self._size_down.set_can_focus(False)
        self._size_down.connect('clicked', self.__value_changed_cb, False)
        hbox.pack_start(self._size_down, False, False, 5)

        # TODO: default?
        self._default_value = default_value
        self._value = self._default_value

        self.image_wrapper = Gtk.EventBox()
        self._intensityImage = Gtk.Image()
        self.image_wrapper.add(self._intensityImage)
        self.image_wrapper.show()
        self._intensityImage.set_from_file(default_image)
        self._intensityImage.show()
        self._palette_invoker.attach_widget(self.image_wrapper)

        hbox.pack_start(self.image_wrapper, False, False, 10)

        self._size_up = ToolButton('go-next-paired')

        self._palette_invoker.attach_tool(self._size_up)

        self._size_up.set_can_focus(False)
        self._size_up.connect('clicked', self.__value_changed_cb, True)
        hbox.pack_start(self._size_up, False, False, 5)

        radius = 2 * subcell_size
        theme_up = "GtkButton {border-radius:0px %dpx %dpx 0px;}" % (radius,
                                                                     radius)
        css_provider_up = Gtk.CssProvider()
        css_provider_up.load_from_data(theme_up)

        style_context = self._size_up.get_style_context()
        style_context.add_provider(css_provider_up,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        theme_down = "GtkButton {border-radius: %dpx 0px 0px %dpx;}" % (radius,
                                                                        radius)
        css_provider_down = Gtk.CssProvider()
        css_provider_down.load_from_data(theme_down)
        style_context = self._size_down.get_style_context()
        style_context.add_provider(css_provider_down,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        self.show_all()
class ToggleToolButton(Gtk.ToggleToolButton):

    __gtype_name__ = 'SugarToggleToolButton'

    def __init__(self, icon_name=None):
        GObject.GObject.__init__(self)

        self._palette_invoker = ToolInvoker(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def set_icon_name(self, icon_name):
        icon = Icon(icon_name=icon_name)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.property(type=str, setter=set_icon_name,
                                 getter=get_icon_name)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def set_tooltip(self, text):
        self.set_palette(Palette(text))

    def set_accelerator(self, accelerator):
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        return self._accelerator

    accelerator = GObject.property(type=str, setter=set_accelerator,
                                   getter=get_accelerator)

    def do_draw(self, cr):
        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.ToggleToolButton.do_draw(self, cr)

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        return False

    def do_clicked(self):
        if self.palette:
            self.palette.popdown(True)

    palette = property(get_palette, set_palette)
class ToolButton(Gtk.ToolButton):
    '''
    The ToolButton class manages a Gtk.ToolButton styled for Sugar.

    Keyword Args:
        icon_name(string): name of themed icon.

        accelerator (string): keyboard shortcut to be used to
            activate this button.

        tooltip (string): tooltip to be displayed when user hovers
            over button.

        hide_tooltip_on_click (bool): Whether or not the tooltip
            is hidden when user clicks on button.

    '''

    __gtype_name__ = 'SugarToolButton'

    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.get_child().connect('can-activate-accel',
                                 self.__button_can_activate_accel_cb)

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def __button_can_activate_accel_cb(self, button, signal_id):
        # Accept activation via accelerators regardless of this widget's state
        return True

    def set_tooltip(self, tooltip):
        '''
        Set the tooltip.

        Args:
            tooltip (string): tooltip to be set.
        '''
        if self.palette is None or self._tooltip is None:
            self.palette = Palette(tooltip)
        elif self.palette is not None:
            self.palette.set_primary_text(tooltip)

        self._tooltip = tooltip

        # Set label, shows up when toolbar overflows
        Gtk.ToolButton.set_label(self, tooltip)

    def get_tooltip(self):
        '''
        Return the tooltip.
        '''
        return self._tooltip

    tooltip = GObject.Property(type=str,
                               setter=set_tooltip,
                               getter=get_tooltip)

    def get_hide_tooltip_on_click(self):
        '''
        Return True if the tooltip is hidden when a user
        clicks on the button, otherwise return False.
        '''
        return self._hide_tooltip_on_click

    def set_hide_tooltip_on_click(self, hide_tooltip_on_click):
        '''
        Set whether or not the tooltip is hidden when a user
        clicks on the button.

        Args:
            hide_tooltip_on_click (bool): True if the tooltip is
            hidden on click, and False otherwise.
        '''
        if self._hide_tooltip_on_click != hide_tooltip_on_click:
            self._hide_tooltip_on_click = hide_tooltip_on_click

    hide_tooltip_on_click = GObject.Property(type=bool,
                                             default=True,
                                             getter=get_hide_tooltip_on_click,
                                             setter=set_hide_tooltip_on_click)

    def set_accelerator(self, accelerator):
        '''
        Set accelerator that activates the button.

        Args:
            accelerator(string): accelerator to be set.
        '''
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        '''
        Return accelerator that activates the button.
        '''
        return self._accelerator

    accelerator = GObject.Property(type=str,
                                   setter=set_accelerator,
                                   getter=get_accelerator)

    def set_icon_name(self, icon_name):
        '''
        Set name of icon.

        Args:
            icon_name (string): name of icon
        '''
        icon = Icon(icon_name=icon_name)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        '''
        Return icon name, or None if there is no icon name.
        '''
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.Property(type=str,
                                 setter=set_icon_name,
                                 getter=get_icon_name)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.Property(type=object,
                               setter=set_palette,
                               getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.Property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def do_draw(self, cr):
        '''
        Implementation method for drawing the button.
        '''
        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(cr, self.palette)

        return False

    def do_clicked(self):
        '''
        Implementation method for hiding the tooltip when
        the button is clicked.
        '''
        if self._hide_tooltip_on_click and self.palette:
            self.palette.popdown(True)
class FilterToolItem(Gtk.ToolButton):
    __gsignals__ = {
        'changed': (GObject.SignalFlags.RUN_LAST, None, ([])), }

    def __init__(self, tagline, default_icon, default_label, palette_content):
        self._palette_invoker = ToolInvoker()
        Gtk.ToolButton.__init__(self)
        self._label = default_label

        self.set_is_important(False)
        self.set_size_request(style.GRID_CELL_SIZE, -1)

        self._label_widget = Gtk.Label()
        self._label_widget.set_alignment(0.0, 0.5)
        self._label_widget.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
        self._label_widget.set_max_width_chars(10)
        self._label_widget.set_use_markup(True)
        self._label_widget.set_markup(default_label)
        self.set_label_widget(self._label_widget)
        self._label_widget.show()

        self.set_widget_icon(icon_name=default_icon)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        self.palette = Palette(tagline)
        self.palette.set_invoker(self._palette_invoker)

        self.props.palette.set_content(palette_content)

    def set_widget_icon(self, icon_name=None, file_name=None):
        if file_name is not None:
            icon = Icon(file=file_name,
                        pixel_size=style.SMALL_ICON_SIZE,
                        xo_color=XoColor('white'))
        else:
            icon = Icon(icon_name=icon_name,
                        pixel_size=style.SMALL_ICON_SIZE,
                        xo_color=XoColor('white'))
        self.set_icon_widget(icon)
        icon.show()

    def set_widget_label(self, label=None):
        # FIXME: Ellipsis is not working on these labels.
        if label is None:
            label = self._label
        """
        if len(label) > 10:
            label = label[0:7] + '...' + label[-7:]
        """
        self._label_widget.set_markup(label)
        self._label = label

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.Property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.Property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def do_draw(self, cr):
        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(cr, self.palette)

        return False
Exemple #31
0
class ToolButton(Gtk.ToolButton):
    '''
    The ToolButton class manages a Gtk.ToolButton styled for Sugar.

    Keyword Args:
        icon_name(string): name of themed icon.

        accelerator (string): keyboard shortcut to be used to
            activate this button.

        tooltip (string): tooltip to be displayed when user hovers
            over button.

        hide_tooltip_on_click (bool): Whether or not the tooltip
            is hidden when user clicks on button.

    '''

    __gtype_name__ = 'SugarToolButton'

    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.get_child().connect('can-activate-accel',
                                 self.__button_can_activate_accel_cb)

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def __button_can_activate_accel_cb(self, button, signal_id):
        # Accept activation via accelerators regardless of this widget's state
        return True

    def set_tooltip(self, tooltip):
        '''
        Set the tooltip.

        Args:
            tooltip (string): tooltip to be set.
        '''
        if self.palette is None or self._tooltip is None:
            self.palette = Palette(tooltip)
        elif self.palette is not None:
            self.palette.set_primary_text(tooltip)

        self._tooltip = tooltip

        # Set label, shows up when toolbar overflows
        Gtk.ToolButton.set_label(self, tooltip)

    def get_tooltip(self):
        '''
        Return the tooltip.
        '''
        return self._tooltip

    tooltip = GObject.property(type=str, setter=set_tooltip,
                               getter=get_tooltip)

    def get_hide_tooltip_on_click(self):
        '''
        Return True if the tooltip is hidden when a user
        clicks on the button, otherwise return False.
        '''
        return self._hide_tooltip_on_click

    def set_hide_tooltip_on_click(self, hide_tooltip_on_click):
        '''
        Set whether or not the tooltip is hidden when a user
        clicks on the button.

        Args:
            hide_tooltip_on_click (bool): True if the tooltip is
            hidden on click, and False otherwise.
        '''
        if self._hide_tooltip_on_click != hide_tooltip_on_click:
            self._hide_tooltip_on_click = hide_tooltip_on_click

    hide_tooltip_on_click = GObject.property(
        type=bool, default=True, getter=get_hide_tooltip_on_click,
        setter=set_hide_tooltip_on_click)

    def set_accelerator(self, accelerator):
        '''
        Set accelerator that activates the button.

        Args:
            accelerator(string): accelerator to be set.
        '''
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        '''
        Return accelerator that activates the button.
        '''
        return self._accelerator

    accelerator = GObject.property(type=str, setter=set_accelerator,
                                   getter=get_accelerator)

    def set_icon_name(self, icon_name):
        '''
        Set name of icon.

        Args:
            icon_name (string): name of icon
        '''
        icon = Icon(icon_name=icon_name)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        '''
        Return icon name, or None if there is no icon name.
        '''
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.property(type=str, setter=set_icon_name,
                                 getter=get_icon_name)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def do_draw(self, cr):
        '''
        Implementation method for drawing the button.
        '''
        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(cr, self.palette)

        return False

    def do_clicked(self):
        '''
        Implementation method for hiding the tooltip when
        the button is clicked.
        '''
        if self._hide_tooltip_on_click and self.palette:
            self.palette.popdown(True)
class IntensitySelector(Gtk.ToolItem):

    __gsignals__ = {
        'changed': (GObject.SignalFlags.RUN_LAST, None, ([])), }

    def __init__(self, value_range, default_value, default_image):

        Gtk.ToolItem.__init__(self)
        self._palette_invoker = ToolInvoker()

        self.palette = None
        self._values = value_range
        self._palette_invoker.attach_tool(self)

        # theme the buttons, can be removed if add the style to the sugar css
        # these are the same values used in gtk-widgets.css.em
        if style.zoom(100) == 100:
            subcell_size = 15
            default_padding = 6
        else:
            subcell_size = 11
            default_padding = 4

        hbox = Gtk.HBox()
        vbox = Gtk.VBox()
        self.add(vbox)
        # add a vbox to set the padding up and down
        vbox.pack_start(hbox, True, True, default_padding)

        self._size_down = ToolButton('go-previous-paired')
        self._palette_invoker.attach_tool(self._size_down)

        self._size_down.set_can_focus(False)
        self._size_down.connect('clicked', self.__value_changed_cb, False)
        hbox.pack_start(self._size_down, False, False, 5)

        # TODO: default?
        self._default_value = default_value
        self._value = self._default_value

        self.image_wrapper = Gtk.EventBox()
        self._intensityImage = Gtk.Image()
        self.image_wrapper.add(self._intensityImage)
        self.image_wrapper.show()
        self._intensityImage.set_from_file(default_image)
        self._intensityImage.show()
        self._palette_invoker.attach_widget(self.image_wrapper)

        hbox.pack_start(self.image_wrapper, False, False, 10)

        self._size_up = ToolButton('go-next-paired')

        self._palette_invoker.attach_tool(self._size_up)

        self._size_up.set_can_focus(False)
        self._size_up.connect('clicked', self.__value_changed_cb, True)
        hbox.pack_start(self._size_up, False, False, 5)

        radius = 2 * subcell_size
        theme_up = "GtkButton {border-radius:0px %dpx %dpx 0px;}" % (radius,
                                                                     radius)
        css_provider_up = Gtk.CssProvider()
        css_provider_up.load_from_data(theme_up)

        style_context = self._size_up.get_style_context()
        style_context.add_provider(css_provider_up,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        theme_down = "GtkButton {border-radius: %dpx 0px 0px %dpx;}" % (radius,
                                                                        radius)
        css_provider_down = Gtk.CssProvider()
        css_provider_down.load_from_data(theme_down)
        style_context = self._size_down.get_style_context()
        style_context.add_provider(css_provider_down,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        self.show_all()

    def __destroy_cb(self, **args):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def __value_changed_cb(self, button, increase):
        if self._value in self._values:
            i = self._values.index(self._value)
            if increase:
                if i < len(self._values) - 1:
                    i += 1
            else:
                if i > 0:
                    i -= 1
        else:
            i = self._values.index(self._default_value)

        self._value = self._values[i]
        self._size_down.set_sensitive(i != 0)
        self._size_up.set_sensitive(i < len(self._values) - 1)
        self.emit('changed')

    def set_value(self, val):
        if val not in self._values:
            # assure the val assigned is in the range
            # if not, assign one close.
            for v in self._values:
                if v > val:
                    val = v
                    break
            if val > self._values[-1]:
                size = self._values[-1]

        self._value = size
        self._size_label.set_text(str(self._value))

        # update the buttons states
        i = self._values.index(self._value)
        self._size_down.set_sensitive(i != 0)
        self._size_up.set_sensitive(i < len(self._value) - 1)
        self.emit('changed')

    def set_tooltip(self, tooltip):
        """ Set a simple palette with just a single label.
        """
        if self.palette is None or self._tooltip is None:
            self.palette = Palette(tooltip)
        elif self.palette is not None:
            self.palette.set_primary_text(tooltip)

        self._tooltip = tooltip

    def get_hide_tooltip_on_click(self):
        return self._hide_tooltip_on_click

    def set_hide_tooltip_on_click(self, hide_tooltip_on_click):
        if self._hide_tooltip_on_click != hide_tooltip_on_click:
            self._hide_tooltip_on_click = hide_tooltip_on_click

    hide_tooltip_on_click = GObject.Property(
        type=bool, default=True, getter=get_hide_tooltip_on_click,
        setter=set_hide_tooltip_on_click)

    def get_tooltip(self):
        return self._tooltip

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.Property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.Property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def do_draw(self, cr):
        Gtk.ToolButton.do_draw(self, cr)

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        return False

    def do_clicked(self):
        if self._hide_tooltip_on_click and self.palette:
            self.palette.popdown(True)

    def set_image(self, image):
        self._intensityImage.set_from_file(image)

    def get_value(self):
        return self._value
class ColorToolButton(Gtk.ToolItem):
    # This not ideal. It would be better to subclass Gtk.ToolButton, however
    # the python bindings do not seem to be powerfull enough for that.
    # (As we need to change a variable in the class structure.)

    __gtype_name__ = 'SugarColorToolButton'
    __gsignals__ = {'color-set': (GObject.SignalFlags.RUN_FIRST, None,
                                  tuple())}

    def __init__(self, icon_name='color-preview', **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._palette = None

        GObject.GObject.__init__(self, **kwargs)

        # The Gtk.ToolButton has already added a normal button.
        # Replace it with a ColorButton
        color_button = _ColorButton(icon_name=icon_name, has_invoker=False)
        self.add(color_button)
        color_button.show()

        # The following is so that the behaviour on the toolbar is correct.
        color_button.set_relief(Gtk.ReliefStyle.NONE)
        color_button.icon_size = Gtk.IconSize.LARGE_TOOLBAR

        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        # This widget just proxies the following properties to the colorbutton
        color_button.connect('notify::color', self.__notify_change)
        color_button.connect('notify::icon-name', self.__notify_change)
        color_button.connect('notify::icon-size', self.__notify_change)
        color_button.connect('notify::title', self.__notify_change)
        color_button.connect('color-set', self.__color_set_cb)
        color_button.connect('can-activate-accel',
                             self.__button_can_activate_accel_cb)

    def __button_can_activate_accel_cb(self, button, signal_id):
        # Accept activation via accelerators regardless of this widget's state
        return True

    def set_accelerator(self, accelerator):
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        return self._accelerator

    accelerator = GObject.property(type=str, setter=set_accelerator,
                                   getter=get_accelerator)

    def create_palette(self):
        self._palette = self.get_child().create_palette()
        return self._palette

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def set_expanded(self, expanded):
        box = self.toolbar_box
        if not box:
            return

        if not expanded:
            self._palette_invoker.notify_popdown()
            return

        if box.expanded_button is not None:
            box.expanded_button.queue_draw()
            if box.expanded_button != self:
                box.expanded_button.set_expanded(False)
        box.expanded_button = self

    def get_toolbar_box(self):
        parent = self.get_parent()
        if not hasattr(parent, 'owner'):
            return None
        return parent.owner

    toolbar_box = property(get_toolbar_box)

    def set_color(self, color):
        self.get_child().props.color = color

    def get_color(self):
        return self.get_child().props.color

    color = GObject.property(type=object, getter=get_color, setter=set_color)

    def set_icon_name(self, icon_name):
        self.get_child().props.icon_name = icon_name

    def get_icon_name(self):
        return self.get_child().props.icon_name

    icon_name = GObject.property(type=str,
                                 getter=get_icon_name, setter=set_icon_name)

    def set_icon_size(self, icon_size):
        self.get_child().props.icon_size = icon_size

    def get_icon_size(self):
        return self.get_child().props.icon_size

    icon_size = GObject.property(type=int,
                                 getter=get_icon_size, setter=set_icon_size)

    def set_title(self, title):
        self.get_child().props.title = title

    def get_title(self):
        return self.get_child().props.title

    title = GObject.property(type=str, getter=get_title, setter=set_title)

    def do_draw(self, cr):
        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.ToolItem.do_draw(self, cr)

        if self._palette and self._palette.is_up():
            invoker = self._palette.props.invoker
            invoker.draw_rectangle(cr, self._palette)

        return False

    def __notify_change(self, widget, pspec):
        self.notify(pspec.name)

    def __color_set_cb(self, widget):
        self.emit('color-set')
class FilterToolItem(Gtk.ToolButton):

    _LABEL_MAX_WIDTH = 18
    _MAXIMUM_PALETTE_COLUMNS = 4

    __gsignals__ = {
        'changed': (GObject.SignalFlags.RUN_LAST, None, ([str])), }

    def __init__(self, default_icon, default_value, options):
        self._palette_invoker = ToolInvoker()
        self._options = options
        Gtk.ToolButton.__init__(self)
        logging.debug('filter options %s', options)
        self._value = default_value
        self._label = self._options[default_value]
        self.set_is_important(True)
        self.set_size_request(style.GRID_CELL_SIZE, -1)

        self._label_widget = Gtk.Label()
        self._label_widget.set_alignment(0.0, 0.5)
        self._label_widget.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
        self._label_widget.set_max_width_chars(self._LABEL_MAX_WIDTH)
        self._label_widget.set_use_markup(True)
        self._label_widget.set_markup(self._label)
        self.set_label_widget(self._label_widget)
        self._label_widget.show()

        self.set_widget_icon(icon_name=default_icon)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        self.palette = Palette(_('Select language'))
        self.palette.set_invoker(self._palette_invoker)

        self.props.palette.set_content(self.set_palette_list(options))

    def set_options(self, options):
        self._options = options
        self.palette = Palette(_('Select language'))
        self.palette.set_invoker(self._palette_invoker)
        self.props.palette.set_content(self.set_palette_list(options))
        if self._value not in self._options.keys():
            new_value = self._options.keys()[0]
            self._value = new_value
            self._set_widget_label(self._options[new_value])
            self.emit('changed', new_value)

    def set_widget_icon(self, icon_name=None):
        icon = Icon(icon_name=icon_name,
                    pixel_size=style.SMALL_ICON_SIZE)
        self.set_icon_widget(icon)
        icon.show()

    def _set_widget_label(self, label=None):
        # FIXME: Ellipsis is not working on these labels.
        if label is None:
            label = self._label
        if len(label) > self._LABEL_MAX_WIDTH:
            label = label[0:7] + '...' + label[-7:]
        self._label_widget.set_markup(label)
        self._label = label

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def do_draw(self, cr):
        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(cr, self.palette)

        return False

    def set_palette_list(self, options):
        _menu_item = PaletteMenuItem(text_label=options[options.keys()[0]])
        req2 = _menu_item.get_preferred_size()[1]
        menuitem_width = req2.width
        menuitem_height = req2.height

        palette_width = Gdk.Screen.width() - style.GRID_CELL_SIZE
        palette_height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 3

        nx = min(self._MAXIMUM_PALETTE_COLUMNS,
                 int(palette_width / menuitem_width))
        ny = min(int(palette_height / menuitem_height), len(options) + 1)
        if ny >= len(options):
            nx = 1
            ny = len(options)

        grid = Gtk.Grid()
        grid.set_row_spacing(style.DEFAULT_PADDING)
        grid.set_column_spacing(0)
        grid.set_border_width(0)
        grid.show()

        x = 0
        y = 0

        for key in options.keys():
            menu_item = PaletteMenuItem()
            menu_item.set_label(options[key])

            menu_item.set_size_request(style.GRID_CELL_SIZE * 3, -1)

            menu_item.connect('button-release-event', self._option_selected,
                              key)
            grid.attach(menu_item, x, y, 1, 1)
            x += 1
            if x == nx:
                x = 0
                y += 1

            menu_item.show()

        if palette_height < (y * menuitem_height + style.GRID_CELL_SIZE):
            # if the grid is bigger than the palette, put in a scrolledwindow
            scrolled_window = Gtk.ScrolledWindow()
            scrolled_window.set_policy(Gtk.PolicyType.NEVER,
                                       Gtk.PolicyType.AUTOMATIC)
            scrolled_window.set_size_request(nx * menuitem_width,
                                             (ny + 1) * menuitem_height)
            scrolled_window.add_with_viewport(grid)
            return scrolled_window
        else:
            return grid

    def _option_selected(self, menu_item, event, key):
        self._set_widget_label(self._options[key])
        self._value = key
        self.emit('changed', key)
class ColorToolButton(Gtk.ToolItem):
    # This not ideal. It would be better to subclass Gtk.ToolButton, however
    # the python bindings do not seem to be powerfull enough for that.
    # (As we need to change a variable in the class structure.)

    __gtype_name__ = 'SugarColorToolButton'
    __gsignals__ = {
        'color-set': (GObject.SignalFlags.RUN_FIRST, None, tuple())
    }

    def __init__(self, icon_name='color-preview', **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._palette = None

        GObject.GObject.__init__(self, **kwargs)

        # The Gtk.ToolButton has already added a normal button.
        # Replace it with a ColorButton
        color_button = _ColorButton(icon_name=icon_name, has_invoker=False)
        self.add(color_button)
        color_button.show()

        # The following is so that the behaviour on the toolbar is correct.
        color_button.set_relief(Gtk.ReliefStyle.NONE)
        color_button.icon_size = Gtk.IconSize.LARGE_TOOLBAR

        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        # This widget just proxies the following properties to the colorbutton
        color_button.connect('notify::color', self.__notify_change)
        color_button.connect('notify::icon-name', self.__notify_change)
        color_button.connect('notify::icon-size', self.__notify_change)
        color_button.connect('notify::title', self.__notify_change)
        color_button.connect('color-set', self.__color_set_cb)
        color_button.connect('can-activate-accel',
                             self.__button_can_activate_accel_cb)

    def __button_can_activate_accel_cb(self, button, signal_id):
        # Accept activation via accelerators regardless of this widget's state
        return True

    def set_accelerator(self, accelerator):
        '''
        Sets keyboard shortcut that activates this button.
        
        Args:
            accelerator(string): accelerator to be set. Should be in
            form <modifier>Letter
            Find about format here :
            https://developer.gnome.org/gtk3/stable/gtk3-Keyboard-Accelerators.html#gtk-accelerator-parse
        
        Example:
            set_accelerator(self, 'accel')
        '''
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        '''
        Returns the above accelerator string.
        '''
        return self._accelerator

    accelerator = GObject.Property(type=str,
                                   setter=set_accelerator,
                                   getter=get_accelerator)

    def create_palette(self):
        '''
        The create_palette function is called when the palette needs to be
        invoked.  For example, when the user has right clicked the icon or
        the user has hovered over the icon for a long time.
        
        The create_palette will only be called once or zero times.  The palette
        returned will be stored and re-used if the user invokes the palette
        multiple times.
        
        Your create_palette implementation does not need to
        :any:`Gtk.Widget.show` the palette, as this will be done by the
        invoker.  However, you still need to show
        the menu items, etc that you place in the palette.
        
        Returns:
            
            sugar3.graphics.palette.Palette, or None to indicate that you
            do not want a palette shown
        
        The default implementation returns None, to indicate no palette should
        be shown.
        '''
        self._palette = self.get_child().create_palette()
        return self._palette

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.Property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def set_expanded(self, expanded):
        box = self.toolbar_box
        if not box:
            return

        if not expanded:
            self._palette_invoker.notify_popdown()
            return

        if box.expanded_button is not None:
            box.expanded_button.queue_draw()
            if box.expanded_button != self:
                box.expanded_button.set_expanded(False)
        box.expanded_button = self

    def get_toolbar_box(self):
        parent = self.get_parent()
        if not hasattr(parent, 'owner'):
            return None
        return parent.owner

    toolbar_box = property(get_toolbar_box)

    def set_color(self, color):
        '''
        Sets the color of the colorbutton
        '''
        self.get_child().props.color = color

    def get_color(self):
        '''
        Gets the above set color string.
        '''
        return self.get_child().props.color

    color = GObject.Property(type=object, getter=get_color, setter=set_color)

    def set_icon_name(self, icon_name):
        '''
        Sets the icon for the tool button from a named themed icon.
        If it is none then no icon will be shown.
        
        Args:
            icon_name(string): The name for a themed icon.
            It can be set as 'None' too.
        
        Example:
            set_icon_name('view-radial')
        '''
        self.get_child().props.icon_name = icon_name

    def get_icon_name(self):
        '''
        The get_icon_name() method returns the value of the icon_name
        property that contains the name of a themed icon or None.
        '''
        return self.get_child().props.icon_name

    icon_name = GObject.Property(type=str,
                                 getter=get_icon_name,
                                 setter=set_icon_name)

    def set_icon_size(self, icon_size):
        '''
        Sets the size of icons in the colorbutton.
        '''
        self.get_child().props.icon_size = icon_size

    def get_icon_size(self):
        '''
        Gets the size of icons in the colorbutton.
        '''
        return self.get_child().props.icon_size

    icon_size = GObject.Property(type=int,
                                 getter=get_icon_size,
                                 setter=set_icon_size)

    def set_title(self, title):
        '''
        The set_title() method sets the "title" property to the value of 
        title. The "title" property contains the string that is used to 
        set the colorbutton title.
        '''
        self.get_child().props.title = title

    def get_title(self):
        '''
        Return the above title string.
        '''
        return self.get_child().props.title

    title = GObject.Property(type=str, getter=get_title, setter=set_title)

    def do_draw(self, cr):
        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.ToolItem.do_draw(self, cr)

        if self._palette and self._palette.is_up():
            invoker = self._palette.props.invoker
            invoker.draw_rectangle(cr, self._palette)

        return False

    def __notify_change(self, widget, pspec):
        self.notify(pspec.name)

    def __color_set_cb(self, widget):
        self.emit('color-set')
class ToolButton(Gtk.ToolButton):

    __gtype_name__ = 'SugarToolButton'

    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.get_child().connect('can-activate-accel',
                                 self.__button_can_activate_accel_cb)

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def __button_can_activate_accel_cb(self, button, signal_id):
        # Accept activation via accelerators regardless of this widget's state
        return True

    def set_tooltip(self, tooltip):
        """ Set a simple palette with just a single label.
        """
        if self.palette is None or self._tooltip is None:
            self.palette = Palette(tooltip)
        elif self.palette is not None:
            self.palette.set_primary_text(tooltip)

        self._tooltip = tooltip

        # Set label, shows up when toolbar overflows
        Gtk.ToolButton.set_label(self, tooltip)

    def get_tooltip(self):
        return self._tooltip

    tooltip = GObject.property(type=str, setter=set_tooltip,
        getter=get_tooltip)

    def get_hide_tooltip_on_click(self):
        return self._hide_tooltip_on_click

    def set_hide_tooltip_on_click(self, hide_tooltip_on_click):
        if self._hide_tooltip_on_click != hide_tooltip_on_click:
            self._hide_tooltip_on_click = hide_tooltip_on_click

    hide_tooltip_on_click = GObject.property(
        type=bool, default=True, getter=get_hide_tooltip_on_click,
        setter=set_hide_tooltip_on_click)

    def set_accelerator(self, accelerator):
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        return self._accelerator

    accelerator = GObject.property(type=str, setter=set_accelerator,
            getter=get_accelerator)

    def set_icon_name(self, icon_name):
        icon = Icon(icon_name=icon_name)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.property(type=str, setter=set_icon_name,
                                 getter=get_icon_name)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def do_draw(self, cr):
        child = self.get_child()
        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(cr, self.palette)

        return False

    def do_clicked(self):
        if self._hide_tooltip_on_click and self.palette:
            self.palette.popdown(True)
class ButtonStrokeColor(Gtk.ToolItem):
    """Class to manage the Stroke Color of a Button"""

    __gtype_name__ = 'BrushColorToolButton'
    __gsignals__ = {'color-set': (GObject.SignalFlags.RUN_FIRST, None,
                    tuple())}

    def __init__(self, activity, **kwargs):
        self._activity = activity
        self.properties = self._activity.area.tool
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._palette = None
        self._selected_tool = None

        GObject.GObject.__init__(self, **kwargs)

        # The Gtk.ToolButton has already added a normal button.
        # Replace it with a ColorButton
        self.color_button = BrushButton(has_invoker=False)
        self.add(self.color_button)
        self.color_button.set_brush_size(self.properties['line size'])
        self.color_button.set_brush_shape(self.properties['line shape'])
        self.color_button.set_stamp_size(20)

        # The following is so that the behaviour on the toolbar is correct.
        self.color_button.set_relief(Gtk.ReliefStyle.NONE)

        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        # This widget just proxies the following properties to the colorbutton
        self.color_button.connect('notify::color', self.__notify_change)
        self.color_button.connect('notify::icon-name', self.__notify_change)
        self.color_button.connect('notify::icon-size', self.__notify_change)
        self.color_button.connect('notify::title', self.__notify_change)
        self.color_button.connect('can-activate-accel',
                                  self.__button_can_activate_accel_cb)

        self.create_palette()

    def __button_can_activate_accel_cb(self, button, signal_id):
        # Accept activation via accelerators regardless of this widget's state
        return True

    def __notify_change(self, widget, pspec):
        self.color_button.set_color(self.get_color())
        self.notify(pspec.name)

    def _color_button_cb(self, widget, pspec):
        color = self.get_color()
        self.set_stroke_color(color)

    def create_palette(self):
        self._palette = self.get_child().create_palette()

        color_palette_hbox = self._palette._picker_hbox
        self.custom_box = Gtk.VBox()

        self.vbox_brush_options = Gtk.VBox()

        # This is where we set restrictions for size:
        # Initial value, minimum value, maximum value, step

        adj = Gtk.Adjustment(self.properties['line size'], 1.0, 100.0, 1.0)
        self.size_scale = Gtk.HScale()
        self.size_scale.set_adjustment(adj)
        self.size_scale.set_draw_value(False)
        self.size_scale.set_size_request(style.zoom(200), -1)
        self.size_label = Gtk.Label(label=_('Size'))
        self.size_label.props.halign = Gtk.Align.START
        self.vbox_brush_options.pack_start(self.size_label, True, True, 0)
        self.vbox_brush_options.pack_start(self.size_scale, True, True, 0)

        self.size_scale.connect('value-changed', self._on_value_changed)

        # Control alpha
        alpha = self.properties['alpha'] * 100
        adj_alpha = Gtk.Adjustment(alpha, 10.0, 100.0, 1.0)
        self.alpha_scale = Gtk.HScale()
        self.alpha_scale.set_adjustment(adj_alpha)
        self.alpha_scale.set_draw_value(False)
        self.alpha_scale.set_size_request(style.zoom(200), -1)
        self.alpha_label = Gtk.Label(label=_('Opacity'))
        self.alpha_label.props.halign = Gtk.Align.START
        self.vbox_brush_options.pack_start(self.alpha_label, True, True, 0)
        self.vbox_brush_options.pack_start(self.alpha_scale, True, True, 0)

        self.alpha_scale.connect('value-changed', self._on_alpha_changed)

        # User is able to choose Shapes for 'Brush' and 'Eraser'
        self.shape_box = Gtk.HBox()
        self.custom_box.pack_start(self.vbox_brush_options, True, True, 0)
        item1 = RadioToolButton()
        item1.set_icon_name('tool-shape-ellipse')

        item2 = RadioToolButton()
        item2.set_icon_name('tool-shape-rectangle')
        item2.props.group = item1

        if self.properties['line shape'] == 'circle':
            item1.set_active(True)
        else:
            item2.set_active(True)

        item1.connect('toggled', self._on_toggled, self.properties, 'circle')
        item2.connect('toggled', self._on_toggled, self.properties, 'square')

        self.shape_box.pack_start(Gtk.Label(_('Shape')), True, True, 0)
        self.shape_box.pack_start(item1, True, True, 0)
        self.shape_box.pack_start(item2, True, True, 0)

        self.vbox_brush_options.pack_start(self.shape_box, True, True, 0)

        self.keep_aspect_checkbutton = Gtk.CheckButton(_('Keep aspect'))
        ratio = self._activity.area.keep_aspect_ratio
        self.keep_aspect_checkbutton.set_active(ratio)
        self.keep_aspect_checkbutton.connect(
            'toggled', self._keep_aspect_checkbutton_toggled)
        self.vbox_brush_options.pack_start(self.keep_aspect_checkbutton, True,
                                           True, 0)

        self.custom_separator = Gtk.VSeparator()
        color_palette_hbox.pack_start(self.custom_separator, True, True,
                                      padding=style.DEFAULT_SPACING)
        color_palette_hbox.pack_start(self.custom_box, True, True,
                                      padding=style.DEFAULT_SPACING)
        color_palette_hbox.show_all()
        self._update_palette()
        return self._palette

    def _keep_aspect_checkbutton_toggled(self, checkbutton):
        self._activity.area.keep_aspect_ratio = checkbutton.get_active()

    def _update_palette(self):
        tool_name = self._selected_tool
        show_controls = ()
        show_colors = False
        if tool_name == 'brush' or tool_name is None:
            title = _('Brush properties')
            show_colors = True
            show_controls = (self.size_label, self.size_scale, self.shape_box,
                             self.alpha_label, self.alpha_scale)
        elif tool_name == 'stamp':
            show_controls = (self.size_label, self.size_scale)
            title = _('Stamp properties')
        elif tool_name == 'eraser':
            show_controls = (self.size_label, self.size_scale,
                             self.shape_box)
            title = _('Eraser properties')
        elif tool_name == 'bucket':
            show_colors = True
            title = _('Bucket properties')
        elif tool_name == 'picker':
            title = _('Picker properties')
        elif tool_name == 'marquee-rectangular':
            title = _('Select Area')
            show_controls = (self.keep_aspect_checkbutton,)
        else:
            title = ''

        self._palette._picker_hbox.show_all()
        # Hide palette color widgets except size:
        if not show_colors:
            palette_children = self._palette._picker_hbox.get_children()
            for ch in palette_children:
                if ch != self.custom_box:
                    ch.hide()
        elif not show_controls:
            self.custom_separator.hide()

        self.vbox_brush_options.show_all()
        controls = self.vbox_brush_options.get_children()
        for control in controls:
            if control not in show_controls:
                control.hide()

        # Change title:
        self.set_title(title)

        self._palette._picker_hbox.resize_children()
        self._palette._picker_hbox.queue_draw()

    def update_stamping(self):
        if self.color_button.is_stamping():
            self.size_scale.set_value(self.color_button.stamp_size)
        else:
            self.size_scale.set_value(self.color_button.brush_size)
        self._update_palette()

    def _on_alpha_changed(self, scale):
        alpha = scale.get_value() / 100.0
        self._activity.area.set_alpha(alpha)
        self.color_button.set_alpha(alpha)

    def _on_value_changed(self, scale):
        size = int(scale.get_value())
        if self.color_button.is_stamping():
            # avoid stamps too small
            if size > 5:
                self.properties['stamp size'] = size
                resized_stamp = self._activity.area.resize_stamp(size)
                self.color_button.set_resized_stamp(resized_stamp)
                self.color_button.set_stamp_size(self.properties['stamp size'])
        else:
            self.properties['line size'] = size
            self.color_button.set_brush_size(self.properties['line size'])
        self._activity.area.set_tool(self.properties)

    def _on_toggled(self, radiobutton, tool, shape):
        if radiobutton.get_active():
            self.properties['line shape'] = shape
            self.color_button.set_brush_shape(shape)
            self.color_button.set_brush_size(self.properties['line size'])

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def set_expanded(self, expanded):
        box = self.toolbar_box
        if not box:
            return

        if not expanded:
            self._palette_invoker.notify_popdown()
            return

        if box.expanded_button is not None:
            box.expanded_button.queue_draw()
            if box.expanded_button != self:
                box.expanded_button.set_expanded(False)
        box.expanded_button = self

    def get_toolbar_box(self):
        parent = self.get_parent()
        if not hasattr(parent, 'owner'):
            return None
        return parent.owner

    toolbar_box = property(get_toolbar_box)

    def set_color(self, color):
        self.color_button.set_color(color)

    def get_color(self):
        return self.get_child().props.color

    color = GObject.property(type=object, getter=get_color, setter=set_color)

    def set_title(self, title):
        self.get_child().props.title = title

    def get_title(self):
        return self.get_child().props.title

    title = GObject.property(type=str, getter=get_title, setter=set_title)

    def get_selected_tool(self):
        return self._selected_tool

    def set_selected_tool(self, tool_name):
        self._selected_tool = tool_name

    def do_draw(self, cr):
        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.ToolItem.do_draw(self, cr)

        if self._palette and self._palette.is_up():
            invoker = self._palette.props.invoker
            invoker.draw_rectangle(cr, self._palette)

        return False
class FontComboBox(Gtk.ToolItem):

    __gsignals__ = {
        'changed': (GObject.SignalFlags.RUN_LAST, None, ([])), }

    def __init__(self):
        self._palette_invoker = ToolInvoker()
        Gtk.ToolItem.__init__(self)
        self._font_label = FontLabel()
        bt = Gtk.Button('')
        bt.set_can_focus(False)
        bt.remove(bt.get_children()[0])
        box = Gtk.HBox()
        bt.add(box)
        icon = Icon(icon_name='font-text')
        box.pack_start(icon, False, False, 10)
        box.pack_start(self._font_label, False, False, 10)
        self.add(bt)
        self.show_all()

        self._font_name = 'Sans'

        # theme the button, can be removed if add the style to the sugar css
        if style.zoom(100) == 100:
            subcell_size = 15
        else:
            subcell_size = 11
        radius = 2 * subcell_size
        theme = "GtkButton {border-radius: %dpx;}" % radius
        css_provider = Gtk.CssProvider()
        css_provider.load_from_data(theme)
        style_context = bt.get_style_context()
        style_context.add_provider(css_provider,
                                   Gtk.STYLE_PROVIDER_PRIORITY_USER)

        # init palette
        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True

        self.palette = Palette(_('Select font'))
        self.palette.set_invoker(self._palette_invoker)

        # load the fonts in the palette menu
        self._menu_box = PaletteMenuBox()
        self.props.palette.set_content(self._menu_box)
        self._menu_box.show()

        context = self.get_pango_context()

        self._init_font_list()

        tmp_list = []
        for family in context.list_families():
            name = family.get_name()
            if name in self._font_white_list:
                tmp_list.append(name)
        for name in sorted(tmp_list):
            self._add_menu(name, self.__font_selected_cb)

        self._font_label.set_font(self._font_name)

    def _init_font_list(self):
        self._font_white_list = []
        self._font_white_list.extend(DEFAULT_FONTS)

        # check if there are a user configuration file
        if not os.path.exists(USER_FONTS_FILE_PATH):
            # verify if exists a file in /etc
            if os.path.exists(GLOBAL_FONTS_FILE_PATH):
                shutil.copy(GLOBAL_FONTS_FILE_PATH, USER_FONTS_FILE_PATH)

        if os.path.exists(USER_FONTS_FILE_PATH):
            # get the font names in the file to the white list
            fonts_file = open(USER_FONTS_FILE_PATH)
            # get the font names in the file to the white list
            for line in fonts_file:
                self._font_white_list.append(line.strip())
            # monitor changes in the file
            gio_fonts_file = Gio.File.new_for_path(USER_FONTS_FILE_PATH)
            self.monitor = gio_fonts_file.monitor_file(
                Gio.FileMonitorFlags.NONE, None)
            self.monitor.set_rate_limit(5000)
            self.monitor.connect('changed', self._reload_fonts)

    def _reload_fonts(self, monitor, gio_file, other_file, event):
        if event != Gio.FileMonitorEvent.CHANGES_DONE_HINT:
            return
        self._font_white_list = []
        self._font_white_list.extend(DEFAULT_FONTS)
        fonts_file = open(USER_FONTS_FILE_PATH)
        for line in fonts_file:
            self._font_white_list.append(line.strip())
        # update the menu
        for child in self._menu_box.get_children():
            self._menu_box.remove(child)
            child = None
        context = self.get_pango_context()
        tmp_list = []
        for family in context.list_families():
            name = family.get_name()
            if name in self._font_white_list:
                tmp_list.append(name)
        for name in sorted(tmp_list):
            self._add_menu(name, self.__font_selected_cb)
        return False

    def __font_selected_cb(self, menu, font_name):
        self._font_name = font_name
        self._font_label.set_font(font_name)
        self.emit('changed')

    def _add_menu(self, font_name, activate_cb):
        label = '<span font="%s">%s</span>' % (font_name, font_name)
        menu_item = PaletteMenuItem()
        menu_item.set_label(label)
        menu_item.connect('activate', activate_cb, font_name)
        self._menu_box.append_item(menu_item)
        menu_item.show()

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def set_font_name(self, font_name):
        self._font_label.set_font(font_name)

    def get_font_name(self):
        return self._font_name
class ColorToolButton(Gtk.ToolItem):
    # This not ideal. It would be better to subclass Gtk.ToolButton, however
    # the python bindings do not seem to be powerfull enough for that.
    # (As we need to change a variable in the class structure.)

    __gtype_name__ = 'SugarColorToolButton'
    __gsignals__ = {'color-set': (GObject.SignalFlags.RUN_FIRST, None,
                                  tuple())}

    def __init__(self, icon_name='color-preview', **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._palette = None

        GObject.GObject.__init__(self, **kwargs)

        # The Gtk.ToolButton has already added a normal button.
        # Replace it with a ColorButton
        color_button = _ColorButton(icon_name=icon_name, has_invoker=False)
        self.add(color_button)
        color_button.show()

        # The following is so that the behaviour on the toolbar is correct.
        color_button.set_relief(Gtk.ReliefStyle.NONE)
        color_button.icon_size = Gtk.IconSize.LARGE_TOOLBAR

        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        # This widget just proxies the following properties to the colorbutton
        color_button.connect('notify::color', self.__notify_change)
        color_button.connect('notify::icon-name', self.__notify_change)
        color_button.connect('notify::icon-size', self.__notify_change)
        color_button.connect('notify::title', self.__notify_change)
        color_button.connect('color-set', self.__color_set_cb)
        color_button.connect('can-activate-accel',
                             self.__button_can_activate_accel_cb)

    def __button_can_activate_accel_cb(self, button, signal_id):
        # Accept activation via accelerators regardless of this widget's state
        return True

    def set_accelerator(self, accelerator):
        '''
        Sets keyboard shortcut that activates this button.

        Args:
            accelerator(string): accelerator to be set. Should be in
            form <modifier>Letter
            Find about format here :
            https://developer.gnome.org/gtk3/stable/gtk3-Keyboard-Accelerators.html#gtk-accelerator-parse

        Example:
            set_accelerator(self, 'accel')
        '''
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        '''
        Returns the above accelerator string.
        '''
        return self._accelerator

    accelerator = GObject.Property(type=str, setter=set_accelerator,
                                   getter=get_accelerator)

    def create_palette(self):
        '''
        The create_palette function is called when the palette needs to be
        invoked.  For example, when the user has right clicked the icon or
        the user has hovered over the icon for a long time.

        The create_palette will only be called once or zero times.  The palette
        returned will be stored and re-used if the user invokes the palette
        multiple times.

        Your create_palette implementation does not need to
        :any:`Gtk.Widget.show` the palette, as this will be done by the
        invoker.  However, you still need to show
        the menu items, etc that you place in the palette.

        Returns:

            sugar3.graphics.palette.Palette, or None to indicate that you
            do not want a palette shown

        The default implementation returns None, to indicate no palette should
        be shown.
        '''
        self._palette = self.get_child().create_palette()
        return self._palette

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.Property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def set_expanded(self, expanded):
        box = self.toolbar_box
        if not box:
            return

        if not expanded:
            self._palette_invoker.notify_popdown()
            return

        if box.expanded_button is not None:
            box.expanded_button.queue_draw()
            if box.expanded_button != self:
                box.expanded_button.set_expanded(False)
        box.expanded_button = self

    def get_toolbar_box(self):
        parent = self.get_parent()
        if not hasattr(parent, 'owner'):
            return None
        return parent.owner

    toolbar_box = property(get_toolbar_box)

    def set_color(self, color):
        '''
        Sets the color of the colorbutton
        '''
        self.get_child().props.color = color

    def get_color(self):
        '''
        Gets the above set color string.
        '''
        return self.get_child().props.color

    color = GObject.Property(type=object, getter=get_color, setter=set_color)

    def set_icon_name(self, icon_name):
        '''
        Sets the icon for the tool button from a named themed icon.
        If it is none then no icon will be shown.

        Args:
            icon_name(string): The name for a themed icon.
            It can be set as 'None' too.

        Example:
            set_icon_name('view-radial')
        '''
        self.get_child().props.icon_name = icon_name

    def get_icon_name(self):
        '''
        The get_icon_name() method returns the value of the icon_name
        property that contains the name of a themed icon or None.
        '''
        return self.get_child().props.icon_name

    icon_name = GObject.Property(type=str,
                                 getter=get_icon_name, setter=set_icon_name)

    def set_icon_size(self, icon_size):
        '''
        Sets the size of icons in the colorbutton.
        '''
        self.get_child().props.icon_size = icon_size

    def get_icon_size(self):
        '''
        Gets the size of icons in the colorbutton.
        '''
        return self.get_child().props.icon_size

    icon_size = GObject.Property(type=int,
                                 getter=get_icon_size, setter=set_icon_size)

    def set_title(self, title):
        '''
        The set_title() method sets the "title" property to the value of
        title. The "title" property contains the string that is used to
        set the colorbutton title.
        '''
        self.get_child().props.title = title

    def get_title(self):
        '''
        Return the above title string.
        '''
        return self.get_child().props.title

    title = GObject.Property(type=str, getter=get_title, setter=set_title)

    def do_draw(self, cr):
        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.ToolItem.do_draw(self, cr)

        if self._palette and self._palette.is_up():
            invoker = self._palette.props.invoker
            invoker.draw_rectangle(cr, self._palette)

        return False

    def __notify_change(self, widget, pspec):
        self.notify(pspec.name)

    def __color_set_cb(self, widget):
        self.emit('color-set')
class ProgressToolButton(ToolButton):
    """
    This class provides a simple wrapper based on the :class:`ToolButton`
    Displays the progress filling the ToolButton icon.

    Call update(progress) with the new progress to update the ToolButton icon.

    The direction defaults to 'vertical', in which case the icon is
    filled from bottom to top.  If direction is set to 'horizontal',
    it will be filled from right to left or from left to right,
    depending on the system's language RTL setting.
    """

    __gtype_name__ = 'SugarProgressToolButton'

    def __init__(self, icon_name=None, pixel_size=None,
                direction=Gtk.Orientation.VERTICAL, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._progress = 0.0
        self._icon_name = icon_name
        self._pixel_size = pixel_size
        self._direction = direction

        GObject.GObject.__init__(self, **kwargs)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)

        self._stroke = get_surface(
            icon_name=self._icon_name, width=self._pixel_size, height=self._pixel_size,
            stroke_color=style.COLOR_BUTTON_GREY.get_svg(),
            fill_color=style.COLOR_TRANSPARENT.get_svg())

        self._fill = get_surface(
            icon_name=self._icon_name, width=self._pixel_size, height=self._pixel_size,
            stroke_color=style.COLOR_TRANSPARENT.get_svg(),
            fill_color=style.COLOR_WHITE.get_svg())

    def do_draw(self, cr):
        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()

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        # Changes the outline color of the progressicon on activation
        if self._progress > 0:
            self._stroke = get_surface(
                icon_name=self._icon_name, width=self._pixel_size, height=self._pixel_size,
                stroke_color=style.COLOR_WHITE.get_svg(),
                fill_color=style.COLOR_TRANSPARENT.get_svg())
        else:
            self._stroke = get_surface(
                icon_name=self._icon_name, width=self._pixel_size, height=self._pixel_size,
                stroke_color=style.COLOR_BUTTON_GREY.get_svg(),
                fill_color=style.COLOR_TRANSPARENT.get_svg())

        allocation = self.get_allocation()

        # Center the graphic in the allocated space.
        margin_x = (allocation.width - self._stroke.get_width()) / 2
        margin_y = (allocation.height - self._stroke.get_height()) / 2
        cr.translate(margin_x, margin_y)

        # Paint the fill, clipping it by the progress.
        x_, y_ = 0, 0
        width, height = self._stroke.get_width(), self._stroke.get_height()
        if self._direction == 'vertical':  # vertical direction, bottom to top
            y_ = self._stroke.get_height()
            height *= self._progress * -1
        else:
            rtl_direction = \
                Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL
            if rtl_direction:  # horizontal direction, right to left
                x_ = self._stroke.get_width()
                width *= self._progress * -1
            else:  # horizontal direction, left to right
                width *= self._progress

        cr.rectangle(x_, y_, width, height)
        cr.clip()
        cr.set_source_surface(self._fill, 0, 0)
        cr.paint()

        # Paint the stroke over the fill.
        cr.reset_clip()
        cr.set_source_surface(self._stroke, 0, 0)
        cr.paint()

        return False

    def update(self, progress):
        # Updates the progress
        self._progress = progress
        self.queue_draw()
class ToggleToolButton(Gtk.ToggleToolButton):
    '''
    UI for toggletoolbutton.
    A ToggleToolButton is a ToolItem that contains a toggle button,
    having an icon, a tooltip palette, and an accelerator.
    Use ToggleToolButton.new() to create a new ToggleToolButton.

    Args:
        accelerator (string): keyboard shortcut to be used to
        activate this button.
        Find about format here :
        https://developer.gnome.org/gtk3/stable/gtk3-Keyboard-Accelerators.html#gtk-accelerator-parse

        tooltip (string): tooltip to be displayed when user
        hovers over toggle button.

    Keyword Args:
        icon_name(string): name of themed icon which is to be used.
    '''

    __gtype_name__ = 'SugarToggleToolButton'

    def __init__(self, icon_name=None):
        GObject.GObject.__init__(self)

        self._palette_invoker = ToolInvoker(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def set_icon_name(self, icon_name):
        '''
        Sets the icon for the tool button from a named themed icon.
        If it is none then no icon will be shown.

        Args:
            icon_name(string): The name for a themed icon.
            It can be set as 'None' too.

        Example:
            set_icon_name('view-radial')
        '''
        icon = Icon(icon_name=icon_name)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        '''
        The get_icon_name() method returns the value of the icon_name
        property that contains the name of a themed icon or None.
        '''
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.property(type=str, setter=set_icon_name,
                                 getter=get_icon_name)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def set_tooltip(self, text):
        '''
        Sets the tooltip of the toogle tool button. Displays when
        user hovers over the button with cursor.

        Args:
            tooltip (string): tooltip to be added to the button
        '''
        self.set_palette(Palette(text))

    def set_accelerator(self, accelerator):
        '''
        Sets keyboard shortcut that activates this button.

        Args:
            accelerator(string): accelerator to be set. Should be in
            form <modifier>Letter
            Find about format here :
            https://developer.gnome.org/gtk3/stable/gtk3-Keyboard-Accelerators.html#gtk-accelerator-parse

        Example:
            set_accelerator(self, 'accel')
        '''
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        '''
        Returns above accelerator string.
        '''
        return self._accelerator

    accelerator = GObject.property(type=str, setter=set_accelerator,
                                   getter=get_accelerator)

    def do_draw(self, cr):
        '''
        Implementation method for drawing the toogle tool button
        '''
        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.ToggleToolButton.do_draw(self, cr)

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        return False

    def do_clicked(self):
        '''
        Implementation method for hiding the tooltip when the
        toggle button is clicked
        '''
        if self.palette:
            self.palette.popdown(True)

    palette = property(get_palette, set_palette)
Exemple #42
0
class FilterToolItem(Gtk.ToolButton):

    __gsignals__ = {
        'changed': (GObject.SignalFlags.RUN_LAST, None, ([])),
    }

    def __init__(self, default_icon, default_label, palette_content):
        self._palette_invoker = ToolInvoker()
        Gtk.ToolButton.__init__(self)
        self._label = default_label

        self.set_is_important(False)
        self.set_size_request(style.GRID_CELL_SIZE, -1)

        self._label_widget = Gtk.Label()
        self._label_widget.set_alignment(0.0, 0.5)
        self._label_widget.set_ellipsize(style.ELLIPSIZE_MODE_DEFAULT)
        self._label_widget.set_max_width_chars(_LABEL_MAX_WIDTH)
        self._label_widget.set_use_markup(True)
        self._label_widget.set_markup(default_label)
        self.set_label_widget(self._label_widget)
        self._label_widget.show()

        self.set_widget_icon(icon_name=default_icon)

        self._hide_tooltip_on_click = True
        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        self.palette = Palette(_('Select filter'))
        self.palette.set_invoker(self._palette_invoker)

        self.props.palette.set_content(palette_content)

    def set_widget_icon(self, icon_name=None, file_name=None):
        if file_name is not None:
            icon = Icon(file=file_name,
                        pixel_size=style.SMALL_ICON_SIZE,
                        xo_color=XoColor('white'))
        else:
            icon = Icon(icon_name=icon_name,
                        pixel_size=style.SMALL_ICON_SIZE,
                        xo_color=XoColor('white'))
        self.set_icon_widget(icon)
        icon.show()

    def set_widget_label(self, label=None):
        # FIXME: Ellipsis is not working on these labels.
        if label is None:
            label = self._label
        if len(label) > _LABEL_MAX_WIDTH:
            label = label[0:7] + '...' + label[-7:]
        self._label_widget.set_markup(label)
        self._label = label

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.Property(type=object,
                               setter=set_palette,
                               getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.Property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def do_draw(self, cr):
        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(cr, self.palette)

        return False
class ColorToolButton(Gtk.ToolItem):
    # This not ideal. It would be better to subclass Gtk.ToolButton, however
    # the python bindings do not seem to be powerfull enough for that.
    # (As we need to change a variable in the class structure.)

    __gtype_name__ = 'SugarColorToolButton'
    __gsignals__ = {
        'color-set': (GObject.SignalFlags.RUN_FIRST, None, tuple())
    }

    def __init__(self, icon_name='color-preview', **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._palette_invoker = ToolInvoker()
        self._palette = None

        GObject.GObject.__init__(self, **kwargs)

        # The Gtk.ToolButton has already added a normal button.
        # Replace it with a ColorButton
        color_button = _ColorButton(icon_name=icon_name, has_invoker=False)
        self.add(color_button)
        color_button.show()

        # The following is so that the behaviour on the toolbar is correct.
        color_button.set_relief(Gtk.ReliefStyle.NONE)
        color_button.icon_size = Gtk.IconSize.LARGE_TOOLBAR

        self._palette_invoker.attach_tool(self)
        self._palette_invoker.props.toggle_palette = True
        self._palette_invoker.props.lock_palette = True

        # This widget just proxies the following properties to the colorbutton
        color_button.connect('notify::color', self.__notify_change)
        color_button.connect('notify::icon-name', self.__notify_change)
        color_button.connect('notify::icon-size', self.__notify_change)
        color_button.connect('notify::title', self.__notify_change)
        color_button.connect('color-set', self.__color_set_cb)
        color_button.connect('can-activate-accel',
                             self.__button_can_activate_accel_cb)

    def __button_can_activate_accel_cb(self, button, signal_id):
        # Accept activation via accelerators regardless of this widget's state
        return True

    def set_accelerator(self, accelerator):
        self._accelerator = accelerator
        setup_accelerator(self)

    def get_accelerator(self):
        return self._accelerator

    accelerator = GObject.property(type=str,
                                   setter=set_accelerator,
                                   getter=get_accelerator)

    def create_palette(self):
        self._palette = self.get_child().create_palette()
        return self._palette

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def set_expanded(self, expanded):
        box = self.toolbar_box
        if not box:
            return

        if not expanded:
            self._palette_invoker.notify_popdown()
            return

        if box.expanded_button is not None:
            box.expanded_button.queue_draw()
            if box.expanded_button != self:
                box.expanded_button.set_expanded(False)
        box.expanded_button = self

    def get_toolbar_box(self):
        parent = self.get_parent()
        if not hasattr(parent, 'owner'):
            return None
        return parent.owner

    toolbar_box = property(get_toolbar_box)

    def set_color(self, color):
        self.get_child().props.color = color

    def get_color(self):
        return self.get_child().props.color

    color = GObject.property(type=object, getter=get_color, setter=set_color)

    def set_icon_name(self, icon_name):
        self.get_child().props.icon_name = icon_name

    def get_icon_name(self):
        return self.get_child().props.icon_name

    icon_name = GObject.property(type=str,
                                 getter=get_icon_name,
                                 setter=set_icon_name)

    def set_icon_size(self, icon_size):
        self.get_child().props.icon_size = icon_size

    def get_icon_size(self):
        return self.get_child().props.icon_size

    icon_size = GObject.property(type=int,
                                 getter=get_icon_size,
                                 setter=set_icon_size)

    def set_title(self, title):
        self.get_child().props.title = title

    def get_title(self):
        return self.get_child().props.title

    title = GObject.property(type=str, getter=get_title, setter=set_title)

    def do_draw(self, cr):
        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.ToolItem.do_draw(self, cr)

        if self._palette and self._palette.is_up():
            invoker = self._palette.props.invoker
            invoker.draw_rectangle(cr, self._palette)

        return False

    def __notify_change(self, widget, pspec):
        self.notify(pspec.name)

    def __color_set_cb(self, widget):
        self.emit('color-set')
class RadioToolButton(Gtk.RadioToolButton):
    """An implementation of a "push" button."""

    __gtype_name__ = "SugarRadioToolButton"

    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._xo_color = None
        self._hide_tooltip_on_click = True

        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.connect("destroy", self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def set_tooltip(self, tooltip):
        if self.palette is None or self._tooltip is None:
            self.palette = Palette(tooltip)
        elif self.palette is not None:
            self.palette.set_primary_text(tooltip)

        self._tooltip = tooltip

        # Set label, shows up when toolbar overflows
        Gtk.RadioToolButton.set_label(self, tooltip)

    def get_tooltip(self):
        return self._tooltip

    tooltip = GObject.property(type=str, setter=set_tooltip, getter=get_tooltip)

    def set_accelerator(self, accelerator):
        self._accelerator = accelerator
        toolbutton.setup_accelerator(self)

    def get_accelerator(self):
        return self._accelerator

    accelerator = GObject.property(type=str, setter=set_accelerator, getter=get_accelerator)

    def set_icon_name(self, icon_name):
        icon = Icon(icon_name=icon_name, xo_color=self._xo_color)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.property(type=str, setter=set_icon_name, getter=get_icon_name)

    def set_xo_color(self, xo_color):
        if self._xo_color != xo_color:
            self._xo_color = xo_color
            if self.props.icon_widget is not None:
                self.props.icon_widget.props.xo_color = xo_color

    def get_xo_color(self):
        return self._xo_color

    xo_color = GObject.property(type=object, setter=set_xo_color, getter=get_xo_color)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def do_draw(self, cr):
        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.RadioToolButton.do_draw(self, cr)

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        return False

    def get_hide_tooltip_on_click(self):
        return self._hide_tooltip_on_click

    def set_hide_tooltip_on_click(self, hide_tooltip_on_click):
        if self._hide_tooltip_on_click != hide_tooltip_on_click:
            self._hide_tooltip_on_click = hide_tooltip_on_click

    hide_tooltip_on_click = GObject.property(
        type=bool, default=True, getter=get_hide_tooltip_on_click, setter=set_hide_tooltip_on_click
    )

    def do_clicked(self):
        if self._hide_tooltip_on_click and self.palette:
            self.palette.popdown(True)
class RadioToolButton(Gtk.RadioToolButton):
    """An implementation of a "push" button."""

    __gtype_name__ = 'SugarRadioToolButton'

    def __init__(self, icon_name=None, **kwargs):
        self._accelerator = None
        self._tooltip = None
        self._xo_color = None
        self._hide_tooltip_on_click = True

        self._palette_invoker = ToolInvoker()

        GObject.GObject.__init__(self, **kwargs)

        self._palette_invoker.attach_tool(self)

        if icon_name:
            self.set_icon_name(icon_name)

        self.connect('destroy', self.__destroy_cb)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def set_tooltip(self, tooltip):
        if self.palette is None or self._tooltip is None:
            self.palette = Palette(tooltip)
        elif self.palette is not None:
            self.palette.set_primary_text(tooltip)

        self._tooltip = tooltip

        # Set label, shows up when toolbar overflows
        Gtk.RadioToolButton.set_label(self, tooltip)

    def get_tooltip(self):
        return self._tooltip

    tooltip = GObject.property(type=str,
                               setter=set_tooltip,
                               getter=get_tooltip)

    def set_accelerator(self, accelerator):
        self._accelerator = accelerator
        toolbutton.setup_accelerator(self)

    def get_accelerator(self):
        return self._accelerator

    accelerator = GObject.property(type=str,
                                   setter=set_accelerator,
                                   getter=get_accelerator)

    def set_icon_name(self, icon_name):
        icon = Icon(icon_name=icon_name, xo_color=self._xo_color)
        self.set_icon_widget(icon)
        icon.show()

    def get_icon_name(self):
        if self.props.icon_widget is not None:
            return self.props.icon_widget.props.icon_name
        else:
            return None

    icon_name = GObject.property(type=str,
                                 setter=set_icon_name,
                                 getter=get_icon_name)

    def set_xo_color(self, xo_color):
        if self._xo_color != xo_color:
            self._xo_color = xo_color
            if self.props.icon_widget is not None:
                self.props.icon_widget.props.xo_color = xo_color

    def get_xo_color(self):
        return self._xo_color

    xo_color = GObject.property(type=object,
                                setter=set_xo_color,
                                getter=get_xo_color)

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = GObject.property(type=object,
                               setter=set_palette,
                               getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = GObject.property(type=object,
                                       setter=set_palette_invoker,
                                       getter=get_palette_invoker)

    def do_draw(self, cr):
        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.RadioToolButton.do_draw(self, cr)

        if self.palette and self.palette.is_up():
            invoker = self.palette.props.invoker
            invoker.draw_rectangle(cr, self.palette)

        return False

    def get_hide_tooltip_on_click(self):
        return self._hide_tooltip_on_click

    def set_hide_tooltip_on_click(self, hide_tooltip_on_click):
        if self._hide_tooltip_on_click != hide_tooltip_on_click:
            self._hide_tooltip_on_click = hide_tooltip_on_click

    hide_tooltip_on_click = GObject.property(type=bool,
                                             default=True,
                                             getter=get_hide_tooltip_on_click,
                                             setter=set_hide_tooltip_on_click)

    def do_clicked(self):
        if self._hide_tooltip_on_click and self.palette:
            self.palette.popdown(True)