diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
commit | cca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch) | |
tree | 146f39ded1c938019e1ed42d30923c2ac9e86789 /src/ui/dialog/align-and-distribute.cpp | |
parent | Initial commit. (diff) | |
download | inkscape-upstream/1.2.2.tar.xz inkscape-upstream/1.2.2.zip |
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/ui/dialog/align-and-distribute.cpp | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp new file mode 100644 index 0000000..cc6c58b --- /dev/null +++ b/src/ui/dialog/align-and-distribute.cpp @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** @file + * @brief Align and Distribute widget + */ +/* Authors: + * Tavmjong Bah + * + * Based on dialog by: + * Bryce W. Harrington <bryce@bryceharrington.org> + * Aubanel MONNIER <aubi@libertysurf.fr> + * Frank Felfe <innerspace@iname.com> + * Lauris Kaplinski <lauris@kaplinski.com> + * + * Copyright (C) 2021 Tavmjong Bah + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "align-and-distribute.h" // widget + +#include <iostream> + +#include <giomm.h> + +#include "desktop.h" // Tool switching. +#include "inkscape-window.h" // Activate window action. +#include "actions/actions-tools.h" // Tool switching. +#include "io/resource.h" +#include "ui/dialog/dialog-base.h" // Tool switching. + +namespace Inkscape { +namespace UI { +namespace Dialog { + +using Inkscape::IO::Resource::get_filename; +using Inkscape::IO::Resource::UIS; + +AlignAndDistribute::AlignAndDistribute(Inkscape::UI::Dialog::DialogBase* dlg) + : Gtk::Box(Gtk::ORIENTATION_VERTICAL) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + Glib::ustring builder_file = get_filename(UIS, "align-and-distribute.ui"); + auto builder = Gtk::Builder::create(); + try + { + builder->add_from_file(builder_file); + } + catch (const Glib::Error& ex) + { + std::cerr << "AlignAndDistribute::AlignAndDistribute: " << builder_file << " file not read! " << ex.what().raw() << std::endl; + } + + builder->get_widget("align-and-distribute-box", align_and_distribute_box); + if (!align_and_distribute_box) { + std::cerr << "AlignAndDistribute::AlignAndDistribute: failed to load widget (box)!" << std::endl; + } else { + add(*align_and_distribute_box); + } + + builder->get_widget("align-and-distribute-object", align_and_distribute_object); + if (!align_and_distribute_object) { + std::cerr << "AlignAndDistribute::AlignAndDistribute: failed to load widget (object)!" << std::endl; + } else { + align_and_distribute_object->show(); + } + + builder->get_widget("align-and-distribute-node", align_and_distribute_node); + if (!align_and_distribute_node) { + std::cerr << "AlignAndDistribute::AlignAndDistribute: failed to load widget (node)!" << std::endl; + } else { + align_and_distribute_node->hide(); + } + + // ------------ Object Align ------------- + + builder->get_widget("align-relative-object", align_relative_object); + if (!align_relative_object) { + std::cerr << "AlignAndDistribute::AlignAndDistribute: failed to load widget (combobox)!" << std::endl; + } else { + std::string align_to = prefs->getString("/dialogs/align/objects-align-to", "selection"); + align_relative_object->set_active_id(align_to); + align_relative_object->signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_align_relative_object_changed)); + } + + builder->get_widget("align-move-as-group", align_move_as_group); + if (!align_move_as_group) { + std::cerr << "AlignAndDistribute::AlignAndDistribute: failed to load widget (group button)!" << std::endl; + } else { + bool sel_as_group = prefs->getBool("/dialogs/align/sel-as-groups"); + align_move_as_group->set_active(sel_as_group); + + align_move_as_group->signal_clicked().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_align_as_group_clicked)); + } + + // clang-format off + std::vector<std::pair<std::string, std::string>> align_buttons = { + {"align-horizontal-right-to-anchor", "right anchor" }, + {"align-horizontal-left", "left" }, + {"align-horizontal-center", "hcenter" }, + {"align-horizontal-right", "right" }, + {"align-horizontal-left-to-anchor", "left anchor" }, + {"align-horizontal-baseline", "horizontal" }, + {"align-vertical-bottom-to-anchor", "bottom anchor" }, + {"align-vertical-top", "top" }, + {"align-vertical-center", "vcenter" }, + {"align-vertical-bottom", "bottom" }, + {"align-vertical-top-to-anchor", "top anchor" }, + {"align-vertical-baseline", "vertical" } + }; + // clang-format on + + for (auto align_button: align_buttons) { + Gtk::Button* button; + builder->get_widget(align_button.first, button); + if (!button) { + std::cerr << "AlignAndDistribute::AlignAndDisribute: failed to get button: " + << align_button.first << " " << align_button.second << std::endl; + } else { + button->signal_button_press_event().connect( + sigc::bind<std::string>(sigc::mem_fun(*this, &AlignAndDistribute::on_align_button_press_event), align_button.second), false); + } + } + + + // ------------ Remove overlap ------------- + + builder->get_widget("remove-overlap-button", remove_overlap_button); + if (!remove_overlap_button) { + std::cerr << "AlignAndDistribute::AlignAndDistribute: failed to load widget!" << std::endl; + } else { + remove_overlap_button->signal_button_press_event().connect( + sigc::mem_fun(*this, &AlignAndDistribute::on_remove_overlap_button_press_event), false); // false => run first. + } + + builder->get_widget("remove-overlap-hgap", remove_overlap_hgap); + if (!remove_overlap_hgap) { + std::cerr << "AlignAndDistribute::AlignAndDistribute: failed to load widget!" << std::endl; + } + + builder->get_widget("remove-overlap-vgap", remove_overlap_vgap); + if (!remove_overlap_vgap) { + std::cerr << "AlignAndDistribute::AlignAndDistribute: failed to load widget!" << std::endl; + } + + // ------------ Node Align ------------- + + builder->get_widget("align-relative-node", align_relative_node); + if (!align_relative_node) { + std::cerr << "AlignAndDistribute::AlignAndDistribute: failed to load widget (combobox)!" << std::endl; + } else { + std::string align_nodes_to = prefs->getString("/dialogs/align/nodes-align-to", "first"); + align_relative_node->set_active_id(align_nodes_to); + align_relative_node->signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_align_relative_node_changed)); + } + + std::vector<std::pair<std::string, std::string>> align_node_buttons = { + {"align-node-horizontal", "horizontal"}, + {"align-node-vertical", "vertical" } + }; + + for (auto align_button: align_node_buttons) { + Gtk::Button* button; + builder->get_widget(align_button.first, button); + if (!button) { + std::cerr << "AlignAndDistribute::AlignAndDisribute: failed to get button: " + << align_button.first << " " << align_button.second << std::endl; + } else { + button->signal_button_press_event().connect( + sigc::bind<std::string>(sigc::mem_fun(*this, &AlignAndDistribute::on_align_node_button_press_event), align_button.second), false); + } + } + + + // ------------ Set initial values ------------ + + // Normal or node alignment? + auto desktop = dlg->getDesktop(); + if (desktop) { + desktop_changed(desktop); + } +} + +void +AlignAndDistribute::desktop_changed(SPDesktop* desktop) +{ + tool_connection.disconnect(); + if (desktop) { + tool_connection = + desktop->connectEventContextChanged(sigc::mem_fun(*this, &AlignAndDistribute::tool_changed_callback)); + tool_changed(desktop); + } +} + +void +AlignAndDistribute::tool_changed(SPDesktop* desktop) +{ + bool node = get_active_tool(desktop) == "Node"; + if (node) { + align_and_distribute_object->hide(); + align_and_distribute_node->show(); + } else { + align_and_distribute_object->show(); + align_and_distribute_node->hide(); + } +} + +void +AlignAndDistribute::tool_changed_callback(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec) +{ + tool_changed(desktop); +} + + +void +AlignAndDistribute::on_align_as_group_clicked() +{ + bool state = align_move_as_group->get_active(); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setBool("/dialogs/align/sel-as-groups", state); +} + +void +AlignAndDistribute::on_align_relative_object_changed() +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setString("/dialogs/align/objects-align-to", align_relative_object->get_active_id()); +} + +void +AlignAndDistribute::on_align_relative_node_changed() +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setString("/dialogs/align/nodes-align-to", align_relative_node->get_active_id()); +} + +bool +AlignAndDistribute::on_align_button_press_event(GdkEventButton* button_event, const std::string& align_to) +{ + Glib::ustring argument = align_to; + + argument += " " + align_relative_object->get_active_id(); + + if (align_move_as_group->get_active()) { + argument += " group"; + } + + auto variant = Glib::Variant<Glib::ustring>::create(argument); + auto app = Gio::Application::get_default(); + + if (align_to.find("vertical") != Glib::ustring::npos or align_to.find("horizontal") != Glib::ustring::npos) { + app->activate_action("object-align-text", variant); + } else { + app->activate_action("object-align", variant); + } + + return true; +} + +bool +AlignAndDistribute::on_remove_overlap_button_press_event(GdkEventButton* button_event) +{ + double hgap = remove_overlap_hgap->get_value(); + double vgap = remove_overlap_vgap->get_value(); + + auto variant = Glib::Variant<std::tuple<double, double>>::create(std::tuple<double, double>(hgap, vgap)); + auto app = Gio::Application::get_default(); + app->activate_action("object-remove-overlaps", variant); + return true; +} + +bool +AlignAndDistribute::on_align_node_button_press_event(GdkEventButton* button_event, const std::string& direction) +{ + Glib::ustring argument = align_relative_node->get_active_id(); + + auto variant = Glib::Variant<Glib::ustring>::create(argument); + InkscapeWindow* win = InkscapeApplication::instance()->get_active_window(); + if (!win) { + return true; + } + if (direction == "horizontal") { + win->activate_action("node-align-horizontal", variant); + } else { + win->activate_action("node-align-vertical", variant); + } + + return true; +} + +} // 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 : |