Ejemplo n.º 1
0
  /**
   * Creates new RelationLine
   *
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @param leftRole Describe what the parameter does
   * @param rightRole Describe what the parameter does
   * @param leftTable Describe what the parameter does
   * @param rightTable Describe what the parameter does
   */
  public RelationLine(
      RelationshipRole leftRole,
      RelationshipRole rightRole,
      JTablePanel leftTable,
      JTablePanel rightTable) {
    _log.debug(
        "new RelationLine for "
            + leftTable.getTable().getSqlName()
            + "-"
            + rightTable.getTable().getSqlName());
    _leftRole = leftRole;
    _rightRole = rightRole;
    _leftTable = leftTable;
    _rightTable = rightTable;

    // left table points
    _log.debug("A:" + _leftRole.getColumnMaps().length);
    _leftEdgeY = new int[_leftRole.getColumnMaps().length];
    for (int i = 0; i < _leftEdgeY.length; i++) {
      _leftEdgeY[i] = _leftTable.getColumnY(_leftRole.getColumnMaps()[i].getPrimaryKey());
      _leftColumnY += _leftEdgeY[i];
    }
    _leftColumnY = _leftColumnY / _leftEdgeY.length;

    // right table points
    if (!_leftRole.getRelation().isMany2Many()) {
      _log.debug("M:" + _leftRole.getColumnMaps().length);
      _rightEdgeY = new int[_leftRole.getColumnMaps().length];
      for (int i = 0; i < _rightEdgeY.length; i++) {
        _rightEdgeY[i] = _rightTable.getColumnY(_leftRole.getColumnMaps()[i].getForeignKey());
        _rightColumnY += _rightEdgeY[i];
      }
      _rightColumnY = _rightColumnY / _rightEdgeY.length;
    } else {
      _log.debug("B:" + _rightRole.getColumnMaps().length);
      _rightEdgeY = new int[_rightRole.getColumnMaps().length];
      for (int i = 0; i < _rightEdgeY.length; i++) {
        _rightEdgeY[i] = _rightTable.getColumnY(_rightRole.getColumnMaps()[i].getPrimaryKey());
        _rightColumnY += _rightEdgeY[i];
      }
      _rightColumnY = _rightColumnY / _rightRole.getColumnMaps().length;
    }

    _leftLines = createLines(_leftEdgeY.length);
    _rightLines = createLines(_rightEdgeY.length);

    _mainLine = new Line2D.Float();

    _leftCardinalityPoint = new Point2D.Float();
    _rightCardinalityPoint = new Point2D.Float();

    _leftFkPoint = new Point2D.Float();
    _rightFkPoint = new Point2D.Float();

    _leftArrowPoint = new Point2D.Float();
    _rightArrowPoint = new Point2D.Float();

    _leftArrowLine1 = new Line2D.Float();
    _leftArrowLine2 = new Line2D.Float();
    _rightArrowLine1 = new Line2D.Float();
    _rightArrowLine2 = new Line2D.Float();
    _leftArrowPoint1 = new Point2D.Float();
    _leftArrowPoint2 = new Point2D.Float();
    _rightArrowPoint1 = new Point2D.Float();
    _rightArrowPoint2 = new Point2D.Float();
    _temp = new Point2D.Float();
    _arrowTransform = new AffineTransform();
  }
Ejemplo n.º 2
0
/**
 * This class represents a relation line. Responsible for drawing the 2D stuff.
 *
 * @author <a href="mailto:[email protected]">Aslak Hellesøy</a>
 * @created 3. oktober 2001
 * @version $Id: RelationLine.java,v 1.1 2005/10/25 14:59:22 lusu Exp $
 */
public class RelationLine {

  /** @todo-javadoc Describe the column */
  private final Stroke _regularStroke = new BasicStroke(2);

