Author: thn
Date: 2011-04-01 07:56:09-0700
New Revision: 19172
Added:
trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationModel.java
trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationPanel.java
trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationValueField.java
Log:
UML2: a simple value specification panel, e.g. for initial values
TODO: needs to handle different kinds
Added: trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationModel.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationModel.java?view=markup&pathrev=19172
==============================================================================
--- (empty file)
+++ trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationModel.java 2011-04-01 07:56:09-0700
@@ -0,0 +1,241 @@
+/* $Id$
+ *******************************************************************************
+ * Copyright (c) 2011 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:
+ * Thomas Neustupny
+ *******************************************************************************
+ */
+
+package org.argouml.core.propertypanels.ui;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.EventListenerList;
+
+import org.apache.log4j.Logger;
+import org.argouml.model.Model;
+
+/**
+ * The model for value specifications.
+ * The target is the UML element to which this ValueSpecification is attached.
+ *
+ * The ChangeEvent/ChangeListener handling is inspired by
+ * javax.swing.DefaultBoundedRangeModel.
+ * It listens to UML model changes not caused by us,
+ * which need to trigger an update of the UI rendering.
+ *
+ * @author Thomas Neustupny
+ */
+ class UMLValueSpecificationModel
+ implements PropertyChangeListener {
+
+ private static final Logger LOG =
+ Logger.getLogger(UMLValueSpecificationModel.class);
+
+ private Object target;
+ private String propertyName;
+
+ /** This member is only used when we set the expression ourselves.
+ * In this case, we do not wish to receive UML model change events
+ * for this self-inflicted change.
+ * So, this member is used to detect this situation. */
+ private Object rememberExpression;
+
+// private boolean mustRefresh;
+ private static final String EMPTYSTRING = "";
+
+ /** The listeners waiting for model changes. */
+ protected EventListenerList listenerList = new EventListenerList();
+
+ /**
+ * Only one <code>ChangeEvent</code> is needed per model instance
+ * since the event's only (read-only) state is the expression. The source
+ * of events generated here is always "this".
+ */
+ protected transient ChangeEvent changeEvent = null;
+
+ /**
+ * The constructor.
+ *
+ * @param target the UML element
+ * @param name the name of the property
+ */
+ public UMLValueSpecificationModel(Object target, String name) {
+ this.target = target;
+ propertyName = name;
+// mustRefresh = true;
+ startListeningForModelChanges();
+ }
+
+ protected void startListeningForModelChanges() {
+ if (Model.getFacade().isAUMLElement(target)) {
+ Model.getPump().addModelEventListener(this, target,
+ propertyName);
+ }
+ LOG.debug(">>Start listening for UML changes...");
+ }
+
+ protected void stopListeningForModelChanges() {
+ if (Model.getFacade().isAUMLElement(target)) {
+ Model.getPump().removeModelEventListener(this, target,
+ propertyName);
+ }
+ LOG.debug(">>Stop listening for UML changes...");
+ }
+
+ public void propertyChange(PropertyChangeEvent e) {
+ if (propertyName.equals(e.getPropertyName())) {
+ if (rememberExpression != e.getNewValue()) {
+ fireStateChanged();
+ LOG.debug(">>UML expression changed.");
+ } else {
+ /* This should not happen. */
+ LOG.debug(">>Got an event for a modelchange that we inflicted ourselves...");
+ }
+ }
+ }
+
+ protected Object getTarget() {
+ return target;
+ }
+
+ /**
+ * @return the expression
+ */
+ private Object getExpression() {
+ return Model.getFacade().getInitialValue(getTarget());
+ }
+
+ /**
+ * @param expr the expression
+ */
+ private void setExpression(Object expression) {
+ Object target = getTarget();
+ assert (expression == null) || Model.getFacade().isAExpression(expression);
+ /* If we do not set it to null first, then we get a MDR DebugException: */
+ Model.getCoreHelper().setInitialValue(target, null);
+ Model.getCoreHelper().setInitialValue(target, expression);
+ }
+
+ /**
+ * @return a new expression with given language and body
+ */
+ public Object newExpression(String lang, String body) {
+ return Model.getDataTypesFactory().createExpression(lang, body);
+ }
+
+ /**
+ * @return The value text of the value specification.
+ */
+ public String getText() {
+ Object expression = getExpression();
+ if (expression == null) {
+ return EMPTYSTRING;
+ }
+ return Model.getFacade().getBody(expression).toString();
+ }
+
+ /**
+ * @param text the value text of the value specification
+ */
+ public void setText(String text) {
+
+ Object expression = getExpression();
+ boolean mustChange = true;
+ if (expression != null) {
+ Object oldValue = Model.getFacade().getBody(expression).toString();
+ if (oldValue != null && oldValue.equals(text)) {
+ mustChange = false;
+ }
+ }
+ if (mustChange) {
+ String lang = null;
+ if (expression != null) {
+ lang = Model.getDataTypesHelper().getLanguage(expression);
+ }
+ if (lang == null) {
+ lang = EMPTYSTRING;
+ }
+
+ setExpression(lang, text);
+ }
+ }
+
+ /**
+ * This is only called if we already know that the values differ.
+ *
+ * @param lang the language of the expression
+ * @param body the body text of the expression
+ */
+ private void setExpression(String lang, String body) {
+ assert lang != null;
+ assert body != null;
+
+ // Expressions are DataTypes, not independent model elements
+ // be careful not to reuse them
+ rememberExpression = getExpression();
+ stopListeningForModelChanges();
+ if (rememberExpression != null) {
+ Model.getUmlFactory().delete(rememberExpression);
+ }
+ if (lang.length() == 0 && body.length()==0) {
+ rememberExpression = null;
+ } else {
+ rememberExpression = newExpression(lang, body);
+ }
+ setExpression(rememberExpression);
+ startListeningForModelChanges();
+ }
+
+ /**
+ * Adds a <code>ChangeListener</code>.
+ * The change listeners are run each
+ * time the expression changes.
+ *
+ * @param l the ChangeListener to add
+ * @see #removeChangeListener
+ */
+ public void addChangeListener(ChangeListener l) {
+ listenerList.add(ChangeListener.class, l);
+ LOG.debug(">>Add listener");
+ }
+
+ /**
+ * Removes a <code>ChangeListener</code>.
+ *
+ * @param l the <code>ChangeListener</code> to remove
+ * @see #addChangeListener
+ */
+ public void removeChangeListener(ChangeListener l) {
+ listenerList.remove(ChangeListener.class, l);
+ LOG.debug(">>Remove listener");
+ }
+
+ /**
+ * Runs each <code>ChangeListener</code>'s
+ * <code>stateChanged</code> method.
+ *
+ * @see #setRangeProperties
+ * @see EventListenerList
+ */
+ protected void fireStateChanged() {
+ LOG.debug(">>Fire state changed to listeners.");
+ Object[] listeners = listenerList.getListenerList();
+ for (int i = listeners.length - 2; i >= 0; i -=2 ) {
+ if (listeners[i] == ChangeListener.class) {
+ if (changeEvent == null) {
+ changeEvent = new ChangeEvent(this);
+ }
+ ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
+ }
+ }
+ }
+}
Added: trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationPanel.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationPanel.java?view=markup&pathrev=19172
==============================================================================
--- (empty file)
+++ trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationPanel.java 2011-04-01 07:56:09-0700
@@ -0,0 +1,63 @@
+/* $Id$
+ *******************************************************************************
+ * Copyright (c) 2011 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:
+ * Thomas Neustupny
+ *******************************************************************************
+ */
+
+package org.argouml.core.propertypanels.ui;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.apache.log4j.Logger;
+import org.tigris.swidgets.LabelledLayout;
+
+/**
+ * The panel that shows a value specification for an other UML element.
+ */
+class UMLValueSpecificationPanel extends JPanel implements ChangeListener {
+
+ private static final Logger LOG = Logger
+ .getLogger(UMLValueSpecificationPanel.class);
+
+ private final UMLValueSpecificationModel model;
+ private final UMLValueSpecificationValueField valueField;
+
+ public UMLValueSpecificationPanel(UMLValueSpecificationModel model,
+ String title) {
+
+ super(new LabelledLayout());
+ LOG.debug(">>New ValueSpecification panel created");
+
+ TitledBorder border = new TitledBorder(title);
+ this.setBorder(border);
+
+ this.model = model;
+ this.valueField = new UMLValueSpecificationValueField(model, true);
+
+ add(new JScrollPane(valueField));
+
+ model.addChangeListener(this);
+ }
+
+ @Override
+ public void removeNotify() {
+ model.removeChangeListener(this);
+ super.removeNotify();
+ }
+
+ public void stateChanged(ChangeEvent e) {
+ LOG.debug(">>Values shown on panel are changed");
+ valueField.update();
+ }
+}
Added: trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationValueField.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationValueField.java?view=markup&pathrev=19172
==============================================================================
--- (empty file)
+++ trunk/src/argouml-core-umlpropertypanels/src/org/argouml/core/propertypanels/ui/UMLValueSpecificationValueField.java 2011-04-01 07:56:09-0700
@@ -0,0 +1,95 @@
+/* $Id$
+ *******************************************************************************
+ * Copyright (c) 2011 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:
+ * Thomas Neustupny
+ *******************************************************************************
+ */
+
+package org.argouml.core.propertypanels.ui;
+
+import javax.swing.JTextArea;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+
+import org.apache.log4j.Logger;
+import org.argouml.i18n.Translator;
+import org.argouml.ui.LookAndFeelMgr;
+
+/**
+ * This text field shows the value of a UML value specification.
+ *
+ */
+class UMLValueSpecificationValueField extends JTextArea implements
+ DocumentListener {
+
+ /**
+ * Logger.
+ */
+ private static final Logger LOG = Logger
+ .getLogger(UMLValueSpecificationValueField.class);
+
+ private UMLValueSpecificationModel model;
+ private boolean notifyModel;
+
+ /**
+ * The constructor.
+ *
+ * @param model
+ * ValueSpecification model, should be shared between the fields
+ * @param notify
+ * Set to true to forward events to model. Only one of Language
+ * and Body fields should have this set to true.
+ */
+ public UMLValueSpecificationValueField(UMLValueSpecificationModel model,
+ boolean notify) {
+ this.model = model;
+ this.notifyModel = notify;
+ getDocument().addDocumentListener(this);
+ setToolTipText(Translator.localize("label.body.tooltip"));
+ setFont(LookAndFeelMgr.getInstance().getStandardFont());
+ setRows(2); // make it stretch vertically
+
+ update();
+ }
+
+ void update() {
+ String oldText = getText();
+ String newText = model.getText();
+
+ if (oldText == null || newText == null || !oldText.equals(newText)) {
+ if (oldText != newText) {
+ setText(newText);
+ }
+ }
+ }
+
+ /*
+ * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.
+ * DocumentEvent)
+ */
+ public void changedUpdate(final DocumentEvent p1) {
+ model.setText(getText());
+ }
+
+ /*
+ * @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.
+ * DocumentEvent)
+ */
+ public void removeUpdate(final DocumentEvent p1) {
+ model.setText(getText());
+ }
+
+ /*
+ * @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.
+ * DocumentEvent)
+ */
+ public void insertUpdate(final DocumentEvent p1) {
+ model.setText(getText());
+ }
+}
------------------------------------------------------
http://argouml.tigris.org/ds/viewMessage.do?dsForumId=5905&dsMessageId=2716086
To unsubscribe from this discussion, e-mail: [[email protected]].
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.