/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.jorphan.gui;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class JLabeledChoice extends JPanel implements JLabeledField {
private static final long serialVersionUID = 240L;
private final JLabel mLabel = new JLabel();
private final JComboBox<String> choiceList;
private final boolean withButtons;
private final ArrayList<ChangeListener> mChangeListeners = new ArrayList<>(3);
private JButton delete;
private JButton add;
/**
* Default constructor, The label and the Text field are left empty.
*/
public JLabeledChoice() {
super();
choiceList = new JComboBox<>();
withButtons = false;
init();
}
public JLabeledChoice(String pLabel, boolean editable) {
super();
choiceList = new JComboBox<>();
mLabel.setText(pLabel);
choiceList.setEditable(editable);
withButtons = false;
init();
}
/**
* Constructs a non-edittable combo-box with the label displaying the passed text.
*
* @param pLabel - the text to display in the label.
* @param items - the items to display in the Combo box
*/
public JLabeledChoice(String pLabel, String[] items) {
this(pLabel, items, false);
}
/**
* Constructs a combo-box with the label displaying the passed text.
*
* @param pLabel - the text to display in the label.
* @param items - the items to display in the Combo box
* @param editable - if true, then Add and Delete buttons are created.
*
*/
public JLabeledChoice(String pLabel, String[] items, boolean editable) {
this(pLabel, items, editable, editable);
}
/**
* Constructs a combo-box with the label displaying the passed text.
*
* @param pLabel - the text to display in the label.
* @param items - the items to display in the Combo box
* @param editable - the box is made editable
* @param withButtons - if true, then Add and Delete buttons are created.
*
*/
public JLabeledChoice(String pLabel, String[] items, boolean editable, boolean withButtons) {
super();
mLabel.setText(pLabel);
choiceList = new JComboBox<>(items);
choiceList.setEditable(editable);
this.withButtons = withButtons;
init();
}
/**
* Get the label {@link JLabel} followed by the combo-box @link {@link JComboBox}.
*/
@Override
public List<JComponent> getComponentList() {
List<JComponent> comps = new LinkedList<>();
comps.add(mLabel);
comps.add(choiceList);
return comps;
}
public void setEditable(boolean editable) {
choiceList.setEditable(editable);
}
public void addValue(String item) {
choiceList.addItem(item);
}
public void setValues(String[] items) {
choiceList.removeAllItems();
for (String item : items) {
choiceList.addItem(item);
}
}
/**
* Initialises all of the components on this panel.
*/
private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final)
// Register the handler for focus listening. This handler will
// only notify the registered when the text changes from when
// the focus is gained to when it is lost.
choiceList.addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
notifyChangeListeners();
}
});
// Add the sub components
this.add(mLabel);
this.add(choiceList);
if (withButtons) {
add = new JButton("Add");
add.setMargin(new Insets(1, 1, 1, 1));
add.addActionListener(new AddListener());
this.add(add);
delete = new JButton("Del");
delete.setMargin(new Insets(1, 1, 1, 1));
delete.addActionListener(new DeleteListener());
this.add(delete);
}
}
public void setChoiceListEnabled(boolean enabled) {
choiceList.setEnabled(enabled);
}
/**
* Set the text displayed in the label.
*
* @param pLabel
* The new label text.
*/
@Override
public void setLabel(String pLabel) {
mLabel.setText(pLabel);
}
/**
* Set the text displayed in the Text Field.
*
* @param pText
* The new text to display in the text field.
*/
@Override
public void setText(String pText) {
choiceList.setSelectedItem(pText);
}
public void setSelectedIndex(int index){
choiceList.setSelectedIndex(index);
}
/**
* Returns the text in the Text Field.
*
* @return The text in the Text Field. Never returns null.
*/
@Override
public String getText() {
Object item = choiceList.getSelectedItem();
if (item == null) {
return "";
} else {
return (String) item;
}
}
public int getSelectedIndex(){
return choiceList.getSelectedIndex();
}
public Object[] getSelectedItems() {
return choiceList.getSelectedObjects();
}
public String[] getItems() {
String[] items = new String[choiceList.getItemCount()];
for (int i = 0; i < items.length; i++) {
items[i] = choiceList.getItemAt(i);
}
return items;
}
/**
* Returns the text of the label.
*
* @return The text of the label.
*/
public String getLabel() {
return mLabel.getText();
}
/**
* Registers the text to display in a tool tip.
* The text displays when the cursor lingers over the component.
* @param text the string to display; if the text is null,
* the tool tip is turned off for this component
*/
@Override
public void setToolTipText(String text) {
choiceList.setToolTipText(text);
}
/**
* Returns the tooltip string that has been set with setToolTipText
* @return the text of the tool tip
*/
@Override
public String getToolTipText() {
if (choiceList == null){ // Necessary to avoid NPE when testing serialisation
return null;
}
return choiceList.getToolTipText();
}
/**
* Adds a change listener, that will be notified when the text in the text
* field is changed. The ChangeEvent that will be passed to registered
* listeners will contain this object as the source, allowing the new text
* to be extracted using the {@link #getText() getText} method.
*
* @param pChangeListener
* The listener to add
*/
@Override
public void addChangeListener(ChangeListener pChangeListener) {
mChangeListeners.add(pChangeListener);
}
/**
* Removes a change listener.
*
* @param pChangeListener
* The change listener to remove.
*/
public void removeChangeListener(ChangeListener pChangeListener) {
mChangeListeners.remove(pChangeListener);
}
/**
* Notify all registered change listeners that the text in the text field
* has changed.
*/
private void notifyChangeListeners() {
ChangeEvent ce = new ChangeEvent(this);
for (ChangeListener mChangeListener : mChangeListeners) {
mChangeListener.stateChanged(ce);
}
}
private class AddListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String item = (String) choiceList.getSelectedItem();
int index = choiceList.getSelectedIndex();
if (!item.equals(choiceList.getItemAt(index))) {
choiceList.addItem(item);
}
choiceList.setSelectedItem(item);
notifyChangeListeners();
}
}
private class DeleteListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (choiceList.getItemCount() > 1) {
choiceList.removeItemAt(choiceList.getSelectedIndex());
notifyChangeListeners();
}
}
}
}