  /** @todo-javadoc Describe the column */
  private final Stroke _dashedStroke =
      new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10, new float[] {5, 5}, 0);

  /** @todo-javadoc Describe the column */
  private boolean _isSelected;

  /** @todo-javadoc Describe the column */
  //	private final Relation _relation;

  private final RelationshipRole _leftRole;
  /** @todo-javadoc Describe the column */
  private final RelationshipRole _rightRole;

  /** @todo-javadoc Describe the column */
  private final JTablePanel _leftTable;
  /** @todo-javadoc Describe the column */
  private final JTablePanel _rightTable;

  /** The lines from each key column to the main line on the western table */
  private final Line2D.Float[] _leftLines;
  /** The lines from each key column to the main line on the eastern table */
  private final Line2D.Float[] _rightLines;
  /** @todo-javadoc Describe the column */
  private final Line2D.Float _mainLine;
  /** @todo-javadoc Describe the column */
  private final Point2D.Float _leftArrowPoint;
  /** @todo-javadoc Describe the column */
  private final Point2D.Float _rightArrowPoint;

  /** @todo-javadoc Describe the column */
  private final Line2D.Float _leftArrowLine1;
  /** @todo-javadoc Describe the column */
  private final Line2D.Float _leftArrowLine2;
  /** @todo-javadoc Describe the column */
  private final Line2D.Float _rightArrowLine1;
  /** @todo-javadoc Describe the column */
  private final Line2D.Float _rightArrowLine2;
  /** @todo-javadoc Describe the column */
  private final Point2D.Float _leftArrowPoint1;
  /** @todo-javadoc Describe the column */
  private final Point2D.Float _leftArrowPoint2;
  /** @todo-javadoc Describe the column */
  private final Point2D.Float _rightArrowPoint1;
  /** @todo-javadoc Describe the column */
  private final Point2D.Float _rightArrowPoint2;
  /** @todo-javadoc Describe the column */
  private final Point2D.Float _temp;
  /** @todo-javadoc Describe the column */
  private final AffineTransform _arrowTransform;

  /** @todo-javadoc Describe the column */
  private final Point2D.Float _leftCardinalityPoint;
  /** @todo-javadoc Describe the column */
  private final Point2D.Float _rightCardinalityPoint;

  /** @todo-javadoc Describe the column */
  private final Point2D.Float _leftFkPoint;
  /** @todo-javadoc Describe the column */
  private final Point2D.Float _rightFkPoint;
  /** @todo-javadoc Describe the column */
  private double _mainLength;
  /** @todo-javadoc Describe the column */
  private boolean _leftIsWest;

  /** Average y between all key columns */
  private int _leftColumnY = 0;

  /** Average y between all key columns */
  private int _rightColumnY = 0;

  /** @todo-javadoc Describe the field */
  private int[] _leftEdgeY;
  /** @todo-javadoc Describe the field */
  private int[] _rightEdgeY;

  /** @todo-javadoc Describe the column */
  private static Image _star = new ImageIcon(RelationLine.class.getResource("star.gif")).getImage();
  /** @todo-javadoc Describe the column */
  private static Image _one = new ImageIcon(RelationLine.class.getResource("one.gif")).getImage();

  /** @todo-javadoc Describe the column */
  private static Image _star_white =
      new ImageIcon(RelationLine.class.getResource("star_white.gif")).getImage();
  /** @todo-javadoc Describe the column */
  private static Image _one_white =
      new ImageIcon(RelationLine.class.getResource("one_white.gif")).getImage();

  /** @todo-javadoc Describe the column */
  private static Image _fk = new ImageIcon(RelationLine.class.getResource("fk.gif")).getImage();

  /** Get static reference to Log4J Logger */
  private static org.apache.log4j.Category _log =
      org.apache.log4j.Category.getInstance(RelationLine.class.getName());

  /** @todo-javadoc Describe the column */
  private static RenderingHints _renderHints;

  /**
   * Creates new RelationLine
   *
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @param leftRole Describe what the parameter does
   * @param rightRole Describe what the parameter does
   * @param leftTable Describe what the parameter does
   * @param rightTable Describe what the parameter does
   */
  public RelationLine(
      RelationshipRole leftRole,
      RelationshipRole rightRole,
      JTablePanel leftTable,
      JTablePanel rightTable) {
    _log.debug(
        "new RelationLine for "
            + leftTable.getTable().getSqlName()
            + "-"
            + rightTable.getTable().getSqlName());
    _leftRole = leftRole;
    _rightRole = rightRole;
    _leftTable = leftTable;
    _rightTable = rightTable;

    // left table points
    _log.debug("A:" + _leftRole.getColumnMaps().length);
    _leftEdgeY = new int[_leftRole.getColumnMaps().length];
    for (int i = 0; i < _leftEdgeY.length; i++) {
      _leftEdgeY[i] = _leftTable.getColumnY(_leftRole.getColumnMaps()[i].getPrimaryKey());
      _leftColumnY += _leftEdgeY[i];
    }
    _leftColumnY = _leftColumnY / _leftEdgeY.length;

    // right table points
    if (!_leftRole.getRelation().isMany2Many()) {
      _log.debug("M:" + _leftRole.getColumnMaps().length);
      _rightEdgeY = new int[_leftRole.getColumnMaps().length];
      for (int i = 0; i < _rightEdgeY.length; i++) {
        _rightEdgeY[i] = _rightTable.getColumnY(_leftRole.getColumnMaps()[i].getForeignKey());
        _rightColumnY += _rightEdgeY[i];
      }
      _rightColumnY = _rightColumnY / _rightEdgeY.length;
    } else {
      _log.debug("B:" + _rightRole.getColumnMaps().length);
      _rightEdgeY = new int[_rightRole.getColumnMaps().length];
      for (int i = 0; i < _rightEdgeY.length; i++) {
        _rightEdgeY[i] = _rightTable.getColumnY(_rightRole.getColumnMaps()[i].getPrimaryKey());
        _rightColumnY += _rightEdgeY[i];
      }
      _rightColumnY = _rightColumnY / _rightRole.getColumnMaps().length;
    }

    _leftLines = createLines(_leftEdgeY.length);
    _rightLines = createLines(_rightEdgeY.length);

    _mainLine = new Line2D.Float();

    _leftCardinalityPoint = new Point2D.Float();
    _rightCardinalityPoint = new Point2D.Float();

    _leftFkPoint = new Point2D.Float();
    _rightFkPoint = new Point2D.Float();

    _leftArrowPoint = new Point2D.Float();
    _rightArrowPoint = new Point2D.Float();

    _leftArrowLine1 = new Line2D.Float();
    _leftArrowLine2 = new Line2D.Float();
    _rightArrowLine1 = new Line2D.Float();
    _rightArrowLine2 = new Line2D.Float();
    _leftArrowPoint1 = new Point2D.Float();
    _leftArrowPoint2 = new Point2D.Float();
    _rightArrowPoint1 = new Point2D.Float();
    _rightArrowPoint2 = new Point2D.Float();
    _temp = new Point2D.Float();
    _arrowTransform = new AffineTransform();
  }

  /**
   * Sets the Selected attribute of the RelationLine object
   *
   * @param isSelected The new Selected value
   */
  public void setSelected(boolean isSelected) {
    _isSelected = isSelected;
  }

  /**
   * Gets the Selected attribute of the RelationLine object
   *
   * @return The Selected value
   */
  public boolean isSelected() {
    return _isSelected;
  }

  /**
   * Updates all coordinates
   *
   * @todo Optimise. Some info can be cached
   * @todo Handle m:n (leftY/rightY etc)
   */
  public void update() {
    /*
     *  int leftY = _leftTable.getY() + _leftTable.getColumnY(_leftRole.getColumnMap().getPrimaryKey());
     *  int rightY;
     *  if (!_leftRole.getRelation().isMany2Many()) {
     *  rightY = _rightTable.getY() + _rightTable.getColumnY(_leftRole.getColumnMap().getForeignKey());
     *  }
     *  else {
     *  rightY = _rightTable.getY() + _rightTable.getColumnY(_rightRole.getColumnMap().getPrimaryKey());
     *  }
     */
    int leftY = _leftTable.getY() + _leftColumnY;
    int rightY = _rightTable.getY() + _rightColumnY;

    // find out which table is farthest west (and east)
    JTablePanel westTable;
    JTablePanel eastTable;
    int westY;
    int eastY;
    Line2D.Float[] westLines;
    Line2D.Float[] eastLines;
    int[] westEdgeY;
    int[] eastEdgeY;

    _leftIsWest = _leftTable.getX() < _rightTable.getX();

    if (_leftIsWest) {
      westTable = _leftTable;
      eastTable = _rightTable;
      westY = leftY;
      eastY = rightY;
      westLines = _leftLines;
      eastLines = _rightLines;
      westEdgeY = _leftEdgeY;
      eastEdgeY = _rightEdgeY;
    } else {
      westTable = _rightTable;
      eastTable = _leftTable;
      westY = rightY;
      eastY = leftY;
      westLines = _rightLines;
      eastLines = _leftLines;
      westEdgeY = _rightEdgeY;
      eastEdgeY = _leftEdgeY;
    }

    // find out whether the tables are more or less vertically aligned
    boolean aligned = (eastTable.getX() - westTable.getX()) < eastTable.getWidth() / 2;
    // TODO: handle different widths

    int westX;
    if (aligned) {
      westX = westTable.getX() - 10;
      for (int i = 0; i < westEdgeY.length; i++) {
        westLines[i].setLine(westX, westY, westTable.getX(), westEdgeY[i] + westTable.getY());
      }
    } else {
      westX = westTable.getX() + westTable.getWidth() + 10;
      for (int i = 0; i < westEdgeY.length; i++) {
        westLines[i].setLine(
            westX, westY, westTable.getX() + westTable.getWidth(), westEdgeY[i] + westTable.getY());
      }
    }
    int eastX = eastTable.getX() - 10;

    for (int i = 0; i < eastEdgeY.length; i++) {
      eastLines[i].setLine(eastX, eastY, eastTable.getX(), eastEdgeY[i] + eastTable.getY());
    }

    _mainLine.setLine(westX, westY, eastX, eastY);

    setCardinalityPoints();
  }

  /**
   * Describe what the method does
   *
   * @todo-javadoc Write javadocs for method
   * @todo-javadoc Write javadocs for method parameter
   * @param g Describe what the parameter does
   */
  public void paint(Graphics2D g) {
    g.setRenderingHints(_renderHints);
    /*
     *  if( isSelected() ) {
     *  g.setColor( Color.red );
     *  } else {
     *  g.setColor( Color.black );
     *  }
     */
    if (_leftRole.getRelation().isMany2Many()) {
      g.setStroke(_dashedStroke);
    } else {
      g.setStroke(_regularStroke);
    }
    drawLineUnlessItsLengthIsZero(g, _mainLine);

    g.setStroke(_regularStroke);
    for (int i = 0; i < _leftLines.length; i++) {
      drawLineUnlessItsLengthIsZero(g, _leftLines[i]);
    }
    for (int i = 0; i < _rightLines.length; i++) {
      drawLineUnlessItsLengthIsZero(g, _rightLines[i]);
    }
    drawImage(
        g,
        getDisplayImage(_rightRole, g.getColor()),
        _leftCardinalityPoint.x - 8,
        _leftCardinalityPoint.y - 8);
    drawImage(
        g,
        getDisplayImage(_leftRole, g.getColor()),
        _rightCardinalityPoint.x - 8,
        _rightCardinalityPoint.y - 8);

    if (_rightRole.isEnabled()) {
      drawLineUnlessItsLengthIsZero(g, _leftArrowLine1);
      drawLineUnlessItsLengthIsZero(g, _leftArrowLine2);
    }
    if (_leftRole.isEnabled()) {
      drawLineUnlessItsLengthIsZero(g, _rightArrowLine1);
      drawLineUnlessItsLengthIsZero(g, _rightArrowLine2);
    }

    // draw the fk image
    if (!_leftRole.isOriginPrimaryKey()) {
      drawImage(g, _fk, _leftFkPoint.x - 6, _leftFkPoint.y - 6);
    }
    if (!_rightRole.isOriginPrimaryKey()) {
      drawImage(g, _fk, _rightFkPoint.x - 6, _rightFkPoint.y - 6);
    }
  }

  /**
   * @todo Refactor this. Shouldn't mix localisation logic and relation mutation logic in one method
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for return value
   * @todo-javadoc Write javadocs for method parameter
   * @param evt Describe what the parameter does
   * @return Describe the return value
   */
  public boolean selectMaybe(MouseEvent evt) {
    boolean multiplicity = evt.isControlDown();
    boolean cardinality = evt.isShiftDown();
    Point point = evt.getPoint();
    setSelected(_mainLine.intersects(point.getX() - 5, point.getY() - 5, 10, 10));
    if (isSelected()) {
      double distFromP1 =
          Point2D.distance(_mainLine.getX1(), _mainLine.getY1(), point.getX(), point.getY());

      boolean nearP1 = distFromP1 < _mainLength / 2;
      boolean leftChosen = (_leftIsWest && nearP1) || (!_leftIsWest && !nearP1);
      RelationshipRole role = leftChosen ? _rightRole : _leftRole;
      if (multiplicity) {
        // toggle multiplicity. Let's prevent the user from doing something stupid. Some
        // cardinalities
        // can't be changed. we know best etc.
        if (role.getRelation().isMany2Many()) {
          // don't allow to change cardinality of m:n relationships
          JOptionPane.showMessageDialog(
              null,
              "Can't change the cardinality of a many-to-many relationship",
              "Cardinality",
              JOptionPane.INFORMATION_MESSAGE);
          return false;
        }
        if (role.isFkPk()) {
          // don't allow to change cardinality of 1:1 relationships that are 1:1 because fk is also
          // pk
          JOptionPane.showMessageDialog(
              null,
              "Can't change the cardinality of a one-to-one relationship where the foreign key is also a primary key",
              "Cardinality",
              JOptionPane.INFORMATION_MESSAGE);
          return false;
        }
        if (role.isTargetPrimaryKey()) {
          JOptionPane.showMessageDialog(
              null,
              "Can't change the cardinality of a the one-side of a relationship that corresponds to a primary key",
              "Cardinality",
              JOptionPane.INFORMATION_MESSAGE);
          return false;
        }
        // All checks passed. Do the toggle
        role.setTargetMany(!role.isTargetMany());
      }
      if (cardinality) {
        // toggle between uni/bidirectional
        role.setEnabled(!role.isEnabled());
      }
      return true;
    } else {
      return false;
    }
  }

  /**
   * Sets the CardinalityPoints attribute of the RelationLine object
   *
   * @todo refactor this duplicate code!!!
   */
  private void setCardinalityPoints() {
    // compute vector of length 1
    _mainLength =
        Point2D.distance(
            _mainLine.getX1(), _mainLine.getY1(), _mainLine.getX2(), _mainLine.getY2());
    double vx = (_mainLine.getX2() - _mainLine.getX1()) / _mainLength;
    double vy = (_mainLine.getY2() - _mainLine.getY1()) / _mainLength;
    double cardx = 20.0 * vx;
    double cardy = 20.0 * vy;
    double arrowx = 30.0 * vx;
    double arrowy = 30.0 * vy;
    if (_leftIsWest) {
      _leftArrowPoint.setLocation(_mainLine.getX1() + cardx, _mainLine.getY1() + cardy);
      _rightArrowPoint.setLocation(_mainLine.getX2() - cardx, _mainLine.getY2() - cardy);

      // The left-side arrow head
      _temp.setLocation(_mainLine.getX1() + arrowx, _mainLine.getY1() + arrowy);

      _arrowTransform.setToRotation(Math.PI / 6, _leftArrowPoint.getX(), _leftArrowPoint.getY());
      _arrowTransform.transform(_temp, _leftArrowPoint1);
      _leftArrowLine1.setLine(
          _leftArrowPoint.getX(),
          _leftArrowPoint.getY(),
          _leftArrowPoint1.getX(),
          _leftArrowPoint1.getY());

      _arrowTransform.setToRotation(-Math.PI / 6, _leftArrowPoint.getX(), _leftArrowPoint.getY());
      _arrowTransform.transform(_temp, _leftArrowPoint2);
      _leftArrowLine2.setLine(
          _leftArrowPoint.getX(),
          _leftArrowPoint.getY(),
          _leftArrowPoint2.getX(),
          _leftArrowPoint2.getY());

      _arrowTransform.setToRotation(Math.PI / 2, _leftArrowPoint.getX(), _leftArrowPoint.getY());
      _arrowTransform.transform(_temp, _leftCardinalityPoint);

      _arrowTransform.setToRotation(-Math.PI / 2, _leftArrowPoint.getX(), _leftArrowPoint.getY());
      _arrowTransform.transform(_temp, _leftFkPoint);

      // The right-side arrow head
      _temp.setLocation(_mainLine.getX2() - arrowx, _mainLine.getY2() - arrowy);

      _arrowTransform.setToRotation(Math.PI / 6, _rightArrowPoint.getX(), _rightArrowPoint.getY());
      _arrowTransform.transform(_temp, _rightArrowPoint1);
      _rightArrowLine1.setLine(
          _rightArrowPoint.getX(),
          _rightArrowPoint.getY(),
          _rightArrowPoint1.getX(),
          _rightArrowPoint1.getY());

      _arrowTransform.setToRotation(-Math.PI / 6, _rightArrowPoint.getX(), _rightArrowPoint.getY());
      _arrowTransform.transform(_temp, _rightArrowPoint2);
      _rightArrowLine2.setLine(
          _rightArrowPoint.getX(),
          _rightArrowPoint.getY(),
          _rightArrowPoint2.getX(),
          _rightArrowPoint2.getY());

      _arrowTransform.setToRotation(-Math.PI / 2, _rightArrowPoint.getX(), _rightArrowPoint.getY());
      _arrowTransform.transform(_temp, _rightCardinalityPoint);

      _arrowTransform.setToRotation(Math.PI / 2, _rightArrowPoint.getX(), _rightArrowPoint.getY());
      _arrowTransform.transform(_temp, _rightFkPoint);
    } else {
      _leftArrowPoint.setLocation(_mainLine.getX2() - cardx, _mainLine.getY2() - cardy);
      _rightArrowPoint.setLocation(_mainLine.getX1() + cardx, _mainLine.getY1() + cardy);

      // The left-side arrow head
      _temp.setLocation(_mainLine.getX2() - arrowx, _mainLine.getY2() - arrowy);

      _arrowTransform.setToRotation(Math.PI / 6, _leftArrowPoint.getX(), _leftArrowPoint.getY());
      _arrowTransform.transform(_temp, _leftArrowPoint1);
      _leftArrowLine1.setLine(
          _leftArrowPoint.getX(),
          _leftArrowPoint.getY(),
          _leftArrowPoint1.getX(),
          _leftArrowPoint1.getY());

      _arrowTransform.setToRotation(-Math.PI / 6, _leftArrowPoint.getX(), _leftArrowPoint.getY());
      _arrowTransform.transform(_temp, _leftArrowPoint2);
      _leftArrowLine2.setLine(
          _leftArrowPoint.getX(),
          _leftArrowPoint.getY(),
          _leftArrowPoint2.getX(),
          _leftArrowPoint2.getY());

      _arrowTransform.setToRotation(Math.PI / 2, _leftArrowPoint.getX(), _leftArrowPoint.getY());
      _arrowTransform.transform(_temp, _leftCardinalityPoint);

      _arrowTransform.setToRotation(-Math.PI / 2, _leftArrowPoint.getX(), _leftArrowPoint.getY());
      _arrowTransform.transform(_temp, _leftFkPoint);

      // The right-side arrow head
      _temp.setLocation(_mainLine.getX1() + arrowx, _mainLine.getY1() + arrowy);

      _arrowTransform.setToRotation(Math.PI / 6, _rightArrowPoint.getX(), _rightArrowPoint.getY());
      _arrowTransform.transform(_temp, _rightArrowPoint1);
      _rightArrowLine1.setLine(
          _rightArrowPoint.getX(),
          _rightArrowPoint.getY(),
          _rightArrowPoint1.getX(),
          _rightArrowPoint1.getY());

      _arrowTransform.setToRotation(-Math.PI / 6, _rightArrowPoint.getX(), _rightArrowPoint.getY());
      _arrowTransform.transform(_temp, _rightArrowPoint2);
      _rightArrowLine2.setLine(
          _rightArrowPoint.getX(),
          _rightArrowPoint.getY(),
          _rightArrowPoint2.getX(),
          _rightArrowPoint2.getY());

      _arrowTransform.setToRotation(-Math.PI / 2, _rightArrowPoint.getX(), _rightArrowPoint.getY());
      _arrowTransform.transform(_temp, _rightCardinalityPoint);

      _arrowTransform.setToRotation(Math.PI / 2, _rightArrowPoint.getX(), _rightArrowPoint.getY());
      _arrowTransform.transform(_temp, _rightFkPoint);
    }
  }

  /**
   * Gets the cardinality Image to display. It's a 1 or a *, black or blue.
   *
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @param role Describe what the parameter does
   * @param c Describe what the parameter does
   * @return The LeftDisplayString value
   */
  private Image getDisplayImage(RelationshipRole role, Color c) {
    // This is quite dirty, but it works
    if (c == Color.white) {
      return role.isTargetMany() ? _star_white : _one_white;
    } else {
      return role.isTargetMany() ? _star : _one;
    }
  }

  /**
   * Describe what the method does
   *
   * @todo-javadoc Write javadocs for method
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @param g Describe what the parameter does
   * @param i Describe what the parameter does
   * @param x Describe what the parameter does
   * @param y Describe what the parameter does
   */
  private final void drawImage(final Graphics2D g, final Image i, final float x, final float y) {
    if (!Float.isNaN(x)) {
      g.drawImage(i, (int) x, (int) y, null);
    }
  }

  /**
   * Describe what the method does
   *
   * @todo-javadoc Write javadocs for method
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @param g Describe what the parameter does
   * @param line Describe what the parameter does
   */
  private final void drawLineUnlessItsLengthIsZero(final Graphics2D g, final Line2D line) {
    // Any coord is NaN if the length is zero
    if (!Double.isNaN(line.getP1().getX())) {
      g.draw(line);
    }
  }

  /**
   * Describe what the method does
   *
   * @todo-javadoc Write javadocs for method
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for return value
   * @param n Describe what the parameter does
   * @return Describe the return value
   */
  private static Line2D.Float[] createLines(int n) {
    Line2D.Float[] result = new Line2D.Float[n];
    for (int i = 0; i < n; i++) {
      result[i] = new Line2D.Float();
    }
    return result;
  }

  static {
    _renderHints =
        new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    _renderHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
  }
}
/**
 * @author <a href="mailto:[email protected]">Aslak Hellesøy</a>
 * @created 3. oktober 2001
 * @version $Id: JMiddlegenFrame.java,v 1.1 2005/10/25 14:59:22 lusu Exp $
 */
