// tooltip — pure implementation. See tooltip.h. NO REAPER / SWELL / LICE / vendor. #include "tooltip.h" namespace reasampler { std::string stripActionPrefix(const std::string& fullName, const std::string& prefix) { if (prefix.empty()) return fullName; if (fullName.size() >= prefix.size() && fullName.compare(0, prefix.size(), prefix) == 0) return fullName.substr(prefix.size()); return fullName; } TooltipBox computeTooltip(int anchorX, int anchorY, int anchorW, int anchorH, int textW, int textH, int clientW, int clientH, const TooltipSpec& spec) { TooltipBox box; if (textW <= 0 || textH <= 0 || clientW <= 0 || clientH <= 0) return box; // Clamp boxW so it never exceeds the available client span; then clamp x so the (possibly // reduced) box always sits within [margin, clientW - margin]. const int maxBoxW = clientW - 2 * spec.margin; const int boxW = (textW + 2 * spec.padX < maxBoxW) ? textW + 2 * spec.padX : maxBoxW; const int boxH = textH + 2 * spec.padY; // Horizontal: centre on the anchor, then clamp within [margin, clientW - margin - boxW]. int x = anchorX + (anchorW - boxW) / 2; const int maxX = clientW - spec.margin - boxW; if (x > maxX) x = maxX; if (x < spec.margin) x = spec.margin; // Vertical: prefer BELOW the anchor; flip ABOVE if it would clip the bottom edge. int y = anchorY + anchorH + spec.gap; if (y + boxH > clientH - spec.margin) { const int above = anchorY - spec.gap - boxH; if (above >= spec.margin) { y = above; // fits above — flip } else { // Fits neither cleanly (tall tooltip / short client): clamp to the bottom margin. const int maxY = clientH - spec.margin - boxH; y = maxY < spec.margin ? spec.margin : maxY; } } box.x = x; box.y = y; box.width = boxW; box.height = boxH; return box; } } // namespace reasampler