/**
* $Id: $
* $Date: $
*
*/
package org.xmlsh.sh.ui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.List;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.text.JTextComponent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.xmlsh.core.Options;
import org.xmlsh.core.XValue;
import org.xmlsh.sh.shell.SerializeOpts;
import org.xmlsh.sh.shell.Shell;
import org.xmlsh.sh.ui.TextResultPane.OutputType;
import org.xmlsh.util.FileUtils;
import org.xmlsh.util.Util;
public class XShell {
private volatile JFrame mframe = null ;
private TextAreaComponent mScriptTextArea;
private XShellThread mShell = null;
private TextResultPane mResultArea ;
private File mCurdir;
private LogFrame mLogWindow = null;
private JTextField mCommandInputField;
private SerializeOpts mSerializeOpts ;
private final ButtonGroup buttonGroup = new ButtonGroup();
private static Logger mLogger = LogManager.getLogger();
/**
* Launch the application.
*/
public static void main(String[] args) {
run(args);
}
public static void run(final String[] args) {
run(Util.toXValueList(args));
}
public static void run(List<XValue> args) {
run(new File("."), args ,new SerializeOpts() );
}
public static void run(File curdir , List<XValue> args) {
run(curdir, args ,new SerializeOpts() );
}
public static void run(final File curdir, final List<XValue> args , final SerializeOpts sopts ) {
run(curdir, args, sopts,null);
}
public static void run(final File curdir, final List<XValue> args , final SerializeOpts sopts , Shell parentShell ) {
final ThreadGroup threadGroup =
parentShell == null ? new ThreadGroup("xmlshui") : new ThreadGroup( parentShell.getThreadGroup() ,"xmlshui");
// TODO: Propogate variables and environment ?
try {
// Set System L&F
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
mLogger.warn(e);
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
XShell window = new XShell(threadGroup ,curdir, args , sopts );
window.mframe.setVisible(true);
window.mScriptTextArea.requestFocusInWindow();
} catch (Exception e) {
mLogger.warn(e);
}
}
});
}
public XShell(ThreadGroup threadGroup , File curdir, List<XValue> args,SerializeOpts sopts) throws Exception {
mCurdir = curdir;
Options opts = new Options( "c=command:,cf=command-file:,f=file:", SerializeOpts.getOptionDefs() );
opts.parse(args);
sopts.setOptions(opts);
mSerializeOpts = sopts ;
String command = opts.getOptString("c", null);
if( command == null ){
String fname = opts.getOptString("cf", null );
if( fname != null ){
command = FileUtils.convertPath(fname , false );
}
if( command == null ){
fname = opts.getOptString("f", null);
if( fname != null )
command = Util.readString(new File(curdir, fname ) , sopts.getInput_text_encoding() );
}
}
initialize(threadGroup , command,opts.getRemainingArgs());
}
/**
* Initialize the contents of the frame.
* @param threadGroup
* @param list
* @param command
*
* @throws Exception
*/
private void initialize(ThreadGroup threadGroup, String command, List<XValue> args) throws Exception {
mframe = new JFrame();
mframe.setMinimumSize(new Dimension(300, 200));
mframe.getContentPane().setMinimumSize(new Dimension(280, 180));
mframe.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
mShell.close();
}
});
mframe.setBounds(100, 100, 709, 604);
mframe.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();
menuBar.setMargin(new Insets(0, 20, 0, 20));
menuBar.setAlignmentY(Component.CENTER_ALIGNMENT);
mframe.setJMenuBar(menuBar);
JMenu mnFile = new JMenu("File");
menuBar.add(mnFile);
JMenuItem mntmExit = new JMenuItem("Exit");
mntmExit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFrame top = mframe ;
mframe = null ;
if( top != null )
top.dispose();
}
});
JMenuItem mntmNew = new JMenuItem("New");
mntmNew.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
}
});
mnFile.add(mntmNew);
JMenuItem mntmOpen = new JMenuItem("Open...");
mntmOpen.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser(mCurdir);
// Show open dialog; this method does not return until the dialog is closed
if( fc.showSaveDialog(mframe) == JFileChooser.APPROVE_OPTION ){
File selFile = fc.getSelectedFile();
String data = readFrom( selFile );
if( data != null )
mScriptTextArea.setText(data);
}
}
});
mnFile.add(mntmOpen);
JMenuItem mntmSaveAs = new JMenuItem("Save As...");
mntmSaveAs.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser(mCurdir);
// Show open dialog; this method does not return until the dialog is closed
fc.showSaveDialog(mframe);
if( fc.showSaveDialog(mframe) == JFileChooser.APPROVE_OPTION ){
File selFile = fc.getSelectedFile();
saveTo( mScriptTextArea.getText() , selFile );
}
}
});
mnFile.add(mntmSaveAs);
JMenuItem mntmSaveResults = new JMenuItem("Save Results..");
mntmSaveResults.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser(mCurdir);
// Show open dialog; this method does not return until the dialog is closed
if( fc.showSaveDialog(mframe) == JFileChooser.APPROVE_OPTION ){
File selFile = fc.getSelectedFile();
saveTo( mResultArea.getAsText() , selFile );
}
}
});
mnFile.add(mntmSaveResults);
JSeparator separator = new JSeparator();
mnFile.add(separator);
mnFile.add(mntmExit);
JMenu mnView = new JMenu("View");
menuBar.add(mnView);
JMenuItem mntmLogWindow = new JMenuItem("Log Window");
mntmLogWindow.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mLogWindow.setVisible( ! mLogWindow.isVisible());
}
});
mnView.add(mntmLogWindow);
Component horizontalStrut_3 = Box.createHorizontalStrut(20);
menuBar.add(horizontalStrut_3);
JToolBar toolBar = new JToolBar();
menuBar.add(toolBar);
JButton btnRun = new JButton("Run");
btnRun.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mShell.putCommand(mScriptTextArea.getText());
}
});
toolBar.add(btnRun);
mframe.getContentPane().setLayout(new BoxLayout(mframe.getContentPane(), BoxLayout.X_AXIS));
JSplitPane splitPane = new JSplitPane();
splitPane.setMinimumSize(new Dimension(250, 150));
splitPane.setPreferredSize(new Dimension(280, 180));
splitPane.setAlignmentY(Component.CENTER_ALIGNMENT);
splitPane.setAlignmentX(Component.CENTER_ALIGNMENT);
splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
mframe.getContentPane().add(splitPane);
JPanel inputPanel = new JPanel();
GridBagLayout gbl_inputPanel = new GridBagLayout();
gbl_inputPanel.columnWidths = new int[]{645, 0};
gbl_inputPanel.rowHeights = new int[]{100, 0};
gbl_inputPanel.columnWeights = new double[]{1.0, Double.MIN_VALUE};
gbl_inputPanel.rowWeights = new double[]{1.0, Double.MIN_VALUE};
inputPanel.setLayout(gbl_inputPanel);
JPanel resultPanel = new JPanel( );
resultPanel.setMinimumSize(new Dimension(200, 100));
resultPanel.setBorder(null);
resultPanel.setPreferredSize(new Dimension(300, 100));
GridBagLayout gbl_resultPanel = new GridBagLayout();
gbl_resultPanel.rowHeights = new int[]{323, 0};
gbl_resultPanel.columnWeights = new double[]{1.0};
gbl_resultPanel.rowWeights = new double[]{1.0, 0.0};
resultPanel.setLayout(gbl_resultPanel);
mResultArea = new TextResultPane(OutputType.PLAIN_TEXT);
JTextComponent textPane = mResultArea.getTextComponent();
//textPane.setPreferredSize(new Dimension(4, 100));
JPanel textOuterPanel = new JPanel( new BorderLayout());
textOuterPanel.add(textPane);
JScrollPane scrollResult = new JScrollPane(textOuterPanel,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
textPane.setEditable(false);
new TextComponentPopupMenu( mResultArea );
GridBagConstraints gbc_scrollResult = new GridBagConstraints();
gbc_scrollResult.fill = GridBagConstraints.BOTH;
gbc_scrollResult.gridx = 0;
gbc_scrollResult.gridy = 0;
resultPanel.add(scrollResult, gbc_scrollResult);
splitPane.setLeftComponent(inputPanel);
splitPane.setRightComponent(resultPanel);
mCommandInputField = new JTextField();
mCommandInputField.setAlignmentY(Component.BOTTOM_ALIGNMENT);
mCommandInputField.setMargin(new Insets(0, 0, 0, 0));
mCommandInputField.setHorizontalAlignment(SwingConstants.LEFT);
GridBagConstraints gbc_CommandText = new GridBagConstraints();
gbc_CommandText.ipady = 2;
gbc_CommandText.ipadx = 2;
gbc_CommandText.insets = new Insets(2, 2, 2, 2);
gbc_CommandText.fill = GridBagConstraints.HORIZONTAL;
gbc_CommandText.anchor = GridBagConstraints.SOUTH;
gbc_CommandText.gridx = 0;
gbc_CommandText.gridy = 1;
resultPanel.add(mCommandInputField, gbc_CommandText);
mCommandInputField.setColumns(50);
splitPane.setDividerLocation(0.5);
mScriptTextArea = new TextAreaComponent();
JScrollPane scrollCommand = new JScrollPane(mScriptTextArea,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollCommand.setPreferredSize(new Dimension(200, 100));
scrollCommand.setMinimumSize(new Dimension(200, 50));
scrollCommand.setAlignmentY(Component.TOP_ALIGNMENT);
GridBagConstraints gbc_scrollCommand = new GridBagConstraints();
gbc_scrollCommand.fill = GridBagConstraints.BOTH;
gbc_scrollCommand.gridx = 0;
gbc_scrollCommand.gridy = 0;
inputPanel.add( scrollCommand, gbc_scrollCommand);
new TextComponentPopupMenu( mScriptTextArea );
mLogWindow = new LogFrame(mSerializeOpts);
if( command != null )
mScriptTextArea.setText( command + " " + Util.stringJoin( Util.toStringList(args)," ") );
JButton btnStop = new JButton("Stop");
btnStop.setEnabled(false);
toolBar.add(btnStop);
mShell = new XShellThread( this , threadGroup , null , mResultArea , mCommandInputField , btnRun , btnStop , mSerializeOpts );
Component horizontalStrut = Box.createHorizontalStrut(20);
toolBar.add(horizontalStrut);
JToolBar toolBar_format = new JToolBar();
toolBar_format.setAlignmentY(Component.CENTER_ALIGNMENT);
toolBar_format.setAlignmentX(Component.RIGHT_ALIGNMENT);
toolBar_format.setSize(new Dimension(199, 0));
toolBar_format.setLocation(new Point(100, 0));
menuBar.add(toolBar_format);
Component horizontalStrut_2 = Box.createHorizontalStrut(20);
toolBar_format.add(horizontalStrut_2);
JLabel lblNewLabel = new JLabel("Output Format");
lblNewLabel.setHorizontalTextPosition(SwingConstants.LEADING);
lblNewLabel.setFont(new Font("Tahoma", Font.BOLD, 11));
lblNewLabel.setForeground(Color.BLUE);
toolBar_format.add(lblNewLabel);
Component horizontalStrut_1 = Box.createHorizontalStrut(20);
toolBar_format.add(horizontalStrut_1);
JRadioButton textRadioButton = new JRadioButton("Text");
textRadioButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mResultArea.setOutputFormat(
((JRadioButton)e.getSource()).isSelected() ? OutputType.PLAIN_TEXT : OutputType.HTML);
}
});
buttonGroup.add(textRadioButton);
textRadioButton.setHorizontalAlignment(SwingConstants.CENTER);
textRadioButton.setSelected(true);
lblNewLabel.setLabelFor(textRadioButton);
toolBar_format.add(textRadioButton);
JRadioButton htmlRadioButton = new JRadioButton("Html");
htmlRadioButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mResultArea.setOutputFormat(
!((JRadioButton)e.getSource()).isSelected() ? OutputType.PLAIN_TEXT : OutputType.HTML );
}
});
buttonGroup.add(htmlRadioButton);
htmlRadioButton.setHorizontalAlignment(SwingConstants.CENTER);
toolBar_format.add(htmlRadioButton);
Component horizontalStrut_4 = Box.createHorizontalStrut(20);
toolBar_format.add(horizontalStrut_4);
mShell.start();
}
protected void saveTo(String text, File selFile) {
try {
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(selFile),
"utf8");
writer.write(text);
writer.close();
} catch (IOException e) {
JOptionPane.showMessageDialog(mframe,
"Error writing to file: " + e.getLocalizedMessage());
}
}
protected String readFrom(File selFile) {
try {
return Util.readString(selFile, "utf8");
} catch (IOException e) {
mLogger.warn(e);
JOptionPane.showMessageDialog(mframe,
"Error reading from file: " + e.getLocalizedMessage());
return null;
}
}
public void onThreadExit(XShellThread thread )
{
if( mShell == thread ) {
JFrame top = mframe ;
mframe = null ;
// unexpected termination
if( top != null )
top.dispose();
}
}
}
//
//
// Copyright (C) 2008-2014 David A. Lee.
//
// The contents of this file are subject to the "Simplified BSD License" (the
// "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the
// License at http://www.opensource.org/licenses/bsd-license.php
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
// See the License for the specific language governing rights and limitations
// under the License.
//
// The Original Code is: all this file.
//
// The Initial Developer of the Original Code is David A. Lee
//
// Portions created by (your name) are Copyright (C) (your legal entity). All
// Rights Reserved.
//
// Contributor(s): none.
//