Package com.google.gwt.widgetideas.table.client

Source Code of com.google.gwt.widgetideas.table.client.SelectionGrid$SelectionGridCellFormatter

/*
* Copyright 2008 Google Inc.
*
* Licensed 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 com.google.gwt.widgetideas.table.client;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.widgetideas.table.client.overrides.Grid;
import com.google.gwt.widgetideas.table.client.overrides.OverrideDOM;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
* A variation of the {@link Grid} that supports row or cell hovering and row
* selection.
*
* <h3>CSS Style Rules</h3>
* <ul class="css">
* <li> tr.selected { applied to selected rows } </li>
* <li> tr.hovering { applied to row currently being hovered } </li>
* <li> td.hovering { applied to cell currently being hovered } </li>
* </ul>
*/
public class SelectionGrid extends Grid implements SourceTableSelectionEvents {
  /**
   * This class contains methods used to format a table's cells.
   */
  public class SelectionGridCellFormatter extends CellFormatter {
    @Override
    protected Element getRawElement(int row, int column) {
      return super.getRawElement(row, column);
    }
  }

  /**
   * This class contains methods used to format a table's rows.
   */
  public class SelectionGridRowFormatter extends RowFormatter {
    @Override
    protected Element getRawElement(int row) {
      return super.getRawElement(row);
    }
  }

  /**
   * Selection policies.
   *
   * <ul>
   * <li>DISABLED - selection is disabled</li>
   * <li>ONE_ROW - one row can be selected at a time</li>
   * <li>MULTI_ROW - multiple rows can be selected at a time</li>
   * </ul>
   */
  public static enum SelectionPolicy {
    DISABLED, ONE_ROW, MULTI_ROW
  }

  /**
   * The cell element currently being hovered.
   */
  private Element hoveringCellElem = null;

  /**
   * The index of the cell currently being hovered.
   */
  private int hoveringCellIndex = -1;

  /**
   * The row element currently being hovered.
   */
  private Element hoveringRowElem = null;

  /**
   * The index of the row currently being hovered.
   */
  private int hoveringRowIndex = -1;

  /**
   * The index of the row that the user selected last.
   */
  private int lastSelectedRowIndex = -1;

  /**
   * The rows that are currently selected.
   */
  private Map<Integer, Element> selectedRows = new HashMap<Integer, Element>();

  /**
   * The selection policy determines if the user can select zero, one, or many
   * rows.
   */
  private SelectionPolicy selectionPolicy = SelectionPolicy.MULTI_ROW;

  /**
   * The {@link TableSelectionListener}s attached to this grid.
   */
  private TableSelectionListenerCollection tableSelectionListeners = null;

