Blob Blame History Raw
#!/usr/bin/python -Es
# -*- coding: utf-8 -*-
#
# Copyright (C) 2008,2012 Red Hat, Inc.
#
# Authors:
# Thomas Woerner <twoerner@redhat.com>
# Florian Festi <ffesti@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class ChooserButton(object):
    def __init__(self, button, default_label=""):
        self.button = button
        self.default_label = default_label

        self.label = None
        self._menu = None
        self._icon = None

        children = self.button.get_children()
        if len(children) == 1 and isinstance(children[0], (Gtk.HBox, Gtk.Box)):
            children = children[0].get_children()
            for child in children:
                if isinstance(child, Gtk.Label):
                    self.label = child
                    break
        else:
            for child in list(button.get_children()):
                button.remove(child)
            hbox = Gtk.HBox()
            self.label = Gtk.Label()
            arrow = Gtk.Arrow(arrow_type=Gtk.ArrowType.DOWN,
                              shadow_type=Gtk.ShadowType.IN)
            hbox.set_spacing(2)
            hbox.pack_start(self.label, True, True, 0)
            hbox.pack_end(arrow, False, False, 0)
            button.add(hbox)
        if not self.label:
            raise ValueError("%s is not a ChooserButton" % button.get_name())
        self.connect("clicked", self._show_menu)
        self.reset()

    def set_sensitive(self, value):
        self.button.set_sensitive(value)

    def get_sensitive(self):
        return self.button.get_sensitive()

    def is_sensitive(self):
        return self.button.is_sensitive()

    def connect(self, _type, *args):
        return self.button.connect(_type, *args)

    def disconnect(self, *args):
        self.button.disconnect(*args)

    def get_text(self):
        return self.text

    def set_text(self, text):
        if not text or len(text) < 1:
            self.reset()
        self.text = text
        self.label.set_text(self.text)

    def set_stock_icon(self, name, size=Gtk.IconSize.MENU):
        if self._icon is None:
            self._icon = Gtk.Image()
            hbox = self.button.get_child()
            hbox.pack_start(self._icon, True, True, 0)
            hbox.reorder_child(self._icon, 0)
            
        self._icon.set_from_stock(name, size)

    def reset(self):
        self.text = None
        self.label.set_text(self.default_label)

    def set_menu(self, menu):
        self._menu = menu
        if menu:
            menu.attach_to_widget(self.button, self._detach_menu)

    def get_menu(self):
        return self._menu

    def _detach_menu(self):
        self._menu = None

    def _show_menu(self, *dummy):
        if not self._menu:
            return
        self._menu.popup(None, None, self._menu_position_func, 0, 0, 0)

    def _menu_position_func(self, menu, dummy):
        allocation = self.button.get_allocation()
        req = menu.size_request()
        menu_width = req.width
        menu_height = req.height
        if menu_width != allocation.width:
            menu.set_size_request(-1, -1)
            req = menu.size_request()
            if req.width > allocation.width:
                menu.set_size_request(req.width, req.height)
            else:
                menu.set_size_request(allocation.width, -1)

        (x, y) = self.button.get_parent_window().get_origin()[1:]
        x += allocation.x
        y += allocation.y + allocation.height

        root = self.button.get_root_window()
        (dummy, dummy, dummy, root_height) = root.get_geometry()

        if y + menu_height > root_height:
            y -= menu_height + allocation.height

        return (x, y, True)


class ToolChooserButton(object):
    
    def __init__(self, button, default_label=''):
        
        self.button = button
        self.default_label = default_label

        self._menu = None
        self._icon = None

        self.reset()

        self.set_sensitive = self.button.set_sensitive

    def get_text(self):
        return self.text

    def set_text(self, text):
        if not text or len(text) < 1:
            self.reset()
        self.text = text
        self.button.set_label(text)

    def set_stock_icon(self, name, size=Gtk.IconSize.BUTTON):
        if self._icon is None:
            self._icon = Gtk.Image()
            self.button.set_icon_widget(self._icon)

        self._icon.set_from_stock(name, size)

    def reset(self):
        self.text = None
        self.button.set_label(self.default_label)

    def set_menu(self, menu):
        self._menu = menu
        self.button.set_menu(menu)

    def get_menu(self):
        return self._menu

    def _detach_menu(self):
        self._menu = None