/*FreeMind - A Program for creating and viewing Mindmaps
*Copyright (C) 2000-2006 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitri Polivaev and others.
*
*See COPYING for Details
*
*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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package freemind.modes.mindmapmode.attributeactors;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import freemind.controller.filter.util.SortedListModel;
import freemind.main.Resources;
import freemind.main.Tools;
public class ListDialog extends JDialog {
private final class TextChangeListener implements DocumentListener {
private void update() {
updateButtons();
}
public void insertUpdate(DocumentEvent e) {
update();
}
public void removeUpdate(DocumentEvent e) {
update();
}
public void changedUpdate(DocumentEvent e) {
update();
}
}
private final class ListSelectionChangeListener implements
ListSelectionListener {
/*
* (non-Javadoc)
*
* @see
* javax.swing.event.ListSelectionListener#valueChanged(javax.swing.
* event.ListSelectionEvent)
*/
public void valueChanged(ListSelectionEvent e) {
int minIndex = list.getMinSelectionIndex();
int maxIndex = list.getMaxSelectionIndex();
if (minIndex == maxIndex && minIndex != -1) {
textField.setText(data.getElementAt(minIndex).toString());
selectText();
}
updateButtons();
}
}
private class AddAction implements ActionListener {
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
* )
*/
public void actionPerformed(ActionEvent e) {
data.add(getCurrentText());
addButton.setEnabled(false);
selectText();
}
}
private class RenameAction implements ActionListener {
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
* )
*/
public void actionPerformed(ActionEvent e) {
Object[] selectedValues = list.getSelectedValues();
for (int i = 0; i < selectedValues.length; i++) {
if (!selectedValues[i].equals(getCurrentText())) {
data.replace(selectedValues[i], getCurrentText());
}
}
renameButton.setEnabled(false);
list.clearSelection();
selectText();
}
}
private class DeleteAction implements ActionListener {
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
* )
*/
public void actionPerformed(ActionEvent e) {
Object[] selectedValues = list.getSelectedValues();
for (int i = 0; i < selectedValues.length; i++) {
data.remove(selectedValues[i]);
}
if (data.getSize() == 0) {
data.add("");
}
list.clearSelection();
}
}
private class CloseAction implements ActionListener {
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
* )
*/
public void actionPerformed(ActionEvent e) {
ListDialog.dialog.dispose();
}
}
private static ListDialog dialog;
private JList list;
private JButton addButton;
private JButton renameButton;
private JButton deleteButton;
private JTextField textField;
private SortedListModel data = null;
public static void showDialog(Component frameComp, Component locationComp,
String labelText, String title, SortedListModel possibleValues,
String longValue) {
Frame frame = JOptionPane.getFrameForComponent(frameComp);
dialog = new ListDialog(frame, locationComp, labelText, title,
possibleValues, longValue);
Tools.addEscapeActionToDialog(dialog);
dialog.show();
}
/**
*
*/
private void updateButtons() {
String text = getCurrentText();
boolean isNewText = -1 == getIndexOf(text);
addButton.setEnabled(isNewText);
int minSelectionIndex = list.getMinSelectionIndex();
renameButton.setEnabled(minSelectionIndex != -1);
deleteButton.setEnabled(minSelectionIndex != -1);
}
private String getCurrentText() {
Document document = textField.getDocument();
try {
String text = document.getText(0, document.getLength());
return text;
} catch (BadLocationException e) {
freemind.main.Resources.getInstance().logException(e);
return "";
}
}
private void selectText() {
textField.requestFocus();
textField.select(0, textField.getDocument().getLength());
}
private ListDialog(Frame frame, Component locationComp, String labelText,
String title, final SortedListModel data, String longValue) {
super(frame, title, true);
this.data = data;
// Create and initialize the buttons.
final JButton closeButton = new JButton();
Tools.setLabelAndMnemonic(closeButton, Resources.getInstance()
.getResourceString("close"));
closeButton.addActionListener(new CloseAction());
getRootPane().setDefaultButton(closeButton);
addButton = new JButton();
Tools.setLabelAndMnemonic(addButton, Resources.getInstance()
.getResourceString("add"));
AddAction addAction = new AddAction();
addButton.addActionListener(addAction);
renameButton = new JButton();
Tools.setLabelAndMnemonic(renameButton, Resources.getInstance()
.getResourceString("rename"));
renameButton.addActionListener(new RenameAction());
deleteButton = new JButton();
Tools.setLabelAndMnemonic(deleteButton, Resources.getInstance()
.getResourceString("delete"));
deleteButton.addActionListener(new DeleteAction());
textField = new JTextField(20);
textField.getDocument().addDocumentListener(new TextChangeListener());
// main part of the dialog
list = new JList(data) {
// Subclass JList to workaround bug 4832765, which can cause the
// scroll pane to not let the user easily scroll up to the beginning
// of the list. An alternative would be to set the unitIncrement
// of the JScrollBar to a fixed value. You wouldn't get the nice
// aligned scrolling, but it should work.
public int getScrollableUnitIncrement(Rectangle visibleRect,
int orientation, int direction) {
int row;
if (orientation == SwingConstants.VERTICAL && direction < 0
&& (row = getFirstVisibleIndex()) != -1) {
Rectangle r = getCellBounds(row, row);
if ((r.y == visibleRect.y) && (row != 0)) {
Point loc = r.getLocation();
loc.y--;
int prevIndex = locationToIndex(loc);
Rectangle prevR = getCellBounds(prevIndex, prevIndex);
if (prevR == null || prevR.y >= r.y) {
return 0;
}
return prevR.height;
}
}
return super.getScrollableUnitIncrement(visibleRect,
orientation, direction);
}
};
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
if (longValue != null) {
list.setPrototypeCellValue(longValue); // get extra space
}
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(-1);
list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
addButton.doClick(); // emulate button click
}
}
});
list.setModel(data);
list.addListSelectionListener(new ListSelectionChangeListener());
JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(new Dimension(250, 80));
listScroller.setAlignmentX(LEFT_ALIGNMENT);
// Create a container so that we can add a title around
// the scroll pane. Can't add a title directly to the
// scroll pane because its background would be white.
// Lay out the label and scroll pane from top to bottom.
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
JLabel label = new JLabel(labelText);
label.setLabelFor(list);
listPane.add(label);
listPane.add(Box.createRigidArea(new Dimension(0, 5)));
listPane.add(listScroller);
listPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// Lay out the buttons from left to right.
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
buttonPane.add(closeButton);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPane.add(addButton);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPane.add(renameButton);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPane.add(deleteButton);
JPanel textPane = new JPanel();
textPane.setLayout(new BoxLayout(textPane, BoxLayout.LINE_AXIS));
textPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
textPane.add(textField);
// Put everything together, using the content pane's BorderLayout.
Container contentPane = getContentPane();
contentPane.add(textPane, BorderLayout.PAGE_START);
contentPane.add(listPane, BorderLayout.CENTER);
contentPane.add(buttonPane, BorderLayout.PAGE_END);
// Initialize values.
updateButtons();
pack();
setLocationRelativeTo(locationComp);
}
private int getIndexOf(String text) {
for (int i = 0; i < data.getSize(); i++) {
if (data.getElementAt(i).toString().equals(text))
return i;
}
return -1;
}
}