package com.revolsys.swing.field;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import org.jdesktop.swingx.HorizontalLayout;
import org.jdesktop.swingx.JXList;
import org.jdesktop.swingx.VerticalLayout;
import org.jdesktop.swingx.decorator.HighlighterFactory;
import com.revolsys.datatype.DataType;
import com.revolsys.swing.EventQueue;
import com.revolsys.swing.component.ValueField;
import com.revolsys.swing.list.ArrayListModel;
import com.revolsys.swing.listener.EventQueueRunnableListener;
import com.revolsys.swing.toolbar.ToolBar;
import com.revolsys.util.Property;
import com.revolsys.util.Strings;
public class StringListField extends ValueField {
public static final String SELECTED = "selected";
private static final long serialVersionUID = 1L;
private final JButton addButton;
private final Comparator<String> comparator;
private final ToolBar toolBar = new ToolBar();
private final JTextField valueEntry = new JTextField();
private final ArrayListModel<String> values = new ArrayListModel<>();
private final JXList valuesField;
public StringListField(final Comparator<String> comparator, final String fieldName) {
super(new HorizontalLayout(2), fieldName, "");
setOpaque(false);
this.comparator = comparator;
final JPanel fieldPanel = new JPanel(new VerticalLayout(2));
fieldPanel.setOpaque(false);
add(fieldPanel);
this.toolBar.setOpaque(false);
this.toolBar.setOrientation(SwingConstants.VERTICAL);
add(this.toolBar);
this.valueEntry.setPreferredSize(new Dimension(600, 25));
fieldPanel.add(this.valueEntry);
this.addButton = this.toolBar.addButtonTitleIcon("add", "Add", "add", this::addValue);
this.valueEntry.addActionListener(this.addButton.getAction());
this.toolBar.addButtonTitleIcon(SELECTED, "Remove Selected", "delete",
this::removeSelectedValues);
this.valuesField = new JXList(this.values);
this.valuesField.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
this.valuesField.setHighlighters(HighlighterFactory.createSimpleStriping(Color.LIGHT_GRAY));
final JScrollPane namesPane = new JScrollPane(this.valuesField);
namesPane.setPreferredSize(new Dimension(100, 3 * 20));
fieldPanel.add(namesPane);
updateFields();
final EventQueueRunnableListener updateFieldListener = EventQueue.addDocument(this.valueEntry,
() -> updateFields());
this.valuesField.addListSelectionListener(updateFieldListener);
}
public StringListField(final String fieldName) {
this(null, fieldName);
}
public void addValue() {
final String value = this.valueEntry.getText();
if (addValue(value)) {
this.valueEntry.setText("");
}
}
public boolean addValue(final String value) {
if (Property.hasValue(value)) {
if (!this.values.contains(value)) {
if (this.comparator == null || this.values.isEmpty()) {
this.values.add(value);
this.valuesField.setSelectedIndex(this.values.size() - 1);
} else {
boolean inserted = false;
for (int i = 0; i < this.values.size() && !inserted; i++) {
final String listValue = this.values.get(i);
if (this.comparator.compare(value, listValue) < 0) {
this.values.add(i, value);
inserted = true;
this.valuesField.setSelectedIndex(i);
}
}
if (!inserted) {
this.values.add(value);
this.valuesField.setSelectedIndex(this.values.size() - 1);
}
}
updateFields();
setFieldValue(Strings.toString(this.values));
return true;
}
}
this.valueEntry.requestFocusInWindow();
return false;
}
public String getSelected() {
return (String)this.valuesField.getSelectedValue();
}
public ToolBar getToolBar() {
return this.toolBar;
}
public void removeSelectedValues() {
final int[] selectedRows = this.valuesField.getSelectedIndices();
if (selectedRows.length > 0) {
for (final int selectedRow : selectedRows) {
this.values.remove(selectedRow);
}
final int index = Math.min(selectedRows[0], this.values.size() - 1);
if (index >= -1) {
final ListSelectionModel selectionModel = this.valuesField.getSelectionModel();
selectionModel.setSelectionInterval(index, index);
}
}
setFieldValue(Strings.toString(this.values));
updateFields();
this.valueEntry.requestFocusInWindow();
}
@Override
public boolean setFieldValue(final Object value) {
if (!DataType.equal(value, getFieldValue())) {
if (this.values != null) {
if (value == null) {
this.values.clear();
} else {
final String string = value.toString();
if (Property.hasValue(string)) {
final List<String> newValues = new ArrayList<>();
for (final String item : string.replaceAll("\\s+", "").split(",+")) {
if (Property.hasValue(item)) {
newValues.add(item);
}
}
if (this.comparator != null) {
Collections.sort(newValues, this.comparator);
}
if (!DataType.equal(this.values, newValues)) {
this.values.clear();
this.values.addAll(newValues);
if (!newValues.isEmpty()) {
this.valuesField.setSelectedIndex(0);
}
}
}
}
return super.setFieldValue(Strings.toString(this.values));
}
}
return false;
}
private void setSelectedButtonsEnabled(final boolean editable) {
for (final Component component : this.toolBar.getGroup(SELECTED)) {
component.setEnabled(editable);
// this.valueEntry.setEditable(editable);
}
}
public void updateFields() {
this.valueEntry.setEnabled(true);
final String text = this.valueEntry.getText();
if (Property.hasValue(text) && !this.values.contains(text)) {
this.addButton.setEnabled(true);
} else {
this.addButton.setEnabled(false);
}
if (this.values.size() == 0) {
setSelectedButtonsEnabled(false);
} else {
setSelectedButtonsEnabled(true);
}
}
}