Package org.eclipse.jst.pagedesigner.viewer

Source Code of org.eclipse.jst.pagedesigner.viewer.CaretPositionResolver

/*******************************************************************************
* 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.viewer;

import java.util.List;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.jst.pagedesigner.IHTMLConstants;
import org.eclipse.jst.pagedesigner.dom.EditModelQuery;
import org.eclipse.jst.pagedesigner.validation.caret.IMovementMediator;
import org.eclipse.jst.pagedesigner.validation.caret.IPositionMediator;
import org.eclipse.jst.pagedesigner.validation.caret.Target;
import org.w3c.dom.Node;

/**
* @author mengbo
* @version 1.5
*/
public class CaretPositionResolver {
  private IPositionMediator _validator;

  private Point _point;

  private static CaretPositionResolver _instance;

  /**
   * @param validator
   * @param point
   * @return the singleton instance
   */
  public static CaretPositionResolver getInstance(
      IPositionMediator validator, Point point) {
    if (_instance == null) {
      _instance = new CaretPositionResolver();
    }
    _instance.setPoint(point);
    _instance.setValidator(validator);
    return _instance;
  }

  /**
   * @param _point
   *            The _point to set.
   */
  private void setPoint(Point _point) {
    this._point = _point;
  }

  /**
   * @param _validator
   *            The _validator to set.
   */
  private void setValidator(IPositionMediator _validator) {
    this._validator = _validator;
  }

  /**
   * Calculate the two part's distance to point, the shorter one will be
   * return. Distance is calculated based on: if there is one box contains
   * point.y, then calculate that box, or if there is no any such one box,
   * then calculate the y distance.
   *
   * @param part1
   * @param part2
   * @param point
   * @return
   */
  static LayoutPart getCloserPart(LayoutPart part1, LayoutPart part2,
      Point _point) {
    if (part1 == null
        || EditModelQuery.isTransparentText(Target.resolveNode(part1
            .getPart()))) {
      return part2;
    } else if (part2 == null
        || EditModelQuery.isTransparentText(Target.resolveNode(part2
            .getPart()))) {
      return part1;
    }
    Rectangle rect1 = part1.getAbsoluteBounds();
    Rectangle rect2 = part2.getAbsoluteBounds();
    Node n1 = Target.resolveNode(part1.getPart());
    Node n2 = Target.resolveNode(part2.getPart());
    // Within same.
    if (EditModelQuery.isChild(n1, n2)
        && (CaretPositionResolver.getXDistance(rect2, _point) == 0)
        && !part1.isCloseToEdgeFromOutSide()) {
      return part2;
    } else if (EditModelQuery.isChild(n2, n1)
        && (CaretPositionResolver.getXDistance(rect1, _point) == 0 && !part2
            .isCloseToEdgeFromOutSide())
        && !part2.isCloseToEdgeFromOutSide()) {
      return part1;
    }
    if (rect1.intersect(new Rectangle(rect1.x, rect2.y, rect1.width,
        rect2.height)).height == 0) {
      return heightFirst(part1, part2, _point);
    }
        return widthFirst(part1, part2, _point);
  }

  private static LayoutPart heightFirst(LayoutPart part1, LayoutPart part2,
      Point _point) {
    Rectangle rect1 = part1.getAbsoluteBounds();
    Rectangle rect2 = part2.getAbsoluteBounds();
    int offset1 = Math.abs(CaretPositionResolver
        .getYDistance(rect1, _point));
    int offset2 = Math.abs(CaretPositionResolver
        .getYDistance(rect2, _point));
    if (offset1 > offset2) {
      return part2;
    } else if (offset1 < offset2) {
      return part1;
    } else {
      offset1 = Math.abs(CaretPositionResolver
          .getXDistance(rect1, _point));
      offset2 = Math.abs(CaretPositionResolver
          .getXDistance(rect2, _point));
      if (offset1 >= offset2) {
        return part2;
      }
            return part1;
    }
  }

  private static LayoutPart widthFirst(LayoutPart part1, LayoutPart part2,
      Point _point) {
    Rectangle rect1 = part1.getAbsoluteBounds();
    Rectangle rect2 = part2.getAbsoluteBounds();
    int offset1 = Math.abs(CaretPositionResolver
        .getXDistance(rect1, _point));
    int offset2 = Math.abs(CaretPositionResolver
        .getXDistance(rect2, _point));
    if (offset1 > offset2) {
      return part2;
    } else if (offset1 < offset2) {
      return part1;
    } else {
      offset1 = Math.abs(CaretPositionResolver
          .getYDistance(rect1, _point));
      offset2 = Math.abs(CaretPositionResolver
          .getYDistance(rect2, _point));
      if (offset1 >= offset2) {
        return part2;
      }
            return part1;
    }
  }

