X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fgtkmm2ext%2Ftearoff.cc;h=fd42528b522c169b8b1327d53bf5748189a7292c;hb=d3c38e28fc71393ed8dd14abf3c1a8f63c978fc5;hp=cdc027d5da1fcc4fc95dae5f06e3818125965ee8;hpb=d766adcec1e3af452fd7edcf1225faff8d5e3b7c;p=ardour.git diff --git a/libs/gtkmm2ext/tearoff.cc b/libs/gtkmm2ext/tearoff.cc index cdc027d5da..fd42528b52 100644 --- a/libs/gtkmm2ext/tearoff.cc +++ b/libs/gtkmm2ext/tearoff.cc @@ -19,111 +19,206 @@ */ #include -#include -#include +#include + +#include "pbd/xml++.h" + +#include "gtkmm2ext/tearoff.h" +#include "gtkmm2ext/utils.h" + +#include "i18n.h" using namespace Gtkmm2ext; using namespace Gtk; +using namespace Gdk; +using namespace Glib; using namespace std; -TearOff::TearOff (Gtk::Widget& c) - : contents (c), - tearoff_arrow (Gtk::ARROW_DOWN, Gtk::SHADOW_OUT), - close_arrow (Gtk::ARROW_UP, Gtk::SHADOW_OUT) +TearOff::TearOff (Widget& c, bool allow_resize) + : contents (c) + , own_window (Gtk::WINDOW_TOPLEVEL) + , tearoff_arrow (ARROW_DOWN, SHADOW_OUT) + , close_arrow (ARROW_UP, SHADOW_OUT) + , dragging (false) + , _visible (true) + , _torn (false) + , _can_be_torn_off (true) + { - dragging = false; + own_window_width = 0; + own_window_height = 0; + own_window_xpos = 0; + own_window_ypos = 0; 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)); + tearoff_event_box.set_tooltip_text (_("Click to tear this into its own window")); + 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->set_type_hint (Gdk::WINDOW_TYPE_HINT_TOOLBAR); - + + close_event_box.set_tooltip_text (_("Click to put this back in the main window")); + 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_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); + + 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 (sigc::mem_fun (*this, &TearOff::own_window_realized)); + own_window.signal_configure_event().connect (sigc::mem_fun (*this, &TearOff::own_window_configured), false); 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); - } 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, bool force) +{ + /* don't change visibility if torn off */ + + if (_torn) { + return; + } + + if (_visible != yn || force) { + _visible = yn; + if (yn) { + show_all(); + Visible (); + } else { + hide (); + Hidden (); + } + } } gint -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; +TearOff::tearoff_click (GdkEventButton* /*ev*/) +{ + tear_it_off (); + return true; } +void +TearOff::tear_it_off () +{ + if (!_can_be_torn_off) { + return; + } + + if (torn_off()) { + return; + } + + remove (contents); + window_box.pack_start (contents); + own_window.set_name (get_name()); + close_event_box.set_name (get_name()); + if (own_window_width == 0) { + own_window.set_position (WIN_POS_MOUSE); + } + own_window.show_all (); + own_window.present (); + hide (); + + _torn = true; + + Detach (); +} + gint -TearOff::close_click (GdkEventButton* ev) +TearOff::close_click (GdkEventButton* /*ev*/) +{ + put_it_back (); + return true; +} + +void +TearOff::put_it_back () { + if (!torn_off()) { + return; + } + window_box.remove (contents); pack_start (contents); reorder_child (contents, 0); - own_window->hide (); + own_window.hide (); show_all (); + + _torn = false; + Attach (); - 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); } @@ -136,12 +231,18 @@ TearOff::window_motion (GdkEventMotion* ev) gint mx, my; double x_delta; double y_delta; - Glib::RefPtr win (own_window->get_window()); + RefPtr 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; @@ -153,11 +254,104 @@ 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 _torn; } + +void +TearOff::add_state (XMLNode& node) const +{ + node.add_property ("tornoff", (_torn ? "yes" : "no")); + + if (own_window_width > 0) { + char buf[32]; + + snprintf (buf, sizeof (buf), "%d", own_window_width); + node.add_property ("width", buf); + snprintf (buf, sizeof (buf), "%d", own_window_height); + node.add_property ("height", buf); + snprintf (buf, sizeof (buf), "%d", own_window_xpos); + node.add_property ("xpos", buf); + snprintf (buf, sizeof (buf), "%d", own_window_ypos); + node.add_property ("ypos", buf); + } +} + +void +TearOff::set_state (const XMLNode& node) +{ + Glib::RefPtr win; + const XMLProperty* prop; + + if ((prop = node.property (X_("tornoff"))) == 0) { + return; + } + + if (prop->value() == "yes") { + tear_it_off (); + } else { + put_it_back (); + } + + if ((prop = node.property (X_("width"))) != 0) { + sscanf (prop->value().c_str(), "%d", &own_window_width); + } + if ((prop = node.property (X_("height"))) != 0) { + sscanf (prop->value().c_str(), "%d", &own_window_height); + } + if ((prop = node.property (X_("xpos"))) != 0) { + sscanf (prop->value().c_str(), "%d", &own_window_xpos); + } + if ((prop = node.property (X_("ypos"))) != 0) { + sscanf (prop->value().c_str(), "%d", &own_window_ypos); + } + + if (own_window.is_realized()) { + own_window.set_default_size (own_window_width, own_window_height); + own_window.move (own_window_xpos, own_window_ypos); + } + /* otherwise do it once the window is realized, see below */ +} + +void +TearOff::own_window_realized () +{ + own_window.get_window()->set_decorations (WMDecoration (DECOR_BORDER|DECOR_RESIZEH)); + + if (own_window_width > 0) { + own_window.set_default_size (own_window_width, own_window_height); + own_window.move (own_window_xpos, own_window_ypos); + } +} + +bool +TearOff::own_window_configured (GdkEventConfigure*) +{ + Glib::RefPtr win; + + win = own_window.get_window (); + + if (win) { + win->get_size (own_window_width, own_window_height); + win->get_position (own_window_xpos, own_window_ypos); + } + + return false; +} + +void +TearOff::hide_visible () +{ + if (torn_off()) { + own_window.hide (); + } + + hide (); +} + +