org.openelis.ui.widget.table.StaticView.java Source code

Java tutorial

Introduction

Here is the source code for org.openelis.ui.widget.table.StaticView.java

Source

/**
 * Exhibit A - UIRF Open-source Based Public Software License.
 * 
 * The contents of this file are subject to the UIRF Open-source Based Public
 * Software License(the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * openelis.uhl.uiowa.edu
 * 
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 * 
 * The Original Code is OpenELIS code.
 * 
 * The Initial Developer of the Original Code is The University of Iowa.
 * Portions created by The University of Iowa are Copyright 2006-2008. All
 * Rights Reserved.
 * 
 * Contributor(s): ______________________________________.
 * 
 * Alternatively, the contents of this file marked "Separately-Licensed" may be
 * used under the terms of a UIRF Software license ("UIRF Software License"), in
 * which case the provisions of a UIRF Software License are applicable instead
 * of those above.
 */
package org.openelis.ui.widget.table;

import java.util.ArrayList;
import java.util.HashMap;

import org.openelis.ui.common.data.QueryData;
import org.openelis.ui.resources.MenuCSS;
import org.openelis.ui.resources.TableCSS;
import org.openelis.ui.resources.UIResources;
import org.openelis.ui.widget.Button;
import org.openelis.ui.widget.CSSUtils;
import org.openelis.ui.widget.CheckMenuItem;
import org.openelis.ui.widget.DragItem;
import org.openelis.ui.widget.Balloon;
import org.openelis.ui.widget.PopupMenuPanel;
import org.openelis.ui.widget.table.event.CellMouseOutEvent;
import org.openelis.ui.widget.table.event.CellMouseOverEvent;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.NativeVerticalScrollbar;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;

/**
 * Composite GWT widget to draw and handle logic for displaying a Table. All
 * methods are protected and only used by the Table widget itself.
 * 
 * @author tschmidt
 * 
 */
public class StaticView extends ViewInt {
    @UiTemplate("staticView.ui.xml")
    interface ViewUiBinder extends UiBinder<Widget, StaticView> {
    };

