X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fui%2Ftool%2Fcontrol-point-selection.cpp;h=de19fef8d0268d47b37aa05f4603f8f3c6f1f260;hb=16e7cf17a1bc8bb0d79dfa6adc4f75b843fb6d16;hp=d10045c623598dffffaf1ae545837c2aeed5fc0f;hpb=16a8c7d5e433b176636a4a1260c42ea43932110b;p=inkscape.git diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index d10045c62..de19fef8d 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -49,8 +49,6 @@ ControlPointSelection::ControlPointSelection(SPDesktop *d, SPCanvasGroup *th_gro , _dragging(false) , _handles_visible(true) , _one_node_handles(false) - , _sculpt_enabled(false) - , _sculpting(false) { signal_update.connect( sigc::bind( sigc::mem_fun(*this, &ControlPointSelection::_updateTransformHandles), @@ -80,26 +78,7 @@ std::pair ControlPointSelection::insert(c return std::pair(found, false); } - boost::shared_ptr clist(new connlist_type()); - - // hide event param and always return false - clist->push_back( - x->signal_grabbed.connect( - sigc::bind_return( - sigc::bind<0>( - sigc::mem_fun(*this, &ControlPointSelection::_selectionGrabbed), - x), - false))); - clist->push_back( - x->signal_dragged.connect( - sigc::mem_fun(*this, &ControlPointSelection::_selectionDragged))); - // hide event parameter - clist->push_back( - x->signal_ungrabbed.connect( - sigc::hide( - sigc::mem_fun(*this, &ControlPointSelection::_selectionUngrabbed)))); - - found = _points.insert(std::make_pair(x, clist)).first; + found = _points.insert(x).first; x->updateState(); _rot_radius.reset(); @@ -111,11 +90,7 @@ std::pair ControlPointSelection::insert(c /** Remove a point from the selection. */ void ControlPointSelection::erase(iterator pos) { - SelectableControlPoint *erased = pos->first; - boost::shared_ptr clist = pos->second; - for (connlist_type::iterator i = clist->begin(); i != clist->end(); ++i) { - i->disconnect(); - } + SelectableControlPoint *erased = *pos; _points.erase(pos); erased->updateState(); _rot_radius.reset(); @@ -140,11 +115,64 @@ void ControlPointSelection::clear() erase(i++); } -/** Transform all selected control points by the supplied affine transformation. */ +/** Select all points that this selection can contain. */ +void ControlPointSelection::selectAll() +{ + for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) { + insert(*i); + } +} +/** Select all points inside the given rectangle (in desktop coordinates). */ +void ControlPointSelection::selectArea(Geom::Rect const &r) +{ + for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) { + if (r.contains(**i)) + insert(*i); + } +} +/** Unselect all selected points and select all unselected points. */ +void ControlPointSelection::invertSelection() +{ + for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) { + if ((*i)->selected()) erase(*i); + else insert(*i); + } +} +void ControlPointSelection::spatialGrow(SelectableControlPoint *origin, int dir) +{ + bool grow = (dir > 0); + Geom::Point p = origin->position(); + double best_dist = grow ? HUGE_VAL : 0; + SelectableControlPoint *match = NULL; + for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) { + bool selected = (*i)->selected(); + if (grow && !selected) { + double dist = Geom::distance((*i)->position(), p); + if (dist < best_dist) { + best_dist = dist; + match = *i; + } + } + if (!grow && selected) { + double dist = Geom::distance((*i)->position(), p); + // use >= to also deselect the origin node when it's the last one selected + if (dist >= best_dist) { + best_dist = dist; + match = *i; + } + } + } + if (match) { + if (grow) insert(match); + else erase(match); + } +} + +/** Transform all selected control points by the given affine transformation. */ void ControlPointSelection::transform(Geom::Matrix const &m) { for (iterator i = _points.begin(); i != _points.end(); ++i) { - SelectableControlPoint *cur = i->first; + SelectableControlPoint *cur = *i; cur->transform(m); } // TODO preserving the rotation radius needs some rethinking... @@ -160,14 +188,14 @@ void ControlPointSelection::align(Geom::Dim2 axis) Geom::OptInterval bound; for (iterator i = _points.begin(); i != _points.end(); ++i) { - bound.unionWith(Geom::OptInterval(i->first->position()[d])); + bound.unionWith(Geom::OptInterval((*i)->position()[d])); } double new_coord = bound->middle(); for (iterator i = _points.begin(); i != _points.end(); ++i) { - Geom::Point pos = i->first->position(); + Geom::Point pos = (*i)->position(); pos[d] = new_coord; - i->first->move(pos); + (*i)->move(pos); } } @@ -184,8 +212,8 @@ void ControlPointSelection::distribute(Geom::Dim2 d) // first we insert all points into a multimap keyed by the aligned coord to sort them // simultaneously we compute the extent of selection for (iterator i = _points.begin(); i != _points.end(); ++i) { - Geom::Point pos = i->first->position(); - sm.insert(std::make_pair(pos[d], i->first)); + Geom::Point pos = (*i)->position(); + sm.insert(std::make_pair(pos[d], (*i))); bound.unionWith(Geom::OptInterval(pos[d])); } @@ -207,7 +235,7 @@ Geom::OptRect ControlPointSelection::pointwiseBounds() { Geom::OptRect bound; for (iterator i = _points.begin(); i != _points.end(); ++i) { - SelectableControlPoint *cur = i->first; + SelectableControlPoint *cur = (*i); Geom::Point p = cur->position(); if (!bound) { bound = Geom::Rect(p, p); @@ -222,7 +250,7 @@ Geom::OptRect ControlPointSelection::bounds() { Geom::OptRect bound; for (iterator i = _points.begin(); i != _points.end(); ++i) { - SelectableControlPoint *cur = i->first; + SelectableControlPoint *cur = (*i); Geom::OptRect r = cur->bounds(); bound.unionWith(r); } @@ -245,52 +273,35 @@ void ControlPointSelection::restoreTransformHandles() _updateTransformHandles(true); } -void ControlPointSelection::_selectionGrabbed(SelectableControlPoint *p, GdkEventMotion *event) +void ControlPointSelection::toggleTransformHandlesMode() { - hideTransformHandles(); - _dragging = true; - if (held_alt(*event) && _sculpt_enabled) { - _sculpting = true; - _grabbed_point = p; + if (_handles->mode() == TransformHandleSet::MODE_SCALE) { + _handles->setMode(TransformHandleSet::MODE_ROTATE_SKEW); + if (size() == 1) _handles->rotationCenter().setVisible(false); } else { - _sculpting = false; + _handles->setMode(TransformHandleSet::MODE_SCALE); } } -void ControlPointSelection::_selectionDragged(Geom::Point const &old_pos, Geom::Point &new_pos, - GdkEventMotion *event) +void ControlPointSelection::_pointGrabbed() { - Geom::Point delta = new_pos - old_pos; - /*if (_sculpting) { - // for now we only support the default sculpting profile (bell) - // others will be added when preferences will be able to store enumerated values - double pressure, alpha; - if (gdk_event_get_axis (event, GDK_AXIS_PRESSURE, &pressure)) { - pressure = CLAMP(pressure, 0.2, 0.8); - } else { - pressure = 0.5; - } - - alpha = 1 - 2 * fabs(pressure - 0.5); - if (pressure > 0.5) alpha = 1/alpha; + hideTransformHandles(); + _dragging = true; +} - for (iterator i = _points.begin(); i != _points.end(); ++i) { - SelectableControlPoint *cur = i->first; - double dist = Geom::distance(cur->position(), _grabbed_point->position()); - - cur->move(cur->position() + delta); - } - } else*/ { - for (iterator i = _points.begin(); i != _points.end(); ++i) { - SelectableControlPoint *cur = i->first; - cur->move(cur->position() + delta); - } - _handles->rotationCenter().move(_handles->rotationCenter().position() + delta); +void ControlPointSelection::_pointDragged(Geom::Point const &old_pos, Geom::Point &new_pos, + GdkEventMotion */*event*/) +{ + Geom::Point delta = new_pos - old_pos; + for (iterator i = _points.begin(); i != _points.end(); ++i) { + SelectableControlPoint *cur = (*i); + cur->move(cur->position() + delta); } + _handles->rotationCenter().move(_handles->rotationCenter().position() + delta); signal_update.emit(); } -void ControlPointSelection::_selectionUngrabbed() +void ControlPointSelection::_pointUngrabbed() { _dragging = false; _grabbed_point = NULL; @@ -298,6 +309,17 @@ void ControlPointSelection::_selectionUngrabbed() signal_commit.emit(COMMIT_MOUSE_MOVE); } +bool ControlPointSelection::_pointClicked(SelectableControlPoint *p, GdkEventButton *event) +{ + // clicking a selected node should toggle the transform handles between rotate and scale mode, + // if they are visible + if (held_no_modifiers(*event) && _handles_visible && p->selected()) { + toggleTransformHandlesMode(); + return true; + } + return false; +} + void ControlPointSelection::_updateTransformHandles(bool preserve_center) { if (_dragging) return; @@ -307,7 +329,7 @@ void ControlPointSelection::_updateTransformHandles(bool preserve_center) _handles->setBounds(*b, preserve_center); _handles->setVisible(true); } else if (_one_node_handles && size() == 1) { // only one control point in selection - SelectableControlPoint *p = begin()->first; + SelectableControlPoint *p = *begin(); _handles->setBounds(p->bounds()); _handles->rotationCenter().move(p->position()); _handles->rotationCenter().setVisible(false); @@ -491,13 +513,7 @@ bool ControlPointSelection::event(GdkEvent *event) case GDK_h: case GDK_H: if (held_shift(event->key)) { - // TODO make a method for mode switching - if (_handles->mode() == TransformHandleSet::MODE_SCALE) { - _handles->setMode(TransformHandleSet::MODE_ROTATE_SKEW); - if (size() == 1) _handles->rotationCenter().setVisible(false); - } else { - _handles->setMode(TransformHandleSet::MODE_SCALE); - } + toggleTransformHandlesMode(); return true; } // any modifiers except shift should cause no action