/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.internal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.ui.internal.registry.RegistryReader;
import org.xmind.gef.dnd.DndData;
import org.xmind.gef.dnd.IDndClient;
import org.xmind.gef.dnd.IDndSupport;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.prefs.PrefConstants;
import org.xmind.ui.util.Logger;
public class MindMapDndSupport extends RegistryReader implements IDndSupport {
private List<String> ids = null;
private Map<String, DndClientDescriptor> map = null;
private Transfer[] transfers = null;
/* package */MindMapDndSupport() {
}
public DndData parseData(TransferData[] dataTypes, Object source,
boolean usePendingData) {
List<String> clientIds = getClientIds();
for (TransferData dataType : dataTypes) {
for (String clientId : clientIds) {
IDndClient client = getDndClient(clientId);
if (client != null) {
Transfer transfer = client.getTransfer();
if (transfer != null) {
if (transfer.isSupportedType(dataType)) {
Object data = parseData(client, transfer, dataType,
source);
if (data == null && usePendingData) {
data = PENDING_DATA;
}
if (data != null)
return new DndData(clientId, data, dataType);
}
}
}
}
}
return null;
}
private Object parseData(IDndClient dndClient, Transfer transfer,
TransferData transferData, Object source) {
if (source instanceof Clipboard)
return ((Clipboard) source).getContents(transfer);
return dndClient.getData(transfer, transferData);
}
public IDndClient getDndClient(String id) {
DndClientDescriptor desc = getDescriptor(id);
if (desc != null)
return desc.getDndClient();
return null;
}
public DndClientDescriptor getDescriptor(String id) {
return getRegistry().get(id);
}
public String[] getDndClientIds() {
return getClientIds().toArray(new String[0]);
}
private List<String> getClientIds() {
ensureLoaded();
return ids;
}
private Map<String, DndClientDescriptor> getRegistry() {
ensureLoaded();
return map;
}
public int getStyle() {
return DND.DROP_DEFAULT | DND.DROP_COPY | DND.DROP_LINK;
}
public Transfer[] getTransfers() {
if (transfers == null) {
List<String> ids = getClientIds();
ArrayList<Transfer> ts = new ArrayList<Transfer>(ids.size());
for (String id : ids) {
IDndClient dndClient = getDndClient(id);
if (dndClient != null) {
Transfer t = dndClient.getTransfer();
if (t != null) {
ts.add(t);
}
}
}
transfers = ts.toArray(new Transfer[ts.size()]);
}
return transfers;
}
private void ensureLoaded() {
if (ids != null && map != null)
return;
if (Platform.isRunning()) {
readRegistry(Platform.getExtensionRegistry(), MindMapUI.PLUGIN_ID,
RegistryConstants.EXT_DND_CLIENTS);
}
if (ids == null)
ids = Collections.emptyList();
else
sortIds();
if (map == null)
map = Collections.emptyMap();
}
private void registerDndClient(DndClientDescriptor descriptor) {
String id = descriptor.getId();
if (ids == null)
ids = new ArrayList<String>();
ids.add(id);
if (map == null)
map = new HashMap<String, DndClientDescriptor>();
map.put(id, descriptor);
}
private void sortIds() {
MindMapUIPlugin plugin = MindMapUIPlugin.getDefault();
if (plugin != null) {
IPreferenceStore ps = plugin.getPreferenceStore();
final String order = ps
.getString(PrefConstants.DND_CLIENT_ID_ORDER);
if (order != null && !"".equals(order)) { //$NON-NLS-1$
boolean hasDefault = ids
.contains(MindMapUI.DND_MINDMAP_ELEMENT);
if (hasDefault) {
ids.remove(MindMapUI.DND_MINDMAP_ELEMENT);
}
List<String> notOrdered = new ArrayList<String>(ids.size());
for (int i = 0; i < ids.size();) {
String id = ids.get(i);
if (order.contains(id)) {
i++;
} else {
ids.remove(i);
notOrdered.add(id);
}
}
if (ids.size() > 1) {
Collections.sort(ids, new Comparator<String>() {
public int compare(String id1, String id2) {
int index1 = order.indexOf(id1);
int index2 = order.indexOf(id2);
return index1 - index2;
}
});
}
for (String id : notOrdered) {
ids.add(id);
}
if (hasDefault) {
ids.add(0, MindMapUI.DND_MINDMAP_ELEMENT);
}
}
}
}
protected boolean readElement(IConfigurationElement element) {
if (RegistryConstants.TAG_DND_CLIENT.equals(element.getName())) {
readDndClient(element);
return true;
}
return false;
}
private void readDndClient(IConfigurationElement element) {
try {
DndClientDescriptor desc = new DndClientDescriptor(element);
registerDndClient(desc);
} catch (CoreException e) {
Logger.log(e, "Unable to load dnd client: " + element.toString()); //$NON-NLS-1$
}
}
}