diff --git a/scwx-qt/source/scwx/qt/util/tooltip.cpp b/scwx-qt/source/scwx/qt/util/tooltip.cpp index fd1b7b0d..efe7c3dc 100644 --- a/scwx-qt/source/scwx/qt/util/tooltip.cpp +++ b/scwx-qt/source/scwx/qt/util/tooltip.cpp @@ -1,8 +1,13 @@ #include +#include #include #include #include +#include +#include +#include +#include namespace scwx { @@ -15,8 +20,42 @@ namespace tooltip static const std::string logPrefix_ = "scwx::qt::util::tooltip"; -void Show(const std::string& text, const QPointF& /* mouseGlobalPos */) +enum class TooltipMethod { + ImGui, + QToolTip, + QLabel +}; + +static TooltipMethod tooltipMethod_ = TooltipMethod::ImGui; + +static std::unique_ptr labelTooltip_ = nullptr; + +void Initialize() +{ + static bool initialized = false; + + if (initialized) + { + return; + } + + labelTooltip_ = std::make_unique(); + labelTooltip_->setWindowFlag(Qt::ToolTip); + labelTooltip_->setMargin(6); + labelTooltip_->setAttribute(Qt::WidgetAttribute::WA_TranslucentBackground); + labelTooltip_->setStyleSheet( + "background-color: rgba(15, 15, 15, 191);" + "border: 1px solid rgba(110, 110, 128, 128);" + "color: rgba(255, 255, 255, 204);"); + + initialized = true; +} + +void Show(const std::string& text, const QPointF& mouseGlobalPos) +{ + Initialize(); + std::size_t textWidth = static_cast( settings::TextSettings::Instance().hover_text_wrap().GetValue()); @@ -31,10 +70,108 @@ void Show(const std::string& text, const QPointF& /* mouseGlobalPos */) // when not wrapping) const std::string& displayText = (textWidth > 0) ? wrappedText : text; - util::ImGui::Instance().DrawTooltip(displayText); + if (tooltipMethod_ == TooltipMethod::ImGui) + { + util::ImGui::Instance().DrawTooltip(displayText); + } + else if (tooltipMethod_ == TooltipMethod::QToolTip) + { + static std::size_t id = 0; + QToolTip::showText( + mouseGlobalPos.toPoint(), + QString("%3") + .arg(++id) + .arg("Inconsolata") + .arg(QString::fromStdString(displayText).replace("\n", "
")), + nullptr, + {}, + std::numeric_limits::max()); + } + else if (tooltipMethod_ == TooltipMethod::QLabel) + { + // Get monospace font size + std::size_t fontSize = 16; + auto fontSizes = + manager::SettingsManager::general_settings().font_sizes().GetValue(); + if (fontSizes.size() > 1) + { + fontSize = fontSizes[1]; + } + else if (fontSizes.size() > 0) + { + fontSize = fontSizes[0]; + } + + // Configure the label + labelTooltip_->setFont( + QFont("Inconsolata", static_cast(std::round(fontSize * 0.72)))); + labelTooltip_->setText(QString::fromStdString(displayText)); + + // Get the screen the label will be displayed on + QScreen* screen = QGuiApplication::screenAt(mouseGlobalPos.toPoint()); + if (screen == nullptr) + { + screen = QGuiApplication::primaryScreen(); + } + + // Default offset for label + const QPoint offset {2, 24}; + + // Get starting label position (below and to the right) + QPoint p = mouseGlobalPos.toPoint() + offset; + + // Adjust position if necessary + const QRect r = screen->geometry(); + if (p.x() + labelTooltip_->width() > r.x() + r.width()) + { + // If the label extends beyond the right of the screen, move it left + p.rx() -= 4 + labelTooltip_->width(); + } + if (p.y() + labelTooltip_->height() > r.y() + r.height()) + { + // If the label extends beyond the bottom of the screen, move it up + p.ry() -= 24 + labelTooltip_->height(); + } + + // Clamp the label within the screen + if (p.y() < r.y()) + { + p.setY(r.y()); + } + if (p.x() + labelTooltip_->width() > r.x() + r.width()) + { + p.setX(r.x() + r.width() - labelTooltip_->width()); + } + if (p.x() < r.x()) + { + p.setX(r.x()); + } + if (p.y() + labelTooltip_->height() > r.y() + r.height()) + { + p.setY(r.y() + r.height() - labelTooltip_->height()); + } + + // Move the label to the calculated offset + labelTooltip_->move(p); + + // Show the label + if (labelTooltip_->isHidden()) + { + labelTooltip_->show(); + } + } } -void Hide() {} +void Hide() +{ + Initialize(); + + // TooltipMethod::QToolTip + QToolTip::hideText(); + + // TooltipMethod::QLabel + labelTooltip_->hide(); +} } // namespace tooltip } // namespace util