/* * BatchDlg.java * (FScape) * * Copyright (c) 2001-2016 Hanns Holger Rutz. All rights reserved. * * This software is published under the GNU General Public License v3+ * * * For further information, please contact Hanns Holger Rutz at * contact@sciss.de */ package de.sciss.fscape.gui; import de.sciss.fscape.Application; import de.sciss.fscape.proc.ProcessorEvent; import de.sciss.fscape.proc.ProcessorListener; import de.sciss.fscape.prop.Presets; import de.sciss.fscape.prop.PropertyArray; import de.sciss.fscape.session.ModulePanel; import de.sciss.fscape.session.Session; import de.sciss.fscape.util.Util; import de.sciss.gui.GUIUtil; import de.sciss.util.Flag; import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellEditor; import javax.swing.table.TableColumn; import javax.swing.text.DefaultFormatter; import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.List; import java.util.Properties; /** * Module for batch processing * a list of other modules. */ public class BatchDlg extends ModulePanel { // -------- private variables -------- // Properties (defaults) private static final int PR_BATCH = 0; // pr.text // private static final int PR_OUTPUTTYPE = 0; // pr.intg // private static final int PR_GAIN = 0; // pr.para private static final int PR_VISIBLE = 0; // pr.bool private static final int PR_CONSOLE = 1; private static final String PRN_BATCH = "Batch"; private static final String PRN_VISIBLE = "Visible"; private static final String PRN_CONSOLE = "Console"; private static final String prText[] = { "" }; private static final String prTextName[] = { PRN_BATCH }; // private static final int prIntg[] = { 0, 0, GAIN_UNITY }; // private static final String prIntgName[] = { PRN_OUTPUTTYPE, PRN_OUTPUTRES, PRN_GAINTYPE }; // private static final Param prPara[] = { null }; // private static final String prParaName[] = { PRN_GAIN }; private static final boolean prBool[] = { false, false }; private static final String prBoolName[] = { PRN_VISIBLE, PRN_CONSOLE }; private static final int GG_BATCH = GG_OFF_OTHER + 0; private static final int GG_CMDCUT = GG_OFF_OTHER + 1; private static final int GG_CMDCOPY = GG_OFF_OTHER + 2; private static final int GG_CMDPASTE = GG_OFF_OTHER + 3; private static final int GG_CMDOPEN = GG_OFF_OTHER + 4; private static final int GG_CMDADD = GG_OFF_OTHER + 5; // private static final int GG_CMDS = GG_OFF_OTHER + 8; // private static final int GG_ERROR = GG_OFF_OTHER + 9; // private static final int GG_ERRSKIP = GG_OFF_OTHER + 10; private static final int GG_PARAMS = GG_OFF_OTHER + 11; // private static final int GG_ENTRYPARAM = GG_OFF_OTHER + 12; // private static final int GG_FILE = GG_OFF_OTHER + 13; private static final int GG_BATCHPANE = GG_OFF_OTHER + 14; private static final int GG_PARAMSPANE = GG_OFF_OTHER + 15; private static final int GG_VISIBLE = GG_OFF_CHECKBOX + PR_VISIBLE; private static final int GG_CONSOLE = GG_OFF_CHECKBOX + PR_CONSOLE; private static PropertyArray static_pr = null; private static Presets static_presets = null; private static final String ERR_DELETE = "File was not deleted"; protected static final String[] EXCLUDE_DLG = { "MainFrame", "PrefsDlg", "ParamSettingsDlg", "FileInfoDlg" }; // Gaga, Batch Table REDO protected BatchTableModel batchTM; protected ParamTableModel paramTM; private BatchCellRenderer batchCR; protected JTable batchTable; private JTable paramTable; protected List<BatchObject> batchVector; // private Vector paramVector; private TableModelListener tml; protected ClipboardOwner cbo; private ProcessorListener procL; // -------- public methods -------- public BatchDlg() { super("Batch Processor"); init2(); } protected void buildGUI() { if( static_pr == null ) { static_pr = new PropertyArray(); static_pr.text = prText; static_pr.textName = prTextName; // static_pr.intg = prIntg; // static_pr.intgName = prIntgName; static_pr.bool = prBool; static_pr.boolName = prBoolName; // static_pr.para = prPara; // static_pr.para[ PR_GAIN ] = new Param( 0.0, Param.DECIBEL_AMP ); // static_pr.paraName = prParaName; // static_pr.superPr = DocumentFrame.static_pr; } // default preset if( static_presets == null ) { static_presets = new Presets( getClass(), static_pr.toProperties( true )); } presets = static_presets; pr = (PropertyArray) static_pr.clone(); // -------- other init -------- batchVector = new ArrayList<BatchObject>(); // paramVector = new Vector(); new BatchObjectArray(); // need to initialize DataFlavor (getClass() doesn't work in static initializer ??) // -------- build GUI -------- GridBagConstraints con; JButton ggCmd; JCheckBox ggVisible, ggConsole; JScrollPane ggBatchPane, ggParamPane; gui = new GUISupport(); con = gui.getGridBagConstraints(); con.insets = new Insets( 1, 2, 1, 2 ); final BatchDlg enc_this = this; cbo = new ClipboardOwner() { public void lostOwnership( Clipboard clipboard, Transferable contents ) { // XXX } }; procL = new ProcessorListener() { public void processorStarted( ProcessorEvent e ) { teleAction(); } public void processorStopped( ProcessorEvent e ) { teleAction(); } public void processorPaused( ProcessorEvent e ) { teleAction(); } public void processorResumed( ProcessorEvent e ) { teleAction(); } public void processorProgress( ProcessorEvent e ) { teleAction(); } private void teleAction() { synchronized( enc_this ) { enc_this.notify(); } } }; ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent e) { int ID = gui.getItemID( e ); int i, j, k; int[] rows; BatchObject[] dup; Transferable t; BatchObject bObj; switch( ID ) { case GG_CMDOPEN: if( batchTable.getSelectedRowCount() != 1 ) break; bObj = batchVector.get( batchTable.getSelectedRow() ); if( bObj.command != BatchObject.CMD_MODULE ) break; ModulePanel procWin; try { procWin = getProcInstance( bObj, null ); procWin.fillGUI(); procWin.setVisible( true ); } catch( Exception e1 ) { GUIUtil.displayError( getComponent(), e1, getTitle() ); } break; case GG_CMDADD: i = batchTable.getSelectedRow() + 1; i = i == 0 ? batchVector.size() : i; batchTable.clearSelection(); batchVector.add( i, new BatchObject() ); batchTM.fireTableRowsInserted( i, i ); batchTable.setRowSelectionInterval( i, i ); break; case GG_CMDCUT: case GG_CMDCOPY: rows = batchTable.getSelectedRows(); if( rows.length > 0 ) { dup = new BatchObject[ rows.length ]; for( i = 0; i < rows.length; i++ ) { dup[i] = new BatchObject(batchVector.get( rows[i] )); } Application.clipboard.setContents( new BatchObjectArray(dup), cbo); if( ID == GG_CMDCUT ) { for( boolean finished = false; !finished; ) { for( i = 0, j = -1, k = -1; i < rows.length; i++ ) { if( rows[i] > j ) { j = rows[i]; k = i; } } if( j >= 0 ) { batchVector.remove( j ); rows[k] = -1; batchTM.fireTableRowsDeleted( j, j ); } else { finished = true; } } } } break; case GG_CMDPASTE: // System.err.println( "Pastie" ); i = batchTable.getSelectedRow() + 1; i = i == 0 ? batchVector.size() : i; try { t = Application.clipboard.getContents(enc_this); if( t != null ) { if( t.isDataFlavorSupported( BatchObjectArray.flavor )) { dup = (BatchObject[]) t.getTransferData( BatchObjectArray.flavor ); if( dup.length > 0 ) { batchTable.clearSelection(); for( j = 0, k = i; j < dup.length; j++, k++ ) { batchVector.add( k, dup[j] ); } batchTM.fireTableRowsInserted( i, k - 1 ); batchTable.setRowSelectionInterval( i, k - 1 ); } } } } catch( IllegalStateException e97 ) { /* ignored */} catch( IOException e98 ) { /* ignored */} catch( UnsupportedFlavorException e99 ) { /* ignored */} break; } } }; tml = new TableModelListener() { public void tableChanged( TableModelEvent e ) { int i, k; BatchObject bObj; if( e.getSource() == batchTM ) { if( e.getType() == TableModelEvent.DELETE ) return; k = e.getFirstRow(); if( k >= 0 && !batchVector.isEmpty() ) { bObj = batchVector.get( k ); if( (bObj.command == BatchObject.CMD_MODULE) && (bObj.modObj.modClass == null) ) { // Iterator winIter = MainMenu.getWindows(); // Object[] modules = Util.iterToArray( winIter ); final Application.DocumentHandler dh = Application.documentHandler; //final Object[] modules = new Object[ dh.getDocumentCount() ]; final Session[] docs = dh.getDocuments(); final ModulePanel[] modules = new ModulePanel[ docs.length]; for( int m = 0; m < modules.length; m++ ) { modules[ m ] = docs[m].getFrame(); } String[] winNames; ListDlg dlg; PropertyArray pa; String str; int winNum = modules.length; List<Integer> v; for( i = 0; i < winNum; i++ ) { str = modules[ i ].getClass().getName(); str = str.substring( str.lastIndexOf( '.' ) + 1 ); if( (modules[ i ] == enc_this) || Util.isValueInArray( str, EXCLUDE_DLG )) { // exclude ourself winNum--; for( int j = i; j < winNum; j++ ) { modules[ j ] = modules[ j + 1 ]; } i--; } } winNames = new String[ winNum ]; for( i = 0; i < winNum; i++ ) { // winNames[ i ] = ((Frame) modules[ i ]).getTitle(); winNames[ i ] = modules[ i ].getModuleName(); // .getTitle(); } if( winNum > 1 ) { // only prompt if there's a real choice ;) dlg = new ListDlg( getComponent(), "Choose Module", winNames ); i = dlg.getList(); } else { i = winNum - 1; } if( i < 0 ) return; // cancel bObj.modObj.name = winNames[ i ]; modules[ i ].fillPropertyArray(); pa = modules[ i ].getPropertyArray(); bObj.modObj.prParam = pa.toProperties( true ); bObj.modObj.modClass = modules[ i ].getClass().getName(); v = new ArrayList<Integer>(); for( int j = 0; j < pa.text.length; j++ ) { if(pa.textName[j].contains("File")) { v.add( new Integer(j) ); } } bObj.modObj.modParam = new String[ v.size() ][ 2 ]; for( int j = 0; j < v.size(); j++ ) { bObj.modObj.modParam[j][0] = pa.textName[ j ]; bObj.modObj.modParam[j][1] = pa.text[ j ]; } batchTM.fireTableRowsUpdated( k, k ); updateParamTable(); } } } else if( e.getSource() == paramTM ) { // ignore } } }; // -------- Command-Gadgets -------- con.fill = GridBagConstraints.BOTH; con.gridwidth = GridBagConstraints.REMAINDER; gui.addLabel( new GroupLabel( "Batch List", GroupLabel.ORIENT_HORIZONTAL, GroupLabel.BRACE_NONE )); con.gridwidth = GridBagConstraints.REMAINDER; con.weightx = 1.0; con.weighty = 1.0; initBatchTable(); gui.registerGadget( batchTable, GG_BATCH ); ggBatchPane = new JScrollPane( batchTable ); gui.addGadget( ggBatchPane, GG_BATCHPANE ); con.fill = GridBagConstraints.HORIZONTAL; con.gridwidth = 1; con.weightx = 0.05; con.weighty = 0.0; final JPanel tb = new JPanel(new FlowLayout()); ggCmd = new JButton( " Add " ); gui.registerGadget( ggCmd, GG_CMDADD ); tb.add( ggCmd ); ggCmd.addActionListener( al ); ggCmd = new JButton( " Cut " ); gui.registerGadget( ggCmd, GG_CMDCUT ); tb.add( ggCmd ); ggCmd.addActionListener( al ); ggCmd = new JButton( " Copy " ); gui.registerGadget( ggCmd, GG_CMDCOPY ); tb.add( ggCmd ); ggCmd.addActionListener( al ); ggCmd = new JButton( " Paste " ); gui.registerGadget( ggCmd, GG_CMDPASTE ); tb.add( ggCmd ); ggCmd.addActionListener( al ); ggCmd = new JButton( " Open " ); //ggCmd.setEnabled( false ); gui.registerGadget( ggCmd, GG_CMDOPEN ); tb.add( ggCmd ); ggCmd.addActionListener( al ); con.gridwidth = GridBagConstraints.REMAINDER; gui.addGadget( tb, GG_OFF_OTHER + 666 ); // -------- Entry-Settings -------- con.fill = GridBagConstraints.BOTH; con.gridwidth = GridBagConstraints.REMAINDER; gui.addLabel( new GroupLabel( "Module Parameter Settings", GroupLabel.ORIENT_HORIZONTAL, GroupLabel.BRACE_NONE )); con.gridwidth = GridBagConstraints.REMAINDER; con.weightx = 1.0; con.weighty = 0.3; initParamTable(); gui.registerGadget( paramTable, GG_PARAMS ); ggParamPane = new JScrollPane( paramTable ); gui.addGadget( ggParamPane, GG_PARAMSPANE ); con.weighty = 0.0; // -------- Control-Settings -------- con.fill = GridBagConstraints.BOTH; con.gridwidth = GridBagConstraints.REMAINDER; gui.addLabel( new GroupLabel( "Control Settings", GroupLabel.ORIENT_HORIZONTAL, GroupLabel.BRACE_NONE )); con.fill = GridBagConstraints.HORIZONTAL; con.gridwidth = 1; ggVisible = new JCheckBox( "Visible modules" ); gui.addCheckbox( ggVisible, GG_VISIBLE, null ); con.gridwidth = GridBagConstraints.REMAINDER; ggConsole = new JCheckBox( "Console output" ); gui.addCheckbox( ggConsole, GG_CONSOLE, null ); // XXX setPreferredSize( new Dimension( 500, 600 )); initGUI( this, FLAGS_PRESETS | FLAGS_PROGBAR | FLAGS_PROGBARASYNC, gui ); } /** * Transfer values from prop-array to GUI */ public void fillGUI() { int i, num; BatchObject bObj; Properties p; super.fillGUI(); super.fillGUI( gui ); p = Presets.valueToProperties(getPropertyArray().text[PR_BATCH]); num = p == null ? 0 : p.size(); batchVector.clear(); for (i = 0; i < num; i++) { bObj = BatchObject.valueOf((String) p.get(String.valueOf(i))); batchVector.add(bObj); } batchTM.fireTableDataChanged(); } /** * Transfer values from GUI to prop-array */ public void fillPropertyArray() { Properties p = new Properties(); int num = batchVector.size(); super.fillPropertyArray(); super.fillPropertyArray( gui ); for( int i = 0; i < num; i++ ) { p.put( String.valueOf( i ), batchVector.get( i ).toString() ); } getPropertyArray().text[ PR_BATCH ] = Presets.propertiesToValue( p ); } private void initBatchTable() { TableColumn column; BatchCellEditor batchCE; int i; batchTM = new BatchTableModel(batchVector); batchTable = new JTable(batchTM); batchCR = new BatchCellRenderer(); // int[] prefWidth = { 16, 64, 256, 48, 48 }; int[] prefWidth = {60, 112, 256, 96, 118}; for (i = 0; i < prefWidth.length; i++) { column = batchTable.getColumnModel().getColumn(i); column.setPreferredWidth(prefWidth[i]); column.setCellRenderer(batchCR); } batchTable.getTableHeader().setReorderingAllowed(false); JComboBox cmdCombo = new JComboBox(); for (i = 0; i < BatchCellRenderer.CMD_NAMES.length; i++) { cmdCombo.addItem(BatchCellRenderer.CMD_NAMES[i]); } JComboBox errCombo = new JComboBox(); for (i = 0; i < BatchCellRenderer.ERR_NAMES.length; i++) { errCombo.addItem(BatchCellRenderer.ERR_NAMES[i]); } batchCE = new BatchCellEditor(); batchTable.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(cmdCombo)); batchTable.getColumnModel().getColumn(2).setCellEditor(batchCE); batchTable.getColumnModel().getColumn(3).setCellEditor(new DefaultCellEditor(errCombo)); batchTable.getColumnModel().getColumn(4).setCellEditor(batchCE); batchTable.setShowHorizontalLines(true); batchTable.setShowVerticalLines(true); batchTable.setIntercellSpacing(new Dimension(1, 1)); // batchTable.setGridColor(Color.lightGray); batchTM.addTableModelListener( tml ); batchTable.getSelectionModel().addListSelectionListener( new ListSelectionListener() { public void valueChanged( ListSelectionEvent e ) { updateParamTable(); } }); } protected void initParamTable() { TableColumn column; int i; BasicCellRenderer bcr = new BasicCellRenderer(); paramTM = new ParamTableModel(); paramTM.addTableModelListener(tml); paramTable = new JTable(paramTM); paramTable.getTableHeader().setReorderingAllowed(false); int[] prefWidth = {108, 324}; for (i = 0; i < prefWidth.length; i++) { column = paramTable.getColumnModel().getColumn(i); column.setPreferredWidth(prefWidth[i]); column.setCellRenderer(bcr); } paramTable.setShowHorizontalLines(true); paramTable.setShowVerticalLines(true); paramTable.setIntercellSpacing(new Dimension(1, 1)); // paramTable.setGridColor(Color.lightGray); } // -------- Processor Interface -------- protected void process() { int i, j; int progGoal; // float modProg; List<BatchObject> loops = new ArrayList<BatchObject>(); int line; int lines = batchVector.size(); BatchObject bObj, bObj2; ModulePanel procWin; Exception cmdErr; int errorCount = 0; Component c; StringBuffer sb; String s; DateFormat df = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.MEDIUM ); boolean telepathy = false; topLevel: try { batchLoop: for( line = 0; threadRunning && (line < lines); ) { // ============================== recalculate progress weights ============================== // ============================== execute command ============================== bObj = batchVector.get( line ); batchTable.clearSelection(); batchTable.setRowSelectionInterval( line, line ); batchTable.scrollRectToVisible( batchTable.getCellRect( line, 0, true )); cmdErr = null; // ---- output to console ---- if( pr.bool[ PR_CONSOLE ]) { sb = new StringBuffer(); s = String.valueOf( line + 1 ); sb.append( " ".substring( s.length() )); sb.append( s ); sb.append( " " ); c = batchCR.getTableCellRendererComponent( batchTable, bObj, false, false, line, 1 ); if( c instanceof JLabel ) { sb.append( ((JLabel) c).getText() ); } sb.append( ": " ); c = batchCR.getTableCellRendererComponent( batchTable, bObj, false, false, line, 2 ); if( c instanceof JLabel ) { sb.append( replaceLoopVars( ((JLabel) c).getText(), loops )); } sb.append( " " ); consoleLine( sb.toString(), df ); } switch( bObj.command ) { case BatchObject.CMD_MODULE: // -------------------- module -------------------- bObj.process = 0.001f; batchTM.fireTableCellUpdated( line, 2 ); try { procWin = getProcInstance( bObj, loops ); procWin.fillGUI(); if( pr.bool[ PR_VISIBLE ]) { procWin.setVisible( true ); } try { telepathy = true; procWin.addProcessorListener( procL ); procWin.start(); progGoal = 1; do { try { synchronized( this ) { wait( 3000 ); } } catch( InterruptedException e3 ) { /* ignored */ } bObj.process = procWin.getProgression(); batchTM.fireTableCellUpdated( line, 2 ); j = (int) (bObj.process * 10); if( j >= progGoal ) { if( pr.bool[ PR_CONSOLE ] ) { System.out.print( (j * 10) + "% " ); } progGoal = j + 1; } setProgression( 0.5f ); if( !procWin.isThreadRunning() ) { telepathy = false; } } while( threadRunning && telepathy); if( procWin.getError() != null ) throw procWin.getError(); telepathy = false; procWin.removeProcessorListener( procL ); procWin.stop(); if( pr.bool[ PR_VISIBLE ]) { procWin.setVisible( false ); } procWin.dispose(); } catch( Exception e2 ) { telepathy = false; procWin.removeProcessorListener( procL ); procWin.stop(); if( pr.bool[ PR_VISIBLE ]) { procWin.setVisible( false ); } procWin.dispose(); throw e2; } } catch( Exception e1 ) { cmdErr = e1; } setProgression( 0.5f ); bObj.process = 0.0f; batchTM.fireTableCellUpdated( line, 2 ); break; case BatchObject.CMD_BEGLOOP: // -------------------- loop start -------------------- bObj.loopObj.processIdx = bObj.loopObj.startIdx; loops.add( bObj ); break; case BatchObject.CMD_ENDLOOP: // -------------------- loop end -------------------- for( i = loops.size() - 1; i >= 0; i-- ) { bObj2 = loops.get( i ); if( bObj.loopObj.variable == bObj2.loopObj.variable ) { if( ++bObj2.loopObj.processIdx <= bObj2.loopObj.stopIdx ) { line = batchVector.indexOf( bObj2 ); if( pr.bool[ PR_CONSOLE ]) { System.out.print( " = " + bObj2.loopObj.processIdx ); } } else { loops.remove( i ); } break; } } break; case BatchObject.CMD_DELFILE: // -------------------- del file -------------------- try { if( !new File( replaceLoopVars( bObj.fileObj, loops )).delete() ) { throw new IOException( ERR_DELETE ); } } catch( Exception e1 ) { cmdErr = e1; } break; case BatchObject.CMD_SKIP: // -------------------- skip -------------------- line = findLabelLine( bObj.labelObj ) - 1; break; } // ---- error handling ---- if( cmdErr == null ) { line++; } else { setError( cmdErr ); errorCount++; if( pr.bool[ PR_CONSOLE ]) { sb = new StringBuffer(); sb.append( "\n" ); sb.append( getError().getClass().getName() ); sb.append( ": " ); sb.append( getError().getLocalizedMessage() ); System.out.println( sb.toString() ); } switch( bObj.errorCmd ) { case BatchObject.ERR_STOP: break batchLoop; case BatchObject.ERR_SKIP: line = findLabelLine( bObj.labelObj ); break; case BatchObject.ERR_CONTINUE: line++; break; default: assert false : bObj.errorCmd; } } if( pr.bool[ PR_CONSOLE ]) { System.out.println(); } } // while lines < lines // .... check running .... if( !threadRunning ) break topLevel; setProgression( 1.0f ); // ---- finish ---- if( pr.bool[ PR_CONSOLE ]) { sb = new StringBuffer(); sb.append( " Done. There " ); sb.append( errorCount == 1 ? "was " : "were " ); sb.append( String.valueOf( errorCount )); sb.append( errorCount == 1 ? " error.\n" : " errors.\n" ); consoleLine( sb.toString(), df ); } if( errorCount > 0 ) { setError( new Exception( getError().getClass().getName() + ": \n" + getError().getLocalizedMessage() + "\n(last out of "+errorCount+" errors)" )); } } catch( IllegalStateException e99 ) { setError( e99 ); } telepathy = false; } // process() // -------- private methods -------- private int findLabelLine(String label) { BatchObject bObj; int i; for (i = 0; i < batchVector.size(); i++) { bObj = batchVector.get(i); if ((bObj.command == BatchObject.CMD_LABEL) && (bObj.labelObj.equals(label))) break; } return i; } private void consoleLine( String line, DateFormat df ) { System.out.print( df.format( new Date() ) + line ); } protected void updateParamTable() { String[][] modParam = null; BatchObject bObj; if (batchTable.getSelectedRowCount() == 1) { bObj = batchVector.get(batchTable.getSelectedRow()); if (bObj.command == BatchObject.CMD_MODULE) { modParam = bObj.modObj.modParam; } } paramTM.setParam(modParam); } protected ModulePanel getProcInstance(BatchObject bObj, List loops) throws ClassNotFoundException, InstantiationException, IllegalAccessException { ModulePanel procWin; int i, j; PropertyArray pa; procWin = (ModulePanel) Class.forName(bObj.modObj.modClass).newInstance(); pa = procWin.getPropertyArray(); pa.fromProperties(true, bObj.modObj.prParam); for (i = 0; i < bObj.modObj.modParam.length; i++) { for (j = 0; j < pa.textName.length; j++) { if (bObj.modObj.modParam[i][0].equals(pa.textName[j])) { pa.text[j] = replaceLoopVars(bObj.modObj.modParam[i][1], loops); break; } } } return procWin; } private String replaceLoopVars(String pattern, List loops) { if ((loops == null) || (loops.isEmpty()) || (!pattern.contains("$"))) return pattern; return replaceLoopVars(pattern, loops, loops.size() - 1, new Flag(false)); } private String replaceLoopVars(String s, List loops, int idx, Flag exists) { final LoopObject lObj = ((BatchObject) loops.get( idx )).loopObj; final String searchStr = "$" + lObj.variable; int j; String result = null; for( int k = 0; k < 2; k++ ) { final StringBuffer sb = new StringBuffer( s ); final boolean useZeros = k == 1; // this way the "failing" case is with all zero-padded (original behaviour) while( (j = sb.indexOf( searchStr )) >= 0 ) { final String procStr = String.valueOf( lObj.processIdx ); final int numZeros = String.valueOf( lObj.stopIdx ).length() - procStr.length(); final String replace; if( useZeros ) { replace = "000000".substring( 0, numZeros ) + procStr; } else { replace = procStr; } sb.replace( j, j + 2, replace ); } result = sb.toString(); if( idx > 0 ) { result = replaceLoopVars( result, loops, idx - 1, exists ); } else { exists.set( new File( result ).exists() ); } if( exists.isSet() ) return result; } return result; } // -------------- internal classes -------------- protected static class BatchTableModel extends AbstractTableModel { private static final String[] columnNames = { "Line", "Command", "Object", "On Error", "Error Label" }; private List<BatchObject> batchVector; private static Class integerClass = Integer.class; private static Class batchObjectClass = BatchObject.class; protected BatchTableModel( List<BatchObject> batchVector ) { this.batchVector = batchVector; } public int getColumnCount() { return columnNames.length; } public int getRowCount() { return batchVector.size(); } public String getColumnName( int column ) { return columnNames[ column ]; } public Object getValueAt( int row, int column ) { switch( column ) { case 0: return new Integer( row + 1 ); default: return batchVector.get( row ); } } public Class getColumnClass( int column ) { switch( column ) { case 0: return integerClass; default: return batchObjectClass; } } /* * Don't need to implement this method unless your table's * editable. */ public boolean isCellEditable( int row, int col ) { return( col >= 1 ); } public void setValueAt( Object value, int row, int column ) { int i; switch( column ) { case 1: if( !(value instanceof String) ) break; for( i = 0; i < BatchCellRenderer.CMD_NAMES.length; i++ ) { if( value.equals( BatchCellRenderer.CMD_NAMES[i] )) { batchVector.get( row ).command = i; break; } } break; case 2: batchVector.set( row, (BatchObject) value ); break; case 3: if( !(value instanceof String) ) break; for( i = 0; i < BatchCellRenderer.ERR_NAMES.length; i++ ) { if( value.equals( BatchCellRenderer.ERR_NAMES[i] )) { batchVector.get( row ).errorCmd = i; break; } } break; } fireTableRowsUpdated( row, row ); } } // BatchTableModel protected static class BatchCellRenderer extends BasicCellRenderer { protected static final String[] CMD_NAMES = { "Module", "Delete File", "Begin Loop", "End Loop", "Skip To", "Label" }; protected static final String[] ERR_NAMES = { "Stop", "Continue", "Skip To" }; private JProgressBar progBar = new JProgressBar( 0, 100 ); protected BatchCellRenderer() { super(); progBar.setStringPainted( true ); } public Component getTableCellRendererComponent( JTable table, Object obj, boolean isSelected, boolean hasFocus, int row, int column ) { super.getTableCellRendererComponent( table, obj, isSelected, hasFocus, row, column ); BatchObject bObj; tr.setText( "" ); switch( column ) { case 0: if( !(obj instanceof Integer) ) break; tr.setText( obj.toString() ); tr.setHorizontalAlignment( SwingConstants.RIGHT ); break; case 1: if( !(obj instanceof BatchObject) ) break; bObj = (BatchObject) obj; tr.setText( CMD_NAMES[ bObj.command ]); break; case 2: if( !(obj instanceof BatchObject) ) break; bObj = (BatchObject) obj; switch( bObj.command ) { case BatchObject.CMD_MODULE: if( bObj.process == 0.0f ) { tr.setFont( boldFont ); tr.setText( bObj.modObj.name ); } else { progBar.setString( bObj.modObj.name ); progBar.setValue( (int) (bObj.process * 100) ); return progBar; } break; case BatchObject.CMD_DELFILE: tr.setText( bObj.fileObj ); break; case BatchObject.CMD_BEGLOOP: tr.setFont( monoFont ); tr.setText( bObj.loopObj.variable + " = " + bObj.loopObj.startIdx + " TO " + bObj.loopObj.stopIdx ); break; case BatchObject.CMD_ENDLOOP: tr.setFont( monoFont ); tr.setText( String.valueOf( bObj.loopObj.variable )); break; case BatchObject.CMD_SKIP: case BatchObject.CMD_LABEL: tr.setFont( italicFont ); tr.setText( bObj.labelObj ); break; default: tr.setText( "" ); break; } break; case 3: if( !(obj instanceof BatchObject) ) break; bObj = (BatchObject) obj; if( BatchObject.CMD_CANERROR[ bObj.command ]) { tr.setText( ERR_NAMES[ bObj.errorCmd ]); } break; case 4: if( !(obj instanceof BatchObject) ) break; bObj = (BatchObject) obj; if( (bObj.errorCmd == BatchObject.ERR_SKIP) && BatchObject.CMD_CANERROR[ bObj.command ]) { tr.setFont( italicFont ); tr.setText( bObj.labelObj ); } break; default: tr.setText( obj.toString() ); break; } return tr; // this; } } // BatchCellRenderer protected class BatchCellEditor extends AbstractCellEditor implements TableCellEditor { private ModuleCellEditor modCE = new ModuleCellEditor(); private JFormattedTextField modFTF = new JFormattedTextField( modCE ); private LabelCellEditor labCE = new LabelCellEditor(); private JFormattedTextField labFTF = new JFormattedTextField( labCE ); private FileCellEditor fileCE = new FileCellEditor(); private JFormattedTextField fileFTF = new JFormattedTextField( fileCE ); private LoopCellEditor loopCE = new LoopCellEditor(); private JFormattedTextField loopFTF = new JFormattedTextField( loopCE ); private BatchObject obj; public Component getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column ) { if( !(value instanceof BatchObject) ) return null; this.obj = (BatchObject) value; switch( column ) { case 2: switch( obj.command ) { case BatchObject.CMD_MODULE: modFTF.setValue( obj ); return modFTF; case BatchObject.CMD_SKIP: case BatchObject.CMD_LABEL: labFTF.setValue( obj ); return labFTF; case BatchObject.CMD_DELFILE: fileFTF.setValue( obj ); return fileFTF; case BatchObject.CMD_BEGLOOP: case BatchObject.CMD_ENDLOOP: loopFTF.setValue( obj ); return loopFTF; } break; case 4: labFTF.setValue( obj ); return labFTF; } return null; } public Object getCellEditorValue() { return obj; } } // BatchCellEditor protected class ModuleCellEditor extends DefaultFormatter { private BatchObject obj = null; public String valueToString( Object o ) { obj = (BatchObject) o; if( obj != null ) { return obj.modObj.name; } else return ""; } public Object stringToValue( String s ) { if( obj != null ) { obj.modObj.name = s; } return obj; } } // ModuleCellEditor protected class LabelCellEditor extends DefaultFormatter { private BatchObject obj = new BatchObject(); public String valueToString( Object o ) { obj = (BatchObject) o; if( obj != null ) { return obj.labelObj; } else return ""; } public Object stringToValue( String s ) { obj.labelObj = s; return obj; } } // LabelCellEditor protected class FileCellEditor extends DefaultFormatter { private BatchObject obj = new BatchObject(); public String valueToString( Object o ) { obj = (BatchObject) o; if( obj != null ) { return obj.fileObj; } else return ""; } public Object stringToValue( String s ) { obj.fileObj = s; return obj; } } // FileCellEditor protected class LoopCellEditor extends DefaultFormatter { private BatchObject obj = null; public String valueToString( Object o ) { obj = (BatchObject) o; if( obj != null ) { if( obj.command == BatchObject.CMD_BEGLOOP ) { return( String.valueOf( obj.loopObj.variable ) + " = " + String.valueOf( obj.loopObj.startIdx ) + " TO " + String.valueOf( obj.loopObj.stopIdx )); } else { return( String.valueOf( obj.loopObj.variable )); } } else return ""; } public Object stringToValue( String s ) { if( obj != null ) { int i, j, k; final String sNorm = s.toUpperCase(); i = sNorm.indexOf( "=" ); j = sNorm.indexOf( "TO", i+1 ); if( (sNorm.length() > 0) && Character.isLetter( sNorm.charAt( 0 ))) { obj.loopObj.variable = sNorm.charAt( 0 ); } if( (i > 0) && (j > (i+1)) && (j+2 < sNorm.length()) ) { try { k = Math.max( 0, Integer.parseInt( sNorm.substring( i+1, j ).trim() )); obj.loopObj.startIdx = k; k = Math.max( k, Integer.parseInt( sNorm.substring( j+2 ).trim() )); obj.loopObj.stopIdx = k; } catch( NumberFormatException e99 ) { /* ignore */} } } return obj; } } // LoopCellEditor protected static class BatchObjectArray implements Transferable { protected static DataFlavor flavor; private static DataFlavor[] flavors; private BatchObject[] obj; protected BatchObjectArray() { if( flavor == null ) { flavor = new DataFlavor( getClass(), "Batch Object Array" ); flavors = new DataFlavor[1]; flavors[0] = flavor; } } protected BatchObjectArray( BatchObject[] obj ) { this.obj = obj; } public DataFlavor[] getTransferDataFlavors() { return flavors; } public boolean isDataFlavorSupported( DataFlavor fl ) { for( int i = 0; i < flavors.length; i++ ) { if( fl.match( flavors[i] )) return true; } return false; } public Object getTransferData( DataFlavor fl ) throws UnsupportedFlavorException { for( int i = 0; i < flavors.length; i++ ) { if( fl.match( flavors[i] )) { BatchObject[] objCopy = new BatchObject[ obj.length ]; for( int j = 0; j < objCopy.length; j++ ) { objCopy[j] = new BatchObject( obj[j] ); } return objCopy; } } throw new UnsupportedFlavorException( fl ); } } /** * Internal class for the list entries */ protected static class BatchObject { protected static final int CMD_MODULE = 0; protected static final int CMD_DELFILE = 1; protected static final int CMD_BEGLOOP = 2; protected static final int CMD_ENDLOOP = 3; protected static final int CMD_SKIP = 4; protected static final int CMD_LABEL = 5; protected static final boolean[] CMD_CANERROR = { true, true, false, false, false, false }; private static final int ERR_STOP = 0; private static final int ERR_CONTINUE = 1; private static final int ERR_SKIP = 2; protected int command = CMD_LABEL; protected int errorCmd = ERR_STOP; protected ModuleObject modObj = new ModuleObject(); protected LoopObject loopObj = new LoopObject(); protected String fileObj = "file"; protected String labelObj = "label"; protected float process = 0.0f; // becomes >0 during the processing of the accompanying module private final static String PR_CMD = "comd"; private final static String PR_ERRCMD = "ecmd"; private final static String PR_FILE = "file"; private final static String PR_LABEL = "labl"; private final static String PR_MODNAME = "mnam"; private final static String PR_MODCLASS = "mcls"; private final static String PR_MODPAR = "mpar"; private final static String PR_MODMOD = "mmod"; private final static String PR_LOOPVAR = "lvar"; private final static String PR_LPSTART = "lbeg"; private final static String PR_LPSTOP = "lend"; protected BatchObject() { /* nothing */ } protected BatchObject( BatchObject source ) { command = source.command; errorCmd = source.errorCmd; modObj = new ModuleObject( source.modObj ); loopObj = new LoopObject( source.loopObj ); fileObj = source.fileObj; labelObj = source.labelObj; } public static BatchObject valueOf(String s) { Properties p = Presets.valueToProperties(s); BatchObject bObj = new BatchObject(); String s2; Properties p2; Enumeration en; int i; try { bObj.fileObj = (String) p.get( PR_FILE ); bObj.labelObj = (String) p.get( PR_LABEL ); bObj.modObj.name = (String) p.get( PR_MODNAME ); bObj.modObj.modClass = (String) p.get( PR_MODCLASS ); bObj.command = Integer.parseInt( (String) p.get( PR_CMD )); bObj.errorCmd = Integer.parseInt( (String) p.get( PR_ERRCMD )); s2 = (String) p.get( PR_LOOPVAR ); if( s2.length() > 0 ) { bObj.loopObj.variable = s2.charAt( 0 ); } bObj.loopObj.startIdx = Integer.parseInt( (String) p.get( PR_LPSTART )); bObj.loopObj.stopIdx = Integer.parseInt( (String) p.get( PR_LPSTOP )); } catch( NumberFormatException e1 ) { /* ignored */ } catch( NullPointerException e2 ) { /* ignored */ } s2 = (String) p.get(PR_MODPAR); if (s2 != null) bObj.modObj.prParam = Presets.valueToProperties(s2); s2 = (String) p.get(PR_MODMOD); if (s2 != null) { p2 = Presets.valueToProperties(s2); bObj.modObj.modParam = new String[p2.size()][2]; en = p2.propertyNames(); for (i = 0; en.hasMoreElements(); i++) { s2 = (String) en.nextElement(); bObj.modObj.modParam[i][0] = s2; bObj.modObj.modParam[i][1] = p2.getProperty(s2); } } return bObj; } public String toString() { Properties p = new Properties(); Properties p2 = new Properties(); int i; p.put( PR_FILE, this.fileObj ); p.put( PR_LABEL, this.labelObj ); p.put( PR_MODNAME, this.modObj.name ); if( this.modObj.modClass != null ) p.put( PR_MODCLASS, this.modObj.modClass ); p.put( PR_CMD, String.valueOf( this.command )); p.put( PR_ERRCMD, String.valueOf( this.errorCmd )); p.put( PR_LOOPVAR, String.valueOf( this.loopObj.variable )); p.put( PR_LPSTART, String.valueOf( this.loopObj.startIdx )); p.put( PR_LPSTOP, String.valueOf( this.loopObj.stopIdx )); if( this.modObj.prParam != null ) { p.put( PR_MODPAR, Presets.propertiesToValue( this.modObj.prParam )); } if( this.modObj.modParam != null ) { for( i = 0; i < this.modObj.modParam.length; i++ ) { p2.setProperty( this.modObj.modParam[i][0], this.modObj.modParam[i][1] ); } p.put( PR_MODMOD, Presets.propertiesToValue( p2 )); } return( Presets.propertiesToValue( p )); } } // BatchObject /** * Internal class for list entries */ protected static class LoopObject { protected char variable = 'A'; protected int startIdx = 1; protected int stopIdx = 9; protected int processIdx; protected LoopObject() { /* nothing */} protected LoopObject(LoopObject source) { variable = source.variable; startIdx = source.startIdx; stopIdx = source.stopIdx; } } // LoopObject /** * Internal class for list entries */ protected static class ModuleObject { protected String name = "module"; protected String modClass = null; protected Properties prParam = new Properties(); protected String[][] modParam = new String[0][2]; protected ModuleObject() { /* nothing */ } protected ModuleObject( ModuleObject source ) { int i; name = source.name; modClass = source.modClass; prParam = source.prParam; modParam = new String[ source.modParam.length ][ 2 ]; for( i = 0; i < modParam.length; i++ ) { modParam[i][0] = source.modParam[i][0]; modParam[i][1] = source.modParam[i][1]; } } } // ModuleObject protected static class ParamTableModel extends AbstractTableModel { private static final String[] columnNames = { "Parameter", "Value" }; private String[][] emptyData = new String[0][2]; private String[][] paramData = emptyData; protected void setParam( String[][] paramData ) { if( paramData != null ) { this.paramData = paramData; fireTableDataChanged(); } else { boolean wasEmpty = this.paramData.length == 0; this.paramData = emptyData; if( !wasEmpty ) fireTableDataChanged(); } } public int getColumnCount() { return columnNames.length; } public int getRowCount() { return paramData.length; } public String getColumnName(int column) { return columnNames[column]; } public Object getValueAt(int row, int column) { return paramData[row][column]; } public Class getColumnClass(int column) { if (paramData.length == 0) return null; return paramData[0][column].getClass(); } /* * Don't need to implement this method unless your table's * editable. */ public boolean isCellEditable(int row, int col) { return (col >= 1); } public void setValueAt(Object value, int row, int column) { paramData[row][column] = (String) value; fireTableRowsUpdated(row, row); } } // ParamTableModel }