package net.sf.jiga.xtended.ui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Closeable;
import java.io.IOException;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
import net.sf.jiga.xtended.kernel.SfThread;
import net.sf.jiga.xtended.kernel.ThreadWorks;
/** This class performs a good graphical interface to Steppable objects like an IPane. It includes 3 implmented buttons.
*@see InstructionsPane#addStepListener(StepListener)
*/
public class StatusPane extends JPanel implements StepListener {
long hash = System.nanoTime();
public int hashCode() {
return (int) hash;
}
/** own pane which has to be stated */
protected final InstructionsPane ownPane;
/** previous step button */
private JButton previous;
/** next step button */
private JButton next;
/** finish button */
private JButton finish;
/** cancel button */
private JButton cancel;
/** active Threads */
private Map<Integer, SfThread> activeThreads = Collections.synchronizedMap(new HashMap<Integer, SfThread>());
/** active Streams */
private Map<Integer, Closeable> activeStreams = Collections.synchronizedMap(new HashMap<Integer, Closeable>());
/** active Timers */
private Map<Integer, javax.swing.Timer> activeTimers = Collections.synchronizedMap(new HashMap<Integer, Timer>());
/** creates a new StatusPane with the action "Exit Java" as Finish button
* @param ownPane the InstructionsPane instance that will be used*/
public StatusPane(InstructionsPane ownPane) {
this(ownPane, new AbstractAction("Exit Java") {
public void actionPerformed(ActionEvent e) {
new Thread(new Runnable() {
public void run() {
System.exit(0);
}
}).start();
}
}, new AbstractAction("") {
public void actionPerformed(ActionEvent e) {
}
});
cancel.setAction(new AbstractAction("Cancel") {
public void actionPerformed(ActionEvent e) {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
switch (UIMessage.showConfirmDialog(StatusPane.this, "Cancel all ?", "", JOptionPane.YES_NO_CANCEL_OPTION)) {
case JOptionPane.CANCEL_OPTION:
break;
case JOptionPane.YES_OPTION:
ThreadWorks.securizedInvokeLater(new Runnable() {
public void run() {
cancelAll();
}
});
break;
default:
break;
}
}
});
}
/** contructs a new Status pane to state the InstructionsPane
* @param ownPane InstructionsPane owning this StatusPane
* @param action_finish the Action to call when pressing the "finish" button
* @param action_cancel the Action to call when pressing the "cancel" button
*/
public StatusPane(InstructionsPane ownPane, Action action_finish, Action action_cancel) {
super(true);
this.ownPane = ownPane;
ownPane.attachStatusPane(this);
next = new JButton("next >>");
next.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
StatusPane.this.ownPane.nextStep();
}
});
previous = new JButton("<< previous");
previous.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
StatusPane.this.ownPane.previousStep();
}
});
add(previous);
add(next);
if (action_cancel instanceof Action) {
cancel = new JButton(action_cancel);
add(cancel);
} else {
cancel = null;
}
if (action_finish instanceof Action) {
finish = new JButton(action_finish);
add(finish);
} else {
finish = null;
}
updateButtons();
}
protected void updateButtons() {
previous.setEnabled(true);
next.setEnabled(true);
if (finish instanceof JButton) {
finish.setEnabled(false);
}
if (ownPane.getCurrentStep() + 1 >= ownPane.getSteps()) {
next.setEnabled(false);
if (finish instanceof JButton) {
finish.setEnabled(true);
}
}
if (ownPane.getCurrentStep() <= 0) {
previous.setEnabled(false);
}
}
/** This StepListener uses this method to update its status. */
public void stepChanged() {
updateButtons();
validate();
repaint();
}
/** This adds a Thread to active operations n progress.
* @param t Thread to add
* @return the id of the added Thread*/
public int addActiveThread(Thread t) {
SfThread sft = new SfThread(t);
activeThreads.put(sft.hashCode(), sft);
return sft.hashCode();
}
/** returns active Threads Map
* @return active Threads map*/
public Map<Integer, SfThread> getActiveThreads() {
return activeThreads;
}
/** returns an active SfThread identified by its id
* @return the Thread
* @param hashcode the SfThread hashCode id*/
public SfThread getActiveThread(int hashcode) {
return activeThreads.get(hashcode);
}
/** This adds an active Stream that can be stopped or paused by this panel.
* @param stream the stream to add
* @return the stream hashcode id*/
public int addActiveStream(Closeable stream) {
long id = System.nanoTime();
activeStreams.put((int) id, stream);
return (int) id;
}
/** returns active Streams map
* @return active Streams map*/
public Map<Integer, Closeable> getActiveStreams() {
return activeStreams;
}
/** returns an active Stream identified by its id
* @return the active Stream
* @param id the id of the Stream*/
public Closeable getActiveStream(int id) {
return activeStreams.get(id);
}
/** adds an active Timer
* @param timer the timer to add
* @return the Timer id
*/
public int addActiveTimer(javax.swing.Timer timer) {
long id = System.nanoTime();
activeTimers.put((int) id, timer);
return (int) id;
}
/** returns the active Timers map
* @return the active Timers map*/
public Map<Integer, javax.swing.Timer> getActiveTimers() {
return activeTimers;
}
/** returns an active Timer from its id
* @return the active timer
* @param id the id*/
public javax.swing.Timer getActiveTimer(int id) {
return activeTimers.get(id);
}
/** remove an active Thread from the map
* @param t the active Thread to remove
* @return the removed active Thread */
public SfThread removeActiveThread(Thread t) {
SfThread sft = new SfThread(t);
return activeThreads.remove(sft.hashCode());
}
/** cancels all activity */
public void cancelAll() {
Collection<javax.swing.Timer> coll0 = activeTimers.values();
synchronized (activeTimers) {
for (Iterator<javax.swing.Timer> i = coll0.iterator(); i.hasNext();) {
javax.swing.Timer t = i.next();
if (t.isRunning()) {
t.stop();
} else {
i.remove();
}
}
}
Collection<Closeable> coll1 = activeStreams.values();
synchronized (activeStreams) {
for (Iterator<Closeable> i = coll1.iterator(); i.hasNext();) {
Closeable stream = i.next();
try {
stream.close();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
i.remove();
}
}
}
Collection<SfThread> coll2 = activeThreads.values();
synchronized (activeThreads) {
for (Iterator<SfThread> i = coll2.iterator(); i.hasNext();) {
Thread t = i.next().getThread();
boolean locked = true;
while (locked && t.isAlive() && !t.isInterrupted()) {
try {
t.checkAccess();
locked = false;
t.interrupt();
i.remove();
} catch (SecurityException ex) {
locked = true;
}
}
}
}
}
}