package open.dolphin.stampbox;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import open.dolphin.client.LocalStampTreeNodeTransferable;
import open.dolphin.client.OrderList;
import open.dolphin.client.OrderListTransferable;
import open.dolphin.infomodel.*;
/**
* StampTreeTransferHandler
*
* @author Minagawa,Kazushi. Digital Globe, Inc.
*/
public class StampTreeTransferHandler extends TransferHandler {
// Drag元のStampTree
private StampTree sourceTree;
// StampTreeNode Flavor
private final DataFlavor stampTreeNodeFlavor = LocalStampTreeNodeTransferable.localStampTreeNodeFlavor;
// KartePaneからDropされるオーダのFlavor
private final DataFlavor orderFlavor = OrderListTransferable.orderListFlavor;
// KartePaneからDropされるテキストFlavor
private final DataFlavor stringFlavor = DataFlavor.stringFlavor;
// 病名エディタからDropされるRegisteredDiagnosis Flavor
private final DataFlavor infoModelFlavor = InfoModelTransferable.infoModelFlavor;
@Override
protected Transferable createTransferable(JComponent c) {
sourceTree = (StampTree)c;
StampTreeNode dragNode = (StampTreeNode)sourceTree.getLastSelectedPathComponent();
return dragNode!=null ? new LocalStampTreeNodeTransferable(dragNode) : null;
}
@Override
public int getSourceActions(JComponent c) {
return COPY_OR_MOVE;
}
@Override
public boolean importData(TransferHandler.TransferSupport support) {
if (!canImport(support)) {
return false;
}
StampTree target;
String targetEntity;
StampTreeNode parentNode;
int childIndex;
target = (StampTree)support.getComponent();
targetEntity = target.getEntity();
if (support.isDrop()) {
JTree.DropLocation dl = (JTree.DropLocation)support.getDropLocation();
TreePath path = dl.getPath();
childIndex = dl.getChildIndex();
parentNode = (StampTreeNode)path.getLastPathComponent();
} else {
// Paste
StampTreeNode selected = target.getSelectedNode();
parentNode = (StampTreeNode)selected.getParent();
childIndex = parentNode.getIndex(selected);
}
Transferable tr = support.getTransferable();
try {
if (support.isDataFlavorSupported(orderFlavor)) {
//----------------------------------------------
// KartePaneからのオーダースタンプ
//----------------------------------------------
OrderList list = (OrderList)tr.getTransferData(orderFlavor);
ModuleModel importStamp = list.orderList[0]; // ToDo multiple drag & drop
// インポートするentity
String importEntity = importStamp.getModuleInfoBean().getEntity();
if (importEntity.equals(targetEntity)) {
//----------------------------------
// targetとdropが同じentityの場合
//----------------------------------
return target.addStamp(parentNode, importStamp, childIndex);
} else if (labtestRelated(importEntity, targetEntity)) {
//----------------------------------
// Labtest,Physiology,Bacteria間の相互入れ替え
//----------------------------------
importStamp.getModuleInfoBean().setEntity(targetEntity); // entityをDrop先に変換する
return target.addStamp(parentNode, importStamp, childIndex);
} else if (targetEntity.equals(IInfoModel.ENTITY_PATH)) {
//---------------------
// パス Tree の場合
//---------------------
return target.addStamp(parentNode, importStamp, childIndex);
} else {
return false;
}
} else if (support.isDataFlavorSupported(stringFlavor)) {
//-----------------------------------------
// KartePaneからDropされたテキストをインポートする
//-----------------------------------------
String text = (String)tr.getTransferData(stringFlavor);
if (targetEntity.equals(IInfoModel.ENTITY_TEXT) || targetEntity.equals(IInfoModel.ENTITY_PATH)) {
return target.addTextStamp(parentNode, text, childIndex);
} else {
return false;
}
} else if (support.isDataFlavorSupported(infoModelFlavor)) {
//------------------------------------------------------------------
// DiagnosisEditorからDropされた病名をインポートする
// 病名Treeに加え、PathTreeにもDrop可能とする->パススタンプに病名のセットが可能
//------------------------------------------------------------------
RegisteredDiagnosisModel rd = (RegisteredDiagnosisModel)tr.getTransferData(InfoModelTransferable.infoModelFlavor);
if (targetEntity.equals(IInfoModel.ENTITY_DIAGNOSIS) ||
targetEntity.equals(IInfoModel.ENTITY_PATH)) {
return target.addDiagnosis(parentNode, rd, childIndex);
} else {
return false;
}
} else if (support.isDataFlavorSupported(stampTreeNodeFlavor)) {
//-----------------------------------------------
// StampTreeNodeの Drop/Paste
// isDrop()==true は同じTree内のみ(GUIで同じTree内でしかDnDできない)
// paste(!isDrop()) の場合は 同じTree内のcopy/paste もしくは target=drop先が汎用の場合のみ
//-----------------------------------------------
StampTreeNode importNode = (StampTreeNode)tr.getTransferData(stampTreeNodeFlavor);
DefaultMutableTreeNode node = (DefaultMutableTreeNode)importNode;
StampTreeNode root = (StampTreeNode)node.getRoot();
TreeInfo info = (TreeInfo)root.getUserObject();
String importEntity = info.getEntity();
//------------------------------------------------------------------------
// root までの親のパスのなかに自分がいるかどうかを判定する
// Drop先が DragNode の子である時は DnD できない i.e 親が自分の子になることはできない
//------------------------------------------------------------------------
DefaultTreeModel model = (DefaultTreeModel)target.getModel();
TreeNode[] parents = model.getPathToRoot(parentNode);
boolean exist = false;
for (TreeNode parent : parents) {
if (parent == (TreeNode)importNode) {
exist = true;
Toolkit.getDefaultToolkit().beep();
break;
}
}
if (exist) {
return false;
}
if (childIndex < 0) {
childIndex = 0;
}
// dropNodeの親==parentNodeの場合
// childIndexを補正する(dropNodeを最初に削除するため)
if (importNode.getParent()==parentNode) {
int cnt = parentNode.getChildCount();
for (int i = 0; i < cnt; i++) {
if (parentNode.getChildAt(i)==importNode) {
childIndex = childIndex > i ? childIndex-1 : childIndex;
break;
}
}
}
// DnD in the same tree
if (support.isDrop()) {
model.removeNodeFromParent(importNode);
model.insertNodeInto(importNode, parentNode, childIndex);
return true;
} else if (importNode.isLeaf()) {
// pasteは leafのみ StampTreePopupAdapter
// copy paste の場合はcloneをpasteする
ModuleInfoBean dropBean = (ModuleInfoBean)importNode.getUserObject();
try {
ModuleInfoBean clone = (ModuleInfoBean)dropBean.clone();
if (labtestRelated(importEntity, targetEntity)) {
// LabTest, Physio, Bacteria の入れ替え
clone.setEntity(targetEntity);
}
StampTreeNode cloneNode = new StampTreeNode(clone);
model.insertNodeInto(cloneNode, parentNode, childIndex);
return true;
} catch (CloneNotSupportedException ex) {
return false;
}
} else {
return false;
}
} else {
return false;
}
} catch (UnsupportedFlavorException | IOException ue) {
ue.printStackTrace(System.err);
}
return false;
}
@Override
public boolean canImport(TransferHandler.TransferSupport support) {
return (support.isDataFlavorSupported(orderFlavor) ||
support.isDataFlavorSupported(stringFlavor) ||
support.isDataFlavorSupported(infoModelFlavor) ||
support.isDataFlavorSupported(stampTreeNodeFlavor));
}
// 検体検査、生体検査、細菌検査の相互入れ替え
private boolean labtestRelated(String importEntity, String targetEntity) {
boolean match = (importEntity.equals(IInfoModel.ENTITY_LABO_TEST) &&
(targetEntity.equals(IInfoModel.ENTITY_PHYSIOLOGY_ORDER)||targetEntity.equals(IInfoModel.ENTITY_BACTERIA_ORDER)));
match = match || (importEntity.equals(IInfoModel.ENTITY_PHYSIOLOGY_ORDER) &&
(targetEntity.equals(IInfoModel.ENTITY_LABO_TEST)||targetEntity.equals(IInfoModel.ENTITY_BACTERIA_ORDER)));
match = match || (importEntity.equals(IInfoModel.ENTITY_BACTERIA_ORDER) &&
(targetEntity.equals(IInfoModel.ENTITY_LABO_TEST)||targetEntity.equals(IInfoModel.ENTITY_PHYSIOLOGY_ORDER)));
return match;
}
}