/*
* Open Source Physics software is free software as described near the bottom of this code file.
*
* For additional information and documentation on Open Source Physics please see:
* <http://www.opensourcephysics.org/>
*/
package org.opensourcephysics.display;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.WindowConstants;
import org.jibble.epsgraphics.EpsGraphics2D;
import org.opensourcephysics.controls.XML;
import org.opensourcephysics.media.gif.GIFEncoder;
public class GUIUtils {
private GUIUtils() {} // prohibits instantiation
/**
* Converts TeX-like notation for Greek symbols to unicode characters.
* @param input
* @return
* @deprecated use TeXParser class.
*/
public static String parseTeX(String input) {
return TeXParser.parseTeX(input);
}
/**
* Removes TeX subscripting from the input.
* @param input
* @return
* @deprecated use TeXParser class.
*/
public static String removeSubscripting(String input) {
return TeXParser.removeSubscripting(input);
}
/**
* Finds an instance of a class in the given container.
*
* @param container Container
* @param c Class
* @return Component
*/
public static Component findInstance(Container container, Class<?> c) {
if((container==null)||c.isInstance(container)) {
return container;
}
Component[] components = container.getComponents();
for(int i = 0, n = components.length; i<n; i++) {
if(c.isInstance(components[i])) {
return components[i];
}
if(components[i] instanceof Container) {
Component comp = findInstance((Container) components[i], c);
if(c.isInstance(comp)) {
return comp;
}
}
}
return null;
}
/**
* Shows all drawing and table frames.
*
* Usually invoked when a model is initialized but may be invoked at other times
* to show frames that have been closed.
*/
public static void showDrawingAndTableFrames() {
Frame[] frames = Frame.getFrames();
for(int i = 0; i<frames.length; i++) {
if(!frames[i].isDisplayable()) {
continue;
}
if((frames[i].getName()!=null)&&(frames[i].getName().indexOf("Tool")>-1)) { //$NON-NLS-1$
continue;
}
if(OSPFrame.class.isInstance(frames[i])) {
if(DataTableFrame.class.isInstance(frames[i])) {
((DataTableFrame) frames[i]).refreshTable();
}
frames[i].setVisible(true);
((OSPFrame) frames[i]).invalidateImage(); // make sure buffers are up to date
frames[i].repaint(); // repaint if frame is already showing
frames[i].toFront();
}
}
if((OSPRuntime.applet!=null)) {
OSPRuntime.applet.getRootPane().repaint();
}
}
/**
* Renders all OSPFrames whose animated property is true.
*
* Usually invoked by an animation thread after every animation step.
*/
public static void renderAnimatedFrames() {
Frame[] frames = Frame.getFrames();
for(int i = 0; i<frames.length; i++) {
if(!frames[i].isDisplayable()||!OSPFrame.class.isInstance(frames[i])) {
continue;
}
if(((OSPFrame) frames[i]).isAnimated()) {
((OSPFrame) frames[i]).render();
}
}
if((OSPRuntime.applet!=null)&&(OSPRuntime.applet instanceof Renderable)) {
((Renderable) OSPRuntime.applet).render();
}
}
/**
* Repaints all OSPFrames whose animated property is true.
*
* Usually invoked by a control's single-step button.
*/
public static void repaintAnimatedFrames() {
Frame[] frames = Frame.getFrames();
for(int i = 0; i<frames.length; i++) {
if(!frames[i].isDisplayable()||!OSPFrame.class.isInstance(frames[i])) {
continue;
}
if(((OSPFrame) frames[i]).isAnimated()) {
((OSPFrame) frames[i]).invalidateImage(); // make sure buffers are up to date
((OSPFrame) frames[i]).repaint();
}
}
}
/**
* Repaints all OSPFrames.
*/
public static void repaintOSPFrames() {
Frame[] frames = Frame.getFrames();
for(int i = 0; i<frames.length; i++) {
if(!frames[i].isVisible()||!frames[i].isDisplayable()||!OSPFrame.class.isInstance(frames[i])) {
continue;
}
((OSPFrame) frames[i]).repaint();
}
}
/**
* Clears the data in animated DrawingFrames and repaints the frame's content.
*
* All frames are cleared if <code> clearAll<\code> is true; otherwise only frames whose <code>autoClear<\code> flag is
* true will be cleared.
*
* @param clearAll clears all frames if true
*/
public static void clearDrawingFrameData(boolean clearAll) {
Frame[] frames = Frame.getFrames();
for(int i = 0; i<frames.length; i++) {
if(!frames[i].isDisplayable()) {
continue;
}
if(OSPFrame.class.isInstance(frames[i])) {
OSPFrame frame = ((OSPFrame) frames[i]);
if(clearAll||frame.isAutoclear()) {
frame.clearDataAndRepaint();
}
}
}
}
/**
* Sets the IgnorRepaint for all animated frames to the given value.
* @param ignoreRepaint boolean
*/
public static void setAnimatedFrameIgnoreRepaint(boolean ignoreRepaint) {
Frame[] frames = Frame.getFrames();
for(int i = 0; i<frames.length; i++) {
if(!frames[i].isDisplayable()||!DrawingFrame.class.isInstance(frames[i])) {
continue;
}
if(((DrawingFrame) frames[i]).isAnimated()) {
DrawingPanel dp = ((DrawingFrame) frames[i]).getDrawingPanel();
if(dp!=null) {
dp.setIgnoreRepaint(ignoreRepaint);
}
}
}
}
/**
* Enables and disables the menu bars in DrawingFrames and DrawingFrame3D.
*
* Usually invoked when a model is initialized but may be invoked at other times.
*/
public static void enableMenubars(boolean enable) {
Frame[] frames = Frame.getFrames();
for(int i = 0; i<frames.length; i++) {
if(!frames[i].isDisplayable()) {
continue;
}
if((frames[i].getName()!=null)&&(frames[i].getName().indexOf("Tool")>-1)) { //$NON-NLS-1$
continue;
}
Class<?> frame3d = null;
try {
frame3d = Class.forName("org.opensourcephysics.display3d.core.DrawingFrame3D"); //$NON-NLS-1$
} catch(ClassNotFoundException ex) {}
if(DrawingFrame.class.isInstance(frames[i])||((frame3d!=null)&&frame3d.isInstance(frames[i]))) {
JMenuBar bar = ((JFrame) frames[i]).getJMenuBar();
if(bar!=null) {
for(int j = 0, n = bar.getMenuCount(); j<n; j++) {
bar.getMenu(j).setEnabled(enable);
}
}
}
}
}
/**
* Disposes all OSP frames except the given frame.
*
* Usually invoked when the control window is being closed.
*
* @param frame will not be disposed
*/
public static void closeAndDisposeOSPFrames(Frame frame) {
Frame[] frames = Frame.getFrames();
for(int i = 0; i<frames.length; i++) {
if(frames[i]==frame) {
continue;
}
// if (frames[i] instanceof org.opensourcephysics.controls.Launcher.LauncherFrame)continue;
if(OSPFrame.class.isInstance(frames[i])) {
((OSPFrame) frames[i]).setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
((OSPFrame) frames[i]).setVisible(false);
((OSPFrame) frames[i]).dispose();
}
}
}
/**
* Pops up a "Save File" file chooser dialog and takes user through process of saving a file.
*
* @param parent the parent component of the dialog,
* can be <code>null</code>;
* see <code>showDialog</code> in class JFileChooser for details
* @return the file or null if an error occurred:
*/
public static File showSaveDialog(Component parent) {
return showSaveDialog(parent, DisplayRes.getString("GUIUtils.Title.Save")); //$NON-NLS-1$
}
/**
* Pops up a "Save File" file chooser dialog and takes user through process of saving a file.
*
* @param parent the parent component of the dialog,
* can be <code>null</code>;
* see <code>showDialog</code> in class JFileChooser for details
* @param title
* @return the file or null if an error occurred:
*/
public static File showSaveDialog(Component parent, String title) {
// JFileChooser fileChooser = new JFileChooser();
JFileChooser fileChooser = OSPRuntime.getChooser();
// fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
if(fileChooser==null) {
return null;
}
String oldTitle = fileChooser.getDialogTitle();
fileChooser.setDialogTitle(title);
int result = fileChooser.showSaveDialog(parent);
fileChooser.setDialogTitle(oldTitle);
if(result!=JFileChooser.APPROVE_OPTION) {
return null;
}
OSPRuntime.chooserDir = fileChooser.getCurrentDirectory().toString();
File file = fileChooser.getSelectedFile();
if(file.exists()) {
int selected = JOptionPane.showConfirmDialog(parent, DisplayRes.getString("DrawingFrame.ReplaceExisting_message")+" "+file.getName()+DisplayRes.getString("DrawingFrame.QuestionMark"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
DisplayRes.getString("DrawingFrame.ReplaceFile_option_title"), //$NON-NLS-1$
JOptionPane.YES_NO_CANCEL_OPTION);
if(selected!=JOptionPane.YES_OPTION) {
return null;
}
}
return file;
}
public static File showOpenDialog(Component parent) {
JFileChooser fileChooser = OSPRuntime.getChooser(); // new JFileChooser();
int result = fileChooser.showOpenDialog(parent);
if(result!=JFileChooser.APPROVE_OPTION) {
return null;
}
OSPRuntime.chooserDir = fileChooser.getCurrentDirectory().toString();
File file = fileChooser.getSelectedFile();
return file;
}
/**
* Test the time to render a drawable component.
* @param drawable
*/
public static void timingTest(Drawable drawable) {
DrawingPanel dp = new DrawingPanel();
DrawingFrame df = new DrawingFrame(dp);
df.setVisible(true);
dp.addDrawable(drawable);
dp.scale();
dp.setPixelScale();
Graphics g2 = dp.getGraphics();
if(g2==null) {
return;
}
long startTime = System.currentTimeMillis();
drawable.draw(dp, g2); // first drawing often takes longer because of initialization
System.out.print("first drawing="+(System.currentTimeMillis()-startTime)); //$NON-NLS-1$
startTime = System.currentTimeMillis(); // reset the time
for(int i = 0; i<5; i++) {
drawable.draw(dp, g2);
}
System.out.println(" avg time/drawing="+((System.currentTimeMillis()-startTime)/5)); //$NON-NLS-1$
g2.dispose();
}
/**
* Saves the contents of the specified component in the given file format. Note method requires Java 1.4
*
* @param comp
* @param outputFile the output file
* @param outputFileFormat output file format. One of eps, gif, jpeg, or png
*/
public static void saveImage(JComponent comp, File outputFile, String outputFileFormat) throws IOException {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outputFile);
if(outputFileFormat.equals("eps")) { //$NON-NLS-1$
EpsGraphics2D g = new EpsGraphics2D("", fos, 0, 0, comp.getWidth(), comp.getHeight()); //$NON-NLS-1$
comp.paint(g);
g.scale(0.24, 0.24); // Set resolution to 300 dpi (0.24 = 72/300)
// g.setColorDepth(EpsGraphics2D.BLACK_AND_WHITE); // Black & white
g.close();
}
else {
BufferedImage bi = new BufferedImage(comp.getWidth(), comp.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
Graphics g = bi.getGraphics();
comp.paint(g);
g.dispose();
if (outputFileFormat.equals("gif")) { //$NON-NLS-1$
GIFEncoder encoder = new GIFEncoder(bi);
encoder.Write(fos);
}
else {
ImageIO.write(bi, outputFileFormat, fos);
}
fos.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(fos!=null) {
fos.close();
}
}
}
/**
* Saves the contents of the specified component in the given file format. Pops
* open a save file dialog to allow the user to select the output file. Note method requires Java 1.4
*
* @param component comp the component
* @param ouputFileFormat output file format. One of eps, jpeg, or png
* @param parent dialog parent
*/
public static void saveImage(JComponent component, String ouputFileFormat, Component parent) {
File outputFile = GUIUtils.showSaveDialog(component, DisplayRes.getString("GUIUtils.Title.SaveImage")); //$NON-NLS-1$
if(outputFile==null) {
return;
}
try {
GUIUtils.saveImage(component, outputFile, ouputFileFormat);
} catch(IOException ioe) {
JOptionPane.showMessageDialog(parent, "An error occurred while saving the file "+outputFile.getName()+".'"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public static void saveImageAs(JComponent component,String type, String title, String description, String[] extensions) {
JFileChooser chooser = OSPRuntime.createChooser(title, description, extensions);
String fileName = OSPRuntime.chooseFilename(chooser);
if(fileName==null) {
return;
}
File file = new File(fileName);
String extension = XML.getExtension(fileName);
if((extension==null)||".".equals(extension)) { //$NON-NLS-1$
fileName = XML.stripExtension(fileName)+"."+extensions[0]; //$NON-NLS-1$
file = new File(fileName);
if(file.exists()) {
int selected = JOptionPane.showConfirmDialog(null, DisplayRes.getString("DrawingFrame.ReplaceExisting_message") //$NON-NLS-1$
+" "+file.getName()+DisplayRes.getString("DrawingFrame.QuestionMark"), //$NON-NLS-1$ //$NON-NLS-2$
DisplayRes.getString("DrawingFrame.ReplaceFile_option_title"), //$NON-NLS-1$
JOptionPane.YES_NO_CANCEL_OPTION);
if(selected!=JOptionPane.YES_OPTION) {
return;
}
}
}
try {
GUIUtils.saveImage(component, file, type);
} catch(IOException ex) {
ex.printStackTrace();
}
}
/**
* Creates a custom cursor from an image. If an exception occurs, a predefined cursor is returned.
*
* @param image the Image
* @param hotspot the position of the cursor hotspot
* @param name the name of the cursor
* @param predefinedCursorType one of the predefined Cursor types
*/
public static Cursor createCustomCursor(Image image, Point hotspot, String name, int predefinedCursorType) {
try {
return Toolkit.getDefaultToolkit().createCustomCursor(image, hotspot, name);
} catch (Exception ex) {
try {
return Cursor.getPredefinedCursor(predefinedCursorType);
} catch (Exception ex1) {
}
}
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
}
}
/*
* Open Source Physics software is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public License (GPL) as
* published by the Free Software Foundation; either version 2 of the License,
* or(at your option) any later version.
* Code that uses any portion of the code in the org.opensourcephysics package
* or any subpackage (subdirectory) of this package must must also be be released
* under the GNU GPL license.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
* or view the license online at http://www.gnu.org/copyleft/gpl.html
*
* Copyright (c) 2007 The Open Source Physics project
* http://www.opensourcephysics.org
*/