/*
* DeferredCharacterComboBoxModel.java
* Missing License Header, Copyright 2016 (C) Andrew Maitland <amaitland@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package pcgen.gui2.tabs.models;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.ComboBoxModel;
import javax.swing.SwingUtilities;
import pcgen.facade.util.ReferenceFacade;
import pcgen.facade.util.event.ReferenceEvent;
import pcgen.facade.util.event.ReferenceListener;
import pcgen.facade.util.ListFacade;
import pcgen.gui2.util.FacadeListModel;
/**
* The Class {@code DeferredCharacterComboBoxModel} is a model for a combo
* box that holds off setting the value until focus is lost. This gets around a bug
* with the keyboard navigation of JComboBox where each key press selects the
* highlighted entry. This model should be used where costly or permanent actions
* are taken when an item is selected (e.h Race).
* <P>
* Note: This class needs to be added as a FocusListener of the target JComboBox
* for selection to work.
*
* <br>
*
* @param <E> The type of object being managed, generally a Facade
*
* @author James Dempsey <jdempsey@users.sourceforge.net>
*/
@SuppressWarnings("serial")
public abstract class DeferredCharacterComboBoxModel<E> extends
FacadeListModel<E> implements ComboBoxModel, ReferenceListener<E>,
FocusListener
{
private ReferenceFacade<E> reference = null;
protected Object selectedItem = null;
public DeferredCharacterComboBoxModel()
{
}
public DeferredCharacterComboBoxModel(ListFacade<E> list, ReferenceFacade<E> ref)
{
setListFacade(list);
setReference(ref);
}
/**
* Set the reference to the selected object that we should listen for external changes to.
* @param ref The reference.
*/
public void setReference(ReferenceFacade<E> ref)
{
if (reference != null)
{
reference.removeReferenceListener(this);
}
reference = ref;
if (reference != null)
{
reference.addReferenceListener(this);
setSelectedItem(reference.get());
}
}
@Override
public Object getSelectedItem()
{
return selectedItem;
}
@Override
public void setSelectedItem(Object item)
{
selectedItem = item;
fireContentsChanged(this, -1, -1);
}
@Override
public void referenceChanged(ReferenceEvent<E> e)
{
setSelectedItem(e.getNewReference());
}
/**
* Now that the user has finished updating the combo box, save the value
* they selected. This should be implemented as appropriate for each child
* of this class.
* @param item The item that the user selected.
*/
public abstract void commitSelectedItem(Object item);
@Override
public void focusGained(FocusEvent e)
{
// Ignored
}
@Override
public void focusLost(FocusEvent e)
{
// Temporary focus lost means something like the drop-down has
// got focus
if (e.isTemporary())
{
return;
}
// Focus was really lost; commit the update but do it after the focus is lost
final Runnable doUpdate = new Runnable()
{
@Override
public void run()
{
commitSelectedItem(selectedItem);
}
};
SwingUtilities.invokeLater(doUpdate);
}
}