/** * Draws a double headed arrow with arrow heads of a given width and height. * * @param aG the canvas to draw on; * @param aX1 the starting X position of the arrow; * @param aY1 the starting Y position of the arrow; * @param aX2 the ending X position of the arrow; * @param aY2 the ending Y position of the arrow; * @param aArrowWidth the total width of the arrow head; * @param aArrowHeight the total height of the arrow head. */ public static final void drawDoubleHeadedArrow( final Graphics aG, final int aX1, final int aY1, final int aX2, final int aY2, final int aArrowWidth, final int aArrowHeight) { final Graphics2D g2d = (Graphics2D) aG.create(); final int lineWidth = Math.abs(aX2 - aX1); final int threshold = (2 * aArrowWidth) + 2; try { int x1 = aX1; int x2 = aX2; if (lineWidth > threshold) { drawArrowHead(g2d, aX1, aY1, LEFT_FACING, aArrowWidth, aArrowHeight); // why x2 needs to be shifted by one pixel is beyond me... drawArrowHead(g2d, aX2 + 1, aY2, RIGHT_FACING, aArrowWidth, aArrowHeight); x1 += aArrowWidth - 1; x2 -= aArrowWidth + 1; } g2d.drawLine(x1, aY1, x2, aY2); } finally { g2d.dispose(); } }
/** * Draws a single arrow head * * @param aG the canvas to draw on; * @param aXpos the X position of the arrow head; * @param aYpos the (center) Y position of the arrow head; * @param aFactor +1 to have a left-facing arrow head, -1 to have a right-facing arrow head; * @param aArrowWidth the total width of the arrow head; * @param aArrowHeight the total height of the arrow head. */ public static final void drawArrowHead( final Graphics2D aG, final int aXpos, final int aYpos, final int aFactor, final int aArrowWidth, final int aArrowHeight) { final double halfHeight = aArrowHeight / 2.0; final int x1 = aXpos + (aFactor * aArrowWidth); final int y1 = (int) Math.ceil(aYpos - halfHeight); final int y2 = (int) Math.floor(aYpos + halfHeight); final Polygon arrowHead = new Polygon(); arrowHead.addPoint(aXpos, aYpos); arrowHead.addPoint(x1, y1); arrowHead.addPoint(x1, y2); aG.fill(arrowHead); }
/** * Creates a button pane in which the given buttons are neatly aligned with proper spacings. * * @param aButtons the buttons to add to the created button pane, will be added in the given * order. * @return the button pane, never <code>null</code>. */ public static JComponent createButtonPane(final JButton... aButtons) { if ((aButtons == null) || (aButtons.length < 1)) { throw new IllegalArgumentException("Need at least one button!"); } final JPanel buttonPane = new JPanel(); buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); buttonPane.setBorder( BorderFactory.createEmptyBorder( BUTTONS_PADDING_TOP, BUTTONS_PADDING_LEFT, BUTTONS_PADDING_BOTTOM, BUTTONS_PADDING_RIGHT)); buttonPane.add(Box.createHorizontalGlue()); // we want equally sized buttons, so we are recording preferred sizes while // adding the buttons and set them to the maximum afterwards... int width = 1; int height = 1; for (JButton button : aButtons) { width = Math.max(width, button.getPreferredSize().width); height = Math.max(height, button.getPreferredSize().height); buttonPane.add(Box.createHorizontalStrut(BUTTONS_SPACING_DEFAULT)); buttonPane.add(button); } buttonPane.add(Box.createHorizontalStrut(BUTTONS_SPACING_DEFAULT)); final Dimension newDims = new Dimension(width, height); // everything added; let's set all sizes for (final JButton button : aButtons) { button.setPreferredSize(newDims); } return buttonPane; }