Package DisplayProject

Source Code of DisplayProject.DropListModel$SelectionChangeHandler

/*
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;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;

import DisplayProject.actions.WidthPolicy;
import DisplayProject.binding.ListElementValueModelConverter;
import DisplayProject.binding.value.ValueHolder;
import DisplayProject.binding.value.ValueModel;
import DisplayProject.controls.AutoResizingComboBox;
import DisplayProject.table.ListFieldCellRenderer;
import Framework.Array_Of_ListElement;
import Framework.BooleanData;
import Framework.CloneHelper;
import Framework.DataValue;
import Framework.IntegerData;
import Framework.ListElement;
import Framework.TextData;

/**
* This class is the JComboBox model that emulates both the Forte DropList and FillInField behaviour.
*/
public class DropListModel extends AbstractListModel implements ActionListener, ComboBoxModel, ListField {
    private static final long serialVersionUID = 3206729867902416032L;
    // TF:22/07/2008:Removed this and deferred the code to the underlying widget
    // protected int SizePolicy = Constants.SP_NATURAL;
    private AutoResizingComboBox cb;
    private boolean self = false;
    private boolean isFillIn = false;
    private ListFieldCellRenderer renderer = null;
    //private final SelectionInList theList;
    private Array_Of_ListElement<ListElement> elements;
    private final ValueModel theModel;

    public DropListModel(Array_Of_ListElement<ListElement> pList, ValueModel pModel, AutoResizingComboBox cb) {
        //SelectionInList aList = new SelectionInList(pList);
        //this.selectionInList = pList;
        this.theModel = pModel;
        // this.selectionHolder = pModel;
        if (pModel != null) {
            this.theModel.addValueChangeListener(new SelectionChangeHandler());
        }

        //this.theList = pList;
        this.cb = cb;
        this.isFillIn = cb.isEditable();

//        this.elements = pList;
        this.setElementList(pList);
    }

    public DropListModel(Array_Of_ListElement<ListElement> pList, AutoResizingComboBox cb) {
        this(pList, new ValueHolder(), cb);
    }

    /**
     * Get the size policy of the underlying combo box
     * @return
     * @deprecated use WidthPolicy.get() instead
     */
    public int getSizePolicy() {
      return WidthPolicy.get(this.cb);
    }

    /**
     * Set the size policy for the underlying combo box
     * @param sizePolicy
     * @deprecated use WidthPolicy.set() instead
     */
    public void setSizePolicy(int sizePolicy) {
      WidthPolicy.set(this.cb, sizePolicy);
    }

    public void setElementList(Array_Of_ListElement<ListElement> pList) {
        // need to clone the passed parameter
        // array of list element before setting the elements of the of
        // the drop list.
        // TF:8/8/07:Made a shallow clone in case there is a really big object attached to the list element
        Array_Of_ListElement<ListElement> clonedList = CloneHelper.clone(pList, false);
        Object currValue = null;
        if (this.theModel != null) {
            if (this.theModel instanceof ListElementValueModelConverter) {
              // TF:20/11/2009:DET-127:Changed this to use a new method on the converter
              ListElementValueModelConverter converter = (ListElementValueModelConverter)this.theModel;
              currValue = converter.getCurrentValue();
                converter.setElements(pList);
            }
            else {
              currValue = this.theModel.getValue();
            }
        }
        this.elements = clonedList;

        if (!this.isFillIn && this.theModel != null) {
          this.theModel.setValue(currValue);
          if (this.theModel instanceof ListElementValueModelConverter) {
            ListElementValueModelConverter conv = (ListElementValueModelConverter)this.theModel;
            if (conv.getCurrentValue() == null && this.getBoundType() != null &&
                !DataValue.class.isAssignableFrom(this.getBoundType())) { //PM:29/11/07 don't set default value if it is null
              this.theModel.setValue(clonedList.get(0));
            }
            // CraigM:11/08/2008 - If we have tried to set a value before, and it didn't exist in the list, then try to set it again now.
              int index = ((ListElementValueModelConverter)this.theModel).getFailedSetIndex();

              if (index != -1) {
                this.setSelectedIndex(index);
              }
          }
          else {
            if (this.theModel.getValue() == null && this.getBoundType() != null &&
                !DataValue.class.isAssignableFrom(this.getBoundType())) { //PM:29/11/07 don't set default value if it is null
              this.theModel.setValue(clonedList.get(0));
            }
            }
        }

        if ((WidthPolicy.get(this.cb) == Constants.SP_NATURAL) && (this.cb instanceof AutoResizingComboBox))
        {
            ((AutoResizingComboBox)this.cb).sizeToNatural();
        }
        // TF:5/2/08:Added firing of the contentsChanged event to ensure correct functionality of the
        // drop list. Without this, there is no guarantee that the drop list will repaint correctly.
        if (pList != null) {
            this.fireContentsChanged(this, 0, pList.size() - 1);
        }
    }

