/*
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.table;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import DisplayProject.ArrayColumnModel;
import DisplayProject.ArrayFieldModel;
import DisplayProject.DropListModel;
import DisplayProject.controls.ArrayField;
import DisplayProject.controls.FillInField;
import Framework.Array_Of_ListElement;
import Framework.DataValue;
import Framework.EventManager;
import Framework.IntegerData;
import Framework.ListElement;
import Framework.TextData;
/**
* We use a direct reference to the FillInField that was created, however, we try to select the correct
* item in the list for the particular cell being edited.
*
* @author Craig Mitchell
* @since 31/08/2007
*/
@SuppressWarnings("serial")
public class FillInFieldCellEditor extends AbstractCellEditor implements ArrayFieldTableCellEditor, StateColourForRowDisplayer {
private FillInField fif;
private transient List<Array_Of_ListElement<ListElement>> rowElements;
private Object rowElementsLock = new Object();
private transient ArrayField table;
private Class<?> editorColumnClass;
private StateColourForRow stateColour;
public FillInFieldCellEditor(FillInField pFIF) {
this.fif = pFIF;
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if (this.table == null || this.table != table) {
if (table instanceof ArrayField) {
this.table = (ArrayField)table;
}
}
if (table.getColumnModel() instanceof ArrayColumnModel){ //this ensures that we get the real column, not the displayed column index
int col = ((ArrayColumnModel)table.getColumnModel()).getColumn(column).getModelIndex();
editorColumnClass = ((ArrayFieldModel)table.getModel()).getColumnClass(col);
} else {
editorColumnClass = table.getModel().getColumnClass(column);
}
Array_Of_ListElement<ListElement> elements = null;
synchronized (rowElementsLock) {
if (rowElements != null){
// TF:02/11/2009:DET-124:Fixed this to allow for appending a row onto the array
if (row < rowElements.size()) {
//PM:10/8/07
/*
* customize the element list per row, if there is
* no customisation for the row
* use the default
*/
elements = rowElements.get(row);
}
else {
// New row doesn't exist yet, create an empty array
elements = new Array_Of_ListElement<ListElement>();
}
}
}
if (elements == null){
//PM:17/7/07 add a DropListModel with the correct data
elements =((DropListModel)this.fif.getModel()).getElementList();
}
this.fif.setModel(new DropListModel(elements, this.fif));
// TF:22/12/2009:DET-137: Added this to set the popup menu
this.fif.setComponentPopupMenu(table.getComponentPopupMenu());
// TF:11/11/2009:DET-126:Stop spurious AfterValueChangeEvents from occurring
if (value == null) {
this.fif.initialise("");
}
else {
this.fif.initialise(value.toString());
}
// TF:10/2/09:set the state being aware of a StateColourForRow plugin
if (this.stateColour != null){
this.fif.setEditable(!this.stateColour.isReadOnly(row));
this.fif.setEnabled(this.stateColour.isEnabled(row));
}
if (value instanceof DataValue && ((DataValue)value).isNull()) {
// TF:02/11/2009:If the passed value is null, ensure we edit it as N/A
this.fif.getEditor().setItem(value.toString());
return this.fif;
}
for (int i = 0; i < this.fif.getModel().getSize(); i++)
{
ListElement element = (ListElement) this.fif.getModel().getElementAt(i);
if (value instanceof Number || value instanceof IntegerData) {
int num;
if (value instanceof Number) {
num = ((Number)value).intValue();
}
else {
num = ((IntegerData)value).intValue();
}
if (num == element.getIntegerValue()) {
this.fif.getModel().setSelectedItem(element);
return this.fif;
}
}
else {
if (value != null) {
String aString = value.toString();
if (aString.equals(element.getTextValue().toString())) {
this.fif.getModel().setSelectedItem(element);
return this.fif;
}
}
}
}
// TF:3/11/07: During the creation of the table editor we should not fire after value change
// events, yet setting the text value or the selected item will have this side effect. We
// must disable this first.
try {
EventManager.disableEventPosting();
if (this.fif.getModel().getSize() > 0 && !this.fif.isEditable()) {
ListElement element = (ListElement)this.fif.getModel().getElementAt(0);
table.getModel().setValueAt(this.getListElementValue(element),row, column);
this.fif.setSelectedIndex(0);
} else if (value != null){
String aString = value.toString();
this.fif.getModel().setSelectedItem(aString);
}
if (value != null) {
this.fif.setTextValue(new TextData(value.toString()));
}
}
finally {
EventManager.enableEventPosting();
}
return this.fif;
}
public Object getCellEditorValue() {
// CraigM:27/06/2008 - We just want the value they have entered / selected
return this.fif.getEditedValue();
// Object o = this.fif.getSelectedItem();
// if (o != null && o instanceof ListElement) {
// return this.getListElementValue((ListElement)o);
// }
//
// // CraigM:27/06/2008 - If there is no object selected, just return the text they have typed
// else if (o == null) {
// o = this.fif.getEditedValue();
// }
// return o;
}
public Object getListElementValue(ListElement element) {
if (element == null || editorColumnClass == null) {
return null;
}
if (Integer.class.equals(editorColumnClass)) {
return new Integer(element.getIntegerValue());
}
else if (IntegerData.class.isAssignableFrom(editorColumnClass)) {
try {
IntegerData newValue = (IntegerData)editorColumnClass.newInstance();
newValue.setValue(element.getIntegerValue());
return newValue;
}
catch (Exception e) {
// Shouldn't get here, let's keep the compiler happy
return new IntegerData(element.getIntegerValue());
}
}
else if (TextData.class.isAssignableFrom(editorColumnClass)) {
// CraigM:25/05/2008 - Not sure what all this is, but it stops users from entering text that is not in the list
// try {
// TextData newValue = (TextData)editorColumnClass.newInstance();
// newValue.setValue(element.getTextValue());
// return newValue;
// }
// catch (Exception e) {
// // Shouldn't get here, let's keep the compiler happy
// return element == null ? null : element.getTextValue();
// }
// CraigM:25/05/2008 - Just return the text value
return this.fif.getTextValue();
}
else if (editorColumnClass.equals(String.class)) {
return element.getTextValue().toString();
}
return null;
}
//PM:10/8/07
/**
* adds an array of ListElements to a specific row
* @param row
* @param elements
*/
public void addRowElements(int row, Array_Of_ListElement<ListElement> elements){
synchronized (this.rowElementsLock) {
if (rowElements == null){
rowElements = new ArrayList<Array_Of_ListElement<ListElement>>();
}
rowElements.add(row, elements);
}
}
public void removeRowElements(int row){
// TF:02/11/2009:DET-124:Added check for out of bounds row (especially for arrays with AllowAppend on)
synchronized (this.rowElementsLock) {
if (rowElements == null || row >= rowElements.size()){
return;
}
rowElements.remove(row);
}
}
public void setRowElements(int row, Array_Of_ListElement<ListElement> elements) {
synchronized (this.rowElementsLock) {
if (rowElements == null) {
rowElements = new ArrayList<Array_Of_ListElement<ListElement>>();
}
// Add new rows as required
while (row >= rowElements.size()) {
rowElements.add(new Array_Of_ListElement<ListElement>());
}
rowElements.set(row, elements);
}
}
public Component getComponent() {
return this.fif;
}
public void setStateColour(StateColourForRow stateColour) {
this.stateColour = stateColour;
}
}