001    /*
002     * PainterPropertyEditor.java
003     *
004     * Created on March 21, 2006, 11:26 AM
005     *
006     * To change this template, choose Tools | Template Manager
007     * and open the template in the editor.
008     */
009    
010    package org.jdesktop.swingx.editors;
011    
012    import java.awt.Color;
013    import java.awt.GradientPaint;
014    import java.awt.geom.AffineTransform;
015    import java.awt.geom.Arc2D;
016    import java.awt.geom.Area;
017    import java.awt.geom.CubicCurve2D;
018    import java.awt.geom.Ellipse2D;
019    import java.awt.geom.GeneralPath;
020    import java.awt.geom.Line2D;
021    import java.awt.geom.PathIterator;
022    import java.awt.geom.Point2D;
023    import java.awt.geom.QuadCurve2D;
024    import java.awt.geom.Rectangle2D;
025    import java.awt.geom.RoundRectangle2D;
026    import java.beans.DefaultPersistenceDelegate;
027    import java.beans.Encoder;
028    import java.beans.Expression;
029    import java.beans.PersistenceDelegate;
030    import java.beans.PropertyEditorSupport;
031    import java.beans.Statement;
032    import java.beans.XMLDecoder;
033    import java.beans.XMLEncoder;
034    import java.io.ByteArrayInputStream;
035    import java.io.ByteArrayOutputStream;
036    import javax.swing.JFrame;
037    import org.apache.batik.ext.awt.LinearGradientPaint;
038    import org.apache.batik.ext.awt.MultipleGradientPaint.ColorSpaceEnum;
039    import org.apache.batik.ext.awt.RadialGradientPaint;
040    import org.jdesktop.swingx.JXPanel;
041    import org.jdesktop.swingx.painter.BackgroundPainter;
042    import org.jdesktop.swingx.painter.CheckerboardPainter;
043    import org.jdesktop.swingx.painter.CompoundPainter;
044    import org.jdesktop.swingx.painter.GlossPainter;
045    import org.jdesktop.swingx.painter.MattePainter;
046    import org.jdesktop.swingx.painter.Painter;
047    import org.jdesktop.swingx.painter.PinstripePainter;
048    import org.jdesktop.swingx.painter.ShapePainter;
049    import org.jdesktop.swingx.painter.TextPainter;
050    import org.jdesktop.swingx.painter.gradient.BasicGradientPainter;
051    import org.jdesktop.swingx.painter.gradient.LinearGradientPainter;
052    import org.jdesktop.swingx.painter.gradient.RadialGradientPainter;
053    
054    /**
055     * Two parts to this property editor. The first part is a simple dropdown.
056     * The second part is a complicated UI for constructing multiple "layers" of
057     * various different Painters, including gradient painters.
058     *
059     * @author Richard
060     */
061    public class PainterPropertyEditor extends PropertyEditorSupport {
062        /** Creates a new instance of PainterPropertyEditor */
063        public PainterPropertyEditor() {
064        }
065        
066        public Painter getValue() {
067            return (Painter)super.getValue();
068        }
069    
070        public String getJavaInitializationString() {
071            Painter painter = getValue();
072            //TODO!!!
073            return painter == null ? "null" : 
074                "new org.jdesktop.swingx.painter.CheckerboardPainter()";
075        }
076    
077        public static void main(String... args) {
078            ByteArrayOutputStream baos = new ByteArrayOutputStream(300);
079            XMLEncoder e = new XMLEncoder(baos);
080            
081            e.setPersistenceDelegate(GradientPaint.class, new GradientPaintDelegate());
082            e.setPersistenceDelegate(Arc2D.Float.class, new Arc2DDelegate());
083            e.setPersistenceDelegate(Arc2D.Double.class, new Arc2DDelegate());
084            e.setPersistenceDelegate(CubicCurve2D.Float.class, new CubicCurve2DDelegate());
085            e.setPersistenceDelegate(CubicCurve2D.Double.class, new CubicCurve2DDelegate());
086            e.setPersistenceDelegate(Ellipse2D.Float.class, new Ellipse2DDelegate());
087            e.setPersistenceDelegate(Ellipse2D.Double.class, new Ellipse2DDelegate());
088            e.setPersistenceDelegate(Line2D.Float.class, new Line2DDelegate());
089            e.setPersistenceDelegate(Line2D.Double.class, new Line2DDelegate());
090            e.setPersistenceDelegate(Point2D.Float.class, new Point2DDelegate());
091            e.setPersistenceDelegate(Point2D.Double.class, new Point2DDelegate());
092            e.setPersistenceDelegate(QuadCurve2D.Float.class, new QuadCurve2DDelegate());
093            e.setPersistenceDelegate(QuadCurve2D.Double.class, new QuadCurve2DDelegate());
094            e.setPersistenceDelegate(Rectangle2D.Float.class, new Rectangle2DDelegate());
095            e.setPersistenceDelegate(Rectangle2D.Double.class, new Rectangle2DDelegate());
096            e.setPersistenceDelegate(RoundRectangle2D.Float.class, new RoundRectangle2DDelegate());
097            e.setPersistenceDelegate(RoundRectangle2D.Double.class, new RoundRectangle2DDelegate());
098            e.setPersistenceDelegate(Area.class, new AreaDelegate());
099            e.setPersistenceDelegate(GeneralPath.class, new GeneralPathDelegate());
100            e.setPersistenceDelegate(AffineTransform.class, new AffineTransformDelegate());
101            e.setPersistenceDelegate(RadialGradientPaint.class, new RadialGradientPaintDelegate());
102            e.setPersistenceDelegate(LinearGradientPaint.class, new LinearGradientPaintDelegate());
103            
104            Area a = new Area(new RoundRectangle2D.Double(20, 20, 50, 50, 4, 4));
105            a.add(new Area(new Ellipse2D.Double(10, 10, 100, 20)));
106            
107            TextPainter textPainter = new TextPainter("Yo dude");
108            textPainter.setPaint(Color.WHITE);
109            
110            e.writeObject(new CompoundPainter(
111                    new BackgroundPainter(),
112                    new CheckerboardPainter(),
113                    new MattePainter(Color.BLACK),
114                    new BasicGradientPainter(BasicGradientPainter.RED_XP),
115                    new LinearGradientPainter(LinearGradientPainter.BLACK_PERSPECTIVE),
116                    new RadialGradientPainter(new RadialGradientPaint(
117                        new Point2D.Double(.5, .5),
118                        .2f, new float[] {0f, .5f, 1f},
119                        new Color[] {Color.BLACK,Color.WHITE,Color.RED})),
120                    new ShapePainter(a),
121                    new PinstripePainter(),
122                    textPainter,
123                    new GlossPainter()
124    //                new IconPainter(), 
125    //                new ImagePainter(),
126                    ));
127            e.close();
128            System.out.println(baos.toString());
129            
130            XMLDecoder d = new XMLDecoder(new ByteArrayInputStream(baos.toByteArray()));
131            
132            Painter p = (Painter)d.readObject();
133            
134            JFrame frame = new JFrame("Yo momma");
135            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
136            JXPanel panel = new JXPanel();
137            panel.setBackgroundPainter(p);
138            frame.add(panel);
139            frame.setSize(800,600);
140            frame.setVisible(true);
141        }
142        
143        public static final class GradientPaintDelegate extends DefaultPersistenceDelegate {
144            public GradientPaintDelegate() {
145                super(new String[] {"point1", "color1", "point2", "color2"});
146            }
147        }
148        public static final class LinearGradientPaintDelegate extends DefaultPersistenceDelegate {
149            public LinearGradientPaintDelegate() {
150                super(new String[] {"startPoint", "endPoint", "fractions", "colors"});
151                //these 3 not yet supported. The problem is the
152                //colorspace. I haven't figured out how to transfer that one yet
153                //, "cycleMethod", "colorSpace", "transform"});
154            }
155    
156            protected Expression instantiate(Object oldInstance, Encoder out) {
157                
158                ColorSpaceEnum e = ((LinearGradientPaint)oldInstance).getColorSpace();
159                Expression retValue;
160                
161                retValue = super.instantiate(oldInstance, out);
162                return retValue;
163            }
164        }
165        public static final class RadialGradientPaintDelegate extends DefaultPersistenceDelegate {
166            public RadialGradientPaintDelegate() {
167                super(new String[] {"centerPoint", "radius", "focusPoint", "fractions", "colors"});
168                //these 3 not yet supported. The problem is the
169                //colorspace. I haven't figured out how to transfer that one yet
170                //, "cycleMethod", "colorSpace", "transform"});
171            }
172        }
173        public static final class Arc2DDelegate extends DefaultPersistenceDelegate {
174            public Arc2DDelegate() {
175                super(new String[] {"x", "y", "width", "height", "angleStart", "angleExtent", "arcType"});
176            }
177        }
178        public static final class CubicCurve2DDelegate extends DefaultPersistenceDelegate {
179            public CubicCurve2DDelegate() {
180                super(new String[] {"x1", "y1", "ctrlX1", "ctrlY1", "ctrlX2", "ctrlY2", "x2", "y2"});
181            }
182        }
183        public static final class Ellipse2DDelegate extends DefaultPersistenceDelegate {
184            public Ellipse2DDelegate() {
185                super(new String[] {"x", "y", "width", "height"});
186            }
187        }
188        public static final class Line2DDelegate extends DefaultPersistenceDelegate {
189            public Line2DDelegate() {
190                super(new String[] {"x1", "y1", "x2", "y2"});
191            }
192        }
193        public static final class Point2DDelegate extends DefaultPersistenceDelegate {
194            public Point2DDelegate() {
195                super(new String[] {"x", "y"});
196            }
197        }
198        public static final class QuadCurve2DDelegate extends DefaultPersistenceDelegate {
199            public QuadCurve2DDelegate() {
200                super(new String[] {"x1", "y1", "ctrlX", "ctrlY", "x2", "y2"});
201            }
202        }
203        public static final class Rectangle2DDelegate extends DefaultPersistenceDelegate {
204            public Rectangle2DDelegate() {
205                super(new String[] {"x", "y", "width", "height"});
206            }
207        }
208        public static final class RoundRectangle2DDelegate extends DefaultPersistenceDelegate {
209            public RoundRectangle2DDelegate() {
210                super(new String[] {"x", "y", "width", "height", "arcWidth", "arcHeight"});
211            }
212        }
213        public static final class AreaDelegate extends PersistenceDelegate {
214            protected Expression instantiate(Object oldInstance, Encoder out) {
215                Area a = (Area)oldInstance;
216    
217                //use the default constructor
218                AffineTransform tx = new AffineTransform();
219                PathIterator itr = a.getPathIterator(tx);
220                
221                GeneralPath path = new GeneralPath();
222                out.writeExpression(new Expression(path, GeneralPath.class, "new", new Object[0]));
223                
224                while (!itr.isDone()) {
225                    float[] segment = new float[6]; //must use floats because lineTo etc use floats
226                    int pathType = itr.currentSegment(segment);
227    
228                    switch (pathType) {
229                        case PathIterator.SEG_CLOSE:
230                            out.writeStatement(new Statement(path, "closePath", new Object[0]));
231                            break;
232                        case PathIterator.SEG_CUBICTO:
233                            out.writeStatement(new Statement(path, "curveTo", new Object[] {segment[0], segment[1], segment[2], segment[3], segment[4], segment[5]}));
234                            break;
235                        case PathIterator.SEG_LINETO:
236                            out.writeStatement(new Statement(path, "lineTo", new Object[] {segment[0], segment[1]}));
237                            break;
238                        case PathIterator.SEG_MOVETO:
239                            out.writeStatement(new Statement(path, "moveTo", new Object[] {segment[0], segment[1]}));
240                            break;
241                        case PathIterator.SEG_QUADTO:
242                            out.writeStatement(new Statement(path, "quadTo", new Object[] {segment[0], segment[1], segment[2], segment[3]}));
243                            break;
244                    }
245                    itr.next();
246                }
247                
248                return new Expression(a, Area.class, "new", new Object[] {path});
249            }
250        }
251        public static final class AffineTransformDelegate extends DefaultPersistenceDelegate {
252            public AffineTransformDelegate() {
253                super(new String[] {"scaleX", "shearY", "shearX", "scaleY", "translateX", "translateY"});
254            }
255        }
256        public static final class GeneralPathDelegate extends PersistenceDelegate {
257            protected Expression instantiate(Object oldInstance, Encoder out) {
258                return new Expression(oldInstance, GeneralPath.class, "new", new Object[0]);
259            }
260            protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
261                GeneralPath a = (GeneralPath)oldInstance;
262    
263                AffineTransform tx = new AffineTransform();
264                PathIterator itr = a.getPathIterator(tx);
265    
266                out.writeStatement(new Statement(a, "setWindingRule", new Object[] {a.getWindingRule()}));
267    
268                while (!itr.isDone()) {
269                    float[] segment = new float[6]; //must use floats because lineTo etc use floats
270                    int pathType = itr.currentSegment(segment);
271    
272                    switch (pathType) {
273                        case PathIterator.SEG_CLOSE:
274                            out.writeStatement(new Statement(a, "closePath", new Object[0]));
275                            break;
276                        case PathIterator.SEG_CUBICTO:
277                            out.writeStatement(new Statement(a, "curveTo", new Object[] {segment[0], segment[1], segment[2], segment[3], segment[4], segment[5]}));
278                            break;
279                        case PathIterator.SEG_LINETO:
280                            out.writeStatement(new Statement(a, "lineTo", new Object[] {segment[0], segment[1]}));
281                            break;
282                        case PathIterator.SEG_MOVETO:
283                            out.writeStatement(new Statement(a, "moveTo", new Object[] {segment[0], segment[1]}));
284                            break;
285                        case PathIterator.SEG_QUADTO:
286                            out.writeStatement(new Statement(a, "quadTo", new Object[] {segment[0], segment[1], segment[2], segment[3]}));
287                            break;
288                    }
289                    itr.next();
290                }
291            }
292        }
293    //    public static final class PaintDelegate extends PersistenceDelegate {
294    //        protected Expression instantiate(Object oldInstance, Encoder out) {
295    //            if (oldInstance instanceof GradientPaint) {
296    //                
297    //            }
298    //        }
299    //    }
300    }