blob: c5070039780f879996a9eecde283534e3f2f569d [file] [log] [blame]
/*
* 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.user.datepicker.client;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.KeyDownEvent;
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.impl.ElementMapperImpl;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.UIObject;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Highlighting, selectable cell grid. Used to help construct the default
* calendar view.
*
* @param <V> type of value in grid.
*/
@SuppressWarnings("unchecked")
abstract class CellGridImpl<V> extends Grid {
/**
* Cell type.
*/
public abstract class Cell extends UIObject {
private boolean enabled = true;
private V value;
private int index;
/**
* Create a cell grid.
*
* @param elem the wrapped element
* @param value the value
*/
public Cell(Element elem, V value) {
this.value = value;
Cell current = this;
index = cellList.size();
cellList.add(current);
setElement(elem);
elementToCell.put(current);
}
public V getValue() {
return value;
}
public boolean isEnabled() {
return enabled;
}
public boolean isHighlighted() {
return this == highlightedCell;
}
public boolean isSelected() {
return selectedCell == this;
}
public final void setEnabled(boolean enabled) {
this.enabled = enabled;
onEnabled(enabled);
}
public void verticalNavigation(int keyCode) {
switch (keyCode) {
case KeyCodes.KEY_UP:
setHighlighted(previousItem());
break;
case KeyCodes.KEY_DOWN:
setHighlighted(nextItem());
break;
case KeyCodes.KEY_ESCAPE:
// Figure out new event for this.
break;
case KeyCodes.KEY_ENTER:
setSelected(this);
break;
}
}
protected Cell nextItem() {
if (index == getLastIndex()) {
return cellList.get(0);
} else {
return cellList.get(index + 1);
}
}
/**
* @param enabled
*/
protected void onEnabled(boolean enabled) {
updateStyle();
}
/**
* @param highlighted
*/
protected void onHighlighted(boolean highlighted) {
updateStyle();
}
/**
* @param selected
*/
protected void onSelected(boolean selected) {
updateStyle();
}
protected Cell previousItem() {
if (index != 0) {
return cellList.get(index - 1);
} else {
return cellList.get(getLastIndex());
}
}
protected abstract void updateStyle();
private int getLastIndex() {
return cellList.size() - 1;
}
}
private Cell highlightedCell;
private Cell selectedCell;
private ElementMapperImpl<Cell> elementToCell = new ElementMapperImpl<Cell>();
private ArrayList<Cell> cellList = new ArrayList<Cell>();
protected CellGridImpl() {
setCellPadding(0);
setCellSpacing(0);
setBorderWidth(0);
sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT);
}
public Cell getCell(Element element) {
// This cast is always valid because both Element types are JSOs and have
// no new fields are added in the subclass.
return elementToCell.get((com.google.gwt.user.client.Element) element);
}
public Cell getCell(Event e) {
// Find out which cell was actually clicked.
Element td = getEventTargetCell(e);
return td != null
? elementToCell.get((com.google.gwt.user.client.Element) td) : null;
}
public Cell getCell(int i) {
return cellList.get(i);
}
public Iterator getCells() {
return cellList.iterator();
}
public Cell getHighlightedCell() {
return highlightedCell;
}
public int getNumCells() {
return cellList.size();
}
public Cell getSelectedCell() {
return selectedCell;
}
public V getSelectedValue() {
return getValue(selectedCell);
}
public V getValue(Cell cell) {
return (cell == null ? null : cell.getValue());
}
@Override
public void onBrowserEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONCLICK: {
Cell cell = getCell(event);
if (isActive(cell)) {
setSelected(cell);
}
break;
}
case Event.ONMOUSEOUT: {
Element e = DOM.eventGetFromElement(event);
if (e != null) {
Cell cell = elementToCell.get((com.google.gwt.user.client.Element) e);
if (cell == highlightedCell) {
setHighlighted(null);
}
}
break;
}
case Event.ONMOUSEOVER: {
Element e = DOM.eventGetToElement(event);
if (e != null) {
Cell cell = elementToCell.get((com.google.gwt.user.client.Element) e);
if (isActive(cell)) {
setHighlighted(cell);
}
}
break;
}
}
}
@Override
public void onUnload() {
setHighlighted(null);
}
public final void setHighlighted(Cell nextHighlighted) {
if (nextHighlighted == highlightedCell) {
return;
}
Cell oldHighlighted = highlightedCell;
highlightedCell = nextHighlighted;
if (oldHighlighted != null) {
oldHighlighted.onHighlighted(false);
}
if (highlightedCell != null) {
highlightedCell.onHighlighted(true);
}
}
public final void setSelected(Cell cell) {
Cell last = getSelectedCell();
selectedCell = cell;
if (last != null) {
last.onSelected(false);
}
if (selectedCell != null) {
selectedCell.onSelected(true);
}
onSelected(last, selectedCell);
}
protected void onKeyDown(Cell lastHighlighted, KeyDownEvent event) {
if (event.isAnyModifierKeyDown()) {
return;
}
int keyCode = event.getNativeKeyCode();
if (lastHighlighted == null) {
if (keyCode == KeyCodes.KEY_DOWN && cellList.size() > 0) {
setHighlighted(cellList.get(0));
}
} else {
lastHighlighted.verticalNavigation(keyCode);
}
}
protected abstract void onSelected(Cell lastSelected, Cell cell);
private boolean isActive(Cell cell) {
return cell != null && cell.isEnabled();
}
}