|
What this is
Other links
The source code// $Id: UMLComboBoxModel2.java,v 1.44 2004/09/15 19:17:04 mvw Exp $ // Copyright (c) 1996-2004 The Regents of the University of California. All // Rights Reserved. Permission to use, copy, modify, and distribute this // software and its documentation without fee, and without a written // agreement is hereby granted, provided that the above copyright notice // and this paragraph appear in all copies. This software program and // documentation are copyrighted by The Regents of the University of // California. The software program and documentation are supplied "AS // IS", without any accompanying services from The Regents. The Regents // does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program // was developed for research purposes and is advised not to rely // exclusively on the program for any reason. IN NO EVENT SHALL THE // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. package org.argouml.uml.ui; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import javax.swing.AbstractListModel; import javax.swing.ComboBoxModel; import org.apache.log4j.Logger; import org.argouml.model.ModelFacade; import org.argouml.model.uml.UmlModelEventPump; import org.argouml.ui.targetmanager.TargetEvent; import org.argouml.ui.targetmanager.TargetListener; import org.tigris.gef.presentation.Fig; import ru.novosoft.uml.MElementEvent; import ru.novosoft.uml.MElementListener; /** * ComboBoxmodel for UML modelelements. This implementation does not use * reflection and seperates Model, View and Controller better then does * UMLComboBoxModel. In the future UMLComboBoxModel and UMLComboBox will be * replaced with this implementation to improve performance. */ public abstract class UMLComboBoxModel2 extends AbstractListModel implements MElementListener, ComboBoxModel, TargetListener { private static final Logger LOG = Logger.getLogger(UMLComboBoxModel2.class); /** * The taget of the comboboxmodel. This is some UML modelelement */ private Object comboBoxTarget = null; /** * The list with objects that should be shown in the combobox */ private List objects = new ArrayList(); /** * The selected object */ private Object selectedObject = null; /** * Flag to indicate if the user may select "" as value in the combobox. If * true the attribute that is shown by this combobox may be set to null. * Makes sure that there is allways a "" in the list with objects so the * user has the oportunity to select this to clear the attribute. */ private boolean isClearable = false; /** * The name of the event with which NSUML sets the attribute that is shown * in this comboboxmodel. */ private String propertySetName; /** * Flag to indicate wether list events should be fired */ private boolean fireListEvents = true; /** * Flag to indicate wether the model is being build */ private boolean buildingModel = false; /** * Constructs a model for a combobox. The container given is used * to retreive the target that is manipulated through this * combobox. If clearable is true, the user can select null in the * combobox and thereby clear the attribute in the model. * * @param name The name of the NSUML event that must be * fired to set the selected item programmatically (via setting * the NSUML model) * @throws IllegalArgumentException if one of the arguments is null * @param clearable Flag to indicate if the user may select "" * as value in the combobox. If true the attribute that is shown * by this combobox may be set to null. * Makes sure that there is allways a "" in the list with objects so the * user has the oportunity to select this to clear the attribute. */ public UMLComboBoxModel2(String name, boolean clearable) { super(); if (name == null || name.equals("")) throw new IllegalArgumentException("one of the arguments is null"); // it would be better that we don't need the container to get // the target this constructor can be without parameters as // soon as we improve targetChanged isClearable = clearable; propertySetName = name; } /** * @see ru.novosoft.uml.MElementListener#listRoleItemSet(MElementEvent) */ public void listRoleItemSet(MElementEvent e) { } /** * If the property that this comboboxmodel depicts is changed by the NSUML * model, this method will make sure that it is changed in the comboboxmodel * too. * @see ru.novosoft.uml.MElementListener#propertySet(MElementEvent) */ public void propertySet(MElementEvent e) { if (e.getName().equals(propertySetName) && e.getSource() == getTarget() && (isClearable || getChangedElement(e) != null)) { Object elem = getChangedElement(e); if (!contains(elem)) addElement(elem); setSelectedItem(elem); } } /** * @see ru.novosoft.uml.MElementListener#recovered(MElementEvent) */ public void recovered(MElementEvent e) { } /** * @see ru.novosoft.uml.MElementListener#removed(MElementEvent) */ public void removed(MElementEvent e) { if (contains(getChangedElement(e))) { Object o = getChangedElement(e); if (o instanceof Collection) { removeAll((Collection) o); } else { removeElement(o); } } } /** * @see ru.novosoft.uml.MElementListener#roleAdded(MElementEvent) */ public void roleAdded(MElementEvent e) { if (getTarget() != null && isValidEvent(e)) { Object o = getChangedElement(e); if (o instanceof Collection) { // this should not happen but // you never know with NSUML LOG.warn( "Collection added via roleAdded! The correct element" + "is probably not selected..."); Iterator it = ((Collection) o).iterator(); while (it.hasNext()) { Object o2 = it.next(); addElement(it.next()); } } else { addElement(o); } } } /** * @see ru.novosoft.uml.MElementListener#roleRemoved(MElementEvent) */ public void roleRemoved(MElementEvent e) { if (contains(getChangedElement(e))) { Object o = getChangedElement(e); if (o instanceof Collection) { removeAll((Collection) o); } else { removeElement(o); } } } /** * Returns true if the given element is valid, i.e. it may be added to the * list of elements. * @param element the given element * @return true if the given element is valid */ protected abstract boolean isValidElement(Object element); /** * Builds the list of elements and sets the selectedIndex to the currently * selected item if there is one. Called from targetChanged every time the * target of the proppanel is changed. */ protected abstract void buildModelList(); /** * Utility method to change all elements in the list with modelelements * at once. * * @param elements the given elements */ protected void setElements(Collection elements) { if (elements != null) { //removeAllElements(); if (!objects.isEmpty()) { fireIntervalRemoved(this, 0, objects.size() - 1); } //addAll(elements); objects = Collections.synchronizedList(new ArrayList(elements)); if (!objects.isEmpty()) { fireIntervalAdded(this, 0, objects.size() - 1); } selectedObject = null; if (isClearable && !elements.contains("")) { addElement(""); } } else throw new IllegalArgumentException("In setElements: may not set " + "elements to null collection"); } /** * Utility method to get the target. Sets the _target if the * _target is null via the method setTarget(). * * @return MModelElement */ protected Object getTarget() { return comboBoxTarget; } /** * Utility method to remove a collection of elements from the model. * * @param col the elements to be removed */ protected void removeAll(Collection col) { Iterator it = col.iterator(); int lower = -1; int index = -1; int lastindex = -1; fireListEvents = false; while (it.hasNext()) { Object o = it.next(); removeElement(o); if (lower == -1) { // start of interval lower = getIndexOf(o); index = lower; } else { if (getIndexOf(o) != index + 1) { // end of interval fireListEvents = true; fireIntervalRemoved(this, lower, index); fireListEvents = false; lower = -1; } else { // in middle of interval index++; } } } fireListEvents = true; } /** * Utility method to add a collection of elements to the model * @param col the elements to be addd */ protected void addAll(Collection col) { Iterator it = col.iterator(); Object o2 = getSelectedItem(); fireListEvents = false; int oldSize = objects.size(); while (it.hasNext()) { Object o = it.next(); addElement(o); } setSelectedItem(o2); fireListEvents = true; fireIntervalAdded(this, oldSize - 1, objects.size() - 1); } /** * Utility method to get the changed element from some event e * @param e the given event * @return Object the changed element */ protected Object getChangedElement(MElementEvent e) { if (e.getAddedValue() != null) return e.getAddedValue(); if (e.getRemovedValue() != null) return e.getRemovedValue(); if (e.getNewValue() != null) return e.getNewValue(); return null; } /** * Sets the target. If the old target is instanceof MBase, it also removes * the model from the element listener list of the target. If the new target * is instanceof MBase, the model is added as element listener to the new * target. * @param target the target */ protected void setTarget(Object target) { target = target instanceof Fig ? ((Fig) target).getOwner() : target; if (ModelFacade.isABase(target) || ModelFacade.isADiagram(target)) { UmlModelEventPump eventPump = UmlModelEventPump.getPump(); if (ModelFacade.isABase(comboBoxTarget)) { eventPump.removeModelEventListener(this, comboBoxTarget, propertySetName); } if (ModelFacade.isABase(target)) { comboBoxTarget = target; // UmlModelEventPump.getPump() // .removeModelEventListener(this, (MBase)_target, // _propertySetName); eventPump.addModelEventListener(this, comboBoxTarget, propertySetName); } else { comboBoxTarget = null; } fireListEvents = false; removeAllElements(); fireListEvents = true; if (comboBoxTarget != null) { buildingModel = true; buildModelList(); buildingModel = false; setSelectedItem(getSelectedModelElement()); if (getSize() > 0) { fireIntervalAdded(this, 0, getSize() - 1); } } if (getSelectedItem() != null && isClearable) { addElement(""); // makes sure we can select 'none' } } } /** * Gets the modelelement that is selected in the NSUML model. For * example, say that this ComboBoxmodel contains all namespaces * (as in UMLNamespaceComboBoxmodel) , this method should return * the namespace that owns the target then. * * @return Object */ protected abstract Object getSelectedModelElement(); /** * @see javax.swing.ListModel#getElementAt(int) */ public Object getElementAt(int index) { if (index >= 0 && index < objects.size()) return objects.get(index); return null; } /** * @see javax.swing.ListModel#getSize() */ public int getSize() { return objects.size(); } /** * @param o the given element * @return the index of the given element */ public int getIndexOf(Object o) { return objects.indexOf(o); } /** * @param o the element to be added */ public void addElement(Object o) { if (!objects.contains(o)) { objects.add(o); fireIntervalAdded(this, objects.size() - 1, objects.size() - 1); } } /** * @see javax.swing.ComboBoxModel#setSelectedItem(java.lang.Object) */ public void setSelectedItem(Object o) { if ((selectedObject != null && !selectedObject.equals(o)) || (selectedObject == null && o != null)) { selectedObject = o; fireContentsChanged(this, -1, -1); } } /** * @param o the element to be removed */ public void removeElement(Object o) { int index = objects.indexOf(o); if (getElementAt(index) == selectedObject) { if (index == 0) { setSelectedItem(getSize() == 1 ? null : getElementAt(index + 1)); } else { setSelectedItem(getElementAt(index - 1)); } } if (index >= 0) { objects.remove(index); fireIntervalRemoved(this, index, index); } } /** * Remove all elements. */ public void removeAllElements() { int startIndex = 0; int endIndex = Math.max(0, objects.size() - 1); // if (!_objects.isEmpty()) { objects.clear(); selectedObject = null; fireIntervalRemoved(this, startIndex, endIndex); // } } /** * @see javax.swing.ComboBoxModel#getSelectedItem() */ public Object getSelectedItem() { return selectedObject; } /** * Returns true if some object elem is contained by the list of choices * @param elem the given element * @return boolean true if it is in the selection */ public boolean contains(Object elem) { if (objects.contains(elem)) return true; if (elem instanceof Collection) { Iterator it = ((Collection) elem).iterator(); while (it.hasNext()) { if (!objects.contains(it.next())) return false; } return true; } return false; } /** * Returns true if some event is valid. An event is valid if the * element changed in the event is valid. This is determined via a * call to isValidElement. This method can be overriden by * subclasses if they cannot determine if it is a valid event just * by checking the changed element. * * @param e the event * @return boolean true if the event is valid */ protected boolean isValidEvent(MElementEvent e) { boolean valid = false; if (!(getChangedElement(e) instanceof Collection)) { valid = isValidElement(getChangedElement(e)); if (!valid && e.getNewValue() == null && e.getOldValue() != null) { valid = true; // we tried to remove a value } } else { Collection col = (Collection) getChangedElement(e); Iterator it = col.iterator(); if (!col.isEmpty()) { valid = true; while (it.hasNext()) { Object o = it.next(); if (!isValidElement(o)) { valid = false; break; } } } else { if (e.getOldValue() instanceof Collection && !((Collection) e.getOldValue()).isEmpty()) { valid = true; } } } return valid; } /** * @see javax.swing.AbstractListModel#fireContentsChanged( * Object, int, int) */ protected void fireContentsChanged(Object source, int index0, int index1) { if (fireListEvents && !buildingModel) super.fireContentsChanged(source, index0, index1); } /** * @see javax.swing.AbstractListModel#fireIntervalAdded( * Object, int, int) */ protected void fireIntervalAdded(Object source, int index0, int index1) { if (fireListEvents && !buildingModel) super.fireIntervalAdded(source, index0, index1); } /** * @see javax.swing.AbstractListModel#fireIntervalRemoved( * Object, int, int) */ protected void fireIntervalRemoved(Object source, int index0, int index1) { if (fireListEvents && !buildingModel) super.fireIntervalRemoved(source, index0, index1); } /** * @see TargetListener#targetAdded(TargetEvent) */ public void targetAdded(TargetEvent e) { setTarget(e.getNewTarget()); } /** * @see TargetListener#targetRemoved(TargetEvent) */ public void targetRemoved(TargetEvent e) { Object currentTarget = comboBoxTarget; Object oldTarget = e.getOldTargets().length > 0 ? e.getOldTargets()[0] : null; if (oldTarget instanceof Fig) { oldTarget = ((Fig) oldTarget).getOwner(); } if (oldTarget == currentTarget) { if (ModelFacade.isABase(currentTarget)) { UmlModelEventPump.getPump().removeModelEventListener(this, currentTarget, propertySetName); } comboBoxTarget = e.getNewTarget(); } // setTarget(e.getNewTarget()); } /** * @see TargetListener#targetSet(TargetEvent) */ public void targetSet(TargetEvent e) { setTarget(e.getNewTarget()); } } |
... this post is sponsored by my books ... | |
![]() #1 New Release! |
![]() FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.