Currently txtUML supports diagram definitions for class- and flat state machine diagrams. The language is universal, but only supports flat (one level) diagrams. For simplicity in this description, whenever a box is referenced, it stands for either a class, state or composition role name. Also if a line is present, it stands for association or transition.
A diagram definition is a Java class inheriting from the appropriate type:
ClassDiagram
.StateMachineDiagram<C>
, where C
is a ModelClass
which states we want to display in this diagram.
This class must contain an inner class definition, inheriting from Layout
. The actual layout constraints can be written as annotations on this inner class.
class MyDiagram extends ClassDiagram { // layout constraints as annotations @North(val = A.class, from = B.class) class MyLayout extends Layout {} }
In this section A and B are boxes (classes, states, compositions) already defined in a txtUML model. Relative layout for these boxes can be given as presented:
@North(val = A.class, from = B.class)
: The diagram can be cut horizontally such that A is in the upper half and B is in the lower half.@East(val = A.class, from = B.class)
: The diagram can be cut vertically such that A is in the right half and B is in the left half.@South(val = A.class, from = B.class)
: The diagram can be cut horizontally such that A is in the lower half and B is in the upper half.@West(val = A.class, from = B.class)
: The diagram can be cut vertically such that A is in the left half and B is in the right half.@Above(val = A.class, from = B.class)
: Box A is north from B and is right next to it.@Right(val = A.class, from = B.class)
: Box A is east from B and is right next to it.@Below(val = A.class, from = B.class)
: Box A is south from B and is right next to it.@Left(val = A.class, from = B.class)
: Box A is west from B and is right next to it.
Example: Model contains these classes: A, B and C.
class MyClassDiagram extends ClassDiagram { @North(val = A.class, from = B.class) @Below(val = A.class, from = C.class) @West(val = C.class, from = B.class) class MyLayout extends Layout {} }
Example: The class A contains these states: Init, Disabled and Active.
class MyStateDiagram extends StateMachineDiagram<A> { @Left(val = Init.class, from = Disabled.class) @Left(val = Disabled.class, from = Active.class) class MyLayout extends Layout {} }
In this section A, B, C and D are boxes already defined in a txtUML model. Complex layout for these boxes can be given as presented:
@Column({A.class, B.class, C.class})
: The boxes A, B and C are arranged in a column, with the top being A and preserving the order. Any number of boxes can be given here.@Row({A.class, B.class, C.class, D.class})
: The boxes A, B, C and D are arranged in a row, with the left most being A and preserving the order. Any number of boxes can be given here.@Diamond(top = A.class, right = B.class, bottom = C.class, left = D.class)
: The boxes A, B, C and D are arranged in a diamond shape where the four boxes are in the corners and an empty spot remains between them.@TopMost(A.class)
: Box A is north from every other box.@RightMost(A.class)
: Box A is east from every other box.@BottomMost(A.class)
: Box A is south from every other box.@LeftMost(A.class)
: Box A is west from every other box.Example: Model contains these classes: C, E, D, O, R, S1 and S2.
class MyDiagram extends ClassDiagram { @Row({R.class, E.class, D.class}) @Column({C.class, R.class, O.class, S1.class, S2.class}) class MyLayout extends Layout {} }
In this section A is a box already defined in a txtUML model and L is a line with an endpoint at box A. Relative layout for the line and box can be given as presented. For reflexive lines a third parameter must be added which is a value of LinkEnd
enum.
@North(val = L.class, from = A.class)
: Line L will connect to box A on A's northern side.@North(val = L.class, from = A.class, end = LinkEnd.Start)
: Reflexive line L's starting point will connect to box A on A's northern side.@North(val = L.class, from = A.class, end = LinkEnd.End)
: Reflexive line L's ending point will connect to box A on A's northern side.@East
, @South
and @West
.@Priority(val = L.class, prior = 50)
: Gives line L a priority value of 50. Higher priority means shorter route and less turns.
Example: Model contains these classes: A and B. Model contains these links: L (A - B) and R (A - A).
class MyDiagram extends ClassDiagram { @North(val = L.class, from = A.class) @East(val = L.class, from = B.class) @Above(val = A.class, from = B.class) @West(val = R.class, from = A.class, end = LinkEnd.Start) @South(val = R.class, from = A.class, end = LinkEnd.End) class MyLayout extends Layout {} }
In this section A, B, C are boxes already defined in a txtUML model and L and J are lines with an endpoint at box A.
A group can be specified by defining a class inheriting either from NodeGroup
or from LinkGroup
. The elements of the group can be specified with the @Contains
annotation. A group can contain model elements of the corresponding type or other groups containing elements of the corresponding type.
@Contains({A.class, B.class}) class NG1 extends NodeGroup {}
@Contains({L.class, J.class}) class LG1 extends LinkGroup {}
If the given group is a NodeGroup
, the annotation @Alignment
can be used to set the alignment of its elements, using items of enum hu.elte.txtuml.layout.lang.AlignmentType, i.e. TopToBottom
, BottomToTop
, RightToLeft
or LeftToRight
.
@Contains({NG1.class, C.class}) @Alignment(AlignmentType.TopToBottom) class NG2 extends NodeGroup {}
This notation of groups is equivalent to using {…}
symbols and enumerate the contents within. This is called an unnamed group, while the previously shown is a named group. Both can be used in the same way.
The previously mentioned statements can be used with these groups as parameters as well.
@North(val = {A.class, B.class}, from = C.class)
: Both boxes A and B are north from C. The layout between A and B is not defined.@North(val = A.class, from = {B.class, C.class})
: Box A is north from box B and from box C as well. The layout between B and C is not defined.@North(val = LG1.class, from = A.class)
: Every element of group LG1 is north from box A. The layout between the elements of LG1 is not defined.@East
, @South
and @West
.@TopMost({A. class, B.class})
: Boxes A and B are north from every other boxes in the model.@TopMost(NG1.class)
: Boxes which are elements of LG1 are north from every other boxes in the model.@RightMost
, @BottomMost
and @LeftMost
.Example: Model contains these classes: A, B, C and D.
class MyDiagram extends ClassDiagram { @Contains({C.class, D.class}) @Alignment(AlignmentType.TopToBottom) class MyGroup extends NodeGroup{} @Row({A.class, MyGroup.class, B.class}) class MyLayout extends Layout {} }
In this section A and B are boxes already defined in a txtUML model. Phantoms are defined by extending class Phantom
and can be used as nodes in layout statements.
Example:
class MyPhantom extends Phantom {} //... @Above(val = A.class, from = MyPhantom.class) @Above(val = MyPhantom.class, from = B.class) //...
If we do not include a box into any statements (annotations) then the box won't appear on the diagram by itself. We can explicitly make it appear - without restricting it's position with other statements - using @Show
.
@Show(A.class)
: Box A is present in the diagram.
Example: Model contains these classes: A and B.
class MyDiagram extends ClassDiagram { @Show(A.class) class MyLayout extends Layout {} }
We can reduce/increase the space between boxes in the generated diagram by using @Spacing
statement (annotation), with a percentage given.
@Spacing(0.8)
: The empty space between diagrams will be 80% of the default. Note: the space between boxes has a lower limit, so depending on a specific diagram using the @Spacing
statement with “too low” values will not affect the generated diagram.
Example: Model contains these classes: A and B.
class MyDiagram extends ClassDiagram { @Spacing(0.6) @Row({A.class, B.class}) class MyLayout extends Layout {} }
There may be certain errors that blocks the running of the diagram layout generation process. This may occur because of:
@North(val = A.class, from = B.class)
and @South(val = A.class, from = B.class)