Report problems to ATLAS LXR Team (with time and IP address indicated)

The LXR Cross Referencer

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Architecture: linux ]
Version: head ] [ nightly ] [ GaudiDev ]
  Links to LXR source navigation pages for stable releases [ 12.*.* ]   [ 13.*.* ]   [ 14.*.* ] 

001 package atlantis.gui;
002 
003 import java.awt.Color;
004 import java.awt.Graphics;
005 import java.awt.GridLayout;
006 import java.awt.Image;
007 import java.awt.Rectangle;
008 import java.awt.event.ActionEvent;
009 import java.awt.event.ActionListener;
010 import java.awt.image.BufferedImage;
011 import java.awt.image.RasterFormatException;
012 import java.beans.PropertyChangeEvent;
013 import java.beans.PropertyChangeListener;
014 import java.io.BufferedOutputStream;
015 import java.io.ByteArrayOutputStream;
016 import java.io.File;
017 import java.io.FileOutputStream;
018 import java.io.IOException;
019 import java.io.OutputStream;
020 
021 import javax.swing.BorderFactory;
022 import javax.swing.ButtonGroup;
023 import javax.swing.JFileChooser;
024 import javax.swing.JMenuBar;
025 import javax.swing.JOptionPane;
026 import javax.swing.JPanel;
027 import javax.swing.JRadioButton;
028 import javax.swing.JRootPane;
029 import javax.swing.filechooser.FileFilter;
030 
031 import atlantis.Atlantis;
032 import atlantis.event.AEvent;
033 import atlantis.canvas.ACanvas;
034 import atlantis.canvas.ALayout;
035 import atlantis.canvas.AWindow;
036 import atlantis.graphics.APSGraphics2D;
037 import atlantis.graphics.encoders.GifEncoder;
038 import atlantis.graphics.encoders.PngEncoder;
039 import atlantis.interactions.AZMRInteraction;
040 import atlantis.utils.AAtlantisException;
041 import atlantis.utils.AUtilities;
042 import atlantis.config.ADefaultValues;
043 
044 
045 /**
046  * Dialog window for saving a picture of the current canvas. This dialog allows
047  * the user to pick the resolution and file type. It also takes care of writing
048  * the actual file.
049  *
050  * @author Eric Jansen
051  */
052 public class ASaveCanvasFileChooser extends JFileChooser implements PropertyChangeListener {
053 
054     /** GUI componont that contains the resolution selection panel. */
055     private AResolutionChooser resolutionChooser;
056 
057     /** Possible image widths shown to user. Heights are fixed by layout restrictions. */
058     private static int[] IMAGE_WIDTHS = {512, 800, 1024};
059 
060     /** Default selected image width. Also the (fixed) width of the EPS images. */
061     private static int IMAGE_WIDTH_DEFAULT = 2;
062 
063     /** Active instance of the dialog. */
064     private static ASaveCanvasFileChooser instance = null;
065 
066     /** String holding the default file name, need to be reset after change of file type. */
067     private static String defaultFileName = null;
068 
069     /**
070      * Pops up the "Save Canvas" dialog.
071      */
072     public static void showDialog()
073     {
074         getInstance();
075         String ext = ((AFileFilter) instance.getFileFilter()).getExtension();
076         instance.setSelectedFile(new File(defaultFileName + "." + ext));
077         instance.showSaveDialog(AGUI.getGUI());
078     }
079 
080 
081     public static String getDefaultFileName()
082     {
083         return defaultFileName;
084     }
085 
086 
087     /**
088      * Methods returns a singleton instance of this class and creates
089      * default name for the target file.
090      * @return ASaveCanvasFileChooser
091      */
092     public static ASaveCanvasFileChooser getInstance()
093     {
094         if(instance == null)
095         {
096             instance = new ASaveCanvasFileChooser();
097         }
098         else
099         {
100             instance.resolutionChooser.updateResolutions();
101         }
102 
103         defaultFileName = makeEventFileName() + "-" + AUtilities.getDateTimeString();
104 
105         return instance;
106 
107     } // getInstance() ------------------------------------------------------
108 
109 
110     /**
111      * Constructor. Instead of this, showDialog() should be used to initiate a
112      * saving operation. That way there will be only one instance and all user
113      * settings will be remembered in a very straightforward way.
114      * Hence this constructor is private.
115      */
116     private ASaveCanvasFileChooser()
117     {
118         super(ADefaultValues.get("LastCanvasPlotSaveDir"));
119 
120         addChoosableFileFilter(new AFileFilter("eps", "Encapsulated Postscript (*.eps)"));
121         addChoosableFileFilter(new AFileFilter("gif", "Graphics Interchange Format (*.gif)"));
122         addChoosableFileFilter(new AFileFilter("png", "Portable Network Graphics (*.png)"));
123 
124         setAcceptAllFileFilterUsed(false);
125         addPropertyChangeListener(this);
126         resolutionChooser = new AResolutionChooser();
127         setAccessory(resolutionChooser);
128         setDialogTitle("Save Canvas");
129     }
130 
131 
132 
133     /**
134      * Grabs canvas and encodes the data in GIF format.
135      * @return byte[]
136      * @throws IOException
137      */
138     public byte[] getGIFData() throws IOException
139     {
140         // Draw image.
141         int imageWidth = resolutionChooser.getImageWidth();
142         int imageHeight = resolutionChooser.getImageHeight();
143         Image image = new BufferedImage(imageWidth, imageHeight,
144                 BufferedImage.TYPE_INT_ARGB);
145         drawScaledCanvas(image.getGraphics(), imageWidth, imageHeight, "gif");
146         ByteArrayOutputStream bs = new ByteArrayOutputStream(102400);
147         // Encode as GIF.
148         GifEncoder encoder = new GifEncoder(image, bs, true);
149         encoder.encode();
150         bs.flush();
151         return bs.toByteArray();
152 
153     } // getGIFData() -------------------------------------------------------
154 
155     /**
156      * Grabs canvas and encodes the data in PNG format.
157      * @return byte[]
158      */
159     public byte[] getPNGData()
160     {
161         // Draw image.
162         int imageWidth = resolutionChooser.getImageWidth();
163         int imageHeight = resolutionChooser.getImageHeight();
164         Image image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
165         drawScaledCanvas(image.getGraphics(), imageWidth, imageHeight, "png");
166 
167         // Encode as PNG.
168         PngEncoder encoder = new PngEncoder(image, true, PngEncoder.FILTER_NONE, 9);
169         byte[] data = encoder.pngEncode();
170         return data;
171         
172     } // getPNGData() -------------------------------------------------------
173 
174 
175     /**
176      * Get the currently selected image width.
177      * @return selected image width
178      */
179     public int getImageWidth()
180     {
181         return resolutionChooser.getImageWidth();
182     }
183 
184 
185 
186     /**
187      * Gets the image height on this button.
188      * @return image height
189      */
190     public int getImageHeight()
191     {
192         return resolutionChooser.getImageHeight();
193     }
194 
195 
196 
197     /**
198      * Called when the user has selected a file and pushes the save button. This function will only
199      * approve the selection when the actual saving was successful.
200      */
201     public void approveSelection()
202     {
203         File file = new File(getSelectedFile().getAbsolutePath());
204 
205         // If the file exists and the user does not want to overwrite it, cancel the save operation.
206         // The dialog is still on screen and the user can pick another file.
207         if (file.exists() && JOptionPane.showConfirmDialog(AGUI.getGUI(), "File exists, overwrite?",
208                 "File exists", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION)
209             return;
210 
211         // All exceptions are handled equally: the user is sent back to the save canvas dialog.
212         try {
213             String type = ((AFileFilter)getFileFilter()).getExtension();
214             byte[] data;
215 
216             // Generate the canvas image in memory.
217             if (type.equals("eps"))
218             {
219                 // Since vector images are scalable, the image size only determines the relative size of
220                 // the data objects. To make the generated EPS independent of the canvas size, we always
221                 // rescale the image to the default size.
222                 int imageWidth = IMAGE_WIDTHS[IMAGE_WIDTH_DEFAULT];
223                 int imageHeight = resolutionChooser.getImageHeight(imageWidth);
224 
225                 StringBuffer sb = new StringBuffer(512 * 1024);
226                 Rectangle bounds = new Rectangle(0, 0, imageWidth, imageHeight);
227                 APSGraphics2D g = new APSGraphics2D(bounds, Color.lightGray, sb);
228                 drawScaledCanvas(g, imageWidth, imageHeight, type);
229                 g.close();
230                 data = sb.toString().getBytes();
231 
232                 /* experiments with jibble EPS library
233                   - requires minor changes in AGraphics and here
234                   - search for occurences of APSGraphics
235                   - last three calls in this method saving data has to be
236                     skipped for jibble EPS as it saved the stream directly
237                   - (this) drawScaledCanvas to call window.paint(g) for
238                     EpsGraphics2D as well
239                 FileOutputStream fos =  new FileOutputStream(file.getAbsolutePath());
240                 EpsGraphics2D epsg = new EpsGraphics2D(null, fos, 0, 0, imageWidth, imageHeight);
241                 drawScaledCanvas(epsg, imageWidth, imageHeight, type);
242                 fos.close();
243                 */
244             }
245             else if (type.equals("gif"))
246             {
247                 data = getGIFData();
248             }
249             else if (type.equals("png"))
250             {
251                 data = getPNGData();
252             }
253 
254             else
255             {
256                 throw new AAtlantisException("Unknown image type: '" + type + "'");
257             }
258 
259             // And finally write the image to the selected file.
260             OutputStream stream = new BufferedOutputStream(new FileOutputStream(file.getAbsolutePath()));
261             stream.write(data);
262             stream.close();
263 
264         }
265         catch(RasterFormatException e)
266         {
267             JOptionPane.showMessageDialog(AGUI.getGUI(),
268                     "The chosen resolution for canvas is too high, try a lower option!",
269                     "Error saving canvas", JOptionPane.INFORMATION_MESSAGE);
270             Atlantis.restoreDefaults();
271             this.cancelSelection();
272         } catch(Exception e)
273         {
274             // Show a dialog with the error message.
275             JOptionPane.showMessageDialog(AGUI.getGUI(), e.getMessage(),
276                     "Error saving canvas", JOptionPane.ERROR_MESSAGE);
277 
278             // The selection is not approved, the user has to select another file or type.
279             return;
280         }
281 
282         // This approves the selection and ends the saving processs.
283         super.approveSelection();
284         ADefaultValues.set("LastCanvasPlotSaveDir", file.getParent() + Atlantis.fileSep);
285 
286     }
287 
288     /**
289      * Mimics the behavior of a normal canvas paint, but with the canvas scaled to a predefined size.
290      * @param g Graphics object to draw on
291      * @param imageWidth width of the image
292      * @param imageHeight height of the image
293      * @param type extension of image
294      */
295     private static void drawScaledCanvas(Graphics g, int imageWidth, int imageHeight, String type)
296     {
297         //hide red ZMR center dot
298         AZMRInteraction.setPaintCenterDot(false);
299         //Auto switch on anti aliasing (too many colors for gif)
300         boolean origAlias = APreferencesControl.getAliasMenuItem();
301         if(!type.equals("gif") && !origAlias)
302             APreferencesControl.setAliasMenuItem(true);
303         else if(type.equals("gif") && origAlias)
304             APreferencesControl.setAliasMenuItem(false);
305         //TODO temporary fix for gif printing
306         boolean origFishEye = APreferencesControl.getFisheyeIndicatorMenuItem();
307         if(type.equals("gif"))
308             APreferencesControl.setFisheyeIndicatorMenuItem(false);
309         ACanvas canvas = ACanvas.getCanvas();
310         ALayout layout = canvas.getCurrentLayout();
311         String[] windows = layout.getWindowNames();
312         JRootPane rootPane = canvas.getRootPane();
313 
314         // Calculate the scale factor.
315         double factor = ((double)imageWidth) / rootPane.getWidth();
316 
317         // Add the title bar, if required.
318         JMenuBar title = canvas.getJMenuBar();
319         if (title != null)
320         {
321             int titleWidth = title.getWidth();
322             int titleHeight = title.getHeight();
323 
324             title.setSize(imageWidth, titleHeight);
325             title.paint(g);
326             title.setSize(titleWidth, titleHeight);
327             g.translate(0, titleHeight);
328         }
329 
330         // Loop over all windows.
331         for (int i=0; i<windows.length; i++)
332         {
333             AWindow window = canvas.getWindow(windows[i]);
334             int x = window.getX();
335             int y = window.getY();
336             int width = window.getWidth();
337             int height = window.getHeight();
338 
339             // If the window is visible resize it temporarily and then draw it.
340             if (canvas.isReallyOnScreen(window))
341             {
342                 g.translate((int)(factor*x), (int)(factor*y));
343                 
344                 // Perhaps I should override window.setSize to automatically validate
345                 // This is because AWindow is now a container with a view inside
346                 // - Adam
347                 window.setSize((int)(factor*width), (int)(factor*height));
348                 window.validate();
349                 
350                 if (g instanceof APSGraphics2D)
351                 {
352                     window.print(g);
353                 }
354                 else
355                 {
356                     window.paint(g);
357                 }
358                 window.setSize(width, height);
359                 window.validate();
360                 g.translate(-(int)(factor*x), -(int)(factor*y));
361             }
362         }
363         //TODO temp fix for gif printing
364         if(type.equals("gif"))
365             APreferencesControl.setFisheyeIndicatorMenuItem(origFishEye);
366         //reset alias
367         if(!type.equals("gif") && !origAlias)
368             APreferencesControl.setAliasMenuItem(origAlias);
369         //reset red ZMR center dot
370         AZMRInteraction.setPaintCenterDot(true);
371     }
372 
373     /**
374      * Property change listener for the JFileChooser
375      * @param e property change event sent by JFileChooser
376      */
377     public void propertyChange(PropertyChangeEvent e)
378     {
379         if (e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
380         {
381             String oldExt = ((AFileFilter)e.getOldValue()).getExtension();
382             String newExt = ((AFileFilter)e.getNewValue()).getExtension();
383 
384             if (oldExt.equals("eps") && !newExt.equals("eps"))
385             {
386                 for (int i=0; i<resolutionChooser.getComponentCount(); i++)
387                 {
388                     resolutionChooser.getComponent(i).setEnabled(true);
389                 }
390             }
391             else if (!oldExt.equals("eps") && newExt.equals("eps"))
392             {
393                 for (int i=0; i<resolutionChooser.getComponentCount(); i++)
394                     resolutionChooser.getComponent(i).setEnabled(false);
395             }
396 
397             // The behaviour of the JFileChooser is somewhat strange. Regardless of what the user has entered,
398             // the input text field will be emptied when the user selects another file type. It is impossible
399             // to retrieve the text that was in this field, so we just reset the default file name.
400             if (getSelectedFile() == null)
401             {
402                 // Reset our default with the new extension
403                 setSelectedFile(new File(defaultFileName + "." + newExt));
404                 updateUI();
405             }
406         }
407     }
408 
409 
410 
411     /**
412      * Generates a file name based on the current event name and the visible projections.
413      * @return auto generated image file name
414      */
415     private static String makeEventFileName()
416     {
417         String name = "Untitled";
418         AEvent ev = Atlantis.getEventManager().getCurrentEvent();
419         if(ev != null)
420         {
421             name = ev.getName();
422             if(name.toLowerCase().endsWith(".xml"))
423             {
424                 // current event comes from XML file, run and event number
425                 // are probably already part of the current filename
426                 name = name.substring(0, name.length() - 4);
427             }
428             else
429             {
430                 // current event was probably retrieved online, add run and
431                 // event numbers into the file name of the canvas plot
432                 if(! ("n/a".equals(ev.getRunNumber()) &&
433                       "n/a".equals(ev.getEventNumber())))
434                 {
435                     name += "_" + ev.getRunNumber() + "_" + ev.getEventNumber();
436                 }
437             }
438         }
439 
440         ACanvas canvas = ACanvas.getCanvas();
441         String[] windows = canvas.getCurrentLayout().getWindowNames();
442         for(int i = 0; i < windows.length; i++)
443         {
444             if(canvas.isReallyOnScreen(canvas.getWindow(windows[i])))
445             {
446                 name += "-" + canvas.getWindow(windows[i]).getProjection().getName();
447             }
448         }
449 
450         return name;
451     }
452 
453 
454 
455     /**
456      * GUI component for the resolution selection panel.
457      */
458     class AResolutionChooser extends JPanel implements ActionListener
459     {
460         /** Currently selected button. */
461         private AResolutionButton selectedButton;
462 
463         /**
464          * Constructor.
465          */
466         public AResolutionChooser()
467         {
468             super(new GridLayout(IMAGE_WIDTHS.length+1, 1));
469             setBorder(BorderFactory.createTitledBorder(" Resolution: "));
470 
471             ButtonGroup group = new ButtonGroup();
472             for (int i=0; i<IMAGE_WIDTHS.length; i++)
473             {
474                 int width = IMAGE_WIDTHS[i];
475                 int height = getImageHeight(IMAGE_WIDTHS[i]);
476 
477                 AResolutionButton button = new AResolutionButton(width, height);
478                 button.addActionListener(this);
479                 if(i == IMAGE_WIDTH_DEFAULT)
480                 {
481                     selectedButton = button;
482                     button.setSelected(true);
483                 }
484                 group.add(button);
485                 add(button);
486             }
487         }
488 
489         /**
490          * Get the currently selected image width.
491          * @return selected image width
492          */
493         public int getImageWidth()
494         {
495             return selectedButton.getImageWidth();
496         }
497 
498         /**
499          * Gets the currently selected image height.
500          * @return selected image height
501          */
502         public int getImageHeight()
503         {
504             return selectedButton.getImageHeight();
505         }
506 
507         public void updateResolutions()
508         {
509             for (int i=0; i<getComponentCount(); i++)
510             {
511                 if (getComponent(i) instanceof AResolutionButton)
512                 {
513                     AResolutionButton button = (AResolutionButton)getComponent(i);
514                     button.setImageHeight(getImageHeight(button.getImageWidth()));
515                 }
516             }
517         }
518 
519         /**
520          * Calculates the image height that will result if one resizes the current canvas to the given width.
521          * @param width canvas width
522          * @return corresponding height
523          */
524         private int getImageHeight(int width)
525         {
526             ACanvas canvas = ACanvas.getCanvas();
527             JRootPane rootPane = canvas.getRootPane();
528 
529             int canvasWidth = rootPane.getWidth();
530             int canvasHeight = rootPane.getHeight();
531 
532             double factor = ((double)width) / canvasWidth;
533 
534             JMenuBar title = canvas.getJMenuBar();
535             if (canvas.getJMenuBar() != null)
536             {
537                 int height = title.getHeight();
538                 return (int)(factor*(canvasHeight-height)) + height;
539             } else {
540                 return (int)(factor*canvasHeight);
541             }
542         }
543 
544         /**
545          * Action listener for the resolution panel.
546          * @param e performed action
547          */
548         public void actionPerformed(ActionEvent e)
549         {
550             selectedButton = (AResolutionButton)e.getSource();
551         }
552 
553         /**
554          * Radio button for the resolution chooser.
555          */
556         public class AResolutionButton extends JRadioButton
557         {
558             /** Image width for this button. */
559             int imageWidth;
560             /** Image height for this button. */
561             int imageHeight;
562 
563             /**
564              * Constructor.
565              * @param imageWidth image width this button corresponds to
566              * @param imageHeight image height this button corresponds to
567              */
568             public AResolutionButton(int imageWidth, int imageHeight)
569             {
570                 super(imageWidth + "x" + imageHeight);
571                 this.imageWidth = imageWidth;
572                 this.imageHeight = imageHeight;
573             }
574 
575             /**
576              * Gets the image width on this button.
577              * @return image width
578              */
579             public int getImageWidth()
580             {
581                 return imageWidth;
582             }
583 
584             /**
585              * Gets the image height on this button.
586              * @return image height
587              */
588             public int getImageHeight()
589             {
590                 return imageHeight;
591             }
592 
593             public void setImageHeight(int imageHeight)
594             {
595                 this.imageHeight = imageHeight;
596                 setText(imageWidth + "x" + imageHeight);
597             }
598         }
599     }
600 
601     /**
602      * Simple filter class that filters files by extension.
603      */
604     private class AFileFilter extends FileFilter
605     {
606         /** File extension. */
607         private String extension;
608         /** Description of the file type this filter shows. */
609         private String description;
610 
611         /**
612          * Constructs a file filter.
613          * @param extension file extension that passes the filter
614          * @param description description of the file type this filter selects
615          */
616         public AFileFilter(String extension, String description)
617         {
618             super();
619             this.extension = extension;
620             this.description = description;
621         }
622 
623         /**
624          * Decides if the filter allows a file to pass or not
625          * @param f file under consideration
626          * @return decision of the filter
627          */
628         public boolean accept(File f)
629         {
630             if (f.isDirectory())
631             {
632                 return true;
633             } else if (f.getName().toLowerCase().endsWith(extension))
634             {
635                 return true;
636             } else {
637                 return false;
638             }
639         }
640 
641         /**
642          * Get the extension this filter filters on.
643          * @return file extension
644          */
645         public String getExtension()
646         {
647             return extension;
648         }
649 
650         /**
651          * Get description of the filter.
652          * @return description
653          */
654         public String getDescription()
655         {
656             return description;
657         }
658     }
659 
660 }

source navigation ] diff markup ] identifier search ] general search ]

Due to the LXR bug, the updates fail sometimes to remove references to deleted files. The Saturday's full rebuilds fix these problems
This page was automatically generated by the LXR engine. Valid HTML 4.01!