diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:29:01 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:29:01 +0000 |
commit | 35a96bde514a8897f6f0fcc41c5833bf63df2e2a (patch) | |
tree | 657d15a03cc46bd099fc2c6546a7a4ad43815d9f /src/selcue.cpp | |
parent | Initial commit. (diff) | |
download | inkscape-35a96bde514a8897f6f0fcc41c5833bf63df2e2a.tar.xz inkscape-35a96bde514a8897f6f0fcc41c5833bf63df2e2a.zip |
Adding upstream version 1.0.2.upstream/1.0.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/selcue.cpp | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/src/selcue.cpp b/src/selcue.cpp new file mode 100644 index 0000000..b1d30bc --- /dev/null +++ b/src/selcue.cpp @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Helper object for showing selected items + * + * Authors: + * bulia byak <bulia@users.sf.net> + * Carl Hetherington <inkscape@carlh.net> + * Abhishek Sharma + * + * Copyright (C) 2004 Authors + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "selcue.h" + +#include "desktop.h" +#include "selection.h" +#include "text-editing.h" + +#include "display/sodipodi-ctrl.h" +#include "display/sodipodi-ctrlrect.h" +#include "display/sp-canvas-util.h" + +#include "libnrtype/Layout-TNG.h" + +#include "object/sp-flowtext.h" +#include "object/sp-text.h" + +Inkscape::SelCue::BoundingBoxPrefsObserver::BoundingBoxPrefsObserver(SelCue &sel_cue) : + Observer("/tools/bounding_box"), + _sel_cue(sel_cue) +{ +} + +void Inkscape::SelCue::BoundingBoxPrefsObserver::notify(Preferences::Entry const &val) +{ + _sel_cue._boundingBoxPrefsChanged(static_cast<int>(val.getBool())); +} + +Inkscape::SelCue::SelCue(SPDesktop *desktop) + : _desktop(desktop), + _bounding_box_prefs_observer(*this) +{ + _selection = _desktop->getSelection(); + + _sel_changed_connection = _selection->connectChanged( + sigc::hide(sigc::mem_fun(*this, &Inkscape::SelCue::_newItemBboxes)) + ); + + { + void(SelCue::*modifiedSignal)() = &SelCue::_updateItemBboxes; + _sel_modified_connection = _selection->connectModified( + sigc::hide(sigc::hide(sigc::mem_fun(*this, modifiedSignal))) + ); + } + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + _updateItemBboxes(prefs); + prefs->addObserver(_bounding_box_prefs_observer); +} + +Inkscape::SelCue::~SelCue() +{ + _sel_changed_connection.disconnect(); + _sel_modified_connection.disconnect(); + + for (auto & _item_bboxe : _item_bboxes) { + sp_canvas_item_destroy(_item_bboxe); + } + _item_bboxes.clear(); + + for (auto & _text_baseline : _text_baselines) { + sp_canvas_item_destroy(_text_baseline); + } + _text_baselines.clear(); +} + +void Inkscape::SelCue::_updateItemBboxes() +{ + _updateItemBboxes(Inkscape::Preferences::get()); +} + +void Inkscape::SelCue::_updateItemBboxes(Inkscape::Preferences *prefs) +{ + gint mode = prefs->getInt("/options/selcue/value", MARK); + if (mode == NONE) { + return; + } + + g_return_if_fail(_selection != nullptr); + + int prefs_bbox = prefs->getBool("/tools/bounding_box"); + + _updateItemBboxes(mode, prefs_bbox); +} + +void Inkscape::SelCue::_updateItemBboxes(gint mode, int prefs_bbox) +{ + auto items = _selection->items(); + if (_item_bboxes.size() != (unsigned int) boost::distance(items)) { + _newItemBboxes(); + return; + } + + int bcount = 0; + auto ll= _selection->items(); + for (auto l = ll.begin(); l != ll.end(); ++l) { + SPItem *item = *l; + SPCanvasItem* box = _item_bboxes[bcount ++]; + + if (box) { + Geom::OptRect const b = (prefs_bbox == 0) ? + item->desktopVisualBounds() : item->desktopGeometricBounds(); + + if (b) { + sp_canvas_item_show(box); + if (mode == MARK) { + SP_CTRL(box)->moveto(Geom::Point(b->min()[Geom::X], b->max()[Geom::Y])); + } else if (mode == BBOX) { + SP_CTRLRECT(box)->setRectangle(*b); + } + } else { // no bbox + sp_canvas_item_hide(box); + } + } + } + + _newTextBaselines(); +} + + +void Inkscape::SelCue::_newItemBboxes() +{ + for (auto & _item_bboxe : _item_bboxes) { + sp_canvas_item_destroy(_item_bboxe); + } + _item_bboxes.clear(); + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gint mode = prefs->getInt("/options/selcue/value", MARK); + if (mode == NONE) { + return; + } + + g_return_if_fail(_selection != nullptr); + + int prefs_bbox = prefs->getBool("/tools/bounding_box"); + + auto ll= _selection->items(); + for (auto l = ll.begin(); l != ll.end(); ++l) { + SPItem *item = *l; + + Geom::OptRect const b = (prefs_bbox == 0) ? + item->desktopVisualBounds() : item->desktopGeometricBounds(); + + SPCanvasItem* box = nullptr; + + if (b) { + if (mode == MARK) { + box = sp_canvas_item_new(_desktop->getControls(), + SP_TYPE_CTRL, + "mode", SP_CTRL_MODE_XOR, + "shape", SP_CTRL_SHAPE_DIAMOND, + "size", 6, + "filled", TRUE, + "fill_color", 0x000000ff, + "stroked", FALSE, + "stroke_color", 0x000000ff, + NULL); + sp_canvas_item_show(box); + SP_CTRL(box)->moveto(Geom::Point(b->min()[Geom::X], b->max()[Geom::Y])); + + sp_canvas_item_move_to_z(box, 0); // just low enough to not get in the way of other draggable knots + + } else if (mode == BBOX) { + box = sp_canvas_item_new(_desktop->getControls(), + SP_TYPE_CTRLRECT, + nullptr); + + SP_CTRLRECT(box)->setRectangle(*b); + SP_CTRLRECT(box)->setColor(0xffffffa0, false, 0); + SP_CTRLRECT(box)->setDashed(true); + SP_CTRLRECT(box)->setInvert(false); + SP_CTRLRECT(box)->setShadow(1, 0x0000c0a0); + + sp_canvas_item_move_to_z(box, 0); + } + } + + if (box) { + _item_bboxes.push_back(box); + } + } + + _newTextBaselines(); +} + +void Inkscape::SelCue::_newTextBaselines() +{ + for (auto & _text_baseline : _text_baselines) { + sp_canvas_item_destroy(_text_baseline); + } + _text_baselines.clear(); + + auto ll = _selection->items(); + for (auto l=ll.begin();l!=ll.end();++l) { + SPItem *item = *l; + + SPCanvasItem* baseline_point = nullptr; + if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { // visualize baseline + Inkscape::Text::Layout const *layout = te_get_layout(item); + if (layout != nullptr && layout->outputExists()) { + boost::optional<Geom::Point> pt = layout->baselineAnchorPoint(); + if (pt) { + baseline_point = sp_canvas_item_new(_desktop->getControls(), SP_TYPE_CTRL, + "mode", SP_CTRL_MODE_XOR, + "size", 5, + "filled", 0, + "stroked", 1, + "stroke_color", 0x000000ff, + NULL); + + sp_canvas_item_show(baseline_point); + SP_CTRL(baseline_point)->moveto((*pt) * item->i2dt_affine()); + sp_canvas_item_move_to_z(baseline_point, 0); + } + } + } + + if (baseline_point) { + _text_baselines.push_back(baseline_point); + } + } +} + +void Inkscape::SelCue::_boundingBoxPrefsChanged(int prefs_bbox) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gint mode = prefs->getInt("/options/selcue/value", MARK); + if (mode == NONE) { + return; + } + + g_return_if_fail(_selection != nullptr); + + _updateItemBboxes(mode, prefs_bbox); +} + +/* + 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 : |