Please provide a way to draw if/elseif/else structure vertically in activity diagrams

0 votes
asked Oct 23, 2015 in Wanted features by MAV (460 points)

I'm working on some code with switch case structures on big enumerate type or if/elsif/else structures with big conditions.

For now, I use the if/elseif/else plantUML structure to draw them but the different cases are placed horizontally.

It is a problem when the associated conditions or actions are big, the diagram becomes very large.

Example :

@startuml
title lot_of_elsif
start
if (Enum) Then (Value_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
:Do_A;
elseif (Enum) Then (Value_BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB)
:Do_B;
elseif (Enum) Then (Value_CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)
:Do_C;
elseif (Enum) Then (Value_DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD)
:Do_D;
elseif (Enum) Then (Value_EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE)
:Do_E;
elseif (Enum) Then (Value_FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
:Do_F;
elseif (Enum) Then (Value_GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG)
:Do_G;
elseif (Enum) Then (Value_HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH)
:Do_H;
Else (Value_ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ)
:Do_Z;
endif
end
@enduml

activity diagram

Please provide a way to draw if/elseif/else structure vertically in activity diagrams.

1 Answer

+1 vote
answered Nov 1, 2015 by plantuml (295,760 points)

This is still under work, but you can try an alpha version here: https://dl.dropboxusercontent.com/u/13064071/plantuml.jar

With this version you must add a line to enable the feature:
!pragma useVerticalIf on

Example:

@startuml
!pragma useVerticalIf on
start
if (condition A) then (yes)
  :Text 1;
elseif (condition B) then (yes)
  :Text 2;
elseif (condition C) then (yes)
  :Text 3;
elseif (condition D) then (yes)
  :Text 4;
else (nothing)
  :Text else;
endif
@enduml

In the final version, this pragma stuff will not be needed.
It's not clear yet if PlantUML will decide on its own to select horizontal/vertical strategy, or if the user will have to use a special command to change the layout (maybe a new keyword instead of "if" )

There are still issue about label layout, but the general idea is here.
Tell us what do you think about it!

commented Feb 20, 2019 by Nathan
thanks, this is very helpful
commented May 1, 2021 by Bert Merchie
Hi,

I really love this feature and use it quite frequently. Recently I bumped onto a case whereby it doesn't seem to do the job :-(. Could you please help me out how I can make it work for this case too?

Many thanks!

@startuml
!pragma useVerticalIf on
scale 1020x4000

start
:**prioCheck_Ondemand_PI**: \n__input parameters__:\n* item = VIDEO_CONTENT\n* highestPrio\n* highestPrioItem\n* selectedProduct\n__output parameters__\n* highestPrio\n* highestPrioItem\n* selectedProduct;
If (item.EntitlementState?) then ("Entitled")
   group entitled on-demand
   If (item.IsTstv?) then (false)
   'ingested entitled on demand                    
      If (highestPrio = 1?) then (no)                      
         :* highestPrio = 1\n* highestPrioItem = item;
      'ElseIf (highestPrioItem.IsViewableOnCpe = false And item.IsViewableOnCpe = true) then (yes)
         ':highestPrioItem = item;
         'note right: prioritize viewable content
      else (yes)
      EndIf
      :product = item.products(0);
      while (more products?)
         if (products(i).Type < product.Type) then (yes)
            :selectedProduct = products(i);
         else (no)
         endif
      endwhile
   Else (true)
      'automatically recorded, entitled                           
      If (highestPrio >= 4?) then (yes)           
         If (highestPrio = 4?) then (yes)          
            'If (highestPrioItem.IsViewableOnCpe = false And item.IsViewableOnCpe = true) then (yes)
               ':highestPrioItem = item;
               '(-> prioritize viewable content)
            'ElseIf (item.FirstAvailability\n> highestPrioItem.FirstAvailability And highestPrioItem.IsViewableOnCpe\n= item.IsViewableOnCpe) then (yes)
            If (item.FirstAvailability\n> highestPrioItem.\nFirstAvailability) then (yes)
               :highestPrioItem = item;                      
               '(-> this autorecorded entitled catchup, recorded more recently than the one selected so far)
            Else (no)                 
            EndIf                 
         else (no)          
            :* highestPrio = 4\n* highestPrioItem = item;
            '(-> this automatically recorded entitled catchup)
         endif                
      else (no)
      endIf                         
      'If (item.EntitlementEnd > Now()                                 '** entitled TVoDs
      '            highestPrioLinkedItem = item                                  '(-> this rented TVoD)
      '            highestPrio = 1                        
      '        Else '(non entitled on-demand)   
      '
   endif
   end group
else ("NotEntitled")
   group non-entitled on-demand
   If (highestPrio >= 6?) then (yes)                     
      If (IsTstv?) then (False)                          
         repeat
           'non-entitled TVoD "Transaction" has higher priority over non-entitled SVoD "Subscription" (FVoD not possible for the non-entitled case)
            If (item.Products(i).Type?) then ("Transactional")
              'ElseIf (highestPrioItem.IsViewableOnCpe = false And item.IsViewableOnCpe = true) Or (item.Products(0).ListPrice < ctaLowestRentalPrice) then  
               If (item.Products(i).ListPrice < ctaLowestRentalPrice?) then (yes)
                  '** non-entitled TVoDs (for ease of implementation, start implementation for lowest ListPrice, not OfferPrice)
                  :highestPrio = 6\n* highestPrioItem = item\n* selectedProduct = item.Products(i)\n* ctaLowestRentalPrice = ListPrice;
                  '(-> this TVoD content option at lower price OR prioritize viewable content)
               endif
            else ("Subscription")
               'If (highestPrio = 7 And (highestPrioItem.IsViewableOnCpe = false And item.IsViewableOnCpe = true) then  
               if (highestPrio > 7) then (yes)
                  'note right: € SVoD
                  :selectedProduct = item.Products(i) ;
                  :highestPrio = 7;
                  :highestPrioItem = item;
               else (no)
               endif
            endif
         repeat while (more products) is (yes)
      else (true)
      '(automatically recorded, non entitled)                    '** non entitled autorecorded catchup
         if (highestPrio > 7) then (yes)
            if (highestPrio = 8) then (yes)
               'If highestPrioItem.IsViewableOnCpe = false And item.IsViewableOnCpe = true
               'highestPrioItem = linkedItem                  '(-> prioritize viewable content)
               'ElseIf item.FirstAvailability > highestPrioItem.FirstAvailability And highestPrioItem.IsViewableOnCpe = item.IsViewableOnCpe
                If (item.FirstAvailability?) then (> highestPrioItem.FirstAvailability)
                   :* highestPrioItem = item\n*  selectedProduct = item.Products(0);
                  '(-> this SVoD content option)
               endif
            else (no)
               :* highestPrioItem = item\n* highestPrio = 8\n* selectedProduct = item.Products(0) ;
               '(-> this SVoD content option)
            endif
         else (no)
         endif
      Endif     
   endif
   end group
endif

   :return\n* highestPrio\n* highestPrioItem\n* selectedProduct;
   end
@enduml
...