  /**
   * Return a descendent part under parent that is one of the closest part to
   * point.
   *
   * @param parent
   * @return
   */
  private LayoutPart getClosestChildPart(LayoutPart parent) {
    LayoutPart result = null;
    if (parent != null) {
      List children = null;
      if ((children = parent.getPart().getChildren()).size() > 0) // &&
      // _validator.hasEditableArea(new
      // Target(parent.getPart())))
      {
        // iterate its children, we know the part doesn't contain p. so
        // we only see if its children can be
        // referenced.
        for (int i = 0, n = children.size(); i < n; i++) {
          LayoutPart nextPart = new LayoutPart((EditPart) children
              .get(i), _point);
          Target target = new Target(nextPart.getPart());
          if (_validator.isValidPosition(new DesignRefPosition(target
              .getPart(), false))) {
            result = getCloserPart(result, nextPart, _point);
          } else if (_validator.hasEditableArea(target)) {
            LayoutPart temp = getClosestChildPart(nextPart);
            if (temp == null) {
              temp = nextPart;
            }
            result = getCloserPart(result, temp, _point);
          }
        }
      }
    }
    return result;
  }

  /**
   * Use by vertical movement, we need to see whther the par
   *
   * @param closestPart
   * @param target
   * @return
   */
  LayoutPart resolveClosestPartFrom(LayoutPart closestPart) {
    Target target = new Target(closestPart.getPart());
    LayoutPart finalPart = null;
    if (EditModelQuery.isInline(Target.resolveNode(closestPart.getPart()))) {

      if (closestPart.isAfterPoint() || closestPart.isBeforePoint()) {
        finalPart = closestPart;
      } else {
        if (_validator.hasEditableArea(target)
            && (_validator instanceof IMovementMediator
                && ((IMovementMediator) _validator)
                    .allowsMoveIn(target) || !(_validator instanceof IMovementMediator))) {
          finalPart = getClosestChildPartOrPart(closestPart);
        }
      }
    }
    // block
    else {
      if (closestPart.contains(_point)) {
        if (_validator.hasEditableArea(target) && //
            (_validator instanceof IMovementMediator
                && ((IMovementMediator) _validator)
                    .allowsMoveIn(target) || !(_validator instanceof IMovementMediator))) {
          finalPart = getClosestChildPartOrPart(closestPart);
        }
      }
      // outside of bounds
      else {
        if (_validator.hasEditableArea(target)
            && !IHTMLConstants.TAG_TABLE.equalsIgnoreCase(target
                .getNode().getNodeName())
            && (_validator instanceof IMovementMediator
                && ((IMovementMediator) _validator)
                    .allowsMoveIn(target) || !(_validator instanceof IMovementMediator))) {
          if (closestPart.atSameRow(_point)) {
            finalPart = getClosestChildPartOrPart(closestPart);
          } else if (!_validator
              .isValidPosition(new DesignRefPosition(target
                  .getPart(), true))) {
            finalPart = getClosestChildPartOrPart(closestPart);
          }
        }
      }
    }
    if (finalPart == null && //
        (_validator.isValidPosition(new DesignRefPosition(target
            .getPart(), true)) || //
        _validator.isValidPosition(new DesignRefPosition(target
            .getPart(), false)))) {
      finalPart = closestPart;
    }
    return finalPart;
  }

  private LayoutPart getClosestChildPartOrPart(LayoutPart closestPart) {
    LayoutPart result = getClosestChildPart(closestPart);
    if (result != null) {
      result = resolveClosestPartFrom(result);
    } else {
      if (closestPart.getConcretePart() == null) {
        result = closestPart;
      }
    }
    return result;
  }

  /**
   * Get the distance from rect's edge to point.x.
   *
   * @param rect
   * @param point
   * @return the X distance
   */
  public static int getXDistance(Rectangle rect, Point point) {
    if (rect.getRight().x <= point.x) {
      return point.x - (rect.getRight().x);
    } else if (rect.x >= point.x) {
      return point.x - rect.x;
    } else if (rect.x <= point.x && point.x <= rect.getRight().x) {
      return 0;
    }
    return -1;
  }

  /**
   * from point to middle's distance. If the result is nagative, point is at
   * left part of rect, if it is positive, the point is at the right part.
   *
   * @param rect
   * @param point
   * @return the X distance
   */
  public static int toXMiddle(Rectangle rect, Point point) {
    return (point.x - (rect.x + rect.getRight().x) / 2);
  }

  /**
   * from point to middle's distance If the result is nagative, point is at
   * upper part of rect, if it is positive, the point is at the lower part.
   *
   * @param rect
   * @param point
   * @return the Y distance
   */
  public static int toYMiddle(Rectangle rect, Point point) {
    return (point.y - (rect.y + rect.getBottom().y) / 2);
  }

  /**
   * @param rect
   * @param point
   * @return the Y distance
   */
  public static int getYDistance(Rectangle rect, Point point) {
    if (rect.y + rect.height <= point.y) {
      return point.y - (rect.y + rect.height);
    } else if (rect.y >= point.y) {
      return point.y - rect.y;
    } else if (rect.y <= point.y && point.y <= rect.y + rect.height) {
      return 0;
    }
    return -1;
  }
}
TOP

Related Classes of org.eclipse.jst.pagedesigner.viewer.CaretPositionResolver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.