Purpose - to provide a form view of the diagrams and objects in the model. The contents of the model is modifiable.
The Property panels will be located in
org.argouml.uml.?
.
The Property panels is a View subsystem. See Section 4.5, “View and Control subsystems”.
The PropPanels for the diagrams are in
org.argouml.uml.diagram.ui
and the property panels for UML objects are in
org.argouml.uml.ui.
.
UML path
Property Panels for UML model elements are found as class
PropPanel
,
where XXX
.javaXXX
is the
UML meta-class. They are in sub-packages of org.argouml.uml.ui
corresponding to the XXX
NSUML packages,
which in turn correspond to
their section in the chapter 2 of the UML 1.3 spec.
So for our example we create a new class
PropPanelExtend
in package
org.argouml.uml.ui.behavior.use_cases
.
Any associated classes that do not fall into the UML classification are provided in org.argouml.uml.ui.
Typically the constructor for the new proppanel class invokes the
parent constructor, and then builds the fields required on the property
tab. The parent constructor may need an icon. If you need a new icon, it
should be placed in org/argouml/Images
and a call to
lookupIcon()
made (note that this is a utility method
of the parent PropPanel class). For our example we had to add
Extend.gif
.
Finally the property panel must be added to the list of property
panels in the run()
method of the
TabProps
class, with a new call of
panels.put()
. If you don't do this, navigation
listeners won't know about it!
The content of the property panel is created as a grid with columns (1 column if there are only a few fields, 2 or 3 if there are more). Each row of each column contains a caption (i.e. label) and its corresponding field.
A caption and its field may be added with one of a small number of utility methods which shield you from the layout stuff: addField() and addSeperator().
A button may be added to the toolbar with the utility method addButton().
Every field is built from Java Swing components. However these are extended by ArgoUML to help in the provision of action methods for fields in the property tab. Several fields involve lists, and these require in addition list models to compute the members of the list.
The fields that you might add to a property panel include:
Simple editable text. For example the Name field. Supported
through the UMLTextField2
class.
A drop down box (aka combobox) of options that can be selected.
Supported by the UMLComboBox2
class. Used
e.g. for the type of a parameter.
A check box. This one does not use a seperate model class,
thanks to the simplicity of the represented boolean value. Supported
by the UMLCheckBox2
class. Used e.g. for the
concurrency checkbox on a composite state.
A radio button. These always come in a group. Supported by the
UMLRadioButtonPanel
class. Used e.g. for selecting
the visibility on the properties panel of a class.
A list. Used e.g. for the Generalizations field on
the proppanel of a class. The non-editable list is supported by the
UMLList2
class and its child
UMLLinkedList
. The latter also exists in the form
of UMLMutableLinkedList
, which allows adding,
creation and deleting elements by popup menu. Used e.g. for the
subvertex list for a composite state.
The list model is usually provided by a sub-class of
UMLModelElementListModel2
. There is a variant
UMLModelElementOrderedListModel2
intended for
ordered links, which adds a few items to the pop-up menu, allowing
sorting. This latter model is used e.g. for attributes of a class.
A drop down box of options that can be selected. This one exists
in several versions, each having different possibilities. The most
simple version is the UMLComboBox2
.
The UMLEditableComboBox
allows editing the
selected item.
The UMLSearchableComboBox
allows editing the
selected item. See e.g. the Operation combobox on the callevent
properties panel.
Then there is a variant with a seperate button for navigation to
the property panel for the currently selected item. This is supported
by theUMLComboBoxNavigator
class. Used e.g. for
the stereotype field.
An editable multiline text area. Supported by the
UMLTextArea2
class. Used e.g. for the text field
of a UML Comment.
Examples of these fields in more detail follow below.
For example we need to add a field to the use case property panel for the extends relationships that derive from this use case.
This field consists of a label and a scrollable pane
(JScrollPane
) containing the list
(JList
), which may be empty, or contain extend
relationships from this use case.
Rather than a straight JList
, we use its child,
UMLLinkedList
, which adds several features to the
standard JList specifically for ArgoUML's properties panels.
The constructor for UMLLinkedList
requires two
arguments, a list model and a flag to indicate whether to show an icon.
The list model should be a subclass of
UMLModelElementListModel2
, a subclass of the Swing
DefaultListModel
which implements
AbstractListModel
. The
UMLModelElementListModel2
implements two
interfaces: one that listens to target changes, and one that listens to
UML model changes.
In our example we create
UMLUseCaseExtendListModel
. Its constructor takes
no arguments. However, we need to provide the parent class with a
NSUML event name by invokeing the constructor of the parent class,
with the event name as parameter.
A string naming an NSUML event that should force a refresh of
the list model. A null value will cause all events to trigger a
refresh. The best way to identify the event you want to use is to
look at the NSUML source for the container object
(MUseCaseImpl
in our example) for calls to
fire
. The first
argument is the name of the event (in our case
XXX
()extend
). There is no definitive list, but from the
NSUML source, these are all the names of events that are used:
action
actionSequence
activator
activityGraph
actualArgument
addition
aggregation
alias
annotatedElement
argument
association
associationEnd
associationEndRole
associationRole
attribute
attributeLink
availableContents
availableFeature
availableQualifier
base
baseClass
baseElement
behavior
behavioralFeature
binding
body
bound
callAction
changeability
changeExpression
child
classifier
classifierInState
classifierRole
classifierRole1
client
clientDependency
collaboration
collaboration1
comment
communicationConnection
communicationLink
componentInstance
concurrency
condition
connection
constrainedElement
constrainedElement2
constrainingElement
constraint
container
contents
context
createAction
defaultElement
defaultValue
deferrableEvent
deploymentLocation
discriminator
dispatchAction
doActivity
dynamicArguments
dynamicMultiplicity
effect
elementImport
elementImport2
elementResidence
entry
event
exit
expression
extend
extend2
extendedElement
extender
extenderID
extension
extensionPoint
feature
generalization
guard
icon
implementationLocation
include
include2
incoming
initialValue
instance
instantiation
inState
interaction
internalTransition
isAbstarct
isAbstract
isActive
isAsynchronous
isConcurent
isDynamic
isInstantiable
isLeaf
isNavigable
isQuery
isRoot
isSpecification
isSynch
kind
link
linkEnd
location
mapping
message
message1
message2
message3
message4
method
modelElement
modelElement2
multiplicity
name
namespace
nodeInstance
objectFlowState
occurrence
operation
ordering
outgoing
ownedElement
owner
ownerScope
package
parameter
parent
participant
partition
partition1
powertype
powertypeRange
predecessor
presentation
qualifiedValue
qualifier
raisedSignal
receiver
reception
recurrence
referenceState
representedClassifier
representedOperation
requiredTag
resident
residentElement
script
sendAction
sender
signal
slot
source
sourceFlow
specialization
specification
state
state1
state2
state3
stateMachine
stereotype
stereotypeConstraint
stimulus
stimulus1
stimulus2
stimulus3
structuralFeature
subject
submachine
submachineState
subvertex
supplier
supplierDependency
tag
taggedValue
target
targetFlow
targetScope
templateParameter
templateParameter2
templateParameter3
top
transition
trigger
type
useCase
value
visibility
when
This list model should then be provided with a number of methods. The following are mandatory, since they are declared abstract in the parent.
protected void buildModelList()
(Re)Builds the list of elements. Called from targetChanged every time the target of the proppanel is changed.
protected boolean isValidElement(Object/*MBase*/
o)
Returns true if the given element is valid, i.e. it may be added to the list of elements. This function is called for many UML elements, to determine if it fits in the list. Remark: The indication /*MBase*/ is a remainder from the time that ArgoUML included direct references to the NSUML model all over the code. Now it is a practical reminder of what we are dealing with.
![]() | Warning |
---|---|
The following description is old and the property panels have undergone some fundamental changes since it was written. It would be good if someone that knows how it works now could write a description on how it works now. |
The following are sometimes provided as an override of the parent, although for many uses the default is fine.
public void open(int index)
Perform the action associated with the “open” pop-up menu on the element at the given index. The default provided in the parent just navigates to that element.
public boolean buildPopup(JPopupMenu popup, int
index)
Build a pop-up menu for the list and return whether it
should be displayed. Any actions will be associated with the
item at the given index in the list. This is built using
UMLListMenuItem
, which can record the index,
rather than plain JListItem
. The default
provides open, add, delete, move up and move down, with add
disabled if there are already as many elements as the upper
bound (if any) for the list, open and delete disabled if there
are no elements and move up and move down disabled if they
cannot be invoked on the given element. The default
implementation always returns true.
The following should be declared as needed to support particular pop-up functions.
public void add(int index)
Perform the actions associated with the “add”
pop-up menu on the element at the given index. There is no
default provided, so this must be given if the
“add” operation is supported. The
addAtUtil()
method (see below) may prove
helpful.
In this routine you may create a new NSUML entity. There
seem to be three ways to do this, in order of preference 1) use
a utility from the MMUtil
class, 2) use the
NSUML Factory class to create what you want 3) use new on a
M
class.
Whilst 1) is best, most of the XXX
ImplMMUtil
routines are not yet general enough.
Be sure to set it up (don't forget e.g namespace etc). Remember also to change anything that references the newly created entity.
![]() | Warning |
---|---|
The NSUML routines generally set up the “other” end of a relationship automatically if you set up one end. If you try to do both (on a NxM relationship) you will probably end up doing it twice. If you do encounter this, the rule of thumb is to explicitly set the ordered end (if you do it the other way round, NSUML will assume you mean the "other" end to be at the end of its ordered list). |
public void delete(int index)
Perform the actions associated with the “delete” pop-up menu on the element at the given index. There is no default provided, so this must be given if the “delete” operation is supported.
public void moveUp(int index)
Perform the actions associated with the “move up” pop-up menu on the element at the given index. There is no default provided, so this must be given if the “move up” operation is supported.
public void moveDown(int index)
Perform the actions associated with the “move down” pop-up menu on the element at the given index. There is no default provided, so this must be given if the “move down” operation is supported.
The following normally use the default method, but may be declared to override methods in the parent
public void resetSize()
Called when an external event may have changed the size of the list. The default just sets a flag, which will ensure recalcModelElementSize (see above) is invoked as needed.
public Object formatElement(MModelElement
element)
Return an object (invariably a String) that represents an element. The default provided in the parent defers this to the container, which in turn defers it to the current profile. This is usually perfectly satisfactory.
public void targetChanged()
Called when the number of elements in the displayed list (including “none”) may have changed. Default invokes the necessary Swing operations to advise of a change in list size.
public void targetReasserted()
Called when the navigation history has been changed (and navigation buttons may need changing). Not clear why anything is needed, but default recomputes the list size, and invokes the necessary Swing operations.
public void roleAdded(final MElementEvent
event)
part of the NSUML EventListener interface. Called when an add event happens, i.e. some NSUML object has been added. The default provided looks to see if the event is the role name we declared, or we are listening to all events, and if so looks to see if it relates to an element in our list. If so Swing is notified that the element has been added.
public void roleRemoved(final MElementEvent
event)
part of the NSUML EventListener interface. Called when a remove event happens, i.e. some NSUML object has been removed. The default provided looks to see if the event is the role name we declared, or we are listening to all events, and if so looks to see if it relates to an element in our list. If so Swing is notified that the element has been removed.
public void recovered(final MElementEvent p1)
,
public void listRoleItemSet(final MElementEvent
p1)
,
public void removed(final MElementEvent p1)
,
public void propertySet(final MElementEvent p1)
these are all required as part of the NSUML EventListener interface, which is not well documented. In each case the default implementation recomputes the size, and advises Swing that the entire list has changed. Needs more investigation.
public void navigateTo(MModelElement
modelElement)
a request to navigate to the specified object as part of the NavigationListener interface. The default in the parent just invokes navigateTo() on the container (ultimately PropPanel).
The following utility routines are also provided in the parent. They are not normally overridden.
public int getUpperBound()
get any upper bound (-1 is used if there is none).
public void setUpperBound(int newBound)
set the upper bound (-1 is used if there is none).
public final String getProperty()
returns the NSUML event name being monitored (null if all are being monitored).
protected final int getModelElementSize()
returns the number of elements in the list. Invokes
recalcModelElementSize()
(see above) if
necessary.
final Object getTarget()
returns the NSUML object associated with the container
(some child of PropPanel
usually) that holds
this list model.
final UMLUserInterfaceContainer getContainer()
returns the the container (some child of
PropPanel
usually) that holds this list
model.
public int getSize()
returns the size of the list. Including if there are no elements in the model, but the list has a default text when empty.
public Object getElementAt(int index)
returns the element at the given index in the list.
static protected Collection addAtUtil(Collection
oldCollection, MModelElement newItem, int index)
helps in writing the “add” function. newItem is added at the specified index in the given oldCollection.
static protected java.util.List moveUpUtil(Collection
oldCollection, int index)
helps in writing the “move up” function. Swaps the elements at offsets index and index-1. Not clear why it doesn't return a Collection.
static protected java.util.List moveDownUtil(Collection
oldCollection, int index)
helps in writing the “move down” function. Swaps the elements at offsets index and index-1. Not clear why it doesn't return a Collection.
static protected MModelElement elementAtUtil(Collection
collection, int index, Class requiredClass)
helps in writing the getElementAt()
.
Finds the element at a specific index. The last argument is
ignored!
By convention the background of the list is set to the same as the background of the PropPanel and the foreground to Color.blue.
The list is then added to a JScrollPane
.
Although ArgoUML has historically not used scrollbars
(JScrollPane.VERTICAL_SCROLLBAR_NEVER
and
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
), it is more
helpful to permit at least a vertical scrollbar where needed
(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
and
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
).
Finally the inherited method addCaption()
is used
to add the label for the field and addField()
to
add the associated scroll pane.
The second argument of each of these identifies the index of the caption/field pair in the vertical column of the grid for this property panel. The third argument identifies the column index. The final argument is a vertical weighting to expand the field if there is room in the property tab. This is usually set to the same non-zero value for all fields and corresponding captions that can have multiple entries, so they expand equally. If none of the fields should expand, the caption only of the last field in each column should be given a non-zero value.
These are added by creating new instances of
PropPanelButton
(you don't need to assign them to
anything - just creating will do).
This has six arguments.
The container, i.e this property panel (usually just use
this
).
The panel for the buttons.
Use buttonPanel
which is inherited from
PropPanel
.
The icon.
Lots of these are already defined in PropPanel
.
The advisory text for the button.
Use localize(string)
to ensure international
portability.
The name of the method to invoke when this button is used. Some of the standard ones (e.g for navigation) are provided, but you will need to write any specials.
The name of the method (if any) to invoke to see if this button should
be enabled.
Use null
if the button should always be
enabled.
In our example, the extend property panel has a “add extension
point” button, with a method
newExtensionPoint
that we provide to create a new
use case.
The PropPanel should override the following (note the spelling of the method name).
protected boolean
isAcceptibleBaseMetaClass(String baseClass)
.
Returns true
if the given base class is a class of
the target in the PropPanel
.
This is used to determine what stereotypes may be shown for this property panel.
Another sort of field that may be useful is the ComboBox. This is useful to allow users to select from a pre-defined list of alongside a navigation arrow to go to the selected entry.
For example this is used to provide drop-down lists for the base and extension use cases of an Extend relationship in PropPanelExtend.
The model behind the drop down is created by using
UMLComboBoxModel
:
UMLComboBoxModel(container, predicate, event, getter, setter,
allowVoid, baseClass, useModel)
.
The container is the PropPanel
where we are setting
up this ComboBox, the predicate is the name of a public method in that
PropPanel that, given a model element, determines if it should be in
the drop down, the event is the NSUML MElementEvent
name we are looking for (see earlier for the list),
getter
is the name of a public method in the
PropPanel that yields the current entry in the combo Box (of type
baseClass
), setter
(with a
single argument of type baseClass
) sets that entry,
allowVoid
if true
will allow an
empty entry for the box, baseClass
is the NSUML
meta-class from which all entries must descend,
useModel
is true
to consider all
the elements in the standard profile model for inclusion (so the Java
types, standard stereotypes etc.).
For our PropPanelExtend
, we provide a predicate
routine the call for the “base” field is:
UMLComboBoxModel(this, "isAcceptableUseCase", "base",
"getBase", "setBase", true, MUseCase.class, true);
and we define the methods isAcceptableUseCase
,
getBase
and setBase
in
PropPanelExtend
.
This information is provided by Jaap Branderhorst (September 2002).
UMLTextField
implements several kinds of
event listeners:
MMelementListener
DocumentListener
FocusListener
Furthermore it is a UMLUserInterfaceComponent
.
Since it is an UMLUserInterfaceComponent
it must implement targetChanged
and
targetReasserted
.
TargetChanged
is called every time the
UMLTextField
is selected.
targetReasserted
is of no interest for
UMLTextField
.
It plays a role in keeping history but since history
is not really implemented at the moment in ArgoUML
it is of no interest.
targetChanged
does two things:
It calls the targetChanged
method
of the UMLTextProperty
this
UMLTextfield
is showing.
It calls the update
method.
The update
method is described further on.
Besides UMLUserInterfaceComponent
there are several other interfaces of interest.
One of them is MMElementListener
.
Every time a MModelElement
is
changed this will fire an MEvent
to UMLChangeDispatch
.
UMLChangeDispatch
will dispatch
these events to all containers implementing
UMLUserInterfaceComponents
interested in this event, including UMLTextField
.
It will also dispatch the event to all children of an interested container
implementing
UMLUserInterfaceComponent
.
By this it is only necessary to register a
PropPanel
which holds an
UMLTextField
at
UMLChangeDispatch
to
dispatch the event to the UMLTextField
too.
MMelementListener
knows several methods of which only one is of interest to
UMLTextField
s:
propertySet
Called every time a property in a
MModelElement
is set.
This method calls
update
too if the
UMLTextProperty
really is affected.
Furthermore UMLTextField
implements
DocumentListener
.
This is very typical for UMLTextField
.
At the moment it is not possible to change the style of
the text in the UMLTextField
.
Therefore the method changedUpdate
does not
have a body.
This method is only called when a DocumentEvent
occurs that changes the style/layout of the text.
The methods insertUpdate
and removeUpdate
are respectively called when a
character is added to the document
UMLTextField
contains or removed.
Since both methods are called when there is true user input
and when the contents of the document are changed programmatically,
the methods distinguish between them.
InsertUpdate
and
removeUpdate
are both handled via the protected method
handleEvent
.
HandleEvent
updates the property in
UMLTextProperty
if it is really changed.
If the update comes via user input, it is checked if it is valid input.
If it is not, a JOptionPane
is shown with '
a warning and the change is not committed into the model.
If it is not via user input, the input is not checked and the
property is set. If the property is set, the update method is called.
The implementation of FocusListener
makes sure that the checking of user input only happens when focus is lost.
Otherwise, it would not be possible to enter 'intermediate' values
that are not legal.
For instance, say the value class is not legal.
Without the implementation of FocusListener
,
it would not be possible to enter class diagram since
handleEvent would pop-up a warning message box.
The method update
updates both the actual
JTextfield
as the diagram as soon
as some property is set.
The updating of the diagram is done by calling the
damage
method of the figs that
represent the property on the diagram.