/* * Copyright (C) 2012 Addition, Lda. (addition at addition dot pt) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 program. If not, see http://www.gnu.org/licenses/. */ package org.addition.epanet.ui; import org.addition.epanet.msx.ENToolkit2; import org.addition.epanet.util.ENException; import org.addition.epanet.hydraulic.HydraulicSim; import org.addition.epanet.msx.EpanetMSX; import org.addition.epanet.network.Network; import org.addition.epanet.network.PropertiesMap; import org.addition.epanet.network.io.input.InputParser; import org.addition.epanet.quality.QualitySim; import org.addition.epanet.util.Utilities; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.logging.*; /** * Configures and executes the epanet (Hydraulic/Quality) and MSX quality simulation through the UI. */ public class ReportOptions implements ActionListener { private JCheckBox hydraulicsCheckBox; private JCheckBox qualityCheckBox; private JCheckBox qualityMSXCheckBox; private JPanel root; private JPanel top; private JCheckBox showSummaryCheckBox; private JCheckBox showHydraulicSolverEventsCheckBox; private JButton runButton; private JPanel reportOptions2; private JPanel reportOptions1; private JPanel actions; private JPanel hydPanel; private JPanel qualityPanel; private JPanel qualityMSXPanel; private JComboBox reportPeriodBox; private JComboBox unitsBox; private JList speciesCheckList; private JList hydVariables; private JScrollPane hydScroll; private JScrollPane qualScroll; private JList qualityVariables; private JProgressBar progressBar; private JLabel statusLabel; private JPanel progressPanel; private JButton cancelButton; private JTextField textSimulationDuration; private JComboBox qualComboBox; private JComboBox hydComboBox; private JTextField textReportStart; private JCheckBox transposeResultsCheckBox; /** * Custom logger messages formater. */ private class HydLogFormater extends Formatter { public String format(LogRecord rec) {return formatMessage(rec)+"\n";} public String getHead(Handler h) {return "";} public String getTail(Handler h) {return "";} } Logger log; /** * This dialog reference. */ private JDialog mainFrame; /** * The XLSX report file dialog. */ private JFileChooser reportFileDialog; /** * Loaded INP network. */ private Network netINP; /** * Loaded MSX simulation. */ private EpanetMSX netMSX; /** * Epanet network config file. */ private File fileINP; /** * MSX config file. */ private File fileMSX; /** * Epanet toolkit for the MSX. */ ENToolkit2 epanetTK; /** * Hydraulic simulator. */ HydraulicSim hydSim = null; /** * Public enum to set the simulation time step duration. */ public enum TimeSteps { STEP_1_MIN(0,60,"1 minute"), STEP_2_MIN(1,120,"2 minutes"), STEP_3_MIN(2,180,"3 minutes"), STEP_4_MIN(3,240,"4 minutes"), STEP_5_MIN(4,300,"5 minutes"), STEP_10_MIN(5,600,"10 minutes"), STEP_15_MIN(6,900,"15 minutes"), STEP_30_MIN(7,1800,"30 minutes"), STEP_1_HOUR(8,3600,"1 hour"), STEP_2_HOUR(9,7200,"2 hours"), STEP_4_HOUR(10,14400,"4 hours"), STEP_6_HOURS(11,21600,"6 hours"), STEP_12_HOURS(12,43200,"12 hours"); /** * Entry sequencial ID */ public final int id; /** * Entry name */ public final String name; /** * Entry timestep duration. */ public final int time; private TimeSteps(int id,int time, String name) { this.id = id; this.name = name; this.time = time; } /** * Get available timestep periods. * @return Array of timesteps names to the UI. */ public static String [] getPeriodsText(){ String [] vec = new String[values().length]; for(TimeSteps step : values()) vec[step.id] = step.name; return vec; } /** * Get the nearest timestep period. * @param time * @return Nearest timestep, if the time is bigger than any timestep returns STEP_12_HOURS. */ public static TimeSteps getNearestStep(long time){ for(TimeSteps step : values()){ if(step.time>=time) return step; } return STEP_12_HOURS; } } /** * Report options dialog constructor. * @param inpFile * @param msxFile */ public ReportOptions(File inpFile,File msxFile, Logger log) { this.log = log; if(inpFile!=null){ fileINP = inpFile; netINP = new Network(); //Logger log = Logger.getAnonymousLogger();//Logger.getLogger(this.getClass().toString()); //log.setUseParentHandlers(false); //log.setLevel(Level.ALL); //LoggerFileHandler fh = null; try { //fh = new LoggerFileHandler(new File(logFile), false); //fh.setFormatter(new SimpleFormatter()); //fh.setLevel(Level.ALL); Network.FileType netType = Network.FileType.INP_FILE; int lastDot = inpFile.getName().lastIndexOf("."); if(lastDot>0 && lastDot+1 < inpFile.getName().length()){ String extension = inpFile.getName().substring(lastDot+1).toLowerCase(); if(extension.equals("xlsx")) netType = Network.FileType.EXCEL_FILE; else if(extension.equals("inp")) netType = Network.FileType.INP_FILE; } InputParser inpParser = InputParser.create(netType,log); inpParser.parse(netINP,inpFile); } catch (ENException en_ex){ JOptionPane.showMessageDialog(root, Utilities.getError(Integer.toString(en_ex.getCodeID())) + "\nCheck epanet.log for detailed error description", "Error", JOptionPane.OK_OPTION); inpFile = null; return; } //catch (IOException e) { // JOptionPane.showMessageDialog(root, "IO error while reading the INP file", "Error", JOptionPane.OK_OPTION); // inpFile = null; // return; //} if(msxFile!=null){ fileMSX = msxFile; epanetTK = new ENToolkit2(netINP); netMSX = new EpanetMSX(epanetTK); try { int ret = netMSX.load(fileMSX); if(ret !=0){ JOptionPane.showMessageDialog(root, "MSX parsing error " + ret, "Error", JOptionPane.OK_OPTION); fileMSX = null; netMSX = null; epanetTK = null; return; } } catch (IOException e) { JOptionPane.showMessageDialog(root, "IO error while reading the MSX file", "Error", JOptionPane.OK_OPTION); fileMSX = null; netMSX = null; epanetTK = null; return; } } } reportFileDialog = new JFileChooser(); } /** * Create and show the window. * @param owner */ public void showWindow(JFrame owner, boolean reset){ if(reset){ // Adjust widgets before showing the window. if(netINP!=null){ try { PropertiesMap pMap = netINP.getPropertiesMap(); if(pMap.getUnitsflag()== PropertiesMap.UnitsType.SI) unitsBox.setSelectedIndex(0); else unitsBox.setSelectedIndex(1); reportPeriodBox.setSelectedIndex(TimeSteps.getNearestStep(pMap.getRstep()).id); hydComboBox.setSelectedIndex(TimeSteps.getNearestStep(pMap.getHstep()).id); qualComboBox.setSelectedIndex(TimeSteps.getNearestStep(pMap.getQstep()).id); textSimulationDuration.setText(Utilities.getClockTime(pMap.getDuration())); textReportStart.setText(Utilities.getClockTime(pMap.getRstart())); if(netINP.getPropertiesMap().getQualflag() != PropertiesMap.QualType.NONE) qualityCheckBox.setEnabled(true); else qualityCheckBox.setEnabled(false); } catch (ENException e) { e.printStackTrace(); } } if(netMSX !=null && netMSX.getSpeciesNames().length>0 ){ String [] speciesNames = netMSX.getSpeciesNames(); speciesCheckList.setListData(createData(speciesNames)); speciesCheckList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); speciesCheckList.setCellRenderer(new CheckListRenderer()); speciesCheckList.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if(!speciesCheckList.isEnabled()) return; int index = speciesCheckList.locationToIndex(e.getPoint()); CheckableItem item = (CheckableItem)speciesCheckList.getModel().getElementAt(index); item.setSelected(! item.isSelected()); Rectangle rect = speciesCheckList.getCellBounds(index, index); speciesCheckList.repaint(rect); } }); } else qualityMSXCheckBox.setEnabled(false); mainFrame = new JDialog(owner,true); mainFrame.add(root); mainFrame.setTitle("Reporting options"); mainFrame.setResizable(false); mainFrame.pack(); mainFrame.setLocationRelativeTo(null); mainFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); hydraulicsCheckBox.addActionListener(this); qualityMSXCheckBox.addActionListener(this); runButton.addActionListener(this); qualityCheckBox.addActionListener(this); cancelButton.addActionListener(this); reportPeriodBox.addActionListener(this); hydComboBox.addActionListener(this); textSimulationDuration.addActionListener(this); textReportStart.addActionListener(this); mainFrame.addWindowListener(new WindowListener() { public void windowOpened(WindowEvent e){} public void windowClosing(WindowEvent e) { if(hydSim!=null){ try { hydSim.stopRunning(); } catch (InterruptedException e1) { e1.printStackTrace(); } } if(netMSX!=null){ try { netMSX.stopRunning(); } catch (InterruptedException e1) { e1.printStackTrace(); } } } public void windowClosed(WindowEvent e){} public void windowIconified(WindowEvent e){} public void windowDeiconified(WindowEvent e){} public void windowActivated(WindowEvent e){} public void windowDeactivated(WindowEvent e){} }); } mainFrame.setVisible(true); progressPanel.setVisible(false); actions.setVisible(true); unlockInterface(); } /** * Custom components creation. */ private void createUIComponents() { String[] unitsString = { "SI", "US"}; unitsBox = new JComboBox(unitsString); reportPeriodBox = new JComboBox(TimeSteps.getPeriodsText()); hydComboBox = new JComboBox(TimeSteps.getPeriodsText()); qualComboBox = new JComboBox(TimeSteps.getPeriodsText()); speciesCheckList = new JList(); hydVariables = new JList(createData(ReportGenerator.HydVariable.getNames())); hydVariables.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); hydVariables.setCellRenderer(new CheckListRenderer()); for(int i = 0;i< ReportGenerator.HydVariable.values().length;i++) ((CheckableItem)hydVariables.getModel().getElementAt(i)).setSelected(true); hydVariables.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if(!hydVariables.isEnabled()) return; int index = hydVariables.locationToIndex(e.getPoint()); CheckableItem item = (CheckableItem)hydVariables.getModel().getElementAt(index); item.setSelected(! item.isSelected()); Rectangle rect = hydVariables.getCellBounds(index, index); hydVariables.repaint(rect); } }); qualityVariables = new JList(createData(ReportGenerator.QualVariable.getNames())); qualityVariables.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); qualityVariables.setCellRenderer(new CheckListRenderer()); for(int i = 0;i<ReportGenerator.QualVariable.values().length;i++) ((CheckableItem)qualityVariables.getModel().getElementAt(i)).setSelected(true); qualityVariables.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if(!qualityVariables.isEnabled()) return; int index = qualityVariables.locationToIndex(e.getPoint()); CheckableItem item = (CheckableItem)qualityVariables.getModel().getElementAt(index); item.setSelected(! item.isSelected()); Rectangle rect = qualityVariables.getCellBounds(index, index); qualityVariables.repaint(rect); } }); } /** * Handle ui components events. * @param e */ public void actionPerformed(ActionEvent e) { if(e.getSource().equals(hydraulicsCheckBox)){ if(hydraulicsCheckBox.isSelected()){ hydVariables.setEnabled(true); } else{ hydVariables.setEnabled(false); } } else if(e.getSource().equals(qualityCheckBox)){ if(qualityCheckBox.isSelected()){ qualityVariables.setEnabled(true); } else{ qualityVariables.setEnabled(false); } } else if(e.getSource().equals(qualityMSXCheckBox)){ if(qualityMSXCheckBox.isSelected()){ speciesCheckList.setEnabled(true); } else speciesCheckList.setEnabled(false); } else if(e.getSource().equals(cancelButton)){ mainFrame.setVisible(false); } else if(e.getSource().equals(hydComboBox)){ if(reportPeriodBox.getSelectedIndex()< hydComboBox.getSelectedIndex() ) reportPeriodBox.setSelectedIndex(hydComboBox.getSelectedIndex()); } else if(e.getSource().equals(reportPeriodBox)){ if(reportPeriodBox.getSelectedIndex()< hydComboBox.getSelectedIndex() ) reportPeriodBox.setSelectedIndex(hydComboBox.getSelectedIndex()); } else if(e.getSource().equals(textReportStart)){ double val = Utilities.getHour(textReportStart.getText(), "") ; System.out.println(val); } else if(e.getSource().equals(textSimulationDuration)){ double val = Utilities.getHour(textSimulationDuration.getText(), "") ; System.out.println(val); } else if(e.getSource().equals(runButton)) { double tmpValue; if( (tmpValue=Utilities.getHour(textSimulationDuration.getText(),"") ) < 0){ JOptionPane.showMessageDialog(mainFrame, "Invalid time expression for simulation duration", "Error", JOptionPane.ERROR_MESSAGE); return; } if( (tmpValue=Utilities.getHour(textReportStart.getText(),"") ) < 0){ JOptionPane.showMessageDialog(mainFrame, "Invalid time expression for report start time", "Error", JOptionPane.ERROR_MESSAGE); return; } // actions.setVisible(false); bug in windows java 7(? general contract) Thread repThread = new Thread() { @Override public void run() { StreamHandler simHandler = null; try{ // File save dialog FileDialog fdialog = new FileDialog(mainFrame,"Save xlsx file",FileDialog.SAVE); fdialog.setFilenameFilter(new XLSXFilterAWT()); String fileTitle = fileINP.getName(); if(fileTitle.lastIndexOf(".")!=-1) fileTitle = fileTitle.substring(0,fileTitle.lastIndexOf(".")); fdialog.setFile("report_"+fileTitle); fdialog.setVisible(true); File xlsxFile = null; if(fdialog.getFile()==null){ mainFrame.setVisible(false); return; } else xlsxFile = new File(fdialog.getDirectory()+fdialog.getFile()+".xlsx"); lockInterface(); progressPanel.setVisible(true); progressBar.setValue(0); progressBar.setMaximum(100); progressBar.setMinimum(0); long reportPeriod = (long)TimeSteps.values()[reportPeriodBox.getSelectedIndex()].time; long reportStartTime = (long)(Utilities.getHour(textReportStart.getText(),"")*3600); long hydTStep = TimeSteps.values()[hydComboBox.getSelectedIndex()].time; long qualTStep = TimeSteps.values()[qualComboBox.getSelectedIndex()].time; long durationTime = (long)(Utilities.getHour(textSimulationDuration.getText(),"")*3600); final PropertiesMap pMap = netINP.getPropertiesMap(); if(showHydraulicSolverEventsCheckBox.isSelected()){ try { simHandler = new StreamHandler(new FileOutputStream(fdialog.getDirectory() + "hydEvents.log"), new SimpleFormatter()){ @Override public boolean isLoggable(LogRecord record) { return record.getLevel()==Level.WARNING; } }; } catch (FileNotFoundException e1) { e1.printStackTrace(); } simHandler.setFormatter(new HydLogFormater()); log.addHandler(simHandler); } statusLabel.setText("Simulating hydraulics"); try { pMap.setRstart(reportStartTime); pMap.setRstep(reportPeriod); pMap.setHstep(hydTStep); pMap.setDuration(durationTime); hydSim = new HydraulicSim(netINP,log); creatSPThread(10, 30, new SPInterface() { @Override public long getTime() { return hydSim.getHtime(); } public double getValue() { try { return (float) getTime() / (float) pMap.getDuration(); } catch (ENException e1) { return 0; } } }); hydSim.simulate(new File("hydFile.bin")); } catch (ENException e1) { if(e1.getCodeID()==1000) throw new InterruptedException(); JOptionPane.showMessageDialog(root, Utilities.getError(Integer.toString(e1.getCodeID())) + "\nCheck epanet.log for detailed error description", "Error", JOptionPane.OK_OPTION); return; } if(fileMSX!=null && qualityMSXCheckBox.isSelected()){ try { Thread.sleep(100); } catch (InterruptedException e1) { e1.printStackTrace(); } statusLabel.setText("Simulating MSX"); try { // reload MSX netMSX = new EpanetMSX(epanetTK); netMSX.load(fileMSX); netMSX.getNetwork().setRstep(reportPeriod); netMSX.getNetwork().setQstep(qualTStep); netMSX.getNetwork().setRstart(reportStartTime); netMSX.getNetwork().setDur(durationTime); epanetTK.open(new File("hydFile.bin")); creatSPThread(30,50, new SPInterface() { @Override public long getTime() { return netMSX.getQTime(); } public double getValue() { try { return (float)netMSX.getQTime()/(float)pMap.getDuration(); } catch (ENException e1) { return 0; } } }); netMSX.run(new File("msxFile.bin")); epanetTK.close(); } catch (IOException e1) { } catch (ENException e1) { throw new InterruptedException(); } //netMSX.getReport().MSXrpt_write(new File("msxFile.bin")); } if(qualityCheckBox.isSelected()) { try { final QualitySim qSim = new QualitySim(netINP,log); statusLabel.setText("Simulating Quality"); creatSPThread(30,50, new SPInterface() { @Override public long getTime() { return qSim.getQtime(); } public double getValue() { try { return (float)qSim.getQtime()/(float)pMap.getDuration(); } catch (ENException e1) { return 0; } } }); qSim.simulate(new File("hydFile.bin"),new File("qualFile.bin")); } catch (ENException e1) { JOptionPane.showMessageDialog(root, Utilities.getError(Integer.toString(e1.getCodeID())) + "\nCheck epanet.log for detailed error description", "Error", JOptionPane.OK_OPTION); } catch (IOException e1) { e1.printStackTrace(); } } progressBar.setValue(50); haltSPPeekThread(); statusLabel.setText("Writting XLSX"); final ReportGenerator gen = new ReportGenerator(xlsxFile); //log try { log.fine("Starting xlsx write"); if(showSummaryCheckBox.isSelected()) gen.writeSummary(fileINP, netINP, fileMSX,netMSX); if(transposeResultsCheckBox.isSelected()) gen.setTransposedMode(true); // Write hydraulic spreadsheets boolean [] values = new boolean[ReportGenerator.HydVariable.values().length]; for(int i = 0;i< ReportGenerator.HydVariable.values().length;i++) values[i] = ((CheckableItem)hydVariables.getModel().getElementAt(i)).isSelected(); statusLabel.setText("Writing hydraulic report"); haltSPPeekThread(); creatSPThread(50,60, new SPInterface() { @Override public long getTime() { return gen.getRtime(); } public double getValue() { try { return (float)(gen.getRtime()-pMap.getRstart())/(float)pMap.getDuration(); } catch (ENException e1) { return 0; } } }); gen.createHydReport(new File("hydFile.bin"),netINP,values); if(qualityCheckBox.isSelected()){ statusLabel.setText("Writing quality report"); haltSPPeekThread(); creatSPThread(60,70, new SPInterface() { @Override public long getTime() { return gen.getRtime(); } public double getValue() { try { return (float)(gen.getRtime()-pMap.getRstart())/(float)pMap.getDuration(); } catch (ENException e1) { return 0; } } }); boolean nodes = ((CheckableItem)qualityVariables.getModel().getElementAt(0)).isSelected(); boolean links = ((CheckableItem)qualityVariables.getModel().getElementAt(1)).isSelected(); gen.createQualReport(new File("qualFile.bin"), netINP, nodes, links); } // Write MSX quality spreadsheets if(fileMSX!=null && qualityMSXCheckBox.isSelected()){ boolean [] valuesMSX = new boolean[speciesCheckList.getModel().getSize()]; for(int i = 0;i<speciesCheckList.getModel().getSize();i++) valuesMSX[i] = ((CheckableItem)speciesCheckList.getModel().getElementAt(i)).isSelected(); gen.createMSXReport(new File("msxFile.bin"), netINP, netMSX, epanetTK,valuesMSX); } statusLabel.setText("Writing workbook"); gen.writeWorksheet(); log.fine("Ending xlsx write"); } catch (IOException e1) { e1.printStackTrace(); } catch (ENException e1) { e1.printStackTrace(); } } catch (InterruptedException e){ System.out.println("Simulation aborted !"); //JOptionPane.showMessageDialog(root, "Simulation aborted !", "Error", JOptionPane.OK_OPTION); } if(simHandler!=null) log.removeHandler(simHandler); haltSPPeekThread(); progressPanel.setVisible(false); mainFrame.setVisible(false); unlockInterface(); } }; repThread.start(); } } /** * Lock the interface during the simulation. */ private void lockInterface(){ hydraulicsCheckBox.setEnabled(false); qualityCheckBox.setEnabled(false); qualityMSXCheckBox.setEnabled(false); hydVariables.setEnabled(false); qualityVariables.setEnabled(false); speciesCheckList.setEnabled(false); showSummaryCheckBox.setEnabled(false); showHydraulicSolverEventsCheckBox.setEnabled(false); reportPeriodBox.setEnabled(false); unitsBox.setEnabled(false); hydComboBox.setEnabled(false); textSimulationDuration.setEnabled(false); qualComboBox.setEnabled(false); textReportStart.setEnabled(false); transposeResultsCheckBox.setEnabled(false); } /** * Unlock the interface during the simulation. */ private void unlockInterface(){ hydraulicsCheckBox.setEnabled(true); transposeResultsCheckBox.setEnabled(true); if(netMSX!=null && netMSX.getSpeciesNames().length>0){ qualityMSXCheckBox.setEnabled(true); if(qualityMSXCheckBox.isSelected()) speciesCheckList.setEnabled(true); } hydVariables.setEnabled(true); try { if(netINP.getPropertiesMap().getQualflag()!=PropertiesMap.QualType.NONE){ if(qualityCheckBox.isSelected()){ qualityVariables.setEnabled(true); qualityCheckBox.setEnabled(true); } } } catch (ENException e) { e.printStackTrace(); } showSummaryCheckBox.setEnabled(true); showHydraulicSolverEventsCheckBox.setEnabled(true); reportPeriodBox.setEnabled(true); unitsBox.setEnabled(true); hydComboBox.setEnabled(true); textSimulationDuration.setEnabled(true); qualComboBox.setEnabled(true); textReportStart.setEnabled(true); } private void haltSPPeekThread(){ SPThreadState = false; try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } /** * Simple state variable to help terminate the progress peek thread. */ private transient boolean SPThreadState = false; /** * Simple abstract class used to peek the simulation progress into the progress bar. */ private abstract class SPInterface{ public abstract double getValue(); public long getTime(){return 0;}; } /** * This method with the SPInterface class peeks the progress of the simulation. * @param start Progress bar start value * @param end Progress bar end value * @param var New instance of a child class of SPInterface to peek the progress. */ private Thread creatSPThread(final int start,final int end, final SPInterface var){ SPThreadState = true; final Thread repThread = new Thread() { @Override public void run() { String initName = statusLabel.getText(); while(true){ if(var.getTime()!=0) statusLabel.setText(initName+ " (" + Utilities.getClockTime(var.getTime()) + ")"); progressBar.setValue((int)(start*(1.0f-var.getValue()) + end*var.getValue())); if(var.getValue()>0.9) return; if(!SPThreadState) return; } } }; repThread.start(); return repThread; } /** * List checkbox item. */ private class CheckableItem { private String str; private boolean isSelected; public CheckableItem(String str) { this.str = str; isSelected = true; } public void setSelected(boolean b) { isSelected = b; } public boolean isSelected() { return isSelected; } public String toString() { return str; } } /** * Checkbox list renderer. */ private class CheckListRenderer extends JCheckBox implements ListCellRenderer { public CheckListRenderer() { setBackground(UIManager.getColor("List.textBackground")); setForeground(UIManager.getColor("List.textForeground")); } public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) { setEnabled(list.isEnabled()); setSelected(((CheckableItem)value).isSelected()); setFont(list.getFont()); setText(value.toString()); return this; } } /** * Create checkbox entries from string array. * @param strs Entries strings. * @return CheckableItem array. */ private CheckableItem[] createData(String[] strs) { int n = strs.length; CheckableItem[] items = new CheckableItem[n]; for (int i=0;i<n;i++) { items[i] = new CheckableItem(strs[i]); } return items; } /** * XLSX File filter for the file dialog. */ private class XLSXFilterAWT implements FilenameFilter { public boolean accept(File dir, String name) { String[] name_extension = name.split("[.]"); if (name_extension.length >= 2) { if (name_extension[name_extension.length - 1].equals("xlsx")) return true; } return false; } } }