Verified Commit 3c868362 authored by Mike Kowalski's avatar Mike Kowalski Committed by Marc Jeanmougin
Browse files

Toggle dock visibility

parent b5d30d55
Pipeline #367437242 canceled with stages
in 21 minutes and 4 seconds
......@@ -68,7 +68,11 @@ namespace Inkscape {
namespace UI {
namespace Dialog {
DialogContainer::~DialogContainer() {}
DialogContainer::~DialogContainer() {
// delete columns; desktop widget deletes dialog container before it get "unrealized",
// so it doesn't get a chance to remove them
delete columns;
}
DialogContainer::DialogContainer()
{
......@@ -256,6 +260,26 @@ Gtk::Widget *DialogContainer::create_notebook_tab(Glib::ustring label_str, Glib:
return cover;
}
// find dialog's multipaned parent; is there a better way?
DialogMultipaned* get_dialog_parent(DialogBase* dialog) {
if (!dialog) return nullptr;
// dialogs are nested inside Gtk::Notebook
if (auto notebook = dynamic_cast<Gtk::Notebook*>(dialog->get_parent())) {
// notebooks are inside viewport, inside scrolled window
if (auto viewport = dynamic_cast<Gtk::Viewport*>(notebook->get_parent())) {
if (auto scroll = dynamic_cast<Gtk::ScrolledWindow*>(viewport->get_parent())) {
// finally get the panel
if (auto panel = dynamic_cast<DialogMultipaned*>(scroll->get_parent())) {
return panel;
}
}
}
}
return nullptr;
}
/**
* Add new dialog to the current container or in a floating window, based on preferences.
*/
......@@ -306,6 +330,10 @@ void DialogContainer::new_dialog(unsigned int code, DialogNotebook *notebook)
// Limit each container to containing one of any type of dialog.
if (DialogBase* existing_dialog = find_existing_dialog(code)) {
// make sure parent window is not hidden/collapsed
if (auto panel = get_dialog_parent(existing_dialog)) {
panel->show();
}
// found existing dialog; blink & exit
existing_dialog->blink();
return;
......@@ -347,6 +375,11 @@ void DialogContainer::new_dialog(unsigned int code, DialogNotebook *notebook)
// Add dialog
notebook->add_page(*dialog, *tab, dialog->get_name());
if (auto panel = dynamic_cast<DialogMultipaned*>(notebook->get_parent())) {
// if panel is collapsed, show it now, or else new dialog will be mysteriously missing
panel->show();
}
}
// recreate dialogs hosted (docked) in a floating DialogWindow; window will be created
......@@ -475,7 +508,7 @@ bool recreate_dialogs_from_state(const Glib::KeyFile *keyfile)
}
/**
* Add a new floating dialog
* Add a new floating dialog (or reuse existing one if it's already up)
*/
DialogWindow *DialogContainer::new_floating_dialog(unsigned int code)
{
......@@ -497,6 +530,10 @@ DialogWindow *DialogContainer::create_new_floating_dialog(unsigned int code, boo
// found existing dialog; blink & exit
if (blink) {
existing_dialog->blink();
// show its window if it is hidden
if (auto window = DialogManager::singleton().find_floating_dialog_window(code)) {
DialogManager::singleton().set_floating_dialog_visibility(window, true);
}
}
return nullptr;
}
......@@ -532,9 +569,54 @@ DialogWindow *DialogContainer::create_new_floating_dialog(unsigned int code, boo
return notebook->pop_tab_callback();
}
// toggle dialogs (visibility) is invoked on a top container embedded in Inkscape window
void DialogContainer::toggle_dialogs()
{
columns->toggle_multipaned_children();
// check how many dialog panels are visible and how many are hidden
// we use this info to decide what it means to toggle visibility
int visible = 0;
int hidden = 0;
for (auto child : columns->get_children()) {
// only examine panels, skip drop zones and handles
if (auto panel = dynamic_cast<DialogMultipaned*>(child)) {
if (panel->is_visible()) {
++visible;
}
else {
++hidden;
}
}
}
// next examine floating dialogs
auto windows = DialogManager::singleton().get_all_floating_dialog_windows();
for (auto wnd : windows) {
if (wnd->is_visible()) {
++visible;
}
else {
++hidden;
}
}
bool show_dialogs = true;
// if some dialogs are hidden, toggle will first show them;
// another option could be to hide all if some dialogs are visible
if (hidden > 0) {
show_dialogs = true;
}
else {
// if everything's visible, hide them
show_dialogs = false;
}
// set visibility of floating dialogs
for (auto wnd : windows) {
DialogManager::singleton().set_floating_dialog_visibility(wnd, show_dialogs);
}
// set visibility of docked dialogs
columns->toggle_multipaned_children(show_dialogs);
}
// Update dialogs
......@@ -940,14 +1022,14 @@ std::unique_ptr<Glib::KeyFile> DialogContainer::save_container_state()
/**
* No zombie windows. TODO: Need to work on this as it still leaves Gtk::Window! (?)
*/
void DialogContainer::on_unmap()
{
parent_type::on_unmap();
void DialogContainer::on_unrealize() {
// Disconnect all signals
for_each(connections.begin(), connections.end(), [&](auto c) { c.disconnect(); });
delete columns;
columns = nullptr;
parent_type::on_unrealize();
}
// Create a new notebook and move page.
......
......@@ -100,7 +100,7 @@ private:
std::vector<sigc::connection> connections;
// Handlers
void on_unmap() override;
void on_unrealize() override;
DialogNotebook *prepare_drop(const Glib::RefPtr<Gdk::DragContext> context);
void prepend_drop(const Glib::RefPtr<Gdk::DragContext> context, DialogMultipaned *column);
void append_drop(const Glib::RefPtr<Gdk::DragContext> context, DialogMultipaned *column);
......
......@@ -6,7 +6,7 @@
#include <limits>
#include "io/resource.h"
#include "inkscape-application.h"
#include "dialog-base.h"
#include "dialog-container.h"
#include "dialog-window.h"
......@@ -77,16 +77,63 @@ bool DialogManager::should_open_floating(unsigned int code)
return floating_dialogs.count(code) > 0;
}
void DialogManager::set_floating_dialog_visibility(DialogWindow* wnd, bool show) {
if (!wnd) return;
if (show) {
if (wnd->is_visible()) return;
// wnd->present(); - not sure which one is better, show or present...
wnd->show();
_hidden_dlg_windows.erase(wnd);
// re-add it to application; hiding removed it
if (auto app = InkscapeApplication::instance()) {
app->gtk_app()->add_window(*wnd);
}
}
else {
if (!wnd->is_visible()) return;
_hidden_dlg_windows.insert(wnd);
wnd->hide();
}
}
std::vector<DialogWindow*> DialogManager::get_all_floating_dialog_windows() {
std::vector<Gtk::Window*> windows = InkscapeApplication::instance()->gtk_app()->get_windows();
std::vector<DialogWindow*> result(_hidden_dlg_windows.begin(), _hidden_dlg_windows.end());
for (auto wnd : windows) {
if (auto dlg_wnd = dynamic_cast<DialogWindow*>(wnd)) {
result.push_back(dlg_wnd);
}
}
return result;
}
DialogWindow* DialogManager::find_floating_dialog_window(unsigned int code) {
auto windows = get_all_floating_dialog_windows();
for (auto dlg_wnd : windows) {
if (auto container = dlg_wnd->get_container()) {
if (auto dlg = container->get_dialog(code)) {
return dlg_wnd;
}
}
}
return nullptr;
}
DialogBase *DialogManager::find_floating_dialog(unsigned int code)
{
std::vector<Gtk::Window *> windows = InkscapeApplication::instance()->gtk_app()->get_windows();
auto windows = get_all_floating_dialog_windows();
for (auto wnd : windows) {
if (auto dlg_wnd = dynamic_cast<DialogWindow *>(wnd)) {
if (auto container = dlg_wnd->get_container()) {
if (auto dlg = container->get_dialog(code)) {
return dlg;
}
for (auto dlg_wnd : windows) {
if (auto container = dlg_wnd->get_container()) {
if (auto dlg = container->get_dialog(code)) {
return dlg;
}
}
}
......
......@@ -6,6 +6,7 @@
#include <glibmm/keyfile.h>
#include <gtkmm/window.h>
#include <map>
#include <set>
#include <memory>
#include <optional>
#include <vector>
......@@ -43,6 +44,9 @@ public:
// find instance of dialog 'code' in one of currently open floating dialog windows
DialogBase *find_floating_dialog(unsigned int code);
// find window hosting floating dialog
DialogWindow* find_floating_dialog_window(unsigned int code);
// find floating window state hosting dialog 'code', if there was one
std::shared_ptr<Glib::KeyFile> find_dialog_state(unsigned int code);
......@@ -55,6 +59,11 @@ public:
// restore state of dialogs
void restore_dialogs_state(DialogContainer *docking_container, bool include_floating);
// find all floating dialog windows
std::vector<DialogWindow*> get_all_floating_dialog_windows();
// show/hide dialog window and keep track of it
void set_floating_dialog_visibility(DialogWindow* wnd, bool show);
private:
DialogManager() = default;
~DialogManager() = default;
......@@ -64,6 +73,7 @@ private:
// transient dialog state for floating windows user closes
std::map<unsigned int, std::shared_ptr<Glib::KeyFile>> floating_dialogs;
std::set<DialogWindow*> _hidden_dlg_windows;
};
} // namespace Dialog
......
This diff is collapsed.
......@@ -59,10 +59,24 @@ public:
~MyHandle() override = default;
bool on_enter_notify_event(GdkEventCrossing *crossing_event) override;
void set_dragging(bool dragging);
private:
bool on_leave_notify_event(GdkEventCrossing* crossing_event) override;
bool on_button_press_event(GdkEventButton* button_event) override;
bool on_button_release_event(GdkEventButton *event) override;
bool on_motion_notify_event(GdkEventMotion* motion_event) override;
void toggle_multipaned();
void update_click_indicator(double x, double y);
void show_click_indicator(bool show);
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
Cairo::Rectangle get_active_click_zone();
int _cross_size;
Gtk::Widget *_child;
void resize_handler(Gtk::Allocation &allocation);
bool is_click_resize_active() const;
bool _click = false;
bool _click_indicator = false;
bool _dragging = false;
};
/* ============ MULTIPANE ============ */
......@@ -97,7 +111,8 @@ public:
// UI functions
void set_dropzone_sizes(int start, int end);
void toggle_multipaned_children();
void toggle_multipaned_children(bool show);
void children_toggled();
void ensure_multipaned_children();
protected:
......@@ -125,7 +140,12 @@ private:
std::vector<Gtk::Widget *> children;
// Values used when dragging handle.
int handle = -1; // Child number of active handle
int _handle = -1; // Child number of active handle
int _drag_handle = -1;
Gtk::Widget* _resizing_widget1 = nullptr;
Gtk::Widget* _resizing_widget2 = nullptr;
Gtk::Widget* _hide_widget1 = nullptr;
Gtk::Widget* _hide_widget2 = nullptr;
Gtk::Allocation start_allocation1;
Gtk::Allocation start_allocationh;
Gtk::Allocation start_allocation2;
......@@ -150,7 +170,6 @@ private:
void add_empty_widget();
void remove_empty_widget();
std::vector<sigc::connection> _connections;
bool hide_multipaned;
};
} // namespace Dialog
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment