blob: 3979017fb048626b1499635ba363c4028a575b0b [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Florian Pirchner - Initial implementation
*
*/
package org.eclipse.osbp.ecview.extension.editparts.emf;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.impl.BasicEObjectImpl;
import org.eclipse.osbp.ecview.core.common.context.IViewContext;
import org.eclipse.osbp.ecview.core.common.editpart.IEmbeddableEditpart;
import org.eclipse.osbp.ecview.core.common.editpart.IKeyStrokeDefinitionEditpart;
import org.eclipse.osbp.ecview.core.common.editpart.emf.EmbeddableEditpart;
import org.eclipse.osbp.ecview.core.common.editpart.validation.IValidatorEditpart;
import org.eclipse.osbp.ecview.core.common.editpart.visibility.IVisibilityProcessorEditpart;
import org.eclipse.osbp.ecview.core.common.model.core.YView;
import org.eclipse.osbp.ecview.core.common.model.visibility.YVisibilityProcessor;
import org.eclipse.osbp.ecview.extension.api.IFocusingEnhancer;
import org.eclipse.osbp.ecview.extension.editparts.IInternalFocusingEditpart;
import org.eclipse.osbp.ecview.extension.editparts.IInternalLayoutingInfoEditpart;
import org.eclipse.osbp.ecview.extension.editparts.ILayoutingInfoEditpart;
import org.eclipse.osbp.ecview.extension.editparts.IStrategyLayoutEditpart;
import org.eclipse.osbp.ecview.extension.editparts.ISuspectEditpart;
import org.eclipse.osbp.ecview.extension.editparts.presentation.IStrategyLayoutPresentation;
import org.eclipse.osbp.ecview.extension.editparts.strategies.IFocusingStrategyEditpart;
import org.eclipse.osbp.ecview.extension.editparts.strategies.ILayoutingStrategyEditpart;
import org.eclipse.osbp.ecview.extension.model.YECviewFactory;
import org.eclipse.osbp.ecview.extension.model.YECviewPackage;
import org.eclipse.osbp.ecview.extension.model.YFocusingStrategy;
import org.eclipse.osbp.ecview.extension.model.YLayoutingInfo;
import org.eclipse.osbp.ecview.extension.model.YLayoutingStrategy;
import org.eclipse.osbp.ecview.extension.model.YStrategyLayout;
import org.eclipse.osbp.ecview.extension.model.YSuspect;
import org.eclipse.osbp.runtime.common.keystroke.KeyStrokeCallback;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The implementation of the IStrategyLayoutEditpart.
*/
public class StrategyLayoutEditpart extends EmbeddableEditpart<YStrategyLayout>
implements IStrategyLayoutEditpart {
/** The Constant LOGGER. */
private static final Logger LOGGER = LoggerFactory
.getLogger(StrategyLayoutEditpart.class);
/** The suspects. */
private List<ISuspectEditpart> suspects;
/** The focusing strategies. */
private List<IFocusingStrategyEditpart> focusingStrategies;
/** The layouting strategy. */
private ILayoutingStrategyEditpart layoutingStrategy;
/** The layouting info. */
private ILayoutingInfoEditpart layoutingInfo;
/** The keystroke callbacks. */
private HashMap<IFocusingStrategyEditpart, KeyStrokeCallback> keystrokeCallbacks = new HashMap<IFocusingStrategyEditpart, KeyStrokeCallback>();
/**
* Instantiates a new strategy layout editpart.
*/
protected StrategyLayoutEditpart() {
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.osbp.ecview.core.common.editpart.datatypes.IDatatypeEditpart
* .DatatypeBridge#getDatatypeValidators()
*/
@Override
public List<IValidatorEditpart> getDatatypeValidators() {
return Collections.emptyList();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.extension.editparts.IStrategyLayoutEditpart#
* getSuspects()
*/
@Override
public List<ISuspectEditpart> getSuspects() {
checkDisposed();
if (suspects == null) {
internalLoadSuspects();
}
return Collections.unmodifiableList(suspects);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.core.common.editpart.emf.EmbeddableEditpart#
* initialize(org.eclipse.osbp.ecview.core.common.model.core.YEmbeddable)
*/
@Override
public void initialize(IViewContext context, YStrategyLayout model) {
checkDisposed();
// register the adapter first to find this editpart later...
EObject eObject = castEObject(model);
try {
// avoid delivery during init
((BasicEObjectImpl) eObject).eSetDeliver(false);
if (!eObject.eAdapters().contains(this)) {
eObject.eAdapters().add(this);
}
// initialize the default strategies if required
//
if (model.getLayoutingStrategy() == null) {
model.setLayoutingStrategy(YECviewFactory.eINSTANCE
.createYDefaultLayoutingStrategy());
}
this.layoutingStrategy = getEditpart(getContext(),
model.getLayoutingStrategy());
if (model.getFocusingStrategies().isEmpty()) {
enhanceDefaultFocusing(model);
}
super.initialize(context, model);
} finally {
((BasicEObjectImpl) eObject).eSetDeliver(true);
}
}
protected void registerAdapter(Adapter adapter) {
// not here!
}
protected void checkAdapter(YStrategyLayout model) {
// not here!
}
/**
* Enhance default focusing.
*
* @param model
* the model
*/
private void enhanceDefaultFocusing(YStrategyLayout model) {
IFocusingEnhancer applier = findFocusingEnhancer(model
.getDefaultFocusingEnhancerId());
if (applier != null) {
applier.enhanceFocusing(model);
}
}
/**
* Find focusing enhancer.
*
* @param defaultFocusingEnhancerId
* the default focusing enhancer id
* @return the i focusing enhancer
*/
private IFocusingEnhancer findFocusingEnhancer(
String defaultFocusingEnhancerId) {
if (defaultFocusingEnhancerId != null) {
return findFocusingEnhancerService(defaultFocusingEnhancerId);
} else {
return findDefaultFocusingEnhancerService();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.extension.editparts.IStrategyLayoutEditpart#
* findFocusingEnhancerService(java.lang.String)
*/
public IFocusingEnhancer findFocusingEnhancerService(String id) {
BundleContext context = FrameworkUtil.getBundle(getClass())
.getBundleContext();
try {
Collection<ServiceReference<IFocusingEnhancer>> references = context
.getServiceReferences(IFocusingEnhancer.class, String
.format("(ecview.focusing.enhancer.id=%s)", id));
if (!references.isEmpty()) {
IFocusingEnhancer provider = context.getService(references
.iterator().next());
return provider;
}
} catch (InvalidSyntaxException e) {
LOGGER.warn("{}", e);
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.extension.editparts.IStrategyLayoutEditpart#
* findDefaultFocusingEnhancerService()
*/
public IFocusingEnhancer findDefaultFocusingEnhancerService() {
BundleContext context = FrameworkUtil.getBundle(getClass())
.getBundleContext();
try {
Collection<ServiceReference<IFocusingEnhancer>> references = context
.getServiceReferences(IFocusingEnhancer.class,
"(ecview.focusing.enhancer.default=true)");
if (!references.isEmpty()) {
IFocusingEnhancer provider = context.getService(references
.iterator().next());
return provider;
}
} catch (InvalidSyntaxException e) {
LOGGER.warn("{}", e);
}
return null;
}
/**
* Clients may override and return a proper default focusing strategy.
*
* @return the default focusing strategy
*/
protected YFocusingStrategy getDefaultFocusingStrategy() {
return null;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.osbp.ecview.core.common.editpart.emf.EmbeddableEditpart#render
* (java.lang.Object)
*/
@Override
public Object render(Object parentWidget) {
if (this.layoutingStrategy != null) {
// call the layout strategy before rendering -> Will set the content
this.layoutingStrategy.layout();
}
internalActivateLayoutingInfo();
internalActivateFocusingStrategies();
Object result = super.render(parentWidget);
internalPostActivateLayoutingInfo();
return result;
}
/**
* Returns true, if the presenter is present.
*
* @return true, if is presentation present
*/
protected boolean isPresentationPresent() {
return internalGetPresentation() != null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.core.common.editpart.emf.EmbeddableEditpart#
* getPresentation()
*/
@SuppressWarnings("unchecked")
@Override
public IStrategyLayoutPresentation<?> getPresentation() {
return super.getPresentation();
}
/**
* {@inheritDoc}
*/
@Override
protected void handleModelSet(int featureId, Notification notification) {
checkDisposed();
switch (featureId) {
case YECviewPackage.YSTRATEGY_LAYOUT__LAYOUTING_STRATEGY:
internalSetLayoutingStrategy((YLayoutingStrategy) notification
.getNewValue());
break;
case YECviewPackage.YSTRATEGY_LAYOUT__LAYOUTING_INFO:
internalSetLayoutingInfo((YLayoutingInfo) notification
.getNewValue());
break;
case YECviewPackage.YSTRATEGY_LAYOUT__DEFAULT_FOCUSING_ENHANCER_ID:
enhanceDefaultFocusing(getModel());
break;
default:
super.handleModelSet(featureId, notification);
}
}
/**
* Set the new content.
*
* @param cxInfo
* the cx info
*/
protected void internalSetLayoutingInfo(YLayoutingInfo cxInfo) {
ILayoutingInfoEditpart newEditpart = getEditpart(getContext(), cxInfo);
if (this.layoutingInfo == newEditpart) {
return;
}
if (this.layoutingInfo != null) {
getPresentation().setContent(null);
this.layoutingInfo.dispose();
}
this.layoutingInfo = newEditpart;
if (isRendered()) {
internalActivateLayoutingInfo();
}
}
/**
* Internal activate layouting info.
*/
protected void internalActivateLayoutingInfo() {
if (this.layoutingInfo != null) {
// refresh the content
IEmbeddableEditpart contentEP = this.layoutingInfo.getContent();
getPresentation().setContent(contentEP);
((IInternalLayoutingInfoEditpart) this.layoutingInfo).activate();
YView yView = (YView) getView().getModel();
for (YVisibilityProcessor yP : yView.getVisibilityProcessors()) {
IVisibilityProcessorEditpart ep = getEditpart(getContext(), yP);
if (ep != null) {
ep.fire();
}
}
}
}
protected void internalPostActivateLayoutingInfo() {
if (this.layoutingInfo != null) {
((IInternalLayoutingInfoEditpart) this.layoutingInfo)
.postActivate();
}
}
/**
* Internal activate focusing strategies.
*/
protected void internalActivateFocusingStrategies() {
for (IFocusingStrategyEditpart strategyEP : getFocusingStrategies()) {
internalActivateFocusingStrategy(strategyEP);
}
}
/**
* Internally activate the focusing strategy.
*
* @param strategy
* the strategy
*/
protected void internalActivateFocusingStrategy(
final IFocusingStrategyEditpart strategy) {
if (strategy != null) {
IKeyStrokeDefinitionEditpart keyStrokeDefEditpart = strategy
.getKeyStrokeDefinition();
if (keyStrokeDefEditpart == null) {
LOGGER.error("Focusing strategy not activated, since missing key stroke definitions. Strategy: "
+ strategy.getId());
return;
}
KeyStrokeCallback callback = new KeyStrokeCallback() {
@Override
public void callback(Object source, Object target) {
requestFocusing(source, target, strategy);
}
};
keystrokeCallbacks.put(strategy, callback);
getPresentation().registerKeyStroke(keyStrokeDefEditpart, callback);
((IInternalFocusingEditpart) strategy).activate();
}
}
/**
* Internally deactivate the focusing strategy.
*
* @param strategy
* the strategy
*/
protected void internalDectivateFocusingStrategy(
final IFocusingStrategyEditpart strategy) {
if (strategy != null) {
KeyStrokeCallback callback = keystrokeCallbacks.remove(strategy);
if (callback != null) {
getPresentation().unregisterKeyStroke(callback);
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.extension.editparts.IStrategyLayoutEditpart#
* deactivate
* (org.eclipse.osbp.ecview.extension.editparts.ILayoutingInfoEditpart)
*/
@Override
public void deactivate(ILayoutingInfoEditpart info) {
if (info == null || info != this.layoutingInfo) {
return;
}
getModel().setLayoutingInfo(null);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.osbp.ecview.extension.editparts.IStrategyLayoutEditpart#activate
* (org.eclipse.osbp.ecview.extension.editparts.ILayoutingInfoEditpart)
*/
@Override
public void activate(ILayoutingInfoEditpart info) {
getModel().setLayoutingInfo((YLayoutingInfo) info.getModel());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.extension.editparts.IStrategyLayoutEditpart#
* requestLayouting()
*/
@Override
public void requestLayouting() {
if (!isRendered()) {
return;
}
if (this.layoutingStrategy != null) {
// call the layout strategy before rendering -> Will set the content
this.layoutingStrategy.layout();
}
}
/**
* Adds the focusing strategy.
*
* @param strategy
* the strategy
*/
protected void internalAddFocusingStrategy(
IFocusingStrategyEditpart strategy) {
checkDisposed();
if (focusingStrategies == null) {
internalLoadFocusingStrategies();
}
if (!focusingStrategies.contains(strategy)) {
focusingStrategies.add(strategy);
if (isRendered()) {
internalActivateFocusingStrategy(strategy);
}
}
}
/**
* Removes the focusing strategy.
*
* @param strategy
* the strategy
*/
protected void internalRemoveFocusingStrategy(
IFocusingStrategyEditpart strategy) {
checkDisposed();
if (focusingStrategies != null && strategy != null) {
// deactivate and dispose the strategy
internalDectivateFocusingStrategy(strategy);
strategy.dispose();
focusingStrategies.remove(strategy);
}
}
/**
* Set the layout strategy.
*
* @param cxStrategy
* the cx strategy
*/
protected void internalSetLayoutingStrategy(YLayoutingStrategy cxStrategy) {
ILayoutingStrategyEditpart newEitpart = getEditpart(getContext(),
cxStrategy);
if (this.layoutingStrategy != null) {
layoutingStrategy.dispose();
}
this.layoutingStrategy = newEitpart;
if (this.layoutingStrategy == null) {
getModel().setLayoutingStrategy(
YECviewFactory.eINSTANCE.createYDefaultLayoutingStrategy());
} else {
this.layoutingStrategy.layout();
}
}
/**
* {@inheritDoc}
*/
protected void handleModelAdd(int featureId, Notification notification) {
checkDisposed();
switch (featureId) {
case YECviewPackage.YSTRATEGY_LAYOUT__SUSPECTS:
YSuspect yElement = (YSuspect) notification.getNewValue();
ISuspectEditpart editPart = (ISuspectEditpart) getEditpart(
getContext(), yElement);
internalAddSuspect(editPart);
break;
case YECviewPackage.YSTRATEGY_LAYOUT__FOCUSING_STRATEGIES:
IFocusingStrategyEditpart focusingEditPart = (IFocusingStrategyEditpart) getEditpart(
getContext(),
(YFocusingStrategy) notification.getNewValue());
internalAddFocusingStrategy(focusingEditPart);
break;
default:
break;
}
}
/**
* {@inheritDoc}
*/
@Override
protected void handleModelMove(int featureId, Notification notification) {
checkDisposed();
switch (featureId) {
case YECviewPackage.YSTRATEGY_LAYOUT__SUSPECTS:
YSuspect yElement = (YSuspect) notification.getNewValue();
ISuspectEditpart editPart = (ISuspectEditpart) getEditpart(
getContext(), yElement);
internalMoveSuspect(editPart, notification.getPosition());
break;
default:
break;
}
}
/**
* {@inheritDoc}
*/
protected void handleModelRemove(int featureId, Notification notification) {
checkDisposed();
switch (featureId) {
case YECviewPackage.YSTRATEGY_LAYOUT__SUSPECTS:
YSuspect yElement = (YSuspect) notification.getOldValue();
ISuspectEditpart editPart = (ISuspectEditpart) getEditpart(
getContext(), yElement);
internalRemoveSuspect(editPart);
break;
case YECviewPackage.YSTRATEGY_LAYOUT__FOCUSING_STRATEGIES:
IFocusingStrategyEditpart focusingEditPart = (IFocusingStrategyEditpart) getEditpart(
getContext(),
(YFocusingStrategy) notification.getOldValue());
internalRemoveFocusingStrategy(focusingEditPart);
break;
default:
break;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.core.common.editpart.emf.ElementEditpart#
* handleModelRemoveMany(int, org.eclipse.emf.common.notify.Notification)
*/
protected void handleModelRemoveMany(int featureId,
Notification notification) {
checkDisposed();
switch (featureId) {
case YECviewPackage.YSTRATEGY_LAYOUT__FOCUSING_STRATEGIES:
@SuppressWarnings("unchecked")
List<YFocusingStrategy> oldValues = (List<YFocusingStrategy>) notification
.getOldValue();
for (YFocusingStrategy cxFocusingStrategy : oldValues) {
IFocusingStrategyEditpart focusingEditPart = (IFocusingStrategyEditpart) getEditpart(
getContext(), cxFocusingStrategy);
internalRemoveFocusingStrategy(focusingEditPart);
}
break;
default:
break;
}
}
/**
* Is called to change the internal state and add the given editpart to the
* list of suspects.
*
* @param editpart
* The editpart to be added
*/
protected void internalAddSuspect(ISuspectEditpart editpart) {
checkDisposed();
if (suspects == null) {
internalLoadSuspects();
}
if (!suspects.contains(editpart)) {
suspects.add(editpart);
}
}
/**
* Is called to change the internal state and to move the given editpart in
* the list of suspects.
*
* @param editpart
* The editpart to be inserted
* @param index
* The index to move the suspect.
*/
protected void internalMoveSuspect(ISuspectEditpart editpart, int index) {
checkDisposed();
if (suspects == null) {
internalLoadSuspects();
} else if (!suspects.contains(editpart)) {
throw new RuntimeException(String.format(
"Editpart %s is not contained in elements",
editpart.getId()));
} else {
suspects.remove(editpart);
suspects.add(index, editpart);
}
}
/**
* Is called to change the internal state and remove the given editpart from
* the list of suspects.
*
* @param editpart
* The editpart to be removed
*/
protected void internalRemoveSuspect(ISuspectEditpart editpart) {
checkDisposed();
if (suspects != null && editpart != null) {
suspects.remove(editpart);
}
}
/**
* Is called to load and initialize all suspects.
*/
protected void internalLoadSuspects() {
checkDisposed();
if (suspects == null) {
suspects = new ArrayList<ISuspectEditpart>();
for (YSuspect yElement : getModel().getSuspects()) {
ISuspectEditpart editPart = getEditpart(getContext(), yElement);
internalAddSuspect(editPart);
}
}
}
/**
* Is called to load and initialize all focusing strategies.
*/
protected void internalLoadFocusingStrategies() {
checkDisposed();
if (focusingStrategies == null) {
focusingStrategies = new ArrayList<IFocusingStrategyEditpart>();
for (YFocusingStrategy yElement : getModel()
.getFocusingStrategies()) {
IFocusingStrategyEditpart editPart = getEditpart(getContext(),
yElement);
internalAddFocusingStrategy(editPart);
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.core.common.editpart.emf.EmbeddableEditpart#
* internalDispose()
*/
@Override
protected void internalDispose() {
try {
LOGGER.info("Disposing " + toString());
if (layoutingInfo != null) {
layoutingInfo.dispose();
layoutingInfo = null;
}
// lazy loading: edit parts also have to be disposed if they have
// not been loaded yet, but exist in the model.
if (suspects != null || getModel().getSuspects().size() > 0) {
List<ISuspectEditpart> tempElements = getSuspects();
synchronized (suspects) {
for (ISuspectEditpart editpart : tempElements
.toArray(new ISuspectEditpart[tempElements.size()])) {
editpart.dispose();
}
}
}
suspects = null;
if (layoutingStrategy != null) {
layoutingStrategy.dispose();
layoutingStrategy = null;
}
if (focusingStrategies != null
|| getModel().getFocusingStrategies().size() > 0) {
List<IFocusingStrategyEditpart> tempElements = getFocusingStrategies();
synchronized (focusingStrategies) {
for (IFocusingStrategyEditpart editpart : tempElements
.toArray(new IFocusingStrategyEditpart[tempElements
.size()])) {
editpart.dispose();
}
}
}
focusingStrategies = null;
} finally {
super.internalDispose();
}
}
/**
* ONLY FOR TESTS!.
*
* @return the focusingStrategy
*/
public List<IFocusingStrategyEditpart> getFocusingStrategies() {
internalLoadFocusingStrategies();
return focusingStrategies != null ? Collections
.unmodifiableList(focusingStrategies) : Collections
.<IFocusingStrategyEditpart> emptyList();
}
/**
* ONLY FOR TESTS!.
*
* @return the layoutingStrategy
*/
public ILayoutingStrategyEditpart getLayoutingStrategy() {
return layoutingStrategy;
}
/**
* Gets the keystroke callbacks.
*
* @return the keystrokeCallbacks
*/
public HashMap<IFocusingStrategyEditpart, KeyStrokeCallback> getKeystrokeCallbacks() {
return keystrokeCallbacks;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.extension.editparts.IStrategyLayoutEditpart#
* requestFocusing(java.lang.Object, java.lang.Object,
* org.eclipse.osbp.ecview
* .extension.editparts.strategies.IFocusingStrategyEditpart)
*/
@Override
public void requestFocusing(Object source, Object target,
IFocusingStrategyEditpart strategy) {
strategy.focus(source, target);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.extension.editparts.IStrategyLayoutEditpart#
* requestRefresh(org.eclipse.osbp.ecview.extension.editparts.strategies.
* IFocusingStrategyEditpart)
*/
@Override
public void requestRefresh(final IFocusingStrategyEditpart strategy) {
internalDectivateFocusingStrategy(strategy);
internalActivateFocusingStrategy(strategy);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.extension.editparts.IStrategyLayoutEditpart#
* resetToDefaultFocusing()
*/
@Override
public void resetToDefaultFocusing() {
enhanceDefaultFocusing(getModel());
}
}