/**
* Copyright 2008-2016 Qualogy Solutions B.V.
*
* 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.qualogy.qafe.gwt.client.component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.gwt.mosaic.ui.client.MessageBox.MessageBoxType;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.gen2.event.dom.client.ScrollEvent;
import com.google.gwt.gen2.event.dom.client.ScrollHandler;
import com.google.gwt.gen2.table.client.ColumnDefinition;
import com.google.gwt.gen2.table.client.DefaultTableDefinition;
import com.google.gwt.gen2.table.client.FixedWidthFlexTable;
import com.google.gwt.gen2.table.client.FixedWidthGrid;
import com.google.gwt.gen2.table.client.PagingScrollTable;
import com.google.gwt.gen2.table.client.TableDefinition;
import com.google.gwt.gen2.table.client.TableModel;
import com.google.gwt.gen2.table.client.TableModel.Callback;
import com.google.gwt.gen2.table.client.TableModelHelper.Request;
import com.google.gwt.gen2.table.client.TableModelHelper.Response;
import com.google.gwt.gen2.table.event.client.RowSelectionEvent;
import com.google.gwt.gen2.table.event.client.RowSelectionHandler;
import com.google.gwt.gen2.table.event.client.TableEvent.Row;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.qualogy.qafe.gwt.client.context.ClientApplicationContext;
import com.qualogy.qafe.gwt.client.ui.renderer.AbstractComponentRenderer.MessageBox;
import com.qualogy.qafe.gwt.client.ui.renderer.DataGridFactory;
import com.qualogy.qafe.gwt.client.util.QAMLConstants;
import com.qualogy.qafe.gwt.client.util.QAMLUtil;
import com.qualogy.qafe.gwt.client.vo.functions.DataContainerGVO;
import com.qualogy.qafe.gwt.client.vo.functions.SetValueGVO;
import com.qualogy.qafe.gwt.client.vo.functions.execute.SetValueExecute;
import com.qualogy.qafe.gwt.client.vo.ui.DataGridColumnGVO;
import com.qualogy.qafe.gwt.client.vo.ui.DataGridGVO;
public class QPagingScrollTable extends PagingScrollTable<DataContainerGVO> implements HasDataGridMethods, RowSelectionHandler, ResultHandler, ScrollHandler, HasRowSelectionChangeHandlers {
private static final Logger logger = Logger.getLogger(QPagingScrollTable.class.getName());
public static final String MSG_LAST_PAGE = "You reached the last page";
protected int qCurrentPage = 0;
protected Boolean hasPredefinedPageSize = false;
private List<Integer> rememberSelectedRows = null;
private List<DataContainerGVO> initialData = new ArrayList<DataContainerGVO>();
private boolean resetInitialData = true;
private String uuid;
private String parent;
private QPagingOptions pagingOptions;
private QPagingScrollTableOperation pagingScrollTableOperations;
private Widget overflow;
private DataGridGVO source = null;
private boolean autoGeneratedColumns = false;
private int scrollPosition;
private boolean scrollEvent = false;
private final Map<String, List<String>> groupedColumns = new HashMap<String, List<String>>();
private final Map<String, SetValueGVO> dropDownColumnAndValues = new HashMap<String, SetValueGVO>();
private Element qHeaderWrapper;
private boolean refreshingExistingRows = false;
private final List<RowSelectionChangeHandler> rowSelectionChangeHandlers = new ArrayList<RowSelectionChangeHandler>();
@Override
public void setVisible(final boolean visible) {
super.setVisible(visible);
if (pagingOptions!=null){
pagingOptions.setVisible(visible && !source.getPageScroll());
}
if (pagingScrollTableOperations!=null){
pagingScrollTableOperations.setVisible(visible);
}
if (overflow!=null){
overflow.setVisible(visible);
}
}
public DataGridGVO getSource() {
return source;
}
public boolean hasOverflow() {
return (overflow != null);
}
public QPagingScrollTable(final TableModel<DataContainerGVO> tableModel, final FixedWidthGrid dataTable, final FixedWidthFlexTable headerTable, final TableDefinition<DataContainerGVO> tableDefinition, final DataGridGVO vo, final String uuid, final String parent) {
super(tableModel, dataTable, headerTable, tableDefinition);
initParameters(vo, uuid, parent);
// Listen for selection events
dataTable.addRowSelectionHandler(this);
}
public QPagingScrollTable(final TableModel<DataContainerGVO> tableModel, final TableDefinition<DataContainerGVO> tableDefinition, final DataGridGVO vo, final String uuid, final String parent) {
super(tableModel, tableDefinition);
initParameters(vo, uuid, parent);
}
private void initParameters(final DataGridGVO vo, final String uuid, final String parent) {
this.source = vo;
this.uuid = uuid;
this.parent = parent;
if (this.source != null) {
this.autoGeneratedColumns = (this.source.getColumns() == null) || (this.source.getColumns().length == 0);
}
// SpreadsheetCell needs to know the parentContainer. So after the constructor is executed we have to
// create tableDefinition with this object as parent for later use and pass the tableDefinition to super class.
createTableDefinition();
// WORKAROUND:
// In IE, when a datagrid has only one visible column (including the rowNumber column),
// that column will shrink each time data is set to the datagrid,
// so changing the width from "100%" to "1px", overflow from "hidden" to "visible" will avoid this problem
final String userAgent = Window.Navigator.getUserAgent();
final boolean isIE = userAgent.toUpperCase().contains("MSIE");
if (isIE && (source != null)) {
final DataGridColumnGVO[] columns = source.getColumns();
if (columns != null) {
int numVisibleColumns = 0;
for (final DataGridColumnGVO column : columns) {
if (column.getVisible()) {
numVisibleColumns++;
}
}
if ((numVisibleColumns == 1) && (qHeaderWrapper != null)) {
qHeaderWrapper.getStyle().setPropertyPx("width", 1);
qHeaderWrapper.getStyle().setProperty("overflow", "visible");
}
}
}
}
@Override
public void onRowSelection(final RowSelectionEvent event) {
if (hasOverflow()) {
final Set<Row> selected = event.getSelectedRows();
for (final Row row : selected) {
final DataContainerGVO dm = getRowValue(row.getRowIndex());
final SetValueGVO setValue = new SetValueGVO();
setValue.setDataContainer(dm);
if (overflow instanceof HasWidgets){
SetValueExecute.processWidgets((HasWidgets)overflow,setValue);
}
}
}
handleRowSelection(event);
}
private void handleRowSelection(final RowSelectionEvent event) {
final int rowIndex = getLastSelectedIndex(event);
Object rowValue = null;
if(rowIndex >= 0) {
rowValue = getRowValue(rowIndex);
}
fireRowSelectionChange(rowIndex, rowValue);
}
private int getLastSelectedIndex(final RowSelectionEvent event) {
int rowIndex = -1;
final Object[] selected = event.getSelectedRows().toArray();
if(selected.length == 0) {
return rowIndex;
}
if(selected[selected.length - 1] instanceof Row) {
final Row lastRowSelected = (Row) selected[selected.length - 1];
rowIndex = lastRowSelected.getRowIndex();
}
return rowIndex;
}
// method checking is columns are defined for datagrid explicitly in qaml.
public Boolean isAutoGeneratedColumns() {
return autoGeneratedColumns;
}
public void clearData() {
if (getDataTable() != null) {
getDataTable().clearAll();
while (getDataTable().getRowCount() > 0) {
getDataTable().removeRow(0);
}
}
cleanRows();
}
private void cleanRows() {
final List<DataContainerGVO> rowValues = getRowValues();
if (rowValues == null) {
return;
}
final List<ColumnDefinition<DataContainerGVO, ?>> visibleColumns = getVisibleColumnDefinitions();
for (int i=0; i<rowValues.size(); i++) {
cleanRowImpl(i, visibleColumns);
}
}
private void cleanRowImpl(final int rowIndex, final List<ColumnDefinition<DataContainerGVO, ?>> visibleColumns) {
if (visibleColumns == null) {
return;
}
for (int i=0; i<visibleColumns.size(); i++) {
final ColumnDefinition<DataContainerGVO, ?> columnDefinition = visibleColumns.get(i);
if (columnDefinition instanceof QColumnDefinition) {
final QColumnDefinition qColumnDefinition = (QColumnDefinition)columnDefinition;
final CellCleaner cellCleaner = qColumnDefinition.getCellCleaner();
if (cellCleaner != null) {
cellCleaner.cleanRow(rowIndex, columnDefinition);
}
}
}
}
@Override
public Integer getMaxRows() {
// TODO Auto-generated method stub
return null;
}
public void setData(final Request request, final Response<DataContainerGVO> response) {
if (hasMatchedColumns(response.getRowValues())) {
setData(getAbsoluteFirstRowIndex(), response.getRowValues());
}
}
// checking any columns are matched with existing columns and columns from new data to set.
private boolean hasMatchedColumns(final Iterator<DataContainerGVO> rows) {
boolean columnMatched = false;
final Iterator<DataContainerGVO> itr = rows;
if ((itr != null) && itr.hasNext()) {
final DataContainerGVO row = itr.next();
if (row != null) {
final List<ColumnDefinition<DataContainerGVO, ?>> columnDefinitionList = getTableDefinition().getVisibleColumnDefinitions();
for (final ColumnDefinition<DataContainerGVO, ?> columnDefinition : columnDefinitionList) {
if (columnDefinition instanceof QColumnDefinition) {
final QColumnDefinition qColumnDefinition = (QColumnDefinition)columnDefinition;
if (row.getDataMap().containsKey(qColumnDefinition.getField())) {
columnMatched = true;
break;
}
}
}
}
}
return columnMatched;
}
private int getColumnIndex(final String name) {
boolean columnFound = false;
int col = -1;
if (source != null && name != null && name.length() > 0 && source.getColumns() != null) {
for (int column = 0; column < source.getColumns().length && !columnFound; column++) {
if (name.equalsIgnoreCase(source.getColumns()[column].getFieldName())) {
columnFound = true;
col = column;
}
}
}
return col;
}
/**
* inserts data to the datagrid, note that to prevent rows from getting
* modified status, we always set append to false. We just make sure we have the complete
* dataset/rows before setting them to the datagrid
*
* @param listOfDataMap data to set to the datagrid
*/
public void insertImportedData(final List<DataContainerGVO> listOfDataMap) {
List<DataContainerGVO> rows = new ArrayList<DataContainerGVO>();
final String importAction = source.getImportAction();
if (ComponentConstants.ADD.equals(importAction)) {
List<DataContainerGVO> currentRows = getRowValues();
// done to make sure we wont get "null" rows since null is a valid list entry
if (currentRows != null) {
rows.addAll(currentRows);
}
rows.addAll(listOfDataMap);
} else if (ComponentConstants.SET.equals(importAction)) {
rows = listOfDataMap;
} else {
logger.log(Level.INFO, "No import action found, using set as default");
rows = listOfDataMap;
}
insertData(rows, false, null, null);
}
// CHECKSTYLE.OFF: CyclomaticComplexity
@Override
public void insertData(final List<DataContainerGVO> listOfDataMap, final Boolean append, final String senderId, final String listenerType) {
boolean makeRowSelected = false;
int rowToSelect = 0;
if(!append && !isPageScrollEvent(senderId, listenerType)) {
// This will make sure scrollbar is placed on top, and so the browser scroll event will not get executed when user set the data.
getDataWrapper().setScrollTop(0);
makeRowSelected = getSource().getSelectFirstRow();
}
if (canProcessEmptyDataSet(listOfDataMap, senderId, listenerType)) { // check is paging action and the resulted data is empty
processEmptyDataSet(listOfDataMap, senderId, listenerType);
} else if(isEmptyDataSet(listOfDataMap, senderId, listenerType)){ // not a paging action but result is empty
if (!append) {
clearData();
this.initialData = new ArrayList<DataContainerGVO>();
clearSelection();
getRowValues().clear();
if(isAutoGeneratedColumns()) {
getHeaderTable().clearAll();
}
}
} else { // result not empty
List<DataContainerGVO> data = listOfDataMap;
int existingDataSize = 0;
if(append){
existingDataSize = getRowValues().size();
} else {
if(resetInitialData){
initialData = makeClone(listOfDataMap);
}
}
if(source.getAdd() || source.getDelete() || source.getEditable()){
final boolean noPaging = !isPagingEvent(senderId, listenerType);
for(final DataContainerGVO dm : listOfDataMap){
++existingDataSize;
if(append && noPaging){
dm.getDataMap().put(DataContainerGVO.ROW_STATUS_KEY, new DataContainerGVO(DataContainerGVO.ROW_STATUS_NEW));
dm.getDataMap().put(DataContainerGVO.ROW_NUMBER, new DataContainerGVO(QAMLConstants.TOKEN_NEW + (existingDataSize)));
makeRowSelected = true;
rowToSelect = existingDataSize - 1;
} else {
dm.getDataMap().put(DataContainerGVO.ROW_STATUS_KEY, new DataContainerGVO(DataContainerGVO.ROW_STATUS_UNMODIFIED));
dm.getDataMap().put(DataContainerGVO.ROW_NUMBER, new DataContainerGVO("" + (existingDataSize)));
}
}
} else if(!source.getEditable()) {
// ROW_NUMBER is maintained so that when $SELECTED_INDEX is used, it picks the right row.
for(final DataContainerGVO dm : listOfDataMap){
++existingDataSize;
dm.getDataMap().put(DataContainerGVO.ROW_NUMBER, new DataContainerGVO("" + (existingDataSize)));
}
}
if (append) {
data = getRowValues();
data.addAll(listOfDataMap);
} else {
clearData();
}
checkColumns(data);
final boolean pageScrollEvent = isPageScrollEvent(senderId, listenerType);
if (pageScrollEvent) {
rememberSelection();
}
((QTableModel) getTableModel()).processData(data);
if (pageScrollEvent) {
restoreSelection();
}
if (makeRowSelected) {
this.selectRow(rowToSelect);
}
}
}
// CHECKSTYLE.ON: CyclomaticComplexity
private void checkColumns(final List<DataContainerGVO> listOfDataMap) {
if ((listOfDataMap != null) && (listOfDataMap.size() > 0)) {
if (isAutoGeneratedColumns()) {
// So there are no columns from the QAML, we make the grid data-driven
// create an array of the datagridcolumns
final List<DataGridColumnGVO> listOfColumns = new ArrayList<DataGridColumnGVO>();
final DataContainerGVO map = listOfDataMap.get(0);
for (final String key : map.getDataMap().keySet()) {
final DataGridColumnGVO dcg = new DataGridColumnGVO();
dcg.setFieldName(key);
dcg.setSortable(dcg.getSortable());
dcg.setStaticField(false);
dcg.setDisplayname(key);
dcg.setContainerName(source.getId());
if (key.equals(DataMap.ROW_STATUS_KEY) || key.equals(DataMap.ROW_NUMBER)) {
dcg.setVisible(false);
}
listOfColumns.add(dcg);
}
setTableDefinition(DataGridFactory.createTableDefinition(source, listOfColumns.toArray(new DataGridColumnGVO[]{}), uuid, parent, this));
refreshColumnHeaders();
}
}
}
@Override
public void insertDataRow(final List<String> listOfDataMap, final Boolean append, final String senderId, final String listenerType) {
if (canProcessEmptyDataSet(listOfDataMap, senderId, listenerType)) {
processEmptyDataSet(listOfDataMap, senderId, listenerType);
} else {
if (!append) {
clearData();
}
}
}
@Override
public void setTableDefinition(final TableDefinition<DataContainerGVO> tableDefinition) {
if (tableDefinition != null) {
super.setTableDefinition(tableDefinition);
}
}
public void createTableDefinition() {
// If no columns are specified, show an empty column
DataGridColumnGVO[] dataGridColumns = source.getColumns();
if ((dataGridColumns == null) || (dataGridColumns.length == 0)) {
final DataGridColumnGVO dataGridColumn = new DataGridColumnGVO();
dataGridColumn.setFieldName("");
dataGridColumns = new DataGridColumnGVO[1];
dataGridColumns[0] = dataGridColumn;
} else {
aggregateGroupedColumns();
}
final TableDefinition<DataContainerGVO> tableDefinition = DataGridFactory.createTableDefinition(source, dataGridColumns, uuid, parent, this);
setTableDefinition(tableDefinition);
}
private void aggregateGroupedColumns() {
for(final DataGridColumnGVO column : source.getColumns()){
if(column.getGroup() != null){
String[] groupNames = null;
if(column.getGroup().contains(",")){ // When column belong to multiple groups.
groupNames = column.getGroup().split(",");
} else {
groupNames = new String[]{column.getGroup()};
}
for(String groupName: groupNames){
groupName = groupName.trim();
if(groupedColumns.containsKey(groupName)){
groupedColumns.get(groupName).add(column.getFieldName());
} else {
final List<String> columnNames = new ArrayList<String>();
columnNames.add(column.getFieldName());
groupedColumns.put(groupName, columnNames);
}
}
}
}
}
@Override
public void processActions(final DataGridGVO gvo, final String uuid, final String parent) {
// TODO Auto-generated method stub
}
@Override
public void setAdd(final Boolean bool) {
// TODO Auto-generated method stub
}
@Override
public void setDelete(final Boolean bool) {
// TODO Auto-generated method stub
}
@Override
public boolean isEditable() {
// TODO Auto-generated method stub
return false;
}
@Override
public void setEditable(final boolean value) {
// TODO Auto-generated method stub
}
@Override
public void setExport(final Boolean bool) {
// TODO Auto-generated method stub
}
public void setMaxRows(final Integer maxRows) {
// TODO Auto-generated method stub
}
@Override
public void setModified(final boolean modified, final int row, final int column, final String value) {
// TODO Auto-generated method stub
}
@Override
public void setModified(final ColumnDefinition<DataContainerGVO, String> columnDefinition, final UIObject uiObject, final DataContainerGVO rowValue, final Object newValue) {
setModified(columnDefinition, uiObject, rowValue, newValue, false);
}
@Override
public void setModified(final ColumnDefinition<DataContainerGVO, String> columnDefinition, final UIObject uiObject, final DataContainerGVO rowValue, final Object newValue, final boolean changedByUser) {
if (columnDefinition instanceof QColumnDefinition) {
if(rowValue != null && rowValue.isMap()) {
final QColumnDefinition colDefinition = (QColumnDefinition)columnDefinition;
final String columnName = colDefinition.getField();
DataContainerGVO dataContainerGVO = rowValue.getDataMap().get(columnName);
if (dataContainerGVO == null) {
dataContainerGVO = new DataContainerGVO();
dataContainerGVO.setKind(DataContainerGVO.KIND_STRING);
rowValue.getDataMap().put(columnName, dataContainerGVO);
}
Object oldValue = null;
if (newValue instanceof Date) {
oldValue = dataContainerGVO.getDateData();
dataContainerGVO.setDateData((Date)newValue);
dataContainerGVO.setStringDataType(DataContainerGVO.TYPE_DATE);
} else if(newValue instanceof Double) {
dataContainerGVO.setStringDataType(DataContainerGVO.TYPE_DOUBLE);
}
final String newValueOfStr = (newValue == null) ? null : newValue.toString();
dataContainerGVO.setDataString(newValueOfStr);
doColumnDataChange(columnDefinition, uiObject, rowValue.getDataMap(), oldValue, newValue, changedByUser);
}
}
}
@Override
public void setOverflow(final Widget overflow) {
this.overflow = overflow;
}
@Override
public void setPageSize(final Integer pageSize) {
setPageSize(pageSize, false);
}
public void setPageSize(final Integer pageSize, final Boolean init) {
if (pageSize != null) {
if ((init) && (pageSize != -1)) {
hasPredefinedPageSize = true;
}
setPageSize((int)pageSize);
}
}
@Override
public void setPageSize(final int pageSize) {
if (hasPredefinedPageSize) {
// pageSize is specified in QAML code
super.setPageSize(pageSize);
}
}
@Override
public void setShowAll(final Boolean bool) {
// TODO Auto-generated method stub
}
@Override
public void setup() {
refreshColumnHeaders();
if (source.getColumns()!=null){
initColumnWidths();
setEmptyTableWidgetVisible(false);
final DataMap dummy = new DataMap();
final DataContainerGVO dummydcg = new DataContainerGVO();
dummydcg.setDataString("");
final List<DataMap> dummylistOfDataMap = new ArrayList<DataMap>();
for(int i=0;i<source.getColumns().length;i++){
dummy.put(""+i,dummydcg );
}
for (int i=0;i<15;i++){
dummylistOfDataMap.add(dummy);
}
}
}
private void refreshColumnHeaders() {
refreshColumnHeaders(false);
}
private void refreshColumnHeaders(final boolean force) {
if ((source != null) && (source.getColumns() != null)) {
if (getHeaderTable() != null) {
if (force || isColumnHeadersChanged()) {
clearColumnHeaders();
buildColumnHeaders();
}
}
}
}
public void initColumnWidths() {
int visibleColIndex = 0;
final DataGridColumnGVO[] columns = source.getColumns();
for (final DataGridColumnGVO columnGVO : columns) {
if (!columnGVO.getVisible()) {
continue;
}
final String width = columnGVO.getWidth();
if (width != null) {
setColumnWidth(visibleColIndex, Integer.parseInt(width));
}
visibleColIndex++;
}
}
private void clearColumnHeaders() {
final FixedWidthFlexTable headerTable = getHeaderTable();
if (headerTable == null) {
return;
}
if (headerTable.getColumnCount() > 0) {
headerTable.removeRow(0);
headerTable.clearAll();
}
}
private void buildColumnHeaders() {
int visibleColIndex = 0;
final DataGridColumnGVO[] columns = source.getColumns();
for (final DataGridColumnGVO columnGVO : columns) {
if (!columnGVO.getVisible()) {
continue;
}
final Widget columnHeader = createColumnHeader(columnGVO);
if (columnHeader == null) {
continue;
}
getHeaderTable().setWidget(0, visibleColIndex, columnHeader);
visibleColIndex++;
}
}
private Widget createColumnHeader(final DataGridColumnGVO columnGVO) {
if ((columnGVO == null) || columnGVO.isQafeChecksum()) {
return null;
}
String displayName = columnGVO.getDisplayname();
if (displayName == null) {
displayName = columnGVO.getFieldName();
}
final Label label = new Label(displayName);
label.setHeight("20px");
if (columnGVO.getStyleClass() != null) {
label.setStylePrimaryName(columnGVO.getStyleClass());
}
return label;
}
private boolean isColumnHeadersChanged() {
final DataGridColumnGVO[] dataGridColumns = source.getColumns();
// Number of columns has been changed, so the columnHeaders
if (getHeaderTable().getColumnCount() != dataGridColumns.length) {
return true;
}
// Fill map with columnNames for faster processing
final Map <String,String> map = new HashMap<String,String>();
for (int i=0; i<dataGridColumns.length; i++) {
final DataGridColumnGVO dataGridColumn = dataGridColumns[i];
if (dataGridColumn != null) {
String displayName = dataGridColumn.getDisplayname();
if (displayName == null) {
displayName = dataGridColumn.getFieldName();
}
if (displayName != null) {
map.put(displayName, null);
}
}
}
// Check existence of all columnNames
final Iterator<Widget> itrWidget = getHeaderTable().iterator();
while (itrWidget.hasNext()) {
final Widget widget = itrWidget.next();
if (widget instanceof Label) {
final Label label = (Label)widget;
if (!map.containsKey(label.getText())) {
return true;
}
}
}
return false;
}
/**
* Reload the current page.
*/
@Override
public void reloadPage() {
if (qCurrentPage >= 0) {
gotoPage(qCurrentPage, true);
} else {
gotoPage(0, true);
}
}
@Override
public int getCurrentPage() {
return qCurrentPage;
}
@Override
public void setCurrentPage(final int currentPage) {
if (hasPredefinedPageSize) {
// pageSize is specified in QAML code
qCurrentPage = Math.max(0, currentPage);
if ((pagingOptions != null) && (qCurrentPage != Integer.MAX_VALUE)) {
pagingOptions.getCurPageBox().setText(String.valueOf(qCurrentPage + 1));
}
}
}
@Override
public int getAbsoluteFirstRowIndex() {
int rowIndex = getCurrentPage();
if (rowIndex != Integer.MAX_VALUE) {
rowIndex = rowIndex * getPageSize();
}
return rowIndex;
}
@Override
public int getAbsoluteLastRowIndex() {
if (getPageSize() > 0) {
int rowIndex = getAbsoluteFirstRowIndex();
if (rowIndex != Integer.MAX_VALUE) {
rowIndex = rowIndex + getPageSize() - 1;
}
return rowIndex;
}
return Math.max(getTableModel().getRowCount(), 0) - 1;
}
public void onDelete() {
//remember the selected rows, after the event body is executed success selected rows needs to be removed in onResult callback.
rememberSelection();
setSenderId(QPagingScrollTableOperation.CONTROLS_DELETE);
gotoPage(getCurrentPage(), true);
}
private void rememberSelection() {
if (rememberSelectedRows == null) {
rememberSelectedRows = new ArrayList<Integer>();
}
rememberSelectedRows.clear();
final Iterator<Integer> itr = getDataTable().getSelectedRows().iterator();
while (itr.hasNext()) {
final Integer rowIndex = itr.next();
rememberSelectedRows.add(rowIndex);
}
}
private void restoreSelection() {
if (rememberSelectedRows == null) {
return;
}
for (final Integer rowIndex : rememberSelectedRows){
getDataTable().selectRow(rowIndex, false);
}
rememberSelectedRows.clear();
}
private void clearSelection() {
getDataTable().deselectAllRows();
getSelectedRowValues().clear();
if(rememberSelectedRows != null){
rememberSelectedRows.clear();
}
}
private void performDelete() {
for(final Integer rowIndex : rememberSelectedRows){
getRowValues().remove(rowIndex.intValue());
getDataTable().removeRow(rowIndex.intValue());
}
clearSelection();
}
public void onAdd() {
setSenderId(QPagingScrollTableOperation.CONTROLS_ADD);
gotoPage(getCurrentPage(), true);
}
public void onSave() {
setSenderId(QPagingScrollTableOperation.CONTROLS_SAVE);
gotoPage(getCurrentPage(), true);
updateQafeChecksum();
}
private void updateQafeChecksum() {
final Collection<DataContainerGVO> rows = getRowValuesToProcess(DataContainerGVO.ROW_STATUS_MODIFIED);
for (final DataContainerGVO row : rows) {
final DataMap dataMap = row.getDataMap();
final DataContainerGVO checksumContainer = dataMap.get(DataContainerGVO.QAFE_CHECKSUM);
if (checksumContainer != null) {
int checksum = 0;
for (final Map.Entry<String, DataContainerGVO> field : dataMap.entrySet()) {
if (!isMetaData(field.getKey())) {
Object value = null;
if (field.getValue() != null) {
value = field.getValue().createType();
}
checksum += QAMLUtil.calculateChecksum(field.getKey(), value);
}
}
checksumContainer.setDataString("" + checksum);
}
}
}
private boolean isMetaData(final String key) {
return DataContainerGVO.ROW_STATUS_KEY.equals(key) || DataContainerGVO.ROW_NUMBER.equals(key)
|| DataContainerGVO.QAFE_CHECKSUM.equals(key);
}
public void onRefresh() {
setSenderId(QPagingScrollTableOperation.CONTROLS_REFRESH);
gotoPage(getCurrentPage(), true);
}
public void onCancel() {
setSenderId(QPagingScrollTableOperation.CONTROLS_CANCEL);
gotoPage(getCurrentPage(), true);
}
@Override
public void gotoFirstPage() {
setSenderId(QPagingOptions.PAGING_FIRSTPAGE);
gotoPage(0, true);
}
@Override
public void gotoLastPage() {
setSenderId(QPagingOptions.PAGING_LASTPAGE);
gotoPage(Integer.MAX_VALUE, true);
}
@Override
public void gotoNextPage() {
setSenderId(QPagingOptions.PAGING_NEXTPAGE);
gotoPage(getCurrentPage() + 1, true);
}
@Override
public void gotoPreviousPage() {
setSenderId(QPagingOptions.PAGING_PREVIOUSPAGE);
gotoPage(Math.max(0, getCurrentPage() - 1), true);
}
@Override
public void gotoPage(final int page, final boolean forced) {
final int currPage = getCurrentPage();
if (currPage != page || forced) {
setCurrentPage(page);
final FixedWidthGrid dataTable = getDataTable();
if ((currPage != page) && (!hasPageScroll())) {
// Deselect rows when switching pages if it is standard pagination
dataTable.deselectAllRows();
}
// Request the new data from the table model
final int firstRow = getAbsoluteFirstRowIndex();
final int lastRow = getAbsoluteLastRowIndex();
final Request request = new Request(firstRow, lastRow, dataTable.getColumnSortList());
final Callback callback = new Callback<DataContainerGVO>(){
@Override
public void onFailure(final Throwable caught) {
ClientApplicationContext.getInstance().log("Setting datagrid values failed", caught);
}
@Override
public void onRowsReady(final Request request, final Response<DataContainerGVO> response) {
setData(request, response);
}
};
if (getTableModel() instanceof QTableModel) {
((QTableModel)getTableModel()).requestRows(request, callback, this);
}
}
}
private boolean hasPageScroll() {
if ((getSource() != null) && getSource().getPageScroll()) {
return true;
}
return false;
}
private void setSenderId(final String sender) {
final TableModel<DataContainerGVO> m = getTableModel();
if (m instanceof QTableModel) {
final QTableModel qm = (QTableModel) m;
if (QPagingOptions.PAGING_FIRSTPAGE.equals(sender)) {
qm.setSender(pagingOptions.getFirstImage());
} else if (QPagingOptions.PAGING_NEXTPAGE.equals(sender)) {
qm.setSender(pagingOptions.getNextImage());
} else if (QPagingOptions.PAGING_LASTPAGE.equals(sender)) {
qm.setSender(pagingOptions.getLastImage());
} else if (QPagingOptions.PAGING_PREVIOUSPAGE.equals(sender)) {
qm.setSender(pagingOptions.getPrevImage());
} else if (QPagingScrollTableOperation.CONTROLS_DELETE.equals(sender)) {
qm.setSender(pagingScrollTableOperations.getDeleteImage());
} else if (QPagingScrollTableOperation.CONTROLS_ADD.equals(sender)) {
qm.setSender(pagingScrollTableOperations.getAddImage());
} else if (QPagingScrollTableOperation.CONTROLS_SAVE.equals(sender)) {
qm.setSender(pagingScrollTableOperations.getSaveImage());
} else if (QPagingScrollTableOperation.CONTROLS_REFRESH.equals(sender)) {
qm.setSender(pagingScrollTableOperations.getRefreshImage());
} else if (QPagingScrollTableOperation.CONTROLS_CANCEL.equals(sender)) {
qm.setSender(pagingScrollTableOperations.getCancelImage());
}
}
}
public void setPagingOptions(final QPagingOptions pagingOptions) {
this.pagingOptions = pagingOptions;
}
public void resetCurrentPage(){
if (getCurrentPage()<0){
gotoPage(0,true);
}
}
@Override
public void selectRow(final int rowNr) {
if (rowNr>=0 && rowNr< getDataTable().getRowCount()){
getDataTable().selectRow(rowNr, true);
final Element rowToShow = getDataTable().getRowFormatter().getElement(rowNr);
scrollIntoView(rowToShow, this.getElement());
} else {
//TODO: call clearSelection to remove the existing selections.
//This will allow end user to remove all selections by passing -1 in set-property
}
}
/**
*
* This method is copied from com.google.gwt.dom.client.DOMImpl class and modified to add an extra check at the end.
* ADDED CODE AT END: if(cur == containerElement) {break;}
* When user add a new record or use set-property to set a row selected we need to show that row in the view.
* When we are using scrollIntoView method of GWT(getDataTable().getRowFormatter().getElement(rowNr).scrollIntoView())
* we got issue after zooming in(CTr+) and then setting the first row as selected.
* Issue is that the entire browser window moves up after , making top part of the screen invisible.
* Now we added extra check tp stop the operation of making the new view position when it reaches the parent(in this case the pagingScrollTable)
*/
protected native void scrollIntoView(Element elem, Element containerElement) /*-{
var left = elem.offsetLeft, top = elem.offsetTop;
var width = elem.offsetWidth, height = elem.offsetHeight;
if (elem.parentNode != elem.offsetParent) {
left -= elem.parentNode.offsetLeft;
top -= elem.parentNode.offsetTop;
}
var cur = elem.parentNode;
while (cur && (cur.nodeType == 1)) {
if (left < cur.scrollLeft) {
cur.scrollLeft = left;
}
if (left + width > cur.scrollLeft + cur.clientWidth) {
cur.scrollLeft = (left + width) - cur.clientWidth;
}
if (top < cur.scrollTop) {
cur.scrollTop = top;
}
if (top + height > cur.scrollTop + cur.clientHeight) {
cur.scrollTop = (top + height) - cur.clientHeight;
}
var offsetLeft = cur.offsetLeft, offsetTop = cur.offsetTop;
if (cur.parentNode != cur.offsetParent) {
offsetLeft -= cur.parentNode.offsetLeft;
offsetTop -= cur.parentNode.offsetTop;
}
left += offsetLeft - cur.scrollLeft;
top += offsetTop - cur.scrollTop;
cur = cur.parentNode;
//added check to stop iteration when the container is datagrid
if(cur == containerElement) {
break;
}
}
}-*/;
public Object getData(final String fetchForRowStatus, final String groupName) {
final Collection<DataContainerGVO> rowValuesToProcess = getRowValuesToProcess(fetchForRowStatus);
List<DataContainerGVO> data = new ArrayList<DataContainerGVO>();
for (final DataContainerGVO row : makeClone(rowValuesToProcess)) {
row.getDataMap().remove(DataContainerGVO.ROW_STATUS_KEY);
if (row.getDataMap().get(DataContainerGVO.ROW_NUMBER) != null) {
final String rowNumber = row.getDataMap().get(DataContainerGVO.ROW_NUMBER).getDataString().replaceAll("[" + QAMLConstants.TOKEN_NEW + QAMLConstants.TOKEN_MODIFIED + QAMLConstants.TOKEN_DELETED + "]", "");
row.getDataMap().get(DataContainerGVO.ROW_NUMBER).setDataString(rowNumber);
}
data.add(row);
}
if (groupName != null) {
final List<DataContainerGVO> filteredRows = new ArrayList<DataContainerGVO>();
final List<String> columnsOfThisGroup = groupedColumns.get(groupName);
if (columnsOfThisGroup != null) {
for (final DataContainerGVO row : makeClone(data)) {
final DataContainerGVO dgvo = new DataContainerGVO(new DataMap());
dgvo.getDataMap().put(DataContainerGVO.ROW_NUMBER, row.getDataMap().get(DataContainerGVO.ROW_NUMBER));
for (final String key : columnsOfThisGroup) {
dgvo.getDataMap().put(key, row.getDataMap().get(key));
}
filteredRows.add(dgvo);
}
data = filteredRows;
}
}
return data;
}
private Collection<DataContainerGVO> getRowValuesToProcess(final String fetchForRowStatus) {
if (fetchForRowStatus == null) {
return getSelectedRowValues();
} else if (DataContainerGVO.ROW_STATUS_ALL.equals(fetchForRowStatus)) {
return getRowValues();
} else if (DataContainerGVO.ROW_STATUS_UNSELECTED.equals(fetchForRowStatus)) {
final Collection<DataContainerGVO> rowValuesToProcess = new ArrayList<DataContainerGVO>(getRowValues());
rowValuesToProcess.removeAll(getSelectedRowValues());
return rowValuesToProcess;
} else {
final Collection<DataContainerGVO> rowValuesToProcess;
rowValuesToProcess = new ArrayList<DataContainerGVO>();
for (final DataContainerGVO row : getRowValues()) {
if ((row.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY).getDataString()).equals(fetchForRowStatus)) {
rowValuesToProcess.add(row);
}
}
return rowValuesToProcess;
}
}
public void setScrollTableOperations(final QPagingScrollTableOperation qPagingScrollTableOperation) {
pagingScrollTableOperations = qPagingScrollTableOperation;
}
protected Boolean isPagingEvent(final String senderId, final String listenerType) {
if (isPageEvent(senderId, listenerType)) {
return true;
}
if (isPageScrollEvent(senderId, listenerType)) {
return true;
}
return false;
}
private boolean isPageEvent(final String senderId, final String listenerType) {
if (QAMLConstants.EVENT_ONCLICK.equals(listenerType)) {
final String dataGridId = this.source.getId().toString();
if (senderId.startsWith((dataGridId + "." + QPagingOptions.PAGING_FIRSTPAGE))
|| senderId.startsWith((dataGridId + "." + QPagingOptions.PAGING_PREVIOUSPAGE))
|| senderId.startsWith((dataGridId + "." + QPagingOptions.PAGING_NEXTPAGE))
|| senderId.startsWith((dataGridId + "." + QPagingOptions.PAGING_LASTPAGE))) {
return true;
}
}
return false;
}
private boolean isPageScrollEvent(final String senderId, final String listenerType) {
if (QAMLConstants.EVENT_ONSCROLL_BOTTOM.equals(listenerType)) {
final String dataGridId = this.source.getId().toString();
if (senderId.startsWith(dataGridId)) {
return true;
}
}
return false;
}
protected Boolean canProcessEmptyDataSet(final Object data, final String senderId, final String listenerType) {
boolean result = false;
if (data == null) {
result = true;
} else if ((data instanceof List) && ((List)data).isEmpty()) {
result = true;
}
result = result ? isPagingEvent(senderId, listenerType) : result;
return result;
}
protected Boolean isEmptyDataSet(final Object data, final String senderId, final String listenerType) {
boolean result = false;
if ((data == null) || ((data instanceof List) && ((List)data).isEmpty()) ) {
result = true;
}
return result;
}
protected void processEmptyDataSet(final Object data, final String senderId, final String listenerType) {
// qCurrentPage should be decrement by 1,
// because it's incremented by 1 already before sending to the back-end
final int currPage = getCurrentPage();
setCurrentPage(currPage - 1);
if ((senderId != null) && (listenerType != null)) {
final String dataGridId = this.source.getId().toString();
if ( (listenerType.equals("onscroll-bottom")) || (listenerType.equals("onclick") && (senderId.startsWith((dataGridId + "." + QPagingOptions.PAGING_NEXTPAGE))))) {
// show a fading message
fadeMessage(MSG_LAST_PAGE);
}
}
}
protected void fadeMessage(final String message) {
setEmptyTableWidgetVisible(true);
final Widget widget = getEmptyTableWidget();
if (widget instanceof MessageBox){
final MessageBox messageBox = (MessageBox)widget;
messageBox.getElement().getStyle().setProperty("width", "100%");
Utils.setWidgetPosition(messageBox, 0, 0);
Utils.fadeMessage(messageBox, message);
}
}
@Override
protected void setEmptyTableWidgetVisible(final boolean visible) {
super.setEmptyTableWidgetVisible(visible);
// when calling super.setEmptyTableWidgetVisible(true),
// data are shown, so set the visibility back to true
getDataWrapper().getStyle().setProperty("display", "");
}
@Override
protected Element createWrapper(final String cssName) {
final Element wrapper = super.createWrapper(cssName);
if ("headerWrapper".equals(cssName)) {
// This will be used in method initParameters
qHeaderWrapper = wrapper;
}
return wrapper;
}
private String getSenderIdOnly(String senderId) {
if ((senderId != null) && (senderId.indexOf("|") > -1)) {
senderId = senderId.substring(0, senderId.indexOf("|"));
}
return senderId;
}
// call back to handle anything to be done after the event body processing.
@Override
public void onResult(String senderId, final String listenerType) {
if (QAMLConstants.EVENT_ONCLICK.equals(listenerType)) {
senderId = getSenderIdOnly(senderId);
if (senderId.endsWith(QPagingScrollTableOperation.CONTROLS_DELETE)) {
handleDeleteRecord();
} else if (senderId.endsWith(QPagingScrollTableOperation.CONTROLS_ADD)) {
handleAddRecord();
} else if (senderId.endsWith(QPagingScrollTableOperation.CONTROLS_SAVE)) {
int rowIndex = 0;
final ArrayList<DataContainerGVO> rowsToRemove = new ArrayList<DataContainerGVO>();
for (final DataContainerGVO row : getRowValues()) {
if (!row.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY).getDataString().equals(DataContainerGVO.ROW_STATUS_DELETED)) {
row.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY).setDataString(DataContainerGVO.ROW_STATUS_UNMODIFIED);
final String rowNumber = row.getDataMap().get(DataContainerGVO.ROW_NUMBER).getDataString().replaceAll("[" + QAMLConstants.TOKEN_NEW + QAMLConstants.TOKEN_MODIFIED + QAMLConstants.TOKEN_DELETED + "]", "");
row.getDataMap().get(DataContainerGVO.ROW_NUMBER).setDataString(rowNumber);
} else {
rowsToRemove.add(row);
}
rowIndex++;
}
for (final DataContainerGVO removeRow : rowsToRemove) {
getRowValues().remove(removeRow);
}
//datagridRendered = false;
resetInitialData = true;
insertData(getRowValues(), false, senderId, listenerType);
clearSelection();
} else if (senderId.endsWith(QPagingScrollTableOperation.CONTROLS_REFRESH)) {
ClientApplicationContext.getInstance().log("performRefresh (senderId) : " + senderId);
} else if (senderId.endsWith(QPagingScrollTableOperation.CONTROLS_CANCEL)) {
if (containsModifiedData()) {
showPrompt(senderId, listenerType);
}
}
}
}
private void handleAddRecord() {
int newRowIndex = -1;
final DataMap dummy = new DataMap();
List<DataContainerGVO> rowValues = getRowValues();
if (rowValues == null) {
rowValues = new ArrayList<DataContainerGVO>();
}
if (rowValues.size() > 0) {
// Add the newly record as last with column names from data
newRowIndex = rowValues.size();
final DataContainerGVO dm = rowValues.get(0);
final Set<String> keys = dm.getDataMap().keySet();
for(final String column: keys) {
final DataContainerGVO dummydcg = new DataContainerGVO("");
dummy.put(column, dummydcg);
}
} else if (source.getColumns() != null) {
// Add the newly record as first with column names from datagrid columns
newRowIndex = 0;
for (final DataGridColumnGVO columnGVO: source.getColumns()) {
final DataContainerGVO dummydcg = new DataContainerGVO("");
dummy.put(columnGVO.getFieldName(), dummydcg);
}
}
// Add the newly record after the selection, if present
final Set<DataContainerGVO> selectedRowValues = getSelectedRowValues();
if ((selectedRowValues != null) && (selectedRowValues.size() > 0)) {
DataContainerGVO selectedRow = null;
final Iterator<DataContainerGVO> itrRow = selectedRowValues.iterator();
while (itrRow.hasNext()) {
selectedRow = itrRow.next();
}
if (selectedRow != null) {
newRowIndex = getRowNumber(selectedRow);
int offset = 1;
final List<DataContainerGVO> newRowValues = new ArrayList<DataContainerGVO>();
for (int i=0; i<rowValues.size(); i++) {
final DataContainerGVO rowValue = rowValues.get(i);
if (i == newRowIndex) {
newRowValues.add(null);
offset++;
}
if (i >= newRowIndex) {
updateRowNumber(rowValue, i + offset);
}
newRowValues.add(rowValue);
}
rowValues.clear();
rowValues.addAll(newRowValues);
}
}
if (newRowIndex > -1) {
dummy.put(DataContainerGVO.ROW_STATUS_KEY, new DataContainerGVO(DataContainerGVO.ROW_STATUS_NEW));
dummy.put(DataContainerGVO.ROW_NUMBER, new DataContainerGVO(QAMLConstants.TOKEN_NEW + (newRowIndex + 1)));
final DataContainerGVO newRecord = new DataContainerGVO(dummy);
if (newRowIndex < rowValues.size()) {
rowValues.set(newRowIndex, newRecord);
} else {
rowValues.add(newRecord);
}
try {
refreshingExistingRows = true;
((QTableModel) getTableModel()).processData(rowValues);
} finally {
refreshingExistingRows = false;
}
selectRow(newRowIndex);
}
}
private void handleDeleteRecord() {
final Collection<DataContainerGVO> selectedRowValues = getSelectedRowValues();
if (selectedRowValues == null) {
return;
}
final List<DataContainerGVO> newlyRowValues = new ArrayList<DataContainerGVO>();
for (final DataContainerGVO rowValue : selectedRowValues) {
final DataContainerGVO statusKeyGVO = rowValue.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY);
final String statusKey = statusKeyGVO.getDataString();
if (DataContainerGVO.ROW_STATUS_DELETED.equals(statusKey)) {
continue;
} else if (DataContainerGVO.ROW_STATUS_NEW.equals(statusKey)) {
newlyRowValues.add(rowValue);
} else {
final DataContainerGVO rowNumberGVO = rowValue.getDataMap().get(DataContainerGVO.ROW_NUMBER);
final String rowNumber = rowNumberGVO.getDataString().replaceAll("[" + QAMLConstants.TOKEN_NEW + QAMLConstants.TOKEN_MODIFIED + QAMLConstants.TOKEN_DELETED + "]", "");
rowNumberGVO.setDataString(QAMLConstants.TOKEN_DELETED + rowNumber);
statusKeyGVO.setDataString(DataContainerGVO.ROW_STATUS_DELETED);
final QLabel label = new QLabel(QAMLConstants.TOKEN_DELETED + rowNumber);
getDataTable().setElement(Integer.parseInt(rowNumber)-1, 0, label.getElement());
}
}
if (newlyRowValues.size() > 0) {
final List<DataContainerGVO> newRowValues = new ArrayList<DataContainerGVO>();
final List<DataContainerGVO> rowValues = getRowValues();
for (int i=0; i<rowValues.size(); i++) {
final DataContainerGVO rowValue = rowValues.get(i);
if (newlyRowValues.contains(rowValue)) {
continue;
}
updateRowNumber(rowValue, newRowValues.size() + 1);
newRowValues.add(rowValue);
}
rowValues.clear();
rowValues.addAll(newRowValues);
try {
refreshingExistingRows = true;
if (rowValues.isEmpty()) {
clearData();
} else {
((QTableModel)getTableModel()).processData(rowValues);
}
} finally {
refreshingExistingRows = false;
}
}
clearSelection();
}
private int getRowNumber(final DataContainerGVO rowValue) {
int rowNumber = -1;
if (rowValue != null) {
final DataContainerGVO rowNumberGVO = rowValue.getDataMap().get(DataContainerGVO.ROW_NUMBER);
final String strRowNumber = rowNumberGVO.getDataString().replaceAll("[" + QAMLConstants.TOKEN_NEW + QAMLConstants.TOKEN_MODIFIED + QAMLConstants.TOKEN_DELETED + "]", "");
rowNumber = Integer.valueOf(strRowNumber);
}
return rowNumber;
}
private void updateRowNumber(final DataContainerGVO rowValue, final int newRowNumber) {
if (rowValue == null) {
return;
}
String status = "";
final String statusKey = rowValue.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY).getDataString();
if (DataContainerGVO.ROW_STATUS_NEW.equals(statusKey)) {
status = QAMLConstants.TOKEN_NEW;
} else if (DataContainerGVO.ROW_STATUS_MODIFIED.equals(statusKey)) {
status = QAMLConstants.TOKEN_MODIFIED;
} else if (DataContainerGVO.ROW_STATUS_DELETED.equals(statusKey)) {
status = QAMLConstants.TOKEN_DELETED;
}
final DataContainerGVO rowNumberGVO = new DataContainerGVO(status + newRowNumber);
rowValue.getDataMap().put(DataContainerGVO.ROW_NUMBER, rowNumberGVO);
}
/**
* Insert a row into the table relative to the total number of rows.
* This is exact the same as defined in the super class,
* except the row removal based on the pagesize
*
* @param beforeRow the row index
*/
@Override
protected void insertAbsoluteRow(final int beforeRow) {
// Physically insert the row
final int lastRow = getAbsoluteLastRowIndex() + 1;
if (beforeRow <= lastRow) {
final int firstRow = getAbsoluteFirstRowIndex();
if (beforeRow >= firstRow) {
// Insert row in the middle of the page
getDataTable().insertRow(beforeRow - firstRow);
} else {
// Insert zero row because row is before this page
getDataTable().insertRow(0);
}
}
}
private boolean containsModifiedData() {
for(final DataContainerGVO row : getRowValues()){
if(!((row.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY).toString()).equals(DataContainerGVO.ROW_STATUS_UNMODIFIED))) {
return true;
}
}
return false;
}
private void showPrompt(final String senderId, final String listenerType) {
final org.gwt.mosaic.ui.client.MessageBox prompt = new org.gwt.mosaic.ui.client.MessageBox(MessageBoxType.PROMPT, "Confirm") {
@Override
public void onClose(final boolean result) {
}
};
final Label message = new Label();
message.setText("Click ok to reset the data to initial value.");
final Button ok = new Button("Ok");
ok.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
resetInitialData = false;
//datagridRendered = false;
getRowValues().clear();
getDataTable().clear();
final List<DataContainerGVO> cloneOfInitialData = makeClone(initialData);
insertData(cloneOfInitialData, false, senderId, listenerType);
prompt.removeFromParent();
clearSelection();
}
});
final Button cancel = new Button("Cancel");
cancel.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
prompt.removeFromParent();
}
});
final HorizontalPanel hp = new HorizontalPanel();
hp.add(ok);
hp.add(cancel);
final VerticalPanel vp = new VerticalPanel();
vp.add(message);
vp.add(hp);
prompt.add(vp);
final int width = Window.getClientWidth() - 10;
final int height = Window.getClientHeight() - 10;
prompt.setSize(width+"", height+"");
prompt.showModal();
}
private static List<DataContainerGVO> makeClone(final Collection<DataContainerGVO> data) {
final List<DataContainerGVO> cloneData = new ArrayList<DataContainerGVO>();
if(data != null) {
for(final DataContainerGVO row : data){
if (row.isMap()){
final DataContainerGVO newMap = new DataContainerGVO(new DataMap());
for(final String key : row.getDataMap().keySet()){
final DataContainerGVO value = row.getDataMap().get(key);
final DataContainerGVO gvo = new DataContainerGVO(value != null? value.getDataString() : null);
if(value != null){
gvo.setStringDataType(value.getStringDataType());
gvo.setDateData(value.getDateData());
}
newMap.getDataMap().put(key, gvo);
}
cloneData.add(newMap);
}
}
}
return cloneData;
}
private void doColumnDataChange(final ColumnDefinition<DataContainerGVO, String> columnDefinition, final UIObject uiObject, final DataMap rowValue, final Object oldValue, final Object newValue, final boolean changedByUser) {
if ((source != null) && (source.getColumns() != null) && (columnDefinition instanceof QColumnDefinition)) {
final QColumnDefinition qColumnDefinition = (QColumnDefinition)columnDefinition;
DataGridColumnGVO dataGridColumnGVO = null;
for (final DataGridColumnGVO columnGVO: source.getColumns()) {
final String fieldName = columnGVO.getFieldName();
if ((fieldName != null) && (fieldName.equals(qColumnDefinition.getField()))) {
dataGridColumnGVO = columnGVO;
break;
}
}
ComponentRendererHelper.handleDataChange(dataGridColumnGVO, uiObject, oldValue, newValue);
if (changedByUser) {
changeRowStatus(rowValue, DataMap.ROW_STATUS_MODIFIED);
}
}
}
private void changeRowStatus(final DataMap rowValue, final String changeStatusTo) {
if (refreshingExistingRows) {
return;
}
if (rowValue == null) {
return;
}
final DataContainerGVO rowStatusGVO = rowValue.get(DataContainerGVO.ROW_STATUS_KEY);
if (rowStatusGVO == null) {
return;
}
// Changes row status only if row is unmodified
final String rowStatus = rowStatusGVO.getDataString();
if (DataContainerGVO.ROW_STATUS_UNMODIFIED.equals(rowStatus) && !DataContainerGVO.ROW_STATUS_NEW.equals(rowStatus)) {
final String rowNumber = rowValue.get(DataContainerGVO.ROW_NUMBER).getDataString();
final int rowIndex = Integer.parseInt(rowNumber) - 1;
final int rowCount = getDataTable().getRowCount();
// Update only the status if rowCount > rowIndex, in this case value is changed by user,
// otherwise the datagrid is being constructed so no need to update
if (rowCount > rowIndex ) {
rowStatusGVO.setDataString(changeStatusTo);
rowValue.get(DataContainerGVO.ROW_NUMBER).setDataString("*" + rowNumber);
getDataTable().setElement(Integer.parseInt(rowNumber)-1, 0, new QLabel("*"+rowNumber).getElement());
}
}
}
@Override
public void onScroll(final ScrollEvent event) {
if (scrollPosition == getDataWrapper().getScrollTop()) {
return;
}
final int clientHeight = getDataWrapper().getClientHeight();
final int scrollHeight = getDataWrapper().getScrollHeight();
scrollPosition = getDataWrapper().getScrollTop();
final boolean scrollBarHitsBottom = (scrollPosition + clientHeight) >= scrollHeight;
final boolean scrollBarIsOnTop = scrollPosition == 0;
if (!scrollBarIsOnTop && scrollBarHitsBottom) {
scrollEvent = true;
gotoNextPage();
}
}
public boolean isScrollEvent() {
return scrollEvent;
}
public void setScrollEvent(final boolean scrollEvent) {
this.scrollEvent = scrollEvent;
}
@Override
public void setDataToCell(final DataContainerGVO valueToSet, final boolean b, final String senderId, final String cellOnRowToSet) {
final String[] inputRef = cellOnRowToSet.split("[.]");
final int rowIndex = getRowIndex(inputRef[0].toString().substring(inputRef[0].indexOf("[")+1, inputRef[0].indexOf("]")));
final String column = inputRef[1];
setColumnValue(rowIndex, column, valueToSet);
}
@Override
public void setColumnValue(final String columnName, final DataContainerGVO value) {
final int rowIndex = getSelectedRowIndex();
setColumnValue(rowIndex, columnName, value);
}
@Override
@SuppressWarnings({"deprecation"})
public void setColumnValue(final int rowIndex, final String columnName, final DataContainerGVO value) {
if (rowIndex < 0) {
return;
}
final DataContainerGVO rowValue = getRowValue(rowIndex);
if (rowValue == null) {
return;
}
final DataMap dataMap = rowValue.getDataMap();
if (hasColumnName(columnName, dataMap)) {
final DataContainerGVO currentValue = dataMap.get(columnName);
if (isChanged(currentValue, value)) {
dataMap.put(columnName, value);
changeRowStatus(dataMap, DataMap.ROW_STATUS_MODIFIED);
setRowValue(rowIndex, rowValue);
}
}
}
@SuppressWarnings("rawtypes")
private boolean hasColumnName(final String columnName, final DataMap dataMap) {
if (dataMap.containsKey(columnName)) {
return true;
}
final DefaultTableDefinition tableDefinition = (DefaultTableDefinition) getTableDefinition();
final int numCols = tableDefinition.getColumnDefinitionCount();
for (int i = 0; i < numCols; i++) {
final QColumnDefinition columnDefinition =
(QColumnDefinition) tableDefinition.getColumnDefinition(i);
final String fieldName = columnDefinition.getField();
if (fieldName.equals(columnName)) {
return true;
}
}
return false;
}
private boolean isChanged(final DataContainerGVO oldValue, final DataContainerGVO newValue) {
if ((oldValue == null) && (newValue != null)) {
return true;
}
if ((oldValue != null) && (newValue == null)) {
return true;
}
if ((oldValue == null) && (newValue == null)) {
return false;
}
return !oldValue.equalsValue(newValue);
}
/*
* The following method returns the row number when setting or getting data is done on a data grid cell.
* Setting and getting of datagrid cell can be done either by using the row index directly or by mentioning the change to be on the selected row.
* */
@Override
public int getRowIndex(final String rowIndex){
if (rowIndex.equals(DataMap.SELECTED_INDEX)) {
return getSelectedRowIndex();
}
return Integer.parseInt(rowIndex);
}
private int getSelectedRowIndex() {
final Set<DataContainerGVO> selectedRowValues = getSelectedRowValues();
if (selectedRowValues != null) {
for (final DataContainerGVO row: selectedRowValues) {
final DataContainerGVO rowNumberColumn = row.getDataMap().get(DataMap.ROW_NUMBER);
if (rowNumberColumn != null) {
String rowIndex = rowNumberColumn.getDataString();
rowIndex = rowIndex.replaceAll("[" + QAMLConstants.TOKEN_NEW + QAMLConstants.TOKEN_MODIFIED + QAMLConstants.TOKEN_DELETED + "]", "");
return Integer.parseInt(rowIndex) - 1;
}
break;
}
}
return -1;
}
@Override
public void addToDropDownValuesForColumnList(final String dropDownColumnName, final SetValueGVO setValue) {
dropDownColumnAndValues.put(dropDownColumnName, setValue);
}
public Map<String, SetValueGVO> getDropDownColumnAndValues() {
return dropDownColumnAndValues;
}
@Override
public void setColumnVisible(final String column, final boolean value) {
final DataGridColumnGVO columnGVO = getColumn(column);
if (columnGVO == null) {
return;
}
columnGVO.setVisible(value);
setTableDefinition(DataGridFactory.createTableDefinition(source, source.getColumns(), uuid, parent, this));
refreshColumnHeaders(true);
((QTableModel) getTableModel()).processData(getRowValues());
redraw();
}
@Override
public void setColumnLabel(final String column, final String value) {
final DataGridColumnGVO columnGVO = getColumn(column);
if (columnGVO == null) {
return;
}
columnGVO.setDisplayname(value);
refreshColumnHeaders(true);
}
private DataGridColumnGVO getColumn(final String column) {
if ((source != null) && (source.getColumns() != null)) {
final DataGridColumnGVO[] columns = source.getColumns();
for (final DataGridColumnGVO columnGVO : columns) {
if (columnGVO == null) {
continue;
}
final String columnId = columnGVO.getId();
if ((columnId != null) && columnId.equals(column)) {
return columnGVO;
}
}
}
return null;
}
@Override
public void addRowSelectionChangeHandler(final RowSelectionChangeHandler handler) {
if (handler != null) {
rowSelectionChangeHandlers.add(handler);
}
}
private void fireRowSelectionChange(final int rowIndex, final Object rowValue) {
for (int i=0; i<rowSelectionChangeHandlers.size(); i++) {
final RowSelectionChangeHandler handler = rowSelectionChangeHandlers.get(i);
final RowSelectionChangeEvent event = new RowSelectionChangeEvent(this, rowIndex, rowValue);
event.dispatch(handler);
}
}
}