    @SuppressWarnings("unchecked")
  public Array_Of_ListElement<ListElement> getElementList() {
        return (Array_Of_ListElement<ListElement>)this.elements.clone();
    }

    public boolean isAdjusting() {
        return self;
    }

    public void actionPerformed(ActionEvent e) {
//        if (self) return;
//        if (!cb.isEnabled()) return;
//        EventManager.startEventChain();
//        FocusHelper.addSetFocusPurgeAction(this.cb);
//        Logger.getLogger(this.getClass()).debug("ComboBox Action: " + e.getActionCommand());
//        if ((e.getActionCommand() == "comboBoxChanged") ||
//                (e.getActionCommand() == "comboBoxEdited"))
//        {
//            ClientEventManager.postEvent( cb, "AfterValueChange" );
//            UIutils.setDataChangedFlag(cb);
//            if (((JComponent)e.getSource()).getParent() != null){
//                Hashtable qq_Params = new Hashtable();
//                qq_Params.put("child", new ParameterHolder(e.getSource()));
//                Container mum = ((JComponent)e.getSource()).getParent();
//                while (mum != null) {
//                    ClientEventManager.postEvent(mum, "ChildAfterValueChange", qq_Params);
//                    mum = mum.getParent();
//                }
//            }
//
//        }
//        EventManager.endEventChain();
    }

    public TextData getTextValue() {
        final TextData target = new TextData();
        final BooleanData isNull = new BooleanData(false);
        UIutils.invokeOnGuiThread(new Runnable () {
            public void run() {
                if (cb.isEditable()) {
                        target.setValue(cb.getEditor().getItem().toString());
                }
                else {
                    if (cb.getSelectedIndex() == -1)
                      isNull.setValue( true );
                    else
                        target.setValue(cb.getSelectedItem().toString());
                }
            }
        });
        if (!isNull.getBooleanValue()) {
          return target;
        }
        else {
          return null;
        }
    }

    public int getIntegerValue() {
        final IntegerData target = new IntegerData();
        UIutils.invokeOnGuiThread(
            new Runnable () {
                public void run() {
                    if (cb.getSelectedIndex() == -1) {
                      // TF:07/10/2008:Tests show that Forte didn't return 0, but rather Integer.MIN_VALUE
                        target.setValue(Integer.MIN_VALUE);
                    }
                    else {
                        target.setValue(((ListElement)cb.getSelectedItem()).getIntegerValue());
                    }
                }
            });
        return target.getValue();
    }


    public ListFieldCellRenderer getRenderer() {
        return renderer;
    }
    public void setRenderer(ListFieldCellRenderer renderer) {
        this.renderer = renderer;
    }

    public Object getObjectValue() {
      // TF:07/10/2008:Changed this to read the selected index instead of the selected item
      // otherwise we get classCastException when reading a drop list with no elements mapped to a TextData
        if (this.getSelectedIndex()!= -1)
            return ((ListElement)this.getSelectedItem()).getObjectValue();
        else
            return null;
    }
    public void setIntegerValue(int value) {
      int foundIndex = -1;
      for (int i = 0; i < this.getSize(); i++) {
        ListElement row = (ListElement)this.getElementAt(i);

        if (row.getIntegerValue() == value) {
          foundIndex = i;
          break;
        }
      }
      if ((foundIndex == -1 ) && (!cb.isEditable()) && this.getSize() > 0)
        foundIndex = 0;

      final int index = foundIndex;
      UIutils.invokeOnGuiThread(new Runnable () {
        public void run() {
          cb.setSelectedIndex(index);
        }
      });
    }

