~aleteoryx/muditaos

6cd60475062f7c407e0d7487589a32f0d031d132 — mkamonMdt 5 years ago f8fc5c8
[EGD-4780] Change in GUI documentation to cover DOM

 * GUI Visitor documentation added
 * GUI DOM documentation added
M changelog.md => changelog.md +1 -0
@@ 4,6 4,7 @@

### Added

* Add GUI visitor and DOM documentation.
* `[PowerManagement]` Critial battery level notification to SystemManager.
* `[Bluetooth]`  Add settings storage to bluetooth related items
* Add Bluetooth virtual audio device.

M module-gui/README.md => module-gui/README.md +87 -0
@@ 95,3 95,90 @@ There are 2 set of parameters for key press:

Now you can use `InputMode::Mode::phone` translation in `gui::Text` widget.
This means `gui::Text` will automatically change text on key press for you, same as in modes `InputMode::Mode::phone` etc.

# Adding new functionalities - Visitor pattern in `gui::Item`

The `gui::Item` class is compatible with visitor pattern providing double dispatch behaviour.
The double dispatch mechanism enables, for all classes in `gui::Item`'s inheritance hierarchy, to easily equip them with new polymorphic behavior without changing classes themselves.

## Structure

Every new functionality to be added to `gui::Item` hierarchy requires creation of new concrete visitor that publicly inherits from `gui::GuiVisitor` interface and specify respective behavior.
In order to ensure that a class in `gui::Item` hierarchy is recognized by it's concrete type in `ConcreteVisitor::visit(...)` method, class must override `gui::Item::accept(gui::GuiVisitor &)`,
otherwise it will be resolved as a closest ancestor. On the diagram below both `gui::CustomItem1` and `gui::CustomItem2` will be resolved as `gui::Rect`
despite existing `gui::GuiVisitor::visit(gui::CustomItem2 &)` overload and `gui::CustomItem1::accept(...)` override.

![Simplified UI](./doc/visitor_item_structure.svg "Visitor-Item structure")

## Tree of `gui::Item`

Each a `gui::Item` object is used as a node to build UI general tree.
That relation is simplest thought of as a tree of dependencies with a node being a parent of zero, one or more other nodes.
Concerning need of a `ConcreteVisitors` to visit not only parent but also all it's children,
`gui::ItemTree` is an interface class providing abstract interface for implementation of `gui::Item` tree traversal.
The concrete realization of `gui::ItemTree` is `gui::DepthFirstItemTree`.

![Simplified UI](./doc/item_tree.svg "ItemTree structure")

### Depth-First tree of `gui::Item`

`gui::DepthFirstItemTree` builds tree of parent-children relation for any `gui::Item` pointed as the root.
The class offers two traverse modes:
* `PreOrder` - in this mode a parent is precedes all it's children
* `PostOrder` - in this mode all children precede it's parent

## Example

![Simplified UI](./doc/visitor_item_example.svg "Visitor-Item  example")

# Domain Object Model of `gui::Item`

Each `gui::Item` object can be serialized into json-formatted stream using `gui::Item2JsonSerializer`.
The serializing class employs dedicated `gui::Item2JsonSerializingVisitor`, `gui::DepthFirstItemTree` in `PostOrder` mode 
in a sequence flow analogous to the one presented above. Below exemplary fragment of DOM serialization output is presented.
```asm
{"Rect": {
    "Active": true, 
    "BorderColor": [0, 0], 
    "Children": [
        {"Label": {
            "Active": true, 
            "BorderColor": [0, 0], 
            "ChildrenCount": 0, 
            "Corners": 240, 
            "DrawArea": [20, 445, 440, 30], 
            "Edges": 0, 
            "FillColor": [15, 15], 
            "Filled": false, 
            "FlatEdges": 0, 
            "Focus": false, 
            "ItemType": 0, 
            "PenFocusWidth": 2, 
            "PenWidth": 1, 
            "TextValue": "Interval Chime", 
            "Visible": true, 
            "WidgetArea": [0, 0, 440, 30], 
            "WidgetMaximumArea": [0, 0, 440, 30], 
            "WidgetMinimumArea": [0, 0, 440, 30], 
            "YapSize": 10, "Yaps": 0}
        },
        {"Label": {...}}
    ], 
    "ChildrenCount": 2, 
    "Corners": 240, 
    "DrawArea": [20, 445, 440, 60], 
    "Edges": 0, 
    "FillColor": [15, 15], 
    "Filled": false, 
    "FlatEdges": 0, 
    "Focus": true, 
    "ItemType": 0, 
    "PenFocusWidth": 2, 
    "PenWidth": 1, 
    "Visible": true, 
    "WidgetArea": [20, 445, 440, 60], 
    "WidgetMaximumArea": [0, 0, 440, 60], 
    "WidgetMinimumArea": [0, 0, 440, 60], 
    "YapSize": 10, "Yaps": 0}
}
```

A module-gui/doc/item_tree.puml => module-gui/doc/item_tree.puml +31 -0
@@ 0,0 1,31 @@
@startuml

class gui::ItemNode
{
    gui::Item*
    int level
}

abstract class gui::ItemTree
{
    bool hasNext()
    gui::ItemNode getNext()
}

enum TraverseMode
{
    PreOrder
    PostOrder
}

class gui::DepthFirstItemTree
{
    DepthFirstItemTree(gui::Item *root, TraverseMode mode)
    bool hasNext()
    gui::ItemNode getNext()
}

gui::ItemTree <|-- gui::DepthFirstItemTree
gui::DepthFirstItemTree o-- TraverseMode

@enduml

