blob: 30096b6f89674d131835291d12d7cf7f0dd607eb [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2012, 2019 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.rtm.base.ui.rexpr;
import static org.eclipse.statet.rtm.base.ui.rexpr.RExprTypeUIAdapter.PRIORITY_DEFAULT;
import static org.eclipse.statet.rtm.base.ui.rexpr.RExprTypeUIAdapter.PRIORITY_INVALID;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.statet.ecommons.emf.core.IContext;
import org.eclipse.statet.ecommons.models.core.util.ElementSourceProvider;
import org.eclipse.statet.rtm.rtdata.types.RTypedExpr;
class RExprViewerDropAdapter extends ViewerDropAdapter {
private final List<RExprTypeUIAdapter> uiAdapters;
private final IContext context;
protected RExprViewerDropAdapter(final Viewer viewer, final List<RExprTypeUIAdapter> uiAdapters,
final IContext context) {
super(viewer);
this.uiAdapters= uiAdapters;
this.context= context;
setFeedbackEnabled(true);
}
@Override
protected int determineLocation(final DropTargetEvent event) {
final int location= super.determineLocation(event);
if (location == LOCATION_ON) {
return LOCATION_AFTER;
}
return location;
}
@Override
public boolean validateDrop(final Object target, final int operation, final TransferData transferType) {
final DropTargetEvent event= getCurrentEvent();
if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) {
if (isValidInput(LocalSelectionTransfer.getTransfer().getSelection(), event)) {
return true;
}
return false;
}
return false;
}
@Override
public boolean performDrop(final Object data) {
final DropTargetEvent event= getCurrentEvent();
if (LocalSelectionTransfer.getTransfer().isSupportedType(event.currentDataType)) {
return setInput(LocalSelectionTransfer.getTransfer().getSelection(), event);
}
return false;
}
protected boolean isValidInput(final Object input, final DropTargetEvent event) {
if (input instanceof IStructuredSelection) {
final IStructuredSelection selection= (IStructuredSelection) input;
if (selection.getFirstElement() instanceof RTypedExpr) {
if ((event.operations & (DND.DROP_MOVE | DND.DROP_COPY)) == 0) {
return false;
}
final List list= selection.toList();
for (final Object element : list) {
if (!(element instanceof RTypedExpr)
|| !isTypeSupported(((RTypedExpr) element).getTypeKey()) ) {
return false;
}
}
int operation= event.detail;
if (operation != DND.DROP_COPY) {
operation= DND.DROP_COPY;
if (selection instanceof ElementSourceProvider) {
final Object source= ((ElementSourceProvider) selection).getElementSource();
final int move= (source instanceof IContext) ? isMoveValid((IContext) source, input) : PRIORITY_INVALID;
if (move > PRIORITY_INVALID && (event.detail == DND.DROP_MOVE
|| (move > PRIORITY_DEFAULT && event.detail == DND.DROP_DEFAULT) )) {
operation= DND.DROP_MOVE;
}
}
}
overrideOperation(operation);
return true;
}
}
{ if ((event.operations & DND.DROP_COPY) == 0) {
return false;
}
for (final RExprTypeUIAdapter uiAdapters : this.uiAdapters) {
if (uiAdapters.isValidInput(input, this.context) > PRIORITY_INVALID) {
overrideOperation(DND.DROP_COPY);
return true;
}
}
return false;
}
}
protected boolean setInput(final Object input, final DropTargetEvent event) {
if (input instanceof IStructuredSelection) {
final IStructuredSelection selection= (IStructuredSelection) input;
if (selection.getFirstElement() instanceof RTypedExpr) {
if (event.detail == DND.DROP_MOVE) {
moveExprs((IContext) ((ElementSourceProvider) input).getElementSource(),
selection.toList(), getInsertIndex(), event.time );
}
else {
final List<RTypedExpr> list= selection.toList();
final List<RTypedExpr> values= new ArrayList<>(list.size());
for (final RTypedExpr expr : list) {
values.add(new RTypedExpr(expr.getTypeKey(), expr.getExpr()));
}
insertExprs(values, getInsertIndex(), event.time);
}
return true;
}
}
{ int selectedPriority= PRIORITY_INVALID;
RExprTypeUIAdapter selectedAdapter= null;
for (final RExprTypeUIAdapter uiAdapters : this.uiAdapters) {
final int priority= uiAdapters.isValidInput(input, this.context);
if ((priority > PRIORITY_INVALID) && ((uiAdapters.getType().getTypeKey() == getCurrentTypeKey()) ?
(priority >= selectedPriority) : (priority > selectedPriority) )) {
selectedPriority= priority;
selectedAdapter= uiAdapters;
}
}
if (selectedAdapter != null) {
final List<String> exprs= selectedAdapter.getInputExprs(input, this.context);
if (exprs != null && !exprs.isEmpty()) {
final String typeKey= selectedAdapter.getType().getTypeKey();
final List<RTypedExpr> values= new ArrayList<>(exprs.size());
for (final String expr : exprs) {
values.add(new RTypedExpr(typeKey, expr));
}
insertExprs(values, getInsertIndex(), event.time);
return true;
}
}
return false;
}
}
protected int getInsertIndex() {
int index= getIndex(getCurrentTarget());
if (index >= 0) {
final int location= getCurrentLocation();
switch (location) {
case LOCATION_BEFORE:
break;
case LOCATION_AFTER:
index++;
break;
default:
index= -1;
break;
}
}
return index;
}
protected Object getSource() {
return this.context;
}
protected int getIndex(final Object element) {
return -1;
}
protected int isMoveValid(final IContext source, final Object input) {
if (!canMove(source, input)) {
return PRIORITY_INVALID;
}
if (getSource() == source) {
return PRIORITY_DEFAULT + 10;
}
if (input instanceof IStructuredSelection) {
final IStructuredSelection selection= (IStructuredSelection) input;
if (selection.getFirstElement() instanceof RTypedExpr) {
int selectedPriority= Integer.MAX_VALUE;
final List<String> checked= new ArrayList<>(this.uiAdapters.size());
for (final Object element : selection.toList()) {
final RTypedExpr expr= (RTypedExpr) element;
if (checked.contains(expr.getTypeKey())) {
continue;
}
checked.add(expr.getTypeKey());
final RExprTypeUIAdapter uiAdapter= getUIAdapter(expr.getTypeKey());
final int priority= uiAdapter.isMoveValid(input, source, this.context);
if (priority <= PRIORITY_INVALID) {
return PRIORITY_INVALID;
}
if (priority < priority) {
selectedPriority= priority;
}
}
return selectedPriority;
}
}
return PRIORITY_INVALID;
}
protected boolean canMove(final IContext source, final Object input) {
return false;
}
protected boolean isTypeSupported(final String typeKey) {
return (getUIAdapter(typeKey) != null);
}
protected RExprTypeUIAdapter getUIAdapter(final String typeKey) {
for (final RExprTypeUIAdapter uiAdapter : this.uiAdapters) {
if (uiAdapter.getType().getTypeKey() == typeKey) {
return uiAdapter;
}
}
return null;
}
protected String getCurrentTypeKey() {
return null;
}
protected void insertExprs(final List<RTypedExpr> exprs, final int index, final int time) {
}
protected void moveExprs(final IContext source, final List<RTypedExpr> exprs, final int index, final int time) {
}
}