midi_clock_slave: enable debugging output
[ardour.git] / libs / gtkmm2ext / tearoff.cc
index df9f046004695543dc12601a1c0a2578533374a3..c33663e8f745cc3fa624e3992b6fa376d104b32c 100644 (file)
 */
 
 #include <cmath>
+#include <iostream>
 #include <gtkmm2ext/tearoff.h>
 #include <gtkmm2ext/utils.h>
 
 using namespace Gtkmm2ext;
 using namespace Gtk;
+using namespace Gdk;
+using namespace Glib;
 using namespace std;
 
-TearOff::TearOff (Gtk::Widget& c)
+TearOff::TearOff (Widget& c, bool allow_resize)
        : contents (c),
-         tearoff_arrow (Gtk::ARROW_DOWN, Gtk::SHADOW_OUT),
-         close_arrow (Gtk::ARROW_UP, Gtk::SHADOW_OUT)
+         own_window (Gtk::WINDOW_TOPLEVEL),
+         tearoff_arrow (ARROW_DOWN, SHADOW_OUT),
+         close_arrow (ARROW_UP, SHADOW_OUT)
 {
        dragging = false;
+       _visible = true;
+       _can_be_torn_off = true;
 
        tearoff_event_box.add (tearoff_arrow);
-       tearoff_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+       tearoff_event_box.set_events (BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK);
        tearoff_event_box.signal_button_release_event().connect (mem_fun (*this, &TearOff::tearoff_click));
 
        close_event_box.add (close_arrow);
-       close_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+       close_event_box.set_events (BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK);
        close_event_box.signal_button_release_event().connect (mem_fun (*this, &TearOff::close_click));
        
-       own_window = new Gtk::Window (Gtk::WINDOW_TOPLEVEL);
-       own_window->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::POINTER_MOTION_HINT_MASK);
-       own_window->set_resizable (false);
+       own_window.add_events (KEY_PRESS_MASK|KEY_RELEASE_MASK|BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK|POINTER_MOTION_MASK|POINTER_MOTION_HINT_MASK);
+       own_window.set_resizable (allow_resize);
+       own_window.set_type_hint (WINDOW_TYPE_HINT_TOOLBAR);
        
        VBox* box1;
        box1 = manage (new VBox);
-       box1->pack_start (close_event_box, false, false, 5);
+       box1->pack_start (close_event_box, false, false, 2);
        
        window_box.pack_end (*box1, false, false, 2);
-       own_window->add (window_box);
+       own_window.add (window_box);
        
-       own_window->signal_button_press_event().connect (mem_fun (*this, &TearOff::window_button_press));
-       own_window->signal_button_release_event().connect (mem_fun (*this, &TearOff::window_button_release));
-       own_window->signal_motion_notify_event().connect (mem_fun (*this, &TearOff::window_motion));
-       own_window->signal_delete_event().connect (mem_fun (*this, &TearOff::window_delete_event));
-       own_window->signal_realize().connect (bind (sigc::ptr_fun (Gtkmm2ext::set_decoration), own_window, Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH)));
+       own_window.signal_button_press_event().connect (mem_fun (*this, &TearOff::window_button_press));
+       own_window.signal_button_release_event().connect (mem_fun (*this, &TearOff::window_button_release));
+       own_window.signal_motion_notify_event().connect (mem_fun (*this, &TearOff::window_motion));
+       own_window.signal_delete_event().connect (mem_fun (*this, &TearOff::window_delete_event));
+       own_window.signal_realize().connect (bind (sigc::ptr_fun (Gtkmm2ext::set_decoration), &own_window, WMDecoration (DECOR_BORDER|DECOR_RESIZEH)));
 
        tearoff_arrow.set_name ("TearOffArrow");
        close_arrow.set_name ("TearOffArrow");
 
        VBox* box2;
        box2 = manage (new VBox);
-       box2->pack_start (tearoff_event_box, false, false, 5);
+       box2->pack_start (tearoff_event_box, false, false, 2);
 
        pack_start (contents);
        pack_start (*box2, false, false, 2);
