Event Bus
The ModernUI event bus is the recommended way to handle normal EA UI actions.
Instead of writing one handler class for every button, checkbox, spin edit, table, tab, dialog, or drawer, you:
- make your panel class inherit
MuiEventSink - connect it with
m_ui.SetEventSink(...) - assign
.Id(...)to interactive controls - handle events in one typed
OnMuiEvent(...)method
Basic Pattern
class CMyPanel : public MuiEventSink
{
private:
MuiRoot m_ui;
MuiButtonAction *m_bSave;
public:
virtual void OnMuiEvent(MuiRoot &root,const MuiEventData &event);
};
Connect the sink after root initialisation:
if(!m_ui.Init(ChartID(),0,"MyPanel_",512,16))
return INIT_FAILED;
m_ui.SetEventSink((MuiEventSink*)GetPointer(this));
Create controls and assign IDs:
m_bSave=Mui::ButtonPrimary(parent,"Save");
m_bSave.Id(APP_ACTION_SAVE);
Route events centrally:
void CMyPanel::OnMuiEvent(MuiRoot &root,const MuiEventData &event)
{
if(event.EventId()==MUI_EVENT_CLICK && event.ControlId()==APP_ACTION_SAVE)
Save(root);
}
Control IDs
A control only emits app-level events when it has a non-negative ID.
m_bBuy.Id(TP_ACTION_BUY);
m_seRisk.Id(TP_ACTION_INPUT_CHANGED);
m_cbConfirm.Id(TP_ACTION_CONFIRM_TRADES);
m_tvPositions.Id(TP_ACTION_POSITIONS_TABLE);
Use enums instead of raw numbers.
enum TRADE_PANEL_ACTION
{
TP_ACTION_BUY,
TP_ACTION_SELL,
TP_ACTION_INPUT_CHANGED,
TP_ACTION_CONFIRM_TRADES,
TP_ACTION_POSITIONS_TABLE
};
MuiEventData Fields
MuiEventData is the typed payload received by OnMuiEvent(...).
| Field | Meaning |
|---|---|
event.EventId() |
Which event happened, such as MUI_EVENT_CLICK. |
event.Sender() |
The control that emitted the event. Use when you need control-specific data. |
event.Is(control) |
Convenience check for event.Sender()==control. |
event.ControlId() |
The ID assigned with .Id(...). This is usually your main routing key. |
event.Value() |
Numeric payload. Kept for compatibility and simple numeric controls. |
event.Text() |
Text payload, such as button text, selected item text, column name, or result ID. |
event.Index() |
New selected index, clicked item index, tab index, table column index, or action index. |
event.OldIndex() |
Previous selected index for controls that track it. |
event.Row() |
Table row or selected row. |
event.Col() |
Table column. |
event.Checked() |
Checkbox, toggle, or confirm boolean. |
event.Expanded() |
Drawer or accordion expanded/open state. |
event.Date() |
Selected date from a date picker. |
event.Argb() |
Selected ARGB color or first button ARGB payload. |
event.CommandId() |
Toolbar command ID. |
Standard UI Events
These are the app-level events EA authors normally handle.
| Event | Emitted by | Main fields |
|---|---|---|
MUI_EVENT_CLICK |
Buttons and icon buttons | ControlId(), Value(), Text(), Argb(), Sender() |
MUI_EVENT_VALUE_CHANGED |
Spin edits and sliders | ControlId(), Value(), Text() |
MUI_EVENT_CHECK_CHANGED |
Checkboxes and toggles | ControlId(), Checked(), Value(), Text() |
MUI_EVENT_DIALOG_RESULT |
Dialog result buttons, close button, scrim dismiss when enabled | ControlId(), Text() |
MUI_EVENT_CONFIRM |
Confirm dialogs | ControlId(), Checked(), Value() |
MUI_EVENT_DRAWER_STATE |
Drawers | ControlId(), Expanded(), Value() |
MUI_EVENT_SELECTION_CHANGED |
List views, combo boxes, dropdown menus, radio groups, table selection, tree selection | ControlId(), Index(), OldIndex(), Row(), Text() |
MUI_EVENT_ITEM_CLICK |
Table rows and tree items | ControlId(), Index(), Row(), Text() |
MUI_EVENT_ITEM_DOUBLE_CLICK |
Tree items | ControlId(), Index(), Text() |
MUI_EVENT_TABLE_CELL_CLICK |
Table cells | ControlId(), Row(), Col(), Text() |
MUI_EVENT_TABLE_CELL_DOUBLE_CLICK |
Table cells | ControlId(), Row(), Col(), Text() |
MUI_EVENT_TABLE_HEADER_CLICK |
Table headers | ControlId(), Index(), Col(), Text() |
MUI_EVENT_EXPANDED_CHANGED |
Accordions and tree expand/collapse | ControlId(), Index(), Expanded(), Text() |
MUI_EVENT_TAB_CHANGED |
Tabs | ControlId(), Index(), OldIndex(), Text() |
MUI_EVENT_DATE_CHANGED |
Date picker | ControlId(), Date(), Value(), Text() |
MUI_EVENT_COLOR_CHANGED |
Color picker committed value | ControlId(), Argb(), Value() |
MUI_EVENT_COLOR_PREVIEW_CHANGED |
Color picker preview while editing | ControlId(), Argb(), Value() |
MUI_EVENT_TOOLBAR_COMMAND |
Toolbar buttons | ControlId(), CommandId(), Value(), Text() |
MUI_EVENT_MENU_ITEM |
Context menu item picks | ControlId(), Index(), Text() |
MUI_EVENT_ALERT_ACTION |
Alert banner action button | ControlId(), Text() |
MUI_EVENT_ALERT_DISMISSED |
Alert banner dismiss button | ControlId(), Text() |
MUI_EVENT_CARD_ACTION |
Card header action icons | ControlId(), Index(), Text(), Argb() |
Controls reference by event
| Event | Detailed control docs |
|---|---|
MUI_EVENT_CLICK |
Buttons |
MUI_EVENT_VALUE_CHANGED |
Spin edit, Slider |
MUI_EVENT_CHECK_CHANGED |
Checkbox, Toggle |
MUI_EVENT_SELECTION_CHANGED |
Combo, Radio, List, Table, Tree, Dropdown |
MUI_EVENT_ITEM_CLICK / ITEM_DOUBLE_CLICK |
Table, Tree |
MUI_EVENT_TABLE_* |
Table view |
MUI_EVENT_TAB_CHANGED |
Tabs |
MUI_EVENT_EXPANDED_CHANGED |
Accordion, Tree |
MUI_EVENT_DIALOG_RESULT / CONFIRM |
Dialog, Modal |
MUI_EVENT_DRAWER_STATE |
Drawer |
MUI_EVENT_DATE_CHANGED / COLOR_* |
Date picker, Color picker |
MUI_EVENT_TOOLBAR_COMMAND |
Toolbar |
MUI_EVENT_MENU_ITEM |
Menu, Context menu |
MUI_EVENT_ALERT_* |
Alert banner |
MUI_EVENT_CARD_ACTION |
Card |
Low-level pointer and keyboard events such as MUI_EVENT_MOUSE_MOVE, MUI_EVENT_MOUSE_DOWN, MUI_EVENT_KEY_DOWN, and MUI_EVENT_WHEEL are internal router events. Normal EAs should usually handle the app-level events above instead.
Common Routing Examples
Button clicks:
if(event.EventId()==MUI_EVENT_CLICK)
{
if(event.ControlId()==TP_ACTION_BUY)
OnBuy(root);
else if(event.ControlId()==TP_ACTION_SELL)
OnSell(root);
return;
}
Spin edits and sliders:
if(event.EventId()==MUI_EVENT_VALUE_CHANGED && event.ControlId()==TP_ACTION_RISK)
{
m_riskPct=event.Value();
Recalculate();
root.RefreshAll();
return;
}
Checkboxes and toggles:
if(event.EventId()==MUI_EVENT_CHECK_CHANGED && event.ControlId()==TP_ACTION_CONFIRM_TRADES)
{
m_confirmBeforeTrade=event.Checked();
return;
}
List, combo, dropdown, and radio selection:
if(event.EventId()==MUI_EVENT_SELECTION_CHANGED && event.ControlId()==APP_ACTION_PROFILE)
{
m_profileIndex=event.Index();
m_profileName=event.Text();
root.RefreshAll();
return;
}
Table interaction:
if(event.EventId()==MUI_EVENT_TABLE_CELL_CLICK && event.ControlId()==APP_ACTION_POSITIONS)
{
int row=event.Row();
int col=event.Col();
string cellText=event.Text();
InspectCell(row,col,cellText);
return;
}
Tabs:
if(event.EventId()==MUI_EVENT_TAB_CHANGED && event.ControlId()==APP_ACTION_MAIN_TABS)
{
m_activeTab=event.Index();
AddLog("Tab: "+event.Text());
return;
}
Dialogs and confirms:
if(event.EventId()==MUI_EVENT_DIALOG_RESULT && event.ControlId()==APP_ACTION_CONFIRM_CLOSE)
AddLog("Dialog result: "+event.Text());
if(event.EventId()==MUI_EVENT_CONFIRM && event.ControlId()==APP_ACTION_CONFIRM_CLOSE)
{
if(event.Checked())
ClosePosition();
return;
}
Drawers and accordions:
if(event.EventId()==MUI_EVENT_DRAWER_STATE && event.ControlId()==APP_ACTION_SETTINGS_DRAWER)
AddLog(event.Expanded() ? "Settings opened" : "Settings closed");
if(event.EventId()==MUI_EVENT_EXPANDED_CHANGED && event.ControlId()==APP_ACTION_FILTERS)
AddLog(event.Text()+" expanded="+(event.Expanded() ? "true" : "false"));
Color picker:
if(event.EventId()==MUI_EVENT_COLOR_CHANGED && event.ControlId()==APP_ACTION_ACCENT)
{
ApplyAccent(event.Argb());
root.RefreshAll();
return;
}
Toolbar commands:
if(event.EventId()==MUI_EVENT_TOOLBAR_COMMAND)
{
if(event.CommandId()=="refresh")
RefreshData(root);
else if(event.CommandId()=="export")
ExportSnapshot(root);
return;
}
Button Payloads
Buttons can carry a numeric payload with UserValue(...).
MuiButtonAction *bRisk1=Mui::Button(parent,"1%");
bRisk1.Id(TP_ACTION_RISK_PRESET);
bRisk1.UserValue(1.0);
Read it with event.Value():
if(event.EventId()==MUI_EVENT_CLICK && event.ControlId()==TP_ACTION_RISK_PRESET)
SetRisk(event.Value());
Buttons can also carry two ARGB values with UserArgb(...).
MuiButtonAction *bBlue=Mui::Button(parent,"Blue");
bBlue.Id(TP_ACTION_ACCENT);
bBlue.UserArgb(0xFF2F6FED,0xFF3AA0FF);
event.Argb() contains the first ARGB value. Use event.Sender() when you need both:
if(event.EventId()==MUI_EVENT_CLICK && event.ControlId()==TP_ACTION_ACCENT)
{
MuiElement *sender=event.Sender();
if(sender!=NULL)
ApplyAccent(sender.UserArgb1(),sender.UserArgb2());
}
Event Bus vs Low-Level Handlers
Use the event bus for normal EA code.
Low-level handlers still exist for advanced library work, custom reusable controls, and compatibility with older examples. They are no longer the recommended first pattern for application-level EA panels.