// This file is part of PleoCommand: // Interactively control Pleo with psychobiological parameters // // Copyright (C) 2010 Oliver Hoffmann - Hoffmann_Oliver@gmx.de // // This program 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 2 // of the License, or (at your option) any later version. // // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Boston, USA. package pleocmd.itfc.gui; import java.awt.Component; import java.awt.Container; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashMap; import java.util.Map; import javax.swing.JButton; import javax.swing.JLabel; import pleocmd.exc.InternalException; import pleocmd.itfc.gui.icons.IconLoader; public final class Layouter { public enum Button { Ok, Apply, Cancel, Close, Revert, Help, Add, Remove, Clear, Modify, Up, Down, Undo, Redo, Browse, SaveTo, LoadFrom } private static final class ButtonText { final String title; // CS_IGNORE final String icon;// CS_IGNORE final String tooltip;// CS_IGNORE protected ButtonText(final String title, final String icon, final String tooltip) { this.title = title; this.icon = icon; this.tooltip = tooltip; } } private static final Map<Button, ButtonText> DEFAULT = new HashMap<Button, ButtonText>(); private static final int MAX_ROWS = 10 * 1024; private static final int LAST_ROW = MAX_ROWS - 1; private final Container container; private final GridBagConstraints gbc; private int span = 1; private int gridYStored; static { DEFAULT.put(Button.Ok, new ButtonText("Ok", "dialog-ok", "Accept the modifications and close this dialog")); DEFAULT.put(Button.Apply, new ButtonText("Apply", "dialog-ok-apply", "Accept the modifications")); DEFAULT.put(Button.Cancel, new ButtonText("Cancel", "dialog-cancel", "Close this dialog without accepting any modifications")); DEFAULT.put(Button.Close, new ButtonText("Close", "dialog-ok", "Close this dialog while keeping any modifications")); DEFAULT.put(Button.Revert, new ButtonText("Revert", "dialog-cancel", "Close this dialog and revert any modifications")); DEFAULT.put(Button.Help, new ButtonText("Help", "help-contents", "Display context sensitive help")); DEFAULT.put(Button.Add, new ButtonText("Add", "list-add", "Add a new entry to the list")); DEFAULT.put(Button.Remove, new ButtonText("Remove", "list-remove", "Remove all selected entries from the list")); DEFAULT.put(Button.Clear, new ButtonText("Clear", "archive-remove", "Remove all entries from the list")); DEFAULT.put(Button.Modify, new ButtonText("Modify", "document-edit", "Modify the currently focused entry in the list")); DEFAULT.put(Button.Up, new ButtonText("Up", "arrow-up", "Move the currently focused entry one position upwards")); DEFAULT.put(Button.Down, new ButtonText("Down", "arrow-down", "Move the currently focused entry one position downwards")); DEFAULT.put(Button.Undo, new ButtonText("Undo", "edit-undo", "Undo the last action")); DEFAULT.put(Button.Redo, new ButtonText("Redo", "edit-redo", "Repeat the last undone action")); DEFAULT.put(Button.Browse, new ButtonText("...", "edit-rename", "Open a file selection dialog")); DEFAULT.put(Button.SaveTo, new ButtonText("Save To ...", "document-save-as", "Save the document to a file")); DEFAULT.put(Button.LoadFrom, new ButtonText("Load From ...", "document-open", "Load a previously saved document from a file")); } public Layouter(final Container container) { this.container = container; container.setLayout(new GridBagLayout()); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.weightx = 0.0; gbc.weighty = 0.0; gbc.anchor = GridBagConstraints.FIRST_LINE_START; gbc.fill = GridBagConstraints.BOTH; gbc.insets = new Insets(2, 2, 2, 2); gbc.ipadx = 0; gbc.ipady = 0; } public Container getContainer() { return container; } public void add(final Component comp, final boolean greedyX) { gbc.gridwidth = span; gbc.weightx = greedyX ? 1.0 : 0.0; gbc.weighty = 0.0; container.add(comp, gbc); gbc.gridx += span; } public void addWholeLine(final Component comp, final boolean greedyY) { gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1.0; gbc.weighty = greedyY ? 1.0 : 0.0; container.add(comp, gbc); newLine(); } /** * The following components will always appear in the last row no matter how * many components will be inserted afterwards.<br> * This mode stops (and Components will be inserted on the current position * again) after {@link #newLine()} or * {@link #addWholeLine(Component, boolean)} or {@link #addVerticalSpacer()} * is invoked. */ public void nextComponentsAlwaysOnLastLine() { gridYStored = gbc.gridy; gbc.gridy = LAST_ROW; } public void newLine() { gbc.gridx = 0; if (gbc.gridy == LAST_ROW) gbc.gridy = gridYStored; else if (++gbc.gridy == LAST_ROW) throw new InternalException("Too many rows in the Layouter"); } public void addSpacer() { add(new JLabel(), true); } public void addVerticalSpacer() { addWholeLine(new JLabel(), true); } public JButton addButton(final Button button, final Runnable run) { final ButtonText bt = DEFAULT.get(button); if (bt == null) throw new RuntimeException("Missing button in map"); return addButton(bt.title, bt.icon, bt.tooltip, run); } public JButton addButton(final Button button, final String tooltip, final Runnable run) { final ButtonText bt = DEFAULT.get(button); if (bt == null) throw new RuntimeException("Missing button in map"); return addButton(bt.title, bt.icon, tooltip, run); } public JButton addButton(final String title, final String icon, final String tooltip, final Runnable run) { final JButton btn = new JButton(title, IconLoader.getIcon(icon)); btn.setToolTipText(tooltip); btn.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { run.run(); } }); add(btn, false); return btn; } public void setSpan(final int span) { this.span = span; } public int getSpan() { return span; } public void clear() { container.removeAll(); } public static Runnable help(final Window owner, final String category) { return new Runnable() { @Override public void run() { HelpDialog.the(owner).display(category); } }; } }