/**
  * 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
   * @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;
    }
  }
  /**
   * 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();
  }