# Copyright (C) 2011 Canonical
#
# Authors:
#  Didier Roche
#
# 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; version 3.
#
# 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

from gi.repository import Gtk


class MenuButton(Gtk.Button):

    def __init__(self, menu, icon=None, label=None):
        super(MenuButton, self).__init__()

        box = Gtk.Box()
        self.add(box)

        if icon:
            box.pack_start(icon, False, True, 1)
        if label:
            box.pack_start(Gtk.Label.new(label), True, True, 0)

        arrow = Gtk.Arrow.new(Gtk.ArrowType.DOWN, Gtk.ShadowType.OUT)
        box.pack_start(arrow, False, False, 1)

        self.menu = menu

        self.connect("button-press-event", self.on_button_pressed, menu)
        self.connect("clicked", self.on_keyboard_clicked, menu)

    def get_menu(self):
        '''Return menu attached to the button'''
        return self.menu

    def on_button_pressed(self, button, event, menu):
        menu.popup(None, None, self.menu_positionner, (button, event.x),
            event.button, event.time)

    def on_keyboard_clicked(self, button, menu):
        menu.popup(None, None, self.menu_positionner, (button, None), 1,
            Gtk.get_current_event_time())

    def menu_positionner(self, menu, (button, x_cursor_pos)):
        (button_id, x, y) = button.get_window().get_origin()

        # compute button position
        x_position = x + button.get_allocation().x
        y_position = (y + button.get_allocation().y +
            button.get_allocated_height())

        # if pressed by the mouse, center the X position to it
        if x_cursor_pos:
            x_position += x_cursor_pos
            x_position = x_position - menu.get_allocated_width() * 0.5

        # computer current monitor height
        current_screen = button.get_screen()
        num_monitor = current_screen.get_monitor_at_point(x_position,
            y_position)
        monitor_geo = current_screen.get_monitor_geometry(num_monitor)

        # if the menu width is of the current monitor, shift is a little
        if x_position < monitor_geo.x:
            x_position = monitor_geo.x
        if (x_position + menu.get_allocated_width() > monitor_geo.x +
                monitor_geo.width):
            x_position = (monitor_geo.x + monitor_geo.width -
                menu.get_allocated_width())

        # if the menu height is too long for the monitor, put it above the
        # widget
        if monitor_geo.height < y_position + menu.get_allocated_height():
            y_position = (y_position - button.get_allocated_height() -
                menu.get_allocated_height())

        return (x_position, y_position, True)


if __name__ == "__main__":

    win = Gtk.Window()
    win.set_size_request(200, 300)

    menu = Gtk.Menu()
    menuitem = Gtk.MenuItem(label="foo")
    menuitem2 = Gtk.MenuItem(label="long long long bar message")
    menu.append(menuitem)
    menu.append(menuitem2)
    menuitem.show()
    menuitem2.show()

    box1 = Gtk.Box()
    box1.pack_start(Gtk.Label.new("something before to show we don't cheat"),
        True, True, 0)
    win.add(box1)

    box2 = Gtk.Box()
    box2.set_orientation(Gtk.Orientation.VERTICAL)
    box1.pack_start(box2, True, True, 0)
    box2.pack_start(Gtk.Label.new("first label with multiple line"), True, True, 0)

    image = Gtk.Image.new_from_stock(Gtk.STOCK_PROPERTIES, Gtk.IconSize.BUTTON)
    label = "fooo"
    button_with_menu = MenuButton(menu, image, label)
    box2.pack_start(button_with_menu, False, False, 1)

    win.connect("destroy", lambda x: Gtk.main_quit())
    win.show_all()

    settings = Gtk.Settings.get_default()
    settings.set_property("gtk-button-images", True)

    Gtk.main()
