/****************************************************************************** * Copyright (C) 2016 Logilite Technologies LLP * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * *****************************************************************************/ package org.adempiere.webui.adwindow; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.adempiere.util.GridRowCtx; import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.component.Button; import org.adempiere.webui.component.Checkbox; import org.adempiere.webui.component.Combinationbox; import org.adempiere.webui.component.ComboEditorBox; import org.adempiere.webui.component.Combobox; import org.adempiere.webui.component.Datebox; import org.adempiere.webui.component.DatetimeBox; import org.adempiere.webui.component.EditorBox; import org.adempiere.webui.component.FilenameBox; import org.adempiere.webui.component.Locationbox; import org.adempiere.webui.component.NumberBox; import org.adempiere.webui.component.PAttributebox; import org.adempiere.webui.component.Paymentbox; import org.adempiere.webui.component.Searchbox; import org.adempiere.webui.component.Textbox; import org.adempiere.webui.component.Urlbox; import org.adempiere.webui.editor.WButtonEditor; import org.adempiere.webui.editor.WEditor; import org.adempiere.webui.editor.WNumberEditor; import org.adempiere.webui.editor.WPAttributeEditor; import org.adempiere.webui.editor.WSearchEditor; import org.adempiere.webui.editor.WebEditorFactory; import org.adempiere.webui.event.ActionEvent; import org.adempiere.webui.event.ActionListener; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.util.GridTabDataBinder; import org.adempiere.webui.util.ZKUpdateUtil; import org.compiere.model.GridField; import org.compiere.model.GridTab; import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.Msg; import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.HtmlBasedComponent; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.event.KeyEvent; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Cell; import org.zkoss.zul.Column; import org.zkoss.zul.Grid; import org.zkoss.zul.Paging; import org.zkoss.zul.RendererCtrl; import org.zkoss.zul.Row; import org.zkoss.zul.RowRenderer; import org.zkoss.zul.RowRendererExt; import org.zkoss.zul.Timebox; /** * Row renderer for Quick GridTab grid (Base on {@link GridTabRowRenderer}) * * @author Logilite Technologies * @since Nov 03, 2017 */ public class QuickGridTabRowRenderer implements RowRenderer, RowRendererExt, RendererCtrl, EventListener { /** Component boolean attribute to indicate this component is own by QuickGridView **/ public static final String IS_QUICK_FORM_COMPONENT = "IS_QUICK_FORM_COMPONENT"; /** Editor component attribute to store row index (absolute) **/ public static final String GRID_ROW_INDEX_ATTR = "grid.row.index"; private static final String CELL_DIV_STYLE = "height: 100%; cursor: pointer; "; private static final String CELL_DIV_STYLE_ALIGN_CENTER = CELL_DIV_STYLE + "text-align:center; "; private static final String CELL_DIV_STYLE_ALIGN_RIGHT = CELL_DIV_STYLE + "text-align:right; "; public static final String CURRENT_ROW_STYLE = "border-top: 2px solid #6f97d2; border-bottom: 2px solid #6f97d2"; // CSS for Disabled component to visible text properly. public static final String CSS_READ_ONLY_COMPONENT = "quickform-readonly "; private GridTab gridTab; private int windowNo; /** Sync field editor changes to GridField **/ private GridTabDataBinder dataBinder; private Paging paging; /** internal listener for row event **/ private RowListener rowListener; /** Grid that own this renderer **/ private Grid grid = null; /** QuickGridView that uses this renderer **/ private QuickGridView gridPanel = null; /** current focus row **/ private Row currentRow; /** values of current row. updated in {@link #render(Row, Object[], int)}. **/ private Object[] currentValues; /** true if current row is in edit mode **/ private boolean editing = false; public int currentRowIndex = -1; /** AD window content part that own this renderer **/ private AbstractADWindowContent m_windowPanel; /** internal listener for button ActionEvent **/ private ActionListener buttonListener; // Row-wise Editors Map public Map> editorsListMap = new LinkedHashMap>(); // Row-wise read-only Editors Map public Map> readOnlyEditorsListMap = new LinkedHashMap>(); /** * Flag detect this view has customized column or not * value is set at {@link #render(Row, Object[], int)} */ private boolean isGridViewCustomized = false; // Keep track of shorted column in Quick form. private Column sortedColumn = null; // Keep track of sorting order of column in Quick form. for e.g Ascending, Descending and Natural private String sortOrder; /** * * @param gridTab * @param windowNo */ public QuickGridTabRowRenderer(GridTab gridTab, int windowNo) { this.gridTab = gridTab; this.windowNo = windowNo; this.dataBinder = new GridTabDataBinder(gridTab); } /** * Get editor for GridField and set value to object parameter. * @param gridField * @param object * @return {@link WEditor} */ private WEditor getEditorCell(GridField gridField, Object object) { WEditor editor = WebEditorFactory.getEditor(gridField, true); if (editor != null) { prepareFieldEditor(gridField, editor); editor.setValue(object); } return editor; } /** * Setup field editor * @param gridField * @param editor */ private void prepareFieldEditor(GridField gridField, WEditor editor) { if (editor instanceof WButtonEditor) { if (buttonListener != null) { ((WButtonEditor)editor).addActionListener(buttonListener); } else { Object window = SessionManager.getAppDesktop().findWindow(windowNo); if (window != null && window instanceof ADWindow) { AbstractADWindowContent windowPanel = ((ADWindow)window).getADWindowContent(); ((WButtonEditor)editor).addActionListener(windowPanel); } } } //Stretch component to fill grid cell if (editor.getComponent() instanceof HtmlBasedComponent) { editor.fillHorizontal(); } } /** * @param field * @return column index for field, -1 if not found */ public int getColumnIndex(GridField field) { GridField[] fields = gridPanel.getFields(); for(int i = 0; i < fields.length; i++) { if (fields[i] == field) return i; } return 0; } /** * @param paging */ public void setPaging(Paging paging) { this.paging = paging; } /** * Render data for row. * @param row * @param data * @param index */ @Override public void render(Row row, Object[] data, int index) throws Exception { //don't render if not visible int columnCount = 0; GridField[] gridPanelFields = null; GridField[] gridTabFields = null; if (gridPanel != null) { if (!gridPanel.isVisible()) { return; } else{ gridPanelFields = gridPanel.getFields(); columnCount = gridPanelFields.length; gridTabFields = gridTab.getFields(); isGridViewCustomized = gridTabFields.length != gridPanelFields.length; } } if (grid == null) grid = (Grid) row.getParent().getParent(); if (rowListener == null) rowListener = new RowListener((Grid)row.getParent().getParent()); if (!isGridViewCustomized) { for(int i = 0; i < gridTabFields.length; i++) { if (gridPanelFields[i].getAD_Field_ID() != gridTabFields[i].getAD_Field_ID()) { isGridViewCustomized = true; break; } } } if (!isGridViewCustomized) { currentValues = data; } else { List dataList = new ArrayList(); for(GridField gridField : gridPanelFields) { for(int i = 0; i < gridTabFields.length; i++) { gridTabFields[i].setValue(data[i], !gridPanel.isNewLineSaved); if (gridField.getAD_Field_ID() == gridTabFields[i].getAD_Field_ID()) { // Update value of gridField for Context Parsing. gridField.setValue(data[i], !gridPanel.isNewLineSaved); dataList.add(data[i]); break; } } } currentValues = dataList.toArray(new Object[0]); } Grid grid = (Grid) row.getParent().getParent(); org.zkoss.zul.Columns columns = grid.getColumns(); int rowIndex = index; if (paging != null && paging.getPageSize() > 0) { rowIndex = (paging.getActivePage() * paging.getPageSize()) + rowIndex; } Cell cell = new Cell(); cell.setTooltiptext(Msg.getMsg(Env.getCtx(), "Select")); Checkbox selection = new Checkbox(); selection.setAttribute(GRID_ROW_INDEX_ATTR, rowIndex); selection.setChecked(gridTab.isSelected(rowIndex)); cell.setStyle("border: none;"); selection.addEventListener(Events.ON_CHECK, this); if (!selection.isChecked()) { if (gridPanel.selectAll.isChecked()) { gridPanel.selectAll.setChecked(false); } } cell.appendChild(selection); row.appendChild(cell); Boolean isActive = null; int colIndex = -1; // Editors List of Current Rendered Row ArrayList editorsList = new ArrayList(); // Read-only editors List of Current Rendered Row ArrayList readOnlyEditorsList = new ArrayList(); for (int i = 0; i < columnCount; i++) { if (!gridPanelFields[i].isQuickForm()){ continue; } if ("IsActive".equals(gridPanelFields[i].getColumnName())) { isActive = Boolean.FALSE; if (currentValues[i] != null) { if ("true".equalsIgnoreCase(currentValues[i].toString())) { isActive = Boolean.TRUE; } } } // IDEMPIERE-2148: when has tab customize, ignore check properties isDisplayedGrid if ((!isGridViewCustomized && gridPanelFields[i].isDisplayedGrid()) || gridPanelFields[i].isToolbarOnlyButton()) { continue; } colIndex ++; Cell div = new Cell(); String divStyle = CELL_DIV_STYLE; org.zkoss.zul.Column column = (org.zkoss.zul.Column) columns.getChildren().get(colIndex); if (column.isVisible()) { WEditor componentEditor = getEditorCell(gridPanelFields[i], currentValues[i]); editorsList.add(componentEditor); componentEditor.getComponent().addEventListener(Events.ON_FOCUS, gridPanel); Component component = componentEditor.getComponent(); component.setAttribute(IS_QUICK_FORM_COMPONENT, true); div.appendChild(component); div.setAttribute("display.component", component); if (componentEditor instanceof WPAttributeEditor) { ((WPAttributeEditor) componentEditor).getComponent().getButton().addEventListener(Events.ON_FOCUS, gridPanel); } else if (componentEditor instanceof WSearchEditor) { ((WSearchEditor) componentEditor).getComponent().getButton().addEventListener(Events.ON_FOCUS, gridPanel); } else if (componentEditor instanceof WNumberEditor) { ((WNumberEditor) componentEditor).getComponent().getButton().addEventListener(Events.ON_FOCUS, gridPanel); } if (gridPanelFields[i].isHeading()) { component.setVisible(false); } if (DisplayType.YesNo == gridPanelFields[i].getDisplayType() || DisplayType.Image == gridPanelFields[i].getDisplayType()) { divStyle = CELL_DIV_STYLE_ALIGN_CENTER; } else if (DisplayType.isNumeric(gridPanelFields[i].getDisplayType())) { divStyle = CELL_DIV_STYLE_ALIGN_RIGHT; } if (isDisableReadonlyComponent(component, true)) { readOnlyEditorsList.add(componentEditor); } GridRowCtx ctx = new GridRowCtx(Env.getCtx(), gridTab, rowIndex); // Enable or Disable Component componentEditor.setReadWrite(gridPanelFields[i].isEditable(ctx, true, false)); if (!gridPanelFields[i].isDisplayed(ctx, true)){ // IDEMPIERE-2253 component.setVisible(false); } } div.setStyle(divStyle); ZKUpdateUtil.setWidth(div, "100%"); div.setAttribute("columnName", gridPanelFields[i].getColumnName()); div.addEventListener(Events.ON_CLICK, rowListener); div.addEventListener(Events.ON_DOUBLE_CLICK, rowListener); editing = true; GridTableListModel model = (GridTableListModel) grid.getModel(); model.setEditing(true); row.appendChild(div); } editorsListMap.put(row, editorsList); readOnlyEditorsListMap.put(row, readOnlyEditorsList); if (rowIndex == gridTab.getCurrentRow()) { setCurrentRow(row); } row.setStyle("cursor:pointer"); row.addEventListener(Events.ON_CLICK, rowListener); row.addEventListener(Events.ON_OK, rowListener); row.setTooltiptext("Row " + (rowIndex+1)); if (isActive == null) { Object isActiveValue = gridTab.getValue(rowIndex, "IsActive"); if (isActiveValue != null) { if ("true".equalsIgnoreCase(isActiveValue.toString())) { isActive = Boolean.TRUE; } else { isActive = Boolean.FALSE; } } } if (isActive != null && !isActive.booleanValue()) { LayoutUtils.addSclass("grid-inactive-row", row); } if (gridTab.isNew()) gridPanel.isNewLineSaved = false; // Set focus to first editable cell of the last record if multiple // records inserted if (gridPanel.paging.getTotalSize() != gridTab.getRowCount()) { gridPanel.updateListIndex(); if (!gridPanel.isNewLineSaved) { gridPanel.isNewLineSaved = true; paging.setActivePage( paging.getActivePage() + (paging.getActivePage() == (paging.getPageCount() - 1) ? 0 : 1)); gridPanel.listModel.setPage(paging.getActivePage()); gridPanel.updateModelIndex(0); setCurrentCell(gridTab.getRowCount() - 1 % paging.getPageSize() - (paging.getActivePage() * paging.getPageSize()), 1, KeyEvent.RIGHT); } Events.echoEvent(QuickGridView.EVENT_ON_SET_FOCUS_TO_FIRST_CELL, gridPanel, null); } // When shorting is done all rows are rendered and focus is lost. // If record are shorting then set focus to the first row of the current page. Column column = gridPanel.findCurrentSortColumn(); if (column != null && gridPanel.isNewLineSaved && (sortedColumn == null || sortedColumn != column || (sortedColumn == column && sortOrder != column.getSortDirection()))) { sortedColumn = column; sortOrder = column.getSortDirection(); Events.echoEvent(QuickGridView.EVENT_ON_PAGE_NAVIGATE, gridPanel, null); } } /** * Disable Read-only components for while pressing tab button focus goes to * read-only component. * Enable Read-only component before display Logic update. * Add/Remove CSS Class from read-only component * * @param component * @param isDisable * @return true if component is read only */ public boolean isDisableReadonlyComponent(Component component, boolean isDisable) { boolean isReadonly = false; if (component instanceof NumberBox) { NumberBox comp = ((NumberBox) component); if (comp.getDecimalbox().isReadonly()) { comp.getDecimalbox().setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof Textbox) { Textbox comp = ((Textbox) component); if (comp.isReadonly()) { comp.setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof Datebox) { Datebox comp = ((Datebox) component); if (comp.isReadonly()) { comp.setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof DatetimeBox) { DatetimeBox comp = ((DatetimeBox) component); if (comp.getTimebox().isReadonly()) { comp.getTimebox().setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } if (comp.getDatebox().isReadonly()) { comp.getDatebox().setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof Searchbox) { Searchbox comp = ((Searchbox) component); if (comp.getTextbox().isReadonly()) { comp.getTextbox().setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof Combinationbox) { Combinationbox comp = ((Combinationbox) component); if (comp.getTextbox().isReadonly()) { comp.getTextbox().setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof EditorBox) { EditorBox comp = ((EditorBox) component); if (comp.getTextbox().isReadonly()) { comp.getTextbox().setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof Urlbox) { Urlbox comp = ((Urlbox) component); if (comp.getTextbox().isReadonly()) { comp.getTextbox().setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof FilenameBox) { FilenameBox comp = ((FilenameBox) component); if (comp.getTextbox().isReadonly()) { comp.getTextbox().setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof Timebox) { Timebox comp = ((Timebox) component); if (comp.isReadonly()) { comp.setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof Paymentbox) { Paymentbox comp = ((Paymentbox) component); if (comp.getCombobox().isReadonly()) { comp.getCombobox().setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } else if (component instanceof PAttributebox) { PAttributebox comp = ((PAttributebox) component); if (comp.getTextbox().isReadonly()) { comp.getTextbox().setDisabled(isDisable); comp.setZclass(addOrRemoveCssClass(comp.getZclass(), isDisable)); isReadonly = true; } } return isReadonly; } /** * Add/Remove CSS class from Read-only Component * * @param zclass * @param isDisable * @return modify zclass */ private String addOrRemoveCssClass(String zclass, boolean isDisable) { if (zclass == null) zclass = ""; if (isDisable) { zclass += CSS_READ_ONLY_COMPONENT; } else { if (zclass.contains(CSS_READ_ONLY_COMPONENT)) zclass.replaceAll(CSS_READ_ONLY_COMPONENT, ""); } return zclass; } private Cell currentCell = null; /** * @return current {@link Cell} */ public Cell getCurrentCell() { return currentCell; } /** * Set current cell * @param currentCell */ public void setCurrentCell(Cell currentCell) { this.currentCell = currentCell; } /** * Set current cell * @param row * @param col * @param code cell navigation code (right, left, down, up, next) */ public void setCurrentCell(int row, int col, int code) { if (col < 0 || row < 0) return; int currentCol = col; boolean isLastCell = false; while (!isEditable(row, col)) { if (!(code == KeyEvent.RIGHT || code == KeyEvent.LEFT || code == KeyEvent.DOWN || code == KeyEvent.UP || code == QuickGridView.NAVIGATE_CODE)) { break; } else if (code == KeyEvent.RIGHT || code == QuickGridView.NAVIGATE_CODE) { ++col; } else if (code == KeyEvent.LEFT) { --col; } // on UP/DOWN go to next editable field if move field is not // editable else if (code == KeyEvent.DOWN || code == KeyEvent.UP) { if (isLastCell) { col--; } else { col++; if (col > gridPanel.getGridField().length) { col = currentCol; isLastCell = true; } } } if (col < 0 && !isLastCell) { setFocusOnCurrentCell(); return; } } if (isAddRemoveListener(code)) { // Remove current row property change listener addRemovePropertyChangeListener(false, col); } int pgIndex = row >= 0 ? row % paging.getPageSize() : 0; if (row != currentRowIndex || pgIndex != currentRowIndex) { if (currentRow != null) currentRow.setStyle(null); if (grid.getRows().getChildren().size() <= 0) { currentCell = null; return; } gridTab.setCurrentRow(pgIndex + paging.getActivePage() * paging.getPageSize()); currentRow = ((Row) grid.getRows().getChildren().get(pgIndex)); currentRowIndex = gridTab.getCurrentRow(); currentRow.setStyle(CURRENT_ROW_STYLE); } setCurrentRow(currentRow); if (isAddRemoveListener(code)) { // Add property change listener to new current row addRemovePropertyChangeListener(true, col); } if (grid.getCell(pgIndex, col) instanceof Cell) { currentCell = (Cell) grid.getCell(pgIndex, col); } if (currentCell != null && code != QuickGridView.FOCUS_CODE) { setFocusOnCurrentCell(); } } /** * Add property change listener (WEditor) to GridField * * @param editorsList */ private void addEditorPropertyChangeListener(ArrayList editorsList) { GridField[] fields = gridPanel.getFields(); for (int i = 0; i < editorsList.size(); i++) { editorsList.get(i).addValueChangeListener(dataBinder); fields[i].removePropertyChangeListener(editorsList.get(i)); fields[i].addPropertyChangeListener(editorsList.get(i)); } } /** * Remove property change listener (WEditor) from GridField * * @param editorsList */ private void removeEditorPropertyChangeListener(ArrayList editorsList) { GridField[] fields = gridPanel.getFields(); for (int i = 0; i < editorsList.size(); i++) { fields[i].removePropertyChangeListener(editorsList.get(i)); editorsList.get(i).removeValuechangeListener(dataBinder); } } /** * If isAddListener is true add Property Change Listener, otherwise Remove Property Change Listener * * @param isAddListener * @param col */ public void addRemovePropertyChangeListener(boolean isAddListener, int col) { ArrayList editorsList = editorsListMap.get(getCurrentRow()); if (editorsList != null) { if (isAddListener) { addEditorPropertyChangeListener(editorsList); gridPanel.dynamicDisplay(col); } else { removeEditorPropertyChangeListener(editorsList); } } } // addRemovePropertyChangeListener /** * @param code cell navigation code * @return true to add property change listener, false otherwise */ public Boolean isAddRemoveListener(int code) { if (code == KeyEvent.DOWN || code == KeyEvent.UP || code == QuickGridView.FOCUS_CODE || code == QuickGridView.NAVIGATE_CODE || code == KeyEvent.HOME) return true; return false; } // isAddRemoveListener /** * Set current row * @param row absolute row index */ public void setRowTo(int row) { int pgIndex = row >= 0 ? row % paging.getPageSize() : 0; currentRow = ((Row) grid.getRows().getChildren().get(pgIndex)); currentRow.setStyle(QuickGridTabRowRenderer.CURRENT_ROW_STYLE); setCurrentRow(currentRow); } /** * @param row * @param col * @return true if cell is editable, false otherwise */ private boolean isEditable(int row, int col) { Cell cell = null; if (col > getCurrentRow().getChildren().size()) return true; if (grid.getCell(row, col) instanceof Cell) cell = (Cell) grid.getCell(row, col); else return true; if (cell == null) return true; if (cell.getChildren().size() <= 0) return false; // get component of cell Component component = cell.getChildren().get(0); if (component instanceof NumberBox && (!((NumberBox) component).getDecimalbox().isDisabled() && !((NumberBox) component).getDecimalbox().isReadonly() && ((NumberBox) component).getDecimalbox().isVisible())) return true; else if (component instanceof Checkbox && (((Checkbox) component).isEnabled() && ((Checkbox) component).isVisible())) return true; else if (component instanceof Combobox && (!((Combobox) component).isReadonly() && ((Combobox) component).isEnabled() && ((Combobox) component).isVisible())) return true; else if (component instanceof Textbox && (!((Textbox) component).isDisabled() && !((Textbox) component).isReadonly() && ((Textbox) component).isVisible())) return true; else if (component instanceof Datebox && (!((Datebox) component).isReadonly() && ((Datebox) component).isEnabled() && ((Datebox) component).isVisible())) return true; else if (component instanceof DatetimeBox && (((DatetimeBox) component).isEnabled() && ((DatetimeBox) component).isVisible())) return true; else if (component instanceof Locationbox && (((Locationbox) component).isEnabled() && ((Locationbox) component).isVisible())) return true; else if (component instanceof Searchbox && (!((Searchbox) component).getTextbox().isDisabled() && !((Searchbox) component).getTextbox().isReadonly() && ((Searchbox) component).getTextbox().isVisible())) return true; else if (component instanceof Button && (((Button) component).isEnabled() && ((Button) component).isVisible())) return true; else if (component instanceof Combinationbox && (!((Combinationbox) component).getTextbox().isReadonly() && ((Combinationbox) component).isEnabled() && ((Combinationbox) component).isVisible())) return true; else if (component instanceof EditorBox && (!((EditorBox) component).getTextbox().isReadonly() && ((EditorBox) component).isEnabled() && ((EditorBox) component).isVisible())) return true; else if (component instanceof Urlbox && (((Urlbox) component).isEnabled() && ((Urlbox) component).isVisible())) return true; else if (component instanceof FilenameBox && (!((FilenameBox) component).getTextbox().isReadonly() && ((FilenameBox) component).isEnabled() && ((FilenameBox) component).isVisible())) return true; else if (component instanceof Timebox && !((Timebox) component).isReadonly() && ((Timebox) component).isVisible()) return true; else if (component instanceof Paymentbox && (((Paymentbox) component).isEnabled() && ((Paymentbox) component).isVisible())) return true; else if (component instanceof PAttributebox && !((PAttributebox) component).getTextbox().isReadonly() && (((PAttributebox) component).isEnabled() && ((PAttributebox) component).isVisible())) return true; else if (component instanceof ComboEditorBox && !((ComboEditorBox) component).getCombobox().isReadonly() && (((ComboEditorBox) component).isEnabled() && ((ComboEditorBox) component).isVisible())) return true; else return false; } /** * Set focus to {@link #currentCell} */ public void setFocusOnCurrentCell() { if (currentCell == null || currentCell.getChildren().size() <= 0) { return; } Component component = currentCell.getChildren().get(0); if (component instanceof NumberBox) { ((NumberBox) component).focus(); ((NumberBox) component).getDecimalbox().select(); } else if (component instanceof Checkbox) ((Checkbox) component).focus(); else if (component instanceof Combobox) ((Combobox) component).focus(); else if (component instanceof Textbox) { ((Textbox) component).focus(); ((Textbox) component).select(); } else if (component instanceof Datebox) ((Datebox) component).focus(); else if (component instanceof DatetimeBox) ((DatetimeBox) component).focus(); else if (component instanceof Locationbox) ((Locationbox) component).focus(); else if (component instanceof Combinationbox) { ((Combinationbox) component).getTextbox().focus(); ((Combinationbox) component).getTextbox().select(); } else if (component instanceof Searchbox) { ((Searchbox) component).getTextbox().focus(); ((Searchbox) component).getTextbox().select(); } else if (component instanceof Button) ((Button) component).focus(); else if (component instanceof EditorBox) ((EditorBox) component).focus(); else if (component instanceof Urlbox) ((Urlbox) component).focus(); else if (component instanceof FilenameBox) ((FilenameBox) component).focus(); else if (component instanceof Timebox) ((Timebox) component).focus(); else if (component instanceof Paymentbox) ((Paymentbox) component).focus(); else if (component instanceof PAttributebox) ((PAttributebox) component).focus(); else ((HtmlBasedComponent) currentCell).focus(); } // setFocusOnCurrentCell /** * Set current focus row * @param row */ public void setCurrentRow(Row row) { currentRow = row; String script = "jq('#" + row.getUuid() + "').addClass('highlight').siblings().removeClass('highlight')"; if (!gridTab.getValueAsBoolean("IsActive")) { script = "jq('#" + row.getUuid() + "').addClass('grid-inactive-row').siblings().removeClass('highlight')"; } Clients.response(new AuScript(script)); } /** * @return Row */ public Row getCurrentRow() { return currentRow; } /** * @return current row index ( absolute ) */ public int getCurrentRowIndex() { return currentRowIndex; } /** * Enter edit mode for current focus row. */ public void editCurrentRow() { if (currentRow != null && currentRow.getParent() != null && currentRow.isVisible() && grid != null && grid.isVisible() && grid.getParent() != null && grid.getParent().isVisible()) { editing = true; GridTableListModel model = (GridTableListModel) grid.getModel(); model.setEditing(true); } } /** * @see RowRendererExt#getControls() */ public int getControls() { return DETACH_ON_RENDER; } /** * @see RowRendererExt#newCell(Row) */ public Component newCell(Row row) { return null; } /** * @see RowRendererExt#newRow(Grid) */ public Row newRow(Grid grid) { return null; } /** * @see RendererCtrl#doCatch(Throwable) */ public void doCatch(Throwable ex) throws Throwable { } /** * @see RendererCtrl#doFinally() */ public void doFinally() { } /** * @see RendererCtrl#doTry() */ public void doTry() { } /** * Set {@link QuickGridView} that own this renderer. * @param gridPanel */ public void setGridPanel(QuickGridView gridPanel) { this.gridPanel = gridPanel; } /** * Internal listener for row event (ON_CLICK, ON_DOUBLE_CLICK and ON_OK). */ static class RowListener implements EventListener { private Grid _grid; public RowListener(Grid grid) { _grid = grid; } public void onEvent(Event event) throws Exception { if (Events.ON_CLICK.equals(event.getName())) { if (Executions.getCurrent().getAttribute("gridView.onSelectRow") != null) return; Event evt = new Event(Events.ON_CLICK, _grid, event.getTarget()); Events.sendEvent(_grid, evt); evt.stopPropagation(); } else if (Events.ON_DOUBLE_CLICK.equals(event.getName())) { Event evt = new Event(Events.ON_DOUBLE_CLICK, _grid, _grid); Events.sendEvent(_grid, evt); } else if (Events.ON_OK.equals(event.getName())) { Event evt = new Event(Events.ON_OK, _grid, _grid); Events.sendEvent(_grid, evt); } } } /** * @return true if current row is in edit mode, false otherwise */ public boolean isEditing() { return editing; } /** * Set AD window content part that own this renderer. * {@link #buttonListener} need this to call {@link AbstractADWindowContent#actionPerformed(ActionEvent)}. * @param windowPanel */ public void setADWindowPanel(AbstractADWindowContent windowPanel) { if (this.m_windowPanel == windowPanel) return; this.m_windowPanel = windowPanel; buttonListener = new ActionListener() { public void actionPerformed(ActionEvent event) { WButtonEditor editor = (WButtonEditor) event.getSource(); Integer rowIndex = (Integer) editor.getComponent().getAttribute(GRID_ROW_INDEX_ATTR); if (rowIndex != null) { int newRowIndex = gridTab.navigate(rowIndex); if (newRowIndex == rowIndex) { m_windowPanel.actionPerformed(event); } } else { m_windowPanel.actionPerformed(event); } } }; } @Override public void onEvent(Event event) throws Exception { if (event.getTarget() instanceof Cell) { Cell cell = (Cell) event.getTarget(); if (cell.getSclass() != null && cell.getSclass().indexOf("row-indicator-selected") >= 0) Events.sendEvent(gridPanel, new Event(DetailPane.ON_EDIT_EVENT, gridPanel)); else Events.sendEvent(event.getTarget().getParent(), event); } else if (event.getTarget() instanceof Checkbox) { Executions.getCurrent().setAttribute("gridView.onSelectRow", Boolean.TRUE); Checkbox checkBox = (Checkbox) event.getTarget(); Events.sendEvent(gridPanel, new Event("onSelectRow", gridPanel, checkBox)); } } /** * Clear editorsListmap on page change and dispose. */ public void clearMaps() { editorsListMap.clear(); readOnlyEditorsListMap.clear(); } }