/*******************************************************************************
* Copyright (c) 2003-2005, 2013 Till Zoppke.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Till Zoppke - initial API and implementation
******************************************************************************/
/*
* Created on 24.02.2004
*/
package eniac.io;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;
import eniac.Manager;
import eniac.lang.Dictionary;
import eniac.util.Status;
import eniac.util.StatusListener;
import eniac.window.EFrame;
/**
* @author zoppke
*/
public class Progressor extends JDialog implements Runnable, StatusListener {
// jpanel as contentpane
private JPanel _panel = new JPanel(new BorderLayout());
// a separate thread is startet in order to show the dialog whith blocking
// all other gui but without blocking the initialization process.
private Thread _thread = null;
// cancel button
private JButton _button = new JButton();
// label to display the current task, its progress we are showing
private JLabel _label = new JLabel(Dictionary.INITIALIZING.getText());
// progressbar to show progress of our
private JProgressBar _progressBar = new JProgressBar();
// ============================ singleton stuff
// =============================
// singleton self reference
private static Progressor instance;
private Progressor() {
// create progressor as modal dialog with eframe as owner
super(EFrame.getInstance(), Dictionary.PLEASE_WAIT.getText(), true);
// add as status listener to be notified when language or runlevel
// changes
Status.LANGUAGE.addListener(this);
Status.LIFECYCLE.addListener(this);
// init components
// _progressBar.setIndeterminate(true);
setAction(null);
_panel.add(_label, BorderLayout.NORTH);
_panel.add(_progressBar, BorderLayout.CENTER);
_panel.add(_button, BorderLayout.SOUTH);
setContentPane(_panel);
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
// bring it to the screen.
pack();
setLocationRelativeTo(EFrame.getInstance());
// start thread that controlles visibility
_thread = new Thread(this);
_thread.start();
}
public static Progressor getInstance() {
if (instance == null) {
instance = new Progressor();
}
return instance;
}
// =============================== methods
// ==================================
public void setAction(Action a) {
// if no action wanted, disable button.
if (a == null) {
a = new AbstractAction(Dictionary.CANCEL.getText()) {
public void actionPerformed(ActionEvent e) {
// empty
}
public boolean isEnabled() {
return false;
}
};
}
// create and add action
_panel.getActionMap().put(a.getValue(Action.NAME), a);
// map action to button
_button.setAction(a);
_button.setEnabled(true);
// fill actionMap
_panel.getActionMap().put(Dictionary.CANCEL, a);
// fill inputMap
_panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), Dictionary.CANCEL);
// adjust inputMaps of buttons
_button.getActionMap().setParent(_panel.getActionMap());
_button.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
Dictionary.CANCEL);
}
public void setText(String text) {
_label.setText(text);
}
public void clear() {
setText(Dictionary.INITIALIZING.getText());
_progressBar.setIndeterminate(true);
}
public void incrementValue() {
_progressBar.setValue(_progressBar.getValue() + 1);
}
public void setProgress(int value, int max) {
_progressBar.setIndeterminate(false);
_progressBar.setValue(value);
_progressBar.setMaximum(max);
}
public void run() {
// run this thread until applet is shutting down.
while (Status.LIFECYCLE.getValue() != Manager.LifeCycle.STOPPED
|| Status.LIFECYCLE.getValue() != Manager.LifeCycle.DESTROYED) {
// show progressor, if applet is busy
if (Status.LIFECYCLE.getValue() != Manager.LifeCycle.RUNNING) {
setVisible(true);
}
// wait until the runlevel changes
synchronized (this) {
if (Status.LIFECYCLE.getValue() == Manager.LifeCycle.BLOCKED) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// applet is shutting down. Hide and dispose progressor.
setVisible(false);
_thread = null;
instance = null;
dispose();
}
public synchronized void statusChanged(Status status, Object newValue) {
assert status == Status.LANGUAGE || status == Status.LIFECYCLE;
switch (status) {
case LANGUAGE :
_button.setText(Dictionary.CANCEL.getText());
setTitle(Dictionary.PLEASE_WAIT.getText());
break;
case LIFECYCLE :
// If applet is idling, hide progressor.
// otherwise notify thread to show it.
if (newValue == Manager.LifeCycle.RUNNING) {
setVisible(false);
}
else if (newValue == Manager.LifeCycle.STOPPED) {
setVisible(false);
notifyAll();
}
else {
notifyAll();
}
break;
default :
break;
}
}
}