    public void setObjectValue(Object value) {
      int foundIndex = -1;
      for (int i = 0; i < this.getSize(); i++) {
        ListElement row = (ListElement)this.getElementAt(i);

        if (row.getObjectValue()!= null && row.getObjectValue().equals(value)) {
          foundIndex = i;
          break;
        }
      }

      final int index = foundIndex;
      UIutils.invokeOnGuiThread(new Runnable () {
        public void run() {
          cb.setSelectedIndex(index);
        }
      });
    }

    public void setTextValue(TextData value) {
        int foundIndex = -1;
        ListElement row = null;

        for (int i = 0; i < this.getSize(); i++) {
      row = (ListElement)this.getElementAt(i);

            if (row.getTextValue().isEqual(value,true).getValue()) {
                foundIndex = i;
                break;
            }
        }

        // If we are editable (FillInField), then allow setting of text to a non element. CraigM 27/09/2007.
        if (foundIndex == -1 && cb.isEditable()) {
          // TF:26/06/2008:Check to make sure it's not an existing value first.
          Object o = cb.getSelectedItem();
          if ((o instanceof String && ((String)o).equals(value)) ||
              (o instanceof TextData && ((TextData)o).toString().equals(value)) ||
              (o instanceof ListElement && ((ListElement)o).getTextValue() != null && ((ListElement)o).getTextValue().toString().equals(value))) {
            // No change to the value, do nothing
          }
          else {
            // CraigM:19/08/2008 - We don't want to post events back to the user
            // cb.setSelectedItem(new ListElement(value.toString()));
            cb.setSelectedItemWithoutPosting(new ListElement(value.toString()));
          }
        }
        else {
        // CraigM:19/08/2008 - We don't want to post events back to the user
            // cb.setSelectedIndex(foundIndex);
            cb.setSelectedItemWithoutPosting(row);
        }
    }

    public boolean isFillIn() {
        return isFillIn;
    }
    /**
     * Returns the <code>ListElement</code> found with the given text value.
     *
     * @param value - TextData 
     * @return an Object that reflects the <code>ListElement</code> found to match the input text value 
     */
    public Object getElementFor(TextData value) {
        return getElementFor(value.toString());
    }

    /**
     * Returns the <code>ListElement</code> found with the given text value.
     *
     * @param value - String 
     * @return an Object that reflects the <code>ListElement</code> found to match the input text value 
     */
    public Object getElementFor(String value) {
        Object element = null;
        for (int i = 0; i < this.getSize(); i++) {
            ListElement row = (ListElement)this.getElementAt(i);
            if (row.equals(value)) {
                element = row;
            }
        }
        if (element == null && isFillIn()) {
            element = value;
        }
        return element;
    }

    /**
     * Returns the <code>ListElement</code> found with the given integer value.
     *
     * @param value - int 
     * @return an Object that reflects the <code>ListElement</code> found to match the input text value 
     */
    public Object getElementFor(int value) {
        Object element = null;
        for (int i = 0; i < this.getSize(); i++) {
            ListElement row = (ListElement)this.getElementAt(i);
            if (row.equals(value)) {
                element = row;
            }
        }
        if (element == null && isFillIn()) {
            element = String.valueOf(value);
        }
        return element;
    }

    /**
     * Returns the <code>ListElement</code> found with the given integer value.
     *
     * @param value - int 
     * @return an Object that reflects the <code>ListElement</code> found to match the input text value 
     */
    public Object getElementFor(Object value) {
        Object element = null;
        for (int i = 0; i < this.getSize(); i++) {
            ListElement row = (ListElement)this.getElementAt(i);
            if (row.equals(value)) {
                element = row;
            }
        }
        if (element == null && isFillIn())
            element = String.valueOf(value);
        return element;
    }

