components/visual-panels/core/src/java/util/com/oracle/solaris/vp/util/swing/ListSelector.java
changeset 3553 f1d133b09a8c
parent 3552 077ebe3d0d24
child 3554 ef58713bafc4
equal deleted inserted replaced
3552:077ebe3d0d24 3553:f1d133b09a8c
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 package com.oracle.solaris.vp.util.swing;
       
    27 
       
    28 import java.awt.*;
       
    29 import java.awt.event.*;
       
    30 import javax.swing.*;
       
    31 import javax.swing.event.*;
       
    32 import com.oracle.solaris.vp.util.misc.finder.Finder;
       
    33 import com.oracle.solaris.vp.util.swing.layout.*;
       
    34 
       
    35 @SuppressWarnings({"serial"})
       
    36 public class ListSelector extends JPanel {
       
    37     //
       
    38     // Inner classes
       
    39     //
       
    40 
       
    41     protected class DragDropList extends ExtList {
       
    42 	//
       
    43 	// Constructors
       
    44 	//
       
    45 
       
    46 	public DragDropList(ListModel dataModel) {
       
    47 	    super(dataModel);
       
    48 	    setDragEnabled(true);
       
    49 	    setDropMode(DropMode.INSERT);
       
    50 	    setTransferHandler(handler);
       
    51 	    setFillsViewportHeight(true);
       
    52 	}
       
    53 
       
    54 	//
       
    55 	// DragDropList methods
       
    56 	//
       
    57 
       
    58 	public Boolean getMove() {
       
    59 	    return true;
       
    60 	}
       
    61 
       
    62 	public void setMove(Boolean move) {
       
    63 	    moveSelection(this == rightList);
       
    64 	}
       
    65     }
       
    66 
       
    67     //
       
    68     // Static data
       
    69     //
       
    70 
       
    71     private static final int LIST_VISIBLE_ROWS = 4;
       
    72 
       
    73     //
       
    74     // Instance data
       
    75     //
       
    76 
       
    77     private JList leftList;
       
    78     private JList rightList;
       
    79     private JLabel leftLabel;
       
    80     private JLabel rightLabel;
       
    81     private JButton moveLeftButton;
       
    82     private JButton moveRightButton;
       
    83     private JButton defaultsButton;
       
    84     private Object[] leftData;
       
    85     private Object[] rightData;
       
    86 
       
    87     private TransferHandler handler = new TransferHandler("move") {
       
    88 	@Override
       
    89 	public int getSourceActions(JComponent c) {
       
    90 	    return MOVE;
       
    91 	}
       
    92     };
       
    93 
       
    94     //
       
    95     // Constructors
       
    96     //
       
    97 
       
    98     public ListSelector(DefaultListModel leftModel, DefaultListModel rightModel,
       
    99 	String leftLabelText, String rightLabelText) {
       
   100 
       
   101 	JPanel buttonPanel = createButtonPanel();
       
   102 
       
   103 	leftList = createList(leftModel, moveRightButton);
       
   104 	JScrollPane leftListScroll = new ExtScrollPane(leftList);
       
   105 
       
   106 	rightList = createList(rightModel, moveLeftButton);
       
   107 	JScrollPane rightListScroll = new ExtScrollPane(rightList);
       
   108 
       
   109 	saveAsDefaults();
       
   110 
       
   111 	leftLabel = new JLabel();
       
   112 	setLeftLabel(leftLabelText);
       
   113 
       
   114 	rightLabel = new JLabel();
       
   115 	setRightLabel(rightLabelText);
       
   116 
       
   117 	int gap = GUIUtil.getHalfGap();
       
   118 
       
   119 	AbstractTableConstraint unweighted = new SimpleTableConstraint(gap, 0);
       
   120 	AbstractTableConstraint weighted = new SimpleTableConstraint(gap, 1);
       
   121 
       
   122 	AbstractTableConstraint[] rowConstraints = {
       
   123 	    unweighted, weighted.clone().setGap(0), // unweighted
       
   124 	};
       
   125 
       
   126 	AbstractTableConstraint[] colConstraints = {
       
   127 	    weighted, unweighted, weighted,
       
   128 	};
       
   129 
       
   130 	TableLayout layout = new TableLayout(rowConstraints, colConstraints) {
       
   131 	    @Override
       
   132 	    protected TableInfo getTableInfo(
       
   133 		Container container, boolean preferred) {
       
   134 
       
   135 		TableInfo info = super.getTableInfo(container, preferred);
       
   136 		RowOrColSet set = info.getColumns();
       
   137 
       
   138 		// Make sure columns 0 and 2 are always laid out with the same
       
   139 		// width (the maximum of the two widths)
       
   140 		if (set.getSize(0) < set.getSize(2)) {
       
   141 		    set.setSize(0, set.getSize(2));
       
   142 		} else {
       
   143 		    set.setSize(2, set.getSize(0));
       
   144 		}
       
   145 
       
   146 		return info;
       
   147 	    }
       
   148 	};
       
   149 
       
   150 	setLayout(layout);
       
   151 
       
   152 	HasAnchors a = new SimpleHasAnchors(
       
   153 	    HorizontalAnchor.FILL, VerticalAnchor.FILL);
       
   154 
       
   155 	add(leftLabel, a);
       
   156 	add(createSpacer(), a);
       
   157 	add(rightLabel, a);
       
   158 
       
   159 	add(leftListScroll, a);
       
   160 	add(buttonPanel, a);
       
   161 	add(rightListScroll, a);
       
   162 
       
   163 //	add(createSpacer(), a);
       
   164 //	add(createSpacer(), a);
       
   165 //	add(defaultsButton, new SimpleHasAnchors(
       
   166 //	    HorizontalAnchor.CENTER, VerticalAnchor.CENTER));
       
   167     }
       
   168 
       
   169     public ListSelector(Object[] leftData, Object[] rightData,
       
   170 	String leftLabelText, String rightLabelText) {
       
   171 
       
   172 	this(toModel(leftData), toModel(rightData), leftLabelText,
       
   173 	    rightLabelText);
       
   174     }
       
   175 
       
   176     public ListSelector(DefaultListModel leftModel,
       
   177 	DefaultListModel rightModel) {
       
   178 
       
   179 	this(leftModel, rightModel, null, null);
       
   180     }
       
   181 
       
   182     public ListSelector(Object[] leftData, Object[] rightData) {
       
   183 	this(leftData, rightData, null, null);
       
   184     }
       
   185 
       
   186     //
       
   187     // ListSelector methods
       
   188     //
       
   189 
       
   190     public JButton getDefaultsButton() {
       
   191 	return defaultsButton;
       
   192     }
       
   193 
       
   194     public String getLeftLabel() {
       
   195 	return leftLabel.getText();
       
   196     }
       
   197 
       
   198     public JList getLeftList() {
       
   199 	return leftList;
       
   200     }
       
   201 
       
   202     public JButton getMoveLeftButton() {
       
   203 	return moveLeftButton;
       
   204     }
       
   205 
       
   206     public String getRightLabel() {
       
   207 	return rightLabel.getText();
       
   208     }
       
   209 
       
   210     public JList getRightList() {
       
   211 	return rightList;
       
   212     }
       
   213 
       
   214     public JButton getMoveRightButton() {
       
   215 	return moveRightButton;
       
   216     }
       
   217 
       
   218     public void moveSelection(boolean leftToRight) {
       
   219 	JList srcList, destList;
       
   220 	if (leftToRight) {
       
   221 	    srcList = leftList;
       
   222 	    destList = rightList;
       
   223 	} else {
       
   224 	    srcList = rightList;
       
   225 	    destList = leftList;
       
   226 	}
       
   227 
       
   228 	DefaultListModel srcModel = (DefaultListModel)srcList.getModel();
       
   229 	DefaultListModel destModel = (DefaultListModel)destList.getModel();
       
   230 
       
   231 	int[] selected = srcList.getSelectedIndices();
       
   232 	if (selected.length != 0) {
       
   233 	    destList.clearSelection();
       
   234 
       
   235 	    for (int i = selected.length - 1; i >= 0; i--) {
       
   236 		int index = selected[i];
       
   237 		Object datum = srcModel.getElementAt(index);
       
   238 		destModel.addElement(datum);
       
   239 		srcModel.removeElementAt(index);
       
   240 
       
   241 		index = destModel.indexOf(datum);
       
   242 		if (index != -1) {
       
   243 		    destList.addSelectionInterval(index, index);
       
   244 		    destList.ensureIndexIsVisible(index);
       
   245 		}
       
   246 	    }
       
   247 	}
       
   248     }
       
   249 
       
   250     /**
       
   251      * Reverts the lists to the default state.
       
   252      */
       
   253     public void revertToDefaults() {
       
   254 	DefaultListModel leftModel = (DefaultListModel)getLeftList().getModel();
       
   255 	leftModel.clear();
       
   256 	for (Object datum : leftData) {
       
   257 	    leftModel.addElement(datum);
       
   258 	}
       
   259 
       
   260 	DefaultListModel rightModel =
       
   261 	    (DefaultListModel)getRightList().getModel();
       
   262 	rightModel.clear();
       
   263 	for (Object datum : rightData) {
       
   264 	    rightModel.addElement(datum);
       
   265 	}
       
   266     }
       
   267 
       
   268     /**
       
   269      * Saves the current state of the lists, which can be reverted back to using
       
   270      * the the "defaults" button.
       
   271      */
       
   272     public void saveAsDefaults() {
       
   273 	leftData = ((DefaultListModel)getLeftList().getModel()).toArray();
       
   274 	rightData = ((DefaultListModel)getRightList().getModel()).toArray();
       
   275     }
       
   276 
       
   277     public void setLeftLabel(String text) {
       
   278 	leftLabel.setText(text);
       
   279 	leftLabel.setVisible(text != null);
       
   280     }
       
   281 
       
   282     public void setRightLabel(String text) {
       
   283 	rightLabel.setText(text);
       
   284 	rightLabel.setVisible(text != null);
       
   285     }
       
   286 
       
   287     /**
       
   288      * Sets the prototype cell for each list to be the widest cell of either
       
   289      * list.  Helps to maintain a consistent width between each list.
       
   290      */
       
   291     public void setWidestCellAsPrototype() {
       
   292 	int mWidth = 0;
       
   293 	Object mObject = null;
       
   294 	JList[] lists = new JList[] {getLeftList(), getRightList()};
       
   295 
       
   296 	for (JList list : lists) {
       
   297 	    ListModel model = list.getModel();
       
   298 	    ListCellRenderer renderer = list.getCellRenderer();
       
   299 
       
   300 	    for (int i = 0, n = model.getSize(); i < n; i++) {
       
   301 		Object object = model.getElementAt(i);
       
   302 		Component c = renderer.getListCellRendererComponent(
       
   303 		    list, object, i, false, false);
       
   304 		int width = c.getPreferredSize().width;
       
   305 
       
   306 		if (width > mWidth) {
       
   307 		    mWidth = width;
       
   308 		    mObject = object;
       
   309 		}
       
   310 	    }
       
   311 
       
   312 	}
       
   313 
       
   314 	for (JList list : lists) {
       
   315 	    // May be null
       
   316 	    list.setPrototypeCellValue(mObject);
       
   317 	}
       
   318     }
       
   319 
       
   320     //
       
   321     // Private methods
       
   322     //
       
   323 
       
   324     private JPanel createButtonPanel() {
       
   325 	int gap = GUIUtil.getHalfGap();
       
   326 
       
   327 	moveLeftButton = new JButton(Finder.getString("list.button.moveleft"),
       
   328 	    Finder.getIcon("images/button/moveleft.png"));
       
   329 	moveLeftButton.addActionListener(
       
   330 	    new ActionListener() {
       
   331 		@Override
       
   332 		public void actionPerformed(ActionEvent e) {
       
   333 		    moveSelection(false);
       
   334 		}
       
   335 	    });
       
   336 
       
   337 	moveRightButton = new JButton(Finder.getString("list.button.moveright"),
       
   338 	    Finder.getIcon("images/button/moveright.png"));
       
   339 	moveRightButton.addActionListener(
       
   340 	    new ActionListener() {
       
   341 		@Override
       
   342 		public void actionPerformed(ActionEvent e) {
       
   343 		    moveSelection(true);
       
   344 		}
       
   345 	    });
       
   346 
       
   347 	defaultsButton = new JButton(Finder.getString("list.button.defaults"));
       
   348 	defaultsButton.addActionListener(
       
   349 	    new ActionListener() {
       
   350 		@Override
       
   351 		public void actionPerformed(ActionEvent e) {
       
   352 		    revertToDefaults();
       
   353 		}
       
   354 	    });
       
   355 
       
   356 	ColumnLayout buttonLayout = new ColumnLayout(VerticalAnchor.CENTER);
       
   357 	ColumnLayoutConstraint c = new ColumnLayoutConstraint(
       
   358 	    HorizontalAnchor.CENTER, gap);
       
   359 	JPanel buttonPanel = new JPanel(buttonLayout);
       
   360 	buttonPanel.setOpaque(false);
       
   361 	buttonPanel.add(moveRightButton, c);
       
   362 	buttonPanel.add(moveLeftButton, c);
       
   363 	buttonPanel.add(defaultsButton, c);
       
   364 
       
   365 	return buttonPanel;
       
   366     }
       
   367 
       
   368     private JList createList(ListModel model, final JButton moveButton) {
       
   369 	final JList list = new DragDropList(model);
       
   370 	list.setVisibleRowCount(LIST_VISIBLE_ROWS);
       
   371 
       
   372 	ListSelectionListener moveButtonEnabler =
       
   373 	    new ListSelectionListener() {
       
   374 		@Override
       
   375 		public void valueChanged(ListSelectionEvent e) {
       
   376 		    moveButton.setEnabled(list.getSelectedIndex() != -1);
       
   377 		}
       
   378 	    };
       
   379 
       
   380 	// Initialize button state
       
   381 	moveButtonEnabler.valueChanged(null);
       
   382 
       
   383 	list.addListSelectionListener(moveButtonEnabler);
       
   384 
       
   385 	list.addMouseListener(
       
   386 	    new MouseAdapter() {
       
   387 		@Override
       
   388 		public void mouseClicked(MouseEvent e) {
       
   389 		    if (GUIUtil.isUnmodifiedClick(e, 2)) {
       
   390 			moveButton.doClick(0);
       
   391 		    }
       
   392 		}
       
   393 	    });
       
   394 
       
   395 	return list;
       
   396     }
       
   397 
       
   398     private Component createSpacer() {
       
   399 	Spacer s = new Spacer();
       
   400 	s.setVisible(false);
       
   401 
       
   402 	return s;
       
   403     }
       
   404 
       
   405     //
       
   406     // Static methods
       
   407     //
       
   408 
       
   409     private static DefaultListModel toModel(Object[] data) {
       
   410 	DefaultListModel model = new SortedListModel();
       
   411 
       
   412 	if (data != null) {
       
   413 	    for (Object datum : data) {
       
   414 		model.addElement(datum);
       
   415 	    }
       
   416 	}
       
   417 
       
   418 	return model;
       
   419     }
       
   420 
       
   421     // XXX Unit test -- remove
       
   422     public static void main(String args[]) {
       
   423 	String[] data1 = {
       
   424 	    "one", "two", "three",
       
   425 	    "four", "five", "six",
       
   426 	    "seven", "eight", "nine",
       
   427 	    "ten", "eleven", "twelve",
       
   428 	};
       
   429 
       
   430 	String[] data2 = {
       
   431 	    "1", "2", "3",
       
   432 	    "4", "5", "6",
       
   433 	    "7", "8", "9",
       
   434 	    "10", "11", "12",
       
   435 	};
       
   436 
       
   437 	ListSelector selector =
       
   438 //	    new ListSelector(data1, data2, null, null);
       
   439 	    new ListSelector(data1, data2, "Unselected", "Selected");
       
   440 
       
   441 	JFrame frame = new JFrame();
       
   442 	Container c = frame.getContentPane();
       
   443 	c.setLayout(new BorderLayout());
       
   444 	c.add(selector, BorderLayout.CENTER);
       
   445 	frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
       
   446 	frame.pack();
       
   447 	frame.setVisible(true);
       
   448     }
       
   449 }