APIC – Operator Graphical Interface (OGI) development

Operator Graphical Interface (OGI) application manual for developers

UI application development

APIC OGI uses AvaloniaUI platform for it cross platform user interface applications, the UI applications communicate with the Core-Engine application via events and the LRUs share memory infrastructure.

See also: How to Build an APIC System for Software Engineers for where building the (optional) OGI application fits into the overall system-engineering workflow.
Scope of this guide: it covers adding a control to an existing OGI Avalonia project's AXAML - not scaffolding a brand-new GUI application from an empty folder. An OGI GUI project is a real, standalone Avalonia .NET desktop application (its own .csproj, a standard Avalonia Program.cs/App.axaml entry point, and a MainWindow.axaml/.axaml.cs pair) that connects to a running CoreEngine externally - it is not compiled into CoreEngine itself. Start from an existing OGI project as a template rather than generating this scaffolding from scratch. There is no ICoreEngineApi interface and no C# class ever derives from CModelBase - Models are exclusively C++ and are a completely separate context from the GUI application (see the CoreEngine framework development guide).

axaml File anatomy

Example of AvaloniaUI control snippet

	<ProgressBar x:Name="ControlName"
		Minimum="{sim:SimBinding UI.OGI.ProgressMin}" 
		Maximum="{sim:SimBinding UI.OGI.ProgressMax}"
		Value="{sim:SimBinding UI.OGI.ProgressPos}"
		Height="10" Margin="0 10 0 0">
        <ProgressBar.Tag>
            [Tag Data goes here (See below)]
        </ProgressBar.Tag>
	</ProgressBar>
            

Key Features

Note: A control must have an x:Name assigned. Without it, the UI parser will ignore and omit that control.

Example of AvaloniaUI control TAG

        TAG data:
            [notify{mouse};]
            type{button | toggle | tab | check | imagebutton | stateImage | image};
            [group{all buttons name participate in the group including this one};]     //Only for type=check
            states{
            1=.\Bitmaps\btn-new_enable.bmp, 1(hot)=.\Bitmaps\btn-new_hot.bmp,
            2=.\Bitmaps\btn-new_selected.bmp, 2(hot)=.\Bitmaps\btn-new_selectedhot.bmp,
            3=.\Bitmaps\btn-new_disable.bmp, 3(hot)=.\Bitmaps\btn-new_disableHot.bmp,
            4="Text", 4(hot)="TextHot",
            5=#controlName, 4(hot)=#controlName,
            enable=1, click=2, notclick=1[checkbox only], disable=3, MouseLeftButtonDown=2};           //named state
            [defaultState={any state above or empty to hide the control};]        //the default state and visibility on startup
            [
            statesMachine{MouseLeftButtonDown:1=2,2=3,3=1|
            MouseRightButtonDown:1=2,2=3,3=1 |
            MouseEnter: ... |
            MouseLeave: ... |
            MouseLeftButtonUp: ... |
            MouseRightButtonUp: ...
            };
            ]
            

TAG Data Specification

Defines how the control changes state and handle events.

1. Notifications

[notify{mouse};]

Enables mouse-based notifications for this control.
Notifications are send to the Core-Engine App.

2. Control Type

type{button | toggle | tab | check | imagebutton | stateImage | image | progressbar};

Defines how the control behaves visually and functionally.

3. Group (checkbox only)

[group{all buttons name participate in the group including this one};]

Groups check-type controls together.

4. States

states{
    1 = .\Bitmaps\btn-new_enable.bmp,
    1(hot) = .\Bitmaps\btn-new_hot.bmp,

    2 = .\Bitmaps\btn-new_selected.bmp,
    2(hot) = .\Bitmaps\btn-new_selectedhot.bmp,

    3 = .\Bitmaps\btn-new_disable.bmp,
    3(hot) = .\Bitmaps\btn-new_disableHot.bmp,

    4 = "Text",
    4(hot) = "TextHot",

    5 = #controlName,
    5(hot) = #controlName,

    enable = 1,
    click = 2,
    notclick = 1,
    disable = 3,
    MouseLeftButtonDown = 2
};

Defines images, text, or references to use for each visual state.

5. Default State

[defaultState={stateName or empty}];

Sets the initial state or hides the control if empty.

6. State Machine

statesMachine{
    MouseLeftButtonDown: 1=2, 2=3, 3=1 |
    MouseRightButtonDown: 1=2, 2=3, 3=1 |
    MouseEnter: ... |
    MouseLeave: ... |
    MouseLeftButtonUp: ... |
    MouseRightButtonUp: ...
};

States defined by content assigned to numeric value which represents the state ID
States content can be image or text.

C++ Code behind anatomy

Auto-generated files vs. what you write

Running the OGI application against your AXAML regenerates exactly 2 files - do not hand-edit these, your changes are overwritten on the next run:

You write one more pair of files yourself, not regenerated, named after your project (e.g. OGIROMAH.h / OGIROMAH.cpp for a project called ROMAH):

Note: there is no Model involved anywhere in this pattern. The class you write derives from COGICmdTarget, not the Model base class (CModelBase) used elsewhere in CoreEngine development - OGI event handling is its own, separate context.