/* * Copyright 2014 Red Hat, Inc. and/or its affiliates. * * 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 org.dashbuilder.client.widgets.dataset.editor.column; import com.google.gwt.editor.client.EditorDelegate; import com.google.gwt.editor.client.EditorError; import com.google.gwt.editor.client.adapters.EditorSource; import com.google.gwt.editor.client.adapters.ListEditor; import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.Widget; import org.dashbuilder.client.widgets.dataset.editor.driver.DataColumnDefDriver; import org.dashbuilder.client.widgets.dataset.event.ColumnsChangedEvent; import org.dashbuilder.client.widgets.resources.i18n.DataSetEditorConstants; import org.dashbuilder.dataprovider.DataSetProviderType; import org.dashbuilder.dataset.client.editor.DataColumnDefEditor; import org.dashbuilder.dataset.def.DataColumnDef; import org.jboss.errai.ioc.client.container.SyncBeanManager; import org.uberfire.client.mvp.UberView; import javax.annotation.PostConstruct; import javax.enterprise.context.Dependent; import javax.enterprise.event.Event; import javax.inject.Inject; import java.util.LinkedList; import java.util.List; /** * <p>Data Set column list editor presenter.</p> * * @since 0.4.0 */ @Dependent public class ColumnListEditor implements IsWidget, org.dashbuilder.dataset.client.editor.ColumnListEditor { public interface View extends UberView<ColumnListEditor> { View insert(int index, org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor.View columnEditorView, boolean selected, boolean enabled, String altText); View remove(int index); View clear(); } SyncBeanManager beanManager; DataColumnDefDriver dataColumnDefDriver; Event<ColumnsChangedEvent> columnsChangedEvent; public View view; ListEditor<DataColumnDef, DataColumnDefEditor> listEditor; List<DataColumnDef> acceptableColumns; final List<String> restrictedColumns = new LinkedList<String>(); DataSetProviderType providerType; @Inject public ColumnListEditor(final SyncBeanManager beanManager, final DataColumnDefDriver dataColumnDefDriver, final Event<ColumnsChangedEvent> columnsChangedEvent, final View view) { this.beanManager = beanManager; this.dataColumnDefDriver = dataColumnDefDriver; this.columnsChangedEvent = columnsChangedEvent; this.view = view; } @PostConstruct public void init() { listEditor = ListEditor.of(createDataColumnDefEditorSource()); view.init(this); } @Override public Widget asWidget() { return view.asWidget(); } /** * Set all data set available columns (not only the current used ones) * * @param acceptableValues Acceptable values for the editor. */ @Override public void setAcceptableValues(final List<DataColumnDef> acceptableValues) { clear(); // Register column editor for each available column of the data set. this.acceptableColumns = new LinkedList<DataColumnDef>(acceptableValues); int index = 0; for (final DataColumnDef columnDef : this.acceptableColumns ) { org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor editor = createDummyColumnEditor(columnDef); view.insert(index, editor.view, false, true, null); index++; } } /** * Set the column that cannot be removed from the list, as it's used by the filter. * @param value The column id. */ @Override public void onValueRestricted(final String value) { this.restrictedColumns.add(value); setEditorEnabled(value, false, DataSetEditorConstants.INSTANCE.columnIsUsedInFilter()); } /** * Set the column that can be removed again from the list, as it's no longer used by the filter. * @param value The column id. */ @Override public void onValueUnRestricted(final String value) { this.restrictedColumns.remove(value); // Check single column used in data set -> it cannot be unselected. if (listEditor.getList().size() == 1) { setEditorEnabled(0 ,false, DataSetEditorConstants.INSTANCE.dataSetMustHaveAtLeastOneColumn()); } else { setEditorEnabled(value, true, null); } } @Override public void setProviderType(final DataSetProviderType type) { this.providerType = type; } public void clear() { acceptableColumns = null; providerType = null; view.clear(); } /************************************************************* ** GWT EDITOR CONTRACT METHODS ** *************************************************************/ @Override public DataColumnDefEditor createEditorForTraversal() { return listEditor.createEditorForTraversal(); } @Override public String getPathElement(final DataColumnDefEditor subEditor) { return listEditor.getPathElement(subEditor); } @Override public void setEditorChain(final EditorChain<DataColumnDef, DataColumnDefEditor> chain) { listEditor.setEditorChain(chain); } @Override public void setDelegate(final EditorDelegate<List<DataColumnDef>> delegate) { listEditor.setDelegate(delegate); } @Override public void showErrors(final List<EditorError> errors) { } @Override public void flush() { listEditor.flush(); } @Override public void onPropertyChange(final String... paths) { listEditor.onPropertyChange(paths); } @Override public void setValue(final List<DataColumnDef> value) { listEditor.setValue(value); } /************************************************************* ** VIEW CALLBACK METHODS ** *************************************************************/ void onColumnSelect(final int index, final boolean selected) { final DataColumnDef columnDef = acceptableColumns.get(index); if (selected) { listEditor.getList().add(columnDef.clone()); } else { listEditor.getList().remove(columnDef); } columnsChangedEvent.fire(new ColumnsChangedEvent(this, listEditor.getList())); } /************************************************************* ** PRIVATE EDITOR METHODS ** *************************************************************/ private void replace(final int index, final org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor columnEditor, final boolean selected, final boolean enabled, final String altText) { view.remove(index); columnEditor.isEditMode(selected && enabled); view.insert(index, columnEditor.view, selected, enabled, altText); } private int getAvailableColumnIndex(final String id) { int x = 0; for (final DataColumnDef column : acceptableColumns) { if (column.getId().equals(id)) return x; x++; } return -1; } DataColumnDefEditorSource createDataColumnDefEditorSource() { return new DataColumnDefEditorSource(); } class DataColumnDefEditorSource extends EditorSource<DataColumnDefEditor> { @Override public DataColumnDefEditor create(final int index) { final DataColumnDef column = listEditor.getList().get(index); final int localIndex = acceptableColumns.indexOf(column); // Check single column used in data set -> it cannot be unselected. if (!checkSingleColumnEditorDisabled()) { // Enable column selection if more than one column remains on the data set. checkMultipleColumnsEditorEnabled(); } // Create the new editor. final org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor editor = createColumnEditor(); final boolean hasSingleColumn = listEditor.getList().size() == 1; final boolean isRestricted = restrictedColumns.contains(column.getId()); final String tooltipText = hasSingleColumn ? DataSetEditorConstants.INSTANCE.dataSetMustHaveAtLeastOneColumn() : ( isRestricted ? DataSetEditorConstants.INSTANCE.columnIsUsedInFilter() : null ); doSetOriginalColumnType(column.getId(), editor); replace(localIndex, editor, true, !isRestricted && !hasSingleColumn, tooltipText); return editor; } @Override public void dispose(DataColumnDefEditor subEditor) { // Column to be removed. final String columnId = subEditor.id().getValue(); final int localIndex = getAvailableColumnIndex(columnId); if (localIndex > -1) { final DataColumnDef column = acceptableColumns.get(localIndex); // Dispose and remove sub-editor. super.dispose(subEditor); subEditor.removeFromParent(); // Create a new dummy editor for the available column. final org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor editor = createDummyColumnEditor(column); replace(localIndex, editor, false, true, null); // Disable column selection if only one column remains on the data set. checkSingleColumnEditorDisabled(); } } }; /** * Checks that if only single column used in data set -> it cannot be unselected. */ private boolean checkSingleColumnEditorDisabled() { final int size = listEditor.getList().size(); final boolean hasEditors = !listEditor.getEditors().isEmpty(); if (size == 1 && hasEditors) { setEditorEnabled(0 ,false, DataSetEditorConstants.INSTANCE.dataSetMustHaveAtLeastOneColumn()); return true; } return false; } /** * Checks that if multiple columns are used in data set -> the column editors must be enabed, if the columns are not are restricted. */ private boolean checkMultipleColumnsEditorEnabled() { final int size = listEditor.getList().size(); if (size == 2 && !listEditor.getEditors().isEmpty()) { final String cId = listEditor.getEditors().get(0).id().getValue(); if (!restrictedColumns.contains(cId)) { setEditorEnabled(0, true, null); } return true; } return false; } private void setEditorEnabled(final String columnId, final boolean enabled, final String altText) { final org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor e = getEditor(columnId); if (e != null) { setEditorEnabled(e, enabled, altText); } } private void setEditorEnabled(final int index, final boolean enabled, final String altText) { final org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor _e = (org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor) listEditor.getEditors().get(index); if (_e != null) { setEditorEnabled(_e, enabled, altText); } } private void setEditorEnabled(org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor _e, final boolean enabled, final String altText) { final String cId = _e.id().getValue(); final int _index = getAvailableColumnIndex(cId); if (_index > -1) { replace(_index, _e, true, enabled, altText); } } private void doSetOriginalColumnType(final String cId, final DataColumnDefEditor editor) { final int _index = getAvailableColumnIndex(cId); final DataColumnDef originalCol = acceptableColumns.get(_index); if (originalCol != null) { editor.setOriginalColumnType(originalCol.getColumnType()); } } private org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor getEditor(final String columnId) { List<DataColumnDefEditor> editors = listEditor.getEditors(); if (editors != null && !editors.isEmpty()) { for (final DataColumnDefEditor editor : editors) { final String cId = editor.id().getValue(); if (columnId.equals(cId)) return (org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor) editor; } } return null; } private org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor createColumnEditor() { org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor e = beanManager.lookupBean(org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor.class).newInstance(); e.setProviderType(providerType); return e; } private org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor createDummyColumnEditor(final DataColumnDef def) { final org.dashbuilder.client.widgets.dataset.editor.column.DataColumnDefEditor editor = createColumnEditor(); // Column is available but not selected, do not allow edition. editor.isEditMode(false); // Initialze edtiro with the column attributes. dataColumnDefDriver.initialize(editor); dataColumnDefDriver.edit(def); doSetOriginalColumnType(def.getId(), editor); return editor; } }