Skip to content

Commit

Permalink
GUI: replace ProgressBar with ProgressMonitor
Browse files Browse the repository at this point in the history
  • Loading branch information
pjonsson committed Dec 2, 2022
1 parent 00c3305 commit 6ae6d96
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 45 deletions.
14 changes: 14 additions & 0 deletions java/org/contikios/cooja/Cooja.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.swing.JDesktopPane;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.ProgressMonitor;
import javax.swing.SwingUtilities;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -1903,6 +1905,18 @@ public static void setProgressMessage(String msg, int type) {
}
}

public static void tickProgress() {
if (gui != null) {
gui.tickProgress();
}
}

public static void setMaxProgress(int max) {
if (gui != null) {
gui.setMaxProgress(max);
}
}

/**
* Load quick help for given object or identifier. Note that this method does not
* show the quick help pane.
Expand Down
96 changes: 52 additions & 44 deletions java/org/contikios/cooja/GUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
Expand Down Expand Up @@ -78,7 +77,6 @@
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
Expand All @@ -87,6 +85,7 @@
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.ProgressMonitor;
import javax.swing.RepaintManager;
import javax.swing.SwingWorker;
import javax.swing.Timer;
Expand Down Expand Up @@ -119,7 +118,9 @@ public class GUI {

static JFrame frame;
final JDesktopPane myDesktopPane;
private static JProgressBar PROGRESS_BAR = null;

private ProgressMonitor progressMonitor = null;
private int loadProgress = 0;
private final ArrayList<String> PROGRESS_WARNINGS = new ArrayList<>();

final ArrayList<Class<? extends Plugin>> menuMotePluginClasses = new ArrayList<>();
Expand Down Expand Up @@ -1260,35 +1261,17 @@ public SwingWorker<Simulation, Cooja.SimulationCreationException> createLoadSimW
addToFileHistory(configFile);
}

final JPanel progressPanel;
final JDialog progressDialog;
if (quick) {
final String progressTitle = "Loading " + (configFile == null ? "" : configFile.getAbsolutePath());
progressDialog = new JDialog(frame, progressTitle, Dialog.ModalityType.APPLICATION_MODAL);

progressPanel = new JPanel(new BorderLayout());
var progressBar = new JProgressBar(0, 100);
progressBar.setValue(0);
progressBar.setIndeterminate(true);

PROGRESS_BAR = progressBar; // Allow various parts of Cooja to show messages.

var button = new JButton("Abort");

progressPanel.add(BorderLayout.CENTER, progressBar);
progressPanel.add(BorderLayout.SOUTH, button);
progressPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

progressDialog.getContentPane().add(progressPanel);
progressDialog.setSize(400, 200);

progressDialog.getRootPane().setDefaultButton(button);
progressDialog.setLocationRelativeTo(frame);
progressDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
var file = configFile == null ? cooja.getSimulation().getCfg().file() : configFile.getAbsolutePath();
final String progressTitle = "Loading " + (file == null ? "" : file);
progressMonitor = new ProgressMonitor(frame, progressTitle,"", 0, 6);
progressMonitor.setMillisToDecideToPopup(0);
progressMonitor.setMillisToPopup(0);
progressMonitor.setProgress(0);
} else {
progressPanel = null;
progressDialog = null;
progressMonitor = null;
}
loadProgress = 0;

// SwingWorker can pass information from worker to process() through publish().
// Communicate information the other way through this shared queue.
Expand Down Expand Up @@ -1322,10 +1305,22 @@ public Simulation doInBackground() {
return newSim;
}

private boolean closeProgressMonitor() {
if (progressMonitor != null) {
var cancelled = progressMonitor.isCanceled();
progressMonitor.close();
progressMonitor = null;
loadProgress = 0;
return cancelled;
}
return false;
}

@Override
protected void process(List<Cooja.SimulationCreationException> exs) {
var cancelled = closeProgressMonitor();
for (var e : exs) {
var retry = showErrorDialog("Simulation load error", e, true);
var retry = !cancelled && showErrorDialog("Simulation load error", e, true);
try {
channel.put(retry ? 1 : 0);
} catch (InterruptedException ex) {
Expand All @@ -1337,6 +1332,10 @@ protected void process(List<Cooja.SimulationCreationException> exs) {

@Override
protected void done() {
if (closeProgressMonitor()) {
cooja.doRemoveSimulation();
return;
}
// Simulation loaded, plugins started, now Z-order visualized plugins.
for (int z = 0; z < myDesktopPane.getAllFrames().length; z++) {
for (var plugin : myDesktopPane.getAllFrames()) {
Expand Down Expand Up @@ -1397,19 +1396,8 @@ public void actionPerformed(ActionEvent e) {
dialog.setVisible(true);
}
PROGRESS_WARNINGS.clear();
if (progressDialog != null && progressDialog.isDisplayable()) {
progressDialog.dispose();
}
}
};

if (progressDialog != null) {
java.awt.EventQueue.invokeLater(() -> {
progressPanel.setVisible(true);
progressDialog.getRootPane().getDefaultButton().addActionListener(e -> worker.cancel(true));
progressDialog.setVisible(true);
});
}
return worker;
}

Expand Down Expand Up @@ -1448,10 +1436,30 @@ private void updateDesktopSize() {
myDesktopPane.revalidate();
}

public void tickProgress() {
if (progressMonitor != null) {
progressMonitor.setProgress(++loadProgress);
repaintProgress(progressMonitor);
}
}

public void setMaxProgress(int max) {
if (progressMonitor != null) {
progressMonitor.setMaximum(max);
repaintProgress(progressMonitor);
}
}

/** Forces an immediate repaint of the progress monitor. */
private static void repaintProgress(ProgressMonitor pm) {
if (pm.getAccessibleContext().getAccessibleParent() instanceof JDialog dialog) {
dialog.paintAll(dialog.getGraphics());
}
}

