package org.aplikator.client.local.widgets;
import static org.aplikator.client.local.widgets.DateFieldWidget.mapLanguageToAplikatorLocale;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.aplikator.client.local.Aplikator;
import org.aplikator.client.local.SettingsStorage;
import org.aplikator.client.local.wizards.WizardSupport;
import org.aplikator.client.local.wizards.WizardSupportCallbacks;
import org.aplikator.client.shared.data.ClientContext;
import org.aplikator.client.shared.data.Operation;
import org.aplikator.client.shared.data.PrimaryKey;
import org.aplikator.client.shared.data.RecordContainerDTO;
import org.aplikator.client.shared.data.RecordDTO;
import org.aplikator.client.shared.data.SearchResult;
import org.aplikator.client.shared.descriptor.FunctionDTO;
import org.aplikator.client.shared.descriptor.PropertyDTO;
import org.aplikator.client.shared.descriptor.QueryDescriptorDTO;
import org.aplikator.client.shared.descriptor.QueryParameterDTO;
import org.aplikator.client.shared.descriptor.RecordsPageDTO;
import org.aplikator.client.shared.descriptor.SortDescriptorDTO;
import org.aplikator.client.shared.descriptor.ViewDTO;
import org.aplikator.client.shared.descriptor.WizardPageDTO;
import org.aplikator.client.shared.rpc.AplikatorErrorCallback;
import org.aplikator.client.shared.rpc.AplikatorException;
import org.aplikator.client.shared.rpc.AplikatorService;
import org.gwtbootstrap3.client.shared.event.ModalShownEvent;
import org.gwtbootstrap3.client.shared.event.ModalShownHandler;
import org.gwtbootstrap3.client.ui.*;
import org.gwtbootstrap3.client.ui.constants.FormType;
import org.gwtbootstrap3.client.ui.constants.IconType;
import org.gwtbootstrap3.client.ui.constants.ModalBackdrop;
import org.gwtbootstrap3.client.ui.gwt.CellTable;
import org.gwtbootstrap3.client.ui.html.Div;
import org.gwtbootstrap3.client.ui.html.Span;
import org.gwtbootstrap3.client.ui.html.Strong;
import org.gwtbootstrap3.extras.datetimepicker.client.ui.DateTimePicker;
import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.constants.DateTimePickerView;
import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.events.ChangeDateEvent;
import org.gwtbootstrap3.extras.datetimepicker.client.ui.base.events.ChangeDateHandler;
import org.jboss.errai.common.client.api.RemoteCallback;
import org.jboss.errai.enterprise.client.jaxrs.api.RestClient;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.AbstractPager;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.cellview.client.HasKeyboardPagingPolicy;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DeckPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.CellPreviewEvent;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.HasRows;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
public class TableListerWidget extends Composite implements TableInterface {
public static final int TABLE_NAVBAR_HEIGHT = 52;
private static final int MAX_TABLE_STRING_LENGTH = 80;
private static Logger LOG = Logger.getLogger(TableListerWidget.class.getName());
private static TableListerWidgetUiBinder uiBinder = GWT.create(TableListerWidgetUiBinder.class);
static {
TableListerWidgetResources.INSTANCE.cellListStyle().ensureInjected();
}
private final CellList<RecordDTO> cellList;
private final SingleSelectionModel<RecordDTO> listSelectionModel;
private final ShowMorePagerPanel listPagerPanel;
private final ScrollPanel listScroller;
private final ScrollPanel formScroller;
private final AplikatorDataProvider listDataProvider;
private final SingleSelectionModel<RecordDTO> gridSelectionModel;
private final ScrollPanel gridScroller;
private final GridDataProvider gridDataProvider;
private final ViewDTO view;
private final String ownerProperty;
@UiField
Navbar navbar;
@UiField
Strong title;
@UiField
ButtonGroup switchTableList;
@UiField
RadioButton buttonList;
@UiField
RadioButton buttonTable;
@UiField
Row listContainer;
@UiField
Row gridContainer;
@UiField
NavbarForm queryControls;
@UiField
ListBox querySelector;
@UiField
FormLabel queryLabel;
@UiField
NavbarForm sortControls;
@UiField
ListBox sortSelector;
@UiField
FormLabel sortLabel;
@UiField
NavbarForm queryParameters;
@UiField
TextBox queryTextField;
@UiField
ListBox queryListField;
@UiField
DateTimePicker queryDateField;
@UiField
Button buttonQuery;
@UiField
Button buttonPopupSearch;
@UiField
TextBox searchField;
@UiField
Button buttonSearch;
@UiField
Modal searchModal;
@UiField
Button buttonCreate;
@UiField
Button buttonDelete;
@UiField
Button buttonReload;
@UiField
Button buttonCancel;
@UiField
Button buttonSave;
@UiField
Button buttonFunction;
@UiField
ListDropDown menuFunction;
@UiField
DropDownMenu menuFunctionItems;
@UiField
NavbarText rangeLabelHolder;
RangeLabelPager listPager;
SimplePager gridPager;
@UiField
Column listColumn;
@UiField
Column formColumn;
@UiField
Column gridColumn;
CellTable<RecordDTO> grid;
Modal formPopup;
FormWidget formForGrid;
RecordContainerDTO recordContainerDTO;
private NestedEditorNotification nestedEditorNotification = null;
private FormWidget form;
private DeckPanel formHolder;
private Label noForm;
private boolean editingNewRecord = false;
private ListMode listMode = ListMode.STANDARD;
private DisplayMode displayMode = DisplayMode.LIST;
private int pageSize = 0;
private String indexSearchArgument;
private RecordDTO listSelectedRecordDTO = null;
private RecordDTO gridSelectedRecordDTO = null;
private int recordCount = -1;
private PrimaryKey ownerPrimaryKey;
private HasFields ownerForm;
private boolean enabled = true;
private boolean initialized = false;
@SuppressWarnings("GWTStyleCheck")
public TableListerWidget(ViewDTO view, PropertyDTO ownerProperty, HasFields ownerForm, int availableHeight) {
super();
this.view = view;
this.pageSize = view.getPageSize();
this.ownerProperty = (ownerProperty != null) ? ownerProperty.getId() : null;
this.ownerForm = ownerForm;
recordContainerDTO = new RecordContainerDTO();
initWidget(uiBinder.createAndBindUi(this));
//top navigation panel
if (ownerProperty != null) {
navbar.addStyleName("nestedTableNavbar");
}
//title
title.setText(this.view.getLocalizedName());
//buttons
LayoutUtils.addTooltip(buttonList, Aplikator.application.getConfigString("aplikator.table.showList"));
LayoutUtils.addTooltip(buttonTable, Aplikator.application.getConfigString("aplikator.table.showGrid"));
LayoutUtils.addTooltip(buttonReload, Aplikator.application.getConfigString("aplikator.table.reload"));
LayoutUtils.addTooltip(buttonCreate, Aplikator.application.getConfigString("aplikator.table.create"));
LayoutUtils.addTooltip(buttonDelete, Aplikator.application.getConfigString("aplikator.table.delete"));
LayoutUtils.addTooltip(buttonCancel, Aplikator.application.getConfigString("aplikator.table.cancel"));
LayoutUtils.addTooltip(buttonSave, Aplikator.application.getConfigString("aplikator.table.save"));
//sort selector
for (SortDescriptorDTO sd : this.view.getSortDescriptors()) {
String sortLabel = sd.getLocalizedName();
if (sd.isPrimaryAscending()) {
sortLabel = "\u2191 " + sortLabel;
} else {
sortLabel = "\u2193 " + sortLabel;
}
sortSelector.addItem(sortLabel, sd.getId());
}
final String searchPopupTitlePrefix = Aplikator.application.getConfigString("aplikator.table.searchPopupPrefix");
sortSelector.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
buttonPopupSearch.setEnabled(isSelectedSortScrollable());
SortDescriptorDTO activeSort = getSelectedSort();
TableListerWidget.this.view.setActiveSort(activeSort.getId());
searchModal.setTitle(searchPopupTitlePrefix + " " + activeSort.getLocalizedName());
SettingsStorage.storeSetting(TableListerWidget.this.view.getId() + SettingsStorage.ACTIVE_SORT, activeSort.getId());
reload();
}
});
if (this.view.getSortDescriptors().size() > 0) {
String storedSort = SettingsStorage.getSetting(TableListerWidget.this.view.getId() + SettingsStorage.ACTIVE_SORT);
int storedSortIndex = TableListerWidget.this.view.getSortIndex(storedSort);
sortSelector.setSelectedIndex(-1);
sortSelector.setSelectedIndex(storedSortIndex);
TableListerWidget.this.view.setActiveSort(TableListerWidget.this.view.getSortDescriptors().get(storedSortIndex).getId());
searchModal.setTitle(searchPopupTitlePrefix + " " + TableListerWidget.this.view.getSortDescriptors().get(storedSortIndex).getLocalizedName());
}
sortLabel.setText(Aplikator.application.getConfigString("aplikator.table.sort"));
sortControls.setVisible(this.view.getSortDescriptors().size() > 1);
//search field and button
buttonPopupSearch.setEnabled(false);
//searchModal.getWidget(0).addStyleName("app-mg-right-15");
searchModal.getWidget(0).addStyleName("app-mg-top-94");
searchModal.addShownHandler(new ModalShownHandler() {
@Override
public void onShown(ModalShownEvent evt) {
searchField.setFocus(true);
}
});
buttonPopupSearch.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
searchModal.show();
}
});
buttonSearch.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
searchModal.hide();
TableListerWidget.this.sqlSearch();
}
});
searchField.addKeyUpHandler(new KeyUpHandler() {
@Override
public void onKeyUp(KeyUpEvent event) {
event.stopPropagation();
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
searchModal.hide();
TableListerWidget.this.sqlSearch();
}
}
});
//filter selector
queryDateField.setFormat("dd.MM.yyyy");
queryDateField.setMinView(DateTimePickerView.MONTH);
queryDateField.setAutoClose(true);
for (QueryDescriptorDTO qd : this.view.getQueryDescriptors()) {
querySelector.addItem(qd.getLocalizedName(), qd.getId());
}
querySelector.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
enableQueryParameterFields(true);
}
});
buttonQuery.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
reload();
}
});
queryTextField.addKeyUpHandler(new KeyUpHandler() {
@Override
public void onKeyUp(KeyUpEvent event) {
event.stopPropagation();
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
reload();
}
}
});
queryListField.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
event.stopPropagation();
reload();
}
});
queryDateField.addChangeDateHandler(new ChangeDateHandler() {
@Override
public void onChangeDate(ChangeDateEvent evt) {
reload();
}
});
if (this.view.getQueryDescriptors().size() > 0) {
String storedFilter = SettingsStorage.getSetting(TableListerWidget.this.view.getId() + SettingsStorage.ACTIVE_FILTER);
int storedFilterIndex = TableListerWidget.this.view.getQueryIndex(storedFilter);
querySelector.setSelectedIndex(-1);
querySelector.setSelectedIndex(storedFilterIndex);
//querySelector.setItemSelected(querySelector.getSelectedIndex(), false);
TableListerWidget.this.view.setActiveFilter(TableListerWidget.this.view.getQueryDescriptors().get(storedFilterIndex).getId());
}
queryLabel.setText(Aplikator.application.getConfigString("aplikator.table.filter"));
queryControls.setVisible(this.view.getQueryDescriptors().size() > 1);
queryParameters.setVisible(TableListerWidget.this.view.getQueryDescriptors().get(querySelector.getSelectedIndex()).getQueryParameters().size() == 1);
if (view.getFunctions().size() == 1) {
buttonFunction.setVisible(true);
buttonFunction.setEnabled(true);
buttonFunction.setText(view.getFunctions().get(0).getLocalizedName());
ClientContext clientContext = new ClientContext();
clientContext.setUser(Aplikator.application.getUsername());
clientContext.setLocale(Aplikator.application.getLocale());
clientContext.setView(view);
final WizardSupport wizardSupport = new WizardSupport(view.getFunctions().get(0), clientContext, new WizardSupportCallbacks() {
@Override
public void wizardPageCallback(WizardPageDTO response, boolean forw) {
}
@Override
public void runBeforeFunctionCallback() {
buttonFunction.setEnabled(false);
}
@Override
public void runAfterFunctionCallback() {
buttonFunction.setEnabled(true);
}
});
buttonFunction.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
wizardSupport.changePageRequest(true);
}
});
} else if (view.getFunctions().size() > 1) {
menuFunction.setVisible(true);
for (FunctionDTO functionDTO : view.getFunctions()) {
final AnchorListItem functionHandle = new AnchorListItem(functionDTO.getLocalizedName());
menuFunctionItems.add(functionHandle);
ClientContext clientContext = new ClientContext();
clientContext.setUser(Aplikator.application.getUsername());
clientContext.setLocale(Aplikator.application.getLocale());
clientContext.setView(view);
final WizardSupport wizardSupport = new WizardSupport(functionDTO, clientContext, new WizardSupportCallbacks() {
@Override
public void wizardPageCallback(WizardPageDTO response, boolean forw) {
}
@Override
public void runBeforeFunctionCallback() {
functionHandle.setEnabled(false);
}
@Override
public void runAfterFunctionCallback() {
functionHandle.setEnabled(true);
}
});
functionHandle.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
wizardSupport.changePageRequest(true);
}
});
}
}
listPager = new RangeLabelPager();
gridPager = new SimplePager(SimplePager.TextLocation.CENTER, false, false) {
@Override
protected String createText() {
// Default text is 1 based.
NumberFormat formatter = NumberFormat.getFormat("#,###");
HasRows display = getDisplay();
Range range = display.getVisibleRange();
int pageStart = range.getStart() + 1;
int pageSize = range.getLength();
int dataSize = display.getRowCount();
int endIndex = Math.min(dataSize, pageStart + pageSize - 1);
endIndex = Math.max(pageStart, endIndex);
boolean exact = display.isRowCountExact();
return formatter.format(pageStart) + "-" + formatter.format(endIndex)
+ (exact ? " : " : " : ") + formatter.format(dataSize);
}
};
rangeLabelHolder.add(listPager);
rangeLabelHolder.add(gridPager);
// scrollable cellList
cellList = new CellList<RecordDTO>(new RecordCell(), TableListerWidgetResources.INSTANCE, RecordDTO.KEY_PROVIDER);
cellList.setPageSize(pageSize);
listSelectionModel = new SingleSelectionModel<RecordDTO>(RecordDTO.KEY_PROVIDER);
cellList.setSelectionModel(listSelectionModel, DefaultSelectionEventManager.createCustomManager(createVetoTranslator()));
cellList.setKeyboardPagingPolicy(HasKeyboardPagingPolicy.KeyboardPagingPolicy.CHANGE_PAGE);
cellList.setKeyboardSelectionPolicy(HasKeyboardSelectionPolicy.KeyboardSelectionPolicy.ENABLED);
cellList.setLoadingIndicator(new LoadingLabel());
cellList.setEmptyListWidget(new EmptyLabel());
listSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
if (listSelectionModel.getSelectedObject() != null) {
listSelectedRecordDTO = listSelectionModel.getSelectedObject();
formHolder.showWidget(1);
if (!editingNewRecord) {
openForm();
}
} else {
listSelectedRecordDTO = null;
formHolder.showWidget(0);
}
}
});
final int SCROLL_OFFSET = Aplikator.application.isShowNavigation() ? Aplikator.MAINMENUBAR_HEIGHT + TABLE_NAVBAR_HEIGHT : TABLE_NAVBAR_HEIGHT;
final int scrollHeight = (availableHeight > 0 ? availableHeight + TABLE_NAVBAR_HEIGHT + SCROLL_OFFSET : Window.getClientHeight()) - SCROLL_OFFSET;
listScroller = new ScrollPanel();
listScroller.getElement().getStyle().setHeight(scrollHeight, Unit.PX);
listPagerPanel = new ShowMorePagerPanel(listScroller);
listPagerPanel.setIncrementSize(pageSize);
listPagerPanel.setDisplay(cellList);
listPager.setDisplay(cellList);
listDataProvider = new AplikatorDataProvider(listScroller, pageSize);
listDataProvider.addDataDisplay(cellList);
form = new FormWidget(this.view, this, this.ownerForm);
form.addStyleName("app-mg-top-5");
form.addStyleName("app-row-divider");
noForm = new Label(Aplikator.application.getConfigString("aplikator.table.noselect"));
formHolder = new DeckPanel();
formHolder.add(noForm);
formHolder.add(form);
formHolder.showWidget(0);
formScroller = new ScrollPanel(formHolder);
formScroller.addStyleName("formscroller");
formScroller.getElement().getStyle().setHeight(scrollHeight, Unit.PX);
formPopup = createFormPopup();
grid = new CellTable<RecordDTO>(pageSize, RecordDTO.KEY_PROVIDER);
grid.setWidth("100%");
gridSelectionModel = new SingleSelectionModel<RecordDTO>(RecordDTO.KEY_PROVIDER);
grid.setSelectionModel(gridSelectionModel/*, DefaultSelectionEventManager.createCustomManager(createVetoTranslator())*/);
grid.setKeyboardPagingPolicy(HasKeyboardPagingPolicy.KeyboardPagingPolicy.CHANGE_PAGE);
grid.setKeyboardSelectionPolicy(HasKeyboardSelectionPolicy.KeyboardSelectionPolicy.BOUND_TO_SELECTION);
grid.setLoadingIndicator(new LoadingLabel());
grid.setEmptyTableWidget(new EmptyLabel());
gridSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
if (gridSelectionModel.getSelectedObject() != null) {
gridSelectedRecordDTO = gridSelectionModel.getSelectedObject();
} else {
gridSelectedRecordDTO = null;
}
}
});
for (final PropertyDTO propertyDTO : view.getProperties()) {
grid.addColumn(new com.google.gwt.user.cellview.client.Column<RecordDTO, String>(new TextCell()) {
@Override
public String getValue(RecordDTO row) {
String retval = propertyDTO.getStringValue(row);
if (retval.length() <= MAX_TABLE_STRING_LENGTH) {
return retval;
} else {
return retval.substring(0, MAX_TABLE_STRING_LENGTH) + "...";
}
}
}, propertyDTO.getLocalizedName());
}
grid.addCellPreviewHandler(new CellPreviewEvent.Handler<RecordDTO>() {
long lastClick = -1000;
@Override
public void onCellPreview(CellPreviewEvent<RecordDTO> event) {
long clictAt = System.currentTimeMillis();
if (BrowserEvents.CLICK.equalsIgnoreCase(event.getNativeEvent().getType())) {
if (clictAt - lastClick < 300) { // dblclick on 2 clicks detected within 300 ms
showFormPopup(event.getValue().getPrimaryKey());
}
lastClick = System.currentTimeMillis();
}
if (BrowserEvents.KEYUP.equalsIgnoreCase(event.getNativeEvent().getType())) {
event.getNativeEvent().stopPropagation();
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
showFormPopup(event.getValue().getPrimaryKey());
}
}
}
});
gridScroller = new ScrollPanel();
gridScroller.getElement().getStyle().setHeight(scrollHeight, Unit.PX);
// gridPagerPanel = new ShowMorePagerPanel(gridScroller);
// gridPagerPanel.setIncrementSize(pageSize);
// gridPagerPanel.setDisplay(grid);
gridPager.setDisplay(grid);
gridDataProvider = new GridDataProvider();
gridDataProvider.addDataDisplay(grid);
if (ownerProperty == null) {
gridScroller.add(grid);
}
if (availableHeight <= 0) {
Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
listScroller.getElement().getStyle().setHeight(event.getHeight() - SCROLL_OFFSET, Unit.PX);
formScroller.getElement().getStyle().setHeight(event.getHeight() - SCROLL_OFFSET, Unit.PX);
gridScroller.getElement().getStyle().setHeight(event.getHeight() - SCROLL_OFFSET, Unit.PX);
formPopup.setPixelSize(Window.getClientWidth() - 40, Window.getClientHeight());
}
});
}
listColumn.setSize(LayoutUtils.size(this.view.getListPanelWidth()));
listColumn.add(listPagerPanel);
formColumn.setSize(LayoutUtils.size(12 - this.view.getListPanelWidth()));
formColumn.add(formScroller);
gridScroller.getElement().getStyle().setHeight(scrollHeight, Unit.PX);
if (ownerProperty == null) {
gridColumn.add(gridScroller);
} else {
gridColumn.add(grid);
}
initialized = true;
boolean openAsTable = view.isOpenAsTable();
String storedtableModeString = SettingsStorage.getSetting(TableListerWidget.this.view.getId() + SettingsStorage.TABLE_MODE);
if (storedtableModeString != null) {
openAsTable = Boolean.parseBoolean(storedtableModeString);
}
if (openAsTable) {
showTable(null);
} else {
showList(null);
}
enableNavigationControls();
enableQueryParameterFields(false);
}
private void enableQueryParameterFields(boolean fireReload) {
QueryDescriptorDTO activeFilter = TableListerWidget.this.view.getQueryDescriptors().get(querySelector.getSelectedIndex());
TableListerWidget.this.view.setActiveFilter(activeFilter.getId());
SettingsStorage.storeSetting(TableListerWidget.this.view.getId() + SettingsStorage.ACTIVE_FILTER, activeFilter.getId());
if (activeFilter.getQueryParameters().size() == 1) {
queryParameters.setVisible(true);
if ("java.util.Date".equals(TableListerWidget.this.view.getActiveQueryDescriptor().getQueryParameters().get(0).getProperty().getType())) {
String formatPattern = TableListerWidget.this.view.getActiveQueryDescriptor().getQueryParameters().get(0).getProperty().getFormatPattern();
queryDateField.setFormat(formatPattern.replace("M", "m"));
queryDateField.setLanguage(mapLanguageToAplikatorLocale());
if (!formatPattern.contains("h") && !formatPattern.contains("H")) { //display date picker only
queryDateField.setMinView(DateTimePickerView.MONTH);
}
queryDateField.setVisible(true);
queryListField.setVisible(false);
queryTextField.setVisible(false);
queryDateField.setValue(null);
} else if (TableListerWidget.this.view.getActiveQueryDescriptor().getQueryParameters().get(0).getProperty().getListValues() != null) {
queryDateField.setVisible(false);
queryListField.setVisible(true);
queryTextField.setVisible(false);
queryListField.clear();
for (org.aplikator.client.shared.data.ListItem item : TableListerWidget.this.view.getActiveQueryDescriptor().getQueryParameters().get(0).getProperty().getListValues()) {
queryListField.addItem(item.getName(), item.getValue().toString());
}
queryListField.setSelectedIndex(0);
queryListField.setFocus(true);
reload();
} else {
queryDateField.setVisible(false);
queryListField.setVisible(false);
queryTextField.setVisible(true);
queryTextField.setText("");
queryTextField.setFocus(true);
}
} else {
queryParameters.setVisible(false);
if (fireReload) {
reload();
}
}
}
private void showFormPopup(PrimaryKey primaryKey) {
formPopup.setPixelSize(Window.getClientWidth() - 40, Window.getClientHeight());
formPopup.show();
formForGrid.displayRecord(primaryKey, recordContainerDTO, TableListerWidget.this.ownerProperty, ownerPrimaryKey, null);
}
private Modal createFormPopup() {
ModalBody formPopupContents = new ModalBody();
formPopupContents.addStyleName("formscroller");
final Modal formPopup = new Modal();
formPopup.getElement().getStyle().setOverflowY(Style.Overflow.AUTO);//fix against hidding scrollbar in modal stack
formPopup.setDataBackdrop(ModalBackdrop.STATIC);
formForGrid = new FormWidget(this.view, this, this.ownerForm);
ModalHeader buttonPanel = new ModalHeader();
Button buttonCancelPopup = new Button("", IconType.BAN, new ClickHandler() {
public void onClick(ClickEvent event) {
formForGrid.cancel();
if (editingNewRecord) {
gridDataProvider.removeFirstRecord();
}
editingNewRecord = false;
formPopup.hide();
focusGrid();
}
});
buttonPanel.add(buttonCancelPopup);
final Button buttonSavePopup = new Button("", IconType.SAVE, new ClickHandler() {
public void onClick(ClickEvent event) {
formPopup.hide();
if (formForGrid != null) {
formForGrid.save(true);
}
focusGrid();
}
});
buttonPanel.add(buttonSavePopup);
LayoutUtils.addTooltip(buttonCancelPopup, Aplikator.application.getConfigString("aplikator.table.cancel"));
LayoutUtils.addTooltip(buttonSavePopup, Aplikator.application.getConfigString("aplikator.table.save"));
formPopup.add(buttonPanel);
formPopup.add(formPopupContents);
Row formPopupHolder = new Row();
formPopupHolder.add(formForGrid);
formPopupContents.add(formPopupHolder);
return formPopup;
}
@UiHandler("buttonList")
void showList(ClickEvent e) {
if (!buttonList.isEnabled()) {
buttonTable.setActive(true);
buttonList.setActive(false);
return;
}
gridContainer.setVisible(false);
listContainer.setVisible(true);
gridPager.setVisible(false);
listPager.setVisible(true);
rangeLabelHolder.getElement().getStyle().setMarginTop(15, Unit.PX);
rangeLabelHolder.getElement().getStyle().setMarginBottom(15, Unit.PX);
displayMode = DisplayMode.LIST;
buttonCancel.setVisible(true);
buttonSave.setVisible(true);
buttonList.setActive(true);
buttonTable.setActive(false);
listDataProvider.refreshListAndExtendScroll(0, null, cellList);
focusList();
SettingsStorage.storeSetting(TableListerWidget.this.view.getId() + SettingsStorage.TABLE_MODE, "false");
}
@UiHandler("buttonTable")
void showTable(ClickEvent e) {
if (!buttonTable.isEnabled()) {
buttonTable.setActive(false);
buttonList.setActive(true);
return;
}
if (listMode.equals(ListMode.INSERT)) {
refresh();
}
listContainer.setVisible(false);
gridContainer.setVisible(true);
listPager.setVisible(false);
gridPager.setVisible(true);
rangeLabelHolder.getElement().getStyle().setMarginTop(11, Unit.PX);
rangeLabelHolder.getElement().getStyle().setMarginBottom(11, Unit.PX);
displayMode = DisplayMode.GRID;
buttonCancel.setVisible(false);
buttonSave.setVisible(false);
buttonList.setActive(false);
buttonTable.setActive(true);
focusGrid();
SettingsStorage.storeSetting(TableListerWidget.this.view.getId() + SettingsStorage.TABLE_MODE, "true");
}
private void focusList() {
if (ownerProperty == null && displayMode.equals(DisplayMode.LIST)) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
@Override
public void execute() {
cellList.setFocus(true);
}
});
}
}
private void focusGrid() {
if (ownerProperty == null && displayMode.equals(DisplayMode.GRID)) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
@Override
public void execute() {
grid.setFocus(true);
}
});
}
}
public SingleSelectionModel<RecordDTO> getListSelectionModel() {
return listSelectionModel;
}
private boolean canEnableEmbedded() {
if (ownerPrimaryKey == null) {
return true;
} else {
return ownerPrimaryKey.getId() != -1;
}
}
void enableEditingControls() {
searchField.setEnabled(false);
buttonSearch.setEnabled(false);
buttonCreate.setEnabled(false);
buttonDelete.setEnabled(false);
buttonReload.setEnabled(false);
buttonPopupSearch.setEnabled(false);
sortSelector.setEnabled(false);
querySelector.setEnabled(false);
queryTextField.setEnabled(false);
queryListField.setEnabled(false);
queryDateField.setEnabled(false);
buttonQuery.setEnabled(false);
boolean canEnable = canEnableEmbedded();
buttonCancel.setEnabled(canEnable && enabled);
buttonSave.setEnabled(canEnable && enabled);
buttonList.setEnabled(false);
buttonTable.setEnabled(false);
if (nestedEditorNotification != null) {
nestedEditorNotification.nestedEditorStarted();
}
cellList.setKeyboardSelectionPolicy(HasKeyboardSelectionPolicy.KeyboardSelectionPolicy.DISABLED);
}
void enableNavigationControls() {
boolean canEnable = canEnableEmbedded();
searchField.setEnabled(canEnable);
buttonSearch.setEnabled(canEnable);
buttonCreate.setEnabled(canEnable && enabled);
buttonDelete.setEnabled(canEnable && enabled);
buttonReload.setEnabled(canEnable);
buttonPopupSearch.setEnabled(canEnable && isSelectedSortScrollable());
sortSelector.setEnabled(canEnable);
querySelector.setEnabled(canEnable);
queryTextField.setEnabled(canEnable);
queryListField.setEnabled(canEnable);
queryDateField.setEnabled(canEnable);
buttonQuery.setEnabled(canEnable);
buttonCancel.setEnabled(false);
buttonSave.setEnabled(false);
buttonList.setEnabled(canEnable);
buttonTable.setEnabled(canEnable);
if (nestedEditorNotification != null) {
nestedEditorNotification.nestedEditorFinished();
}
cellList.setKeyboardSelectionPolicy(HasKeyboardSelectionPolicy.KeyboardSelectionPolicy.BOUND_TO_SELECTION);
}
private boolean isSelectedSortScrollable() {
SortDescriptorDTO sort = getSelectedSort();
if (sort.getPrimarySortProperty().getType().equals("java.lang.String")) {//accept all strings
return true;
}
if (sort.getPrimarySortProperty().getType().equals("java.lang.Integer") //accept all int except primary key
&& !sort.getPrimarySortProperty().getId().equals(view.getEntity().getPrimaryKey().getId())) {
return true;
}
if (sort.getPrimarySortProperty().getType().equals("java.math.BigDecimal")) {//accept all numbers
return true;
}
return false;
}
private SortDescriptorDTO getSelectedSort() {
return TableListerWidget.this.view.getSortDescriptors().get(sortSelector.getSelectedIndex());
}
private DefaultSelectionEventManager.EventTranslator<RecordDTO> createVetoTranslator() {
DefaultSelectionEventManager.EventTranslator<RecordDTO> translator = new DefaultSelectionEventManager.EventTranslator<RecordDTO>() {
@Override
public boolean clearCurrentSelection(CellPreviewEvent<RecordDTO> event) {
NativeEvent nativeEvent = event.getNativeEvent();
boolean ctrlOrMeta = nativeEvent.getCtrlKey() || nativeEvent.getMetaKey();
return !ctrlOrMeta;
}
@Override
public DefaultSelectionEventManager.SelectAction translateSelectionEvent(CellPreviewEvent<RecordDTO> event) {
if (form.isDirty()) {
return DefaultSelectionEventManager.SelectAction.IGNORE;
}
return DefaultSelectionEventManager.SelectAction.DEFAULT;
}
};
return translator;
}
public void reload(String searchArgument) {
this.indexSearchArgument = searchArgument;
refresh();
}
@Override
public void initFromContainer(RecordContainerDTO initializingRecords) {
//Not supported for table yet, just reload
reload();
}
@Override
public void reload() {
this.indexSearchArgument = null;
searchField.setText("");
view.setSearchString("");
if (view.getActiveQueryDescriptor() != null && view.getActiveQueryDescriptor().getQueryParameters().size() > 1) {
final QueryParamDialogBox dialogBox = createQueryParamDialogBox();
dialogBox.show();
} else if (view.getActiveQueryDescriptor() != null && view.getActiveQueryDescriptor().getQueryParameters().size() == 1) {
view.getActiveQueryDescriptor().getQueryParameters().get(0).setValue(getQueryFieldValue());
refresh();
} else {
refresh();
}
}
private String getQueryFieldValue() {
if ("java.util.Date".equals(view.getActiveQueryDescriptor().getQueryParameters().get(0).getProperty().getType())) {
if (queryDateField.getValue() != null) {
return Long.toString(queryDateField.getValue().getTime());
} else {
return null;
}
} else if (view.getActiveQueryDescriptor().getQueryParameters().get(0).getProperty().getListValues() != null) {
return queryListField.getSelectedValue();
}
return queryTextField.getText();
}
@Override
public void refresh() {
editingNewRecord = false;
listSelectionModel.clear();
gridSelectionModel.clear();
if (ownerPrimaryKey == null) {
recordContainerDTO.clear();
}
if (indexSearchArgument != null) {
//loadDataSearch();
listMode = ListMode.INDEX;
recordCount = 0;
resetDataProviders();
} else {
listMode = ListMode.STANDARD;
recordCount = 0;
//resetDataProviders();
listDataProvider.resetCache();
cellList.setRowCount(0);
cellList.setVisibleRange(0, 0);
gridDataProvider.resetCache();
grid.setRowCount(0);
grid.setVisibleRange(0, 0);
RestClient.create(AplikatorService.class, new RemoteCallback<Integer>() {
@Override
public void callback(Integer resp) {
recordCount = resp;
resetDataProviders();
}
},
new AplikatorErrorCallback("aplikator.table.loaderror")
).getRecordCount(view.getId(), view.getActiveFilter(), view.getActiveSort(), view.getActiveQueryDescriptor(), view.getSearchString(), ownerProperty, (ownerPrimaryKey == null) ? null : ownerPrimaryKey.getSerializationString());
}
enableNavigationControls();
}
private void resetDataProviders() {
listDataProvider.resetCache();
cellList.setVisibleRange(0, pageSize);
listDataProvider.updateRowCount(recordCount, false);
listDataProvider.onRangeChanged(cellList);
gridDataProvider.resetCache();
grid.setVisibleRange(0, pageSize);
gridDataProvider.updateRowCount(recordCount, false);
gridDataProvider.onRangeChanged(grid);
}
private QueryParamDialogBox createQueryParamDialogBox() {
Container dialogWrapper = new Container();
dialogWrapper.setFluid(true);
Form dialogContents = new Form();
dialogContents.setType(FormType.HORIZONTAL);
final QueryParamDialogBox dialogBox = new QueryParamDialogBox();
dialogBox.setTitle(Aplikator.application.getConfigString("aplikator.table.queryparams"));
ModalBody contents = new ModalBody();
dialogWrapper.add(dialogContents);
contents.add(dialogWrapper);
dialogBox.add(contents);
final int paramCount = view.getActiveQueryDescriptor().getQueryParameters().size();
final ParamValues[] paramValues = new ParamValues[paramCount];
final Button closeButton = new Button(Aplikator.application.getConfigString("aplikator.table.ok"), new ClickHandler() {
@SuppressWarnings("unchecked")
public void onClick(ClickEvent event) {
queryParamDialogBoxClosed(dialogBox, paramCount, paramValues);
}
});
for (int i = 0; i < paramCount; i++) {
FormGroup paramPane = new FormGroup();
FormLabel paramLabel = new FormLabel();
paramLabel.setText(view.getActiveQueryDescriptor().getQueryParameters().get(i).getName());
paramPane.add(paramLabel);
paramValues[i] = new ParamValues(view.getActiveQueryDescriptor().getQueryParameters().get(i), dialogBox, paramCount, paramValues);
if (i == 0) {
dialogBox.firstField = paramValues[i];
}
paramPane.add(paramValues[i]);
dialogContents.add(paramPane);
}
ModalFooter buttonPanel = new ModalFooter();
dialogBox.add(buttonPanel);
buttonPanel.add(closeButton);
return dialogBox;
}
private void queryParamDialogBoxClosed(Modal dialogBox, int paramCount, ParamValues[] paramValues) {
dialogBox.hide();
for (int i = 0; i < paramCount; i++) {
view.getActiveQueryDescriptor().getQueryParameters().get(i).setValue(paramValues[i].getQueryParamValue());
}
refresh();
}
public PrimaryKey getSelectedPrimaryKey() {
RecordDTO rec = getSelectedRecord();
return rec == null ? null : rec.getPrimaryKey();
}
public RecordDTO getSelectedRecord() {
if (displayMode.equals(DisplayMode.GRID)) {
return this.gridSelectedRecordDTO;
} else {
return this.listSelectedRecordDTO;
}
}
private void sqlSearch() {
view.setSearchString(searchField.getText());
indexSearchArgument = null;
refresh();
}
private void indexSearch() {
indexSearchArgument = (searchField.getText());
refresh();
}
@UiHandler("buttonCreate")
void buttonCreateClicked(ClickEvent event) {
RecordDTO recordToCopy = null;
NativeEvent nEv = event.getNativeEvent();
if (nEv.getAltKey()) {
recordToCopy = getSelectedRecord();
}
listMode = ListMode.INSERT;
if (displayMode.equals(DisplayMode.GRID)) {
formPopup.setPixelSize(Window.getClientWidth() - 40, Window.getClientHeight());
formPopup.show();
formForGrid.addRecord(recordContainerDTO, ownerProperty, ownerPrimaryKey, recordToCopy, new AddRecordCallback() {
@Override
public void recordAdded(RecordDTO recordDTO) {
recordDTO.setPreview(Aplikator.application.getConfigString("aplikator.table.newRecordLabel"));
editingNewRecord = true;
gridSelectionModel.clear();
gridDataProvider.insertRecord(recordDTO);
gridSelectionModel.setSelected(recordDTO, true);
}
});
} else {
formHolder.showWidget(1);
form.addRecord(recordContainerDTO, ownerProperty, ownerPrimaryKey, recordToCopy, new AddRecordCallback() {
@Override
public void recordAdded(RecordDTO recordDTO) {
recordDTO.setPreview(Aplikator.application.getConfigString("aplikator.table.newRecordLabel"));
editingNewRecord = true;
listSelectionModel.clear();
listDataProvider.insertRecord(recordDTO);
listSelectionModel.setSelected(recordDTO, true);
}
});
formScroller.setVerticalScrollPosition(0);
}
}
@UiHandler("buttonCancel")
void buttonCancelClicked(ClickEvent event) {
buttonSave.setEnabled(false);
buttonCancel.setEnabled(false);
form.cancel();
if (editingNewRecord) {
listDataProvider.removeFirstRecord();
}
editingNewRecord = false;
}
private void openForm() {
form.displayRecord(getSelectedPrimaryKey(), recordContainerDTO, ownerProperty, ownerPrimaryKey, null);
formScroller.setVerticalScrollPosition(0);
}
@UiHandler("buttonSave")
void buttonSaveClicked(ClickEvent event) {
buttonSave.setEnabled(false);
buttonCancel.setEnabled(false);
form.save(true);
}
public void updateEditedRecord(RecordDTO savedRecordDTO) {
if (displayMode.equals(DisplayMode.LIST)) {
if (editingNewRecord) {
if (listSelectedRecordDTO != null && listSelectedRecordDTO.getPrimaryKey().equals(savedRecordDTO.getPrimaryKey())) {
listSelectionModel.setSelected(listSelectedRecordDTO, false);//remove temporary record from selection before changing ID and reselect afterwards
listSelectedRecordDTO.getPrimaryKey().setId(savedRecordDTO.getPrimaryKey().getId());
listSelectionModel.setSelected(listSelectedRecordDTO, true);
} else {
Messages.warning("Inconsistent state: selected pk:" + listSelectedRecordDTO.getPrimaryKey() + "\nsaved pk:" + savedRecordDTO.getPrimaryKey());
}
editingNewRecord = false;
}
if (listSelectedRecordDTO != null && listSelectedRecordDTO.getPrimaryKey().equals(savedRecordDTO.getPrimaryKey())) {
LOG.fine("UPDATE EDITED RECORD:" + listSelectedRecordDTO.getPrimaryKey() + " - " + savedRecordDTO.getPreview());
listSelectedRecordDTO.setPreview(savedRecordDTO.getPreview());
for (String s : savedRecordDTO.getProperties()) {
listSelectedRecordDTO.setValue(s, savedRecordDTO.getValue(s));
}
cellList.redraw();
}
} else {
if (editingNewRecord) {
if (gridSelectedRecordDTO != null && gridSelectedRecordDTO.getPrimaryKey().equals(savedRecordDTO.getPrimaryKey())) {
gridSelectionModel.setSelected(gridSelectedRecordDTO, false);//remove temporary record from selection before changing ID and reselect afterwards
gridSelectedRecordDTO.getPrimaryKey().setId(savedRecordDTO.getPrimaryKey().getId());
gridSelectionModel.setSelected(gridSelectedRecordDTO, true);
} else {
Messages.warning("Inconsistent state: selected pk:" + gridSelectedRecordDTO.getPrimaryKey() + "\nsaved pk:" + savedRecordDTO.getPrimaryKey());
}
editingNewRecord = false;
}
if (gridSelectedRecordDTO != null && gridSelectedRecordDTO.getPrimaryKey().equals(savedRecordDTO.getPrimaryKey())) {
LOG.fine("UPDATE EDITED RECORD:" + gridSelectedRecordDTO.getPrimaryKey() + " - " + savedRecordDTO.getPreview());
gridSelectedRecordDTO.setPreview(savedRecordDTO.getPreview());
for (String s : savedRecordDTO.getProperties()) {
gridSelectedRecordDTO.setValue(s, savedRecordDTO.getValue(s));
}
grid.redraw();
}
}
}
@Override
public void save() {
if (form != null && ownerProperty == null) {
form.save(true);
}
}
@UiHandler("buttonDelete")
void buttonDeleteClicked(ClickEvent event) {
createDeleteConfirmDialogBox().show();
}
private Modal createDeleteConfirmDialogBox() {
// Create a dialog box and set the caption text
// Create a table to layout the content
final Modal dialogBox = new Modal();
dialogBox.setDataBackdrop(ModalBackdrop.STATIC);
dialogBox.setTitle(Aplikator.application.getConfigString("aplikator.table.confirmation"));
ModalBody contents = new ModalBody();
contents.add(new Span(Aplikator.application.getConfigString("aplikator.table.confirmdelete")));
dialogBox.add(contents);
// Add a close button at the bottom of the dialog
Button okButton = new Button(Aplikator.application.getConfigString("aplikator.table.ok"), new ClickHandler() {
@SuppressWarnings("unchecked")
public void onClick(ClickEvent event) {
dialogBox.hide();
//if (ownerProperty != null) {
// recordContainer.addRecord(view, getSelectedRecord(), null, Operation.DELETE);
// pageData.remove(getSelectedRecord());
// redrawPage();
//} else {
RecordContainerDTO newContainer = new RecordContainerDTO();
if (displayMode.equals(DisplayMode.LIST)) {
//for (Record toDelete : listSelectionModel.getSelectedList()) {
newContainer.addRecord(view.getId(), listSelectionModel.getSelectedObject(), null, Operation.DELETE);
//}
} else {
//for (RecordDTO toDelete : gridSelectionModel.getSelectedList()) {
newContainer.addRecord(view.getId(), gridSelectionModel.getSelectedObject(), null, Operation.DELETE);
//}
}
try {
RestClient.create(AplikatorService.class,
new RemoteCallback<RecordContainerDTO>() {
@Override
public void callback(RecordContainerDTO records) {
Messages.success(Aplikator.application.getConfigString("aplikator.table.deletedok"));
reload();
}
},
new AplikatorErrorCallback("aplikator.table.deletederror")
).processRecords(newContainer);
} catch (AplikatorException e) {
Window.alert("CHYBA: " + e);
}
//}
}
});
Button cancelButton = new Button(Aplikator.application.getConfigString("aplikator.table.cancel"), new ClickHandler() {
@SuppressWarnings("unchecked")
public void onClick(ClickEvent event) {
dialogBox.hide();
}
});
ModalFooter buttonPanel = new ModalFooter();
dialogBox.add(buttonPanel);
buttonPanel.add(cancelButton);
buttonPanel.add(okButton);
// Return the dialog box
return dialogBox;
}
@UiHandler("buttonReload")
void buttonReloadClicked(ClickEvent event) {
reload();
}
public PrimaryKey getOwnerPrimaryKey() {
return ownerPrimaryKey;
}
public void setOwnerPrimaryKey(PrimaryKey value) {
ownerPrimaryKey = value;
}
public void setRecordContainerDTO(RecordContainerDTO recordContainerDTO) {
this.recordContainerDTO = recordContainerDTO;
}
public void setDirty(boolean dirty) {
// for (Form nestedForm:nestedForms){
// nestedForm.setDirty(dirty);
// }
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
this.form.setEnabled(enabled);
this.formForGrid.setEnabled(enabled);
}
void setListAccess(boolean active) {
if (!active) {
cellList.getElement().addClassName("inactive");
} else {
cellList.getElement().removeClassName("inactive");
}
}
public void addNestedEditorNotification(NestedEditorNotification nestedEditorNotification) {
this.nestedEditorNotification = nestedEditorNotification;
}
private enum ListMode {STANDARD, INSERT, INDEX}
private enum DisplayMode {LIST, GRID}
interface TableListerWidgetUiBinder extends UiBinder<Div, TableListerWidget> {
}
public interface TableListerWidgetResources extends CellList.Resources {
public static final TableListerWidgetResources INSTANCE = GWT.create(TableListerWidgetResources.class);
@Source("TableListerCellList.css")
CellList.Style cellListStyle();
}
public interface DataGridResources extends CellList.Resources {
public static final TableListerWidgetResources INSTANCE = GWT.create(TableListerWidgetResources.class);
@Source("TableListerCellList.css")
CellList.Style cellListStyle();
}
private static class QueryParamDialogBox extends Modal {
ParamValues firstField;
@Override
public void show() {
super.show();
if (firstField != null) {
firstField.setFocus();
}
}
}
private static class RecordCell extends AbstractCell<RecordDTO> {
@Override
public void render(Context ctx, RecordDTO value, SafeHtmlBuilder sb) {
if (value != null) {
String preview = value.getPreview();
if (preview == null || "".equals(preview)) {
preview = " ";
}
sb.appendHtmlConstant(preview);
}
}
}
private class ParamValues extends Composite {
TextBox queryTextField;
ListBox queryListField;
DateTimePicker queryDateField;
QueryParameterDTO queryParameter;
Div holder;
ParamValues(QueryParameterDTO queryParameter, final Modal dialogBox, final int paramCount, final ParamValues[] paramValues) {
this.queryParameter = queryParameter;
holder = new Div();
initWidget(holder);
if ("java.util.Date".equals(queryParameter.getProperty().getType())) {
queryDateField = new DateTimePicker();
String formatPattern = queryParameter.getProperty().getFormatPattern();
queryDateField.setFormat(formatPattern.replace("M", "m"));
queryDateField.setLanguage(mapLanguageToAplikatorLocale());
if (!formatPattern.contains("h") && !formatPattern.contains("H")) { //display date picker only
queryDateField.setMinView(DateTimePickerView.MONTH);
}
queryDateField.setAutoClose(true);
queryDateField.setValue(null);
holder.add(queryDateField);
} else if (queryParameter.getProperty().getListValues() != null) {
queryListField = new ListBox();
for (org.aplikator.client.shared.data.ListItem item : queryParameter.getProperty().getListValues()) {
queryListField.addItem(item.getName(), item.getValue().toString());
}
queryListField.setSelectedIndex(0);
holder.add(queryListField);
} else {
queryTextField = new TextBox();
queryTextField.setText("");
holder.add(queryTextField);
queryTextField.addKeyUpHandler(new KeyUpHandler() {
@Override
public void onKeyUp(KeyUpEvent event) {
event.stopPropagation();
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
queryParamDialogBoxClosed(dialogBox, paramCount, paramValues);
}
}
});
}
}
String getQueryParamValue() {
if ("java.util.Date".equals(queryParameter.getProperty().getType())) {
if (queryDateField.getValue() != null) {
return Long.toString(queryDateField.getValue().getTime());
} else {
return null;
}
} else if (queryParameter.getProperty().getListValues() != null) {
return queryListField.getSelectedValue();
} else {
return queryTextField.getValue();
}
}
void setFocus() {
if (queryTextField != null) {
queryTextField.setFocus(true);
} else if (queryListField != null) {
queryListField.setFocus(true);
}
}
}
/**
* A scrolling pager that automatically increases the range every time the
* scroll bar reaches the bottom.
*/
class ShowMorePagerPanel extends AbstractPager {
/**
* The default increment size.
*/
private static final int DEFAULT_INCREMENT = 20;
/**
* The scrollable panel.
*/
private final ScrollPanel scrollable;
/**
* The increment size.
*/
private int incrementSize = DEFAULT_INCREMENT;
/**
* The last scroll position.
*/
private int lastScrollPos = 0;
/**
* Construct a new {@link ShowMorePagerPanel}.
*/
public ShowMorePagerPanel(ScrollPanel scrollPanel) {
scrollable = scrollPanel;
initWidget(scrollable);
// Do not let the scrollable take tab focus.
scrollable.getElement().setTabIndex(-1);
// Handle scroll events.
scrollable.addScrollHandler(new ScrollHandler() {
@Override
public void onScroll(ScrollEvent event) {
HasRows display = getDisplay();
if (display == null) {
return;
}
// If scrolling up, ignore the event.
int oldScrollPos = lastScrollPos;
lastScrollPos = scrollable.getVerticalScrollPosition();
//LOG.info(TableListerWidget.this.view.getLocalizedName()+" OldScrollPos:" + oldScrollPos + " LastScrollPos:" + lastScrollPos);
if (oldScrollPos >= lastScrollPos) {
return;
}
int maxScrollTop = scrollable.getWidget().getOffsetHeight()
- scrollable.getOffsetHeight();
//LOG.info(TableListerWidget.this.view.getLocalizedName()+" Lastscrollpos:"+lastScrollPos+ " maxScrollTop:"+maxScrollTop);
//LOG.info(TableListerWidget.this.view.getLocalizedName()+" WidgetOffset:" + scrollable.getWidget().getOffsetHeight() + " panelOffset:" + scrollable.getOffsetHeight());
if (lastScrollPos >= maxScrollTop - 10) {
// We are near the end, so increase the page size.
int newPageSize = Math.min(
display.getVisibleRange().getLength() + incrementSize,
display.getRowCount());
//LOG.info(TableListerWidget.this.view.getLocalizedName()+" Extending scroll down. Size:" + newPageSize);
display.setVisibleRange(0, newPageSize);
}
}
});
}
/**
* Get the number of rows by which the range is increased when the scrollbar
* reaches the bottom.
*
* @return the increment size
*/
public int getIncrementSize() {
return incrementSize;
}
/**
* Set the number of rows by which the range is increased when the scrollbar
* reaches the bottom.
*
* @param incrementSize the incremental number of rows
*/
public void setIncrementSize(int incrementSize) {
this.incrementSize = incrementSize;
}
@Override
public void setDisplay(HasRows display) {
assert display instanceof Widget : "display must extend Widget";
scrollable.setWidget((Widget) display);
super.setDisplay(display);
}
@Override
protected void onRangeOrRowCountChanged() {
}
}
private class RangeLabelPager extends AbstractPager {
/**
* The label that shows the current range.
*/
private final Span label = new Span();
/**
* Construct a new {@link RangeLabelPager}.
*/
public RangeLabelPager() {
initWidget(label);
//label.addStyleName("control-label");
}
@Override
protected void onRangeOrRowCountChanged() {
if (listMode.equals(ListMode.STANDARD) || listMode.equals(ListMode.INDEX)) {
HasRows display = getDisplay();
Range range = display.getVisibleRange();
int start = range.getStart();
int end = Math.min(start + range.getLength(), display.getRowCount());
label.setText((start + 1) + " - " + end + " : " + display.getRowCount());
} else if (listMode.equals(ListMode.INSERT)) {
label.setText(Aplikator.application.getConfigString("aplikator.table.insertMode"));
}
}
}
private class AplikatorDataProvider extends AsyncDataProvider<RecordDTO> {
private final ScrollPanel scrollable;
private final int incrementSize;
private final List<RecordDTO> recordCache = new ArrayList<RecordDTO>();
private final List<RecordDTO> insertList = new ArrayList<RecordDTO>();
private boolean waitingForNextPage = false;
public AplikatorDataProvider(ScrollPanel scrollPanel, int inc) {
scrollable = scrollPanel;
incrementSize = inc;
}
/**
* {@link #onRangeChanged(HasData)} is called when the table requests a new
* range of data. You can push data back to the displays using
* {@link #updateRowData(int, List)}.
*/
@Override
protected void onRangeChanged(final HasData<RecordDTO> display) {
if (listMode.equals(ListMode.STANDARD)) {
// Get the new range.
final Range range = display.getVisibleRange();
final int start = range.getStart();
if (start > 0) {
Messages.warning("ONRANGECHANGE START>0");
}
final int length = range.getLength();
if (recordCount == 0 || length == 0) {
display.setRowCount(0);
return;
}
if (length > recordCache.size() && !waitingForNextPage) {
if (ownerProperty != null && (ownerPrimaryKey == null || ownerPrimaryKey.getId() == -1)) {
return;
}
final int pageStart = recordCache.size();
final int pageSize = length - pageStart;
//LOG.fine("LOADING PAGE:"+pageStart+"-"+length);
if (initialized) {
waitingForNextPage = true;
RestClient.create(AplikatorService.class,
new RemoteCallback<RecordsPageDTO>() {
@Override
public void callback(RecordsPageDTO resp) {
waitingForNextPage = false;
if (resp.getOffset() == recordCache.size()) {
processPageCallback(resp.getRecords(), start, display);
}
}
},
new AplikatorErrorCallback("aplikator.table.loaderror")
).getRecords(view.getId(), view.getActiveFilter(), view.getActiveSort(), view.getActiveQueryDescriptor(), view.getSearchString(), ownerProperty, (ownerPrimaryKey == null) ? null : ownerPrimaryKey.getSerializationString(), pageStart, pageSize);
}
}
} else if (listMode.equals(ListMode.INSERT)) {
updateRowCount(insertList.size(), true);
updateRowData(0, insertList);
if ((listSelectionModel.getSelectedObject() == null /*|| listSelectionModel.getSelectedList().size() == 0*/) && insertList.size() > 0) {
listSelectionModel.setSelected(insertList.get(0), true);
}
} else if (listMode.equals(ListMode.INDEX)) {
// Get the new range.
final Range range = display.getVisibleRange();
final int start = range.getStart();
if (start > 0) {
Messages.warning("ONRANGECHANGE START>0");
}
final int length = range.getLength();
//if (recordCount == 0 || length == 0)
// return;
if (length > recordCache.size() && !waitingForNextPage) {
final int pageStart = recordCache.size();
final int pageSize = length - pageStart;
waitingForNextPage = true;
RestClient.create(AplikatorService.class,
new RemoteCallback<SearchResult>() {
@Override
public void callback(SearchResult resp) {
recordCount = resp.getCount().intValue();
listDataProvider.updateRowCount(recordCount, true);
processPageCallback(resp.getRecords(), start, display);
}
},
new AplikatorErrorCallback("aplikator.table.loaderror")
).getPageSearch(view.getId(), indexSearchArgument, pageStart, pageSize);
}
}
}
private void processPageCallback(List<RecordDTO> newPage, int start, HasData<RecordDTO> display) {
int oldListEnd = recordCache.size();
recordCache.addAll(newPage);
waitingForNextPage = false;
refreshListAndExtendScroll(oldListEnd, newPage, display);
if ((listSelectionModel.getSelectedObject() == null /* || listSelectionModel.getSelectedList().size() == 0 */) && newPage.size() > 0) {
listSelectionModel.setSelected(newPage.get(0), true);
if (ownerProperty == null) {
cellList.setKeyboardSelectedRow(0, true);
}
}
}
public void refreshListAndExtendScroll(int start, List<RecordDTO> newPage, HasData<RecordDTO> display) {
if (cellList.getKeyboardSelectedRow() >= 0 && cellList.getKeyboardSelectedRow() <= (start - pageSize - 1)) {
//Window.alert("SELECTED:"+cellList.getKeyboardSelectedRow()+" START:"+start+" pageSize:"+pageSize);
scrollable.getElement().focus();
}
if (newPage == null && start == 0) {
updateRowData(start, recordCache);
} else {
updateRowData(start, newPage);
}
int scrollpos = scrollable.getMaximumVerticalScrollPosition();
if (TableListerWidget.this.ownerProperty == null && scrollpos <= 0 && scrollable.getElement().getClientHeight() > Window.getClientHeight()) {
return; //Safeguard against unreliable scroll.getMaximumVerticalScrollPosition() (but only for top level tables
}
int rangestart = display.getVisibleRange().getStart();
int rangelength = display.getVisibleRange().getLength();
int rowcount = display.getRowCount();
int newPageSize = Math.min(
display.getVisibleRange().getLength() + incrementSize,
display.getRowCount());
//LOG.fine("???Display "+TableListerWidget.this.view.getLocalizedName()+" VISIBLE:"+scrollable.isVisible()+"!!!Size:" + newPageSize + " scrolpos:" + scrollpos + " rangestart:" + rangestart + " rangelength:" + rangelength + " rowcount:" + rowcount);
if (scrollpos <= 0 && (rangestart + rangelength < rowcount)) {
//LOG.fine("!!!Display"+TableListerWidget.this.view.getLocalizedName()+" Extending scroll down automatically.-" + (rangestart+rangelength)+"<"+rowcount);
if (displayMode.equals(DisplayMode.LIST)) {
display.setVisibleRange(0, newPageSize);
}
}
}
public void resetCache() {
recordCache.clear();
waitingForNextPage = false;
insertList.clear();
}
public void insertRecord(RecordDTO rec) {
insertList.add(0, rec);
updateRowCount(insertList.size(), true);
updateRowData(0, insertList);
cellList.redraw();
}
public void removeFirstRecord() {
if (insertList.size() > 0) {
listSelectionModel.setSelected(insertList.get(0), false);
insertList.remove(0);
}
updateRowCount(insertList.size(), true);
updateRowData(0, insertList);
cellList.redraw();
}
}
private class GridDataProvider extends AsyncDataProvider<RecordDTO> {
private final List<RecordDTO> insertList = new ArrayList<RecordDTO>();
public GridDataProvider() {
}
/**
* {@link #onRangeChanged(HasData)} is called when the table requests a new
* range of data. You can push data back to the displays using
* {@link #updateRowData(int, List)}.
*/
@Override
protected void onRangeChanged(final HasData<RecordDTO> display) {
if (listMode.equals(ListMode.STANDARD)) {
// Get the new range.
final Range range = display.getVisibleRange();
final int start = range.getStart();
final int length = range.getLength();
if (recordCount == 0 || length == 0) {
display.setRowCount(0);
return;
}
if (initialized) {
RestClient.create(AplikatorService.class,
new RemoteCallback<RecordsPageDTO>() {
@Override
public void callback(RecordsPageDTO resp) {
updateRowData(start, resp.getRecords());
if ((gridSelectionModel.getSelectedObject() == null/* || gridSelectionModel.getSelectedList().size() == 0*/) && resp.getRecords().size() > 0) {
gridSelectionModel.setSelected(resp.getRecords().get(0), true);
if (ownerProperty == null) {
grid.setKeyboardSelectedRow(0, true);
focusGrid();
}
}
}
},
new AplikatorErrorCallback("aplikator.table.loaderror")
).getRecords(view.getId(), view.getActiveFilter(), view.getActiveSort(), view.getActiveQueryDescriptor(), view.getSearchString(), ownerProperty, (ownerPrimaryKey == null) ? null : ownerPrimaryKey.getSerializationString(), start, length);
}
} else if (listMode.equals(ListMode.INSERT)) {
updateRowCount(insertList.size(), true);
updateRowData(0, insertList);
if ((gridSelectionModel.getSelectedObject() == null /*|| gridSelectionModel.getSelectedList().size() == 0*/) && insertList.size() > 0) {
gridSelectionModel.setSelected(insertList.get(0), true);
}
}
}
public void resetCache() {
insertList.clear();
}
public void insertRecord(RecordDTO rec) {
insertList.add(0, rec);
updateRowCount(insertList.size(), true);
updateRowData(0, insertList);
grid.redraw();
}
public void removeFirstRecord() {
if (insertList.size() > 0) {
gridSelectionModel.setSelected(insertList.get(0), false);
insertList.remove(0);
}
updateRowCount(insertList.size(), true);
updateRowData(0, insertList);
grid.redraw();
}
}
}