/* * Created on Apr 11, 2003 */ package org.vorthmann.zome.ui; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FileDialog; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.Writer; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.border.TitledBorder; import javax.vecmath.Quat4d; import org.vorthmann.j3d.MouseToolDefault; import org.vorthmann.j3d.Tool; import org.vorthmann.j3d.Trackball; import org.vorthmann.ui.Controller; /** * @author vorth * * So far, just a stripped-down ZomicEditorPanel with names changed. */ public class PythonConsolePanel extends JPanel implements Tool { private final FileDialog mFileChooser; private static final String OPEN = "Select a .py file to open"; private static final String SAVE = "Save a .py file"; private final JTextArea mTextArea = new JTextArea(); private static final String PYTHON_HINT = "\n# Type or paste a Python script here, \n" + "# then select all or part and execute it.\n"; public abstract class PythonOutputAction implements ActionListener { public abstract void outputScript( String script ); @Override public void actionPerformed( ActionEvent e ) { String script = mTextArea .getSelectedText(); if ( script != null && script .length() > 0 ) outputScript( script ); mTextArea .requestFocus(); } } public abstract class PythonInputAction implements ActionListener { public abstract String inputScript(); @Override public void actionPerformed( ActionEvent e ) { String script = inputScript(); if ( script != null && script .length() > 0 ) { int start = mTextArea .getSelectionStart(); mTextArea .replaceSelection( script ); // int end = mTextArea .getSelectionEnd(); mTextArea .setSelectionStart( start ); } mTextArea .requestFocus(); } }; private String readFromFile() { mFileChooser .setTitle( OPEN ); mFileChooser .setMode( FileDialog .LOAD ); mFileChooser .setVisible( true ); String fileName = mFileChooser .getFile(); if ( fileName != null ) { File file = new File( mFileChooser .getDirectory(), fileName ); String result = readTextFromFile( file ); if ( result == null ) { JOptionPane .showMessageDialog( PythonConsolePanel.this, "An exception prevented successful reading of the file.", "File read error", JOptionPane.ERROR_MESSAGE ); return null; } else return result; } return null; } private static String readTextFromFile( File file ) { try { InputStream input = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int num; while ( ( num = input .read( buf, 0, 1024 )) > 0 ) out .write( buf, 0, num ); return new String( out .toByteArray() ); } catch (IOException exc) { exc.printStackTrace(); return null; } } private void writeToFile( String script ) { mFileChooser .setTitle( SAVE ); mFileChooser .setMode( FileDialog .SAVE ); mFileChooser .setVisible( true ); String fileName = mFileChooser .getFile(); if ( fileName != null ) { File file = new File( mFileChooser .getDirectory(), fileName ); // A try-with-resources block closes the resource even if an exception occurs try (Writer out = new FileWriter( file )) { out .write( script ); } catch (Exception exc) { JOptionPane .showMessageDialog( PythonConsolePanel.this, "An exception prevented successful writing of the file.", "File save error", JOptionPane.ERROR_MESSAGE ); exc.printStackTrace(); } } } private final Controller mController; /** * @param viewer */ public PythonConsolePanel( Frame frame, Controller controller ) { mController = controller; mFileChooser = new FileDialog( frame, OPEN ); mTextArea .setTabSize( 4 ); JScrollPane areaScrollPane = new JScrollPane(mTextArea); areaScrollPane .setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED ); areaScrollPane .setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED ); mTextArea .setText( PYTHON_HINT ); mTextArea .selectAll(); JPanel controlPanel = new JPanel(); controlPanel.setLayout( new BoxLayout( controlPanel, BoxLayout.Y_AXIS ) ); JPanel upDownPanel = new JPanel(); upDownPanel.setLayout( new BoxLayout( upDownPanel, BoxLayout.X_AXIS ) ); JButton button = new JButton( "run" ); Dimension size = button .getPreferredSize(); size .width = 50; button .setPreferredSize( size ); button .addActionListener( new PythonOutputAction() { @Override public void outputScript( String script ){ mController .doScriptAction( "runPythonScript" , script ); } } ); button .setToolTipText( "Execute the selection on the model." ); upDownPanel .add( button ); button = new JButton( "load" ); button .addActionListener( new PythonInputAction() { @Override public String inputScript(){ return readFromFile(); } } ); button .setToolTipText( "Replace the selection from the script file." ); upDownPanel .add( button ); button = new JButton( "save" ); button .addActionListener( new PythonOutputAction() { @Override public void outputScript( String script ){ writeToFile( script ); } } ); button .setToolTipText( "Save the selection to the script file." ); upDownPanel .add( button ); controlPanel .add( upDownPanel ); JPanel top = new JPanel(); BoxLayout box = new BoxLayout( top, BoxLayout.Y_AXIS ); top .setLayout( box ); top .add( controlPanel ); top .add( areaScrollPane ); top .setBorder( new TitledBorder( null, "script editing", 4, 2, new java.awt.Font("Dialog", 1, 12), new java.awt.Color(0, 0, 0))); controlPanel = new JPanel(); controlPanel .setLayout( new BoxLayout( controlPanel, BoxLayout.X_AXIS ) ); top .setMinimumSize( new Dimension( 300, 300 ) ); setLayout( new BorderLayout() ); add( top, BorderLayout.CENTER ); setPreferredSize( new Dimension( 500, 800 ) ); } @Override public String getToolName() { return "script"; } @Override public void toolSelected() { mTextArea .requestFocus(); } @Override public void toolUnselected(){} @Override public MouseToolDefault getMouseTool() { return new Trackball() { @Override protected void trackballRolled( Quat4d roll ) { // TODO remove this? } }; } }