mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-23 00:40:04 +00:00
Add Widget::is/setTransparent property to paint a widget merged with its background
This fixes problems with tooltips, toolbar popups and context bar popups. It fixes issue #297 (undo notifications rendering problems).
This commit is contained in:
parent
2b3a4d1668
commit
a34d181530
@ -150,21 +150,24 @@ protected:
|
||||
|
||||
private:
|
||||
void openPopup() {
|
||||
Border border = Border(2, 2, 2, 3)*jguiscale();
|
||||
Rect rc = getBounds();
|
||||
rc.y += rc.h;
|
||||
rc.w *= 3;
|
||||
m_popupWindow = new PopupWindow("", PopupWindow::kCloseOnClickInOtherWindow);
|
||||
m_popupWindow->setAutoRemap(false);
|
||||
m_popupWindow->setBounds(rc);
|
||||
m_popupWindow->setBorder(border);
|
||||
m_popupWindow->setBounds(rc + border);
|
||||
|
||||
Region rgn(rc.createUnion(getBounds()));
|
||||
Region rgn(m_popupWindow->getBounds().createUnion(getBounds()));
|
||||
m_popupWindow->setHotRegion(rgn);
|
||||
m_brushType = new ButtonSet(3, 1, m_penType,
|
||||
PART_BRUSH_CIRCLE,
|
||||
PART_BRUSH_SQUARE,
|
||||
PART_BRUSH_LINE);
|
||||
|
||||
PART_BRUSH_CIRCLE,
|
||||
PART_BRUSH_SQUARE,
|
||||
PART_BRUSH_LINE);
|
||||
m_brushType->ItemChange.connect(&BrushTypeField::onBrushTypeChange, this);
|
||||
m_brushType->setTransparent(true);
|
||||
m_brushType->setBgColor(ui::ColorNone);
|
||||
|
||||
m_popupWindow->addChild(m_brushType);
|
||||
m_popupWindow->openWindow();
|
||||
|
@ -913,7 +913,8 @@ void SkinTheme::paintBox(PaintEvent& ev)
|
||||
Widget* widget = static_cast<Widget*>(ev.getSource());
|
||||
Graphics* g = ev.getGraphics();
|
||||
|
||||
g->fillRect(BGCOLOR, g->getClipBounds());
|
||||
if (!is_transparent(BGCOLOR))
|
||||
g->fillRect(BGCOLOR, g->getClipBounds());
|
||||
}
|
||||
|
||||
void SkinTheme::paintButton(PaintEvent& ev)
|
||||
@ -1039,7 +1040,8 @@ void SkinTheme::paintGrid(PaintEvent& ev)
|
||||
Widget* widget = static_cast<Widget*>(ev.getSource());
|
||||
Graphics* g = ev.getGraphics();
|
||||
|
||||
g->fillRect(BGCOLOR, g->getClipBounds());
|
||||
if (!is_transparent(BGCOLOR))
|
||||
g->fillRect(BGCOLOR, g->getClipBounds());
|
||||
}
|
||||
|
||||
void SkinTheme::paintEntry(PaintEvent& ev)
|
||||
@ -1136,7 +1138,9 @@ void SkinTheme::paintLabel(PaintEvent& ev)
|
||||
ui::Color fg = widget->getTextColor();
|
||||
Rect text, rc = widget->getClientBounds();
|
||||
|
||||
g->fillRect(bg, rc);
|
||||
if (!is_transparent(bg))
|
||||
g->fillRect(bg, rc);
|
||||
|
||||
rc.shrink(widget->getBorder());
|
||||
|
||||
widget->getTextIconInfo(NULL, &text);
|
||||
@ -1639,8 +1643,10 @@ void SkinTheme::paintView(PaintEvent& ev)
|
||||
Graphics* g = ev.getGraphics();
|
||||
View* widget = static_cast<View*>(ev.getSource());
|
||||
gfx::Rect bounds = widget->getClientBounds();
|
||||
ui::Color bg = BGCOLOR;
|
||||
|
||||
g->fillRect(BGCOLOR, bounds);
|
||||
if (!is_transparent(bg))
|
||||
g->fillRect(bg, bounds);
|
||||
|
||||
draw_bounds_nw(g, bounds,
|
||||
(widget->hasFocus() ?
|
||||
@ -1687,8 +1693,10 @@ void SkinTheme::paintViewViewport(PaintEvent& ev)
|
||||
{
|
||||
Viewport* widget = static_cast<Viewport*>(ev.getSource());
|
||||
Graphics* g = ev.getGraphics();
|
||||
ui::Color bg = BGCOLOR;
|
||||
|
||||
g->fillRect(BGCOLOR, widget->getClientBounds());
|
||||
if (!is_transparent(bg))
|
||||
g->fillRect(bg, widget->getClientBounds());
|
||||
}
|
||||
|
||||
void SkinTheme::paintWindow(PaintEvent& ev)
|
||||
@ -1720,11 +1728,14 @@ void SkinTheme::paintWindow(PaintEvent& ev)
|
||||
|
||||
void SkinTheme::paintPopupWindow(PaintEvent& ev)
|
||||
{
|
||||
Widget* widget = static_cast<Widget*>(ev.getSource());
|
||||
Window* window = static_cast<Window*>(ev.getSource());
|
||||
Graphics* g = ev.getGraphics();
|
||||
gfx::Rect pos = window->getClientBounds();
|
||||
|
||||
get_style("menubox")->paint(g, pos, NULL, Style::State());
|
||||
if (!is_transparent(BGCOLOR))
|
||||
get_style("menubox")->paint(g, pos, NULL, Style::State());
|
||||
|
||||
pos.shrink(window->getBorder());
|
||||
|
||||
g->drawString(window->getText(),
|
||||
@ -1814,8 +1825,12 @@ ui::Color SkinTheme::getWidgetBgColor(Widget* widget)
|
||||
ui::Color c = widget->getBgColor();
|
||||
bool decorative = widget->isDecorative();
|
||||
|
||||
return (!is_transparent(c) ? c: (decorative ? getColor(ThemeColor::Selected):
|
||||
getColor(ThemeColor::Face)));
|
||||
if (!is_transparent(c) || widget->getType() == kWindowWidget)
|
||||
return c;
|
||||
else if (decorative)
|
||||
return getColor(ThemeColor::Selected);
|
||||
else
|
||||
return getColor(ThemeColor::Face);
|
||||
}
|
||||
|
||||
void SkinTheme::drawTextString(Graphics* g, const char *t, ui::Color fg_color, ui::Color bg_color,
|
||||
|
@ -462,6 +462,8 @@ void ToolBar::openPopupWindow(int group_index, ToolGroup* tool_group)
|
||||
rgn.createUnion(rgn, Region(getBounds()));
|
||||
m_popupWindow->setHotRegion(rgn);
|
||||
|
||||
m_popupWindow->setTransparent(true);
|
||||
m_popupWindow->setBgColor(ui::ColorNone);
|
||||
m_popupWindow->setAutoRemap(false);
|
||||
m_popupWindow->setBounds(rc);
|
||||
toolstrip->setBounds(rc);
|
||||
@ -632,6 +634,7 @@ ToolBar::ToolStrip::ToolStrip(ToolGroup* group, ToolBar* toolbar)
|
||||
m_toolbar = toolbar;
|
||||
|
||||
setDoubleBuffered(true);
|
||||
setTransparent(true);
|
||||
}
|
||||
|
||||
ToolBar::ToolStrip::~ToolStrip()
|
||||
@ -730,7 +733,6 @@ void ToolBar::ToolStrip::onPaint(PaintEvent& ev)
|
||||
{
|
||||
Graphics* g = ev.getGraphics();
|
||||
gfx::Rect bounds = getClientBounds();
|
||||
gfx::Rect clip = g->getClipBounds();
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
|
||||
ToolBox* toolbox = App::instance()->getToolBox();
|
||||
Rect toolrc;
|
||||
|
@ -32,6 +32,10 @@ namespace ui {
|
||||
Graphics(BITMAP* bmp, int dx, int dy);
|
||||
~Graphics();
|
||||
|
||||
BITMAP* getInternalBitmap() { return m_bmp; }
|
||||
int getInternalDeltaX() { return m_dx; }
|
||||
int getInternalDeltaY() { return m_dy; }
|
||||
|
||||
gfx::Rect getClipBounds() const;
|
||||
void setClipBounds(const gfx::Rect& rc);
|
||||
bool intersectClipRect(const gfx::Rect& rc);
|
||||
|
@ -139,8 +139,9 @@ void IntEntry::openPopup()
|
||||
|
||||
m_popupWindow = new PopupWindow("", PopupWindow::kCloseOnClickInOtherWindow);
|
||||
m_popupWindow->setAutoRemap(false);
|
||||
m_popupWindow->setTransparent(true);
|
||||
m_popupWindow->setBgColor(ui::ColorNone);
|
||||
m_popupWindow->setBounds(rc);
|
||||
m_popupWindow->setBgColor(rgba(0, 0, 0, 0));
|
||||
m_popupWindow->Close.connect(&IntEntry::onPopupClose, this);
|
||||
|
||||
Region rgn(rc.createUnion(getBounds()));
|
||||
@ -149,6 +150,7 @@ void IntEntry::openPopup()
|
||||
|
||||
m_slider = new Slider(m_min, m_max, getValue());
|
||||
m_slider->setFocusStop(false); // In this way the IntEntry doesn't lost the focus
|
||||
m_slider->setTransparent(true);
|
||||
m_slider->Change.connect(&IntEntry::onChangeSlider, this);
|
||||
m_popupWindow->addChild(m_slider);
|
||||
|
||||
|
@ -155,6 +155,8 @@ TipWindow::TipWindow(const char *text)
|
||||
: PopupWindow(text, kCloseOnClickInOtherWindow)
|
||||
, m_arrowAlign(0)
|
||||
{
|
||||
setTransparent(true);
|
||||
|
||||
makeFixed();
|
||||
initTheme();
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ Widget::Widget(WidgetType type)
|
||||
|
||||
m_preferredSize = NULL;
|
||||
m_doubleBuffered = false;
|
||||
m_transparent = false;
|
||||
}
|
||||
|
||||
Widget::~Widget()
|
||||
@ -655,6 +656,9 @@ void Widget::getDrawableRegion(gfx::Region& region, DrawableRegionFlags flags)
|
||||
it != windows_list.rend()) {
|
||||
// Subtract the rectangles
|
||||
for (++it; it != windows_list.rend(); ++it) {
|
||||
if (!(*it)->isVisible())
|
||||
continue;
|
||||
|
||||
Region reg1;
|
||||
(*it)->getRegion(reg1);
|
||||
region.createSubtraction(region, reg1);
|
||||
@ -917,7 +921,79 @@ void Widget::flushRedraw()
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::isDoubleBuffered()
|
||||
void Widget::paint(Graphics* graphics, const gfx::Region& drawRegion)
|
||||
{
|
||||
if (drawRegion.isEmpty())
|
||||
return;
|
||||
|
||||
std::queue<Widget*> processing;
|
||||
processing.push(this);
|
||||
|
||||
while (!processing.empty()) {
|
||||
Widget* widget = processing.front();
|
||||
processing.pop();
|
||||
|
||||
ASSERT_VALID_WIDGET(widget);
|
||||
|
||||
// If the widget is hidden
|
||||
if (!widget->isVisible())
|
||||
continue;
|
||||
|
||||
UI_FOREACH_WIDGET(widget->getChildren(), it) {
|
||||
Widget* child = *it;
|
||||
processing.push(child);
|
||||
}
|
||||
|
||||
// Intersect drawRegion with widget's drawable region.
|
||||
Region region;
|
||||
widget->getDrawableRegion(region, kCutTopWindows);
|
||||
region.createIntersection(region, drawRegion);
|
||||
|
||||
Graphics graphics2(graphics->getInternalBitmap(),
|
||||
widget->getBounds().x,
|
||||
widget->getBounds().y);
|
||||
graphics2.setFont(widget->getFont());
|
||||
|
||||
for (Region::const_iterator
|
||||
it = region.begin(),
|
||||
end = region.end(); it != end; ++it) {
|
||||
IntersectClip clip(&graphics2, Rect(*it).offset(
|
||||
-widget->getBounds().x,
|
||||
-widget->getBounds().y));
|
||||
widget->paintEvent(&graphics2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::paintEvent(Graphics* graphics)
|
||||
{
|
||||
// For transparent widgets we have to draw the parent first.
|
||||
if (isTransparent()) {
|
||||
#if _DEBUG
|
||||
// In debug mode we can fill the area with Red so we know if the
|
||||
// we are drawing the parent correctly.
|
||||
graphics->fillRect(ui::rgba(255, 0, 0), getClientBounds());
|
||||
#endif _DEBUG
|
||||
|
||||
this->flags |= JI_HIDDEN;
|
||||
|
||||
gfx::Region rgn(getParent()->getBounds());
|
||||
rgn.createIntersection(rgn,
|
||||
gfx::Region(
|
||||
graphics->getClipBounds().offset(
|
||||
graphics->getInternalDeltaX(),
|
||||
graphics->getInternalDeltaY())));
|
||||
getParent()->paint(graphics, rgn);
|
||||
|
||||
this->flags &= ~JI_HIDDEN;
|
||||
}
|
||||
|
||||
PaintEvent ev(this, graphics);
|
||||
onPaint(ev); // Fire onPaint event
|
||||
return ev.isPainted();
|
||||
}
|
||||
|
||||
bool Widget::isDoubleBuffered() const
|
||||
{
|
||||
return m_doubleBuffered;
|
||||
}
|
||||
@ -927,6 +1003,16 @@ void Widget::setDoubleBuffered(bool doubleBuffered)
|
||||
m_doubleBuffered = doubleBuffered;
|
||||
}
|
||||
|
||||
bool Widget::isTransparent() const
|
||||
{
|
||||
return m_transparent;
|
||||
}
|
||||
|
||||
void Widget::setTransparent(bool transparent)
|
||||
{
|
||||
m_transparent = transparent;
|
||||
}
|
||||
|
||||
void Widget::invalidate()
|
||||
{
|
||||
if (isVisible()) {
|
||||
@ -1217,9 +1303,7 @@ bool Widget::onProcessMessage(Message* msg)
|
||||
ASSERT(ptmsg->rect().h > 0);
|
||||
|
||||
GraphicsPtr graphics = getGraphics(toClient(ptmsg->rect()));
|
||||
PaintEvent ev(this, graphics);
|
||||
onPaint(ev); // Fire onPaint event
|
||||
return ev.isPainted();
|
||||
return paintEvent(graphics);
|
||||
}
|
||||
|
||||
case kKeyDownMessage:
|
||||
|
@ -296,9 +296,12 @@ namespace ui {
|
||||
// REFRESH ISSUES
|
||||
// ===============================================================
|
||||
|
||||
bool isDoubleBuffered();
|
||||
bool isDoubleBuffered() const;
|
||||
void setDoubleBuffered(bool doubleBuffered);
|
||||
|
||||
bool isTransparent() const;
|
||||
void setTransparent(bool transparent);
|
||||
|
||||
void invalidate();
|
||||
void invalidateRect(const gfx::Rect& rect);
|
||||
void invalidateRegion(const gfx::Region& region);
|
||||
@ -376,6 +379,9 @@ namespace ui {
|
||||
virtual void onSetBgColor();
|
||||
|
||||
private:
|
||||
void paint(Graphics* graphics, const gfx::Region& drawRegion);
|
||||
bool paintEvent(Graphics* graphics);
|
||||
|
||||
base::string m_id; // Widget's id
|
||||
Theme* m_theme; // Widget's theme
|
||||
int m_align; // Widget alignment
|
||||
@ -387,7 +393,8 @@ namespace ui {
|
||||
WidgetsList m_children; // Sub-widgets
|
||||
Widget* m_parent; // Who is the parent?
|
||||
gfx::Size* m_preferredSize;
|
||||
bool m_doubleBuffered : 1;
|
||||
bool m_doubleBuffered;
|
||||
bool m_transparent;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
Loading…
x
Reference in New Issue
Block a user