001 /*
002 * PainterUtil.java
003 *
004 * Created on July 20, 2006, 1:18 PM
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
013 import java.awt.GradientPaint;
014 import java.awt.Graphics2D;
015 import java.awt.Insets;
016 import java.awt.LinearGradientPaint;
017 import java.awt.RadialGradientPaint;
018 import java.awt.RenderingHints;
019 import java.awt.geom.AffineTransform;
020 import java.awt.geom.Arc2D;
021 import java.awt.geom.Area;
022 import java.awt.geom.CubicCurve2D;
023 import java.awt.geom.Ellipse2D;
024 import java.awt.geom.GeneralPath;
025 import java.awt.geom.Line2D;
026 import java.awt.geom.Point2D;
027 import java.awt.geom.QuadCurve2D;
028 import java.awt.geom.Rectangle2D;
029 import java.awt.geom.RoundRectangle2D;
030 import java.awt.image.BufferedImage;
031 import java.beans.BeanInfo;
032 import java.beans.DefaultPersistenceDelegate;
033 import java.beans.Encoder;
034 import java.beans.ExceptionListener;
035 import java.beans.Expression;
036 import java.beans.Introspector;
037 import java.beans.PersistenceDelegate;
038 import java.beans.PropertyDescriptor;
039 import java.beans.Statement;
040 import java.beans.XMLDecoder;
041 import java.beans.XMLEncoder;
042 import java.io.File;
043 import java.io.FileNotFoundException;
044 import java.io.FileOutputStream;
045 import java.io.IOException;
046 import java.lang.reflect.Field;
047 import java.lang.reflect.Modifier;
048 import java.net.MalformedURLException;
049 import java.net.URL;
050
051 import javax.imageio.ImageIO;
052 import javax.swing.JComponent;
053
054 import org.jdesktop.swingx.JXButton;
055 import org.jdesktop.swingx.JXLabel;
056 import org.jdesktop.swingx.JXPanel;
057 import org.jdesktop.swingx.editors.PainterPropertyEditor.AffineTransformDelegate;
058 import org.jdesktop.swingx.editors.PainterPropertyEditor.Arc2DDelegate;
059 import org.jdesktop.swingx.editors.PainterPropertyEditor.AreaDelegate;
060 import org.jdesktop.swingx.editors.PainterPropertyEditor.CubicCurve2DDelegate;
061 import org.jdesktop.swingx.editors.PainterPropertyEditor.Ellipse2DDelegate;
062 import org.jdesktop.swingx.editors.PainterPropertyEditor.GeneralPathDelegate;
063 import org.jdesktop.swingx.editors.PainterPropertyEditor.GradientPaintDelegate;
064 import org.jdesktop.swingx.editors.PainterPropertyEditor.InsetsDelegate;
065 import org.jdesktop.swingx.editors.PainterPropertyEditor.Line2DDelegate;
066 import org.jdesktop.swingx.editors.PainterPropertyEditor.LinearGradientPaintDelegate;
067 import org.jdesktop.swingx.editors.PainterPropertyEditor.Point2DDelegate;
068 import org.jdesktop.swingx.editors.PainterPropertyEditor.QuadCurve2DDelegate;
069 import org.jdesktop.swingx.editors.PainterPropertyEditor.RadialGradientPaintDelegate;
070 import org.jdesktop.swingx.editors.PainterPropertyEditor.Rectangle2DDelegate;
071 import org.jdesktop.swingx.editors.PainterPropertyEditor.RoundRectangle2DDelegate;
072 import org.jdesktop.swingx.painter.AbstractLayoutPainter;
073 import org.jdesktop.swingx.painter.AbstractPainter;
074 import org.jdesktop.swingx.painter.CompoundPainter;
075 import org.jdesktop.swingx.painter.ImagePainter;
076 import org.jdesktop.swingx.painter.Painter;
077 import org.jdesktop.swingx.painter.RectanglePainter;
078
079 /**
080 *
081 * @author joshy
082 */
083 public class PainterUtil {
084
085 /** Creates a new instance of PainterUtil */
086 private PainterUtil() {
087 }
088 /*
089 public static void main(String[] args) throws Exception {
090 ImagePainter ip = new ImagePainter();
091 ip.setImageString("file:/Users/joshy/Pictures/cooltikis.jpg");
092 File outfile = new File("/Users/joshy/Desktop/test.xml");
093 outfile.createNewFile();
094 p("outfile = " + outfile.getAbsolutePath());
095 p("exists = " + outfile.exists());
096 savePainterToFile(ip, outfile, outfile.getParentFile().toURL());
097 p("---------");
098 ip = (ImagePainter)loadPainter(outfile);
099 p("image = " + ip.getImage());
100 ip = (ImagePainter)loadPainter(outfile.toURL());
101 p("image = " + ip.getImage());
102 p("==================");
103
104
105 }*/
106
107 public static Painter loadPainter(File file) throws FileNotFoundException, MalformedURLException, IOException {
108 return loadPainter(file.toURI().toURL(), file.toURI().toURL());
109 }
110
111 private static Painter loadPainter(final URL in, URL baseURL) throws FileNotFoundException, IOException {
112 Thread.currentThread().setContextClassLoader(PainterUtil.class.getClassLoader());
113 XMLDecoder dec = new XMLDecoder(in.openStream());
114 // p("creating a persistence owner with the base url: " + baseURL);
115 dec.setOwner(new PersistenceOwner(baseURL));
116 dec.setExceptionListener(new ExceptionListener() {
117 public void exceptionThrown(Exception ex) {
118 System.out.println(ex.getMessage());
119 ex.printStackTrace();
120 }
121 });
122 Object obj = dec.readObject();
123 return (Painter)obj;
124 }
125
126 public static Painter loadPainter(URL url) throws IOException {
127 return loadPainter(url,url);
128 }
129
130 static public void savePainterToFile(Painter compoundPainter, File file) throws IOException {
131 savePainterToFile(compoundPainter,file,file.getParentFile().toURI().toURL());
132 }
133
134 static public void savePainterToFile(Painter compoundPainter, File file, URL baseURL) throws IOException {
135 //System.setErr(null);
136 // u.p("writing out to: " + file.getCanonicalPath());
137 setTransient(ImagePainter.class, "image");
138 setTransient(ImagePainter.class, "imageString");
139 //setTransient(CompoundPainter.class,"antialiasing");
140 //setTransient(AbstractPainter.class,"antialiasing");
141 //setTransient(AbstractPainter.class,"renderingHints");
142 //setPropertyDelegate();
143
144 XMLEncoder e = new XMLEncoder(new FileOutputStream(file));
145 e.setOwner(new PersistenceOwner(baseURL));
146 //p("owner = " + e.getOwner());
147 //e.setOwner(compoundPainter);
148
149 // serialize the enums
150 //e.setPersistenceDelegate(AbstractPainter.Antialiasing.class, new TypeSafeEnumPersistenceDelegate());
151 e.setPersistenceDelegate(AbstractPainter.Interpolation.class, new TypeSafeEnumPersistenceDelegate());
152 // e.setPersistenceDelegate(AbstractPainter.FractionalMetrics.class, new TypeSafeEnumPersistenceDelegate());
153 e.setPersistenceDelegate(RectanglePainter.Style.class, new TypeSafeEnumPersistenceDelegate());
154 e.setPersistenceDelegate(AbstractLayoutPainter.HorizontalAlignment.class, new TypeSafeEnumPersistenceDelegate());
155 e.setPersistenceDelegate(AbstractLayoutPainter.VerticalAlignment.class, new TypeSafeEnumPersistenceDelegate());
156
157
158 e.setPersistenceDelegate(AbstractPainter.class, new AbstractPainterDelegate());
159 e.setPersistenceDelegate(ImagePainter.class, new ImagePainterDelegate());
160 e.setPersistenceDelegate(RenderingHints.class, new RenderingHintsDelegate());
161 e.setPersistenceDelegate(GradientPaint.class, new GradientPaintDelegate());
162 e.setPersistenceDelegate(Arc2D.Float.class, new Arc2DDelegate());
163 e.setPersistenceDelegate(Arc2D.Double.class, new Arc2DDelegate());
164 e.setPersistenceDelegate(CubicCurve2D.Float.class, new CubicCurve2DDelegate());
165 e.setPersistenceDelegate(CubicCurve2D.Double.class, new CubicCurve2DDelegate());
166 e.setPersistenceDelegate(Ellipse2D.Float.class, new Ellipse2DDelegate());
167 e.setPersistenceDelegate(Ellipse2D.Double.class, new Ellipse2DDelegate());
168 e.setPersistenceDelegate(Line2D.Float.class, new Line2DDelegate());
169 e.setPersistenceDelegate(Line2D.Double.class, new Line2DDelegate());
170 e.setPersistenceDelegate(Point2D.Float.class, new Point2DDelegate());
171 e.setPersistenceDelegate(Point2D.Double.class, new Point2DDelegate());
172 e.setPersistenceDelegate(QuadCurve2D.Float.class, new QuadCurve2DDelegate());
173 e.setPersistenceDelegate(QuadCurve2D.Double.class, new QuadCurve2DDelegate());
174 e.setPersistenceDelegate(Rectangle2D.Float.class, new Rectangle2DDelegate());
175 e.setPersistenceDelegate(Rectangle2D.Double.class, new Rectangle2DDelegate());
176 e.setPersistenceDelegate(RoundRectangle2D.Float.class, new RoundRectangle2DDelegate());
177 e.setPersistenceDelegate(RoundRectangle2D.Double.class, new RoundRectangle2DDelegate());
178 e.setPersistenceDelegate(Area.class, new AreaDelegate());
179 e.setPersistenceDelegate(GeneralPath.class, new GeneralPathDelegate());
180 e.setPersistenceDelegate(AffineTransform.class, new AffineTransformDelegate());
181 e.setPersistenceDelegate(RadialGradientPaint.class, new RadialGradientPaintDelegate());
182 e.setPersistenceDelegate(LinearGradientPaint.class, new LinearGradientPaintDelegate());
183 e.setPersistenceDelegate(Insets.class, new InsetsDelegate());
184
185 e.writeObject(compoundPainter);
186 e.close();
187 }
188
189 //private static void setPropertyDelegate(Class clazz, String property, )
190 private static void setTransient(Class clazz, String property) {
191 try {
192 BeanInfo info = Introspector.getBeanInfo(clazz);
193 PropertyDescriptor[] propertyDescriptors =
194 info.getPropertyDescriptors();
195 for (int i = 0; i < propertyDescriptors.length; ++i) {
196 PropertyDescriptor pd = propertyDescriptors[i];
197 if (pd.getName().equals(property)) {
198 pd.setValue("transient", Boolean.TRUE);
199 //u.p(pd.attributeNames());
200 }
201 }
202 } catch (Exception ex) {
203 //u.p(ex);
204 }
205 }
206
207 static class TypeSafeEnumPersistenceDelegate extends PersistenceDelegate {
208 protected boolean mutatesTo( Object oldInstance, Object newInstance ) {
209 return oldInstance == newInstance;
210 }
211
212 protected Expression instantiate( Object oldInstance, Encoder out ) {
213 Class type = oldInstance.getClass();
214 if ( !Modifier.isPublic( type.getModifiers() ) )
215 throw new IllegalArgumentException( "Could not instantiate instance of non-public class: " + oldInstance );
216
217 for ( Field field : type.getFields() ) {
218 int mod = field.getModifiers();
219 if ( Modifier.isPublic( mod ) && Modifier.isStatic( mod ) && Modifier.isFinal( mod ) && ( type == field.getDeclaringClass() ) ) {
220 try {
221 if ( oldInstance == field.get( null ) )
222 return new Expression( oldInstance, field, "get", new Object[]{null} );
223 } catch ( IllegalAccessException exception ) {
224 throw new IllegalArgumentException( "Could not get value of the field: " + field, exception );
225 }
226 }
227 }
228 throw new IllegalArgumentException( "Could not instantiate value: " + oldInstance );
229 }
230 }
231
232 public static final class RenderingHintsDelegate extends PersistenceDelegate {
233 protected Expression instantiate(Object oldInstance, Encoder out) {
234 //u.p("rh inst");
235 // give it a constructor w/ null as the argument
236 return new Expression(oldInstance, oldInstance.getClass(),
237 "new", new Object[] { null });
238 }
239 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
240 //u.p("rh init ");
241 RenderingHints rh = (RenderingHints)oldInstance;
242 out.writeStatement(new Statement(oldInstance, "put",
243 new Object[] {RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON}));
244 //u.p("done");
245 }
246 }
247
248 public static final class AbstractPainterDelegate extends DefaultPersistenceDelegate {
249 protected void initialize(Class type, Object oldInstance,
250 Object newInstance, Encoder out) {
251 // p("ap delegate called");
252 super.initialize(type, oldInstance, newInstance, out);
253 }
254 }
255
256 public static final class ImagePainterDelegate extends DefaultPersistenceDelegate {
257 protected void initialize(Class type, Object oldInstance,
258 Object newInstance, Encoder out) {
259 // p("image painter delegate called");
260 super.initialize(type, oldInstance, newInstance, out);
261 //p("old instance = " + oldInstance);
262 //p("owner = " + ((XMLEncoder)out).getOwner());
263 PersistenceOwner owner = (PersistenceOwner)((XMLEncoder)out).getOwner();
264 ImagePainter ip = (ImagePainter)oldInstance;
265 // p("need to convert string: " + ip.getImageString());
266 String s = owner.toXMLURL(ip.getImageString());
267 // p("converted to: " + s);
268 //out.writeExpression(new Expression(oldInstance,owner,"fromXMLURL",new Object[]{ip.getImageString()}));
269 //out.writeStatement(new Statement(owner,"fromXMLURL",new Object[]{ip.getImageString()}));
270 //out.writeStatement(new Statement(oldInstance,"setImageString",new Object[]{
271 //new Expression(oldInstance,owner,"fromXMLURL",new Object[]{ip.getImageString()})
272 //}));
273
274 out.writeStatement(new Statement(oldInstance,"setResolver",new Object[]{owner}));
275 out.writeStatement(new Statement(oldInstance,"setImageString",new Object[]{s}));
276 }
277 }
278
279 public static void savePainterToImage(JComponent testPanel, CompoundPainter compoundPainter, File file) throws IOException {
280 BufferedImage img = new BufferedImage(testPanel.getWidth(),testPanel.getHeight(),
281 BufferedImage.TYPE_INT_ARGB);
282 Graphics2D g = img.createGraphics();
283 setBGP(testPanel,compoundPainter);
284 testPanel.paint(g);
285 ImageIO.write(img,"png",file);
286 }
287
288 public static void setBGP(JComponent comp, Painter painter) {
289 if(comp instanceof JXPanel) {
290 ((JXPanel)comp).setBackgroundPainter(painter);
291 }
292 if(comp instanceof JXButton) {
293 ((JXButton)comp).setBackgroundPainter(painter);
294 }
295 }
296 public static void setFGP(JComponent comp, Painter painter) {
297 if(comp instanceof JXLabel) {
298 ((JXLabel)comp).setForegroundPainter(painter);
299 }
300 if(comp instanceof JXButton) {
301 ((JXButton)comp).setForegroundPainter(painter);
302 }
303 }
304
305 public static Painter getFGP(JComponent comp) {
306 if(comp instanceof JXLabel) {
307 return ((JXLabel)comp).getForegroundPainter();
308 }
309 if(comp instanceof JXButton) {
310 return ((JXButton)comp).getForegroundPainter();
311 }
312 return null;
313 }
314
315 public static Painter getBGP(JComponent comp) {
316 if(comp instanceof JXPanel) {
317 return ((JXPanel)comp).getBackgroundPainter();
318 }
319 if(comp instanceof JXButton) {
320 return ((JXButton)comp).getBackgroundPainter();
321 }
322 return null;
323 }
324
325 public static class PersistenceOwner {
326 private URL baseURL;
327 public PersistenceOwner(URL baseURL) {
328 this.baseURL = baseURL;
329 }
330
331 public URL getBaseURL() {
332 return baseURL;
333 }
334 public String toXMLURL(String url) {
335 // p("========");
336 // p("in toXMLURL()");
337 // p("base url = " + baseURL);
338 // p("url to convert = " + url);
339 //trim off the beginning if the url is relative to the base
340 if(url.startsWith(baseURL.toString())) {
341 // p("it's a valid substring!!!!!!!!!!!!");
342 url = url.substring(baseURL.toString().length());
343 // p("subsstring = " + url);
344 }
345 // p("final url = " + url);
346 // p("========");
347 return url;
348 }
349
350 public String fromXMLURL(String url) throws MalformedURLException {
351 /*p("========");
352 p("in fromXMLURL()");
353 p("base url = " + baseURL);
354 p("url to convert: " + url);*/
355 String s = new URL(baseURL,url).toString();
356 // p("returning: " + s);
357 // p("========");
358 return s;
359 }
360 }
361 }