Java tutorial
/* * Licensed to The Apereo Foundation under one or more contributor license * agreements. See the NOTICE file distributed with this work for * additional information regarding copyright ownership. * * The Apereo Foundation 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.unitime.timetable.gwt.client.widgets; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.unitime.timetable.gwt.client.aria.AriaCheckBox; import org.unitime.timetable.gwt.client.page.UniTimeNotifications; import com.google.gwt.aria.client.Roles; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Cursor; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Composite; 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.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HasVerticalAlignment.VerticalAlignmentConstant; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.TextBoxBase; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant; /** * @author Tomas Muller */ public class UniTimeTable<T> extends FlexTable { private List<MouseOverListener<T>> iMouseOverListeners = new ArrayList<MouseOverListener<T>>(); private List<MouseOutListener<T>> iMouseOutListeners = new ArrayList<MouseOutListener<T>>(); private List<MouseClickListener<T>> iMouseClickListeners = new ArrayList<MouseClickListener<T>>(); private List<DataChangedListener<T>> iDataChangedListeners = new ArrayList<DataChangedListener<T>>(); private PopupPanel iHintPanel = null; private HintProvider<T> iHintProvider = null; private int iLastHoverRow = -1; private Map<Integer, String> iLastHoverBackgroundColor = new HashMap<Integer, String>(); private boolean iAllowSelection = false, iAllowMultiSelect = true; public UniTimeTable() { setCellPadding(2); setCellSpacing(0); sinkEvents(Event.ONMOUSEOVER); sinkEvents(Event.ONMOUSEOUT); sinkEvents(Event.ONCLICK); sinkEvents(Event.ONKEYDOWN); setStylePrimaryName("unitime-MainTable"); iHintPanel = new PopupPanel(); iHintPanel.setStyleName("unitime-PopupHint"); Roles.getGridRole().set(getElement()); } public void setAllowSelection(boolean allow) { iAllowSelection = allow; } public boolean isAllowSelection() { return iAllowSelection; } public void setAllowMultiSelect(boolean allow) { iAllowMultiSelect = allow; } public boolean isAllowMultiSelect() { return iAllowMultiSelect; } public void clearTable(int headerRows) { for (int row = getRowCount() - 1; row >= headerRows; row--) removeRow(row); iLastHoverBackgroundColor.clear(); } public void clearTable() { clearTable(0); } public void addRow(T data, Widget... widgets) { List<Widget> list = new ArrayList<Widget>(); for (Widget widget : widgets) list.add(widget); addRow(data, list); } public int addRow(T data, List<? extends Widget> widgets) { int row = getRowCount(); setRow(row, data, widgets); return row; } public void setRow(int row, T data, List<? extends Widget> widgets) { SmartTableRow<T> oldRow = getSmartRow(row); if (oldRow != null && oldRow.getData() != null) { DataChangedEvent<T> event = new DataChangedEvent<T>(oldRow.getData(), row); for (DataChangedListener<T> listener : iDataChangedListeners) listener.onDataRemoved(event); } SmartTableRow smartRow = new SmartTableRow(data); int col = 0, x = 0; for (Widget widget : widgets) { SmartTableCell cell = new SmartTableCell(smartRow, widget); int colspan = 1; if (widget instanceof HasColSpan) { colspan = ((HasColSpan) widget).getColSpan(); getFlexCellFormatter().setColSpan(row, col, colspan); } if (widget instanceof HasStyleName && ((HasStyleName) widget).getStyleName() != null) getFlexCellFormatter().setStyleName(row, col, ((HasStyleName) widget).getStyleName()); if (widget instanceof HasAdditionalStyleNames) { List<String> styleNames = ((HasAdditionalStyleNames) widget).getAdditionalStyleNames(); if (styleNames != null) for (String styleName : styleNames) getFlexCellFormatter().addStyleName(row, col, styleName); } if (widget instanceof HasCellAlignment) getFlexCellFormatter().setHorizontalAlignment(row, col, ((HasCellAlignment) widget).getCellAlignment()); if (widget instanceof HasVerticalCellAlignment) getFlexCellFormatter().setVerticalAlignment(row, col, ((HasVerticalCellAlignment) widget).getVerticalCellAlignment()); if (widget instanceof HasColumn) ((HasColumn) widget).setColumn(col); setWidget(row, col, cell); if (widget instanceof UniTimeTableHeader) { Roles.getColumnheaderRole().set(getCellFormatter().getElement(row, col)); } else { Roles.getGridcellRole().set(getCellFormatter().getElement(row, col)); } x += colspan; if (row > 0) { if (colspan == 1) { getCellFormatter().setVisible(row, col, isColumnVisible(x - 1)); } else { int span = 0; for (int h = x - colspan; h < x; h++) if (isColumnVisible(h)) span++; getCellFormatter().setVisible(row, col, span > 0); getFlexCellFormatter().setColSpan(row, col, Math.max(1, span)); } } col++; } Roles.getRowRole().set(getRowFormatter().getElement(row)); if (data != null) { DataChangedEvent<T> event = new DataChangedEvent<T>(data, row); for (DataChangedListener<T> listener : iDataChangedListeners) listener.onDataInserted(event); } } public boolean isColumnVisible(int col) { if (getRowCount() <= 0) return true; for (int c = 0; c < getCellCount(0); c++) { col -= getFlexCellFormatter().getColSpan(0, c); if (col < 0) return getCellFormatter().isVisible(0, c); } return true; } public void setColumnVisible(int col, boolean visible) { for (int r = 0; r < getRowCount(); r++) { if (r == 0) { // now colspans for the first row getCellFormatter().setVisible(r, col, visible); continue; } int x = 0; for (int c = 0; c < getCellCount(r); c++) { Widget w = getWidget(r, c); int colSpan = (w instanceof HasColSpan ? ((HasColSpan) w).getColSpan() : 1); x += colSpan; if (x > col) { if (colSpan > 1) { // use first row to count the colspan int span = 0; for (int h = x - colSpan; h < x; h++) if (isColumnVisible(h)) span++; getCellFormatter().setVisible(r, c, span > 0); getFlexCellFormatter().setColSpan(r, c, Math.max(1, span)); } else { getCellFormatter().setVisible(r, c, visible); } break; } } } } public static class SmartTableRow<T> { private List<SmartTableCell> iCells = new ArrayList<SmartTableCell>(); private T iData = null; public SmartTableRow(T data) { iData = data; } public T getData() { return iData; } public boolean hasData() { return iData != null; } public List<SmartTableCell> getCells() { return iCells; } public Comparator<SmartTableRow<T>> getComparator(final Comparator<T> cmp) { return new Comparator<SmartTableRow<T>>() { public int compare(SmartTableRow<T> a, SmartTableRow<T> b) { return cmp.compare(a.getData(), b.getData()); } }; } } public static class SmartTableCell extends Composite { SmartTableRow iRow; public SmartTableCell(SmartTableRow row, Widget widget) { iRow = row; row.getCells().add(this); initWidget(widget); } public SmartTableRow getRow() { return iRow; } public boolean focus() { if (getWidget() instanceof HasFocus) { return ((HasFocus) getWidget()).focus(); } else if (getWidget() instanceof Focusable) { ((Focusable) getWidget()).setFocus(true); if (getWidget() instanceof TextBoxBase) ((TextBoxBase) getWidget()).selectAll(); return true; } return false; } public Widget getInnerWidget() { return getWidget(); } } public Widget getWidget(int row, int col) { Widget w = super.getWidget(row, col); if (w == null) return w; if (w instanceof SmartTableCell) return ((SmartTableCell) w).getInnerWidget(); return w; } public Widget replaceWidget(int row, int col, Widget widget) { Widget w = super.getWidget(row, col); if (w == null) super.setWidget(row, col, widget); else if (w instanceof SmartTableCell) super.setWidget(row, col, new SmartTableCell(((SmartTableCell) w).getRow(), widget)); else super.setWidget(row, col, widget); return w; } private boolean focus(int row, int col) { if (!getRowFormatter().isVisible(row) || col >= getCellCount(row)) return false; Widget w = super.getWidget(row, col); if (w == null || !w.isVisible()) return false; if (w instanceof SmartTableCell) { return ((SmartTableCell) w).focus(); } else if (w instanceof HasFocus) { return ((HasFocus) w).focus(); } else if (w instanceof Focusable) { ((Focusable) w).setFocus(true); if (w instanceof TextBoxBase) ((TextBoxBase) w).selectAll(); return true; } return false; } public T getData(int row) { SmartTableRow<T> r = getSmartRow(row); return (r == null ? null : r.getData()); } public List<T> getData() { List<T> ret = new ArrayList<T>(); for (int row = 0; row < getRowCount(); row++) { T data = getData(row); if (data != null) ret.add(data); } return ret; } public SmartTableRow<T> getSmartRow(int row) { if (row < 0 || row >= getRowCount()) return null; for (int col = 0; col < getCellCount(row); col++) { Widget w = super.getWidget(row, col); if (w != null && w instanceof SmartTableCell) return ((SmartTableCell) w).getRow(); } return null; } private void swapRows(int r0, int r1) { if (r0 == r1) return; if (r0 > r1) { swapRows(r1, r0); } else { // r0 < r1 Element body = getBodyElement(); Element a = DOM.getChild(body, r0); Element b = DOM.getChild(body, r1); body.removeChild(a); body.removeChild(b); DOM.insertChild(body, b, r0); DOM.insertChild(body, a, r1); } } public void sort(int column, final Comparator<T> rowComparator) { sort(getHeader(column), rowComparator); } public void sort(String columnName, final Comparator<T> rowComparator) { sort(getHeader(columnName), rowComparator); } public void sort(UniTimeTableHeader header, final Comparator<T> rowComparator) { if (header != null) { sort(header, rowComparator, header.getOrder() == null ? true : !header.getOrder()); } else { sort(header, rowComparator, true); } } public void sort(UniTimeTableHeader header, final Comparator<T> rowComparator, boolean asc) { if (header != null) { for (int i = 0; i < getCellCount(0); i++) { Widget w = getWidget(0, i); if (w != null && w instanceof UniTimeTableHeader) { UniTimeTableHeader h = (UniTimeTableHeader) w; h.setOrder(null); } } header.setOrder(asc); } Element body = getBodyElement(); ArrayList<Object[]> rows = new ArrayList<Object[]>(); for (int row = 0; row < getRowCount(); row++) { SmartTableRow<T> r = getSmartRow(row); if (r != null && r.hasData()) { rows.add(new Object[] { r, getRowFormatter().getElement(row) }); } } if (asc) { Collections.sort(rows, new Comparator<Object[]>() { public int compare(Object[] a, Object[] b) { return rowComparator.compare(((SmartTableRow<T>) a[0]).getData(), ((SmartTableRow<T>) b[0]).getData()); } }); } else { Collections.sort(rows, new Comparator<Object[]>() { public int compare(Object[] a, Object[] b) { return -rowComparator.compare(((SmartTableRow<T>) a[0]).getData(), ((SmartTableRow<T>) b[0]).getData()); } }); } int idx = 0; List<DataChangedEvent<T>> changeEvents = new ArrayList<DataChangedEvent<T>>(); for (int row = 0; row < getRowCount(); row++) { SmartTableRow<T> a = getSmartRow(row); if (a != null && a.hasData()) { Object[] o = rows.get(idx++); int otherRow = DOM.getChildIndex(body, (Element) o[1]); swapRows(row, otherRow); changeEvents.add(new DataChangedEvent<T>(((SmartTableRow<T>) o[0]).getData(), row)); } } for (DataChangedListener<T> listener : iDataChangedListeners) listener.onDataSorted(changeEvents); } public void sortByRow(int column, final Comparator<Integer> rowComparator) { sortByRow(getHeader(column), rowComparator); } public void sortByRow(String columnName, final Comparator<Integer> rowComparator) { sortByRow(getHeader(columnName), rowComparator); } public void sortByRow(UniTimeTableHeader header, final Comparator<Integer> rowComparator) { if (header != null) { sortByRow(header, rowComparator, header.getOrder() == null ? true : !header.getOrder()); } else { sortByRow(header, rowComparator, true); } } public void sortByRow(UniTimeTableHeader header, final Comparator<Integer> rowComparator, boolean asc) { if (header != null) { for (int i = 0; i < getCellCount(0); i++) { Widget w = getWidget(0, i); if (w != null && w instanceof UniTimeTableHeader) { UniTimeTableHeader h = (UniTimeTableHeader) w; h.setOrder(null); } } header.setOrder(asc); } Element body = getBodyElement(); ArrayList<Object[]> rows = new ArrayList<Object[]>(); for (int row = 0; row < getRowCount(); row++) { SmartTableRow<T> r = getSmartRow(row); if (r != null && r.hasData()) { rows.add(new Object[] { r, getRowFormatter().getElement(row), row }); } } if (asc) { Collections.sort(rows, new Comparator<Object[]>() { public int compare(Object[] a, Object[] b) { return rowComparator.compare((Integer) a[2], (Integer) b[2]); } }); } else { Collections.sort(rows, new Comparator<Object[]>() { public int compare(Object[] a, Object[] b) { return -rowComparator.compare((Integer) a[2], (Integer) b[2]); } }); } int idx = 0; List<DataChangedEvent<T>> changeEvents = new ArrayList<DataChangedEvent<T>>(); for (int row = 0; row < getRowCount(); row++) { SmartTableRow<T> a = getSmartRow(row); if (a != null && a.hasData()) { Object[] o = rows.get(idx++); int otherRow = DOM.getChildIndex(body, (Element) o[1]); swapRows(row, otherRow); changeEvents.add(new DataChangedEvent<T>(((SmartTableRow<T>) o[0]).getData(), row)); } } for (DataChangedListener<T> listener : iDataChangedListeners) listener.onDataSorted(changeEvents); } public boolean canSwapRows(T a, T b) { return true; } public void onBrowserEvent(final Event event) { Element td = getEventTargetCell(event); if (td == null) return; final Element tr = DOM.getParent(td); int col = DOM.getChildIndex(tr, td); Element body = DOM.getParent(tr); int row = DOM.getChildIndex(body, tr); Widget widget = getWidget(row, col); SmartTableRow<T> r = getSmartRow(row); boolean hasData = (r != null && r.getData() != null); TableEvent<T> tableEvent = new TableEvent<T>(event, row, col, tr, td, hasData ? r.getData() : null); Widget hint = null; if (widget instanceof HasHint) { String html = ((HasHint) widget).getHint(); if (html != null && !html.isEmpty()) hint = new HTML(html, false); } if (hint == null && iHintProvider != null) hint = iHintProvider.getHint(tableEvent); String style = getRowFormatter().getStyleName(row); switch (DOM.eventGetType(event)) { case Event.ONMOUSEOVER: if (hasData) { if (!iMouseClickListeners.isEmpty()) getRowFormatter().getElement(row).getStyle().setCursor(Cursor.POINTER); boolean selected = false; if (isAllowSelection()) { if ("unitime-TableRowSelected".equals(style)) { getRowFormatter().setStyleName(row, "unitime-TableRowSelectedHover"); selected = true; } else { getRowFormatter().setStyleName(row, "unitime-TableRowHover"); } } else { getRowFormatter().addStyleName(row, "unitime-TableRowHover"); } iLastHoverRow = row; if (!selected) { String color = getRowFormatter().getElement(row).getStyle().getBackgroundColor(); if (color != null && !color.isEmpty()) { getRowFormatter().getElement(row).getStyle().clearBackgroundColor(); iLastHoverBackgroundColor.put(row, color); } else { iLastHoverBackgroundColor.remove(row); } } } if (!iHintPanel.isShowing() && hint != null) { iHintPanel.setWidget(hint); iHintPanel.setPopupPositionAndShow(new PopupPanel.PositionCallback() { @Override public void setPosition(int offsetWidth, int offsetHeight) { boolean top = (tr.getAbsoluteBottom() - Window.getScrollTop() + 15 + offsetHeight > Window .getClientHeight()); iHintPanel.setPopupPosition( Math.max(Math.min(event.getClientX(), tr.getAbsoluteRight() - offsetWidth - 15), tr.getAbsoluteLeft() + 15), top ? tr.getAbsoluteTop() - offsetHeight - 15 : tr.getAbsoluteBottom() + 15); } }); } for (MouseOverListener<T> listener : iMouseOverListeners) listener.onMouseOver(tableEvent); break; case Event.ONMOUSEOUT: if (hasData) { if (!iMouseClickListeners.isEmpty()) getRowFormatter().getElement(row).getStyle().clearCursor(); boolean selected = false; if (isAllowSelection()) { if ("unitime-TableRowHover".equals(style)) { getRowFormatter().setStyleName(row, null); } else if ("unitime-TableRowSelectedHover".equals(style)) { getRowFormatter().setStyleName(row, "unitime-TableRowSelected"); selected = true; } } else { getRowFormatter().removeStyleName(row, "unitime-TableRowHover"); } if (!selected) { String color = iLastHoverBackgroundColor.remove(row); if (color != null && !color.isEmpty()) { getRowFormatter().getElement(row).getStyle().setBackgroundColor(color); } } iLastHoverRow = -1; } if (iHintPanel.isShowing()) iHintPanel.hide(); for (MouseOutListener<T> listener : iMouseOutListeners) listener.onMouseOut(tableEvent); break; case Event.ONMOUSEMOVE: if (iHintPanel.isShowing()) { boolean top = (tr.getAbsoluteBottom() - Window.getScrollTop() + 15 + iHintPanel.getOffsetHeight() > Window.getClientHeight()); iHintPanel.setPopupPosition( Math.max( Math.min(event.getClientX(), tr.getAbsoluteRight() - iHintPanel.getOffsetWidth() - 15), tr.getAbsoluteLeft() + 15), top ? tr.getAbsoluteTop() - iHintPanel.getOffsetHeight() - 15 : tr.getAbsoluteBottom() + 15); } break; case Event.ONCLICK: if (isAllowSelection() && hasData) { Element element = DOM.eventGetTarget(event); while (element.getPropertyString("tagName").equalsIgnoreCase("div")) element = DOM.getParent(element); if (isAllowMultiSelect()) { if (element.getPropertyString("tagName").equalsIgnoreCase("td")) { boolean hover = ("unitime-TableRowHover".equals(style) || "unitime-TableRowSelectedHover".equals(style)); boolean selected = !("unitime-TableRowSelected".equals(style) || "unitime-TableRowSelectedHover".equals(style)); getRowFormatter().setStyleName(row, "unitime-TableRow" + (selected ? "Selected" : "") + (hover ? "Hover" : "")); } } else { int old = getSelectedRow(); if (old != row && old >= 0) setSelected(old, false); boolean hover = ("unitime-TableRowHover".equals(style) || "unitime-TableRowSelectedHover".equals(style)); getRowFormatter().setStyleName(row, "unitime-TableRowSelected" + (hover ? "Hover" : "")); } } if (iHintPanel != null && iHintPanel.isShowing()) iHintPanel.hide(); for (MouseClickListener<T> listener : iMouseClickListeners) listener.onMouseClick(tableEvent); break; case Event.ONKEYDOWN: if (event.getKeyCode() == KeyCodes.KEY_RIGHT && (event.getAltKey() || event.getMetaKey())) { do { col++; if (col >= getCellCount(row)) break; } while (!focus(row, col)); event.stopPropagation(); event.preventDefault(); } if (event.getKeyCode() == KeyCodes.KEY_LEFT && (event.getAltKey() || event.getMetaKey())) { do { col--; if (col < 0) break; } while (!focus(row, col)); event.stopPropagation(); event.preventDefault(); } if (event.getKeyCode() == KeyCodes.KEY_UP && (event.getAltKey() || event.getMetaKey())) { do { row--; if (row < 0) break; } while (!focus(row, col)); event.stopPropagation(); event.preventDefault(); } else if (hasData && event.getKeyCode() == KeyCodes.KEY_UP && event.getCtrlKey()) { SmartTableRow<T> up = getSmartRow(row - 1); if (up != null && up.getData() != null && canSwapRows(r.getData(), up.getData())) { getRowFormatter().removeStyleName(row, "unitime-TableRowHover"); getRowFormatter().removeStyleName(row - 1, "unitime-TableRowHover"); swapRows(row - 1, row); focus(row - 1, col); if (!iDataChangedListeners.isEmpty()) { List<DataChangedEvent<T>> e = new ArrayList<DataChangedEvent<T>>(); e.add(new DataChangedEvent<T>(up.getData(), row)); e.add(new DataChangedEvent<T>(r.getData(), row - 1)); for (DataChangedListener<T> listener : iDataChangedListeners) { listener.onDataMoved(e); } } } event.stopPropagation(); event.preventDefault(); } if (event.getKeyCode() == KeyCodes.KEY_DOWN && (event.getAltKey() || event.getMetaKey())) { do { row++; if (row >= getRowCount()) break; } while (!focus(row, col)); event.stopPropagation(); event.preventDefault(); } else if (hasData && event.getKeyCode() == KeyCodes.KEY_DOWN && event.getCtrlKey()) { SmartTableRow<T> dn = getSmartRow(row + 1); if (dn != null && dn.getData() != null && canSwapRows(r.getData(), dn.getData())) { getRowFormatter().removeStyleName(row, "unitime-TableRowHover"); getRowFormatter().removeStyleName(row + 1, "unitime-TableRowHover"); swapRows(row + 1, row); focus(row + 1, col); if (!iDataChangedListeners.isEmpty()) { List<DataChangedEvent<T>> e = new ArrayList<DataChangedEvent<T>>(); e.add(new DataChangedEvent<T>(dn.getData(), row)); e.add(new DataChangedEvent<T>(r.getData(), row + 1)); for (DataChangedListener<T> listener : iDataChangedListeners) { listener.onDataMoved(e); } } } event.stopPropagation(); event.preventDefault(); } break; } } public void clearHover() { if (iLastHoverRow >= 0 && iLastHoverRow < getRowCount()) { boolean selected = false; if (isAllowSelection()) { String style = getRowFormatter().getStyleName(iLastHoverRow); selected = ("unitime-TableRowSelected".equals(style) || "unitime-TableRowSelectedHover".equals(style)); getRowFormatter().setStyleName(iLastHoverRow, "unitime-TableRow" + (selected ? "Selected" : "")); } else { getRowFormatter().removeStyleName(iLastHoverRow, "unitime-TableRowHover"); } if (!selected) { String color = iLastHoverBackgroundColor.remove(iLastHoverRow); if (color != null && !color.isEmpty()) { getRowFormatter().getElement(iLastHoverRow).getStyle().setBackgroundColor(color); } } } iLastHoverRow = -1; } public boolean isSelected(int row) { if (isAllowSelection()) { String style = getRowFormatter().getStyleName(row); return "unitime-TableRowSelected".equals(style) || "unitime-TableRowSelectedHover".equals(style); } else { return false; } } public void setSelected(int row, boolean selected) { if (isAllowSelection() && !isAllowMultiSelect() && selected) { int old = getSelectedRow(); if (old >= 0 && old != row) setSelected(old, false); } if (isAllowSelection()) { String style = getRowFormatter().getStyleName(row); boolean hover = ("unitime-TableRowHover".equals(style) || "unitime-TableRowSelectedHover".equals(style)); boolean wasSelected = ("unitime-TableRowSelected".equals(style) || "unitime-TableRowSelectedHover".equals(style)); getRowFormatter().setStyleName(row, "unitime-TableRow" + (selected ? "Selected" : "") + (hover ? "Hover" : "")); if (!hover && wasSelected != selected) { if (selected) { String color = getRowFormatter().getElement(row).getStyle().getBackgroundColor(); if (color != null && !color.isEmpty()) { getRowFormatter().getElement(row).getStyle().clearBackgroundColor(); iLastHoverBackgroundColor.put(row, color); } } else { String color = iLastHoverBackgroundColor.remove(row); if (color != null && !color.isEmpty()) { getRowFormatter().getElement(row).getStyle().setBackgroundColor(color); } } } } } public int getSelectedCount() { int selected = 0; for (int row = 0; row < getRowCount(); row++) if (isSelected(row)) selected++; return selected; } public int getSelectedRow() { for (int row = 0; row < getRowCount(); row++) if (isSelected(row)) return row; return -1; } public static class TableEvent<T> { private Event iSourceEvent; private int iRow; private int iCol; private Element iTD; private Element iTR; private T iData; public TableEvent(Event sourceEvent, int row, int col, Element tr, Element td, T data) { iRow = row; iCol = col; iTR = tr; iTD = td; iData = data; iSourceEvent = sourceEvent; } public int getRow() { return iRow; } public int getCol() { return iCol; } public T getData() { return iData; } public Element getRowElement() { return iTR; } public Element getCellElement() { return iTD; } public Event getSourceEvent() { return iSourceEvent; } } public static interface MouseOverListener<T> { public void onMouseOver(TableEvent<T> event); } public void addMouseOverListener(MouseOverListener<T> mouseOverListener) { iMouseOverListeners.add(mouseOverListener); } public static interface MouseOutListener<T> { public void onMouseOut(TableEvent<T> event); } public void addMouseOutListener(MouseOutListener<T> mouseOutListener) { iMouseOutListeners.add(mouseOutListener); } public static interface MouseClickListener<T> { public void onMouseClick(TableEvent<T> event); } public void addMouseClickListener(MouseClickListener<T> mouseClickListener) { iMouseClickListeners.add(mouseClickListener); } public static class DataChangedEvent<T> { private T iData; private int iRow; public DataChangedEvent(T data, int row) { iData = data; iRow = row; } public T getData() { return iData; } public int getRow() { return iRow; } } public interface DataChangedListener<T> { public void onDataInserted(DataChangedEvent<T> event); public void onDataRemoved(DataChangedEvent<T> event); public void onDataMoved(List<DataChangedEvent<T>> events); public void onDataSorted(List<DataChangedEvent<T>> events); } public void addDataChangedListener(DataChangedListener<T> listener) { iDataChangedListeners.add(listener); } public UniTimeTableHeader getHeader(String name) { if (getRowCount() <= 0) return null; if (name == null) { Widget w = getWidget(0, 0); return (w != null && w instanceof UniTimeTableHeader ? (UniTimeTableHeader) w : null); } for (int i = 0; i < getCellCount(0); i++) { Widget w = getWidget(0, i); if (w != null && w instanceof UniTimeTableHeader) { UniTimeTableHeader h = (UniTimeTableHeader) w; if (h.getHTML().equals(name)) return h; } } UniTimeNotifications.warn("Header named " + name + " does not exist!"); return null; } public UniTimeTableHeader getHeader(int col) { if (getRowCount() <= 0 || getCellCount(0) <= col) return null; for (int c = 0; c < getCellCount(0); c++) { col -= getFlexCellFormatter().getColSpan(0, c); if (col < 0) { Widget w = getWidget(0, c); return (w != null && w instanceof UniTimeTableHeader ? (UniTimeTableHeader) w : null); } } return null; } public static interface HasFocus { public boolean focus(); } public static interface HasHint { public String getHint(); } public static interface HasColSpan { public int getColSpan(); } public static interface HasCellAlignment { public HorizontalAlignmentConstant getCellAlignment(); } public static interface HasVerticalCellAlignment { public VerticalAlignmentConstant getVerticalCellAlignment(); } public static interface HasStyleName { public String getStyleName(); } public static interface HasAdditionalStyleNames { public List<String> getAdditionalStyleNames(); } public static interface HasDataUpdate { public void update(); } public static interface HasColumn { public int getColumn(); public void setColumn(int column); } public static interface HintProvider<T> { Widget getHint(TableEvent<T> event); } public void setHintProvider(HintProvider<T> hintProvider) { iHintProvider = hintProvider; } public static class NumberCell extends HTML implements HasCellAlignment { public NumberCell(String text) { super(text, false); } public NumberCell(int text) { super(String.valueOf(text), false); } @Override public HorizontalAlignmentConstant getCellAlignment() { return HasHorizontalAlignment.ALIGN_RIGHT; } } public static class CenterredCell extends HTML implements HasCellAlignment { public CenterredCell(String text) { super(text, false); } @Override public HorizontalAlignmentConstant getCellAlignment() { return HasHorizontalAlignment.ALIGN_CENTER; } } public static class CheckBoxCell extends AriaCheckBox implements HasCellAlignment { public CheckBoxCell() { super(); addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { event.stopPropagation(); } }); } @Override public HorizontalAlignmentConstant getCellAlignment() { return HasHorizontalAlignment.ALIGN_CENTER; } } public void setBackGroundColor(int row, String color) { String style = getRowFormatter().getStyleName(row); if (style != null && !style.isEmpty()) { if (color == null || color.isEmpty()) iLastHoverBackgroundColor.remove(row); else iLastHoverBackgroundColor.put(row, color); } else { if (color == null || color.isEmpty()) getRowFormatter().getElement(row).getStyle().clearBackgroundColor(); else getRowFormatter().getElement(row).getStyle().setBackgroundColor(color); } } }