mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 19:20:09 +00:00
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:
parent
06d1929729
commit
cea0970d9d
@ -1764,6 +1764,7 @@ void SkinTheme::paintTooltip(PaintEvent& ev)
|
||||
{
|
||||
ui::TipWindow* widget = static_cast<ui::TipWindow*>(ev.getSource());
|
||||
Graphics* g = ev.getGraphics();
|
||||
Rect absRc = widget->getBounds();
|
||||
Rect rc = widget->getClientBounds();
|
||||
gfx::Color fg = colors.tooltipText();
|
||||
gfx::Color bg = colors.tooltipFace();
|
||||
@ -1788,26 +1789,34 @@ void SkinTheme::paintTooltip(PaintEvent& ev)
|
||||
|
||||
// Draw arrow in sides
|
||||
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()) {
|
||||
case JI_TOP:
|
||||
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;
|
||||
case JI_BOTTOM:
|
||||
arrow = m_part[PART_TOOLTIP_ARROW_S];
|
||||
g->drawRgbaSurface(arrow,
|
||||
rc.x+rc.w/2-arrow->width()/2,
|
||||
rc.y+rc.h-arrow->height());
|
||||
target.x+target.w/2-arrow->width()/2,
|
||||
rc.y+rc.h-arrow->height());
|
||||
break;
|
||||
case JI_LEFT:
|
||||
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;
|
||||
case JI_RIGHT:
|
||||
arrow = m_part[PART_TOOLTIP_ARROW_E];
|
||||
g->drawRgbaSurface(arrow,
|
||||
rc.x+rc.w-arrow->width(),
|
||||
rc.y+rc.h/2-arrow->height()/2);
|
||||
rc.x+rc.w-arrow->width(),
|
||||
target.y+target.h/2-arrow->height()/2);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ static const char* kStatusBarFace = "status_bar_face";
|
||||
class StatusBar::CustomizedTipWindow : public ui::TipWindow {
|
||||
public:
|
||||
CustomizedTipWindow(const char* text)
|
||||
: ui::TipWindow(text)
|
||||
: ui::TipWindow(text, gfx::Rect())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -549,12 +549,13 @@ void ToolBar::openTipWindow(int group_index, Tool* tool)
|
||||
else
|
||||
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->remapWindow();
|
||||
|
||||
Rect toolrc = getToolGroupBounds(group_index);
|
||||
Point arrow = tool ? getToolPositionInGroup(group_index, tool): Point(0, 0);
|
||||
int w = m_tipWindow->getBounds().w;
|
||||
int h = m_tipWindow->getBounds().h;
|
||||
int x = toolrc.x - w + (tool && m_popupWindow && m_popupWindow->isVisible() ? arrow.x-m_popupWindow->getBounds().w: 0);
|
||||
|
@ -215,8 +215,8 @@ public:
|
||||
return false;
|
||||
|
||||
return
|
||||
rc.x <= x+w && rc.x+rc.w > x &&
|
||||
rc.y <= y+h && rc.y+rc.h > y;
|
||||
rc.x < x+w && rc.x+rc.w > x &&
|
||||
rc.y < y+h && rc.y+rc.h > y;
|
||||
}
|
||||
|
||||
// Returns the union rectangle between this and rc rectangle.
|
||||
|
@ -96,67 +96,95 @@ bool TooltipManager::onProcessMessage(Message* msg)
|
||||
void TooltipManager::onTick()
|
||||
{
|
||||
if (!m_tipWindow) {
|
||||
m_tipWindow.reset(new TipWindow(m_target.tipInfo.text.c_str()));
|
||||
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 y = get_mouse_position().y+12*guiscale();
|
||||
int w, h;
|
||||
|
||||
m_tipWindow->setArrowAlign(m_target.tipInfo.arrowAlign);
|
||||
m_tipWindow->remapWindow();
|
||||
int w = m_tipWindow->getBounds().w;
|
||||
int h = m_tipWindow->getBounds().h;
|
||||
|
||||
w = m_tipWindow->getBounds().w;
|
||||
h = m_tipWindow->getBounds().h;
|
||||
int arrowAlign = m_target.tipInfo.arrowAlign;
|
||||
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) {
|
||||
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;
|
||||
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 & (JI_TOP | JI_BOTTOM)) arrowAlign ^= JI_TOP | JI_BOTTOM;
|
||||
if (arrowAlign & (JI_LEFT | JI_RIGHT)) arrowAlign ^= JI_LEFT | JI_RIGHT;
|
||||
break;
|
||||
case 1:
|
||||
// Rotate positions
|
||||
if (arrowAlign & (JI_TOP | JI_LEFT)) arrowAlign ^= JI_TOP | JI_LEFT;
|
||||
if (arrowAlign & (JI_BOTTOM | JI_RIGHT)) arrowAlign ^= JI_BOTTOM | JI_RIGHT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_tipWindow->setArrowAlign(arrowAlign);
|
||||
m_tipWindow->positionWindow(x, y);
|
||||
m_tipWindow->openWindow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_tipWindow->positionWindow(
|
||||
MID(0, x, ui::display_w()-w),
|
||||
MID(0, y, ui::display_h()-h));
|
||||
|
||||
m_tipWindow->openWindow();
|
||||
// No enough room for the tooltip
|
||||
if (trycount == 4) {
|
||||
m_tipWindow.reset();
|
||||
m_timer->stop();
|
||||
}
|
||||
}
|
||||
m_timer->stop();
|
||||
}
|
||||
|
||||
// TipWindow
|
||||
|
||||
TipWindow::TipWindow(const char *text)
|
||||
TipWindow::TipWindow(const char* text, gfx::Rect& target)
|
||||
: PopupWindow(text, kCloseOnClickInOtherWindow)
|
||||
, m_arrowAlign(0)
|
||||
, m_target(target)
|
||||
{
|
||||
setTransparent(true);
|
||||
|
||||
|
@ -56,12 +56,14 @@ namespace ui {
|
||||
|
||||
class TipWindow : public PopupWindow {
|
||||
public:
|
||||
TipWindow(const char *text);
|
||||
TipWindow(const char* text, gfx::Rect& target);
|
||||
~TipWindow();
|
||||
|
||||
int getArrowAlign() const;
|
||||
void setArrowAlign(int arrowAlign);
|
||||
|
||||
const gfx::Rect& target() const { return m_target; }
|
||||
|
||||
protected:
|
||||
bool onProcessMessage(Message* msg) override;
|
||||
void onPreferredSize(PreferredSizeEvent& ev) override;
|
||||
@ -70,6 +72,7 @@ namespace ui {
|
||||
|
||||
private:
|
||||
int m_arrowAlign;
|
||||
gfx::Rect m_target;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
Loading…
x
Reference in New Issue
Block a user