/*
Copyright (c) 2003-2009 ITerative Consulting Pty Ltd. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:
o Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
o Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
o This jcTOOL Helper Class software, whether in binary or source form may not be used within,
or to derive, any other product without the specific prior written permission of the copyright holder
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package DisplayProject.actions;
import java.awt.Component;
import java.util.Enumeration;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JRadioButtonMenuItem;
import DisplayProject.Constants;
import DisplayProject.DropListModel;
import DisplayProject.ListField;
import DisplayProject.RadioList;
import DisplayProject.RadioListModel;
import DisplayProject.ScrollListModel;
import DisplayProject.controls.AutoResizingComboBox;
import DisplayProject.controls.DropList;
import DisplayProject.controls.FillInField;
import DisplayProject.controls.MenuList;
import DisplayProject.controls.ScrollList;
import DisplayProject.factory.MenuFactory;
import Framework.Array_Of_ListElement;
import Framework.CloneHelper;
import Framework.ListElement;
import Framework.TextData;
import Framework.UsageException;
/**
* This action allows the get and set of the collection of ElementList on a FillInField (JComboBox), DropList (JComboBox), MenuList, ScrollList (JList) and RadioList
*
*/
public class ElementList extends ReversableAction {
private Array_Of_ListElement<ListElement> listElements;
private ButtonGroup group;
public ElementList(Component pComponent, Array_Of_ListElement<ListElement> pListElements) {
super(pComponent);
// Because we use a delayed write, we must clone the array to ensure no changes to
// the array are reflected back in the meantime
// TF:08/10/2008:Fixed this up to use a method to reproduce Forte functionality
this.listElements = cloneList(pListElements);
}
public ElementList(ListField pComponent, Array_Of_ListElement<ListElement> pListElements) {
super((Component)pComponent);
// Because we use a delayed write, we must clone the array to ensure no changes to
// the array are reflected back in the meantime
// TF:08/10/2008:Fixed this up to use a method to reproduce Forte functionality
this.listElements = cloneList(pListElements);
}
public ElementList(ButtonGroup pComponent, Array_Of_ListElement<ListElement> pListElements) {
super(null);
this.group = pComponent;
// Because we use a delayed write, we must clone the array to ensure no changes to
// the array are reflected back in the meantime
// TF:08/10/2008:Fixed this up to use a method to reproduce Forte functionality
this.listElements = cloneList(pListElements);
}
public Array_Of_ListElement<ListElement> getListElements() {
return this.listElements;
}
public void performAction() {
performAction(this.getComponent());
}
public void performAction(Component component) {
if (this.listElements == null)
return;
// AD:26/6/2008 Change JComboBox to AutoResizingComboBox to reduce casting later
if (component instanceof AutoResizingComboBox)
_setElementList((AutoResizingComboBox)component, this.listElements);
else if (component instanceof RadioList)
_setElementList((RadioList)component, this.listElements);
else if (component instanceof JList)
_setElementList((JList)component, this.listElements);
else if ((component == null)&&(this.group != null)){
Enumeration<AbstractButton> enum1 = group.getElements();
while (enum1.hasMoreElements()){
group.remove(enum1.nextElement());
}
for (ListElement le : this.listElements) {
MenuFactory.newRadioMenuItem(le.toString(), this.group, le.getIntegerValue());
}
}
}
private static void _setElementList(AutoResizingComboBox comp, Array_Of_ListElement<ListElement> les) {
if (comp.getModel() instanceof DropListModel) {
((DropListModel)comp.getModel()).setElementList(les);
// CraigM:08/07/2008 - Only select the first item if we are a drop list, don't do it for FillInFields
if (comp instanceof DropList) {
//PM:8/10/07 if nothing selected, select first
Object selectedItem = comp.getSelectedItem();
//PM:29/11/07 except if the selected item is null
if (selectedItem == null){
comp.setSelectedItem(null);
} else {
if (comp.getSelectedIndex() == -1 && comp.getItemCount() > 0) {
comp.setSelectedIndex(0);
}
}
}
}
else {
comp.setModel(new DropListModel(les, comp));
}
}
private static void _setElementList(JList comp, Array_Of_ListElement<ListElement> les){
((ScrollListModel)comp.getModel()).setElementList(les);
}
private static void _setElementList(RadioList comp, Array_Of_ListElement<ListElement> les){
((RadioListModel)comp.getModel()).setElementList(les);
}
public static void set(AutoResizingComboBox comp, Array_Of_ListElement<ListElement> les) {
ActionMgr.addAction(new ElementList((ListField)comp, les));
}
public static void setOnJList(JList comp, Array_Of_ListElement<ListElement> les) {
ActionMgr.addAction(new ElementList(comp, les));
}
public static void set(ScrollList comp, Array_Of_ListElement<ListElement> les) {
ActionMgr.addAction(new ElementList((ListField)comp, les));
}
public static void set(MenuList comp, Array_Of_ListElement<ListElement> les) {
// TF:6/11/07:MenuList can set the element list in a Thread safe manner
comp.setElementList(les);
}
public static void set(FillInField comp, Array_Of_ListElement<ListElement> les) {
ActionMgr.addAction(new ElementList((ListField)comp, les));
}
public static void set(ListField comp, Array_Of_ListElement<ListElement> les) {
ActionMgr.addAction(new ElementList(comp, les));
}
public static void set(DropList comp, Array_Of_ListElement<ListElement> les) {
ActionMgr.addAction(new ElementList((ListField)comp, les));
}
/**
* adds entries to the ButtonGroup (formally a MenuList)
* @param comp
* @param les
*/
public static void set(ButtonGroup comp, Array_Of_ListElement<ListElement> les) {
ActionMgr.addAction(new ElementList(comp, les));
}
/**
* Returns an Array_Of_ListElement<ListElement> containing the elements from a AutoResizingComboBox emulating a FOrte DropList or FillInField
* @param comp
* @return
*/
public static Array_Of_ListElement<ListElement> get(AutoResizingComboBox comp) {
// CraigM:01/09/2008 - If we have the incorrect model, it probably means we have been created by a grid that is nested in an ArrayField.
// This code is just temporary code to get around this problem. JIRA: JCT-586.
if (comp.getModel() instanceof DropListModel == false) {
Array_Of_ListElement<ListElement> elements = new Array_Of_ListElement<ListElement>();
for (int i=0; i<comp.getModel().getSize(); i++) {
if (comp.getModel().getElementAt(i) instanceof ListElement) {
elements.add((ListElement)comp.getModel().getElementAt(i));
}
}
comp.setModel(new DropListModel(elements, comp));
}
// TF:28/07/2009:Changed this to return the data from the underlying model. We cannot pass (ListField)comp as the
// second parameter for historical reasons -- this get method was invoked directly from the main thread due to a
// generator bug, and the solution admistered to the code was to have this method calling ElementList.get() indirectly.
// If we pass (ListField)comp here, it will call ElementList.get(comp) which is this method and hence enters
// infinite recursion.
return _getElementList(comp, (DropListModel)comp.getModel());
}
/**
* Returns an Array_Of_ListElement<ListElement> containing the elements from a JList emulating a Forte ScrollList
* @param comp
* @return
*/
public static Array_Of_ListElement<ListElement> get(JList comp){
if (comp instanceof ListField) {
return _getElementList(comp, (ListField)comp);
}
else if (comp.getModel() instanceof ListField) {
return _getElementList(comp, ((ListField)comp.getModel()));
}
// Should never happen
throw new UsageException("ElementList.get(JList) passed a list that did not implment ListField");
}
/**
* Returns an Array_Of_ListElement<ListElement> containing the elements from a JList emulating a Forte ScrollList
* @param comp
* @return
*/
@SuppressWarnings("unchecked")
public static Array_Of_ListElement<ListElement> get(MenuList comp){
Array_Of_ListElement<ListElement> result = comp.getElementList();
if (result != null) {
return (Array_Of_ListElement<ListElement>)result.clone();
}
else {
return null;
}
}
/**
* Returns an Array_Of_ListElement<ListElement> containing the elements from a DropList
* @param comp
* @return
*/
public static Array_Of_ListElement<ListElement> get(DropList comp){
return _getElementList(comp, (ListField)comp);
}
/**
* Returns an Array_Of_ListElement<ListElement> containing the elements from a ScrollList
* @param comp
* @return
*/
public static Array_Of_ListElement<ListElement> get(ScrollList comp){
return _getElementList(comp, (ListField)comp);
}
/**
* Return either the selected, not selected, or all items in the scroll list.
* CraigM:10/07/2008.
*
* @param comp
* @param selected valid values are {@link Constants.ET_SELECTED}, {@link Constants.ET_NOTSELECTED}, or {@link Constants.ET_ALL)
* @return
*/
public static Array_Of_ListElement<ListElement> get(ScrollList comp, int selected) {
Array_Of_ListElement<ListElement> result = new Array_Of_ListElement<ListElement>();
Array_Of_ListElement<ListElement> allItems = ElementList.get(comp);
for (int i=0; i<allItems.size(); i++) {
if (selected == Constants.ET_SELECTED) {
if (ElementSelected.get(comp, i)) {
result.add(allItems.get(i));
}
}
else if (selected == Constants.ET_NOTSELECTED) {
if (ElementSelected.get(comp, i) == false) {
result.add(allItems.get(i));
}
}
else {
result.add(allItems.get(i));
}
}
return result;
}
/**
* Returns an Array_Of_ListElement<ListElement> containing the elements from a JList emulating a Forte RadiolList
* @param comp
* @return
*/
public static Array_Of_ListElement<ListElement> get(RadioList comp){
return _getElementList(comp, (comp.getRadioListModel()));
}
public static Array_Of_ListElement<ListElement> get(ListField comp){
if (comp instanceof JComponent)
return _getElementList((JComponent)comp, null);
else
return null;
}
public static Array_Of_ListElement<ListElement> get(ButtonGroup comp){
Array_Of_ListElement<ListElement> les = new Array_Of_ListElement<ListElement>();
ElementList action = ActionMgr.getAction(comp, ElementList.class);
if (action != null) {
les = action.getListElements();
return les;
}
Enumeration<AbstractButton> enum1 = comp.getElements();
while (enum1.hasMoreElements()){
Object element = enum1.nextElement();
if (element instanceof JRadioButtonMenuItem)
les.add(new ListElement(((JRadioButtonMenuItem) element)
.getText(), ((Integer) ((JRadioButtonMenuItem) element)
.getClientProperty("qq_value")).intValue()));
if (element instanceof JCheckBoxMenuItem)
les.add(new ListElement(((JCheckBoxMenuItem) element)
.getText(), ((Integer) ((JCheckBoxMenuItem) element)
.getClientProperty("qq_value")).intValue()));
}
return les;
}
/**
* Return a copy of the elements in the list associated with the list field
*/
@SuppressWarnings("unchecked")
private static Array_Of_ListElement<ListElement> _getElementList(JComponent comp, ListField lm){
Array_Of_ListElement<ListElement> les;
ElementList action = ActionMgr.getAction(comp, ElementList.class);
if (action != null) {
les = action.getListElements();
return les;
}
// CraigM:08/07/2008 - Removed call to pending action as it causes an endless loop
les = lm.getElementList();
// TF:17/7/07:Return a clone of the array to prevent accident overwriting, for example when clearing
return (Array_Of_ListElement<ListElement>)les.clone();
}
public static ListElement extractByIndex(ListField comp, int index){
if (comp.getClass().isAssignableFrom(JComponent.class))
return extractByIndex((JComponent)comp, index);
else
return null;
}
public static ListElement extractByIndex(DropList comp, int index){
return extractByIndex((JComponent)comp, index);
}
// CraigM:17/11/2008
public static ListElement extractByIndex(ScrollList comp, int index){
return extractByIndex((JComponent)comp, index);
}
public static ListElement extractByIndex(FillInField comp, int index){
return extractByIndex((JComponent)comp, index);
}
/**
* CraigM:22/09/2008 - Added clones to calls. JIRA DET-45.
*
* @param comp
* @param index
* @return
*/
public static ListElement extractByIndex(JComponent comp, int index){
ElementList action = ActionMgr.getAction(comp, ElementList.class);
ListElement result = null;
if (action != null) {
result = (ListElement)action.getListElements().get(index - 1);
} else if (comp instanceof RadioList){
result = ((RadioList)comp).extractListElementByIndex(index);
} else if (comp instanceof DropList){
result = (ListElement)((DropList)comp).getItemAt(index - 1);
} else if (comp instanceof FillInField){
result = (ListElement)((FillInField)comp).getItemAt(index - 1);
} else if (comp instanceof ScrollList){
result = (ListElement)((ScrollList)comp).getModel().getElementAt(index - 1);
}
return CloneHelper.clone(result, true);
}
@Override
public boolean isSameAction(PendingAction a) {
return false;
}
@Override
public PendingAction applyActionTo(Component component) {
return null;
}
/**
* This method will clone an array of list elements in exactly the same way Forte did it: the array of
* list elements is cloned, each list element itself is cloned, the text value is cloned by the object
* value is referenced.
* @param pOrig
* @return
*/
public static Array_Of_ListElement<ListElement> cloneList(final Array_Of_ListElement<ListElement> pOrig) {
if (pOrig == null) {
return null;
}
else {
// We need to clone the array, and then each element of the array
Array_Of_ListElement<ListElement> result = new Array_Of_ListElement<ListElement>();
// Preallocate the space for efficiency
result.ensureCapacity(pOrig.size());
for (ListElement orig : pOrig) {
ListElement clone = new ListElement(
orig.getImageValue(),
orig.getIntegerValue(),
orig.getObjectValue(),
new TextData(orig.getTextValue()),
ListElement.qq_Resolver.cIMAGEVALUE_INTEGERVALUE_OBJECTVALUE_TEXTVALUE);
result.add(clone);
}
return result;
}
}
}