Fix several bugs with tooltip arrows/location

The tooltip arrow is now aligned to the target. And the tooltip is
relocated to the other side if it intersects its target bounds.
This commit is contained in:
David Capello 2015-05-09 13:20:57 -03:00
parent 06d1929729
commit cea0970d9d
6 changed files with 97 additions and 56 deletions

View File

@ -1764,6 +1764,7 @@ void SkinTheme::paintTooltip(PaintEvent& ev)
{ {
ui::TipWindow* widget = static_cast<ui::TipWindow*>(ev.getSource()); ui::TipWindow* widget = static_cast<ui::TipWindow*>(ev.getSource());
Graphics* g = ev.getGraphics(); Graphics* g = ev.getGraphics();
Rect absRc = widget->getBounds();
Rect rc = widget->getClientBounds(); Rect rc = widget->getClientBounds();
gfx::Color fg = colors.tooltipText(); gfx::Color fg = colors.tooltipText();
gfx::Color bg = colors.tooltipFace(); gfx::Color bg = colors.tooltipFace();
@ -1788,26 +1789,34 @@ void SkinTheme::paintTooltip(PaintEvent& ev)
// Draw arrow in sides // Draw arrow in sides
she::Surface* arrow = NULL; she::Surface* arrow = NULL;
gfx::Rect target(widget->target());
target = target.createIntersect(gfx::Rect(0, 0, ui::display_w(), ui::display_h()));
target.offset(-absRc.getOrigin());
switch (widget->getArrowAlign()) { switch (widget->getArrowAlign()) {
case JI_TOP: case JI_TOP:
arrow = m_part[PART_TOOLTIP_ARROW_N]; arrow = m_part[PART_TOOLTIP_ARROW_N];
g->drawRgbaSurface(arrow, rc.x+rc.w/2-arrow->width()/2, rc.y); g->drawRgbaSurface(arrow,
target.x+target.w/2-arrow->width()/2,
rc.y);
break; break;
case JI_BOTTOM: case JI_BOTTOM:
arrow = m_part[PART_TOOLTIP_ARROW_S]; arrow = m_part[PART_TOOLTIP_ARROW_S];
g->drawRgbaSurface(arrow, g->drawRgbaSurface(arrow,
rc.x+rc.w/2-arrow->width()/2, target.x+target.w/2-arrow->width()/2,
rc.y+rc.h-arrow->height()); rc.y+rc.h-arrow->height());
break; break;
case JI_LEFT: case JI_LEFT:
arrow = m_part[PART_TOOLTIP_ARROW_W]; arrow = m_part[PART_TOOLTIP_ARROW_W];
g->drawRgbaSurface(arrow, rc.x, rc.y+rc.h/2-arrow->height()/2); g->drawRgbaSurface(arrow,
rc.x,
target.y+target.h/2-arrow->height()/2);
break; break;
case JI_RIGHT: case JI_RIGHT:
arrow = m_part[PART_TOOLTIP_ARROW_E]; arrow = m_part[PART_TOOLTIP_ARROW_E];
g->drawRgbaSurface(arrow, g->drawRgbaSurface(arrow,
rc.x+rc.w-arrow->width(), rc.x+rc.w-arrow->width(),
rc.y+rc.h/2-arrow->height()/2); target.y+target.h/2-arrow->height()/2);
break; break;
} }

View File

@ -60,7 +60,7 @@ static const char* kStatusBarFace = "status_bar_face";
class StatusBar::CustomizedTipWindow : public ui::TipWindow { class StatusBar::CustomizedTipWindow : public ui::TipWindow {
public: public:
CustomizedTipWindow(const char* text) CustomizedTipWindow(const char* text)
: ui::TipWindow(text) : ui::TipWindow(text, gfx::Rect())
{ {
} }

View File

@ -549,12 +549,13 @@ void ToolBar::openTipWindow(int group_index, Tool* tool)
else else
return; return;
m_tipWindow = new TipWindow(tooltip.c_str()); Rect toolrc = getToolGroupBounds(group_index);
Point arrow = tool ? getToolPositionInGroup(group_index, tool): Point(0, 0);
m_tipWindow = new TipWindow(tooltip.c_str(), gfx::Rect(arrow, toolrc.getSize()));
m_tipWindow->setArrowAlign(JI_TOP | JI_RIGHT); m_tipWindow->setArrowAlign(JI_TOP | JI_RIGHT);
m_tipWindow->remapWindow(); m_tipWindow->remapWindow();
Rect toolrc = getToolGroupBounds(group_index);
Point arrow = tool ? getToolPositionInGroup(group_index, tool): Point(0, 0);
int w = m_tipWindow->getBounds().w; int w = m_tipWindow->getBounds().w;
int h = m_tipWindow->getBounds().h; int h = m_tipWindow->getBounds().h;
int x = toolrc.x - w + (tool && m_popupWindow && m_popupWindow->isVisible() ? arrow.x-m_popupWindow->getBounds().w: 0); int x = toolrc.x - w + (tool && m_popupWindow && m_popupWindow->isVisible() ? arrow.x-m_popupWindow->getBounds().w: 0);

View File

@ -215,8 +215,8 @@ public:
return false; return false;
return return
rc.x <= x+w && rc.x+rc.w > x && rc.x < x+w && rc.x+rc.w > x &&
rc.y <= y+h && rc.y+rc.h > y; rc.y < y+h && rc.y+rc.h > y;
} }
// Returns the union rectangle between this and rc rectangle. // Returns the union rectangle between this and rc rectangle.

View File

@ -96,67 +96,95 @@ bool TooltipManager::onProcessMessage(Message* msg)
void TooltipManager::onTick() void TooltipManager::onTick()
{ {
if (!m_tipWindow) { if (!m_tipWindow) {
m_tipWindow.reset(new TipWindow(m_target.tipInfo.text.c_str()));
gfx::Rect bounds = m_target.widget->getBounds(); gfx::Rect bounds = m_target.widget->getBounds();
m_tipWindow.reset(new TipWindow(m_target.tipInfo.text.c_str(), bounds));
int x = get_mouse_position().x+12*guiscale(); int x = get_mouse_position().x+12*guiscale();
int y = get_mouse_position().y+12*guiscale(); int y = get_mouse_position().y+12*guiscale();
int w, h;
m_tipWindow->setArrowAlign(m_target.tipInfo.arrowAlign);
m_tipWindow->remapWindow(); m_tipWindow->remapWindow();
int w = m_tipWindow->getBounds().w;
int h = m_tipWindow->getBounds().h;
w = m_tipWindow->getBounds().w; int arrowAlign = m_target.tipInfo.arrowAlign;
h = m_tipWindow->getBounds().h; int trycount = 0;
for (; trycount < 4; ++trycount) {
switch (arrowAlign) {
case JI_TOP | JI_LEFT:
x = bounds.x + bounds.w;
y = bounds.y + bounds.h;
break;
case JI_TOP | JI_RIGHT:
x = bounds.x - w;
y = bounds.y + bounds.h;
break;
case JI_BOTTOM | JI_LEFT:
x = bounds.x + bounds.w;
y = bounds.y - h;
break;
case JI_BOTTOM | JI_RIGHT:
x = bounds.x - w;
y = bounds.y - h;
break;
case JI_TOP:
x = bounds.x + bounds.w/2 - w/2;
y = bounds.y + bounds.h;
break;
case JI_BOTTOM:
x = bounds.x + bounds.w/2 - w/2;
y = bounds.y - h;
break;
case JI_LEFT:
x = bounds.x + bounds.w;
y = bounds.y + bounds.h/2 - h/2;
break;
case JI_RIGHT:
x = bounds.x - w;
y = bounds.y + bounds.h/2 - h/2;
break;
}
switch (m_target.tipInfo.arrowAlign) { x = MID(0, x, ui::display_w()-w);
case JI_TOP | JI_LEFT: y = MID(0, y, ui::display_h()-h);
x = bounds.x + bounds.w;
y = bounds.y + bounds.h; if (bounds.intersects(gfx::Rect(x, y, w, h))) {
break; switch (trycount) {
case JI_TOP | JI_RIGHT: case 0:
x = bounds.x - w; case 2:
y = bounds.y + bounds.h; // Switch position
break; if (arrowAlign & (JI_TOP | JI_BOTTOM)) arrowAlign ^= JI_TOP | JI_BOTTOM;
case JI_BOTTOM | JI_LEFT: if (arrowAlign & (JI_LEFT | JI_RIGHT)) arrowAlign ^= JI_LEFT | JI_RIGHT;
x = bounds.x + bounds.w; break;
y = bounds.y - h; case 1:
break; // Rotate positions
case JI_BOTTOM | JI_RIGHT: if (arrowAlign & (JI_TOP | JI_LEFT)) arrowAlign ^= JI_TOP | JI_LEFT;
x = bounds.x - w; if (arrowAlign & (JI_BOTTOM | JI_RIGHT)) arrowAlign ^= JI_BOTTOM | JI_RIGHT;
y = bounds.y - h; break;
break; }
case JI_TOP: }
x = bounds.x + bounds.w/2 - w/2; else {
y = bounds.y + bounds.h; m_tipWindow->setArrowAlign(arrowAlign);
break; m_tipWindow->positionWindow(x, y);
case JI_BOTTOM: m_tipWindow->openWindow();
x = bounds.x + bounds.w/2 - w/2;
y = bounds.y - h;
break;
case JI_LEFT:
x = bounds.x + bounds.w;
y = bounds.y + bounds.h/2 - h/2;
break;
case JI_RIGHT:
x = bounds.x - w;
y = bounds.y + bounds.h/2 - h/2;
break; break;
}
} }
m_tipWindow->positionWindow( // No enough room for the tooltip
MID(0, x, ui::display_w()-w), if (trycount == 4) {
MID(0, y, ui::display_h()-h)); m_tipWindow.reset();
m_timer->stop();
m_tipWindow->openWindow(); }
} }
m_timer->stop(); m_timer->stop();
} }
// TipWindow // TipWindow
TipWindow::TipWindow(const char *text) TipWindow::TipWindow(const char* text, gfx::Rect& target)
: PopupWindow(text, kCloseOnClickInOtherWindow) : PopupWindow(text, kCloseOnClickInOtherWindow)
, m_arrowAlign(0) , m_arrowAlign(0)
, m_target(target)
{ {
setTransparent(true); setTransparent(true);

View File

@ -56,12 +56,14 @@ namespace ui {
class TipWindow : public PopupWindow { class TipWindow : public PopupWindow {
public: public:
TipWindow(const char *text); TipWindow(const char* text, gfx::Rect& target);
~TipWindow(); ~TipWindow();
int getArrowAlign() const; int getArrowAlign() const;
void setArrowAlign(int arrowAlign); void setArrowAlign(int arrowAlign);
const gfx::Rect& target() const { return m_target; }
protected: protected:
bool onProcessMessage(Message* msg) override; bool onProcessMessage(Message* msg) override;
void onPreferredSize(PreferredSizeEvent& ev) override; void onPreferredSize(PreferredSizeEvent& ev) override;
@ -70,6 +72,7 @@ namespace ui {
private: private:
int m_arrowAlign; int m_arrowAlign;
gfx::Rect m_target;
}; };
} // namespace ui } // namespace ui