com.actelion.research.gui.JProgressDialog Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openchemlib Show documentation
Show all versions of openchemlib Show documentation
Open Source Chemistry Library
/*
* Copyright 2017 Idorsia Pharmaceuticals Ltd., Hegenheimermattweg 91, CH-4123 Allschwil, Switzerland
*
* This file is part of DataWarrior.
*
* DataWarrior is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* DataWarrior is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with DataWarrior.
* If not, see http://www.gnu.org/licenses/.
*
* @author Thomas Sander
*/
package com.actelion.research.gui;
import com.actelion.research.calc.ProgressController;
import com.actelion.research.gui.hidpi.HiDPIHelper;
import info.clearthought.layout.TableLayout;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class JProgressDialog extends JDialog implements ActionListener,ProgressController,Runnable {
private static final long serialVersionUID = 0x20070301;
private static final int sActionDispose = 2;
private static final int sActionStart = 4;
private static final int sActionUpdate = 8;
private static final int sActionMessage = 16;
private static final int sActionStop = 32;
private JProgressBar mProgressBar;
private JLabel mProgressLabel,mLabelRemainingTime;
private Frame mNewFrontFrame;
private String mBusyText;
private volatile String mProgressMessage;
private volatile boolean mProcessCancelled;
private volatile int mProgressMin,mProgressMax,mProgressValue,mAction;
private volatile long mProgressStart,mLastUpdate;
private volatile float mProgressFactor;
/**
* Creates a JProgressDialog and schedule it with invokeLater()
* to be set visible without blocking the calling thread.
* @param owner
*/
public JProgressDialog(Frame owner) {
this(owner, true);
}
/**
* Creates a JProgressDialog. If invokeSetVisible is true,
* then the dialog is scheduled to be set visible with invokeLater()
* without blocking the current thread. Otherwise the caller needs
* to call setVisible() manually.
* @param owner
* @param invokeSetVisible
*/
public JProgressDialog(Frame owner, boolean invokeSetVisible) {
// initialized and shows the modal dialog without blocking the thread
super(owner, true);
initialize();
setLocationRelativeTo(owner);
if (invokeSetVisible)
SwingUtilities.invokeLater(() -> setVisible(true) );
}
public void startProgress(String text, int min, int max) {
// may be called safely from any thread
mProgressStart = System.currentTimeMillis();
mBusyText = text;
mProgressMin = min;
mProgressValue = min;
mProgressMax = max;
mProgressFactor = (max - min <= 10000) ? 1.0f : 10000.0f / (max - min);
mAction |= sActionStart;
update();
}
/**
* Update progress status in an absolute or relative way.
* @param value if negative, its abs value is added to current progress.
*/
public void updateProgress(int value) {
// may be called safely from any thread
int newValue = (value >= 0) ? value : mProgressValue-value;
if (mProgressValue < newValue) {
mProgressValue = newValue;
mAction |= sActionUpdate;
update();
}
}
/**
* Update progress status in an absolute or relative way.
* This method also updates the message of the progress dialog
* @param value if negative, its abs value is added to current progress.
* @param message
*/
public void updateProgress(int value, String message) {
// may be called safely from any thread
int newValue = (value >= 0) ? value : mProgressValue-value;
if (mProgressValue < newValue) {
mProgressValue = newValue;
mProgressMessage = message;
mAction |= sActionUpdate | sActionMessage;
update();
}
}
/**
* Sets progress back to zero, hides the progress bar, but keeps the dialog open.
* May be called safely from any thread
*/
public void stopProgress() {
mAction |= sActionStop;
update();
}
/**
* Closes and disposes the dialog.
* If you need to move a newly created window to the front, then use close(Frame newFrontFrame).
* May be called safely from any thread
*/
public void close() {
close(null);
}
/**
* Disposes of the progress dialog and optionally moves the specified
* frame to the front. This may be called safely from any thread.
* @param newFrontFrame null or frame to be moved to the front
*/
public void close(Frame newFrontFrame) {
mAction |= sActionDispose;
mNewFrontFrame = newFrontFrame;
update();
}
public void showErrorMessage(final String message) {
if (SwingUtilities.isEventDispatchThread()) {
showMessage(message);
}
else {
try {
SwingUtilities.invokeAndWait(() -> showMessage(message) );
}
catch (Exception e) {}
}
}
private void showMessage(String message) {
JOptionPane.showMessageDialog(this, message);
}
public boolean threadMustDie() {
return mProcessCancelled;
}
public void actionPerformed(ActionEvent e) {
mProcessCancelled = true;
mAction |= sActionStop;
update();
}
private void initialize() {
double[][] size = { {8, HiDPIHelper.scale(200), 8, TableLayout.PREFERRED, 8},
{8, TableLayout.PREFERRED, 8, TableLayout.PREFERRED, 16, TableLayout.PREFERRED, 8} };
getContentPane().setLayout(new TableLayout(size));
mProgressLabel = new JLabel(" ");
getContentPane().add(mProgressLabel, "1,1,3,1");
mProgressBar = new JProgressBar();
mProgressBar.setVisible(false);
getContentPane().add(mProgressBar, "1,3,3,3");
mLabelRemainingTime = new JLabel();
getContentPane().add(mLabelRemainingTime, "1,5");
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(this);
getContentPane().add(cancelButton, "3,5");
pack();
}
private void update() {
long millis = System.currentTimeMillis();
if ((mAction & ~sActionUpdate) != 0 || millis - mLastUpdate > 100) {
if (SwingUtilities.isEventDispatchThread()) {
mLastUpdate = millis;
run();
}
else {
// try {
mLastUpdate = millis;
SwingUtilities.invokeLater(this);
// }
// catch (Exception e) {}
}
}
}
public void run() {
if ((mAction & sActionDispose) != 0) {
mAction &= ~sActionDispose;
setVisible(false);
dispose();
if (mNewFrontFrame != null)
mNewFrontFrame.toFront();
return;
}
if ((mAction & sActionStart) != 0) {
mAction &= ~sActionStart;
if (mProgressMin == mProgressMax) {
mProgressBar.setIndeterminate(true);
}
else {
mProgressBar.setIndeterminate(false);
mProgressBar.setMinimum(Math.round(mProgressFactor * mProgressMin));
mProgressBar.setMaximum(Math.round(mProgressFactor * mProgressMax));
mProgressBar.setValue(Math.round(mProgressFactor * mProgressMin));
}
mProgressBar.setVisible(true);
mProgressLabel.setText(mBusyText);
}
if ((mAction & sActionUpdate) != 0) {
mAction &= ~sActionUpdate;
mProgressBar.setValue(Math.round(mProgressFactor * mProgressValue));
if (mProgressValue > mProgressMin) {
long milliesUsed = System.currentTimeMillis() - mProgressStart;
long milliesToGo = milliesUsed * (mProgressMax - mProgressValue) / (mProgressValue - mProgressMin);
long millis = (mProgressMax == mProgressMin) ? milliesUsed : milliesToGo;
String timeToShow = (millis >= 7200000) ? ""+(millis/3600000)+" hours"
: (millis >= 120000) ? ""+(millis/60000)+" minutes"
: ""+(millis/1000)+" seconds";
String message = (mProgressMax == mProgressMin) ? " waiting" : " remaining";
mLabelRemainingTime.setText(timeToShow+message);
}
if ((mAction & sActionMessage) != 0) {
mAction &= ~sActionMessage;
mProgressLabel.setText(mProgressMessage);
}
}
if ((mAction & sActionStop) != 0) {
mAction &= ~sActionStop;
mProgressLabel.setText(mProcessCancelled ? "Cancelled; cleaning up..." : "");
if (mProcessCancelled)
mProgressBar.setIndeterminate(true);
else {
mProgressBar.setValue(mProgressBar.getMinimum());
mProgressBar.setVisible(false);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy