/*
* Copyright (C) 2015 Jan Pokorsky
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cz.cas.lib.proarc.webapp.client.widget;
import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.types.ExpansionMode;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.types.TitleOrientation;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.events.SubmitValuesEvent;
import com.smartgwt.client.widgets.form.events.SubmitValuesHandler;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.DataArrivedEvent;
import com.smartgwt.client.widgets.grid.events.DataArrivedHandler;
import com.smartgwt.client.widgets.layout.VLayout;
import cz.cas.lib.proarc.webapp.client.ClientMessages;
import cz.cas.lib.proarc.webapp.client.ds.BibliographyDataSource;
import cz.cas.lib.proarc.webapp.client.ds.BibliographyQueryDataSource;
import cz.cas.lib.proarc.webapp.client.ds.DigitalObjectDataSource.DigitalObject;
import cz.cas.lib.proarc.webapp.shared.rest.BibliographicCatalogResourceApi;
import java.util.HashMap;
import java.util.LinkedHashMap;
/**
* The widget to query catalog metadata.
*
* @author Jan Pokorsky
*/
public class CatalogBrowser implements DatastreamEditor {
/**
* Titles of common field types. Used when the server config does not declare
* any field title. It ensures backward compatibility.
*/
private static final HashMap<String, String> FIELD_TYPE_TITLES = new HashMap<String, String>();
private final ClientMessages i18n;
private Canvas widget;
private Window window;
private DynamicForm formCatalog;
private ListGrid lgResult;
private boolean compactUi;
public CatalogBrowser(ClientMessages i18n) {
this.i18n = i18n;
initFields(i18n);
}
/**
* Gets the selected metadata or {@code null}.
*/
public String getMods() {
ListGridRecord r = lgResult.getSelectedRecord();
String mods = (r == null) ? null : r.getAttribute(BibliographyQueryDataSource.FIELD_MODS);
// ClientUtils.info(LOG, "getMods: %s", mods);
return mods;
}
public String getCatalogId() {
ListGridRecord r = lgResult.getSelectedRecord();
String val = (r == null) ? null : r.getAttribute(BibliographicCatalogResourceApi.CATALOG_ID);
return val;
}
public void bind() {
formCatalog.clearErrors(true);
fixExpandedListGrid();
lgResult.setData(new Record[0]);
}
public boolean isCompactUi() {
return compactUi;
}
public void setCompactUi(boolean compactUi) {
this.compactUi = compactUi;
}
// public void showWindow() {
// if (window == null) {
// window = new Window();
// window.setAutoSize(true);
//// window.setWidth(600);
//// window.setHeight(400);
// window.setAutoCenter(true);
// window.setIsModal(true);
// window.addItem(getUI());
// window.setTitle(i18n.ExportResultWidget_Window_Title());
// window.setShowMinimizeButton(false);
// window.setShowMaximizeButton(true);
// window.setKeepInParentRect(true);
// window.setShowModalMask(true);
// window.setCanDragResize(true);
// }
// window.show();
// }
@Override
public void edit(DigitalObject digitalObject) {
bind();
}
@Override
public void focus() {
if (formCatalog != null) {
formCatalog.focus();
}
}
@Override
public <T> T getCapability(Class<T> clazz) {
return null;
}
@Override
public Canvas[] getToolbarItems() {
return null;
}
@Override
public Canvas getUI() {
if (widget == null) {
widget = createAdvancedOptions();
}
return widget;
}
private Canvas createAdvancedOptions() {
formCatalog = createCatalogForm();
lgResult = new ListGrid();
lgResult.setDataSource(BibliographyQueryDataSource.getInstance());
// lgResult.setUseAllDataSourceFields(true);
ListGridField preview = new ListGridField(BibliographyQueryDataSource.FIELD_PREVIEW,
i18n.CatalogBrowser_HeaderPreview_Title());
ListGridField title = new ListGridField(BibliographyQueryDataSource.FIELD_TITLE,
i18n.CatalogBrowser_HeaderTitle_Title());
lgResult.setDetailField(BibliographyQueryDataSource.FIELD_PREVIEW);
lgResult.setFields(title, preview);
// lgResult.setAutoFetchData(true);
lgResult.setHeight100();
lgResult.setWidth100();
lgResult.setCanExpandRecords(true);
lgResult.setCanExpandMultipleRecords(false);
lgResult.setExpansionMode(ExpansionMode.DETAIL_FIELD);
lgResult.setSelectionType(SelectionStyle.SINGLE);
// lgResult.setSelectionAppearance(SelectionAppearance.CHECKBOX);
lgResult.setAlternateRecordStyles(true);
lgResult.addDataArrivedHandler(new DataArrivedHandler() {
@Override
public void onDataArrived(DataArrivedEvent event) {
if (event.getStartRow() == 0 && event.getEndRow() > 0) {
lgResult.focus();
lgResult.selectSingleRecord(0);
}
}
});
VLayout layout = new VLayout();
layout.setMembers(formCatalog, lgResult);
layout.setMargin(4);
layout.setMembersMargin(4);
layout.setOverflow(Overflow.AUTO);
return layout;
}
private void queryCatalog() {
if (formCatalog.validate()) {
Criteria plain = formCatalog.getValuesAsCriteria();
lgResult.invalidateCache();
lgResult.fetchData(plain);
}
}
private DynamicForm createCatalogForm() {
SelectItem selection = new SelectItem(BibliographicCatalogResourceApi.FIND_CATALOG_PARAM,
i18n.CatalogBrowser_CriteriaCatalog_Title());
selection.setRequired(true);
selection.setOptionDataSource(BibliographyDataSource.getInstance());
// selectModel.setShowOptionsFromDataSource(true);
selection.setValueField(BibliographicCatalogResourceApi.CATALOG_ID);
selection.setDisplayField(BibliographicCatalogResourceApi.CATALOG_NAME);
selection.setAutoFetchData(true);
selection.setDefaultToFirstOption(true);
selection.setWidth(250);
SelectItem selectField = new SelectItem(BibliographicCatalogResourceApi.FIND_FIELDNAME_PARAM,
i18n.CatalogBrowser_CriteriaField_Title());
selectField.setRequired(true);
selectField.setAllowEmptyValue(false);
selectField.setDefaultToFirstOption(true);
CatalogChangedHandler catalogHandler = new CatalogChangedHandler(selection, selectField);
selection.addDataArrivedHandler(catalogHandler);
selection.addChangedHandler(catalogHandler);
TextItem value = new TextItem(BibliographicCatalogResourceApi.FIND_VALUE_PARAM,
i18n.CatalogBrowser_CriteriaQuery_Title());
value.setWidth(300);
value.setRequired(true);
ButtonItem findBtn = new ButtonItem("findBtn", i18n.CatalogBrowser_CriteriaFindBtn_Title());
findBtn.setStartRow(false);
findBtn.setVAlign(VerticalAlignment.BOTTOM);
findBtn.addClickHandler(new com.smartgwt.client.widgets.form.fields.events.ClickHandler() {
@Override
public void onClick(com.smartgwt.client.widgets.form.fields.events.ClickEvent event) {
queryCatalog();
}
});
DynamicForm form = new DynamicForm();
form.setFields(selection, selectField, value, findBtn);
form.setBrowserSpellCheck(false);
form.setAutoWidth();
form.setWrapItemTitles(false);
if (isCompactUi()) {
form.setTitleOrientation(TitleOrientation.LEFT);
form.setNumCols(1);
} else {
form.setTitleOrientation(TitleOrientation.TOP);
form.setNumCols(4);
}
form.setSaveOnEnter(true);
form.addSubmitValuesHandler(new SubmitValuesHandler() {
@Override
public void onSubmitValues(SubmitValuesEvent event) {
queryCatalog();
}
});
return form;
}
/**
* Switching panels containing ListGrid with an expanded record results
* to NPE in GWT javascript code.
* Steps to reproduce:
* 1. New Object
* 2. find catalog records
* 3. expand some record
* 4. select whatever item in main menu
* 5. select New Object again
* 6. panel content not shown
* The workaround is to collapse the selected record before rendering.
*/
private void fixExpandedListGrid() {
ListGridRecord selectedResult = lgResult.getSelectedRecord();
if (selectedResult != null) {
lgResult.collapseRecord(selectedResult);
}
}
private static void initFields(ClientMessages i18n) {
if (FIELD_TYPE_TITLES.isEmpty()) {
FIELD_TYPE_TITLES.put("issn", i18n.CatalogBrowser_CriteriaFieldIssn_Title());
FIELD_TYPE_TITLES.put("isbn", i18n.CatalogBrowser_CriteriaFieldIsbn_Title());
FIELD_TYPE_TITLES.put("ccnb", i18n.CatalogBrowser_CriteriaFieldCcnb_Title());
FIELD_TYPE_TITLES.put("barcode", i18n.CatalogBrowser_CriteriaFieldBarcode_Title());
FIELD_TYPE_TITLES.put("signature", i18n.CatalogBrowser_CriteriaFieldSignature_Title());
FIELD_TYPE_TITLES.put("title", i18n.CatalogBrowser_HeaderTitle_Title());
}
}
private static class CatalogChangedHandler implements ChangedHandler,
com.smartgwt.client.widgets.form.fields.events.DataArrivedHandler {
private final SelectItem selectCatalog;
private final SelectItem selectField;
public CatalogChangedHandler(SelectItem selection, SelectItem selectField) {
this.selectCatalog = selection;
this.selectField = selectField;
}
@Override
public void onChanged(ChangedEvent event) {
ListGridRecord r = selectCatalog.getSelectedRecord();
String lastFieldSelection = selectField.getValueAsString();
Record[] fields = r.getAttributeAsRecordArray(BibliographicCatalogResourceApi.CATALOG_FIELDS);
LinkedHashMap<String, String> fieldMap = new LinkedHashMap<String, String>();
for (Record field : fields) {
String fId = field.getAttribute(BibliographicCatalogResourceApi.CATALOG_FIELD_ID);
String fTitle = field.getAttribute(BibliographicCatalogResourceApi.CATALOG_FIELD_TITLE);
fTitle = fTitle == null || fId.equals(fTitle) ? FIELD_TYPE_TITLES.get(fId) : fTitle;
fTitle = fTitle == null ? fId : fTitle;
fieldMap.put(fId, fTitle);
}
if (!fieldMap.containsKey(lastFieldSelection)) {
if (fieldMap.isEmpty()) {
lastFieldSelection = null;
} else {
lastFieldSelection = fieldMap.keySet().iterator().next();
}
}
selectField.setValueMap(fieldMap);
selectField.setValue(lastFieldSelection);
}
@Override
public void onDataArrived(com.smartgwt.client.widgets.form.fields.events.DataArrivedEvent event) {
onChanged(null);
}
}
}