// ===========================================================
  // Methods
  // ===========================================================
  private void initPanel() {

    final GridPanelOptions opt = mOptions;
    final int rows = opt.getRowCount();
    final int cols = opt.getColCount();

    mCell = new RectangularShape[rows][cols];

    if (opt.isHasHeader()) mHeader = new RectangularShape[cols];
    if (opt.isHasFooter()) mFooter = new RectangularShape[cols];

    this.setColor(opt.getColor());
  }
  private void setItem(
      final ItemType pType, final int pRow, final int pCol, RectangularShape pItem) {

    if (pItem != null)
      if (pItem.getParent() != null)
        throw new IllegalArgumentException("pItem already has a parent!");

    switch (pType) {
      case CAPTION:
        if (mCaption != null) {
          if (mCaption instanceof IMenuItem) mMenuItems.remove(mCaption);
          else detachChild(this.mCaption);
          mCaption = null;
        }
        break;
      case HEADER:
        if (mHeader[pCol] != null) {
          if (mHeader[pCol] instanceof IMenuItem) mMenuItems.remove(mHeader[pCol]);
          else detachChild(mHeader[pCol]);
          mHeader[pCol] = null;
        }
        break;
      case CELL:
        if (mCell[pRow][pCol] != null) {
          if (mCell[pRow][pCol] instanceof IMenuItem) mMenuItems.remove(mCell[pRow][pCol]);
          else detachChild(mCell[pRow][pCol]);
          mCell[pRow][pCol] = null;
        }
        break;
      case FOOTER:
        if (mFooter[pCol] != null) {
          if (mFooter[pCol] instanceof IMenuItem) mMenuItems.remove(mFooter[pCol]);
          else detachChild(mFooter[pCol]);
          mFooter[pCol] = null;
        }
        break;
    }

    if (pItem != null) {
      final GridPanelOptions opt = mOptions;

      final float paddingLeft = opt.getPanelPadding().getLeft();
      final float paddingTop = opt.getPanelPadding().getTop();

      final Margin cellMargin = opt.getCellMargin();
      final float marginLeft = cellMargin.getLeft();
      final float marginTop = cellMargin.getTop();

      final float captionHeight =
          opt.isHasCaption() ? opt.getCaptionMargin().calcOuterHeight(opt.getCaptionHeight()) : 0f;
      final float headerHeight =
          opt.isHasHeader() ? opt.getHeaderMargin().calcOuterHeight(opt.getHeaderHeight()) : 0f;

      final float colWidth = opt.getColWidth();
      final float rowHeight = opt.getRowHeight();

      final float x = paddingLeft + marginLeft + (cellMargin.calcOuterWidth(colWidth)) * pCol;
      float y = paddingTop;

      if (pType == ItemType.HEADER) y += captionHeight;
      if (pType == ItemType.CELL)
        y +=
            captionHeight
                + headerHeight
                + marginTop
                + (cellMargin.calcOuterHeight(rowHeight)) * pRow;
      if (pType == ItemType.FOOTER)
        y +=
            captionHeight
                + headerHeight
                + cellMargin.calcOuterHeight(rowHeight) * opt.getRowCount()
                + opt.getFooterMargin().getTop();

      pItem.setPosition(x, y);

      // TODO scale util
      if (pType == ItemType.CAPTION)
        if (pItem.getHeight() > opt.getCaptionHeight()) {
          pItem.setScale(opt.getCaptionHeight() / pItem.getHeight());
        }
      if (pType == ItemType.HEADER)
        if (pItem.getWidth() != colWidth || pItem.getHeight() != opt.getHeaderHeight()) {
          final float xScaleFactor = colWidth / pItem.getWidth();
          final float yScaleFactor = opt.getHeaderHeight() / pItem.getHeight();

          final float scaleFactor = Math.max(xScaleFactor, yScaleFactor);
          pItem.setScale(scaleFactor);
        }
      if (pType == ItemType.CELL)
        if (pItem.getWidth() != colWidth || pItem.getHeight() != rowHeight) {
          final float xScaleFactor = colWidth / pItem.getWidth();
          final float yScaleFactor = rowHeight / pItem.getHeight();

          final float scaleFactor = Math.max(xScaleFactor, yScaleFactor);
          pItem.setScale(scaleFactor);
        }
      if (pType == ItemType.FOOTER)
        if (pItem.getWidth() != colWidth || pItem.getHeight() != opt.getFooterHeight()) {
          final float xScaleFactor = colWidth / pItem.getWidth();
          final float yScaleFactor = opt.getFooterHeight() / pItem.getHeight();

          final float scaleFactor = Math.max(xScaleFactor, yScaleFactor);
          pItem.setScale(scaleFactor);
        }

      // TODO check skew effect
      final float angle = this.getRotation();
      this.setRotation(0);

      if (pItem instanceof IMenuItem) this.addMenuItem((IMenuItem) pItem);
      else this.attachChild(pItem);

      this.setRotation(angle);

      switch (pType) {
        case CAPTION:
          this.mCaption = pItem;
          break;
        case HEADER:
          this.mHeader[pCol] = pItem;
          break;
        case CELL:
          this.mCell[pRow][pCol] = pItem;
          break;
        case FOOTER:
          this.mFooter[pCol] = pItem;
          break;
      }
    }
  }
 public void setFooterItem(final int pCol, RectangularShape pItem) {
   if (mOptions.isHasFooter()) setItem(ItemType.FOOTER, 0, pCol, pItem);
 }
 public RectangularShape getFooterItem(final int pCol) {
   if (mOptions.isHasFooter()) return mFooter[pCol];
   else return null;
 }
 public void setHeaderItem(final int pCol, RectangularShape pItem) {
   if (mOptions.isHasHeader()) setItem(ItemType.HEADER, 0, pCol, pItem);
 }
 public void setCaption(RectangularShape pItem) {
   if (mOptions.isHasCaption()) setItem(ItemType.CAPTION, 0, 0, pItem);
 }
 public RectangularShape getCaption() {
   if (mOptions.isHasCaption()) return mCaption;
   else return null;
 }