/*******************************************************************************
* Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada
* and IBM Corporation. All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* The Chisel Group, University of Victoria
*******************************************************************************/
package net.sourceforge.tagsea.core.ui.internal.tags;
import java.lang.reflect.InvocationTargetException;
import net.sourceforge.tagsea.TagSEAPlugin;
import net.sourceforge.tagsea.core.ITag;
import net.sourceforge.tagsea.core.IWaypoint;
import net.sourceforge.tagsea.core.TagSEAOperation;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
/**
* Drop adapter for the tags view.
* @author Del Myers
*/
public class TagsViewDropListener extends DropTargetAdapter {
/* (non-Javadoc)
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragEnter(org.eclipse.swt.dnd.DropTargetEvent)
*/
@Override
public void dragEnter(DropTargetEvent event) {
event.detail = DND.DROP_NONE;
for (TransferData type : event.dataTypes) {
if (TagTreeItemTransfer.getInstance().isSupportedType(type)) {
event.detail = DND.DROP_MOVE;
event.currentDataType = type;
return;
}
}
}
/* (non-Javadoc)
* @see org.eclipse.swt.dnd.DropTargetAdapter#drop(org.eclipse.swt.dnd.DropTargetEvent)
*/
@Override
public void drop(DropTargetEvent event) {
TreeItem item = (TreeItem) event.item;
if (TagTreeItemTransfer.getInstance().isSupportedType(event.currentDataType)) {
TagTreeItem[] tagItems = (TagTreeItem[]) event.data;
if (item != null) {
renameTags((TagTreeItem) item.getData(), tagItems);
} else {
//null to make it have no parent.
renameTags(null, tagItems);
}
}
}
public void dragOver(DropTargetEvent event) {
TagsTree tree = null;
Object data = null;
if (event.widget instanceof DropTarget) {
Widget control = ((DropTarget)event.widget).getControl();
data = control.getData();
} else {
data = event.widget.getData();
}
if (data instanceof Object[]) {
for (Object o : ((Object[])data)) {
if (o instanceof TagsTree) {
tree = (TagsTree) o;
break;
}
}
} else if (data instanceof TagsTree) {
tree = (TagsTree) data;
}
if (tree != null && tree.isFlat()) {
event.operations = DND.DROP_NONE;
event.detail = DND.DROP_NONE;
event.feedback = DND.FEEDBACK_NONE;
} else {
event.feedback = DND.FEEDBACK_INSERT_AFTER | DND.FEEDBACK_SCROLL;
}
}
/**
* @param item the new parent, or null if it is to be top-level.
* @param tagItems
*/
private void renameTags(final TagTreeItem newParent, final TagTreeItem[] tagItems) {
TagSEAPlugin.run(new TagSEAOperation("Moving Tags...") {
@Override
public IStatus run(IProgressMonitor monitor) throws InvocationTargetException {
monitor.beginTask("Moving Tags....", tagItems.length);
String newParentName = (newParent != null) ? newParent.getName() : "";
MultiStatus status = new MultiStatus(TagSEAPlugin.PLUGIN_ID, IStatus.OK, "", null);
for (TagTreeItem item : tagItems) {
TagTreeItem parent = item.getParent();
//no need to move if the parents are equal.
if ((parent == null && newParent == null) || ((parent != null && parent.equals(newParent))))
continue;
status.merge(reparentChildren(item, parent, newParentName));
}
return status;
}
private IStatus reparentChildren(TagTreeItem item, TagTreeItem parent, String newParentName) {
ITag tag = item.getTag();
MultiStatus status = new MultiStatus(TagSEAPlugin.PLUGIN_ID, IStatus.OK, "", null);
if (tag != null) {
String oldParentName = (parent != null) ? parent.getName() : "";
String name = item.getName();
name = name.substring(oldParentName.length());
if (!name.startsWith(".")) {
name = "." + name;
}
name = newParentName + name;
if (name.startsWith(".")) {
//remove leading periods: this should be a top-level tag.
char c = name.charAt(0);
int i = 1;
while (c == '.' && i < name.length()) {
c = name.charAt(i);
i++;
}
name = name.substring(i-1);
}
if (!tag.setName(name)) {
moveWaypoints(tag, name);
}
}
for (TagTreeItem child : item.getChildren()) {
status.merge(reparentChildren(child, parent, newParentName));
}
return Status.OK_STATUS;
}
/**
* Moves the waypoints for the given tag to the new name
* if the name already exists.
* @param tag
* @param name
*/
private void moveWaypoints(ITag tag, String name) {
if (TagSEAPlugin.getTagsModel().getTag(name) != null) {
for (IWaypoint wp : tag.getWaypoints()) {
//add the new tag first in order to avoid problems
//of removing the waypoint entirely.
wp.addTag(name);
wp.removeTag(tag);
}
}
}
}, true);
}
}