Skip to content
ModernUI A DaneTrades developer library

Ownership and Lifetime

MQL5 does not have automatic garbage collection.

ModernUI keeps the model simple:

Pseudo-code
Root owns the root UI tree.
Containers own their child controls.
Some handlers/sources are owned; some are not.
Shutdown tears down the normal UI tree.

When in doubt, check the specific API.

Root lifetime

Declare the root globally or at EA scope.

Reference excerpt
MuiRoot g_ui;

Initialise it in OnInit and shut it down in OnDeinit.

Reference excerpt
int OnInit()
{
  if(!g_ui.Init(ChartID(),0,"MyUI_",512,16))
    return(INIT_FAILED);

  return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
  g_ui.Shutdown();
}

Container ownership

Controls added to a container are owned by that container.

UI build fragment
MuiPanel *panel=new MuiPanel();
parent.Add(panel);

When the parent/tree is destroyed, child controls are destroyed as part of the tree.

Fast wrapper ownership

Fast wrappers generally create controls and add them to the supplied parent.

Returned structs are handles, not separate ownership.

UI build fragment
MuiSection section=Mui::Section(app.content,"Settings","");
MuiLabeledSpinEdit risk=Mui::LabeledSpinEdit(section.body,"Risk %",0.1,10.0,0.1,1.0);

The section and risk field live inside the UI tree. The returned structs let you access the pieces.

Handler ownership

Handler ownership varies.

Owned handler example:

Correct
button.SetHandler(new SaveHandler());

Non-owned handler example:

Correct
static MySelectionHandler s_handler;
table.SetSelectionChangedHandler(&s_handler);

Do not assume all handlers are owned or all handlers are non-owned.

Known handler patterns

Area Ownership pattern
MuiButtonAction::SetHandler Owned
ButtonRow button handlers Owned by each button
ButtonGroup internal pick handlers Owned by each button
Selection/list/tree/table intent handlers Not owned
MuiTabs::SetHandler(MuiTabChangedHandler*) Owned
MuiTabs::SetTabChangedHandler(...) Not owned
MuiAccordion per-item SetOnToggle Owned
MuiAccordion::SetExpandedChangedHandler Not owned
Combo SetHandler(MuiComboItemHandler*) Owned
MuiComboBoxHost::SetSelectionChangedHandler Not owned
Dropdown SetMenuHandler Owned
MuiDropdown::SetSelectionChangedHandler Not owned
Date SetHandler(MuiDateChangedHandler*) Owned
MuiDatePicker::SetDateChangedHandler(...) Not owned
Dialog SetResultHandler Not owned
Drawer SetStateChangedHandler Not owned

Source ownership

List/table/tree controls usually reference sources without owning them.

For examples, static sources are common:

UI build fragment
static MyTableSource source;
MuiTableView *table=Mui::TableView(parent,&source,520.0,260.0);

For heap sources, keep a clear owner and do not delete the source while the view uses it.

Simple helpers with sources

Mui::ListBox and Mui::SimpleTable allocate simple backing sources and expose the pointers.

Keep the wrapper value or source pointer if you plan to update rows.

UI build fragment
MuiSimpleTable table=Mui::SimpleTable(parent,headers,4,0.0,180.0,true,true);
table.SetCell(0,0,"Started");

Native input hosts

Text boxes and text areas may create native chart objects.

g_ui.Shutdown() is important because it lets hosts remove those chart objects cleanly.

Common mistakes

Passing stack handlers into owned APIs

Avoid:

Incorrect
SaveHandler h;
button.SetHandler(&h);

Deleting controls owned by a container

If you added a control to a container, do not manually delete it unless the API explicitly says to remove/take ownership.

Deleting source objects too early

If a list/table references a source, the source must stay alive.

Treating returned wrapper structs as owners

Wrapper structs are access handles. They are not separate owners of the UI tree.

Related pages