    /**
     * Holds the list of choices. If this adapter has been constructed
     * without a separate selection holder, the SelectionInList also
     * holds this adapter's selection.
     */
    //private final SelectionInList selectionInList;

    /**
     * In case this adapter has been constructed with a separate
     * selection holder, this ValueModel holds the combo's selection.
     */
    // private final ValueModel selectionHolder;

    // ComboBoxModel API ****************************************************

    /**
     * Returns the selected item by requesting the current value from the
     * either the selection holder or the SelectionInList's selection.
     *
     * @return The selected item or <code>null</code> if there is no selection
     */
    public Object getSelectedItem() {
        if (this.theModel != null) {
            return this.theModel.getValue();
        }
        return null;
    }


    /**
     * Sets the selected item. The implementation of this method should notify
     * all registered <code>ListDataListener</code>s that the contents has
     * changed.
     *
     * @param object the list object to select or <code>null</code> to clear
     *        the selection
     */
    public void setSelectedItem(Object object) {
        if (this.theModel != null) {
            this.self = true;
            this.theModel.setValue(object);
            fireContentsChanged(this, -1, -1);
            this.self = false;
        }
    }


    /**
     * Returns the length of the item list.
     *
     * @return the length of the list
     */
    public int getSize() {
        return this.elements.size();
    }


    /**
     * Returns the value at the specified index.
     *
     * @param index the requested index
     * @return the value at <code>index</code>
     */
    public Object getElementAt(int index) {
        if (index >= 0 && index < this.elements.size()) {
            return this.elements.get(index);
        }
        else {
            return null;
        }
    }


    // Event Handling *********************************************************

    /**
     * Listens to selection changes and fires a contents change event.
     */
    private class SelectionChangeHandler implements PropertyChangeListener {

        /**
         * The selection has changed. Notifies all
         * registered listeners about the change.
         *
         * @param evt the property change event to be handled
         */
        public void propertyChange(PropertyChangeEvent evt)
        {
            //  remove listeners so we do not fire AfterChildValueChange event
            //      when just populating the DropList. The event gets called from
            //      the model when populating, but from the DropList when the actual
            //      value is changed by the user. Advised by Rob.
            ActionListener[] listeners = cb.getActionListeners();
            for (int i=0; i < listeners.length; i++) {
                cb.removeActionListener(listeners[i]);
            }
            // TF:13/8/07:If this value is set from setting the value in code explicitly,
            // we don't actually get the value set. Thus we need to ensure it's set if
            // it's not the same. We'll only do this for drop list models for now...
//            Object oldValue = theModel.getValue();
//            if ((oldValue != null && oldValue.equals(evt.getNewValue())) || (oldValue == null && evt.getNewValue() == null)) {
//              // values are the same, do nothing
//            }
//            else {
//              theModel.setValue(evt.getNewValue());
//            }
           
            // TF:09/01/2010:DET-144:Reflected the actual value back into the model.
            DropListModel.this.theModel.setValue(evt.getNewValue());
            fireContentsChanged(DropListModel.this, -1, -1);

            for (int i=0; i < listeners.length; i++) {
                cb.addActionListener(listeners[i]);
            }           
        }
    }


    public int getSelectedIndex() {
        return this.cb.getSelectedIndex();
    }

    public void setSelectedIndex(int index) {
        // CraigM:01/10/2008 - Forte ignored invalid index, so we will too. JIRA: AXA-12.
      try {
            this.cb.setSelectedIndex(index);
        }
      catch (IllegalArgumentException e) {
        // Ignore
      }
    }
    /**
     * returns the bound type
     * @return
     */
    public Class<?> getBoundType(){
        if (this.theModel instanceof ListElementValueModelConverter) {
            return ((ListElementValueModelConverter)this.theModel).getSubjectType();
        }
        else {
            return null;
        }
    }

  /* (non-Javadoc)
   * @see ListField#setElementSelected(int, boolean)
     * @author AD:26/5/2008
   */
  public void setElementSelected(int index, boolean isSelected) {
    this.cb.setElementSelected(index, isSelected);
  }
}
TOP

Related Classes of DisplayProject.DropListModel$SelectionChangeHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.