5
5
* Lauris Kaplinski <lauris@kaplinski.com>
6
6
* MenTaLguY <mental@rydia.net>
7
7
* bulia byak <buliabyak@users.sf.net>
8
* Andrius R. <knutux@gmail.com>
10
* Copyright (C) 2006 Andrius R.
9
11
* Copyright (C) 2004-2005 MenTaLguY
10
12
* Copyright (C) 1999-2002 Lauris Kaplinski
11
13
* Copyright (C) 2001-2002 Ximian, Inc.
16
18
#ifdef HAVE_CONFIG_H
17
19
# include <config.h>
20
#include <glib/gmain.h>
21
21
#include "macros.h"
22
#include "helper/sp-marshal.h"
23
#include <glibmm/i18n.h>
24
22
#include "inkscape-private.h"
25
23
#include "desktop.h"
26
24
#include "desktop-handles.h"
27
25
#include "document.h"
29
26
#include "selection.h"
30
#include "tools-switch.h"
31
#include "sp-item-group.h"
33
27
#include "xml/repr.h"
35
29
#include "sp-shape.h"
37
#include "helper/stlport.h"
39
32
#define SP_SELECTION_UPDATE_PRIORITY (G_PRIORITY_HIGH_IDLE + 1)
41
_selection_context(NULL),
42
_context_release_handler_id(0),
51
clearOnceInaccessible(&_desktop);
54
48
Selection::~Selection() {
99
93
_modified_signal.emit(this, flags);
102
void Selection::_emitChanged() {
96
void Selection::_emitChanged(bool persist_selection_context/* = false */) {
97
if (persist_selection_context) {
98
if (NULL == _selection_context) {
99
_selection_context = desktop()->currentLayer();
100
sp_object_ref(_selection_context, NULL);
101
_context_release_handler_id = g_signal_connect(
102
G_OBJECT(_selection_context), "release",
103
G_CALLBACK(&Selection::_releaseSelectionContext),
107
_releaseContext(_selection_context);
103
110
inkscape_selection_changed(this);
104
111
_changed_signal.emit(this);
115
Selection::_releaseSelectionContext(SPObject *obj, Selection *selection)
117
selection->_releaseContext(obj);
121
Selection::_releaseContext(SPObject *obj)
123
if (NULL == _selection_context || _selection_context != obj)
126
g_signal_handler_disconnect(G_OBJECT(_selection_context), _context_release_handler_id);
127
sp_object_unref(_selection_context, NULL);
128
_context_release_handler_id = 0;
129
_selection_context = NULL;
107
132
void Selection::_invalidateCachedLists() {
108
133
g_slist_free(_items);
149
SPObject *Selection::activeContext() {
150
if (NULL != _selection_context)
151
return _selection_context;
152
return desktop()->currentLayer();
124
155
bool Selection::includes(SPObject *obj) const {
130
161
return ( g_slist_find(_objs, obj) != NULL );
133
void Selection::add(SPObject *obj) {
164
void Selection::add(SPObject *obj, bool persist_selection_context/* = false */) {
134
165
g_return_if_fail(obj != NULL);
135
166
g_return_if_fail(SP_IS_OBJECT(obj));
165
void Selection::set(SPObject *object) {
196
void Selection::set(SPObject *object, bool persist_selection_context) {
198
add(object, persist_selection_context);
170
201
void Selection::toggle(SPObject *obj) {
292
323
return obj ? SP_OBJECT_REPR(obj) : NULL;
295
NRRect *Selection::bounds(NRRect *bbox) const {
326
NRRect *Selection::bounds(NRRect *bbox) const
296
328
g_return_val_if_fail (bbox != NULL, NULL);
329
NR::Rect const b = bounds();
330
bbox->x0 = b.min()[NR::X];
331
bbox->y0 = b.min()[NR::Y];
332
bbox->x1 = b.max()[NR::X];
333
bbox->y1 = b.max()[NR::Y];
298
GSList const *items=const_cast<Selection *>(this)->itemList();
337
NR::Rect Selection::bounds() const
339
GSList const *items = const_cast<Selection *>(this)->itemList();
300
bbox->x0 = bbox->y0 = bbox->x1 = bbox->y1 = 0.0;
341
return NR::Rect(NR::Point(0, 0), NR::Point(0, 0));
304
bbox->x0 = bbox->y0 = 1e18;
305
bbox->x1 = bbox->y1 = -1e18;
344
GSList const *i = items;
345
NR::Rect bbox = sp_item_bbox_desktop(SP_ITEM(i->data));
307
for ( GSList const *iter=items ; iter != NULL ; iter = iter->next ) {
308
SPItem *item=SP_ITEM(iter->data);
310
sp_item_bbox_desktop(item, &b);
311
if (b.x0 < bbox->x0) bbox->x0 = b.x0;
312
if (b.y0 < bbox->y0) bbox->y0 = b.y0;
313
if (b.x1 > bbox->x1) bbox->x1 = b.x1;
314
if (b.y1 > bbox->y1) bbox->y1 = b.y1;
347
GSList const *i_start = i;
350
bbox = NR::Rect::union_bounds(bbox, sp_item_bbox_desktop(SP_ITEM(i->data)));
320
NR::Rect Selection::bounds() const {
322
return NR::Rect(*bounds(&r));
325
357
NRRect *Selection::boundsInDocument(NRRect *bbox) const {
326
358
g_return_val_if_fail (bbox != NULL, NULL);
348
380
return NR::Rect(*boundsInDocument(&r));
383
/** Extract the position of the center from the first selected object */
384
NR::Point Selection::center() const {
385
GSList *items = (GSList *) const_cast<Selection *>(this)->itemList();
388
SPItem *first = reinterpret_cast<SPItem*>(g_slist_last(items)->data); // from the first item in selection
389
if (first->isCenterSet()) { // only if set explicitly
390
center = first->getCenter();
392
center = bounds().midpoint();
395
center = bounds().midpoint();
352
401
* Compute the list of points in the selection that are to be considered for snapping.
367
416
for (GSList const *iter = items; iter != NULL; iter = iter->next) {
368
417
sp_item_snappoints(SP_ITEM(iter->data), SnapPointsIter(p));
371
std::vector<NR::Point>::iterator i;
420
std::vector<NR::Point>::iterator i;
372
421
NR::ConvexHull cvh(*(p.begin()));
373
422
for (i = p.begin(); i != p.end(); i++) {
374
423
// these are the points we get back
378
NR::Rect rHull = cvh.bounds();
379
std::vector<NR::Point> pHull(4);
380
pHull[0] = rHull.corner(0);
381
pHull[1] = rHull.corner(1);
382
pHull[2] = rHull.corner(2);
383
pHull[3] = rHull.corner(3);
427
NR::Rect rHull = cvh.bounds();
428
std::vector<NR::Point> pHull(4);
429
pHull[0] = rHull.corner(0);
430
pHull[1] = rHull.corner(1);
431
pHull[2] = rHull.corner(2);
432
pHull[3] = rHull.corner(3);
389
438
GSList const *items = const_cast<Selection *>(this)->itemList();
390
439
std::vector<NR::Point> p;
391
440
for (GSList const *iter = items; iter != NULL; iter = iter->next) {
393
sp_item_bbox_desktop(SP_ITEM(iter->data), &b);
394
p.push_back(NR::Point(b.x0, b.y0));
395
p.push_back(NR::Point(b.x1, b.y1));
441
NR::Rect b = sp_item_bbox_desktop(SP_ITEM(iter->data));
442
p.push_back(b.min());
443
p.push_back(b.max());
449
std::vector<NR::Point> Selection::getBBoxPointsOuter() const {
450
std::vector<NR::Point> p;
451
NR::Rect bbox = bounds();
452
p.push_back(bbox.min());
453
p.push_back(bbox.max());
401
457
void Selection::_removeObjectDescendants(SPObject *obj) {
402
458
GSList *iter, *next;
403
459
for ( iter = _objs ; iter ; iter = next ) {
428
484
g_return_val_if_fail(repr != NULL, NULL);
429
485
gchar const *id = repr->attribute("id");
430
486
g_return_val_if_fail(id != NULL, NULL);
431
SPObject *object=SP_DT_DOCUMENT(_desktop)->getObjectById(id);
487
SPObject *object=sp_desktop_document(_desktop)->getObjectById(id);
432
488
g_return_val_if_fail(object != NULL, NULL);
506
guint Selection::numberOfParents() {
507
GSList const *items = const_cast<Selection *>(this)->itemList();
508
GSList *parents = NULL;
509
for (GSList const *iter = items; iter != NULL; iter = iter->next) {
510
SPObject *parent = SP_OBJECT_PARENT(iter->data);
511
if (g_slist_find (parents, parent) == NULL) {
512
parents = g_slist_prepend (parents, parent);
515
guint ret = g_slist_length (parents);
516
g_slist_free (parents);