/*
* 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.frames;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Method;
import java.util.ArrayList;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;
import org.opensourcephysics.controls.OSPLog;
import org.opensourcephysics.controls.XML;
import org.opensourcephysics.controls.XMLControl;
import org.opensourcephysics.display.DataTable;
import org.opensourcephysics.display.DataTableFrame;
import org.opensourcephysics.display.DisplayRes;
import org.opensourcephysics.display.Drawable;
import org.opensourcephysics.display.DrawingFrame;
import org.opensourcephysics.display.Histogram;
import org.opensourcephysics.display.HistogramDataset;
import org.opensourcephysics.display.OSPFrame;
import org.opensourcephysics.display.OSPRuntime;
import org.opensourcephysics.display.PlottingPanel;
import org.opensourcephysics.tools.DataTool;
import org.opensourcephysics.tools.LocalJob;
import org.opensourcephysics.tools.Tool;
/**
* HistogramFrame displays a histogram using a dedicated Histogram object.
*
* @author W. Christian
* @version 1.0
*/
public class HistogramFrame extends DrawingFrame {
protected Histogram histogram = new Histogram();
protected DataTable dataTable = new DataTable();
protected DataTableFrame tableFrame;
DataTool tool;
HistogramDataset dataset;
JCheckBoxMenuItem logItem;
/**
* A DrawingFrame with a Histogram as its drawable.
*
* @param xlabel String
* @param ylabel String
* @param title String
*/
public HistogramFrame(String xlabel, String ylabel, String title) {
super(new PlottingPanel(xlabel, ylabel, null));
// histogram.setDiscrete(false) ;
drawingPanel.addDrawable(histogram);
setTitle(title);
dataTable.add(histogram);
setAnimated(true);
setAutoclear(true);
addMenuItems();
}
/**
* Sets the column names and the dataset name.
*
* @param datasetIndex The new xYColumnNames value
* @param xColumnName
* @param yColumnName
* @param datasetName
*/
public void setXYColumnNames(String xColumnName, String yColumnName, String histogramName) {
histogram.setXYColumnNames(xColumnName, yColumnName, histogramName);
}
/**
* Adds Views menu items on the menu bar.
*/
protected void addMenuItems() {
JMenuBar menuBar = getJMenuBar();
if(menuBar==null) {
return;
}
JMenu helpMenu = this.removeMenu(DisplayRes.getString("DrawingFrame.Help_menu_item")); //$NON-NLS-1$
JMenu menu = getMenu(DisplayRes.getString("DrawingFrame.Views_menu")); //$NON-NLS-1$
if(menu==null) {
menu = new JMenu(DisplayRes.getString("DrawingFrame.Views_menu")); //$NON-NLS-1$
menuBar.add(menu);
menuBar.validate();
} else { // add a separator if views exists
menu.addSeparator();
}
if(helpMenu!=null) {
menuBar.add(helpMenu);
}
// add a menu item to show the data table
JMenuItem tableItem = new JMenuItem(DisplayRes.getString("DrawingFrame.DataTable_menu_item")); //$NON-NLS-1$
tableItem.setAccelerator(KeyStroke.getKeyStroke('T', MENU_SHORTCUT_KEY_MASK));
ActionListener tableListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
showDataTable(true);
}
};
tableItem.addActionListener(tableListener);
menu.add(tableItem);
// log scale
menu.addSeparator();
logItem = new JCheckBoxMenuItem(DisplayRes.getString("HistogramFrame.MenuItem.LogScale"), false); //$NON-NLS-1$
logItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
histogram.logScale = logItem.isSelected();
drawingPanel.repaint();
}
});
//menu.add(logItem);
// add to popup menu
JMenuItem item = new JMenuItem(DisplayRes.getString("DrawingFrame.DataTable_menu_item")); //$NON-NLS-1$
item.addActionListener(tableListener);
if((drawingPanel!=null)&&(drawingPanel.getPopupMenu()!=null)) {
drawingPanel.getPopupMenu().add(item);
}
}
/**
* Adds launchable tools to the specified menu.
*
*/
protected JMenu loadToolsMenu() {
JMenuBar menuBar = getJMenuBar();
if(menuBar==null) {
return null;
}
// add menu item
JMenu toolsMenu = new JMenu(DisplayRes.getString("DrawingFrame.Tools_menu_title")); //$NON-NLS-1$
menuBar.add(toolsMenu);
// test dataset tool
JMenuItem datasetItem = new JMenuItem(DisplayRes.getString("DrawingFrame.DatasetTool_menu_item")); //$NON-NLS-1$
toolsMenu.add(datasetItem);
/*
* datasetItem.addActionListener(new ActionListener() {
* public void actionPerformed(ActionEvent e) {
* tool=DataTool.getTool();
* if(tool==null || !tool.isDisplayable()){
* tool = new DataTool(histogram, histogram.getName());
* }else{
* tool.addTab(histogram, histogram.getName());
* }
* tool.setVisible(true);
* }
* });
*/
Class<?> datasetToolClass = null;
if(OSPRuntime.loadDataTool) {
try {
datasetToolClass = Class.forName("org.opensourcephysics.tools.DataTool"); //$NON-NLS-1$
} catch(Exception ex) {
OSPRuntime.loadDataTool = false;
datasetItem.setEnabled(false);
OSPLog.finest("Cannot instantiate data analysis tool class:\n"+ex.toString()); //$NON-NLS-1$
}
}
final Class<?> finalDatasetToolClass = datasetToolClass; // class must be final for action listener
datasetItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
Method m = finalDatasetToolClass.getMethod("getTool", (Class[]) null); //$NON-NLS-1$
Tool tool = (Tool) m.invoke(null, (Object[]) null);
tool.send(new LocalJob(drawingPanel), reply);
if(tool instanceof OSPFrame) {
((OSPFrame) tool).setKeepHidden(false);
}
((JFrame) tool).setVisible(true);
} catch(Exception ex) {}
}
});
return toolsMenu;
}
/**
* Gets an array containing the bin centers.
*
* @return the bins
*/
public double[] getXPoints() {
return histogram.getXPoints();
}
/**
* Gets an array containing the values stored in the bins.
*
* @return the values of the bins
*/
public double[] getYPoints() {
return histogram.getYPoints();
}
/**
* Gets an array containing the log values of the values stored in the bins.
*
* @return the values of the bins
*/
public double[][] getLogPoints() {
return histogram.getLogPoints();
}
/**
* Gets a data array containing both the bin centers and the values within the bins.
*
* @return a double[index][2] array of data
*/
public double[][] getPoints() {
return histogram.getPoints();
}
/**
* Removes drawable objects added by the user from this frame.
*/
public void clearDrawables() {
drawingPanel.clear(); // removes all drawables
drawingPanel.addDrawable(histogram); // puts complex dataset back into panel
showDataTable(false);
}
/**
* Gets Drawable objects added by the user to this frame.
*
* @return the list
*/
public synchronized ArrayList<Drawable> getDrawables() {
ArrayList<Drawable> list = super.getDrawables();
list.remove(histogram);
return list;
}
/**
* Gets Drawable objects added by the user of an assignable type. The list contains
* objects that are assignable from the class or interface.
*
* @param c the type of Drawable object
*
* @return the cloned list
*
* @see #getObjectOfClass(Class c)
*/
public synchronized <T extends Drawable> ArrayList<T> getDrawables(Class<T> c) {
ArrayList<T> list = super.getDrawables(c);
list.remove(histogram);
return list;
}
/**
* Clears all the data stored.
*/
public void clearData() {
histogram.clear();
dataTable.refreshTable();
if(drawingPanel!=null) {
drawingPanel.invalidateImage();
}
}
/**
* Appends a data point to the histogram.
* @param v data point
*/
public void append(double v) {
histogram.append(v);
// this may be slow if the table is large
if((tableFrame!=null)&&tableFrame.isShowing()) {
dataTable.refreshTable();
}
}
/**
* Append a value with number of occurences to the Histogram.
*
* @param value
* @param numberOfOccurences
*/
public void append(double value, double numberOfOccurences) {
histogram.append(value, numberOfOccurences);
if((tableFrame!=null)&&tableFrame.isShowing()) {
dataTable.refreshTable();
}
}
/**
* Appends an array of values with 1 occurence.
*
* @param values
*/
public void append(double[] values) {
histogram.append(values);
// this may be slow if the table is large
if((tableFrame!=null)&&tableFrame.isShowing()) {
dataTable.refreshTable();
}
}
/**
* Sets the discrete flag in the histogram.
*
* @param b <code>true<\code> if bins are discrete, <code>false<\code> if bins are continuous.
*/
public void setDiscrete(boolean b) {
histogram.setDiscrete(b);
}
/**
* Histogram uses logarithmic scale (true/false)
*/
public void setLogScale(boolean b) {
histogram.logScale = b;
logItem.setSelected(b);
}
/**
* Gets the histogram's log scale value.
* @return boolean
*/
public boolean isLogScale() {
return histogram.logScale;
}
/**
* Sets the width of the bins.
*
* @param binWidth
*/
public void setBinWidth(double binWidth) {
histogram.setBinWidth(binWidth);
}
/**
* Gets the width of the bins.
*
* @param binWidth
*/
public double getBinWidth() {
return histogram.getBinWidth();
}
/**
* Sets the bin's fill and edge colors. If the fill color is null the bin is not filled.
*
* @param fillColor
* @param edgeColor
*/
public void setBinColor(Color fillColor, Color edgeColor) {
histogram.setBinColor(fillColor, edgeColor);
}
/**
* Sets the style for drawing this histogram. Options are DRAW_POINT, which
* draws a point at the top of the bin, and DRAW_BIN which draws the entire
* bin down to the x axis. Default is DRAW_BIN.
*
* @param style
*/
public void setBinStyle(short style) {
histogram.setBinStyle(style);
}
/**
* Sets the offset of the bins. Default is 0.
* A value will be appended to bin n if
* n*binWidth +binOffset <= value < (n+1)*binWidth +binOffset
*
* @param binOffset
*/
public void setBinOffset(double binOffset) {
histogram.setBinOffset(binOffset);
}
/**
* Normalizes the occurrences in this histogram to one (true/false).
*/
public void setNormalizedToOne(boolean b) {
histogram.setNormalizedToOne(b);
histogram.adjustForWidth = b;
}
/**
* Makes the x axis positive by default.
*/
public void positiveX() {
boolean b = drawingPanel.isAutoscaleX();
drawingPanel.setPreferredMinMaxX(0, drawingPanel.getPreferredXMax());
drawingPanel.setAutoscaleX(b);
}
/**
* Shows or hides the data table.
*
* @param show boolean
*/
public synchronized void showDataTable(boolean show) {
if(show) {
if((tableFrame==null)||!tableFrame.isDisplayable()) {
tableFrame = new DataTableFrame(getTitle()+" "+DisplayRes.getString("TableFrame.TitleAddOn.Data"), dataTable); //$NON-NLS-1$ //$NON-NLS-2$
tableFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
dataTable.refreshTable();
dataTable.sort(0);
tableFrame.setVisible(true);
} else {
tableFrame.setVisible(false);
tableFrame.dispose();
tableFrame = null;
}
}
public static XML.ObjectLoader getLoader() {
return new HistogramFrameLoader();
}
static protected class HistogramFrameLoader extends DrawingFrame.DrawingFrameLoader {
/**
* Creates a PlotFame.
*
* @param control XMLControl
* @return Object
*/
public Object createObject(XMLControl control) {
HistogramFrame frame = new HistogramFrame("x", "y", //$NON-NLS-1$ //$NON-NLS-2$
DisplayRes.getString("HistogramFrame.Title")); //$NON-NLS-1$
return frame;
}
/**
* Loads the object with data from the control.
*
* @param control XMLControl
* @param obj Object
* @return Object
*/
public Object loadObject(XMLControl control, Object obj) {
super.loadObject(control, obj);
HistogramFrame frame = ((HistogramFrame) obj);
ArrayList<?> list = frame.getObjectOfClass(Histogram.class);
if(list.size()>0) { // assume the first Histogram belongs to this frame
frame.histogram = (Histogram) list.get(0);
frame.histogram.clear();
frame.dataTable.add(frame.histogram);
}
return obj;
}
}
}
/*
* 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
*/