001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.painter;
020
021import icy.sequence.Sequence;
022import icy.util.XMLUtil;
023
024import java.awt.Color;
025import java.awt.geom.PathIterator;
026import java.awt.geom.Point2D;
027
028import org.w3c.dom.Node;
029
030/**
031 * Anchor for path type shape.<br>
032 * Support extra coordinate to store curve informations.
033 * 
034 * @author Stephane
035 */
036public class PathAnchor2D extends Anchor2D
037{
038    private static final String ID_POS_CEXT_X = "pos_ext1_x";
039    private static final String ID_POS_CEXT_Y = "pos_ext1_y";
040    private static final String ID_POS_QEXT_X = "pos_ext2_x";
041    private static final String ID_POS_QEXT_Y = "pos_ext2_y";
042    private static final String ID_TYPE = "type";
043
044    /**
045     * Curve extra coordinates
046     */
047    private final Point2D.Double posCExt;
048    /**
049     * Quad extra coordinates
050     */
051    private final Point2D.Double posQExt;
052    /**
053     * anchor type (used as PathIterator type)
054     */
055    private int type;
056
057    public PathAnchor2D(double x1, double y1, double x2, double y2, double x3, double y3, int ray, Color color,
058            Color selectedColor, int type)
059    {
060        super(x3, y3, ray, color, selectedColor);
061
062        posCExt = new Point2D.Double(x1, y1);
063        posQExt = new Point2D.Double(x2, y2);
064        this.type = type;
065    }
066
067    public PathAnchor2D(double x1, double y1, double x2, double y2, double x3, double y3, int ray, Color color,
068            Color selectedColor)
069    {
070        this(x1, y1, x2, y2, x3, y3, ray, color, selectedColor, -1);
071    }
072
073    /**
074     * @deprecated Uses {@link #PathAnchor2D(double, double, double, double, double, double, int, Color, Color)}
075     *             instead.
076     */
077    @Deprecated
078    public PathAnchor2D(Sequence sequence, double x1, double y1, double x2, double y2, double x3, double y3, int ray,
079            Color color, Color selectedColor)
080    {
081        this(x1, y1, x2, y2, x3, y3, ray, color, selectedColor, -1);
082
083        if (sequence != null)
084            sequence.addOverlay(this);
085    }
086
087    public PathAnchor2D(double x1, double y1, double x2, double y2, double x3, double y3, Color color,
088            Color selectedColor)
089    {
090        this(x1, y1, x2, y2, x3, y3, DEFAULT_RAY, color, selectedColor, PathIterator.SEG_CUBICTO);
091    }
092
093    public PathAnchor2D(double x1, double y1, double x2, double y2, double x3, double y3)
094    {
095        this(x1, y1, x2, y2, x3, y3, DEFAULT_RAY, DEFAULT_NORMAL_COLOR, DEFAULT_SELECTED_COLOR,
096                PathIterator.SEG_CUBICTO);
097    }
098
099    public PathAnchor2D(double x1, double y1, double x2, double y2, Color color, Color selectedColor)
100    {
101        this(0d, 0d, x1, y1, x2, y2, DEFAULT_RAY, color, selectedColor, PathIterator.SEG_QUADTO);
102    }
103
104    public PathAnchor2D(double x1, double y1, double x2, double y2)
105    {
106        this(0d, 0d, x1, y1, x2, y2, DEFAULT_RAY, DEFAULT_NORMAL_COLOR, DEFAULT_SELECTED_COLOR, PathIterator.SEG_QUADTO);
107    }
108
109    public PathAnchor2D(double x1, double y1, Color color, Color selectedColor, int type)
110    {
111        this(0d, 0d, 0d, 0d, x1, y1, DEFAULT_RAY, color, selectedColor, type);
112    }
113
114    public PathAnchor2D(double x1, double y1, Color color, Color selectedColor)
115    {
116        this(0d, 0d, 0d, 0d, x1, y1, DEFAULT_RAY, color, selectedColor, PathIterator.SEG_LINETO);
117    }
118
119    /**
120     * @deprecated Uses {@link #PathAnchor2D(double, double, double, double, double, double, int, Color, Color)}
121     *             instead.
122     */
123    @Deprecated
124    public PathAnchor2D(double x1, double y1, int ray, Color color, Color selectedColor)
125    {
126        this(0d, 0d, 0d, 0d, x1, y1, ray, color, selectedColor, PathIterator.SEG_MOVETO);
127    }
128
129    public PathAnchor2D(double x1, double y1, int type)
130    {
131        this(0d, 0d, 0d, 0d, x1, y1, DEFAULT_RAY, DEFAULT_NORMAL_COLOR, DEFAULT_SELECTED_COLOR, type);
132    }
133
134    public PathAnchor2D(double x1, double y1)
135    {
136        this(0d, 0d, 0d, 0d, x1, y1, DEFAULT_RAY, DEFAULT_NORMAL_COLOR, DEFAULT_SELECTED_COLOR, PathIterator.SEG_MOVETO);
137    }
138
139    public PathAnchor2D()
140    {
141        this(0d, 0d, 0d, 0d, 0, 0, DEFAULT_RAY, DEFAULT_NORMAL_COLOR, DEFAULT_SELECTED_COLOR, PathIterator.SEG_MOVETO);
142    }
143
144    /**
145     * @return the type
146     */
147    public int getType()
148    {
149        return type;
150    }
151
152    /**
153     * Set the type of this segment
154     * 
155     * @see PathIterator
156     * @param value
157     *        the type to set
158     */
159    public void setType(int value)
160    {
161        if (type != value)
162        {
163            type = value;
164            painterChanged();
165        }
166    }
167
168    @Override
169    public boolean isVisible()
170    {
171        switch (getType())
172        {
173            // CLOSE type point are never visible
174            case PathIterator.SEG_CLOSE:
175                return false;
176
177            default:
178                return super.isVisible();
179        }
180    }
181
182    /**
183     * @return the posQExt
184     */
185    public Point2D.Double getPosQExt()
186    {
187        return posQExt;
188    }
189
190    /**
191     * @return the posCExt
192     */
193    public Point2D.Double getPosCExt()
194    {
195        return posCExt;
196    }
197
198    public void setPosQExt(Point2D p)
199    {
200        setPosQExt(p.getX(), p.getY());
201    }
202
203    public void setPosQExt(double x, double y)
204    {
205        if ((posQExt.x != x) || (posQExt.y != y))
206        {
207            posQExt.x = x;
208            posQExt.y = y;
209
210            positionChanged();
211            painterChanged();
212        }
213    }
214
215    public void setPosCExt(Point2D p)
216    {
217        setPosCExt(p.getX(), p.getY());
218    }
219
220    public void setPosCExt(double x, double y)
221    {
222        if ((posCExt.x != x) || (posCExt.y != y))
223        {
224            posCExt.x = x;
225            posCExt.y = y;
226
227            positionChanged();
228            painterChanged();
229        }
230    }
231
232    /**
233     * @return the PosQExt.x
234     */
235    public double getPosQExtX()
236    {
237        return posQExt.x;
238    }
239
240    /**
241     * @param x
242     *        the PosQExt.x to set
243     */
244    public void setPosQExtX(double x)
245    {
246        setPosQExt(x, posQExt.y);
247    }
248
249    /**
250     * @return the PosQExt.y
251     */
252    public double getPosQExtY()
253    {
254        return posQExt.y;
255    }
256
257    /**
258     * @param y
259     *        the PosQExt.y to set
260     */
261    public void setPosQExtY(double y)
262    {
263        setPosQExt(posQExt.x, y);
264    }
265
266    /**
267     * @return the PosCExt.x
268     */
269    public double getPosCExtX()
270    {
271        return posCExt.x;
272    }
273
274    /**
275     * @param x
276     *        the PosCExt.x to set
277     */
278    public void setPosCExtX(double x)
279    {
280        setPosCExt(x, posCExt.y);
281    }
282
283    /**
284     * @return the PosCExt.y
285     */
286    public double getPosCExtY()
287    {
288        return posCExt.y;
289    }
290
291    /**
292     * @param y
293     *        the PosCExt.y to set
294     */
295    public void setPosCExtY(double y)
296    {
297        setPosCExt(posCExt.x, y);
298    }
299
300    @Override
301    public void translate(double dx, double dy)
302    {
303        beginUpdate();
304        try
305        {
306            super.translate(dx, dy);
307
308            setPosCExt(posCExt.x + dx, posCExt.y + dy);
309            setPosQExt(posQExt.x + dx, posQExt.y + dy);
310        }
311        finally
312        {
313            endUpdate();
314        }
315    }
316
317    @Override
318    public boolean loadPositionFromXML(Node node)
319    {
320        if (node == null)
321            return false;
322
323        beginUpdate();
324        try
325        {
326            super.loadPositionFromXML(node);
327
328            setPosCExtX(XMLUtil.getElementDoubleValue(node, ID_POS_CEXT_X, 0d));
329            setPosCExtY(XMLUtil.getElementDoubleValue(node, ID_POS_CEXT_Y, 0d));
330            setPosQExtX(XMLUtil.getElementDoubleValue(node, ID_POS_QEXT_X, 0d));
331            setPosQExtY(XMLUtil.getElementDoubleValue(node, ID_POS_QEXT_Y, 0d));
332            setType(XMLUtil.getElementIntValue(node, ID_TYPE, -1));
333        }
334        finally
335        {
336            endUpdate();
337        }
338
339        return true;
340    }
341
342    @Override
343    public boolean loadFromXML(Node node)
344    {
345        if (node == null)
346            return false;
347
348        beginUpdate();
349        try
350        {
351            super.loadFromXML(node);
352
353            setPosCExtX(XMLUtil.getElementDoubleValue(node, ID_POS_CEXT_X, 0d));
354            setPosCExtY(XMLUtil.getElementDoubleValue(node, ID_POS_CEXT_Y, 0d));
355            setPosQExtX(XMLUtil.getElementDoubleValue(node, ID_POS_QEXT_X, 0d));
356            setPosQExtY(XMLUtil.getElementDoubleValue(node, ID_POS_QEXT_Y, 0d));
357            setType(XMLUtil.getElementIntValue(node, ID_TYPE, -1));
358        }
359        finally
360        {
361            endUpdate();
362        }
363
364        return true;
365    }
366
367    @Override
368    public boolean savePositionToXML(Node node)
369    {
370        if (node == null)
371            return false;
372
373        super.savePositionToXML(node);
374
375        XMLUtil.setElementDoubleValue(node, ID_POS_CEXT_X, getPosCExtX());
376        XMLUtil.setElementDoubleValue(node, ID_POS_CEXT_Y, getPosCExtY());
377        XMLUtil.setElementDoubleValue(node, ID_POS_QEXT_X, getPosQExtX());
378        XMLUtil.setElementDoubleValue(node, ID_POS_QEXT_Y, getPosQExtY());
379        XMLUtil.setElementIntValue(node, ID_TYPE, getType());
380
381        return true;
382    }
383
384    @Override
385    public boolean saveToXML(Node node)
386    {
387        if (node == null)
388            return false;
389
390        super.saveToXML(node);
391
392        XMLUtil.setElementDoubleValue(node, ID_POS_CEXT_X, getPosCExtX());
393        XMLUtil.setElementDoubleValue(node, ID_POS_CEXT_Y, getPosCExtY());
394        XMLUtil.setElementDoubleValue(node, ID_POS_QEXT_X, getPosQExtX());
395        XMLUtil.setElementDoubleValue(node, ID_POS_QEXT_Y, getPosQExtY());
396        XMLUtil.setElementIntValue(node, ID_TYPE, getType());
397
398        return true;
399    }
400}