public AxisState draw(Graphics2D g2, double cursor, Rectangle2D plotArea, 
            Rectangle2D dataArea, RectangleEdge edge, 
            PlotRenderingInfo plotState) {

        // if the axis is not visible, don't draw it...
        if (!isVisible()) {
            AxisState state = new AxisState(cursor);
            // even though the axis is not visible, we need ticks for the 
            // gridlines...
            List ticks = refreshTicks(g2, state, dataArea, edge); 
            state.setTicks(ticks);
            return state;
        }

        // calculate the adjusted data area taking into account the 3D effect...
        double xOffset = 0.0;
        double yOffset = 0.0;
        Plot plot = getPlot();
        if (plot instanceof CategoryPlot) {
            CategoryPlot cp = (CategoryPlot) plot;
            CategoryItemRenderer r = cp.getRenderer();
            if (r instanceof Effect3D) {
                Effect3D e3D = (Effect3D) r;
                xOffset = e3D.getXOffset();
                yOffset = e3D.getYOffset();
            }
        }

        double adjustedX = dataArea.getMinX();
        double adjustedY = dataArea.getMinY();
        double adjustedW = dataArea.getWidth() - xOffset;
        double adjustedH = dataArea.getHeight() - yOffset;

        if (edge == RectangleEdge.LEFT || edge == RectangleEdge.BOTTOM) {
            adjustedY += yOffset;
        }
        else if (edge == RectangleEdge.RIGHT || edge == RectangleEdge.TOP) {
            adjustedX += xOffset;
        }
        Rectangle2D adjustedDataArea = new Rectangle2D.Double(adjustedX, 
                adjustedY, adjustedW, adjustedH);

        // draw the tick marks and labels...
        AxisState info = drawTickMarksAndLabels(g2, cursor, plotArea, 
                adjustedDataArea, edge);
       
        // draw the axis label...
        info = drawLabel(getLabel(), g2, plotArea, dataArea, edge, info);

        return info;
        
    }