feat: add C++ ImGui functions for core UI and visualization
Funciones C++/ImGui para dashboards (grid, panel, docking, sidebar, tabs), visualizaciones (candlestick, gauge, histogram, pie, sparkline, heatmap, scatter, line, bar, surface3d, kpi, table), grafos (force layout, renderer, viewport, spatial hash, types) y utilidades (time series buffer, tracy zones, memory/fps overlay, plot theme). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
#include "viz/candlestick.h"
|
||||
#include "imgui.h"
|
||||
#include "implot.h"
|
||||
|
||||
void candlestick(const char* title, const double* dates, const double* opens,
|
||||
const double* closes, const double* lows, const double* highs,
|
||||
int count, float width_percent, bool tooltip) {
|
||||
if (count <= 0) return;
|
||||
|
||||
// Compute half-width of each candle body in data coordinates.
|
||||
// Use spacing between consecutive dates when count > 1, else fallback to 0.5.
|
||||
double spacing = (count > 1) ? (dates[1] - dates[0]) : 1.0;
|
||||
double half_w = spacing * (double)width_percent * 0.5;
|
||||
|
||||
ImPlot::SetupAxes("Date", "Price", ImPlotAxisFlags_None, ImPlotAxisFlags_AutoFit);
|
||||
ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);
|
||||
|
||||
// Auto-fit X axis to the data range with a small margin.
|
||||
ImPlot::SetupAxisLimits(ImAxis_X1,
|
||||
dates[0] - spacing,
|
||||
dates[count - 1] + spacing,
|
||||
ImGuiCond_Always);
|
||||
|
||||
if (ImPlot::BeginPlot(title, ImVec2(-1, 0))) {
|
||||
ImDrawList* draw = ImPlot::GetPlotDrawList();
|
||||
|
||||
const ImU32 col_bull = IM_COL32(0, 200, 80, 255); // green — close >= open
|
||||
const ImU32 col_bear = IM_COL32(220, 50, 50, 255); // red — close < open
|
||||
|
||||
int hovered_idx = -1;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
double x = dates[i];
|
||||
double open = opens[i];
|
||||
double close = closes[i];
|
||||
double low = lows[i];
|
||||
double high = highs[i];
|
||||
|
||||
bool bullish = (close >= open);
|
||||
ImU32 col = bullish ? col_bull : col_bear;
|
||||
|
||||
// Convert data coordinates to screen pixels.
|
||||
ImVec2 body_tl = ImPlot::PlotToPixels(x - half_w, bullish ? close : open);
|
||||
ImVec2 body_br = ImPlot::PlotToPixels(x + half_w, bullish ? open : close);
|
||||
ImVec2 wick_hi = ImPlot::PlotToPixels(x, high);
|
||||
ImVec2 wick_lo = ImPlot::PlotToPixels(x, low);
|
||||
float cx = (body_tl.x + body_br.x) * 0.5f;
|
||||
|
||||
// Wick (high-low vertical line).
|
||||
draw->AddLine(ImVec2(cx, wick_hi.y), ImVec2(cx, wick_lo.y), col, 1.5f);
|
||||
|
||||
// Body rectangle (open-close).
|
||||
// Ensure at least 1px height so flat candles are visible.
|
||||
if (body_br.y <= body_tl.y + 1.0f) body_br.y = body_tl.y + 1.0f;
|
||||
draw->AddRectFilled(body_tl, body_br, col);
|
||||
draw->AddRect(body_tl, body_br, col);
|
||||
|
||||
// Track hovered candle for tooltip.
|
||||
if (tooltip && ImPlot::IsPlotHovered()) {
|
||||
ImVec2 mouse = ImGui::GetMousePos();
|
||||
if (mouse.x >= body_tl.x - 4 && mouse.x <= body_br.x + 4 &&
|
||||
mouse.y >= wick_hi.y - 4 && mouse.y <= wick_lo.y + 4) {
|
||||
hovered_idx = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tooltip for the hovered candle.
|
||||
if (tooltip && hovered_idx >= 0) {
|
||||
int i = hovered_idx;
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("O: %.4f", opens[i]);
|
||||
ImGui::Text("H: %.4f", highs[i]);
|
||||
ImGui::Text("L: %.4f", lows[i]);
|
||||
ImGui::Text("C: %.4f", closes[i]);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user