protected void paintGrid(Graphics g, int rowMin, int rowMax, int colMin, int colMax) {
    if (!grid.getShowGrid()) {
      return; // do nothing
    }

    int y1 = grid.getRowPosition(rowMin);
    int y2 = grid.getRowPosition(rowMax) + grid.getRowHeight(rowMax);
    int x1 = grid.getColumnPosition(colMin);
    int x2 = grid.getColumnPosition(colMax) + grid.getColumnWidth(colMax);

    g.setColor(grid.getGridColor());

    // Draw the horizontal lines
    for (int row = rowMin; row <= rowMax; row++) {
      int rowY = grid.getRowPosition(row);
      g.drawLine(x1, rowY, x2, rowY);
    }
    g.drawLine(x1, y2, x2, y2);

    // Draw the vertical gridlines
    for (int col = colMin; col <= colMax; col++) {
      int colX = grid.getColumnPosition(col);
      g.drawLine(colX, y1, colX, y2);
    }
    g.drawLine(x2, y1, x2, y2);
  }
  public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
    // Check there is something to print
    if (pageIndex >= maxNumPage || grid.getRowCount() == 0 || grid.getColumnCount() == 0) {
      return Printable.NO_SUCH_PAGE;
    }

    Graphics2D g2d = (Graphics2D) g;
    g2d.translate((int) pageFormat.getImageableX(), (int) pageFormat.getImageableY());

    int pageWidth = (int) pageFormat.getImageableWidth();
    int pageHeight = (int) pageFormat.getImageableHeight();
    int gridWidth = grid.getColumnModel().getTotalSize();
    int gridHeight = grid.getRowModel().getTotalSize();

    // Check there is something visible to print
    if (gridWidth == 0 || gridHeight == 0) {
      return Printable.NO_SUCH_PAGE;
    }

    // Calculate page to print
    int pageColumn = pageIndex % pageCols;
    int pageRow = pageIndex / pageCols;

    // Calculate scale to make the grid fit in maxNumPage
    float xFitPageScale = (pageWidth * pageCols) / (float) gridWidth;
    float yFitPageScale = (pageHeight * pageRows) / (float) gridHeight;
    float minScale = Math.min(xFitPageScale, yFitPageScale);

    // Scale the print area
    int pageX = (int) ((pageColumn * pageWidth) / minScale);
    int pageY = (int) ((pageRow * pageHeight) / minScale);
    pageWidth = (int) (pageWidth / minScale);
    pageHeight = (int) (pageHeight / minScale);

    // Get clip region for page
    Point p = new Point(pageX, pageY);
    int firstRow = grid.rowAtPoint(p);
    int firstCol = grid.columnAtPoint(p);
    int x1 = grid.getColumnPosition(firstCol);
    int y1 = grid.getRowPosition(firstRow);
    int x2 = x1 + pageWidth;
    int y2 = y1 + pageHeight;
    p = new Point(x2, y2);
    int lastRow = grid.rowAtPoint(p);
    int lastCol = grid.columnAtPoint(p);
    if (grid.getRowPosition(lastRow) + grid.getRowHeight(lastRow) > y2) {
      y2 = grid.getRowPosition(lastRow);
    } else {
      y2 = grid.getRowPosition(lastRow) + grid.getRowHeight(lastRow);
    }
    if (grid.getColumnPosition(lastCol) + grid.getColumnWidth(lastCol) > x2) {
      x2 = grid.getColumnPosition(lastCol);
    } else {
      x2 = grid.getColumnPosition(lastCol) + grid.getColumnWidth(lastCol);
    }
    int x = x1;
    int y = y1;
    int width = x2 - x1;
    int height = y2 - y1;

    SelectionSettings selectionSettings = new SelectionSettings(grid.getSelectionModel());
    selectionSettings.clear();

    // Print the page
    g2d.scale(minScale, minScale);
    g2d.translate(-x, -y);
    g2d.setClip(x, y, width, height);
    grid.print(g2d);

    selectionSettings.restore();

    return Printable.PAGE_EXISTS;
  }