diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/metapost/contrib/macros/metauml |
Initial commit
Diffstat (limited to 'graphics/metapost/contrib/macros/metauml')
87 files changed, 10948 insertions, 0 deletions
diff --git a/graphics/metapost/contrib/macros/metauml/README b/graphics/metapost/contrib/macros/metauml/README new file mode 100644 index 0000000000..f646504337 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/README @@ -0,0 +1,19 @@ +MetaUML https://github.com/ogheorghies/MetaUML + +Version: 0.2.6 +Author : Ovidiu Gheorghies +Date : February 02, 2019 + +MetaUML is a MetaPost library for creating UML diagrams using a textual notation. +It offers partial support for: +- class diagrams +- package diagrams +- activity diagrams +- use case diagrams +- state machine diagrams + +This release contains the following directories: + +doc : PDF documentation +examples : source code for the documentation +inputs : the macros needed to use MetaUML
\ No newline at end of file diff --git a/graphics/metapost/contrib/macros/metauml/doc/metauml-manual-v0.2.6-19d34de3da75cbd9f814f0a9ec03b4e0861b1541.pdf b/graphics/metapost/contrib/macros/metauml/doc/metauml-manual-v0.2.6-19d34de3da75cbd9f814f0a9ec03b4e0861b1541.pdf Binary files differnew file mode 100644 index 0000000000..30c8ae4f5f --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/doc/metauml-manual-v0.2.6-19d34de3da75cbd9f814f0a9ec03b4e0861b1541.pdf diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/activity.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/activity.mp new file mode 100644 index 0000000000..676d1996eb --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/activity.mp @@ -0,0 +1,52 @@ +% Sample MetaUML figures. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +input metauml; + +beginfig(1); + Begin.b; + End.e; + FlowFinal.f; + + leftToRight(20)(b, e, f); + + drawObjects(b, e, f); +endfig; + +beginfig(2); + Activity.A("Learn MetaUML -", + "the MetaPost UML library"); + drawObject(A); +endfig; + +beginfig(3); + Fork.forkA("h", 50); + Fork.forkB("v", 20); + + leftToRight(10)(forkA, forkB); + + drawObjects(forkA, forkB); +endfig; + +beginfig(4); + Branch.testA; + + drawObject(testA); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/activity_diagrams.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/activity_diagrams.mp new file mode 100644 index 0000000000..0807619acd --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/activity_diagrams.mp @@ -0,0 +1,59 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +% for f in `find . | grep '.*\.[1-9]'`; do echo $f; done + +input metauml; + +beginfig(1); + Begin.b; + Activity.eat("Eat something good", "from the kitchen"); + Branch.enough; + Fork.fork("h", 50); + Activity.read("Read a book"); + Activity.listen("Listen to music", "(and ignore it)"); + Fork.join("h", 50); + End.e; + + eat.n = b.s + (0,-20); + enough.n = eat.s + (0,-20); + fork.n = enough.s + (0, -20); + + read.top = listen.top = fork.bottom - 30; + listen.left - read.right = 10; + b.midx = .5[listen.left, read.right]; + + join.n = (b.midx, listen.bottom - 20); + e.n = join.s + (0, -20); + + drawObjects(b, eat, enough, fork, read, listen, join, e); + + clink(transition)(b, eat); + clink(transition)(eat, enough); + link(transition)(pathStepX(enough.w, eat.w, -80)); + clink(transition)(enough, fork); + clink(transition)(fork, read); + clink(transition)(fork, listen); + clink(transition)(read, join); + clink(transition)(listen, join); + clink(transition)(join, e); + + item(iGuard)("still hungry")(obj.se = enough.w + (-20, 0)); + item(iGuard)("had enough")(obj.nw = enough.s + (0, -4)); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/appetizer.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/appetizer.mp new file mode 100644 index 0000000000..ed90dc77dc --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/appetizer.mp @@ -0,0 +1,203 @@ +% Sample MetaUML figures. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + Class.Client("Client")()(); + + Class._Component("Component")()(); + %("+Operation()", "+Add(Component)", "+Remove(Component)", "+GetChild(int)"); + classStereotype._Component("<<interface>>"); + + Class.Leaf("Leaf")()("+Operation()"); + + Class.Composite("Composite")()(); + %("+Operation()", "+Add(Component)", "+Remove(Component)", "+GetChild(int)"); + + leftToRight.top(30)(Client, _Component); + leftToRight.top(20)(Leaf, Composite); + .5[Leaf.ne, Composite.nw] = below(_Component.s, 45); + + drawObjects(Client, _Component, Leaf, Composite); + + link(associationUni)(pathHorizontal(Client.e, _Component.left)); + link(inheritance)(pathStepY(Leaf.n, _Component.s, 20)); + link(inheritance)(pathStepY(Composite.n, _Component.s, 20)); + + link(aggregationUni)(pathStepX(_Component.e, Composite.e, 55)); +endfig; + +beginfig(2); + Begin.b; + Activity.eat("Eat something good", "from the kitchen"); + Branch.enough; + Fork.fork("h", 50); + Activity.read("Read a book"); + Activity.listen("Listen to music", "(and ignore it)"); + Fork.join("h", 50); + End.e; + + leftToRight.top(10)(read, listen); + Group.readListen(read, listen); + + leftToRight(30)(b, eat); + topToBottom(20)(eat, enough, fork, readListen, join, e); + + drawObjects(b, eat, enough, fork, readListen, join, e); + + clink(transition)(b, eat); + clink(transition)(eat, enough); + link(transition)(pathStepX(enough.e, eat.e, 80)); + clink(transition)(enough, fork); + clink(transition)(fork, read); + clink(transition)(fork, listen); + clink(transition)(read, join); + clink(transition)(listen, join); + clink(transition)(join, e); + + item(iGuard)("still hungry")(obj.sw = enough.e + (20, 0)); + item(iGuard)("had enough")(obj.nw = enough.s + (0, -4)); +endfig; + +beginfig(3); + Actor.user("User"); + Actor.db("Database"); + + Usecase.dbquery("Query database"); + Usecase.auth("Authenticate user"); + Usecase.authA("Authenticate by", "username, password"); + Usecase.authB("Authenticate by", "smartcard"); + + leftToRight(30)(user.human, auth, dbquery, db.human); + leftToRight.top(30)(authA, authB); + .5[authA.ne, authB.nw] = below(auth.s, 20); + + drawObjects(user, auth, dbquery, db, authA, authB); + + clink(inheritance)(authA, auth); + clink(inheritance)(authB, auth); + clink(association)(auth, dbquery); + clink(association)(user.human, auth); + clink(association)(dbquery, db.human); +endfig; + +beginfig(4); + save b, e, reading, processing, composite, exit, error, result, theEnd; + + Begin.b; + State.reading("Reading commands")(); + State.processing("Processing commands")(); + End.e; + + State.composite("Working")(b, reading, processing, e); + composite.info.left := composite.info.right := 10; + composite.info.drawNameLine := 1; + + topToBottom(20)(b, reading, processing, e); + drawObject(composite); + + clink(transition)(b, reading); + clink(transition)(reading, processing); + clink(transition)(processing, e); + + ExitPoint.exit; + exit.c=(composite.right, reading.midy); + drawObject(exit); + item(iAssoc)("error")(obj.nw = exit.s); + + clink(transition)(reading, exit); + + State.error("Preparing error report")(); + State.result("Writing result")(); + End.theEnd; + + topToBottom(20)(error, result, theEnd); + leftToRight(30)(exit, error); + + drawObjects(error, result, theEnd); + + clink(transition)(exit, error); + clink(transition)(error, result); + clink(transition)(result, theEnd); + + link(transition)(rpathHorizontal(result.w, composite.right)); +endfig; + + +beginfig(5); + save A, B; + + Note.A("An important", "UML note"); + Note.B("Another note"); + + leftToRight(20)(A, B); + drawObjects(A, B); + + clink(dashedLink)(A, B); +endfig; + +beginfig(6); + Class.A("A")()(); + Class.B("B")()(); + + Package.pA("net.foo")(); + Package.pB("net.foo.bar")(A, B); + + leftToRight(20)(A, B); + leftToRight(50)(pA, pB); + + drawObjects(A, B, pA, pB); + + clink(nest)(pB, pA); +endfig; + +beginfig(7); + save A; + + Class.A("MyClass") + ("attr1: int", "attr2: int") + ("method1(): void", + "method2(): void"); + + A.nw = (0, 0); % optional, implied + drawObject(A); +endfig; + +beginfig(8); + save A, B; + Class.A("A")()(); + Class.B("B")()(); + + A.nw = (0,0); + B.w = A.e + (20, 0); + + drawObjects(A, B); +endfig; + +beginfig(9); + save A, B; + + Class.A("A")()(); + Class.B("B")()(); + B.w = A.e + (20, 0); + drawObjects(A, B); + link(inheritance)(B.w -- A.e); +endfig; +end + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/boxes_vs_util.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/boxes_vs_util.mp new file mode 100644 index 0000000000..985c9bb158 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/boxes_vs_util.mp @@ -0,0 +1,92 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input boxes; +input util_commons; +input util_object; +input util_picture; + +beginfig(1); + boxit.a ("yummy"); + boxit.b ("cool"); + + a.nw = (0,0); + b.sw = a.se + (10,0); + + drawboxed (a, b); + draw a.sw -- b.se dashed evenly withpen pencircle scaled 1.1; + + boxit.c ("yummy"); + boxit.d ("cool"); + + c.nw = (0,-20); + d.sw = c.se + (10,0); + + drawunboxed (c, d); + draw c.sw -- d.se dashed evenly withpen pencircle scaled 1.1; +endfig; + +beginfig(2); + save a, b, c, d; + + Picture.a("yummy"); + Picture.b("cool"); + a.info.boxed := b.info.boxed := 1; + + a.nw = (0,0); + b.sw = a.se + (10,0); + + drawObjects(a, b); + draw a.sw -- b.se dashed evenly withpen pencircle scaled 1.1; + + Picture.c("yummy"); + Picture.d("cool"); + + c.nw = (0,-20); + d.sw = c.se + (10,0); + + drawObjects(c, d); + draw c.sw -- d.se dashed evenly withpen pencircle scaled 1.1; +endfig; + +beginfig(3); + save a, b, c, d; + + iPict.ignoreNegativeBase := 1; + + Picture.a("yummy"); + Picture.b("cool"); + a.info.boxed := b.info.boxed := 1; + + a.nw = (0,0); + b.sw = a.se + (10,0); + + drawObjects(a, b); + draw a.sw -- b.se dashed evenly withpen pencircle scaled 1.1; + + Picture.c("yummy"); + Picture.d("cool"); + + c.nw = (0,-20); + d.sw = c.se + (10,0); + + drawObjects(c, d); + draw c.sw -- d.se dashed evenly withpen pencircle scaled 1.1; +endfig; + + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class.mp new file mode 100644 index 0000000000..e5d03d3d43 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class.mp @@ -0,0 +1,134 @@ +% Sample MetaUML figures. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +input metauml; + +beginfig(1); + Class.A("Point") + ("#x:int", + "#y:int") + ("+set(x:int, y:int)", + "+getX():int", + "+getY():int", + "-debug():void", + "test():void"); + drawObject(A); +endfig; + +beginfig(2); + save A, T; + + Class.A("User")()(); + Class_stereotypes.A("<<interface>>", "<<home>>"); + + drawObject(A); +endfig; + +beginfig(3); + save A, T; + + Class.A("Vector")()(); + ClassTemplate.T("T", "size: int")(A); + + drawObjects(A, T); +endfig; + +beginfig(4); + link(association)( (0,0) -- (50,0) ); +endfig; + +beginfig(5); + link(associationUni)( (0,0) -- (50,0) ); +endfig; + +beginfig(6); + link(inheritance)( (0,0) -- (50,0) ); +endfig; + +beginfig(7); + link(aggregation)( (0,0) -- (50,0) ); +endfig; + +beginfig(8); + link(aggregationUni)( (0,0) -- (50,0) ); +endfig; + +beginfig(9); + link(composition)( (0,0) -- (50,0) ); +endfig; + +beginfig(10); + link(compositionUni)( (0,0) -- (50,0) ); +endfig; + +beginfig(11); + save A; + Interface.A("Observer") + ("+update(src:Object)"); + + drawObject(A); +endfig; + +beginfig(12); + save A; + EClass.A(iAbstractClass)("Observable") + ("observers: Observer[0..*]") + ("+addObserver(o: Observer)", + "+notify()"); + + drawObject(A); +endfig; + +beginfig(13) + save A; + + Class.A("MyModel")()(); + A.info.iName.top := 10; + A.info.iName.bottom := 10; + A.info.iAttributeStack.top := 0; + A.info.iAttributeStack.bottom := 0; + A.info.iMethodStack.top := 0; + A.info.iMethodStack.bottom := 0; + + drawObject(A); +endfig; + +beginfig(14) + save A, B; + + EClass.A(iClassNameOnly)("MyModel")()(); + ClassName.B("AnotherModel"); + classStereotypes.B("<<smart>>"); + + topToBottom(20)(A, B); + + drawObjects(A, B); +endfig; + +beginfig(15); + save A; + + Class.A("Point") + ("#x:int", "#y:int") + ("+toString():String"); + Class_noVisibilityMarkers.A; + + drawObject(A); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_association.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_association.mp new file mode 100644 index 0000000000..2ff5037a8c --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_association.mp @@ -0,0 +1,72 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + save P,B; + + Class.P("Person")()(); + Class.B("Bank")()(); + + P.nw = (0,0); + B.w = P.e + (50,0); + + drawObjects(P, B); + + drawRelation(association)(P.e -- B.w); + + item.assocName(iAssoc)("works for")(assocName.s = .5[P.e,B.w]); + + draw assocName.n -- (assocName.n + (20,20)); + label.urt("association name" infont "tyxtt", assocName.n + (20,20)); +endfig; + +beginfig(2); + save P,C; + + Class.P("Person")()(); + Class.C("Company")()(); + + C.n = P.s + (0, -70); + drawObjects(P, C); + + link(association)(P.s -- C.n); + + item(iAssoc)("employee")(obj.nw = P.s); + item(iAssoc)("1..*")(obj.ne = P.s); + + item(iAssoc)("employer")(obj.sw = C.n); + item(iAssoc)("0..*")(obj.se = C.n); + + item(iAssoc)("works for")(obj.w = .5[P.s,C.n]); +endfig; + +beginfig(3); + save F, O; + + Class.F("Factory")()(); + Class.O("Object")()(); + + O.n = F.s - (0, 50); + drawObjects(F, O); + + clink(dependency)(F, O); + item(iStereo)("<<creates>>")(obj.w = .5[F.s,O.n]) +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_customization.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_customization.mp new file mode 100644 index 0000000000..980915ea00 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_customization.mp @@ -0,0 +1,94 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + iClass.foreColor := (.9, .9, 0); + + Class.A("A")()(); + Class.B("B")()(); + Class.C("C")()(); + + B.w = A.e + (20,0); + C.n = .5[A.se, B.sw] + (0, -10); + + drawObjects(A, B, C); +endfig; + +beginfig(2); + save A, B, C; + iClass.foreColor := (.9, .9, 0); + + Class.A("A")()(); + Class.B("B")()(); + Class.C("C")()(); + C.info.foreColor := (.7, .7, .9); + C.info.borderColor := blue; + C.info.iName.iFont.scale := 2; + + B.w = A.e + (20,0); + C.n = .5[A.se, B.sw] + (0, -10); + + drawObjects(A, B, C); +endfig; + +beginfig(3); + ClassInfoCopy.iHome(iClass); + iHome.foreColor := (0, .9, .9); + + ClassInfo.iRemote; + iRemote.foreColor := (.9, .9, 0); + iRemote.borderColor := (0, 0, .9); + + save A, B, C, D; + + EClass.A(iHome)("UserHome")()(); + EClass.B(iRemote)("UserRemote")()(); + EClass.C(iHome)("CartHome")()(); + EClass.D(iRemote)("CartRemote")()(); + + + B.nw = A.ne + (20,0); + D.nw = C.ne + (20,0); + A.bottom - C.top = 10; + A.left = C.left; + + drawObjects(A, B, C, D); +endfig; + +beginfig(4); + iClass.foreColor := .9white; + save A; + + Class.A("Foo") + ("a: int", "b: int") + ("foo()", "bar()", "gar()"); + A.info.iName.iFont.name := metauml_defaultFontBold; + A.info.iName.iFont.scale := 1.2; + + A.info.iAttributeStack.iPict.iFont.scale := 0.8; + A.info.iAttributeStack.top := 10; + A.info.iAttributeStack.spacing := 11; + + A.info.iMethodStack.iPict.iFont.scale := 2; + A.info.iMethodStack.spacing := 17; + A.info.iMethodStack.bottom := 10; + drawObject(A); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_customization2.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_customization2.mp new file mode 100644 index 0000000000..be45e95240 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_customization2.mp @@ -0,0 +1,31 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + save Test; + Class.Test("TestClass")("attribute1: int","attribute2: double") + ("oneLongMethod(): void", + "anotherLongMethod(): void"); + + Test.nw = (0,0); + Class_draw.Test; +endfig; + + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_diagrams.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_diagrams.mp new file mode 100644 index 0000000000..614cdbeca6 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_diagrams.mp @@ -0,0 +1,212 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + Class.Count("Count") + ("#n: int") + ("+increase(): void", + "+get(): int"); + + %Count.nw = (0,0); + drawObject(Count); + %Class_draw.Count; +endfig; + +beginfig(2); + Class.A("Point") + ("+x: int", + "+y: int") (); + + Class.B("Circle") + ("radius: int") + ("+getRadius(): int", + "+setRadius(r: int):void"); + + A.nw = (0,0); + B.n = A.s - (0,45); + Class_draw.A; + Class_draw.B; + + drawRelation(aggregationUni)(A.s -- B.n); +endfig; + +beginfig(3); + Class.Test("Test")("a1","a2","a3")("aLongMethod():void"); + + Test.nw = (0,0); + Class_draw.Test; + + dotlabel.ulft(btex nw etex, Test.nw); + dotlabel.top(btex n etex, Test.n); + dotlabel.urt(btex ne etex, Test.ne); + dotlabel.rt(btex e etex, Test.e); + dotlabel.lrt(btex se etex, Test.se); + dotlabel.bot(btex s etex, Test.s); + dotlabel.llft(btex sw etex, Test.sw); + dotlabel.lft(btex w etex, Test.w); + + dotlabel.lft(btex c etex, Test.c); + + draw Test.nw - (50,0) -- Test.ne + (10,0); + label.urt(btex top etex, Test.nw - (50,0)); + + draw Test.sw - (50,0) -- Test.se + (10,0); + label.lrt(btex bottom etex, Test.sw - (50,0)); + + draw Test.nw + (0,10) -- Test.sw - (0, 50); + label.bot(btex left etex, Test.sw - (0,50)); + + draw Test.ne + (0,10) -- Test.se - (0, 50); + label.bot(btex right etex, Test.se - (0,50)); + + drawarrow Test.nw - (25,0) -- Test.sw - (25,0); + label.lft(btex height etex, .5[Test.nw, Test.sw] - (25,0)); + + drawarrow Test.sw - (0,25) -- Test.se - (0,25); + label.bot(btex width etex, .5[Test.sw, Test.se] - (0,25)); +endfig; + +%newAssociationDescription.association; +%newAssociationUniDescription.associationUni; +%newInheritanceDescription.inheritance; +%newAggregationDescription.aggregation; +%newAggregationUniDescription.aggregationUni; +%newCompositionDescription.composition; +%newCompositionUniDescription.compositionUni; +%newDashedLinkDescription.dashedLink; +%newDependencyDescription.dependency; + +beginfig(4); + save X, Y; + Class.X("X")()(); + Class.Y("Y")()(); + + X.nw = (0,0); + Y.w = X.e + (50,0); + Class_draw.X; + Class_draw.Y; + + drawRelation(association)(X.e -- Y.w); +endfig; + +beginfig(5); + save X, Y; + Class.X("X")()(); + Class.Y("Y")()(); + + X.nw = (0,0); + Y.w = X.e + (50,0); + Class_draw.X; + Class_draw.Y; + + drawRelation(associationUni)(X.e -- Y.w); +endfig; + +beginfig(6); + save X, Y; + Class.X("X")()(); + Class.Y("Y")()(); + + X.nw = (0,0); + Y.w = X.e + (50,0); + Class_draw.X; + Class_draw.Y; + + drawRelation(inheritance)(X.e -- Y.w); +endfig; + +beginfig(7); + save X, Y; + Class.X("X")()(); + Class.Y("Y")()(); + + X.nw = (0,0); + Y.w = X.e + (50,0); + Class_draw.X; + Class_draw.Y; + + drawRelation(aggregation)(X.e -- Y.w); +endfig; + +beginfig(8); + save X, Y; + Class.X("X")()(); + Class.Y("Y")()(); + + X.nw = (0,0); + Y.w = X.e + (50,0); + Class_draw.X; + Class_draw.Y; + + drawRelation(aggregationUni)(X.e -- Y.w); +endfig; + +beginfig(9); + save X, Y; + Class.X("X")()(); + Class.Y("Y")()(); + + X.nw = (0,0); + Y.w = X.e + (50,0); + Class_draw.X; + Class_draw.Y; + + drawRelation(composition)(X.e -- Y.w); +endfig; + +beginfig(10); + save X, Y; + Class.X("X")()(); + Class.Y("Y")()(); + + X.nw = (0,0); + Y.w = X.e + (50,0); + Class_draw.X; + Class_draw.Y; + + drawRelation(compositionUni)(X.e -- Y.w); +endfig; + +beginfig(11); + save X, Y; + Class.X("X")()(); + Class.Y("Y")()(); + + X.nw = (0,0); + Y.w = X.e + (50,0); + Class_draw.X; + Class_draw.Y; + + drawRelation(dependency)(X.e -- Y.w); +endfig; + +beginfig(12); + save X, Y; + Class.X("X")()(); + Class.Y("Y")()(); + + X.nw = (0,0); + Y.w = X.e + (50,0); + Class_draw.X; + Class_draw.Y; + + drawRelation(realization)(X.e -- Y.w); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_templates.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_templates.mp new file mode 100644 index 0000000000..bf89f9d3cd --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/class_templates.mp @@ -0,0 +1,29 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + Class.V("Vector")("elements: T(n)")(); + Template.T("T", "n: int"); + Template_attachToClass.T(V); + + drawObjects(V); + drawObjects(T); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/component.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/component.mp new file mode 100644 index 0000000000..da46c9d346 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/component.mp @@ -0,0 +1,61 @@ +input metauml; + +beginfig(1); + Component.C("Business Logic")(); + drawObject(C); +endfig; + +beginfig(2); + save A, B, C, BigC; + + Class.A("A")()(); + Package.B("B")(); + Component.C("C")(); + + Component.BigC("Big Component")(A, B, C); + + leftToRight(10)(A, B); + topToBottom(10)(A, C); + + drawObject(BigC); +endfig; + +beginfig(3); + save A, B; + Component.A("A")(); + Component.B("B")(); + + leftToRight(80)(A, B); + + drawObjects(A, B); + + link(providedInterface)( A.e -- .5[A.e, B.w] ); +endfig; + +beginfig(4); + save A, B; + Component.A("A")(); + Component.B("B")(); + + leftToRight(80)(A, B); + + drawObjects(A, B); + + link(requiredInterface)( B.w -- .5[A.e, B.w]); +endfig; + +beginfig(5); + save A, B; + Component.A("A")(); + Component.B("B")(); + + leftToRight(80)(A, B); + + drawObjects(A, B); + + link(providedInterface)( A.e -- .5[A.e, B.w] ); + link(requiredInterface)( B.w -- .5[A.e, B.w] ); +endfig; + + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/group.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/group.mp new file mode 100644 index 0000000000..0e25e58ea6 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/group.mp @@ -0,0 +1,51 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input boxes; +input util_commons; +input util_object; +input util_picture; +input util_margins; +input util_group; + +beginfig(1); + iGroup.left:=20; + iGroup.right:=15; + iGroup.boxed:=1; + iPict.boxed:=1; + + Picture.a("yummy"); + Picture.b("cool"); + Picture.c("fool"); + + a.nw = (0,0); + b.nw = (20,20); + c.nw = (15, 40); + + Group.g(a, b, c); + + drawObjects(g); +endfig; + +beginfig(2); +endfig; + +beginfig(3); +endfig; + + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/how-links-work.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/how-links-work.mp new file mode 100644 index 0000000000..c8d8500358 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/how-links-work.mp @@ -0,0 +1,38 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + drawRelation(aggregationUni) + ((0,0)--(40,0)); +endfig; + + +beginfig(2); + path myPath; + myPath := (0,0) -- (100,0); + LinkStructure.ls(myPath, + aggregationUni.widthA, + aggregationUni.widthB); + + describeLinkStructure(ls); + drawLinkStructure(ls)(aggregationUni); +endfig; + +end + diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/instance.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/instance.mp new file mode 100644 index 0000000000..9417224306 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/instance.mp @@ -0,0 +1,9 @@ +input metauml; + +beginfig(1); + Instance.order("o: Order") + ("name='book'", "{placed}", "{payed}"); + drawObject(order); +endfig; + +end
\ No newline at end of file diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/mptextmp.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/mptextmp.mp new file mode 100644 index 0000000000..3e16f83e56 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/mptextmp.mp @@ -0,0 +1 @@ +btex But this is insane: $\sum_1^3 f(x) \over x$! etex diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/note.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/note.mp new file mode 100644 index 0000000000..f04a5b5e4f --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/note.mp @@ -0,0 +1,74 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; +input TEX; + +beginfig(1); + Note.A("This note", "has two lines."); + drawObject(A); +endfig; + +beginfig(2); + save A, C; + Note.A("This is a class"); + Class.C("Object")()(); + + A.sw = C.ne + (20, 20); + + drawObjects(A, C); + + clink(dashedLink)(A, C); +endfig; + +beginfig(3); + save C; + Note.nA("This is the class name"); + Note.nB("This is a key attribute"); + Note.nC("This is a nice method"); + + Class.C("Object")("+id:int") + ("+clone()", "+serialize()"); + + topToBottom.left(10)(nA, nB, nC); + leftToRight(10)(C, nB); + + drawObjects(C, nA, nB, nC); + + clink(dashedLink)(C.namePict, nA); + clink(dashedLink)(C.attributeStack.pict[0], nB); + clink(dashedLink)(C.methodStack.pict[1], nC); +endfig; + +beginfig(4); + save A; + Note.A("This class implements the formula:", + TEX("$\sum_1^n f(x)\cdot dx$")); + drawObjects(A); +endfig; + +beginfig(5); + save A; + Note.A("Can you do it?", + TEX("$\sum_1^n f(x) \cdot dx " & + "\over \sum_1^m g(y) \cdot dy$")); + A.stack.info.spacing := 30; + A.stack.pict[1].info.ignoreNegativeBase := 0; + drawObjects(A); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/object_stack.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/object_stack.mp new file mode 100644 index 0000000000..b9cd4d32b3 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/object_stack.mp @@ -0,0 +1,46 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input boxes; +input util_commons; +input util_object; +input util_picture; + + +beginfig(1); + iPict.ignoreNegativeBase := 1; + iPict.boxed := 1; + Picture.a0("yummy"); + Picture.a1("cool"); + Picture.a2("fool"); + + a0.nw = (0,0); + setObjectJoin(pa.sw = pb.nw); + + joinObjects(scantokens listArray(a)(3)); + drawObjects(scantokens listArray(a)(3)); + +endfig; + +beginfig(2); +endfig; + +beginfig(3); +endfig; + + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/package.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/package.mp new file mode 100644 index 0000000000..88653b5fee --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/package.mp @@ -0,0 +1,93 @@ +input metauml; +input metauml_package; +input metauml_package_relations; + +beginfig(1); + Package.P("java.lang")(); + drawObject(P); +endfig; + +beginfig(2); + save P; + Package.P("An important", "package")(); + drawObject(P); +endfig; + +beginfig(3); + save P; + Package.P("java.lang")(); + P.info.forceEmptyContent := 1; + drawObject(P); +endfig; + +beginfig(4); + save P, A, B; + Class.A("A")()(); + Class.B("B")()(); + Package.P("net.metauml")(A, B); + + leftToRight(10)(A, B); + + drawObject(P); +endfig; + +beginfig(5); + Package.X("X")(); + Package.Y("Y")(); + + leftToRight(50)(X, Y); + drawObjects(X, Y); + + link(nest)(X.e -- Y.w); +endfig; + +beginfig(8); + Package.emptyPackage("")(); + + Package.nameOnlyPackage("java.sun.com")(); + + Class.oneClass("A class")()(); + Package.oneClassPackage("One class package")(oneClass); + + Instance.oneInstance("An instance")(); + State.oneState("A state")(); + Activity.oneActivity("An activity"); + Package.multiPackage("Multipackage")(oneInstance, oneState, oneActivity); + + Package.allPackage("This package contains them all")(emptyPackage, nameOnlyPackage, + oneClassPackage, multiPackage); + + nameOnlyPackage.nw = emptyPackage.ne + (30, 0); + oneClassPackage.ne = emptyPackage.s - (0, 50); + + multiPackage.top = oneClassPackage.top; + multiPackage.left = oneClassPackage.right + 20; + + centered_align_top(oneState, oneActivity)(10, below(oneInstance.s, 20)); + + drawObjects(allPackage); +endfig; + +beginfig(8); + Package.nameOnlyOnTopPackage("Name on top")(); + nameOnlyOnTopPackage.info.forceEmptyContent := 1; + Package.nameOnlyInMiddlePackage("By default name", "is in the middle")(); + + Class.cl("A class")("Attribute")("Method"); + Package.notEmptyPackage("Contains class")(cl); + + nameOnlyInMiddlePackage.n = nameOnlyOnTopPackage.s - (0, 40); + notEmptyPackage.w = nameOnlyInMiddlePackage.e + (80, 0); + drawObjects(nameOnlyOnTopPackage, nameOnlyInMiddlePackage, notEmptyPackage); + + %link(import)(pathStepX(notEmptyPackage.w, nameOnlyOnTopPackage.e, -30)); + %link(import)(pathVertical(nameOnlyInMiddlePackage.ne - (10, 0), nameOnlyOnTopPackage.bottom)); + %link(import)(notEmptyPackage.sw -- nameOnlyInMiddlePackage.ne); +endfig; + +beginfig(8); + link(nest)((10,10)--(30,30)); +endfig; + + +end
\ No newline at end of file diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/paths.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/paths.mp new file mode 100644 index 0000000000..06ca576120 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/paths.mp @@ -0,0 +1,132 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + pair za, zb; + za = (10,10); + zb = (10,-5); + path cool; + cool := za .. za+(20,10) .. + zb+(20,-20) .. + zb+(-10,-30) -- zb; + link(aggregationUni)(cool); +endfig; + +beginfig(2); + save A, B; + Class.A("A")()(); + Class.B("B")()(); + + B.sw = A.ne + (10,10); + + drawObjects(A, B); + + link(aggregationUni) + (rpathManhattanX(A.e, B.s)); + link(inheritance) + (pathManhattanY(A.n, B.w)); +endfig; + +beginfig(3); + save A, B; + Class.A("A")()(); + Class.B("B")()(); + + B.sw = A.ne + (10,10); + + drawObjects(A, B); + + stepX:=60; + link(aggregationUni) + (pathStepX(A.e, B.e, stepX)); + + stepY:=20; + link(inheritance) + (pathStepY(B.n, A.n, stepY)); + + pair X,Y; + X := A.se + (0,-30); + Y := X + (stepX, 0); + draw A.se -- X dashed evenly; + draw (xpart Y, ypart A.e) -- Y dashed evenly; + drawdblarrow X + (0,15) -- Y + (0,15); + label.top(btex stepX etex, .5[X,Y]); + + pair X,Y; + X := B.n + (-70,-0); + Y := X + (0, stepY); + + draw B.n -- X dashed evenly; + draw B.n + (0,stepY) -- Y dashed evenly; + drawdblarrow X + (15,0) -- Y + (15,0); + label.lft(btex stepY etex, .5[X,Y]); +endfig; + +% horizontal, vertical +beginfig(4); + save A, B; + Class.A("A")()(); + Class.B("B")("b")(); + Class.C("C")("foo: int")(); + + B.sw = A.se + (30,5); + C.sw = A.nw + (0, 30); + + drawObjects(A, B, C); + + untilX := B.left; + drawRelation(association) + (pathHorizontal(A.e, untilX)); + + draw B.nw -- B.sw + (0,-10) dashed evenly; + label.bot(btex untilX etex, B.sw + (0,-10)); + + untilY:= C.bottom; + drawRelation(association)(pathVertical(A.n, untilY)); + + draw C.sw -- C.sw + (-20,0) dashed evenly; + label.lft(btex untilY etex, C.sw + (-20,-0)); + +endfig; + +beginfig(5); + save A,B; + Activity.A("A"); + Activity.B("B"); + + B.nw = A.ne + (40,30); + drawObjects(A,B); + + z = A.se + (30, -10); + link(transition)(pathCut(A, B) + (A.c -- z -- B.c)); +endfig; + +beginfig(6); + save A,B; + Class.A("A")()(); + Class.B("B")()(); + + B.nw = A.ne + (20,30); + drawObjects(A,B); + + clink(inheritance)(A, B); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/paths_man.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/paths_man.mp new file mode 100644 index 0000000000..a6c502f147 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/paths_man.mp @@ -0,0 +1,143 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + save A, B; + Class.A("A")("foo:int")("bar()"); + Class.B("B")()(); + + A.nw = (0,0); + B.s = A.ne + (30,30); + + Class_draw.A; + Class_draw.B; + + drawRelation(aggregationUni) + (A.n ..(30,30)..B.w); + path cool; + cool := A.e .. A.e+(20,10) .. + B.s+(20,-40) .. B.s+(-10,-30) + -- B.s; + drawRelation(inheritance)(cool); +endfig; + +beginfig(2); + save A, B; + Class.A("A")()(); + Class.B("B")()(); + + A.nw = (0,0); + B.sw = A.ne + (10,10); + + Class_draw.A; + Class_draw.B; + + drawRelation(aggregationUni) + (pathManhattanX(A.e, B.s)); + drawRelation(inheritance) + (pathManhattanY(A.n, B.w)); +endfig; + +beginfig(3); + save A, B; + Class.A("A")()(); + Class.B("B")()(); + + A.nw = (0,0); + B.sw = A.ne + (10,10); + + Class_draw.A; + Class_draw.B; + + stepX:=60; + drawRelation(aggregationUni) + (pathStepX(A.e, B.e, stepX)); + + stepY:=20; + drawRelation(inheritance) + (pathStepY(B.n, A.n, stepY)); + + pair X,Y; + X := A.se + (0,-30); + Y := X + (stepX, 0); + draw A.se -- X dashed evenly; + draw (xpart Y, ypart A.e) -- Y dashed evenly; + drawdblarrow X + (0,15) -- Y + (0,15); + label.top(btex stepX etex, .5[X,Y]); + + pair X,Y; + X := B.n + (-70,-0); + Y := X + (0, stepY); + + draw B.n -- X dashed evenly; + draw B.n + (0,stepY) -- Y dashed evenly; + drawdblarrow X + (15,0) -- Y + (15,0); + label.lft(btex stepY etex, .5[X,Y]); +endfig; + +beginfig(4); + save A, B; + Class.A("A")()(); + Class.B("B")("a")(); + + A.nw = (0,0); + B.sw = A.se + (30,5); + + Class_draw.A; + Class_draw.B; + + untilX := B.left; + drawRelation(association) + (pathHorizontal(A.e, untilX)); + + draw B.nw -- B.sw + (0,-10) dashed evenly; + label.bot(btex untilX etex, B.sw + (0,-10)); +endfig; + +beginfig(5); + save A, B; + Class.A("A")()(); + Class.B("B")("a")("foo()"); + + A.nw = (0,0); + B.sw = A.ne + (-20,20); + + Class_draw.A; + Class_draw.B; + + untilY:= B.bottom; + drawRelation(association) + (pathVertical(A.n, untilY)); + + draw B.sw -- B.sw + (-20,0) dashed evenly; + label.lft(btex untilY etex, B.sw + (-20,-0)); +endfig; + +beginfig(6); + save A,B; + Class.A("A")()(); + Class.B("B")()(); + + B.nw = A.ne + (40,30); + drawObjects(A,B); + + link(inheritance)(pathCut(A,B)(A.c -- B.c)); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/picture_info.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/picture_info.mp new file mode 100644 index 0000000000..df3b10145f --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/picture_info.mp @@ -0,0 +1,86 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input boxes; +input util_commons; +input util_object; +input util_picture; +input util_positioning; + +PictureInfoCopy.iBig(iPict); +iBig.left := iBig.right := 20; +iBig.top := 10; +iBig.bottom := 1; +iBig.boxed := 1; +iBig.ignoreNegativeBase := 1; +iBig.iFont.name := defaultfont; +iBig.iFont.scale := 3; + +PictureInfoCopy.iSmall(iPict); +iSmall.boxed := 1; +iSmall.borderColor := green; + +beginfig(1); + EPicture.a(iBig)("yummy"); + EPicture.b(iSmall)("cool"); +% you can still modify a.info +% and b.info if you wish. + + a.nw = (0,0); + b.nw = a.sw + (0,-10); + + drawObjects(a, b) +endfig; + +beginfig(2); + save a, b, c, myFixed; + PictureInfoCopy.myFixed(iPict); + myFixed.ignoreNegativeBase := 1; + myFixed.fixedWidth := 15; + myFixed.fixedHeight := 20; + myFixed.boxed := 1; + + EPicture.a(myFixed)("a"); + EPicture.b(myFixed)(".-."); + EPicture.c(myFixed)("toolong"); + + leftToRight.bottom(10)(a, b, c); + + drawObjects(a, b, c); +endfig; + +beginfig(3); + save a, b, c, myFixed; + PictureInfoCopy.myFixed(iPict); + myFixed.ignoreNegativeBase := 1; + myFixed.bottom := 4.5; + myFixed.valign := "bottom"; + myFixed.halign := "center"; + myFixed.fixedWidth := 25; + myFixed.fixedHeight := 15; + myFixed.boxed := 1; + + EPicture.a(myFixed)("a"); + EPicture.b(myFixed)("yum"); + EPicture.c(myFixed)("b"); + + leftToRight.bottom(10)(a, b, c); + + drawObjects(a, b, c); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/picture_stack.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/picture_stack.mp new file mode 100644 index 0000000000..ee6e09104b --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/picture_stack.mp @@ -0,0 +1,44 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input boxes; +input util_commons; +input util_object; +input util_picture; +input util_group; +input util_picture_stack; + +beginfig(1); + iStack.boxed := 1; + iStack.iPict.boxed := 1; + PictureStack.myStack("foo", + "bar: int" infont "tyxtt", + "cool-man-centered" infont defaultfont, + "nice")("vcenter"); + + myStack.nw = (0,0); + drawObject(myStack); +endfig; + +beginfig(2); +endfig; + +beginfig(3); +endfig; + + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/positioning.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/positioning.mp new file mode 100644 index 0000000000..f98de47182 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/positioning.mp @@ -0,0 +1,139 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + Class.A("A")()(); + Class.B("B")()(); + Class.C("C")()(); + Class.Base("Base")()(); + + + A.ne = B.nw - (20,0); + B.ne = C.nw - (20,0); + Base.s = B.n + (0,20); + + drawObjects(Base, A, B, C); +endfig; + +beginfig(2); + save A, B, C, Base; + + Class.A("A")()(); + Class.B("B")()(); + Class.C("C")()(); + Class.Base("Base")()(); + + leftToRight(20)(A, B, C); + topToBottom(20)(Base, B); + + drawObjects(Base, A, B, C); +endfig; + +iPict.boxed := 1; +spacing := 5; +string strA, strB, strC; +strA := "a"; +strB := "..."; +strC := "Cyan"; + +beginfig(3); + save A, B, C, X, Y, Z; + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + leftToRight.top(spacing)(X, Y, Z); + + drawObjects(X, Y, Z); + + draw (X.left, X.top) -- (Z.right, X.top) dashed evenly withpen pencircle withcolor red; +endfig; + +beginfig(4); + save A, B, C, X, Y, Z; + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + leftToRight.midy(spacing)(X, Y, Z); + + drawObjects(X, Y, Z); + + draw (X.left, X.midy) -- (Z.right, X.midy) dashed evenly withpen pencircle withcolor red;; +endfig; + +beginfig(5); + save A, B, C, X, Y, Z; + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + leftToRight.bottom(spacing)(X, Y, Z); + + drawObjects(X, Y, Z); + + draw (X.left, X.bottom) -- (Z.right, X.bottom) dashed evenly withpen pencircle withcolor red;; +endfig; + +beginfig(6); + save A, B, C, X, Y, Z; + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + topToBottom.left(spacing)(X, Y, Z); + + drawObjects(X, Y, Z); + + draw (X.left, X.top) -- (X.left, Z.bottom) dashed evenly withpen pencircle withcolor red;; +endfig; + +beginfig(7); + save A, B, C, X, Y, Z; + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + topToBottom.midx(spacing)(X, Y, Z); + + drawObjects(X, Y, Z); + + draw (X.midx, X.top) -- (X.midx, Z.bottom) dashed evenly withpen pencircle withcolor red;; +endfig; + +beginfig(8); + save A, B, C, X, Y, Z; + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + topToBottom.right(spacing)(X, Y, Z); + + drawObjects(X, Y, Z); + + draw (X.right, X.top) -- (X.right, Z.bottom) dashed evenly withpen pencircle withcolor red;; +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/properties.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/properties.mp new file mode 100644 index 0000000000..94f71d772e --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/properties.mp @@ -0,0 +1,58 @@ +% Sample MetaUML figures. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +input metauml; + +beginfig(1); + Class.Test("Test")("a1","a2","a3")("aLongMethod():void"); + + Test.nw = (0,0); + Class_draw.Test; + + dotlabel.ulft(btex nw etex, Test.nw); + dotlabel.top(btex n etex, Test.n); + dotlabel.urt(btex ne etex, Test.ne); + dotlabel.rt(btex e etex, Test.e); + dotlabel.lrt(btex se etex, Test.se); + dotlabel.bot(btex s etex, Test.s); + dotlabel.llft(btex sw etex, Test.sw); + dotlabel.lft(btex w etex, Test.w); + + dotlabel.lft(btex c etex, Test.c); + + draw Test.nw - (50,0) -- Test.ne + (10,0); + label.urt(btex top etex, Test.nw - (50,0)); + + draw Test.sw - (50,0) -- Test.se + (10,0); + label.lrt(btex bottom etex, Test.sw - (50,0)); + + draw Test.nw + (0,10) -- Test.sw - (0, 50); + label.bot(btex left etex, Test.sw - (0,50)); + + draw Test.ne + (0,10) -- Test.se - (0, 50); + label.bot(btex right etex, Test.se - (0,50)); + + drawarrow Test.nw - (25,0) -- Test.sw - (25,0); + label.lft(btex height etex, .5[Test.nw, Test.sw] - (25,0)); + + drawarrow Test.sw - (0,25) -- Test.se - (0,25); + label.bot(btex width etex, .5[Test.sw, Test.se] - (0,25)); +endfig; + + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/state.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/state.mp new file mode 100644 index 0000000000..77c7691a9a --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/state.mp @@ -0,0 +1,55 @@ +% Sample MetaUML figures. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +input metauml; + +beginfig(1); + State.s("Take order")(); + drawObject(s); +endfig; + +beginfig(2); + Begin.b; + End.e; + State.c("Component")(); + State.composite("Composite")(b, e, c); + + b.midx = e.midx = c.midx; + c.top = b.bottom - 20; + e.top = c.bottom - 20; + + composite.info.drawNameLine := 1; + drawObject(composite); + + link(transition)(b.s -- c.n); + link(transition)(c.s -- e.n); +endfig; + +beginfig(3); + save s; + State.s("An interesting state", + "which is worth mentioning")(); + stateTransitions.s( + "OnEntry / Open eyes", + "OnExit / Sleep well"); + s.info.drawNameLine := 1; + + drawObject(s); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/statemachine_diagrams.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/statemachine_diagrams.mp new file mode 100644 index 0000000000..ff93a74dd5 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/statemachine_diagrams.mp @@ -0,0 +1,78 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +% for f in `find . | grep '.*\.[1-9]'`; do echo $f; done + +input metauml; + +beginfig(1); + Begin.b; + State.on("On")(); + State.off("Off")(); + End.e; + + setObjectJoin(pb.w = pa.e + (20,0)); + joinObjects(b, on, off, e); + drawObjects(b, on, off, e); + + clink(transition)(b, on); + clink(transition)(on, off); + clink(transition)(off, e); +endfig; + +beginfig(2); + save b, reading, processing, e, exit; + + Begin.b; + State.reading("Commands read")(); + State.processing("Processing commands")(); + End.e; + setObjectJoin(pb.n = pa.s + (0, -20)); + joinObjects(b, reading, processing, e); + + State.composite("Work")(b, reading, processing, e); + drawObject(composite); + + clink(transition)(b, reading); + clink(transition)(reading, processing); + clink(transition)(processing, e); + + ExitPoint.exit; + exit.c=(composite.right, reading.midy); + drawObject(exit); + item(iAssoc)("error")(obj.nw = exit.s); + + clink(transition)(reading, exit); + + State.error("Prepare error report")(); + State.result("Display result")(); + End.theEnd; + + error.midx = result.midx = theEnd.midx = composite.right + 90; + error.midy = exit.midy; + result.midy = processing.midy; + theEnd.midy = e.midy; + drawObjects(error, result, theEnd); + + clink(transition)(exit, error); + clink(transition)(error, result); + clink(transition)(result, theEnd); + + link(transition)(rpathHorizontal(result.w, composite.right)); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_activity.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_activity.mp new file mode 100644 index 0000000000..841bdb8a31 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_activity.mp @@ -0,0 +1,46 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + Begin.b; + End.e; + + e.n = (30,30); + drawObject(b); + show "Object b drawn"; + drawObject(e); + + link(associationUni)(pathCut(b,e)(b.c--e.c)); +endfig; + +beginfig(2); + EActivity.act(iActivity)("go to school", "while singing"); + drawObject(act); + + Branch.br; + br.nw = (50,50); + drawObject(br); + + Fork.fork("h",30); + fork.nw = (30,70); + drawObject(fork); +endfig; + +end + diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class.mp new file mode 100644 index 0000000000..94e1fdc130 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class.mp @@ -0,0 +1,156 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(0); + show "Copying class info..."; + ClassInfoCopy.foo(iClass); +endfig; + +beginfig(1); + Class.A("A")()(); + Class_setDebugMode.A; + + A.nw=(0,0); + Class_draw.A; +endfig; + +beginfig(2); + save B; + Class.B("B")("+ a:int")(); + Class_setDebugMode.B; + + B.nw=(0,0); + Class_draw.B; +endfig; + +beginfig(3); + save C; + Class.C("C")("+ a-#~+:int", "- b-#~+:int", "- g-#~+:int", "~ c-#~+:int", "# g-#~+:double")(); + Class_setDebugMode.C; + + C.nw=(0,0); + Class_draw.C; +endfig; + +beginfig(4); + save D; + Class.D("D") + ("+ a-#~+:int", "- b-#~+:int", "- g-#~+:int", "~ c-#~+:int", "# g-#~+:double") + ("+ a()-#~+:int", "- b()-#~+:int", "- g()-#~+:int", "~ c()-#~+:int", "# g()-#~+:double"); + Class_setDebugMode.D; + + D.nw=(0,0); + Class_draw.D; +endfig; + +beginfig(5); + save P, Q; + + Class.P("AAA")()(); + Class_stereotypes.P("ooo", "home", "interface"); + Class_setDebugMode.P; + P.nw=(0,0); + Class_draw.P; + + Class.Q("AAA")()(); + Class_stereotypes.Q("ooo", "home", "interface"); + Q.nw=P.ne + (20,0); + Class_draw.Q; +endfig; + +beginfig(6); + save A; + + Class.A("User6")()(); + Class_stereotypes.A("<<interface>>","<<home>>"); + A.nw=(0,0); + drawObject(A); +endfig; + +beginfig(7) + save A; + Class.A("User7")()(); + A.info.iMethodStack.left := A.info.iMethodStack.right := 50; + A.info.iMethodStack.top := A.info.iMethodStack.bottom := 20; + + drawObject(A); +endfig; + +beginfig(8) + save inter; + EClass.inter(iInterface)("Observer")()("+update(src: Object)"); + drawObjects(inter); +endfig; + +beginfig(9) + save inter; + EInterface.inter(iInterface)("Observer")("+update(src: Object)"); + drawObjects(inter); +endfig; + +beginfig(10) + save inter; + Interface.inter("Observer")("+update(src: Object)"); + drawObjects(inter); +endfig; + +beginfig(11) + save A; + EClass.A(iAbstractClass)("AbstractClass")("[]{}")("+update(src: Object)"); + drawObjects(A); +endfig; + +beginfig(12) + save A; + AbstractClass.A("AbstractClass")("[]{}")("+update(src: Object)"); + drawObjects(A); +endfig; + +beginfig(13) + save A; + EClass.A(iClassNameOnly)("AClassWithNoCompartments")()(); + drawObjects(A); +endfig; + +beginfig(14) + save A; + ClassName.A("AnotherClass"); + drawObjects(A); +endfig; + +beginfig(15) + save A; + ClassName.A("AnotherClass"); + classStereotypes.A("<<interface>>","<<remote>>"); + + drawObjects(A); +endfig; + +beginfig(16); + save A, B, C; + + Class.A("Foo") + ("+a: int", "-b: int", "#c: int", "d: int") + ("+x()", "-y()", "#z()", "t()"); + Class_noVisibilityMarkers.A; + + drawObjects(A); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class_feature_types.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class_feature_types.mp new file mode 100644 index 0000000000..f35c0b7b68 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class_feature_types.mp @@ -0,0 +1,53 @@ +% Copyright 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +input metauml; + +beginfig(1); + if not metauml_private_isAbstract(abstract "foo"): + 1 = 2; + fi; + + if metauml_private_isAbstract("@abstracp"): + 1 = 2; + fi; +endfig; + +beginfig(2); + if not metauml_private_isStatic(static "bar"): + 1 = 2; + fi; + + if metauml_private_isStatic("@statique"): + 1 = 2; + fi; +endfig; + +beginfig(3); + Class.A("A") + ("+a:int+", static "+b:int") + ("+f+():int", static "+g+():int", abstract "+h():int"); + Class_setDebugMode.A; + drawObjects(A); +endfig; + +beginfig(4); + save A; + Class.A("A") + (static "-instanceCount:int") + (static "+getInstanceCount():int", abstract "+work()"); + drawObjects(A); +endfig; + +beginfig(5); + save A, B; + Class.A("A")()(); + Class.B(abstract "B")()(); + Class.C("C")()(abstract "foo()"); + + leftToRight(5)(A, B, C); + + drawObjects(A, B, C); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class_qual_assoc.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class_qual_assoc.mp new file mode 100644 index 0000000000..735bba19e0 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class_qual_assoc.mp @@ -0,0 +1,53 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + save P,qa; + + Class.P("Person")()(); + QualifiedAssociation.qa("accountNumber:int", "foo: id"); + + P.nw = (0,0); + qa.n = P.s; + + + P.info.iName.left := 35; + P.info.iName.right := 35; + drawObjects(P); + + drawObject(qa); +endfig; + +beginfig(2); + save P,qa; + + Class.P("Person")()(); + QualifiedAssociation.qa("accountNumber:int", "foo: id", "foolang"); + + P.nw = (0,0); + qa.w = P.e; + + P.info.shade := 0; + P.info.iMethodStack.top := 20; + drawObjects(P); + + drawObject(qa); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class_templates.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class_templates.mp new file mode 100644 index 0000000000..c3fc50209c --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_class_templates.mp @@ -0,0 +1,62 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + save P,template; + + Class.P("Person")()(); + Template.template("foo", "bar"); + + drawObjectAt(P)(P.nw=(0,0)); + + Template_attachToClass.template(P); + drawObject(template); +endfig; + +beginfig(2); + save P,template; + + Class.P("Person")()(); + Template.template("foo: int"); + Template_attachToClass.template(P); + + drawObjectAt(P)(P.nw=(0,0)); + drawObject(template); +endfig; + +beginfig(3); + save CA, TA, CB, TB, CC, TC; + Class.CA("VeryVeryLongClassName")()(); + ClassTemplate.TA("int foo")(CA); + + Class.CB("Shortie")("abracadabra: long long int")(); + ClassTemplate.TB("T")(CB); + + Class.CC("Shortie")("abracadabra: long long int")(); + ClassTemplate.TC("TrulyAmazingLongTypename")(CC); + + CA.s = CB.n + (0,14); + CB.s = CC.n + (0,14); + + drawObjects(CA, TA, CB, TB, CC, TC); +endfig; + + + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_component.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_component.mp new file mode 100644 index 0000000000..94d866c753 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_component.mp @@ -0,0 +1,30 @@ +input metauml; +input metauml_component; +input metauml_component_relations; + +beginfig(1); + Class.classA("Class A")()(); + Class.classB("Class B")()(); + + Component.compA("Component A")(); + Component.compB("Component B")(); + Component.compC("Component C")(compA, compB, classA, classB); + + compB.w = compA.e + (40, 0); + classA.w = compB.e + (20, 0); + classB.w = classA.e + (20, 0); + + drawObjects(compC); + + path open; + open := compA.e .. compA.e + (20, 0); + path close; + + close := compB.w .. compA.e + (20, 0); + + link(requiredInterface)(open); + + link(providedInterface)(close); +endfig; + +end
\ No newline at end of file diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_font.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_font.mp new file mode 100644 index 0000000000..21e748a4f7 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_font.mp @@ -0,0 +1,81 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +string theFont; + +beginfig(1); + theFont := "pcrr"; + + boxjoin(a.sw=b.nw); + + boxit.ff(("Font name: ( ) " & theFont) infont theFont); + boxit.s0("<<stereotype>> text with guillemets. ><>><<" infont theFont ); + boxit.s1("<<a>>, <<b>>, <<c>>" infont theFont); + boxit.s2("[g uard] text with square brackets []]." infont theFont); + boxit.s3("{c onstraint} text with curly brackets {}}." infont theFont); + + drawboxed(ff, s0, s1, s2, s3); +endfig; + +beginfig(2); + save ff,s,g,c; + theFont := "tyxbtt"; + + boxjoin(a.sw=b.nw); + + boxit.ff(("Font name: ( ) " & theFont) infont theFont); + boxit.s0("<<stereotype>> text with guillemets. ><>><<" infont theFont ); + boxit.s1("<<a>>, <<b>>, <<c>>" infont theFont); + boxit.s2("[g uard] text with square brackets []]." infont theFont); + boxit.s3("{c onstraint} text with curly brackets {}}." infont theFont); + + drawboxed(ff, s0, s1, s2, s3);endfig; + +beginfig(3); + picture pA, pB, pC; + string sA, sB, sC; + sA := "assembleElementLocalMatrix(k: KeyType, mat: LocalMatrixType, a: AssembleAction)"; + sB := "assembleElementLocalMatri(k: KeyType, mat: LocalMatrixType, a: AssembleAction)"; + sC := "assembleElntLocalMatri(k: KeyType, mat: LocalMatrixType, a: AssembleAction)"; + + pA := sA infont "tyxbtt"; + pB := sB infont "tyxbtt"; + pC := sC infont "tyxbtt"; + + draw pA; + draw pB shifted (0,-20); + draw pC shifted (0,-40); +endfig; + +beginfig(4); + save ff,s,g,c; + theFont := "ptmr8r"; + + boxjoin(a.sw=b.nw); + boxit.ff(("Font name: ( ) " & theFont) infont theFont); + + boxit.s0("<<stereotype>> text with guillemets. ><>><<" infont theFont ); + boxit.s1("<<a>>, <<b>>, <<c>>" infont theFont); + boxit.s2("[g uard] text with square brackets []]." infont theFont); + boxit.s3("{c onstraint} text with curly brackets {}}." infont theFont); + + drawboxed(ff, s0, s1, s2, s3); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_group.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_group.mp new file mode 100644 index 0000000000..17265c458b --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_group.mp @@ -0,0 +1,60 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + save p,q,r,t,g; + + EPicture.p(iPictBoxed)("p0"); + EPicture.q(iPictBoxed)("p1"); + p.se = q.nw; + + string f; + f= enumToString(p,q)(""); + show "f=" & f; + + EGroup.g(iGroup)(p,q); + g.nw = (0,0); + + drawObject(g); +endfig; + +beginfig(2); + save g,h,p,gg; + + Group.g(); + g.info.boxed := 1; + g.nw = (30,30); + drawObject(g); + + Picture.p("Test picture in group"); + p.info.boxed := 1; + Group.h(p); + h.info.boxed := 1; + h.nw = (0,0); + drawObject(h); + + Picture.v0("s"); v0.info.boxed := 1; + Picture.v1("s"); v1.info.boxed := 1; + v1.nw = v0.se + (10,10); + Group.gg(v0, v1); gg.info.boxed := 1; + gg.nw = (70,70); + drawObject(gg); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_instance.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_instance.mp new file mode 100644 index 0000000000..d01ff8452e --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_instance.mp @@ -0,0 +1,35 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Radu-George Radulescu +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + Instance.A(":Foo")("int: val1", "bool: val2"); + Instance.B(":Bar")("very long text for testing purposes"); + Instance.C("s: Student")("line1", "line2", "line3", "line4", "line5"); + Instance.D("Example")("small"); + Instance.E("g: Yummy")("{placed}", "{color=red}"); + + B.w = A.e + (20, 0); + C.n = A.s - (0, 20); + D.w = C.e + (20, 0); + E.w = D.e + (20, 0); + + drawObjects(A, B, C, D, E); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_lars_issues.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_lars_issues.mp new file mode 100644 index 0000000000..428d7b4144 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_lars_issues.mp @@ -0,0 +1,94 @@ +input metauml; + +numeric u; +u = 1.3cm; + +beginfig(1); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Class.ElLocSysAcc("ElementLocalSystemAcceptor") +() +("+startElementAssebly()", + "+assembleElementLocalMatrix(k: KeyType, mat: LocalMatrixType, a: AssembleAction)", + "+assembleElementLocalRHS(k: KeyType, rhs: LocalRHSType, a: AssembleAction)", + "+endElementAssembly()"); + +classStereotypes.ElLocSysAcc("<<interface>>"); +ClassTemplate.TEl("KeyType: typename")(ElLocSysAcc); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Class.FaceLocSysAcc("FaceLocalSystemAcceptor") + () + ("+startFaceAssebly()", + "+assembleFaceLocalMatrix(k1: KeyType, k2: KeyType, mat: LocalMatrixType, a: AssembleAction)", + "+assembleFaceLocalRHS(k: KeyType, rhs: LocalRHSType, a: AssembleAction)", + "+endFaceAssembly()"); + + classStereotypes.FaceLocSysAcc("<<interface>>"); + ClassTemplate.TFa("KeyType: typename")(FaceLocSysAcc); + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Class.SolProvider("SolutionProvider") + () + ("+startSortBack()", + "+getLocalSolution(k: KeyType, sol: LocalSolutionType)", + "+endSortBack()"); + + classStereotypes.SolProvider("<<interface>>"); + ClassTemplate.TSol("KeyType: typename")(SolProvider); + +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % now inherit from these for LapackMatrixSorter + Class.LapackMS("LapackMatrixSorter") + ("-indMan: IndexManager", + "-A: LaGenMatDouble&", + "-x: LaVectorDouble&", + "-b: LaVectorDouble&" + ) + ("+startElementAssembly()"); + + ClassTemplate.TLap("KeyType: typename", "IndexManager: class")(LapackMS); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% where to draw these: +FaceLocSysAcc.nw = ElLocSysAcc.ne + (1.5u, 0); +SolProvider.nw = FaceLocSysAcc.ne + (1.5u, 0); +LapackMS.n = FaceLocSysAcc.s + (0, -3u); + +drawObjects(ElLocSysAcc, TEl, FaceLocSysAcc, TFa, + SolProvider, TSol, LapackMS, TLap); + +% 50: how much should the path raise upwards before making a horizontal turn. +link(inheritance)(pathStepY(LapackMS.n, FaceLocSysAcc.s, 50)); +link(inheritance)(pathStepY(LapackMS.n, SolProvider.s, 50)); +link(inheritance)(pathStepY(LapackMS.n, ElLocSysAcc.s, 50)); + +endfig; + +beginfig(2); + Begin.b; + Activity.A("Activity A", "on line two"); + Activity.B("Activity B"); + End.e; + + % or other positioning code... + setObjectJoin(pa.s = pb.n + (0,20)); + joinObjects(b, A, B, e); + + % important: first draw the activities + drawObjects(b, A, B, e); + + % you can now draw the transitions + clink(transition)(b, A); + clink(transition)(A, B); + link(transition)(pathStepX(B.e, e.e, 30)); + + item(iGuard)("guard")(obj.sw = .5[b.s, A.n]); +endfig; + +end; diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_lowlevel.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_lowlevel.mp new file mode 100644 index 0000000000..952da34f48 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_lowlevel.mp @@ -0,0 +1,66 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; +input util_infrastructure; + +beginfig(1); + show "Lowlevel test"; + %string foo; + %foo := var_instruction(numeric) x, y; + %show foo; + %foo := foo & ";"; + %show foo; + attributes(foo); + _n_ := "foo"; + %scantokens foo; + %string x; + %x := str(numeric); + var(numeric) x; + + label.top("nothing shown (intentionally)", (0,0)); +endfig; + +vardef _foo@#= + attributes(@#); + var(string) @#a[]; + @#a[0] := "fpp"; + @#a[1] := "gqq"; +enddef; + +% _foo.b; % not working + +vardef _bar@#(text s)= + attributes(@#); + var(string) elements; + @#elements := enumToString(s)(""); +enddef; + +beginfig(2); + for f = scantokens "a, b, c": + show f; + endfor; + _bar.xx(a, b, c, d); + show xx.elements; + for f = scantokens xx.elements: + show f; + endfor; + label.top("nothing shown (intentionally)", (0,0)); +endfig; + +end + diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_note.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_note.mp new file mode 100644 index 0000000000..bf8c1aeb2f --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_note.mp @@ -0,0 +1,39 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml_note; +input metauml_base; +input metauml_paths; +input metauml_links; +input metauml_class_relations; + +beginfig(1); + Note.foo("This is the first line", "and this the second one."); + drawObject(foo); +endfig; + +beginfig(2); + save foo; + Note.foo("Please disregard this note."); + Note.bar("Please take the other note", "very seriously."); + + bar.s = foo.n + (10,20); + drawObjects(foo, bar); + clink(dashedLink)(foo, bar); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_package.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_package.mp new file mode 100644 index 0000000000..6d4f97ea9f --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_package.mp @@ -0,0 +1,54 @@ +input metauml; +input metauml_package; +input metauml_package_relations; + +beginfig(1); + Package.emptyPackage("")(); + + Package.nameOnlyPackage("java.sun.com")(); + + Class.oneClass("A class")()(); + Package.oneClassPackage("One class package")(oneClass); + + Instance.oneInstance("An instance")(); + State.oneState("A state")(); + Activity.oneActivity("An activity"); + Package.multiPackage("Multipackage")(oneInstance, oneState, oneActivity); + + Package.allPackage("This package contains them all")(emptyPackage, nameOnlyPackage, + oneClassPackage, multiPackage); + + nameOnlyPackage.nw = emptyPackage.ne + (30, 0); + oneClassPackage.ne = emptyPackage.s - (0, 50); + + multiPackage.top = oneClassPackage.top; + multiPackage.left = oneClassPackage.right + 20; + + centered_align_top(oneState, oneActivity)(10, below(oneInstance.s, 20)); + + drawObjects(allPackage); +endfig; + +beginfig(2); + Package.nameOnlyOnTopPackage("Name on top")(); + nameOnlyOnTopPackage.info.forceEmptyContent := 1; + Package.nameOnlyInMiddlePackage("By default, the name", "is in the middle")(); + + Class.cl("A class")("Attribute")("Method"); + Package.notEmptyPackage("Contains class")(cl); + + nameOnlyInMiddlePackage.n = nameOnlyOnTopPackage.s - (0, 40); + notEmptyPackage.w = nameOnlyInMiddlePackage.e + (80, 0); + drawObjects(nameOnlyOnTopPackage, nameOnlyInMiddlePackage, notEmptyPackage); + + %link(import)(pathStepX(notEmptyPackage.w, nameOnlyOnTopPackage.e, -30)); + %link(import)(pathVertical(nameOnlyInMiddlePackage.ne - (10, 0), nameOnlyOnTopPackage.bottom)); + %link(import)(notEmptyPackage.sw -- nameOnlyInMiddlePackage.ne); +endfig; + +beginfig(3); + link(nest)((10,10)--(30,30)); +endfig; + + +end
\ No newline at end of file diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_paths.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_paths.mp new file mode 100644 index 0000000000..eedd11a9b0 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_paths.mp @@ -0,0 +1,100 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +iPict.boxed := 1; + +beginfig(1); + iClass.shade := 3; + Class.F("Foo")("a: int","b: int")(); + Class.B("Bar")()(); + + B.nw = F.ne + (20,-20); + + drawObjects(B, F); + + link(association)(B.nw -- F.ne); + + draw objectBorder(B) withcolor red; + draw objectBorder(F) withcolor blue; + + link(association)(pathCut(B,F)(B.c--F.c)); +endfig; + +beginfig(2); + save A, B; + + Picture.A("A"); + Picture.B("Blue"); + + B.sw = A.ne + (20,20); + + drawObjects(A, B); + + link(associationUni)(pathManhattanX(A.e, B)); +endfig; + +beginfig(3); + save A, B, C, D, O; + + Picture.A("Alpha"); + Picture.B("Beta"); + Picture.C("Gamma"); + Picture.D("Delta"); + Picture.O("Omega"); + + A.c = O.c + (-50,50); + B.c = O.c + (50,50); + C.c = O.c + (-50,-50); + D.c = O.c + (50,-50); + + drawObjects(O, A, B, C, D); + + link(associationUni)(pathManhattanX(O, A)); + link(associationUni)(pathManhattanX(O, B)); + link(associationUni)(pathManhattanX(O, C)); + link(associationUni)(pathManhattanX(O, D)); +endfig; + +beginfig(3); + show ""; + show ""; + show " FIGURE 3"; + + save A, B, C, D, O; + + Picture.A("Alpha"); + Picture.B("Beta"); + Picture.C("Gamma"); + Picture.D("Delta"); + Picture.O("Omega"); + + A.c = O.c + (-50,50); + B.c = O.c + (50,50); + C.c = O.c + (-50,-50); + D.c = O.c + (50,-50); + + drawObjects(O, A, B, C, D); + + link(associationUni)(pathManhattanX(O, A)); + link(associationUni)(pathManhattanX(O, B)); + link(associationUni)(pathManhattanX(O, C)); + link(associationUni)(pathManhattanX(O, D)); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_picture.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_picture.mp new file mode 100644 index 0000000000..7a56236e82 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_picture.mp @@ -0,0 +1,273 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +string theFont; +theFont := "tyxbtt"; + +beginfig(1); + draw "xxx" infont defaultfont scaled defaultscale shifted (0,0); + draw "yyy" infont (iFont.name) scaled (iFont.scale) shifted (25, 0); + + Picture.p("foo, bar, baz"); + p.nw = (0,0); + drawObject(p); + + Picture.q("qux, norf"); + drawObjectAt(q)( q.nw = (30,30) ); + + FontInfo.foo("tyxbtt", 1); + PictureInfo.iNice(3,6,5,10)(foo); + iNice.boxed := 1; + + EPicture.myPic(iNice)("Custom iPicture"); + drawObjectAt(myPic)( myPic.nw = (70,0)); +endfig; + +beginfig(2); + save p, q, r, t; + + Picture.p("foo"); + Picture.q("bar"); + p.nw = (10, 10); + q.nw = (20, 20); + + drawObject(p); + drawObject(q); + + drawObjects(p, q); + + Picture.a0("root" infont defaultfont); + Picture.a1("toof"); + + a[0].nw = (30, 30); + a[1].nw = (50, 50); + + drawObjects(scantokens listArray(a)(2)); +endfig; + +beginfig(3); + save p, q, r, t, u, pp; + + bboxmargin := 0; + + picture pp; + pp = "a" infont theFont; + Picture.p(pp); + Picture.q("foo" infont theFont); + Picture.r("bar" infont theFont); + Picture.t("baz"); + Picture.u("norf" infont theFont); + + p.nw = (0,0); + setObjectJoin(pa.left=pb.left; pa.bottom = pb.top + 1); + joinDrawObjects(p, q, r, t, u); + + defaultdy:=0; + boxjoin(a.sw=b.nw; a.se=b.ne); + boxit.A0("foo1"); + boxit.A1("bar1"); + boxit.A2("baz2"); + boxit.A3("norf2"); + boxit.A4(".."); + A0.nw=(50,0); + drawboxed(A0,A1,A2,A3,A4); + + myy := 10; + + bboxmargin := 0; + + pair p; + p := (30,myy); + dotlabel.lrt(".", p); + picture x; + x := "f: int" infont theFont; + draw bbox(x) shifted p; + draw x shifted p; + + pair q; + q := (70,myy); + dotlabel.lrt(".", q); + picture y; + y := "goofy: int" infont theFont; + draw bbox(y) shifted q; + draw y shifted q; + + pair qq; + qq := (135,myy); + dotlabel.lrt(".", qq); + picture y; + y := "goot" infont theFont; + draw bbox(y) shifted qq; + draw y shifted qq; + + draw (0,myy)--(150, myy) dashed evenly; + + myyb := 30; + Picture.aa(btex goof etex); + aa.sw = (30, myyb); + Picture_draw.aa; + + draw (0,myyb)--(100, myyb) dashed evenly; +endfig; + +beginfig(4); + save a, b; + FontInfo.myFont(theFont, 1); + PictureInfo.myWay(0,0,0,0)(myFont); + myWay.boxed := 1; + + EPicture.a0(myWay)("goof"); + EPicture.a1(myWay)("Aoorian"); + EPicture.a2(myWay)("fpp"); + EPicture.a3(myWay)("f: int"); + EPicture.a4(myWay)("aa()"); + + a0.nw = (0,0); + setObjectJoin(pa.bottom = pb.bottom; pa.right = pb.left - 10); + joinDrawObjects(scantokens listArray(a)(5)); + + draw a0.sw -- a4.se withcolor black dashed evenly; + + myWay.ignoreNegativeBase := 1; + EPicture.b0(myWay)("foo"); + EPicture.b1(myWay)("Bar baz"); + EPicture.b2(myWay)("qux"); + EPicture.b3(myWay)("f: int"); + EPicture.b4(myWay)("aa()"); + + b0.nw = (0,-20); + setObjectJoin(pa.bottom = pb.bottom; pa.right = pb.left - 10); + joinDrawObjects(scantokens listArray(b)(5)); + + draw b0.sw -- b4.se withcolor black dashed evenly; +endfig; + +beginfig(5); + truecorners := 1; + bboxmargin := 0; + save p; + picture basepict; + basepict := "<<foo>>" infont "tyxtt"; + + draw basepict; + draw bbox basepict; +endfig; + +beginfig(6); + item.foo(iPictBoxed)("foo bar baz")(foo.nw = (0,0)); + item.bar(iPict)("x: int")(bar.nw = (20,20)); + + aitem(iPictBoxed)("an anounymous item")(obj.nw = (40,10)); +endfig; + +beginfig(7); + save a, b, c, d, e, myFixed; + PictureInfoCopy.myFixed(iPict); + myFixed.ignoreNegativeBase := 1; + myFixed.fixedWidth := 20; + myFixed.boxed := 1; + + EPicture.a(myFixed)("a"); + EPicture.b(myFixed)("bar"); + EPicture.c(myFixed)(".-."); + EPicture.d(myFixed)("baz"); + EPicture.e(myFixed)("qux norf"); + + leftToRight.bottom(20)(a, b, c, d, e); + + drawObjects(a, b, c, d, e); +endfig; + +beginfig(8); + save a, b, c, d, e, myFixed; + PictureInfoCopy.myFixed(iPict); + myFixed.halign := "center"; + myFixed.ignoreNegativeBase := 1; + myFixed.fixedWidth := 20; + myFixed.boxed := 1; + + EPicture.a(myFixed)("a"); + EPicture.b(myFixed)("bar"); + EPicture.c(myFixed)(".-."); + EPicture.d(myFixed)("baz"); + EPicture.e(myFixed)("qux norf"); + + leftToRight.bottom(20)(a, b, c, d, e); + + drawObjects(a, b, c, d, e); +endfig; + +beginfig(9); + save a, b, c, d, e, myFixed; + PictureInfoCopy.myFixed(iPict); + myFixed.halign := "center"; + myFixed.ignoreNegativeBase := 1; + myFixed.fixedWidth := 20; + myFixed.fixedHeight := 30; + myFixed.boxed := 1; + + EPicture.a(myFixed)("a"); + EPicture.b(myFixed)("bar"); + EPicture.c(myFixed)(".-."); + EPicture.d(myFixed)("baz"); + EPicture.e(myFixed)("qux norf"); + + leftToRight.bottom(20)(a, b, c, d, e); + + drawObjects(a, b, c, d, e); +endfig; + +beginfig(10); + save a, b, c, d, e, myFixed; + PictureInfoCopy.myFixed(iPict); + myFixed.halign := "center"; + myFixed.valign := "center"; + myFixed.ignoreNegativeBase := 1; + myFixed.fixedWidth := 20; + myFixed.fixedHeight := 30; + myFixed.boxed := 1; + + EPicture.a(myFixed)("a"); + EPicture.b(myFixed)("bar"); + EPicture.c(myFixed)(".-."); + EPicture.d(myFixed)("baz"); + EPicture.e(myFixed)("qux norf"); + + leftToRight.bottom(20)(a, b, c, d, e); + + drawObjects(a, b, c, d, e); +endfig; + +beginfig(11); + save a, b, c; + Picture.a("goo"); + a.info.textDecoration := "underline"; + + Picture.b("foo()"); + b.info.textDecoration := "underline"; + + Picture.c("x"); + c.info.textDecoration := "underline"; + + topToBottom(5)(a, b, c); + + drawObjects(a, b, c); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_picture_stack.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_picture_stack.mp new file mode 100644 index 0000000000..8ad4776fa4 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_picture_stack.mp @@ -0,0 +1,130 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +string theFont; +theFont := "tyxtt"; + +util_log_thresholdlevel := 100; + +beginfig(1); + PictureStackInfoCopy.stackWay(iStack); + + EPictureStack.emptyStack(stackWay)()("vcenter"); + emptyStack.nw=(10,10); + drawObject(emptyStack); +endfig; + +beginfig(2); + PictureStack.myStack("foo")("vcenter"); + myStack.nw = (0,0); + PictureStack_draw.myStack; +endfig; + +beginfig(3); + PictureStack.myStackB("foo", "bar")("vcenter"); + myStackB.nw = (0,0); + PictureStack_draw.myStackB; +endfig; + +beginfig(4); + % 1 + PictureStack.stack("item A", "item B long", "C")("vcenter"); + stack.info.boxed := 1; + stack.info.iPict.boxed := 1; % this does nothing, it's too late + + stack.nw = (0,0); + drawObject(stack); + + % 2 + PictureStack.stackb("item A", "item B long", "C")("vcenter"); + stackb.info.boxed := 1; + stackb.pict[0].info.boxed := 1; + stackb.pict[2].info.boxed := 1; + + stackb.nw = (100,0); + drawObject(stackb); + + % 3 + PictureStackInfoCopy.myInfo(iStack); + myInfo.boxed := 1; + myInfo.iPict.boxed := 1; + EPictureStack.stackc(myInfo)("item A", "item B long", "C")("vcenter"); + + stackc.nw = (200,0); + drawObject(stackc); +endfig; + +beginfig(5); + vardef joinCallback= enddef; + PictureStack.custom("A.A", "B__________B", "C-----C") + ("joinCallback"); + + drawObject(custom); +endfig; + +beginfig(6); + save custom; + + pickup pencircle scaled 4pt; + drawdot origin; + + vardef joinCallbackA= + setObjectJoin(pa.bottom = pb.top + index*10; pa.left = pb.left); + setObjectJoinFirst(pa.nw = (30,0)); + enddef; + + PictureStack.customA("go", "further", "and further", "and further still") + ("joinCallbackA"); + + vardef joinCallbackB= + setObjectJoin(pb.bottom = customA.pict[index].bottom; pb.midx = pa.midx); + setObjectJoinFirst(pa.bottom = customA.pict[index].bottom); + enddef; + + PictureStack.customB(".", "..", "...", "....") + ("joinCallbackB"); + + drawObjects(customA, customB); +endfig; + +beginfig(7); + save stackX; + save stylePA, stylePB; + save stylePictureStack; + + PictureInfoCopy.stylePA(iPict); + stylePA.borderColor := green; + stylePA.boxed := 1; + + PictureInfoCopy.stylePB(iPict); + stylePB.borderColor := red; + stylePB.boxed := 1; + + PictureStackInfoCopy.stylePictureStack(iStack); + + def styleSupplier(expr i)= if i mod 2 = 0: stylePA else: stylePB fi enddef; + + stylePictureStack.childStyleSupplier := "styleSupplier"; + + EPictureStack.stackX(stylePictureStack)("a","b","c","d","e")("vcenter"); + + drawObjects(stackX); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_picture_tex_rendering.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_picture_tex_rendering.mp new file mode 100644 index 0000000000..3c04129869 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_picture_tex_rendering.mp @@ -0,0 +1,43 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +input TEX; + +beginfig(1); + PictureInfoCopy.myP(iPict); + myP.boxed := 1; + myP.ignoreNegativeBase := 1; + + EPicture.p(myP)( TEX("Hello, world $x=7$") ); + + PictureStackInfoCopy.myPS(iStack); + myPS.boxed := 1; + myPS.iPict.boxed := 1; + myPS.iPict.ignoreNegativeBase := 1; + + EPictureStack.ps(myPS)("Hello, world!", + TEX("This is cool: $x=y$."), + TEX("But this is insane: $\sum_1^3 f(x) \over x$!") ) ("vleft"); + + leftToRight(20)(p, ps); + + drawObjects(p, ps); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_positioning.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_positioning.mp new file mode 100644 index 0000000000..6603476771 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_positioning.mp @@ -0,0 +1,195 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +iPict.boxed := 1; +spacing := 5; +string strA, strB, strC; +strA := "a"; +strB := "..."; +strC := "XYZ"; + +beginfig(1); + save A, B, C, X, Y, Z; + + Picture.A(strA); + Picture.B(strB); + Picture.C(strC); + + align(top, left, right)(spacing)("+")(A, B, C); + + drawObjects(A, B, C); + + draw (A.left, A.top) -- (C.right, A.top); + + %%%% + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + leftToRight.top(spacing)(X, Y, Z); + + X.top = A.bottom - 10; + + drawObjects(X, Y, Z); + + draw (X.left, X.top) -- (Z.right, X.top); +endfig; + +beginfig(2); + save A, B, C, X, Y, Z; + + Picture.A(strA); + Picture.B(strB); + Picture.C(strC); + + align(midy, left, right)(spacing)("+")(A, B, C); + + drawObjects(A, B, C); + + draw (A.left, A.midy) -- (C.right, A.midy); + + %%%% + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + leftToRight.midy(spacing)(X, Y, Z); + + X.top = A.bottom - 10; + + drawObjects(X, Y, Z); + + draw (X.left, X.midy) -- (Z.right, X.midy); +endfig; + +beginfig(3); + save A, B, C, X, Y, Z; + + Picture.A(strA); + Picture.B(strB); + Picture.C(strC); + + align(bottom, left, right)(spacing)("+")(A, B, C); + + drawObjects(A, B, C); + + draw (A.left, A.bottom) -- (C.right, A.bottom); + + %%%% + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + leftToRight.bottom(spacing)(X, Y, Z); + + X.top = A.bottom - 10; + + drawObjects(X, Y, Z); + + draw (X.left, X.bottom) -- (Z.right, X.bottom); +endfig; + +beginfig(4); + save A, B, C, X, Y, Z; + + Picture.A(strA); + Picture.B(strB); + Picture.C(strC); + + align(left, top, bottom)(spacing)("-")(A, B, C); + + drawObjects(A, B, C); + + draw (A.left, A.top) -- (A.left, C.bottom); + + %%%% + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + topToBottom.left(spacing)(X, Y, Z); + + X.top = C.bottom - 10; + + drawObjects(X, Y, Z); + + draw (X.left, X.top) -- (X.left, Z.bottom); +endfig; + +beginfig(5); + save A, B, C, X, Y, Z; + + Picture.A(strA); + Picture.B(strB); + Picture.C(strC); + + align(midx, top, bottom)(spacing)("-")(A, B, C); + + drawObjects(A, B, C); + + draw (A.midx, A.top) -- (A.midx, C.bottom); + + %%%% + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + topToBottom.midx(spacing)(X, Y, Z); + + X.top = C.bottom - 10; + + drawObjects(X, Y, Z); + + draw (X.midx, X.top) -- (X.midx, Z.bottom); +endfig; + +beginfig(6); + save A, B, C, X, Y, Z; + + Picture.A(strA); + Picture.B(strB); + Picture.C(strC); + + align(right, top, bottom)(spacing)("-")(A, B, C); + + drawObjects(A, B, C); + + draw (A.right, A.top) -- (A.right, C.bottom); + + %%%% + + Picture.X(strA); + Picture.Y(strB); + Picture.Z(strC); + + topToBottom.right(spacing)(X, Y, Z); + + X.top = C.bottom - 10; + + drawObjects(X, Y, Z); + + draw (X.right, X.top) -- (X.right, Z.bottom); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_skins.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_skins.mp new file mode 100644 index 0000000000..750cee4e97 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_skins.mp @@ -0,0 +1,26 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; +input metauml_skin_simple; + +beginfig(1); + Class.HelloSkin("HelloSkin")("nice: int")("done(): void"); + drawObject(HelloSkin); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_skins_global_defaults.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_skins_global_defaults.mp new file mode 100644 index 0000000000..aaeffd043b --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_skins_global_defaults.mp @@ -0,0 +1,29 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +string metauml_defaultFont, metauml_defaultFontLight; +metauml_defaultFont := "cmr12"; +metauml_defaultFontLight := "cmr10"; + +input metauml; + +beginfig(1); + Class.HelloSkinB("HelloSkinGlobal")("foo: int")("bar(): void"); + drawObject(HelloSkinB); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_state.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_state.mp new file mode 100644 index 0000000000..5420750749 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_state.mp @@ -0,0 +1,73 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +beginfig(1); + EntryPoint.entry; + ExitPoint.exit; + + entry.nw = (0,0); + exit.nw = (50,50); + + drawObjects(entry, exit); + clink(transition)(entry, exit); +endfig; + +beginfig(2); + EState.myState(iState)("The light is", "visibly on")(); + drawObject(myState); + + State.anotherState("Another nice state")(); + anotherState.info.drawNameLine := 1; + drawObjectAt(anotherState)(anotherState.nw = (0,50)); +endfig; + +beginfig(3); + State.interesting("Interesting state")(); + State_internalTransitions.interesting("OnEntry / doVeryHappy", "OnExit / doSomewhatSad"); + interesting.info.drawNameLine := 1; + + drawObject(interesting); +endfig; + +beginfig(4); + Begin.b; + End.e; + State.sa("A state")(); + State.sb("Another state")(); + setObjectJoin(pb.w = pa.e + (40, 0)); + joinObjects(b, sa, sb, e); + + State.composite("Composite state")(b, e, sa, sb); + drawObject(composite); + + clink(transition)(b, sa); + clink(transition)(sa, sb); + clink(transition)(sb, e); +endfig; + +beginfig(5); +endfig; + +beginfig(6); +endfig; + +beginfig(7); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_usecase.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_usecase.mp new file mode 100644 index 0000000000..32688814cf --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/test_usecase.mp @@ -0,0 +1,185 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +input metauml; + +HumanInfoCopy.iDwarf(iHuman); +iDwarf.width := 60; +iDwarf.height := 20; +iDwarf.foreColor := blue; +iDwarf.shadeColor := .8blue; + +beginfig(1); + Human.h; + drawObject(h); + draw objectBox(h); + + Human.h1; + h1.n = (35, 0); + h1.info.foreColor := red; + drawObject(h1); + + Human.h2; + h2.info.height := 90; + h2.nw = (50,0); + drawObject(h2); + draw objectBox(h2); + + EHuman.d(iDwarf); + drawObjectAt(d)(d.s = (10,-50)); + + EHuman.d2(iDwarf); + d2.info.shadeColor := red; + drawObjectAt(d2)(d2.s = (10,-80)); +endfig; + +beginfig(2); + save a,b; + + Actor.a("foo"); + drawObject(a); + + Actor.b("Actor line one", "and line two"); + Actor_setDebugMode.b; + b.n = (70,0); + drawObject(b); +endfig; + +beginfig(3); + Usecase.u("foo"); + drawObject(u); + + draw objectBox(u) withpen pencircle scaled .1; + + draw u.n withpen pencircle scaled 2 withcolor red; + draw u.s withpen pencircle scaled 2 withcolor red; + draw u.e withpen pencircle scaled 2 withcolor red; + draw u.w withpen pencircle scaled 2 withcolor red; + + draw u.ulft withpen pencircle scaled 2 withcolor blue; + draw u.urt withpen pencircle scaled 2 withcolor blue; + draw u.llft withpen pencircle scaled 2 withcolor blue; + draw u.lrt withpen pencircle scaled 2 withcolor blue; + + Usecase.login("Log in for an eagerly", "awaiting user", "which spans well into a very long 3rd line."); + login.s = (0, 5); + drawObject(login); + + Usecase.t("Line 1 goo bar", "Line 2"); + t.s = login.n + (0,10); + drawObject(t); + + Usecase.q("Line 1 abcdefg hij", "abcde", "Line 3 abc def ghe jkl", "Line 4 x"); + q.s = t.n + (0,10); + drawObject(q); + +endfig; + +beginfig(4); + Actor.userA("User A2", "line 2", "line 3 long long long"); + % Any Actor object is made of two sub-objects: nameStack and human. + % Each individual picture in the nameStack can be configured individually. + % + % However, it is not possible to configure all the lines in the nameStack at + % once now, saying something like: + % + % userA.nameStack.info.iPict.iFont.scale := 3; + % + % This happens because the information above is copied into the Picture objects + % in the Actor constructor (and it is useless to modify it afterwards). + % + % If you do want to make such global modifications of the settings, see the + % next two examples. + + userA.nameStack.pict[0].info.iFont.scale := 1.2; + userA.nameStack.pict[1].info.iFont.scale := .7; + userA.nameStack.info.borderColor := blue; + userA.nameStack.info.boxed := 1; + userA.nameStack.group.info.left := 30; + userA.nameStack.group.info.right := 5; + userA.human.info.foreColor := red; + + drawObject(userA); + %draw objectBox(userA.nameStack); + %draw objectBox(userA.human); +endfig; + +beginfig(5); + save userA; + % If you want to have preset a info for specific objects + + ActorInfoCopy.iBig(iActor); + + % ActorInfo contains info-s for two objects + % iNameStack: for the stack representing the actor's name + % iHuman: for the little human + + iBig.iNameStack.iPict.iFont.scale := 3; + iBig.iNameStack.spacing := 25; + iBig.iHuman.height := 25; + + EActor.userA(iBig)("User A", "Specifically configured"); + drawObject(userA); +endfig; + +beginfig(6); + save userA; + + iActor.iNameStack.iPict.iFont.scale := 2; + iActor.iNameStack.spacing := 18; + + Actor.userA("User A", "Globally configured"); + drawObject(userA); +endfig; + +beginfig(7); + save usecaseA; + Usecase.usecaseA("A highly customizable", "usecase. Foo bar!"); + usecaseA.info.iNameStack.iPict.iFont.scale := .5; + drawObject(usecaseA); +endfig; + +beginfig(8); + save usecaseA; + Usecase.usecaseA("A highly customizable", "usecase. Foo bar 2!"); + usecaseA.info.iNameStack.iPict.iFont.scale := 1.1; + usecaseA.info.foreColor := red; + usecaseA.info.borderColor := blue; + usecaseA.info.iShade.background := green; + usecaseA.info.iShade.shift := 4; + drawObject(usecaseA); +endfig; + +beginfig(9); + save usecaseA; + UsecaseInfoCopy.iMyUsecase(iUsecase); + iMyUsecase.iNameStack.iPict.iFont.scale := .6; + iMyUsecase.iNameStack.spacing := 5; + iMyUsecase.foreColor := green; + iMyUsecase.iShade.background := red; + + EUsecase.usecaseA(iMyUsecase)("A highly ", " customizable usecase."); + EUsecase.usecaseB(iMyUsecase)("Another very ", " customizable usecase."); + + usecaseB.info.iShade.background := green; + + leftToRight(20)(usecaseA, usecaseB); + drawObjects(usecaseA, usecaseB); +endfig; + +end + diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/usecase.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/usecase.mp new file mode 100644 index 0000000000..ca8040f57b --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/usecase.mp @@ -0,0 +1,43 @@ +% Sample MetaUML figures. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +input metauml; + +beginfig(1); + Usecase.U("Authenticate user", + "by name, password"); + drawObject(U); +endfig; + +beginfig(2); + Actor.A("User"); + drawObject(A); +endfig; + +beginfig(3); + save A; + + Actor.A("Administrator"); + drawObject(A); + draw A.nw -- A.ne -- A.se -- A.sw -- cycle; + draw A.human.nw -- A.human.ne -- A.human.se -- A.human.sw -- cycle; + +endfig; + + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/fig/usecase_diagrams.mp b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/usecase_diagrams.mp new file mode 100644 index 0000000000..110ca35c07 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/fig/usecase_diagrams.mp @@ -0,0 +1,48 @@ +% Part of the MetaUML manual. +% Copyright (C) 2005 Ovidiu Gheorghies +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +% for f in `find . | grep '.*\.[1-9]'`; do echo $f; done + +input metauml; + +beginfig(1); + Actor.user("User"); + Actor.db("Database"); + + Usecase.dbquery("Query database"); + Usecase.auth("Authentification"); + Usecase.authA("Authentification by", "username, password"); + Usecase.authB("Authentification by", "smartcard"); + + auth.w = user.human.e + (30,0); + dbquery.s = auth.n + (0,30); + db.human.w = dbquery.e + (30,0); + + authB.left - authA.right = 30; + authB.midy = authA.midy; + .5[authB.w, authA.e] = (auth.midx, auth.bottom - 50); + + drawObjects(user, auth, dbquery, db, authA, authB); + + clink(inheritance)(authA, auth); + clink(inheritance)(authB, auth); + clink(association)(auth, dbquery); + clink(association)(user.human, auth); + clink(association)(dbquery, db.human); +endfig; + +end diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/metauml-manual.bib b/graphics/metapost/contrib/macros/metauml/examples/manual/metauml-manual.bib new file mode 100644 index 0000000000..845db1968f --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/metauml-manual.bib @@ -0,0 +1,64 @@ +@misc{metaobj, + author = "Denis Roegel", + title = "The {METAOBJ} tutorial and reference manual", + year = "2002", + url = "http://texdoc.net/texmf-dist/doc/metapost/metaobj/momanual.pdf" +} +@book{texbook, + author = "Donald E. Knuth", + title = "The {\TeX{}}book", + year = "1986", + publisher = "Addison-Wesley Publishing Company" +} +@book{latexbook, + author = "Leslie Lamport", + title = "{\LaTeX} a {D}ocument {P}reparation {S}ystem", + year = "1994", + publisher = "Addison-Wesley Publishing Company" +} +@misc{metapost, + author = "John D. Hobby", + title = "{METAPOST} {A} {U}ser's {M}anual", + year = "2018", + url = "http://www.tug.org/tutorials/mp/mpman.pdf" +} +@misc{umlsty, + author = "Ellef Fange Gjelstad", + title = "uml.sty, a package for writing {UML} diagrams in {LATEX}", + year = "2010", + url = "http://mirror.hmc.edu/ctan/graphics/pstricks/contrib/uml/uml.pdf" +} + +@misc{pstumlsty, + author = "Maurice Diamantini", + title = "Interface utilisateur du package pst-uml", + year = "2006", + url = "http://mirrors.nxthost.com/ctan/graphics/pstricks/contrib/pst-uml/pst-uml-doc.pdf" +} + +@misc{umldoc, + author = "Doug Palmer", + title = "The umldoc {UML} {D}ocumentation {P}ackage", + year = "1999", + url = "https://www.charvolant.org/elements/umldoc.pdf" +} + +@misc{tikzuml, + author = "Nicolas Kielbasiewicz", + title = "The {T}ik{Z}-{UML} package", + year = "2016", + url = "http://perso.ensta-paristech.fr/~kielbasi/tikzuml/var/files/doc/tikzumlmanual.pdf" +} + +@misc{svglatex, + author = "Johan B. C. Engelen", + title = "How to include an SVG image in LATEX", + url = "http://tug.ctan.org/info/svg-inkscape/InkscapePDFLaTeX.pdf" +} + +@misc{umlomg, + publisher = "Object Management Group", + title = "{OMG}® {U}nified {M}odeling {L}anguage® ({OMG} {UML}®)", + year = "2017", + url = "https://www.omg.org/spec/UML/2.5.1/" +} diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/metauml-manual.tex b/graphics/metapost/contrib/macros/metauml/examples/manual/metauml-manual.tex new file mode 100644 index 0000000000..933130a33d --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/metauml-manual.tex @@ -0,0 +1,2072 @@ +% MetaUML: Tutorial, Reference and Test Suite +% +% Copyright (c) 2005-2019 Ovidiu Gheorghies +% Permission is granted to copy, distribute and/or modify this document +% under the terms of the GNU Free Documentation License, Version 1.2 +% or any later version published by the Free Software Foundation; +% with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +% A copy of the license is included in the section entitled "GNU +% Free Documentation License". + +\documentclass{article} + +\usepackage[utf8]{inputenc} +\usepackage[pdftex,colorlinks=true]{hyperref} +\usepackage{multicol} +\usepackage{multido} +\usepackage[style=ieee]{biblatex} +\addbibresource{metauml-manual.bib} + +\ifx\pdftexversion\undefined + \usepackage[dvips]{graphicx} +\else + \usepackage[pdftex]{graphicx} + \DeclareGraphicsRule{*}{mps}{*}{} +\fi + +\newcommand{\code}{\ttfamily} + +\setcounter{page}{1} + +\begin{document} + +MetaUML: A Manual and Test Suite + +\begin{quote} + Copyright \copyright 2005-2019 Ovidiu Gheorghie\c{s}. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +\end{quote} + +\pagebreak +This page is intentionally left blank. + +\pagebreak +\title{MetaUML: A Manual and Test Suite} + +\author{Ovidiu Gheorghie\c{s}} + +\maketitle + +\begin{abstract} +MetaUML is a MetaPost \cite {metapost} library for creating UML \cite{umlomg} diagrams by means of a textual notation. +While presenting the inner workings of MetaUML, this manual doubles as a step-by-step tutorial. +More importantly, its source code contains many useful examples of diagrams, ranging from the very basic to the +more advanced and customized. +\end{abstract} + +\section{Introduction} + +Here is a quick MetaUML showcase: + +\begin{multicols}{2} +\paragraph{A} Class Diagram\\ +\includegraphics[scale=.55]{fig/appetizer.1} +\paragraph{B} Activity Diagram\\ +\includegraphics[scale=.55]{fig/appetizer.2} +\paragraph{C} Notes\\ +\includegraphics[scale=.55]{fig/appetizer.5} +\columnbreak +\paragraph{D} Use Case Diagram\\ +\includegraphics[scale=.55]{fig/appetizer.3} +\paragraph{E} State Machine Diagram\\ +\includegraphics[scale=.55]{fig/appetizer.4} +\paragraph{F} Package Diagram\\ +\includegraphics[scale=.55]{fig/appetizer.6} +\end{multicols} + +\pagebreak + +The code that generates these diagrams is quite straightforward, combining a natural object-oriented parlance +with the power of MetaPost equation solving. + +For example, a UML class is drawn as follows: + +\begin{multicols}{2} +\begin{verbatim} +Class.A("MyClass") + ("attr1: int", "attr2: int") + ("method1(): void", + "method2(): void"); + +A.nw = (0, 0); % optional, implied +drawObject(A); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/appetizer.7} +\end{multicols} + +This code creates a visual object, referenced by its name {\code A}, of the MetaUML-defined type {\code Class}. +Object {\code A} has the following content properties: a name +({\code MyClass}), a list of attributes ({\code attr1}, {\code attr2}) +and a list of methods ({\code method1}, {\code method2}). To set the object's location, we assign a value to the +so-called ``north-west'' point of the encompassing rectangle, {\code A.nw} --- a point which in actual fact references +the upper-left corner. + +Every MetaUML visual object has the layout properties shown in figure \ref{fig:properties}. +These properties may be used to set the location of any given object, either by assigning to them absolute values, +or by linking them relatively to other objects via equations. + +\begin{figure} +\centering +\includegraphics{fig/properties.1} +\caption{Layout properties of MetaUML objects. Here, a {\code Class} object is depicted.} +\label{fig:properties} +\end{figure} + +The following example demonstrates, respectively, the use of absolute and relative positioning for two classes, {\code A} and {\code B}. + +\begin{multicols}{2} +\begin{verbatim} +A.nw = (0,0); +B.w = A.e + (20, 0); +\end{verbatim} +\columnbreak +\includegraphics{fig/appetizer.8} +\end{multicols} + +After the objects have been drawn, it becomes possible to attach links to them. In a class diagram, inheritance +or association relations are meaningful links between classes, while in a state machine diagram, transitions between +states can be used. Here is the general pattern used by MetaUML for drawing links: + +\begin{verbatim} +link(<how-to-draw-information>)(<path-to-draw>); +\end{verbatim} + +The ``how-to-draw-information'' is an object which defines the style of the line (e.g. solid, dashed) and the appearance +of the heads (e.g. nothing, arrow, diamond). One such object, appropriately called {\code inheritance}, defines a solid +line style and a white triangle head. The other parameter, the ``path-to-draw'', is simply a MetaPost path. + +For example, the following call draws an inheritance relation from class {\code B} to class {\code A}. + +\begin{verbatim} +link(inheritance)(B.e -- A.w); +\end{verbatim} + +The direction of the path is important, as MetaUML uses it to determine the +type of adornment to attach to the link ends (if applicable). In our example, a white triangle, +denoting inheritance, points towards the end of the path, that is towards class {\code A}. + +Let us sum up with a diagram typical for MetaUML use. Firstly, we define the objects that we want to include +in our diagram. Secondly, we position these objects relative to each other. Thirdly, we draw the objects. Finally, we +draw the links, by referencing the layout properties of the previously drawn objects. Note that in our example the +positioning of {\code A} need not be set explicitly because ``floating'' objects are automatically positioned at +{\code (0,0)} by their draw method. + +\begin{multicols}{2} + +\begin{verbatim} +input metauml; + +beginfig(1); + Class.A("A")()(); % 1. Define the objects + Class.B("B")()(); + B.w = A.e + (20, 0); % 2. Position the objects + drawObjects(A, B); % 3. Draw the objects + link(inheritance)(B.w -- A.e); % 4. Draw links between objects +endfig; +end +\end{verbatim} +\columnbreak +\includegraphics{fig/appetizer.9} +\end{multicols} + +As far as a user is concerned, this is all there is to MetaUML. With a reference describing how the +UML elements are created, arbitrarily complex diagrams can be crafted. + +\section{Class Diagrams} + +A class is created as follows: + +\begin{verbatim} +Class.<name>(<class-name>) + (<list-of-attributes>) + (<list-of-methods>); +\end{verbatim} + +The suffix {\code <name>} specifies an identifier for the newly created {\code Class} object +(which, of course, represents a UML class). +The name of the UML class is a string given by {\code <class-name>}; +the attributes and methods are given as list of strings, {\code <list-of-attributes>} and {\code <list-of-methods>} +respectively. The list of attributes and the list of methods may be void. + +An attribute or a method string may begin with a visibility marker: ``$+$'' for +public, ``\#'' for protected, ``$-$'' for private, and ``\textasciitilde'' for package private. +The default visibility is package private. + +\begin{multicols}{2} +\begin{verbatim} +Class.A("Point") + ("#x:int", "#y:int") + ("+set(x:int, y:int)", + "+getX():int", + "+getY():int", + "-debug():void", + "test():void"); +drawObject(A); +\end{verbatim} +\columnbreak +\includegraphics{fig/class.1} +\end{multicols} + +To disable showing the visibility markers, use {\code Class\_noVisibilityMarkers}, as shown below: + +\begin{multicols}{2} +\begin{verbatim} + Class.A("Point") + ("#x:int", "#y:int") + ("+toString():String"); + Class_noVisibilityMarkers.A; + + drawObject(A); +\end{verbatim} +\columnbreak +\includegraphics{fig/class.15} +\end{multicols} + +\subsection{Stereotypes} + +After a class is created, but before it is drawn, its stereotypes may be specified by using {\code Class\_stereotypes}: + +\begin{verbatim} +Class_stereotypes.<name>(<list-of-stereotypes>); +\end{verbatim} + +Here, {\code <name>} is the object name of a previously created class and {\code <list-of-stereotypes>} +is a comma-separated list of strings. Here is an example: + +\begin{multicols}{2} +\begin{verbatim} +Class.A("User")()(); +Class_stereotypes.A("<<interface>>","<<home>>"); + +drawObject(A); +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/class.2} +\end{multicols} + +\subsection{Interfaces and Abstract Classes} + +At times it is preferred to write the name of an interface in an oblique font, rather than using the ``interface'' +stereotype. This can be easily achieved by using the macro {\code Interface}: + +\begin{verbatim} +Interface.name(class-name) + (list-of-methods); +\end{verbatim} + +Here is an example: + +\begin{multicols}{2} +\begin{verbatim} +Interface.A("Observer") + ("+update(src:Object)"); + +drawObject(A); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/class.11} +\end{multicols} + +Since internally {\code Interface} treated as a special kind of {\code Class}, the code above is equivalent to: +\begin{verbatim} +EClass.A(iInterface)("Observer")() + ("+update(src:Object)"); +\end{verbatim} + +Abstract classes can be drawn similarly using the {\code iAbstractClass} style: +\begin{samepage} +\begin{multicols}{2} +\begin{verbatim} +EClass.A(iAbstractClass)("Observable") + ("observers: Observer[0..*]") + ("+addObserver(o: Observer)", + "+notify()"); + +drawObject(A); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/class.12} +\end{multicols} +\end{samepage} + +If you prefer, you can use equivalent construct: + +\begin{verbatim} +AbstractClass.A("Observable") + ("observers: Observer[0..*]") + ("+addObserver(o: Observer)", + "+notify()"); +\end{verbatim} + +\subsection{Displaying Class Name Only} + +If you want the empty methods and attributes compartments in a class not being displayed, one way is to set the spacing +at their top and the bottom to {\code 0}: +\begin{samepage} +\begin{multicols}{2} +\begin{verbatim} +Class.A("MyModel")()(); +A.info.iName.top := 10; +A.info.iName.bottom := 10; +A.info.iAttributeStack.top := 0; +A.info.iAttributeStack.bottom := 0; +A.info.iMethodStack.top := 0; +A.info.iMethodStack.bottom := 0; + +drawObject(A); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/class.13} +\end{multicols} +\end{samepage} + +The same effect can be achieved by using the formatting information object {\code iClassNameOnly} or the {\code ClassName} macro: + +\begin{multicols}{2} +\begin{verbatim} +EClass.A(iClassNameOnly)("MyModel")()(); +ClassName.B("AnotherModel"); +Class_stereotypes.B("<<smart>>"); + +topToBottom(20)(A, B); + +drawObjects(A, B); +\end{verbatim} +\columnbreak +\hspace{2cm}\includegraphics{fig/class.14} +\end{multicols} + +To customize the space around the class name globally, you can set the values of {\code iClassNameOnly.iName.top} and {\code iClassNameOnly.iName.bottom}. Individually, for a given object, say {\code B}, the attributes {\code B.info.iName.top} and {\code B.info.iName.bottom} can be used. + +\subsection{Objects (or Class Instances)} + +A UML object (or class instance) is created as follows: + +\begin{verbatim} +Instance.name(object-name) + (list-of-attributes); +\end{verbatim} + +The suffix {\code name} gives a name to the {\code Instance} object. The name of the object (given by {\code object-name}) is typeset underlined. The attributes are given as a comma-separated list of strings, {\code list-of-attributes}. + +\begin{multicols}{2} +\begin{verbatim} +Instance.order("o: Order") + ("name='book'", "{placed}", "{payed}"); +drawObject(order); +\end{verbatim} +\columnbreak +\hspace{2cm}\includegraphics{fig/instance.1} +\end{multicols} + + +\subsection{Parametrized Classes (Templates)} + +The most convenient way of typesetting a class template in MetaUML is to use the macro {\code ClassTemplate}. +This macro creates a visual object which is appropriately positioned near the class object it adorns. + +\begin{verbatim} +ClassTemplate.name(list-of-templates) + (class-object); +\end{verbatim} + +The {\code name} is the name of the template object, {\code list-of-templates} is a comma-separated list of strings and the {\code class-object} is the name of a class object. + +Here is an example: + +\begin{multicols}{2} +\begin{verbatim} +Class.A("Vector")()(); +ClassTemplate.T("T", "size: int")(A); + +drawObjects(A, T); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/class.3} +\end{multicols} + +The macro {\code Template} can also be used to create a template object, but this time the resulting +object can be positioned freely. + +\begin{verbatim} +Template.name(list-of-templates); +\end{verbatim} + +Of course, it is possible to specify both stereotypes and template parameters for a given class. + +\subsection{Types of Links} + +In this section we enumerate the relations that can be drawn between classes by means +of MetaUML macros. Suppose that we have the declared two points, {\code A} (on the left) +and {\code B} (on the right): + +\begin{verbatim} +pair A, B; +A = (0,0); +B = (50,0); +\end{verbatim} + +\begin{tabular}{||l|c||} +\hline +{\code link(association)(X.e -- Y.w)} & \includegraphics{fig/class_diagrams.4} \\ +\hline +{\code link(associationUni)(X.e -- Y.w)} & \includegraphics{fig/class_diagrams.5} \\ +\hline +{\code link(inheritance)(X.e -- Y.w)} & \includegraphics{fig/class_diagrams.6} \\ +\hline +{\code link(realization)(X.e -- Y.w)} & \includegraphics{fig/class_diagrams.12} \\ +\hline +{\code link(aggregation)(X.e -- Y.w)} & \includegraphics{fig/class_diagrams.7} \\ +\hline +{\code link(aggregationUni)(X.e -- Y.w)} & \includegraphics{fig/class_diagrams.8} \\ +\hline +{\code link(composition)(X.e -- Y.w)} & \includegraphics{fig/class_diagrams.9} \\ +\hline +{\code link(compositionUni)(X.e -- Y.w)} & \includegraphics{fig/class_diagrams.10} \\ +\hline +{\code link(dependency)(X.e -- Y.w)} & \includegraphics{fig/class_diagrams.11} \\ +\hline +\end{tabular} + +\subsection{Associations} +In UML an association typically has two of association ends and may have a name specified for it. +In turn, each association end may specify a multiplicity, a role, a visibility, an ordering. +These entities are treated in MetaUML as pictures having specific drawing information +(spacings, font). + +The first method of creating association ``items'' is by giving them explicit names. +Having a name for an association item comes in handy when referring to its properties +is later needed (see the non UML-compliant diagram below). The last parameter of the macro {\code item} is an equation which may use the item's name to perform positioning. + +\begin{multicols}{2} +\begin{verbatim} +Class.P("Person")()(); +Class.C("Company")()(); +% drawing code ommited + +item.aName(iAssoc)("works for") + (aName.s = .5[P.w, C.w]); +draw aName.n -- (aName.n + (20,20)); +label.urt("association name" infont "tyxtt", + aName.n + (20,20)); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics[scale=.8]{fig/class_association.1} +\end{multicols} + +However, giving names to every association item may become an annoying burden +(especially when there are many of them). Because of this, MetaUML also allows for +``anonymous items''. In this case, the positioning is set by an equation +which refers to the anonymous item as {\code obj}. + +\begin{multicols}{2} +\begin{verbatim} +% P and C defined as in the previous example + +item(iAssoc)("employee")(obj.nw = P.s); +item(iAssoc)("1..*")(obj.ne = P.s); + +% other items are drawn similarly +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/class_association.2} +\end{multicols} + +\subsection{Dependencies and Stereotypes} + +Stereotypes are frequently used with dependencies. Below is an example. +\pagebreak + +\begin{multicols}{2} +\begin{verbatim} +Class.F("Factory")()(); +Class.O("Object")()(); + +O.n = F.s - (0, 50); +drawObjects(F, O); + +clink(dependency)(F, O); +item(iStereo)("<<creates>>")(obj.w = .5[F.s,O.n]) +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/class_association.3} +\end{multicols} + +\section{Notes} + +A note is created as follows: + +\begin{verbatim} +Note.name(list-of-lines); +\end{verbatim} + +The suffix {\code name} is the name of the {\code Note} object. The contents of the note is given by a comma-separated +list of strings, {\code list-of-lines}, gives the text contents of the note object, each string being drawn on its own +line. + +Here is an example: + +\begin{multicols}{2} +\begin{verbatim} +Note.A("This note", "has two lines."); +drawObject(A); +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/note.1} +\end{multicols} + +\subsection{Attaching notes to diagram elements} + +Notes can be attached to diagram elements by using a link of type {\code dashedLink}. + +\begin{multicols}{2} +\begin{verbatim} +Note.A("This is a class"); +Class.C("Object")()(); + +A.sw = C.ne + (20, 20); + +drawObject(A, C); + +clink(dashedLink)(A, C); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/note.2} +\end{multicols} + +Now let us see a more complex example, which demontrates the ability of accessing sub-elements in a MetaUML diagram. +\pagebreak + +\begin{multicols}{2} +\begin{verbatim} +Note.nA("This is the class name"); +Note.nB("This is a key attribute"); +Note.nC("This is a nice method"); + +Class.C("Object")("+id:int") + ("+clone()", "+serialize()"); + +topToBottom.left(10)(nA, nB, nC); +leftToRight(10)(C, nB); + +drawObjects(C, nA, nB, nC); + +clink(dashedLink)(C.namePict, nA); +clink(dashedLink)(C.attributeStack.pict[0], nB); +clink(dashedLink)(C.methodStack.pict[1], nC); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/note.3} +\end{multicols} + +Macros like {\code leftToRight} and {\code topToBottom} are presented in section \ref{section:positioning}. + +\subsection{Using mathematical formulae} + +MetaUML notes can contain mathematical formulae written in TeX \cite{texbook}. Regretably, LaTeX \cite{latexbook} support for formulae is {\bf not} available. +Limited as it may be, this feature is considered experimental, as it is not always straightforward to use. In the example below, note that the MetaPost package {\code TEX} is imported. + +\begin{multicols}{2} +\begin{verbatim} +input metauml; +input TEX; + +beginfig(1); + Note.A("This class implements the formula:", + TEX("$\sum_1^n f(x) \cdot dx$")); + drawObjects(A); +endfig; + +end +\end{verbatim} +\columnbreak +\hspace{0.5cm}\includegraphics{fig/note.4} +\end{multicols} + +For taller formulae, you must be prepared to do some advanced stunts. Remark: {\code "aaa" \& "bbb"} is MetaPost's way to concatenate the strings into {\code "aaabbb"}; +the string containing the formula was split in two for layout reasons. + +\begin{multicols}{2} +\begin{verbatim} +Note.A("Can you do it?", + TEX("$\sum_1^n f(x) \cdot dx " & + "\over \sum_1^m g(y) \cdot dy$")); +A.stack.info.spacing := 30; +A.stack.pict[1].info.ignoreNegativeBase := 0; + +drawObject(A); +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/note.5} +\end{multicols} + +Alas, this trick does not entirely solve the problem: a third line in the note would be badly aligned. Therefore, +until MetaUML's {\code Note} class is upgraded to better support this scenario, you may want to limit yourself +to two lines per note --- at least when tall formulae are involved. + +\section{Packages} + +MetaUML allows for the creation of packages in various forms. Firstly, we have the option of writing the package +name in the middle of the main box. Secondly, we can write the name on the tiny box above the main box, leaving +the main box empty. Lastly, we can write the package name as in the second case, but the main box can have an arbitrary +contents: classes, other packages, or even other UML items. + +The macro that creates a package has the following synopsis: + +\begin{verbatim} +Package.name(package-name)(subitems-list); +\end{verbatim} + +The parameter {\code package-name} is a string or a list of comma-separated strings representing the package's name. +The {\code subitems-list} parameter is used to specify the subitems (tipically classes or packages) of this package; +its form is as a comma-separated list of objects, which can be void. + +\begin{multicols}{2} +\begin{verbatim} +Package.P("java.lang")(); +drawObject(P); +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/package.1} +\end{multicols} + +Below is another example: + +\begin{multicols}{2} +\begin{verbatim} +Package.P("An important", "package")(); +drawObject(P); +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/package.2} +\end{multicols} + +If you wish to leave the main box empty, you can use the following code: + +\begin{multicols}{2} +\begin{verbatim} +Package.P("java.lang")(); +P.info.forceEmptyContent := 1; +drawObject(P); +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/package.3} +\end{multicols} + +The same effect as above can be achieved globally by doing: + +\begin{verbatim} +iPackage.forceEmptyContent := 1; +\end{verbatim} + +More information on MetaUML's way of managing global and per-object configuration data can be found in +section \ref{section:infrastructure} and section \ref{section:customization}. + +Here is an example involving items contained in a package. + +\begin{multicols}{2} +\begin{verbatim} +Class.A("A")()(); +Class.B("B")()(); +Package.P("net.metauml")(A, B); + +leftToRight(10)(A, B); + +drawObject(P); +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/package.4} +\end{multicols} + +\subsection{Types of Links} + +The nesting relation between packages is created by using the {\code nest} link information. + +\begin{tabular}{||l|c||} +\hline +{\code link(nest)(X.e -- Y.w)} & \includegraphics{fig/package.5} \\ +\hline +\end{tabular} + +\section{Component Diagrams} + +A component is created by the macro {\code Component}: + +\begin{verbatim} +Component.name(component-name) + (subitems-list) +\end{verbatim} + +The parameter {\code component-name} is a string representing the component's name. The {\code subitems-list} parameter +is used to specify the subitems of this component (possibly classes, packages or other components); its form is as a +comma-separated list of objects, which can be void. + +\begin{multicols}{2} +\begin{verbatim} +Component.C("Business Logic")(); +drawObject(C); +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/component.1} +\end{multicols} + +Here is an example involving subitems in a component: + +\begin{multicols}{2} +\begin{verbatim} +Class.A("A")()(); +Package.B("B")(); +Component.C("C")(); + +Component.BigC("Big Component")(A, B, C); + +leftToRight(10)(A, B); +topToBottom(10)(A, C); + +drawObject(BigC); +\end{verbatim} +\columnbreak +\hspace{3cm}\includegraphics{fig/component.2} +\end{multicols} + +\subsection{Types of Links} + +\begin{tabular}{||l|c||} +\hline +{\code link(requiredInterface)( A.e -- .5[A.e, B.w] );} & \includegraphics{fig/component.3} \\ +\hline +{\code link(providedInterface)( .5[A.e, B.w] -- B.w );} & \includegraphics{fig/component.4} \\ +\hline +\end{tabular} + +\vspace{0.5cm} + +The {\code requiredInterface} and {\code providedInterface} visual constructs can be easily combined, as shown in the following example: + +\begin{multicols}{2} +\begin{verbatim} +Component.A("A")(); +Component.B("B")(); + +leftToRight(80)(A, B); + +drawObjects(A, B); + +link(providedInterface)( A.e -- .5[A.e, B.w] ); +link(requiredInterface)( B.w -- .5[A.e, B.w] ); +\end{verbatim} +\columnbreak +\hspace{-1cm}\includegraphics{fig/component.5} +\end{multicols} + + +\section{Use Case Diagrams} + +\subsection{Use Cases} +An use case is created by the macro {\code Usecase}: + +\begin{verbatim} +Usecase.name(list-of-lines); +\end{verbatim} + +The {\code list-of-lines} is a comma-separated list of strings. These strings are placed +on top of each other, centered and surrounded by the appropriate visual UML notation. + +Here is an use case example: + +\begin{multicols}{2} +\begin{verbatim} +Usecase.U("Authenticate user", + "by name, password"); +drawObject(U); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/usecase.1} +\end{multicols} + +\subsection{Actors} + +An actor is created by the macro {\code Actor}: + +\begin{verbatim} +Actor.name(list-of-lines); +\end{verbatim} + +Here, {\code list-of-lines} represents the actor's name. For convenience, the name may be +given as a list of strings which are placed on top of each other, to provide support for +the situations when the role is quite long. Otherwise, giving a single string +as an argument to the Actor constructor is perfectly fine. + +Here is an actor example: + +\begin{multicols}{2} +\begin{verbatim} +Actor.A("User"); +drawObject(A); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/usecase.2} +\end{multicols} + +Sometimes it may be preferable to draw diagram relations positioned relatively to +the visual representation of an actor (the ``human'') rather than relatively to the whole +actor object (which also includes the text). Because of that, MetaUML provides access +to the ``human'' of every actor object {\code actor} by means of the sub-object {\code actor.human}. + +\begin{multicols}{2} +\begin{verbatim} +Actor.A("Administrator"); +drawObject(A); +draw objectBox(A); +draw objectBox(A.human); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/usecase.3} +\end{multicols} + +In MetaUML, {\code objectBox(X)} is equivalent to {\code X.nw -- X.ne -- X.se -- X.sw -- cycle} for every object {\code X}. {\code A.human} is considered a MetaUML object, so you can use expressions like {\code A.human.n} or {\code A.human.midx}. + +\subsection{Types of Links} + +Some of the types of links defined for class diagrams (such as inheritance, association etc.) can be used with similar semantics within use case diagrams. + +\section{Activity Diagrams} + +\subsection{Begin, End and Flow End} + +The begin and the end of an activity diagram can be marked by using the macros {\code Begin} +and {\code End} or {\code FlowFinal}, respectively. The constructors of these visual objects take no parameters: + +\begin{verbatim} +Begin.beginName; +End.endName; +\end{verbatim} + +Below is an example: + +\begin{multicols}{2} +\begin{verbatim} +Begin.b; +End.e; +FlowFinal.f; + +leftToRight(20)(b, e, f); + +drawObjects(b, e, f); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/activity.1} +\end{multicols} + +\subsection{Activity} + +An activity is constructed as follows: +\begin{verbatim} +Activity.name(list-of-strings); +\end{verbatim} + +The parameter {\code list-of-strings} is a comma-separated list of strings. These strings are +centered on top of each other to allow for the accommodation of a longer activity description +within a reasonable space. + +An example is given below: + +\begin{multicols}{2} +\begin{verbatim} +Activity.A("Learn MetaUML -", + "the MetaPost UML library"); +drawObject(A); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/activity.2} +\end{multicols} + +\subsection{Fork and Join} + +A fork or join is created by the macro: + +\begin{verbatim} +Fork.name(type, length); +\end{verbatim} + +The parameter {\code type} is a string and can be either of {\code "h"}, {\code "horiz"}, {\code "horizontal"} +for horizontal bars, and either of {\code "v"}, {\code "vert"}, {\code "vertical"} for vertical bars. +The {\code length} gives the bar's length. + +\begin{multicols}{2} +\begin{verbatim} +Fork.forkA("h", 100); +Fork.forkB("v", 20); + +leftToRight(10)(forkA, forkB); + +drawObject(forkA, forkB); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/activity.3} +\end{multicols} + +\subsection{Branch} + +A branch is created by the macro: + +\begin{verbatim} +Branch.name; +\end{verbatim} + +Here is an example: + +\begin{multicols}{2} +\begin{verbatim} +Branch.testA; + +drawObject(testA); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/activity.4} +\end{multicols} + + +\subsection{Types of Links} + +In activity diagrams, transitions between activities are needed. They are typeset +as in the example below. In section \ref{composite-states} such a transition +is showed. This type of link is also used for state machine diagrams. + +\begin{verbatim} +link(transition)( pointA -- pointB ); +\end{verbatim} + +\section{State Diagrams} + +The constructor of a state allows for aggregated sub-states: + +\begin{verbatim} +State.name(state-name)(substates-list); +\end{verbatim} + +The parameter {\code state-name} is a string or a list of comma-separated strings representing +the state's name or description. The {\code substates-list} parameter is used to specify +the substates of this state as a comma-separated list of objects; this list may be void. + +An example of a simple state: + +\begin{multicols}{2} +\begin{verbatim} +State.s("Take order")(); +drawObject(s); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/state.1} +\end{multicols} + + +\subsection{Composite States} +\label{composite-states} + +A composite state is defined by enumerating at the end of its constructor the inner +states. Interestingly enough, the composite state takes care of drawing the sub-states it +contains. The transitions must be drawn after the composite state, as seen in the +next example: + +\begin{multicols}{2} +\begin{verbatim} +Begin.b; +End.e; +State.c("Component")(); +State.composite("Composite")(b, e, c); + +b.midx = e.midx = c.midx; +c.top = b.bottom - 20; +e.top = c.bottom - 20; + +composite.info.drawNameLine := 1; +drawObject(composite); + +link(transition)(b.s -- c.n); +link(transition)(c.s -- e.n); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/state.2} +\end{multicols} + +\subsection{Internal Transitions} + +Internal transitions can be specified by using the macro: +\begin{verbatim} +stateTransitions.name(list-transitions); +\end{verbatim} + +Identifier {\code name} gives the state object whose internal transitions are being set, +and parameter {\code list-transitions} is a comma-separated string list. + + +An example is given below: + +\begin{multicols}{2} +\begin{verbatim} +State.s("An interesting state", + "which is worth mentioning")(); +stateTransitions.s( + "OnEntry / Open eyes", + "OnExit / Sleep well"); +s.info.drawNameLine := 1; + +drawObject(s); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/state.3} +\end{multicols} + +\subsection{Special States} + +Similarly to the usage of {\code Begin} and {\code End} macros, one can define history states, +exit/entry point states and terminate pseudo-states, by using the following constructors. + +\begin{verbatim} +History.nameA; +ExitPoint.nameB; +EntryPoint.nameC; +Terminate.nameD; +\end{verbatim} + +\section{Drawing Paths} + +The {\code link} macro is powerful enough to draw relations following arbitrary paths: + +\begin{multicols}{2} +\begin{verbatim} +path cool; +cool := A.e .. A.e+(20,10) .. + B.s+(20,-40) .. B.s+(-10,-30) + -- B.s; +link(inheritance)(cool); + +link(aggregationUni) + (A.n ..(30,30)..B.w); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/paths.1} +\end{multicols} + +Amusing as it may be, this feature gets old soon. When typesetting UML diagrams in good style, rectangular paths are usually preferred. +It is for this kind of paths that MetaUML offers extensive support, by means of ``syntactic sugar'' constructs which +are not only self-documenting, but reduce the amount of typing and thinking required. + +\subsection{Manhattan Paths} + +The ``Manhattan'' path macros generate a path between two points consisting of one +horizontal and one vertical segment. The macro {\code pathManhattanX} generates first a +horizontal segment, while the macro {\code pathManhattanY} generates first a +vertical segment. In MetaUML it also matters the direction of a path, so you +can choose to reverse it by using {\code rpathManhattanX} and {\code rpathManhattanY} +(note the prefix ``{\code r}''): + +\begin{verbatim} +pathManhattanX(A, B) +pathManhattanY(A, B) + +rpathManhattanX(A, B) +rpathManhattanY(A, B) +\end{verbatim} + +\pagebreak +Here is an example: + +\begin{multicols}{2} +\begin{verbatim} +Class.A("A")()(); +Class.B("B")()(); + +B.sw = A.ne + (10,10); +drawObjects(A, B); + +link(aggregationUni) + (rpathManhattanX(A.e, B.s)); +link(inheritance) + (pathManhattanY(A.n, B.w)); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/paths.2} +\end{multicols} + +\subsection{Stair Step Paths} + +These path macros generate stair-like paths between two points. +The ``stair'' can ``rise'' first in the direction of $Ox$ axis ({\code pathStepX}) +or in the direction of $Oy$ axis ({\code pathStepY}). How much should a step +rise is given by an additional parameter, {\code delta}. Again, the macros +prefixed with ``{\code r}'' reverse the direction of the path given by their +unprefixed counterparts. + +\begin{verbatim} +pathStepX(A, B, delta) +pathStepY(A, B, delta) + +rpathStepX(A, B, delta) +rpathStepY(A, B, delta) +\end{verbatim} + +Here is an example: + +\begin{multicols}{2} +\begin{verbatim} +stepX:=60; +link(aggregationUni) + (pathStepX(A.e, B.e, stepX)); + +stepY:=20; +link(inheritance) + (pathStepY(B.n, A.n, stepY)); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/paths.3} +\end{multicols} + +\subsection{Horizontal and Vertical Paths} + +There are times when drawing horizontal or vertical links is required, +even when the objects are not properly aligned. To this aim, the following macros +are useful: + +\begin{verbatim} +pathHorizontal(pA, untilX) +pathVertical(pA, untilY) + +rpathHorizontal(pA, untilX) +rpathVertical(pA, untilY) +\end{verbatim} + +A path created by {\code pathHorizonal} starts from the point {\code pA} +and continues horizontally until coordinate {\code untilX} is reached. The macro +{\code pathVertical} constructs the path dually, working vertically. +The prefix ``{\code r}'' reverses the direction of the path. + +Usage example: + +\begin{multicols}{2} +\begin{verbatim} +untilX := B.left; +link(association) + (pathHorizontal(A.e, untilX)); + +untilY:= C.bottom; +link(association) + (pathVertical(A.n, untilY)); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/paths.4} +\end{multicols} + +\subsection{Direct Paths} + +A direct path can be created with {\code directPath}. The call {\code directPath(A, B)} +is equivalent to {\code A -{}- B}. + +\subsection{Paths between Objects} + +Using the constructs presented above, links between diagram objects are drawn easily like this: + +\begin{verbatim} +link(transition)(directPath(objA.nw, objB.se)); +\end{verbatim} + +There are times however when this direct approach may yield unsatisfactory visual results, +especially when the object's corners is round. To tackle these situations, MetaUML provides the macro +{\code pathCut}, whose aim is to limit a given path exactly to the region outside the actual +borders of the objects it connects. The macro's synopsis is: + +\begin{verbatim} +pathCut(thePath)(objectA, objectB) +\end{verbatim} + +Here, {\code thePath} is a given MetaPost path and {\code objectA} and {\code objectB} +are two MetaUML objects. By contract, each MetaUML object of type, say, {\code X} +defines a macro {\code X\_border} which returns the path that surrounds it. Because +of that, {\code pathCut} can make the appropriate modifications to {\code thePath}. + +The following code demonstrates the benefits of the {\code pathCut} macro: + +\begin{multicols}{2} +\begin{verbatim} +z = A.se + (30, -10); +link(transition) + (pathCut(A, B)(A.c--z--B.c)); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/paths.5} +\end{multicols} + +\subsubsection{Direct Paths between Centers} + +At times is quicker to just draw direct paths between the center of two objects, +minding of course the object margins. The macro which does this is {\code clink}: + +\begin{verbatim} +clink(how-to-draw-information)(objA, objB); +\end{verbatim} + +The parameter {\code how-to-draw-information} is the same as for the macro {\code link}; +{\code objA} and {\code objB} are two MetaUML objects. + +Below is an example which involves the inheritance relation: + +\begin{multicols}{2} +\begin{verbatim} +clink(inheritance)(A, B); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/paths.6} +\end{multicols} + +\section{Arranging Diagram Items} +\label{section:positioning} + +Using equations involving cardinal points, such as {\code A.nw = B.ne + (10,0)}, is +good enough for achieving the desired results. However, programs are best to +be written for human audience, rather than for compilers. It does become a bit +tiresome to think all the time of cardinal points and figure out the +direction of positive or negative offsets. Because of that, MetaUML offers +syntactic sugar which allows for an easier understanding of the intent behind +the positioning code. + +Suppose that we have three classes, {\code A}, {\code B}, {\code C} and their base class +{\code Base}. We want the base class to be at the top, and the derived classes to be +on a line below. This code will do: + +\begin{verbatim} +A.ne = B.nw + (20,0); +B.ne = C.nw + (20,0); +Base.s = B.n + (0,-20); +\end{verbatim} + +Unfortunately, writing code such as this makes it hard for fellow programmers to visualize +its intent upon reading it. And ``fellow programmers`` include the author, five minutes later. + +Perhaps the next version of the code will drive home the point. The outcome is +the same as before, but the layout is stated in a more human-friendly way. You might even +infer by yourself that the numeric argument represents the distance between the objects. + +\begin{multicols}{2} +\begin{verbatim} +leftToRight(20)(A, B, C); +topToBottom(20)(Base, B); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/positioning.2} +\end{multicols} + +Below there are examples which show how these macros can be used. Suppose that we have the +following definitions for objects {\code X}, {\code Y}, and {\code Z}; also, let's assume +that {\code spacing} is a numeric variable set to {\code 5}. + +\begin{verbatim} +Picture.X("a"); +Picture.Y("..."); +Picture.Z("Cyan"); +\end{verbatim} + +\begin{tabular}{||l|c||} +\hline +{\code leftToRight.top(spacing)(X, Y, Z);} & \includegraphics{fig/positioning.3} \\ +\hline +{\code leftToRight.midy(spacing)(X, Y, Z);} & \includegraphics{fig/positioning.4} \\ +\hline +{\code leftToRight.bottom(spacing)(X, Y, Z);} & \includegraphics{fig/positioning.5} \\ +\hline +{\code topToBottom.left(spacing)(X, Y, Z);} & \includegraphics{fig/positioning.6} \\ +\hline +{\code topToBottom.midx(spacing)(X, Y, Z);} & \includegraphics{fig/positioning.7} \\ +\hline +{\code topToBottom.right(spacing)(X, Y, Z);} & \includegraphics{fig/positioning.8} \\ +\hline +\end{tabular} \\ + +To make things even easier, the following equivalent contructs are also allowed: + +\begin{verbatim} +leftToRight.midy(spacing)(X, Y, Z); +leftToRight(spacing)(X, Y, Z); +\end{verbatim} + +\begin{verbatim} +topToBottom.midx(spacing)(X, Y, Z); +topToBottom(spacing)(X, Y, Z); +\end{verbatim} + +If you want to specify that some objects have a given property equal, while the distance between them is given elsewhere, you can use the macro {\code same}. +This macro accepts a variable number of parameters, but at least two. The following table gives the interpretation of the macro for a simple example. + +\begin{tabular}{||l|l||} +\hline +{\code same.top(X, Y, Z);} & {\code X.top = Y.top = Z.top;} \\ +\hline +{\code same.midy(X, Y, Z);} & {\code X.midy = Y.midy = Z.midy;} \\ +\hline +{\code same.bottom(X, Y, Z);} & {\code X.bottom = Y.bottom = Z.bottom;} \\ +\hline +{\code same.left(X, Y, Z);} & {\code X.left = Y.left = Z.left;} \\ +\hline +{\code same.midx(X, Y, Z);} & {\code X.midx = Y.midx = Z.midx;} \\ +\hline +{\code same.right(X, Y, Z);} & {\code X.right = Y.right = Z.right;} \\ +\hline +\end{tabular} \\ + +Relative positions of two points can be declared more easily using the macros {\code below}, {\code above}, {\code atright}, {\code atleft}. +Let us assume that {\code A} and {\code B} are two points (objects of type {\code pair} in MetaPost). The following constructs are equivalent: + +\begin{tabular}{||l|l||} +\hline +{\code B = A + (5,0);} & {\code B = atright(A, 5);} \\ +{\code B = A - (5,0);} & {\code B = atleft(A, 5);} \\ +{\code B = A + (0,5);} & {\code B = above(A, 5);} \\ +{\code B = A - (0,5);} & {\code B = below(A, 5);} \\ +\hline +\end{tabular} + + +\section{The MetaUML Infrastructure} +\label{section:infrastructure} + +MetaPost is a macro language based on equation solving. Using it may seem quite +tricky at first for a programmer accustomed to modern object-oriented languages. +However, the great power of MetaPost consists in its versatility. Indeed, it is possible to write +a system which mimics quite well object-oriented behavior. Along this line, METAOBJ +\cite{metaobj} is a library worth mentioning: it provides a high-level objects +infrastructure along with a battery of predefined objects. + +Surprisingly enough, MetaUML does not use METAOBJ. Instead, it uses a custom written, +lightweight object-oriented infrastructure, provisionally called ``{\code util}''. +METAOBJ's facilities, although impressive, were perceived by me as being a bit too much +for what was initially intented as a quick way of getting some UML diagrams layed out. +Inspired by METAOBJ, ``{\code util}'' was designed to fulfill with minimal effort +the specific tasks needed to confortably position, allign or group visual objects +which include text. + +Another library having some object-oriented traits is the {\code boxes} +library, which comes with the standard MetaPost distribution. Early versions of +MetaUML did use {\code boxes} as an infrastructure, but this approach had to be abandoned eventually. +The main reason was that it was difficult to achieve good visual results when stacking texts +(more on that further on). For all it's worth, it did not fit well with the way in which MetaUML's +layout mechanism was shaping up at the time. + +\subsection{Motivation} + +Suppose that we want to typeset two texts with their bottom lines aligned, using {\code boxit}: + +\begin{multicols}{2} +\begin{verbatim} +boxit.a ("yummy"); +boxit.b ("cool"); + +a.nw = (0,0); b.sw = a.se + (10,0); + +drawboxed (a, b); % or drawunboxed(a,b) +draw a.sw -- b.se dashed evenly + withpen pencircle scaled 1.1; +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/boxes_vs_util.1} +\end{multicols} + +Note that, despite supposedly having their bottom lines alligned, +``yummy'' {\it looks} slightly higher than ``cool''. This would be unacceptable +in a UML class diagram, when roles are placed at the ends of a horizontal association. +Regardless of the default spacing being smaller in the {\code util} library, +the very same unfortunate misalignment effect rears its ugly head: + +\begin{multicols}{2} +\begin{verbatim} +Picture.a("yummy"); +Picture.b("cool"); +% comment next line for unboxed +a.info.boxed := b.info.boxed := 1; + +b.sw = a.se + (10,0); + +drawObjects(a, b); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/boxes_vs_util.2} +\end{multicols} + +However, the strong point of {\code util} is that we have a recourse to this problem: + +\begin{multicols}{2} +\begin{verbatim} +iPict.ignoreNegativeBase := 1; + +Picture.a("yummy"); +Picture.b("cool"); +% the rest the same as above +drawObjects(a, b); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/boxes_vs_util.3} +\end{multicols} + +\subsection{The Picture Macro} + +We have seen previously the line {\code iPict.ignoreNegativeBase := 1}. +Who is {\code iPict} and what is it doing in our program? MetaUML +aims at separating the ``business logic'' (what to draw) from the +``interface'' (how to draw). In order to achieve this, it records the ``how to draw'' +information within the so-called {\code Info} structures. The object {\code iPict} +is an instance of {\code PictureInfo} structure, which has the following properties +(or attributes): +\begin{verbatim} +left, right, top, bottom +ignoreNegativeBase +boxed, borderColor +\end{verbatim} + +The first four attributes specify how much space should be left around the +actual item to be drawn. The marvelous effect of {\code ignoreNegativeBase} +has just been shown (off), while the last two attributes control whether the border +should be drawn (when {\code boxed=1}) and if drawn, in which color. + +There's one more thing: the font to typeset the text in. This is specified +in a {\code FontInfo} structure which has two attributes: the font name +and the font scale. This information is kept within the {\code PictureInfo} structure +as a contained attribute {\code iFont}. Both {\code FontInfo} and {\code PictureInfo} +have ``copy constructors'' which can be used to make copies. We have already +the effect of these copy constructors at work, when we used: + +\begin{verbatim} +Picture.a("yummy"); +a.info.boxed := 1; +\end{verbatim} + +A copy of the default info for a picture, {\code iPict}, has been made within +the object {\code a} and can be accessed as {\code a.info}. Having a copy of the +info in each object may seem like an overkill, but it allows for a fine grained +control of the drawing mode of each individual object. This feature comes in very +handy when working with a large number of settings, as it is the case for MetaUML. + +Let us imagine for a moment that we have two types of text to write: one with a small font +and a small margin and one with a big font and a big margin. We could in theory +configure each individual object or set back and forth global parameters, but +this is far for convenient. It is preferable to have two sets of settings and specify +them explicitly when they are needed. The following code could be placed somewhere +in a configuration file and loaded before any {\code beginfig} macro: +\begin{verbatim} +PictureInfoCopy.iBig(iPict); +iBig.left := iBig.right := 20; +iBig.top := 10; +iBig.bottom := 1; +iBig.boxed := 1; +iBig.ignoreNegativeBase := 1; +iBig.iFont.name := defaultfont; +iBig.iFont.scale := 3; + +PictureInfoCopy.iSmall(iPict); +iSmall.boxed := 1; +iSmall.borderColor := green; +\end{verbatim} + +Below is an usage example of these definitions. Note the name of the macro: {\code EPicture}. +The prefix comes form ``explicit'' and it's used to acknowledge that the +``how to draw'' information is given explicitly --- as a parameter, +rather than defaulted to what's recorded in {\code iPict}, as with the {\code Picture} macro. +Having predefined configurations yields short, convenient code. + +\begin{multicols}{2} +\begin{verbatim} +EPicture.a(iBig)("yummy"); +EPicture.b(iSmall)("cool"); +% you can still modify a.info, b.info + +b.sw = a.se + (10,0); + +drawObjects(a, b); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/picture_info.1} +\end{multicols} + +\subsubsection{Fixed Sizes} + +By default, the size of a {\code Picture} object is set by its contents. However, +it is possible to specify fixed dimensions both the width and the height, independently. +This can be done by setting the {\code info}'s attributes {\code fixedWidth} and {\code fixedHeight} to values +greater than 0. If any of these attributes is left to its default value, {\code -1}, then for the corresponding +axis the dimension is set according to the dimension of the content. Nevertheless, the fixed dimensions are enforced, even though the contained object would have needed additional space. + +\begin{multicols}{2} +\begin{verbatim} +PictureInfoCopy.myFixed(iPict); +myFixed.ignoreNegativeBase := 1; +myFixed.fixedWidth := 15; +myFixed.fixedHeight := 20; +myFixed.boxed := 1; + +EPicture.a(myFixed)("a"); +EPicture.b(myFixed)(".-."); +EPicture.c(myFixed)("toolong"); + +leftToRight.bottom(10)(a, b, c); + +drawObjects(a, b, c); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/picture_info.2} +\end{multicols} + +\subsubsection{Content alignment} + +When fixed dimensions are used, one most likely would prefer a centered alignement of the contents in the +{\code Picture} box. This option can be expressed independently for each of the axes, +by setting the {\code info}'s attributes {\code valign} and {\code halign} to descriptive string values. +For horizontal alignement, {\code halign} can be set to {\code "left"} or {\code "center"}, and for +vertical alignement, {\code valign} can be set to {\code "bottom} or {\code "center"}. The default +values for these attributes are {\code "left"} and {\code "bottom"}, respectively. + +The next example uses horizontal centered alignement and a bottom alignement with a {\code 4.5} base offset, for +vertical alignement. This vertical alignement gives a better visual result than the centered one, at +least for the situations in which there are texts to be placed horizontally. + +\begin{multicols}{2} +\begin{verbatim} +PictureInfoCopy.myFixed(iPict); +myFixed.ignoreNegativeBase := 1; +myFixed.bottom := 4.5; +myFixed.valign := "bottom"; +myFixed.halign := "center"; +myFixed.fixedWidth := 25; +myFixed.fixedHeight := 15; +myFixed.boxed := 1; + +EPicture.a(myFixed)("a"); +EPicture.b(myFixed)("yum"); +EPicture.c(myFixed)("b"); + +leftToRight.bottom(10)(a, b, c); + +drawObjects(a, b, c); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/picture_info.3} +\end{multicols} + +\subsection{Stacking Objects} + +It is possible to stack objects, much in the style of {\code setboxjoin} +from {\code boxes} library. + +\begin{multicols}{2} +\begin{verbatim} +Picture.a0("yummy"); +Picture.a1("cool"); +Picture.a2("fool"); + +setObjectJoin(pa.sw = pb.nw); +joinObjects(scantokens listArray(a)(3)); + +drawObjects(scantokens listArray(a)(3)); +% or drawObjects (a0, a1, a2); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/object_stack.1} +\end{multicols} + +The {\code listArray} macro provides here a shortcut for writing +{\code a0, a1, a2}. This macro is particularly useful for generic +code which does not know beforehand the number of elements to be drawn. +Having to write the {\code scantokens} keyword is admittedly a nuisance, but +this is required. + + +\subsection{The Group Macro} + +It is possible to group objects in MetaUML. This feature is the cornerstone +of MetaUML, allowing for the easy development of complex objects, such as +composite stats in state machine diagrams. + +Similarly to the macro {\code Picture}, the structure {\code GroupInfo} +is used for specifying group properties; its default instantiation is +{\code iGroup}. Furthermore, the macro {\code EGroup} explicitely sets the +layout information. + +Here is an example: + +\begin{multicols}{2} +\begin{verbatim} +iGroup.left:=20; +iGroup.right:=15; +iGroup.boxed:=1; +iPicture.boxed:=1; + +Picture.a("yummy"); +Picture.b("cool"); +Picture.c("fool"); + +b.nw = a.nw + (20,20); % A +c.nw = a.nw + (15, 40); % B + +Group.g(a, b, c); +g.nw = (10,10); % C + +drawObject(g); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/group.1} +\end{multicols} + +After some objects are grouped, they can only be drawn +by invoking the {\code drawObject} macro on the group that aggregates them, and not individually. +Conveniently, once the relative positioning of objects within a group is set (line A and B), the whole +group can be ``moved'' do the desired position (line C), and all the contained objects will move along. + +\subsection{The PictureStack Macro} + +The {\code PictureStack} macro is a syntactic sugar for a set of pictures, +stacked according to predefined equations and grouped together. + +\begin{multicols}{2} +\begin{verbatim} +iStack.boxed := 1; +iStack.iPict.boxed := 1; +PictureStack.myStack("foo", + "bar: int" infont "tyxtt", + "nicely-centered" infont defaultfont, + "nice")("vcenter"); + +drawObject(myStack); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/picture_stack.1} +\end{multicols} + +Note the last parameter of the macro {\code PictureStack}, here {\code vcenter}. +It is used to generate appropriate equations based on a descriptive name. +The spacing between individual picture objects is set by the field +{\code iStack.spacing}. Currently, the following alignment names are +defined: {\code vleft}, {\code vright}, {\code vcenter}, +{\code vleftbase}, {\code vrightbase}, {\code vcenterbase}. All these +names refer to vertical alignment (the prefix ``{\code v}''); alignment can +be at left, right or centered. The variants having the suffix ``{\code base}'' align +the pictures so that {\code iStack.spacing} refer to the distance between the +bottom lines of the pictures. The unsuffixed variants use {\code iStack.spacing} as +the distance between one's bottom line and the next's top line. + +The ``{\code base}'' alignment is particularly useful for stacking text, since it +offers better visual appearance when {\code iPict.ignoreNegativeBase} is set to {\code 1}. + +\section{Components Design} + +Each MetaUML component (e.g. {\code Picture}, {\code PictureStack}, {\code Class}) is +designed according to an established pattern. This section gives more insight +on this. + +In order to draw a component, MetaUML categorizes the required information as follows: +\begin{itemize} +\item what to draw, or what are the elements of a component. +\item how to draw, or how are the elements positioned in relation to each other within the component +\item where to draw +\end{itemize} + +For example, in order to draw a picture object we must know, respectively: +\begin{itemize} +\item what is the text or the native picture that needs to be drawn +\item what are the margins that should be left around the contents +\item where is the picture to be drawn +\end{itemize} + +Why do we bother with these questions? Why don't we just simply draw the picture +component as soon as it was created and get it over with? +That is, why doesn't the following code just work? + +\begin{verbatim} +Picture.pict("foo"); +\end{verbatim} + +Well, although we have the answer to question 1 (what to draw), +we still need to have question 3 answered. The code below becomes thus a +necessity (actually, you are not forced to specify the positioning of an object, +because its draw method positions it to {\code (0,0)} by default): + +\begin{verbatim} +% question 1: what to draw +Picture.pict("foo"); + +% question 3: where to draw +pict.nw = (10,10); + +% now we can draw +drawObject(pict); +\end{verbatim} + +How about question 2, how to draw? By default, this problem is addressed behind the +scenes by the component. This means, for the Picture object, that a native picture is created +from the given string, and around that picture certain margins are placed, by means of MetaPost equations. +(The margins also come in handy when stacking Picture objects, so that the result doesn't look too cluttered.) +If these equations were defined within the Picture constructor, then an +usability problem would have appeared, because it wouldn't have been possible to modify the margins, +as in the code below: + +\begin{verbatim} +% question 1: what to draw +Picture.pict("foo"); + +% question 2: how to draw +pict.info.left := 10; +pict.info.boxed := 1; + +% question 3: where to draw +pict.nw = (0,0); + +% now we can draw +drawObject(pict); +\end{verbatim} + +To allow for this type of code, the equations that define the layout of the {\code Picture} object (here, what the margins are) +must be defined somewhere after the constructor. This is done by a macro called {\code Picture\_layout}. +This macro defines all the equations which link the ``what to draw'' information to the ``how to draw'' +information (which in our case is taken from the {\code info} member, a copy of {\code iPict}). +Nevertheless, notice that {\code Picture\_layouts} is not explicitly invoked. To the user's +great relief, this is taken care of automatically within the {\code Picture\_draw} macro. + +There are times however, when explicitly invoking a macro like {\code Picture\_layout} +becomes a necessity. This is because, by contract, it is only after the {\code layout} +macro is invoked that the final dimensions (width, height) of an object are +definitely and permanently known. Imagine that we have a component whose job is to +surround in a red-filled rectangle some other objects. This component +needs to know what the dimensions of the contained objects are, in order to be able to set +its own dimensions. At drawing time, the contained objects must not have been drawn already, +because the red rectangle of the container would overwrite them. +Therefore, the whole pseudo-code would be: +\begin{verbatim} +Create objects o1, o2, ... ok; +Create container c(o1, o2, ..., ok); +Optional: modify info-s for o1, o2, ... ok; +Optional: modify info for c; + +layout c, requiring layout of o1, o2, ... ok; +establish where to draw c; +draw red rectangle defined by c; +draw components o1, o2, ...ok within c +\end{verbatim} + +A natural conclusion is that an object must not be laid out more than once, because otherwise +inconsistent or superfluous equations would arise. To enforce this, by contract, +any object must keep record of whether its layout method has already been invoked, +and if the answer is affirmative, subsequent invocations of the layout macro would +do nothing. It is very important to mention that after the {\code layout} macro is +invoked over an object, modifying the {\code info} member of that object has +no subsequent effect, since the layout equations are declared and interpreted only once. + +\subsection{Notes on the Implementation of Links} + +MetaUML considers edges in diagram graphs as links. A link is composed of a path and the +heads (possible none, one or two). For example, since an association has no heads, it suffices +to draw along the path with a solid pen; however, an unidirectional aggregation has, in addition +to a solid path, two heads: one is an arrow and the other is a diamond. + +The general algorithm for drawing a link is: + +\begin{verbatim} +0. Reserve space for heads +1. Draw the path (except for the heads) +2. Draw head 1 +3. Draw head 2 +\end{verbatim} + +Each of the UML link types define how the drawing should be done, in each of the +cases (1, 2 and 3). Consider the link type of unidirectional composition. +Its ``class'' is declared as: + +\begin{verbatim} +vardef CompositionUniInfo@# = + LinkInfo@#; + + @#widthA = defaultRelationHeadWidth; + @#heightA = defaultRelationHeadHeight; + @#drawMethodA = "drawArrow"; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawDiamondBlack"; + + @#drawMethod = "drawLine"; +enddef; +\end{verbatim} + +Using this definition, the actual description is created like this: + +\begin{verbatim} +CompositionUniInfo.compositionUni; +\end{verbatim} + +As shown previously, is is the macro {\code link} which +performs the actual drawing, using the link description information +which is given as parameter (generally called {\code iLink}). +For example, we can use: + +\begin{verbatim} +link(aggregationUni)((0,0)--(40,0)); +\end{verbatim} + +%\begin{figure} +%\centering +%\includegraphics{fig/how-links-work.1} +%\caption{An example of a picture stack.} +%\label{fig:hlw} +%\end{figure} + +Let us see now the inner workings of macro {\code link}. Its definition is: + +\begin{verbatim} +vardef link(text iLink)(expr myPath)= + LinkStructure.ls(myPath, + iLink.widthA, iLink.widthB); + drawLinkStructure(ls)(iLink); +enddef; +\end{verbatim} + +\begin{figure} +\centering +\begin{tabular}{l|l} +$AB$ & the path specified by the user \\ +$|AA'|$ & {\code iLink.widthA}\\ +$|BB'|$ & {\code iLink.widthB} +\end{tabular} +\includegraphics{fig/how-links-work.2} +\caption{Details on how a link is drawn by MetaUML.} +\label{fig:hlw2} +\end{figure} + +First, space is reserved for heads, by ``shortening'' the given path {\code myPath} +by {\code iLink.widthA} at the beginning and by {\code iLink.widthB} at the end. +After that, the shortened path is drawn with the ``method'' +given by {\code iLink.drawMethod} and the heads with the ``methods'' +{\code iLink.drawMethodA} and {\code iLink.drawMethodB}, +respectively (figure \ref{fig:hlw2}). + +\subsection{Object Definitions: Easier {\code generic\_declare}} + +In MetaPost, if somebody wants to define something resembling a class in an object-oriented language, +named, say, {\code Person}, he would do something like this: + +\begin{verbatim} +vardef Person@#(expr _name, _age)= + % @# prefix can be seen as `this` pointer + string @#name; + numeric @#age; + + @#name := _name; + @#age := _age; +enddef; +\end{verbatim} + +This allows for the creation of instances (or objects) of class {\code Person} by using +declarations like: + +\begin{verbatim} +Person.personA; +Person.personB; +\end{verbatim} + + However, if one also wants to able able to create indexed arrays of persons, such as +{\code Person.student0}, {\code Person.student1} etc., the definition of class +{\code Person} must read: + +\begin{verbatim} +vardef Person@#(expr _name, _age)= + _n_ := str @#; + generic_declare(string) _n.name; + generic_declare(numeric) _n.age; + + @#name := _name; + @#age := _age; +enddef; +\end{verbatim} + +This construction is rather inelegant. MetaUML offers alternative macros to achieve +the same effect, uncluttering the code by removing the need for the unaesthetic {\code \_n\_} and +{\code \_n}. + +\begin{verbatim} +vardef Person@#(expr _name, _age)= + attributes(@#); + var(string) name; + var(numeric) age; + + @#name := _name; + @#age := _age; +enddef; +\end{verbatim} + +\section{Customization in MetaUML: Examples} +\label{section:customization} + +We have seen that in MetaUML the ``how to draw'' information is memorized into the so-called +``{\code Info}'' structures. For example, the default way in which a {\code Picture} object is +to be drawn is recorded into an instance of {\code PictureInfo}, named {\code iPict}. In this section we +present a case study involving the customization of {\code Class} objects. The customization of +any other MetaUML objects works similarly. Here we cannot possibly present all the customization +options for all kinds of MetaUML objects: this would take too long. Nevertheless, an interested reader can refer +to the top of the appropriate MetaUML library file, where {\code Info} structures are defined. +For example, class diagram related definitions are in {\code metauml\_class.mp}, activity diagram +definitions are in {\code metauml\_activity.mp} etc. + +\subsection{Global settings} + +Let us assume that we do not particularly like the default foreground color of all classes, and wish +to change it so something yellowish. In this scenario, one would most likely want to change +the appropriate field in {\code iClass}: + +\begin{verbatim} +iClass.foreColor := (.9, .9, 0); +\end{verbatim} + +After this, we can obtain the following result: + +\begin{multicols}{2} +\begin{verbatim} +Class.A("A")()(); +Class.B("B")()(); +Class.C("C")()(); + +B.w = A.e + (20,0); +C.n = .5[A.se, B.sw] + (0, -10); + +drawObjects(A, B, C); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/class_customization.1} +\end{multicols} + +\subsection{Individual settings} + +To modify the settings of one particular {\code Class} objects, another strategy is more appropriate. How about having class +{\code C} stand out with a light blue foreground color, a bigger font size for the class name and a blue border? + +\begin{multicols}{2} +\begin{verbatim} +iPict.foreColor := (.9, .9, 0); + +Class.A("A")()(); +Class.B("B")()(); +Class.C("C")()(); +C.info.foreColor := (.9, .7, .7); +C.info.borderColor := green; +C.info.iName.iFont.scale := 2; + +% positioning code ommited +drawObjects(A, B, C); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/class_customization.2} +\end{multicols} + +As an aside, each {\code Class} object has an {\code info} member which is created as +a copy of {\code iClass}; the actual drawing is performed using this copied +information. Because of that, the {\code info} member can be safely modified after the object +has been created, obtaining the expected results and not influencing other objects. + +Another thing worth mentioning is that the {\code ClassInfo} structure contains +the {\code iName} member, which is an instance of {\code PictureInfo}. In our example we +do not want to modify the spacings around the {\code Picture} object, +but the characteristics of the font its contents is typeset into. To do that, +we modify the {\code iName.iFont} member, which by default is a copy of {\code iFont} +(an instance of {\code FontInfo}, defined in {\code util\_picture.mp}). +If, for example, we want to change the font the class name is rendered into, we would set +the attribute {\code iName.iFont.name} to a string representing a font name +on our system (as used with the MetaPost {\code infont} operator). + +\subsection{Predefined settings} + +This usage scenario is perhaps more interesting. Suppose that we have two +types of classes which we want to draw differently. Making the setting adjustments +for each individual class object would soon become a nuisance. MetaUML's solution consists in the +ability of using predefined ``how to draw'' {\code Info} objects. Let us create such objects: + +\begin{verbatim} +ClassInfoCopy.iHome(iClass); +iHome.foreColor := (0, .9, .9); + +ClassInfo.iRemote; +iRemote.foreColor := (.9, .9, 0); +iRemote.borderColor := green; +\end{verbatim} + +Object {\code iHome} is a copy of {\code iClass} (as it might have been set at +the time of the macro call). Object {\code iRemote} is created just as {\code iClass} +is originally created. We can now use these {\code Info} objects to easily set the +``how to draw'' information for classes. The result is depicted below, +please note the ``{\code E}'' prefix in {\code EClass}: + +\begin{multicols}{2} +\begin{verbatim} +EClass.A(iHome)("UserHome")()(); +EClass.B(iRemote)("UserRemote")()(); +EClass.C(iHome)("CartHome")()(); +EClass.D(iRemote)("CartRemote")()(); +\end{verbatim} +\columnbreak +\hspace{1cm}\includegraphics{fig/class_customization.3} +\end{multicols} + +\subsection{Extreme customization} + +When another font (or font size) is used, it may become necessary to change the space between the +baselines of attributes and methods. Figure below is the result of the (unlikely) code: + +\begin{multicols}{2} +\begin{verbatim} +Class.A("Foo") + ("a: int", "b: int") + ("foo()", "bar()", "gar()"); + +A.info.iName.iFont.name := metauml_defaultFontBold; +A.info.iName.iFont.scale := 1.2; + +A.info.iAttributeStack.iPict.iFont.scale := 0.8; +A.info.iAttributeStack.top := 10; +A.info.iAttributeStack.spacing := 11; + +A.info.iMethodStack.iPict.iFont.scale := 2; +A.info.iMethodStack.spacing := 17; +A.info.iMethodStack.bottom := 10; + +drawObject(A); +\end{verbatim} +\columnbreak +\hspace{4cm}\includegraphics{fig/class_customization.4} +\end{multicols} + +\begin{verbatim} +\end{verbatim} + +Both {\code iAttributeStack} and {\code iMethodStack} are instances of +{\code PictureStackInfo}, which is used to control the display of {\code PictureStack} objects. +%We can also customize the size and colors of the ``locks'' by setting {\code A.info.iLock}. + +As font names, you can choose from the globally defined {\code metauml\_defaultFont}, {\code metauml\_defaultFontOblique}, {\code metauml\_defaultFontBold}, {\code metauml\_defaultFontBoldOblique}, or any other name of a font that is available on your system. + +\section{Alternatives to MetaUML} + +No software package is perfect, and for this MetaUML is a prime example. Here is a list of packages that may also be used to create UML diagrams for LaTeX work: + +\begin{itemize} +\item uml.sty \cite{umlsty} +\item pst-uml \cite{pstumlsty} +\item umldoc \cite{umldoc} +\item TiKZ-UML \cite{tikzuml} +\end{itemize} + +Do not ignore the possibility of creating your diagrams using a GUI program, and then exporting them into a LaTex-friendly open format such as SVG \cite{svglatex}. + +\pagebreak +\input{test-suite} + +\pagebreak +\section{References} +\printbibliography[heading=none] + +\end{document} diff --git a/graphics/metapost/contrib/macros/metauml/examples/manual/test-suite.tex b/graphics/metapost/contrib/macros/metauml/examples/manual/test-suite.tex new file mode 100644 index 0000000000..b0aa9a6685 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/examples/manual/test-suite.tex @@ -0,0 +1,82 @@ +% Part of the MetaUML manual +% Copyright (c) 2005 Ovidiu Gheorghies +% +% Permission is granted to copy, distribute and/or modify this document +% under the terms of the GNU Free Documentation License, Version 1.2 +% or any later version published by the Free Software Foundation; +% with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +% A copy of the license is included in the section entitled "GNU +% Free Documentation License". + +\newcommand{\metaumltest}[2]{Test #2 --- \\ \includegraphics{fig/test_#1.#2} \\ } +\newcommand{\metaumltests}[2]{\multido{\iA=1+1}{#2}{\metaumltest{#1}{\iA}}} + +\section{Test Suite} + +\subsection{Low-level} + \metaumltests{lowlevel}{2} + +\subsection{Fonts} + \metaumltests{font}{3} + +\subsection{Util library} + \subsubsection{Picture tests} + \metaumltests{picture}{10} + + \subsubsection{Picture tests - TeX rendering} + \metaumltests{picture_tex_rendering}{1} + + \subsubsection{Group tests} + \metaumltests{group}{2} + + \subsubsection{PictureStack tests} + \metaumltests{picture_stack}{7} + + \subsubsection{Positioning tests} + \metaumltests{positioning}{6} + +\subsection{Class diagram} + \subsubsection{Class tests} + \metaumltests{class}{16} + \subsubsection{Class feature types tests} + \metaumltests{class_feature_types}{5} + \subsubsection{Class template tests} + \metaumltests{class_templates}{3} + + \subsubsection{Qualified Association tests} + \metaumltests{class_qual_assoc}{2} + +\subsection{Package diagram} +\subsubsection{Package tests} + \metaumltests{package}{2} + +\subsection{Component diagram} +\subsubsection{Component tests} + \metaumltests{component}{1} + +\subsection{Paths} + \metaumltests{paths}{3} + +\subsection{Behavioral diagrams} + \subsubsection{Activity tests} + \metaumltests{activity}{2} + + \subsubsection{State Machine tests} + \metaumltests{state}{5} + + \subsubsection{Usecase tests} + \metaumltests{usecase}{9} + +\subsection{Miscelaneous} + \subsubsection{Notes} + \metaumltests{note}{2} + \subsubsection{Objects (Class Instances)} + \metaumltests{instance}{1} + +\subsection{User requests} + Test 1 --- \\ \includegraphics[scale=.2]{fig/test_lars_issues.1} \\ + \metaumltest{lars_issues}{2} + +\subsection{Skins} + \metaumltests{skins}{1} + \metaumltests{skins_global_defaults}{1} diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml.mp new file mode 100644 index 0000000000..95748cf767 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml.mp @@ -0,0 +1,66 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_mp: + expandafter endinput +fi; +_metauml_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_infrastructure; +inputonce util_object; +inputonce util_commons; +inputonce util_margins; +inputonce util_picture; +inputonce util_group; +inputonce util_picture_stack; +inputonce util_positioning; +inputonce util_shade; + +inputonce metauml_base; + +inputonce metauml_links; +inputonce metauml_paths; + +inputonce metauml_note; + +inputonce metauml_stereotype; + +inputonce metauml_class; +inputonce metauml_instance; +inputonce metauml_class_relations; +inputonce metauml_class_assoc; + +inputonce metauml_package; +inputonce metauml_package_relations; + +inputonce metauml_behavioral_common; +inputonce metauml_activity; +inputonce metauml_state; + +inputonce metauml_usecase_clipart; +inputonce metauml_usecase; + +input metauml_behavioral_common; +input metauml_activity; +input metauml_state; + +input metauml_usecase_clipart; +input metauml_usecase; + +input metauml_component; +input metauml_component_relations; + +input metauml_templates; + diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_activity.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_activity.mp new file mode 100644 index 0000000000..79ac5042e2 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_activity.mp @@ -0,0 +1,229 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_activity_mp: + expandafter endinput +fi; +_metauml_activity_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce metauml_defaults; +inputonce util_log; + +vardef ActivityInfo@#= + attributes(@#); + var(color) foreColor, borderColor; + + FontInfo.@#iFont(metauml_defaultFont, defaultscale); + @#iFont.ignoreNegativeBase := 1; + + PictureInfo.@#iText (2, 2, 2, 2)(@#iFont); + PictureStackInfo.@#iStack (2, 2, 2, 2)(9)(@#iText); + + @#iStack.iPict.ignoreNegativeBase := 1; + + Margins.@#(2,2,2,2); + + @#fat := 5; + + ShadeInfo.@#iShade; + @#foreColor := .9white; + @#borderColor := black; +enddef; + +vardef ActivityInfoCopy@#(text src)= + log "ActivityInfoCopy: Copying activity info"; + + attributes(@#); + var(color) foreColor, borderColor; + + PictureStackInfoCopy.@#iStack (src.iStack); + MarginsCopy.@#(src); + @#fat := src.fat; + + ShadeInfoCopy.@#iShade(src.iShade); + + @#foreColor := src.foreColor; + @#borderColor := src.borderColor; +enddef; + +ActivityInfo.iActivity; + +vardef Activity@#(text contents)= + EActivity.@#(iActivity)(contents); +enddef; + +vardef EActivity@#(text _info)(text contents)= + ObjectEquations(@#); + @#className := "Activity"; + + ActivityInfoCopy.@#info(_info); + + numeric @#nLines; @#nLines := 0; + string @#lines[]; + for l=contents: + @#lines[@#nLines] := l; + @#nLines := @#nLines + 1; + endfor; + + EPictureStack.@#stack(@#info.iStack)(scantokens listArray(@#lines)(@#nLines))("vcenterbase"); +enddef; + +vardef Activity_layout@#= + if @#laidout = 1: + log "Activity " & (str @#) & " has already been layed out"; + else: + @#laidout := 1; + + PictureStack_layout.@#stack; + + @#width = @#stack.width + @#info.left + @#info.right + 2 * @#info.fat; + @#height = @#stack.height + @#info.top + @#info.bottom; + + @#c = @#stack.c; + + pair @#urt, @#lrt, @#ulft, @#llft; + + @#urt := @#ne - (@#info.fat, 0); + @#lrt := @#se - (@#info.fat, 0); + @#ulft := @#nw + (@#info.fat, 0); + @#llft := @#sw + (@#info.fat, 0); + fi; +enddef; + +vardef Activity_draw@#= + Activity_layout@#; + objectEnsurePositioning.@#; + + attributes(@#); + var(path) border; + @#border := @#ulft -- @#urt .. @#e .. @#lrt -- @#llft .. @#w .. cycle; + + drawObjectShade(@#); + fill @#border withcolor @#info.foreColor; + draw @#border withcolor @#info.borderColor; + + drawObject(@#stack); +enddef; + +vardef Activity_border@#= + @#border +enddef; + + +vardef BranchInfo@#= + @#width := 10; + @#height := 10; + + numeric @#shade; + color @#shadeColor, @#foreColor; + @#shade := .3; + @#shadeColor := .6white; + @#foreColor := white; +enddef; + +BranchInfo.iBranch; + +vardef Branch@#= + ObjectEquations(@#); + @#className := "Branch"; + + @#width = iBranch.width; + @#height = iBranch.height; +enddef; + +vardef Branch_layout@#= + % nothing to do +enddef; + +vardef Branch_draw@#= + objectEnsurePositioning.@#; + + path @#border; + @#border := @#n -- @#e -- @#s -- @#w -- cycle; + + fill @#border shifted (iBranch.shade, -iBranch.shade) withcolor iBranch.shadeColor; + fill @#border withcolor iBranch.foreColor; + draw @#border; +enddef; + +vardef Branch_border@#= + @#border +enddef; + +vardef ForkInfo@#= + @#thickness := 3; + + numeric @#shade; + color @#shadeColor, @#foreColor; + @#shade := .3; + @#shadeColor := .6white; + @#foreColor := black; +enddef; + +ForkInfo.iFork; + +vardef Fork@#(expr orientation, length)= + ObjectEquations(@#); + @#className := "Fork"; + + if (orientation="h") or (orientation="horiz") or (orientation="horizontal"): + @#width = length; + @#height = iFork.thickness; + else: + @#height = length; + @#width = iFork.thickness; + fi; +enddef; + +vardef Fork_layout@#= + % nothing to do +enddef; + +vardef Fork_draw@#= + objectEnsurePositioning.@#; + + path @#border; + @#border := @#nw -- @#ne -- @#se -- @#sw -- cycle; + + fill @#border shifted (iFork.shade, -iFork.shade) withcolor iFork.shadeColor; + fill @#border withcolor iFork.foreColor; +enddef; + +vardef Fork_border@#= + @#border +enddef; + +defaultTransitionHeadWidth := 15; +defaultTransitionHeadHeight := 5; + +vardef TransitionInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = defaultTransitionHeadWidth; + @#heightB = defaultTransitionHeadHeight; + @#drawMethodB = "drawArrow"; + + @#drawMethod = "drawLine"; +enddef; + +TransitionInfo.transition; + +FontInfo.guardFont(metauml_defaultFont, .7); +PictureInfo.iGuard(2, 2, 2, 2)(guardFont); +iGuard.ignoreNegativeBase := 1; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_base.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_base.mp new file mode 100644 index 0000000000..22f73d3906 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_base.mp @@ -0,0 +1,171 @@ +% Copyright 2006 2015 Ovidiu Gheorghies, Radu-George Radulescu +% Licensed under the Apache License, Version 2.0. + +if known _metauml_base_mp: + expandafter endinput +fi; +_metauml_base_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_log; + +vardef markPoint(text p)(text color) = + draw p withpen pencircle scaled 1 withcolor color; +enddef; + +vardef drawLine(text pA)(text pB)(text base) = + draw pA--pB; +enddef; + +vardef drawArrow(text pA)(text pB)(text base) = + numeric dx, dy; + dx = xpart(pB - pA); + dy = ypart(pB - pA); + + numeric alfa; + alfa = angle(dx, dy); + + pair pC, pD; + pC := (0, base/2); + pC := pC rotated (alfa) shifted pA; + pD := (0, base/2); + pD := pD rotated (180+alfa) shifted pA; + + %fill pA--pC--pB--pD--cycle withcolor .8white; + + draw pA--pB; + draw pB--pC; + draw pB--pD; +enddef; + +vardef drawTriangle(text pA)(text pB)(text base) = + numeric dx, dy; + dx = xpart(pB - pA); + dy = ypart(pB - pA); + + numeric alfa; + alfa = angle(dx, dy); + pair pC, pD; + pC := (0, base/2); + pC := pC rotated (alfa) shifted pA; + pD := (0, base/2); + pD := pD rotated (180+alfa) shifted pA; + + fill pA--pC--pB--pD--cycle withcolor white; + + draw pA--pC;% withcolor red; + draw pA--pD;% withcolor green; + draw pB--pC;% withcolor blue; + draw pB--pD; +enddef; + +vardef drawDiamond(text pA)(text pB)(text height) = + numeric dx, dy; + dx = xpart(pB - pA); + dy = ypart(pB - pA); + + numeric alfa; + alfa = angle(dx, dy); + + numeric width; + width = _length(pA)(pB); + + path diamond; + diamond = (0,0)--(width/2, height/2)--(width, 0)--(width/2, -height/2)--cycle; + + fill diamond rotated alfa shifted pA withcolor white; + draw diamond rotated alfa shifted pA; +enddef; + +vardef drawDiamondBlack(text pA)(text pB)(text height) = + numeric dx, dy; + dx = xpart(pB - pA); + dy = ypart(pB - pA); + + numeric alfa; + alfa = angle(dx, dy); + + numeric width; + width = _length(pA)(pB); + + path diamond; + diamond = (0,0)--(width/2, height/2)--(width, 0)--(width/2, -height/2)--cycle; + + fill diamond rotated alfa shifted pA; +enddef; + +vardef drawCrossedCircle(text pA)(text pB)(text height) = + numeric dx, dy; + dx = xpart(pB - pA); + dy = ypart(pB - pA); + + numeric alfa; + alfa = angle(dx, dy); + + numeric width; + width = _length(pA)(pB); + + pair pC, pD; + pC := (width/2, height/2 + 1); + pC := pC rotated (alfa) shifted pA; + pD := (width/2, -height/2 - 1); + pD := pD rotated (alfa) shifted pA; + + fill pA..pB..pA -- cycle withcolor white; + + draw pA -- pB; + draw pC -- pD; + draw pA .. pB .. pA; +enddef; + +vardef drawSemiCircle(text pA)(text pB)(text height) = + numeric dx, dy; + dx = xpart(pB - pA); + dy = ypart(pB - pA); + + numeric alfa; + alfa = angle(dx, dy); + + numeric width; + width = _length(pA)(pB); + + pair pC, pD; + pC := (width/2 + 5, height/2 + 1); + pC := pC rotated (alfa) shifted pB; + pD := (width/2 + 5, -height/2 - 1); + pD := pD rotated (alfa) shifted pB; + + draw pC .. pA .. pD; +enddef; + +vardef drawCircle(text pA)(text pB)(text height) = + fill pA..pB..pA -- cycle withcolor white; + + draw pA .. pB .. pA; +enddef; + +vardef drawLine(expr my_path) = + draw my_path; +enddef; + +vardef drawLineDashed(expr my_path) = + draw my_path dashed evenly; +enddef; + +vardef drawNothing(text pA)(text pB)(text base) = +enddef; + +def shorterLineEndPoint(text pA)(text pB)(text delta) = + (xpart(pA) + _dx(pA)(pB)*(1 - delta/_length(pA)(pB)), ypart(pA) + _dy(pA)(pB) * (1 - delta/_length(pA)(pB)) ) +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_behavioral_common.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_behavioral_common.mp new file mode 100644 index 0000000000..190980eb69 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_behavioral_common.mp @@ -0,0 +1,214 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_behavioral_common_mp: + expandafter endinput +fi; +_metauml_behavioral_common_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_log; + +vardef SpecialStateInfo@#= + numeric @#diameter; + color @#discColor; + + numeric @#shade; + color @#shadeColor, @#foreColor; + + @#diameter := 0.4cm; + @#discColor := black; + @#foreColor := black; + + ShadeInfo.@#iShade; +enddef; + +vardef SpecialStateInfoCopy@#(text src)= + SpecialStateInfo.@#; + ShadeInfo_copy.@#iShade(src.iShade); + + @#diameter := src.diameter; + @#discColor := src.discColor; + @#foreColor := src.foreColor; +enddef; + +%%%%%%%%%%%%%%%%%% +% BEGIN % +%%%%%%%%%%%%%%%%%% + +SpecialStateInfo.iBegin; + +vardef Begin@#= + ObjectEquations(@#); + @#className := "Begin"; + + SpecialStateInfoCopy.@#info(iBegin); +enddef; + +vardef Begin_layout@#= + if @#laidout = 1: + log "Begin " & (str @#) & " has already been layed out"; + else: + @#laidout := 1; + + @#width = @#info.diameter; + @#height = @#info.diameter; + fi; +enddef; + +vardef Begin_draw@#= + Begin_layout@#; + objectEnsurePositioning.@#; + + path @#border; + @#border := @#n..@#e..@#s..@#w..cycle; + + drawObjectShade(@#); + + fill @#border withcolor @#info.discColor; + draw @#border withcolor @#info.foreColor; +enddef; + +vardef Begin_border@#= + @#border +enddef; + +%%%%%%%%%%%%%%%%%% +% END % +%%%%%%%%%%%%%%%%%% + +SpecialStateInfo.iEnd; +iEnd.innerSpacing := 2; +iEnd.discColor := white; + +vardef End@#= + ObjectEquations(@#); + @#className := "End"; + SpecialStateInfoCopy.@#info(iEnd); + @#info.innerSpacing := iEnd.innerSpacing; +enddef; + +vardef End_layout@#= + Begin_layout@#; +enddef; + +vardef End_draw@#= + Begin_draw.@#; + + path @#innerDisc; + @#innerDisc := @#n - (0, @#info.innerSpacing) .. + @#e - (@#info.innerSpacing, 0) .. + @#s + (0, @#info.innerSpacing) .. + @#w + (@#info.innerSpacing, 0) ..cycle; + + fill @#innerDisc withcolor @#info.foreColor; +enddef; + +vardef End_border@#= + @#border +enddef; + +%%%%%%%%%%%%%%%%%% +% ENTRY POINT % +%%%%%%%%%%%%%%%%%% + +SpecialStateInfo.iEntryPoint; +iEntryPoint.discColor := white; +iEntryPoint.innerSpacing := 2; + +vardef EntryPoint@#= + ObjectEquations(@#); + @#className := "EntryPoint"; + SpecialStateInfoCopy.@#info(iEntryPoint); + @#info.innerSpacing := iEntryPoint.innerSpacing; +enddef; + +vardef EntryPoint_layout@#= + Begin_layout@#; +enddef; + +vardef EntryPoint_draw@#= + Begin_draw.@#; +enddef; + +vardef EntryPoint_border@#= + @#border +enddef; + +%%%%%%%%%%%%%%%%%% +% EXIT POINT % +%%%%%%%%%%%%%%%%%% + +SpecialStateInfo.iExitPoint; +iExitPoint.discColor := white; +iExitPoint.innerSpacing := 2; + +vardef ExitPoint@#= + ObjectEquations(@#); + @#className := "ExitPoint"; + SpecialStateInfoCopy.@#info(iExitPoint); + @#info.innerSpacing := iExitPoint.innerSpacing; + @#info.iShade.shift := 0; +enddef; + +vardef ExitPoint_layout@#= + Begin_layout@#; +enddef; + +vardef ExitPoint_draw@#= + Begin_draw.@#; + + _n_ := str @#; + generic_declare(pair) _n.urt, _n.lrt, _n.llft, _n.ulft; + + @#urt := @#c + @#info.diameter/2 * (sind(45), cosd(45)); + @#lrt := @#c + @#info.diameter/2 * (sind(135), cosd(135)); + @#llft := @#c + @#info.diameter/2 * (sind(225), cosd(225)); + @#ulft := @#c + @#info.diameter/2 * (sind(315), cosd(315)); + + draw @#urt -- @#llft; + draw @#ulft -- @#lrt; +enddef; + +vardef ExitPoint_border@#= + @#border +enddef; + +%%%%%%%%%%%%%%%%%% +% FlowFinal % +%%%%%%%%%%%%%%%%%% + +SpecialStateInfo.iFlowFinal; +iFlowFinal.discColor := white; +iFlowFinal.innerSpacing := 2; + +vardef FlowFinal@#= + ObjectEquations(@#); + @#className := "FlowFinal"; + SpecialStateInfoCopy.@#info(iFlowFinal); + @#info.innerSpacing := iFlowFinal.innerSpacing; + %@#info.iShade.shift := 0; +enddef; + +vardef FlowFinal_layout@#= + Begin_layout@#; +enddef; + +vardef FlowFinal_draw@#= + ExitPoint_draw@# +enddef; + +vardef FlowFinal_border@#= + @#border +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_class.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_class.mp new file mode 100644 index 0000000000..c3ac333b21 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_class.mp @@ -0,0 +1,485 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_class_mp: + expandafter endinput +fi; +_metauml_class_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce metauml_defaults; +inputonce util_log; + +inputonce util_picture; +inputonce util_picture_stack; +inputonce util_shade; + +string visibilityPublic, visibilityProtected, visibilityPrivate, visibilityPackage; +visibilityPublic:="+"; +visibilityProtected:="#"; +visibilityPrivate:="-"; +visibilityPackage:="~"; + +string metauml_private_abstractMarker, metauml_private_staticMarker; +metauml_private_abstractMarker := "@abstract"; +metauml_private_staticMarker := "@static"; + +def abstract expr methodName= metauml_private_abstractMarker&methodName enddef; +def static expr featureName= metauml_private_staticMarker&featureName enddef; + +def metauml_private_isAbstract(expr name) = (substring (0, 9) of name = metauml_private_abstractMarker) enddef; +def metauml_private_isStatic(expr name) = (substring (0, 7) of name = metauml_private_staticMarker) enddef; +def metauml_private_stripStatic(expr name) = substring (7,infinity) of name enddef; +def metauml_private_stripAbstract(expr name) = substring (9,infinity) of name enddef; + +vardef ClassInfo@#= + attributes(@#); + var(color) foreColor, borderColor; + var(string) featureVisibilityMode; + + FontInfo.@#nameFont(metauml_defaultFont, defaultscale); + FontInfo.@#featureFont (metauml_defaultFont, defaultscale); + FontInfo.@#stereotypeFont(metauml_defaultFont, .7); + + ShadeInfo.@#iShade; + + @#featureVisibilityMode := "individual"; % "none", "grouped" + + @#foreColor := .9white; + @#borderColor := black; + + PictureInfo.@#iName (2, 2, 1, 3)(@#nameFont); + @#iName.ignoreNegativeBase := 1; + + PictureInfoCopy.@#iNameAbstract(@#iName); + @#iNameAbstract.iFont.name := metauml_defaultFontOblique; + + PictureInfo.@#iStereotype(2, 2, 2, 2)(@#stereotypeFont); + @#iStereotypeStack.iPict.ignoreNegativeBase := 1; + + PictureStackInfo.@#iStereotypeStack(2, 2, 1, 1)(5.5)(@#iStereotype); + + PictureInfo.@#iFeature (2, 2, 1.25, 0)(@#featureFont); + + PictureInfoCopy.@#iFeatureAbstract (@#iFeature); + @#iFeatureAbstract.iFont.name := metauml_defaultFontOblique; + + PictureInfoCopy.@#iFeatureStatic (@#iFeature); + @#iFeatureStatic.textDecoration := "underline"; + + PictureStackInfo.@#iFeatureStack (2, 2, 2.5, 2)(10.5)(@#iFeature); + PictureStackInfoCopy.@#iAttributeStack(@#iFeatureStack); + PictureStackInfoCopy.@#iMethodStack(@#iFeatureStack); + + @#iFeatureStack.iPict.bottom := 2; + @#iFeatureStack.iPict.ignoreNegativeBase := 1; + + PictureStackInfoCopy.@#iAttributeVisibilityStack (@#iFeatureStack); + PictureStackInfoCopy.@#iMethodVisibilityStack (@#iFeatureStack); + + @#iAttributeVisibilityStack.right := 0; + @#iMethodVisibilityStack.right := 0; +enddef; + +vardef ClassInfoCopy@#(text src)= + log "ClassInfoCopy: Copying class"; + + attributes(@#); + var(numeric) featureVisibilitySpacing, visibilityWidth, visibilityHeight; + var(color) foreColor, borderColor; + var(string) featureVisibilityMode; + + FontInfoCopy.@#nameFont(src.nameFont); + FontInfoCopy.@#featureFont(src.featureFont); + FontInfoCopy.@#stereotypeFont(src.stereotypeFont); + + ShadeInfoCopy.@#iShade(src.iShade); + + @#foreColor := src.foreColor; + @#borderColor := src.borderColor; + + PictureInfoCopy.@#iName (src.iName); + PictureInfoCopy.@#iNameAbstract (src.iNameAbstract); + + PictureInfoCopy.@#iStereotype(src.iStereotype); + PictureInfoCopy.@#iFeature (src.iFeature); + PictureInfoCopy.@#iFeatureAbstract (src.iFeatureAbstract); + PictureInfoCopy.@#iFeatureStatic (src.iFeatureStatic); + + PictureStackInfoCopy.@#iStereotypeStack(src.iStereotypeStack); + PictureStackInfoCopy.@#iFeatureStack (src.iFeatureStack); + PictureStackInfoCopy.@#iAttributeStack (src.iAttributeStack); + PictureStackInfoCopy.@#iMethodStack (src.iMethodStack); + PictureStackInfoCopy.@#iAttributeVisibilityStack (src.iAttributeVisibilityStack); + PictureStackInfoCopy.@#iMethodVisibilityStack (src.iMethodVisibilityStack); + + @#featureVisibilityMode := src.featureVisibilityMode; +enddef; + +ClassInfo.iClass; + +ClassInfoCopy.iClassNameOnly(iClass); +iClassNameOnly.iName.top := 10; +iClassNameOnly.iName.bottom := 10; +iClassNameOnly.iAttributeStack.top := 0; +iClassNameOnly.iAttributeStack.bottom := 0; +iClassNameOnly.iMethodStack.top := 0; +iClassNameOnly.iMethodStack.bottom := 0; + +ClassInfoCopy.iInterface(iClass); +iInterface.iAttributeStack.top := 0; +iInterface.iAttributeStack.bottom := 0; +iInterface.iName.iFont.name := metauml_defaultFontOblique; + +ClassInfoCopy.iAbstractClass(iClass); +iAbstractClass.iName.iFont.name := metauml_defaultFontOblique; + +% +% CLASS +% +vardef defClass@#(expr pname) = + ObjectEquations(@#); + @#className := "Class"; + + string @#name; + boolean @#isAbstract; + + @#isAbstract := metauml_private_isAbstract(pname); + if @#isAbstract: + @#name = metauml_private_stripAbstract(pname); + else: + @#name = pname; + fi + + numeric @#nStereotypes; + string @#stereotypes[]; + + string @#attributes[]; + string @#attributesVisibility[]; + boolean @#attributesIsStatic[]; + + string @#methods[]; + string @#methodsVisibility[]; + boolean @#methodsIsStatic[]; + boolean @#methodsIsAbstract[]; + + numeric @#nAttrs; + numeric @#nMethods; + numeric @#nStereotypes; + + @#nStereotypes := 0; + @#nAttrs := 0; + @#nMethods := 0; +enddef; + +vardef addAttribute@#(expr pcontent) = + string visibility; + string attribute; + + attribute := pcontent; + + @#attributesIsStatic[@#nAttrs] := metauml_private_isStatic(attribute); + if @#attributesIsStatic[@#nAttrs]: + attribute := metauml_private_stripStatic(attribute); + fi + + visibility := substring(0,1) of attribute; + if (not (visibility = visibilityPublic)) and + (not (visibility = visibilityPrivate)) and + (not (visibility = visibilityProtected)) and + (not (visibility = visibilityPackage)): + + @#.attributes[@#.nAttrs] := attribute; + @#.attributesVisibility[@#.nAttrs] := visibilityPackage; + else: + save from; + from := 1; + if (substring(1,2) of attribute) = " ": from := 2; fi; + + @#.attributes[@#.nAttrs] := substring(from, infinity) of attribute; + @#.attributesVisibility[@#.nAttrs] := visibility; + fi; + + @#.nAttrs := @#.nAttrs + 1; +enddef; + +vardef addMethod@#(expr pcontent) = + string visibility; + string method; + + method := pcontent; + + @#methodsIsStatic[@#nMethods] := metauml_private_isStatic(method); + if @#methodsIsStatic[@#nMethods]: + method := metauml_private_stripStatic(method); + fi + + @#methodsIsAbstract[@#nMethods] := metauml_private_isAbstract(method); + if @#methodsIsAbstract[@#nMethods]: + method := metauml_private_stripAbstract(method); + @#isAbstract := true; + fi + + visibility := substring(0,1) of method; + if (not (visibility = visibilityPublic)) and + (not (visibility = visibilityPrivate)) and + (not (visibility = visibilityProtected)) and + (not (visibility = visibilityPackage)): + + @#.methods[@#.nMethods] := method; + @#.methodsVisibility[@#.nMethods] := visibilityPackage; + else: + save from; + from := 1; + if (substring(1,2) of method) = " ": from := 2; fi; + + @#.methods[@#.nMethods] := substring(from, infinity) of method; + @#.methodsVisibility[@#.nMethods] := visibility; + fi; + + @#.nMethods := @#.nMethods + 1; +enddef; + +vardef classStereotype@#(expr pcontent) = + show "Macro classStereotype is deprecated, use Class_stereotypes instead."; + Class_stereotypes.@#(pcontent); +enddef; + +vardef classStereotypes@#(text stereotypes)= + show "Macro classStereotypes is deprecated, use Class_stereotypes instead."; + Class_stereotypes.@#(stereotypes); +enddef; + +vardef EClass@#(text _info)(expr name)(text attributes)(text methods)= + log "EClass begin: " & str @#; + + defClass@#(name); + + log "Copying class info"; + ClassInfoCopy.@#info(_info); + + for a=attributes: + log "Adding attribute ", a; + addAttribute@#(a); + endfor; + for m=methods: + log "Adding method ", m; + addMethod@#(m); + endfor; +enddef; + +vardef Class@#(expr name)(text attributes)(text methods)= + EClass@#(iClass)(name)(attributes)(methods); +enddef; + +vardef Interface@#(expr name)(text methods)= + EClass@#(iInterface)(name)()(methods); +enddef; + +vardef EInterface@#(text _info)(expr name)(text methods)= + EClass@#(_info)(name)()(methods); +enddef; + +vardef ClassName@#(expr name)= + EClass@#(iClassNameOnly)(name)()(); +enddef; + +vardef EClassName@#(text _info)(expr name)= + EClass@#(_info)(name)()(); +enddef; + +vardef AbstractClass@#(expr name)(text attributes)(text methods)= + EClass@#(iAbstractClass)(name)(attributes)(methods); +enddef; + +vardef EAbstractClass@#(text _info)(expr name)(text methods)= + EClass@#(_info)(name)()(methods); +enddef; + +vardef Class_border@#= + objectBox(@#) +enddef; + +vardef Class_noVisibilityMarkers@#= + @#info.featureVisibilityMode := "none"; +enddef; + +vardef Class_layout@# = + if @#laidout = 1: + log "Class " & (str @#) & " has already been layed out"; + else: + @#laidout := 1; + log "Class layout: " & (str @#); + + EPictureStack.@#stereotypeStack(@#info.iStereotypeStack) + (scantokens listArray(@#stereotypes)(@#nStereotypes))("vcenterbase"); + + if (@#isAbstract): + EPicture.@#namePict(@#info.iNameAbstract)(@#name); + else: + EPicture.@#namePict(@#info.iName)(@#name); + fi; + + layoutObjects(@#stereotypeStack, @#namePict); + + % Define attributes + + def metauml_private_attributeStyleSupplier(expr i)= + if @#attributesIsStatic[i]: @#info.iFeatureStatic + else: @#info.iFeature + fi + enddef; + + @#info.iAttributeStack.childStyleSupplier := "metauml_private_attributeStyleSupplier"; + + EPictureStack.@#attributeStack(@#info.iAttributeStack) + (scantokens listArray(@#attributes)(@#nAttrs))("vleftbase"); + + if @#info.featureVisibilityMode = "individual": + vardef joinCallbackAttributesVisibility@#= + setObjectJoin(pb.bottom = @#.attributeStack.pict[index].bottom; pb.midx = pa.midx); + setObjectJoinFirst(pa.bottom = @#.attributeStack.pict[index].bottom); + enddef; + + EPictureStack.@#attributeVisibilityStack(@#info.iAttributeVisibilityStack) + (scantokens listArray(@#attributesVisibility)(@#nAttrs)) + ("joinCallbackAttributesVisibility." & (str @#)); + elseif @#info.featureVisibilityMode = "none": + EPicture.@#attributeVisibilityStack(iPictNoMargins)(""); + else: + show "Unknown feature visibility mode", @#featureVisibilityMode; + 1=2; + fi; + + % Define methods + + def metauml_private_methodStyleSupplier(expr i)= + if @#methodsIsStatic[i]: @#info.iFeatureStatic + elseif @#methodsIsAbstract[i]: @#info.iFeatureAbstract + else: @#info.iFeature + fi + enddef; + + @#info.iMethodStack.childStyleSupplier := "metauml_private_methodStyleSupplier"; + + EPictureStack.@#methodStack(@#info.iMethodStack) + (scantokens listArray(@#methods)(@#nMethods))("vleftbase"); + + if @#info.featureVisibilityMode = "individual": + vardef joinCallbackMethodsVisibility@#= + setObjectJoin(pb.bottom = @#.methodStack.pict[index].bottom; pb.midx = pa.midx); + setObjectJoinFirst(pa.bottom = @#.methodStack.pict[index].bottom); + enddef; + + EPictureStack.@#methodVisibilityStack(@#info.iMethodVisibilityStack) + (scantokens listArray(@#methodsVisibility)(@#nMethods)) + ("joinCallbackMethodsVisibility." & (str @#)); + elseif @#info.featureVisibilityMode = "none": + EPicture.@#methodVisibilityStack(iPictNoMargins)(""); + else: + show "Unknown feature visibility mode", @#featureVisibilityMode; + 1=2; + fi; + + % Integrate components + show layoutObjects(@#attributeStack, @#methodStack); + layoutObjects(@#attributeStack, @#methodStack); + + @#attributeStack.left = @#methodStack.left; + @#methodStack.top = @#attributeStack.bottom; + + layoutObjects(@#attributeVisibilityStack, @#methodVisibilityStack); + + @#attributeVisibilityStack.midx = @#methodVisibilityStack.midx; + + if (@#.nMethods = 0) or (@#info.featureVisibilityMode="none"): + @#methodVisibilityStack.top = @#methodStack.top; + fi; + if (@#.nAttrs = 0) or (@#info.featureVisibilityMode="none"): + @#attributeVisibilityStack.top = @#attributeStack.top; + fi; + + EGroup.@#visibilityStacks(iGroupNoMargins)(@#attributeVisibilityStack, @#methodVisibilityStack); + + EGroup.@#featureStacks(iGroupNoMargins)(@#attributeStack, @#methodStack); + + layoutObjects(@#visibilityStacks, @#featureStacks); + + @#visibilityStacks.right = @#featureStacks.left; + + EGroup.@#featureGroup(iGroupNoMargins)(@#visibilityStacks, @#featureStacks); + + topToBottom(0)(@#stereotypeStack, @#namePict, @#featureGroup); + + EGroup.@#all(iGroupNoMargins)(@#stereotypeStack, @#namePict, @#featureGroup); + + layoutObjects(@#all); + + @#.nw = @#all.nw; + @#.se = @#all.se; + + log "Class layout for " & (str @#) & " done..."; + fi; +enddef; + +vardef Class_paintSkin@# = + log "Painting class skin..."; + nameAttributeY := @#attributeStack.top; + attributeMethodY := @#methodStack.top; + + drawObjectShade(@#); + + fill Class_border.@# withcolor @#info.foreColor; + draw Class_border.@# withcolor @#info.borderColor; + + draw (xpart @#nw, nameAttributeY)--(xpart @#se, nameAttributeY) withcolor @#info.borderColor; + draw (xpart @#nw, attributeMethodY)--(xpart @#se, attributeMethodY) withcolor @#info.borderColor; +enddef; + +vardef Class_draw@#= + log "Class_draw begin " & @#; + Class_layout.@#; + objectEnsurePositioning.@#; + Class_paintSkin.@#; + + drawObjects(@#all); + log "Class_draw end " & @#; +enddef; + +vardef Class_setDebugMode@#= + @#.info.iName.boxed := 1; + + @#.info.iFeature.boxed := 1; + @#.info.iFeatureStatic.boxed := 1; + @#.info.iFeatureAbstract.boxed := 1; + + @#.info.iStereotypeStack.boxed := 1; + @#.info.iStereotypeStack.iPict.boxed := 1; + @#.info.iAttributeStack.boxed := 1; + @#.info.iAttributeStack.iPict.boxed := 1; + @#.info.iMethodStack.boxed := 1; + @#.info.iMethodStack.iPict.boxed := 1; + + @#.info.iAttributeVisibilityStack.boxed := 1; + @#.info.iAttributeVisibilityStack.iPict.boxed := 1; + @#.info.iMethodVisibilityStack.boxed := 1; + @#.info.iMethodVisibilityStack.iPict.boxed := 1; +enddef; + +vardef Class_stereotypes@#(text _stereotypes)= + for stereotype = _stereotypes: + @#stereotypes[@#nStereotypes] := stereotype; + @#nStereotypes := @#nStereotypes + 1; + endfor; +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_class_assoc.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_class_assoc.mp new file mode 100644 index 0000000000..720117fc90 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_class_assoc.mp @@ -0,0 +1,93 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_class_assoc_mp: + expandafter endinput +fi; +_metauml_class_assoc_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_log; +inputonce metauml_defaults; + +FontInfo.assocFont(metauml_defaultFont, .7); +PictureInfo.iAssoc(2, 2, 2, 2)(assocFont); +iAssoc.ignoreNegativeBase := 1; + +vardef QualifiedAssociationInfo@#= + color @#background; + color @#borderColor; + numeric @#borderScale; + + @#background := .9white; + @#borderColor := black; + @#borderScale := .5; + + FontInfo.@#iFont(metauml_defaultFont, .9); + PictureInfo.@#iPict(2, 2, 2, 2)(@#iFont); + PictureStackInfo.@#iStack(2, 2, 1, 1)(7)(@#iPict); + + @#iStack.iPict.ignoreNegativeBase := 1; +enddef; + +vardef QualifiedAssociationInfoCopy@#(text src)= + color @#background; + color @#borderColor; + numeric @#borderScale; + + @#background := src.background; + @#borderColor := src.borderColor; + @#borderScale := src.borderScale; + + FontInfoCopy.@#iFont(src.iFont); + PictureInfoCopy.@#iPict(src.iPict); + PictureStackInfoCopy.@#iStack(src.iStack); +enddef; + +QualifiedAssociationInfo.iQualifiedAssociation; + +% +% QualifiedAssociation +% +vardef EQualifiedAssociation@#(text _info)(text qualifiedAssociations) = + ObjectEquations(@#); + @#className := "QualifiedAssociation"; + + QualifiedAssociationInfoCopy.@#info(_info); + + EPictureStack.@#elementsStack(@#info.iStack)(qualifiedAssociations)("vleftbase"); + + @#nw = @#elementsStack.nw; + @#se = @#elementsStack.se; +enddef; + +vardef QualifiedAssociation@#(text qualifiedAssociations)= + EQualifiedAssociation@#(iQualifiedAssociation)(qualifiedAssociations); +enddef; + +vardef QualifiedAssociation_paintSkin@# = + log "Painting qualifiedAssociation skin..."; + + fill objectBox(@#) withcolor @#info.background; + + draw objectBox(@#) + withpen pencircle scaled @#info.borderScale withcolor @#info.borderColor; +enddef; + +vardef QualifiedAssociation_draw@# = + PictureStack_layout.@#elementsStack; + + QualifiedAssociation_paintSkin.@#; + drawObject(@#elementsStack); +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_class_relations.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_class_relations.mp new file mode 100644 index 0000000000..0379aceeca --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_class_relations.mp @@ -0,0 +1,172 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_class_relations_mp: + expandafter endinput +fi; +_metauml_class_relations_mp:=1; + +defaultRelationHeadWidth := 25; +defaultRelationHeadHeight := 10; + +vardef AssociationInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = 0; + @#heightB = 0; + @#drawMethodB = "drawNothing"; + + @#drawMethod = "drawLine"; +enddef; + +vardef AssociationUniInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawArrow"; + + @#drawMethod = "drawLine"; +enddef; + +vardef InheritanceInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawTriangle"; + + @#drawMethod = "drawLine"; +enddef; + +vardef AggregationInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawDiamond"; + + @#drawMethod = "drawLine"; +enddef; + +vardef AggregationUniInfo@# = + LinkInfo@#; + + @#widthA = defaultRelationHeadWidth; + @#heightA = defaultRelationHeadHeight; + @#drawMethodA = "drawArrow"; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawDiamond"; + + @#drawMethod = "drawLine"; +enddef; + +vardef CompositionInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawDiamondBlack"; + + @#drawMethod = "drawLine"; +enddef; + +vardef CompositionUniInfo@# = + LinkInfo@#; + + @#widthA = defaultRelationHeadWidth; + @#heightA = defaultRelationHeadHeight; + @#drawMethodA = "drawArrow"; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawDiamondBlack"; + + @#drawMethod = "drawLine"; +enddef; + +vardef DashedLinkInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = 0; + @#heightB = 0; + @#drawMethodB = "drawNothing"; + + @#drawMethod = "drawLineDashed"; +enddef; + +vardef DependencyInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawArrow"; + + @#drawMethod = "drawLineDashed"; +enddef; + +vardef RealizationInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawTriangle"; + + @#drawMethod = "drawLineDashed"; +enddef; + +AssociationInfo.association; +AssociationUniInfo.associationUni; +InheritanceInfo.inheritance; +AggregationInfo.aggregation; +AggregationUniInfo.aggregationUni; +CompositionInfo.composition; +CompositionUniInfo.compositionUni; +DashedLinkInfo.dashedLink; +DependencyInfo.dependency; +RealizationInfo.realization; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Deprecated, kept to support code using the older API. +% Using the generic formulation involving link, e.g. +% link(association)(A.n--B.s) is preferable. +% link and clink are defined in metauml_links +% +vardef drawRelation(text iLink)(expr myPath)= + link(iLink)(myPath); +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_component.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_component.mp new file mode 100644 index 0000000000..c124f77110 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_component.mp @@ -0,0 +1,186 @@ +% Copyright 2006 2015 Radu-George Radulescu, Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_component_mp: + expandafter endinput +fi; +_metauml_component_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce metauml_defaults; +inputonce util_log; + +vardef ComponentInfo@#= + attributes(@#); + var(color) foreColor, borderColor; + var(numeric) minimumNameContentsDifference; + + FontInfo.@#iFont(metauml_defaultFont, defaultscale); + @#iFont.ignoreNegativeBase := 1; + + PictureInfo.@#iText (2, 2, 2, 2)(@#iFont); + PictureStackInfo.@#iNameStack (2, 2, 2, 2)(9)(@#iText); + @#iNameStack.iPict.ignoreNegativeBase := 1; + + Margins.@#(2,2,2,2); + + ShadeInfo.@#iShade; + @#foreColor := .9white; + @#borderColor := black; + + @#minimumNameContentsDifference := 20; + + GroupInfo.@#iContentsGroup(2, 2, 10, 2); +enddef; + +vardef ComponentInfoCopy@#(text src)= + log "ComponentInfoCopy: Copying component info"; + + attributes(@#); + var(color) foreColor, borderColor; + var(numeric) minimumNameContentsDifference; + + PictureStackInfoCopy.@#iNameStack (src.iNameStack); + MarginsCopy.@#(src); + + ShadeInfoCopy.@#iShade(src.iShade); + @#foreColor := src.foreColor; + @#borderColor := src.borderColor; + + @#minimumNameContentsDifference := src.minimumNameContentsDifference; + + GroupInfoCopy.@#iContentsGroup(src.iContentsGroup); +enddef; + +ComponentInfo.iComponent; + +vardef Component@#(text contents)(text _subItems)= + EComponent.@#(iComponent)(contents)(_subItems); +enddef; + +vardef EComponent@#(text _info)(text contents)(text _subItems)= + ObjectEquations(@#); + @#className := "Component"; + + ComponentInfoCopy.@#info(_info); + + numeric @#nLines; @#nLines := 0; + string @#lines[]; + numeric @#nSubItems; @#nSubItems := 0; + + for l=contents: + @#lines[@#nLines] := l; + @#nLines := @#nLines + 1; + endfor; + + for s=_subItems: + @#nSubItems := @#nSubItems + 1; + endfor; + + EGroup.@#subItems(@#info.iContentsGroup)(_subItems); + + EPictureStack.@#nameStack(@#info.iNameStack)(scantokens listArray(@#lines)(@#nLines))("vcenterbase"); +enddef; + +vardef Component_layout@#= + if @#laidout = 1: + log "Component '" & (str @#) & "' has already been layed out"; + else: + @#laidout := 1; + log "Component layout: '" & (str @#) & "'"; + + log "Component name layout '" & (str @#) & "'..."; + PictureStack_layout.@#nameStack; + log "SubItems for component layout '" & (str @#) & "'..."; + Group_layout.@#subItems; + + log "All elements in component '" & (str @#) & "' successfully layed out, integrating..."; + + + if @#subItems.width < @#nameStack.width + @#info.minimumNameContentsDifference: + @#contentWidth = @#nameStack.width + @#info.minimumNameContentsDifference; + else: + @#contentWidth = lmax(@#nameStack.width, @#subItems.width); + fi; + + @#width = @#contentWidth + @#info.left + @#info.right + 15; + + if @#nSubItems = 0: + @#height = @#info.top + @#info.bottom + @#subItems.height + 15; + @#nameStack.n = @#n - (0, 7); + else: + @#height = @#info.top + @#info.bottom + @#subItems.height + 30; + @#nameStack.n = @#n + (0, @#info.top) - (0, 5); + fi; + + @#subItems.n = @#n + (0, -((@#height - @#subItems.height)/2)) - (0, 5); + + log "Component layout for " & (str @#) & " ended."; + fi; +enddef; + +vardef Component_draw@#= + Component_layout.@#; + objectEnsurePositioning.@#; + + attributes(@#); + var(path) border; + + @#border := @#ne -- @#nw -- @#sw -- @#se -- cycle; + + drawObjectShade(@#); + + fill @#border withcolor @#info.foreColor; + draw @#border withcolor @#info.borderColor; + + drawComponentVisualStereotype(@#ne); + + drawObject(@#nameStack); + drawObject(@#subItems); + +enddef; + +vardef drawComponentVisualStereotype(text ne)= + % lud = left-up-down of the top-right rectangle; luu = left-up-up of the top-right rectangle etc. + pair lud, luu, ru, rd, ldd, ldu, lmd, lmu; + % urectld = upper rectangle left-down, lrectru = lower rectangle right-up + pair urectld, urectlu, urectru, urectrd, lrectld, lrectlu, lrectru, lrectrd; + lud = ne - (14, 5 ); + luu = lud + (0, 2 ); + ru = luu + (8, 0 ); + rd = ru - (0, 14); + ldd = rd - (8, 0 ); + ldu = ldd + (0, 2 ); + lmd = ldu + (0, 3 ); + lmu = lud - (0, 3 ); + + urectld = lmu - (3, 0); + urectlu = lud - (3, 0); + urectru = lud + (3, 0); + urectrd = lmu + (3, 0); + + lrectld = ldu - (3, 0); + lrectlu = lmd - (3, 0); + lrectru = lmd + (3, 0); + lrectrd = ldu + (3, 0); + + draw lud -- luu -- ru -- rd -- ldd -- ldu; + draw lmd -- lmu; + draw urectld -- urectlu -- urectru -- urectrd -- urectld; + draw lrectld -- lrectlu -- lrectru -- lrectrd -- lrectld; +enddef; + +vardef Component_border@#= + @#border +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_component_relations.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_component_relations.mp new file mode 100644 index 0000000000..e6800a2acb --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_component_relations.mp @@ -0,0 +1,55 @@ +% Copyright 2006 2015 Radu-George Radulescu, Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_component_relations_mp: + expandafter endinput +fi; +_metauml_component_relations_mp:=1; + +defaultRelationHeadWidth := 25; +defaultRelationHeadHeight := 10; +requiredInterfaceHeadWidth := 5; +requiredInterfaceHeadHeight := 15; + +vardef requiredInterfaceInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = requiredInterfaceHeadWidth; + @#heightB = requiredInterfaceHeadHeight; + @#drawMethodB = "drawSemiCircle"; + + @#drawMethod = "drawLine"; +enddef; + +vardef providedInterfaceInfo@# = + LinkInfo@#; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawCircle"; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#drawMethod = "drawLine"; +enddef; + +requiredInterfaceInfo.requiredInterface; +providedInterfaceInfo.providedInterface; + +vardef drawRelation(text iLink)(expr myPath)= + link(iLink)(myPath); +enddef; + +vardef drawLine(expr my_path) = + draw my_path; +enddef; + +vardef drawNothing(text pA)(text pB)(text base) = +enddef; + diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_defaults.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_defaults.mp new file mode 100644 index 0000000000..228df4c48c --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_defaults.mp @@ -0,0 +1,31 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_defaults_mp: + expandafter endinput +fi; +_metauml_defaults_mp:=1; + +% txbtt + +if not known metauml_defaultFont: + string metauml_defaultFont; + metauml_defaultFont := "ptmr8r"; +fi; + +if not known metauml_defaultFontOblique: + string metauml_defaultFontOblique; + metauml_defaultFontOblique := "ptmro8r"; +fi; + +if not known metauml_defaultFontBold: + string metauml_defaultFontBold; + metauml_defaultFontBold := "ptmb8r"; +fi; + +if not known metauml_defaultFontBoldOblique: + string metauml_defaultFontBoldOblique; + metauml_defaultFontBoldOblique := "ptmbo8r"; +fi; + + diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_instance.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_instance.mp new file mode 100644 index 0000000000..543920eb49 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_instance.mp @@ -0,0 +1,186 @@ +% Copyright 2005 2015 Radu-George Radulescu +% Licensed under the Apache License, Version 2.0. + +if known _metauml_instance_mp: + expandafter endinput +fi; +_metauml_instance_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce metauml_defaults; +inputonce util_log; + +inputonce util_picture; +inputonce util_picture_stack; +inputonce util_shade; + +vardef InstanceInfo@#= + attributes(@#); + var(color) foreColor, borderColor; + + FontInfo.@#nameFont(metauml_defaultFont, defaultscale); + + FontInfo.@#attributeFont(metauml_defaultFont, defaultscale); + + ShadeInfo.@#iShade; + + @#foreColor := .9white; + @#borderColor := black; + + PictureInfo.@#iName (2, 2, 1, 3)(@#nameFont); + + PictureInfo.@#iAttribute (2, 2, 1.25, 0)(@#attributeFont); + + PictureStackInfo.@#iAttributeStack (2, 2, 2.5, 2)(10.5)(@#iAttribute); % 8.5 + @#iAttributeStack.iPict.bottom := 2; + + @#iName.ignoreNegativeBase := 1; + @#iAttributeStack.iPict.ignoreNegativeBase := 1; +enddef; + +vardef InstanceInfoCopy@#(text src)= + log "InstanceInfoCopy: Copying Instance"; + + attributes(@#); + var(color) foreColor, borderColor; + + FontInfoCopy.@#nameFont(src.nameFont); + + FontInfoCopy.@#attributeFont(src.attributeFont); + + ShadeInfoCopy.@#iShade(src.iShade); + + @#foreColor := src.foreColor; + @#borderColor := src.borderColor; + + PictureInfoCopy.@#iName (src.iName); + + PictureInfoCopy.@#iAttribute (src.iAttribute); + PictureStackInfoCopy.@#iAttributeStack (src.iAttributeStack); + +enddef; + +InstanceInfo.iInstance; + +% +% Instance +% +vardef defInstance@#(expr pname) = + ObjectEquations(@#); + @#className := "Instance"; + + string @#name; + @#name = pname; + + string @#attributes[]; + numeric @#nAttrs; + @#nAttrs := 0; +enddef; + +vardef Instance_addAttribute@#(expr pcontent) = + + @#.attributes[@#.nAttrs] := pcontent; + @#.nAttrs := @#.nAttrs + 1; + +enddef; + +vardef EInstance@#(text _info)(expr name)(text attributes)= + log "EInstance begin"; + defInstance@#(name); + + log "Copying Instance info"; + InstanceInfoCopy.@#info(_info); + + for a = attributes: + log "Adding attribute ", a; + Instance_addAttribute@#(a); + endfor; +enddef; + +vardef Instance@#(expr name)(text attributes)= + EInstance@#(iInstance)(name)(attributes); +enddef; + +vardef Instance_border@#= + objectBox(@#) +enddef; + +vardef Instance_layout@# = + if @#laidout = 1: + log "Instance " & (str @#) & " has already been layed out"; + else: + @#laidout := 1; + log "Instance layout: " & (str @#); + + @#maxFeatureWidth := 0; + + EPicture.@#namePict(@#info.iName)(@#name); + EPictureStack.@#attributeStack(@#info.iAttributeStack) + (scantokens listArray(@#attributes)(@#nAttrs))("vleftbase"); + + layoutObjects(@#namePict, @#attributeStack); + + @#maxFeatureWidth := lmax(@#namePict.width, @#attributeStack.width) + 1; + + @#namePict.midx = @#midx; + + @#namePict.top = @#top - 1; + @#attributeStack.top = @#namePict.bottom - 1; + + @#attributeStack.left = @#left; + + @#width = @#maxFeatureWidth; + @#bottom = @#attributeStack.bottom; + + log "Layout done..."; + fi; +enddef; + +vardef Instance_drawFeatures@#= + log "Drawing name"; + drawObject(@#namePict); + log "Underlining name"; + pair A, B; + A := @#namePict.se + (-@#namePict.info.left, @#namePict.info.bottom-1); + B := @#namePict.sw + (@#namePict.info.right, @#namePict.info.bottom-1); + draw A--B; + log "Drawing attribute stack"; + drawObject(@#attributeStack); + +enddef; + +vardef Instance_paintSkin@# = + log "Painting Instance skin..."; + + drawObjectShade(@#); + + fill Instance_border.@# withcolor @#info.foreColor; + draw Instance_border.@# withcolor @#info.borderColor; + + draw (xpart @#nw, @#attributeStack.top)--(xpart @#se, @#attributeStack.top) withcolor @#info.borderColor; +enddef; + +vardef Instance_draw@#= + log "draw Instance begin..."; + Instance_layout.@#; + objectEnsurePositioning.@#; + Instance_paintSkin.@#; + Instance_drawFeatures.@#; +enddef; + +vardef Instance_setDebugMode@#= + @#.info.iName.boxed := 1; + @#.info.iAttributeStack.boxed := 1; + @#.info.iAttributeStack.iPict.boxed := 1; +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_links.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_links.mp new file mode 100644 index 0000000000..06a9dbabba --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_links.mp @@ -0,0 +1,86 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +% A LinkStructure is used to compute the relevant elements +% of a link, such as what is the main path of the link and +% where the link ends are to be drawn. +% +% For example, for a unidirectional aggregation between points +% A and B one must reserve some space for one diamond to the left and one arrow +% to the right, and draw the continous line on a segment shorter than AB. +% + +if known _metauml_links_mp: + expandafter endinput +fi; +_metauml_links_mp:=1; + +vardef LinkStructure@#(expr my_path, widthA, widthB) = + pair @#pointA, @#pointB, @#pointAc, @#pointBc; + path @#circleA, @#circleB; + numeric @#timeA, @#timeB; + path @#actualPath; + + @#pointA = point 0 of my_path; + @#pointB = point infinity of my_path; + + @#circleA = fullcircle scaled widthA shifted @#pointA; + @#circleB = fullcircle scaled widthB shifted @#pointB; + + @#timeA = xpart (my_path intersectiontimes @#circleA); + @#timeB = xpart (my_path intersectiontimes @#circleB); + @#pointAc = point @#timeA of my_path; + @#pointBc = point @#timeB of my_path; + + @#actualPath = subpath (@#timeA, @#timeB) of my_path; +enddef; + +% Used for visual debugging purposes +% +vardef describeLinkStructure(text linkStruct)= + %draw linkStruct.pointA -- linkStruct.pointB withpen pencircle scaled 2 withcolor green; + + draw linkStruct.circleA; + draw linkStruct.circleB; + + dotlabel.lft("A", linkStruct.pointA); + dotlabel.rt ("B", linkStruct.pointB); + + dotlabel.urt("A1", linkStruct.pointAc); + dotlabel.ulft("B1", linkStruct.pointBc); + + draw linkStruct.actualPath withcolor red; +enddef; + +% Draws the path using graphical elements specified by iLink +% using the landmark points computed in the LinkStructure +% linkStruct. +% +vardef drawLinkStructure(text linkStruct)(text iLink) = + scantokens(iLink.drawMethod)(linkStruct.actualPath); + + scantokens(iLink.drawMethodA)(linkStruct.pointAc)(linkStruct.pointA)(iLink.heightA); + scantokens(iLink.drawMethodB)(linkStruct.pointBc)(linkStruct.pointB)(iLink.heightB); +enddef; + +vardef LinkInfo@# = + numeric @#widthA, @#heightA; + string @#drawMethodA; + + numeric @#widthB, @#heightB; + string @#drawMethodB; + + string @#drawMethod; +enddef; + +% Draws a link using the given path as support. +% +vardef link(text iLink)(expr myPath)= + LinkStructure.ls(myPath, iLink.widthA, iLink.widthB); + drawLinkStructure(ls)(iLink); +enddef; + +% Draws a direct link between the center of the objects. +vardef clink(text iLink)(suffix objectA, objectB)= + link(iLink)(pathCut(objectA, objectB)(objectA.c--objectB.c)); +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_note.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_note.mp new file mode 100644 index 0000000000..083b686f65 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_note.mp @@ -0,0 +1,140 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_note_mp: + expandafter endinput +fi; +_metauml_note_mp:=1; + +% def metauml_note_debug text txt=log txt enddef; +def metauml_note_debug text txt= enddef; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce metauml_defaults; +inputonce util_log; + +inputonce util_object; +inputonce util_picture_stack; +inputonce util_shade; +inputonce util_margins; + +vardef NoteInfo@#= + attributes(@#); + var(color) foreColor, borderColor; + var(numeric) horizontalFolding, verticalFolding; + + FontInfo.@#iFont(metauml_defaultFont, defaultscale); + @#iFont.ignoreNegativeBase := 1; + + PictureInfo.@#iText (2, 2, 2, 2)(@#iFont); + PictureStackInfo.@#iStack (0, 0, 0, 0)(9)(@#iText); + + @#iStack.iPict.ignoreNegativeBase := 1; + + ShadeInfo.@#iShade; + Margins.@#(2,2,2,2); + + @#foreColor := .9white; + @#borderColor := black; + @#horizontalFolding := 10; + @#verticalFolding := 10; +enddef; + +vardef NoteInfoCopy@#(text src)= + attributes(@#); + var(color) foreColor, borderColor; + + log "NoteInfoCopy: Copying usecase info"; + + PictureStackInfoCopy.@#iStack (src.iStack); + MarginsCopy.@#(src); + ShadeInfoCopy.@#iShade(src.iShade); + + @#foreColor := src.foreColor; + @#borderColor := src.borderColor; + @#horizontalFolding := src.horizontalFolding; + @#verticalFolding := src.verticalFolding; +enddef; + +NoteInfo.iNote; + +vardef Note@#(text contents)= + ENote.@#(iNote)(contents); +enddef; + +vardef ENote@#(text _info)(text contents)= + ObjectEquations(@#); + @#className := "Note"; + + NoteInfoCopy.@#info(_info); + + %% The following code cannot work when pictures are given in the contents argument, such as in: + %% ENote.myNote(iNote)("This is a formula", TEX("$a=b$")); + %% + %numeric @#nLines; @#nLines := 0; + %string @#lines[]; + %for l=contents: + % @#lines[@#nLines] := l; + % @#nLines := @#nLines + 1; + %endfor; + % + %EPictureStack.@#stack(@#info.iStack)(scantokens listArray(@#lines)(@#nLines))("vleftbase"); + + EPictureStack.@#stack(@#info.iStack)(contents)("vleftbase"); +enddef; + +vardef Note_layout@#= + if @#laidout = 1: + log "Note " & (str @#) & " has already been layed out"; + else: + @#laidout := 1; + log "Note layout: " & (str @#); + + PictureStack_layout.@#stack; + + @#width = @#stack.width + @#info.left + @#info.right + @#info.horizontalFolding; + @#height = @#stack.height + @#info.top + @#info.bottom; + + @#top = @#stack.top + @#info.top; + @#left = @#stack.left - @#info.left; + fi; +enddef; + +vardef Note_draw@#= + Note_layout@#; + objectEnsurePositioning.@#; + + attributes(@#); + var(path) border, corner; + + @#border := @#nw -- (@#ne - (@#info.horizontalFolding, 0)) -- + (@#ne - (0, @#info.verticalFolding) ) -- @#se -- @#sw -- cycle; + + @#corner := (@#ne - (@#info.horizontalFolding, 0)) -- + (@#ne - (@#info.horizontalFolding, @#info.verticalFolding)) -- + (@#ne - (0, @#info.verticalFolding)); + + drawObjectShade(@#); + + fill Note_border.@# withcolor @#info.foreColor; + draw Note_border.@# withcolor @#info.borderColor; + + draw @#corner withcolor @#info.borderColor; + drawObject(@#stack); +enddef; + +vardef Note_border@#= + @#border +enddef; + diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_package.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_package.mp new file mode 100644 index 0000000000..2e76c41fd1 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_package.mp @@ -0,0 +1,176 @@ +% Copyright 2006 2015 Radu-George Radulescu, Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_package_mp: + expandafter endinput +fi; +_metauml_package_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce metauml_defaults; +inputonce util_log; + +vardef PackageInfo@#= + attributes(@#); + var(color) foreColor, borderColor; + var(numeric) forceEmptyContent; + var(numeric) minimumNameContentsDifference; + + FontInfo.@#iFont(metauml_defaultFont, defaultscale); + @#iFont.ignoreNegativeBase := 1; + + PictureInfo.@#iText (2, 2, 2, 2)(@#iFont); + PictureStackInfo.@#iNameStack (2, 2, 2, 2)(9)(@#iText); + @#iNameStack.iPict.ignoreNegativeBase := 1; + + Margins.@#(2,2,2,2); + + ShadeInfo.@#iShade; + @#foreColor := .9white; + @#borderColor := black; + + @#forceEmptyContent := 0; + + @#minimumNameContentsDifference := 20; + + GroupInfo.@#iContentsGroup(2, 2, 10, 2); +enddef; + +vardef PackageInfoCopy@#(text src)= + log "PackageInfoCopy: Copying package info"; + + attributes(@#); + var(color) foreColor, borderColor; + var(numeric) forceEmptyContent; + var(numeric) minimumNameContentsDifference; + + PictureStackInfoCopy.@#iNameStack (src.iNameStack); + MarginsCopy.@#(src); + + ShadeInfoCopy.@#iShade(src.iShade); + @#foreColor := src.foreColor; + @#borderColor := src.borderColor; + + @#forceEmptyContent := src.forceEmptyContent; + + @#minimumNameContentsDifference := src.minimumNameContentsDifference; + + GroupInfoCopy.@#iContentsGroup(src.iContentsGroup); +enddef; + +PackageInfo.iPackage; + +vardef Package@#(text contents)(text _subItems)= + EPackage.@#(iPackage)(contents)(_subItems); +enddef; + +vardef EPackage@#(text _info)(text contents)(text _subItems)= + ObjectEquations(@#); + @#className := "Package"; + + PackageInfoCopy.@#info(_info); + + numeric @#nLines; @#nLines := 0; + string @#lines[]; +% numeric @#nSubItems; @#nSubItems := 0; + numeric @#nameInCenter; @#nameInCenter := 0; + + for l=contents: + @#lines[@#nLines] := l; + @#nLines := @#nLines + 1; + endfor; + +% for s=_subItems: +% @#nSubItems := @#nSubItems + 1; +% endfor; + + EGroup.@#subItems(@#info.iContentsGroup)(_subItems); + + EPictureStack.@#nameStack(@#info.iNameStack)(scantokens listArray(@#lines)(@#nLines))("vcenterbase"); +enddef; + +vardef Package_layout@#= + if @#laidout = 1: + log "Package '" & (str @#) & "' has already been layed out"; + else: + @#laidout := 1; + log "Package layout: '" & (str @#) & "'"; + + log "Package name layout '" & (str @#) & "'..."; + PictureStack_layout.@#nameStack; + log "SubItems for package layout '" & (str @#) & "'..."; + Group_layout.@#subItems; + + log "All elements in package '" & (str @#) & "' successfully layed out, integrating..."; + + if @#subItems.nObjects = 0: + if @#info.forceEmptyContent = 0: + @#nameInCenter := 1; + fi; + fi; + + if @#subItems.width < @#nameStack.width + @#info.minimumNameContentsDifference: + @#contentWidth = @#nameStack.width + @#info.minimumNameContentsDifference; + else: + @#contentWidth = lmax(@#nameStack.width, @#subItems.width); + fi; + + if @#nameInCenter = 1: + @#height = @#info.top + @#info.bottom + @#nameStack.height; + @#width = @#info.left + @#info.right + @#nameStack.width; + @#nameStack.sw = @#sw + (@#info.left, @#info.bottom); + else: + @#nameStack.sw = @#nw; + @#width = @#contentWidth + @#info.left + @#info.right; + @#height = @#info.top + @#info.bottom + @#subItems.height; + fi; + + @#subItems.n = @#n + (0, -((@#height - @#subItems.height)/2)); + + log "Package layout for " & (str @#) & " ended."; + fi; +enddef; + +vardef Package_draw@#= + Package_layout.@#; + objectEnsurePositioning.@#; + + attributes(@#); + var(path) border, nameStackBorder, emptyNameBorder; + + @#border := @#ne -- @#nw -- @#sw -- @#se -- cycle; + @#nameStackBorder := @#nameStack.ne -- @#nameStack.nw -- @#nameStack.sw -- @#nameStack.se -- cycle; + @#emptyNameBorder := @#nw -- @#nw + (0, 10) -- @#n + (0, 10) -- @#n -- cycle; + + drawObjectShade(@#); + + fill @#border withcolor @#info.foreColor; + draw @#border withcolor @#info.borderColor; + if @#nameInCenter = 0: + fill @#nameStackBorder withcolor @#info.foreColor; + draw @#nameStackBorder withcolor @#info.borderColor; + else: + fill @#emptyNameBorder withcolor @#info.foreColor; + draw @#emptyNameBorder withcolor @#info.borderColor; + fi; + + + drawObject(@#nameStack); + drawObject(@#subItems); + +enddef; + +vardef Package_border@#= + @#border +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_package_relations.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_package_relations.mp new file mode 100644 index 0000000000..87f1cc4dd1 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_package_relations.mp @@ -0,0 +1,37 @@ +% Copyright 2006 2015 Radu-George Radulescu +% Licensed under the Apache License, Version 2.0. + +if known _metauml_package_relations_mp: + expandafter endinput +fi; +_metauml_package_relations_mp:=1; + +defaultRelationHeadWidth := 25; +defaultRelationHeadHeight := 10; + +vardef NestInfo@# = + LinkInfo@#; + + @#widthA = 0; + @#heightA = 0; + @#drawMethodA = "drawNothing"; + + @#widthB = defaultRelationHeadWidth; + @#heightB = defaultRelationHeadHeight; + @#drawMethodB = "drawCrossedCircle"; + + @#drawMethod = "drawLine"; +enddef; + +NestInfo.nest; + +vardef drawRelation(text iLink)(expr myPath)= + link(iLink)(myPath); +enddef; + +vardef drawLine(expr my_path) = + draw my_path; +enddef; + +vardef drawNothing(text pA)(text pB)(text base) = +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_paths.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_paths.mp new file mode 100644 index 0000000000..d93832fd0f --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_paths.mp @@ -0,0 +1,173 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_paths_mp: + expandafter endinput +fi; +_metauml_paths_mp:=1; + +def pathDirect(expr pA,pB) = + pA--pB +enddef; + +vardef pathManhattanX(text twoParams) = + pair pointA__, pointB__; + string paramA_str__, paramB_str__; + boolean paramA_isObject__, paramB_isObject__; + + paramA_isObject__ := true; + paramB_isObject__ := true; + + boolean isFirstParam__; + isFirstParam__ := true; + + %string twoParams; + %twoParams := ""; + + %twoParams := str paramA & ", " & str paramB; + %%includeonce% show "the two params are: " & twoParams; + + forsuffixes param__ = twoParams: + + if isFirstParam__: + isFirstParam__ := false; + paramA_str__ := str param__; + %includeonce% show "paramA_str__ <-- " & paramA_str__; + + if not known (scantokens (paramA_str__ & ".className")): + %includeonce% show "paramA is not an object"; + paramA_isObject__ := false; + fi; + else: + paramB_str__ := str param__; + %includeonce% show "paramB_str__ <-- " & paramB_str__; + + if not known (scantokens (paramB_str__ & ".className")): + %includeonce% show "paramB is not an object"; + paramB_isObject__ := false; + fi; + fi; + endfor; + + %includeonce% show paramA_str__; + %includeonce% show paramA_isObject__; + + %includeonce% show paramB_str__; + %includeonce% show paramB_isObject__; + + string stringPath__; + stringPath__ := "(0,0)--(50,50)"; + + if (not paramA_isObject__) and (not paramB_isObject__): + %includeonce% show "Both are points!"; + + + stringPath__ := paramA_str__ & "--(xpart " & paramB_str__ & ", ypart " & paramA_str__ & ") -- " & paramB_str__; + %includeonce% show stringPath__; + else: + pair refPointA__, refPointB__; + if paramA_isObject__: + refPointA__ := scantokens (paramA_str__ & ".c"); + else: + refPointA__ := scantokens paramA_str__; + fi; + if paramB_isObject__: + refPointB__ := scantokens (paramB_str__ & ".c"); + else: + refPointB__ := scantokens paramB_str__; + fi; + + %includeonce% show "Reference point A: "; + %includeonce% show refPointA__; + %includeonce% show "Reference point B: "; + %includeonce% show refPointB__; + + numeric dx__, dy__; + dx__ := xpart refPointB__ - xpart refPointA__; + dy__ := ypart refPointB__ - ypart refPointA__; + + string addornmentA__; + addornmentA__ := ""; + string addornmentB__; + addornmentB__ := ""; + + if (paramA_isObject__): + if (dx__ > 0): + addornmentA__ := ".e"; + else: + addornmentA__ := ".w"; + fi; + fi; + + if (paramB_isObject__): + if (dy__ > 0): + addornmentB__ := ".s"; + else: + addornmentB__ := ".n"; + fi; + fi; + stringPath__ := "pathManhattanX(" & paramA_str__ & addornmentA__ & ", " & paramB_str__ & addornmentB__ & ")"; + + %includeonce% show stringPath; + %includeonce% show "-------------------> recursive call"; + fi; + + scantokens stringPath__ +enddef; + +vardef rpathManhattanX(text twoParams) = + reverse pathManhattanX(twoParams) +enddef; + +vardef pathManhattanY(expr pA,pB) = + pA--(xpart(pA), ypart(pB))--pB +enddef; + +vardef rpathManhattanY(expr pA,pB) = + pB--(xpart(pA), ypart(pB))--pA +enddef; + +vardef pathStepX(expr pA,pB, deltax) = + pA--(pA+(deltax, 0))--(((xpart pA)+deltax), ypart(pB))--pB +enddef; + +vardef rpathStepX(expr pA,pB, deltax) = + pB--(((xpart pA)+deltax), ypart(pB))--(pA+(deltax, 0))--pA +enddef; + +vardef pathStepY(expr pA,pB, deltay) = + pA--(pA+(0, deltay))--(xpart(pB), ((ypart pA)+deltay))--pB +enddef; + +vardef rpathStepY(expr pA,pB, deltay) = + pB--(xpart(pB), ((ypart pA)+deltay))--(pA+(0, deltay))--pA +enddef; + +vardef pathHorizontal(expr pA, untilX) = + pA--(untilX,ypart(pA)) +enddef; + +vardef rpathHorizontal(expr pA, untilX) = + (untilX,ypart(pA))--pA +enddef; + +vardef pathVertical(expr pA, untilY) = + pA--(xpart(pA), untilY) +enddef; + +vardef rpathVertical(expr pA, untilY) = + (xpart(pA), untilY)--pA +enddef; + +% Cuts path thePath so that it won't intersect the objects +% objectA and objectB. The border of the objects is obtained +% by invoking the method "_border". +% +vardef pathCut(suffix objectA, objectB)(expr thePath)= + save timeA, timeB; + + timeA = xpart (thePath intersectiontimes objectBorder(objectA)); + timeB = xpart (thePath intersectiontimes objectBorder(objectB)); + + subpath (timeA, timeB) of thePath +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_skin_simple.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_skin_simple.mp new file mode 100644 index 0000000000..3225eb8fc3 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_skin_simple.mp @@ -0,0 +1,28 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +%% Usage of skins +%% +%% Skins are configuration files that, in geneal, customize the settings of +%% MetaUML *Info objects. You most likely want to include the skin file after +%% all other MetaUML files have been included: +%% +%% input metauml +%% input metauml_skin_simple +%% +%% % normal usage of MetaUML follows here +%% +%% More advanced skin files might customize fonts for specific elements +%% (eg for Class and Note), and also colors (eg foreground, shade, line etc.) + +if known _metauml_skin_simple_mp: + expandafter endinput +fi; +_metauml_skin_simple_mp:=1; + +iClass.foreColor := blue; +iClass.iName.iFont.name := "cmr12"; +iClass.iAttributeStack.iPict.iFont.name := "cmr10"; +iClass.iMethodStack.iPict.iFont.name := "cmr10"; + + diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_state.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_state.mp new file mode 100644 index 0000000000..08b5d3be24 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_state.mp @@ -0,0 +1,201 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_state_mp: + expandafter endinput +fi; +_metauml_state_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce metauml_defaults; +inputonce util_log; + +vardef StateInfo@#= + attributes(@#); + var(color) foreColor, borderColor; + var(numeric) round; + + FontInfo.@#iFont(metauml_defaultFont, defaultscale); + @#iFont.ignoreNegativeBase := 1; + + PictureInfo.@#iText (2, 2, 2, 2)(@#iFont); + PictureStackInfo.@#iStack (2, 2, 2, 2)(9)(@#iText); + + @#iStack.iPict.ignoreNegativeBase := 1; + + Margins.@#(2,2,0,6); + + GroupInfo.@#iGroupSubstates(2, 2, 4, 2); + + @#round := 5; + @#drawNameLine := 0; + + ShadeInfo.@#iShade; + @#foreColor := .9white; + @#borderColor := black; +enddef; + +vardef StateInfoCopy@#(text src)= + log "StateInfoCopy: Copying state info"; + attributes(@#); + var(color) foreColor, borderColor; + var(numeric) round; + + PictureStackInfoCopy.@#iStack (src.iStack); + MarginsCopy.@#(src); + @#round := src.round; + @#drawNameLine := src.drawNameLine; + + GroupInfoCopy.@#iGroupSubstates(src.iGroupSubstates); + + ShadeInfoCopy.@#iShade(src.iShade); + @#foreColor := src.foreColor; + @#borderColor := src.borderColor; +enddef; + +StateInfo.iState; + +vardef State@#(text contents)(text _substates)= + EState.@#(iState)(contents)(_substates); +enddef; + +vardef EState@#(text _info)(text contents)(text _substates)= + ObjectEquations(@#); + @#className := "State"; + + StateInfoCopy.@#info(_info); + + numeric @#nLines; @#nLines := 0; + string @#lines[]; + + numeric @#nInternalTransitions; @#nInternalTransitions := 0; + string @#internalTransitions[]; + + for l=contents: + @#lines[@#nLines] := l; + @#nLines := @#nLines + 1; + endfor; + + EGroup.@#substates(@#info.iGroupSubstates)(_substates); + %@#substates.info.boxed := 1; + + EPictureStack.@#stack(@#info.iStack)(scantokens listArray(@#lines)(@#nLines))("vcenterbase"); +enddef; + +vardef stateTransitions@#(text transitions)= + State_internalTransitions@#(transitions); +enddef; + +vardef State_internalTransitions@#(text transitions)= + for transition=transitions: + @#internalTransitions[@#nInternalTransitions] := transition; + @#nInternalTransitions := @#nInternalTransitions + 1; + endfor; +enddef; + +vardef State_layout@#= + if @#laidout = 1: + log "State '" & (str @#) & "' has already been layed out"; + else: + @#laidout := 1; + log "State layout: '" & (str @#) & "'"; + + EPictureStack.@#internalTransitionsStack(@#info.iStack) + (scantokens listArray(@#internalTransitions)(@#nInternalTransitions))("vleftbase"); + + log "State name layout '" & (str @#) & "'..."; + PictureStack_layout.@#stack; + log "Internal transitions layout '" & (str @#) & "'..."; + PictureStack_layout.@#internalTransitionsStack; + log "Substates layout '" & (str @#) & "'..."; + Group_layout.@#substates; + + log "All elements in state '" & (str @#) & "' successfully layed out, integrating..."; + +% @#internalTransitionsStack.info.boxed := 1; + + @#contentWidth = lmax(@#stack.width, @#internalTransitionsStack.width, @#substates.width); + + @#width = @#contentWidth + @#info.left + @#info.right + 2 * @#info.round; + @#height = @#stack.height + @#info.top + @#info.bottom + + @#internalTransitionsStack.height + @#substates.height; + + @#stack.n = @#n + (0, -@#info.top); + @#substates.n = @#stack.s; + + @#internalTransitionsStack.sw = @#sw + (@#info.round, @#info.round); + + attributes(@#); + var(pair) urt, lrt, ulft, llft; + var(pair) urta, lrta, ulfta, llfta; + var(pair) urtb, lrtb, ulftb, llftb; + + @#urta := @#ne - (@#info.round, 0); + @#urtb := @#ne - (0, @#info.round); + + @#lrta := @#se + (0, @#info.round); + @#lrtb := @#se - (@#info.round, 0); + + @#ulfta := @#nw - (0, @#info.round); + @#ulftb := @#nw + (@#info.round, 0); + + @#llfta := @#sw + (@#info.round, 0); + @#llftb := @#sw + (0, @#info.round); + + @#urt := @#ne - (@#info.round, @#info.round) + @#info.round * (sind(45),cosd(45)); + @#lrt := @#se + (-@#info.round, @#info.round) + @#info.round * (sind(135),cosd(135)); + @#llft := @#sw + (@#info.round, @#info.round) + @#info.round * (sind(225),cosd(225)); + @#ulft := @#nw + (@#info.round, -@#info.round) + @#info.round * (sind(315),cosd(315)); + + var(pair) nameLineLeft, nameLineRight; + ypart @#nameLineLeft = ypart @#nameLineRight = @#stack.bottom; + xpart @#nameLineLeft = xpart @#nw; + xpart @#nameLineRight = xpart @#ne; + + log "State layout for " & (str @#) & " ended."; + fi; +enddef; + +vardef State_draw@#= + State_layout.@#; + objectEnsurePositioning.@#; + + attributes(@#); + var(path) border; + + @#border := @#urta .. @#urt .. @#urtb -- % + @#lrta .. @#lrt .. @#lrtb -- % + @#llfta .. @#llft .. @#llftb -- % + @#ulfta .. @#ulft .. @#ulftb -- cycle; + + %fill @#border shifted (@#info.shade, -@#info.shade) withcolor .7white; + drawObjectShade(@#); + + fill @#border withcolor @#info.foreColor; + draw @#border withcolor @#info.borderColor; + + + drawObject(@#internalTransitionsStack); + drawObject(@#stack); + drawObject(@#substates); + + if @#info.drawNameLine = 1: + draw @#nameLineLeft -- @#nameLineRight; + fi; +enddef; + +vardef State_border@#= + @#border +enddef; + diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_stereotype.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_stereotype.mp new file mode 100644 index 0000000000..9251c30833 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_stereotype.mp @@ -0,0 +1,25 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_stereotype_mp: + expandafter endinput +fi; +_metauml_stereotype_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce metauml_defaults; + +FontInfo.assocFont(metauml_defaultFont, .7); +PictureInfo.iStereo(2, 2, 2, 2)(assocFont); +iStereo.ignoreNegativeBase := 1; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_templates.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_templates.mp new file mode 100644 index 0000000000..940377bc20 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_templates.mp @@ -0,0 +1,132 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_templates_mp: + expandafter endinput +fi; +_metauml_templates_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce metauml_defaults; +inputonce util_log; + +vardef TemplateInfo@#= + color @#background; + color @#borderColor; + numeric @#borderScale; + + @#background := .9white; + @#borderColor := black; + @#borderScale := 1; + + FontInfo.@#iFont(metauml_defaultFont, .9); + PictureInfo.@#iPict(2, 2, 2, 2)(@#iFont); + PictureStackInfo.@#iStack(2, 2, 1, 1)(7)(@#iPict); + + @#iStack.iPict.ignoreNegativeBase := 1; +enddef; + +vardef TemplateInfoCopy@#(text src)= + color @#background; + color @#borderColor; + numeric @#borderScale; + + @#background := src.background; + @#borderColor := src.borderColor; + @#borderScale := src.borderScale; + + FontInfoCopy.@#iFont(src.iFont); + PictureInfoCopy.@#iPict(src.iPict); + PictureStackInfoCopy.@#iStack(src.iStack); +enddef; + +TemplateInfo.iTemplate; + +% +% Template +% +vardef ETemplate@#(text _info)(text templates) = + ObjectEquations(@#); + @#className := "Template"; + + TemplateInfoCopy.@#info(_info); + + EPictureStack.@#elementsStack(@#info.iStack)(templates)("vleftbase"); + + @#nw = @#elementsStack.nw; + @#se = @#elementsStack.se; +enddef; + +vardef Template@#(text templates) = + ETemplate@#(iTemplate)(templates); +enddef; + +vardef EClassTemplate@#(text _info)(text templates)(text theClass)= + ETemplate.@#(_info)(templates); + Template_attachToClass.@#(theClass); +enddef; + +vardef ClassTemplate@#(text templates)(text theClass)= + EClassTemplate.@#(iTemplate)(templates)(theClass); +enddef; + +vardef Template_layout@#= + if @#laidout = 1: + log "Template " & (str @#) & " has already been layed out"; + else: + @#laidout := 1; + log "Template layout: " & (str @#); + PictureStack_layout.@#elementsStack; + fi; +enddef; + +vardef Template_paintSkin@# = + log "Painting template skin..."; + + fill objectBox(@#) withcolor @#info.background; + + draw objectBox(@#) dashed evenly scaled .8 + withpen pencircle scaled @#info.borderScale withcolor @#info.borderColor; +enddef; + +vardef Template_draw@# = + Template_layout.@#; + + Template_paintSkin.@#; + drawObject(@#elementsStack); +enddef; + +vardef Template_attachToClass@#(text theClass)= + Template_layout.@#; + Class_layout.theClass; + + log "--- Attaching template " & (str @#) & " to class " & (str theClass); + + save __nItems, __nameToRight; + + __nItems := @#elementsStack.nItems; + __nameToRight := theClass.right - theClass.namePict.right; + + @#elementsStack.pict[__nItems-1].midy = theClass.top; + + if __nameToRight > @#width/2: + @#midx = theClass.right; + log "X"; + else: + @#midx = theClass.right + (@#width/2 - __nameToRight) + 2; + log "Y"; + fi; + + %@#elementsStack.pict[__nItems-1].info.boxed:=1; +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_usecase.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_usecase.mp new file mode 100644 index 0000000000..f9c666abf3 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_usecase.mp @@ -0,0 +1,215 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _metauml_usecase_mp: + expandafter endinput +fi; +_metauml_usecase_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce metauml_defaults; +inputonce util_log; + +vardef ActorInfo@#= + FontInfo.@#iFont(metauml_defaultFont, defaultscale); + @#iFont.ignoreNegativeBase := 1; + + PictureInfo.@#iName (2, 2, 2, 2)(@#iFont); + PictureStackInfo.@#iNameStack (1pt, 1pt, 1pt, 1pt)(9)(@#iName); + + @#iNameStack.iPict.ignoreNegativeBase := 1; + + HumanInfo.@#iHuman(25, 35, .3, .35, .5, 1, 1); +enddef; + +vardef ActorInfoCopy@#(text src)= + log "ActorInfoCopy: Copying actor info"; + + PictureStackInfoCopy.@#iNameStack (src.iNameStack); + + HumanInfoCopy.@#iHuman(src.iHuman); +enddef; + +ActorInfo.iActor; + +vardef Actor@#(text contents)= + EActor.@#(iActor)(contents); +enddef; + +vardef EActor@#(text _info)(text contents)= + ObjectEquations(@#); + @#className := "Actor"; + + ActorInfoCopy.@#info(_info); + + numeric @#nLines; @#nLines := 0; + string @#lines[]; + for l=contents: + @#lines[@#nLines] := l; + @#nLines := @#nLines + 1; + endfor; + EHuman.@#human(@#info.iHuman); + EPictureStack.@#nameStack(@#info.iNameStack)(scantokens listArray(@#lines)(@#nLines))("vcenterbase"); +enddef; + +vardef Actor_setDebugMode@#= + @#.nameStack.info.boxed := 1; +enddef; + +vardef Actor_layout@#= + if @#laidout = 1: + log "Actor " & (str @#) & " has already been layed out"; + else: + @#laidout := 1; + log "Actor layout: " & (str @#); + Human_layout.@#human; + PictureStack_layout.@#nameStack; + + @#width = max(@#nameStack.width)(@#human.width); + @#height = @#nameStack.height + @#human.height; + + @#n = @#human.n; + @#nameStack.n=@#human.s; + @#s = @#nameStack.s; + fi; +enddef; + +vardef Actor_draw@#= + Actor_layout.@#; + + objectEnsurePositioning.@#; + + drawObjects(@#nameStack, @#human); +enddef; + +vardef Actor_border@#= + objectBox(@#); +enddef; + +vardef UsecaseInfo@#= + attributes(@#); + var(color) foreColor, borderColor; + + FontInfo.@#iFont(metauml_defaultFont, defaultscale); + @#iFont.ignoreNegativeBase := 1; + + PictureInfo.@#iName (2, 2, 2, 2)(@#iFont); + PictureStackInfo.@#iNameStack (0, 0, 0, 0)(9)(@#iName); + + @#iNameStack.iPict.ignoreNegativeBase := 1; + + Margins.@#(2,2,2,2); + + @#hFatRatio := .1; + @#vFatRatio := .15; + + ShadeInfo.@#iShade; + @#foreColor := .9white; + @#borderColor := black; +enddef; + +vardef UsecaseInfoCopy@#(text src)= + log "UsecaseInfoCopy: Copying usecase info"; + attributes(@#); + var(color) foreColor, borderColor; + + PictureStackInfoCopy.@#iNameStack (src.iNameStack); + MarginsCopy.@#(src); + @#hFatRatio := src.hFatRatio; + @#vFatRatio := src.vFatRatio; + + ShadeInfoCopy.@#iShade(src.iShade); + @#foreColor := src.foreColor; + @#borderColor := src.borderColor; +enddef; + +UsecaseInfo.iUsecase; + +vardef Usecase@#(text contents)= + EUsecase.@#(iUsecase)(contents); +enddef; + +vardef EUsecase@#(text _info)(text contents)= + ObjectEquations(@#); + @#className := "Usecase"; + + UsecaseInfoCopy.@#info(_info); + + attributes(@#); + var(numeric) nLines; + @#nLines := 0; + + string @#lines[]; + for l=contents: + @#lines[@#nLines] := l; + @#nLines := @#nLines + 1; + endfor; +enddef; + +vardef Usecase_layout@#= + if @#laidout = 1: + log "Usecase " & (str @#) & " has already been layed out"; + else: + @#laidout := 1; + + EPictureStack.@#nameStack(@#info.iNameStack)(scantokens listArray(@#lines)(@#nLines))("vcenterbase"); + PictureStack_layout.@#nameStack; + + numeric @#vFat, @#hFat; + + @#hFat = 0; + @#vFat = 10; + + @#width = @#nameStack.width + @#info.left + @#info.right + 2 * @#hFat; + @#height = @#nameStack.height + @#info.top + @#info.bottom + 2 * @#vFat; + + log "UC w,h"; + log @#hFat; + log @#vFat; + log @#nameStack.width; + log @#nameStack.height; + log @#width; + log @#height; + + @#c = @#nameStack.c; + fi; +enddef; + +vardef Usecase_draw@#= + Usecase_layout@#; + + pair @#urt, @#lrt, @#ulft, @#llft; + + @#urt = @#nameStack.ne; + @#lrt = @#nameStack.se; + @#ulft = @#nameStack.nw; + @#llft = @#nameStack.sw; + + objectEnsurePositioning.@#; + + path @#border; + %@#border := @#w .. @#ulft .. @#n .. @#urt .. @#e .. @#lrt .. @#s .. @#llft .. cycle; + @#border := @#w .. @#n .. @#e .. @#s .. cycle; + + drawObjectShade(@#); + + fill Usecase_border.@# withcolor @#info.foreColor; + draw Usecase_border.@# withcolor @#info.borderColor; + + drawObject(@#nameStack); +enddef; + +vardef Usecase_border@#= + @#border +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/metauml_usecase_clipart.mp b/graphics/metapost/contrib/macros/metauml/inputs/metauml_usecase_clipart.mp new file mode 100644 index 0000000000..3344454bc4 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/metauml_usecase_clipart.mp @@ -0,0 +1,158 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +%% +%% This file contains various drawings which can be used in +%% UML usecase diagrams +%% + +if known _metauml_usecase_clipart_mp: + expandafter endinput +fi; +_metauml_usecase_clipart_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_log; + +vardef HumanInfo@#(expr _width, _height, _yHeadRatio, _yBodyRatio, _yHandsRatio, _xHandsRatio, _xLegsRatio)= + attributes(@#); + + var(numeric) width, height, yHeadRatio, yBodyRatio, + yHandsRatio, xHandsRatio, xLegsRatip; + var(color) foreColor, shadeColor; + var(numeric) shade; + + @#width := _width; + @#height := _height; + @#yHeadRatio := _yHeadRatio; + @#yBodyRatio := _yBodyRatio; + @#yHandsRatio := _yHandsRatio; + @#xHandsRatio := _xHandsRatio; + @#xLegsRatio := _xLegsRatio; + + @#foreColor := black; + @#shadeColor := .7white; + @#shade := .5; + + Margins.@#(2,2,1,0); +enddef; + +vardef HumanInfoCopy@#(text src)= + HumanInfo@#(src.width, src.height, src.yHeadRatio, src.yBodyRatio, src.yHandsRatio, src.xHandsRatio, src.xLegsRatio); + + _n_ := str @#; + var(color) foreColor, shadeColor; + var(numeric) shade; + + @#foreColor := src.foreColor; + @#shadeColor := src.shadeColor; + @#shade := src.shade; + + MarginsCopy.@#(src); +enddef; + +HumanInfo.iHuman(25, 25, .3, .35, .55, 1, 1); + +vardef EHuman@#(text _info)= + ObjectEquations(@#); + @#className := "Human"; + + var(path) pHead, pBody, pHands, pLegs; + + HumanInfoCopy.@#info(_info); +enddef; + +vardef Human@#= + EHuman@#(iHuman); +enddef; + +vardef Human_layout@#= + if @#laidout = 1: + log "Human " & (str @#) & " has already been layed out"; + else: + @#laidout := 1; + log "Human layout: " & (str @#); + + attributes(@#); + + @#height = @#info.height; + @#width = @#info.width; + + log "(W, H) MUST BE SET. Their values are: " & (decimal @#height) &" "& (decimal @#width); + + var(numeric) actualHeight, actualWidth; + @#actualHeight = @#height - @#info.top - @#info.bottom; + @#actualWidth = @#width - @#info.left - @#info.right; + + % HEAD + var(pair) headS, headE, headW; + + ypart @#headW = ypart @#headE; + .5[@#n - (0, @#info.top), @#headS] = .5[@#headE, @#headW]; + (ypart @#n - @#info.top) - (ypart @#headS) = + (xpart @#headE) - (xpart @#headW) = + @#actualHeight * @#info.yHeadRatio; + (xpart @#headS) = (xpart @#n); + + % BODY + var(pair) bodyS; + xpart @#bodyS = xpart @#headS; + ypart @#headS - ypart @#bodyS = @#actualHeight * @#info.yBodyRatio; + + % HANDS + var(pair) handsW, handsE; + ypart @#handsW = ypart @#handsE = ypart @#n - (@#actualHeight * @#info.yHandsRatio); + .5[xpart @#handsE, xpart @#handsW] = @#midx; + xpart @#handsE - xpart @#handsW = @#actualWidth * @#info.xHandsRatio; + + % LEGS + var(pair) footW, footE; + ypart @#footW = ypart @#footE = ypart @#s + @#info.bottom; + .5[xpart @#footW, xpart @#footE] = @#midx; + xpart @#footE - xpart @#footW = @#actualWidth * @#info.xLegsRatio; + + log "Human layout completed"; + fi; +enddef; + +vardef Human_draw@#= + log "Drawing human"; + + Human_layout.@#; + objectEnsurePositioning.@#; + + % all coordinates must be set to known values in order to compute the paths + @#pHead := (@#n - (0, @#info.top)) .. @#headE .. @#headS .. @#headW .. cycle; + @#pBody := @#headS -- @#bodyS; + @#pHands := @#handsW -- @#handsE; + @#pLegs := @#footW -- @#bodyS -- @#footE; + + attributes(@#); + var(pair) shadeShift; + @#shadeShift = (@#info.shade, -@#info.shade); + + draw @#pHead shifted @#shadeShift withcolor @#info.shadeColor; + draw @#pBody shifted @#shadeShift withcolor @#info.shadeColor; + draw @#pHands shifted @#shadeShift withcolor @#info.shadeColor; + draw @#pLegs shifted @#shadeShift withcolor @#info.shadeColor; + + draw @#pHead withcolor @#info.foreColor; + draw @#pBody withcolor @#info.foreColor; + draw @#pHands withcolor @#info.foreColor; + draw @#pLegs withcolor @#info.foreColor; +enddef; + +vardef Human_border@#= + objectBox(@#) +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/util_commons.mp b/graphics/metapost/contrib/macros/metauml/inputs/util_commons.mp new file mode 100644 index 0000000000..3ff7f06e83 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/util_commons.mp @@ -0,0 +1,137 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _util_commons_mp: + expandafter endinput +fi; +_util_commons_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_log; + +vardef lmax(text items)= + log "finding lmax of items " & str items; + save current, nItems; + numeric current, nItems; + nItems := 0; + current:= 0; + + for item = items: + log nItems; + log item; + + if nItems = 0: + current := item; + else: + current := max(current)(item); + fi; + nItems := nItems + 1; + endfor; + + current +enddef; + +vardef lmin(text items)= + save current, nItems; + numeric current, nItems; + nItems := 0; + current:= 0; + + for item = items: + if nItems = 0: + current := item; + else: + current := min(current)(item); + fi; + nItems := nItems + 1; + endfor; + + current +enddef; + +def _max(text a)(text b)= + if (a > b): a% + else:b% + fi; +enddef; + +def _min(text a)(text b)= + if (a < b): a% + else:b% + fi; +enddef; + +vardef ensurePict(text pictOrText)(expr font, scale) = + save p; picture p; + if picture pictOrText: p=pictOrText + else: p = pictOrText infont font scaled scale + fi; + p +enddef; + +def pictHeight(text obj) = + (ypart (urcorner obj) - ypart (llcorner obj)) +enddef; + +def pictWidth(text obj) = + (xpart (urcorner obj) - xpart (llcorner obj)) +enddef; + +vardef listArray(text array)(text nElements)= + save objEnum; + string objEnum; + objEnum := ""; + + for i = 0 upto nElements-1: + if i>0: + objEnum := objEnum & ", "; + fi; + objEnum := objEnum & (str array) & (decimal i); + endfor; + + objEnum +enddef; + +vardef enumToString(text enumeration)(expr prefix)= + save ret, firstVar; + string ret; + ret := ""; + + numeric firstVar; + firstVar := 1; + + forsuffixes v = enumeration: + if firstVar = 0: + ret := ret & ","; + else: + firstVar := 0; + fi; + + ret := ret & prefix & (str v); + endfor; + + ret +enddef; + +def _dx(text pA)(text pB) = + (xpart(pB)-xpart(pA)) +enddef; + +def _dy(text pA, pB) = + (ypart(pB)-ypart(pA)) +enddef; + +def _length(text pA)(text pB) = + sqrt (_dx(pA)(pB)*_dx(pA)(pB) + _dy(pA)(pB)*_dy(pA)(pB)) +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/util_group.mp b/graphics/metapost/contrib/macros/metauml/inputs/util_group.mp new file mode 100644 index 0000000000..7dad82ba02 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/util_group.mp @@ -0,0 +1,181 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _util_group_mp: + expandafter endinput +fi; +_util_group_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_object; +inputonce util_commons; +inputonce util_margins; +inputonce util_log; + +vardef GroupInfo@#(expr pleft, pright, ptop, pbottom)= + attributes(@#); + var(color) borderColor; + var(numeric) boxed; + + @#boxed := 0; + @#borderColor := red; + + Margins.@#(pleft, pright, ptop, pbottom); +enddef; + +vardef GroupInfoCopy@#(text src)= + GroupInfo@#(src.left, src.right, src.top, src.bottom); + + @#boxed := src.boxed; + @#borderColor := src.borderColor; + +enddef; + +GroupInfo.iGroup(2, 2, 2, 2); +GroupInfo.iGroupNoMargins(0, 0, 0, 0); + +GroupInfoCopy.iGroupBoxed(iGroup); +iGroupBoxed.boxed := 1; + +vardef EGroup@#(text groupInfo)(text objects)= + ObjectEquations(@#); + @#className := "Group"; + + var(numeric) minx, maxx, miny, maxy; + var(numeric) nObjects; + var(string) objectsAsString; + + GroupInfoCopy.@#info(groupInfo); + + @#objectsAsString := enumToString(objects)(""); + log @#objectsAsString; + + @#nObjects := 0; + if @#objectsAsString <> "": + forsuffixes obj = scantokens @#objectsAsString: + @#nObjects := @#nObjects + 1; + endfor; + fi; + +enddef; + +vardef Group@#(text objects)= + EGroup@#(iGroup)(objects); +enddef; + +vardef Group_layout@#= + if @#laidout = 0: + log "Needing layout for group " & (str @#); + @#laidout := 1; + + log "Calling layout for objects in group '" & (str @#) & "' ."; + log " Objects are: '" & @#objectsAsString & "'."; + + if (@#objectsAsString = ""): + log "Empty layout begin"; + @#width = @#info.left + @#info.right; + @#height = @#info.top + @#info.bottom; + log "Empty layout end"; + else: + log "Layout with content"; + layoutObjects(scantokens @#objectsAsString); + log "All objects in group '" & (str @#) & "' are now laid out."; + + % As already tested, @#objectsAsString must be <> "". + % See page 53, User's manual for MetaPost + % "if some of the suffixes are empty, the loop gets + % executed, with the loop index parameter set to + % the empty suffix" (!) + + log "Group_layout: finding min/max x/y of objects:" & @#objectsAsString; + + __objectIndex := 0; + forsuffixes obj__ = scantokens @#objectsAsString: + if __objectIndex = 0: + log "Group_layout: first object " & str obj__ & ", initial minx, maxx, miny, maxy follow."; + @#minx := obj__.left; + @#maxx := obj__.right; + @#miny := obj__.bottom; + @#maxy := obj__.top; + + log @#minx; + log @#maxx; + log @#miny; + log @#maxy; + __objectIndex := __objectIndex + 1; + else: + log "Group_layout: current object " & str obj__; + + log "comparing minx"; + log @#minx; + log obj__.left; + @#minx := min(@#minx, obj__.left); + + log "comparing maxx"; + log @#maxx; + log obj__.right; + @#maxx := max(@#maxx, obj__.right); + + log "comparing miny"; + log @#miny; + log obj__.bottom; + @#miny := min(@#miny, obj__.bottom); + + log "comparing maxy"; + log @#maxy; + log obj__.top; + @#maxy := max(@#maxy, obj__.top); + + __objectIndex := __objectIndex + 1; + fi; + endfor; + log "Group_layout: finding min/max x/y: done."; + log @#minx; + log @#maxx; + log @#miny; + log @#maxy; + + log "Group_layout: about to set nw, se"; + log @#nw; + log @#se; + + @#nw = (@#minx - @#info.left, @#maxy + @#info.top); + @#se = (@#maxx + @#info.right, @#miny - @#info.bottom); + + log "Done performing actual layout for group " & str @#; + fi; + else: + log "NOT needing layout for group " & (str @#); + fi; +enddef; + +vardef Group_draw@#= + log "Drawing group...."; + Group_layout@#; + objectEnsurePositioning.@#; + + if @#objectsAsString <> "": + drawObjects(scantokens @#objectsAsString); + fi; + + if (@#info.boxed = 1): + draw objectBox(@#) withcolor @#info.borderColor; + fi; +enddef; + +vardef Group_border@#= + objectBox(@#) +enddef; + + diff --git a/graphics/metapost/contrib/macros/metauml/inputs/util_infrastructure.mp b/graphics/metapost/contrib/macros/metauml/inputs/util_infrastructure.mp new file mode 100644 index 0000000000..8e6c2ed05d --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/util_infrastructure.mp @@ -0,0 +1,56 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _util_infrastructure_mp: + expandafter endinput +fi; +_util_infrastructure_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_log; + +vardef attributes(text objectName)= + _n_ := str objectName +enddef; + +vardef variables_ext text variables= + save ret, firstVar; + string ret; + ret := ""; + + numeric firstVar; + firstVar := 1; + + forsuffixes v = variables: + if firstVar = 0: + ret := ret & ","; + else: + firstVar := 0; + fi; + + ret := ret & " _n." & (str v); + endfor; + + ret +enddef; + +vardef var(text type) text variables = + save _variables; + string _variables; + _variables := variables_ext variables; + + generic_declare(type) scantokens _variables; +enddef; + + diff --git a/graphics/metapost/contrib/macros/metauml/inputs/util_log.mp b/graphics/metapost/contrib/macros/metauml/inputs/util_log.mp new file mode 100644 index 0000000000..61c86ec8d6 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/util_log.mp @@ -0,0 +1,31 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +%%% if known _util_log_mp: +%%% expandafter endinput +%%% fi; +_util_log_mp:=1; + +util_loglevel_PARANOIA:=1; +util_loglevel_DEBUG:=2; +util_loglevel_RELEASE:=3; +util_loglevel_SILENT:=4; + +util_log_thresholdlevel := util_loglevel_DEBUG; +util_log_defaultlevel := util_loglevel_RELEASE; + +def elog(expr loglevel) text txt= + if (loglevel <= util_log_thresholdlevel): + %includeonce% show txt + else: + % do nothing + fi; +enddef; + +def log text txt= + if (util_log_defaultlevel <= util_log_thresholdlevel): + show txt + else: + % do nothing + fi; +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/util_margins.mp b/graphics/metapost/contrib/macros/metauml/inputs/util_margins.mp new file mode 100644 index 0000000000..7b014ee9e7 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/util_margins.mp @@ -0,0 +1,21 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _util_margins_mp: + expandafter endinput +fi; +_util_margins_mp:=1; + +vardef Margins@#(expr pleft, pright, ptop, pbottom)= + attributes(@#); + var(numeric) left, right, top, bottom; + + @#left := pleft; + @#right := pright; + @#top := ptop; + @#bottom := pbottom; +enddef; + +vardef MarginsCopy@#(text src)= + Margins@#(src.left, src.right, src.top, src.bottom); +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/util_object.mp b/graphics/metapost/contrib/macros/metauml/inputs/util_object.mp new file mode 100644 index 0000000000..fbc569dd6f --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/util_object.mp @@ -0,0 +1,233 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _util_object_mp: + expandafter endinput +fi; +_util_object_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_infrastructure; +inputonce util_log; + +def ObjectEquations(suffix $)= + attributes($); + var(pair) n, ne, e, se, s, sw, w, nw, c; + var(pair) dim; + var(numeric) width, height; + + var(numeric) left, right; + var(numeric) top, bottom; + var(numeric) midx, midy; + + var(picture) pict; + var(string) className; + + var(numeric) laidout, drawn; + + $.laidout := 0; + $.drawn := 0; + + $.left = xpart $.nw = xpart $.sw; + $.right = xpart $.ne = xpart $.se; + + $.top = ypart $.ne = ypart $.nw; + $.bottom = ypart $.se = ypart $.sw; + + $.w = .5[$.nw,$.sw]; + $.s = .5[$.sw,$.se]; + $.e = .5[$.ne,$.se]; + $.n = .5[$.ne,$.nw]; + + $.c = .5[$.nw, $.se]; + + $.width = $.right - $.left; + $.height = $.top - $.bottom; + + $.midx = xpart($.c); + $.midy = ypart($.c); + + xpart $.dim = $.width; + ypart $.dim = $.height; + + $.className := "Object"; +enddef; + +def objectBox(text obj)= + obj.nw -- obj.ne -- obj.se -- obj.sw -- cycle +enddef; + +vardef objectBorder(suffix @#)= + save methodName; + string methodName; + methodName := @#className & "_border"; + log "objectBorder: invoking " & methodName & " arg=" & str @#; + + scantokens (methodName).@# +enddef; + +vardef Object_toString(text obj)= + save ret; string ret; + ret := "Generic object"; + ret +enddef; + +vardef toString(suffix @#)= + scantokens (@#className & "_toString").@# +enddef; + +vardef layoutObject(suffix @#)= + save methodName; + string methodName; + methodName := @#className & "_layout"; + log "layoutObject: invoking " & methodName & " arg=" & str @#; + + scantokens (methodName).@#; +enddef; + +vardef drawObject(suffix @#)= + save methodName; + string methodName; + methodName := @#className & "_draw"; + log "drawObject: invoking " & methodName & " arg=" & str @#; + + scantokens (methodName).@#; +enddef; + +vardef drawObjectShade(suffix @#)= + fill objectBorder(@#) shifted + (@#.info.iShade.shift, -@#.info.iShade.shift) withcolor @#.info.iShade.background; +enddef; + +vardef objectEnsurePositioning@#= + if unknown (xpart @#nw): + log "*** WARNING: DEFAULTING OBJECT'S (" & (str @#) & ") x TO 0"; + xpart @#nw = 0; + fi; + if unknown (ypart @#nw): + log "*** WARNING: DEFAULTING OBJECT'S (" & (str @#) & ") y TO 0"; + ypart @#nw = 0; + fi; +enddef; + +vardef drawObjectAt(suffix @#)(text eq)= + eq; + drawObject(@#); +enddef; + +vardef layoutObjects(text objects)= + log "layoutObjects: begin"; + forsuffixes o = objects: + if (str o) <> "": + layoutObject(o); + fi; + endfor; + log "layoutObjects: end"; +enddef; + +vardef drawObjects(text objects)= + % This needs to be done first in order to allow for equations which define + % relative positioning to be appropiately solved. Otherwise, for example, + % object0 may be positioned somewhere by default, and object1 also, leading + % to inconsitent equations. Inconsistency would have been caused by the fact that the + % positioning equations become meaningful only after object layout is performed + % --- but that would have been too late, since the positioning would have been + % done already to inappropriate values. + % + layoutObjects(objects); + + forsuffixes o = objects: + if (str o) <> "": + drawObject(o); + fi; + endfor; +enddef; + +%% +%% Joins the given pictures according to the equation given +%% by the pictureDoJoin macro. Note: the pictureDoJoin macro +%% can be conveniently set by calling setPicutureJoin macro. +%% +%% Usage example: +%% joinObjects (p, q, r); +%% +def joinObjects(text pictures)= + log "joinObjects: call started."; + + save _index; + _index := 0; + forsuffixes p=pictures: + exitif (str p) = ""; + if _index=0: + log " joinObjects: calling join for first object."; + log _index; + log p; + objectDoJoinFirst(p)(_index); + else: + log " joinObjects: calling join for next object."; + log _index; + log p; + objectDoJoin(previousPic, p)(_index); + fi; + + _index := _index + 1; + def previousPic=p enddef; + endfor; + + log "joinObjects: call ended." +enddef; + +%% +%% Sets the macro pictureDoJoin, which is used by joinObjects to join +%% one picture into another. +%% +%% The pictureDoJoin macro has two arguments: pa and pb. +%% pa represents the first picture and pb the second picture. +%% The second picture is positioned relatively to pa as specified +%% by the given equation. +%% +%% Usage examples: +%% +%% % place the second picture at the bottom of the first +%% setPictureJoin(pa.sw = pb.nw); +%% +%% % place the second picture at the right of the first +%% setPictureJoin(pa.ne = pb.nw); +%% +def setObjectJoin(text eq)= + def objectDoJoin(suffix pa, pb)(expr index)=eq; enddef; + def objectDoJoinFirst(suffix pa)(expr index)= log " objectDoJoinFirst: NOP"; enddef; +enddef; + +def setObjectJoinFirst(text eq)= + def objectDoJoinFirst(suffix pa)(expr index)=eq; enddef; +enddef; + +%% +%% A shortcut for setting the join equation and actually performing the join. +% +def joinObjectsEq(text objects)(text eq)= + setObjectJoin(eq); + joinObjects(objects); +enddef; + + +%% +%% Joins the pictures and draws them. A shorthand for +%% the corresponding two macro invocations. +%% +def joinDrawObjects(text pictures)= + joinObjects(pictures); + drawObjects(pictures); +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/util_picture.mp b/graphics/metapost/contrib/macros/metauml/inputs/util_picture.mp new file mode 100644 index 0000000000..85ce68f7d4 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/util_picture.mp @@ -0,0 +1,285 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _util_picture_mp: + expandafter endinput +fi; +_util_picture_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_log; +inputonce util_margins; + +if not known _n_cur_:input boxes;fi; + +vardef FontInfo@#(expr tname, tscale)= + attributes(@#); + var(string) className; + var(string) name; + var(numeric) scale; + + @#className := "FontInfo"; + + @#name := tname; + @#scale := tscale; +enddef; + +vardef FontInfoCopy@#(text fontInfo)= + FontInfo@#(fontInfo.name, fontInfo.scale); + @#ignoreNegativeBase := fontInfo.ignoreNegativeBase; +enddef; + +vardef FontInfo_toString@#= + save ret; string ret; + ret := "FontInfo(" & (str @#) & "): {" & (@#name) & ", " & (decimal @#scale) & "}"; + ret +enddef; + +log "()()() Creating iFont"; +FontInfo.iFont(defaultfont, defaultscale); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% PICTURE % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +vardef PictureInfo@#(expr pleft, pright, ptop, pbottom)(text pfont)= + attributes(@#); + var(string) className; + @#className := "PictureInfo"; + + var(color) borderColor; + var(numeric) boxed; + + %% Used to set the base of a text to the natural base of the letters. + %% If set to '1', 'y' and 'a' will have the same base line, the tail + %% of 'y' being rendered below that line + %% + var(numeric) ignoreNegativeBase; + + %% If these attributes are set to -1, the height and width of the + %% Picture object is deduced from the dimensions of the contained + %% object (picture or text). If one of these parameters is set to + %% a positive value, then the given value is used, regardless of the + %% size of the contents. + %% + var(numeric) fixedWidth, fixedHeight; + + %% Controls how the contents of the picture is to be aligned relatively + %% to the picture margins. Can be one of "left", "centered", and defaults to + %% "left". The "centered" setting is useful for Picture-s whose fixedWidth + %% is set to a given value. + %% + var(string) halign, valign; + + var(string) textDecoration; + + @#boxed := 0; + @#borderColor := blue; + + @#ignoreNegativeBase := 0; + + @#fixedWidth := -1; + @#fixedHeight := -1; + + @#halign := "left"; + @#valign := "bottom"; + + @#textDecoration := "none"; + + Margins.@#(pleft, pright, ptop, pbottom); + + FontInfoCopy.@#iFont(pfont); +enddef; + +vardef PictureInfoCopy@#(text src)= + PictureInfo@#(src.left, src.right, src.top, src.bottom)(src.iFont); + + @#boxed := src.boxed; + @#borderColor := src.borderColor; + @#ignoreNegativeBase := src.ignoreNegativeBase; + @#textDecoration := src.textDecoration; + + @#fixedWidth := src.fixedWidth; + @#fixedHeight := src.fixedHeight; + + @#halign := src.halign; + @#valign := src.valign; +enddef; + +vardef PictureInfo_toString@#= + save ret; string ret; + ret := "PictureInfo(" & (str @#) & "): {" & (decimal @#left) & ", " & (decimal @#right) & ", " & (decimal @#top) & ", " & (decimal @#bottom) & "}" & " boxed: " & (decimal @#boxed); + ret := ret & " Font: " & toString(@#iFont); + ret +enddef; + +PictureInfo.iPict(2, 2, 2, 2)(iFont); +PictureInfo.iPictNoMargins(0, 0, 0, 0)(iFont); + +PictureInfoCopy.iPictBoxed(iPict); +iPictBoxed.boxed := 1; + +%% +%% Contructs a Picture object by wrapping around the +%% low-level picture thePict. +%% +vardef EPicture@#(text iPict)(expr thePict) = + ObjectEquations(@#); + @#className := "Picture"; + + var(pair) contentShift; + var(picture) pict; + var(numeric) negativeBase; + var(string) contentAsString; + var(picture) contentAsPicture; + + PictureInfoCopy.@#info(iPict); + + if string thePict: + log "Picture " & (str @#) & " is a text"; + @#contentAsString := thePict; + log @#contentAsString; + elseif picture thePict: + log "Picture " & (str @#) & " is a native pict"; + @#contentAsPicture := thePict; + log @#contentAsPicture; + else: + log "Picture " & (str @#) & " [error]"; + fi; + +enddef; + +%% +%% Contructs a Picture object by wrapping around the +%% low-level picture thePict. +%% +vardef Picture@#(expr thePict) = + EPicture@#(iPict)(thePict); +enddef; + +%% +%% Lays out the Picture. +%% +vardef Picture_layout@# = + if @#laidout = 1: + log "Picture " & str @# & " already laid out."; + else: + log "Laying out " & (str @#); + + @#laidout := 1; + + if known @#contentAsPicture: + log "Content is known to be a picture"; + @#pict = @#contentAsPicture; + elseif known @#contentAsString: + log "Content is known to be a string: " & @#contentAsString; + @#pict = @#contentAsString infont @#info.iFont.name scaled @#info.iFont.scale; + else: + log "Show unknown parameter type in picture layout"; + 2 = 3; % force an error + fi; + + @#negativeBase = ypart llcorner @#pict; + + if @#info.ignoreNegativeBase = 0: + negativeBaseAdjustement__ := 0; + else: + negativeBaseAdjustement__ := @#negativeBase; + fi; + + if @#info.fixedWidth = -1: + @#width = pictWidth(@#pict) + @#info.left + @#info.right; + else: + @#width = @#info.fixedWidth; + fi; + + if @#info.fixedHeight = -1: + @#height = pictHeight(@#pict) + @#info.top + @#info.bottom + negativeBaseAdjustement__; + else: + @#height = @#info.fixedHeight; + fi; + + if @#info.halign = "left": + xdelta__ := @#info.left; + elseif @#info.halign = "center": + xdelta__ := (@#width-pictWidth(@#pict))/2; + else: + 2 = 3; % throw exception illegal value for @#info.halign + fi; + + if @#info.valign = "bottom": + ydelta__ := @#info.bottom - @#negativeBase + negativeBaseAdjustement__; + elseif @#info.valign = "center": + ydelta__ := (@#height-pictHeight(@#pict))/2 - @#negativeBase + negativeBaseAdjustement__; + else: + 2 = 3; % throw exception illegal value for @#info.valign + fi; + + @#contentShift = @#sw + (xdelta__, ydelta__); + fi; +enddef; + +%% +%% Draws the Picture. +%% +vardef Picture_draw@# = + Picture_layout@#; + objectEnsurePositioning.@#; + + draw @#pict shifted @#contentShift; + + if (@#info.textDecoration = "underline"): + save ydelta, height; + height := pictHeight(@#pict) - @#negativeBase; + + ydelta := @#info.bottom - @#negativeBase - 0.8; + + draw @#sw + (@#info.left, ydelta) -- @#se + (-@#info.right, ydelta) withcolor black withpen pencircle scaled 0.2bp; + fi; + + if (@#info.boxed = 1): + draw objectBox(@#) withcolor @#info.borderColor; + fi; +enddef; + +vardef Picture_border@#= + objectBox(@#) +enddef; + +vardef aitem(text pictInfo)(text thePict)(text equation)= + save obj; + EPicture.obj(pictInfo)(thePict); + equation; + drawObject(obj); +enddef; + +vardef item@#(text iPict)(text thePict)(text equation)= + save itemName; + string itemName; + itemName := str @#; + + log "Creating an item with name: '" & itemName & "'"; + + if itemName = "": + log "Name is empty, creating an anonymous item!"; + aitem(iPict)(thePict)(equation); + else: + EPicture@#(iPict)(thePict); + equation; + drawObject(@#); + fi; +enddef; + diff --git a/graphics/metapost/contrib/macros/metauml/inputs/util_picture_stack.mp b/graphics/metapost/contrib/macros/metauml/inputs/util_picture_stack.mp new file mode 100644 index 0000000000..edade327ef --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/util_picture_stack.mp @@ -0,0 +1,153 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _util_picture_stack_mp: + expandafter endinput +fi; +_util_picture_stack_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_picture; +inputonce util_commons; +inputonce util_group; + +inputonce util_log; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% PICTURE STACK % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Style for a stack of child pictures with the given margins, spacing between children, and a common child style. +%% If child style supplier @#childStyleSupplier is set, it takes precedence over the common child style. +%% The child style supplier must be the name of a macro taking a child index as an argument and returning a child style. +vardef PictureStackInfo@#(expr marginLeft, marginRight, marginTop, marginBottom)(text _spacing)(text _childStyle)= + attributes(@#); + var(numeric) boxed; + var(color) borderColor; + var(numeric) spacing; + var(string) childStyleSupplier; + + Margins@#(marginLeft, marginRight, marginTop, marginBottom); + + @#spacing := _spacing; + + @#boxed := 0; + @#borderColor := green; + + @#childStyleSupplier := ""; + + PictureInfoCopy.@#iPict(_childStyle); +enddef; + +vardef PictureStackInfoCopy@#(text src)= + PictureStackInfo@#(src.left, src.right, src.top, src.bottom)(src.spacing)(src.iPict); + + @#childStyleSupplier := src.childStyleSupplier; + @#boxed := src.boxed; + @#borderColor := src.borderColor; +enddef; + +PictureStackInfo.iStack(2, 2, 2, 2)(2)(iPict); + +vardef EPictureStack@#(text pictStackInfo)(text thePictures)(text how)= + ObjectEquations(@#); + @#className := "PictureStack"; + + PictureStackInfoCopy.@#info(pictStackInfo); + + attributes(@#); + var(numeric) nItems; + var(numeric) minx, miny, maxx, maxy; + var(string) picturesAsString; + %var(text) joinMethod; + + string @#joinMethod; + + %@#joinMethod := str how; + for l=how: + @#joinMethod := l; + endfor; + + @#nItems := 0; + for p=thePictures: + if (@#info.childStyleSupplier <> ""): + EPicture.@#pict[@#nItems](scantokens (@#info.childStyleSupplier)(@#nItems))(p); + else: + EPicture.@#pict[@#nItems](@#info.iPict)(p); + fi; + @#nItems := @#nItems + 1; + endfor; + + @#picturesAsString := listArray(@#pict)(@#nItems); + + EGroup.@#group(@#info)(scantokens @#picturesAsString); + + @#nw = @#group.nw; + @#se = @#group.se; +enddef; + +vardef PictureStack@#(text thePictures)(text how)= + EPictureStack@#(iStack)(thePictures)(how); +enddef; + +vardef PictureStack_layout@#= + if @#laidout = 1: + log "PictureStack " & (str @#) & " has already been layed out"; + else: + @#laidout := 1; + + layoutObjects(scantokens @#picturesAsString); + + if @#joinMethod = "vleft": + setObjectJoin(pa.left=pb.left; pa.bottom = pb.top + @#info.spacing); + elseif @#joinMethod = "vcenter": + setObjectJoin(pa.midx=pb.midx; pa.bottom = pb.top + @#info.spacing); + elseif @#joinMethod = "vright": + setObjectJoin(pa.right=pb.right; pa.bottom = pb.top + @#info.spacing); + elseif @#joinMethod = "vleftbase": + setObjectJoin(pa.left=pb.left; pa.bottom = pb.bottom + @#info.spacing); + elseif @#joinMethod = "vcenterbase": + setObjectJoin(pa.midx=pb.midx; pa.bottom = pb.bottom + @#info.spacing); + elseif @#joinMethod = "vrightbase": + setObjectJoin(pa.right=pb.right; pa.bottom = pb.bottom + @#info.spacing); + else: + setObjectJoin(pa.c = pb.c); % By default, stack objects on top of each other. + scantokens @#joinMethod; + fi; + + joinObjects(scantokens @#picturesAsString); + + Group_layout.@#group; + fi; +enddef; + +vardef PictureStack_draw@#= + PictureStack_layout.@#; + objectEnsurePositioning.@#; + + for i=0 upto @#nItems-1: + Picture_draw.@#pict[i]; + endfor; + + if (@#info.boxed = 1): + draw objectBox(@#) withcolor @#info.borderColor; + fi; +enddef; + +vardef PictureStack_border@#= + objectBox(@#) +enddef; + diff --git a/graphics/metapost/contrib/macros/metauml/inputs/util_positioning.mp b/graphics/metapost/contrib/macros/metauml/inputs/util_positioning.mp new file mode 100644 index 0000000000..9f32a0a54e --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/util_positioning.mp @@ -0,0 +1,242 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _util_positioning_mp: + expandafter endinput +fi; +_util_positioning_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_log; + +%% Gives a point which is below the given @point with the given @value. +%% +def below(expr point, value) = + (point - (0, value)) +enddef; + +%% Gives a point which is above the given @point with the given @value. +%% +def above(expr point, value) = + (point + (0, value)) +enddef; + +%% Gives a point which is at the right of the given @point with the given @value. +%% +def atright(expr point, value) = + (point + (value, 0)) +enddef; + +%% Gives a point which is at the left of the given @point with the given @value. +%% +def atleft(expr point, value) = + (point - (value, 0)) +enddef; + +%% Positions the given objects so that they: +%% * have their tops aligned +%% * the distance between the objects is @distance +%% * the center of gravity of the objects (taken on the top line) is at @middlePoint +%% +%% @distance +%% |---------------------------| +%% | | +%% | @middlePoint | +%% __________|_____________._____________|____________ the same top +%% [objectA] | [objectB] +%% +vardef centered_align_top(suffix objectA, objectB)(expr distance, middlePoint)= + log middlePoint; + objectA.top = objectB.top; + objectB.left - objectA.right = distance; + middlePoint = .5[objectB.nw, objectA.ne]; +enddef; + +%% Deprecated, kept for backward compatibility (align is misspelled). +%% +vardef centered_allign_top(suffix objectA, objectB)(expr distance, middlePoint)= + log middlePoint; + objectA.top = objectB.top; + objectB.left - objectA.right = distance; + middlePoint = .5[objectB.nw, objectA.ne]; +enddef; + +%% theString means here not a sequence of characters but +%% the horizontal or vertical line on which objects are placed. +%% For example, if theString is top, then the objects are +%% "hanging" on a horizontal line, like freshly washed +%% clothes on a string. + +vardef align(suffix theString, extremityNew, extremityOld) + (text distanceBetweenObjects)(expr sign)(text objects)= + string objectsAsString__; + objectsAsString__ := enumToString(objects)(""); + + log "Aligning '" & objectsAsString__ & "' at " & str theString; + log sign; + + if (objectsAsString__ = ""): + log "Nothing to do, bailing out."; + else: + string previousObject__; + previousObject__ := ""; + objectIndex__ := 0; + + forsuffixes obj = objects: + log "object: " & str obj; + if objectIndex__ = 0: + objectIndex__ := objectIndex__ + 1; + previousObject__ := str obj; + else: + objectIndex__ := objectIndex__ + 1; + + log str theString; + log str extremityOld; + log str extremityNew; + log distanceBetweenObjects; + + string eqA__, eqB__; + eqA__ := previousObject__ & "." & str theString & " = " & str obj & "." & str theString; + + if (sign = "+"): + eqB__ := previousObject__ & "." & str extremityOld & " + " & (str distanceBetweenObjects) & " = " & str obj & "." & str extremityNew; + %eqB__ := previousObject__ & "." & str extremityOld & " + distanceBetweenObjects = " & str obj & "." & str extremityNew; + else: + eqB__ := previousObject__ & "." & str extremityOld & " - " & (str distanceBetweenObjects) & " = " & str obj & "." & str extremityNew; + fi; + + log eqA__, eqB__; + scantokens eqA__; + scantokens eqB__; + + previousObject__ := str obj; + fi; + endfor; + fi; +enddef; + +vardef leftToRight@#(text distanceBetweenObjects)(text objects)= + if str @# = "": + log "String is empty, aligning to midy"; + align(midy, left, right)(distanceBetweenObjects)("+")(objects); + else: + align(@#, left, right)(distanceBetweenObjects)("+")(objects); + fi; +enddef; + +vardef rightToLeft@#(text distanceBetweenObjects)(text objects)= + if str @# = "": + log "String is empty, aligning to midy"; + align(midy, right, left)(distanceBetweenObjects)("-")(objects); + else: + align(@#, right, left)(distanceBetweenObjects)("-")(objects); + fi; +enddef; + +vardef topToBottom@#(text distanceBetweenObjects)(text objects)= + if str @# = "": + log "String is empty, aligning to midx"; + align(midx, top, bottom)(distanceBetweenObjects)("-")(objects); + else: + align(@#, top, bottom)(distanceBetweenObjects)("-")(objects); + fi; +enddef; + +vardef bottomToTop@#(text distanceBetweenObjects)(text objects)= + if str @# = "": + log "String is empty, aligning to midx"; + align(midx, bottom, top)(distanceBetweenObjects)("+")(objects); + else: + align(@#, bottom, top)(distanceBetweenObjects)("+")(objects); + fi; +enddef; + +%% +%% Defines an equation which sets the given prefix to be equal for all the given objects. +%% For example: +%% +%% same.top(a, b, c); +%% +%% is equivalent to +%% a.top = b.top = c.top; +%% +vardef same@#(text objects)= + log "begin macro: same@#(text objects)="; + + string equation__, property__; + equation__ := ""; + property__ := str @#; + + objectIndex__ := 0; + forsuffixes obj = objects: + log "object: " & str obj; + + if objectIndex__ = 0: + objectIndex__ := objectIndex__ + 1; + equation__ := equation__ & str obj & "." & property__; + else: + objectIndex__ := objectIndex__ + 1; + equation__ := equation__ & "=" & str obj & "." & property__; + fi; + endfor; + + equation__ := equation__ & ";"; + + log "Equation is: '" & equation__ & "'"; + + if objectIndex__ <= 1: + log "One or no objects, nothing to do!"; + else: + scantokens equation__; + fi; +enddef; + +%% this macro is NOT usable (yet) +vardef leftToRightCentered@#(expr distanceBetweenObjects, middlePoint)(text objects)= + string objectsAsString__; + objectsAsString__ := enumToString(objects)(""); + + if (objectsAsString__ = ""): + log "Nothing to do, bailing out."; + else: + log "ASDFGHJ"; + leftToRight@#(distanceBetweenObjects)(objects); + + string firstObject__, lastObject__; + objectIndex__ := 0; + forsuffixes obj = objects: + if objectIndex__ = 0: + objectIndex__ := objectIndex__ + 1; + firstObject__ := str obj; + else: + objectIndex__ := objectIndex__ + 1; + lastObject__ := str obj; + fi; + endfor; + + log "___"; + .5[authA.nw,authB.ne] = middlePoint; + log "___"; + + string eqCenter__; + eqCenter__ := ".5[" & firstObject__ & ".nw," & lastObject__ & ".ne] = middlePoint"; + + log eqCenter__; + log middlePoint; + + log "XXX"; + scantokens eqCenter__; + log "XXX"; + fi; +enddef; diff --git a/graphics/metapost/contrib/macros/metauml/inputs/util_shade.mp b/graphics/metapost/contrib/macros/metauml/inputs/util_shade.mp new file mode 100644 index 0000000000..b5231164b9 --- /dev/null +++ b/graphics/metapost/contrib/macros/metauml/inputs/util_shade.mp @@ -0,0 +1,53 @@ +% Copyright 2005 2015 Ovidiu Gheorghies +% Licensed under the Apache License, Version 2.0. + +if known _util_shade_mp: + expandafter endinput +fi; +_util_shade_mp:=1; + +% Sadly, this copy of the macro is needed to prevent multiple file loads being shown by MetaPost. +% The guard values (such as _metauml_mp) do ensure that the file isn't loaded multiple times, +% but this macro makes sure that MetaPost won't try to load the file and display a message for that. +def inputonce text libraryFile= + if not known scantokens ("_" & str libraryFile & "_mp"): + %includeonce% show "Loading " & str libraryFile; + scantokens ("input " & str libraryFile); + else: + %includeonce% show str libraryFile & " already loaded."; + fi; +enddef; + +inputonce util_log; + +vardef ShadeInfo@#= + _n_ := str @#; + generic_declare(numeric) _n.shift; + generic_declare(color) _n.background; + + @#shift := 1; + @#background := .7white; +enddef; + +vardef ShadeInfoCopy@#(text src)= + ShadeInfo.@#; + ShadeInfo_copy@#(src); +enddef; + +vardef ShadeInfo_copy@#(text src)= + @#shift := src.shift; + @#background := src.background; +enddef; + +vardef ShadeInfo_toString@#= + save @#ret; + string @#ret; + @#ret := "Shade (shift: " & (decimal @#shift) & " back: (" & + (decimal redpart @#background) & ", " & + (decimal greenpart @#background) & ", " & + (decimal bluepart @#background) & ")"; + + @#ret +enddef; + + |