A module-gui/doc/item_tree.svg => module-gui/doc/item_tree.svg +44 -0
@@ 0,0 1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="372px" preserveAspectRatio="none" style="width:413px;height:372px;" version="1.1" viewBox="0 0 413 372" width="413px" zoomAndPan="magnify"><defs><filter height="300%" id="fbi96ixapffwh" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><!--class gui::ItemNode--><rect fill="#FEFECE" filter="url(#fbi96ixapffwh)" height="73.6094" id="gui::ItemNode" style="stroke: #A80036; stroke-width: 1.5;" width="119" x="6" y="8"/><ellipse cx="21" cy="24" fill="#ADD1B2" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M23.9688,29.6406 Q23.3906,29.9375 22.75,30.0781 Q22.1094,30.2344 21.4063,30.2344 Q18.9063,30.2344 17.5781,28.5938 Q16.2656,26.9375 16.2656,23.8125 Q16.2656,20.6875 17.5781,19.0313 Q18.9063,17.375 21.4063,17.375 Q22.1094,17.375 22.75,17.5313 Q23.4063,17.6875 23.9688,17.9844 L23.9688,20.7031 Q23.3438,20.125 22.75,19.8594 Q22.1563,19.5781 21.5313,19.5781 Q20.1875,19.5781 19.5,20.6563 Q18.8125,21.7188 18.8125,23.8125 Q18.8125,25.9063 19.5,26.9844 Q20.1875,28.0469 21.5313,28.0469 Q22.1563,28.0469 22.75,27.7813 Q23.3438,27.5 23.9688,26.9219 L23.9688,29.6406 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="87" x="35" y="28.1543">gui::ItemNode</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="7" x2="124" y1="40" y2="40"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="56" x="12" y="54.2104">gui::Item*</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="44" x="12" y="67.0151">int level</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="7" x2="124" y1="73.6094" y2="73.6094"/><!--class gui::ItemTree--><rect fill="#FEFECE" filter="url(#fbi96ixapffwh)" height="73.6094" id="gui::ItemTree" style="stroke: #A80036; stroke-width: 1.5;" width="146" x="160.5" y="8"/><ellipse cx="189.45" cy="24" fill="#A9DCDF" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M189.5594,19.3438 L188.4031,24.4219 L190.7313,24.4219 L189.5594,19.3438 Z M188.075,17.1094 L191.0594,17.1094 L194.4188,29.5 L191.9656,29.5 L191.2,26.4375 L187.9188,26.4375 L187.1688,29.5 L184.7313,29.5 L188.075,17.1094 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacingAndGlyphs" textLength="83" x="206.55" y="28.1543">gui::ItemTree</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="161.5" x2="305.5" y1="40" y2="40"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="161.5" x2="305.5" y1="48" y2="48"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="82" x="166.5" y="62.2104">bool hasNext()</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="134" x="166.5" y="75.0151">gui::ItemNode getNext()</text><!--class TraverseMode--><rect fill="#FEFECE" filter="url(#fbi96ixapffwh)" height="73.6094" id="TraverseMode" style="stroke: #A80036; stroke-width: 1.5;" width="120" x="173.5" y="288"/><ellipse cx="188.5" cy="304" fill="#EB937F" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M192.6094,310 L184.8906,310 L184.8906,297.6094 L192.6094,297.6094 L192.6094,299.7656 L187.3438,299.7656 L187.3438,302.4375 L192.1094,302.4375 L192.1094,304.5938 L187.3438,304.5938 L187.3438,307.8438 L192.6094,307.8438 L192.6094,310 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="88" x="202.5" y="308.1543">TraverseMode</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="174.5" x2="292.5" y1="320" y2="320"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="52" x="179.5" y="334.2104">PreOrder</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="58" x="179.5" y="347.0151">PostOrder</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="174.5" x2="292.5" y1="353.6094" y2="353.6094"/><!--class gui::DepthFirstItemTree--><rect fill="#FEFECE" filter="url(#fbi96ixapffwh)" height="86.4141" id="gui::DepthFirstItemTree" style="stroke: #A80036; stroke-width: 1.5;" width="337" x="65" y="142"/><ellipse cx="155.75" cy="158" fill="#ADD1B2" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M158.7188,163.6406 Q158.1406,163.9375 157.5,164.0781 Q156.8594,164.2344 156.1563,164.2344 Q153.6563,164.2344 152.3281,162.5938 Q151.0156,160.9375 151.0156,157.8125 Q151.0156,154.6875 152.3281,153.0313 Q153.6563,151.375 156.1563,151.375 Q156.8594,151.375 157.5,151.5313 Q158.1563,151.6875 158.7188,151.9844 L158.7188,154.7031 Q158.0938,154.125 157.5,153.8594 Q156.9063,153.5781 156.2813,153.5781 Q154.9375,153.5781 154.25,154.6563 Q153.5625,155.7188 153.5625,157.8125 Q153.5625,159.9063 154.25,160.9844 Q154.9375,162.0469 156.2813,162.0469 Q156.9063,162.0469 157.5,161.7813 Q158.0938,161.5 158.7188,160.9219 L158.7188,163.6406 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="147" x="176.25" y="162.1543">gui::DepthFirstItemTree</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="66" x2="401" y1="174" y2="174"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="66" x2="401" y1="182" y2="182"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="325" x="71" y="196.2104">DepthFirstItemTree(gui::Item *root, TraverseMode mode)</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="82" x="71" y="209.0151">bool hasNext()</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="134" x="71" y="221.8198">gui::ItemNode getNext()</text><!--link gui::ItemTree to gui::DepthFirstItemTree--><path d="M233.5,102.62 C233.5,115.66 233.5,129.31 233.5,141.62 " fill="none" id="gui::ItemTree-gui::DepthFirstItemTree" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="none" points="226.5,102.26,233.5,82.26,240.5,102.26,226.5,102.26" style="stroke: #A80036; stroke-width: 1.0;"/><!--link gui::DepthFirstItemTree to TraverseMode--><path d="M233.5,241.5 C233.5,257.06 233.5,273.57 233.5,287.7 " fill="none" id="gui::DepthFirstItemTree-TraverseMode" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="#FFFFFF" points="233.5,228.15,229.5,234.15,233.5,240.15,237.5,234.15,233.5,228.15" style="stroke: #A80036; stroke-width: 1.0;"/><!--
@startuml

