/*
* Copyright 2017 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.renderer.client.selector;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import org.dashbuilder.dataset.DataColumn;
import org.dashbuilder.dataset.DataSetLookupConstraints;
import org.dashbuilder.dataset.group.ColumnGroup;
import org.dashbuilder.dataset.group.DataSetGroup;
import org.dashbuilder.dataset.group.Interval;
import org.dashbuilder.dataset.sort.DataSetSort;
import org.dashbuilder.dataset.sort.SortOrder;
import org.dashbuilder.displayer.ColumnSettings;
import org.dashbuilder.displayer.DisplayerAttributeDef;
import org.dashbuilder.displayer.DisplayerAttributeGroupDef;
import org.dashbuilder.displayer.DisplayerConstraints;
import org.dashbuilder.displayer.client.AbstractErraiDisplayer;
import org.jboss.errai.ioc.client.container.SyncBeanManager;
@Dependent
public class SelectorDropDownDisplayer extends AbstractErraiDisplayer<SelectorDropDownDisplayer.View> {
public interface View extends AbstractErraiDisplayer.View<SelectorDropDownDisplayer> {
void showTitle(String title);
void margins(int top, int bottom, int left, int right);
void setWidth(int width);
void showSelectHint(String column, boolean multiple);
void showResetHint(String column, boolean multiple);
void showCurrentSelection(String text, String hint);
void clearItems();
void addItem(SelectorDropDownItem item);
String getGroupsTitle();
String getColumnsTitle();
}
protected View view;
protected boolean filterOn = false;
protected boolean multipleSelections = false;
protected SyncBeanManager beanManager;
protected Set<SelectorDropDownItem> itemCollection = new HashSet<>();
@Inject
public SelectorDropDownDisplayer(View view, SyncBeanManager beanManager) {
this.beanManager = beanManager;
this.view = view;
this.view.init(this);
}
@Override
public View getView() {
return view;
}
@Override
public void close() {
super.close();
clearItems();
}
protected void clearItems() {
view.clearItems();
for (SelectorDropDownItem item : itemCollection) {
beanManager.destroyBean(item);
}
itemCollection.clear();
}
protected void resetItems() {
for (SelectorDropDownItem item : itemCollection) {
item.reset();
}
}
@Override
public DisplayerConstraints createDisplayerConstraints() {
DataSetLookupConstraints lookupConstraints = new DataSetLookupConstraints()
.setGroupRequired(true)
.setGroupColumn(true)
.setMaxColumns(-1)
.setMinColumns(1)
.setExtraColumnsAllowed(true)
.setGroupsTitle(view.getGroupsTitle())
.setColumnsTitle(view.getColumnsTitle());
return new DisplayerConstraints(lookupConstraints)
.supportsAttribute(DisplayerAttributeDef.TYPE)
.supportsAttribute(DisplayerAttributeDef.SUBTYPE)
.supportsAttribute(DisplayerAttributeDef.RENDERER)
.supportsAttribute(DisplayerAttributeDef.TITLE)
.supportsAttribute(DisplayerAttributeDef.TITLE_VISIBLE)
.supportsAttribute(DisplayerAttributeGroupDef.SELECTOR_GROUP)
.excludeAttribute(DisplayerAttributeGroupDef.SELECTOR_SHOW_INPUTS)
.supportsAttribute(DisplayerAttributeGroupDef.CHART_MARGIN_GROUP)
.supportsAttribute(DisplayerAttributeGroupDef.COLUMNS_GROUP)
.supportsAttribute(DisplayerAttributeGroupDef.FILTER_GROUP)
.supportsAttribute(DisplayerAttributeGroupDef.REFRESH_GROUP);
}
@Override
protected void beforeDataSetLookup() {
// Make sure the drop down entries are sorted
DataSetGroup group = dataSetHandler.getCurrentDataSetLookup().getLastGroupOp();
if (dataSetHandler.getCurrentDataSetLookup().getOperationList(DataSetSort.class).isEmpty() && group != null) {
ColumnGroup column = group.getColumnGroup();
dataSetHandler.sort(column.getSourceId(), SortOrder.ASCENDING);
}
}
@Override
protected void createVisualization() {
if (displayerSettings.isTitleVisible()) {
view.showTitle(displayerSettings.getTitle());
}
if (displayerSettings.getSelectorWidth() > 0) {
view.setWidth(displayerSettings.getSelectorWidth());
}
view.margins(displayerSettings.getChartMarginTop(),
displayerSettings.getChartMarginBottom(),
displayerSettings.getChartMarginLeft(),
displayerSettings.getChartMarginRight());
multipleSelections = displayerSettings.isSelectorMultiple();
updateVisualization();
}
@Override
protected void updateVisualization() {
DataColumn firstColumn = dataSet.getColumnByIndex(0);
ColumnSettings columnSettings = displayerSettings.getColumnSettings(firstColumn);
String firstColumnName = columnSettings.getColumnName();
List<Integer> currentFilter = super.filterIndexes(firstColumn.getId());
clearItems();
// Generate the list entries from the current data set
for (int i = 0; i < dataSet.getRowCount(); i++) {
Object obj = dataSet.getValueAt(i, 0);
if (obj == null) {
continue;
}
String value = super.formatValue(i, 0);
StringBuilder title = new StringBuilder();
int ncolumns = dataSet.getColumns().size();
if (ncolumns > 1) {
for (int j = 1; j < ncolumns; j++) {
DataColumn extraColumn = dataSet.getColumnByIndex(j);
columnSettings = displayerSettings.getColumnSettings(extraColumn);
String extraColumnName = columnSettings.getColumnName();
Object extraValue = dataSet.getValueAt(i, j);
if (extraValue != null) {
title.append(j > 1 ? " " : "");
String formattedValue = super.formatValue(i, j);
title.append(extraColumnName).append("=").append(formattedValue);
}
}
}
final SelectorDropDownItem item = beanManager.lookupBean(SelectorDropDownItem.class).newInstance();
item.init(i, value, title.toString());
item.setSelectionIconVisible(multipleSelections);
item.setOnSelectCommand(() -> onItemSelected(item));
item.setOnResetCommand(() -> onItemReset(item));
if (currentFilter.contains(i)) {
item.select();
} else {
item.reset();
}
view.addItem(item);
itemCollection.add(item);
}
// Add a selector hint according to the filter status
if (currentFilter.isEmpty()) {
view.showSelectHint(firstColumnName, multipleSelections);
} else {
view.showResetHint(firstColumnName, multipleSelections);
}
}
public String getFirstColumnId() {
DataColumn firstColumn = dataSet.getColumnByIndex(0);
return firstColumn.getId();
}
public String getFirstColumnName() {
DataColumn firstColumn = dataSet.getColumnByIndex(0);
ColumnSettings columnSettings = displayerSettings.getColumnSettings(firstColumn);
return columnSettings.getColumnName();
}
protected void onItemSelected(SelectorDropDownItem item) {
if (displayerSettings.isFilterEnabled()) {
String firstColumnId = getFirstColumnId();
String firstColumnName = getFirstColumnName();
// Reset current selection (if any) in single selection mode
if (!multipleSelections) {
List<Integer> currentFilter = filterIndexes(firstColumnId);
if (currentFilter != null && !currentFilter.isEmpty()) {
resetItems();
super.filterReset();
item.select();
}
}
// Filter by the selected entry
filterUpdate(firstColumnId, item.getId());
List<Integer> currentFilter = super.filterIndexes(firstColumnId);
showSelectedItems(currentFilter);
view.showResetHint(firstColumnName, multipleSelections);
}
}
protected void onItemReset(SelectorDropDownItem item) {
if (displayerSettings.isFilterEnabled()) {
String firstColumnId = getFirstColumnId();
String firstColumnName = getFirstColumnName();
filterUpdate(firstColumnId, item.getId());
List<Integer> currentFilter = super.filterIndexes(firstColumnId);
if (currentFilter.isEmpty()) {
view.showSelectHint(firstColumnName, multipleSelections);
} else {
showSelectedItems(currentFilter);
}
}
}
protected void showSelectedItems(List<Integer> currentFilter) {
List<String> itemList = new ArrayList<>();
for (Integer idx : currentFilter) {
String value = super.formatValue(idx, 0);
itemList.add(value);
}
int width = displayerSettings.getSelectorWidth();
String hint = formatItemList(itemList);
String text = width > 0 ? formatItemList(itemList, width) : hint;
view.showCurrentSelection(text, hint);
}
public String formatItemList(List<String> itemList) {
StringBuffer out = new StringBuffer();
for (String item : itemList) {
if (out.length() > 0) {
out.append(", ");
}
out.append(item);
}
return out.toString() + " ";
}
public String formatItemList(List<String> itemList, int maxWidth) {
StringBuffer out = new StringBuffer();
int charLength = 9;
int availableChars = maxWidth / charLength;
for (String item : itemList) {
if (availableChars < 0) {
out.append(" ...");
return out.toString();
}
if (out.length() > 0) {
availableChars -= 2;
if (availableChars <= 0) {
out.append(" ...");
return out.toString();
} else {
out.append(", ");
}
}
if (item.length() > availableChars) {
out.append(item.substring(0, availableChars)).append("...");
return out.toString();
}
else {
availableChars -= item.length();
out.append(item);
}
}
return out.toString() + " ";
}
void onResetSelections() {
filterReset();
updateVisualization();
}
}