com.dmurph.mvc.gui.combo.MVCJComboBox Maven / Gradle / Ivy
/**
* Copyright (c) 2010 Daniel Murphy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Created at Aug 20, 2010, 2:58:08 AM
*/
package com.dmurph.mvc.gui.combo;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import javax.swing.JComboBox;
import com.dmurph.mvc.model.MVCArrayList;
/**
* This class is for having a combo box that will always reflect the data of
* an MVCArrayList. There is a lot of flexibility provided with filtering
* and sorting the elements.
*
* @author Daniel Murphy
*/
public class MVCJComboBox extends JComboBox {
private static final long serialVersionUID = 1L;
private MVCJComboBoxModel model;
private MVCArrayList data;
private IMVCJComboBoxFilter filter;
private final Object lock = new Object();
private MVCJComboBoxStyle style;
private Comparator comparator = null;
private final PropertyChangeListener plistener = new PropertyChangeListener() {
@SuppressWarnings("unchecked")
public void propertyChange(PropertyChangeEvent argEvt) {
String prop = argEvt.getPropertyName();
if (prop.equals(MVCArrayList.ADDED)) {
add((E)argEvt.getNewValue());
}
else if(prop.equals(MVCArrayList.ADDED_ALL)){
addAll((Collection) argEvt.getNewValue());
}
else if (prop.equals(MVCArrayList.CHANGED)) {
change((E)argEvt.getOldValue(),(E) argEvt.getNewValue());
}
else if (prop.equals(MVCArrayList.REMOVED)) {
remove((E)argEvt.getOldValue());
}
else if(prop.equals(MVCArrayList.REMOVED_ALL)){
synchronized(lock){
model.removeAllElements();
}
}
}
};
/**
* Constructs with no data, no filter, no
* {@link Comparator}, and style set to
* {@link MVCJComboBoxStyle#ADD_NEW_TO_BEGINNING}.
*/
public MVCJComboBox() {
this(null, new IMVCJComboBoxFilter() {
public boolean showItem(E argComponent) {
return true;
};
}, MVCJComboBoxStyle.SORT, null);
}
/**
* Constructs a combo box with the given style. If you want
* the {@link MVCJComboBoxStyle#SORT} style, then you'll want to specify
* a comparator as well.
* @param argData
* @param argStyle
*/
public MVCJComboBox(MVCJComboBoxStyle argStyle) {
this(null, new IMVCJComboBoxFilter() {
public boolean showItem(E argComponent) {
return true;
};
}, argStyle, null);
}
/**
* Constracts a dynamic combo box with the given data and
* default style of {@link MVCJComboBoxStyle#SORT}.
* @param argData
*/
public MVCJComboBox(MVCArrayList argData, Comparator argComparator) {
this(argData, new IMVCJComboBoxFilter() {
public boolean showItem(E argComponent) {
return true;
};
}, MVCJComboBoxStyle.SORT, argComparator);
}
/**
* Constructs a combo box with the given data and style. If you want
* the {@link MVCJComboBoxStyle#SORT} style, then you'll want to specify
* a comparator as well.
* @param argData
* @param argStyle
*/
public MVCJComboBox(MVCArrayList argData, MVCJComboBoxStyle argStyle) {
this(argData, new IMVCJComboBoxFilter() {
public boolean showItem(E argComponent) {
return true;
};
}, argStyle, null);
}
/**
* Constructs a dynamic combo box with the given data, filter, and comparator.
* The style will be {@link MVCJComboBoxStyle#SORT} by default.
* @param argData
* @param argFilter
* @param argComparator
*/
public MVCJComboBox(MVCArrayList argData, IMVCJComboBoxFilter argFilter, Comparator argComparator) {
this(argData, argFilter, MVCJComboBoxStyle.SORT, null);
}
/**
*
* @param argData
* @param argFilter
* @param argStyle
* @param argComparator
*/
public MVCJComboBox(MVCArrayList argData, IMVCJComboBoxFilter argFilter, MVCJComboBoxStyle argStyle, Comparator argComparator) {
data = argData;
style = argStyle;
filter = argFilter;
comparator = argComparator;
model = new MVCJComboBoxModel();
super.setModel(model);
if(data != null){
argData.addPropertyChangeListener(plistener);
// add the data
for (E o : data) {
if(filter.showItem(o)){
model.addElement(o);
}
}
// start with allowing the comparator to be null, in case they intend to set it later. and call refreshData()
if(style == MVCJComboBoxStyle.SORT && comparator != null){
model.sort(comparator);
}
}
}
/**
* Gets the rendering style of this combo box. Default style is
* {@link MVCJComboBoxStyle#SORT}.
* @return
*/
public MVCJComboBoxStyle getStyle(){
return style;
}
/**
* Gets the data list. This is used to access
* data with {@link #refreshData()}, so override
* if you want to customize what the data is (sending
* null to the contructor for the data
* is a good idea in that case)
* @return
*/
public ArrayList getData(){
return data;
}
/**
* Sets the data of this combo box. This causes the box
* to refresh it's model
* @param argData can be null
*/
public void setData(MVCArrayList argData){
synchronized (lock) {
if(data != null){
data.removePropertyChangeListener(plistener);
}
data = argData;
if(data != null){
data.addPropertyChangeListener(plistener);
}
}
refreshData();
}
/**
* Sets the comparator used for the {@link MVCJComboBoxStyle#SORT} style.
* @param argComparator
*/
public void setComparator(Comparator argComparator) {
this.comparator = argComparator;
}
/**
* Gets the comparator that's used for sorting.
* @return
*/
public Comparator getComparator() {
return comparator;
}
/**
* @return the filter
*/
public IMVCJComboBoxFilter getFilter() {
return filter;
}
/**
* @param argFilter the filter to set
*/
public void setFilter(IMVCJComboBoxFilter argFilter) {
filter = argFilter;
}
/**
* @see javax.swing.JComboBox#processKeyEvent(java.awt.event.KeyEvent)
*/
@Override
public void processKeyEvent(KeyEvent argE) {
if(argE.getKeyChar() == KeyEvent.VK_BACK_SPACE || argE.getKeyChar() == KeyEvent.VK_DELETE){
setSelectedItem(null);
super.hidePopup();
}else{
super.processKeyEvent(argE);
}
}
/**
* Sets the style of this combo box
* @param argStyle
*/
public void setStyle(MVCJComboBoxStyle argStyle){
style = argStyle;
if(style == MVCJComboBoxStyle.SORT){
if(comparator == null){
throw new NullPointerException("DynamicJComboBox style is set to Alpha Sort, but the comparator is null.");
}
model.sort(comparator);
}
}
public void refreshData(){
synchronized (lock) {
// remove all elements
model.removeAllElements();
if(getData() == null){
return;
}
for(E e: getData()){
if(filter.showItem(e)){
model.addElement(e);
}
}
if(style == MVCJComboBoxStyle.SORT){
if(comparator == null){
throw new NullPointerException("DynamicJComboBox style is set to Alpha Sort, but the comparator is null.");
}
model.sort(comparator);
}
}
}
private void add(E argNewObj) {
boolean b = filter.showItem(argNewObj);
if (b == false) {
return;
}
synchronized (lock) {
switch(style){
case SORT:{
if(comparator == null){
throw new NullPointerException("DynamicJComboBox style is set to Alpha Sort, but the comparator is null.");
}
boolean inserted = false;
for(int i=0; i 0){
model.insertElementAt(argNewObj, i);
inserted = true;
break;
}
}
if(!inserted){
model.addElement(argNewObj);
}
break;
}
case ADD_NEW_TO_BEGINNING:{
model.insertElementAt(argNewObj, 0);
break;
}
case ADD_NEW_TO_END:{
model.addElement(argNewObj);
}
}
}
}
private void addAll(Collection argNewObjects) {
LinkedList filtered = new LinkedList();
Iterator it = argNewObjects.iterator();
while(it.hasNext()){
E e = it.next();
if(filter.showItem(e)){
filtered.add(e);
}
}
if(filtered.size() == 0){
return;
}
synchronized (lock) {
switch(style){
case SORT:{
if(comparator == null){
throw new NullPointerException("DynamicJComboBox style is set to Alpha Sort, but the comparator is null.");
}
model.addElements(filtered);
model.sort(comparator);
break;
}
case ADD_NEW_TO_BEGINNING:{
model.addElements(0, filtered);
break;
}
case ADD_NEW_TO_END:{
model.addElements(filtered);
}
}
}
}
private void change(E argOld, E argNew) {
boolean so = filter.showItem(argOld);
boolean sn = filter.showItem(argNew);
if(!sn){
remove(argOld);
return;
}
if(!so){
if(sn){
add(argNew);
return;
}else{
return;
}
}
synchronized (lock) {
int size = model.getSize();
for (int i = 0; i < size; i++) {
E e = model.getElementAt(i);
if (e == argOld) {
model.setElementAt(argNew, i);
return;
}
}
if(style == MVCJComboBoxStyle.SORT){
if(comparator == null){
throw new NullPointerException("DynamicJComboBox style is set to Alpha Sort, but the comparator is null.");
}
model.sort(comparator);
}
}
}
private void remove(E argVal) {
boolean is = filter.showItem(argVal);
if (!is) {
return;
}
synchronized (lock) {
for(int i=0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy