/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pivot.wtk.skin;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;

import org.apache.pivot.collections.Dictionary;
import org.apache.pivot.collections.Sequence;
import org.apache.pivot.wtk.Bounds;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.Dimensions;
import org.apache.pivot.wtk.GraphicsUtilities;
import org.apache.pivot.wtk.Insets;
import org.apache.pivot.wtk.Orientation;
import org.apache.pivot.wtk.TablePane;
import org.apache.pivot.wtk.TablePaneAttributeListener;
import org.apache.pivot.wtk.TablePaneListener;

/**
 * Table pane skin.
 */
public class TablePaneSkin extends ContainerSkin implements TablePane.Skin, TablePaneListener,
    TablePaneAttributeListener {
    private Insets padding = Insets.NONE;
    private int horizontalSpacing = 0;
    private int verticalSpacing = 0;
    private boolean showHorizontalGridLines = false;
    private boolean showVerticalGridLines = false;
    private Color horizontalGridColor;
    private Color verticalGridColor;
    private Color highlightBackgroundColor = Color.GRAY;

    private int[] columnWidths = null;
    private int[] rowHeights = null;

    public TablePaneSkin() {
        horizontalGridColor = defaultForegroundColor();
        verticalGridColor = defaultForegroundColor();
    }

    @Override
    public void install(Component component) {
        super.install(component);

        TablePane tablePane = (TablePane) component;
        tablePane.getTablePaneListeners().add(this);
        tablePane.getTablePaneAttributeListeners().add(this);
    }

    @Override
    public int getPreferredWidth(int height) {
        TablePane tablePane = (TablePane) getComponent();
        TablePane.RowSequence rows = tablePane.getRows();
        TablePane.ColumnSequence columns = tablePane.getColumns();

        int rowCount = rows.getLength();
        int columnCount = columns.getLength();

        int[] columnWidthsLocal = new int[columnCount];
        int[] relativeWeights = new int[columnCount];
        boolean[] defaultWidthColumns = new boolean[columnCount];

        int totalRelativeWeight = 0;

        // First, we calculate the base widths of the columns, giving relative
        // columns their preferred width

        for (int i = 0; i < columnCount; i++) {
            TablePane.Column column = columns.get(i);
            int columnWidth = column.getWidth();
            boolean isRelative = column.isRelative();

            defaultWidthColumns[i] = (columnWidth < 0);

            if (isRelative) {
                relativeWeights[i] = columnWidth;
                totalRelativeWeight += columnWidth;
            }

            if (columnWidth < 0 || isRelative) {
                columnWidth = getPreferredColumnWidth(i);
            }

            columnWidthsLocal[i] = columnWidth;
        }

        // Next, we adjust the widths of the relative columns upwards where
        // necessary to reconcile their widths relative to one another while
        // ensuring that they still get at least their preferred width

        if (totalRelativeWeight > 0) {
            int totalRelativeWidth = 0;

            // Calculate the total relative width after the required upward
            // adjustments

            for (int i = 0; i < columnCount; i++) {
                int columnWidth = columnWidthsLocal[i];
                int relativeWeight = relativeWeights[i];

                if (relativeWeight > 0) {
                    float weightPercentage = relativeWeight / (float) totalRelativeWeight;
                    totalRelativeWidth = Math.max(totalRelativeWidth,
                        (int) (columnWidth / weightPercentage));
                }
            }

            // Perform the upward adjustments using the total relative width

            for (int i = 0; i < columnCount; i++) {
                int relativeWeight = relativeWeights[i];

                if (relativeWeight > 0) {
                    float weightPercentage = relativeWeight / (float) totalRelativeWeight;
                    columnWidthsLocal[i] = (int) (weightPercentage * totalRelativeWidth);
                }
            }
        }

        // Finally, we account for spanning cells, which have been ignored thus
        // far. If any spanned cell is default-width (including relative width
        // columns), then we ensure that the sum of the widths of the spanned
        // cells is enough to satisfy the preferred width of the spanning
        // content

        for (int i = 0; i < rowCount; i++) {
            TablePane.Row row = rows.get(i);

            for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
                Component component = row.get(j);

                if (component != null && component.isVisible()) {
                    int columnSpan = TablePane.getColumnSpan(component);

                    if (columnSpan > 1) {
                        // We might need to adjust column widths to accomodate
                        // this spanning cell. First, we find out if any of the
                        // spanned cells are default width and how much space
                        // we've allocated thus far for those cells

                        int spannedDefaultWidthCellCount = 0;
                        int spannedRelativeWeight = 0;
                        int spannedWidth = 0;

                        for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
                            if (defaultWidthColumns[j + k]) {
                                spannedDefaultWidthCellCount++;
                            }

                            spannedRelativeWeight += relativeWeights[j + k];
                            spannedWidth += columnWidthsLocal[j + k];
                        }

                        if (spannedRelativeWeight > 0 || spannedDefaultWidthCellCount > 0) {
                            int rowHeight = row.isRelative() ? -1 : row.getHeight();
                            int componentPreferredWidth = component.getPreferredWidth(rowHeight);

                            if (componentPreferredWidth > spannedWidth) {
                                // The component's preferred width is larger
                                // than the width we've allocated thus far, so
                                // an adjustment is necessary
                                int adjustment = componentPreferredWidth - spannedWidth;

                                if (spannedRelativeWeight > 0) {
                                    // We'll distribute the adjustment across
                                    // the spanned relative columns and adjust
                                    // other relative column widths to keep all
                                    // relative column widths reconciled
                                    float unitAdjustment = adjustment
                                        / (float) spannedRelativeWeight;

                                    for (int k = 0; k < columnCount; k++) {
                                        int relativeWeight = relativeWeights[k];

                                        if (relativeWeight > 0) {
                                            int columnAdjustment = Math.round(unitAdjustment
                                                * relativeWeight);

                                            columnWidthsLocal[k] += columnAdjustment;
                                        }
                                    }
                                } else {
                                    // We'll distribute the adjustment evenly
                                    // among the default-width columns
                                    for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
                                        if (defaultWidthColumns[j + k]) {
                                            int columnAdjustment = adjustment
                                                / spannedDefaultWidthCellCount;

                                            columnWidthsLocal[j + k] += columnAdjustment;

                                            // Adjust these to avoid rounding
                                            // errors
                                            adjustment -= columnAdjustment;
                                            spannedDefaultWidthCellCount--;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        // The preferred width of the table pane is the sum of the column
        // widths, plus padding and spacing

        boolean[][] occupiedCells = getOccupiedCells();
        int visibleColumnCount = 0;

        int preferredWidth = padding.left + padding.right;

        for (int j = 0; j < columnCount; j++) {
            boolean columnVisible = false;

            for (int i = 0; i < rowCount; i++) {
                if (occupiedCells[i][j]) {
                    columnVisible = true;
                    break;
                }
            }

            if (columnVisible) {
                preferredWidth += columnWidthsLocal[j];
                visibleColumnCount++;
            }
        }

        if (visibleColumnCount > 1) {
            preferredWidth += (visibleColumnCount - 1) * horizontalSpacing;
        }

        return preferredWidth;
    }

    @Override
    public int getPreferredHeight(int width) {
        TablePane tablePane = (TablePane) getComponent();
        TablePane.RowSequence rows = tablePane.getRows();
        TablePane.ColumnSequence columns = tablePane.getColumns();

        int rowCount = rows.getLength();
        int columnCount = columns.getLength();

        int[] rowHeightsLocal = new int[rowCount];
        int[] relativeWeights = new int[rowCount];
        boolean[] defaultHeightRows = new boolean[rowCount];

        int totalRelativeWeight = 0;

        int widthUpdated = width;
        if (widthUpdated < 0) {
            widthUpdated = getPreferredWidth(-1);
        }

        int[] columnWidthsLocal = getColumnWidths(widthUpdated);

        // First, we calculate the base heights of the rows, giving relative
        // rows their preferred height

        for (int i = 0; i < rowCount; i++) {
            TablePane.Row row = rows.get(i);
            int rowHeight = row.getHeight();
            boolean isRelative = row.isRelative();

            defaultHeightRows[i] = (rowHeight < 0);

            if (isRelative) {
                relativeWeights[i] = rowHeight;
                totalRelativeWeight += rowHeight;
            }

            if (rowHeight < 0 || isRelative) {
                rowHeight = getPreferredRowHeight(i, columnWidthsLocal);
            }

            rowHeightsLocal[i] = rowHeight;
        }

        // Next, we adjust the heights of the relative rows upwards where
        // necessary to reconcile their heights relative to one another while
        // ensuring that they still get at least their preferred height

        if (totalRelativeWeight > 0) {
            int totalRelativeHeight = 0;

            // Calculate the total relative height after the required upward
            // adjustments

            for (int i = 0; i < rowCount; i++) {
                int rowHeight = rowHeightsLocal[i];
                int relativeWeight = relativeWeights[i];

                if (relativeWeight > 0) {
                    float weightPercentage = relativeWeight / (float) totalRelativeWeight;
                    totalRelativeHeight = Math.max(totalRelativeHeight,
                        (int) (rowHeight / weightPercentage));
                }
            }

            // Perform the upward adjustments using the total relative height

            for (int i = 0; i < rowCount; i++) {
                int relativeWeight = relativeWeights[i];

                if (relativeWeight > 0) {
                    float weightPercentage = relativeWeight / (float) totalRelativeWeight;
                    rowHeightsLocal[i] = (int) (weightPercentage * totalRelativeHeight);
                }
            }
        }

        // Finally, we account for spanning cells, which have been ignored thus
        // far. If any spanned cell is default-height (including relative height
        // rows), then we ensure that the sum of the heights of the spanned
        // cells is enough to satisfy the preferred height of the spanning
        // content

        for (int i = 0; i < rowCount; i++) {
            TablePane.Row row = rows.get(i);

            for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
                Component component = row.get(j);

                if (component != null && component.isVisible()) {
                    int rowSpan = TablePane.getRowSpan(component);

                    if (rowSpan > 1) {
                        // We might need to adjust row heights to accomodate
                        // this spanning cell. First, we find out if any of the
                        // spanned cells are default height and how much space
                        // we've allocated thus far for those cells

                        int spannedDefaultHeightCellCount = 0;
                        int spannedRelativeWeight = 0;
                        int spannedHeight = 0;

                        for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
                            if (defaultHeightRows[i + k]) {
                                spannedDefaultHeightCellCount++;
                            }

                            spannedRelativeWeight += relativeWeights[i + k];
                            spannedHeight += rowHeightsLocal[i + k];
                        }

                        if (spannedRelativeWeight > 0 || spannedDefaultHeightCellCount > 0) {
                            int componentPreferredHeight = component.getPreferredHeight(columnWidthsLocal[j]);

                            if (componentPreferredHeight > spannedHeight) {
                                // The component's preferred height is larger
                                // than the height we've allocated thus far, so
                                // an adjustment is necessary
                                int adjustment = componentPreferredHeight - spannedHeight;

                                if (spannedRelativeWeight > 0) {
                                    // We'll distribute the adjustment across
                                    // the spanned relative rows and adjust
                                    // other relative row heights to keep all
                                    // relative row heights reconciled
                                    float unitAdjustment = adjustment
                                        / (float) spannedRelativeWeight;

                                    for (int k = 0; k < rowCount; k++) {
                                        int relativeWeight = relativeWeights[k];

                                        if (relativeWeight > 0) {
                                            int rowAdjustment = Math.round(unitAdjustment
                                                * relativeWeight);

                                            rowHeightsLocal[k] += rowAdjustment;
                                        }
                                    }
                                } else {
                                    // We'll distribute the adjustment evenly
                                    // among the default-height rows
                                    for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
                                        if (defaultHeightRows[i + k]) {
                                            int rowAdjustment = adjustment
                                                / spannedDefaultHeightCellCount;

                                            rowHeightsLocal[i + k] += rowAdjustment;

                                            // Adjust these to avoid rounding
                                            // errors
                                            adjustment -= rowAdjustment;
                                            spannedDefaultHeightCellCount--;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        // The preferred height of the table pane is the sum of the row
        // heights, plus padding and spacing

        boolean[][] occupiedCells = getOccupiedCells();
        int visibleRowCount = 0;

        int preferredHeight = padding.top + padding.bottom;

        for (int i = 0; i < rowCount; i++) {
            boolean rowVisible = false;

            for (int j = 0; j < columnCount; j++) {
                if (occupiedCells[i][j]) {
                    rowVisible = true;
                    break;
                }
            }

            if (rowVisible) {
                preferredHeight += rowHeightsLocal[i];
                visibleRowCount++;
            }
        }

        if (visibleRowCount > 1) {
            preferredHeight += (visibleRowCount - 1) * verticalSpacing;
        }

        return preferredHeight;
    }

    @Override
    public Dimensions getPreferredSize() {
        // TODO Optimize by performing calculations here
        int preferredWidth = getPreferredWidth(-1);
        int preferredHeight = getPreferredHeight(preferredWidth);
        return new Dimensions(preferredWidth, preferredHeight);
    }

    @Override
    public int getBaseline(int width, int height) {
        TablePane tablePane = (TablePane) getComponent();

        TablePane.RowSequence rows = tablePane.getRows();
        TablePane.ColumnSequence columns = tablePane.getColumns();

        int rowCount = rows.getLength();
        int columnCount = columns.getLength();

        int[] columnWidthsLocal = getColumnWidths(width);
        int[] rowHeightsLocal = getRowHeights(height, columnWidthsLocal);
        boolean[][] occupiedCells = getOccupiedCells();

        int baseline = -1;

        int rowY = padding.top;

        for (int i = 0; i < rowCount && baseline == -1; i++) {
            TablePane.Row row = rows.get(i);
            boolean rowVisible = false;

            for (int j = 0, n = row.getLength(); j < n && j < columnCount && baseline == -1; j++) {
                Component component = row.get(j);

                if (component != null && component.isVisible()) {
                    int columnSpan = Math.min(TablePane.getColumnSpan(component), columnCount - j);
                    int componentWidth = (columnSpan - 1) * horizontalSpacing;
                    for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
                        componentWidth += columnWidthsLocal[j + k];
                    }

                    int rowSpan = Math.min(TablePane.getRowSpan(component), rowCount - i);
                    int componentHeight = (rowSpan - 1) * verticalSpacing;
                    for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
                        componentHeight += rowHeightsLocal[i + k];
                    }

                    baseline = component.getBaseline(Math.max(componentWidth, 0),
                        Math.max(componentHeight, 0));

                    if (baseline != -1) {
                        baseline += rowY;
                    }
                }

                rowVisible |= occupiedCells[i][j];
            }

            if (rowVisible) {
                rowY += (rowHeightsLocal[i] + verticalSpacing);
            }
        }

        return baseline;
    }

    @Override
    public void layout() {
        TablePane tablePane = (TablePane) getComponent();

        TablePane.RowSequence rows = tablePane.getRows();
        TablePane.ColumnSequence columns = tablePane.getColumns();

        int rowCount = rows.getLength();
        int columnCount = columns.getLength();

        int width = getWidth();
        int height = getHeight();

        // NOTE We cache column widths and row heights to make getColumnAt()
        // and getRowAt() more efficient
        columnWidths = getColumnWidths(width);
        rowHeights = getRowHeights(height, columnWidths);

        // Determine which rows and column should be visible so we know which
        // ones should be collapsed
        boolean[] visibleRows = new boolean[rowCount];
        boolean[] visibleColumns = new boolean[columnCount];

        boolean[][] occupiedCells = getOccupiedCells();
        for (int i = 0; i < rowCount; i++) {
            for (int j = 0; j < columnCount; j++) {
                if (occupiedCells[i][j]) {
                    visibleRows[i] = true;
                    visibleColumns[j] = true;
                }
            }
        }

        int componentY = padding.top;
        for (int i = 0; i < rowCount; i++) {
            TablePane.Row row = rows.get(i);

            int componentX = padding.left;
            for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
                Component child = row.get(j);

                if (child != null && child.isVisible()) {
                    child.setLocation(componentX, componentY);

                    int columnSpan = TablePane.getColumnSpan(child);
                    columnSpan = Math.min(columnSpan, columnCount - j);
                    int childWidth = (columnSpan - 1) * horizontalSpacing;
                    for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
                        childWidth += columnWidths[j + k];
                    }

                    int rowSpan = TablePane.getRowSpan(child);
                    rowSpan = Math.min(rowSpan, rowCount - i);
                    int childHeight = (rowSpan - 1) * verticalSpacing;
                    for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
                        childHeight += rowHeights[i + k];
                    }

                    // Set the component's size
                    child.setSize(Math.max(childWidth, 0), Math.max(childHeight, 0));
                }

                if (visibleColumns[j]) {
                    componentX += (columnWidths[j] + horizontalSpacing);
                }
            }

            if (visibleRows[i]) {
                componentY += (rowHeights[i] + verticalSpacing);
            }
        }
    }

    @Override
    public void paint(Graphics2D graphics) {
        super.paint(graphics);

        TablePane tablePane = (TablePane) getComponent();

        TablePane.RowSequence rows = tablePane.getRows();
        TablePane.ColumnSequence columns = tablePane.getColumns();

        int rowCount = rows.getLength();
        int columnCount = columns.getLength();

        int width = getWidth();
        int height = getHeight();

        graphics.setPaint(highlightBackgroundColor);

        // Paint the highlighted rows
        for (int i = 0, rowY = padding.top; i < rowCount; i++) {
            TablePane.Row row = rows.get(i);

            if (row.isHighlighted()) {
                graphics.fillRect(0, rowY, width, rowHeights[i]);
            }

            rowY += rowHeights[i] + verticalSpacing;
        }

        // Paint the highlighted columns
        for (int j = 0, columnX = padding.left; j < columnCount; j++) {
            TablePane.Column column = columns.get(j);

            if (column.isHighlighted()) {
                graphics.fillRect(columnX, 0, columnWidths[j], height);
            }

            columnX += columnWidths[j] + horizontalSpacing;
        }

        // Paint the grid lines
        if ((showHorizontalGridLines && verticalSpacing > 0)
            || (showVerticalGridLines && horizontalSpacing > 0)) {
            Graphics2D gridGraphics = (Graphics2D) graphics.create();

            gridGraphics.setStroke(new BasicStroke());
            gridGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

            // Find any components that span multiple rows or columns, and
            // ensure that the grid lines don't get painted through their
            // cells. We'll only instantiate gridClip if we find such cells
            Area gridClip = null;

            for (int i = 0, componentY = padding.top; i < rowCount; i++) {
                for (int j = 0, componentX = padding.left; j < columnCount; j++) {
                    Component component = tablePane.getCellComponent(i, j);

                    if (component != null) {
                        int rowSpan = TablePane.getRowSpan(component);
                        int columnSpan = TablePane.getColumnSpan(component);

                        if (rowSpan > 1 || columnSpan > 1) {
                            int rowY = componentY;
                            int columnX = componentX;

                            int rowHeight = rowHeights[i];
                            int columnWidth = columnWidths[j];

                            for (int k = i + 1; k < i + rowSpan && k < rowCount; k++) {
                                rowHeight += rowHeights[k] + verticalSpacing;
                            }

                            for (int k = j + 1; k < j + columnSpan && k < columnCount; k++) {
                                columnWidth += columnWidths[k] + horizontalSpacing;
                            }

                            if (gridClip == null) {
                                gridClip = new Area(graphics.getClip());
                            }

                            if (horizontalSpacing > 1) {
                                columnWidth += horizontalSpacing - 1;
                                columnX -= (int) ((horizontalSpacing * 0.5f) - 0.5f);
                            }

                            if (verticalSpacing > 1) {
                                rowHeight += verticalSpacing - 1;
                                rowY -= (int) ((verticalSpacing * 0.5f) - 0.5f);
                            }

                            Rectangle2D.Float bounds = new Rectangle2D.Float(columnX, rowY,
                                columnWidth, rowHeight);
                            gridClip.subtract(new Area(bounds));
                        }
                    }

                    componentX += columnWidths[j] + horizontalSpacing;
                }

                componentY += rowHeights[i] + verticalSpacing;
            }

            if (gridClip != null) {
                gridGraphics.clip(gridClip);
            }

            boolean[][] occupiedCells = getOccupiedCells();

            if (showHorizontalGridLines && verticalSpacing > 0 && rowCount > 1) {
                gridGraphics.setPaint(horizontalGridColor);

                int rowY = padding.top;
                int visibleRowCount = 0;

                for (int i = 0; i < rowCount; i++) {
                    boolean rowVisible = false;

                    for (int j = 0; j < columnCount; j++) {
                        if (occupiedCells[i][j]) {
                            rowVisible = true;
                            break;
                        }
                    }

                    if (rowVisible) {
                        if (visibleRowCount++ > 0) {
                            int gridY = Math.max(rowY - (int) Math.ceil(verticalSpacing * 0.5f), 0);
                            GraphicsUtilities.drawLine(gridGraphics, 0, gridY, width,
                                Orientation.HORIZONTAL);
                        }

                        rowY += (rowHeights[i] + verticalSpacing);
                    }
                }
            }

            if (showVerticalGridLines && horizontalSpacing > 0 && columnCount > 1) {
                gridGraphics.setPaint(verticalGridColor);

                int columnX = padding.left;
                int visibleColumnCount = 0;

                for (int j = 0; j < columnCount; j++) {
                    boolean columnVisible = false;

                    for (int i = 0; i < rowCount; i++) {
                        if (occupiedCells[i][j]) {
                            columnVisible = true;
                            break;
                        }
                    }

                    if (columnVisible) {
                        if (visibleColumnCount++ > 0) {
                            int gridX = Math.max(
                                columnX - (int) Math.ceil(horizontalSpacing * 0.5), 0);
                            GraphicsUtilities.drawLine(gridGraphics, gridX, 0, height,
                                Orientation.VERTICAL);
                        }

                        columnX += (columnWidths[j] + horizontalSpacing);
                    }
                }
            }

            gridGraphics.dispose();
        }
    }

    /**
     * @return The amount of space that will be reserved around the inside edges
     * of the table pane.
     */
    public Insets getPadding() {
        return padding;
    }

    /**
     * Sets the amount of space that will be reserved around the inside edges of
     * the table pane.
     *
     * @param padding The individual padding amounts for each edge.
     */
    public void setPadding(Insets padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        this.padding = padding;
        invalidateComponent();
    }

    /**
     * Sets the amount of space that will be reserved around the inside edges of
     * the table pane.
     *
     * @param padding The single padding value to use for all the edges.
     */
    public final void setPadding(int padding) {
        setPadding(new Insets(padding));
    }

    /**
     * Sets the amount of space that will be reserved around the inside edges of
     * the table pane.
     *
     * @param padding A dictionary with keys in the set {left, top, bottom,
     * right}.
     */
    public final void setPadding(Dictionary<String, ?> padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        setPadding(new Insets(padding));
    }

    /**
     * Sets the amount of space that will be reserved around the inside edges of
     * the table pane.
     *
     * @param padding The single padding value to use for all the edges.
     */
    public final void setPadding(Number padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        setPadding(padding.intValue());
    }

    /**
     * Sets the amount of space that will be reserved around the inside edges of
     * the table pane.
     *
     * @param padding A string containing an integer or a JSON dictionary with
     * keys left, top, bottom, and/or right.
     */
    public final void setPadding(String padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        setPadding(Insets.decode(padding));
    }

    /**
     * @return The spacing that will be applied between the table pane's columns
     * during layout.
     */
    public int getHorizontalSpacing() {
        return horizontalSpacing;
    }

    /**
     * Sets the spacing that will be applied between the table pane's columns
     * during layout.
     *
     * @param horizontalSpacing The new spacing value.
     */
    public void setHorizontalSpacing(int horizontalSpacing) {
        if (horizontalSpacing < 0) {
            throw new IllegalArgumentException("horizontalSpacing is negative");
        }

        this.horizontalSpacing = horizontalSpacing;
        invalidateComponent();
    }

    /**
     * @return The spacing that will be applied in between the table pane's rows
     * during layout.
     */
    public int getVerticalSpacing() {
        return verticalSpacing;
    }

    /**
     * Sets the spacing that will be applied in between the table pane's rows
     * during layout.
     *
     * @param verticalSpacing The new spacing value.
     */
    public void setVerticalSpacing(int verticalSpacing) {
        if (verticalSpacing < 0) {
            throw new IllegalArgumentException("verticalSpacing is negative");
        }

        this.verticalSpacing = verticalSpacing;
        invalidateComponent();
    }

    /**
     * @return Whether or not horizontal grid lines will be painted in between the
     * table pane's rows.
     */
    public boolean getShowHorizontalGridLines() {
        return showHorizontalGridLines;
    }

    /**
     * Sets whether or not horizontal grid lines will be painted in between the
     * table pane's rows.
     *
     * @param showHorizontalGridLines Whether to show the horizontal lines.
     */
    public void setShowHorizontalGridLines(boolean showHorizontalGridLines) {
        this.showHorizontalGridLines = showHorizontalGridLines;
        repaintComponent();
    }

    /**
     * @return Whether or not vertical grid lines will be painted in between the
     * table pane's columns.
     */
    public boolean getShowVerticalGridLines() {
        return showVerticalGridLines;
    }

    /**
     * Sets whether or not vertical grid lines will be painted in between the
     * table pane's columns.
     *
     * @param showVerticalGridLines Whether to show the vertical lines.
     */
    public void setShowVerticalGridLines(boolean showVerticalGridLines) {
        this.showVerticalGridLines = showVerticalGridLines;
        repaintComponent();
    }

    /**
     * @return The color used to paint the table pane's horizontal grid lines.
     */
    public Color getHorizontalGridColor() {
        return horizontalGridColor;
    }

    /**
     * Sets the color used to paint the table pane's horizontal grid lines.
     *
     * @param horizontalGridColor The new grid line color.
     */
    public void setHorizontalGridColor(Color horizontalGridColor) {
        if (horizontalGridColor == null) {
            throw new IllegalArgumentException("horizontalGridColor is null.");
        }

        this.horizontalGridColor = horizontalGridColor;

        if (showHorizontalGridLines || showVerticalGridLines) {
            repaintComponent();
        }
    }

    /**
     * Sets the color used to paint the table pane's horizontal grid lines.
     *
     * @param horizontalGridColor Any of the
     * {@linkplain GraphicsUtilities#decodeColor color values recognized by
     * Pivot}.
     */
    public final void setHorizontalGridColor(String horizontalGridColor) {
        if (horizontalGridColor == null) {
            throw new IllegalArgumentException("horizontalGridColor is null.");
        }

        setHorizontalGridColor(GraphicsUtilities.decodeColor(horizontalGridColor));
    }

    /**
     * @return The color used to paint the table pane's vertical grid lines.
     */
    public Color getVerticalGridColor() {
        return verticalGridColor;
    }

    /**
     * Sets the color used to paint the table pane's vertical grid lines.
     *
     * @param verticalGridColor The new grid line color.
     */
    public void setVerticalGridColor(Color verticalGridColor) {
        if (verticalGridColor == null) {
            throw new IllegalArgumentException("verticalGridColor is null.");
        }

        this.verticalGridColor = verticalGridColor;

        if (showHorizontalGridLines || showVerticalGridLines) {
            repaintComponent();
        }
    }

    /**
     * Sets the color used to paint the table pane's vertical grid lines.
     *
     * @param verticalGridColor Any of the
     * {@linkplain GraphicsUtilities#decodeColor color values recognized by
     * Pivot}.
     */
    public final void setVerticalGridColor(String verticalGridColor) {
        if (verticalGridColor == null) {
            throw new IllegalArgumentException("verticalGridColor is null.");
        }

        setVerticalGridColor(GraphicsUtilities.decodeColor(verticalGridColor));
    }

    /**
     * @return The background color used to paint the highlighted rows and columns.
     */
    public Color getHighlightBackgroundColor() {
        return highlightBackgroundColor;
    }

    /**
     * Sets the background color used to paint the highlighted rows and columns.
     *
     * @param highlightBackgroundColor The new highlight color.
     */
    public void setHighlightBackgroundColor(Color highlightBackgroundColor) {
        if (highlightBackgroundColor == null) {
            throw new IllegalArgumentException("highlightBackgroundColor is null.");
        }

        this.highlightBackgroundColor = highlightBackgroundColor;
        repaintComponent();
    }

    /**
     * Sets the background color used to paint the highlighted rows and columns.
     *
     * @param highlightBackgroundColor Any of the
     * {@linkplain GraphicsUtilities#decodeColor color values recognized by
     * Pivot}.
     */
    public final void setHighlightBackgroundColor(String highlightBackgroundColor) {
        if (highlightBackgroundColor == null) {
            throw new IllegalArgumentException("highlightBackgroundColor is null.");
        }

        setHighlightBackgroundColor(GraphicsUtilities.decodeColor(highlightBackgroundColor));
    }

    /**
     * Returns a grid indicating which cells are occupied. A component is said
     * to occupy a cell if it is visible and either lives in the cell directly
     * or spans the cell. Conversely, vacant cells do not have visible
     * components within them or spanning them.
     *
     * @return A grid of booleans, where occupied cells are denoted by
     * <tt>true</tt>, and vacant cells are denoted by <tt>false</tt>
     */
    private boolean[][] getOccupiedCells() {
        TablePane tablePane = (TablePane) getComponent();

        TablePane.RowSequence rows = tablePane.getRows();
        TablePane.ColumnSequence columns = tablePane.getColumns();

        int rowCount = rows.getLength();
        int columnCount = columns.getLength();

        boolean[][] occupiedCells = new boolean[rowCount][columnCount];

        for (int i = 0; i < rowCount; i++) {
            TablePane.Row row = rows.get(i);

            for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
                Component component = row.get(j);

                if (component != null && component.isVisible()) {

                    int rowSpan = TablePane.getRowSpan(component);
                    int columnSpan = TablePane.getColumnSpan(component);

                    for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
                        for (int l = 0; l < columnSpan && j + l < columnCount; l++) {
                            occupiedCells[i + k][j + l] = true;
                        }
                    }
                }
            }
        }

        return occupiedCells;
    }

    /**
     * Gets the preferred width of a table pane column, which is defined as the
     * maximum preferred width of the column's visible components. <p> Because
     * their preferred width relates to the preferred widths of other columns,
     * components that span multiple columns will not be considered in this
     * calculation (even if they live in the column directly). It is up to the
     * caller to factor such components into the column widths calculation.
     *
     * @param columnIndex The index of the column whose preferred width we're
     * calculating
     */
    private int getPreferredColumnWidth(int columnIndex) {
        TablePane tablePane = (TablePane) getComponent();

        TablePane.RowSequence rows = tablePane.getRows();

        int preferredWidth = 0;

        for (int i = 0, n = rows.getLength(); i < n; i++) {
            TablePane.Row row = rows.get(i);

            if (row.getLength() > columnIndex) {
                Component component = row.get(columnIndex);

                if (component != null && component.isVisible()
                    && TablePane.getColumnSpan(component) == 1) {
                    preferredWidth = Math.max(preferredWidth, component.getPreferredWidth(-1));
                }
            }
        }

        return preferredWidth;
    }

    /**
     * Tells whether or not the specified column is visible. A column is visible
     * if and only if one or more visible components occupies it. A component is
     * said to occupy a cell if it either lives in the cell directly or spans
     * the cell.
     *
     * @param columnIndex The index of the column within the table pane
     * @return <tt>true</tt> if the column is visible; <tt>false</tt> otherwise
     */
    private boolean isColumnVisible(int columnIndex) {
        boolean visible = false;

        boolean[][] occupiedCells = getOccupiedCells();

        for (int i = 0; i < occupiedCells.length; i++) {
            if (occupiedCells[i][columnIndex]) {
                visible = true;
                break;
            }
        }

        return visible;
    }

    /**
     * Gets the preferred height of a table pane row, which is defined as the
     * maximum preferred height of the row's visible components. The preferred
     * height of each constituent component will be constrained by the width of
     * the column that the component occupies (as specified in the array of
     * column widths). <p> Because their preferred height relates to the
     * preferred heights of other rows, components that span multiple rows will
     * not be considered in this calculation (even if they live in the column
     * directly). It is up to the caller to factor such components into the row
     * heights calculation.
     *
     * @param rowIndex The index of the row whose preferred height we're
     * calculating
     * @param columnWidthsArgument An array of column width values corresponding
     * to the columns of the table pane
     */
    private int getPreferredRowHeight(int rowIndex, int[] columnWidthsArgument) {
        if (columnWidthsArgument == null) {
            throw new IllegalArgumentException("columnWidths is null");
        }

        TablePane tablePane = (TablePane) getComponent();

        TablePane.ColumnSequence columns = tablePane.getColumns();
        TablePane.Row row = tablePane.getRows().get(rowIndex);

        int preferredHeight = 0;

        for (int j = 0, n = row.getLength(), m = columns.getLength(); j < n && j < m; j++) {
            Component component = row.get(j);

            if (component != null && component.isVisible() && TablePane.getRowSpan(component) == 1) {
                preferredHeight = Math.max(preferredHeight,
                    component.getPreferredHeight(columnWidthsArgument[j]));
            }
        }

        return preferredHeight;
    }

    /**
     * Tells whether or not the specified row is visible. A row is visible if
     * and only if one or more visible components occupies it. A component is
     * said to occupy a cell if it either lives in the cell directly or spans
     * the cell.
     *
     * @param rowIndex The index of the row within the table pane
     * @return <tt>true</tt> if the row is visible; <tt>false</tt> otherwise
     */
    private boolean isRowVisible(int rowIndex) {
        boolean visible = false;

        boolean[][] occupiedCells = getOccupiedCells();

        for (int j = 0; j < occupiedCells[rowIndex].length; j++) {
            if (occupiedCells[rowIndex][j]) {
                visible = true;
                break;
            }
        }

        return visible;
    }

    /**
     * Gets the width of each table pane column given the specified table pane
     * width.
     *
     * @param width The width constraint of the table pane
     * @return An array containing the width of each column in the table pane
     * given the specified constraint
     */
    private int[] getColumnWidths(int width) {
        TablePane tablePane = (TablePane) getComponent();

        TablePane.RowSequence rows = tablePane.getRows();
        TablePane.ColumnSequence columns = tablePane.getColumns();

        int rowCount = rows.getLength();
        int columnCount = columns.getLength();

        int[] columnWidthsLocal = new int[columnCount];

        boolean[] defaultWidthColumns = new boolean[columnCount];
        int totalRelativeWeight = 0;
        int visibleColumnCount = 0;

        int reservedWidth = padding.left + padding.right;

        // First, we allocate the widths of non-relative columns. We store the
        // widths of relative columns as negative values for later processing

        for (int j = 0; j < columnCount; j++) {
            if (isColumnVisible(j)) {
                TablePane.Column column = columns.get(j);
                int columnWidth = column.getWidth();

                if (column.isRelative()) {
                    columnWidthsLocal[j] = -columnWidth;
                    totalRelativeWeight += columnWidth;
                } else {
                    if (columnWidth < 0) {
                        // Default width column; we must calculate the width
                        columnWidth = getPreferredColumnWidth(j);
                        defaultWidthColumns[j] = true;
                    }

                    columnWidthsLocal[j] = columnWidth;
                    reservedWidth += columnWidth;
                }

                visibleColumnCount++;
            } else {
                columnWidthsLocal[j] = 0;
            }
        }

        if (visibleColumnCount > 1) {
            reservedWidth += (visibleColumnCount - 1) * horizontalSpacing;
        }

        // Next, we we account for default-width columns containing spanning
        // cells, which have been ignored thus far. We ensure that the sum of
        // the widths of the spanned cells is enough to satisfy the preferred
        // width of the spanning content.

        for (int i = 0; i < rowCount; i++) {
            TablePane.Row row = rows.get(i);

            for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
                Component component = row.get(j);

                if (component != null && component.isVisible()) {
                    int columnSpan = TablePane.getColumnSpan(component);

                    if (columnSpan > 1) {
                        // We might need to adjust column widths to accomodate
                        // this spanning cell. First, we find out if any of the
                        // spanned cells are default width and how much space
                        // we've allocated thus far for those cells

                        boolean adjustCells = true;
                        int spannedDefaultWidthCellCount = 0;
                        int spannedWidth = 0;

                        for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
                            if (columnWidthsLocal[j + k] < 0) {
                                adjustCells = false;
                                break;
                            }

                            if (defaultWidthColumns[j + k]) {
                                spannedDefaultWidthCellCount++;
                            }

                            spannedWidth += columnWidthsLocal[j + k];
                        }

                        // If we span any relative-width columns, we assume
                        // that we'll achieve the desired spanning width when
                        // we divvy up the remaining space, so there's no need
                        // to make an adjustment here. This assumption is safe
                        // because our preferred width policy is to *either*
                        // divide the adjustment among the relative-width
                        // columns *or* among the default-width columns if we
                        // don't span any relative-width columns

                        if (adjustCells && spannedDefaultWidthCellCount > 0) {
                            int componentPreferredWidth = component.getPreferredWidth(-1);

                            if (componentPreferredWidth > spannedWidth) {
                                // The component's preferred width is larger
                                // than the width we've allocated thus far, so
                                // an adjustment is necessary
                                int adjustment = componentPreferredWidth - spannedWidth;

                                // We'll distribute the adjustment evenly
                                // among the default-width columns
                                for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
                                    if (defaultWidthColumns[j + k]) {
                                        int columnAdjustment = adjustment
                                            / spannedDefaultWidthCellCount;

                                        columnWidthsLocal[j + k] += columnAdjustment;
                                        reservedWidth += columnAdjustment;

                                        // Adjust these to avoid rounding errors
                                        adjustment -= columnAdjustment;
                                        spannedDefaultWidthCellCount--;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        // Finally, we allocate the widths of the relative columns by divvying
        // up the remaining width

        int remainingWidth = Math.max(width - reservedWidth, 0);
        if (totalRelativeWeight > 0 && remainingWidth > 0) {
            for (int j = 0; j < columnCount; j++) {
                if (columnWidthsLocal[j] < 0) {
                    int relativeWeight = -columnWidthsLocal[j];
                    float weightPercentage = relativeWeight / (float) totalRelativeWeight;
                    int columnWidth = (int) (remainingWidth * weightPercentage);

                    columnWidthsLocal[j] = columnWidth;

                    // NOTE we adjust remainingWidth and totalRelativeWeight as
                    // we go
                    // to avoid potential rounding errors in the columnWidth
                    // calculation
                    remainingWidth -= columnWidth;
                    totalRelativeWeight -= relativeWeight;
                }
            }
        }

        return columnWidthsLocal;
    }

    /**
     * Gets the height of each row of a table pane given the specified
     * constraints.
     *
     * @param height The height constraint of the table pane
     * @param columnWidthsArgument The widths of the table pane's columns, which
     * will be used as width constraints to the row heights when necessary, or
     * <tt>null</tt> if the column widths are not yet known (the row heights
     * will be unconstrained)
     * @return An array containing the height of each row in the table pane given
     * the specified constraints
     */
    private int[] getRowHeights(int height, int[] columnWidthsArgument) {
        if (columnWidthsArgument == null) {
            throw new IllegalArgumentException("columnWidths is null");
        }

        TablePane tablePane = (TablePane) getComponent();
        TablePane.RowSequence rows = tablePane.getRows();

        int rowCount = rows.getLength();
        int columnCount = tablePane.getColumns().getLength();

        int rowHeightsLocal[] = new int[rowCount];

        boolean[] defaultHeightRows = new boolean[rowCount];
        int totalRelativeWeight = 0;
        int visibleRowCount = 0;

        int reservedHeight = padding.top + padding.bottom;

        // First, we allocate the heights of non-relative rows. We store the
        // heights of relative rows as negative values for later processing

        for (int i = 0; i < rowCount; i++) {
            if (isRowVisible(i)) {
                TablePane.Row row = rows.get(i);
                int rowHeight = row.getHeight();

                if (row.isRelative()) {
                    rowHeightsLocal[i] = -rowHeight;
                    totalRelativeWeight += rowHeight;
                } else {
                    if (rowHeight < 0) {
                        // Default height row; we must calculate the height
                        rowHeight = getPreferredRowHeight(i, columnWidthsArgument);
                        defaultHeightRows[i] = true;
                    }

                    rowHeightsLocal[i] = rowHeight;
                    reservedHeight += rowHeight;
                }

                visibleRowCount++;
            } else {
                rowHeightsLocal[i] = 0;
            }
        }

        if (visibleRowCount > 1) {
            reservedHeight += (visibleRowCount - 1) * verticalSpacing;
        }

        // Next, we we account for default-width columns containing spanning
        // cells, which have been ignored thus far. We ensure that the sum of
        // the widths of the spanned cells is enough to satisfy the preferred
        // width of the spanning content.

        for (int i = 0; i < rowCount; i++) {
            TablePane.Row row = rows.get(i);

            for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
                Component component = row.get(j);

                if (component != null && component.isVisible()) {
                    int rowSpan = TablePane.getRowSpan(component);

                    if (rowSpan > 1) {
                        // We might need to adjust row heights to accommodate
                        // this spanning cell. First, we find out if any of the
                        // spanned cells are default height and how much space
                        // we've allocated thus far for those cells

                        boolean adjustCells = true;
                        int spannedDefaultHeightCellCount = 0;
                        int spannedHeight = 0;

                        for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
                            if (rowHeightsLocal[i + k] < 0) {
                                adjustCells = false;
                                break;
                            }

                            if (defaultHeightRows[i + k]) {
                                spannedDefaultHeightCellCount++;
                            }

                            spannedHeight += rowHeightsLocal[i + k];
                        }

                        // If we span any relative-height rows, we assume
                        // that we'll achieve the desired spanning height when
                        // we divvy up the remaining space, so there's no need
                        // to make an adjustment here. This assumption is safe
                        // because our preferred height policy is to *either*
                        // divide the adjustment among the relative-height
                        // rows *or* among the default-height rows if we
                        // don't span any relative-height rows

                        if (adjustCells && spannedDefaultHeightCellCount > 0) {
                            int componentPreferredHeight = component.getPreferredHeight(columnWidthsArgument[j]);

                            if (componentPreferredHeight > spannedHeight) {
                                // The component's preferred height is larger
                                // than the height we've allocated thus far, so
                                // an adjustment is necessary
                                int adjustment = componentPreferredHeight - spannedHeight;

                                // We'll distribute the adjustment evenly
                                // among the default-height rows
                                for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
                                    if (defaultHeightRows[i + k]) {
                                        int rowAdjustment = adjustment
                                            / spannedDefaultHeightCellCount;

                                        rowHeightsLocal[i + k] += rowAdjustment;
                                        reservedHeight += rowAdjustment;

                                        // Adjust these to avoid rounding errors
                                        adjustment -= rowAdjustment;
                                        spannedDefaultHeightCellCount--;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        // Finally, we allocate the heights of the relative rows by divvying
        // up the remaining height

        int remainingHeight = height - reservedHeight;
        if (totalRelativeWeight > 0 && remainingHeight > 0) {
            for (int i = 0; i < rowCount; i++) {
                if (rowHeightsLocal[i] < 0) {
                    int relativeWeight = -rowHeightsLocal[i];
                    float weightPercentage = relativeWeight / (float) totalRelativeWeight;
                    int rowHeight = (int) (remainingHeight * weightPercentage);

                    rowHeightsLocal[i] = rowHeight;

                    // NOTE we adjust remainingHeight and totalRelativeWeight as
                    // we
                    // go to avoid potential rounding errors in the rowHeight
                    // calculation
                    remainingHeight -= rowHeight;
                    totalRelativeWeight -= relativeWeight;
                }
            }
        }

        // If we have don't actually have enough height available

        boolean progress = true; // prevent infinite loop
        while (remainingHeight < 0 && progress) {
            progress = false;
            for (int i = 0; i < rowCount; i++) {
                if (isRowVisible(i)) {
                    TablePane.Row row = rows.get(i);
                    if (!row.isRelative()) {
                        if (rowHeightsLocal[i] > 0) {
                            rowHeightsLocal[i]--;
                            remainingHeight++;
                            progress = true;
                            if (remainingHeight >= 0) {
                                break;
                            }
                        }
                    }
                }
            }
        }

        return rowHeightsLocal;
    }

    // TablePane.Skin methods

    @Override
    public int getRowAt(int y) {
        if (rowHeights == null) {
            return -1;
        }

        int rowIndex = -1;

        for (int i = 0, rowY = padding.top; rowY <= y && i < rowHeights.length; i++) {
            int rowHeight = rowHeights[i];

            if (y < rowY + rowHeight) {
                rowIndex = i;
                break;
            }

            rowY += rowHeight + verticalSpacing;
        }

        return rowIndex;
    }

    @Override
    public Bounds getRowBounds(int row) {
        if (rowHeights == null) {
            return new Bounds(0, 0, 0, 0);
        }

        if (row < 0 || row >= rowHeights.length) {
            throw new IndexOutOfBoundsException(String.valueOf(row));
        }

        int rowY = padding.top;

        for (int i = 0; i < row; i++) {
            rowY += rowHeights[i] + verticalSpacing;
        }

        return new Bounds(0, rowY, getWidth(), rowHeights[row]);
    }

    @Override
    public int getColumnAt(int x) {
        if (columnWidths == null) {
            return -1;
        }

        int columnIndex = -1;

        for (int j = 0, columnX = padding.left; columnX <= x && j < columnWidths.length; j++) {
            int columnWidth = columnWidths[j];

            if (x < columnX + columnWidth) {
                columnIndex = j;
                break;
            }

            columnX += columnWidth + horizontalSpacing;
        }

        return columnIndex;
    }

    @Override
    public Bounds getColumnBounds(int column) {
        if (columnWidths == null) {
            return new Bounds(0, 0, 0, 0);
        }

        if (column < 0 || column >= columnWidths.length) {
            throw new IndexOutOfBoundsException(String.valueOf(column));
        }

        int columnX = padding.left;

        for (int j = 0; j < column; j++) {
            columnX += columnWidths[j] + horizontalSpacing;
        }

        return new Bounds(columnX, 0, columnWidths[column], getHeight());
    }

    // TablePaneListener methods

    @Override
    public void rowInserted(TablePane tablePane, int index) {
        invalidateComponent();
    }

    @Override
    public void rowsRemoved(TablePane tablePane, int index, Sequence<TablePane.Row> rows) {
        invalidateComponent();
    }

    @Override
    public void rowHeightChanged(TablePane.Row row, int previousHeight, boolean previousRelative) {
        invalidateComponent();
    }

    @Override
    public void rowHighlightedChanged(TablePane.Row row) {
        TablePane tablePane = row.getTablePane();
        repaintComponent(getRowBounds(tablePane.getRows().indexOf(row)));
    }

    @Override
    public void columnInserted(TablePane tablePane, int index) {
        invalidateComponent();
    }

    @Override
    public void columnsRemoved(TablePane tablePane, int index, Sequence<TablePane.Column> columns) {
        invalidateComponent();
    }

    @Override
    public void columnWidthChanged(TablePane.Column column, int previousWidth,
        boolean previousRelative) {
        invalidateComponent();
    }

    @Override
    public void columnHighlightedChanged(TablePane.Column column) {
        TablePane tablePane = column.getTablePane();
        repaintComponent(getColumnBounds(tablePane.getColumns().indexOf(column)));
    }

    @Override
    public void cellInserted(TablePane.Row row, int column) {
        invalidateComponent();
    }

    @Override
    public void cellsRemoved(TablePane.Row row, int column, Sequence<Component> removed) {
        invalidateComponent();
    }

    @Override
    public void cellUpdated(TablePane.Row row, int column, Component previousComponent) {
        invalidateComponent();
    }

    // TablePaneAttribute events

    @Override
    public void rowSpanChanged(TablePane tablePane, Component component, int previousRowSpan) {
        invalidateComponent();
    }

    @Override
    public void columnSpanChanged(TablePane tablePane, Component component, int previousColumnSpan) {
        invalidateComponent();
    }
}
