/**
   * @param aEvent
   * @param aStartPoint
   */
  protected void handleZoomRegion(final MouseEvent aEvent, final Point aStartPoint) {
    // For now, disabled by default as it isn't 100% working yet...
    if (Boolean.FALSE.equals(Boolean.valueOf(System.getProperty("zoomregionenabled", "false")))) {
      return;
    }

    final JComponent source = (JComponent) aEvent.getComponent();
    final boolean dragging = (aEvent.getID() == MouseEvent.MOUSE_DRAGGED);

    final GhostGlassPane glassPane =
        (GhostGlassPane) SwingUtilities.getRootPane(source).getGlassPane();

    Rectangle viewRect;
    final JScrollPane scrollPane =
        SwingComponentUtils.getAncestorOfClass(JScrollPane.class, source);
    if (scrollPane != null) {
      final JViewport viewport = scrollPane.getViewport();
      viewRect = SwingUtilities.convertRectangle(viewport, viewport.getVisibleRect(), glassPane);
    } else {
      viewRect = SwingUtilities.convertRectangle(source, source.getVisibleRect(), glassPane);
    }

    final Point start = SwingUtilities.convertPoint(source, aStartPoint, glassPane);
    final Point current = SwingUtilities.convertPoint(source, aEvent.getPoint(), glassPane);

    if (dragging) {
      if (!glassPane.isVisible()) {
        glassPane.setVisible(true);
        glassPane.setRenderer(new RubberBandRenderer(), start, current, viewRect);
      } else {
        glassPane.updateRenderer(start, current, viewRect);
      }

      glassPane.repaintPartially();
    } else
    /* if ( !dragging ) */
    {
      // Fire off a signal to the zoom controller to do its job...
      this.controller.getZoomController().zoomRegion(aStartPoint, aEvent.getPoint());

      glassPane.setVisible(false);
    }
  }
  /**
   * This calls the other relevant <code>paint...()</code> methods in this object. The layering of
   * the focus varies based on whether it should be painted outside or inside the filled shape, but
   * otherwise the layers are:
   *
   * <ul>
   *   <li>Filling the bounds with <code>button.getBackground()</code> (if <code>button.isOpaque()
   *       </code> is true).
   *   <li>If <code>getShadowHighlight()</code> is non-null, painting the stroke/border 1 pixel
   *       below its usual location.
   *   <li><code>paintBackground(g)</code>
   *   <li><code>paintEffects(g,false)</code>
   *   <li><code>paintIcon(g)</code>
   *   <li><code>paintText(g)</code>
   *   <LI><code>paintForeground(g)</code>
   *   <LI><code>paintEffects(g,true)</code>
   * </ul>
   */
  @Override
  public void paint(Graphics g0, JComponent c) {
    AbstractButton button = (AbstractButton) c;

    if (isLayoutValid(button) == false) updateLayout(button, getButtonInfo(button));

    if (button.isOpaque()) {
      g0.setColor(button.getBackground());
      g0.fillRect(0, 0, button.getWidth(), button.getHeight());
    }

    Graphics2D g = new OptimizedGraphics2D((Graphics2D) g0);

    g.setComposite(getComposite(button));

    ButtonInfo info = getButtonInfo(button);

    Color highlight = fill.getShadowHighlight(button);
    if (highlight != null && isStrokePainted(button)) {
      g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g.translate(0, 1);
      g.setColor(highlight);
      g.draw(info.fill);
      g.translate(0, -1);
    }

    PaintFocus focus = getFocusPainting(button);
    boolean hasFocus = hasFocus(button);
    if (Boolean.FALSE.equals(hasFocus) || button.isFocusPainted() == false) focus = PaintFocus.NONE;

    // this shouldn't be an issue, but just in case:
    if (isEnabled(button) == false) focus = PaintFocus.NONE;

    if (focus == PaintFocus.OUTSIDE) {
      if (isFillOpaque()) {
        // the opaque fill will overwrite the inner part of
        // this stroke...
        PlafPaintUtils.paintFocus(g, info.stroke, focusSize);
      } else {
        // this still has some rendering quirks in
        // Quartz (remove the clipping to study closely)
        // ... but other than the top horizontal & vertical
        // line it's OK.  And even those are ... partly there.
        Graphics2D focusG = (Graphics2D) g.create();
        GeneralPath outsideClip = new GeneralPath(Path2D.WIND_EVEN_ODD);
        outsideClip.append(new Rectangle(0, 0, button.getWidth(), button.getHeight()), false);
        outsideClip.append(info.fill, false);
        focusG.clip(outsideClip);
        PlafPaintUtils.paintFocus(focusG, info.stroke, focusSize);
        focusG.dispose();
      }
    }
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);

    paintBackground(g, info);
    paintEffects(g, info, true);

    g.setStroke(new BasicStroke(1));
    if (focus == PaintFocus.INSIDE) {
      Graphics2D focusG = (Graphics2D) g.create();
      focusG.clip(info.fill);
      PlafPaintUtils.paintFocus(focusG, info.stroke, focusSize);
      focusG.dispose();
      paintStroke(g, info);
    } else if (focus == PaintFocus.BOTH) {
      paintStroke(g, info);
      PlafPaintUtils.paintFocus(g, info.stroke, focusSize);
    } else {
      paintStroke(g, info);
    }

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    paintIcon(g, info);
    paintText(g, info);

    g.setComposite(isEnabled(button) ? AlphaComposite.SrcOver : SRC_OVER_TRANSLUCENT);
    paintForeground(g, info);
    paintEffects(g, info, false);
  }