summaryrefslogtreecommitdiffstats
path: root/src/ui/dialog/dialog-base.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/ui/dialog/dialog-base.cpp320
1 files changed, 320 insertions, 0 deletions
diff --git a/src/ui/dialog/dialog-base.cpp b/src/ui/dialog/dialog-base.cpp
new file mode 100644
index 0000000..8ddc5c4
--- /dev/null
+++ b/src/ui/dialog/dialog-base.cpp
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/** @file
+ * @brief A base class for all dialogs.
+ *
+ * Authors: see git history
+ * Tavmjong Bah
+ *
+ * Copyright (c) 2018 Tavmjong Bah, Authors
+ *
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#include "dialog-base.h"
+
+#include <glibmm/i18n.h>
+#include <glibmm/main.h>
+#include <glibmm/refptr.h>
+#include <gtkmm/cssprovider.h>
+#include <gtkmm/notebook.h>
+#include <gtkmm/scrolledwindow.h>
+#include <iostream>
+
+#include "inkscape.h"
+#include "desktop.h"
+#include "ui/dialog/dialog-data.h"
+#include "ui/dialog/dialog-notebook.h"
+#include "ui/dialog-events.h"
+// get_latin_keyval
+#include "ui/tools/tool-base.h"
+#include "widgets/spw-utilities.h"
+#include "ui/widget/canvas.h"
+#include "ui/util.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+/**
+ * DialogBase constructor.
+ *
+ * @param prefs_path characteristic path to load/save dialog position.
+ * @param dialog_type is the "type" string for the dialog.
+ */
+DialogBase::DialogBase(gchar const *prefs_path, Glib::ustring dialog_type)
+ : Gtk::Box(Gtk::ORIENTATION_VERTICAL)
+ , desktop(nullptr)
+ , document(nullptr)
+ , selection(nullptr)
+ , _name("DialogBase")
+ , _prefs_path(prefs_path)
+ , _dialog_type(dialog_type)
+ , _app(InkscapeApplication::instance())
+{
+ auto const &dialog_data = get_dialog_data();
+
+ // Derive a pretty display name for the dialog.
+ auto it = dialog_data.find(dialog_type);
+ if (it != dialog_data.end()) {
+
+ _name = it->second.label; // Already translated
+
+ // remove ellipsis and mnemonics
+ int pos = _name.find("...", 0);
+ if (pos >= 0 && pos < _name.length() - 2) {
+ _name.erase(pos, 3);
+ }
+ pos = _name.find("…", 0);
+ if (pos >= 0 && pos < _name.length()) {
+ _name.erase(pos, 1);
+ }
+ pos = _name.find("_", 0);
+ if (pos >= 0 && pos < _name.length()) {
+ _name.erase(pos, 1);
+ }
+ }
+
+ set_name(_dialog_type); // Essential for dialog functionality
+ property_margin().set_value(1); // Essential for dialog UI
+ ensure_size();
+}
+
+DialogBase::~DialogBase() {
+#ifdef _WIN32
+ // this is bad, but it supposedly fixes some resizng problem on Windows
+ ensure_size();
+#endif
+
+ unsetDesktop();
+};
+
+void DialogBase::ensure_size() {
+ if (desktop) {
+ resize_widget_children(desktop->getToplevel());
+ }
+}
+
+void DialogBase::on_map() {
+ // Update asks the dialogs if they need their Gtk widgets updated.
+ update();
+ // Set the desktop on_map, although we might want to be smarter about this.
+ // Note: Inkscape::Application::instance().active_desktop() is used here, as it contains current desktop at
+ // the time of dialog creation. Formerly used _app.get_active_view() did not at application start-up.
+ setDesktop(Inkscape::Application::instance().active_desktop());
+ parent_type::on_map();
+}
+
+bool DialogBase::on_key_press_event(GdkEventKey* key_event) {
+ switch (Inkscape::UI::Tools::get_latin_keyval(key_event)) {
+ case GDK_KEY_Escape:
+ defocus_dialog();
+ return true;
+ }
+
+ return parent_type::on_key_press_event(key_event);
+}
+
+
+/**
+ * Highlight notebook where dialog already exists.
+ */
+void DialogBase::blink()
+{
+ Gtk::Notebook *notebook = dynamic_cast<Gtk::Notebook *>(get_parent());
+ if (notebook && notebook->get_is_drawable()) {
+ // Switch notebook to this dialog.
+ notebook->set_current_page(notebook->page_num(*this));
+ notebook->get_style_context()->add_class("blink");
+
+ // Add timer to turn off blink.
+ sigc::slot<bool> slot = sigc::mem_fun(*this, &DialogBase::blink_off);
+ sigc::connection connection = Glib::signal_timeout().connect(slot, 1000); // msec
+ }
+}
+
+void DialogBase::focus_dialog() {
+ if (auto window = dynamic_cast<Gtk::Window*>(get_toplevel())) {
+ window->present();
+ }
+
+ // widget that had focus, if any
+ if (auto child = get_focus_child()) {
+ child->grab_focus();
+ }
+ else {
+ // find first focusable widget
+ if (auto child = sp_find_focusable_widget(this)) {
+ child->grab_focus();
+ }
+ }
+}
+
+void DialogBase::defocus_dialog() {
+ if (auto wnd = dynamic_cast<Gtk::Window*>(get_toplevel())) {
+ // defocus floating dialog:
+ sp_dialog_defocus_cpp(wnd);
+
+ // for docked dialogs, move focus to canvas
+ if (auto desktop = getDesktop()) {
+ desktop->getCanvas()->grab_focus();
+ }
+ }
+}
+
+/**
+ * Callback to reset the dialog highlight.
+ */
+bool DialogBase::blink_off()
+{
+ Gtk::Notebook *notebook = dynamic_cast<Gtk::Notebook *>(get_parent());
+ if (notebook && notebook->get_is_drawable()) {
+ notebook->get_style_context()->remove_class("blink");
+ }
+ return false;
+}
+
+/**
+ * Called when the desktop might have changed for this dialog.
+ */
+void DialogBase::setDesktop(SPDesktop *new_desktop)
+{
+ if (desktop == new_desktop) {
+ return;
+ }
+
+ unsetDesktop();
+
+ if (new_desktop) {
+ desktop = new_desktop;
+
+ if (desktop->selection) {
+ selection = desktop->selection;
+ _select_changed = selection->connectChanged(sigc::mem_fun(*this, &DialogBase::selectionChanged_impl));
+ _select_modified = selection->connectModified(sigc::mem_fun(*this, &DialogBase::selectionModified_impl));
+ }
+
+ _doc_replaced = desktop->connectDocumentReplaced(sigc::hide<0>(sigc::mem_fun(*this, &DialogBase::setDocument)));
+ _desktop_destroyed = desktop->connectDestroy(sigc::mem_fun(*this, &DialogBase::desktopDestroyed));
+ this->setDocument(desktop->getDocument());
+
+ if (desktop->selection) {
+ this->selectionChanged(selection);
+ }
+ set_sensitive(true);
+ }
+
+ desktopReplaced();
+}
+
+//
+void DialogBase::fix_inner_scroll(Gtk::Widget *scrollwindow)
+{
+ auto scrollwin = dynamic_cast<Gtk::ScrolledWindow *>(scrollwindow);
+ auto viewport = dynamic_cast<Gtk::ScrolledWindow *>(scrollwin->get_child());
+ Gtk::Widget *child = nullptr;
+ if (viewport) { //some widgets has viewportother not
+ child = viewport->get_child();
+ } else {
+ child = scrollwin->get_child();
+ }
+ if (child && scrollwin) {
+ Glib::RefPtr<Gtk::Adjustment> adjustment = scrollwin->get_vadjustment();
+ child->signal_scroll_event().connect([=](GdkEventScroll* event) {
+ auto container = dynamic_cast<Gtk::Container *>(this);
+ if (container) {
+ std::vector<Gtk::Widget*> widgets = container->get_children();
+ if (widgets.size()) {
+ auto parentscroll = dynamic_cast<Gtk::ScrolledWindow *>(widgets[0]);
+ if (parentscroll) {
+ if (event->delta_y > 0 && (adjustment->get_value() + adjustment->get_page_size()) == adjustment->get_upper()) {
+ parentscroll->event((GdkEvent*)event);
+ return true;
+ } else if (event->delta_y < 0 && adjustment->get_value() == adjustment->get_lower()) {
+ parentscroll->event((GdkEvent*)event);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ });
+ }
+}
+
+/**
+ * implementation method that call to main function only when tab is showing
+ */
+void
+DialogBase::selectionChanged_impl(Inkscape::Selection *selection) {
+ if (_showing) {
+ selectionChanged(selection);
+ }
+}
+
+/**
+ * implementation method that call to main function only when tab is showing
+ */
+void
+DialogBase::selectionModified_impl(Inkscape::Selection *selection, guint flags) {
+ if (_showing) {
+ selectionModified(selection, flags);
+ }
+}
+
+/**
+ * function called from notebook dialog that performs an update of the dialog and sets the dialog showing state true
+ */
+void
+DialogBase::setShowing(bool showing) {
+ _showing = showing;
+ selectionChanged(getSelection());
+}
+
+/**
+ * Called to destruct desktops, must not call virtuals
+ */
+void DialogBase::unsetDesktop()
+{
+ desktop = nullptr;
+ document = nullptr;
+ selection = nullptr;
+ _desktop_destroyed.disconnect();
+ _doc_replaced.disconnect();
+ _select_changed.disconnect();
+ _select_modified.disconnect();
+}
+
+void DialogBase::desktopDestroyed(SPDesktop* old_desktop)
+{
+ if (old_desktop == desktop && desktop) {
+ unsetDesktop();
+ set_sensitive(false);
+ }
+}
+
+/**
+ * Called when the document might have changed, called from setDesktop too.
+ */
+void DialogBase::setDocument(SPDocument *new_document)
+{
+ if (document != new_document) {
+ document = new_document;
+ documentReplaced();
+ }
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :