add explanatory comment
[ardour.git] / gtk2_ardour / ardour_dropdown.cc
index eabed85c029dcaaa755fadbe2b9483aabf48dfac..dd1b77c6dbb0784b348fc86c48e0b063c2b3f375 100644 (file)
@@ -50,6 +50,9 @@ ArdourDropdown::ArdourDropdown (Element e)
        : _scrolling_disabled(false)
 {
 //     signal_button_press_event().connect (sigc::mem_fun(*this, &ArdourDropdown::on_mouse_pressed));
+       _menu.signal_size_request().connect (sigc::mem_fun(*this, &ArdourDropdown::menu_size_request));
+
+       _menu.set_reserve_toggle_size(false);
 
        add_elements(e);
        add_elements(ArdourButton::Menu);
@@ -59,8 +62,15 @@ ArdourDropdown::~ArdourDropdown ()
 {
 }
 
+void
+ArdourDropdown::menu_size_request(Requisition *req) {
+       req->width = max(req->width, get_allocation().get_width());
+}
+
 void
 ArdourDropdown::position_menu(int& x, int& y, bool& push_in) {
+       using namespace Menu_Helpers;
+
         /* TODO: lacks support for rotated dropdown buttons */
 
        if (!has_screen () || !get_has_window ()) {
@@ -124,14 +134,31 @@ ArdourDropdown::position_menu(int& x, int& y, bool& push_in) {
        }
 
        /* For the y position, try in order:
-        *  a) align the top of the menu with the bottom of the button if there is
+        *  a) if there is a menu item with the same text as the button, align it
+        *     with the button, unless that makes the menu overflow the monitor.
+        *  b) align the top of the menu with the bottom of the button if there is
         *     enough room below the button;
-        *  b) align the bottom of the menu with the top of the button if there is
+        *  c) align the bottom of the menu with the top of the button if there is
         *     enough room above the button;
-        *  c) align the bottom of the menu with the bottom of the monitor if there
+        *  d) align the bottom of the menu with the bottom of the monitor if there
         *     is enough room, but avoid moving the menu to another monitor */
 
-       if (y + allocation.get_height() + menu_req.height <= monitor.get_y() + monitor.get_height()) {
+       const MenuList& items = _menu.items ();
+       const std::string button_text = get_text();
+       int offset = 0;
+
+       MenuList::const_iterator i = items.begin();
+       for ( ; i != items.end(); ++i) {
+               if (button_text == ((std::string) i->get_label())) {
+                       break;
+               }
+               offset += i->size_request().height;
+       }
+       if (i != items.end() &&
+           y - offset >= monitor.get_y() &&
+           y - offset + menu_req.height <= monitor.get_y() + monitor.get_height()) {
+               y -= offset;
+       } else if (y + allocation.get_height() + menu_req.height <= monitor.get_y() + monitor.get_height()) {
                y += allocation.get_height(); /* a) */
        } else if ((y - menu_req.height) >= monitor.get_y()) {
                y -= menu_req.height; /* b) */