Search Results for

    Show / Hide Table of Contents

    Live Diagram

    Overview

    Live Diagram is a library derived from Diagram Studio. It has all the features of the base suite and moreover it can execute the diagrams.
    The main component is the Live Diagram (TLiveDiagram), a graphic control able of managing the thread-safe execution of its Live Blocks (TCustomLiveBlock descendants).

    To have an executable Diagram, basically we need of design rules and execution strategy. Design rules state how the blocks can be connected each other to form a "well formatted" execution chart, execution strategy states how the blocks must be executed i.e. their flow.
    These rules are not set in the diagram, TCustomLiveBlock descendants implement them, so they can be easily extended.

    In a Live Diagram can be inserted Live Blocks and traditional components at the same time, but only live blocks will be "managed" (checked, linked, executed).

    Purpose

    • Computer science fundamentals training and teaching.

    • Algorithms check.

    • Rapid prototype.

    • Extreme user-customization of applications.

    Features overview

    • Inheritance of all features of TatDiagram without restrictions.

    • Design time support for executing native Delphi code.

    • Separate threads for execution and visualization, both synchronized.

    • Balancing of execution thread CPU consumption.

    • Thread safe model, multiple diagram can run at the same time.

    • Step by step execution mode.

    • Possibility of executing diagrams without a line of code.

    • Specialized blocks : Error handler, Line jointer, Connectors.

    • Multiple executions paths.

    Lacks overview

    • Not suitable for industrial automation or critical applications.

    • Non time-deterministic execution.

    • Simulated multithread (due to Synchronize method).

    TLiveDiagram component

    It's the Live Diagram main component, it inherits from TatDiagram.

    Key Properties

    State: TDiagramState = (dsEdit, dsRunning, dsPaused)
    Reflects the status of the diagram. It can be used to enable/disable actions and buttons.
    When not in edit mode, the editing is disabled. Do not modify State directly, use DoAction method instead.

    RunError: integer
    Contains the value of the last Error flag (see TCustomLiveBlock.Execute).

    ExitCode: integer
    After the execution termination contains the exit code (see TCustomLiveBlock.Execute).

    Liveds[index : integer]: TCustomLiveBlock
    Contains the list of all LivedBlocks. It's only filled after a call to Link method. Do not use it in edit mode.

    IdlePercent: DWORD
    Allows the CPU balancing. Every block execution is time-marked, so if a block is executed in 20ms (for instance) and IdlePercent=50 the execution thread will sleep for 20ms.
    It's possible to modify it during the diagram execution.

    SleepVisual: DWORD
    It refers to the visual thread and is a fixed value of sleep time.

    RunColor: TColor
    It's the background diagram color during the execution.

    Key Methods

    function Link: boolean
    Checks the diagram consistence and links the blocks, returns true if everything is ok. After a successful link, Liveds property contains the lived block list. Everything that doesn't inherits from TCustomLiveBlock or from a wire is ignored.
    Don't call Link directly, override it or PrepareRun.

    function PrepareRun: boolean
    It's invoked every time the run is request if the diagram was modified. Just calls Link, override this method to perform special init operations.

    procedure DoAction(Action: TDiagramAction)
    TDiagramAction = (daRun, daRunPaused, daPause, daStop, daForceStop, daReset, daStep)
    Performs a diagram operation:

    • daRun: Starts the diagram execution;
    • daRunPaused: Starts the diagram execution in pause mode, a daStep command is necessary to continue;
    • daPause: Pauses the execution;
    • daStop: Stops the execution;
    • daForceStop: Forces the stop without firing OnTerminate event;
    • daReset: Resets the execution - Start became the current block;
    • daStep: Executes the next block and returns in pause mode.

    An operation to be performed must be compatible with the Diagram state, otherwise it's ignored.

    dsEdit dsRunning dsPause
    daRun OK Ignored OK
    daRunPaused OK Ignored Ignored
    daPause Ignored OK Ignored
    daStop Ignored OK OK
    daForceStop Ignored OK OK
    daReset Ignored Ignored OK
    daStep Ignored Ignored OK

    Key Events

    property OnStart: TStartEvent = procedure(Sender: TLiveDiagram; StartMode: TStartMode)
    TStartMode = (smCold, smWarm)
    This event is fired whenever the daRun action is requested, StartMode=smCold if the diagram starts the run from dsEdit, StartMode=smWarm if the diagram starts the run from dsPaused.

    Note

    daStep action doesn't fire this event.

    property OnChangeState: TChangeStateEvent = procedure(Sender: TLiveDiagram; NewState: TDiagramState)
    This event is fired whenever the diagram state changes.

    property OnUnhandledRunError: TRunErrorEvent = procedure(Sender: TLiveDiagram; Block: TCustomLiveBlock; var Error: integer; var ResumeNext: boolean = false)
    This event is fired when an error occurred (User Error flag>0, see TCustomLiveBlock.Execute) and an Error handler doesn't exists.
    Block is the LiveBlock that raised the error, if ResumeNext is set to true the error is zeroised and the execution continues with Block.Next, otherwise the program is terminated with Exitcode=Error.
    If this property is not assigned and Error handler doesn't exists the program terminates with Exitcode=xUnhandled_error.

    property OnShift: TShiftEvent = procedure(Sender: TLiveDiagram; OldBlock, NewBlock: TCustomLiveBlock)
    This event is fired when NewBlock is being to execute, OldBlock is the block just executed.
    The method that fires the event is DoShift (virtual).

    Warning

    OldBlock or NewBlock could be nil.

    property OnTerminate: TTerminateEvent = procedure(Sender: TLiveDiagram; ExitCode: integer)
    This event is fired when the diagram terminates the execution.

    TCustomLiveBlock base class

    It is (and must be) the ancestor of all live blocks. It inherits from TCustomDiagramBlock. It's a base class, so isn't registered with RegisterDControl.

    Key Properties

    ControlState: TControlState = (csEdit, csRunON, csRunOFF, csRunERR)
    It's the block state, this property is used to show different color during the block execution.

    PassThrough: boolean
    It's true when the block is not "executable", a passthrough block is used to perform special connections (see Jointers and Connectors) and it's completely transparent to the execution. When implementing a passthrough block a mechanism to avoid endless loop during the link process must be set (see at TLiveJoin.GetNext).

    IsErrorHandler: boolean
    A descendent block that implements error handling must set to true this property. Many error handler can be defined in the same set, but only one of these can be inserted in a chart.

    IsStartBlock: boolean
    Every chart must contain a start block, it must be unique, this property must be true when the descendant is defined as start point.

    IsEndBlock: boolean
    Every block can terminate the diagram, but only the End Block will terminate it with the code xNormal_termination (see Execute procedure). The End Block must have this property set to true.

    Next: TCustomLiveBlock
    Points to the next executable block. The execution strategy is implemented here (the value is read through GetNext method).

    RunColors: TBlockColors = class(TPersistent)
    Stores the three run colors associated to the ControlState (when in edit mode the block colors are stored in Color and SelColor properties).
    It would be better to avoid the use of bitmaps in Liveblocks, the gradient is automatically disabled during the execution, the shadow doesn't create any problem.

    Key Methods

    function Link: boolean
    Finds the next block and stores it into FNext (the field image of Next), returns true when FNext is not nil. Every block which can have an unassigned Next must return true to avoid a design error (see TLiveHeader and TLiveErrorHandler).
    Link is called by TLiveDiagram.

    function Execute(var Error, Decision: integer): TCustomLiveBlock
    Executes the block. Do not call Execute directly, it's declared as public only to be visible outside the unit, OnExecute must be used instead. The variable Error is an user passthrough flag in accord to:

    • 0: the execution continues with the Next block;

    • -1: the block requested the "End of Program", if the block has IsEndBlock=true the program exitcode is xNormal_Termination (0), otherwise the exitcode is xProgram_Termination (2);

    • -2: there was an exception in the OnExecute event, the program will terminate with xCode_Exception (4) exit code.

    • >0: the Error handler block is the next block to be executed. If it doesn't exists in the chart, TLiveDiagram fires the OnUnhandledRunError event.

    The variable Decision must be set only for special blocks that perform decisions, like TLiveDecisionBlock and TLiveCaseBlock.
    The result of the function is the next block that have to be executed, to perform special operation it would be better to override GetNext method.

    procedure DoBeforeRun
    This method is called whenever the diagram is about to be executed, override it to perform initialization stuff.

    function AcceptLink(ALink: TCustomDiagramLine; LinkIndex: integer; Direction: TLinkDirection): boolean
    TLinkDirection = (ldInput, ldOutput)
    It's the key method for implementing the design rules. LinkIndex is the block linkpoint number, Direction reflects the link (TCustomDiagramLine) direction source or target.
    This function is called by TLiveDiagram whenever a link between two link points is about to be made. Do not call this method directly, override it to perform special checks.

    function GetNext: TCustomLiveBlock
    It's the read function of the property Next, override this function to setup the execution strategy.

    Note

    Do not perform heavy operation in this function to avoid slowing down, since it's called at runtime.

    Key Events

    property OnExecute: TExecuteEvent = function(Sender: TCustomLiveBlock; var Error, Decision: integer): integer
    This event is fired on the block execution. See Execute method.

    Visual examples of Passthrough, Next and Link

    In the diagram below, the flowchart at the left performs the same thing as the flowchart at the right. The "A" blocks are TLiveConnectorSource and TLiveConnectorTarget blocks, and after (following) the second "A" there is a TLiveLineJoin. Those three blocks have the Passthrough property set to true, so they perform no action at all.

    Also, in both diagrams, the Block1.Next property points to Block2.

    livediagram passthrough

    In the diagram below, after a call to Link method, the error message appears. Regardless of the strange "path", Block1 is unlinked.

    livediagram passthrough error

    Basic live diagram objects

    All live diagram objects are available under the category "Live Diagram". This category is displayed in the diagram toolbar.

    For now, there are 3 groups of live diagram objects: basic, flowchart and statechart. This topic covers the basic objects.

    toolbar livediagram

    From the left to right in the above picture:

    • TLiveConnectorSource (Source connector)

    • TLiveConnectorTarget (Target connector)

    • TLiveLineJoin (Line jointer)

    • TLiveWire (Live wire)

    • TLiveSideWire (Live side wire)

    • TLiveArc (Live arc)

    • TLiveBezier (Live bezier)

    TLiveConnectorSource and TLiveConnectionTarget

    These blocks connect two or more points of a diagram to increase the readability. They are not executable i.e. PassThrough=true.

    To be linked they must have the same text (case insensitive). Many source connectors can be linked to an unique target connector. In the picture below, Decision1.Next = Subroutine1.Next = Document1.Next = Action1.

    livediagram connectors

    TLiveLineJoin (Line jointer)

    Joints multiple input links with an unique output link, it's not executable i.e. PassThrough=true.

    livediagram jointer

    Wire objects

    The wire connection objects are TLiveWire (Live wire), TLiveSideWire (Live side wire), TLiveArc (Live arc) and TLiveBezier (Live bezier). Other wire objects can be created, they behave the same way.

    The wire connections are "Vector" DiagramLines i.e. the target arrow is always explicit. They are connection aware, when a wire is not connected it's line appears dotted.

    When their SourceLinkpoint is connected to a Case block an unique integer value must be written in the text cell.

    livediagram wire

    Key Methods

    function Transition(Sender: TCustomLiveBlock): boolean
    This function fires the OnTransition event, returns false if the event is not assigned.

    Wires are not TCustomLiveBlock descendants, so the blocks that need to manage transition must call this function during their execution (see StateChart blocks implementation), Sender is the Block that requests the transition check.

    Key Events

    property OnTransition: TTransitionEvent = function(Sender: TCustomDiagramLine; FromBlock: TCustomLiveBlock): boolean
    Is the user event fired by the Transition Function. Sender is the Wire and FromBlock is the Block that called the function.

    Flowchart objects

    This set of objects (avaible in the LiveFlowChart.pas unit) allows the creation/execution of Flowcharts. The base rule implemented is that every block can have many inputs and only an output (except for decision and selection).

    The integer selector (case) and the error handler are not present in the base flowchart specification, they represent a power extension.

    The execution of a flowchart only depends on the blocks, the wires are only links.

    toolbar live flowchart

    From the left to right:

    • TLiveActionBlock (Action)

    • TLiveDecisionBlock (Decision)

    • TLiveCaseBlock (Case)

    • TLiveStartBlock (Start program)

    • TLiveEndBlock (End program)

    • TLiveErrorHandler (Error handler)

    • TLiveHeader (Header)

    TLiveActionBlock (Action block)

    Is the main live executable block, it inherits from TCustomLiveBlock. PassThrough property is false and OnExecute event is published.

    Key Properties

    ActionShape: TActionShape = (asBox, asAlternate, asData, asDocument, asInput, asSubRoutine)
    It's only a cosmetic property, it can be changed at runtime without loosing the linkpoints information i.e. the wires connected remain valid.

    livediagram actions

    TLiveDecisionBlock (Decision)

    Performs the decision of flowchart, it inherits from TCustomLiveBlock. PassThrough property is false and OnExecute event is published. The Decision variable in the OnExecute method tells the digram if the decision was false (value 0) or true (value different from 0).

    Key Properties

    DecisionShape: TDecisionShape = (dsBottomRight, dsRightBottom, dsLeftRight, dsRightLeft, dsBottomLeft, dsLeftBottom)
    It's only a cosmetic property but is very useful to have nice diagrams, it can be changed at runtime without loosing the linkpoints information i.e. the wires connected remain valid.

    livediagram decision

    TLiveCaseBlock (Case)

    Performs an integer selection (called case in more programming languages). It inherits from TCustomLiveBlock. PassThrough is false and OnExecute event is published. The next block executed depends of the integer value of parameter Decision of OnExecute event. If no case was matched, the block connected to ELSE output will be executed. Many wires can be connected to case output, and the chosen wire will be the one which text (caption) is the same as the number returned in the Decision parameter of OnExecute event.

    Key Properties

    CaseShape: TCaseShape = (csBottomRight, csBottomLeft)
    It's the cosmetic property that allows different orientation of the block, it can be changed at runtime without loosing the linkpoints information i.e. the wires connected remain valid.

    livediagram case

    TLiveStartBlock (Start program)

    It's the start point of the program, it's executable and can be executed once, so usually should contain initialization code.

    Must be always present and must be unique. The text "START" can be freely edited.

    livediagram start end

    TLiveEndBlock (End program)

    It's the endpoint of the program, it's executable and can be executed once, so usually should contain deinitialization code.

    Can be absent. The text "END" can be freely edited.

    livediagram start end

    TLiveErrorHandler (Error handler)

    It's an asynchronous block, it's executed when a block exits with Error > 0.
    It has no input, if it's Next is assigned the execution continues there, otherwise is performed an implicit "resume next", i.e. is executed the next block in the chain.
    Error handler can be absent, but if present must be unique. To avoid loop it must reset the error variable. The text "OnError" can be free edited.

    For historical reasons, the Error handler doesn't exists in the traditional flowchart component set, it creates a "not structured" point in the diagram.
    Its use should be limited to error handling, use the decision for normal branch.

    livediagram error fixed
    Fixed output


    livediagram error resume
    Resume next

    TLiveHeader (Header)

    It's just a container and is not executable.

    State chart objects

    This set of objects allows the creation/execution of Statecharts. The base rule implemented is that every block can have many inputs and many outputs.

    The execution of a statechart depends on the blocks and on the wires which are named transitions here, important examples of state diagrams are Petri's Net and Grafcet.

    In this implementation the Transition method of wires is used, an extension could be possible to write a specialized block (TLiveStateTransition for example) to accomplish the shift check.

    Since they are descendant of TCustomLiveBlock, the States blocks also have the Execute method.

    The base class for all state blocks is the TCustomLiveState class. All state blocks inherit from it and make use of its key properties.

    toolbar live statechart

    The avaiable state objects, from the left to right in the above picture, are:

    • TLiveStateBlock (State): It's the "usable" state block, it inherits from TCustomLiveState and only publishes some properties.

    • TLiveStateStart (Start state): It's the initial state in the chart i.e. it's the program start point. It accepts only an unique output link freely anchorable at any linkpoint, and there is no transition check i.e. the output link transition is always true.
      Its shape reflects the UML standard (a small circle).

    • TLiveStateEnd (End state): It's the program end. It accepts only input links, after it's execution the program terminates.
      Its shape reflects the UML standard (a small circle with a black inscribed solid circle).

    • TLiveStateError (Error state handler): It's the StateChart error handler. Since every state can have multiple outputs, here is not possible for the diagram to implement the "resume next" feature, so an output link must always be specified.
      This block accepts only an unique output link freely anchorable at any linkpoint.

    TCustomLiveState class

    It's the ancestor of all "state" components, it implements the design rules and the execution strategy. It inherits from TCustomLiveBlock.

    Key Properties

    OneShot: boolean
    Normally a state is active until a transition is satisfied, if OneShot = true the event OnExecute is fired once, otherwise it's execute before every transitions scan.

    StateShape: TStateShape = (ssCircle, ssSquare)
    It's the cosmetic property that allows different shapes of the block, it can be changed at runtime without loosing the linkpoints information i.e. the wires connected remain valid.

    livediagram stateshape

    Extending Live Diagram

    Due to its modular design, the extension of Live Diagram is quite simple. You should proceed through the following steps (after the reading the topics about the live diagram classes like TLiveDiagram, TCustomLiveBlock, flowchart blocks, statechart blocks and wires).

    An extension is a set of blocks that must implement design rules and execution strategies; this set, for design coherence should be contained in a separated file (LiveXXXXChart for example), writing it from scratch or inheriting it from an existing one.

    1. Set up design rules

    As said, they state how the blocks can be connected each other to form a "well formatted" chart.

    To do this, override the method TCustomLiveBlock.AcceptLink in order to reflect the rule during the design. The function Link must check the connections and must return true if everything (a design time) is ok, by default it pre-calculates the next block in the execution chain.

    Moreover there are some basic rules that are always checked directly by the diagram.

    • Every chart must contain a Start Block and it must be unique.

    • Every chart can contain an End Block, it's suggested but it's not mandatory.

    • Every chart can contain an unique Error Handler Block.

    2. Setup execution strategy

    After the execution, a block must provide the "next" block that must be executed, by default this was pre-calculated by the function Link. In certain cases (when the block has more then one output) the block must determine at runtime his successor in according to its internal status. For example, the decision block and the case block in the flowchart set override the DoExecute method to do this.

    Note that even though a block can have more than one output at design time, it must provide only one "next" at runtime.

    Note

    LiveChart requests only a well formatted diagram which is not automatically a structured diagram, especially if "case" blocks in flowchart are used (Search Böhm-Jacopini theorem on the Net for further information). Moreover the Diagram doesn't perform any "style check" - it's possible to insert in the same diagram flowchart blocks and statechart blocks.

    Live Diagram limitations

    • AutomaticNodes property doesn't affects the execution of the diagram but could generate confusion.
    In This Article
    Back to top TMS Diagram Studio v4.31
    © 2002 - 2025 tmssoftware.com