package org.archstudio.xadl.bna.logics;
import org.archstudio.bna.BNAModelEvent;
import org.archstudio.bna.IBNAModelListener;
import org.archstudio.bna.IBNAWorld;
import org.archstudio.bna.IThing;
import org.archstudio.bna.ThingEvent;
import org.archstudio.bna.facets.IHasAlpha;
import org.archstudio.bna.facets.IHasBackground;
import org.archstudio.bna.facets.IHasMutableGlow;
import org.archstudio.bna.facets.IHasSelected;
import org.archstudio.bna.keys.IThingKey;
import org.archstudio.bna.keys.ThingKey;
import org.archstudio.bna.logics.AbstractThingLogic;
import org.archstudio.bna.logics.coordinating.MirrorValueLogic;
import org.archstudio.bna.logics.tracking.ThingValueTrackingLogic;
import org.archstudio.bna.utils.Assemblies;
import org.archstudio.bna.utils.BNAUtils;
import org.archstudio.xadl.bna.facets.IHasObjRef;
import org.archstudio.xarchadt.ObjRef;
import org.archstudio.xarchadt.variability.IXArchADTVariability;
import org.archstudio.xarchadt.variability.IXArchADTVariability.ChangeStatus;
import org.archstudio.xarchadt.variability.IXArchADTVariabilityListener;
import org.archstudio.xarchadt.variability.XArchADTVariabilityEvent;
import org.archstudio.xarchadt.variability.XArchADTVariabilityEvent.Type;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.swt.graphics.RGB;
@NonNullByDefault
public class DecorateChangesLogic extends AbstractThingLogic implements IXArchADTVariabilityListener, IBNAModelListener {
private static final IThingKey<ChangeStatus> CHANGE_STATUS_KEY = ThingKey.create("ChangeStatus");
protected final ThingValueTrackingLogic valueLogic;
protected final MirrorValueLogic mirrorLogic;
protected final IXArchADTVariability xarch;
public DecorateChangesLogic(IBNAWorld world, IXArchADTVariability xarch) {
super(world);
valueLogic = logics.addThingLogic(ThingValueTrackingLogic.class);
mirrorLogic = logics.addThingLogic(MirrorValueLogic.class);
this.xarch = xarch;
}
@Override
public void handleXArchADTVariabilityEvent(final XArchADTVariabilityEvent evt) {
BNAUtils.checkLock();
if (evt.getType() == Type.STATUS) {
for (IThing t : valueLogic.getThings(IHasObjRef.OBJREF_KEY, evt.getChangedObjRef())) {
updateDecoration(t, evt.getChangeStatus());
}
}
}
@Override
public void bnaModelChanged(BNAModelEvent evt) {
BNAUtils.checkLock();
switch (evt.getEventType()) {
case THING_ADDED: {
IThing t = evt.getTargetThing();
if (t != null) {
ObjRef objRef = t.get(IHasObjRef.OBJREF_KEY);
if (objRef != null) {
updateDecoration(t, xarch.getChangeStatus(objRef));
}
}
}
break;
case THING_REMOVED: {
IThing t = evt.getTargetThing();
if (t != null) {
removeDecoration(t);
}
}
break;
case THING_CHANGED: {
ThingEvent te = evt.getThingEvent();
if (te != null) {
if (IHasObjRef.OBJREF_KEY.equals(te.getPropertyName())) {
ObjRef objRef = (ObjRef) te.getNewPropertyValue();
if (objRef != null) {
updateDecoration(te.getTargetThing(), xarch.getChangeStatus(objRef));
}
else {
removeDecoration(te.getTargetThing());
}
}
}
}
break;
default: // do nothing
}
}
protected void updateDecoration(IThing t, ChangeStatus changeStatus) {
switch (changeStatus) {
case ATTACHED:
removeDecoration(t);
break;
case EXPLICITLY_ADDED:
updateDecoration(t, new RGB(0, 255, 255), 1f, true);
break;
case EXPLICITLY_ADDED_BUT_REALLY_REMOVED:
updateDecoration(t, new RGB(0, 255, 255), 0.5f, false);
break;
case EXPLICITLY_MODIFIED:
updateDecoration(t, new RGB(255, 0, 255), 1f, true);
break;
case EXPLICITLY_MODIFIED_BUT_REALLY_REMOVED:
updateDecoration(t, new RGB(255, 0, 255), 0.5f, false);
break;
case EXPLICITLY_REMOVED:
updateDecoration(t, new RGB(255, 0, 0), 0.5f, false);
break;
case EXPLICITLY_REMOVED_BUT_REALLY_ADDED:
updateDecoration(t, new RGB(255, 0, 0), 1f, true);
break;
case OVERVIEW:
updateDecoration(t, null, 0.5f, false);
break;
case NOT_ENABLED:
// do nothing
break;
default:
throw new IllegalArgumentException(changeStatus.toString());
}
}
private void updateDecoration(IThing t, RGB rgb, float alpha, boolean editable) {
removeDecoration(t);
updateAttributes(t, alpha, editable);
if (t instanceof IHasMutableGlow) {
((IHasMutableGlow) t).setGlowColor(rgb);
((IHasMutableGlow) t).setGlowAlpha(alpha);
}
}
protected void removeDecoration(IThing t) {
if (t instanceof IHasMutableGlow) {
((IHasMutableGlow) t).setGlowColor(null);
}
t.remove(CHANGE_STATUS_KEY);
updateAttributes(t, 1f, true);
}
private void updateAttributes(IThing t, double alpha, boolean editable) {
t.set(IHasAlpha.ALPHA_KEY, alpha);
t.set(IHasBackground.BACKGROUND_KEY, !editable);
if (!editable && t.has(IHasSelected.SELECTED_KEY, true)) {
t.set(IHasSelected.SELECTED_KEY, false);
}
for (IThing p : Assemblies.getParts(model, t).values()) {
if (!p.has(IHasObjRef.OBJREF_KEY) || p.has(IHasObjRef.OBJREF_KEY, t.get(IHasObjRef.OBJREF_KEY))) {
updateAttributes(p, alpha, editable);
}
}
}
}