diff --git a/src/selection.cpp b/src/selection.cpp
index 05bd8d030283fd1d94d40fb2dfe46e8ba933fcba..b71f27815214e527d8059792c352bdf5d21b5e4c 100644 (file)
--- a/src/selection.cpp
+++ b/src/selection.cpp
#include "sp-shape.h"
#include "sp-path.h"
+#include "sp-item-group.h"
+#include "box3d.h"
+#include "box3d.h"
+#include "persp3d.h"
#include <sigc++/functors/mem_fun.h>
/* Handler for selected objects "modified" signal */
-void Selection::_schedule_modified(SPObject *obj, guint flags) {
+void Selection::_schedule_modified(SPObject */*obj*/, guint flags) {
if (!this->_idle) {
/* Request handling to be run in _idle loop */
this->_idle = g_idle_add_full(SP_SELECTION_UPDATE_PRIORITY, GSourceFunc(&Selection::_emit_modified), this, NULL);
@@ -157,6 +161,27 @@ void Selection::add(SPObject *obj, bool persist_selection_context/* = false */)
_emitChanged(persist_selection_context);
}
+void Selection::add_box_perspective(SPBox3D *box) {
+ Persp3D *persp = box3d_get_perspective(box);
+ std::map<Persp3D *, unsigned int>::iterator p = _persps.find(persp);
+ if (p != _persps.end()) {
+ (*p).second++;
+ } else {
+ _persps[persp] = 1;
+ }
+}
+
+void Selection::add_3D_boxes_recursively(SPObject *obj) {
+ std::list<SPBox3D *> boxes = box3d_extract_boxes(obj);
+
+ for (std::list<SPBox3D *>::iterator i = boxes.begin(); i != boxes.end(); ++i) {
+ SPBox3D *box = *i;
+ box3d_add_to_selection(box);
+ _3dboxes.push_back(box);
+ add_box_perspective(box);
+ }
+}
+
void Selection::_add(SPObject *obj) {
// unselect any of the item's ancestors and descendants which may be selected
// (to prevent double-selection)
_objs = g_slist_prepend(_objs, obj);
+ add_3D_boxes_recursively(obj);
+
_release_connections[obj] = obj->connectRelease(sigc::mem_fun(*this, (void (Selection::*)(SPObject *))&Selection::remove));
_modified_connections[obj] = obj->connectModified(sigc::mem_fun(*this, &Selection::_schedule_modified));
}
_emitChanged();
}
+void Selection::remove_box_perspective(SPBox3D *box) {
+ Persp3D *persp = box3d_get_perspective(box);
+ std::map<Persp3D *, unsigned int>::iterator p = _persps.find(persp);
+ if (p == _persps.end()) {
+ g_print ("Warning! Trying to remove unselected perspective from selection!\n");
+ return;
+ }
+ if ((*p).second > 1) {
+ _persps[persp]--;
+ } else {
+ _persps.erase(p);
+ }
+}
+
+void Selection::remove_3D_boxes_recursively(SPObject *obj) {
+ std::list<SPBox3D *> boxes = box3d_extract_boxes(obj);
+
+ for (std::list<SPBox3D *>::iterator i = boxes.begin(); i != boxes.end(); ++i) {
+ SPBox3D *box = *i;
+ box3d_remove_from_selection(box);
+ std::list<SPBox3D *>::iterator b = std::find(_3dboxes.begin(), _3dboxes.end(), box);
+ if (b == _3dboxes.end()) {
+ g_print ("Warning! Trying to remove unselected box from selection.\n");
+ return;
+ }
+ _3dboxes.erase(b);
+ remove_box_perspective(box);
+ }
+}
+
void Selection::_remove(SPObject *obj) {
_modified_connections[obj].disconnect();
_modified_connections.erase(obj);
_release_connections[obj].disconnect();
_release_connections.erase(obj);
+ remove_3D_boxes_recursively(obj);
+
_objs = g_slist_remove(_objs, obj);
}
return _reprs;
}
+std::list<Persp3D *> const Selection::perspList() {
+ std::list<Persp3D *> pl;
+ for (std::map<Persp3D *, unsigned int>::iterator p = _persps.begin(); p != _persps.end(); ++p) {
+ pl.push_back((*p).first);
+ }
+ return pl;
+}
+
+std::list<SPBox3D *> const Selection::box3DList() {
+ return _3dboxes;
+}
+
SPObject *Selection::single() {
if ( _objs != NULL && _objs->next == NULL ) {
return reinterpret_cast<SPObject *>(_objs->data);
return obj ? SP_OBJECT_REPR(obj) : NULL;
}
-NRRect *Selection::bounds(NRRect *bbox) const
+NRRect *Selection::bounds(NRRect *bbox, SPItem::BBoxType type) const
{
g_return_val_if_fail (bbox != NULL, NULL);
- *bbox = NRRect(bounds());
+ *bbox = NRRect(bounds(type));
return bbox;
}
-NR::Maybe<NR::Rect> Selection::bounds() const
+boost::optional<NR::Rect> Selection::bounds(SPItem::BBoxType type) const
{
GSList const *items = const_cast<Selection *>(this)->itemList();
- NR::Maybe<NR::Rect> bbox = NR::Nothing();
+ boost::optional<NR::Rect> bbox;
for ( GSList const *i = items ; i != NULL ; i = i->next ) {
- bbox = NR::union_bounds(bbox, sp_item_bbox_desktop(SP_ITEM(i->data)));
+ bbox = NR::union_bounds(bbox, sp_item_bbox_desktop(SP_ITEM(i->data), type));
}
return bbox;
}
-NRRect *Selection::boundsInDocument(NRRect *bbox) const {
+NRRect *Selection::boundsInDocument(NRRect *bbox, SPItem::BBoxType type) const {
g_return_val_if_fail (bbox != NULL, NULL);
GSList const *items=const_cast<Selection *>(this)->itemList();
for ( GSList const *iter=items ; iter != NULL ; iter = iter->next ) {
SPItem *item=SP_ITEM(iter->data);
- NR::Matrix const i2doc(sp_item_i2doc_affine(item));
- sp_item_invoke_bbox(item, bbox, i2doc, FALSE);
+ NR::Matrix i2doc(from_2geom(sp_item_i2doc_affine(item)));
+ sp_item_invoke_bbox(item, bbox, i2doc, FALSE, type);
}
return bbox;
}
-NR::Maybe<NR::Rect> Selection::boundsInDocument() const {
+boost::optional<NR::Rect> Selection::boundsInDocument(SPItem::BBoxType type) const {
NRRect r;
- return boundsInDocument(&r)->upgrade();
+ return boundsInDocument(&r, type)->upgrade();
}
/** Extract the position of the center from the first selected object */
-NR::Maybe<NR::Point> Selection::center() const {
+boost::optional<NR::Point> Selection::center() const {
GSList *items = (GSList *) const_cast<Selection *>(this)->itemList();
NR::Point center;
if (items) {
return first->getCenter();
}
}
- NR::Maybe<NR::Rect> bbox = bounds();
+ boost::optional<NR::Rect> bbox = bounds();
if (bbox) {
return bounds()->midpoint();
} else {
- return NR::Nothing();
+ return boost::optional<NR::Point>();
}
}
/**
* Compute the list of points in the selection that are to be considered for snapping.
- * This includes all special points of each item in the selection, except path nodes
*/
-std::vector<NR::Point> Selection::getSnapPoints() const {
+std::vector<NR::Point> Selection::getSnapPoints(bool includeItemCenter) const {
GSList const *items = const_cast<Selection *>(this)->itemList();
std::vector<NR::Point> p;
for (GSList const *iter = items; iter != NULL; iter = iter->next) {
- // getSnapPoints() is only being used in the selector tool, which should
- // not snap path nodes. Only the node tool should snap those.
SPItem *this_item = SP_ITEM(iter->data);
- if (!SP_IS_PATH(this_item)) {
- // Only snap if we don't have a path at hand
- // (Same check occurs in sp-item-group)
- sp_item_snappoints(this_item, SnapPointsIter(p));
- }
+ sp_item_snappoints(this_item, false, SnapPointsIter(p));
+ //Include the transformation origin for snapping
+ //For a group only the group's origin is considered
+ if (includeItemCenter) {
+ p.push_back(this_item->getCenter());
+ }
}
return p;
std::vector<NR::Point> p;
for (GSList const *iter = items; iter != NULL; iter = iter->next) {
- sp_item_snappoints(SP_ITEM(iter->data), SnapPointsIter(p));
+ sp_item_snappoints(SP_ITEM(iter->data), false, SnapPointsIter(p));
}
std::vector<NR::Point> pHull;
cvh.add(*i);
}
- NR::Maybe<NR::Rect> rHull = cvh.bounds();
+ boost::optional<NR::Rect> rHull = cvh.bounds();
if (rHull) {
for ( unsigned i = 0 ; i < 4 ; ++i ) {
pHull.push_back(rHull->corner(i));