/** * {@inheritDoc} * * @see VertexView#getPerimeterPoint(EdgeView, Point2D, Point2D) */ @Override public final Point2D getPerimeterPoint( EdgeView edge, @SuppressWarnings("unused") Point2D source, Point2D p) { Rectangle2D r = getBounds(); State state = null; if (getCell() instanceof DefaultStateView) { DefaultStateView defaultStateView = (DefaultStateView) getCell(); state = defaultStateView.getState(); } boolean loopTransition = false; State otherState = null; if (edge != null) { loopTransition = edge.getSource().getParentView() == edge.getTarget().getParentView(); if (edge.getSource().getParentView() == this) { StateView stateView = (StateView) edge.getTarget().getParentView(); if (stateView.getCell() instanceof DefaultStateView) { DefaultStateView defaultStateView = (DefaultStateView) stateView.getCell(); otherState = defaultStateView.getState(); } } else { StateView stateView = (StateView) edge.getSource().getParentView(); if (stateView.getCell() instanceof DefaultStateView) { DefaultStateView defaultStateView = (DefaultStateView) stateView.getCell(); otherState = defaultStateView.getState(); } } } double x = r.getX(); double y = r.getY(); double a = r.getWidth() / 2; double b = r.getHeight() / 2; // x1, y1 - point double x1 = p.getX(); double y1 = p.getY(); if ((state != null) && (otherState != null) && !loopTransition) { boolean firstTransition = false; for (Transition current : state.getTransitionBegin()) { if (current.getStateEnd() == otherState) { firstTransition = true; } } boolean secondTransition = false; for (Transition current : otherState.getTransitionBegin()) { if (current.getStateEnd() == state) { secondTransition = true; } } if (otherState.isStartState() && !(firstTransition && secondTransition)) { x1 += START_OFFSET / 2; } if (otherState.isLoopTransition() && !(firstTransition && secondTransition)) { y1 += LOOP_TRANSITION_OFFSET / 2; } } if (state != null) { if (state.isStartState()) { x = r.getX() + START_OFFSET; a = (r.getWidth() - START_OFFSET) / 2; } if (state.isLoopTransition()) { y = r.getY() + LOOP_TRANSITION_OFFSET; b = (r.getHeight() - LOOP_TRANSITION_OFFSET) / 2; } } // x0, y0 - center of ellipse double x0 = x + a; double y0 = y + b; // calculate straight line equation through point and ellipse center double dx = x1 - x0; double dy = y1 - y0; if (dx == 0) { return new Point((int) x0, (int) (y0 + b * dy / Math.abs(dy))); } double d = dy / dx; double h = y0 - d * x0; // calculate intersection double e = a * a * d * d + b * b; double f = -2 * x0 * e; double g = a * a * d * d * x0 * x0 + b * b * x0 * x0 - a * a * b * b; double det = Math.sqrt(f * f - 4 * e * g); // two solutions (perimeter points) double xout1 = (-f + det) / (2 * e); double xout2 = (-f - det) / (2 * e); double yout1 = d * xout1 + h; double yout2 = d * xout2 + h; double dist1Squared = Math.pow((xout1 - x1), 2) + Math.pow((yout1 - y1), 2); double dist2Squared = Math.pow((xout2 - x1), 2) + Math.pow((yout2 - y1), 2); // correct solution double xout, yout; if (dist1Squared < dist2Squared) { xout = xout1; yout = yout1; } else { xout = xout2; yout = yout2; } if ((state != null) && state.isPowerState()) { int checkX = (int) (xout - x); int checkY = (int) (yout - y); if ((checkX >= a) && (checkY <= b)) { Color color = getColor(POWER_STATE_100, checkX, checkY); while ((color.getRed() == 0) && (color.getGreen() == 0) && (color.getBlue() == 0)) { xout = xout + 1; yout = yout - 1; checkX = (int) (xout - x); checkY = (int) (yout - y); color = getColor(POWER_STATE_100, checkX, checkY); } } else if ((checkX <= a) && (checkY <= b)) { Color color = getColor(POWER_STATE_100, checkX, checkY); while ((color.getRed() == 0) && (color.getGreen() == 0) && (color.getBlue() == 0)) { xout = xout - 1; yout = yout - 1; checkX = (int) (xout - x); checkY = (int) (yout - y); color = getColor(POWER_STATE_100, checkX, checkY); } } else if ((checkX <= a) && (checkY >= b)) { Color color = getColor(POWER_STATE_100, checkX, checkY); while ((color.getRed() == 0) && (color.getGreen() == 0) && (color.getBlue() == 0)) { xout = xout - 1; yout = yout + 1; checkX = (int) (xout - x); checkY = (int) (yout - y); color = getColor(POWER_STATE_100, checkX, checkY); } } else if ((checkX >= a) && (checkY >= b)) { Color color = getColor(POWER_STATE_100, checkX, checkY); while ((color.getRed() == 0) && (color.getGreen() == 0) && (color.getBlue() == 0)) { xout = xout + 1; yout = yout + 1; checkX = (int) (xout - x); checkY = (int) (yout - y); color = getColor(POWER_STATE_100, checkX, checkY); } } } return getAttributes().createPoint(xout, yout); }
/** * {@inheritDoc} * * @see VertexRenderer#paint(Graphics) */ @Override public final void paint(Graphics g) { State state = null; DefaultStateView defaultStateView = null; if (this.stateView.getCell() instanceof DefaultStateView) { defaultStateView = (DefaultStateView) this.stateView.getCell(); state = defaultStateView.getState(); } else { return; } int b = this.borderWidth; int offsetX = state.isStartState() ? START_OFFSET : 0; int offsetY = state.isLoopTransition() ? LOOP_TRANSITION_OFFSET : 0; Graphics2D g2 = (Graphics2D) g; Dimension d = getSize(); boolean tmp = this.selected; if (super.isOpaque()) { Color background = null; // overwritten color if (defaultStateView.getOverwrittenColor() != null) { background = defaultStateView.getOverwrittenColor(); } // error else if (state.isError()) { background = this.preferenceStateError; } // active else if (state.isActive()) { background = this.preferenceStateActive; } // start else if (state.isStartState()) { background = this.preferenceStateStart; } // final else if (state.isFinalState()) { background = this.preferenceStateFinal; } // normal else { background = this.preferenceStateBackground; } g.setColor(background); if ((this.gradientColor != null) && !this.preview) { setOpaque(false); g2.setPaint( new GradientPaint( 0, 0, background, getWidth(), getHeight(), this.gradientColor, true)); } // final state if (state.isPowerState()) { if (state.isFinalState()) { g.fillRoundRect( offsetX + b + 3, offsetY + b + 3, d.width - b - 8 - offsetX, d.height - b - 8 - offsetY, 50, 50); } else { g.fillRoundRect( offsetX + b - 1, offsetY + b - 1, d.width - b - offsetX, d.height - b - offsetY, 50, 50); } } else { if (state.isFinalState()) { g.fillOval( offsetX + b + 3, offsetY + b + 3, d.width - b - 8 - offsetX, d.height - b - 8 - offsetY); } else { g.fillOval( offsetX + b - 1, offsetY + b - 1, d.width - b - offsetX, d.height - b - offsetY); } } } try { setBorder(null); setOpaque(false); this.selected = false; g.setColor(this.preferenceState); g.setFont(getFont()); FontMetrics metrics = g.getFontMetrics(); int dx = offsetX + ((d.width - offsetX) / 2) - (metrics.stringWidth(state.toString()) / 2) - 1; int dy = offsetY + ((d.height - offsetY) / 2) + (metrics.getHeight() / 2) - 3; PrettyString prettyString = new PrettyString(); prettyString.add(state.toPrettyString()); int insets = state.isFinalState() ? 20 : 10; // short version if ((metrics.stringWidth(state.toString()) + insets) > (d.width - offsetX)) { state.setShortNameUsed(true); dx = insets / 2; String dots = " ..."; // $NON-NLS-1$ PrettyToken lastPrettyToken = null; while ((!prettyString.isEmpty()) && ((metrics.stringWidth(prettyString.toString() + dots) + 2 * dx) > (d.width - offsetX))) { lastPrettyToken = prettyString.removeLastPrettyToken(); } if (lastPrettyToken != null) { char[] chars = lastPrettyToken.getChar(); int i = 0; String addText = ""; // $NON-NLS-1$ while ((i < chars.length) && ((metrics.stringWidth(prettyString.toString() + addText + dots) + 2 * dx) <= (d.width - offsetX))) { addText += chars[i]; i++; } if (addText.length() > 0) { addText = addText.substring(0, addText.length() - 1); } prettyString.add(new PrettyToken(addText, lastPrettyToken.getStyle())); } dx += offsetX; // center the dots if there are no pretty tokens if (prettyString.isEmpty()) { dots = "..."; // $NON-NLS-1$ dx = offsetX + ((d.width - offsetX) / 2) - (metrics.stringWidth(dots) / 2) - 1; } prettyString.add(new PrettyToken(dots, Style.NONE)); } // normal version else { state.setShortNameUsed(false); } for (PrettyToken currentToken : prettyString) { Font font = null; if (!currentToken.isBold() && !currentToken.isItalic()) { font = g.getFont().deriveFont(Font.PLAIN); } else if (currentToken.isBold() && currentToken.isItalic()) { font = g.getFont().deriveFont(Font.BOLD | Font.ITALIC); } else if (currentToken.isBold()) { font = g.getFont().deriveFont(Font.BOLD); } else if (currentToken.isItalic()) { font = g.getFont().deriveFont(Font.ITALIC); } g.setFont(font); g.setColor(currentToken.getColor()); char[] chars = currentToken.getChar(); for (int i = 0; i < chars.length; i++) { g.drawChars(chars, i, 1, dx, dy); dx += metrics.charWidth(chars[i]); } } } finally { this.selected = tmp; } if (this.bordercolor != null) { g.setColor(this.bordercolor); g2.setStroke(new BasicStroke(b)); if (state.isPowerState()) { g.drawRoundRect( offsetX + b - 1, offsetY + b - 1, d.width - b - offsetX, d.height - b - offsetY, 50, 50); if (state.isFinalState()) { g.drawRoundRect( offsetX + b + 3, offsetY + b + 3, d.width - b - 8 - offsetX, d.height - b - 8 - offsetY, 50, 50); } } else { g.drawOval( offsetX + b - 1, offsetY + b - 1, d.width - b - offsetX, d.height - b - offsetY); if (state.isFinalState()) { g.drawOval( offsetX + b + 3, offsetY + b + 3, d.width - b - 8 - offsetX, d.height - b - 8 - offsetY); } } } if (this.selected) { g.setColor(this.preferenceStateSelected); if (state.isPowerState()) { g.drawRoundRect( offsetX + b - 1, offsetY + b - 1, d.width - b - offsetX, d.height - b - offsetY, 50, 50); if (state.isFinalState()) { g.drawRoundRect( offsetX + b + 3, offsetY + b + 3, d.width - b - 8 - offsetX, d.height - b - 8 - offsetY, 50, 50); } } else { g.drawOval( offsetX + b - 1, offsetY + b - 1, d.width - b - offsetX, d.height - b - offsetY); if (state.isFinalState()) { g.drawOval( offsetX + b + 3, offsetY + b + 3, d.width - b - 8 - offsetX, d.height - b - 8 - offsetY); } } } if (state.isStartState()) { g.setFont(getFont().deriveFont(Font.BOLD)); g.setColor(this.preferenceTransition); g.drawLine(0, offsetY + 35, START_OFFSET, offsetY + 35); g.drawLine(START_OFFSET - 2, offsetY + 34, START_OFFSET - 2, offsetY + 36); g.drawLine(START_OFFSET - 3, offsetY + 33, START_OFFSET - 3, offsetY + 37); g.drawLine(START_OFFSET - 4, offsetY + 32, START_OFFSET - 4, offsetY + 38); g.drawLine(START_OFFSET - 5, offsetY + 31, START_OFFSET - 5, offsetY + 39); g.drawLine(START_OFFSET - 6, offsetY + 30, START_OFFSET - 6, offsetY + 40); g.drawString("Start", 10, offsetY + 30); // $NON-NLS-1$ } }