~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/selection.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-07-06 22:03:02 UTC
  • mto: (2.4.1 sid) (1.4.1 upstream) (45.1.3 maverick)
  • mto: This revision was merged to the branch mainline in revision 9.
  • Revision ID: james.westby@ubuntu.com-20060706220302-itgso3qgxdaxjmcy
Tags: upstream-0.44
ImportĀ upstreamĀ versionĀ 0.44

Show diffs side-by-side

added added

removed removed

Lines of Context:
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>
8
9
 *
 
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>
18
20
#endif
19
 
#include <algorithm>
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"
28
 
#include "sp-item.h"
29
26
#include "selection.h"
30
 
#include "tools-switch.h"
31
 
#include "sp-item-group.h"
32
 
#include "inkscape.h"
33
27
#include "xml/repr.h"
34
28
 
35
29
#include "sp-shape.h"
36
30
 
37
 
#include "helper/stlport.h"
38
31
 
39
32
#define SP_SELECTION_UPDATE_PRIORITY (G_PRIORITY_HIGH_IDLE + 1)
40
33
 
45
38
    _reprs(NULL),
46
39
    _items(NULL),
47
40
    _desktop(desktop),
 
41
    _selection_context(NULL),
 
42
    _context_release_handler_id(0),
48
43
    _flags(0),
49
44
    _idle(0)
50
45
{
51
 
    clearOnceInaccessible(&_desktop);
52
46
}
53
47
 
54
48
Selection::~Selection() {
99
93
    _modified_signal.emit(this, flags);
100
94
}
101
95
 
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),
 
104
                                            this);
 
105
        }
 
106
    } else {
 
107
        _releaseContext(_selection_context);
 
108
    }
 
109
 
103
110
    inkscape_selection_changed(this);
104
111
    _changed_signal.emit(this);
105
112
}
106
113
 
 
114
void
 
115
Selection::_releaseSelectionContext(SPObject *obj, Selection *selection)
 
116
{
 
117
    selection->_releaseContext(obj);
 
118
}
 
119
 
 
120
void
 
121
Selection::_releaseContext(SPObject *obj)
 
122
{
 
123
    if (NULL == _selection_context || _selection_context != obj)
 
124
        return;
 
125
 
 
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;
 
130
}
 
131
 
107
132
void Selection::_invalidateCachedLists() {
108
133
    g_slist_free(_items);
109
134
    _items = NULL;
121
146
    }
122
147
}
123
148
 
 
149
SPObject *Selection::activeContext() {
 
150
    if (NULL != _selection_context)
 
151
        return _selection_context;
 
152
    return desktop()->currentLayer();
 
153
    }
 
154
 
124
155
bool Selection::includes(SPObject *obj) const {
125
156
    if (obj == NULL)
126
157
        return FALSE;
130
161
    return ( g_slist_find(_objs, obj) != NULL );
131
162
}
132
163
 
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));
136
167
 
140
171
 
141
172
    _invalidateCachedLists();
142
173
    _add(obj);
143
 
    _emitChanged();
 
174
    _emitChanged(persist_selection_context);
144
175
}
145
176
 
146
177
void Selection::_add(SPObject *obj) {
162
193
    */
163
194
}
164
195
 
165
 
void Selection::set(SPObject *object) {
 
196
void Selection::set(SPObject *object, bool persist_selection_context) {
166
197
    _clear();
167
 
    add(object);
 
198
    add(object, persist_selection_context);
168
199
}
169
200
 
170
201
void Selection::toggle(SPObject *obj) {
292
323
    return obj ? SP_OBJECT_REPR(obj) : NULL;
293
324
}
294
325
 
295
 
NRRect *Selection::bounds(NRRect *bbox) const {
 
326
NRRect *Selection::bounds(NRRect *bbox) const
 
327
{
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];
 
334
    return bbox;
 
335
}
297
336
 
298
 
    GSList const *items=const_cast<Selection *>(this)->itemList();
 
337
NR::Rect Selection::bounds() const
 
338
{
 
339
    GSList const *items = const_cast<Selection *>(this)->itemList();
299
340
    if (!items) {
300
 
        bbox->x0 = bbox->y0 = bbox->x1 = bbox->y1 = 0.0;
301
 
        return bbox;
 
341
        return NR::Rect(NR::Point(0, 0), NR::Point(0, 0));
302
342
    }
303
343
 
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));
306
346
 
307
 
    for ( GSList const *iter=items ; iter != NULL ; iter = iter->next ) {
308
 
        SPItem *item=SP_ITEM(iter->data);
309
 
        NRRect b;
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;
 
348
    while (i != NULL) {
 
349
        if (i != i_start)
 
350
            bbox = NR::Rect::union_bounds(bbox, sp_item_bbox_desktop(SP_ITEM(i->data)));
 
351
        i = i->next;
315
352
    }
316
353
 
317
354
    return bbox;
318
355
}
319
356
 
320
 
NR::Rect Selection::bounds() const {
321
 
    NRRect r;
322
 
    return NR::Rect(*bounds(&r));
323
 
}
324
 
 
325
357
NRRect *Selection::boundsInDocument(NRRect *bbox) const {
326
358
    g_return_val_if_fail (bbox != NULL, NULL);
327
359
 
348
380
    return NR::Rect(*boundsInDocument(&r));
349
381
}
350
382
 
 
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();
 
386
    NR::Point center;
 
387
    if (items) {
 
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();
 
391
        } else {
 
392
            center = bounds().midpoint();
 
393
        }
 
394
    } else {
 
395
        center = bounds().midpoint();
 
396
    }
 
397
    return center;
 
398
}
 
399
 
351
400
/**
352
401
 * Compute the list of points in the selection that are to be considered for snapping.
353
402
 */
367
416
    for (GSList const *iter = items; iter != NULL; iter = iter->next) {
368
417
        sp_item_snappoints(SP_ITEM(iter->data), SnapPointsIter(p));
369
418
    }
370
 
    
371
 
    std::vector<NR::Point>::iterator i; 
 
419
 
 
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
375
 
        cvh.add(*i); 
 
424
        cvh.add(*i);
376
425
    }
377
 
    
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); 
 
426
 
 
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);
384
433
 
385
434
    return pHull;
386
435
}
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) {
392
 
        NRRect b;
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());
396
444
    }
397
445
 
398
446
    return p;
399
447
}
400
448
 
 
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());
 
454
    return p;
 
455
}
 
456
 
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);
433
489
    return object;
434
490
}
447
503
        return ret;
448
504
}
449
505
 
 
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);
 
513
                }
 
514
        }
 
515
        guint ret = g_slist_length (parents);
 
516
        g_slist_free (parents);
 
517
        return ret;
 
518
}
 
519
 
450
520
}
451
521
 
452
522
/*