Author: bobtarling
Date: 2011-02-13 09:51:28-0800
New Revision: 19029
Added:
trunk/src/argouml-app/src/org/argouml/uml/ui/UMLModelElementStereotypeListModel.java
- copied, changed from r19025,
/trunk/src/argouml-app/src/org/argouml/uml/ui/foundation/core/UMLModelElementStereotypeListModel.java
trunk/src/argouml-app/src/org/argouml/uml/ui/UMLStereotypeListModel.java
Removed:
trunk/src/argouml-app/src/org/argouml/uml/ui/foundation/core/UMLModelElementStereotypeListModel.java
Modified:
trunk/src/argouml-app/src/org/argouml/uml/ui/TabStereotype.java
Log:
Introduce UMLStereotypeListModel so that there is no dependence on deprecated
UMLModelElementListModel2
Modified: trunk/src/argouml-app/src/org/argouml/uml/ui/TabStereotype.java
Url:
http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/ui/TabStereotype.java?view=diff&pathrev=19029&r1=19028&r2=19029
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/ui/TabStereotype.java
(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/ui/TabStereotype.java
2011-02-13 09:51:28-0800
@@ -66,7 +66,6 @@
import org.argouml.ui.TabModelTarget;
import org.argouml.ui.targetmanager.TargetManager;
import org.argouml.uml.StereotypeUtility;
-import org.argouml.uml.ui.foundation.core.UMLModelElementStereotypeListModel;
import org.tigris.gef.presentation.Fig;
import org.tigris.swidgets.Horizontal;
import org.tigris.swidgets.Vertical;
@@ -262,7 +261,7 @@
* the ones already applied.
*/
private static class UMLModelStereotypeListModel
- extends UMLModelElementListModel2 {
+ extends UMLStereotypeListModel {
/**
* Constructor for UMLModelElementNamespaceListModel.
Copied:
trunk/src/argouml-app/src/org/argouml/uml/ui/UMLModelElementStereotypeListModel.java
(from r19025,
/trunk/src/argouml-app/src/org/argouml/uml/ui/foundation/core/UMLModelElementStereotypeListModel.java)
Url:
http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/ui/UMLModelElementStereotypeListModel.java?view=diff&pathrev=19029&r1=19025&r2=19029
==============================================================================
---
/trunk/src/argouml-app/src/org/argouml/uml/ui/foundation/core/UMLModelElementStereotypeListModel.java
(original)
+++
trunk/src/argouml-app/src/org/argouml/uml/ui/UMLModelElementStereotypeListModel.java
2011-02-13 09:51:28-0800
@@ -36,7 +36,7 @@
// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-package org.argouml.uml.ui.foundation.core;
+package org.argouml.uml.ui;
import javax.swing.Action;
import javax.swing.Icon;
@@ -46,15 +46,14 @@
import org.argouml.model.Model;
import org.argouml.uml.StereotypeUtility;
-import org.argouml.uml.ui.UMLModelElementListModel2;
/**
* The swing List Model for displaying stereotypes.
* @since Oct 24, 2005
* @author Bob Tarling
*/
-public class UMLModelElementStereotypeListModel
- extends UMLModelElementListModel2 {
+class UMLModelElementStereotypeListModel
+ extends UMLStereotypeListModel {
/**
* Constructor for UMLModelElementNamespaceListModel.
Added: trunk/src/argouml-app/src/org/argouml/uml/ui/UMLStereotypeListModel.java
Url:
http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/ui/UMLStereotypeListModel.java?view=markup&pathrev=19029
==============================================================================
--- (empty file)
+++ trunk/src/argouml-app/src/org/argouml/uml/ui/UMLStereotypeListModel.java
2011-02-13 09:51:28-0800
@@ -0,0 +1,557 @@
+/* $Id: UMLStereotypeListModel.java 18588 2010-07-28 21:30:25Z bobtarling $
+ *****************************************************************************
+ * Copyright (c) 2009 Contributors - see below
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * mvw
+ *****************************************************************************
+ *
+ * Some portions of this file was previously release using the BSD License:
+ */
+
+// Copyright (c) 2002-2008 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.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JPopupMenu;
+
+import org.apache.log4j.Logger;
+import org.argouml.model.AddAssociationEvent;
+import org.argouml.model.AssociationChangeEvent;
+import org.argouml.model.AttributeChangeEvent;
+import org.argouml.model.InvalidElementException;
+import org.argouml.model.Model;
+import org.argouml.model.RemoveAssociationEvent;
+import org.argouml.ui.targetmanager.TargetEvent;
+import org.argouml.ui.targetmanager.TargetListener;
+import org.tigris.gef.base.Diagram;
+import org.tigris.gef.presentation.Fig;
+
+/**
+ * The model for a list that contains ModelElements. The state of the Element
is
+ * still kept in the model subsystem itself. This list is only to be used as
the
+ * model for some GUI element like UMLLinkedList.
+ *
+ * @since Oct 2, 2002
+ * @author [email protected]
+ */
+abstract class UMLStereotypeListModel extends DefaultListModel
+ implements TargetListener, PropertyChangeListener {
+
+ private static final Logger LOG =
+ Logger.getLogger(UMLStereotypeListModel.class);
+
+ private String eventName = null;
+ private Object listTarget = null;
+
+ /**
+ * 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;
+
+ /**
+ * The type of model elements this list model is designed to hold.
+ */
+ private Object metaType;
+
+ /**
+ * Indicates that drops onto this list should connect in the opposite
+ * way to standard.
+ */
+ private boolean reverseDropConnection;
+
+ /**
+ * Constructor to be used if the subclass does not depend on the
+ * MELementListener methods and setTarget method implemented in this
+ * class.
+ */
+ public UMLStereotypeListModel() {
+ super();
+ }
+
+ /**
+ * Constructor for UMLModelElementListModel2.
+ *
+ * @param name the name of the event to listen to, which triggers us
+ * to update the list model from the UML data
+ */
+ public UMLStereotypeListModel(String name) {
+ super();
+ eventName = name;
+ }
+
+ /**
+ * Constructor for UMLModelElementListModel2.
+ *
+ * @param name the name of the event to listen to, which triggers us
+ * to update the list model from the UML data
+ * @param theMetaType the type of model element that the list model
+ * is designed to contain.
+ */
+ public UMLStereotypeListModel(String name, Object theMetaType) {
+ super();
+ this.metaType = theMetaType;
+ eventName = name;
+ }
+
+ /**
+ * Constructor for UMLModelElementListModel2.
+ *
+ * @param name the name of the event to listen to, which triggers us
+ * to update the list model from the UML data
+ * @param theMetaType the type of model element that the list model
+ * is designed to contain.
+ * @param reverseTheDropConnection tells the JList to reverse the
+ * connection made and drop during dnd.
+ */
+ public UMLStereotypeListModel(
+ String name,
+ Object theMetaType,
+ boolean reverseTheDropConnection) {
+ super();
+ this.metaType = theMetaType;
+ eventName = name;
+ this.reverseDropConnection = reverseTheDropConnection;
+ }
+
+ /**
+ * Get the type of objects that this list model is designed to contain.
+ * @return metaType the meta type.
+ */
+ public Object getMetaType() {
+ return metaType;
+ }
+
+ public boolean isReverseDropConnection() {
+ return reverseDropConnection;
+ }
+
+ /**
+ * @param building The buildingModel to set.
+ */
+ protected void setBuildingModel(boolean building) {
+ this.buildingModel = building;
+ }
+
+ /**
+ * @param t the list target to set
+ */
+ protected void setListTarget(Object t) {
+ this.listTarget = t;
+ }
+
+ /*
+ * @see
java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+ *
+ * TODO: This should be reviewed to see if it can be improved with a view
+ * towards removing some of the overrriding methods used as workarounds
for
+ * differences between NSUML and MDR - tfm - 20060302
+ */
+ public void propertyChange(PropertyChangeEvent e) {
+ if (e instanceof AttributeChangeEvent) {
+ try {
+ if (isValidEvent(e)) {
+ rebuildModelList();
+ }
+ } catch (InvalidElementException iee) {
+ return;
+ }
+ } else if (e instanceof AddAssociationEvent) {
+ if (isValidEvent(e)) {
+ Object o = getChangedElement(e);
+ if (o instanceof Collection) {
+ ArrayList tempList = new ArrayList((Collection) o);
+ Iterator it = tempList.iterator();
+ while (it.hasNext()) {
+ Object o2 = it.next();
+ addElement(o2);
+ }
+ } else {
+ /* TODO: If this is an ordered list, then you have to
+ add in the right location! */
+ addElement(o);
+ }
+ }
+ } else if (e instanceof RemoveAssociationEvent) {
+ boolean valid = false;
+ if (!(getChangedElement(e) instanceof Collection)) {
+ valid = contains(getChangedElement(e));
+ } else {
+ Collection col = (Collection) getChangedElement(e);
+ Iterator it = col.iterator();
+ valid = true;
+ while (it.hasNext()) {
+ Object o = it.next();
+ if (!contains(o)) {
+ valid = false;
+ break;
+ }
+ }
+ }
+ if (valid) {
+ Object o = getChangedElement(e);
+ if (o instanceof Collection) {
+ Iterator it = ((Collection) o).iterator();
+ while (it.hasNext()) {
+ Object o3 = it.next();
+ removeElement(o3);
+ }
+ } else {
+ removeElement(o);
+ }
+ }
+ }
+ }
+
+ /**
+ * Delete and rebuild the model list from scratch.
+ */
+ private void rebuildModelList() {
+ removeAllElements();
+ buildingModel = true;
+ try {
+ buildModelList();
+ } catch (InvalidElementException exception) {
+ /*
+ * This can throw an exception if the target has been
+ * deleted. We don't want to try locking the repository
+ * because this is called from the event delivery thread and
+ * could cause a deadlock. Instead catch the exception and
+ * leave the model empty.
+ */
+ LOG.debug("buildModelList threw exception for target "
+ + getTarget() + ": "
+ + exception);
+ } finally {
+ buildingModel = false;
+ }
+ if (getSize() > 0) {
+ fireIntervalAdded(this, 0, getSize() - 1);
+ }
+ }
+
+ /**
+ * Builds the list of elements. Called from targetChanged every time the
+ * target of the proppanel is changed. Usually the method setAllElements is
+ * called with the result.
+ */
+ protected abstract void buildModelList();
+
+ /**
+ * Utility method to set the elements of this list to the contents of the
+ * given collection.
+ * @param col the given collection
+ */
+ protected void setAllElements(Collection col) {
+ if (!isEmpty())
+ removeAllElements();
+ addAll(col);
+ }
+
+ /**
+ * Utility method to add a collection of elements to the model
+ * @param col the given collection
+ */
+ protected void addAll(Collection col) {
+ if (col.size() == 0) return;
+ Iterator it = col.iterator();
+ fireListEvents = false;
+ int intervalStart = getSize() == 0 ? 0 : getSize() - 1;
+ while (it.hasNext()) {
+ Object o = it.next();
+ addElement(o);
+ }
+ fireListEvents = true;
+ fireIntervalAdded(this, intervalStart, getSize() - 1);
+ }
+
+ /**
+ * Utility method to get the target. Sets the target if the target is null
+ * via the method setTarget().
+ * @return MModelElement
+ */
+ public Object getTarget() {
+ return listTarget;
+ }
+
+ /**
+ * Utility method to get the changed element from some event e
+ * @param e the event
+ * @return Object the changed element
+ */
+ protected Object getChangedElement(PropertyChangeEvent e) {
+ if (e instanceof AssociationChangeEvent) {
+ return ((AssociationChangeEvent) e).getChangedValue();
+ }
+ if (e instanceof AttributeChangeEvent) {
+ return ((AttributeChangeEvent) e).getSource();
+ }
+ return e.getNewValue();
+ }
+
+ /*
+ * @see javax.swing.DefaultListModel#contains(java.lang.Object)
+ */
+ public boolean contains(Object elem) {
+ if (super.contains(elem)) {
+ return true;
+ }
+ if (elem instanceof Collection) {
+ Iterator it = ((Collection) elem).iterator();
+ while (it.hasNext()) {
+ if (!super.contains(it.next())) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets the target. If the old target is a ModelElement, it also removes
+ * the model from the element listener list of the target. If the new
target
+ * is instanceof ModelElement, the model is added as element listener to
the
+ * new target. <p>
+ *
+ * This function is called when the user changes the target.
+ * Hence, this shall not result in any UML model changes.
+ * Hence, we block firing list events completely by setting
+ * buildingModel to true for the duration of this function. <p>
+ *
+ * This function looks a lot like the one in UMLComboBoxModel2.
+ *
+ * @param theNewTarget the new target
+ */
+ public void setTarget(Object theNewTarget) {
+ theNewTarget = theNewTarget instanceof Fig
+ ? ((Fig) theNewTarget).getOwner() : theNewTarget;
+ if (Model.getFacade().isAUMLElement(theNewTarget)
+ || theNewTarget instanceof Diagram) {
+ if (Model.getFacade().isAUMLElement(listTarget)) {
+ Model.getPump().removeModelEventListener(this, listTarget,
+ eventName);
+ // Allow listening to other elements:
+ removeOtherModelEventListeners(listTarget);
+ }
+
+ if (Model.getFacade().isAUMLElement(theNewTarget)) {
+ listTarget = theNewTarget;
+ Model.getPump().addModelEventListener(this, listTarget,
+ eventName);
+ // Allow listening to other elements:
+ addOtherModelEventListeners(listTarget);
+
+ rebuildModelList();
+
+ } else {
+ listTarget = null;
+ removeAllElements();
+ }
+ }
+ }
+
+ /**
+ * This function allows subclasses to listen to more modelelements.
+ * The given target is guaranteed to be a UML modelelement.
+ *
+ * @param oldTarget the UML modelelement
+ */
+ protected void removeOtherModelEventListeners(Object oldTarget) {
+ /* Do nothing by default. */
+ }
+
+ /**
+ * This function allows subclasses to listen to more modelelements.
+ * The given target is guaranteed to be a UML modelelement.
+ *
+ * @param newTarget the UML modelelement
+ */
+ protected void addOtherModelEventListeners(Object newTarget) {
+ /* Do nothing by default. */
+ }
+
+ /**
+ * Returns true if the given element is valid, i.e. it may be added to the
+ * list of elements.
+ *
+ * @param element the element to be tested
+ * @return true if valid
+ */
+ protected abstract boolean isValidElement(Object element);
+
+ /**
+ * 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 valid
+ */
+ protected boolean isValidEvent(PropertyChangeEvent e) {
+ boolean valid = false;
+ if (!(getChangedElement(e) instanceof Collection)) {
+ // TODO: Considering all delete events to be valid like below
+ // is going to cause lots of unecessary work and some problems
+ if ((e.getNewValue() == null && e.getOldValue() != null)
+ // Don't test changed element if it was deleted
+ || isValidElement(getChangedElement(e))) {
+ 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.DefaultListModel#addElement(java.lang.Object)
+ */
+ public void addElement(Object obj) {
+ if (obj != null && !contains(obj)) {
+ super.addElement(obj);
+ }
+ }
+
+ /**
+ * Returns the eventName. This method is only here for testing goals.
+ * @return String
+ */
+ String getEventName() {
+ return eventName;
+ }
+
+ /**
+ * Sets the eventName. The eventName is the name of the
+ * MElementEvent to which the list should listen. The list is
+ * registred with UMLModelEventPump and only gets events that have
+ * a name like eventName. This method should be called in the
+ * constructor of every subclass.
+ *
+ * @param theEventName The eventName to set
+ */
+ protected void setEventName(String theEventName) {
+ eventName = theEventName;
+ }
+
+ /*
+ * @see TargetListener#targetAdded(TargetEvent)
+ */
+ public void targetAdded(TargetEvent e) {
+ setTarget(e.getNewTarget());
+ }
+
+ /*
+ * @see TargetListener#targetRemoved(TargetEvent)
+ */
+ public void targetRemoved(TargetEvent e) {
+ setTarget(e.getNewTarget());
+ }
+
+ /*
+ * @see TargetListener#targetSet(TargetEvent)
+ */
+ public void targetSet(TargetEvent e) {
+ setTarget(e.getNewTarget());
+ }
+
+ /*
+ * @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);
+ }
+
+ /**
+ * Override this if you want a popup menu.
+ * See for an example UMLModelElementOrderedListModel2.
+ *
+ * @param popup the popup menu
+ * @param index the selected item in the list at the moment
+ * the mouse was clicked
+ * @return true if a popup menu is created, and needs to be shown
+ */
+ public boolean buildPopup(JPopupMenu popup, int index) {
+ return false;
+ }
+
+ protected boolean hasPopup() {
+ return false;
+ }
+
+}
Removed:
trunk/src/argouml-app/src/org/argouml/uml/ui/foundation/core/UMLModelElementStereotypeListModel.java
Url:
http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/ui/foundation/core/UMLModelElementStereotypeListModel.java?view=markup&pathrev=19028
------------------------------------------------------
http://argouml.tigris.org/ds/viewMessage.do?dsForumId=5905&dsMessageId=2703702
To unsubscribe from this discussion, e-mail:
[[email protected]].