19
19
from gi.repository import Gtk
21
22
class MenuButton(Gtk.Button):
23
24
def __init__(self, menu, icon=None, label=None):
24
25
super(MenuButton, self).__init__()
30
31
box.pack_start(icon, False, True, 1)
32
33
box.pack_start(Gtk.Label(label), True, True, 0)
34
35
arrow = Gtk.Arrow.new(Gtk.ArrowType.DOWN, Gtk.ShadowType.OUT)
35
36
box.pack_start(arrow, False, False, 1)
39
40
self.connect("button-press-event", self.on_button_pressed, menu)
40
41
self.connect("clicked", self.on_keyboard_clicked, menu)
46
47
def on_button_pressed(self, button, event, menu):
47
menu.popup(None, None, self.menu_positionner, (button, event.x), event.button, event.time)
48
menu.popup(None, None, self.menu_positionner, (button, event.x),
49
event.button, event.time)
49
51
def on_keyboard_clicked(self, button, menu):
50
menu.popup(None, None, self.menu_positionner, (button, None), 1, Gtk.get_current_event_time())
52
menu.popup(None, None, self.menu_positionner, (button, None), 1,
53
Gtk.get_current_event_time())
52
55
def menu_positionner(self, menu, (button, x_cursor_pos)):
53
56
(button_id, x, y) = button.get_window().get_origin()
55
58
# compute button position
56
59
x_position = x + button.get_allocation().x
57
y_position = y + button.get_allocation().y + button.get_allocated_height()
60
y_position = (y + button.get_allocation().y +
61
button.get_allocated_height())
59
63
# if pressed by the mouse, center the X position to it
61
65
x_position += x_cursor_pos
64
68
# computer current monitor height
65
69
current_screen = button.get_screen()
66
num_monitor = current_screen.get_monitor_at_point(x_position, y_position)
70
num_monitor = current_screen.get_monitor_at_point(x_position,
67
72
monitor_geo = current_screen.get_monitor_geometry(num_monitor)
69
74
# if the menu width is of the current monitor, shift is a little
70
75
if x_position < monitor_geo.x:
71
76
x_position = monitor_geo.x
72
if x_position + menu.get_allocated_width() > monitor_geo.x + monitor_geo.width:
73
x_position = monitor_geo.x + monitor_geo.width - menu.get_allocated_width()
75
# if the menu height is too long for the monitor, put it above the widget
77
if (x_position + menu.get_allocated_width() > monitor_geo.x +
79
x_position = (monitor_geo.x + monitor_geo.width -
80
menu.get_allocated_width())
82
# if the menu height is too long for the monitor, put it above the
76
84
if monitor_geo.height < y_position + menu.get_allocated_height():
77
y_position = y_position - button.get_allocated_height() - menu.get_allocated_height()
85
y_position = (y_position - button.get_allocated_height() -
86
menu.get_allocated_height())
79
88
return (x_position, y_position, True)
96
box1.pack_start(Gtk.Label("something before to show we don't cheat"), True, True, 0)
105
box1.pack_start(Gtk.Label("something before to show we don't cheat"),
100
box2.set_orientation(Gtk.Orientation.VERTICAL)
110
box2.set_orientation(Gtk.Orientation.VERTICAL)
101
111
box1.pack_start(box2, True, True, 0)
102
112
box2.pack_start(Gtk.Label("first label with multiple line"), True, True, 0)
104
114
image = Gtk.Image.new_from_stock(Gtk.STOCK_PROPERTIES, Gtk.IconSize.BUTTON)
106
116
button_with_menu = MenuButton(menu, image, label)
107
box2.pack_start(button_with_menu, False, False, 1)
117
box2.pack_start(button_with_menu, False, False, 1)
109
119
win.connect("destroy", lambda x: Gtk.main_quit())
112
122
settings = Gtk.Settings.get_default()
113
123
settings.set_property("gtk-button-images", True)