@@ -72,57 +78,102 @@ TearOff::TearOff (Gtk::Widget& c)
 
 TearOff::~TearOff ()
 {
-       delete own_window;
+}
+
+void
+TearOff::set_can_be_torn_off (bool yn)
+{
+       if (yn != _can_be_torn_off) {
+               if (yn) {
+                       tearoff_arrow.set_no_show_all (false);
+                       tearoff_arrow.show ();
+               } else {
+                       tearoff_arrow.set_no_show_all (true);
+                       tearoff_arrow.hide ();
+               }
+               _can_be_torn_off = yn;
+       }
+}
+
+void
+TearOff::set_visible (bool yn)
+{
+       /* don't change visibility if torn off */
+
+       if (own_window.is_visible()) {
+               return;
+       }
+
+       if (_visible != yn) {
+               _visible = yn;
+               if (yn) {
+                       show_all();
+                       Visible ();
+               } else {
+                       hide ();
+                       Hidden ();
+               }
+       }
 }
 
 gint
-TearOff::tearoff_click (GdkEventButton* ev)
+TearOff::tearoff_click (GdkEventButton* /*ev*/)
 {
-       remove (contents);
-       window_box.pack_start (contents);
-       own_window->set_name (get_name());
-       close_event_box.set_name (get_name());
-       own_window->show_all ();
-//     own_window->realize ();
-       hide ();
-       Detach ();
-       return TRUE;
+       if (_can_be_torn_off) {
+               remove (contents);
+               window_box.pack_start (contents);
+               own_window.set_name (get_name());
+               close_event_box.set_name (get_name());
+               own_window.show_all ();
+               own_window.present ();
+               std::cerr << "own window should be visible\n";
+               hide ();
+               Detach ();
+       }
+
+       return true;
 }
 
 gint
-TearOff::close_click (GdkEventButton* ev)
+TearOff::close_click (GdkEventButton* /*ev*/)
 {
        window_box.remove (contents);
        pack_start (contents);
        reorder_child (contents, 0);
-       own_window->hide ();
+       own_window.hide ();
        show_all ();
        Attach ();
-       return TRUE;
+       return true;
 }              
 
 gint
 TearOff::window_button_press (GdkEventButton* ev)
 {
+       if (dragging || ev->button != 1) {
+               dragging = false;
+               own_window.remove_modal_grab();
+               return true;
+       }
+
        dragging = true;
        drag_x = ev->x_root;
        drag_y = ev->y_root;
 
-       own_window->add_modal_grab();
+       own_window.add_modal_grab();
 
-       return TRUE;
+       return true;
 }
 
 gint
-TearOff::window_button_release (GdkEventButton* ev)
+TearOff::window_button_release (GdkEventButton* /*ev*/)
 {
        dragging = false;
-       own_window->remove_modal_grab();
-       return TRUE;
+       own_window.remove_modal_grab();
+       return true;
 }
 
 gint
-TearOff::window_delete_event (GdkEventAny* ev)
+TearOff::window_delete_event (GdkEventAny* /*ev*/)
 {
        return close_click(0);
 }
@@ -135,12 +186,18 @@ TearOff::window_motion (GdkEventMotion* ev)
        gint mx, my;
        double x_delta;
        double y_delta;
-       Glib::RefPtr<Gdk::Window> win (own_window->get_window());
+       RefPtr<Gdk::Window> win (own_window.get_window());
        
-       own_window->get_pointer (mx, my);
+       own_window.get_pointer (mx, my);
 
        if (!dragging) {
-               return TRUE;
+               return true;
+       }
+
+       if (!(ev->state & GDK_BUTTON1_MASK)) {
+               dragging = false;
+               own_window.remove_modal_grab();
+               return true;
        }
 
        x_delta = ev->x_root - drag_x;
@@ -152,11 +209,11 @@ TearOff::window_motion (GdkEventMotion* ev)
        drag_x = ev->x_root;
        drag_y = ev->y_root;
        
-       return TRUE;
+       return true;
 }
 
 bool
 TearOff::torn_off() const
 {
-       return own_window->is_visible();
+       return own_window.is_visible();
 }