[gui-dev] layout patch
Felix Berger <[email protected]> Sun, 27 Feb 2005 19:20:17 +0100
| Newsgroups | gmane.network.gnutella.limewire.gui.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi, while looking around how things are done in Limewire I did polished the ListEditor and the StandardListEditor. The changes for the StandardListEditor are: * use gridbag layout to make the (add, remove) buttons on the right have the same horizontal size. * Removed button row implementation for this purpose, made ButtonRow.BUTTON_SEP public so the buttons still have the same distance from each other * Use Actions internally * no interface changes The changes for ListEditor are: * use gridbag layout for nicer layout of the buttons, the insets can still be tweaked * disable remove button when nothing is selected * enter key in editor field triggers add action * delete key in list triggers remove action * use actions internally * no public interface changes It's all in one patch. Regards, Felix -- Try Debian GNU/Linux! http://www.felix.beldesign.de/ _______________________________________________ gui-dev mailing list [email protected] http://www.limewire.org/mailman/listinfo/gui-dev
layout.patch
(text/x-diff, 14.6 KB)
Index: com/limegroup/gnutella/gui/ListEditor.java
===================================================================
RCS file: /cvs/gui/com/limegroup/gnutella/gui/ListEditor.java,v
retrieving revision 1.16
diff -u -b -B -d -w -U5 -r1.16 ListEditor.java
--- com/limegroup/gnutella/gui/ListEditor.java 10 Feb 2005 21:33:02 -0000 1.16
+++ com/limegroup/gnutella/gui/ListEditor.java 27 Feb 2005 18:02:26 -0000
@@ -1,19 +1,27 @@
package com.limegroup.gnutella.gui;
import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
import java.util.Vector;
-import javax.swing.BoxLayout;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ActionMap;
import javax.swing.DefaultListModel;
+import javax.swing.InputMap;
import javax.swing.JButton;
+import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
+import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
@@ -65,41 +73,67 @@
* @see setModel
*/
public ListEditor(Vector /* of String */ model) {
this.listeners=new Vector();
+ GridBagLayout gl = new GridBagLayout();
+ setLayout(gl);
+
//Top half of the editor
- JPanel controls=new JPanel();
editor=new LimeTextField("");
editor.setColumns(DEFAULT_COLUMNS);
editor.setPreferredSize(new Dimension(500, 20));
editor.setMaximumSize(new Dimension(500, 20));
- addButton =
- new JButton(GUIMediator.getStringResource("LIST_EDITOR_ADD_BUTTON_2"));
- addButton.addActionListener(new AddListener());
- removeButton =
- new JButton(GUIMediator.getStringResource("LIST_EDITOR_REMOVE_BUTTON"));
- removeButton.addActionListener(new RemoveListener());
- controls.setLayout(new BoxLayout(controls, BoxLayout.X_AXIS));
- controls.add(editor);
- controls.add(addButton);
- controls.add(removeButton);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.weightx = 1;
+
+ gl.setConstraints(editor, gbc);
+ add(editor);
+
+ Action addAction = new AddAction();
+ addButton = new JButton(addAction);
+ bindKey(editor, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), addAction);
+
+ gbc = new GridBagConstraints();
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.insets = new Insets(0, ButtonRow.BUTTON_SEP, 0, 0);
+
+ gl.setConstraints(addButton, gbc);
+ add(addButton);
+
+ Action removeAction = new RemoveAction();
+ removeButton = new JButton(removeAction);
+ removeButton.setEnabled(false);
+
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gl.setConstraints(removeButton, gbc);
+ add(removeButton);
//Bottom half of the editor
list=new JList();
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addListSelectionListener(new ListListener());
+ bindKey(list, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), removeAction);
+
JScrollPane scrollPane=new JScrollPane(list,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
setModel(model);
scrollPane.setPreferredSize(new Dimension(500, 50));
scrollPane.setMaximumSize(new Dimension(500, 50));
- //Put them together
- setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
- add(controls);
+ gbc = new GridBagConstraints();
+ gbc.insets = new Insets(ButtonRow.BUTTON_SEP, 0, 0, 0);
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.weighty = 1;
+
+ gl.setConstraints(scrollPane, gbc);
add(scrollPane);
}
/**
* @requires model not subsequently modified
@@ -167,24 +201,59 @@
*/
public synchronized void addListDataListener(ListDataListener listener) {
listeners.add(listener);
}
- /** Someone selected something from the list. */
+ /**
+ * Binds a key stroke to the given action for the component. The action is triggered when the
+ * key is pressed while the component has the keyboard focus.
+ * @param c component for which the keybinding is installed
+ * @param key the key that triggers the action
+ * @param a the action
+ */
+ private void bindKey(JComponent c, KeyStroke key, Action a)
+ {
+ InputMap inputMap = c.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+ ActionMap actionMap = c.getActionMap();
+ if (inputMap != null && actionMap != null) {
+ inputMap.put(key, a);
+ actionMap.put(a, a);
+ }
+
+ }
+
+ /**
+ * Enables the remove button if the selection of the lis is not empty, otherwise disables it.
+ * Also sets the text of the currently selected value in the edit field.
+ */
private class ListListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
+
+ if (list.isSelectionEmpty()) {
+ removeButton.setEnabled(false);
+ }
+ else {
+ removeButton.setEnabled(true);
+ }
+
//Put it in the editor.
Object val=list.getSelectedValue();
if (val==null)
return;
else
editor.setText((String)val);
}
}
/** Someone tried to add something to the list. */
- private class AddListener implements ActionListener {
+ private class AddAction extends AbstractAction {
+
+ public AddAction()
+ {
+ putValue(Action.NAME, GUIMediator.getStringResource("LIST_EDITOR_ADD_BUTTON_2"));
+ }
+
public void actionPerformed(ActionEvent e) {
String text=editor.getText();
//If nothing in editor, ignore
if (text.trim().equals(""))
return;
@@ -226,21 +295,27 @@
editor.setText("");
list.clearSelection();
}
}
- private class RemoveListener implements ActionListener {
+ private class RemoveAction extends AbstractAction
+ {
+
+ public RemoveAction()
+ {
+ putValue(Action.NAME, GUIMediator.getStringResource("LIST_EDITOR_REMOVE_BUTTON"));
+ }
+
/** Someone tried to remove something from the list. */
public void actionPerformed(ActionEvent e) {
//If something is selected, remove it. Notify listeners.
int i=list.getSelectedIndex();
if (i!=-1)
removeItem(i);
}
}
-// public static void main(String args[]) {
// Vector model=new Vector();
// model.addElement("britney");
// model.addElement("n'sync");
// model.addElement("money");
// model.addElement("spam");
Index: com/limegroup/gnutella/gui/StandardListEditor.java
===================================================================
RCS file: /cvs/gui/com/limegroup/gnutella/gui/StandardListEditor.java,v
retrieving revision 1.11
diff -u -b -B -d -w -U5 -r1.11 StandardListEditor.java
--- com/limegroup/gnutella/gui/StandardListEditor.java 12 Oct 2004 21:45:32 -0000 1.11
+++ com/limegroup/gnutella/gui/StandardListEditor.java 27 Feb 2005 18:02:26 -0000
@@ -1,16 +1,22 @@
package com.limegroup.gnutella.gui;
import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Vector;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JList;
+import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
@@ -24,11 +30,11 @@
public final class StandardListEditor {
/**
* Constant handle to the main panel in the editor.
*/
- private final BoxPanel MAIN_PANEL = new BoxPanel(BoxPanel.X_AXIS);
+ private final JPanel MAIN_PANEL = new JPanel(new GridBagLayout());
/**
* Constant handle to the underlying <tt>JList</tt> instance.
*/
private final JList LIST = new JList();
@@ -42,13 +48,23 @@
* Handle to the add button.
*/
private final JButton ADD_BUTTON;
/**
- * Default listener for the add button.
+ * Default add action which delegates to the <code>addListener</code> if it is set.
*/
- private ActionListener _defaultAddListener;
+ private AddAction _addAction;
+
+ /**
+ * Handle to the remove action used for disabling it when no item in the list is selected.
+ */
+ private RemoveAction _removeAction;
+
+ /**
+ * Handle to the set add listener.
+ */
+ private ActionListener _addListener = null;
/**
* Member variable for whether or not the list data has changed
* since the last call to reset this value.
*/
@@ -98,41 +114,40 @@
* for the label in the generic text input component used by default
*/
public StandardListEditor(final String ADD_BUTTON_KEY,
final String REMOVE_BUTTON_KEY,
final String INPUT_FIELD_KEY) {
- String[] buttonLabelKeys = {
- ADD_BUTTON_KEY,
- REMOVE_BUTTON_KEY
- };
- String[] buttonLabelTips = {
- "LIST_EDITOR_ADD_BUTTON_TIP",
- "LIST_EDITOR_REMOVE_BUTTON_TIP"
- };
-
- _defaultAddListener = new AddActionListener(INPUT_FIELD_KEY);
- ActionListener[] buttonListeners = {
- _defaultAddListener,
- new RemoveListener()
- };
-
- ButtonRow buttons = new ButtonRow(buttonLabelKeys,
- buttonLabelTips,
- buttonListeners,
- ButtonRow.Y_AXIS,
- ButtonRow.BOTTOM_GLUE);
+ _addAction = new AddAction(ADD_BUTTON_KEY, INPUT_FIELD_KEY);
+ _removeAction = new RemoveAction(REMOVE_BUTTON_KEY);
- ADD_BUTTON = buttons.getButtonAtIndex(0);
- REMOVE_BUTTON = buttons.getButtonAtIndex(1);
- REMOVE_BUTTON.setEnabled(false);
LIST.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
LIST.addListSelectionListener(new ListEditorSelectionListener());
JScrollPane scrollPane = new JScrollPane(LIST);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.gridheight = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1;
+ gbc.weighty = 1;
+ gbc.fill = GridBagConstraints.BOTH;
+ ((GridBagLayout)MAIN_PANEL.getLayout()).setConstraints(scrollPane, gbc);
MAIN_PANEL.add(scrollPane);
- MAIN_PANEL.add(buttons);
+ gbc = new GridBagConstraints();
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.insets = new Insets(0, 3, ButtonRow.BUTTON_SEP, 0);
+
+ ADD_BUTTON = new JButton(_addAction);
+ ((GridBagLayout)MAIN_PANEL.getLayout()).setConstraints(ADD_BUTTON, gbc);
+ MAIN_PANEL.add(ADD_BUTTON);
+
+ REMOVE_BUTTON = new JButton(_removeAction);
+ ((GridBagLayout)MAIN_PANEL.getLayout()).setConstraints(REMOVE_BUTTON, gbc);
+ MAIN_PANEL.add(REMOVE_BUTTON);
}
/**
* Provides access to the wrapped <tt>Component</tt> of the
* <tt>StandardListEditor</tt>. This is the <tt>Component</tt>
@@ -270,12 +285,11 @@
* Sets the <tt>ActionListener</tt> to use for the add button.
*
* @param addAction the <tt>ActionListener</tt> to use for the add button
*/
private void setAddActionListener(ActionListener addListener) {
- ADD_BUTTON.removeActionListener(_defaultAddListener);
- ADD_BUTTON.addActionListener(addListener);
+ this._addListener = addListener;
}
/**
* Returns whether or not the list has changed since the last
* call to reset the list. Note that this will not be
@@ -301,32 +315,53 @@
/**
* This class responds to a click of the add button and pops
* up a window for the user to enter a new element to add
* to the list.
*/
- private class AddActionListener implements ActionListener {
+ private class AddAction extends AbstractAction {
+
private final String INPUT_FIELD_KEY;
- public AddActionListener(final String key) {
+
+ public AddAction(final String name, final String key) {
+ putValue(Action.NAME, GUIMediator.getStringResource(name));
+ putValue(Action.SHORT_DESCRIPTION, GUIMediator.getStringResource("LIST_EDITOR_ADD_BUTTON_TIP"));
INPUT_FIELD_KEY = key;
}
+
public void actionPerformed(ActionEvent e) {
+
+ // delegate event if there is a special addListener
+ if (_addListener != null) {
+ _addListener.actionPerformed(e);
+ }
+ else {
+
InputFieldDialog dialog = new InputFieldDialog(INPUT_FIELD_KEY);
int returnCode = dialog.showDialog();
if(returnCode == InputFieldDialog.TEXT_ENTERED) {
_listChanged = true;
addElement(dialog.getText());
}
}
}
+ }
/**
* This class responds to a click of the remove button and removes
* the selected element from the list.
*/
- private class RemoveListener implements ActionListener {
+ private class RemoveAction extends AbstractAction {
+
+ public RemoveAction(final String name)
+ {
+ putValue(Action.NAME, GUIMediator.getStringResource(name));
+ putValue(Action.SHORT_DESCRIPTION, GUIMediator.getStringResource("LIST_EDITOR_REMOVE_BUTTON_TIP"));
+ setEnabled(false);
+ }
+
public void actionPerformed(ActionEvent e) {
_listChanged = true;
// return if nothing is selected
if(LIST.isSelectionEmpty()) return;
Index: com/limegroup/gnutella/gui/ButtonRow.java
===================================================================
RCS file: /cvs/gui/com/limegroup/gnutella/gui/ButtonRow.java,v
retrieving revision 1.25
diff -u -b -B -d -w -U5 -r1.25 ButtonRow.java
--- com/limegroup/gnutella/gui/ButtonRow.java 3 Nov 2004 17:01:11 -0000 1.25
+++ com/limegroup/gnutella/gui/ButtonRow.java 27 Feb 2005 18:02:27 -0000
@@ -24,11 +24,11 @@
private JButton[] _buttons;
/**
* The number of pixels separating buttons.
*/
- private final int BUTTON_SEP = 6;
+ public static final int BUTTON_SEP = 6;
/**
* Specifies that the buttons should be aligned along the x axis.
*/
public static final int X_AXIS = BoxLayout.X_AXIS;