/*
* File: MainPanel.java
* Author: Daniel Rogers
* Created on Jan 7, 2008
*
*/
package gri.tasks.gui;
import java.awt.*;
import javax.swing.*;
import gri.tasks.ParameterDef;
import gri.tasks.TaskDef;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import gri.tasks.*;
import gri.tasks.managers.JobManager;
import gri.tasks.managers.JobSubmission;
import gri.tasks.managers.JobManagerSet;
import gri.tasks.gui.widgets.InputParameterWidgetFactory;
import gri.tasks.gui.widgets.ParameterWidgetFactory;
import gri.tasks.gui.util.JobEntry;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import dan.swing.event.DefaultButtonChangeListener;
/**
* Panel which displays a Task selection panel on the left
* and input panels for the currently selected task on the right.
* Jobs can be submitted
*
* @author dan.rogers
*/
public class MainPanel extends JPanel implements TaskSelectionListener {
JobManagerSet jobManagers;
ParameterWidgetFactory inputWidgetFactory;
List submitListeners = new ArrayList(3);
int jobCount = 0;
JSplitPane splitPane;
TaskSelectionPanel taskSelector;
DefaultButtonChangeListener defaultButtonListener = null;
//StatusFrameJobManager runningJobManager;
// ---------------------------------------------------- Constructors
public MainPanel(JobManagerSet jobManagers) {
super(new BorderLayout());
this.jobManagers = jobManagers;
this.inputWidgetFactory = new InputParameterWidgetFactory();
init();
}
// ------------------------------------------------------- Accessors
public void setDefaultButtonChangeListener(DefaultButtonChangeListener listener) {
this.defaultButtonListener = listener;
}
public void setInputWidgetFactory(ParameterWidgetFactory factory) {
this.inputWidgetFactory = factory;
}
public void addSubmitListener(JobSubmissionListener listener) {
submitListeners.add(listener);
}
public void removeSubmitListener(JobSubmissionListener listener) {
submitListeners.remove(listener);
}
// -------------------------------------------------- Implementation
protected void init() {
taskSelector = new TaskSelectionPanel(this.jobManagers);
taskSelector.addTaskSelectionListener(this);
JScrollPane lstTasks_scroll = new JScrollPane(taskSelector);
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
lstTasks_scroll, new JPanel());
add(splitPane, BorderLayout.CENTER);
setPreferredSize(new Dimension(600, 300));
}
/**
* Listener for task selection events. Will display an input
* form for the newly selected task.
*/
public void taskSelected(TaskInfo taskInfo) {
if (taskInfo == null) {
setTaskPanel(new JPanel());
setDefaultButton(null);
}
else {
TaskInputPanel inputPanel = new TaskInputPanel(
taskInfo.getTaskDescription(),
taskInfo.getTaskDefinition().getInputsArray(),
inputWidgetFactory);
TaskExecutionListener listener = new TaskExecutionListener(taskInfo, inputPanel);
inputPanel.addExecutionListener(listener);
setTaskPanel(inputPanel);
setDefaultButton(inputPanel.getExecuteButton());
}
}
/**
* Submits a job. The TaskInfo object provides us with information
* on the JobManager for the current task. The submission object
* is then submitted to this manager and all submit listeners are
* notified.
*/
protected void submitJob(TaskInfo taskInfo, JobSubmission submission) throws Exception {
//execute:
JobManager jobManager = taskInfo.getJobManager();
String jobId = jobManager.submitJob(submission);
//notify listeners (provide running task object):
JobEntry jobEntry = new JobEntry(submission.getTaskId(), jobId, jobManager);
for (int i=0; i<submitListeners.size(); i++)
((JobSubmissionListener)submitListeners.get(i)).jobSubmitted(jobEntry);
}
/**
* Displays the panel on the right side of the divider. A JScrollPane
* is automatically added.
*/
protected void setTaskPanel(JPanel panel) {
int position = splitPane.getDividerLocation(); //store position (so it doesn't change)
JScrollPane panel_scroll = new JScrollPane(panel);
splitPane.setRightComponent(panel_scroll);
splitPane.setDividerLocation(position);
}
/**
* Sets the default button. This will notify our defaultButtonListener
* if it exists and allow us to set the default button on a parent
* frame.
*/
protected void setDefaultButton(JButton button) {
if (defaultButtonListener != null)
defaultButtonListener.defaultButtonChanged(button);
}
// -------------------------------------------------------- Messages
protected void error(String msg) {
JOptionPane.showMessageDialog(this, msg, "ERROR", JOptionPane.ERROR_MESSAGE);
}
protected void error(String msg, Exception e) {
e.printStackTrace();
error(msg);
}
protected void error(Exception e) {
error(e.getMessage(), e);
}
protected void info(String msg) {
JOptionPane.showMessageDialog(this, msg);
}
// --------------------------------------------------------- Inner Classes
/**
* Listener to respond when the "submit" button for a job is clicked.
* This will grab the inputs and validate them, forming a JobSubmission
* object and passing this off to "submitJob()" on the parent panel.
*/
class TaskExecutionListener implements ActionListener {
TaskInfo taskInfo;
TaskInputPanel inputPanel;
public TaskExecutionListener(TaskInfo taskInfo, TaskInputPanel inputPanel) {
this.taskInfo = taskInfo;
this.inputPanel = inputPanel;
}
public void actionPerformed(ActionEvent e) {
//get/validate inputs:
Map inputs = this.inputPanel.getValues();
TaskDef taskDef = taskInfo.getTaskDefinition();
ParameterDef [] inputDefs = taskDef.getInputsArray();
for (int i=0; i<inputDefs.length; i++) {
String paramName = inputDefs[i].getName();
if (inputDefs[i].isRequired() && inputs.get(paramName) == null) {
error("Required parameter not entered: " + paramName);
return;
}
}
//set inputs:
Iterator entries = inputs.entrySet().iterator();
JobSubmission submission = new JobSubmission(taskInfo.getTaskId());
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry)entries.next();
String paramName = entry.getKey().toString();
Object value = entry.getValue();
submission.setInput(paramName, value);
}
try {
submitJob(taskInfo, submission);
}
catch(Exception ex) {
error(ex);
}
}
}
/**
* ErrorHandler to display errors from tasks as message dialogs.
* NOTE: This is passed to the JobManagerTask, but the task
* currently ignores it.
*/
class NotifyErrorHandler implements AsyncEventHandler {
Component parent;
public NotifyErrorHandler(Component parent) {
this.parent = parent;
}
public void handleError(Exception e) {
e.printStackTrace();
String msg = e.getMessage();
JOptionPane.showMessageDialog(parent, msg, "ERROR", JOptionPane.ERROR_MESSAGE);
}
public void notifyComplete() {
//do nothing
}
}
}