package org.aplikator.client.local.widgets;
import org.aplikator.client.local.Aplikator;
import org.aplikator.client.shared.data.ItemSuggestion;
import org.aplikator.client.shared.data.RecordDTO;
import org.aplikator.client.shared.descriptor.PropertyDTO;
import org.aplikator.client.shared.descriptor.SuggestionsDTO;
import org.aplikator.client.shared.descriptor.ViewDTO;
import org.aplikator.client.shared.rpc.AplikatorErrorCallback;
import org.aplikator.client.shared.rpc.AplikatorService;
import org.gwtbootstrap3.client.ui.Button;
import org.gwtbootstrap3.client.ui.Column;
import org.gwtbootstrap3.client.ui.FormLabel;
import org.gwtbootstrap3.client.ui.Modal;
import org.gwtbootstrap3.client.ui.ModalBody;
import org.gwtbootstrap3.client.ui.Row;
import org.gwtbootstrap3.client.ui.SuggestBox;
import org.gwtbootstrap3.client.ui.TextBox;
import org.gwtbootstrap3.client.ui.Well;
import org.gwtbootstrap3.client.ui.constants.ColumnSize;
import org.gwtbootstrap3.client.ui.constants.IconType;
import org.gwtbootstrap3.client.ui.constants.ModalBackdrop;
import org.gwtbootstrap3.client.ui.constants.Pull;
import org.gwtbootstrap3.client.ui.html.Div;
import org.gwtbootstrap3.client.ui.html.Span;
import org.jboss.errai.common.client.api.ErrorCallback;
import org.jboss.errai.common.client.api.RemoteCallback;
import org.jboss.errai.enterprise.client.jaxrs.api.RestClient;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
public class ReferenceFieldWidget extends ContainerFieldBase implements DataField<Integer> {
Row searchPanel;
Row formPanel;
private Button buttonSearch;
private Button buttonDelete;
private final Button buttonSwitch;
private SuggestBox typeahead;
private TextBox searchBox;
private boolean searchBoxActive = false;
private Integer value;// TODO change to pk
private PropertyDTO property;
private ViewDTO view;
private TableListerWidget table;
private Modal dialogBox;
private ModalBody dialogContents;
private RecordDTO selectedRecordDTO = null;
private boolean dirty;
public ReferenceFieldWidget(String caption, ViewDTO view, Widget child, int size) {
super();
this.view = view;
wrapper = new Column(ColumnSize.XS_1);
initWidget(wrapper);
this.label = new FormLabel();
this.label.addStyleName("fieldLabel");
this.label.setText(caption);
if (caption != null && !"".equals(caption) && !"null".equals(caption)) {
wrapper.add(this.label);
}
setGridSize(size);
// forms container
dataPanel = new Row();
dataPanel.add(child);
buttonSearch = new Button("", IconType.SEARCH, new ClickHandler() {
public void onClick(ClickEvent event) {
if (dialogBox == null) {
dialogBox = createDialogBox();
}
dialogBox.setPixelSize(Window.getClientWidth() - 40, Window.getClientHeight());
dialogBox.show();
if (ReferenceFieldWidget.this.view.getActivePrimarySortProperty() != null && searchBoxActive) {
ReferenceFieldWidget.this.view.setSearchString(searchBox.getText());
}
table.refresh();
}
});
Widget buttonSearchWrapper = LayoutUtils.addTooltip(buttonSearch, Aplikator.application.getConfigString("aplikator.reference.search"));
//buttonSearchWrapper.getElement().getStyle().setDisplay(Style.Display.INLINE_BLOCK);
buttonSearch.getElement().getStyle().setDisplay(Style.Display.TABLE_CELL);
buttonSearch.getElement().getStyle().setProperty("width", "auto");
buttonSearch.getElement().getStyle().setVerticalAlign(Style.VerticalAlign.BASELINE);
buttonDelete = new Button("", IconType.TRASH_O, new ClickHandler() {
public void onClick(ClickEvent event) {
selectedRecordDTO = null;
resetSearchBox();
setValue(-1, true);
buttonDelete.setVisible(false);
}
});
buttonDelete.getElement().getStyle().setMarginLeft(0, Style.Unit.PX);
buttonDelete.getElement().getStyle().setMarginBottom(10, Style.Unit.PX);
buttonDelete.getElement().getStyle().setMarginRight(0, Style.Unit.PX);
Widget buttonDeleteWrapper = LayoutUtils.addTooltip(buttonDelete, Aplikator.application.getConfigString("aplikator.reference.delete"));
buttonDelete.setVisible(false);
searchPanel = new Row();
//searchPanel.addStyleName("refHeader");
searchPanel.getElement().getStyle().setMarginLeft(0, Style.Unit.PX);
searchPanel.getElement().getStyle().setMarginRight(0, Style.Unit.PX);
Div searchBlock = new Div();
searchBlock.getElement().getStyle().setMarginTop(0, Style.Unit.PX);
searchBlock.getElement().getStyle().setMarginBottom(0, Style.Unit.PX);
searchBlock.getElement().getStyle().setPaddingLeft(15, Style.Unit.PX);
searchBlock.setPull(Pull.LEFT);
searchBlock.getElement().getStyle().setProperty("width", "calc( 100% - 40px )");
searchBlock.getElement().getStyle().setDisplay(Style.Display.TABLE);
Div deleteBlock = new Div();
deleteBlock.getElement().getStyle().setMarginTop(0, Style.Unit.PX);
deleteBlock.getElement().getStyle().setMarginBottom(0, Style.Unit.PX);
deleteBlock.setPull(Pull.RIGHT);
deleteBlock.add(buttonDeleteWrapper);
if (view.getActivePrimarySortProperty() != null) {
ItemSuggestOracle oracle = new ItemSuggestOracle();
searchBox = new TextBox();
//searchBox.getElement().getStyle().setProperty("maxWidth", "100px");
//searchBox.getElement().getStyle().setDisplay(Style.Display.INLINE_BLOCK);
searchBox.getElement().getStyle().setDisplay(Style.Display.TABLE_CELL);
searchBox.getElement().getStyle().setProperty("width", "auto");
typeahead = new SuggestBox(oracle, searchBox);
resetSearchBox();
//searchBox.setStyleName(RefFormWidgetResources.INSTANCE.css().refSearchLeft());
searchBox.addFocusHandler(new FocusHandler() {
public void onFocus(FocusEvent event) {
searchBox.setText("");
searchBoxActive = true;
}
});
typeahead.addSelectionHandler(new SelectionHandler<Suggestion>() {
@Override
public void onSelection(SelectionEvent<Suggestion> se) {
ItemSuggestion selectedSuggestion = (ItemSuggestion) se.getSelectedItem();
int id = selectedSuggestion.getId();
selectedRecordDTO = ((ItemSuggestion) selectedSuggestion).getRecord();
setValue(id, true);
}
});
typeahead.getElement().getStyle().setDisplay(Style.Display.TABLE_CELL);
Span prepend = new Span();
prepend.setText(Aplikator.application.getConfigString("aplikator.reference.searchby"));
prepend.getElement().getStyle().setMarginRight(5, Style.Unit.PX);
//prepend.getElement().getStyle().setDisplay(Style.Display.TABLE_CELL);
//prepend.getElement().getStyle().setProperty("width","auto");
searchBlock.add(prepend);
searchBlock.add(typeahead);
searchBlock.add(buttonSearch);
} else {
searchBlock.add(buttonSearch);
}
searchPanel.add(searchBlock);
searchPanel.add(deleteBlock);
buttonSwitch = new Button("");
buttonSwitch.setIcon(IconType.EDIT);
buttonSwitch.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
searchPanel.setVisible(true);
searchPanel.addStyleName("refHeader");
buttonSwitch.setVisible(false);
buttonDelete.setVisible(true);
}
});
buttonSwitch.getElement().getStyle().setMarginLeft(0, Style.Unit.PX);
buttonSwitch.getElement().getStyle().setMarginBottom(10, Style.Unit.PX);
buttonSwitch.getElement().getStyle().setMarginRight(0, Style.Unit.PX);
formPanel = new Row();
formPanel.getElement().getStyle().setMarginLeft(0, Style.Unit.PX);
formPanel.getElement().getStyle().setMarginRight(0, Style.Unit.PX);
Column formHolder = new Column(LayoutUtils.size(11), dataPanel);
formHolder.getElement().getStyle().setProperty("width", "calc( 100% - 45px )");
Column buttonHolder = new Column(LayoutUtils.size(1), LayoutUtils.addTooltip(buttonSwitch, Aplikator.application.getConfigString("aplikator.reference.switch")));
buttonHolder.getElement().getStyle().setWidth(40, Style.Unit.PX);
buttonHolder.getElement().getStyle().setFloat(Style.Float.RIGHT);
//formHolder.getElement().getStyle().setPaddingRight(0, Style.Unit.PX);
//formHolder.getElement().getStyle().setPaddingLeft(0, Style.Unit.PX);
buttonHolder.getElement().getStyle().setPaddingLeft(0, Style.Unit.PX);
buttonHolder.getElement().getStyle().setPaddingRight(0, Style.Unit.PX);
formPanel.add(formHolder);
formPanel.add(buttonHolder);
searchPanel.setVisible(true);
formPanel.setVisible(false);
Well well = new Well();
wrapper.add(well);
well.add(searchPanel);
well.add(formPanel);
}
private void resetSearchBox() {
if (view.getActivePrimarySortProperty() != null) {
searchBox.setText(view.getActivePrimarySortProperty().getLocalizedName() + ":");
searchBoxActive = false;
}
}
public PropertyDTO getProperty() {
return property;
}
public void setProperty(PropertyDTO property) {
this.property = property;
}
public void setValue(Integer value) {
setValue(value, false);
selectedRecordDTO = null;
resetSearchBox();
}
public void setValue(Integer value, boolean fireEvents) {
Integer oldValue = this.value;
this.value = value;
if (fireEvents) {
//if (value != null && !value.equals(oldValue)) {
setDirty(true);
//}
ValueChangeEvent.fire(this, value);
}
if (value != null && value.intValue() > 0) {
searchPanel.setVisible(false);
formPanel.setVisible(true);
buttonSwitch.setVisible(true);
} else {
searchPanel.setVisible(true);
searchPanel.removeStyleName("refHeader");
formPanel.setVisible(false);
}
}
public Integer getValue() {
return value;
}
public void setEnabled(boolean enabled) {
buttonSearch.setEnabled(enabled);
buttonSwitch.setEnabled(enabled);
if (searchBox != null) {
searchBox.setEnabled(enabled);
}
}
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Integer> handler) {
return this.addHandler(handler, ValueChangeEvent.getType());
}
private Modal createDialogBox() {
dialogContents = new ModalBody();
final Modal dialogBox = new Modal();
dialogBox.getElement().getStyle().setOverflowY(Style.Overflow.AUTO);//fix against hiding scrollbar in modal stack
dialogBox.setDataBackdrop(ModalBackdrop.STATIC);
dialogBox.setTitle(Aplikator.application.getConfigString("aplikator.reference.dialogtitle") + " - " + view.getLocalizedName());
dialogBox.add(dialogContents);
Row buttonPanel = new Row();
buttonPanel.addStyleName("refButtonPanel");
Button closeButton = new Button(Aplikator.application.getConfigString("aplikator.reference.cancel"), IconType.BAN, new ClickHandler() {
public void onClick(ClickEvent event) {
dialogBox.hide();
}
});
closeButton.addStyleName("refSelectButton");
buttonPanel.add(closeButton);
final Button OKButton = new Button(Aplikator.application.getConfigString("aplikator.reference.select"), IconType.CHECK, new ClickHandler() {
public void onClick(ClickEvent event) {
dialogBox.hide();
selectedRecordDTO = table.getSelectedRecord();
setValue(table.getSelectedPrimaryKey().getId(), true);
}
});
OKButton.setEnabled(false);
OKButton.addStyleName("refSelectButton");
buttonPanel.add(OKButton);
dialogContents.add(buttonPanel);
table = (TableListerWidget) TableFactory.create(view, null, null, 450);
table.addStyleName("refTablePanel");
dialogContents.add(table);
table.addNestedEditorNotification(new NestedEditorNotification() {
@Override
public void nestedEditorStarted() {
OKButton.setEnabled(false);
}
@Override
public void nestedEditorFinished() {
OKButton.setEnabled(true);
}
});
final SingleSelectionModel<RecordDTO> selectionModel = table.getListSelectionModel();
selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
if (selectionModel.getSelectedObject() != null) {
OKButton.setEnabled(true);
} else {
OKButton.setEnabled(false);
}
}
});
return dialogBox;
}
public RecordDTO getSelectedRecord() {
return selectedRecordDTO;
}
@Override
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
@Override
public boolean isDirty() {
return dirty;
}
@Override
public void grabFocus() {
}
@Override
public void addEnterHandler(Command command) {
}
public class ItemSuggestOracle extends SuggestOracle {
public boolean isDisplayStringHTML() {
return true;
}
public void requestSuggestions(SuggestOracle.Request req, SuggestOracle.Callback callback) {
RestClient.create(AplikatorService.class,
new ItemSuggestCallback(req, callback),
new AplikatorErrorCallback()
).getSuggestions(view.getId(), view.getActiveSort(), req.getQuery());
}
class ItemSuggestCallback implements RemoteCallback<SuggestionsDTO>, ErrorCallback {
private SuggestOracle.Request req;
private SuggestOracle.Callback callback;
public ItemSuggestCallback(SuggestOracle.Request r, SuggestOracle.Callback c) {
req = r;
callback = c;
}
@Override
public boolean error(Object message, java.lang.Throwable throwable) {
callback.onSuggestionsReady(req, new SuggestOracle.Response());
return false;
}
@Override
public void callback(SuggestionsDTO dto) {
callback.onSuggestionsReady(req, new SuggestOracle.Response(dto.getSuggestions()));
}
}
}
}