blob: d4f2f9882d52b36b79865a90bb4f5363316850ce [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 Sybase, Inc. and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.pagedesigner.commands.nav;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.jst.pagedesigner.common.logging.Logger;
import org.eclipse.jst.pagedesigner.dom.EditModelQuery;
import org.eclipse.jst.pagedesigner.validation.caret.ActionData;
import org.eclipse.jst.pagedesigner.validation.caret.IMovementMediator;
import org.eclipse.jst.pagedesigner.validation.caret.InlineEditingNavigationMediator;
import org.eclipse.jst.pagedesigner.validation.caret.Target;
import org.eclipse.jst.pagedesigner.viewer.DesignPosition;
import org.eclipse.jst.pagedesigner.viewer.DesignRange;
import org.eclipse.jst.pagedesigner.viewer.EditPartPositionHelper;
import org.eclipse.jst.pagedesigner.viewer.IHTMLGraphicalViewer;
import org.eclipse.swt.widgets.Caret;
/**
* @author mengbo
*/
public class VerticalMoveCommand extends Command {
private static Logger _log = PDPlugin
.getLogger(HorizontalMoveCommand.class);
IHTMLGraphicalViewer _viewer;
boolean _up;
boolean _onlyMoveEnd;
/**
* @param viewer
* @param b
* @param c
*/
public VerticalMoveCommand(IHTMLGraphicalViewer viewer, boolean up,
boolean c) {
_viewer = viewer;
_up = up;
_onlyMoveEnd = c;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.commands.Command#execute()
*/
public void execute() {
int OFFSET = 2;
DesignRange range = _viewer.getRangeSelection();
if (range == null || !range.isValid()) {
_log.error("invalud range");
return;
}
IMovementMediator moveMediator = new InlineEditingNavigationMediator(
new ActionData(ActionData.KEYBOARD_NAVAGATION, null));
DesignPosition position = range.getEndPosition();
Caret caret = _viewer.getCaret();
Point point = null;
DesignPosition newPos = position;
EditPart containerpart = null, rootpart1;
if (_up) {
point = new Point(((CaretPositionTracker) _viewer).getXoffset(),
caret.getBounds().y);
} else {
point = new Point(((CaretPositionTracker) _viewer).getXoffset(),
caret.getBounds().y + caret.getBounds().height);
}
rootpart1 = getRootEditablePart(position.getContainerPart(),
moveMediator);// position.getContainerPart();
if (rootpart1 == null) {
return;
} else {
point = adjustLocation(rootpart1, point);
}
Rectangle bound = EditPartPositionHelper.getAbsoluteBounds(rootpart1);
// get current according to the point.
// FlowBoxLine line =
// getCurrentLine(moveMediator.getEditableContainer(new
// Target(rootpart)), point, moveMediator);
while (true) {
// try to change offset and then to search for new point.
if (_up) {
point.y -= OFFSET;
if (point.y <= bound.y) {
newPos = position;
break;
}
} else {
point.y += OFFSET;
if (point.y >= bound.y + bound.height) {
newPos = position;
break;
}
}
containerpart = ((InlineEditingNavigationMediator) moveMediator)
.getConstainedEditableContainer(position, point, _viewer);
if (containerpart != null) {
if (!EditModelQuery.isChild(Target.resolveNode(rootpart1),
Target.resolveNode(containerpart))) {
containerpart = rootpart1;
}
bound = EditPartPositionHelper.getAbsoluteBounds(rootpart1);
newPos = EditPartPositionHelper
.findEditPartPositionConstrained(containerpart, point,
moveMediator);
} else {
newPos = position;
break;
}
if (newPos != null) {
if (found(newPos, position)) {
break;
}
}
}
setRange(position, newPos);
}
private void setRange(DesignPosition position, DesignPosition newPos) {
if (!EditModelQuery.isSame(position, newPos)) {
{
if (_onlyMoveEnd) {
_viewer.setRangeEndPosition(newPos);
} else {
_viewer.setRange(newPos, newPos);
}
}
}
}
/*
* We should change this, it is too tricky to do in this way.
*/
private Point adjustLocation(EditPart rootPart, Point point) {
Point result = point.getCopy();
Rectangle bounds = EditPartPositionHelper.getAbsoluteBounds(rootPart);
if (!bounds.contains(point)) {
if (bounds.getLeft().x > point.x) {
result.x = bounds.getLeft().x;
} else if (bounds.getRight().x < point.x) {
result.x = bounds.getRight().x;
}
}
return result;
}
private EditPart getRootEditablePart(EditPart part,
IMovementMediator moveMediator) {
EditPart rootpart = null;
if ((rootpart = ((InlineEditingNavigationMediator) moveMediator)
.getRootConstainedEditableContainer(new Target(part))) == null) {
rootpart = moveMediator.getEditableContainer(new Target(part));
}
return rootpart;
}
private boolean found(DesignPosition newPos, DesignPosition prevPos) {
Rectangle newRec = EditPartPositionHelper
.convertToAbsoluteCaretRect(newPos);
Rectangle prevRec = EditPartPositionHelper
.convertToAbsoluteCaretRect(prevPos);
if (_up) {
return getYDistance(newRec, prevRec, _up) < 0;
} else {
return getYDistance(newRec, prevRec, _up) > 0;
}
}
/**
* Distance from rec1 to rec2 at y coordination, if top, compare top,
* otherwise compare bottom.
*
* @param rec1
* @param rec2
* @param up
* @return
*/
private int getYDistance(Rectangle rec1, Rectangle rec2, boolean top) {
if (rec1.getCopy().intersect(rec2).height > 0) {
return 0;
} else {
if (top) {
return rec1.getTop().y - rec2.getTop().y;
} else {
return rec1.getBottom().y - rec2.getBottom().y;
}
}
}
}