org.datacleaner.panels.fuse.StreamColumnListPanel Maven / Gradle / Ivy
/**
* DataCleaner (community edition)
* Copyright (C) 2014 Free Software Foundation, Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.datacleaner.panels.fuse;
import java.awt.Component;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import org.apache.metamodel.schema.Table;
import org.apache.metamodel.util.CollectionUtils;
import org.datacleaner.actions.ReorderColumnsActionListener;
import org.datacleaner.api.InputColumn;
import org.datacleaner.job.builder.AnalysisJobBuilder;
import org.datacleaner.panels.DCPanel;
import org.datacleaner.util.IconUtils;
import org.datacleaner.util.WidgetFactory;
import org.datacleaner.util.WidgetUtils;
import org.datacleaner.widgets.DCCheckBox;
import org.datacleaner.widgets.DCLabel;
import org.jdesktop.swingx.HorizontalLayout;
import org.jdesktop.swingx.VerticalLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class StreamColumnListPanel extends DCPanel implements ReorderColumnsActionListener.ReorderColumnsCallback {
public interface Listener {
void onValueChanged(StreamColumnListPanel panel);
}
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(StreamColumnListPanel.class);
private final Table _table;
private final List _listeners;
private final DCPanel _selectedCheckboxesPanel;
private final DCPanel _availableCheckboxesPanel;
private DCPanel _buttonPanelForSelected;
public StreamColumnListPanel(final AnalysisJobBuilder rootAnalysisJobBuilder, final Table table,
final Listener listener) {
super();
_table = table;
_listeners = new ArrayList<>();
_listeners.add(listener);
setLayout(new VerticalLayout(0));
_selectedCheckboxesPanel = new DCPanel();
_selectedCheckboxesPanel.setLayout(new VerticalLayout(0));
_selectedCheckboxesPanel.setBorder(WidgetUtils.BORDER_LIST_ITEM);
_selectedCheckboxesPanel.setVisible(false);
_availableCheckboxesPanel = new DCPanel();
_availableCheckboxesPanel.setLayout(new VerticalLayout(0));
final DCLabel streamHeader = DCLabel.dark(table.getName());
streamHeader.setFont(WidgetUtils.FONT_SMALL.deriveFont(Font.BOLD));
streamHeader.setBorder(WidgetUtils.BORDER_CHECKBOX_LIST_INDENTATION);
add(streamHeader);
final JButton reorderColumnsButton = WidgetFactory.createSmallButton(IconUtils.ACTION_REORDER_COLUMNS);
reorderColumnsButton.setToolTipText("Reorder columns");
reorderColumnsButton.addActionListener(new ReorderColumnsActionListener(this));
final JButton selectAllButton = WidgetFactory.createDefaultButton("Select all");
selectAllButton.setFont(WidgetUtils.FONT_SMALL);
selectAllButton.addActionListener(e -> {
for (final DCCheckBox> checkBox : getAvailableInputColumnCheckBoxes()) {
checkBox.setSelected(true);
}
fireValueChanged();
});
final JButton selectNoneButton = WidgetFactory.createDefaultButton("Select none");
selectNoneButton.setFont(WidgetUtils.FONT_SMALL);
selectNoneButton.addActionListener(e -> {
for (final DCCheckBox> checkBox : getSelectedInputColumnCheckBoxes()) {
checkBox.setSelected(false);
}
fireValueChanged();
});
_buttonPanelForSelected = createButtonPanel();
_buttonPanelForSelected.setVisible(false);
_buttonPanelForSelected.add(reorderColumnsButton);
_buttonPanelForSelected.add(selectNoneButton);
// only show the "selected" button panel when there are any selections
addListener(panel -> refresh());
final DCPanel buttonPanelForAvailable = createButtonPanel();
buttonPanelForAvailable.add(selectAllButton);
add(_buttonPanelForSelected);
add(_selectedCheckboxesPanel);
add(buttonPanelForAvailable);
add(_availableCheckboxesPanel);
}
public void addListener(final Listener listener) {
_listeners.add(listener);
}
private void fireValueChanged() {
for (final Listener listener : _listeners) {
listener.onValueChanged(this);
}
}
private DCPanel createButtonPanel() {
final DCPanel buttonPanel = new DCPanel();
buttonPanel.setLayout(new HorizontalLayout(2));
buttonPanel.setBorder(
new CompoundBorder(new EmptyBorder(4, 0, 0, 0), WidgetUtils.BORDER_CHECKBOX_LIST_INDENTATION));
return buttonPanel;
}
protected List>> getSelectedInputColumnCheckBoxes() {
return getInputColumnCheckBoxes(_selectedCheckboxesPanel);
}
protected List>> getAvailableInputColumnCheckBoxes() {
return getInputColumnCheckBoxes(_availableCheckboxesPanel);
}
@SuppressWarnings("unchecked")
private List>> getInputColumnCheckBoxes(final DCPanel panel) {
final Component[] components = panel.getComponents();
return CollectionUtils.map(components, component -> (DCCheckBox>) component);
}
public void addInputColumn(final InputColumn> inputColumn, final boolean coalesced) {
final DCCheckBox> checkBox = new DCCheckBox<>(inputColumn.getName(), coalesced);
checkBox.addListener((item, selected) -> {
if (selected) {
_availableCheckboxesPanel.remove(checkBox);
_selectedCheckboxesPanel.add(checkBox);
} else {
_selectedCheckboxesPanel.remove(checkBox);
_availableCheckboxesPanel.add(checkBox);
}
fireValueChanged();
});
checkBox.setValue(inputColumn);
if (coalesced) {
_selectedCheckboxesPanel.add(checkBox);
} else {
_availableCheckboxesPanel.add(checkBox);
}
}
public List> getAllInputColumns() {
final List> result = new ArrayList<>();
for (final DCCheckBox> checkBox : getSelectedInputColumnCheckBoxes()) {
result.add(checkBox.getValue());
}
for (final DCCheckBox> checkBox : getAvailableInputColumnCheckBoxes()) {
result.add(checkBox.getValue());
}
return result;
}
public List> getCoalescedInputColumns() {
final List> result = new ArrayList<>();
for (final DCCheckBox> checkBox : getSelectedInputColumnCheckBoxes()) {
result.add(checkBox.getValue());
}
return result;
}
public Table getTable() {
return _table;
}
@Override
public InputColumn>[] getColumns() {
return getCoalescedInputColumns().toArray(new InputColumn[0]);
}
@Override
public void reorderColumns(final InputColumn>[] newValue) {
final List>> selectedInputColumnCheckBoxes = getSelectedInputColumnCheckBoxes();
_selectedCheckboxesPanel.removeAll();
for (final InputColumn> inputColumn : newValue) {
// find the corresponding checkbox and add it
boolean found = false;
for (int i = 0; i < selectedInputColumnCheckBoxes.size(); i++) {
final DCCheckBox> checkBox = selectedInputColumnCheckBoxes.get(i);
if (checkBox.getValue().equals(inputColumn)) {
found = true;
_selectedCheckboxesPanel.add(checkBox);
break;
}
}
if (!found) {
logger.warn("Failed to find reordered column: {}", inputColumn);
}
}
fireValueChanged();
}
public boolean hasSelectedInputColumns() {
return _selectedCheckboxesPanel.getComponentCount() > 0;
}
public void refresh() {
final boolean hasSelectedInputColumns = hasSelectedInputColumns();
_buttonPanelForSelected.setVisible(hasSelectedInputColumns);
_selectedCheckboxesPanel.setVisible(hasSelectedInputColumns);
}
}