blob: 7d7c58f2af13fa8a7e3a5903a1ca03998d937c71 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2012, 2020 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 java.util.List;
import org.eclipse.core.databinding.observable.IObserving;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Image;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.emf.core.IContext;
import org.eclipse.statet.ecommons.emf.core.databinding.IEMFEditPropertyContext;
import org.eclipse.statet.ecommons.emf.core.util.EFeatureReference;
import org.eclipse.statet.ecommons.emf.core.util.RuleSet;
import org.eclipse.statet.ltk.core.ElementName;
import org.eclipse.statet.ltk.ui.ElementNameProvider;
import org.eclipse.statet.r.core.model.RElement;
import org.eclipse.statet.r.core.model.RElementName;
import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rtm.base.ui.RtModelUIPlugin;
import org.eclipse.statet.rtm.base.ui.rexpr.RExprWidget.TypeDef;
import org.eclipse.statet.rtm.base.util.RExprType;
import org.eclipse.statet.rtm.rtdata.RtDataPackage;
import org.eclipse.statet.rtm.rtdata.types.RTypedExpr;
public class DefaultRExprTypeUIAdapters {
public static class DirectName implements ElementNameProvider {
@Override
public @Nullable ElementName getElementName(final Object selectionElement) {
ElementName elementName;
if (selectionElement instanceof RElement) {
elementName= ((RElement)selectionElement).getElementName();
}
else if (selectionElement instanceof RElementName) {
elementName= (ElementName) selectionElement;
}
else {
return null;
}
return elementName;
}
}
public static class LastName implements ElementNameProvider {
@Override
public @Nullable ElementName getElementName(final Object selectionElement) {
ElementName elementName;
if (selectionElement instanceof RElement) {
elementName= ((RElement)selectionElement).getElementName();
}
else if (selectionElement instanceof RElementName) {
elementName= (ElementName) selectionElement;
}
else {
return null;
}
return elementName.getLastSegment();
}
}
static ElementNameProvider DIRECT_NAME= new DirectName();
static ElementNameProvider LAST_NAME= new LastName();
public static class RObjectTypeAdapter extends RExprTypeUIAdapter {
public RObjectTypeAdapter(final RExprType type, final Image image) {
super(type, image);
}
protected boolean isValidRObject(final RObject rObject) {
return (rObject.getRObjectType() == RObject.TYPE_DATAFRAME);
}
@Override
public int isValidElement(final Object element) {
if (element instanceof RElement) {
final RElement rElement= (RElement)element;
if (rElement.getElementName() == null) {
return PRIORITY_INVALID;
}
if (element instanceof RObject) {
if (isValidRObject((RObject) element)) {
return PRIORITY_DEFAULT + 10;
}
return PRIORITY_INVALID;
}
return PRIORITY_DEFAULT;
}
return PRIORITY_INVALID;
}
}
public static class RDataframeColumnTypeAdapter extends RExprTypeUIAdapter {
public RDataframeColumnTypeAdapter(final RExprType type, final Image image) {
super(type, image);
}
protected boolean isValidRObject(final RObject rObject, final RElement parent) {
return ((rObject.getRObjectType() == RObject.TYPE_VECTOR)
&& (parent instanceof RObject)
&& (((RObject) parent).getRObjectType() == RObject.TYPE_DATAFRAME) );
}
@Override
protected int isValidElements(final List<?> elements) {
final Object first= elements.get(0);
if (first instanceof RElement) {
final RElement parent= ((RElement)first).getModelParent();
if (parent instanceof RObject) {
if (((RObject) parent).getRObjectType() != RObject.TYPE_DATAFRAME) {
return PRIORITY_INVALID;
}
for (final Object element : elements) {
if ((!(element instanceof RElement))) {
return PRIORITY_INVALID;
}
final RElement rElement= (RElement)element;
if (rElement.getElementName() == null
|| rElement.getModelParent() != parent) {
return PRIORITY_INVALID;
}
if (element instanceof RObject
&& ((RObject) element).getRObjectType() != RObject.TYPE_VECTOR) {
return PRIORITY_INVALID;
}
}
return PRIORITY_DEFAULT + 10;
}
else if (parent != null) {
for (final Object element : elements) {
if ((!(element instanceof RElement))) {
return PRIORITY_INVALID;
}
final RElement rElement= (RElement)element;
if (rElement.getElementName() == null
|| rElement.getModelParent() != parent) {
return PRIORITY_INVALID;
}
switch (rElement.getElementName().getType()) {
case RElementName.SUB_NAMEDPART:
case RElementName.SUB_INDEXED_D:
break;
default:
return PRIORITY_INVALID;
}
}
return PRIORITY_DEFAULT;
}
else {
for (final Object element : elements) {
if ((!(element instanceof RElement))) {
return PRIORITY_INVALID;
}
final RElement rElement= (RElement)element;
RElementName elementName= rElement.getElementName();
if (elementName == null) {
return PRIORITY_INVALID;
}
if (elementName.getNextSegment() != null) {
RElementName parentName= null;
do {
parentName= elementName;
elementName= elementName.getNextSegment();
} while (elementName.getNextSegment() != null);
switch (elementName.getType()) {
case RElementName.SUB_NAMEDPART:
case RElementName.SUB_INDEXED_D:
break;
default:
return PRIORITY_INVALID;
}
}
else {
switch (elementName.getType()) {
case RElementName.MAIN_DEFAULT:
case RElementName.MAIN_OTHER:
case RElementName.SUB_NAMEDPART:
case RElementName.SUB_INDEXED_D:
break;
default:
return PRIORITY_INVALID;
}
}
}
return PRIORITY_DEFAULT;
}
}
return PRIORITY_INVALID;
}
@Override
public List<String> getInputExprs(final Object input, final IContext context) {
final List<?> elements= getElements(input);
final Object first= elements.get(0);
ElementNameProvider nameProvider;
if (first instanceof RElement) {
nameProvider= DIRECT_NAME;
final RElement parent= ((RElement)first).getModelParent();
if (parent instanceof RObject) {
if (checkParent(parent, input, context) == false) {
return null;
}
}
}
else {
nameProvider= LAST_NAME;
}
return collectElementName(elements, nameProvider);
}
protected boolean checkParent(final RElement parent, final Object input, final IContext context) {
final ElementName parentName= (input instanceof ElementNameProvider) ?
((ElementNameProvider) input).getElementName(parent) : parent.getElementName();
if (!(parentName instanceof RElementName)) {
return true;
}
return checkParent((RElementName) parentName, context, "data"); //$NON-NLS-1$
}
protected boolean checkParent(final RElementName parentName, final IContext context, final String parentField) {
if (parentName == null) {
return true;
}
final IEMFEditPropertyContext propertyContext= context.getAdapter(IEMFEditPropertyContext.class);
final RuleSet ruleSet= context.getAdapter(RuleSet.class);
if (propertyContext == null || ruleSet == null) {
return true;
}
final EObject owner= (EObject) ((IObserving) propertyContext.getPropertyObservable()).getObserved();
final List<EFeatureReference> parents= (List<EFeatureReference>) ruleSet.get(
owner, propertyContext.getEFeature(), (parentField + RuleSet.PARENT_FEATURES_ID_SUFFIX) );
if (parents == null) {
return true;
}
if (parents.isEmpty()) {
return false;
}
EFeatureReference change= null;
for (int i= 0; i < parents.size(); i++) {
final EFeatureReference parent= parents.get(i);
final Object value= parent.getValue();
if (value == null) {
continue;
}
if (matches(value, parentName)) {
return true;
}
else {
break;
}
}
for (int i= parents.size() - 1; i >= 0; i--) {
final EFeatureReference parent= parents.get(i);
if (parent.getValue() == null) {
change= parent;
break;
}
}
final String newExpr= parentName.getDisplayName();
if (change == null) {
final String oldExpr= ((RTypedExpr) parents.get(0).getValue()).getExpr();
final IShellProvider shellProvider= context.getAdapter(IShellProvider.class);
final MessageDialog dialog= new MessageDialog((shellProvider != null) ? shellProvider.getShell() : null,
"Change Dataframe", null,
NLS.bind("The column seems to belong to a different dataframe than specified in ''{0}''.\n\n" +
"Do you want to adapt the expression for the dataframe to ''{2}''?",
new Object[] { parentField, oldExpr, newExpr }),
MessageDialog.QUESTION,
new String[] { "Change dataframe", "Ignore", "Cancel" }, 0);
switch (dialog.open()) {
case 0:
change= parents.get(0);
break;
case 2:
return false;
default:
return true;
}
}
final Command command= SetCommand.create(propertyContext.getEditingDomain(),
change.getEObject(), change.getEFeature(),
new RTypedExpr(RTypedExpr.R, newExpr) );
propertyContext.getEditingDomain().getCommandStack().execute(command);
return true;
}
protected boolean matches(final Object obj, final RElementName expectedName) {
if (obj instanceof RTypedExpr) {
final RTypedExpr rExpr= (RTypedExpr) obj;
if (rExpr.getExpr().equals(expectedName.getDisplayName())) {
return true;
}
final ElementName parsedName= RElementName.parseDefault(rExpr.getExpr());
if (parsedName == null) {
return true;
}
if (!parsedName.equals(expectedName)) {
return false;
}
}
return true;
}
@Override
public int isMoveValid(final Object input, final IContext sourceContext, final IContext context) {
final IEMFEditPropertyContext propertyContext= context.getAdapter(IEMFEditPropertyContext.class);
final IEMFEditPropertyContext sourcePropertyContext= sourceContext.getAdapter(IEMFEditPropertyContext.class);
if (propertyContext != null && sourcePropertyContext != null
&& propertyContext.getEditingDomain() == sourcePropertyContext.getEditingDomain()) {
if (propertyContext.getPropertyObservable() == sourcePropertyContext.getPropertyObservable()) {
return PRIORITY_DEFAULT + 10;
}
final EObject owner= (EObject) ((IObserving) propertyContext.getPropertyObservable()).getObserved();
if (owner != null) {
final RuleSet ruleSet= sourcePropertyContext.getAdapter(RuleSet.class);
final EObject sourceObject= (EObject) ((IObserving) sourcePropertyContext.getPropertyObservable()).getObserved();
if (ruleSet != null && sourceObject != null) {
final List<EFeatureReference> disjoints= (List<EFeatureReference>) ruleSet.get(
owner, propertyContext.getEFeature(), RuleSet.DISJOINT_FEATURES_ID );
if (disjoints != null) {
for (final EFeatureReference disjoint : disjoints) {
if (disjoint.getEObject() == sourceObject
&& disjoint.getEFeature() == sourcePropertyContext.getEFeature() ) {
return PRIORITY_DEFAULT + 10;
}
}
}
}
}
return PRIORITY_DEFAULT;
}
return PRIORITY_INVALID;
}
}
public static class CommonRExprAdapter extends RExprTypeUIAdapter {
public CommonRExprAdapter(final RExprType type, final Image image) {
super(type, image);
}
@Override
public int isValidInput(final Object input, final IContext context) {
return PRIORITY_DEFAULT;
}
}
public static class LabelTextAdapter extends RExprTypeUIAdapter {
public LabelTextAdapter(final RExprType type, final Image image) {
super(type, image);
}
@Override
public String adopt(final String typeKey, final String expr) {
if (typeKey == RTypedExpr.R) {
return expr;
}
return super.adopt(typeKey, expr);
}
}
public static class LabelRExprAdapter extends RExprTypeUIAdapter {
public LabelRExprAdapter(final RExprType type, final Image image) {
super(type, image);
}
@Override
public String adopt(final String typeKey, final String expr) {
if (typeKey == RTypedExpr.CHAR) {
return expr;
}
return super.adopt(typeKey, expr);
}
}
public static class ColorRExprAdapter extends RExprTypeUIAdapter {
public ColorRExprAdapter(final RExprType type, final Image image) {
super(type, image);
}
@Override
public TypeDef createWidgetDef() {
return new ColorType(this);
}
}
public static class AlphaRExprAdapter extends RExprTypeUIAdapter {
public AlphaRExprAdapter(final RExprType type, final Image image) {
super(type, image);
}
@Override
public TypeDef createWidgetDef() {
return new AlphaType(this);
}
}
public static class FontFamilyRExprAdapter extends RExprTypeUIAdapter {
public FontFamilyRExprAdapter(final RExprType type, final Image image) {
super(type, image);
}
@Override
public TypeDef createWidgetDef() {
return new FontFamilyType(this);
}
}
protected static final RExprTypeUIAdapter DATAFRAME_ADAPTER= new RObjectTypeAdapter(
RExprType.DATAFRAME_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_DATAFRAME_TYPE_IMAGE_ID) );
protected static final RExprTypeUIAdapter EXPR_VALUE_ADAPTER= new CommonRExprAdapter(
RExprType.EXPR_VALUE_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_REXPR_TYPE_IMAGE_ID) );
protected static final RExprTypeUIAdapter TEXT_VALUE_ADAPTER= new RExprTypeUIAdapter(
RExprType.TEXT_VALUE_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_TEXT_TYPE_IMAGE_ID) );
protected static final RExprTypeUIAdapter LABEL_TEXT_VALUE_ADAPTER= new LabelTextAdapter(
RExprType.TEXT_VALUE_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_TEXT_TYPE_IMAGE_ID) );
protected static final RExprTypeUIAdapter LABEL_EXPR_VALUE_ADAPTER= new LabelRExprAdapter(
RExprType.EXPR_VALUE_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_REXPR_TYPE_IMAGE_ID) );
protected static final RExprTypeUIAdapter COLOR_EXPR_VALUE_ADAPTER= new ColorRExprAdapter(
RExprType.EXPR_COLOR_VALUE_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_COLOR_TYPE_IMAGE_ID) );
protected static final RExprTypeUIAdapter ALHPA_EXPR_VALUE_ADAPTER= new AlphaRExprAdapter(
RExprType.EXPR_ALPHA_VALUE_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_REXPR_TYPE_IMAGE_ID) );
protected static final RExprTypeUIAdapter FONT_FAMILY_EXPR_VALUE_ADAPTER= new FontFamilyRExprAdapter(
RExprType.EXPR_FONT_FAMILY_VALUE_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_REXPR_TYPE_IMAGE_ID) );
protected static final RExprTypeUIAdapter FUNCTION_ADAPTER= new RExprTypeUIAdapter(
RExprType.EXPR_FUNCTION_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_REXPR_TYPE_IMAGE_ID) );
protected static final RExprTypeUIAdapter DATAFRAME_COLUMN_ADAPTER= new RDataframeColumnTypeAdapter(
RExprType.DATAFRAME_COLUMN_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_COLUMN_TYPE_IMAGE_ID) );
protected static final RExprTypeUIAdapter DATAFRAME_COLUMNS_ADAPTER= new RDataframeColumnTypeAdapter(
RExprType.DATAFRAME_COLUMN_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_COLUMN_TYPE_IMAGE_ID) ) {
@Override
protected boolean isMulti() {
return true;
}
};
/* with link */
protected static final RExprTypeUIAdapter LABEL_TEXT_VALUE_LINK_ADAPTER= new LabelTextAdapter(
RExprType.TEXT_VALUE_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_TEXT_TYPE_IMAGE_ID) ) {
@Override
public TypeDef createWidgetDef() {
return new HyperlinkType(this);
}
};
protected static final RExprTypeUIAdapter LABEL_EXPR_VALUE_LINK_ADAPTER= new LabelRExprAdapter(
RExprType.EXPR_VALUE_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_REXPR_TYPE_IMAGE_ID) ) {
@Override
public TypeDef createWidgetDef() {
return new HyperlinkType(this);
}
};
protected static final RExprTypeUIAdapter DATAFRAME_COLUMN_LINK_ADAPTER= new RDataframeColumnTypeAdapter(
RExprType.DATAFRAME_COLUMN_TYPE,
RtModelUIPlugin.getInstance().getImageRegistry().get(RtModelUIPlugin.OBJ_COLUMN_TYPE_IMAGE_ID) ) {
@Override
public TypeDef createWidgetDef() {
return new HyperlinkType(this);
}
};
public RExprTypeUIAdapter getUIAdapter(final RExprType type, final EStructuralFeature eFeature) {
if (type == RExprType.DATAFRAME_TYPE) {
return DATAFRAME_ADAPTER;
}
if (type == RExprType.EXPR_VALUE_TYPE) {
if (eFeature.getEType() == RtDataPackage.Literals.RLABEL) {
return LABEL_EXPR_VALUE_ADAPTER;
}
return EXPR_VALUE_ADAPTER;
}
if (type == RExprType.TEXT_VALUE_TYPE) {
if (eFeature.getEType() == RtDataPackage.Literals.RLABEL) {
return LABEL_TEXT_VALUE_ADAPTER;
}
return TEXT_VALUE_ADAPTER;
}
if (type == RExprType.EXPR_LABEL_VALUE_TYPE) {
return LABEL_EXPR_VALUE_ADAPTER;
}
if (type == RExprType.EXPR_COLOR_VALUE_TYPE) {
return COLOR_EXPR_VALUE_ADAPTER;
}
if (type == RExprType.EXPR_ALPHA_VALUE_TYPE) {
return ALHPA_EXPR_VALUE_ADAPTER;
}
if (type == RExprType.EXPR_FONT_FAMILY_VALUE_TYPE) {
return FONT_FAMILY_EXPR_VALUE_ADAPTER;
}
if (type == RExprType.EXPR_FUNCTION_TYPE) {
return FUNCTION_ADAPTER;
}
if (type == RExprType.DATAFRAME_COLUMN_TYPE) {
if (eFeature.isMany()) {
return DATAFRAME_COLUMNS_ADAPTER;
}
return DATAFRAME_COLUMN_ADAPTER;
}
return null;
}
}