Created
January 1, 2024 21:38
-
-
Save dhsrocha/4c275de093bcc05f9328814dab94b064 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ludo.adapter.awt; | |
import java.awt.BorderLayout; | |
import java.awt.Dialog; | |
import java.awt.EventQueue; | |
import java.awt.event.ActionEvent; | |
import java.awt.event.KeyEvent; | |
import java.beans.PropertyChangeEvent; | |
import java.beans.PropertyChangeListener; | |
import java.io.BufferedReader; | |
import java.io.InputStreamReader; | |
import java.io.Serializable; | |
import java.util.ArrayList; | |
import java.util.List; | |
import javax.swing.AbstractAction; | |
import javax.swing.BorderFactory; | |
import javax.swing.JButton; | |
import javax.swing.JDialog; | |
import javax.swing.JLabel; | |
import javax.swing.JPanel; | |
import javax.swing.JProgressBar; | |
import javax.swing.JScrollPane; | |
import javax.swing.JTextArea; | |
import javax.swing.SwingConstants; | |
import javax.swing.SwingWorker; | |
import javax.swing.WindowConstants; | |
final class Client { | |
private static final System.Logger LOGGER = System.getLogger(""); | |
private static final System.Logger.Level INFO = System.Logger.Level.INFO; | |
private static final String TITLE = "Swing Worker Example"; | |
private final ExamplePanel panel; | |
Client(final Runnable callback) { | |
this.panel = new ExamplePanel(); | |
this.panel.addPropertyChangeListener(new PropListener(this.panel, callback)); | |
} | |
public static void main(final String[] args) { | |
EventQueue.invokeLater( | |
() -> { | |
LOGGER.log(INFO, "Here I start"); | |
final Runnable cb = () -> LOGGER.log(INFO, "This is being displayed from a Runnable"); | |
new Client(cb).displayGUI(); | |
LOGGER.log(INFO, "This is displayed after the dialog is no longer visible"); | |
}); | |
} | |
private void displayGUI() { | |
final var modal = new JDialog(null, TITLE, Dialog.ModalityType.APPLICATION_MODAL); | |
modal.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); | |
modal.add(panel); | |
modal.pack(); | |
modal.setLocationByPlatform(true); | |
modal.setVisible(true); | |
panel.run(); | |
} | |
private record PropListener(ExamplePanel panel, Runnable callback) | |
implements PropertyChangeListener { | |
@Override | |
public void propertyChange(final PropertyChangeEvent event) { | |
if (event.getNewValue() == SwingWorker.StateValue.DONE) { | |
final var status = panel.getProcessStatus(); | |
LOGGER.log(INFO, "Process State: " + status + "\n"); | |
callback.run(); // simply run it. No need to place into a new thread | |
} | |
} | |
} | |
} | |
final class ExamplePanel extends JPanel implements Runnable { | |
// Components | |
private final JLabel status = new JLabel("Status: ", SwingConstants.CENTER); | |
private final JTextArea textArea = new JTextArea(20, 30); | |
private final JProgressBar bar = new JProgressBar(); | |
// Actions | |
private final StartAction start = new StartAction("Start", KeyEvent.VK_S); | |
private final StopAction stop = new StopAction("Stop", KeyEvent.VK_T); | |
private Worker worker; | |
private int processStatus; | |
ExamplePanel() { | |
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); | |
setLayout(new BorderLayout(5, 5)); | |
final var sp = new JScrollPane(); | |
sp.setBorder(BorderFactory.createTitledBorder("Output: ")); | |
sp.setViewportView(textArea); | |
add(sp, BorderLayout.CENTER); | |
final var buttonTray = new JPanel(); | |
buttonTray.add(new JButton(start)); | |
buttonTray.add(new JButton(stop)); | |
buttonTray.add(bar); | |
add(buttonTray, BorderLayout.PAGE_END); | |
add(status, BorderLayout.PAGE_START); | |
textArea.setFocusable(false); | |
stop.setEnabled(false); | |
} | |
int getProcessStatus() { | |
return processStatus; | |
} | |
@Override | |
public void run() { | |
if (worker != null && !worker.isDone()) { | |
return; // background task not yet done | |
} | |
textArea.setText(""); | |
start.setEnabled(false); | |
stop.setEnabled(true); | |
worker = new Worker(); | |
worker.addPropertyChangeListener(new PropListener(this::printAndDisableComponents)); | |
worker.execute(); | |
bar.setIndeterminate(true); | |
} | |
void cancel() { | |
if (worker != null && !worker.isDone()) { | |
worker.cancel(true); | |
} | |
} | |
void printAndDisableComponents() { | |
status.setText(worker.getState() + " " + processStatus); | |
stop.setEnabled(false); | |
start.setEnabled(true); | |
bar.setIndeterminate(false); | |
} | |
private final class PropListener implements PropertyChangeListener { | |
private final Runnable whenDone; | |
private PropListener(final Runnable whenDone) { | |
this.whenDone = whenDone; | |
} | |
@Override | |
public void propertyChange(final PropertyChangeEvent event) { | |
if (event.getNewValue() == SwingWorker.StateValue.DONE) { | |
whenDone.run(); | |
} | |
firePropertyChange(event.getPropertyName(), event.getOldValue(), event.getNewValue()); | |
} | |
} | |
private final class Worker extends SwingWorker<Integer, String> implements Serializable { | |
@Override | |
protected Integer doInBackground() throws Exception { | |
final var list = new ArrayList<String>(); | |
list.add("ping"); | |
list.add(System.getProperty("os.name").startsWith("Win") ? "-n" : "-c"); | |
list.add("5"); | |
list.add("google.com"); | |
final var pb = new ProcessBuilder(list); | |
pb.redirectErrorStream(true); | |
final var p = pb.start(); | |
String s; | |
final var stdout = new BufferedReader(new InputStreamReader(p.getInputStream())); | |
while ((s = stdout.readLine()) != null && !isCancelled()) { | |
publish(s); | |
} | |
if (!isCancelled()) { | |
processStatus = p.waitFor(); | |
} | |
p.getInputStream().close(); | |
p.getOutputStream().close(); | |
p.getErrorStream().close(); | |
p.destroy(); | |
return processStatus; | |
} | |
@Override | |
protected void process(final List<String> messages) { | |
status.setText((this.getState()).toString()); | |
for (final var m : messages) { | |
textArea.append(m + "\n"); | |
} | |
} | |
} | |
private final class StartAction extends AbstractAction { | |
StartAction(final String name, final int mnemonic) { | |
super(name); | |
putValue(MNEMONIC_KEY, mnemonic); | |
} | |
@Override | |
public void actionPerformed(final ActionEvent e) { | |
run(); | |
} | |
} | |
private final class StopAction extends AbstractAction { | |
public StopAction(final String name, final int mnemonic) { | |
super(name); | |
putValue(MNEMONIC_KEY, mnemonic); | |
} | |
@Override | |
public void actionPerformed(final ActionEvent e) { | |
cancel(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment