/*
* Copyright (C) 2011 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.DSCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.ResultSet;
import com.smartgwt.client.types.DSOperationType;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.widgets.IconButton;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.CheckboxItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.form.fields.events.DataArrivedEvent;
import com.smartgwt.client.widgets.form.fields.events.DataArrivedHandler;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.toolbar.ToolStrip;
import com.smartgwt.client.widgets.tree.Tree;
import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeGridField;
import com.smartgwt.client.widgets.tree.TreeNode;
import com.smartgwt.client.widgets.tree.events.FolderClickEvent;
import com.smartgwt.client.widgets.tree.events.FolderClickHandler;
import cz.cas.lib.proarc.webapp.client.ClientMessages;
import cz.cas.lib.proarc.webapp.client.ClientUtils;
import cz.cas.lib.proarc.webapp.client.action.AbstractAction;
import cz.cas.lib.proarc.webapp.client.action.Action;
import cz.cas.lib.proarc.webapp.client.action.ActionEvent;
import cz.cas.lib.proarc.webapp.client.action.Actions;
import cz.cas.lib.proarc.webapp.client.action.RefreshAction;
import cz.cas.lib.proarc.webapp.client.action.RefreshAction.Refreshable;
import cz.cas.lib.proarc.webapp.client.ds.DeviceDataSource;
import cz.cas.lib.proarc.webapp.client.ds.ImportBatchDataSource;
import cz.cas.lib.proarc.webapp.client.ds.ImportBatchDataSource.BatchRecord;
import cz.cas.lib.proarc.webapp.client.ds.ImportTreeDataSource;
import cz.cas.lib.proarc.webapp.client.ds.ImportTreeDataSource.ImportRecord;
import cz.cas.lib.proarc.webapp.shared.rest.ConfigurationProfileResourceApi.ProfileGroup;
import java.util.logging.Logger;
/**
* UI allowing to select file system folder with digitalized content.
*
* @author Jan Pokorsky
*/
public final class ImportSourceChooser extends VLayout implements Refreshable {
private static final Logger LOG = Logger.getLogger(ImportSourceChooser.class.getName());
private final DataSource dataSource = ImportTreeDataSource.getInstance();
// private final DataSource metaModelSource = MetaModelDataSource.getInstance();
private final TreeGrid treeGrid;
private final DynamicForm optionsForm;
private final Label lblCurrSelection;
private ImportSourceChooserHandler viewHandler;
private final ClientMessages i18n;
private IconButton loadButton;
public ImportSourceChooser(ClientMessages i18n) {
this.i18n = i18n;
VLayout layout = this;
setWidth100();
setHeight100();
VLayout innerLayout = new VLayout();
innerLayout.setLayoutMargin(4);
lblCurrSelection = new Label(i18n.ImportSourceChooser_NothingSelected_Title());
lblCurrSelection.setWidth100();
lblCurrSelection.setAutoFit(true);
lblCurrSelection.setMargin(4);
lblCurrSelection.setCanSelectText(true);
treeGrid = new TreeGrid();
treeGrid.setHeight100();
treeGrid.setDataSource(dataSource);
TreeGridField stateField = new TreeGridField(
ImportTreeDataSource.FIELD_STATE,
i18n.ImportSourceChooser_TreeHeaderImportState_Title());
stateField.setWidth(100);
treeGrid.setFields(
new TreeGridField(ImportTreeDataSource.FIELD_NAME, i18n.ImportSourceChooser_TreeHeaderFolderName_Title()),
stateField);
treeGrid.setShowConnectors(true);
treeGrid.setEmptyMessage(i18n.ImportSourceChooser_NoDataOnServer_Title());
treeGrid.setAlternateRecordStyles(true);
treeGrid.setSelectionType(SelectionStyle.SINGLE);
treeGrid.addFolderClickHandler(new FolderClickHandler() {
@Override
public void onFolderClick(FolderClickEvent event) {
updateOnSelection();
// issue 41: open node on single click
TreeNode folder = event.getFolder();
event.getViewer().getTree().openFolder(folder);
}
});
ToolStrip toolbar = createToolbar();
optionsForm = createOptionsForm();
innerLayout.setMembers(optionsForm, lblCurrSelection, treeGrid);
layout.setMembers(toolbar, innerLayout);
}
public void setViewHandler(ImportSourceChooserHandler handler) {
this.viewHandler = handler;
}
public void edit() {
optionsForm.resetValues();
this.treeGrid.fetchData(null, new DSCallback() {
@Override
public void execute(DSResponse response, Object rawData, DSRequest request) {
treeGrid.selectRecord(0);
treeGrid.focus();
updateOnSelection();
}
});
}
public Record getImportSource() {
return treeGrid.getSelectedRecord();
}
public String getImportProfile() {
return optionsForm.getValueAsString(ImportBatchDataSource.FIELD_PROFILE_ID);
}
public Boolean getGenerateIndices() {
return (Boolean) optionsForm.getValue(ImportBatchDataSource.FIELD_INDICES);
}
public String getDevice() {
return optionsForm.getValueAsString(ImportBatchDataSource.FIELD_DEVICE);
}
public boolean validateOptions() {
return optionsForm.validate();
}
@Override
public void refresh() {
treeGrid.invalidateCache();
}
/**
* Refreshes selected node or the whole tree.
*/
public void refreshSelectedNode() {
Tree tree = treeGrid.getTree();
TreeNode node = treeGrid.getSelectedRecord();
if (node != null) {
TreeNode parent = tree.getParent(node);
if (parent != null) {
tree.reloadChildren(parent);
return ;
}
}
treeGrid.invalidateCache();
}
/**
* Updates folder status of the selected node in the data source cache.
*/
public void updateCache(String status) {
TreeNode node = treeGrid.getSelectedRecord();
// issue 205
node.setAttribute(ImportTreeDataSource.FIELD_STATE, status);
dataSource.updateCaches(new DSResponse(null, DSOperationType.UPDATE, node));
}
private void updateOnSelection() {
ListGridRecord selectedRecord = treeGrid.getSelectedRecord();
String label = (selectedRecord == null)
? i18n.ImportSourceChooser_NothingSelected_Title()
: selectedRecord.getAttribute(ImportTreeDataSource.FIELD_PATH);
lblCurrSelection.setContents(label);
ImportRecord importRecord = selectedRecord == null ? null : new ImportRecord(selectedRecord);
loadButton.setDisabled(importRecord == null || !importRecord.isNew());
}
private ToolStrip createToolbar() {
ToolStrip t = Actions.createToolStrip();
RefreshAction refreshAction = new RefreshAction(i18n);
t.addMember(Actions.asIconButton(refreshAction, this));
Action loadAction = new AbstractAction(i18n.ImportWizard_ButtonLoadFolder_Title(),
"[SKIN]/actions/add.png", null) {
@Override
public void performAction(ActionEvent event) {
viewHandler.sourceSelected();
}
};
loadButton = Actions.asIconButton(loadAction, this);
t.addMember(loadButton);
return t;
}
private DynamicForm createOptionsForm() {
DynamicForm form = new DynamicForm();
form.setNumCols(10);
form.setGroupTitle(i18n.ImportSourceChooser_Options_Title());
form.setIsGroup(true);
form.setWrapItemTitles(false);
final CheckboxItem cbiPageIndexes = new CheckboxItem(ImportBatchDataSource.FIELD_INDICES,
i18n.ImportSourceChooser_OptionPageIndices_Title());
cbiPageIndexes.setValue(true);
final SelectItem selectScanner = createScannerSelection();
final SelectItem selectProfile = ProfileChooser.createProfileSelection(ProfileGroup.IMPORTS, i18n);
selectProfile.setName(ImportBatchDataSource.FIELD_PROFILE_ID);
selectProfile.addChangedHandler(new ChangedHandler() {
@Override
public void onChanged(ChangedEvent event) {
String profile = getImportProfile();
Criteria criteria = new Criteria();
if (profile != null) {
criteria.addCriteria(ImportTreeDataSource.FIELD_PROFILE, profile);
}
treeGrid.setCriteria(criteria);
boolean notArchive = !BatchRecord.isArchive(profile);
selectScanner.setRequired(notArchive);
if (notArchive) {
selectScanner.show();
cbiPageIndexes.show();
} else {
selectScanner.hide();
cbiPageIndexes.hide();
}
}
});
form.setFields(selectProfile, selectScanner, cbiPageIndexes);
return form;
}
private SelectItem createScannerSelection() {
final SelectItem selectScanner = new SelectItem(ImportBatchDataSource.FIELD_DEVICE,
i18n.ImportSourceChooser_OptionScanner_Title());
DeviceDataSource.setOptionDataSource(selectScanner);
selectScanner.setAllowEmptyValue(true);
selectScanner.setEmptyDisplayValue(
ClientUtils.format("<i><%s></i>", i18n.NewDigObject_OptionModel_EmptyValue_Title()));
selectScanner.setRequired(true);
selectScanner.setWidth(300);
selectScanner.addDataArrivedHandler(new DataArrivedHandler() {
@Override
public void onDataArrived(DataArrivedEvent event) {
if (event.getStartRow() == 0) {
ResultSet data = event.getData();
int length = data.getLength();
if (length == 1) {
// issue 190: select in case of single device
Record device = data.get(0);
String deviceId = device.getAttribute(DeviceDataSource.FIELD_ID);
selectScanner.setValue(deviceId);
selectScanner.setDefaultValue(deviceId);
}
}
}
});
return selectScanner;
}
public interface ImportSourceChooserHandler {
void sourceSelected();
}
}