package com.opendoorlogistics.core.scripts.parameters.controls;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ComboBoxEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import com.opendoorlogistics.api.tables.ODLColumnType;
import com.opendoorlogistics.core.utils.ui.FileBrowserPanel;
import javax.swing.UnsupportedLookAndFeelException;
public class SmartComboBox extends JPanel {
private final JComboBox<String> box;
private final JTextField textField;
private final JLabel labelCtrl;
private boolean editable = true;
private final HashSet<SmartComboValueChangedListener> listeners = new HashSet<>();
public SmartComboBox(String label, Collection<String> values, Integer comboWidth,ODLColumnType valueType, boolean useChangeValuePrompt) {
setBorder(BorderFactory.createEmptyBorder());
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
labelCtrl = new JLabel(label);
add(labelCtrl);
add(Box.createRigidArea(new Dimension(6, 1)));
// Use a text field as the editor for a combo box so we can reliably get
// mouse clicked events; with the default editor it is not clear when
// this would happen
textField = new JTextField();
// Set the text field not to be editable - as we only only OK / Cancel
// editing with the modal
// dialog, however we create a border which gives the same look-and-feel
// as an editable text field
textField.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1), BorderFactory.createLineBorder(Color.DARK_GRAY, 1)));
textField.setEditable(!useChangeValuePrompt);
if (useChangeValuePrompt) {
textField.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
doModalDataEdit();
}
public void mousePressed(MouseEvent e) {
doModalDataEdit();
}
private void doModalDataEdit() {
if (editable) {
// String newValue =
// JOptionPane.showInputDialog(SmartComboBox.this,
// "Enter new value", getValue());
Object newValue = JOptionPane.showInputDialog(SmartComboBox.this, "Enter new value for " + labelCtrl.getText(), labelCtrl.getText(), JOptionPane.PLAIN_MESSAGE, null, null,
getValue());
if (newValue != null) {
setValue(newValue.toString());
}
}
}
});
}else{
textField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
fireValueChangedListeners();
}
@Override
public void insertUpdate(DocumentEvent e) {
fireValueChangedListeners();
}
@Override
public void changedUpdate(DocumentEvent e) {
fireValueChangedListeners();
}
});
}
if(valueType == ODLColumnType.FILE_DIRECTORY){
box = null;
setSizes(textField, comboWidth);
add(textField);
add(FileBrowserPanel.createBrowseButton(true, "OK", textField));
}
// wrap in a combobox if we have selectable values
else if (values != null && values.size() > 0) {
box = new JComboBox<String>(values.toArray(new String[values.size()]));
box.setEditable(true);
ComboBoxEditor cbe = new ComboBoxEditor() {
@Override
public void setItem(Object anObject) {
// setValue(value);
// textField.setText(anObject!=null ?
// anObject.toString():"");
SmartComboBox.this.setValue(anObject != null ? anObject.toString() : "");
}
@Override
public void selectAll() {
}
@Override
public void removeActionListener(ActionListener l) {
textField.removeActionListener(l);
}
@Override
public Object getItem() {
return textField.getText();
}
@Override
public Component getEditorComponent() {
return textField;
}
@Override
public void addActionListener(ActionListener l) {
textField.addActionListener(l);
}
};
box.setEditor(cbe);
setSizes(box, comboWidth);
add(box);
} else {
box = null;
setSizes(textField, comboWidth);
add(textField);
}
}
private static void setSizes(JComponent component, Integer comboWidth) {
if(comboWidth!=null){
Dimension size = new Dimension(comboWidth, 24);
component.setMaximumSize(size);
component.setMinimumSize(size);
component.setPreferredSize(size);
}
}
public void setToolTipText(String text) {
super.setToolTipText(text);
labelCtrl.setToolTipText(text);
if (box != null) {
box.setToolTipText(text);
}
textField.setToolTipText(text);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
try {
UIManager.setLookAndFeel(info.getClassName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ArrayList<String> values = new ArrayList<>();
values.add("1");
SmartComboBox box = new SmartComboBox("Number", values, 100,ODLColumnType.STRING, false);
box.setEditable(true);
box.setToolTipText("blah");
// give focus to the panel so the textfield doesn't have it
// panel.requestFocus();
JFrame frame = new JFrame();
frame.add(box);
frame.setVisible(true);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
public boolean isEditable() {
return editable;
}
public void setEditable(boolean editable) {
this.editable = editable;
}
// public void setItems(String [] items){
// if(box!=null){
// box.setModel(new DefaultComboBoxModel<String>(items));
// }
// }
//
public void setValue(String value) {
// if(box!=null){
// box.setSelectedItem(value);
// }else{
textField.setText(value);
// }
fireValueChangedListeners();
}
private void fireValueChangedListeners() {
for (SmartComboValueChangedListener listener : listeners) {
listener.onValueChanged(this, getValue());
}
}
public String getValue() {
return textField.getText();
}
public void addValueChangedListener(SmartComboValueChangedListener listener) {
listeners.add(listener);
}
}