    public static final ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class);

    /**
     * Reference to Table this View is used in
     */
    protected Table table;

    /**
     * Table used to draw Table flexTable
     */
    @UiField
    protected FlexTable flexTable;

    /**
     * Table used to draw Header flexTable for the table
     */
    @UiField(provided = true)
    protected Header header;

    @UiField
    protected FocusPanel menu;

    // @UiField 
    // protected Grid                   menuGrid;

    /**
     * Scrollable area that contains flexTable and possibly header for
     * horizontal scroll.
     */
    @UiField
    protected ScrollPanel scrollView;

    @UiField
    protected LayoutPanel outer, inner;

    /**
     * Flag used to determine if the table has been attached to know when to do
     * layout for the first time.
     */
    protected boolean attached, sized;

    /**
     * Container to hold the widget for formatting and spacing
     */
    private Container container;

    protected TableCSS css;
    protected MenuCSS menuCss;

    protected StaticView source = this;

    /**
     * Constructor that takes a reference to the table that will use this view
     * 
     * @param tree
     */
    public StaticView(Table tbl) {
        header = GWT.create(Header.class);
        header.init(tbl);

        initWidget(uiBinder.createAndBindUi(this));

        this.table = tbl;

        setCSS(UIResources.INSTANCE.table());

        menuCss = UIResources.INSTANCE.menuCss();
        menuCss.ensureInjected();

        container = new Container();
        container.setStyleName(css.CellContainer());

        scrollView.addScrollHandler(new ScrollHandler() {
            @Override
            public void onScroll(ScrollEvent event) {
                alignHeader();
            }
        });

        flexTable.addCellMouseOutHandler(new CellMouseOutEvent.Handler() {

            @Override
            public void onCellMouseOut(CellMouseOutEvent event) {
                if (table.balloonTimer != null)
                    table.balloonTimer.cancel();
                Balloon.hide();
            }
        });

        menu.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                final PopupMenuPanel panel = new PopupMenuPanel();
                panel.setStyleName(menuCss.MenuPanel());
                for (int i = 0; i < table.getColumnCount(); i++) {
                    CheckMenuItem item = new CheckMenuItem(table.getColumnAt(i).label, "", false);
                    item.setCheck(table.getColumnAt(i).isDisplayed());
                    item.setEnabled(true);
                    panel.addItem(item);
                }
                panel.setPopupPosition(menu.getAbsoluteLeft(), menu.getAbsoluteTop());
                panel.show();
                panel.getElement().getStyle().setZIndex(1000);
                panel.addCloseHandler(new CloseHandler<PopupPanel>() {
                    public void onClose(CloseEvent<PopupPanel> event) {
                        for (int i = 0; i < table.getColumnCount(); i++) {
                            CheckMenuItem item = (CheckMenuItem) panel.getWidget(i);
                            if (item.isChecked() != table.getColumnAt(i).isDisplayed()) {
                                table.getColumnAt(i).setDisplay(item.isChecked());
                            }
                        }
                    }
                });
            }
        });
    }

    @UiHandler("flexTable")
    protected void handleDoubleClick(DoubleClickEvent event) {
        int r, c;

        // if x < 0 the user moused out of table before letting up button
        // ignore event in this case
        if (event.getClientX() < 0)
            return;

        r = flexTable.getRowForEvent(event.getNativeEvent());
        c = flexTable.getColForEvent(event.getNativeEvent());

        table.fireCellDoubleClickedEvent(r, c);
    }

    @UiHandler("flexTable")
    protected void cellClick(ClickEvent event) {
        int r, c;

        // if x < 0 the user moused out of table before letting up button
        // ignore event in this case
        if (event.getClientX() < 0)
            return;

        r = flexTable.getRowForEvent(event.getNativeEvent());
        c = flexTable.getColForEvent(event.getNativeEvent());

        // chrome does not return -x if moused out while holding button
        // but does return negative col index
        if (r < 0 || c < 0)
            return;

        if (table.fireCellClickedEvent(r, c, event.isControlKeyDown(), event.isShiftKeyDown()))
            table.startEditing(r, c, event.getNativeEvent());
    }

    /**
     * Method that will layout the table view and is called on first time
     * attached and when attributes affecting layout are changed in the table
     */
    protected void layout() {

        Node colgroup;

        /*
         * If View is not attached to DOM yet get out. onAttach will call
         * layout() the first time this widget attached.
         */

        if (!attached)
            return;

        colgroup = flexTable.getElement().getElementsByTagName("colgroup").getItem(0);

        if (colgroup != null) {
            while (colgroup.getChildCount() > table.getColumnCount())
                colgroup.removeChild(colgroup.getChild(0));
        }

        for (int c = 0; c < table.getColumnCount(); c++) {
            flexTable.getColumnFormatter().setWidth(c, table.getColumnAt(c).getWidth() + "px");
            if (table.getColumnAt(c).getStyle() != null)
                flexTable.getColumnFormatter().setStyleName(c, table.getColumnAt(c).getStyle());
        }

        flexTable.setWidth(table.getTotalColumnWidth() + "px");
        flexTable.setHeight("1px");
        DOM.setStyleAttribute(flexTable.getElement(), "backgroundColor", "transparent");

        // ********** Create and attach Header **************
        if (table.hasHeader()) {
            UIObject.setVisible(inner.getWidgetContainerElement(header), true);
            header.setVisible(true);
            header.layout();
            outer.setWidgetTopBottom(scrollView, CSSUtils.getHeight(header), Unit.PX, 0, Unit.PX);
            alignHeader();
        } else {
            UIObject.setVisible(inner.getWidgetContainerElement(header), false);
            header.setVisible(false);
            outer.setWidgetTopBottom(scrollView, 0, Unit.PX, 0, Unit.PX);
        }

        if (table.hasHeader && table.hasMenu()) {
            UIObject.setVisible(inner.getWidgetContainerElement(menu), true);
            menu.setVisible(true);
            menu.setHeight(header.getOffsetHeight() - 2 + "px");

        } else {
            UIObject.setVisible(inner.getWidgetContainerElement(menu), false);
            menu.setVisible(false);
        }
    }

    protected void alignHeader() {
        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                DOM.setStyleAttribute(header.getElement(), "left",
                        (0 - scrollView.getHorizontalScrollPosition()) + "px");
            }
        });
    }

    /**
     * This method is called when a column width is changed. It will resize the
     * columns to there currently set width.
     */
    protected void resize() {

        for (int c = 0; c < table.getColumnCount(); c++)
            flexTable.getColumnFormatter().setWidth(c, table.getColumnAt(c).getWidth() + "px");
        flexTable.setWidth(table.getTotalColumnWidth() + "px");
    }

    /**
     * Will create the the necessary visible rows for the flexTable table
     * depending on what is needed at the time. If model.size() < visibleRows
     * then the number of rows created will equal model.size() else the number
     * visibleRows will be created for the flexTable table.
     */
    protected void createRow(int rc) {
        flexTable.insertRow(rc);
        flexTable.getRowFormatter().getElement(rc).setAttribute("height", (table.getRowHeight() + 3) + "px");
        flexTable.getRowFormatter().getElement(rc).setAttribute("index", "" + rc);

        if (table.getDragController() != null)
            table.dragController.makeDraggable(new DragItem(table, flexTable.getRowFormatter().getElement(rc)));
    }

    /**
     * This method will redraw the table from the startRow to the endRow that
     * are passed in as params. Rows are passed as -1,-1 the entire view will be
     * drawn.
     * 
     * @param smr
     * @param emr
     */
    protected void renderView(int smr, int emr) {
        int r, startMax;

        table.finishEditing();

        if (smr < 0)
            smr = 0;

        if (emr < 0)
            emr = table.getRowCount() - 1;

        startMax = scrollView.getMaximumVerticalScrollPosition();

        /*
         * Create/Load Rows in the flexTable table
         */
        for (r = smr; r <= emr; r++) {
            /*
             * Create table row if needed
             */
            if (r >= flexTable.getRowCount()) {
                createRow(flexTable.getRowCount());
                /*
                 * ColumnFormatter is not available until first row is inserted
                 * so call resize after that
                 */
                if (r == 0)
                    resize();
            }

            for (int c = 0; c < table.getColumnCount(); c++)
                renderCell(r, c);

            applyRowStyle(r);
        }

        while (flexTable.getRowCount() > table.getRowCount())
            flexTable.removeRow(table.getRowCount());

        adjustForScroll(startMax);

        if (!table.fixScrollBar && !sized) {
            Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
                @Override
                public void execute() {
                    if (flexTable.getOffsetHeight() < scrollView.getOffsetHeight())
                        table.getParent().setHeight(CSSUtils.getHeight(flexTable) + "px");
                    sized = true;
                }

            });
        }
    }

    protected void bulkRender() {
        CellRenderer renderer;
        String style;

        SafeHtmlBuilder tb = new SafeHtmlBuilder();

        for (int i = 0; i < table.getRowCount(); i++) {
            style = table.getRowAt(i).getStyle(i);
            tb.appendHtmlConstant("<tr height='" + (table.getRowHeight() + 3) + "px' index='" + i + "'"
                    + (style != null ? " class='" + style + "'>" : ">"));
            for (int j = 0; j < table.getColumnCount(); j++) {
                renderer = table.getColumnAt(j).getCellRenderer();
                if (table.getColumnAt(j).display)
                    tb.appendHtmlConstant("<td>");
                else
                    tb.appendHtmlConstant("<td style=\"display : none;\">)");
                tb.append(renderer.bulkRender(table.getValueAt(i, j)));
                tb.appendHtmlConstant("</td>");
            }
            tb.appendHtmlConstant("</tr>");
        }

        // this is in a try catch only to get by for unit testing
        try {
            flexTable.getElement().getElementsByTagName("tbody").getItem(0).setInnerSafeHtml(tb.toSafeHtml());
        } catch (Exception e) {
        }

        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                adjustForScroll(0);
            }
        });

    }

    protected void addRow(int r) {
        int startMax = scrollView.getMaximumVerticalScrollPosition();

        createRow(r);

        for (int c = 0; c < table.getColumnCount(); c++)
            renderCell(r, c);

        applyRowStyle(r);

        adjustForScroll(startMax);

    }

    protected void addColumn(int c) {
        for (int i = 0; i < flexTable.getRowCount(); i++) {
            flexTable.insertCell(i, c);
        }
        layout();
        for (int i = 0; i < flexTable.getRowCount(); i++) {
            renderCell(i, c);
        }
    }

    protected void removeColumn(int c) {

        for (int i = 0; i < flexTable.getRowCount(); i++) {
            flexTable.removeCell(i, c);
        }

        layout();
    }

    protected void removeRow(int r) {
        int startMax = scrollView.getMaximumVerticalScrollPosition();

        flexTable.removeRow(r);

        adjustForScroll(startMax);
    }

    protected void removeAllRows() {
        flexTable.removeAllRows();
    }

    protected void renderSelections(int start, int end) {

        for (int r = start; r <= end; r++) {
            if (table.isRowSelected(r))
                flexTable.getRowFormatter().addStyleName(r, css.Selection());
            else
                flexTable.getRowFormatter().removeStyleName(r, css.Selection());
        }

    }

    protected void renderExceptions(int start, int end) {
        start = start < 0 ? 0 : start;
        end = end < 0 ? flexTable.getRowCount() - 1 : end;

        for (int r = start; r <= end; r++) {
            for (int c = 0; c < table.getColumnCount(); c++) {
                if (table.hasExceptions(r, c)) {
                    flexTable.getCellFormatter().addStyleName(r, c,
                            Balloon.isWarning(table.getEndUserExceptions(r, c), table.getValidateExceptions(r, c))
                                    ? css.InputWarning()
                                    : css.InputError());
                    flexTable.addCellMouseOverHandler(new CellMouseOverEvent.Handler(r, c) {

                        @Override
                        public void onCellMouseOver(CellMouseOverEvent event) {
                            table.drawExceptions(event.getRow(), event.getCol(), event.getX(), event.getY());
                        }

                    });
                } else {
                    flexTable.getCellFormatter().removeStyleName(r, c, css.InputWarning());
                    flexTable.getCellFormatter().removeStyleName(r, c, css.InputError());
                    flexTable.removeHandler(r, c);
                }

                flexTable.getCellFormatter().setVisible(r, c, table.getColumnAt(c).isDisplayed());
            }
        }
    }

    /**
     * This method will apply either a style that is set in the Row getStyle
     * method or the selection style if the row is selected
     */
    protected void applyRowStyle(int r) {
        String style;

        if (r >= table.getRowCount())
            return;

        style = table.getRowAt(r).getStyle(r);
        if (style != null)
            flexTable.getRowFormatter().setStyleName(r, style);
        else
            flexTable.getRowFormatter().setStyleName(r, "");

        if (table.isRowSelected(r))
            flexTable.getRowFormatter().addStyleName(r, css.Selection());
        else
            flexTable.getRowFormatter().removeStyleName(r, css.Selection());
    }

    /**
     * Applies the selection style to a table row
     * 
     * @param r
     */
    protected void applySelectionStyle(int r) {
        int rc;

        rc = r;
        if (rc > -1)
            flexTable.getRowFormatter().addStyleName(rc, css.Selection());

    }

    /**
     * Removes the Selection style from a table row
     * 
     * @param r
     */
    protected void applyUnselectionStyle(int r) {
        int rc;

        rc = r;
        if (rc > -1)
            flexTable.getRowFormatter().removeStyleName(rc, css.Selection());

    }

    protected void renderCell(int r, int c) {
        CellRenderer renderer;

        renderer = table.getColumnAt(c).getCellRenderer();

        if (table.getQueryMode())
            renderer.renderQuery(flexTable, r, c, (QueryData) table.getValueAt(r, c));
        else
            renderer.render(flexTable, r, c, table.getValueAt(r, c));

        if (table.hasExceptions(r, c)) {
            flexTable.getCellFormatter().addStyleName(r, c,
                    Balloon.isWarning(table.getEndUserExceptions(r, c), table.getValidateExceptions(r, c))
                            ? css.InputWarning()
                            : css.InputError());
            flexTable.addCellMouseOverHandler(new CellMouseOverEvent.Handler(r, c) {
                @Override
                public void onCellMouseOver(CellMouseOverEvent event) {
                    int x, y;
                    Element td = flexTable.getCellFormatter().getElement(event.getRow(), event.getCol());

                    y = td.getAbsoluteTop();
                    x = td.getAbsoluteLeft() + (td.getOffsetWidth() / 2);
                    table.drawExceptions(event.getRow(), event.getCol(), x, y);
                }

            });
        } else {
            flexTable.getCellFormatter().removeStyleName(r, c, css.InputError());
            flexTable.getCellFormatter().removeStyleName(r, c, css.InputWarning());
            flexTable.removeHandler(r, c);
        }

        flexTable.getCellFormatter().setVisible(r, c, table.getColumnAt(c).isDisplayed());
    }

    protected void setColumnDisplay(int c, boolean display) {
        table.computeColumnsWidth();
        header.flexTable.getColumnFormatter().getElement(c).getStyle().setDisplay(Display.NONE);
        header.layout();
        flexTable.getColumnFormatter().getElement(c).getStyle().setDisplay(Display.NONE);
        for (int r = 0; r < flexTable.getRowCount(); r++) {
            flexTable.getCellFormatter().setVisible(r, c, display);
        }
        table.resize();
    }

    protected void bulkExceptions(HashMap<Row, HashMap<Integer, ArrayList<Exception>>> exceptions) {
        for (Row row : exceptions.keySet()) {
            int r = table.convertModelIndexToView(table.getModel().indexOf(row));
            for (int c : exceptions.get(row).keySet()) {
                flexTable.getCellFormatter().addStyleName(r, c,
                        Balloon.isWarning(table.getEndUserExceptions(r, c), table.getValidateExceptions(r, c))
                                ? css.InputWarning()
                                : css.InputError());
                flexTable.addCellMouseOverHandler(new CellMouseOverEvent.Handler(r, c) {
                    @Override
                    public void onCellMouseOver(CellMouseOverEvent event) {
                        table.drawExceptions(event.getRow(), event.getCol(), event.getX(), event.getY());
                    }

                });
            }
        }
    }

    /**
     * Will put the passed cell into edit mode making sure the the cell is
     * compeltely visible first
     * 
     * @param r
     * @param c
     * @param value
     * @param event
     */
    protected void startEditing(final int r, final int c, Object value, NativeEvent event) {
        container.setWidth((table.getColumnAt(c).getWidth() - 3));
        container.setHeight((table.getRowHeight()));
        flexTable.setWidget(r, c, container);

        if (table.getQueryMode())
            table.getColumnAt(c).getCellEditor().startEditingQuery((QueryData) table.getValueAt(r, c), container,
                    event);
        else
            table.getColumnAt(c).getCellEditor().startEditing(table.getValueAt(r, c), container, event);
    }

    /**
     * Returns the value of the CellEditor
     * 
     * @param r
     * @param c
     * @return
     */
    protected Object finishEditing(int r, int c) {
        CellEditor cellEditor;

        cellEditor = table.getColumnAt(c).getCellEditor();

        return cellEditor.finishEditing();
    }

    /**
     * This method will re-adjust the scrollbar height based on number of rows
     * in the model
     */
    protected void adjustScrollBarHeight() {

    }

    /**
     * Method will scroll the table to make sure the passed row is included in
     * the view
     * 
     * @param r
     * @return
     */
    protected boolean scrollToVisible(int r) {

        if (scrollView.getMaximumVerticalScrollPosition() == 0)
            return false;

        if (isRowVisible(r))
            return false;

        int hPos = scrollView.getHorizontalScrollPosition();

        DOM.scrollIntoView(flexTable.getRowFormatter().getElement(r));

        scrollView.setHorizontalScrollPosition(hPos);

        return true;
    }

    /**
     * Method will scroll the view up or down by the passed number of rows. Pass
     * negative value to scroll up.
     * 
     * @param n
     */
    protected void scrollBy(int n) {

    }

    /**
     * Returns true if the passed row is drawn in the current view
     * 
     * @param r
     * @return
     */
    protected boolean isRowVisible(int r) {
        Element row = flexTable.getRowFormatter().getElement(r);
        int top = row.getOffsetTop();
        int height = row.getOffsetHeight();

        return top >= scrollView.getVerticalScrollPosition()
                && ((top + height) <= scrollView.getVerticalScrollPosition() + CSSUtils.getHeight(scrollView));
    }

    /**
     * Method is overridden from Composite so that layout() can be deferred
     * until it is attached to the DOM
     */
    @Override
    protected void onAttach() {

        super.onAttach();

        if (attached)
            return;

        attached = true;
        layout();
        flexTable.setVisible(false);
        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {

            @Override
            public void execute() {
                flexTable.setVisible(true);
                Element svEl = outer.getWidgetContainerElement(scrollView);

                if (scrollView.getMaximumVerticalScrollPosition() == 0)
                    table.setWidth(CSSUtils.getWidth(svEl) - 1);
                else
                    table.setWidth(CSSUtils.getWidth(svEl) - NativeVerticalScrollbar.getNativeScrollbarWidth() - 1);

                if (CSSUtils.getWidth((svEl)) > 0) {
                    table.setWidth(CSSUtils.getWidth(svEl) - 1);
                    scrollView.setWidth(
                            CSSUtils.getWidth(svEl) - CSSUtils.getAddedBorderWidth(table.getElement()) + "px");
                }

                if (CSSUtils.getHeight(svEl) > 0) {
                    scrollView.setHeight(CSSUtils.getHeight(svEl) - CSSUtils.getHeight(header)
                            - CSSUtils.getAddedBorderHeight(table.getElement()) + "px");

                }
            }
        });

    }

    /**
     * Returns the Header for this view
     * 
     * @return
     */
    protected Header getHeader() {
        return header;
    }

    /**
     * Returns the actual drawn row height on the screen
     */
    protected int getRowHeight() {
        return table.rowHeight;
    }

    public void setCSS(TableCSS css) {
        css.ensureInjected();

        for (int i = 0; i < flexTable.getRowCount(); i++) {
            if (flexTable.getRowFormatter().getStyleName(i).contains(this.css.Selection())) {
                flexTable.getRowFormatter().removeStyleName(i, this.css.Selection());
                flexTable.getRowFormatter().addStyleName(i, css.Selection());
            }
            for (int j = 0; j < flexTable.getCellCount(i); j++) {
                if (flexTable.getCellFormatter().getStyleName(i, j).contains(this.css.InputError())) {
                    flexTable.getCellFormatter().removeStyleName(i, j, this.css.InputError());
                    flexTable.getCellFormatter().addStyleName(i, j, css.InputError());
                }
                if (flexTable.getCellFormatter().getStyleName(i, j).contains(this.css.InputWarning())) {
                    flexTable.getCellFormatter().removeStyleName(i, j, this.css.InputWarning());
                    flexTable.getCellFormatter().addStyleName(i, j, css.InputWarning());
                }
            }
        }

        this.css = css;

        flexTable.setStyleName(css.Table());

    }

    @Override
    protected int rowHeight() {
        return 0;
    }

    @Override
    FlexTable table() {
        return flexTable;
    }

    @Override
    ScrollPanel scrollView() {
        return scrollView;
    }

    @Override
    TableCSS css() {
        return css;
    }

    @Override
    public void onResize() {
        super.onResize();

        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {

            @Override
            public void execute() {
                Element svEl = outer.getWidgetContainerElement(scrollView);

                if (CSSUtils.getWidth(svEl) > 0) {

                    scrollView.setWidth(
                            CSSUtils.getWidth(svEl) - CSSUtils.getAddedBorderWidth(table.getElement()) + "px");

                    if (CSSUtils.getHeight(outer) > 0) {
                        int height = CSSUtils.getHeight(outer) - CSSUtils.getHeight(header)
                                - CSSUtils.getAddedBorderHeight(table.getElement());
                        /*
                         * This check is here only for Unit Testing.  If not done Unit test on the
                         * table will fail here with assertion check from the widget.
                         */
                        if (height > 0)
                            scrollView.setHeight(height + "px");
                    }

                    if (scrollView.getMaximumVerticalScrollPosition() == 0)
                        table.setWidth(CSSUtils.getWidth(svEl) - 1);
                    else
                        table.setWidth(CSSUtils.getWidth(svEl) -

                                NativeVerticalScrollbar.getNativeScrollbarWidth() - 1);

                    adjustForScroll(0);

                }

            }
        });

    }

    private void adjustForScroll(int before) {
        if (before == 0 && scrollView.getMaximumVerticalScrollPosition() > 0)
            table.setWidth((table.getOffsetWidth() - NativeVerticalScrollbar.getNativeScrollbarWidth() - 1) + "px");
        else if (before > 0 && scrollView.getMaximumVerticalScrollPosition() == 0)
            table.setWidth(table.getOffsetWidth() - 1 + "px");
    }

    /*
     * This public method added for unit testing 
     */
    public String getCellDisplay(int row, int col) {
        return flexTable.getText(row, col);
    }

    public Widget getCellWidget(int row, int col) {
        Widget wid;

        wid = flexTable.getWidget(row, col);

        if (wid == container)
            return container.editor;

        return wid;

    }

}