public class JMiddlegenFrame extends JFrame {
  /** @todo-javadoc Describe the column */
  private final JDatabasePanel _databasePanel;
  /** @todo-javadoc Describe the field */
  private final JSplitPane _split;

  /** @todo-javadoc Describe the column */
  private final Middlegen _middlegen;

  /**
   * This action generates sources
   *
   * @todo refactor the meat to a separate method
   */
  private Action _generateAction =
      new AbstractAction("Generate") {
        public void actionPerformed(ActionEvent evt) {
          try {
            setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            try {
              _middlegen.writeSource();
            } catch (MiddlegenException e) {
              error(e);
            }
          } finally {
            setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
          }
        }
      };

  /** Get static reference to Log4J Logger */
  private static org.apache.log4j.Category _log =
      org.apache.log4j.Category.getInstance(JMiddlegenFrame.class.getName());

  /**
   * The main program for the MiddlemanFrame class
   *
   * @todo describe the command line arguments
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @param middlegen Describe what the parameter does
   * @param title Describe what the parameter does
   */
  public JMiddlegenFrame(Middlegen middlegen, String title) {
    super(title);
    _middlegen = middlegen;
    setKuststoffLF();

    // make panel with label header and tabs in center.
    JLabel header = new JLabel("", JLabel.CENTER);
    JSettingsTabPane settingsTabs = new JSettingsTabPane(middlegen.getPlugins());
    JPanel headerTabs = new JPanel(new BorderLayout());

    headerTabs.add(header, BorderLayout.NORTH);
    // headerTabs.add(settingsTabs, BorderLayout.CENTER);
    JToolBar pluginToolBar = new JToolBar();
    pluginToolBar.add(settingsTabs);
    headerTabs.add(pluginToolBar, BorderLayout.CENTER);

    _databasePanel = new JDatabasePanel(settingsTabs, header);

    JScrollPane scroll = new JScrollPane(_databasePanel);
    _split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scroll, headerTabs);
    _split.setDividerLocation(0.5);
    getContentPane().add(_split, BorderLayout.CENTER);

