#include "gtkmm2ext/utils.h"
#include "gtkmm2ext/visibility_tracker.h"
+#include "pbd/stacktrace.h"
+
#include "i18n.h"
using namespace Gtkmm2ext;
Tabbable::Tabbable (Widget& w, const string& name)
: WindowProxy (name)
, _contents (w)
- , tab_close_image (ArdourIcon::CloseCross, 0xffffffff)
+ , _parent_notebook (0)
+ , tab_requested_by_state (true)
{
- /* make the image about the same size as an actual X */
- set_size_request_to_display_given_text (tab_close_image, "X", 0, 0);
-
- _tab_box.set_spacing (2);
- _tab_box.pack_start (_tab_label, true, true);
- _tab_box.pack_start (_tab_close_button, false, false);
- _tab_close_button.add (tab_close_image);
-
- _tab_close_button.signal_clicked().connect (sigc::mem_fun (*this, &Tabbable::tab_close_clicked));
}
Tabbable::~Tabbable ()
}
}
-void
-Tabbable::set_allow_hide (bool yn)
-{
- if (yn) {
- tab_close_image.show ();
- } else {
- tab_close_image.hide ();
- }
-}
-
-void
-Tabbable::tab_close_clicked ()
-{
- hide_tab ();
-}
-
void
Tabbable::add_to_notebook (Notebook& notebook, const string& tab_title)
{
- _tab_label.set_text (tab_title);
- _tab_box.show_all ();
-
- notebook.append_page (_contents, _tab_box);
-
- Gtkmm2ext::UI::instance()->set_tip (_tab_label,
- string_compose (_("Drag this tab to the desktop to show %1 in its own window\n\n"
- "To put the window back, click on its \"close\" button"), tab_title));
-
- notebook.set_tab_detachable (_contents);
- notebook.set_tab_reorderable (_contents);
-
_parent_notebook = ¬ebook;
- _tab_title = tab_title;
+
+ if (tab_requested_by_state) {
+ attach ();
+ }
}
Window*
if (parent) {
parent->remove (_contents);
}
- _own_notebook.append_page (_contents, _tab_box);
+ _own_notebook.append_page (_contents);
}
return win;
}
bool
-Tabbable::window_visible ()
+Tabbable::window_visible () const
{
- if (!own_window()) {
+ if (!_window) {
return false;
}
- return visible();
+ return _window->is_visible();
}
Window*
return 0;
}
- /* From here on, we're creating the window
+ /* From here on, we're creating the window
*/
-
+
if ((_window = new Window (WINDOW_TOPLEVEL)) == 0) {
return 0;
}
_own_notebook.show ();
_own_notebook.set_show_tabs (false);
+ _window->signal_map().connect (sigc::mem_fun (*this, &Tabbable::window_mapped));
+ _window->signal_unmap().connect (sigc::mem_fun (*this, &Tabbable::window_unmapped));
+
/* do other window-related setup */
setup ();
/* window should be ready for derived classes to do something with it */
-
+
return _window;
}
if (parent) {
alloc = parent->get_allocation();
}
-
+
(void) use_own_window (and_pack_it);
-
+
if (parent) {
_window->set_default_size (alloc.get_width(), alloc.get_height());
}
- _window->show_all ();
+ tab_requested_by_state = false;
+
_window->present ();
}
}
}
+/** If this Tabbable is currently parented by a tab, ensure that the tab is the
+ * current one. If it is parented by a window, then toggle the visibility of
+ * that window.
+ */
+void
+Tabbable::change_visibility ()
+{
+ if (tabbed()) {
+ _parent_notebook->set_current_page (_parent_notebook->page_num (_contents));
+ return;
+ }
+
+ if (tab_requested_by_state) {
+ /* should be tabbed, but currently isn't parented by a notebook */
+ return;
+ }
+
+ if (_window && (current_toplevel() == _window)) {
+ /* Use WindowProxy method which will rotate then hide */
+ toggle();
+ }
+}
+
void
Tabbable::make_visible ()
{
if (_window && (current_toplevel() == _window)) {
+ set_pos ();
_window->present ();
} else {
- show_tab ();
+
+ if (!tab_requested_by_state) {
+ show_own_window (true);
+ } else {
+ show_tab ();
+ }
}
}
hide_tab ();
}
}
-
+
void
Tabbable::detach ()
{
if (!_parent_notebook) {
return;
}
-
- if (_parent_notebook->page_num (_contents) >= 0) {
+
+ if (tabbed()) {
/* already tabbed */
return;
}
/* unpack Tabbable from parent, put it back in the main tabbed
* notebook
*/
-
+
save_pos_and_size ();
-
+
_contents.get_parent()->remove (_contents);
-
+
/* leave the window around */
-
+
_window->hide ();
}
-
- _parent_notebook->append_page (_contents, _tab_box);
+
+ _parent_notebook->append_page (_contents);
_parent_notebook->set_tab_detachable (_contents);
_parent_notebook->set_tab_reorderable (_contents);
_parent_notebook->set_current_page (_parent_notebook->page_num (_contents));
+
+ /* have to force this on, which is semantically correct, since
+ * the user has effectively asked for it.
+ */
+
+ tab_requested_by_state = true;
+ StateChange (*this);
}
bool
}
bool
-Tabbable::is_tabbed () const
+Tabbable::tabbed () const
{
- Window* toplevel = (Window*) _contents.get_toplevel();
-
- if (_window && (toplevel == _window)) {
+ if (_window && (current_toplevel() == _window)) {
return false;
}
- if (_parent_notebook && _contents.get_parent()) {
+ if (_parent_notebook && (_parent_notebook->page_num (_contents) >= 0)) {
return true;
}
-
+
return false;
}
void
Tabbable::hide_tab ()
{
- if (_parent_notebook) {
+ if (tabbed()) {
_parent_notebook->remove_page (_contents);
+ StateChange (*this);
}
}
{
if (!window_visible() && _parent_notebook) {
if (_contents.get_parent() == 0) {
+ tab_requested_by_state = true;
add_to_notebook (*_parent_notebook, _tab_title);
}
_parent_notebook->set_current_page (_parent_notebook->page_num (_contents));
+ current_toplevel()->present ();
}
}
return WindowProxy::xml_node_name();
}
+bool
+Tabbable::tabbed_by_default() const
+{
+ return tab_requested_by_state;
+}
+
XMLNode&
Tabbable::get_state()
{
XMLNode& node (WindowProxy::get_state());
+ node.add_property (X_("tabbed"), tabbed() ? X_("yes") : X_("no"));
+
return node;
}
{
int ret;
- if ((ret = WindowProxy::set_state (node, version)) == 0) {
- if (_visible) {
- if (use_own_window (true) == 0) {
- ret = -1;
- }
+ if ((ret = WindowProxy::set_state (node, version)) != 0) {
+ return ret;
+ }
+
+ if (_visible) {
+ show_own_window (true);
+ }
+
+ XMLNodeList children = node.children ();
+ XMLNode* window_node = node.child ("Window");
+
+ if (window_node) {
+ XMLProperty const * prop = window_node->property (X_("tabbed"));
+ if (prop) {
+ tab_requested_by_state = PBD::string_is_affirmative (prop->value());
+ }
+ }
+
+ if (!_visible) {
+ if (tab_requested_by_state) {
+ attach ();
+ } else {
+ /* this does nothing if not tabbed */
+ hide_tab ();
}
}
return ret;
}
+void
+Tabbable::window_mapped ()
+{
+ StateChange (*this);
+}
+
+void
+Tabbable::window_unmapped ()
+{
+ StateChange (*this);
+}