package org.archstudio.bna.logics.editing;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
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.IHasMutableAnchorPoint;
import org.archstudio.bna.facets.IHasMutableBoundingBox;
import org.archstudio.bna.logics.AbstractThingLogic;
import org.archstudio.bna.logics.coordinating.StickPointLogic;
import org.archstudio.bna.ui.IBNAMenuListener2;
import org.archstudio.bna.utils.BNAAction;
import org.archstudio.bna.utils.BNAAlignUtils;
import org.archstudio.bna.utils.BNADistributeUtils;
import org.archstudio.bna.utils.BNAUtils;
import org.archstudio.bna.utils.BNAUtils2.ThingsAtLocation;
import org.archstudio.swtutils.constants.HorizontalAlignment;
import org.archstudio.swtutils.constants.VerticalAlignment;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
public class AlignAndDistributeLogic extends AbstractThingLogic implements IBNAMenuListener2 {
protected ImageRegistry imageRegistry = null;
protected static final String ALIGN_LEFT = "alignLeft";
protected static final String ALIGN_CENTER = "alignCenter";
protected static final String ALIGN_RIGHT = "alignRight";
protected static final String ALIGN_TOP = "alignTop";
protected static final String ALIGN_MIDDLE = "alignMiddle";
protected static final String ALIGN_BOTTOM = "alignBottom";
protected static final String DISTRIBUTE_HORIZONTAL_LOOSE = "distributeHorizontalLoose";
protected static final String DISTRIBUTE_HORIZONTAL_TIGHT = "distributeHorizontalTight";
protected static final String DISTRIBUTE_VERTICAL_LOOSE = "distributeVerticalLoose";
protected static final String DISTRIBUTE_VERTICAL_TIGHT = "distributeVerticalTight";
final StickPointLogic stickLogic;
public AlignAndDistributeLogic(IBNAWorld world) {
super(world);
stickLogic = logics.getThingLogic(StickPointLogic.class);
}
protected void loadImages(IBNAView view) {
Display disp = view.getBNAUI().getComposite().getDisplay();
imageRegistry = new ImageRegistry(disp);
imageRegistry.put(ALIGN_LEFT, new Image(disp, getClass().getResourceAsStream("res/align-left.gif")));
imageRegistry.put(ALIGN_CENTER, new Image(disp, getClass().getResourceAsStream("res/align-center.gif")));
imageRegistry.put(ALIGN_RIGHT, new Image(disp, getClass().getResourceAsStream("res/align-right.gif")));
imageRegistry.put(ALIGN_TOP, new Image(disp, getClass().getResourceAsStream("res/align-top.gif")));
imageRegistry.put(ALIGN_MIDDLE, new Image(disp, getClass().getResourceAsStream("res/align-middle.gif")));
imageRegistry.put(ALIGN_BOTTOM, new Image(disp, getClass().getResourceAsStream("res/align-bottom.gif")));
imageRegistry.put(DISTRIBUTE_HORIZONTAL_LOOSE,
new Image(disp, getClass().getResourceAsStream("res/distribute-horizontal-loose.gif")));
imageRegistry.put(DISTRIBUTE_HORIZONTAL_TIGHT,
new Image(disp, getClass().getResourceAsStream("res/distribute-horizontal-tight.gif")));
imageRegistry.put(DISTRIBUTE_VERTICAL_LOOSE,
new Image(disp, getClass().getResourceAsStream("res/distribute-vertical-loose.gif")));
imageRegistry.put(DISTRIBUTE_VERTICAL_TIGHT,
new Image(disp, getClass().getResourceAsStream("res/distribute-vertical-tight.gif")));
}
@Override
public void dispose() {
BNAUtils.checkLock();
if (imageRegistry != null) {
imageRegistry.dispose();
}
}
@Override
public void fillMenu(IBNAView view, ICoordinate location, ThingsAtLocation things, IMenuManager menu) {
BNAUtils.checkLock();
if (imageRegistry == null) {
loadImages(view);
}
// Make sure at least two things have either an anchor point or bounding box.
Collection<IThing> selectedThings = BNAUtils.getSelectedThings(view.getBNAWorld().getBNAModel());
final List<IThing> thingsToEditList = new ArrayList<IThing>();
for (IThing st : selectedThings) {
if (st instanceof IHasMutableBoundingBox || st instanceof IHasMutableAnchorPoint) {
thingsToEditList.add(st);
}
}
if (thingsToEditList.size() > 2) {
final IThing[] thingsToEdit = thingsToEditList.toArray(new IThing[thingsToEditList.size()]);
final Runnable undoRunnable = BNAOperations.takeSnapshotOfLocations(model, thingsToEditList);
IMenuManager alignMenu = new MenuManager("Align");
alignMenu.add(new BNAAction("Align &Top", imageRegistry.getDescriptor(ALIGN_TOP)) {
@Override
public void runWithLock() {
BNAAlignUtils.align(thingsToEdit, VerticalAlignment.TOP);
BNAOperations.runnable("Align", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, thingsToEditList), false);
}
});
alignMenu.add(new BNAAction("Align &Middle", imageRegistry.getDescriptor(ALIGN_MIDDLE)) {
@Override
public void runWithLock() {
BNAAlignUtils.align(thingsToEdit, VerticalAlignment.MIDDLE);
BNAOperations.runnable("Align", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, thingsToEditList), false);
}
});
alignMenu.add(new BNAAction("Align &Bottom", imageRegistry.getDescriptor(ALIGN_BOTTOM)) {
@Override
public void runWithLock() {
BNAAlignUtils.align(thingsToEdit, VerticalAlignment.BOTTOM);
BNAOperations.runnable("Align", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, thingsToEditList), false);
}
});
alignMenu.add(new BNAAction("Align &Left", imageRegistry.getDescriptor(ALIGN_LEFT)) {
@Override
public void runWithLock() {
BNAAlignUtils.align(thingsToEdit, HorizontalAlignment.LEFT);
BNAOperations.runnable("Align", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, thingsToEditList), false);
}
});
alignMenu.add(new BNAAction("Align &Center", imageRegistry.getDescriptor(ALIGN_CENTER)) {
@Override
public void runWithLock() {
BNAAlignUtils.align(thingsToEdit, HorizontalAlignment.CENTER);
BNAOperations.runnable("Align", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, thingsToEditList), false);
}
});
alignMenu.add(new BNAAction("Align &Right", imageRegistry.getDescriptor(ALIGN_RIGHT)) {
@Override
public void runWithLock() {
BNAAlignUtils.align(thingsToEdit, HorizontalAlignment.RIGHT);
BNAOperations.runnable("Align", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, thingsToEditList), false);
}
});
menu.add(alignMenu);
IMenuManager distributeMenu = new MenuManager("Distribute");
distributeMenu.add(new BNAAction("Distribute Horizontal Loose",
imageRegistry.getDescriptor(DISTRIBUTE_HORIZONTAL_LOOSE)) {
@Override
public void runWithLock() {
BNADistributeUtils.distributeHorizontalLoose(thingsToEdit);
BNAOperations.runnable("Distribute", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, thingsToEditList), false);
}
});
distributeMenu.add(new BNAAction("Distribute Horizontal Tight",
imageRegistry.getDescriptor(DISTRIBUTE_HORIZONTAL_TIGHT)) {
@Override
public void runWithLock() {
BNADistributeUtils.distributeHorizontalTight(thingsToEdit);
BNAOperations.runnable("Distribute", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, thingsToEditList), false);
}
});
distributeMenu.add(
new BNAAction("Distribute Vertical Loose", imageRegistry.getDescriptor(DISTRIBUTE_VERTICAL_LOOSE)) {
@Override
public void runWithLock() {
BNADistributeUtils.distributeVerticalLoose(thingsToEdit);
BNAOperations.runnable("Distribute", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, thingsToEditList), false);
}
});
distributeMenu.add(
new BNAAction("Distribute Vertical Tight", imageRegistry.getDescriptor(DISTRIBUTE_VERTICAL_TIGHT)) {
@Override
public void runWithLock() {
BNADistributeUtils.distributeVerticalTight(thingsToEdit);
BNAOperations.runnable("Distribute", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, thingsToEditList), false);
}
});
menu.add(distributeMenu);
}
// Select all things if nothing is selected.
Collection<IThing> thingsToFlip = Lists.newArrayList(BNAUtils.getSelectedThings(model));
if (thingsToFlip.isEmpty()) {
thingsToFlip.addAll(model.getAllThings());
}
thingsToFlip = Collections2.filter(thingsToFlip, BNAAlignUtils.FLIP_THING_PREDICATE);
if (thingsToFlip.size() >= 1) {
final Collection<IThing> finalThingsToFlip = thingsToFlip;
final Runnable undoRunnable = BNAOperations.takeSnapshotOfLocations(model, thingsToEditList);
IMenuManager flipMenu = new MenuManager("Flip");
flipMenu.add(new BNAAction("Flip &Vertically", imageRegistry.getDescriptor(ALIGN_MIDDLE)) {
@Override
public void runWithLock() {
BNAAlignUtils.flip(stickLogic, finalThingsToFlip, false);
BNAOperations.runnable("Flip Vertically", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, finalThingsToFlip), false);
}
});
flipMenu.add(new BNAAction("Flip &Horizontally", imageRegistry.getDescriptor(ALIGN_CENTER)) {
@Override
public void runWithLock() {
BNAAlignUtils.flip(stickLogic, finalThingsToFlip, true);
BNAOperations.runnable("Flip Horizontally", undoRunnable,
BNAOperations.takeSnapshotOfLocations(model, finalThingsToFlip), false);
}
});
menu.add(flipMenu);
}
}
}