/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* 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 3 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, see http://www.gnu.org/licenses/
*/
package com.bc.ceres.swing.selection.support;
import com.bc.ceres.swing.selection.AbstractSelectionContext;
import com.bc.ceres.swing.selection.Selection;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.ListModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
/**
* A selection provider that wraps a {@link javax.swing.JList}.
* Elements contained in {@link Selection}s handled by this provider
* represent currently selected list objects.
*/
public class ListSelectionContext extends AbstractSelectionContext {
private final ListSelectionListener listSelectionListener;
private JList list;
public ListSelectionContext(final JList list) {
listSelectionListener = new ListSelectionHandler();
this.list = list;
this.list.addListSelectionListener(listSelectionListener);
}
@Override
public Selection getSelection() {
if (list.getSelectedIndex() == -1) {
return DefaultSelection.EMPTY;
}
return new DefaultSelection<Object>(list.getSelectedValues());
}
@Override
public void setSelection(Selection selection) {
if (selection.isEmpty()) {
list.clearSelection();
return;
}
final ListModel listModel = list.getModel();
final Object[] selectedElements = selection.getSelectedValues();
int[] indices = new int[selectedElements.length];
int indexCount = 0;
for (int i = 0; i < listModel.getSize(); i++) {
final Object element = listModel.getElementAt(i);
for (Object selectedElement : selectedElements) {
if (element.equals(selectedElement)) {
indices[indexCount++] = i;
break;
}
}
}
if (indexCount == 0) {
list.clearSelection();
return;
}
if (indexCount < indices.length) {
int[] t = new int[indexCount];
System.arraycopy(indices, 0, t, 0, indexCount);
indices = t;
}
list.setValueIsAdjusting(true);
list.setSelectedIndices(indices);
list.setValueIsAdjusting(false);
}
@Override
public void insert(Transferable transferable) throws IOException, UnsupportedFlavorException {
Object transferData = transferable.getTransferData(DataFlavor.stringFlavor);
if (transferData != null) {
int selectedIndex = list.getSelectedIndex();
if (selectedIndex >= 0) {
((DefaultListModel) list.getModel()).add(selectedIndex, transferData.toString());
} else {
((DefaultListModel) list.getModel()).addElement(transferData.toString());
}
}
}
@Override
public boolean canInsert(Transferable contents) {
return isListEditable()
&& contents.isDataFlavorSupported(DataFlavor.stringFlavor);
}
@Override
public boolean canDeleteSelection() {
return !getSelection().isEmpty() && isListEditable();
}
@Override
public void deleteSelection() {
Object[] items = getList().getSelectedValues();
for (Object item : items) {
((DefaultListModel) getList().getModel()).removeElement(item);
}
// todo - post undoable edit
}
boolean isListEditable() {
return getList().getModel() instanceof DefaultListModel;
}
public JList getList() {
return list;
}
public void setList(JList list) {
if (list != this.list) {
this.list.removeListSelectionListener(listSelectionListener);
this.list = list;
this.list.addListSelectionListener(listSelectionListener);
fireSelectionChange(getSelection());
}
}
protected void handleListSelectionChange(ListSelectionEvent event) {
if (!event.getValueIsAdjusting()) {
fireSelectionChange(getSelection());
}
}
private class ListSelectionHandler implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent event) {
handleListSelectionChange(event);
}
}
}