/**
   * Paints this Figure's children. The caller must save the state of the graphics prior to calling
   * this method, such that <code>graphics.restoreState()</code> may be called safely, and doing so
   * will return the graphics to its original state when the method was entered.
   *
   * <p>This method must leave the Graphics in its original state upon return.
   *
   * @param graphics the graphics used to paint
   * @since 2.0
   */
  protected void paintChildren(Graphics graphics) {
    IFigure child;

    Rectangle clip = Rectangle.SINGLETON;
    for (int i = 0; i < children.size(); i++) {
      child = (IFigure) children.get(i);
      if (child.isVisible() && child.intersects(graphics.getClip(clip))) {
        graphics.clipRect(child.getBounds());
        child.paint(graphics);
        graphics.restoreState();
      }
    }
  }
  /**
   * Paints this Figure's client area. The client area is typically defined as the anything inside
   * the Figure's {@link Border} or {@link Insets}, and by default includes the children of this
   * Figure. On return, this method must leave the given Graphics in its initial state.
   *
   * @param graphics The Graphics used to paint
   * @since 2.0
   */
  protected void paintClientArea(Graphics graphics) {
    if (children.isEmpty()) return;

    boolean optimizeClip = getBorder() == null || getBorder().isOpaque();

    if (useLocalCoordinates()) {
      graphics.translate(getBounds().x + getInsets().left, getBounds().y + getInsets().top);
      if (!optimizeClip) graphics.clipRect(getClientArea(PRIVATE_RECT));
      graphics.pushState();
      paintChildren(graphics);
      graphics.popState();
      graphics.restoreState();
    } else {
      if (optimizeClip) paintChildren(graphics);
      else {
        graphics.clipRect(getClientArea(PRIVATE_RECT));
        graphics.pushState();
        paintChildren(graphics);
        graphics.popState();
        graphics.restoreState();
      }
    }
  }
  /**
   * Paints this Figure and its children.
   *
   * @param graphics The Graphics object used for painting
   * @see #paintFigure(Graphics)
   * @see #paintClientArea(Graphics)
   * @see #paintBorder(Graphics)
   */
  public void paint(Graphics graphics) {
    if (getLocalBackgroundColor() != null) graphics.setBackgroundColor(getLocalBackgroundColor());
    if (getLocalForegroundColor() != null) graphics.setForegroundColor(getLocalForegroundColor());
    if (font != null) graphics.setFont(font);

    graphics.pushState();
    try {
      paintFigure(graphics);
      graphics.restoreState();
      paintClientArea(graphics);
      paintBorder(graphics);
    } finally {
      graphics.popState();
    }
  }