package org.archstudio.xadl.bna.logics.editing;
import java.util.List;
import java.util.Map;
import org.archstudio.bna.BNAModelEvent;
import org.archstudio.bna.IBNAModelListener;
import org.archstudio.bna.IBNAView;
import org.archstudio.bna.IBNAWorld;
import org.archstudio.bna.ICoordinate;
import org.archstudio.bna.IThing;
import org.archstudio.bna.facets.IHasMutableReferencePoint;
import org.archstudio.bna.facets.IHasMutableSelected;
import org.archstudio.bna.facets.IHasSelected;
import org.archstudio.bna.logics.AbstractThingLogic;
import org.archstudio.bna.things.utility.EnvironmentPropertiesThing;
import org.archstudio.bna.ui.IBNAMenuListener2;
import org.archstudio.bna.utils.BNAAction;
import org.archstudio.bna.utils.BNAUtils;
import org.archstudio.bna.utils.BNAUtils2.ThingsAtLocation;
import org.archstudio.bna.utils.GridUtils;
import org.archstudio.bna.utils.UserEditableUtils;
import org.archstudio.swtutils.SWTWidgetUtils;
import org.archstudio.utils.resources.Resources;
import org.archstudio.utils.resources.swt.ImageUtils;
import org.archstudio.xadl.bna.facets.IHasObjRef;
import org.archstudio.xadl.bna.utils.XArchADTCopyPaste;
import org.archstudio.xadl.bna.utils.XArchADTOperations;
import org.archstudio.xarchadt.IXArchADT;
import org.archstudio.xarchadt.IXArchADTFeature;
import org.archstudio.xarchadt.IXArchADTTypeMetadata;
import org.archstudio.xarchadt.ObjRef;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class XadlCopyPasteLogic extends AbstractThingLogic implements IBNAMenuListener2, IBNAModelListener {
protected final IXArchADT xarch;
protected static final XArchADTCopyPaste copyPaste = new XArchADTCopyPaste();
protected final Map<ObjRef, Integer> selectAndMoveObjRefs = Maps.newHashMap();
protected int pasteOffset = 0;
public XadlCopyPasteLogic(IBNAWorld world, IXArchADT xarch) {
super(world);
this.xarch = xarch;
SWTWidgetUtils.async(Display.getDefault(), new Runnable() {
@Override
public void run() {
IActionBars actionBars = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
.getActiveEditor().getEditorSite().getActionBars();
actionBars.setGlobalActionHandler(ActionFactory.CUT.getId(), new BNAAction() {
@Override
public void runWithEventAndLock(@Nullable Event event) {
copy();
delete();
}
@Override
public ImageDescriptor getImageDescriptor() {
return ImageUtils
.toImageDescriptor(ImageUtils.getImage(Display.getDefault(), Resources.CUT_ICON_16));
}
});
actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), new BNAAction() {
@Override
public void runWithEventAndLock(@Nullable Event event) {
copy();
}
@Override
public ImageDescriptor getImageDescriptor() {
return ImageUtils
.toImageDescriptor(ImageUtils.getImage(Display.getDefault(), Resources.COPY_ICON_16));
}
});
actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), new BNAAction() {
@Override
public void runWithEventAndLock(@Nullable Event event) {
paste();
}
@Override
public ImageDescriptor getImageDescriptor() {
return ImageUtils
.toImageDescriptor(ImageUtils.getImage(Display.getDefault(), Resources.PASTE_ICON_16));
}
});
actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), new BNAAction() {
@Override
public void runWithEventAndLock(@Nullable Event event) {
delete();
}
@Override
public ImageDescriptor getImageDescriptor() {
return ImageUtils
.toImageDescriptor(ImageUtils.getImage(Display.getDefault(), Resources.DELETE_ICON_16));
}
});
actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), new BNAAction() {
@Override
public void runWithEventAndLock(@Nullable Event event) {
selectAll();
}
});
actionBars.updateActionBars();
}
});
}
@Override
public void dispose() {
BNAUtils.checkLock();
SWTWidgetUtils.async(Display.getDefault(), new Runnable() {
@Override
public void run() {
IActionBars actionBars = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
.getActiveEditor().getEditorSite().getActionBars();
actionBars.setGlobalActionHandler(ActionFactory.CUT.getId(), null);
actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), null);
actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), null);
actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), null);
actionBars.updateActionBars();
}
});
super.dispose();
}
List<ObjRef> getSelectedObjRefs() {
List<ObjRef> objRefs = Lists.newArrayList();
for (IThing t : model.getAllThings()) {
if (t.has(IHasSelected.SELECTED_KEY, true)) {
ObjRef objRef = t.get(IHasObjRef.OBJREF_KEY);
if (objRef != null) {
objRefs.add(objRef);
}
}
}
return objRefs;
}
public void selectAll() {
BNAUtils.checkLock();
for (IThing t : model.getAllThings()) {
if (UserEditableUtils.isEditableForAllQualities(t, IHasMutableSelected.USER_MAY_SELECT)) {
t.set(IHasSelected.SELECTED_KEY, true);
}
}
}
public void copy() {
BNAUtils.checkLock();
pasteOffset = 0;
copyPaste.copy(xarch, getSelectedObjRefs());
}
public void paste() {
BNAUtils.checkLock();
EnvironmentPropertiesThing ept = EnvironmentPropertiesThing.createIn(world);
ObjRef rootRef = ept.get(IHasObjRef.OBJREF_KEY);
if (rootRef != null) {
XArchADTOperations xarch = new XArchADTOperations(this.xarch);
// unselect everything
for (IThing t : model.getAllThings()) {
t.set(IHasSelected.SELECTED_KEY, false);
}
selectAndMoveObjRefs.clear();
// keep track of the new ObjRefs to select and move them
pasteOffset += GridUtils.getGridSpacing(world);
for (ObjRef objRef : copyPaste.paste(xarch, rootRef)) {
selectAndMoveObjRefs.put(objRef, pasteOffset);
}
xarch.done("Paste");
}
}
@Override
public void bnaModelChanged(BNAModelEvent evt) {
BNAUtils.checkLock();
// select the new ObjRefs added by paste()
switch (evt.getEventType()) {
case THING_CHANGED:
IThing ct = evt.getTargetThing();
if (ct != null) {
if (selectAndMoveObjRefs.containsKey(ct.get(IHasObjRef.OBJREF_KEY))) {
int move = selectAndMoveObjRefs.remove(ct.get(IHasObjRef.OBJREF_KEY));
if (UserEditableUtils.isEditableForAllQualities(ct, IHasMutableSelected.USER_MAY_SELECT)) {
ct.set(IHasSelected.SELECTED_KEY, true);
}
if (ct instanceof IHasMutableReferencePoint) {
Point p = ((IHasMutableReferencePoint) ct).getReferencePoint();
p.x += move;
p.y += move;
((IHasMutableReferencePoint) ct).setReferencePoint(p);
}
}
}
break;
default:
// do nothing
}
}
public void delete() {
BNAUtils.checkLock();
XArchADTOperations xarch = new XArchADTOperations(this.xarch);
for (ObjRef objRef : getSelectedObjRefs()) {
ObjRef parentRef = xarch.getParent(objRef);
IXArchADTTypeMetadata parentType = xarch.getTypeMetadata(parentRef);
String featureName = xarch.getContainingFeatureName(objRef);
IXArchADTFeature feature = parentType.getFeatures().get(featureName);
switch (feature.getType()) {
case ATTRIBUTE:
throw new IllegalArgumentException();
case ELEMENT_SINGLE:
xarch.clear(parentRef, featureName);
break;
case ELEMENT_MULTIPLE:
xarch.remove(parentRef, featureName, objRef);
break;
}
}
xarch.done("Delete");
}
@Override
public void fillMenu(IBNAView view, ICoordinate location, ThingsAtLocation things, IMenuManager menu) {
BNAUtils.checkLock();
menu.add(new BNAAction("Cut") {
@Override
public void runWithLock() {
copy();
delete();
}
@Override
public ImageDescriptor getImageDescriptor() {
return ImageUtils.toImageDescriptor(ImageUtils.getImage(Display.getDefault(), Resources.CUT_ICON_16));
}
});
menu.add(new BNAAction("Copy") {
@Override
public void runWithLock() {
copy();
}
@Override
public ImageDescriptor getImageDescriptor() {
return ImageUtils.toImageDescriptor(ImageUtils.getImage(Display.getDefault(), Resources.COPY_ICON_16));
}
});
menu.add(new BNAAction("Paste") {
@Override
public void runWithLock() {
paste();
}
@Override
public ImageDescriptor getImageDescriptor() {
return ImageUtils.toImageDescriptor(ImageUtils.getImage(Display.getDefault(), Resources.PASTE_ICON_16));
}
});
}
}