001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs.relation; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.datatransfer.Transferable; 007import java.awt.datatransfer.UnsupportedFlavorException; 008import java.io.IOException; 009import java.util.ArrayList; 010import java.util.Collection; 011 012import javax.swing.JComponent; 013import javax.swing.JTable; 014import javax.swing.TransferHandler; 015 016import org.openstreetmap.josm.Main; 017import org.openstreetmap.josm.data.osm.OsmPrimitive; 018import org.openstreetmap.josm.data.osm.PrimitiveData; 019import org.openstreetmap.josm.data.osm.RelationMember; 020import org.openstreetmap.josm.data.osm.RelationMemberData; 021import org.openstreetmap.josm.gui.datatransfer.PrimitiveTransferable; 022import org.openstreetmap.josm.gui.datatransfer.RelationMemberTransferable; 023import org.openstreetmap.josm.tools.Utils.Function; 024 025class MemberTransferHandler extends TransferHandler { 026 027 @Override 028 public int getSourceActions(JComponent c) { 029 return COPY_OR_MOVE; 030 } 031 032 @Override 033 protected Transferable createTransferable(JComponent c) { 034 final MemberTable source = (MemberTable) c; 035 return new RelationMemberTransferable(source.getMemberTableModel().getSelectedMembers()); 036 } 037 038 @Override 039 public boolean canImport(TransferSupport support) { 040 support.setShowDropLocation(true); 041 return support.isDataFlavorSupported(RelationMemberTransferable.RELATION_MEMBER_DATA) 042 || support.isDataFlavorSupported(PrimitiveTransferable.PRIMITIVE_DATA); 043 } 044 045 @Override 046 public boolean importData(TransferSupport support) { 047 final MemberTable destination = (MemberTable) support.getComponent(); 048 final int insertRow = ((JTable.DropLocation) support.getDropLocation()).getRow(); 049 050 try { 051 if (support.isDataFlavorSupported(RelationMemberTransferable.RELATION_MEMBER_DATA)) { 052 importRelationMemberData(support, destination, insertRow); 053 } else if (support.isDataFlavorSupported(PrimitiveTransferable.PRIMITIVE_DATA)) { 054 importPrimitiveData(support, destination, insertRow); 055 } 056 } catch (Exception e) { 057 Main.warn(e); 058 return false; 059 } 060 061 return true; 062 } 063 064 protected void importRelationMemberData(TransferSupport support, final MemberTable destination, int insertRow) 065 throws UnsupportedFlavorException, IOException { 066 final RelationMemberTransferable.Data memberData = (RelationMemberTransferable.Data) 067 support.getTransferable().getTransferData(RelationMemberTransferable.RELATION_MEMBER_DATA); 068 importData(destination, insertRow, memberData.getRelationMemberData(), new Function<RelationMemberData, RelationMember>() { 069 @Override 070 public RelationMember apply(RelationMemberData member) { 071 final OsmPrimitive p = destination.getLayer().data.getPrimitiveById(member.getUniqueId(), member.getType()); 072 if (p == null) { 073 Main.warn(tr("Cannot add {0} since it is not part of dataset", member)); 074 return null; 075 } else { 076 return new RelationMember(member.getRole(), p); 077 } 078 } 079 }); 080 } 081 082 protected void importPrimitiveData(TransferSupport support, final MemberTable destination, int insertRow) 083 throws UnsupportedFlavorException, IOException { 084 final PrimitiveTransferable.Data data = (PrimitiveTransferable.Data) 085 support.getTransferable().getTransferData(PrimitiveTransferable.PRIMITIVE_DATA); 086 importData(destination, insertRow, data.getPrimitiveData(), new Function<PrimitiveData, RelationMember>() { 087 @Override 088 public RelationMember apply(PrimitiveData data) { 089 final OsmPrimitive p = destination.getLayer().data.getPrimitiveById(data); 090 if (p == null) { 091 Main.warn(tr("Cannot add {0} since it is not part of dataset", data)); 092 return null; 093 } else { 094 return destination.getMemberTableModel().getRelationMemberForPrimitive(p); 095 } 096 } 097 }); 098 } 099 100 protected <T> void importData(MemberTable destination, int insertRow, 101 Collection<T> memberData, Function<T, RelationMember> toMemberFunction) { 102 final Collection<RelationMember> membersToAdd = new ArrayList<>(memberData.size()); 103 for (T i : memberData) { 104 final RelationMember member = toMemberFunction.apply(i); 105 if (member != null) { 106 membersToAdd.add(member); 107 } 108 } 109 destination.getMemberTableModel().addMembersAtIndex(membersToAdd, insertRow); 110 } 111 112 @Override 113 protected void exportDone(JComponent sourceComponent, Transferable data, int action) { 114 if (action != MOVE) { 115 return; 116 } 117 final MemberTable source = (MemberTable) sourceComponent; 118 final MemberTableModel model = source.getMemberTableModel(); 119 model.remove(source.getSelectedRows()); 120 model.selectionChanged(null); 121 } 122}