/* * Ext GWT 2.2.4 - Ext for GWT * Copyright(c) 2007-2010, Ext JS, LLC. * licensing@extjs.com * * http://extjs.com/license */ package com.extjs.gxt.ui.client.widget.grid; import com.extjs.gxt.ui.client.GXT; import com.extjs.gxt.ui.client.data.ModelData; import com.extjs.gxt.ui.client.event.DomEvent; import com.extjs.gxt.ui.client.event.EditorEvent; import com.extjs.gxt.ui.client.event.EventType; import com.extjs.gxt.ui.client.event.Events; import com.extjs.gxt.ui.client.event.GridEvent; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.store.ListStore; import com.extjs.gxt.ui.client.store.Record; import com.extjs.gxt.ui.client.widget.grid.EditorGrid.ClicksToEdit; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; @SuppressWarnings("deprecation") public class EditorSupport<M extends ModelData> { protected Grid<M> grid; protected ListStore<M> store; protected ColumnModel cm; protected CellEditor activeEditor; protected Listener<DomEvent> editorListener; protected Record activeRecord; protected boolean editing; protected boolean ignoreScroll; protected ClicksToEdit clicksToEdit = ClicksToEdit.ONE; protected Listener<GridEvent<M>> gridListener; @SuppressWarnings({"unchecked", "rawtypes"}) public void bind(Grid grid) { this.grid = grid; this.store = grid.getStore(); this.cm = grid.getColumnModel(); } public void doRender() { gridListener = new Listener<GridEvent<M>>() { public void handleEvent(GridEvent<M> e) { EventType type = e.getType(); if (type == Events.BodyScroll) { if (!ignoreScroll) { stopEditing(true); } } else if (type == Events.CellClick || type == Events.CellDoubleClick) { e.cancelBubble(); onCellDoubleClick(e); } } }; grid.addListener(Events.BodyScroll, gridListener); if (clicksToEdit == ClicksToEdit.ONE) { grid.addListener(Events.CellClick, gridListener); } else { grid.addListener(Events.CellDoubleClick, gridListener); } grid.addStyleName("x-edit-grid"); if (GXT.isSafari) { grid.el().setTop(0); grid.el().setScrollTop(0); grid.el().makePositionable(); } } public CellEditor getActiveEditor() { return activeEditor; } /** * Returns the clicks to edit. * * @return the clicks to edit */ public ClicksToEdit getClicksToEdit() { return clicksToEdit; } /** * Returns true if editing is active. * * @return the editing state */ public boolean isEditing() { return editing; } public boolean onDoubleClick(GridEvent<M> e) { if (clicksToEdit == ClicksToEdit.TWO) { if (e.getRowIndex() != -1) { grid.fireEvent(Events.RowDoubleClick, e); if (e.getColIndex() != -1) { grid.fireEvent(Events.CellDoubleClick, e); } } return true; } return false; } /** * Sets the number of clicks to edit (defaults to ONE). * * @param clicksToEdit the clicks to edit */ public void setClicksToEdit(ClicksToEdit clicksToEdit) { this.clicksToEdit = clicksToEdit; } public void startEditing(final int row, final int col) { stopEditing(); if (cm.isCellEditable(col)) { final M m = store.getAt(row); final String field = cm.getDataIndex(col); GridEvent<M> e = new GridEvent<M>(grid); e.setModel(m); e.setRecord(store.getRecord(m)); e.setProperty(field); e.setRowIndex(row); e.setColIndex(col); e.setValue(m.get(field)); if (grid.fireEvent(Events.BeforeEdit, e)) { grid.getView().ensureVisible(row, col, false); DeferredCommand.addCommand(new Command() { public void execute() { deferStartEditing(m, field, row, col); } }); } } } public void stopEditing() { stopEditing(false); } /** * Stops any active editing. * * @param cancel true to cancel, false to complete */ public void stopEditing(boolean cancel) { if (activeEditor != null) { if (cancel) { activeEditor.cancelEdit(); } else { activeEditor.completeEdit(); } } } protected void deferStartEditing(M m, String field, int row, int col) { editing = true; CellEditor ed = cm.getEditor(col); ed.row = row; ed.col = col; activeRecord = store.getRecord(m); if (!ed.isRendered()) { ed.render((Element) grid.getView().getEditorParent()); } if (editorListener == null) { editorListener = new Listener<DomEvent>() { public void handleEvent(DomEvent e) { if (e.getType() == Events.Complete) { EditorEvent ee = (EditorEvent) e; onEditComplete((CellEditor) ee.getEditor(), ee.getValue(), ee.getStartValue()); } else if (e.getType() == Events.SpecialKey) { grid.getSelectionModel().onEditorKey(e); } else if (e.getType() == Events.CancelEdit) { EditorEvent ee = (EditorEvent) e; onEditCancel((CellEditor) ee.getEditor(), ee.getValue(), ee.getStartValue()); } } }; } ed.addListener(Events.Complete, editorListener); ed.addListener(Events.SpecialKey, editorListener); ed.addListener(Events.CancelEdit, editorListener); activeEditor = ed; // when inserting the editor into the last row, the body is // scrolling and edit is being cancelled ignoreScroll = true; ed.startEdit((Element) grid.getView().getCell(row, col), m.get(field)); DeferredCommand.addCommand(new Command() { public void execute() { ignoreScroll = false; } }); } protected void onAutoEditClick(GridEvent<M> e) { if (e.getEvent().getButton() != Event.BUTTON_LEFT) { return; } int row = grid.getView().findRowIndex(e.getTarget()); int cell = grid.getView().findRowIndex(e.getTarget()); if (row != -1 && cell != -1) { stopEditing(); } } protected void onCellDoubleClick(GridEvent<M> e) { startEditing(e.getRowIndex(), e.getColIndex()); } protected void onEditCancel(CellEditor ed, Object value, Object startValue) { editing = false; activeEditor = null; activeRecord = null; ed.removeListener(Events.SpecialKey, editorListener); ed.removeListener(Events.Complete, editorListener); ed.removeListener(Events.CancelEdit, editorListener); grid.getView().focusCell(ed.row, ed.col, false); } protected void onEditComplete(CellEditor ed, Object value, Object startValue) { editing = false; activeEditor = null; ed.removeListener(Events.SpecialKey, editorListener); ed.removeListener(Events.Complete, editorListener); ed.removeListener(Events.CancelEdit, editorListener); Record r = activeRecord; activeRecord = null; String field = cm.getDataIndex(ed.col); GridEvent<M> ge = new GridEvent<M>(grid); ge.setRecord(r); ge.setProperty(field); ge.setValue(value); ge.setStartValue(startValue); ge.setRowIndex(ed.row); ge.setColIndex(ed.col); if (grid.fireEvent(Events.ValidateEdit, ge)) { r.setValid(ge.getProperty(), ed.getField().isValid(true)); r.set(ge.getProperty(), ge.getValue()); grid.fireEvent(Events.AfterEdit, ge); } grid.getView().focusCell(ed.row, ed.col, false); } }