package magic.ui.widget.alerter; import java.awt.Cursor; import java.awt.Font; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.concurrent.ExecutionException; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.SwingWorker; import magic.ui.MagicSound; @SuppressWarnings("serial") public abstract class AlertButton extends JButton { private AbstractAction alertAction; /** * The action to perform when the alert button is clicked. */ protected abstract AbstractAction getAlertAction(); /** * Subclass should implement its alert check code and return the text to * show on the alert button if alert is triggered, otherwise empty string. * <p> * Runs on non-EDT so UI is not affected by lengthy alert check. */ protected abstract String getAlertCaption(); AlertButton() { setFont(getFont().deriveFont(Font.BOLD)); setVisible(false); setMouseListener(); setAlertAction(); } private void setAlertAction() { if (alertAction == null) { alertAction = getAlertAction(); setAction(alertAction); } } private void setMouseListener() { addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { super.mouseEntered(e); setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } @Override public void mouseExited(MouseEvent e) { super.mouseExited(e); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } }); } /** * Alert subclass can override with own sound if required. */ protected void playNewAlertSoundEffect() { MagicSound.ALERT.play(); } /** * Runs code specific to alert subclass on non-EDT so that UI * is not affected since alert check may take a while to complete. */ public void doAlertCheck() { new SwingWorker<String, Void>() { @Override protected String doInBackground() throws Exception { return getAlertCaption(); } @Override protected void done() { try { setText(get().trim()); if (!getText().isEmpty()) { playNewAlertSoundEffect(); setVisible(true); } else { setVisible(false); } } catch (InterruptedException | ExecutionException ex) { throw new RuntimeException(ex); } } }.execute(); } }