    JToolBar toolBar = new JToolBar();
    toolBar.add(_generateAction);
    toolBar.addSeparator();
    toolBar.add(new JLabel("CTRL-Click relations to modify their cardinality"));
    toolBar.addSeparator();
    toolBar.add(new JLabel("SHIFT-Click relations to modify their directionality"));
    getContentPane().add(toolBar, BorderLayout.NORTH);

    ImageIcon icon = new ImageIcon(getClass().getResource("m.gif"));
    setIconImage(icon.getImage());

    // dispose Frame on closing, so VM will exit when Ant Task has finished
    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

    // I have a dodgy feeling that a Mac would try to exit the VM when the
    // window closes. Try to uncomment this line on a Mac.
    // System.setSecurityManager(new NoExitSecurityManager());

    addWindowListener(
        new WindowAdapter() {

          public void windowClosing(WindowEvent evt) {
            // Tell the halted Ant task to resume.
            synchronized (MiddlegenTask.getLock()) {
              // Update positions of tables
              _databasePanel.setPrefs();
              // Let the ant task to continue
              MiddlegenTask.getLock().notify();
            }
          }
        });
  }

  /** Sets the Splitter attribute of the JMiddlegenFrame object */
  public void setSplitter() {
    int fheight = this.getHeight();
    int sheight = Toolkit.getDefaultToolkit().getScreenSize().height;
    if (fheight >= sheight) {
      _split.setDividerLocation(sheight - 480);
    }
    _split.setOneTouchExpandable(true);
  }

  /**
   * Sets the Visible attribute of the JMiddlegenFrame object
   *
   * @param flag The new Visible value
   */
  public void setVisible(boolean flag) {
    super.setVisible(flag);
    _databasePanel.reset(_middlegen);
    pack();
  }

  /** Sets the cool kunststoff L&F. */
  private void setKuststoffLF() {
    /*
     *  try {
     *  com.incors.plaf.kunststoff.KunststoffLookAndFeel kunststoffLnF
     *  = new com.incors.plaf.kunststoff.KunststoffLookAndFeel();
     *  kunststoffLnF.setCurrentTheme(new com.incors.plaf.kunststoff.KunststoffTheme());
     *  UIManager.setLookAndFeel(kunststoffLnF);
     *  / this line needs to be implemented in order to make JWS work properly
     *  UIManager.getLookAndFeelDefaults().put("ClassLoader", getClass().getClassLoader());
     *  } catch (Throwable ignore) {
     *  }
     */
  }

  /**
   * Describe what the method does
   *
   * @todo-javadoc Write javadocs for method
   * @todo-javadoc Write javadocs for method parameter
   * @param t Describe what the parameter does
   */
  private void error(Throwable t) {
    t.printStackTrace();
    JOptionPane.showMessageDialog(this, t);
  }

  /**
   * This security manager will cause an ExitException to be thrown whenever System.exit is called
   * instead of terminating the VM.
   *
   * @author Aslak Hellesøy
   * @created 2. desember 2002
   */
  public static class NoExitSecurityManager extends SecurityManager {
    /**
     * Throws an ExitException instead of terminating the VM.
     *
     * @todo-javadoc Write javadocs for method parameter
     * @param status Describe what the parameter does
     */
    public void checkExit(int status) {
      throw new ExitException(status);
    }

    /**
     * Allows anything.
     *
     * @todo-javadoc Write javadocs for method parameter
     * @param p Describe what the parameter does
     */
    public void checkPermission(java.security.Permission p) {}
  }

  /**
   * Describe what this class does
   *
   * @author Aslak Hellesøy
   * @created 2. desember 2002
   * @todo-javadoc Write javadocs
   */
  public static class ExitException extends RuntimeException {
    /** @todo-javadoc Describe the field */
    private int _status;

    /**
     * Describe what the ExitException constructor does
     *
     * @todo-javadoc Write javadocs for constructor
     * @todo-javadoc Write javadocs for method parameter
     * @param status Describe what the parameter does
     */
    public ExitException(int status) {
      _status = status;
    }

    /**
     * Gets the Status attribute of the ExitException object
     *
     * @return The Status value
     */
    public int getStatus() {
      return _status;
    }
  }
}