package com.eas.grid;
import java.util.ArrayList;
import java.util.List;
import com.eas.core.XElement;
import com.eas.grid.builders.NullHeaderOrFooterBuilder;
import com.eas.grid.builders.ThemedHeaderOrFooterBuilder;
import com.eas.grid.columns.ModelColumn;
import com.eas.grid.columns.header.HasSortList;
import com.eas.grid.columns.header.HeaderNode;
import com.eas.menu.MenuItemCheckBox;
import com.eas.menu.PlatypusPopupMenu;
import com.eas.ui.PublishedColor;
import com.eas.ui.XDataTransfer;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.StyleElement;
import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DragEndEvent;
import com.google.gwt.event.dom.client.DragEndHandler;
import com.google.gwt.event.dom.client.DragEnterEvent;
import com.google.gwt.event.dom.client.DragEnterHandler;
import com.google.gwt.event.dom.client.DragEvent;
import com.google.gwt.event.dom.client.DragHandler;
import com.google.gwt.event.dom.client.DragLeaveEvent;
import com.google.gwt.event.dom.client.DragLeaveHandler;
import com.google.gwt.event.dom.client.DragOverEvent;
import com.google.gwt.event.dom.client.DragOverHandler;
import com.google.gwt.event.dom.client.DropEvent;
import com.google.gwt.event.dom.client.DropHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.cellview.client.AbstractCellTable;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent;
import com.google.gwt.user.cellview.client.ColumnSortList;
import com.google.gwt.user.cellview.client.Header;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.ProvidesResize;
import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.SetSelectionModel;
/**
*
* @author mg
* @param <T>
*/
public abstract class Grid<T> extends SimplePanel implements ProvidesResize, RequiresResize, HasSortList, Focusable {
protected interface DynamicCellStyles extends SafeHtmlTemplates {
public static DynamicCellStyles INSTANCE = GWT.create(DynamicCellStyles.class);
@Template(".{0}{" + "border-style: solid;" + "border-top-width: {1}px;" + "border-bottom-width: {1}px;"
+ "border-left-width: {2}px;" + "border-right-width: {2}px;" + "border-color: {3};}")
public SafeHtml td(String aCssRuleName, double hBorderWidth, double vBorderWidth, String aLinesColor);
@Template(".{0}{" + "position: relative; white-space: nowrap; height: {1}px;}")
public SafeHtml cell(String aCssRuleName, double aRowsHeight);
}
public static final String GRID_SHELL_STYLE = "grid-shell";
public static final String RULER_STYLE = "grid-ruler";
public static final String COLUMN_PHANTOM_STYLE = "grid-column-phantom";
public static final String COLUMNS_CHEVRON_STYLE = "grid-columns-chevron";
public static final int MINIMUM_COLUMN_WIDTH = 15;
//
protected FlexTable hive;
protected SimplePanel headerLeftContainer;
protected GridSection<T> headerLeft;
protected SimplePanel headerRightContainer;
protected GridSection<T> headerRight;
protected SimplePanel frozenLeftContainer;
protected GridSection<T> frozenLeft;
protected SimplePanel frozenRightContainer;
protected GridSection<T> frozenRight;
protected SimplePanel scrollableLeftContainer;
protected GridSection<T> scrollableLeft;
protected ScrollPanel scrollableRightContainer;
protected GridSection<T> scrollableRight;
protected SimplePanel footerLeftContainer;
protected GridSection<T> footerLeft;
protected ScrollPanel footerRightContainer;
protected GridSection<T> footerRight;
//
protected HTML columnsChevron = new HTML();
//
protected final ColumnSortList sortList = new ColumnSortList();
protected int rowsHeight;
protected boolean showHorizontalLines = true;
protected boolean showVerticalLines = true;
protected boolean showOddRowsInOtherColor = true;
protected PublishedColor gridColor;
protected PublishedColor oddRowsColor = PublishedColor.create(241, 241, 241, 255);
protected String dynamicTDClassName = "grid-td-" + Document.get().createUniqueId();
protected String dynamicCellClassName = "grid-cell-" + Document.get().createUniqueId();
protected String dynamicOddRowsClassName = "grid-odd-row-" + Document.get().createUniqueId();
protected String dynamicEvenRowsClassName = "grid-even-row-" + Document.get().createUniqueId();
protected StyleElement tdsStyleElement = Document.get().createStyleElement();
protected StyleElement cellsStyleElement = Document.get().createStyleElement();
protected StyleElement oddRowsStyleElement = Document.get().createStyleElement();
protected StyleElement evenRowsStyleElement = Document.get().createStyleElement();
protected ListDataProvider<T> dataProvider;
protected int frozenColumns;
protected int frozenRows;
public Grid(ProvidesKey<T> aKeyProvider) {
super();
getElement().getStyle().setPosition(Style.Position.RELATIVE);
getElement().appendChild(tdsStyleElement);
getElement().appendChild(cellsStyleElement);
getElement().appendChild(oddRowsStyleElement);
getElement().appendChild(evenRowsStyleElement);
setRowsHeight(30);
hive = new FlexTable();
setWidget(hive);
hive.setCellPadding(0);
hive.setCellSpacing(0);
hive.setBorderWidth(0);
headerLeft = new GridSection<T>(aKeyProvider);
headerLeftContainer = new ScrollPanel(headerLeft);
headerRight = new GridSection<T>(aKeyProvider);
headerRightContainer = new ScrollPanel(headerRight);
frozenLeft = new GridSection<T>(aKeyProvider) {
@Override
protected void replaceAllChildren(List<T> values, SafeHtml html) {
super.replaceAllChildren(values, html);
footerLeft.redrawFooters();
frozenLeftRendered();
}
@Override
protected void replaceChildren(List<T> values, int start, SafeHtml html) {
super.replaceChildren(values, start, html);
footerLeft.redrawFooters();
frozenLeftRendered();
}
@Override
protected void onFocus() {
super.onFocus();
Element focused = getKeyboardSelectedElement();
if (focused != null)
focused.setTabIndex(tabIndex);
FocusEvent.fireNativeEvent(Document.get().createFocusEvent(), Grid.this);
}
@Override
protected void onBlur() {
super.onBlur();
FocusEvent.fireNativeEvent(Document.get().createBlurEvent(), Grid.this);
}
};
frozenLeftContainer = new ScrollPanel(frozenLeft);
frozenRight = new GridSection<T>(aKeyProvider) {
@Override
protected void replaceAllChildren(List<T> values, SafeHtml html) {
super.replaceAllChildren(values, html);
footerRight.redrawFooters();
frozenRightRendered();
}
@Override
protected void replaceChildren(List<T> values, int start, SafeHtml html) {
super.replaceChildren(values, start, html);
footerRight.redrawFooters();
frozenRightRendered();
}
@Override
protected void onFocus() {
super.onFocus();
Element focused = getKeyboardSelectedElement();
if (focused != null)
focused.setTabIndex(tabIndex);
FocusEvent.fireNativeEvent(Document.get().createFocusEvent(), Grid.this);
}
@Override
protected void onBlur() {
super.onBlur();
FocusEvent.fireNativeEvent(Document.get().createBlurEvent(), Grid.this);
}
};
frozenRightContainer = new ScrollPanel(frozenRight);
scrollableLeft = new GridSection<T>(aKeyProvider) {
@Override
protected void replaceAllChildren(List<T> values, SafeHtml html) {
super.replaceAllChildren(values, html);
footerLeft.redrawFooters();
scrollableLeftRendered();
}
@Override
protected void replaceChildren(List<T> values, int start, SafeHtml html) {
super.replaceChildren(values, start, html);
footerLeft.redrawFooters();
scrollableLeftRendered();
}
@Override
protected void onFocus() {
super.onFocus();
Element focused = getKeyboardSelectedElement();
if (focused != null)
focused.setTabIndex(tabIndex);
FocusEvent.fireNativeEvent(Document.get().createFocusEvent(), Grid.this);
}
@Override
protected void onBlur() {
super.onBlur();
FocusEvent.fireNativeEvent(Document.get().createBlurEvent(), Grid.this);
}
};
scrollableLeftContainer = new ScrollPanel(scrollableLeft);
scrollableRight = new GridSection<T>(aKeyProvider) {
@Override
protected void replaceAllChildren(List<T> values, SafeHtml html) {
super.replaceAllChildren(values, html);
footerRight.redrawFooters();
scrollableRightRendered();
}
@Override
protected void replaceChildren(List<T> values, int start, SafeHtml html) {
super.replaceChildren(values, start, html);
footerRight.redrawFooters();
scrollableRightRendered();
}
@Override
protected void onFocus() {
super.onFocus();
Element focused = getKeyboardSelectedElement();
if (focused != null)
focused.setTabIndex(tabIndex);
FocusEvent.fireNativeEvent(Document.get().createFocusEvent(), Grid.this);
}
@Override
protected void onBlur() {
super.onBlur();
FocusEvent.fireNativeEvent(Document.get().createBlurEvent(), Grid.this);
}
};
scrollableRightContainer = new ScrollPanel(scrollableRight);
footerLeft = new GridSection<>(aKeyProvider);
footerLeftContainer = new ScrollPanel(footerLeft);
footerRight = new GridSection<>(aKeyProvider);
footerRightContainer = new ScrollPanel(footerRight);
// positioning context / overflow setup
// overflow
for (Widget w : new Widget[] { headerLeftContainer, headerRightContainer, frozenLeftContainer,
frozenRightContainer, scrollableLeftContainer, footerLeftContainer, footerRightContainer }) {
w.getElement().getStyle().setOverflow(Style.Overflow.HIDDEN);
}
// scrollableRightContainer.getElement().getStyle().setOverflow(Style.Overflow.AUTO);
// default value
// context
for (Widget w : new Widget[] { headerLeftContainer, headerRightContainer, frozenLeftContainer,
frozenRightContainer, scrollableLeftContainer, scrollableRightContainer, footerLeftContainer,
footerRightContainer }) {
w.getElement().getFirstChildElement().getStyle().setPosition(Style.Position.ABSOLUTE);
}
scrollableLeftContainer.getElement().getStyle().setPosition(Style.Position.ABSOLUTE);
scrollableLeftContainer.getElement().getStyle().setBottom(0, Style.Unit.PX);
scrollableLeftContainer.getElement().getStyle().setHeight(100, Style.Unit.PCT);
scrollableRightContainer.getElement().getStyle().setPosition(Style.Position.ABSOLUTE);
scrollableRightContainer.getElement().getStyle().setBottom(0, Style.Unit.PX);
scrollableRightContainer.getElement().getStyle().setHeight(100, Style.Unit.PCT);
// propagation of some widths
headerLeft.setWidthPropagator(new GridWidthPropagator<T>(headerLeft) {
@Override
public void changed() {
super.changed();
propagateHeaderWidth();
}
});
for (GridSection<T> section : (GridSection<T>[]) new GridSection<?>[] { headerRight, frozenLeft, frozenRight,
scrollableLeft, scrollableRight, footerLeft, footerRight }) {
section.setWidthPropagator(new GridWidthPropagator<>(section));
}
headerLeft.setColumnsPartners(new AbstractCellTable[] { frozenLeft, scrollableLeft, footerLeft });
headerRight.setColumnsPartners(new AbstractCellTable[] { frozenRight, scrollableRight, footerRight });
ColumnsRemover leftColumnsRemover = new ColumnsRemoverAdapter<T>(headerLeft, frozenLeft, scrollableLeft,
footerLeft);
ColumnsRemover rightColumnsRemover = new ColumnsRemoverAdapter<T>(headerRight, frozenRight, scrollableRight,
footerRight);
for (GridSection<T> section : (GridSection<T>[]) new GridSection<?>[] { headerLeft, frozenLeft, scrollableLeft,
footerLeft }) {
section.setColumnsRemover(leftColumnsRemover);
}
for (GridSection<T> section : (GridSection<T>[]) new GridSection<?>[] { headerRight, frozenRight,
scrollableRight, footerRight }) {
section.setColumnsRemover(rightColumnsRemover);
}
for (GridSection<T> section : (GridSection<T>[]) new GridSection<?>[] { frozenLeft, scrollableLeft,
footerLeft }) {
section.setHeaderSource(headerLeft);
}
for (GridSection<T> section : (GridSection<T>[]) new GridSection<?>[] { frozenRight, scrollableRight,
footerRight }) {
section.setHeaderSource(headerRight);
}
for (GridSection<T> section : (GridSection<T>[]) new GridSection<?>[] { headerLeft, frozenLeft,
scrollableLeft }) {
section.setFooterSource(footerLeft);
}
for (GridSection<T> section : (GridSection<T>[]) new GridSection<?>[] { headerRight, frozenRight,
scrollableRight }) {
section.setFooterSource(footerRight);
}
// hive organization
hive.setWidget(0, 0, headerLeftContainer);
hive.setWidget(0, 1, headerRightContainer);
hive.setWidget(1, 0, frozenLeftContainer);
hive.setWidget(1, 1, frozenRightContainer);
hive.setWidget(2, 0, scrollableLeftContainer);
scrollableLeftContainer.getElement().getParentElement().getStyle().setPosition(Style.Position.RELATIVE);
hive.setWidget(2, 1, scrollableRightContainer);
scrollableRightContainer.getElement().getParentElement().getStyle().setPosition(Style.Position.RELATIVE);
hive.setWidget(3, 0, footerLeftContainer);
hive.setWidget(3, 1, footerRightContainer);
for (Widget w : new Widget[] { headerLeftContainer, headerRightContainer, frozenLeftContainer,
frozenRightContainer, scrollableLeftContainer, scrollableRightContainer, footerLeftContainer,
footerRightContainer }) {
w.setWidth("100%");
w.setHeight("100%");
}
// misc
for (Widget w : new Widget[] { headerRightContainer, frozenRightContainer, footerRightContainer,
scrollableLeftContainer }) {
w.getElement().getParentElement().getStyle().setOverflow(Style.Overflow.HIDDEN);
}
hive.getElement().getStyle().setTableLayout(Style.TableLayout.FIXED);
hive.getElement().getStyle().setPosition(Style.Position.RELATIVE);
for (CellTable<?> tbl : new CellTable<?>[] { headerLeft, headerRight, frozenLeft, frozenRight, scrollableLeft,
scrollableRight, footerLeft, footerRight }) {
tbl.setTableLayoutFixed(true);
}
// header
headerLeft.setHeaderBuilder(new ThemedHeaderOrFooterBuilder<T>(headerLeft, false, this));
headerLeft.setFooterBuilder(new NullHeaderOrFooterBuilder<T>(headerLeft, true));
headerRight.setHeaderBuilder(new ThemedHeaderOrFooterBuilder<T>(headerRight, false, this));
headerRight.setFooterBuilder(new NullHeaderOrFooterBuilder<T>(headerRight, true));
// footer
footerLeft.setHeaderBuilder(new NullHeaderOrFooterBuilder<T>(footerLeft, false));
footerLeft.setFooterBuilder(new ThemedHeaderOrFooterBuilder<T>(footerLeft, true));
footerRight.setHeaderBuilder(new NullHeaderOrFooterBuilder<T>(footerRight, false));
footerRight.setFooterBuilder(new ThemedHeaderOrFooterBuilder<T>(footerRight, true));
// data bodies
for (GridSection<?> section : new GridSection<?>[] { frozenLeft, frozenRight, scrollableLeft,
scrollableRight }) {
GridSection<T> gSection = (GridSection<T>) section;
gSection.setHeaderBuilder(new NullHeaderOrFooterBuilder<T>(gSection, false));
gSection.setFooterBuilder(new NullHeaderOrFooterBuilder<T>(gSection, true));
}
for (GridSection<?> section : new GridSection<?>[] { headerLeft, headerRight, frozenLeft, frozenRight,
scrollableLeft, scrollableRight, footerLeft, footerRight }) {
section.setAutoHeaderRefreshDisabled(true);
}
for (GridSection<?> section : new GridSection<?>[] { headerLeft, headerRight, footerLeft, footerRight }) {
section.setAutoFooterRefreshDisabled(true);
}
// cells
installCellBuilders();
scrollableRightContainer.addScrollHandler(new ScrollHandler() {
@Override
public void onScroll(ScrollEvent event) {
int aimLeft = scrollableRightContainer.getElement().getScrollLeft();
if (isHeaderVisible()) {
headerRightContainer.getElement().setScrollLeft(aimLeft);
int factLeftDelta0 = aimLeft - headerRightContainer.getElement().getScrollLeft();
if (factLeftDelta0 > 0) {
headerRightContainer.getElement().getStyle().setRight(factLeftDelta0, Style.Unit.PX);
} else {
headerRightContainer.getElement().getStyle().clearRight();
}
}
if (frozenColumns > 0 || frozenRows > 0) {
int aimTop = scrollableRightContainer.getElement().getScrollTop();
scrollableLeftContainer.getElement().setScrollTop(aimTop);
int factTopDelta = aimTop - scrollableLeftContainer.getElement().getScrollTop();
if (factTopDelta > 0) {
scrollableLeftContainer.getElement().getStyle().setBottom(factTopDelta, Style.Unit.PX);
} else {
scrollableLeftContainer.getElement().getStyle().setBottom(0, Style.Unit.PX);
//scrollableLeftContainer.getElement().getStyle().clearBottom();
}
frozenRightContainer.getElement().setScrollLeft(aimLeft);
int factLeftDelta1 = aimLeft - frozenRightContainer.getElement().getScrollLeft();
if (factLeftDelta1 > 0) {
frozenRightContainer.getElement().getStyle().setRight(factLeftDelta1, Style.Unit.PX);
} else {
frozenRightContainer.getElement().getStyle().clearRight();
}
footerRightContainer.getElement()
.setScrollLeft(scrollableRightContainer.getElement().getScrollLeft());
int factLeftDelta2 = aimLeft - footerRightContainer.getElement().getScrollLeft();
if (factLeftDelta2 > 0) {
footerRightContainer.getElement().getStyle().setRight(factLeftDelta2, Style.Unit.PX);
} else {
footerRightContainer.getElement().getStyle().clearRight();
}
}
}
});
ghostLine = Document.get().createDivElement();
ghostLine.addClassName(RULER_STYLE);
ghostLine.getStyle().setPosition(Style.Position.ABSOLUTE);
ghostLine.getStyle().setTop(0, Style.Unit.PX);
ghostColumn = Document.get().createDivElement();
ghostColumn.addClassName(COLUMN_PHANTOM_STYLE);
ghostColumn.getStyle().setPosition(Style.Position.ABSOLUTE);
ghostColumn.getStyle().setTop(0, Style.Unit.PX);
addDomHandler(new DragEnterHandler() {
@Override
public void onDragEnter(DragEnterEvent event) {
if (DraggedColumn.instance != null) {
if (DraggedColumn.instance.isMove()) {
event.preventDefault();
event.stopPropagation();
DraggedColumn<T> target = findTargetDraggedColumn(event.getNativeEvent().getEventTarget());
if (target != null) {
showColumnMoveDecorations(target);
event.getDataTransfer().<XDataTransfer> cast().setDropEffect("move");
} else {
event.getDataTransfer().<XDataTransfer> cast().setDropEffect("none");
}
} else {
}
}
}
}, DragEnterEvent.getType());
addDomHandler(new DragHandler() {
@Override
public void onDrag(DragEvent event) {
if (DraggedColumn.instance != null && DraggedColumn.instance.isResize()) {
event.stopPropagation();
}
}
}, DragEvent.getType());
addDomHandler(new DragOverHandler() {
@Override
public void onDragOver(DragOverEvent event) {
if (DraggedColumn.instance != null) {
event.preventDefault();
event.stopPropagation();
if (DraggedColumn.instance.isMove()) {
DraggedColumn<T> target = findTargetDraggedColumn(event.getNativeEvent().getEventTarget());
if (target != null) {
event.getDataTransfer().<XDataTransfer> cast().setDropEffect("move");
} else {
hideColumnDecorations();
event.getDataTransfer().<XDataTransfer> cast().setDropEffect("none");
}
} else {
Element hostElement = Grid.this.getElement();
int clientX = event.getNativeEvent().getClientX();
int hostAbsX = hostElement.getAbsoluteLeft();
int hostScrollX = hostElement.getScrollLeft();
int docScrollX = hostElement.getOwnerDocument().getScrollLeft();
int relativeX = clientX - hostAbsX + hostScrollX + docScrollX;
ghostLine.getStyle().setLeft(relativeX, Style.Unit.PX);
ghostLine.getStyle().setHeight(hostElement.getClientHeight(), Style.Unit.PX);
if (ghostLine.getParentElement() != hostElement) {
hostElement.appendChild(ghostLine);
}
}
}
}
}, DragOverEvent.getType());
addDomHandler(new DragLeaveHandler() {
@Override
public void onDragLeave(DragLeaveEvent event) {
if (DraggedColumn.instance != null) {
event.stopPropagation();
if (DraggedColumn.instance.isMove()) {
if (event.getNativeEvent().getEventTarget() == (JavaScriptObject) Grid.this.getElement()) {
hideColumnDecorations();
}
}
}
}
}, DragLeaveEvent.getType());
addDomHandler(new DragEndHandler() {
@Override
public void onDragEnd(DragEndEvent event) {
if (DraggedColumn.instance != null) {
event.stopPropagation();
hideColumnDecorations();
DraggedColumn.instance = null;
}
}
}, DragEndEvent.getType());
addDomHandler(new DropHandler() {
@Override
public void onDrop(DropEvent event) {
DraggedColumn<?> source = DraggedColumn.instance;
DraggedColumn<T> target = targetDraggedColumn;
hideColumnDecorations();
DraggedColumn.instance = null;
if (source != null) {
event.preventDefault();
event.stopPropagation();
if (source.isMove()) {
AbstractCellTable<T> sourceSection = (AbstractCellTable<T>) source.getTable();
// target table may be any section in our grid
if (target != null) {
Header<?> sourceHeader = source.getHeader();
Header<?> targetHeader = target.getHeader();
if (sourceHeader instanceof DraggableHeader<?>
&& targetHeader instanceof DraggableHeader<?>) {
DraggableHeader<T> sourceDH = (DraggableHeader<T>) sourceHeader;
DraggableHeader<T> targetDH = (DraggableHeader<T>) targetHeader;
moveColumnNode(sourceDH.getHeaderNode(), targetDH.getHeaderNode());
} else {
int sourceIndex = source.getColumnIndex();
int targetIndex = target.getColumnIndex();
GridSection<T> targetSection = (GridSection<T>) target.getTable();
boolean isSourceLeft = sourceSection == headerLeft || sourceSection == frozenLeft
|| sourceSection == scrollableLeft || sourceSection == footerLeft;
boolean isTargetLeft = targetSection == headerLeft || targetSection == frozenLeft
|| targetSection == scrollableLeft || targetSection == footerLeft;
sourceSection = isSourceLeft ? headerLeft : headerRight;
targetSection = isTargetLeft ? headerLeft : headerRight;
int generalSourceIndex = isSourceLeft ? sourceIndex : sourceIndex + frozenColumns;
int generalTargetIndex = isTargetLeft ? targetIndex : targetIndex + frozenColumns;
Header<?> header = sourceSection.getHeader(sourceIndex);
if (header instanceof DraggableHeader) {
((DraggableHeader) header).setTable(targetSection);
}
if (generalSourceIndex != generalTargetIndex) {
Column<T, ?> column = (Column<T, ?>) source.getColumn();
if (!(header instanceof DraggableHeader)
|| ((DraggableHeader) header).isMoveable()) {
moveColumn(generalSourceIndex, generalTargetIndex);
}
}
}
}
} else {
Header<?> header = source.getHeader();
if (!(header instanceof DraggableHeader) || ((DraggableHeader) header).isResizable()) {
int newWidth = Math.max(
event.getNativeEvent().getClientX() - source.getCellElement().getAbsoluteLeft(),
MINIMUM_COLUMN_WIDTH);
// Source and target tables are the same, so we can
// cast to DraggedColumn<T> with no care
setColumnWidthFromHeaderDrag(((DraggedColumn<T>) source).getColumn(), newWidth,
Style.Unit.PX);
}
}
}
}
}, DropEvent.getType());
columnsChevron.getElement().getStyle().setPosition(Style.Position.ABSOLUTE);
columnsChevron.getElement().addClassName(COLUMNS_CHEVRON_STYLE);
getElement().appendChild(columnsChevron.getElement());
columnsChevron.addDomHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
PlatypusPopupMenu columnsMenu = new PlatypusPopupMenu();
fillColumns(columnsMenu, headerLeft);
fillColumns(columnsMenu, headerRight);
columnsMenu.setPopupPosition(columnsChevron.getAbsoluteLeft(), columnsChevron.getAbsoluteTop());
columnsMenu.showRelativeTo(columnsChevron);
}
private void fillColumns(MenuBar aTarget, final GridSection<T> aSection) {
for (int i = 0; i < aSection.getColumnCount(); i++) {
Header<?> h = aSection.getHeader(i);
final Column<T, ?> column = aSection.getColumn(i);
SafeHtml rendered;
if (h.getValue() instanceof String) {
String hVal = (String) h.getValue();
rendered = hVal.startsWith("<html>") ? SafeHtmlUtils.fromTrustedString(hVal.substring(6))
: SafeHtmlUtils.fromString(hVal);
} else {
Cell.Context context = new Cell.Context(0, i, h.getKey());
SafeHtmlBuilder sb = new SafeHtmlBuilder();
h.render(context, sb);
rendered = sb.toSafeHtml();
}
MenuItemCheckBox miCheck = new MenuItemCheckBox(!aSection.isColumnHidden(column),
rendered.asString(), true);
miCheck.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
if (Boolean.TRUE.equals(event.getValue())) {
showColumn(column);
} else {
hideColumn(column);
}
Grid.this.onResize();
}
});
aTarget.addItem(miCheck);
}
}
}, ClickEvent.getType());
ColumnSortEvent.Handler sectionSortHandler = new ColumnSortEvent.Handler() {
@Override
public void onColumnSort(ColumnSortEvent event) {
boolean isCtrlKey = ((GridSection<?>) event.getSource()).isCtrlKey();
boolean contains = false;
int containsAt = -1;
for (int i = 0; i < sortList.size(); i++) {
if (sortList.get(i).getColumn() == event.getColumn()) {
contains = true;
containsAt = i;
break;
}
}
if (!contains) {
if (!isCtrlKey) {
sortList.clear();
}
sortList.insert(sortList.size(), new ColumnSortList.ColumnSortInfo(event.getColumn(), true));
} else {
boolean wasAscending = sortList.get(containsAt).isAscending();
if (!isCtrlKey) {
sortList.clear();
if (wasAscending) {
sortList.push(new ColumnSortList.ColumnSortInfo(event.getColumn(), false));
}
} else {
sortList.remove(sortList.get(containsAt));
if (wasAscending) {
sortList.insert(containsAt, new ColumnSortList.ColumnSortInfo(event.getColumn(), false));
}
}
}
ColumnSortEvent.fire(Grid.this, sortList);
}
};
headerLeft.getColumnSortList().setLimit(1);
headerLeft.addColumnSortHandler(sectionSortHandler);
headerRight.getColumnSortList().setLimit(1);
headerRight.addColumnSortHandler(sectionSortHandler);
gridColor = PublishedColor.create(211, 211, 211, 255);
regenerateDynamicTDStyles();
regenerateDynamicOddRowsStyles();
getElement().<XElement> cast().addResizingTransitionEnd(this);
setStyleName(GRID_SHELL_STYLE);
}
protected void installCellBuilders() {
for (GridSection<?> section : new GridSection<?>[] { frozenLeft, frozenRight, scrollableLeft,
scrollableRight }) {
GridSection<T> gSection = (GridSection<T>) section;
gSection.setTableBuilder(new ThemedCellTableBuilder<>(gSection, dynamicTDClassName, dynamicCellClassName,
dynamicOddRowsClassName, dynamicEvenRowsClassName));
}
}
@Override
public ColumnSortList getSortList() {
return sortList;
}
/**
* Add a handler to handle {@link ColumnSortEvent}s.
*
* @param handler
* the {@link ColumnSortEvent.Handler} to add
* @return a {@link HandlerRegistration} to remove the handler
*/
public HandlerRegistration addColumnSortHandler(ColumnSortEvent.Handler handler) {
return addHandler(handler, ColumnSortEvent.getType());
}
public ListDataProvider<T> getDataProvider() {
return dataProvider;
}
protected DraggedColumn<T> findTargetDraggedColumn(JavaScriptObject aEventTarget) {
if (Element.is(aEventTarget)) {
GridSection<T> targetSection = null;
Element targetCell = null;
Element currentTarget = Element.as(aEventTarget);
if (COLUMN_PHANTOM_STYLE.equals(currentTarget.getClassName())
|| RULER_STYLE.equals(currentTarget.getClassName())) {
return targetDraggedColumn;
}
while ((targetCell == null || targetSection == null) && currentTarget != null
&& currentTarget != Grid.this.getElement()) {
if (targetCell == null) {
if ("td".equalsIgnoreCase(currentTarget.getTagName())
|| "th".equalsIgnoreCase(currentTarget.getTagName())) {
targetCell = currentTarget;
}
}
if (targetSection == null) {
if (currentTarget == headerLeft.getElement()) {
targetSection = headerLeft;
} else if (currentTarget == frozenLeft.getElement()) {
targetSection = frozenLeft;
} else if (currentTarget == scrollableLeft.getElement()) {
targetSection = scrollableLeft;
} else if (currentTarget == footerLeft.getElement()) {
targetSection = footerLeft;
} else if (currentTarget == headerRight.getElement()) {
targetSection = headerRight;
} else if (currentTarget == frozenRight.getElement()) {
targetSection = frozenRight;
} else if (currentTarget == scrollableRight.getElement()) {
targetSection = scrollableRight;
} else if (currentTarget == footerRight.getElement()) {
targetSection = footerRight;
}
}
currentTarget = currentTarget.getParentElement();
}
if (targetSection != null && targetCell != null) {
Column<T, ?> col = targetSection.getHeaderBuilder().getColumn(targetCell);
Header<?> header = targetSection.getHeaderBuilder().getHeader(targetCell);
if (col != null && header != null)
return new DraggedColumn<T>(col, header, targetSection, targetCell, Element.as(aEventTarget));
else
return null;
}
return null;
} else {
return null;
}
}
protected Element ghostLine;
protected Element ghostColumn;
protected DraggedColumn<T> targetDraggedColumn;
protected void hideColumnDecorations() {
ghostLine.removeFromParent();
ghostColumn.removeFromParent();
targetDraggedColumn = null;
}
protected void showColumnMoveDecorations(DraggedColumn<T> target) {
targetDraggedColumn = target;
Element hostElement = getElement();
Element thtdElement = target.getCellElement();
int thLeft = thtdElement.getAbsoluteLeft();
thLeft = thLeft - getAbsoluteLeft() + hostElement.getScrollLeft();
ghostLine.getStyle().setLeft(thLeft, Style.Unit.PX);
ghostLine.getStyle().setHeight(hostElement.getClientHeight(), Style.Unit.PX);
ghostColumn.getStyle().setLeft(thLeft, Style.Unit.PX);
ghostColumn.getStyle().setWidth(thtdElement.getOffsetWidth(), Style.Unit.PX);
ghostColumn.getStyle().setHeight(hostElement.getClientHeight(), Style.Unit.PX);
if (ghostLine.getParentElement() != hostElement) {
ghostLine.removeFromParent();
hostElement.appendChild(ghostLine);
}
if (ghostColumn.getParentElement() != hostElement) {
ghostColumn.removeFromParent();
hostElement.appendChild(ghostColumn);
}
}
public String getDynamicCellClassName() {
return dynamicTDClassName;
}
public boolean isShowHorizontalLines() {
return showHorizontalLines;
}
public void setShowHorizontalLines(boolean aValue) {
if (showHorizontalLines != aValue) {
showHorizontalLines = aValue;
regenerateDynamicTDStyles();
}
}
public boolean isShowVerticalLines() {
return showVerticalLines;
}
public void setShowVerticalLines(boolean aValue) {
if (showVerticalLines != aValue) {
showVerticalLines = aValue;
regenerateDynamicTDStyles();
}
}
protected void regenerateDynamicTDStyles() {
tdsStyleElement.setInnerSafeHtml(DynamicCellStyles.INSTANCE.td(dynamicTDClassName, showHorizontalLines ? 1 : 0,
showVerticalLines ? 1 : 0, gridColor != null ? gridColor.toStyled() : ""));
}
protected void regenerateDynamicOddRowsStyles() {
if (showOddRowsInOtherColor && oddRowsColor != null) {
oddRowsStyleElement.setInnerHTML(
"." + dynamicOddRowsClassName + "{background-color: " + oddRowsColor.toStyled() + "}");
} else {
oddRowsStyleElement.setInnerHTML("");
}
}
public PublishedColor getGridColor() {
return gridColor;
}
public void setGridColor(PublishedColor aValue) {
gridColor = aValue;
regenerateDynamicTDStyles();
}
public PublishedColor getOddRowsColor() {
return oddRowsColor;
}
public void setOddRowsColor(PublishedColor aValue) {
oddRowsColor = aValue;
regenerateDynamicOddRowsStyles();
}
public int getRowsHeight() {
return rowsHeight;
}
public void setRowsHeight(int aValue) {
if (rowsHeight != aValue && aValue >= 10) {
rowsHeight = aValue;
cellsStyleElement.setInnerSafeHtml(DynamicCellStyles.INSTANCE.cell(dynamicCellClassName, rowsHeight));
onResize();
}
}
private void propagateHeaderWidth() {
double lw = headerLeft.getElement().getOffsetWidth();
headerLeftContainer.getElement().getParentElement().getStyle().setWidth(lw, Style.Unit.PX);
frozenLeftContainer.getElement().getParentElement().getStyle().setWidth(lw, Style.Unit.PX);
scrollableLeftContainer.getElement().getParentElement().getStyle().setWidth(lw, Style.Unit.PX);
footerLeftContainer.getElement().getParentElement().getStyle().setWidth(lw, Style.Unit.PX);
double rw = getElement().getClientWidth() - lw;
headerRightContainer.getElement().getParentElement().getStyle().setWidth(rw, Style.Unit.PX);
frozenRightContainer.getElement().getParentElement().getStyle().setWidth(rw, Style.Unit.PX);
scrollableRightContainer.getElement().getParentElement().getStyle().setWidth(rw, Style.Unit.PX);
footerRightContainer.getElement().getParentElement().getStyle().setWidth(rw, Style.Unit.PX);
}
protected void propagateHeightButScrollable() {
int r0Height = Math.max(headerLeft.getOffsetHeight(), headerRight.getOffsetHeight());
headerLeftContainer.getElement().getParentElement().getStyle().setHeight(r0Height, Style.Unit.PX);
headerRightContainer.getElement().getParentElement().getStyle().setHeight(r0Height, Style.Unit.PX);
int r1Height = Math.max(frozenLeft.getOffsetHeight(), frozenRight.getOffsetHeight());
frozenLeftContainer.getElement().getParentElement().getStyle().setHeight(r1Height, Style.Unit.PX);
frozenRightContainer.getElement().getParentElement().getStyle().setHeight(r1Height, Style.Unit.PX);
int r3Height = Math.max(footerLeft.getOffsetHeight(), footerRight.getOffsetHeight());
footerLeftContainer.getElement().getParentElement().getStyle().setHeight(r3Height, Style.Unit.PX);
footerRightContainer.getElement().getParentElement().getStyle().setHeight(r3Height, Style.Unit.PX);
// special care about scrollable
// row height is free, but cells' height is setted by hand in order to
// support gecko browsers
// scrollableLeftContainer.getElement().getParentElement().getStyle().setHeight(100,
// Style.Unit.PCT);
// scrollableRightContainer.getElement().getParentElement().getStyle().setHeight(100,
// Style.Unit.PCT);
// some code for opera...
//scrollableLeftContainer.getElement().getStyle().clearHeight();
//scrollableRightContainer.getElement().getStyle().clearHeight();
// it seems that after clearing the height, hive offsetHeight is changed
// ...
//scrollableLeftContainer.getElement().getStyle()
// .setHeight(hive.getElement().getOffsetHeight() - r0Height - r1Height - r3Height, Style.Unit.PX);
//scrollableRightContainer.getElement().getStyle()
// .setHeight(hive.getElement().getOffsetHeight() - r0Height - r1Height - r3Height, Style.Unit.PX);
}
@Override
protected void onAttach() {
super.onAttach();
adopt(columnsChevron);
}
@Override
protected void onDetach() {
orphan(columnsChevron);
super.onDetach();
}
protected void onColumnsResize() {
// no op here because of natural columns width's
}
@Override
public void onResize() {
if (isAttached()) {
hive.setSize("100%", "100%");//(getElement().getClientWidth() + "px", getElement().getClientHeight() + "px");
propagateHeaderWidth();
onColumnsResize();
propagateHeightButScrollable();
// columnsChevron.setHeight(Math.max(headerLeftContainer.getOffsetHeight(),
// headerRightContainer.getOffsetHeight()) + "px");
for (Widget child : new Widget[] { headerLeftContainer, headerRightContainer, frozenLeftContainer,
frozenRightContainer, scrollableLeftContainer, scrollableRightContainer }) {
if (child instanceof RequiresResize) {
((RequiresResize) child).onResize();
}
}
}
}
public boolean isHeaderVisible() {
return !Style.Display.NONE.equals(headerLeft.getElement().getStyle().getDisplay())
&& !Style.Display.NONE.equals(headerRight.getElement().getStyle().getDisplay());
}
public void setHeaderVisible(boolean aValue) {
hive.getRowFormatter().setVisible(0, aValue);
if (aValue) {
columnsChevron.getElement().getStyle().clearDisplay();
headerLeftContainer.getElement().getStyle().clearDisplay();
headerRightContainer.getElement().getStyle().clearDisplay();
} else {
columnsChevron.getElement().getStyle().setDisplay(Style.Display.NONE);
headerLeftContainer.getElement().getStyle().setDisplay(Style.Display.NONE);
headerRightContainer.getElement().getStyle().setDisplay(Style.Display.NONE);
}
if (isAttached())
onResize();
}
public int getFrozenColumns() {
return frozenColumns;
}
public void setFrozenColumns(int aValue) {
if (aValue >= 0 && frozenColumns != aValue) {
if (aValue >= 0) {
frozenColumns = aValue;
if (getDataColumnCount() > 0 && aValue <= getDataColumnCount()) {
refreshColumns();
}
}
}
}
public int getFrozenRows() {
return frozenRows;
}
public void setFrozenRows(int aValue) {
if (aValue >= 0 && frozenRows != aValue) {
frozenRows = aValue;
if (dataProvider != null && aValue <= dataProvider.getList().size()) {
setupVisibleRanges();
}
}
}
public boolean isShowOddRowsInOtherColor() {
return showOddRowsInOtherColor;
}
public void setShowOddRowsInOtherColor(boolean aValue) {
if (showOddRowsInOtherColor != aValue) {
showOddRowsInOtherColor = aValue;
regenerateDynamicOddRowsStyles();
}
}
/**
*
* @param sModel
*/
public void setSelectionModel(SelectionModel<T> sModel) {
headerLeft.setSelectionModel(sModel);
headerRight.setSelectionModel(sModel);
frozenLeft.setSelectionModel(sModel);
frozenRight.setSelectionModel(sModel);
scrollableLeft.setSelectionModel(sModel);
scrollableRight.setSelectionModel(sModel);
}
public SetSelectionModel<? super T> getSelectionModel() {
return (SetSelectionModel<? super T>)scrollableRight.getSelectionModel();
}
/**
* @param aDataProvider
*/
public void setDataProvider(ListDataProvider<T> aDataProvider) {
if (dataProvider != aDataProvider) {
unbindDataProvider();
dataProvider = aDataProvider;
bindDataProvider();
setupVisibleRanges();
}
}
protected void unbindDataProvider() {
if (dataProvider != null) {
dataProvider.removeDataDisplay(headerLeft);
dataProvider.removeDataDisplay(headerRight);
dataProvider.removeDataDisplay(frozenLeft);
dataProvider.removeDataDisplay(frozenRight);
dataProvider.removeDataDisplay(scrollableLeft);
dataProvider.removeDataDisplay(scrollableRight);
dataProvider.removeDataDisplay(footerLeft);
dataProvider.removeDataDisplay(footerRight);
}
}
protected void bindDataProvider() {
if (dataProvider != null) {
dataProvider.addDataDisplay(headerLeft);
dataProvider.addDataDisplay(headerRight);
dataProvider.addDataDisplay(frozenLeft);
dataProvider.addDataDisplay(frozenRight);
dataProvider.addDataDisplay(scrollableLeft);
dataProvider.addDataDisplay(scrollableRight);
dataProvider.addDataDisplay(footerLeft);
dataProvider.addDataDisplay(footerRight);
}
}
public void setupVisibleRanges() {
List<T> list = dataProvider != null ? dataProvider.getList() : null;
int generalLength = list != null ? list.size() : 0;
int lfrozenRows = generalLength >= frozenRows ? frozenRows : generalLength;
if(lfrozenRows == 0){
hive.getRowFormatter().setVisible(1, false);
} else {
hive.getRowFormatter().setVisible(1, true);
}
int scrollableRowCount = generalLength - lfrozenRows;
//
headerLeft.setVisibleRange(new Range(0, 0));
headerRight.setVisibleRange(new Range(0, 0));
frozenLeft.setVisibleRange(new Range(0, lfrozenRows));
frozenRight.setVisibleRange(new Range(0, lfrozenRows));
scrollableLeft.setVisibleRange(new Range(lfrozenRows, scrollableRowCount >= 0 ? scrollableRowCount : 0));
scrollableRight.setVisibleRange(new Range(lfrozenRows, scrollableRowCount >= 0 ? scrollableRowCount : 0));
footerLeft.setVisibleRange(new Range(0, 0));
footerRight.setVisibleRange(new Range(0, 0));
//Since footerLeft and footerRight have bpth zero range,
//hide them entirely
hive.getRowFormatter().setVisible(3, false);
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
onResize();
}
});
}
public void addColumn(Column<T, ?> aColumn, String aWidth, Header<?> aHeader, Header<?> aFooter, boolean hidden) {
addColumn(false, getDataColumnCount(), aColumn, aWidth, aHeader, aFooter, hidden);
}
public void addColumn(int aIndex, Column<T, ?> aColumn, String aWidth, Header<?> aHeader, Header<?> aFooter,
boolean hidden) {
addColumn(true, aIndex, aColumn, aWidth, aHeader, aFooter, hidden);
}
public void addColumn(boolean forceRefreshColumns, int aIndex, Column<T, ?> aColumn, String aWidth,
Header<?> aHeader, Header<?> aFooter, boolean hidden) {
/*
* if (aHeader instanceof DraggableHeader<?>) { DraggableHeader<T> h =
* (DraggableHeader<T>) aHeader; h.setColumn(aColumn); } WARNING! Before
* uncomment, answer the question: DraggableHeader can change its
* column?
*/
if (aIndex < frozenColumns) {
if (aHeader instanceof DraggableHeader<?>) {
DraggableHeader<T> h = (DraggableHeader<T>) aHeader;
h.setTable(headerLeft);
}
headerLeft.insertColumn(aIndex, aColumn, aHeader);
frozenLeft.insertColumn(aIndex, aColumn);
scrollableLeft.insertColumn(aIndex, aColumn);
footerLeft.insertColumn(aIndex, aColumn, null, aFooter);
headerLeft.setColumnWidth(aColumn, aWidth);// column partners will
// take care of width
// seetings in other
// sections
//
if (forceRefreshColumns)
refreshColumns();
} else {
if (aHeader instanceof DraggableHeader<?>) {
DraggableHeader<T> h = (DraggableHeader<T>) aHeader;
h.setTable(headerRight);
}
headerRight.insertColumn(aIndex - frozenColumns, aColumn, aHeader);
frozenRight.insertColumn(aIndex - frozenColumns, aColumn);
scrollableRight.insertColumn(aIndex - frozenColumns, aColumn);
footerRight.insertColumn(aIndex - frozenColumns, aColumn, null, aFooter);
headerRight.setColumnWidth(aColumn, aWidth);// column partners will
// take care of width
// seetings in other
// sections
//
}
if (hidden) {
hideColumn(aColumn);
}
}
public void moveColumn(int aFromIndex, int aToIndex) {
Header<?> footer = getColumnFooter(aFromIndex);
Header<?> header = getColumnHeader(aFromIndex);
String width = getColumnWidth(aFromIndex);
Column<T, ?> column = getColumn(aFromIndex);
clearColumnWidth(aFromIndex);
removeColumn(aFromIndex);
addColumn(aToIndex, column, width, header, footer, false);
headerLeft.getWidthPropagator().changed();
}
public void moveColumnNode(HeaderNode<T> aSubject, HeaderNode<T> aInsertBefore) {
}
public void hideColumn(Column<T, ?> aColumn) {
for (GridSection<?> section : new GridSection<?>[] { headerLeft, frozenLeft, scrollableLeft, footerLeft,
headerRight, frozenRight, scrollableRight, footerRight }) {
GridSection<T> gSection = (GridSection<T>) section;
gSection.hideColumn(aColumn);
}
}
public void showColumn(Column<T, ?> aColumn) {
for (GridSection<?> section : new GridSection<?>[] { headerLeft, frozenLeft, scrollableLeft, footerLeft,
headerRight, frozenRight, scrollableRight, footerRight }) {
GridSection<T> gSection = (GridSection<T>) section;
gSection.showColumn(aColumn);
}
}
/*
* public void insertColumn(int aIndex, Column<T, ?> aColumn, String
* aHeaderValue, Header<?> aFooter) { if (aIndex < frozenColumns) {
* headerLeft.insertColumn(aIndex, aColumn, new
* DraggableHeader<T>(aHeaderValue, headerLeft, aColumn, getElement()));
* frozenLeft.insertColumn(aIndex, aColumn);
* scrollableLeft.insertColumn(aIndex, aColumn);
* footerLeft.insertColumn(aIndex, aColumn, null, aFooter);
* refreshColumns(); } else { headerRight.insertColumn(aIndex, aColumn, new
* DraggableHeader<T>(aHeaderValue, headerRight, aColumn, getElement()));
* frozenRight.insertColumn(aIndex, aColumn);
* scrollableRight.insertColumn(aIndex, aColumn);
* footerRight.insertColumn(aIndex, aColumn, null, aFooter); } }
*/
public void removeColumn(int aIndex) {
if (aIndex < frozenColumns) {
headerLeft.removeColumn(aIndex);// ColumnsRemover will care
// about columns sharing
refreshColumns();
} else {
headerRight.removeColumn(aIndex - frozenColumns);// ColumnsRemover
// will care
// about columns sharing
}
}
protected void refreshColumns() {
List<Column<T, ?>> cols = new ArrayList<>();
List<Header<?>> headers = new ArrayList<>();
List<Header<?>> footers = new ArrayList<>();
List<String> widths = new ArrayList<>();
List<Boolean> hidden = new ArrayList<>();
for (int i = headerRight.getColumnCount() - 1; i >= 0; i--) {
Column<T, ?> col = headerRight.getColumn(i);
cols.add(0, col);
widths.add(0, headerRight.getColumnWidth(col, true));
headers.add(0, headerRight.getHeader(i));
footers.add(0, footerRight.getFooter(i));
hidden.add(0, headerRight.isColumnHidden(col));
headerRight.removeColumn(i);// ColumnsRemover will care about
// columns sharing
}
for (int i = headerLeft.getColumnCount() - 1; i >= 0; i--) {
Column<T, ?> col = headerLeft.getColumn(i);
cols.add(0, col);
widths.add(0, headerLeft.getColumnWidth(col, true));
headers.add(0, headerLeft.getHeader(i));
footers.add(0, footerLeft.getFooter(i));
hidden.add(0, headerLeft.isColumnHidden(col));
headerLeft.removeColumn(i);// ColumnsRemover will care about
// columns sharing
}
headerLeft.setWidth("0px", true);
frozenLeft.setWidth("0px", true);
scrollableLeft.setWidth("0px", true);
footerLeft.setWidth("0px", true);
headerRight.setWidth("0px", true);
frozenRight.setWidth("0px", true);
scrollableRight.setWidth("0px", true);
footerRight.setWidth("0px", true);
for (int i = 0; i < cols.size(); i++) {
Column<T, ?> col = cols.get(i);
Header<?> h = headers.get(i);
Header<?> f = footers.get(i);
String w = widths.get(i);
Boolean b = hidden.get(i);
addColumn(col, w, h, f, b);
}
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
onResize();
}
});
}
public void setColumnWidthFromHeaderDrag(Column<T, ?> aColumn, double aWidth, Style.Unit aUnit) {
setColumnWidth(aColumn, aWidth, aUnit);
propagateHeightButScrollable();
}
public void setColumnWidth(Column<T, ?> aColumn, double aWidth, Style.Unit aUnit) {
if (headerLeft.getColumnIndex(aColumn) != -1) {
headerLeft.setColumnWidth(aColumn, aWidth, aUnit);
frozenLeft.setColumnWidth(aColumn, aWidth, aUnit);
scrollableLeft.setColumnWidth(aColumn, aWidth, aUnit);
footerLeft.setColumnWidth(aColumn, aWidth, aUnit);
} else if (headerRight.getColumnIndex(aColumn) != -1) {
headerRight.setColumnWidth(aColumn, aWidth, aUnit);
frozenRight.setColumnWidth(aColumn, aWidth, aUnit);
scrollableRight.setColumnWidth(aColumn, aWidth, aUnit);
footerRight.setColumnWidth(aColumn, aWidth, aUnit);
} else {
// Logger.getLogger(Grid.class.getName()).log(Level.WARNING,
// "Unknown column is met while setting column width");
}
}
public void redrawRow(int index) {
frozenLeft.redrawRow(index);
frozenRight.redrawRow(index);
scrollableLeft.redrawRow(index);
scrollableRight.redrawRow(index);
}
public void redraw() {
headerRight.redraw();
frozenLeft.redraw();
frozenRight.redraw();
scrollableLeft.redraw();
scrollableRight.redraw();
footerLeft.redraw();
footerRight.redraw();
}
public void redrawHeaders() {
headerLeft.redrawHeaders();
headerRight.redrawHeaders();
}
public void redrawFooters() {
footerLeft.redrawFooters();
footerRight.redrawFooters();
}
public int getDataColumnCount() {
return (headerLeft != null ? headerLeft.getColumnCount() : 0)
+ (headerRight != null ? headerRight.getColumnCount() : 0);
}
public Column<T, ?> getDataColumn(int aIndex) {
if (aIndex >= 0 && aIndex < getDataColumnCount()) {
return aIndex >= 0 && aIndex < headerLeft.getColumnCount() ? headerLeft.getColumn(aIndex)
: headerRight.getColumn(aIndex - headerLeft.getColumnCount());
} else
return null;
}
public Header<?> getColumnHeader(int aIndex) {
if (aIndex >= 0 && aIndex < getDataColumnCount()) {
return aIndex >= 0 && aIndex < headerLeft.getColumnCount() ? headerLeft.getHeader(aIndex)
: headerRight.getHeader(aIndex - headerLeft.getColumnCount());
} else
return null;
}
public Column<T, ?> getColumn(int aIndex) {
if (aIndex >= 0 && aIndex < getDataColumnCount()) {
return aIndex >= 0 && aIndex < headerLeft.getColumnCount() ? headerLeft.getColumn(aIndex)
: headerRight.getColumn(aIndex - headerLeft.getColumnCount());
} else
return null;
}
public String getColumnWidth(int aIndex) {
if (aIndex >= 0 && aIndex < getDataColumnCount()) {
Column<T, ?> col = getColumn(aIndex);
return aIndex >= 0 && aIndex < headerLeft.getColumnCount() ? headerLeft.getColumnWidth(col)
: headerRight.getColumnWidth(col);
} else
return null;
}
public Header<?> getColumnFooter(int aIndex) {
if (aIndex >= 0 && aIndex < getDataColumnCount()) {
return aIndex >= 0 && aIndex < headerLeft.getColumnCount() ? headerLeft.getFooter(aIndex)
: headerRight.getFooter(aIndex - headerLeft.getColumnCount());
} else
return null;
}
public void clearColumnWidth(int aIndex) {
if (aIndex >= 0 && aIndex < getDataColumnCount()) {
Column<T, ?> col = getColumn(aIndex);
if (aIndex >= 0 && aIndex < headerLeft.getColumnCount()) {
headerLeft.clearColumnWidth(aIndex);
headerLeft.clearColumnWidth(col);
} else {
headerRight.clearColumnWidth(aIndex - headerLeft.getColumnCount());
headerRight.clearColumnWidth(col);
}
}
}
public TableCellElement getViewCell(int aRow, int aCol) {
GridSection<T> targetSection;
if (aRow < frozenRows) {
if (aCol < frozenColumns) {
targetSection = frozenLeft;
} else {
aCol -= frozenColumns;
targetSection = frozenRight;
}
} else {
aRow -= frozenRows;
if (aCol < frozenColumns) {
targetSection = scrollableLeft;
} else {
aCol -= frozenColumns;
targetSection = scrollableRight;
}
}
return targetSection.getCell(aRow, aCol);
}
public void focusViewCell(int aRow, int aCol) {
GridSection<T> targetSection;
if (aRow < frozenRows) {
if (aCol < frozenColumns) {
targetSection = frozenLeft;
} else {
aCol -= frozenColumns;
targetSection = frozenRight;
}
} else {
aRow -= frozenRows;
if (aCol < frozenColumns) {
targetSection = scrollableLeft;
} else {
aCol -= frozenColumns;
targetSection = scrollableRight;
}
}
targetSection.focusCell(aRow, aCol);
}
public void unsort() {
sortList.clear();
ColumnSortEvent.fire(Grid.this, sortList);
redrawHeaders();
}
public void addSort(ModelColumn aColumn, boolean isAscending) {
if (aColumn.isSortable()) {
boolean contains = false;
int containsAt = -1;
for (int i = 0; i < sortList.size(); i++) {
if (sortList.get(i).getColumn() == aColumn) {
contains = true;
containsAt = i;
break;
}
}
if (contains) {
boolean wasAscending = sortList.get(containsAt).isAscending();
if (wasAscending == isAscending) {
return;
}
}
sortList.insert(sortList.size(), new ColumnSortList.ColumnSortInfo(aColumn, isAscending));
ColumnSortEvent.fire(Grid.this, sortList);
redrawHeaders();
}
}
public void unsortColumn(ModelColumn aColumn) {
if (aColumn.isSortable()) {
boolean contains = false;
int containsAt = -1;
for (int i = 0; i < sortList.size(); i++) {
if (sortList.get(i).getColumn() == aColumn) {
contains = true;
containsAt = i;
break;
}
}
if (contains) {
sortList.remove(sortList.get(containsAt));
ColumnSortEvent.fire(Grid.this, sortList);
redrawHeaders();
}
}
}
protected int tabIndex;
protected Element calcFocusedElement() {
Element focusedEelement = scrollableRight.getKeyboardSelectedElement();
if (focusedEelement == null)
focusedEelement = scrollableLeft.getKeyboardSelectedElement();
if (focusedEelement == null)
focusedEelement = frozenLeft.getKeyboardSelectedElement();
if (focusedEelement == null)
focusedEelement = frozenRight.getKeyboardSelectedElement();
if (focusedEelement == null)
focusedEelement = getElement();
return focusedEelement;
}
protected void frozenLeftRendered() {
checkRenderingCompleted();
}
protected void frozenRightRendered() {
checkRenderingCompleted();
}
protected void scrollableLeftRendered() {
checkRenderingCompleted();
}
protected void scrollableRightRendered() {
checkRenderingCompleted();
}
private ScheduledCommand renderingCompletedCommand;
private void checkRenderingCompleted(){
renderingCompletedCommand = new ScheduledCommand() {
@Override
public void execute() {
if (renderingCompletedCommand == this) {
renderingCompletedCommand = null;
renderingCompleted();
}
}
};
Scheduler.get().scheduleDeferred(renderingCompletedCommand);
}
protected void renderingCompleted(){
Element focusedElement = calcFocusedElement();
if (focusedElement == getElement())
getElement().setTabIndex(tabIndex);
else
getElement().removeAttribute("tabindex");
}
@Override
public int getTabIndex() {
return tabIndex;
}
@Override
public void setAccessKey(char key) {
}
@Override
public void setFocus(boolean focused) {
Element focusedElement = calcFocusedElement();
focusedElement.setTabIndex(tabIndex);
if (focused)
focusedElement.focus();
else
focusedElement.blur();
}
@Override
public void setTabIndex(int index) {
tabIndex = index;
Element focusedElement = calcFocusedElement();
focusedElement.setTabIndex(tabIndex);
}
}