package org.xmind.ui.internal.dnd; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.swt.dnd.TransferData; import org.xmind.core.IBoundary; import org.xmind.core.IImage; import org.xmind.core.IRelationship; import org.xmind.core.ISheet; import org.xmind.core.ITopic; import org.xmind.core.ITopicExtension; import org.xmind.core.ITopicExtensionElement; import org.xmind.core.ITopicRange; import org.xmind.core.IWorkbook; import org.xmind.core.marker.IMarker; import org.xmind.core.marker.IMarkerGroup; import org.xmind.core.marker.IMarkerRef; import org.xmind.gef.GEF; import org.xmind.gef.IViewer; import org.xmind.gef.Request; import org.xmind.gef.command.Command; import org.xmind.gef.command.CompoundCommand; import org.xmind.gef.dnd.IDndClient; import org.xmind.gef.part.IPart; import org.xmind.ui.commands.AddBoundaryCommand; import org.xmind.ui.commands.AddMarkerCommand; import org.xmind.ui.commands.AddRelationshipCommand; import org.xmind.ui.commands.AddTopicCommand; import org.xmind.ui.commands.DeleteMarkerCommand; import org.xmind.ui.commands.ModifyFoldedCommand; import org.xmind.ui.commands.ModifyImageAlignmentCommand; import org.xmind.ui.commands.ModifyImageSizeCommand; import org.xmind.ui.commands.ModifyImageSourceCommand; import org.xmind.ui.commands.ModifyRangeCommand; import org.xmind.ui.commands.ModifyRightNumberOfUnbalancedStructureCommand; import org.xmind.ui.commands.ModifyTopicHyperlinkCommand; import org.xmind.ui.internal.branch.UnbalancedData; import org.xmind.ui.mindmap.ITopicPart; import org.xmind.ui.util.MindMapUtils; public abstract class MindMapDNDClientBase implements IDndClient { /** * @deprecated */ public final Object[] toViewerElements(Object transferData, IViewer viewer, Object target) { return null; } public Command makeDNDCommand(Object transferredData, Request request) { IViewer viewer = request.getTargetViewer(); if (viewer == null) return null; ISheet sheet = (ISheet) viewer.getAdapter(ISheet.class); if (sheet == null) return null; IWorkbook workbook = sheet.getOwnedWorkbook(); IPart parent = (IPart) request.getParameter(GEF.PARAM_PARENT); if (parent != null || request.getTargets().size() == 1) { boolean dropInParent = request.getTargets().contains(parent); if (parent == null) { parent = request.getPrimaryTarget(); } ITopic targetParent = findTargetParentTopic(viewer, parent); return makeDNDCommand(transferredData, request, workbook, targetParent, dropInParent, request.getParameter(GEF.PARAM_PARENT) == null); } else if (!request.getTargets().isEmpty()) { List<Command> commands = new ArrayList<Command>(); for (IPart target : request.getTargets()) { ITopic targetParent = findTargetParentTopic(viewer, target); if (targetParent != null) { commands.add(makeDNDCommand(transferredData, request, workbook, targetParent, false, false)); } } return new CompoundCommand(commands); } else { return null; } } private ITopic findTargetParentTopic(IViewer viewer, IPart parent) { Object targetParentModel = MindMapUtils.getRealModel(parent); ITopic targetParent; if (targetParentModel == null || !(targetParentModel instanceof ITopic)) { targetParent = (ITopic) viewer.getAdapter(ITopic.class); } else { targetParent = (ITopic) targetParentModel; } return targetParent; } protected Command makeDNDCommand(Object transferData, Request request, IWorkbook workbook, ITopic targetParent, boolean dropInParent, boolean floating) { Object[] elements = toViewerElements(transferData, request, workbook, targetParent, dropInParent); if (elements == null || elements.length == 0) return null; List<Command> commands = new ArrayList<Command>(); makeDNDCommands(request, workbook, targetParent, elements, commands, floating, dropInParent); return new CompoundCommand(commands); } protected void makeDNDCommands(Request request, IWorkbook workbook, ITopic targetParent, Object[] elements, List<Command> commands, boolean floating, boolean dropInParent) { ISheet sheet = (ISheet) request.getTargetViewer() .getAdapter(ISheet.class); int index = request.getIntParameter(GEF.PARAM_INDEX, -1); int sourceIndex = index; Point position = (Point) request.getParameter(GEF.PARAM_POSITION); int countForUnbalacedStructure = 0; preAdded(targetParent, commands); for (Object element : elements) { if (element instanceof Command) { commands.add((Command) element); } else if (element instanceof ITopic) { if (targetParent != null) { ITopic topic = (ITopic) element; if (floating && position != null) { topic.setPosition(position.x, position.y); commands.add(new AddTopicCommand(topic, targetParent, -1, ITopic.DETACHED)); } else { countForUnbalacedStructure = modifyRightNumeberForUnbalancedStructure( request, targetParent, countForUnbalacedStructure); topic.setPosition(null); commands.add(new AddTopicCommand(topic, targetParent, index, ITopic.ATTACHED)); if (index >= 0) index++; } } } else if (element instanceof IRelationship) { if (sheet != null) { IRelationship relationship = (IRelationship) element; commands.add( new AddRelationshipCommand(relationship, sheet)); } } else if (element instanceof IBoundary) { if (targetParent != null) { IBoundary boundary = (IBoundary) element; commands.add( new AddBoundaryCommand(boundary, targetParent)); } } else if (element instanceof IMarkerRef || element instanceof IMarker) { if (targetParent != null) { IMarker marker = (element instanceof IMarker) ? (IMarker) element : ((IMarkerRef) element).getMarker(); if (marker != null) { String markerId = (element instanceof IMarker) ? ((IMarker) element).getId() : ((IMarkerRef) element).getMarkerId(); if (floating && position != null) { ITopic topic = workbook.createTopic(); topic.setPosition(position.x, position.y); commands.add(new AddTopicCommand(topic, targetParent, -1, ITopic.DETACHED)); commands.add(new AddMarkerCommand(topic, markerId)); return; } else if (!dropInParent) { ITopic topic = workbook.createTopic(); commands.add(new AddTopicCommand(topic, targetParent, index, ITopic.ATTACHED)); commands.add(new AddMarkerCommand(topic, markerId)); return; } IMarkerGroup group = marker.getParent(); if (group.isSingleton()) { for (IMarker m : group.getMarkers()) { if (targetParent.hasMarker(m.getId())) { commands.add(new DeleteMarkerCommand( targetParent, m.getId())); } } } commands.add( new AddMarkerCommand(targetParent, markerId)); } } } else if (element instanceof IImage) { IImage image = (IImage) element; if (targetParent != null) { commands.add(new ModifyImageSourceCommand(targetParent, image.getSource())); commands.add(new ModifyImageSizeCommand(targetParent, image.getWidth(), image.getHeight())); commands.add(new ModifyImageAlignmentCommand(targetParent, image.getAlignment())); } } else if (element instanceof URI) { URI uri = (URI) element; if (targetParent != null) { commands.add(new ModifyTopicHyperlinkCommand(targetParent, uri.toString())); } } } if (countForUnbalacedStructure != 0) { IViewer viewer = request.getTargetViewer(); ITopic centralTopic = (ITopic) viewer.getAdapter(ITopic.class); ITopicExtension extension = centralTopic.createExtension( UnbalancedData.EXTENTION_UNBALANCEDSTRUCTURE); ITopicExtensionElement element = extension.getContent() .getCreatedChild( UnbalancedData.EXTENTIONELEMENT_RIGHTNUMBER); String preDndRightNum = element.getTextContent(); if (preDndRightNum == null) preDndRightNum = String.valueOf(0); int postDndRightNum = Integer.valueOf(preDndRightNum); commands.add(new ModifyRightNumberOfUnbalancedStructureCommand( centralTopic, preDndRightNum, postDndRightNum + countForUnbalacedStructure)); } postAdded(elements, targetParent, sourceIndex, floating, commands); } private void preAdded(ITopic targetParent, List<Command> commands) { ensureParentUnfolded(targetParent, commands); } private void ensureParentUnfolded(ITopic targetParent, List<Command> commands) { if (targetParent.isFolded()) { commands.add(new ModifyFoldedCommand(targetParent, false)); } } private void postAdded(Object[] elements, ITopic targetParent, int sourceIndex, boolean floating, List<Command> commands) { boolean containsTopic = false; for (Object object : elements) { if (object instanceof ITopic) { containsTopic = true; break; } } if (containsTopic && !floating) { if (sourceIndex >= 0) { modifyRanges(targetParent, sourceIndex, commands); } } } private void modifyRanges(ITopic targetParent, int sourceIndex, List<Command> commands) { modifyRanges(targetParent.getBoundaries(), sourceIndex, commands); modifyRanges(targetParent.getSummaries(), sourceIndex, commands); } private void modifyRanges(Collection<? extends ITopicRange> ranges, int sourceIndex, List<Command> commands) { for (ITopicRange range : ranges) { int startIndex = range.getStartIndex(); int endIndex = range.getEndIndex(); if (startIndex >= 0 && endIndex >= 0) { if (startIndex >= sourceIndex) { commands.add(new ModifyRangeCommand(range, startIndex + 1, true)); } if (endIndex >= sourceIndex) { commands.add( new ModifyRangeCommand(range, endIndex + 1, false)); } } } } private int modifyRightNumeberForUnbalancedStructure(Request request, ITopic targetParent, int count) { IViewer viewer = request.getTargetViewer(); if (viewer == null) return count; ITopic centralTopic = (ITopic) viewer.getAdapter(ITopic.class); if (centralTopic == targetParent) { String centralTopicStructure = centralTopic.getStructureClass(); boolean isUnbalancedStructure = centralTopicStructure == null || UnbalancedData.STRUCTUREID_UNBALANCED .equalsIgnoreCase(centralTopicStructure); if (isUnbalancedStructure) { ITopicExtension extension = centralTopic.createExtension( UnbalancedData.EXTENTION_UNBALANCEDSTRUCTURE); ITopicExtensionElement element = extension.getContent() .getCreatedChild( UnbalancedData.EXTENTIONELEMENT_RIGHTNUMBER); String preDndRightNum = element.getTextContent(); if (preDndRightNum == null) preDndRightNum = String.valueOf(0); int postDndRightNum = Integer.valueOf(preDndRightNum); ITopicPart parentPart = (ITopicPart) request .getParameter(GEF.PARAM_PARENT); if (parentPart != null || postDndRightNum <= 2) { if (parentPart != null) { Rectangle bounds = parentPart.getFigure().getBounds(); if (bounds.getCenter() .getDifference((Point) request.getParameter( GEF.PARAM_POSITION_ABSOLUTE)).width < 0) { count++; } } else if (postDndRightNum <= 2) { count++; } } } } return count; } protected Command createModifyImageCommand(ITopic target, String source, int width, int height, String alignment) { List<Command> commands = new ArrayList<Command>(3); commands.add(new ModifyImageSourceCommand(target, source)); commands.add(new ModifyImageSizeCommand(target, width, height)); commands.add(new ModifyImageAlignmentCommand(target, alignment)); return new CompoundCommand(commands); } /** * Subclasses may override this method. * * @param transferData * @param request * @param workbook * @param targetParent * @param dropInParent * TODO * @return */ protected abstract Object[] toViewerElements(Object transferData, Request request, IWorkbook workbook, ITopic targetParent, boolean dropInParent); public boolean canCopy(TransferData transferData, IViewer viewer, Point location, IPart target) { return true; } public boolean canLink(TransferData data, IViewer viewer, Point location, IPart target) { return false; } public boolean canMove(TransferData data, IViewer viewer, Point location, IPart target) { return true; } }