package de.netsysit.controller;
import de.netsysit.model.ChangeListModel;
import de.netsysit.model.DataBaseModel;
import de.netsysit.model.PolicyModel;
import de.netsysit.policymanager.PolicyManager;
import de.netsysit.policymanager.PolicyUtilities;
import java.awt.Component;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
import javax.swing.*;
/**
*
* @author Ducksoul
*/
public class DnD {
static class ListMoveDataFlavor extends DataFlavor {
private final ChangeListModel model;
public ListMoveDataFlavor(ChangeListModel model) {
super(ListMoveTransferData.class, "List Data");
this.model = model;
}
public ChangeListModel getModel() {
return model;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((model == null) ? 0 : model.hashCode());
return result;
}
@Override
public boolean equals(DataFlavor that) {
if (this == that) {
return true;
}
if (!super.equals(that) || getClass() != that.getClass()) {
return false;
}
return match(model, that);
}
public static boolean match(ChangeListModel model, DataFlavor flavor) {
return flavor instanceof ListMoveDataFlavor
&& ((ListMoveDataFlavor) flavor).getModel() == model;
}
}
private static class ListMoveTransferData {
private final ChangeListModel model;
private final int[] indices;
ListMoveTransferData(ChangeListModel model, int[] indices) {
this.model = model;
this.indices = indices;
}
int[] getIndices() {
return indices;
}
public ChangeListModel getModel() {
return model;
}
}
static class ListMoveTransferable implements Transferable {
private final ListMoveTransferData data;
public ListMoveTransferable(ListMoveTransferData data) {
this.data = data;
}
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{new ListMoveDataFlavor(data.getModel())};
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return ListMoveDataFlavor.match(data.getModel(), flavor);
}
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (!isDataFlavorSupported(flavor)) {
throw new UnsupportedFlavorException(flavor);
}
return data;
}
}
static class ListMoveTransferHandler extends TransferHandler {
DataBaseModel dbModel = PolicyManager.getPolicyModel();
JList list;
/** Serial version UID */
private static final long serialVersionUID = 6703461043403098490L;
@Override
public int getSourceActions(JComponent c) {
final JList list = (JList) c;
this.list = list;
return list.getModel() instanceof ChangeListModel ? MOVE : NONE;
}
@Override
public Icon getVisualRepresentation(Transferable t) {
return PolicyUtilities.createImageIcon("/images/new_16.png");
}
@Override
public boolean canImport(TransferHandler.TransferSupport info) {
final Component comp = info.getComponent();
final JList.DropLocation location = (JList.DropLocation) info.getDropLocation();
PolicyModel p = null;
List<PolicyModel> policies = null;
// prüfen, ob Komponente eine JList
if (!(comp instanceof JList)) {
return false;
}
final JList list = (JList) comp;
// prüfen, ob Liste als Model ChangeListModel besitzt
if (!(list.getModel() instanceof ChangeListModel)) {
return false;
}
final ChangeListModel model = (ChangeListModel) list.getModel();
// prüfen, ob Flavor unterstützt
final DataFlavor flavor = new ListMoveDataFlavor(model);
if (!info.isDataFlavorSupported(flavor)) {
return false;
}
// auslesen der Policies
switch (dbModel.getActiveLevel()) {
case A:
policies = dbModel.getAPolicies();
break;
case C:
policies = dbModel.getCPolicies();
break;
case I:
policies = dbModel.getIPolicies();
break;
}
// prüfen, der Dragvoraussetzung
if (list.getSelectedIndex() != -1) {
p = (PolicyModel) model.getElementAt(list.getSelectedIndex());
if (PolicyUtilities.getParentPolicy(p, policies) != null) {
return false;
}
// prüfen, der Dropvoraussetzung
int index = location.getIndex();
if (index <= model.getSize() - 1) {
p = (PolicyModel) model.getElementAt(location.getIndex());
if (PolicyUtilities.getParentPolicy(p, policies) == null) {
return true;
} else {
return false;
}
} else {
return true;
}
}
return false;
}
@Override
protected Transferable createTransferable(JComponent c) {
final JList list = (JList) c;
final ChangeListModel model = (ChangeListModel) list.getModel();
// int[] selectedIndices = list.getSelectedIndices();
PolicyModel p = (PolicyModel) model.getElementAt(list.getSelectedIndex());
int count = 1;
int index = list.getSelectedIndex();
while (p.getFallback() != null) {
count++;
p = p.getFallback();
}
int[] selectedIndices = new int[count];
selectedIndices[0] = index;
for (int i = 1; i < count; i++) {
selectedIndices[i] = index + i;
}
return new ListMoveTransferable(new ListMoveTransferData(
(ChangeListModel) list.getModel(), selectedIndices));
}
@Override
public boolean importData(TransferHandler.TransferSupport info) {
final Component comp = info.getComponent();
if (!info.isDrop() || !(comp instanceof JList)) {
return false;
}
final JList list = (JList) comp;
final ListModel lm = list.getModel();
if (!(lm instanceof ChangeListModel)) {
return false;
}
final ChangeListModel listModel = (ChangeListModel) lm;
final DataFlavor flavor = new ListMoveDataFlavor(listModel);
if (!info.isDataFlavorSupported(flavor)) {
return false;
}
final Transferable transferable = info.getTransferable();
try {
final ListMoveTransferData data =
(ListMoveTransferData) transferable.getTransferData(flavor);
// get the initial insertion index
final JList.DropLocation dropLocation = list.getDropLocation();
int insertAt = dropLocation.getIndex();
// get the indices sorted (we use them in reverse order, below)
final int[] indices = data.getIndices();
PolicyModel p = (PolicyModel) lm.getElementAt(indices[0]);
Arrays.sort(indices);
// remove old elements from model, store them on stack
final Stack<Object> elements = new Stack<Object>();
int shift = 0;
for (int i = indices.length - 1; i >= 0; i--) {
final int index = indices[i];
if (index < insertAt) {
shift--;
}
elements.push(listModel.remove(index));
}
insertAt += shift;
// insert stored elements from stack to model
final ListSelectionModel sm = list.getSelectionModel();
try {
sm.setValueIsAdjusting(true);
sm.clearSelection();
final int anchor = insertAt;
while (!elements.isEmpty()) {
listModel.insertElementAt(elements.pop(), insertAt);
sm.addSelectionInterval(insertAt, insertAt++);
}
final int lead = insertAt - 1;
if (!sm.isSelectionEmpty()) {
sm.setAnchorSelectionIndex(anchor);
sm.setLeadSelectionIndex(lead);
}
} finally {
// richtige Selection setzen
list.setSelectedValue(p, true);
int index = list.getSelectedIndex();
sm.setSelectionInterval(index, index);
sm.setValueIsAdjusting(false);
// Ränge neu ordnen
List<PolicyModel> policies = new ArrayList();
for (int i = 0; i < listModel.size(); i++) {
policies.add((PolicyModel) listModel.get(i));
}
PolicyUtilities.setPolicyRanks(policies, true);
}
return true;
} catch (UnsupportedFlavorException ex) {
return false;
} catch (IOException ex) {
// FIXME: Logging
return false;
}
}
}
}