  /**
   * Constructor.
   */
  public SelectionGrid() {
    super();
    setCellFormatter(new SelectionGridCellFormatter());
    setRowFormatter(new SelectionGridRowFormatter());

    // Sink hover and selection events
    sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONMOUSEDOWN);
  }

  /**
   * Constructs a {@link SelectionGrid} with the requested size.
   *
   * @param rows the number of rows
   * @param columns the number of columns
   * @throws IndexOutOfBoundsException
   */
  public SelectionGrid(int rows, int columns) {
    this();
    resize(rows, columns);
  }

  /**
   * Add a {@link TableSelectionListener}.
   *
   * @param listener the listener
   */
  public void addTableSelectionListener(TableSelectionListener listener) {
    if (tableSelectionListeners == null) {
      tableSelectionListeners = new TableSelectionListenerCollection();
    }
    tableSelectionListeners.add(listener);
  }

  /**
   * Deselect a row in the grid. This method is safe to call even if the row is
   * not selected, or doesn't exist (out of bounds).
   *
   * @param row the row index
   */
  public void deselectRow(int row) {
    Element rowElem = selectedRows.remove(new Integer(row));
    if (rowElem != null) {
      setStyleName(rowElem, "selected", false);
      if (tableSelectionListeners != null) {
        tableSelectionListeners.fireRowDeselected(this, row);
      }
    }
  }

  /**
   * Deselect all selected rows in the data table.
   */
  public void deselectRows() {
    // Deselect all rows
    for (Map.Entry<Integer, Element> entry : selectedRows.entrySet()) {
      setStyleName(entry.getValue(), "selected", false);
    }

    // Fire grid listeners
    if (tableSelectionListeners != null) {
      tableSelectionListeners.fireAllRowsDeselected(this);
    }

    // Clear out the rows
    selectedRows.clear();
  }

  /**
   * @return the set of selected row indexes
   */
  public Set<Integer> getSelectedRows() {
    return selectedRows.keySet();
  }

  /**
   * Explicitly gets the {@link SelectionGridCellFormatter}. The results of
   * {@link com.google.gwt.widgetideas.table.client.overrides.HTMLTable#getCellFormatter()}
   * may also be downcast to a {@link SelectionGridCellFormatter}.
   *
   * @return the FlexTable's cell formatter
   */
  public SelectionGridCellFormatter getSelectionGridCellFormatter() {
    return (SelectionGridCellFormatter) getCellFormatter();
  }

  /**
   * Explicitly gets the {@link SelectionGridRowFormatter}. The results of
   * {@link com.google.gwt.widgetideas.table.client.overrides.HTMLTable#getRowFormatter()}
   * may also be downcast to a {@link SelectionGridRowFormatter}.
   *
   * @return the FlexTable's cell formatter
   */
  public SelectionGridRowFormatter getSelectionGridRowFormatter() {
    return (SelectionGridRowFormatter) getRowFormatter();
  }

  /**
   * @return the selection policy
   */
  public SelectionPolicy getSelectionPolicy() {
    return selectionPolicy;
  }

  /**
   * @param row the row index
   * @return true if the row is selected, false if not
   */
  public boolean isRowSelected(int row) {
    return selectedRows.containsKey(new Integer(row));
  }

  /**
   * @see com.google.gwt.widgetideas.table.client.overrides.HTMLTable
   */
  @Override
  public void onBrowserEvent(Event event) {
    super.onBrowserEvent(event);
    Element targetRow = null;
    Element targetCell = null;

    switch (DOM.eventGetType(event)) {
      // Hover the cell on mouse over
      case Event.ONMOUSEOVER:
        Element cellElem = getEventTargetCell(event);
        if (cellElem != null) {
          hoverCell(cellElem);
        }
        break;

      // Unhover on mouse out
      case Event.ONMOUSEOUT:
        Element toElem = DOM.eventGetToElement(event);
        if (hoveringRowElem != null
            && (toElem == null || !DOM.isOrHasChild(hoveringRowElem, toElem))) {
          // Check that the coordinates are not directly over the cell
          int clientX = DOM.eventGetClientX(event);
          int clientY = DOM.eventGetClientY(event);
          int rowLeft = DOM.getAbsoluteLeft(hoveringRowElem);
          int rowTop = DOM.getAbsoluteTop(hoveringRowElem);
          int rowWidth = DOM.getElementPropertyInt(hoveringRowElem,
              "offsetWidth");
          int rowHeight = DOM.getElementPropertyInt(hoveringRowElem,
              "offsetHeight");
          int rowBottom = rowTop + rowHeight;
          int rowRight = rowLeft + rowWidth;
          if (clientX > rowLeft && clientX < rowRight && clientY > rowTop
              && clientY < rowBottom) {
            return;
          }

          // Unhover the current cell
          hoverCell(null);
        }
        break;

      // Select a row on click
      case Event.ONMOUSEDOWN:
        // Get the target row
        targetCell = getEventTargetCell(event);
        if (targetCell == null) {
          return;
        }
        targetRow = DOM.getParent(targetCell);
        int targetRowIndex = getRowIndex(targetRow);

        // Select the row
        if (selectionPolicy == SelectionPolicy.MULTI_ROW) {
          boolean shiftKey = DOM.eventGetShiftKey(event);
          boolean ctrlKey = DOM.eventGetCtrlKey(event)
              || DOM.eventGetMetaKey(event);

          // Prevent default text selection
          if (ctrlKey || shiftKey) {
            DOM.eventPreventDefault(event);
          }

          // Select the rows
          selectRow(targetRowIndex, ctrlKey, shiftKey);
        } else if (selectionPolicy == SelectionPolicy.ONE_ROW) {
          selectRow(-1, targetRow, true, true);
          lastSelectedRowIndex = targetRowIndex;
          break;
        }
        break;
    }
  }

  /**
   * Remove a {@link TableSelectionListener}.
   *
   * @param listener the listener to remove
   */
  public void removeTableSelectionListener(TableSelectionListener listener) {
    if (tableSelectionListeners != null) {
      tableSelectionListeners.remove(listener);
    }
  }

  /**
   * Select a row in the data table.
   *
   * @param row the row index
   * @param unselectAll unselect all other rows first
   * @throws IndexOutOfBoundsException
   */
  public void selectRow(int row, boolean unselectAll) {
    selectRow(row, getRowFormatter().getElement(row), unselectAll, true);
  }

  /**
   * Select a row in the data table. Simulate the effect of a shift click and/or
   * control click. This method ignores the selection policy, which only applies
   * to user selection via mouse events.
   *
   * @param row the row index
   * @param ctrlKey true to simulate a control click
   * @param shiftKey true to simulate a shift selection
   * @throws IndexOutOfBoundsException
   */
  public void selectRow(int row, boolean ctrlKey, boolean shiftKey) {
    // Check the row bounds
    checkRowBounds(row);

    // Deselect all rows
    if (!ctrlKey) {
      deselectRows();
    }

    if (shiftKey && (lastSelectedRowIndex > -1)) {
      // Shift+select rows
      SelectionGridRowFormatter formatter = getSelectionGridRowFormatter();
      int firstRow = Math.min(row, lastSelectedRowIndex);
      int lastRow = Math.max(row, lastSelectedRowIndex);
      lastRow = Math.min(lastRow, getRowCount() - 1);
      for (int curRow = firstRow; curRow <= lastRow; curRow++) {
        selectRow(curRow, formatter.getRawElement(curRow), false, false);
      }

      // Fire grid listeners
      if (tableSelectionListeners != null) {
        tableSelectionListeners.fireRowsSelected(this, firstRow, lastRow
            - firstRow + 1);
      }
    } else if (selectedRows.containsKey(new Integer(row))) {
      // Ctrl+unselect a selected row
      deselectRow(row);
      lastSelectedRowIndex = row;
    } else {
      // Select the row
      SelectionGridRowFormatter formatter = getSelectionGridRowFormatter();
      selectRow(row, formatter.getRawElement(row), false, true);
      lastSelectedRowIndex = row;
    }
  }

  /**
   * Set the selection policy, which determines if the user can select zero,
   * one, or multiple rows.
   *
   * @param selectionPolicy the selection policy
   */
  public void setSelectionPolicy(SelectionPolicy selectionPolicy) {
    if (this.selectionPolicy != selectionPolicy) {
      deselectRows();
      this.selectionPolicy = selectionPolicy;
    }
  }

  /**
   * @return a map or selected row indexes to their elements
   */
  protected Map<Integer, Element> getSelectedRowsMap() {
    return selectedRows;
  }

  /**
   * Set the current hovering cell.
   *
   * @param cellElem the cell element
   */
  protected void hoverCell(Element cellElem) {
    // Ignore if the cell is already being hovered
    if (DOM.compare(cellElem, hoveringCellElem)) {
      return;
    }

    // Get the row element
    Element rowElem = null;
    if (cellElem != null) {
      rowElem = DOM.getParent(cellElem);
    }

    // Unhover the current cell
    if (hoveringCellElem != null) {
      setStyleName(hoveringCellElem, "hovering", false);
      if (tableSelectionListeners != null) {
        tableSelectionListeners.fireCellUnhover(this, hoveringRowIndex,
            hoveringCellIndex);
      }
      hoveringCellElem = null;
      hoveringCellIndex = -1;

      // Unhover the current row if it changed
      if (!DOM.compare(rowElem, hoveringRowElem)) {
        setStyleName(hoveringRowElem, "hovering", false);
        if (tableSelectionListeners != null) {
          tableSelectionListeners.fireRowUnhover(this, hoveringRowIndex);
        }
        hoveringRowElem = null;
        hoveringRowIndex = -1;
      }
    }

    // Hover the cell
    if (cellElem != null) {
      setStyleName(cellElem, "hovering", true);
      hoveringCellElem = cellElem;
      hoveringCellIndex = OverrideDOM.getCellIndex(cellElem);

      // Hover the row if it changed
      if (hoveringRowElem == null) {
        setStyleName(rowElem, "hovering", true);
        hoveringRowElem = rowElem;
        hoveringRowIndex = getRowIndex(hoveringRowElem);
        if (tableSelectionListeners != null) {
          tableSelectionListeners.fireRowHover(this, hoveringRowIndex);
        }
      }

      // Fire listeners
      if (tableSelectionListeners != null) {
        tableSelectionListeners.fireCellHover(this, hoveringRowIndex,
            hoveringCellIndex);
      }
    }
  }

  /**
   * @see com.google.gwt.widgetideas.table.client.overrides.HTMLTable
   */
  @Override
  protected int insertRow(int beforeRow) {
    deselectRows();
    return super.insertRow(beforeRow);
  }

  /**
   * @see com.google.gwt.widgetideas.table.client.overrides.HTMLTable
   */
  @Override
  protected void removeRow(int row) {
    super.removeRow(row);
    deselectRows();
  }

  /**
   * Select a row in the data table.
   *
   * @param row the row index, or -1 if unknown
   * @param rowElem the row element
   * @param unselectAll true to unselect all currently selected rows
   * @param fireEvent true to fire the select event to listeners
   */
  protected void selectRow(int row, Element rowElem, boolean unselectAll,
      boolean fireEvent) {
    // Get the row index if needed
    if (row < 0) {
      row = getRowIndex(rowElem);
    }

    // Ignore request if row already selected
    Integer rowI = new Integer(row);
    if (selectedRows.containsKey(rowI)) {
      return;
    }

    // Deselect current rows
    if (unselectAll) {
      deselectRows();
    }

    // Select the new row
    selectedRows.put(rowI, rowElem);
    setStyleName(rowElem, "selected", true);

    // Fire grid listeners
    if (fireEvent && tableSelectionListeners != null) {
      tableSelectionListeners.fireRowsSelected(this, row, 1);
    }
  }
}
TOP

Related Classes of com.google.gwt.widgetideas.table.client.SelectionGrid$SelectionGridCellFormatter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.