/** * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. * * Copyright 2012-2015 the original author or authors. */ package org.assertj.swing.test.swing; import static javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.util.Lists.newArrayList; import static org.assertj.swing.edt.GuiActionRunner.execute; import java.util.List; import javax.swing.DefaultListModel; import javax.swing.JList; import org.assertj.swing.annotation.RunsInCurrentThread; import org.assertj.swing.annotation.RunsInEDT; /** * <p> * {@code JList} that requires a name and supports drag and drop. * </p> * * <p> * Adapted from the tutorial <a href="http://java.sun.com/docs/books/tutorial/uiswing/dnd/intro.html" * target="_blank">Introduction to Drag and Drop and Data Transfer</a>. * </p> * * @author Alex Ruiz * @author Yvonne Wang */ public final class TestList extends JList { final DefaultListModel model = new DefaultListModel(); @RunsInCurrentThread public TestList(String... elements) { this(null, newArrayList(elements)); } @RunsInCurrentThread public TestList(String name, List<String> elements) { setDragEnabled(true); setSelectionMode(MULTIPLE_INTERVAL_SELECTION); for (String e : elements) { model.addElement(e); } setModel(model); setName(name); setTransferHandler(new ListTransferHandler()); } @RunsInEDT public String[] elements() { return execute(() -> { int count = model.getSize(); String[] elements = new String[count]; for (int i = 0; i < count; i++) { elements[i] = (String) model.get(i); } return elements; }); } @RunsInEDT public void requireElements(String... expected) { assertThat(elements()).isEqualTo(expected); } private static class ListTransferHandler extends StringTransferHandler<JList> { ListTransferHandler() { super(JList.class); } // Bundle up the selected items in the list as a single string, for export. @Override protected String exportString(JList list) { rows = list.getSelectedIndices(); Object[] values = list.getSelectedValues(); StringBuilder b = new StringBuilder(); for (int i = 0; i < values.length; i++) { Object val = values[i]; b.append(val == null ? "" : val.toString()); if (i != values.length - 1) { b.append("\n"); } } return b.toString(); } // Take the incoming string and wherever there is a newline, break it into a separate item in the list. @Override protected void importString(JList target, String s) { DefaultListModel listModel = (DefaultListModel) target.getModel(); int index = target.getSelectedIndex(); // Prevent the user from dropping data back on itself. if (rows != null && index >= rows[0] - 1 && index <= rows[rows.length - 1]) { rows = null; return; } int max = listModel.getSize(); if (index < 0) { index = max; } else { index++; if (index > max) { index = max; } } addIndex = index; String[] values = s.split("\n"); addCount = values.length; for (String value : values) { listModel.add(index++, value); } } // If the remove argument is true, the drop has been successful and it's time to remove the selected items from the // list. If the remove argument is false, it was a Copy operation and the original list is left intact. @Override protected void cleanup(JList source, boolean remove) { if (remove && rows != null) { DefaultListModel model = (DefaultListModel) source.getModel(); // If we are moving items around in the same list, we need to adjust the indices accordingly, since those after // the insertion point have moved. if (addCount > 0) { for (int i = 0; i < rows.length; i++) { if (rows[i] > addIndex) { rows[i] += addCount; } } } for (int i = rows.length - 1; i >= 0; i--) { model.remove(rows[i]); } } } } }