feat(market): OHLC hover readout on the candlestick chart
Candles had no hover (the line's close tooltip is gated off for them). Add a candle-aware readout: the candle under the cursor gets a column highlight + crosshair, and a small box shows its date and open/high/low/close (colored green up / red down). Verified via a forced-hover render (date + O/H/L/C over the highlighted candle). Line charts keep their existing single-price tooltip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1526,6 +1526,43 @@ static void mktDrawPriceChart(const MktCtx& cx)
|
||||
dl->AddRectFilled(ImVec2(xc - bodyW * 0.5f, bT), ImVec2(xc + bodyW * 0.5f, bB),
|
||||
WithAlpha(col, 230), 1.0f);
|
||||
}
|
||||
// Hover: highlight the candle under the cursor + an OHLC readout (date + open/high/low/close).
|
||||
ImVec2 mp = ImGui::GetIO().MousePos;
|
||||
if (mp.x >= plotLeft && mp.x <= plotRight && mp.y >= plotTop && mp.y <= plotBottom) {
|
||||
int hi = (int)((mp.x - plotLeft) / slotW);
|
||||
if (hi < 0) hi = 0;
|
||||
if (hi >= cn) hi = cn - 1;
|
||||
const auto& hc = candles[hi];
|
||||
const float hx = plotLeft + ((float)hi + 0.5f) * slotW;
|
||||
dl->AddRectFilled(ImVec2(hx - slotW * 0.5f, plotTop), ImVec2(hx + slotW * 0.5f, plotBottom),
|
||||
IM_COL32(255, 255, 255, 12));
|
||||
dl->AddLine(ImVec2(hx, plotTop), ImVec2(hx, plotBottom), IM_COL32(255, 255, 255, 45), 1.0f);
|
||||
char when[40] = "";
|
||||
std::time_t tt = hc.time;
|
||||
if (std::tm* tmv = std::localtime(&tt))
|
||||
std::strftime(when, sizeof(when), s_mkt.chartInterval <= 2 ? "%b %d %H:%M" : "%b %d, %Y", tmv);
|
||||
char l2[80], l3[80];
|
||||
snprintf(l2, sizeof(l2), "O %s H %s", FormatPrice(hc.open).c_str(), FormatPrice(hc.high).c_str());
|
||||
snprintf(l3, sizeof(l3), "L %s C %s", FormatPrice(hc.low).c_str(), FormatPrice(hc.close).c_str());
|
||||
const float lh = capFont->LegacySize;
|
||||
const float pad = Layout::spacingSm();
|
||||
const float gap = 3.0f * mktDp;
|
||||
float tw = std::max(capFont->CalcTextSizeA(lh, FLT_MAX, 0, when).x,
|
||||
std::max(capFont->CalcTextSizeA(lh, FLT_MAX, 0, l2).x,
|
||||
capFont->CalcTextSizeA(lh, FLT_MAX, 0, l3).x));
|
||||
float th = lh * 3 + gap * 2 + pad * 2;
|
||||
float tipX = hx + 10.0f * mktDp;
|
||||
if (tipX + tw + pad * 2 > plotRight) tipX = hx - tw - pad * 2 - 10.0f * mktDp;
|
||||
tipX = std::max(plotLeft, tipX);
|
||||
float tipY = plotTop + 4.0f * mktDp;
|
||||
ImVec2 tMin(tipX, tipY), tMax(tipX + tw + pad * 2, tipY + th);
|
||||
dl->AddRectFilled(tMin, tMax, IM_COL32(20, 20, 30, 235), 4.0f);
|
||||
dl->AddRect(tMin, tMax, IM_COL32(255, 255, 255, 30), 4.0f, 0, 1.0f);
|
||||
ImU32 cCol = (hc.close >= hc.open) ? Success() : Error();
|
||||
dl->AddText(capFont, lh, ImVec2(tipX + pad, tipY + pad), OnSurface(), when);
|
||||
dl->AddText(capFont, lh, ImVec2(tipX + pad, tipY + pad + lh + gap), cCol, l2);
|
||||
dl->AddText(capFont, lh, ImVec2(tipX + pad, tipY + pad + 2 * lh + 2 * gap), cCol, l3);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
float t = (n > 1) ? (float)i / (float)(n - 1) : 0.0f;
|
||||
|
||||
Reference in New Issue
Block a user