package org.basex.gui.dialog; import static org.basex.core.Text.*; import org.basex.gui.GUI; import org.basex.gui.GUIConstants.Fill; import org.basex.gui.GUIConstants.Msg; import org.basex.gui.layout.BaseXBack; import org.basex.gui.layout.BaseXButton; import static org.basex.gui.layout.BaseXKeys.ENTER; import static org.basex.gui.layout.BaseXKeys.modifier; import org.basex.gui.layout.TableLayout; import org.basex.util.Util; import javax.swing.*; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.net.URI; /** * This class provides the architecture for consistent dialog windows. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public abstract class Dialog extends JDialog { /** Used mnemonics. */ public final StringBuilder mnem = new StringBuilder(); /** Reference to main window. */ public final GUI gui; /** Reference to the root panel. */ final BaseXBack panel; /** Remembers if the window was correctly closed. */ boolean ok; /** Dialog position. */ private int[] loc; /** Key listener, triggering an action with each click. */ final KeyAdapter keys = new KeyAdapter() { @Override public void keyReleased(final KeyEvent e) { if(!modifier(e)) action(ENTER.is(e) ? e.getSource() : null); } }; /** * Default constructor. * @param main reference to main window * @param title dialog title */ Dialog(final GUI main, final String title) { this(main, title, true); } /** * Default constructor. * @param main reference to the main window * @param title dialog title * @param modal modal flag */ Dialog(final GUI main, final String title, final boolean modal) { super(main, title, modal); gui = main; panel = new BaseXBack(new BorderLayout()).border(10, 10, 10, 10); add(panel, BorderLayout.CENTER); setResizable(false); addWindowListener(new WindowAdapter() { @Override public void windowClosing(final WindowEvent e) { cancel(); } }); } /** * Sets a component at the specified {@link BorderLayout} position. * @param comp component to be added * @param pos layout position */ final void set(final Component comp, final String pos) { panel.add(comp, pos); } /** * Finalizes the dialog layout and sets it visible. * @param l optional dialog location, relative to main window */ final void finish(final int[] l) { pack(); if(l == null) setLocationRelativeTo(gui); else setLocation(gui.getX() + l[0], gui.getY() + l[1]); loc = l; setVisible(true); } @Override public void setLocation(final int x, final int y) { final Dimension scr = Toolkit.getDefaultToolkit().getScreenSize(); final int xx = Math.max(0, Math.min(scr.width - getWidth(), x)); final int yy = Math.max(0, Math.min(scr.height - getHeight(), y)); super.setLocation(xx, yy); } /** * Reacts on user input; can be overwritten. * @param comp the action component */ @SuppressWarnings("unused") public void action(final Object comp) { } /** * Cancels the dialog; can be overwritten. */ public void cancel() { ok = false; dispose(); } /** * Closes the dialog and stores the location of the dialog window; * can be overwritten. */ public void close() { ok = true; dispose(); } @Override public void dispose() { if(loc != null) { final Container par = getParent(); loc[0] = getX() - par.getX(); loc[1] = getY() - par.getY(); gui.gprop.write(); } super.dispose(); } /** * States if the dialog window was confirmed or canceled. * @return true when dialog was confirmed */ public final boolean ok() { return ok; } /** * Creates a OK and CANCEL button. * @return button list */ BaseXBack okCancel() { return newButtons(B_OK, B_CANCEL); } /** * Creates a new button list. * @param buttons button names or objects * @return button list */ BaseXBack newButtons(final Object... buttons) { // horizontal/vertical layout final BaseXBack pnl = new BaseXBack(Fill.NONE). border(12, 0, 0, 0).layout(new TableLayout(1, buttons.length, 8, 0)); for(final Object obj : buttons) { final BaseXButton b; if(obj instanceof BaseXButton) { b = (BaseXButton) obj; } else { b = new BaseXButton(obj.toString(), this); } pnl.add(b); } final BaseXBack but = new BaseXBack(Fill.NONE).layout(new BorderLayout()); but.add(pnl, BorderLayout.EAST); return but; } /** * Enables/disables a button in the specified panel. * @param panel button panel * @param label button label * @param enabled enabled/disabled */ static void enableOK(final JComponent panel, final String label, final boolean enabled) { for(final Component c : panel.getComponents()) { if(!(c instanceof JComponent)) { } else if(c instanceof BaseXButton) { final BaseXButton b = (BaseXButton) c; if(b.getText().equals(label)) b.setEnabled(enabled); } else { enableOK((JComponent) c, label, enabled); } } } /** * Static yes/no dialog. Returns a {@code null} reference if the dialog * was canceled. * @param gui parent reference * @param text text * @return true if dialog was confirmed */ public static Boolean yesNoCancel(final GUI gui, final String text) { final DialogMessage msg = new DialogMessage(gui, text.trim(), Msg.YESNOCANCEL); return msg.canceled() ? null : msg.ok(); } /** * Static yes/no dialog. * @param gui parent reference * @param text text * @return true if dialog was confirmed */ public static boolean confirm(final GUI gui, final String text) { return new DialogMessage(gui, text.trim(), Msg.QUESTION).ok(); } /** * Static information dialog. * @param gui parent reference * @param text text */ public static void info(final GUI gui, final String text) { new DialogMessage(gui, text.trim(), Msg.SUCCESS); } /** * Static error dialog. * @param gui parent reference * @param text text */ public static void error(final GUI gui, final String text) { new DialogMessage(gui, text.trim(), Msg.ERROR); } /** * Browses the specified url. * @param gui parent reference * @param url url to be browsed */ public static void browse(final GUI gui, final String url) { try { Desktop.getDesktop().browse(new URI(url)); } catch(final Exception ex) { error(gui, Util.info(H_BROWSER_ERROR_X, URL)); } } }