DearMQL5/Core/UEventQueue.mqh
Alex David Hernandez Maturrano 78e7ae5145 feat: initial release of DearMQL5 v1.0.0 - Immediate-Mode GUI Engine for MetaTrader 5
DearMQL5 is an institutional-grade, immediate-mode graphical user interface
(GUI) engine designed from the ground up for MetaTrader 5 (MQL5), inspired by
the ergonomics and performance of Dear ImGui.

### Core Architecture & Execution Pipeline
- Immediate-Mode Paradigm: Declarative frame-based rendering pipeline with zero
  memory allocation churn during render loops and deterministic execution.
- Modular Per-Hub Canvas Surfaces (CUWindowSurface): Replaces full-screen canvas
  overlays with isolated, window-bounded CCanvas bitmaps, reducing memory usage
  by up to 93% (~570 KB vs 8.3 MB for 1080p) and preventing click-swallowing.
- 0-Cost Hardware Texture Drag Engine: Absolute-anchor drag mechanics update
  native MT5 OBJPROP_XDISTANCE and OBJPROP_YDISTANCE properties directly on
  the compositor, bypassing CPU rasterization completely (0.00% CPU usage).
- Chart Scroll Protection: Automatically suppresses chart history sliding
  (CHART_MOUSE_SCROLL) during active HUD dragging and safely restores it on release.
- Two-Phase Hit-Testing: Interactive controls (buttons, sliders, toggles) receive
  first-priority click focus, cleanly separating widget actions from window drags.

### Subsystems & Components
- Core State & Input (Core/):
  * UInputState: Mouse/keyboard tracking, deltas, and chart scroll lock.
  * UState: Retained state hash map in pure MQL5 with 64-bit FNV-1a hashing.
  * UIdStack: Hierarchical identifier scoping preventing widget ID collisions.
  * ULayout: Automatic cursor placement supporting SameLine, Indent, and Unindent.
  * UEventQueue: Non-blocking circular UI event queue for decoupled handling.
  * UTheme: Institutional OneDark/Nord dark color palette and typography metrics.
- Rendering Backends (Render/):
  * URendererCanvas: Isolated per-hub surfaces with 32-bit ARGB alpha transparency.
  * URendererNative: Native MT5 object pool (OBJ_RECTANGLE_LABEL) with diff caching.
  * UFont: Anti-aliased font metrics and width cache.
- Complete Widget Suite (Widgets/):
  * UButton: Click-on-release standard, accent, and emergency panic buttons.
  * UToggle: Smooth draggable/clickable iOS-style toggle switches.
  * USlider: Draggable horizontal float and integer sliders.
  * UProgressBar: Adaptive progress bars with dynamic green->amber->red color ramps.
  * UHeader: Collapsible section headers with immediate-mode state retention.
  * ULabel & USeparator: Formatted text, colored metrics, and horizontal dividers.
- Window Management (Windows/):
  * UWindow: Window container with titlebar, collapse toggle, and coordinate clipping.
  * UWindowManager: Multi-window coordinator with GlobalVariable persistence across
    chart timeframe changes and backward-compatible key resolution.

### Tooling, Documentation & Reference Implementation
- Examples/EA_DearMQL5_Demo.mq5: Complete reference Prop-Firm cockpit HUD.
- README.md: Comprehensive institutional English documentation for GitHub and Algo Forge.
- Docs/ARCHITECTURE.md: Technical architecture specification with Mermaid lifecycle.
2026-10-12 08:35:18 -03:00

88 righe
2,5 KiB
MQL5

//+------------------------------------------------------------------+
//| UEventQueue.mqh |
//| Copyright 2026, DearMQL5 GUI Engine |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, DearMQL5 GUI Engine"
#property link "https://www.mql5.com"
#property strict
/// Event types generated by DearMQL5 widgets.
enum ENUM_U_EVENT_TYPE
{
U_EVENT_NONE = 0,
U_EVENT_CLICK = 1,
U_EVENT_VALUE_CHANGE= 2,
U_EVENT_SUBMIT = 3,
U_EVENT_DRAG = 4
};
/// Discrete GUI event packet.
struct SUIEvent
{
ENUM_U_EVENT_TYPE type; ///< Category of event
ulong widget_id; ///< FNV-1a hash of source widget
double float_value; ///< Numeric payload (slider values, etc.)
string string_value; ///< Textual payload (edit boxes, etc.)
};
/// Circular event buffer for decoupling widget interaction from consumer code.
class UEventQueue
{
private:
static SUIEvent s_queue[64];
static int s_head;
static int s_tail;
static int s_count;
public:
/// Resets the event queue.
static void Clear(void)
{
s_head = 0;
s_tail = 0;
s_count = 0;
}
/// Pushes an event to the queue.
static bool Push(const ENUM_U_EVENT_TYPE type,
const ulong widget_id,
const double float_val = 0.0,
const string str_val = "")
{
if(s_count >= 64)
return(false); // Buffer full
s_queue[s_tail].type = type;
s_queue[s_tail].widget_id = widget_id;
s_queue[s_tail].float_value = float_val;
s_queue[s_tail].string_value = str_val;
s_tail = (s_tail + 1) % 64;
s_count++;
return(true);
}
/// Pops the next event from the queue. Returns false if queue is empty.
static bool Pop(SUIEvent &event)
{
if(s_count <= 0)
return(false);
event = s_queue[s_head];
s_head = (s_head + 1) % 64;
s_count--;
return(true);
}
/// Returns whether there are pending events in the queue.
static bool HasEvents(void)
{
return(s_count > 0);
}
};
SUIEvent UEventQueue::s_queue[64];
int UEventQueue::s_head = 0;
int UEventQueue::s_tail = 0;
int UEventQueue::s_count = 0;