diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2016-11-21 11:34:27 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2016-11-21 11:34:27 +0000 |
| commit | b045203981fee53df04a760039ed2730d854f8fd (patch) | |
| tree | e0e5131c8c8dec7ec678acaf65e90a8b8719fd3c /src | |
| parent | Fix #1643408. Bug in pap LPE (diff) | |
| download | inkscape-b045203981fee53df04a760039ed2730d854f8fd.tar.gz inkscape-b045203981fee53df04a760039ed2730d854f8fd.zip | |
Keep corner nodes selected when possible for corner operations.
(bzr r15264)
Diffstat (limited to 'src')
| -rw-r--r-- | src/gradient-drag.cpp | 200 | ||||
| -rw-r--r-- | src/gradient-drag.h | 5 | ||||
| -rw-r--r-- | src/ui/tools/mesh-tool.cpp | 14 |
3 files changed, 177 insertions, 42 deletions
diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 2d36e6a3f..370f4fcba 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -116,6 +116,7 @@ static void gr_drag_sel_modified(Inkscape::Selection */*selection*/, guint /*fla { GrDrag *drag = (GrDrag *) data; if (drag->local_change) { + drag->refreshDraggers (); // Needed to move mesh handles and toggle visibility drag->local_change = false; } else { drag->updateDraggers (); @@ -1660,6 +1661,21 @@ GrDragger::~GrDragger() /** * Select the dragger which has the given draggable. */ +GrDragger *GrDrag::getDraggerFor(GrDraggable *d) { + for (std::vector<GrDragger *>::const_iterator i = this->draggers.begin(); i != this->draggers.end(); ++i ) { + GrDragger *dragger = *i; + for (std::vector<GrDraggable *>::const_iterator j = dragger->draggables.begin(); j != dragger->draggables.end(); ++j ) { + if (d == *j) { + return dragger; + } + } + } + return NULL; +} + +/** + * Select the dragger which has the given draggable. + */ GrDragger *GrDrag::getDraggerFor(SPItem *item, GrPointType point_type, gint point_i, Inkscape::PaintTarget fill_or_stroke) { for (std::vector<GrDragger *>::const_iterator i = this->draggers.begin(); i != this->draggers.end(); ++i ) { @@ -1894,7 +1910,7 @@ void GrDrag::addCurve(SPItem *item, Geom::Point p0, Geom::Point p1, Geom::Point * If there already exists a dragger within MERGE_DIST of p, add the draggable to it; otherwise create * new dragger and add it to draggers list. */ -void GrDrag::addDragger(GrDraggable *draggable) +GrDragger* GrDrag::addDragger(GrDraggable *draggable) { Geom::Point p = getGradientCoords(draggable->item, draggable->point_type, draggable->point_i, draggable->fill_or_stroke); @@ -1904,13 +1920,14 @@ void GrDrag::addDragger(GrDraggable *draggable) // distance is small, merge this draggable into dragger, no need to create new dragger dragger->addDraggable (draggable); dragger->updateKnotShape(); - return; + return dragger; } } GrDragger *new_dragger = new GrDragger(this, p, draggable); // fixme: draggers should be added AFTER the last one: this way tabbing through them will be from begin to end. this->draggers.push_back(new_dragger); + return new_dragger; } /** @@ -1991,53 +2008,129 @@ void GrDrag::addDraggersMesh(SPMeshGradient *mg, SPItem *item, Inkscape::PaintTa for( guint j = 0; j < nodes[i].size(); ++j ) { // std::cout << " Draggers: " << i << " " << j << " " << nodes[i][j]->node_type << std::endl; + switch ( nodes[i][j]->node_type ) { + + case MG_NODE_TYPE_CORNER: + { + mg->array.corners.push_back( nodes[i][j] ); + GrDraggable *corner = new GrDraggable (item, POINT_MG_CORNER, icorner, fill_or_stroke); + addDragger ( corner ); + nodes[i][j]->draggable = icorner; + ++icorner; + break; + } - if( nodes[i][j]->set ) { - switch ( nodes[i][j]->node_type ) { + case MG_NODE_TYPE_HANDLE: + { + mg->array.handles.push_back( nodes[i][j] ); + GrDraggable *handle = new GrDraggable (item, POINT_MG_HANDLE, ihandle, fill_or_stroke); + GrDragger* dragger = addDragger ( handle ); - case MG_NODE_TYPE_CORNER: - { - mg->array.corners.push_back( nodes[i][j] ); - GrDraggable *corner = new GrDraggable (item, POINT_MG_CORNER, icorner, fill_or_stroke); - addDragger ( corner ); - nodes[i][j]->draggable = icorner; - ++icorner; - break; + if( !show_handles || !nodes[i][j]->set ) { + dragger->knot->hide(); } + nodes[i][j]->draggable = ihandle; + ++ihandle; + break; + } - case MG_NODE_TYPE_HANDLE: - { - if( show_handles ) { - mg->array.handles.push_back( nodes[i][j] ); - GrDraggable *handle = new GrDraggable (item, POINT_MG_HANDLE, ihandle, fill_or_stroke); - addDragger ( handle ); - nodes[i][j]->draggable = ihandle; - ++ihandle; - break; - } + case MG_NODE_TYPE_TENSOR: + { + mg->array.tensors.push_back( nodes[i][j] ); + GrDraggable *tensor = new GrDraggable (item, POINT_MG_TENSOR, itensor, fill_or_stroke); + GrDragger* dragger = addDragger ( tensor ); + if( show_handles || !nodes[i][j]->set ) { + dragger->knot->hide(); } + nodes[i][j]->draggable = itensor; + ++itensor; + break; + } - case MG_NODE_TYPE_TENSOR: - { - if( show_handles ) { - mg->array.tensors.push_back( nodes[i][j] ); - GrDraggable *tensor = new GrDraggable (item, POINT_MG_TENSOR, itensor, fill_or_stroke); - addDragger ( tensor ); - nodes[i][j]->draggable = itensor; - ++itensor; - break; + default: + std::cerr << "Bad Mesh draggable type" << std::endl; + break; + } + } + } + + mg->array.draggers_valid = true; +} + +/** + * Refresh draggers, moving and toggling visibility as necessary. + * Does not regenerate draggers (as does updateDraggersMesh()). + */ +void GrDrag::refreshDraggersMesh(SPMeshGradient *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke) +{ + mg->ensureArray(); + std::vector< std::vector< SPMeshNode* > > nodes = mg->array.nodes; + + bool show_handles = true; //abs(prefs->getBool("/tools/mesh/show_handles", true)); + + // Make sure we have at least one patch defined. + if( mg->array.patch_rows() == 0 || mg->array.patch_columns() == 0 ) { + + std::cerr << "GrDrag::refreshDraggersMesh: Empty Mesh, No Draggers to refresh!" << std::endl; + return; + } + + guint ihandle = 0; + guint itensor = 0; + + for( guint i = 0; i < nodes.size(); ++i ) { + for( guint j = 0; j < nodes[i].size(); ++j ) { + + // std::cout << " Draggers: " << i << " " << j << " " << nodes[i][j]->node_type << std::endl; + + switch ( nodes[i][j]->node_type ) { + + case MG_NODE_TYPE_CORNER: + // Do nothing, corners are always shown. + break; + + case MG_NODE_TYPE_HANDLE: + { + GrDragger* dragger = getDraggerFor(item, POINT_MG_HANDLE, ihandle, fill_or_stroke); + if (dragger) { + Geom::Point pk = getGradientCoords( item, POINT_MG_HANDLE, ihandle, fill_or_stroke); + dragger->knot->moveto(pk); + if( !show_handles || !nodes[i][j]->set ) { + dragger->knot->hide(); + } else { + dragger->knot->show(); } + } else { + std::cerr << "GrDrag::refreshDraggersMesh: No dragger!" << std::endl; } + ++ihandle; + break; + } - default: - std::cerr << "Bad Mesh draggable type" << std::endl; - break; + case MG_NODE_TYPE_TENSOR: + { + GrDragger* dragger = getDraggerFor(item, POINT_MG_TENSOR, itensor, fill_or_stroke); + if (dragger) { + Geom::Point pk = getGradientCoords( item, POINT_MG_TENSOR, itensor, fill_or_stroke); + dragger->knot->moveto(pk); + if( !show_handles || !nodes[i][j]->set ) { + dragger->knot->hide(); + } else { + dragger->knot->show(); + } + } else { + std::cerr << "GrDrag::refreshDraggersMesh: No dragger!" << std::endl; + } + ++itensor; + break; } + + default: + std::cerr << "Bad Mesh draggable type" << std::endl; + break; } } } - - mg->array.draggers_valid = true; } /** @@ -2118,6 +2211,41 @@ void GrDrag::updateDraggers() /** + * Refresh draggers, moving and toggling visibility as necessary. + * Does not regenerate draggers (as does updateDraggers()). + * Only applies to mesh gradients. + */ +void GrDrag::refreshDraggers() +{ + + g_return_if_fail(this->selection != NULL); + auto list = this->selection->items(); + for (auto i = list.begin(); i != list.end(); ++i) { + SPItem *item = *i; + SPStyle *style = item->style; + + if (style && (style->fill.isPaintserver())) { + SPPaintServer *server = style->getFillPaintServer(); + if ( server && SP_IS_GRADIENT( server ) ) { + if ( SP_IS_MESHGRADIENT(server) ) { + refreshDraggersMesh( SP_MESHGRADIENT(server), item, Inkscape::FOR_FILL ); + } + } + } + + if (style && (style->stroke.isPaintserver())) { + SPPaintServer *server = style->getStrokePaintServer(); + if ( server && SP_IS_GRADIENT( server ) ) { + if ( SP_IS_MESHGRADIENT(server) ) { + refreshDraggersMesh( SP_MESHGRADIENT(server), item, Inkscape::FOR_STROKE ); + } + } + } + } +} + + +/** * Returns true if at least one of the draggers' knots has the mouse hovering above it. */ bool GrDrag::mouseOver() diff --git a/src/gradient-drag.h b/src/gradient-drag.h index cf0a35c89..a50bb24ed 100644 --- a/src/gradient-drag.h +++ b/src/gradient-drag.h @@ -168,6 +168,7 @@ public: // FIXME: make more of this private! bool keep_selection; + GrDragger *getDraggerFor(GrDraggable *d); GrDragger *getDraggerFor(SPItem *item, GrPointType point_type, gint point_i, Inkscape::PaintTarget fill_or_stroke); void grabKnot(GrDragger *dragger, gint x, gint y, guint32 etime); @@ -185,6 +186,7 @@ public: // FIXME: make more of this private! std::vector<SPCtrlLine *> lines; void updateDraggers(); + void refreshDraggers(); void updateLines(); void updateLevels(); @@ -205,11 +207,12 @@ private: void addLine( SPItem *item, Geom::Point p1, Geom::Point p2, Inkscape::PaintTarget fill_or_stroke); void addCurve(SPItem *item, Geom::Point p0, Geom::Point p1, Geom::Point p2, Geom::Point p3, Inkscape::PaintTarget fill_or_stroke); - void addDragger(GrDraggable *draggable); + GrDragger *addDragger(GrDraggable *draggable); void addDraggersRadial(SPRadialGradient *rg, SPItem *item, Inkscape::PaintTarget fill_or_stroke); void addDraggersLinear(SPLinearGradient *lg, SPItem *item, Inkscape::PaintTarget fill_or_stroke); void addDraggersMesh( SPMeshGradient *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke); + void refreshDraggersMesh(SPMeshGradient *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke); bool styleSet( const SPCSSAttr *css ); diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index d01837c49..7f05906f4 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -355,12 +355,13 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) std::map<SPMeshGradient*, std::vector<guint> > points; std::map<SPMeshGradient*, SPItem*> items; - + std::map<SPMeshGradient*, Inkscape::PaintTarget> fill_or_stroke; + // Get list of selected draggers for each mesh. - // For all selected draggers + // For all selected draggers (a dragger may include draggerables from different meshes). for (std::set<GrDragger *>::const_iterator i = drag->selected.begin(); i != drag->selected.end(); ++i) { GrDragger *dragger = *i; - // For all draggables of dragger + // For all draggables of dragger (a draggable corresponds to a unique mesh). for (std::vector<GrDraggable *>::const_iterator j = dragger->draggables.begin(); j != dragger->draggables.end() ; ++j) { GrDraggable *d = *j; @@ -373,6 +374,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) // Collect points together for same gradient points[gradient].push_back( d->point_i ); items[gradient] = d->item; + fill_or_stroke[gradient] = d->fill_or_stroke ? Inkscape::FOR_FILL: Inkscape::FOR_STROKE; } } @@ -426,6 +428,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) case MG_CORNER_SIDE_TOGGLE: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Toggled mesh path type.")); + drag->local_change = true; // Don't create new draggers. break; case MG_CORNER_SIDE_ARC: @@ -435,16 +438,17 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) case MG_CORNER_TENSOR_TOGGLE: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Toggled mesh tensors.")); + drag->local_change = true; // Don't create new draggers. break; case MG_CORNER_COLOR_SMOOTH: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Smoothed mesh corner color.")); - drag->local_change = true; + drag->local_change = true; // Don't create new draggers. break; case MG_CORNER_COLOR_PICK: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Picked mesh corner color.")); - drag->local_change = true; + drag->local_change = true; // Don't create new draggers. break; case MG_CORNER_INSERT: |
