diff --git a/src/app/ui/skin/skin_theme.cpp b/src/app/ui/skin/skin_theme.cpp index 645eb3535..572bc0637 100644 --- a/src/app/ui/skin/skin_theme.cpp +++ b/src/app/ui/skin/skin_theme.cpp @@ -1660,7 +1660,7 @@ void SkinTheme::paintTooltip(PaintEvent& ev) she::Surface* sw = tooltipPart->bitmapSW(); she::Surface* w = tooltipPart->bitmapW(); - switch (widget->getArrowAlign()) { + switch (widget->arrowAlign()) { case TOP | LEFT: nw = parts.tooltipArrow()->bitmapNW(); break; case TOP | RIGHT: ne = parts.tooltipArrow()->bitmapNE(); break; case BOTTOM | LEFT: sw = parts.tooltipArrow()->bitmapSW(); break; @@ -1675,7 +1675,7 @@ void SkinTheme::paintTooltip(PaintEvent& ev) target = target.createIntersection(gfx::Rect(0, 0, ui::display_w(), ui::display_h())); target.offset(-absRc.origin()); - switch (widget->getArrowAlign()) { + switch (widget->arrowAlign()) { case TOP: arrow = parts.tooltipArrow()->bitmapN(); g->drawRgbaSurface(arrow, diff --git a/src/app/ui/status_bar.cpp b/src/app/ui/status_bar.cpp index 03921d4f8..e82349aa7 100644 --- a/src/app/ui/status_bar.cpp +++ b/src/app/ui/status_bar.cpp @@ -59,7 +59,7 @@ using namespace doc; class StatusBar::CustomizedTipWindow : public ui::TipWindow { public: CustomizedTipWindow(const std::string& text) - : ui::TipWindow(text, gfx::Rect()) + : ui::TipWindow(text) { } diff --git a/src/app/ui/toolbar.cpp b/src/app/ui/toolbar.cpp index 2000f5d95..68cbd6b7b 100644 --- a/src/app/ui/toolbar.cpp +++ b/src/app/ui/toolbar.cpp @@ -507,20 +507,15 @@ void ToolBar::openTipWindow(int group_index, Tool* tool) else return; - Rect toolrc = getToolGroupBounds(group_index); - Point arrow = tool ? getToolPositionInGroup(group_index, tool): Point(0, 0); - - m_tipWindow = new TipWindow(tooltip, gfx::Rect(arrow, toolrc.size())); - m_tipWindow->setArrowAlign(TOP | RIGHT); + m_tipWindow = new TipWindow(tooltip); m_tipWindow->remapWindow(); - int w = m_tipWindow->bounds().w; - int h = m_tipWindow->bounds().h; - int x = toolrc.x - w + (tool && m_popupWindow && m_popupWindow->isVisible() ? arrow.x-m_popupWindow->bounds().w: 0); - int y = toolrc.y + toolrc.h; + Rect toolrc = getToolGroupBounds(group_index); + Point arrow = (tool ? getToolPositionInGroup(group_index, tool): Point(0, 0)); + if (tool && m_popupWindow && m_popupWindow->isVisible()) + toolrc.x += arrow.x - m_popupWindow->bounds().w; - m_tipWindow->positionWindow(MID(0, x, ui::display_w()-w), - MID(0, y, ui::display_h()-h)); + m_tipWindow->pointAt(TOP | RIGHT, toolrc); if (m_tipOpened) m_tipWindow->openWindow(); diff --git a/src/ui/tooltips.cpp b/src/ui/tooltips.cpp index efb559bb7..88782ede7 100644 --- a/src/ui/tooltips.cpp +++ b/src/ui/tooltips.cpp @@ -101,82 +101,18 @@ bool TooltipManager::onProcessMessage(Message* msg) void TooltipManager::onTick() { if (!m_tipWindow) { - gfx::Rect bounds = m_target.widget->bounds(); - - m_tipWindow.reset(new TipWindow(m_target.tipInfo.text, bounds)); - int x = get_mouse_position().x+12*guiscale(); - int y = get_mouse_position().y+12*guiscale(); - - m_tipWindow->remapWindow(); - int w = m_tipWindow->bounds().w; - int h = m_tipWindow->bounds().h; + m_tipWindow.reset(new TipWindow(m_target.tipInfo.text)); int arrowAlign = m_target.tipInfo.arrowAlign; - int trycount = 0; - for (; trycount < 4; ++trycount) { - switch (arrowAlign) { - case TOP | LEFT: - x = bounds.x + bounds.w; - y = bounds.y + bounds.h; - break; - case TOP | RIGHT: - x = bounds.x - w; - y = bounds.y + bounds.h; - break; - case BOTTOM | LEFT: - x = bounds.x + bounds.w; - y = bounds.y - h; - break; - case BOTTOM | RIGHT: - x = bounds.x - w; - y = bounds.y - h; - break; - case TOP: - x = bounds.x + bounds.w/2 - w/2; - y = bounds.y + bounds.h; - break; - case BOTTOM: - x = bounds.x + bounds.w/2 - w/2; - y = bounds.y - h; - break; - case LEFT: - x = bounds.x + bounds.w; - y = bounds.y + bounds.h/2 - h/2; - break; - case RIGHT: - x = bounds.x - w; - y = bounds.y + bounds.h/2 - h/2; - break; - } + gfx::Rect target = m_target.widget->bounds(); + if (!arrowAlign) + target.setOrigin(ui::get_mouse_position()+12*guiscale()); - x = MID(0, x, ui::display_w()-w); - y = MID(0, y, ui::display_h()-h); - - if (bounds.intersects(gfx::Rect(x, y, w, h))) { - switch (trycount) { - case 0: - case 2: - // Switch position - if (arrowAlign & (TOP | BOTTOM)) arrowAlign ^= TOP | BOTTOM; - if (arrowAlign & (LEFT | RIGHT)) arrowAlign ^= LEFT | RIGHT; - break; - case 1: - // Rotate positions - if (arrowAlign & (TOP | LEFT)) arrowAlign ^= TOP | LEFT; - if (arrowAlign & (BOTTOM | RIGHT)) arrowAlign ^= BOTTOM | RIGHT; - break; - } - } - else { - m_tipWindow->setArrowAlign(arrowAlign); - m_tipWindow->positionWindow(x, y); - m_tipWindow->openWindow(); - break; - } + if (m_tipWindow->pointAt(arrowAlign, target)) { + m_tipWindow->openWindow(); } - - // No enough room for the tooltip - if (trycount == 4) { + else { + // No enough room for the tooltip m_tipWindow.reset(); m_timer->stop(); } @@ -186,10 +122,9 @@ void TooltipManager::onTick() // TipWindow -TipWindow::TipWindow(const std::string& text, const gfx::Rect& target) +TipWindow::TipWindow(const std::string& text) : PopupWindow(text, ClickBehavior::CloseOnClickInOtherWindow) , m_arrowAlign(0) - , m_target(target) , m_closeOnKeyDown(true) { setTransparent(true); @@ -198,25 +133,88 @@ TipWindow::TipWindow(const std::string& text, const gfx::Rect& target) initTheme(); } -TipWindow::~TipWindow() -{ -} - -int TipWindow::getArrowAlign() const -{ - return m_arrowAlign; -} - -void TipWindow::setArrowAlign(int arrowAlign) -{ - m_arrowAlign = arrowAlign; -} - void TipWindow::setCloseOnKeyDown(bool state) { m_closeOnKeyDown = state; } +bool TipWindow::pointAt(int arrowAlign, const gfx::Rect& target) +{ + m_target = target; + m_arrowAlign = arrowAlign; + + remapWindow(); + + int x = target.x; + int y = target.y; + int w = bounds().w; + int h = bounds().h; + + int trycount = 0; + for (; trycount < 4; ++trycount) { + switch (arrowAlign) { + case TOP | LEFT: + x = m_target.x + m_target.w; + y = m_target.y + m_target.h; + break; + case TOP | RIGHT: + x = m_target.x - w; + y = m_target.y + m_target.h; + break; + case BOTTOM | LEFT: + x = m_target.x + m_target.w; + y = m_target.y - h; + break; + case BOTTOM | RIGHT: + x = m_target.x - w; + y = m_target.y - h; + break; + case TOP: + x = m_target.x + m_target.w/2 - w/2; + y = m_target.y + m_target.h; + break; + case BOTTOM: + x = m_target.x + m_target.w/2 - w/2; + y = m_target.y - h; + break; + case LEFT: + x = m_target.x + m_target.w; + y = m_target.y + m_target.h/2 - h/2; + break; + case RIGHT: + x = m_target.x - w; + y = m_target.y + m_target.h/2 - h/2; + break; + } + + x = MID(0, x, ui::display_w()-w); + y = MID(0, y, ui::display_h()-h); + + if (m_target.intersects(gfx::Rect(x, y, w, h))) { + switch (trycount) { + case 0: + case 2: + // Switch position + if (arrowAlign & (TOP | BOTTOM)) arrowAlign ^= TOP | BOTTOM; + if (arrowAlign & (LEFT | RIGHT)) arrowAlign ^= LEFT | RIGHT; + break; + case 1: + // Rotate positions + if (arrowAlign & (TOP | LEFT)) arrowAlign ^= TOP | LEFT; + if (arrowAlign & (BOTTOM | RIGHT)) arrowAlign ^= BOTTOM | RIGHT; + break; + } + } + else { + m_arrowAlign = arrowAlign; + positionWindow(x, y); + break; + } + } + + return (trycount < 4); +} + bool TipWindow::onProcessMessage(Message* msg) { switch (msg->type()) { diff --git a/src/ui/tooltips.h b/src/ui/tooltips.h index 6d3514859..db5cc9096 100644 --- a/src/ui/tooltips.h +++ b/src/ui/tooltips.h @@ -20,8 +20,7 @@ namespace ui { class TipWindow; - class TooltipManager : public Widget - { + class TooltipManager : public Widget { public: TooltipManager(); ~TooltipManager(); @@ -57,15 +56,16 @@ namespace ui { class TipWindow : public PopupWindow { public: - TipWindow(const std::string& text, const gfx::Rect& target); - ~TipWindow(); + TipWindow(const std::string& text = ""); - int getArrowAlign() const; - void setArrowAlign(int arrowAlign); + int arrowAlign() const { return m_arrowAlign; } + const gfx::Rect& target() const { return m_target; } void setCloseOnKeyDown(bool state); - const gfx::Rect& target() const { return m_target; } + // Returns false there is no enough screen space to show the + // window. + bool pointAt(int arrowAlign, const gfx::Rect& target); protected: bool onProcessMessage(Message* msg) override;