/* $Id: UMLAddDialog.java 17881 2010-01-12 21:09:28Z linus $ ***************************************************************************** * Copyright (c) 2009 Contributors - see below * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * tfmorris ***************************************************************************** * * Some portions of this file was previously release using the BSD License: */ // Copyright (c) 1996-2008 The Regents of the University of California. All // Rights Reserved. Permission to use, copy, modify, and distribute this // software and its documentation without fee, and without a written // agreement is hereby granted, provided that the above copyright notice // and this paragraph appear in all copies. This software program and // documentation are copyrighted by The Regents of the University of // California. The software program and documentation are supplied "AS // IS", without any accompanying services from The Regents. The Regents // does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program // was developed for research purposes and is advised not to rely // exclusively on the program for any reason. IN NO EVENT SHALL THE // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. package org.argouml.uml.ui; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; import java.util.Vector; import javax.swing.AbstractListModel; import javax.swing.BorderFactory; import javax.swing.Box; 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.ListCellRenderer; import javax.swing.ListModel; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.WindowConstants; import org.argouml.application.helpers.ResourceLoaderWrapper; import org.argouml.i18n.Translator; import org.argouml.uml.util.SortedListModel; /** * UMLAddDialog is a modal dialog which allows the user to do a multiple select * from a list of choices. The dialog has two possible uses: * <ol> * <li>As dialog as described above with a custom cellrenderer or a default * cellrenderer. * <li>As dialog with a UMLCellRenderer. Cells in the choices list and selected * list are presented with their name instead of their toString function. * </ol> * <p> * <em>NOTE:</em> An incompatible change to the API contract was made between * 0.24 and 0.26. A number of internal methods which had public visibility * were made private. */ public class UMLAddDialog extends JPanel implements ActionListener { /** * The GUI list for the choices */ private JList choicesList = null; /** * The GUI list for the selected choices */ private JList selectedList = null; private JButton addButton = null; private JButton removeButton = null; private JButton okButton = null; private JButton cancelButton = null; private JDialog dialog = null; private String title = null; private boolean multiSelectAllowed = false; /** * The returnvalue of the method showDialog. Returnvalue can be either * JOptionPane.OK_OPTION or JOptionPane.CANCEL_OPTION */ private int returnValue; private boolean exclusive; /** * Constructs a UMLAddDialog with a UMLListCellRenderer. Modelelements are * represented with their names in the choices list and the selected list. * * @param theChoices * A List containing the choices a user has. * @param preselected * A List containing the preselected choices * @param theTitle * The title of the dialog * @param multiselectAllowed * True if the user may select multiple choices * @param isExclusive * True if choices in the selected list may not appear in the * choices list. If true preselected choices are removed from the * choices list. */ public UMLAddDialog(final List theChoices, final List preselected, final String theTitle, final boolean multiselectAllowed, final boolean isExclusive) { this(theChoices, preselected, theTitle, new UMLListCellRenderer2(true), multiselectAllowed, isExclusive); } /** * Constructs a UMLAddDialog with a given UMLListCellRenderer. * * @param theChoices * A List containing the choices a user has. * @param preselected * A List containing the preselected choices * @param theTitle * The title of the dialog * @param renderer * The cellrenderer of the choices list and the selected list * @param multiselectAllowed * True if the user may select multiple choices * @param isExclusive * True if choices in the selected list may not appear in the * choices list. If true preselected choices are removed from the * choices list. */ public UMLAddDialog(final List theChoices, final List preselected, final String theTitle, final ListCellRenderer renderer, final boolean multiselectAllowed, final boolean isExclusive) { multiSelectAllowed = multiselectAllowed; if (theChoices == null) { throw new IllegalArgumentException( "There should always be choices in UMLAddDialog"); } exclusive = isExclusive; List choices = new ArrayList(theChoices); if (isExclusive && preselected != null && !preselected.isEmpty()) { choices.removeAll(preselected); } if (theTitle != null) { title = theTitle; } else { title = ""; } setLayout(new BorderLayout()); JPanel upperPanel = new JPanel(); JPanel panelChoices = new JPanel(new BorderLayout()); JPanel panelSelected = new JPanel(new BorderLayout()); choicesList = new JList(constructListModel(choices)); choicesList.setMinimumSize(new Dimension(150, 300)); if (renderer != null) { choicesList.setCellRenderer(renderer); } if (multiselectAllowed) { choicesList.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); } else { choicesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); } choicesList.setVisibleRowCount(15); JScrollPane choicesScroll = new JScrollPane(choicesList); panelChoices.add(new JLabel(Translator.localize("label.choices")), BorderLayout.NORTH); panelChoices.add(choicesScroll, BorderLayout.CENTER); addButton = new JButton(ResourceLoaderWrapper .lookupIconResource("NavigateForward")); addButton.addActionListener(this); removeButton = new JButton(ResourceLoaderWrapper .lookupIconResource("NavigateBack")); removeButton.addActionListener(this); Box buttonBox = Box.createVerticalBox(); // buttonBox.add(Box.createRigidArea(new Dimension(0, 20))); buttonBox.add(addButton); buttonBox.add(Box.createRigidArea(new Dimension(0, 5))); buttonBox.add(removeButton); selectedList = new JList(constructListModel(preselected)); selectedList.setMinimumSize(new Dimension(150, 300)); if (renderer != null) { selectedList.setCellRenderer(renderer); } selectedList .setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); selectedList.setVisibleRowCount(15); JScrollPane selectedScroll = new JScrollPane(selectedList); panelSelected.add(new JLabel(Translator.localize("label.selected")), BorderLayout.NORTH); panelSelected.add(selectedScroll, BorderLayout.CENTER); upperPanel.add(panelChoices); upperPanel.add(Box.createRigidArea(new Dimension(5, 0))); upperPanel.add(buttonBox); upperPanel.add(Box.createRigidArea(new Dimension(5, 0))); upperPanel.add(panelSelected); // upperPanel.setBorder(BorderFactory.createEtchedBorder()); add(upperPanel, BorderLayout.NORTH); JPanel okCancelPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); okButton = new JButton(Translator.localize("button.ok")); okButton.addActionListener(this); cancelButton = new JButton(Translator.localize("button.cancel")); cancelButton.addActionListener(this); okCancelPanel.add(okButton); okCancelPanel.add(cancelButton); okCancelPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 10)); add(okCancelPanel, BorderLayout.SOUTH); setBorder(BorderFactory.createEmptyBorder(20, 10, 20, 10)); update(); } /* * @see java.awt.event.ActionListener#actionPerformed(ActionEvent) */ public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source.equals(addButton)) { addSelection(); update(); } if (source.equals(removeButton)) { removeSelection(); update(); } if (source.equals(okButton)) { ok(); } if (source.equals(cancelButton)) { cancel(); } } /** * Updates the add and remove button (sets enabled/disabled). Called * whenever the model is changed. */ private void update() { if (choicesList.getModel().getSize() == 0) { addButton.setEnabled(false); } else { addButton.setEnabled(true); } if (selectedList.getModel().getSize() == 0) { removeButton.setEnabled(false); } else { removeButton.setEnabled(true); } if (selectedList.getModel().getSize() > 1 && !multiSelectAllowed) { addButton.setEnabled(false); okButton.setEnabled(false); } else { addButton.setEnabled(true); okButton.setEnabled(true); } } /** * Utility method to construct a AbstractListModel from a List * * @param list the given list * @return AbstractListModel */ protected AbstractListModel constructListModel(List list) { SortedListModel model = new SortedListModel(); if (list != null) { model.addAll(list); } return model; } /** * Shows the dialog. First a dialog must be constructed using one of the * constructors of this class. After that this method should be called to * actually show the dialog. This method returns either * JOptionPane.OK_OPTION if the user wants to select his choices or * JOptionPane.CANCEL_OPTION if he does not want to. * * @param parent * The parent frame of this dialog. * @return int The returnvalue, can be either JOptionPane.OK_OPTION or * JOptionPane.CANCEL_OPTION */ public int showDialog(Component parent) { Frame frame = parent instanceof Frame ? (Frame) parent : (Frame) SwingUtilities .getAncestorOfClass(Frame.class, parent); // String title = getUI().getDialogTitle(this); dialog = new JDialog(frame, title, true); Container contentPane = dialog.getContentPane(); contentPane.setLayout(new BorderLayout()); contentPane.add(this, BorderLayout.CENTER); dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); dialog.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we) { cancel(); } }); dialog.pack(); dialog.setLocationRelativeTo(parent); dialog.setVisible(true); return returnValue; } /** * Returns the choices a user can make. * @return List of choices */ private List getChoices() { List result = new ArrayList(); for (int index : choicesList.getSelectedIndices()) { result.add(choicesList.getModel().getElementAt(index)); } return result; } /** * Returns the selected elements in the selected list * * @return List */ private List getSelectedChoices() { List result = new ArrayList(); for (int index : selectedList.getSelectedIndices()) { result.add(selectedList.getModel().getElementAt(index)); } return result; } /** * Returns the elements of the right-hand "selected" list. Note * that these are not the elements selected (ie highlighted) in the * Swing sense, but rather the entire contents of the list containing * the user selections. * * @return a Vector of selected elements. */ public Vector getSelected() { Vector result = new Vector(); ListModel list = selectedList.getModel(); for (int i = 0; i < list.getSize(); i++) { result.add(list.getElementAt(i)); } return result; } /** * Adds the selected elements in the choices list to the selected list. * */ private void addSelection() { List theChoices = getChoices(); if (exclusive) { ((SortedListModel) choicesList.getModel()).removeAll(theChoices); } ((SortedListModel) selectedList.getModel()).addAll(theChoices); } /** * Removes the selected elements in the selected list and adds them to the * choices list. The GUI will be updated by the ListModel listeners. */ private void removeSelection() { List theChoices = getSelectedChoices(); ((SortedListModel) selectedList.getModel()).removeAll(theChoices); if (exclusive) { ((SortedListModel) choicesList.getModel()).addAll(theChoices); } } /** * Called when the OK button is pressed. Closes this dialog and sets the * return value to JOptionPane.OK_OPTION. */ private void ok() { if (dialog != null) { dialog.setVisible(false); returnValue = JOptionPane.OK_OPTION; } } /** * Called when the cancel button is pressed. Closes this dialog and sets the * returnvalue to JOptionPane.CANCEL_OPTION. The state of any selections * is indeterminate after cancel is called. */ private void cancel() { if (dialog != null) { dialog.setVisible(false); returnValue = JOptionPane.CANCEL_OPTION; } } }