public void setProgressMessage(String msg, int type) {
if (PROGRESS_BAR != null && PROGRESS_BAR.isShowing()) {
PROGRESS_BAR.setString(msg);
PROGRESS_BAR.setStringPainted(true);
if (progressMonitor != null && !progressMonitor.isCanceled()) {
progressMonitor.setNote(msg);
}
if (type != MessageListUI.NORMAL) {
PROGRESS_WARNINGS.add(msg);
Expand Down
7 changes: 6 additions & 1 deletion java/org/contikios/cooja/Simulation.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ public Simulation(SimConfig cfg, Cooja cooja, String title, boolean generateSeed
}, "sim");
simulationThread.start();
if (root != null) {
var numMoteTypes = root.getChild("simulation").getChildren("motetype").size();
var numPlugins = root.getChildren("plugin").size();
Cooja.setMaxProgress(numMoteTypes + numPlugins);
// Track identifier of mote types to deal with the legacy-XML format that used <motetype_identifier>.
var moteTypesMap = new HashMap<String, MoteType>();
// Parse elements
Expand Down Expand Up @@ -308,6 +311,7 @@ public Simulation(SimConfig cfg, Cooja cooja, String title, boolean generateSeed
throw new MoteType.MoteTypeCreationException("Mote type was not created: " + element.getText().trim());
}
addMoteType(moteType);
Cooja.tickProgress();
for (var mote : element.getChildren("mote")) {
createMote(moteType, mote);
}
Expand Down Expand Up @@ -409,7 +413,7 @@ private SimulationCreationException startPlugins(Element root, Cooja cooja) {
logger.warn("Old simulation config detected: visualizers have been remade");
pluginClassName = "org.contikios.cooja.plugins.Visualizer";
}

Cooja.setProgressMessage("Starting " + pluginClassName);
var pluginClass = cooja.tryLoadClass(this, Plugin.class, pluginClassName);
if (pluginClass == null) {
logger.fatal("Could not load plugin class: " + pluginClassName);
Expand Down Expand Up @@ -438,6 +442,7 @@ private SimulationCreationException startPlugins(Element root, Cooja cooja) {
}
return new SimulationCreationException("Failed to start plugin: " + ex.getMessage(), ex);
}
Cooja.tickProgress();
}
// Non-GUI Cooja requires a simulation controller, ensure one is started.
if (!Cooja.isVisualized() && !hasController) {
Expand Down

0 comments on commit 6ae6d96

Please sign in to comment.