class gui::ItemNode
{
    gui::Item*
    int level
}

abstract class gui::ItemTree
{
    bool hasNext()
    gui::ItemNode getNext()
}

enum TraverseMode
{
    PreOrder
    PostOrder
}

class gui::DepthFirstItemTree
{
    DepthFirstItemTree(gui::Item *root, TraverseMode mode)
    bool hasNext()
    gui::ItemNode getNext()
}

gui::ItemTree <|- - gui::DepthFirstItemTree
gui::DepthFirstItemTree o- - TraverseMode

@enduml

PlantUML version 1.2018.13(Mon Nov 26 18:11:51 CET 2018)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 11.0.9.1+1-Ubuntu-0ubuntu1.20.04
Operating System: Linux
OS Version: 5.4.0-56-generic
Default Encoding: UTF-8
Language: en
Country: US
--></g></svg>
\ No newline at end of file

A module-gui/doc/visitor_item_example.puml => module-gui/doc/visitor_item_example.puml +47 -0
@@ 0,0 1,47 @@
@startuml

participant "ConcreteTree" as ct
participant "ConcreteWalker" as cw
participant "ConcreteVisitor" as cv
participant "gui::Item" as item


[o->cw : traverse(root)
    create ct
        activate cw #DarkGreen
    ct <- cw : <<create>>(root)
    activate ct #DarkGreen

        create cv
        cw -> cv : <<create>>
            activate cv #DarkGreen
loop tree::hasNext()
    ct <- cw : getNext
    activate ct #LimeGreen
    ct --> cw : node
    deactivate ct
        cw -> item : accept(visitor)
                activate item #DarkGreen
            cv <- item : visit(*this)
            activate cv #LimeGreen

            cv -> item : interaction
                activate item #LimeGreen
            cv <-- item
                deactivate item

            cv --> item
            deactivate cv
        cw <-- item
                deactivate item
        cw -> cv : <<concrete interaction>>
            activate cv #LimeGreen
        cw <-- cv
            deactivate cv
end
        cw -x cv : <<delete>>
            deactivate cv
    ct x- cw : <<delete>>
    deactivate ct

@enduml

A module-gui/doc/visitor_item_example.svg => module-gui/doc/visitor_item_example.svg +60 -0
@@ 0,0 1,60 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="538px" preserveAspectRatio="none" style="width:665px;height:538px;" version="1.1" viewBox="0 0 665 538" width="665px" zoomAndPan="magnify"><defs><filter height="300%" id="fkjo6aca5dlwn" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#006400" filter="url(#fkjo6aca5dlwn)" height="371.6563" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="75" y="108.5625"/><rect fill="#32CD32" filter="url(#fkjo6aca5dlwn)" height="29.1328" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="80" y="213.2891"/><rect fill="#006400" filter="url(#fkjo6aca5dlwn)" height="419.7891" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="282" y="69.4297"/><rect fill="#006400" filter="url(#fkjo6aca5dlwn)" height="297.2266" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="488" y="153.8594"/><rect fill="#32CD32" filter="url(#fkjo6aca5dlwn)" height="57.1328" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="493" y="300.6875"/><rect fill="#32CD32" filter="url(#fkjo6aca5dlwn)" height="14" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="493" y="400.9531"/><rect fill="#006400" filter="url(#fkjo6aca5dlwn)" height="100.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="599.5" y="271.5547"/><rect fill="#32CD32" filter="url(#fkjo6aca5dlwn)" height="14" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="604.5" y="329.8203"/><rect fill="#FEFECE" filter="url(#fkjo6aca5dlwn)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="110" x="23" y="77.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="96" x="30" y="97.4248">ConcreteTree</text><rect fill="#FEFECE" filter="url(#fkjo6aca5dlwn)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="120" x="431" y="122.7266"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="106" x="438" y="142.7217">ConcreteVisitor</text><rect fill="#FFFFFF" filter="url(#fkjo6aca5dlwn)" height="247.9297" style="stroke: #000000; stroke-width: 2.0;" width="641" x="13" y="175.0234"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="80" x2="80" y1="110.0781" y2="498.2188"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="287" x2="287" y1="38.2969" y2="498.2188"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="493" x2="493" y1="155.375" y2="498.2188"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="604" x2="604" y1="38.2969" y2="498.2188"/><rect fill="#FEFECE" filter="url(#fkjo6aca5dlwn)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="110" x="23" y="497.2188"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="96" x="30" y="517.2139">ConcreteTree</text><rect fill="#FEFECE" filter="url(#fkjo6aca5dlwn)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="124" x="223" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="110" x="230" y="22.9951">ConcreteWalker</text><rect fill="#FEFECE" filter="url(#fkjo6aca5dlwn)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="124" x="223" y="497.2188"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="110" x="230" y="517.2139">ConcreteWalker</text><rect fill="#FEFECE" filter="url(#fkjo6aca5dlwn)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="120" x="431" y="497.2188"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="106" x="438" y="517.2139">ConcreteVisitor</text><rect fill="#FEFECE" filter="url(#fkjo6aca5dlwn)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="75" x="565" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="61" x="572" y="22.9951">gui::Item</text><rect fill="#FEFECE" filter="url(#fkjo6aca5dlwn)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="75" x="565" y="497.2188"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="61" x="572" y="517.2139">gui::Item</text><rect fill="#006400" filter="url(#fkjo6aca5dlwn)" height="371.6563" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="75" y="108.5625"/><rect fill="#32CD32" filter="url(#fkjo6aca5dlwn)" height="29.1328" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="80" y="213.2891"/><rect fill="#006400" filter="url(#fkjo6aca5dlwn)" height="419.7891" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="282" y="69.4297"/><rect fill="#006400" filter="url(#fkjo6aca5dlwn)" height="297.2266" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="488" y="153.8594"/><rect fill="#32CD32" filter="url(#fkjo6aca5dlwn)" height="57.1328" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="493" y="300.6875"/><rect fill="#32CD32" filter="url(#fkjo6aca5dlwn)" height="14" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="493" y="400.9531"/><rect fill="#006400" filter="url(#fkjo6aca5dlwn)" height="100.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="599.5" y="271.5547"/><rect fill="#32CD32" filter="url(#fkjo6aca5dlwn)" height="14" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="604.5" y="329.8203"/><ellipse cx="10.5" cy="68.6797" fill="none" rx="4" ry="4" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#A80036" points="270,65.4297,280,69.4297,270,73.4297,274,69.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="15" x2="276" y1="69.4297" y2="69.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="89" x="18" y="64.3638">traverse(root)</text><polygon fill="#A80036" points="148,94.5625,138,98.5625,148,102.5625,144,98.5625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="142" x2="281" y1="98.5625" y2="98.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="121" x="154" y="93.4966">&lt;&lt;create&gt;&gt;(root)</text><rect fill="#FEFECE" filter="url(#fkjo6aca5dlwn)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="110" x="23" y="77.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="96" x="30" y="97.4248">ConcreteTree</text><polygon fill="#A80036" points="419,139.8594,429,143.8594,419,147.8594,423,143.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="292" x2="425" y1="143.8594" y2="143.8594"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="85" x="299" y="138.7935">&lt;&lt;create&gt;&gt;</text><rect fill="#FEFECE" filter="url(#fkjo6aca5dlwn)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="120" x="431" y="122.7266"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="106" x="438" y="142.7217">ConcreteVisitor</text><path d="M13,175.0234 L90,175.0234 L90,182.0234 L80,192.0234 L13,192.0234 L13,175.0234 " fill="#EEEEEE" style="stroke: #000000; stroke-width: 1.0;"/><rect fill="none" height="247.9297" style="stroke: #000000; stroke-width: 2.0;" width="641" x="13" y="175.0234"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="32" x="28" y="188.0903">loop</text><text fill="#000000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="106" x="105" y="187.2339">[tree::hasNext()]</text><polygon fill="#A80036" points="101,209.2891,91,213.2891,101,217.2891,97,213.2891" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="95" x2="281" y1="213.2891" y2="213.2891"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="51" x="107" y="208.2231">getNext</text><polygon fill="#A80036" points="270,238.4219,280,242.4219,270,246.4219,274,242.4219" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="85" x2="276" y1="242.4219" y2="242.4219"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="32" x="92" y="237.356">node</text><polygon fill="#A80036" points="587.5,267.5547,597.5,271.5547,587.5,275.5547,591.5,271.5547" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="292" x2="593.5" y1="271.5547" y2="271.5547"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="91" x="299" y="266.4888">accept(visitor)</text><polygon fill="#A80036" points="514,296.6875,504,300.6875,514,304.6875,510,300.6875" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="508" x2="598.5" y1="300.6875" y2="300.6875"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="65" x="520" y="295.6216">visit(*this)</text><polygon fill="#A80036" points="592.5,325.8203,602.5,329.8203,592.5,333.8203,596.5,329.8203" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="503" x2="598.5" y1="329.8203" y2="329.8203"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="68" x="510" y="324.7544">interaction</text><polygon fill="#A80036" points="514,339.8203,504,343.8203,514,347.8203,510,343.8203" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="508" x2="598.5" y1="343.8203" y2="343.8203"/><polygon fill="#A80036" points="587.5,353.8203,597.5,357.8203,587.5,361.8203,591.5,357.8203" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="498" x2="593.5" y1="357.8203" y2="357.8203"/><polygon fill="#A80036" points="303,367.8203,293,371.8203,303,375.8203,299,371.8203" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="297" x2="603.5" y1="371.8203" y2="371.8203"/><polygon fill="#A80036" points="481,396.9531,491,400.9531,481,404.9531,485,400.9531" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="292" x2="487" y1="400.9531" y2="400.9531"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="172" x="299" y="395.8872">&lt;&lt;concrete interaction&gt;&gt;</text><polygon fill="#A80036" points="303,410.9531,293,414.9531,303,418.9531,299,414.9531" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="297" x2="487" y1="414.9531" y2="414.9531"/><line style="stroke: #A80036; stroke-width: 2.0;" x1="475" x2="485" y1="446.0859" y2="456.0859"/><line style="stroke: #A80036; stroke-width: 2.0;" x1="475" x2="485" y1="456.0859" y2="446.0859"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="292" x2="480" y1="451.0859" y2="451.0859"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="84" x="299" y="446.02">&lt;&lt;delete&gt;&gt;</text><line style="stroke: #A80036; stroke-width: 2.0;" x1="86" x2="96" y1="475.2188" y2="485.2188"/><line style="stroke: #A80036; stroke-width: 2.0;" x1="86" x2="96" y1="485.2188" y2="475.2188"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="92" x2="281" y1="480.2188" y2="480.2188"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="84" x="97" y="475.1528">&lt;&lt;delete&gt;&gt;</text><!--
@startuml

participant "ConcreteTree" as ct
participant "ConcreteWalker" as cw
participant "ConcreteVisitor" as cv
participant "gui::Item" as item


[o->cw : traverse(root)
    create ct
        activate cw #DarkGreen
    ct <- cw : <<create>>(root)
    activate ct #DarkGreen

        create cv
        cw -> cv : <<create>>
            activate cv #DarkGreen
loop tree::hasNext()
    ct <- cw : getNext
    activate ct #LimeGreen
    ct - -> cw : node
    deactivate ct
        cw -> item : accept(visitor)
                activate item #DarkGreen
            cv <- item : visit(*this)
            activate cv #LimeGreen

            cv -> item : interaction
                activate item #LimeGreen
            cv <- - item
                deactivate item

            cv - -> item
            deactivate cv
        cw <- - item
                deactivate item
        cw -> cv : <<concrete interaction>>
            activate cv #LimeGreen
        cw <- - cv
            deactivate cv
end
        cw -x cv : <<delete>>
            deactivate cv
    ct x- cw : <<delete>>
    deactivate ct

@enduml

PlantUML version 1.2018.13(Mon Nov 26 18:11:51 CET 2018)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 11.0.9.1+1-Ubuntu-0ubuntu1.20.04
Operating System: Linux
OS Version: 5.4.0-56-generic
Default Encoding: UTF-8
Language: en
Country: US
--></g></svg>
\ No newline at end of file

A module-gui/doc/visitor_item_structure.puml => module-gui/doc/visitor_item_structure.puml +57 -0
@@ 0,0 1,57 @@
@startuml

abstract class gui::GuiVisitor
{
    void visit(gui::Item &item)
    void visit(gui::Rect &item)
    void visit(gui::Text &item)
    ... visit overloads ...
    void visit(gui::CustomItem2 &item)
}

class gui::ConcreteVisitor1
{
    void visit(gui::Item &item)
    void visit(gui::Rect &item)
    void visit(gui::Text &item)
    ... visit overloads ...
    void visit(gui::CustomItem2 &item)
}

class gui::ConcreteVisitor2
{
    void visit(gui::Item &item)
    void visit(gui::Rect &item)
    void visit(gui::Text &item)
    ... visit overloads ...
    void visit(gui::CustomItem2 &item)
}

gui::GuiVisitor <|-- gui::ConcreteVisitor1
gui::GuiVisitor <|-- gui::ConcreteVisitor2

class gui::Item
{
    void accept(gui::GuiVisitor &visitor)
}
class gui::Rect
{
    void accept(gui::GuiVisitor &visitor)
}
class gui::Text
{
    void accept(gui::GuiVisitor &visitor)
}
class gui::CustomItem1
{
    void accept(gui::GuiVisitor &visitor)
}
class gui::CustomItem2
{
}

gui::Item <|-- gui::Rect
gui::Rect <|-- gui::Text
gui::Rect <|-- gui::CustomItem1
gui::Rect <|-- gui::CustomItem2
@enduml

A module-gui/doc/visitor_item_structure.svg => module-gui/doc/visitor_item_structure.svg +70 -0
@@ 0,0 1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="415px" preserveAspectRatio="none" style="width:896px;height:415px;" version="1.1" viewBox="0 0 896 415" width="896px" zoomAndPan="magnify"><defs><filter height="300%" id="f14eszahge7obk" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><!--class gui::GuiVisitor--><rect fill="#FEFECE" filter="url(#f14eszahge7obk)" height="108.0234" id="gui::GuiVisitor" style="stroke: #A80036; stroke-width: 1.5;" width="210" x="129" y="8"/><ellipse cx="187.25" cy="24" fill="#A9DCDF" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M187.3594,19.3438 L186.2031,24.4219 L188.5313,24.4219 L187.3594,19.3438 Z M185.875,17.1094 L188.8594,17.1094 L192.2188,29.5 L189.7656,29.5 L189,26.4375 L185.7188,26.4375 L184.9688,29.5 L182.5313,29.5 L185.875,17.1094 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacingAndGlyphs" textLength="85" x="207.75" y="28.1543">gui::GuiVisitor</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="130" x2="338" y1="40" y2="40"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="147" x="135" y="54.2104">void visit(gui::Item &amp;item)</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="146" x="135" y="67.0151">void visit(gui::Rect &amp;item)</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="146" x="135" y="79.8198">void visit(gui::Text &amp;item)</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="198" x="135" y="109.4292">void visit(gui::CustomItem2 &amp;item)</text><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,2.0;" x1="130" x2="184.5" y1="92.8164" y2="92.8164"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="99" x="184.5" y="96.1245">. visit overloads .</text><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,2.0;" x1="283.5" x2="338" y1="92.8164" y2="92.8164"/><!--class gui::ConcreteVisitor1--><rect fill="#FEFECE" filter="url(#f14eszahge7obk)" height="108.0234" id="gui::ConcreteVisitor1" style="stroke: #A80036; stroke-width: 1.5;" width="210" x="6" y="176"/><ellipse cx="42.15" cy="192" fill="#ADD1B2" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M45.1188,197.6406 Q44.5406,197.9375 43.9,198.0781 Q43.2594,198.2344 42.5563,198.2344 Q40.0563,198.2344 38.7281,196.5938 Q37.4156,194.9375 37.4156,191.8125 Q37.4156,188.6875 38.7281,187.0313 Q40.0563,185.375 42.5563,185.375 Q43.2594,185.375 43.9,185.5313 Q44.5563,185.6875 45.1188,185.9844 L45.1188,188.7031 Q44.4938,188.125 43.9,187.8594 Q43.3063,187.5781 42.6813,187.5781 Q41.3375,187.5781 40.65,188.6563 Q39.9625,189.7188 39.9625,191.8125 Q39.9625,193.9063 40.65,194.9844 Q41.3375,196.0469 42.6813,196.0469 Q43.3063,196.0469 43.9,195.7813 Q44.4938,195.5 45.1188,194.9219 L45.1188,197.6406 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="131" x="60.85" y="196.1543">gui::ConcreteVisitor1</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="7" x2="215" y1="208" y2="208"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="147" x="12" y="222.2104">void visit(gui::Item &amp;item)</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="146" x="12" y="235.0151">void visit(gui::Rect &amp;item)</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="146" x="12" y="247.8198">void visit(gui::Text &amp;item)</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="198" x="12" y="277.4292">void visit(gui::CustomItem2 &amp;item)</text><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,2.0;" x1="7" x2="61.5" y1="260.8164" y2="260.8164"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="99" x="61.5" y="264.1245">. visit overloads .</text><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,2.0;" x1="160.5" x2="215" y1="260.8164" y2="260.8164"/><!--class gui::ConcreteVisitor2--><rect fill="#FEFECE" filter="url(#f14eszahge7obk)" height="108.0234" id="gui::ConcreteVisitor2" style="stroke: #A80036; stroke-width: 1.5;" width="210" x="251" y="176"/><ellipse cx="287.15" cy="192" fill="#ADD1B2" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M290.1188,197.6406 Q289.5406,197.9375 288.9,198.0781 Q288.2594,198.2344 287.5563,198.2344 Q285.0563,198.2344 283.7281,196.5938 Q282.4156,194.9375 282.4156,191.8125 Q282.4156,188.6875 283.7281,187.0313 Q285.0563,185.375 287.5563,185.375 Q288.2594,185.375 288.9,185.5313 Q289.5563,185.6875 290.1188,185.9844 L290.1188,188.7031 Q289.4938,188.125 288.9,187.8594 Q288.3063,187.5781 287.6813,187.5781 Q286.3375,187.5781 285.65,188.6563 Q284.9625,189.7188 284.9625,191.8125 Q284.9625,193.9063 285.65,194.9844 Q286.3375,196.0469 287.6813,196.0469 Q288.3063,196.0469 288.9,195.7813 Q289.4938,195.5 290.1188,194.9219 L290.1188,197.6406 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="131" x="305.85" y="196.1543">gui::ConcreteVisitor2</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="252" x2="460" y1="208" y2="208"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="147" x="257" y="222.2104">void visit(gui::Item &amp;item)</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="146" x="257" y="235.0151">void visit(gui::Rect &amp;item)</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="146" x="257" y="247.8198">void visit(gui::Text &amp;item)</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="198" x="257" y="277.4292">void visit(gui::CustomItem2 &amp;item)</text><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,2.0;" x1="252" x2="306.5" y1="260.8164" y2="260.8164"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="99" x="306.5" y="264.1245">. visit overloads .</text><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,2.0;" x1="405.5" x2="460" y1="260.8164" y2="260.8164"/><!--class gui::Item--><rect fill="#FEFECE" filter="url(#f14eszahge7obk)" height="60.8047" id="gui::Item" style="stroke: #A80036; stroke-width: 1.5;" width="213" x="496.5" y="31.5"/><ellipse cx="571.75" cy="47.5" fill="#ADD1B2" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M574.7188,53.1406 Q574.1406,53.4375 573.5,53.5781 Q572.8594,53.7344 572.1563,53.7344 Q569.6563,53.7344 568.3281,52.0938 Q567.0156,50.4375 567.0156,47.3125 Q567.0156,44.1875 568.3281,42.5313 Q569.6563,40.875 572.1563,40.875 Q572.8594,40.875 573.5,41.0313 Q574.1563,41.1875 574.7188,41.4844 L574.7188,44.2031 Q574.0938,43.625 573.5,43.3594 Q572.9063,43.0781 572.2813,43.0781 Q570.9375,43.0781 570.25,44.1563 Q569.5625,45.2188 569.5625,47.3125 Q569.5625,49.4063 570.25,50.4844 Q570.9375,51.5469 572.2813,51.5469 Q572.9063,51.5469 573.5,51.2813 Q574.0938,51 574.7188,50.4219 L574.7188,53.1406 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="54" x="592.25" y="51.6543">gui::Item</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="497.5" x2="708.5" y1="63.5" y2="63.5"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="497.5" x2="708.5" y1="71.5" y2="71.5"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="201" x="502.5" y="85.7104">void accept(gui::GuiVisitor &amp;visitor)</text><!--class gui::Rect--><rect fill="#FEFECE" filter="url(#f14eszahge7obk)" height="60.8047" id="gui::Rect" style="stroke: #A80036; stroke-width: 1.5;" width="213" x="496.5" y="199.5"/><ellipse cx="571.25" cy="215.5" fill="#ADD1B2" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M574.2188,221.1406 Q573.6406,221.4375 573,221.5781 Q572.3594,221.7344 571.6563,221.7344 Q569.1563,221.7344 567.8281,220.0938 Q566.5156,218.4375 566.5156,215.3125 Q566.5156,212.1875 567.8281,210.5313 Q569.1563,208.875 571.6563,208.875 Q572.3594,208.875 573,209.0313 Q573.6563,209.1875 574.2188,209.4844 L574.2188,212.2031 Q573.5938,211.625 573,211.3594 Q572.4063,211.0781 571.7813,211.0781 Q570.4375,211.0781 569.75,212.1563 Q569.0625,213.2188 569.0625,215.3125 Q569.0625,217.4063 569.75,218.4844 Q570.4375,219.5469 571.7813,219.5469 Q572.4063,219.5469 573,219.2813 Q573.5938,219 574.2188,218.4219 L574.2188,221.1406 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="55" x="591.75" y="219.6543">gui::Rect</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="497.5" x2="708.5" y1="231.5" y2="231.5"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="497.5" x2="708.5" y1="239.5" y2="239.5"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="201" x="502.5" y="253.7104">void accept(gui::GuiVisitor &amp;visitor)</text><!--class gui::Text--><rect fill="#FEFECE" filter="url(#f14eszahge7obk)" height="60.8047" id="gui::Text" style="stroke: #A80036; stroke-width: 1.5;" width="213" x="248.5" y="344"/><ellipse cx="324.25" cy="360" fill="#ADD1B2" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M327.2188,365.6406 Q326.6406,365.9375 326,366.0781 Q325.3594,366.2344 324.6563,366.2344 Q322.1563,366.2344 320.8281,364.5938 Q319.5156,362.9375 319.5156,359.8125 Q319.5156,356.6875 320.8281,355.0313 Q322.1563,353.375 324.6563,353.375 Q325.3594,353.375 326,353.5313 Q326.6563,353.6875 327.2188,353.9844 L327.2188,356.7031 Q326.5938,356.125 326,355.8594 Q325.4063,355.5781 324.7813,355.5781 Q323.4375,355.5781 322.75,356.6563 Q322.0625,357.7188 322.0625,359.8125 Q322.0625,361.9063 322.75,362.9844 Q323.4375,364.0469 324.7813,364.0469 Q325.4063,364.0469 326,363.7813 Q326.5938,363.5 327.2188,362.9219 L327.2188,365.6406 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="53" x="344.75" y="364.1543">gui::Text</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="249.5" x2="460.5" y1="376" y2="376"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="249.5" x2="460.5" y1="384" y2="384"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="201" x="254.5" y="398.2104">void accept(gui::GuiVisitor &amp;visitor)</text><!--class gui::CustomItem1--><rect fill="#FEFECE" filter="url(#f14eszahge7obk)" height="60.8047" id="gui::CustomItem1" style="stroke: #A80036; stroke-width: 1.5;" width="213" x="496.5" y="344"/><ellipse cx="544.25" cy="360" fill="#ADD1B2" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M547.2188,365.6406 Q546.6406,365.9375 546,366.0781 Q545.3594,366.2344 544.6563,366.2344 Q542.1563,366.2344 540.8281,364.5938 Q539.5156,362.9375 539.5156,359.8125 Q539.5156,356.6875 540.8281,355.0313 Q542.1563,353.375 544.6563,353.375 Q545.3594,353.375 546,353.5313 Q546.6563,353.6875 547.2188,353.9844 L547.2188,356.7031 Q546.5938,356.125 546,355.8594 Q545.4063,355.5781 544.7813,355.5781 Q543.4375,355.5781 542.75,356.6563 Q542.0625,357.7188 542.0625,359.8125 Q542.0625,361.9063 542.75,362.9844 Q543.4375,364.0469 544.7813,364.0469 Q545.4063,364.0469 546,363.7813 Q546.5938,363.5 547.2188,362.9219 L547.2188,365.6406 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="109" x="564.75" y="364.1543">gui::CustomItem1</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="497.5" x2="708.5" y1="376" y2="376"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="497.5" x2="708.5" y1="384" y2="384"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="201" x="502.5" y="398.2104">void accept(gui::GuiVisitor &amp;visitor)</text><!--class gui::CustomItem2--><rect fill="#FEFECE" filter="url(#f14eszahge7obk)" height="48" id="gui::CustomItem2" style="stroke: #A80036; stroke-width: 1.5;" width="141" x="744.5" y="350.5"/><ellipse cx="759.5" cy="366.5" fill="#ADD1B2" rx="11" ry="11" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M762.4688,372.1406 Q761.8906,372.4375 761.25,372.5781 Q760.6094,372.7344 759.9063,372.7344 Q757.4063,372.7344 756.0781,371.0938 Q754.7656,369.4375 754.7656,366.3125 Q754.7656,363.1875 756.0781,361.5313 Q757.4063,359.875 759.9063,359.875 Q760.6094,359.875 761.25,360.0313 Q761.9063,360.1875 762.4688,360.4844 L762.4688,363.2031 Q761.8438,362.625 761.25,362.3594 Q760.6563,362.0781 760.0313,362.0781 Q758.6875,362.0781 758,363.1563 Q757.3125,364.2188 757.3125,366.3125 Q757.3125,368.4063 758,369.4844 Q758.6875,370.5469 760.0313,370.5469 Q760.6563,370.5469 761.25,370.2813 Q761.8438,370 762.4688,369.4219 L762.4688,372.1406 Z "/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="109" x="773.5" y="370.6543">gui::CustomItem2</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="745.5" x2="884.5" y1="382.5" y2="382.5"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="745.5" x2="884.5" y1="390.5" y2="390.5"/><!--link gui::GuiVisitor to gui::ConcreteVisitor1--><path d="M182.15,132.97 C171.49,147.36 160.44,162.28 150.31,175.95 " fill="none" id="gui::GuiVisitor-gui::ConcreteVisitor1" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="none" points="176.87,128.34,194.4,116.44,188.12,136.67,176.87,128.34" style="stroke: #A80036; stroke-width: 1.0;"/><!--link gui::GuiVisitor to gui::ConcreteVisitor2--><path d="M285.42,132.97 C296,147.36 306.96,162.28 317.01,175.95 " fill="none" id="gui::GuiVisitor-gui::ConcreteVisitor2" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="none" points="279.48,136.7,273.27,116.44,290.76,128.41,279.48,136.7" style="stroke: #A80036; stroke-width: 1.0;"/><!--link gui::Item to gui::Rect--><path d="M603,112.77 C603,140.97 603,175.29 603,199.3 " fill="none" id="gui::Item-gui::Rect" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="none" points="596,112.68,603,92.68,610,112.68,596,112.68" style="stroke: #A80036; stroke-width: 1.0;"/><!--link gui::Rect to gui::Text--><path d="M534.14,270.57 C493.81,293.74 443.7,322.53 406.75,343.77 " fill="none" id="gui::Rect-gui::Text" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="none" points="530.79,264.42,551.61,260.53,537.76,276.56,530.79,264.42" style="stroke: #A80036; stroke-width: 1.0;"/><!--link gui::Rect to gui::CustomItem1--><path d="M603,280.64 C603,301.59 603,325.3 603,343.52 " fill="none" id="gui::Rect-gui::CustomItem1" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="none" points="596,280.53,603,260.53,610,280.53,596,280.53" style="stroke: #A80036; stroke-width: 1.0;"/><!--link gui::Rect to gui::CustomItem2--><path d="M663.58,271.72 C701.5,297.21 748.98,329.12 780.56,350.35 " fill="none" id="gui::Rect-gui::CustomItem2" style="stroke: #A80036; stroke-width: 1.0;"/><polygon fill="none" points="659.62,277.49,646.93,260.53,667.43,265.87,659.62,277.49" style="stroke: #A80036; stroke-width: 1.0;"/><!--
@startuml

abstract class gui::GuiVisitor
{
    void visit(gui::Item &item)
    void visit(gui::Rect &item)
    void visit(gui::Text &item)
    ... visit overloads ...
    void visit(gui::CustomItem2 &item)
}

class gui::ConcreteVisitor1
{
    void visit(gui::Item &item)
    void visit(gui::Rect &item)
    void visit(gui::Text &item)
    ... visit overloads ...
    void visit(gui::CustomItem2 &item)
}

class gui::ConcreteVisitor2
{
    void visit(gui::Item &item)
    void visit(gui::Rect &item)
    void visit(gui::Text &item)
    ... visit overloads ...
    void visit(gui::CustomItem2 &item)
}

gui::GuiVisitor <|- - gui::ConcreteVisitor1
gui::GuiVisitor <|- - gui::ConcreteVisitor2

class gui::Item
{
    void accept(gui::GuiVisitor &visitor)
}
class gui::Rect
{
    void accept(gui::GuiVisitor &visitor)
}
class gui::Text
{
    void accept(gui::GuiVisitor &visitor)
}
class gui::CustomItem1
{
    void accept(gui::GuiVisitor &visitor)
}
class gui::CustomItem2
{
}

gui::Item <|- - gui::Rect
gui::Rect <|- - gui::Text
gui::Rect <|- - gui::CustomItem1
gui::Rect <|- - gui::CustomItem2
@enduml

PlantUML version 1.2018.13(Mon Nov 26 18:11:51 CET 2018)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 11.0.9.1+1-Ubuntu-0ubuntu1.20.04
Operating System: Linux
OS Version: 5.4.0-56-generic
Default Encoding: UTF-8
Language: en
Country: US
--></g></svg>
\ No newline at end of file

M module-gui/gui/dom/Item2JsonSerializer.hpp => module-gui/gui/dom/Item2JsonSerializer.hpp +2 -0
@@ 22,6 22,8 @@ namespace gui
        void handleOther(gui::ItemNode &node, prototype &doc, int &level);

      public:
        /// On traverse all `gui::Item`-based classes in the parent-children tree of given root will be serialized into
        /// JSON format and kept in `document`.
        void traverse(gui::Item &root);
        void dump(std::ostream &stream);
    };

M module-gui/gui/dom/Item2JsonSerializingVisitor.hpp => module-gui/gui/dom/Item2JsonSerializingVisitor.hpp +4 -0
@@ 13,6 13,8 @@ namespace gui
    class BoundingBox;
    class Color;

    /// Visitor serializing a single object of a class in a `gui::Item`'s inheritance hierarchy into the JSON format. On
    /// each visit, acceptor is serialized with a result appended into the `sink`.
    class Item2JsonSerializingVisitor : public GuiVisitor
    {
        json11::Json::object sink;


@@ 30,10 32,12 @@ namespace gui
        void visit(gui::TopBar &item) override;

      public:
        /// retrieves current state of the `sink`. The state of the `sink` after call is default-initialized
        [[nodiscard]] auto moveState() noexcept -> json11::Json::object
        {
            return std::move(sink);
        }
        /// retrieves name of a object's type that was serialized.
        [[nodiscard]] auto moveName() noexcept -> std::string
        {
            return std::move(itemName);

M module-gui/gui/widgets/visitor/DepthFirstItemTree.hpp => module-gui/gui/widgets/visitor/DepthFirstItemTree.hpp +2 -0
@@ 11,6 11,8 @@ namespace gui
    class DepthFirstItemTree : public ItemTree
    {
      public:
        /// Tree traverse modes. In `PreOrder` mode a parent precedes it's children. In `PostOrder` mode, children
        /// precedes it's parent.
        enum class TraverseMode
        {
            PreOrder,

M module-gui/gui/widgets/visitor/GuiVisitor.hpp => module-gui/gui/widgets/visitor/GuiVisitor.hpp +2 -0
@@ 13,6 13,8 @@ namespace gui
    class BottomBar;
    class TopBar;

    /// The general purpose abstract interface for enabling Double-Dispatch behavior throughout `gui::Item`'s
    /// inheritance hierarchy.
    class GuiVisitor
    {
      public:

M module-gui/gui/widgets/visitor/ItemNode.hpp => module-gui/gui/widgets/visitor/ItemNode.hpp +2 -0
@@ 9,6 9,8 @@ namespace gui
{
    class Item;

    /// General wrapper for a `gui::Item`'s parent-children hierarchy. Encapsulates a object's reference together with
    /// it's level in a hierarchy
    class ItemNode
    {
      public:

M module-gui/gui/widgets/visitor/ItemTree.hpp => module-gui/gui/widgets/visitor/ItemTree.hpp +3 -0
@@ 7,10 7,13 @@

namespace gui
{
    /// General abstraction of `gui::Item`'s parent-children hierarchy with defined traverse order
    class ItemTree
    {
      public:
        [[nodiscard]] virtual auto hasNext() const noexcept -> bool    = 0;
        /// Provides wrapper for next `gui::Item` object in traverse order. On call concrete implementations might
        /// change state of the tree by removing node being returned. Must be used in pair with `hasNode()`
        [[nodiscard]] virtual auto getNext() noexcept -> gui::ItemNode = 0;

        virtual ~ItemTree() = default;