/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.gef.draw2d.geometry;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
public class AlignmentSolver extends AbstractPositionSolver implements
Comparator<Object> {
private int alignmentHint;
private ITransformer t;
/**
* @see PositionConstants#LEFT
* @see PositionConstants#CENTER
* @see PositionConstants#RIGHT
* @see PositionConstants#TOP
* @see PositionConstants#MIDDLE
* @see PositionConstants#BOTTOM
* @param alignmentHint
*/
public AlignmentSolver(int alignmentHint) {
this.alignmentHint = alignmentHint;
this.t = new Transposer();
this.t.setEnabled(!isHorizontal());
}
public int getAlignmentHint() {
return alignmentHint;
}
public void setAlignmentHint(int alignmentHint) {
this.alignmentHint = alignmentHint;
boolean horizontal = isHorizontal();
this.t.setEnabled(!horizontal);
}
protected boolean isHorizontal() {
return (getAlignmentHint() & PositionConstants.LEFT_CENTER_RIGHT) != 0;
}
public void setOrigin(int x, int y) {
t.setOrigin(x, y);
super.setOrigin(x, y);
}
public void setOrigin(Point origin) {
t.setOrigin(origin);
super.setOrigin(origin);
}
public void solve() {
Rectangle refBounds = getReferenceBounds();
if (refBounds == null)
return;
setOrigin(refBounds.x + refBounds.width / 2, refBounds.y
+ refBounds.height / 2);
t.t(refBounds);
int refLine = getReferenceLine(refBounds);
Object[] keys = sort(getFreeKeys().toArray());
for (Object key : keys) {
Point pos = getSolvedPosition(key);
Rectangle bounds = getSolvedBounds(key);
t.t(pos);
pos.x += refLine - getReferenceLine(t.tr(bounds));
t.r(pos);
}
}
protected Collection<Object> getFreeKeys() {
return getKeys(IIntersectionSolver.CATEGORY_FREE);
}
private Object[] sort(Object[] keys) {
Arrays.sort(keys, this);
return keys;
}
protected Collection<Object> getReferenceKeys() {
return getKeys();
}
protected Rectangle getReferenceBounds() {
Rectangle r = null;
for (Object key : getReferenceKeys()) {
r = Geometry.union(r, getSolvedBounds(key));
}
return r;
}
private int getReferenceLine(Rectangle bounds) {
if (isLead())
return bounds.x;
if (isTrail())
return bounds.x + bounds.width;
return bounds.x + bounds.width / 2;
}
private boolean isLead() {
return (getAlignmentHint() & PositionConstants.LEFT) != 0
|| (getAlignmentHint() & PositionConstants.TOP) != 0;
}
private boolean isTrail() {
return (getAlignmentHint() & PositionConstants.RIGHT) != 0
|| (getAlignmentHint() & PositionConstants.BOTTOM) != 0;
}
public int compare(Object o1, Object o2) {
Rectangle r1 = t.tr(getSolvedBounds(o1));
Rectangle r2 = t.tr(getSolvedBounds(o2));
int c1 = r1.y + r1.height / 2;
int c2 = r2.y + r2.height / 2;
if (c1 == c2)
return 1;
return c1 - c2;
}
}