package jas.hist; import jas.plot.TextBlock; import jas.util.DoubleWithError; import jas.util.ScientificFormat; import java.awt.Component; import java.awt.Frame; import java.awt.event.ActionEvent; import java.text.Format; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.SwingUtilities; /** * The main class used to display and format statistics. * When a user selects showStatistics from the plots popupmenu, a statistics text block * is displayed showing each displayed plots' statistics (Vector stats) and name. The statistics block * requires a number formatting method to be set (setFormat), the default method is * implemented by jas.util.ScientificFormat. */ public class StatisticsBlock extends TextBlock { public StatisticsBlock() { this(new ScientificFormat()); } public StatisticsBlock(Format g) { super("Statistics"); //set default format types initializeDefaultFormats(g); setFormat(g); } /** * Calculates and returns the total number of lines to be displayed in the statistics block, * including a draw line seperator, plot title (if available) and formatted * statistics for each data set displayed in the plot area. */ public int getNLines() { NothingToShow =false; if (stats.isEmpty()) return 1; int n = 0; for (int i=0; i<stats.size(); i++) { JASHistData data = (JASHistData) stats.elementAt(i); Statistics stat = data.getStatistics(); if (selectedentries != null ) { n += addDisplayLines(compareEntries(stat)).length; }else { n += addDisplayLines(stat.getStatisticNames()).length; } } if(n==0) { NothingToShow =true; return n=1; } return n; } /**Returns a line to be displayed in the statistics block as a String. If the line * corresponding to index j is a statisic, the stat (double) is formated by the set * formatting method and returned with the stat name to be displayed. Also returned * are Strings that generate a line Seperator ("\n") in the statistics block and the * data set title. */ public String getLine(int j) { if (stats.isEmpty() || NothingToShow) { return "No Statistics"; } int n = 0; for (int i=0; i<stats.size(); i++) { JASHistData data = (JASHistData) stats.elementAt(i); Statistics stat = data.getStatistics(); String [] lines_selectedentries = addDisplayLines(compareEntries(stat)); String[] lines_noselected = addDisplayLines(stat.getStatisticNames()); if(selectedentries!=null) { if (j-n < lines_selectedentries.length) { line = (String) lines_selectedentries[j-n]; if(line.equals("addplottitle"))return data.getLegendText(); if(line.equals("\n"))return line; String returnline; if(stat instanceof ExtendedStatistics) { Object obj = ((ExtendedStatistics)stat).getExtendedStatistic(line); if(obj == null) obj = new Double(stat.getStatistic(line)); Format extendf = (Format) formats.get(obj.getClass()); if(extendf != null)returnline = line+ "\t"+ extendf.format(obj); else returnline = line+ "\t"+ obj.toString(); }else { Double d = new Double( stat.getStatistic(line)); returnline =line +"\t"+ f.format(d); } return returnline; } n += lines_selectedentries.length; }else { if (j-n < lines_noselected.length) { line = lines_noselected[j-n]; if(line.equals("addplottitle")) return data.getLegendText(); if(line.equals("\n"))return line; String returnline; if(stat instanceof ExtendedStatistics) { Object obj = ((ExtendedStatistics)stat).getExtendedStatistic(line); if(obj == null) obj = new Double(stat.getStatistic(line));//can getStatistic be overriden to return a non double? Format extendf = (Format) formats.get(obj.getClass()); if(extendf != null)returnline = line+ "\t"+ extendf.format(obj); else returnline = line+ "\t"+ obj.toString(); }else { Double d = new Double( stat.getStatistic(line)); returnline =line +"\t"+ f.format(d); } return returnline; } n += lines_noselected.length; } } throw new IllegalArgumentException(); } /**Passed in to this method is the array of stat names to be displayed for a single * Statistics set. This method adds "\n" (indicating a line seperator), and "addplottitle" * to the beginning of the stats array. */ private String[] addDisplayLines(String[] s) { String[] addline; if(showtitles == SHOWTITLES_ALWAYS || (showtitles == SHOWTITLES_AUTOMATIC && stats.size()>1 && s.length>0)) { addline = new String[s.length+2]; addline[0] = "\n"; addline[1] = "addplottitle"; for(int i=0;i<s.length;i++) { addline[i+2]=s[i]; } return addline; }else if(s.length>0) { addline = new String[s.length+1]; addline[0] = "\n"; for(int i=0;i<s.length;i++) { addline[i+1]=s[i]; } return addline; }else { return s; } } /**Compares stats names to those selected in gui, returns 0 length array if non selected */ private String[] compareEntries(Statistics stat) { String[] compare = stat.getStatisticNames(); Vector vcompare = new Vector(); for(int i=0;i<compare.length;i++) { if(selectedentries!=null) { for(int ii=0;ii<selectedentries.length;ii++) { if(compare[i].equals(selectedentries[ii])) vcompare.addElement(selectedentries[ii]); } } } compare = new String[vcompare.size()]; vcompare.copyInto(compare); return compare; } /**Sets the statistics to be formatted and displayed in the block as a String of *stat names. If called, only the stats corresponding to these names are *formatted and displayed. This method is invoked when "Statistics Properties.." *popup is invoked (base.jas.hist.StatsWindow). */ public void setSelectedEntries(String[] s) { selectedentries = s; } /**Returns the statistics to be formatted and displayed in the block as a String of *stat names. If selectedentries != null, only the stats corresponding to *these names are formatted and displayed. */ public String[] getSelectedEntries() { return selectedentries; } /**Sets user selection from stats window of allways show all stats or show a subset selection * from check box list of stats. Used so that when user regenerates stats window the previous * setting will be displayed. Calles on ok/apply from stats window. */ void set_AllwaysAll_Subset(boolean alwaysall) { this.alwaysall = alwaysall; } /**Get previous settting from stats window of allways show all stats or show a subset selection * from check box list of stats. Used so that when user regenerates stats window the previous * setting will be displayed. */ boolean get_AllwaysAll_Subset() { return alwaysall; } /**Returns an array of stat names corresponding to every different stat name in the * Vector stats. These are the stat names listed in the popup window base.jas.util.StatsWindow */ public String[] getStatNames() { Vector vlistednames = new Vector(); listnames=null; for (int i=0; i<stats.size(); i++) { JASHistData data = (JASHistData) stats.elementAt(i); Statistics stat = data.getStatistics(); if (stat!=null) listnames = stat.getStatisticNames(); if(listnames!=null) { for (int ii=0;ii<listnames.length;ii++) { if( !(vlistednames.contains(listnames[ii])) ) { vlistednames.addElement(listnames[ii]); } } } } listnames = new String[vlistednames.size()]; vlistednames.copyInto(listnames); return listnames; } /** * Adds a Statistcs element to the Vector stats if not null */ public void add(JASHistData data) { if(data.getStatistics() != null)stats.addElement(data); } /** * Removes a Statistcs element from the Vector stats and the corresponding data set * title from the titles Vector. */ public void remove(JASHistData data) { stats.removeElement(data); } /**Clears the Vector stats and titles. No statistics are available */ public void clear() { stats.removeAllElements(); } /** * Sets the number formating object. If a statistics window is user generated the format * is set to base.jas.util.ScientificFormat and this method is invoked by * each click of the apply and ok buttons */ public void setFormat(Format g) { f = g; updateFormatsInstances(f); this.revalidate(); this.repaint(); } /**Returns the current formatting object; */ public Format getFormat() { return f; } public void putFormat(Class c,Format f) { formats.put(c,f); } private void updateFormatsInstances(Format f) { Enumeration e = formats.keys(); while(e.hasMoreElements()) { Object obj = e.nextElement(); if( formats.get(obj).getClass() == f.getClass()) { putFormat(obj.getClass(),f);//all values of same class get argumet format instance } } } private void initializeDefaultFormats(Format f) { if(f instanceof ScientificFormat) { putFormat(Double.class,f); putFormat(DoubleWithError.class,f); }else { ScientificFormat defaultsciformat = new ScientificFormat(); putFormat(Double.class,defaultsciformat); putFormat(DoubleWithError.class,defaultsciformat); } } /**When implemented, getSplitStringAlignment() should return an integer between 1 and 3 * corresponding to the chosen alignment for the second half of strings split by '\t'. * For leftalignment: return 1. For rightaignment: return 2. For noalignment: return 3. * */ public int getSplitStringAlign() { return splitstringalign; } /**When implemented, setSplitStringAlignment() should set an integer between 1 and 3 * corresponding to the chosen alignment for the second half of strings split by '\t'. * For leftalignment: return 1. For rightalignment: return 2. For noalignment: return 3. * */ public void setSplitStringAlign(int a) { if((a<4) && (a >0)) { splitstringalign=a; }else throw new IllegalArgumentException("Integer splitstringalign must be set to 1,2 or 3"); } /**Sets the (int) showtitles to one of three values:SHOWTITLES_ALWAYS, * SHOWTITLES_NEVER, SHOWTITLES_AUTOMATIC. The value controls when a plot title is * displayed in the stat block. If showtitles = SHOWTITLES_AUTOMATIC then titles will * be displayed if there is more than one plot displayed. */ public void setShowTitles(int settitles) { if((settitles<4) && (settitles >0)) { showtitles = settitles; }else throw new IllegalArgumentException("Integer showtitles must be set to 1,2 or 3"); } /**Returns the (int) showtitles which has three values:SHOWTITLES_ALWAYS, * SHOWTITLES_NEVER, SHOWTITLES_AUTOMATIC. The value controls when a plot title is * displayed in the stat block. If showtitles = SHOWTITLES_AUTOMATIC then titles will * be displayed if there is more than one plot displayed. */ public int getShowTitles() { return showtitles; } public void modifyPopupMenu(final JPopupMenu menu, final Component source) { if (menu.getComponentCount() > 0) menu.addSeparator(); statpropertiesitem = new JMenuItem(getPrefix()+" Properties...") { protected void fireActionPerformed( final ActionEvent e) { statwin = new StatsWindow(StatisticsBlock.this); final Frame frame = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, this); statwin.showStatsWindow(); } }; menu.add(statpropertiesitem); super.modifyPopupMenu(menu,source); } private boolean NothingToShow; private Format f; private Hashtable formats = new Hashtable(); private StatsWindow statwin; private Vector stats = new Vector(); private String[] selectedentries; private String[] listnames; private int showtitles = SHOWTITLES_AUTOMATIC; private int splitstringalign=RIGHTALIGNSPLIT; private String line; private JMenuItem statpropertiesitem; private boolean alwaysall=true; final public static int SHOWTITLES_ALWAYS = 1; final public static int SHOWTITLES_NEVER = 2; final public static int SHOWTITLES_AUTOMATIC = 3; final public static int LEFTALIGNSPLIT = 1; final public static int RIGHTALIGNSPLIT = 2; final public static int NOALIGNSPLIT = 3; }