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]].

Reply via email to