Class GraphicsUtils

java.lang.Object
edu.cnu.mdi.graphics.GraphicsUtils

public final class GraphicsUtils extends Object
Static utility methods for general-purpose 2D graphics operations.

Graphics context

Every drawing method in this class accepts a Graphics2D context directly. The legacy Graphics parameter type has been removed throughout; no internal casts are performed.

Note for callers that override Component.paint(java.awt.Graphics): Java AWT declares paint(Graphics g) with a fixed signature. Inside that override, cast once at the entry point and pass the result to these utilities:

 @Override
 public void paint(Graphics g) {
     Graphics2D g2 = (Graphics2D) g;
     GraphicsUtils.drawHighlightedRectangle(g2, rect);
 }
 

Stroke caching

BasicStroke objects are expensive to construct and are immutable. getStroke(float, LineStyle) caches every stroke it creates in strokes so that repeated calls with the same parameters return the same object without allocation.

Highlighted drawing

"Highlighted" shapes (rectangles, ovals, polylines, etc.) are drawn twice with complementary dashed strokes — dash1/dash2 or dash1_2/dash2_2 — in two alternating colors. The result is a marching-ants selection indicator. Default colors are highlightColor1 (red) and highlightColor2 (yellow).

  • Field Details

    • highlightColor1

      public static final Color highlightColor1
      Primary color used for highlighted (marching-ants) drawing. Defaults to Color.red.
    • highlightColor2

      public static final Color highlightColor2
      Secondary color used for highlighted (marching-ants) drawing. Defaults to Color.yellow.
    • dash1

      public static final BasicStroke dash1
      1-pixel dashed stroke, phase 0 — first pass of a marching-ants pair. Used with dash2 to draw highlighted outlines.
    • dash2

      public static final BasicStroke dash2
      1-pixel dashed stroke, phase 8 — second pass of a marching-ants pair. Used with dash1 to draw highlighted outlines.
    • dash1_2

      public static final BasicStroke dash1_2
      2-pixel dashed stroke, phase 0 — first pass of a medium-weight marching-ants pair. Used with dash2_2.
    • dash2_2

      public static final BasicStroke dash2_2
      2-pixel dashed stroke, phase 8 — second pass of a medium-weight marching-ants pair. Used with dash1_2.
    • dash1_2t

      public static final BasicStroke dash1_2t
      4-pixel dashed stroke, phase 0 — first pass of a thick marching-ants pair. Used with dash2_2t.
    • dash2_2t

      public static final BasicStroke dash2_2t
      4-pixel dashed stroke, phase 8 — second pass of a thick marching-ants pair. Used with dash1_2t.
    • simpleDash

      public static final BasicStroke simpleDash
      1-pixel dashed stroke, phase 8. A convenient general-purpose dashed stroke for non-highlighted use.
    • simpleDash2

      public static final BasicStroke simpleDash2
      1-pixel dashed stroke, phase 0.5. A slight phase offset from simpleDash for situations where two complementary dashed lines are needed without the full marching-ants machinery.
  • Method Details

    • setSizeSmall

      public static void setSizeSmall(JComponent component)
      Apply the "small" size variant to a Swing component.

      This is a macOS-specific client property that instructs the native look-and-feel to render the component at a reduced size. It has no effect on other platforms.

      Parameters:
      component - the component to resize; must not be null
    • setSizeMini

      public static void setSizeMini(JComponent component)
      Apply the "mini" size variant to a Swing component.

      This is a macOS-specific client property that instructs the native look-and-feel to render the component at its smallest available size. It has no effect on other platforms.

      Parameters:
      component - the component to resize; must not be null
    • setSquareButton

      public static void setSquareButton(JButton button)
      Apply the square button style to a JButton.

      On macOS this suppresses the default rounded-capsule style in favour of a square-cornered button that is more compact in tight layouts. Has no effect on other platforms.

      Parameters:
      button - the button to restyle; must not be null
    • setTexturedButton

      public static void setTexturedButton(JButton button)
      Apply the textured button style to a JButton.

      On macOS this gives the button a brushed-metal texture suitable for toolbar-adjacent controls. Has no effect on other platforms.

      Parameters:
      button - the button to restyle; must not be null
    • minClip

      public static Rectangle minClip(Shape currentClip, Rectangle rect)
      Compute the intersection of a current clip shape with a rectangle.

      Returns the intersection bounding rectangle, or null if either argument is null, degenerate (zero area), or if the intersection is empty.

      Parameters:
      currentClip - the current clip shape (e.g. from Graphics.getClip())
      rect - the rectangle to intersect with the clip
      Returns:
      the intersection as a Rectangle, or null
    • getStroke

      public static BasicStroke getStroke(float lineWidth, LineStyle lineStyle)
      Return a cached BasicStroke for the given line width and style.

      The first call for any (width, style) combination creates and caches the stroke; subsequent calls return the cached instance. A width of zero is treated identically to a width of one.

      Supported styles and their dash patterns:

      Parameters:
      lineWidth - the desired stroke width in pixels
      lineStyle - the dash pattern style; must not be null
      Returns:
      a BasicStroke matching the requested parameters
    • copyWithNewWidth

      public static BasicStroke copyWithNewWidth(BasicStroke original, float newWidth)
      Copy a BasicStroke, replacing its width with newWidth while preserving all other attributes (cap, join, miter limit, dash array, and dash phase).
      Parameters:
      original - the stroke to copy; must not be null
      newWidth - the replacement width in pixels
      Returns:
      a new BasicStroke identical to original except for the width
    • rectangleToPoints

      public static Point[] rectangleToPoints(Rectangle rect)
      Return the four corners of a Rectangle as an array of Point objects.

      Corners are returned in order: top-left, top-right, bottom-right, bottom-left. Useful for computing item selection handles.

      Parameters:
      rect - the rectangle; must not be null
      Returns:
      array of four corner points
    • rectangleFromPoints

      public static Rectangle rectangleFromPoints(Point p1, Point p2)
      Build a Rectangle from two arbitrary corner points.

      The returned rectangle always has non-negative width and height, regardless of the relative positions of the two points.

      Parameters:
      p1 - one corner; if null and p2 is non-null, returns a zero-size rectangle at p2
      p2 - the opposite corner; if null and p1 is non-null, returns a zero-size rectangle at p1
      Returns:
      the bounding rectangle, or null if both points are null
    • getComponentImageBuffer

      public static BufferedImage getComponentImageBuffer(Component c)
      Allocate an opaque BufferedImage large enough to hold an off-screen rendering of c.

      The image is not painted; call paintComponentOnImage(Component, BufferedImage) separately. Returns null if c is null or has zero size.

      Parameters:
      c - the component whose size determines the image dimensions
      Returns:
      a new TYPE_INT_RGB image, or null
    • getComponentTranslucentImageBuffer

      public static BufferedImage getComponentTranslucentImageBuffer(Component c)
      Allocate a translucent BufferedImage large enough to hold an off-screen rendering of c.

      Use this instead of getComponentImageBuffer(java.awt.Component) when the component may have transparent or semi-transparent regions. Returns null if c is null or has zero size.

      Parameters:
      c - the component whose size determines the image dimensions
      Returns:
      a new translucent image, or null
    • paintComponentOnImage

      public static void paintComponentOnImage(Component c, BufferedImage image)
      Paint c onto an existing BufferedImage.

      A Graphics2D context is obtained from the image, the component is painted, and the context is disposed. The image must be at least as large as the component.

      Parameters:
      c - the component to paint; no-op if null
      image - the target image; no-op if null
    • getComponentImage

      public static BufferedImage getComponentImage(Component c)
      Parameters:
      c - the component to render; may return null if c is null or has zero size
      Returns:
      an image containing the rendered component, or null
    • drawSimple3DRect

      public static void drawSimple3DRect(Graphics2D g2, int x, int y, int width, int height, boolean raised)
      Draws a simple one-pixel 3D border around a rectangle using brighter and darker variants of the graphics context's current color.
      Parameters:
      g2 - the graphics context
      x - the left edge
      y - the top edge
      width - the rectangle width
      height - the rectangle height
      raised - true for a raised appearance; false for a recessed appearance
    • drawEtchedText

      public static void drawEtchedText(Graphics2D g2, String text, int x, int y)
      Draw etched text.

      The string is drawn twice: first in white at (x+1, y+1) to create a shadow, then in black at (x, y). This makes the text readable against any background color.

      Parameters:
      g2 - the graphics context
      text - the string to draw; must not be null
      x - the x pixel coordinate of the text baseline anchor
      y - the y pixel coordinate of the text baseline
    • drawRotatedText

      public static void drawRotatedText(Graphics2D g2, String s, Font font, int x, int y, double angleDegrees)
      Draw a string at the given position, rotated by angleDegrees around its baseline anchor.

      If the angle is less than 0.5° (effectively zero) the text is drawn normally without any rotation transform.

      Parameters:
      g2 - the graphics context
      s - the string to draw; must not be null
      font - the font to use
      x - the x pixel coordinate of the baseline anchor
      y - the y pixel coordinate of the baseline anchor
      angleDegrees - the counter-clockwise rotation angle in degrees
    • drawRotatedText

      public static void drawRotatedText(Graphics2D g2, String s, Font font, int xo, int yo, int delX, int delY, double angleDegrees)
      Draw a string rotated around an anchor point with an additional unrotated offset applied before rotation.

      The offset (delX, delY) is first rotated by angleDegrees and then added to the anchor (xo, yo) to determine where the string baseline is drawn.

      If the angle is less than 0.5° (effectively zero) the text is drawn normally at (xo + delX, yo + delY) without any rotation transform, which avoids floating-point error in the identity case.

      Parameters:
      g2 - the graphics context
      s - the string to draw; must not be null
      font - the font to use
      xo - the x pixel coordinate of the rotation anchor
      yo - the y pixel coordinate of the rotation anchor
      delX - horizontal offset from the anchor, measured before rotation is applied
      delY - vertical offset from the anchor, measured before rotation is applied
      angleDegrees - the counter-clockwise rotation angle in degrees
    • drawStyleLine

      public static void drawStyleLine(Graphics2D g2, Color lineColor, float lineWidth, LineStyle lineStyle, int x1, int y1, int x2, int y2)
      Draw a line with explicit color, width, and dash style.

      The graphics context's stroke is restored to its previous value after drawing.

      Parameters:
      g2 - the graphics context
      lineColor - the line color; must not be null
      lineWidth - the line width in pixels
      lineStyle - the dash style
      x1 - x pixel coordinate of the start point
      y1 - y pixel coordinate of the start point
      x2 - x pixel coordinate of the end point
      y2 - y pixel coordinate of the end point
    • drawHighlightedRectangle

      public static void drawHighlightedRectangle(Graphics2D g2, Rectangle r)
      Draw a highlighted rectangle using the default colors (highlightColor1 and highlightColor2).
      Parameters:
      g2 - the graphics context
      r - the rectangle to highlight; no-op if null
    • drawHighlightedRectangle

      public static void drawHighlightedRectangle(Graphics2D g2, Rectangle r, Color color1, Color color2)
      Draw a highlighted (marching-ants) rectangle outline.

      The rectangle is drawn twice: once with dash1 in color1 and once with dash2 in color2. The complementary dash phases produce the marching-ants effect.

      Parameters:
      g2 - the graphics context; no-op if null
      r - the rectangle to highlight; no-op if null
      color1 - primary dash color
      color2 - secondary dash color
    • drawHighlightedLine

      public static void drawHighlightedLine(Graphics2D g2, int x1, int y1, int x2, int y2, Color color1, Color color2)
      Draw a highlighted (marching-ants) line segment.

      The line is drawn twice with dash1_2 and dash2_2 (2-pixel width) in alternating colors.

      Parameters:
      g2 - the graphics context
      x1 - x pixel coordinate of the start point
      y1 - y pixel coordinate of the start point
      x2 - x pixel coordinate of the end point
      y2 - y pixel coordinate of the end point
      color1 - primary dash color
      color2 - secondary dash color
    • drawThickHighlightedLine

      public static void drawThickHighlightedLine(Graphics2D g2, int x1, int y1, int x2, int y2, Color color1, Color color2)
      Draw a thick highlighted (marching-ants) line segment.

      Identical to drawHighlightedLine(java.awt.Graphics2D, int, int, int, int, java.awt.Color, java.awt.Color) but uses dash1_2t and dash2_2t (4-pixel width) for a more prominent indicator.

      Parameters:
      g2 - the graphics context
      x1 - x pixel coordinate of the start point
      y1 - y pixel coordinate of the start point
      x2 - x pixel coordinate of the end point
      y2 - y pixel coordinate of the end point
      color1 - primary dash color
      color2 - secondary dash color
    • drawHighlightedArc

      public static void drawHighlightedArc(Graphics2D g2, int x, int y, int width, int height, int startAngle, int arcAngle, Color color1, Color color2)
      Draw a highlighted (marching-ants) arc.

      The arc is drawn twice with dash1 and dash2 (1-pixel width) in alternating colors.

      Parameters:
      g2 - the graphics context
      x - x pixel coordinate of the bounding rectangle's top-left corner
      y - y pixel coordinate of the bounding rectangle's top-left corner
      width - width of the bounding rectangle in pixels
      height - height of the bounding rectangle in pixels
      startAngle - start angle of the arc in degrees (0 = 3 o'clock, measured counter-clockwise)
      arcAngle - angular extent of the arc in degrees
      color1 - primary dash color
      color2 - secondary dash color
    • drawHighlightedOval

      public static void drawHighlightedOval(Graphics2D g2, Rectangle r)
      Draw a highlighted oval using the default colors (highlightColor1 and highlightColor2).
      Parameters:
      g2 - the graphics context
      r - the bounding rectangle of the oval; no-op if null
    • drawHighlightedOval

      public static void drawHighlightedOval(Graphics2D g2, Rectangle r, Color color1, Color color2)
      Draw a highlighted (marching-ants) oval outline.

      The oval is drawn twice with dash1 and dash2 (1-pixel width) in alternating colors.

      Parameters:
      g2 - the graphics context; no-op if null
      r - the bounding rectangle of the oval; no-op if null
      color1 - primary dash color
      color2 - secondary dash color
    • drawHighlightedPolyline

      public static void drawHighlightedPolyline(Graphics2D g2, int[] x, int[] y, int n)
      Draw a highlighted polyline using the default colors (highlightColor1 and highlightColor2).
      Parameters:
      g2 - the graphics context
      x - x coordinate array
      y - y coordinate array
      n - number of points to draw
    • drawHighlightedPolyline

      public static void drawHighlightedPolyline(Graphics2D g2, int[] x, int[] y, int n, Color color1, Color color2)
      Draw a highlighted (marching-ants) open polyline.

      The polyline is drawn twice with dash1 and dash2 (1-pixel width) in alternating colors.

      Parameters:
      g2 - the graphics context
      x - x coordinate array
      y - y coordinate array
      n - number of points to draw
      color1 - primary dash color
      color2 - secondary dash color
    • drawHighlightedShape

      public static void drawHighlightedShape(Graphics2D g2, Shape shape)
      Draw a highlighted shape using the default colors (highlightColor1 and highlightColor2).
      Parameters:
      g2 - the graphics context
      shape - the shape to highlight; no-op if null
    • drawHighlightedShape

      public static void drawHighlightedShape(Graphics2D g2, Shape shape, Color color1, Color color2)
      Draw a highlighted (marching-ants) arbitrary Shape outline.

      The shape is drawn twice with dash1 and dash2 (1-pixel width) in alternating colors.

      Parameters:
      g2 - the graphics context; no-op if null
      shape - the shape to highlight; no-op if null
      color1 - primary dash color
      color2 - secondary dash color
    • pointOnLine

      public static boolean pointOnLine(int px, int py, int startx, int starty, int endx, int endy)
      Test whether a pixel point lies on a pixel line segment within the tolerance defined by SELECTRES.

      The test is performed in pixel space using a parametric projection. A point is considered "on" the line if:

      • The projection of the point onto the infinite line through the segment falls within the segment (t ∈ [0, 1]), and
      • The perpendicular distance from the point to the line is less than SELECTRES pixels.

      If the segment is nearly degenerate (both |Δx| and |Δy| are less than 2 pixels) the method returns false.

      Parameters:
      px - x coordinate of the point to test
      py - y coordinate of the point to test
      startx - x coordinate of the segment start
      starty - y coordinate of the segment start
      endx - x coordinate of the segment end
      endy - y coordinate of the segment end
      Returns:
      true if the point is within tolerance of the segment
    • pointOnLine

      public static boolean pointOnLine(Point p, Point start, Point end)
      Test whether a pixel point lies on a pixel line segment within the tolerance defined by SELECTRES.
      Parameters:
      p - the point to test; no-op returns false if null
      start - the start of the segment; no-op returns false if null
      end - the end of the segment; no-op returns false if null
      Returns:
      true if the point is within tolerance of the segment
      See Also:
    • colorToHex

      public static String colorToHex(Color color)
      Convert a Color to an 8-digit hex string in #rrggbbaa format.

      All four channels (red, green, blue, alpha) are included. Returns "#000000ff" (opaque black) if color is null.

      Parameters:
      color - the color to convert; may be null
      Returns:
      hex string in the form #rrggbbaa
    • colorFromHex

      public static Color colorFromHex(String hex)
      Parse a hex color string in common internet format.

      The string may be in any of these forms:

      • rrggbbaa — 8 hex digits, fully specified
      • rrggbb — 6 hex digits; alpha defaults to ff (fully opaque)
      • #rrggbbaa or #rrggbb — leading # is optional

      Strings shorter than 6 hex digits are zero-padded on the right. Returns Color.black if hex is null or cannot be parsed.

      Parameters:
      hex - the hex color string; may be null
      Returns:
      the corresponding Color, or Color.black on error
    • getParentContainer

      public static Container getParentContainer(Component component)
      Walk up the component hierarchy and return the first ancestor that is a JInternalFrame, JDialog, or Window.

      Returns null if no such ancestor exists (e.g. the component has not been added to a window yet) or if component is null.

      Parameters:
      component - the component whose ancestry should be searched
      Returns:
      the nearest enclosing top-level container, or null