ELTE-Soft / txtUML

Textual, eXecutable, Translatable UML
http://txtuml.inf.elte.hu
Eclipse Public License 1.0
26 stars 9 forks source link

Diagram Layout - Grouping boxes and restructuring Layout definition #214

Open GregoBalu opened 8 years ago

GregoBalu commented 8 years ago

It would be nice to have a new Statement to our existing language that would encapsulate certain boxes and "hide" them with one outer bigger box. With this method we can sort of solve the:

  1. different-sized-boxes problem (one bigger box and smaller boxes beside it, in the same row/column of the grid)
  2. hierarchy in diagrams (State Machines)

The user would have to define a group of boxes and another box that will "contain" that group physically. The latter could be an in-model box or a phantom node as well:

phantom(NewBox)
group({A, B, C}, G)
encapsulate(G, NewBox)    //Members of G are now inside of phantom box NewBox

This abstract name is debatable, but is not visible to the user. The front-end would get a small overhaul so it can support structuring (better readability) and could be something like these:

// The example Class
class MC extends ModelClass {        
        class S0 extends State {}
     class CS extends CompositeState {
         class S1 extends State {}
         class S2 extends State {}
         class S3 extends State {}
    }
}

First version:

// The example State Machine Diagram of the above Class
class D extends StateMachineDiagram<MC> {   
    @Show(CS.class)
    class L extends Layout<Top> {}    
            // This is the layout for 'Top' level elements (possibly S0 and CS),
            //  for example in a Class Diagram here we could
            // give the layout of classes in the model

            // Ph phantom box contains S1 and S2 boxes ( encapsulate({S1, S2}, Ph) )
    @Contains({S1.class, S2.class)
    class Ph extends PhantomNode<CS> {}     /* Top */ 
            // Ph is defined as a Phantom box under CS (could be Top as well)

    @Show(S3.class)
    class L2 extends Layout<CS> {}
            // Layout for CS level (layout for elements inside CS: possibly S1, S2, S3)

    @North(val = S1.class, from = S2.class)
    class L3 extends Layout<Ph> {}
            // Layout for Ph level (layout for elements inside Ph: S1, S2)
}

This version separates the diagram by levels, but comes with a price: We have to give that template parameter for the layout class every time, which is frustrating when only defining elements on the Top level (Top is a bit arbitrary value). This is most noticeable when defining Class diagrams where most (all) of the boxes are on top level.

Second version:

class D extends StateMachineDiagram<MC> {   
            // We have to give a name to this inner element
            // The inner element's type (extends XYZ<AB>) is debatable
    class CSDiagram extends StateMachineDiagram<CS> {
            // Layout inside CS
        @North(val = S3.class, from = Ph.class)
        class L extends Layout {}

            // Ph Phantom box is defined inside the "Diagram" of CS state
            // Ph encapsulates S1 and S2
        @Contains({S1.class, S2.class})
        class Ph extends PhantomNode {
            // Layout inside Ph
            @North(val = S1.class, from = S2.class)
            class L extends Layout {}
        }
    }

            // Layout for MC (Top level)
    @Show(CS.class)
    class L extends Layout {}   
}

The second version would need less technical reconstruction and less writings (no template paramters) than the first one. On the other hand we had to give a name for the diagram inside CS (CSDiagram) which is not used.

The expected result of a Diagram using this encapsulation:

Model:
  A, B, C
Layout: 
  phantom(Phantom1)
  encapsulate({B, C}, Phantom1)
  right(Phantom1, A)
  column({B,C})

encapsulate_example

GregoBalu commented 8 years ago

The team agreed to disagree on naming of certain elements but accepted the following format:

...
state CompositeStateName {
    state InnerState1, innerState2, InnerState3;
}
state OtherState;
...
class MyDiagram extends StateMachineDiagram<ClassName>
{   
    @Inside(CompositeStateName.class)
    class MyDiagramForCompositeState extends Box    //This is a visible Box
    {
        class Ph extends Box    //This is an invisible Box (traditional phantom)
        {
            @East(val = InnerState2.class, from = InnerState3.class)
            class L extends Layout {}
        }

        @North(val = InnerState1.class, from = Ph.class)
        class L extends Layout {}
    }

    @Row({CompositeStateName.class, OtherState.class})
    class L extends Layout {}   
}

Or instead of name Box, we could use Phantom for the invisible box and something else (?) for the visible box.

GregoBalu commented 8 years ago

First ever hierarchical diagram with txtUML Layout. Behold.

Using this layout:

class ProducerConsumerDiagram extends ClassDiagram {

    class ContainerPhantom extends Box
    {
        @South(val = Item.class, from = Storage.class)
        class PhantomLayout extends Layout{}
    }

    @Row({ Producer.class, ContainerPhantom.class, Consumer.class })
    class ProducerConsumerLayout extends Layout {
    }
}

Got this (textual version, because textual modelling is op):

  * - - - - - - - - - *                 
  | * - - - - - - - * |                 
  | |             # @ @ #               
  | |             #Stora#               
  | |             # # # @ - - - - *     
# @ @ #           # # @ #       # @ # # 
#Produ#               + - - - - @Consu# 
# # # #               |         # # # # 
# # # #               |         # # # # 
                      |                 
                  # # @ #               
                  #Item #               
                  # # # #               
                  # # # #               

It's far from perfect, but hey - it's something

GregoBalu commented 8 years ago

Update:

                        # # # # # # #                   
                        # Storage # #                   
                        # # # # # # #                   
                        # # # # # # #                   
                        # # # # # # #                   
    * - - - - - - - - - @ # # # # # @ - - - - - - *     
    |                   # @ # @ # @ #             |     
# # @ #                   |   |   |             # @ # # 
# Prod@ - - - - - - - - - *   |   * - - - - - - @ Cons# 
# # # #                       |                 # # # # 
# # # #                       |                 # # # # 
                              |                         
                              |                         
                              |                         
                              |                         
                          # # @ #                       
                          # Item#                       
                          # # # #                       
                          # # # #                       
GregoBalu commented 7 years ago

@ELTE-Soft/all *Most statements are scoped to their layer (in case of hierarchical diagrams). Should Spacing statement be the same? Then it would be possible to customize the diagram spacing of inner layers regardless of the outer. If no inner Spacing is present then the outer Spacing would be considered.

dobreffandras commented 7 years ago

I think that's good. So if I specify a spacing on the outer box, it should affect the inner as well when the inner has no spacing. If the inner has spacing the outer has no effect on it any more.

devaigergely81 commented 7 years ago

Agree.