001: /*
002: * MyGWT Widget Library
003: * Copyright(c) 2007, MyGWT.
004: * licensing@mygwt.net
005: *
006: * http://mygwt.net/license
007: */
008: package net.mygwt.ui.client.widget.table;
009:
010: import java.util.ArrayList;
011: import java.util.List;
012:
013: import net.mygwt.ui.client.Events;
014: import net.mygwt.ui.client.MyGWT;
015: import net.mygwt.ui.client.Style;
016: import net.mygwt.ui.client.event.BaseEvent;
017: import net.mygwt.ui.client.event.Listener;
018:
019: import com.google.gwt.user.client.DOM;
020: import com.google.gwt.user.client.Element;
021: import com.google.gwt.user.client.ui.KeyboardListener;
022:
023: /**
024: * Row selection model.
025: *
026: * <dl>
027: * <dt><b>Styles:</b></dt>
028: * <dd>SINGLE, MULTI</dd>
029: * </dl>
030: */
031: public class RowSelectionModel implements Listener {
032:
033: protected int style;
034: protected Table table;
035: protected List selectedItems;
036: protected TableItem lastSelected;
037:
038: /**
039: * Creates a new selection model.
040: *
041: * @param style the style information
042: */
043: public RowSelectionModel(int style) {
044: this .style = style;
045: selectedItems = new ArrayList();
046: }
047:
048: /**
049: * Deselects the item at the given index. If the item at the index was already
050: * deselected, it remains deselected.
051: *
052: * @param index the item to deselect
053: */
054: public void deselect(int index) {
055: selectItems(index, index, false, true);
056: }
057:
058: /**
059: * Deselects the items at the given indices. If the item at the given index is
060: * selected, it is deselected. If the item at the index was not selected, it
061: * remains deselected.
062: *
063: * @param begin the start index
064: * @param end the end index
065: */
066: public void deselect(int begin, int end) {
067: selectItems(begin, end, false, true);
068: }
069:
070: /**
071: * Deselects all selections.
072: */
073: public void deselectAll() {
074: while (selectedItems.size() > 0) {
075: TableItem item = (TableItem) selectedItems.remove(0);
076: deselect(table.indexOf(item));
077:
078: }
079: lastSelected = null;
080: }
081:
082: public void handleEvent(BaseEvent be) {
083: switch (be.type) {
084: case Events.CellClick:
085: onCellClick(be);
086: break;
087: case Events.CellDoubleClick:
088: onCellDoubleClick(be);
089: break;
090: case Events.KeyDown:
091: onKeyPress(be);
092: break;
093: case Events.Remove:
094: TableItem item = (TableItem) be.item;
095: if (lastSelected == item) {
096: lastSelected = null;
097: }
098: selectedItems.remove(item);
099: }
100: }
101:
102: /**
103: * Returns <code>true</code> if the row is selected.
104: *
105: * @param index the row index
106: * @return the selected state
107: */
108: public boolean isSelected(int index) {
109: TableItem item = table.getItem(index);
110: return selectedItems.contains(item);
111: }
112:
113: /**
114: * Refreshes the selections.
115: */
116: public void refresh() {
117: int rows = table.getItemCount();
118: for (int i = 0; i < rows; i++) {
119: TableItem item = table.getItem(i);
120: item.setSelected(isSelected(i));
121: }
122: }
123:
124: /**
125: * Selects the item at the given index. If the item at the index was already
126: * selected, it remains selected.
127: *
128: * @param index the row to select
129: */
130: public void select(int index) {
131: selectItems(index, index, true, true);
132: }
133:
134: /**
135: * Selects the item in the range specified by the given indices. The current
136: * selection is not cleared before the new rows are selected.
137: *
138: * @param start the start of the range
139: * @param end the end of the range
140: */
141: public void select(int start, int end) {
142: selectItems(start, end, true, true);
143: }
144:
145: /**
146: * Selects all items.
147: */
148: public void selectAll() {
149: selectItems(0, table.getItemCount() - 1, true, true);
150: }
151:
152: protected void init(Table table) {
153: this .table = table;
154: table.addListener(Events.CellClick, this );
155: table.addListener(Events.CellDoubleClick, this );
156: table.addListener(Events.KeyDown, this );
157: table.addListener(Events.Remove, this );
158: }
159:
160: protected void unbind(Table table) {
161: this .table = null;
162: table.removeListener(Events.CellClick, this );
163: table.removeListener(Events.CellDoubleClick, this );
164: table.removeListener(Events.KeyDown, this );
165: table.removeListener(Events.Remove, this );
166: }
167:
168: protected void onCellClick(BaseEvent be) {
169: int row = be.rowIndex;
170: boolean shiftkey = be.isShiftKey();
171: boolean controlKey = be.isControlKey();
172:
173: boolean single = style == Style.SINGLE;
174: if (single) {
175: selectItems(row, row, !(isSelected(row) && controlKey),
176: false);
177: return;
178: }
179:
180: if (be.isRightClick()) {
181: TableItem item = table.findItem(be.getTarget());
182: if (selectedItems.contains(item)) {
183: return;
184: }
185: }
186:
187: if (shiftkey) {
188: if (lastSelected != null) {
189: selectItems(table.indexOf(lastSelected), row, true,
190: false);
191: } else {
192: selectItems(0, row, true, false);
193: }
194: } else if (controlKey) {
195: selectItems(row, row, !isSelected(row), true);
196: } else {
197: selectItems(row, row, true, false);
198: }
199:
200: // safari needs focus put on table of click unless
201: // the source is a widget - determined by sunk events
202: if (MyGWT.isSafari) {
203: Element elem = be.getTarget();
204: if (DOM.getEventsSunk(elem) == 0) {
205: table.focus();
206: }
207:
208: }
209: }
210:
211: protected void onCellDoubleClick(BaseEvent be) {
212:
213: }
214:
215: protected void onKeyPress(BaseEvent be) {
216: int code = be.getKeyCode();
217: switch (code) {
218: case KeyboardListener.KEY_UP: {
219: int index = table.indexOf(lastSelected) - 1;
220: selectItems(index, index, true, false);
221: be.stopEvent();
222: break;
223: }
224: case KeyboardListener.KEY_DOWN: {
225: int index = table.indexOf(lastSelected) + 1;
226: selectItems(index, index, true, false);
227: be.stopEvent();
228: break;
229: }
230:
231: }
232: }
233:
234: protected void remove(TableItem item) {
235: if (lastSelected == item) {
236: lastSelected = null;
237: }
238: if (selectedItems.remove(item)) {
239: BaseEvent be = new BaseEvent();
240: be.widget = table;
241: table.fireEvent(Events.SelectionChange, be);
242: }
243: }
244:
245: protected void selectItems(final int start, final int end,
246: final boolean state, final boolean keepSelected) {
247: if (!table.isRendered()) {
248: table.addListener(Events.Render, new Listener() {
249: public void handleEvent(BaseEvent be) {
250: selectItems(start, end, state, keepSelected);
251: }
252: });
253: return;
254: }
255: if (start < 0 || end >= table.getItemCount())
256: return;
257: if (!keepSelected) {
258: for (int i = 0; selectedItems.size() > 0; i++) {
259: TableItem item = (TableItem) selectedItems.remove(0);
260: item.setSelected(false);
261: }
262: }
263: lastSelected = table.getItem(end);
264: int beginIndex = start < end ? start : end;
265: int endIndex = start < end ? end : start;
266: for (int i = beginIndex; i <= endIndex; i++) {
267: boolean sel = isSelected(i);
268: TableItem item = table.getItem(i);
269: if (state) {
270: if (!sel) {
271: selectedItems.add(item);
272: }
273: table.scrollIntoView(item);
274: } else {
275: selectedItems.remove(item);
276: }
277: item.setSelected(state);
278: }
279:
280: // safari needs focus on table for keyboard navigation
281: if (MyGWT.isSafari) {
282: table.focus();
283: }
284:
285: BaseEvent be = new BaseEvent();
286: be.widget = table;
287: table.fireEvent(Events.SelectionChange, be);
288: }
289:
290: List getSelection() {
291: return selectedItems;
292: }
293:
294: }
|