Convert tabs painting code to new styles

This commit is contained in:
David Capello 2017-03-13 13:47:37 -03:00
parent aabdb11779
commit ca2aae6349
4 changed files with 196 additions and 161 deletions

View File

@ -662,84 +662,6 @@
<background color="hot_face" />
</style>
<!-- tab -->
<style id="tab">
<background part="tab_normal" repeat="repeat" />
<text color="tab_normal_text" align="left" valign="middle" padding-left="4" padding-top="2" />
</style>
<style id="tab:active">
<background part="tab_active" repeat="repeat" />
<text color="tab_active_text" />
</style>
<!-- tab_text -->
<style id="tab_text">
<text color="tab_normal_text" align="left" valign="middle" padding-left="4" padding-top="2" />
</style>
<style id="tab_text:active">
<text color="tab_active_text" />
</style>
<!-- tab_bottom -->
<style id="tab_bottom">
<background part="tab_bottom_normal" repeat="repeat-x" />
</style>
<style id="tab_bottom:active">
<background part="tab_bottom_active" color="tab_active_face" />
</style>
<!-- tab_filler -->
<style id="tab_filler">
<background part="tab_filler" repeat="repeat-x" />
</style>
<!-- tab_icon -->
<style id="tab_icon">
<icon align="left" valign="middle" x="3" />
</style>
<style id="tab_icon:hover">
<background part="tab_icon_bg_hover" />
</style>
<style id="tab_icon:clicked">
<background part="tab_icon_bg_clicked" />
</style>
<!-- tab_close_icon -->
<style id="tab_close_icon" base="tab_icon">
<icon part="tab_close_icon_normal" />
</style>
<style id="tab_close_icon:hover">
<icon part="tab_close_icon_normal" />
</style>
<style id="tab_close_icon:active">
<icon part="tab_close_icon_active" />
</style>
<style id="tab_close_icon:clicked">
<icon part="tab_close_icon_normal" />
</style>
<!-- tab_modified_icon -->
<style id="tab_modified_icon" base="tab_icon">
<icon part="tab_modified_icon_normal" />
</style>
<style id="tab_modified_icon:hover">
<icon part="tab_modified_icon_normal" />
</style>
<style id="tab_modified_icon:active">
<icon part="tab_modified_icon_active" />
</style>
<style id="tab_modified_icon:clicked">
<icon part="tab_modified_icon_normal" />
</style>
<!-- tab_home -->
<style id="tab_home">
<icon part="tab_home_icon_normal" align="left" valign="middle" x="4" y="1" />
</style>
<style id="tab_home:active">
<icon part="tab_home_icon_active" />
</style>
</stylesheet>
<styles>
@ -957,10 +879,10 @@
</style>
<style id="horizontal_separator"
border-left="2"
border-top="4"
border-right="2"
border-bottom="0">
border-left="2"
border-top="4"
border-right="2"
border-bottom="0">
<background part="separator_horz" color="window_face" align="middle" />
<text color="separator_label" x="4" align="left middle" />
</style>
@ -973,10 +895,10 @@
</style>
<style id="vertical_separator"
border-left="4"
border-top="2"
border-right="1"
border-bottom="2">
border-left="4"
border-top="2"
border-right="1"
border-bottom="2">
<background part="separator_vert" align="center" />
</style>
@ -1005,10 +927,10 @@
</style>
<style id="scrollbar">
<background part="scrollbar_bg" repeat="repeat" />
<background part="scrollbar_bg" />
</style>
<style id="scrollbar_thumb">
<background part="scrollbar_thumb" repeat="repeat" />
<background part="scrollbar_thumb" />
</style>
<style id="mini_scrollbar">
<background part="mini_scrollbar_bg" />
@ -1027,6 +949,48 @@
<background part="transparent_scrollbar_thumb_hot" state="mouse" />
</style>
<style id="main_tabs">
<background color="window_face" />
</style>
<style id="workspace_tabs">
<background color="workspace" />
</style>
<style id="tab">
<background part="tab_normal" align="middle" />
<background part="tab_active" align="middle" state="focus" />
<text color="tab_normal_text" align="left" valign="middle" padding-left="4" padding-top="2" />
<text color="tab_active_text" state="focus" />
</style>
<style id="tab_text">
<text color="tab_normal_text" align="left middle" x="4" y="1" />
<text color="tab_active_text" align="left middle" x="4" y="1" state="focus" />
</style>
<style id="tab_bottom">
<background part="tab_bottom_normal" align="middle" />
<background part="tab_bottom_active" color="tab_active_face" state="focus" />
</style>
<style id="tab_filler">
<background part="tab_filler" align="middle" />
</style>
<style id="tab_icon">
<background part="tab_icon_bg_hover" state="mouse" />
<background part="tab_icon_bg_clicked" state="selected" />
</style>
<style id="tab_close_icon" extends="tab_icon">
<icon part="tab_close_icon_normal" align="left middle" x="3" />
<icon part="tab_close_icon_active" align="left middle" x="3" state="focus" />
<icon part="tab_close_icon_normal" align="left middle" x="3" state="selected" />
</style>
<style id="tab_modified_icon" extends="tab_icon">
<icon part="tab_modified_icon_normal" align="left middle" x="3" />
<icon part="tab_modified_icon_active" align="left middle" x="3" state="focus" />
<icon part="tab_modified_icon_normal" align="left middle" x="3" state="selected" />
</style>
<style id="tab_home">
<icon part="tab_home_icon_normal" align="left middle" x="4" y="1" />
<icon part="tab_home_icon_active" align="left middle" x="4" y="1" state="focus" />
</style>
</styles>
</theme>

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -63,13 +63,13 @@ Tabs::Tabs(TabsDelegate* delegate)
{
enableFlags(CTRL_RIGHT_CLICK);
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
setStyle(theme->newStyles.mainTabs());
setDoubleBuffered(true);
initTheme();
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
m_tabsHeight = theme->dimensions.tabsHeight();
m_tabsBottomHeight = theme->dimensions.tabsBottomHeight();
setBgColor(theme->colors.windowFace());
}
Tabs::~Tabs()
@ -256,7 +256,7 @@ void Tabs::setDockedStyle()
m_tabsHeight = theme->dimensions.dockedTabsHeight();
m_tabsBottomHeight = 0;
setBgColor(theme->colors.workspace());
setStyle(theme->newStyles.workspaceTabs());
}
void Tabs::setDropViewPreview(const gfx::Point& pos, TabView* view)
@ -459,12 +459,13 @@ bool Tabs::onProcessMessage(Message* msg)
void Tabs::onPaint(PaintEvent& ev)
{
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
Graphics* g = ev.graphics();
gfx::Rect rect = clientBounds();
gfx::Rect box(rect.x, rect.y, rect.w,
m_tabsHeight - m_tabsBottomHeight);
m_tabsHeight - m_tabsBottomHeight);
g->fillRect(bgColor(), g->getClipBounds());
theme->paintWidget(g, this, style(), rect);
if (!m_docked)
drawFiller(g, box);
@ -513,7 +514,6 @@ void Tabs::onPaint(PaintEvent& ev)
// New tab from other Tab that want to be dropped here.
if (m_dropNewTab) {
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
Tab newTab(m_dropNewTab);
newTab.width = newTab.oldWidth =
@ -552,7 +552,7 @@ void Tabs::selectTabInternal(TabPtr& tab)
}
void Tabs::drawTab(Graphics* g, const gfx::Rect& _box,
Tab* tab, int dy, bool hover, bool selected)
Tab* tab, int dy, bool hover, bool selected)
{
gfx::Rect box = _box;
if (box.w < ui::guiscale()*8)
@ -569,14 +569,15 @@ void Tabs::drawTab(Graphics* g, const gfx::Rect& _box,
clipTextRightSide = closeBox.w;
}
skin::Style::State state;
if (selected) state += skin::Style::active();
if (hover) state += skin::Style::hover();
// Tab without text
theme->styles.tab()->paint(g,
PaintWidgetPartInfo info;
info.styleFlags =
(selected ? ui::Style::Layer::kFocus: 0) |
(hover ? ui::Style::Layer::kMouse: 0);
theme->paintWidgetPart(
g, theme->newStyles.tab(),
gfx::Rect(box.x, box.y+dy, box.w, box.h),
nullptr, state);
info);
{
IntersectClip clip(g, gfx::Rect(box.x, box.y+dy, box.w-clipTextRightSide, box.h));
@ -589,13 +590,14 @@ void Tabs::drawTab(Graphics* g, const gfx::Rect& _box,
break;
case TabIcon::HOME:
{
theme->styles.tabHome()->paint(g,
theme->paintWidgetPart(
g, theme->newStyles.tabHome(),
gfx::Rect(
box.x,
box.y+dy,
box.x-dx,
box.h),
nullptr, state);
info);
dx += theme->dimensions.tabsIconWidth();
}
break;
@ -603,21 +605,26 @@ void Tabs::drawTab(Graphics* g, const gfx::Rect& _box,
// Tab with text + clipping the close button
if (box.w > 8*ui::guiscale()) {
theme->styles.tabText()->paint(g,
info.text = &tab->text;
theme->paintWidgetPart(
g, theme->newStyles.tabText(),
gfx::Rect(box.x+dx, box.y+dy, box.w-dx, box.h),
tab->text.c_str(), state);
info);
info.text = nullptr;
}
}
// Tab bottom part
if (!m_docked)
theme->styles.tabBottom()->paint(g,
if (!m_docked) {
theme->paintWidgetPart(
g, theme->newStyles.tabBottom(),
gfx::Rect(box.x, box.y2(), box.w, bounds().y2()-box.y2()),
nullptr, state);
info);
}
// Close button
if (!closeBox.isEmpty()) {
skin::Style* style = theme->styles.tabCloseIcon();
ui::Style* style = theme->newStyles.tabCloseIcon();
if (m_delegate) {
if (tab->view)
@ -625,22 +632,20 @@ void Tabs::drawTab(Graphics* g, const gfx::Rect& _box,
if (tab->modified &&
(!hover || !m_hotCloseButton)) {
style = theme->styles.tabModifiedIcon();
style = theme->newStyles.tabModifiedIcon();
}
}
state = skin::Style::State();
info.styleFlags = 0;
if (selected)
info.styleFlags |= ui::Style::Layer::kFocus;
if (hover && m_hotCloseButton) {
state += skin::Style::hover();
if (selected)
state += skin::Style::active();
info.styleFlags |= ui::Style::Layer::kMouse;
if (m_clickedCloseButton)
state += skin::Style::clicked();
info.styleFlags |= ui::Style::Layer::kSelected;
}
else if (selected)
state += skin::Style::active();
style->paint(g, closeBox, nullptr, state);
theme->paintWidgetPart(g, style, closeBox, info);
}
}
@ -648,13 +653,16 @@ void Tabs::drawFiller(ui::Graphics* g, const gfx::Rect& box)
{
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
gfx::Rect rect = clientBounds();
skin::Style::State state;
theme->styles.tabFiller()->paint(g,
gfx::Rect(box.x, box.y, rect.x2()-box.x, box.h), nullptr, state);
theme->paintWidgetPart(
g, theme->newStyles.tabFiller(),
gfx::Rect(box.x, box.y, rect.x2()-box.x, box.h),
PaintWidgetPartInfo());
theme->styles.tabBottom()->paint(g,
gfx::Rect(box.x, box.y2(), rect.x2()-box.x, rect.y2()-box.y2()), nullptr, state);
theme->paintWidgetPart(
g, theme->newStyles.tabBottom(),
gfx::Rect(box.x, box.y2(), rect.x2()-box.x, rect.y2()-box.y2()),
PaintWidgetPartInfo());
}
Tabs::TabsListIterator Tabs::getTabIteratorByView(TabView* tabView)

View File

@ -40,16 +40,10 @@ int compare_layer_flags(int a, int b)
return a - b;
}
void for_each_layer(const Widget* widget,
void for_each_layer(const int flags,
const Style* style,
std::function<void(const Style::Layer&)> callback)
{
int flags =
(widget->isEnabled() ? 0: Style::Layer::kDisabled) |
(widget->isSelected() ? Style::Layer::kSelected: 0) |
(widget->hasMouse() ? Style::Layer::kMouse: 0) |
(widget->hasFocus() ? Style::Layer::kFocus: 0);
const Style::Layer* bestLayer = nullptr;
for (const auto& layer : style->layers()) {
@ -71,8 +65,46 @@ void for_each_layer(const Widget* widget,
callback(*bestLayer);
}
void for_each_layer(const Widget* widget,
const Style* style,
std::function<void(const Style::Layer&)> callback)
{
for_each_layer(
PaintWidgetPartInfo::getStyleFlagsForWidget(widget),
style,
callback);
}
} // anonymous namespace
PaintWidgetPartInfo::PaintWidgetPartInfo()
{
bgColor = gfx::ColorNone;
styleFlags = 0;
text = nullptr;
mnemonic = 0;
}
PaintWidgetPartInfo::PaintWidgetPartInfo(const Widget* widget)
{
bgColor = (!widget->isTransparent() ?
widget->bgColor():
gfx::ColorNone);
styleFlags = PaintWidgetPartInfo::getStyleFlagsForWidget(widget);
text = &widget->text();
mnemonic = widget->mnemonic();
}
// static
int PaintWidgetPartInfo::getStyleFlagsForWidget(const Widget* widget)
{
return
(widget->isEnabled() ? 0: Style::Layer::kDisabled) |
(widget->isSelected() ? Style::Layer::kSelected: 0) |
(widget->hasMouse() ? Style::Layer::kMouse: 0) |
(widget->hasFocus() ? Style::Layer::kFocus: 0);
}
Theme::Theme()
: m_guiscale(1)
{
@ -139,26 +171,38 @@ void Theme::setDecorativeWidgetBounds(Widget* widget)
}
}
void Theme::paintWidgetPart(Graphics* g,
const Style* style,
const gfx::Rect& bounds,
const PaintWidgetPartInfo& info)
{
ASSERT(g);
ASSERT(style);
// External background
if (!gfx::is_transparent(info.bgColor))
g->fillRect(info.bgColor, bounds);
gfx::Rect rc = bounds;
gfx::Color outBgColor = gfx::ColorNone;
for_each_layer(
info.styleFlags, style,
[this, g, &info, &rc, &outBgColor](const Style::Layer& layer) {
paintLayer(g, layer,
(info.text ? *info.text: std::string()),
info.mnemonic, rc, outBgColor);
});
}
void Theme::paintWidget(Graphics* g,
const Widget* widget,
const Style* style,
const gfx::Rect& bounds)
{
ASSERT(g);
ASSERT(widget);
ASSERT(style);
// External background
if (!widget->isTransparent())
g->fillRect(widget->bgColor(), bounds);
gfx::Rect rc = bounds;
gfx::Color bgColor = gfx::ColorNone;
for_each_layer(
widget, style,
[this, g, widget, &rc, &bgColor](const Style::Layer& layer) {
paintLayer(g, widget, layer, rc, bgColor);
});
PaintWidgetPartInfo info(widget);
paintWidgetPart(g, style, bounds, info);
}
void Theme::paintScrollBar(Graphics* g,
@ -168,15 +212,14 @@ void Theme::paintScrollBar(Graphics* g,
const gfx::Rect& bounds,
const gfx::Rect& thumbBounds)
{
paintWidget(g, widget, style, bounds);
gfx::Rect rc = thumbBounds;
gfx::Color bgColor = gfx::ColorNone;
for_each_layer(
widget, thumbStyle,
[this, g, widget, &rc, &bgColor](const Style::Layer& layer) {
paintLayer(g, widget, layer, rc, bgColor);
});
PaintWidgetPartInfo info(widget);
paintWidgetPart(g, style, bounds, info);
// TODO flags for the thumb could have "mouse" only
// when the mouse is inside the thumb
info.bgColor = gfx::ColorNone;
paintWidgetPart(g, thumbStyle, thumbBounds, info);
}
void Theme::paintTooltip(Graphics* g,
@ -241,8 +284,9 @@ void Theme::paintTooltip(Graphics* g,
}
void Theme::paintLayer(Graphics* g,
const Widget* widget,
const Style::Layer& layer,
const std::string& text,
const int mnemonic,
gfx::Rect& rc,
gfx::Color& bgColor)
{
@ -350,13 +394,13 @@ void Theme::paintLayer(Graphics* g,
gfx::Rect textBounds = rc;
textBounds.offset(layer.offset());
g->drawAlignedUIText(widget->text(),
g->drawAlignedUIText(text,
layer.color(),
bgColor,
textBounds, layer.align());
}
else {
gfx::Size textSize = g->measureUIText(widget->text());
gfx::Size textSize = g->measureUIText(text);
gfx::Point pt;
if (layer.align() & LEFT)
@ -375,10 +419,10 @@ void Theme::paintLayer(Graphics* g,
pt += layer.offset();
g->drawUIText(widget->text(),
g->drawUIText(text,
layer.color(),
bgColor,
pt, widget->mnemonic());
pt, mnemonic);
}
}
break;
@ -389,9 +433,8 @@ void Theme::paintLayer(Graphics* g,
gfx::Size iconSize(icon->width(), icon->height());
gfx::Point pt;
if (layer.align() & LEFT) {
if (layer.align() & LEFT)
pt.x = rc.x;
}
else if (layer.align() & RIGHT)
pt.x = rc.x+rc.w-iconSize.w;
else
@ -404,6 +447,8 @@ void Theme::paintLayer(Graphics* g,
else
pt.y = rc.y+rc.h/2-iconSize.h/2;
pt += layer.offset();
if (layer.color() != gfx::ColorNone)
g->drawColoredRgbaSurface(icon, layer.color(), pt.x, pt.y);
else

View File

@ -33,6 +33,18 @@ namespace ui {
class SizeHintEvent;
class Widget;
struct PaintWidgetPartInfo {
gfx::Color bgColor;
int styleFlags; // ui::Style::Layer flags
const std::string* text;
int mnemonic;
PaintWidgetPartInfo();
PaintWidgetPartInfo(const Widget* widget);
static int getStyleFlagsForWidget(const Widget* widget);
};
class Theme {
public:
Theme();
@ -65,6 +77,11 @@ namespace ui {
virtual void paintTextBox(PaintEvent& ev) = 0;
virtual void paintViewViewport(PaintEvent& ev) = 0;
virtual void paintWidgetPart(Graphics* g,
const Style* style,
const gfx::Rect& bounds,
const PaintWidgetPartInfo& info);
// Default implementation to draw widgets with new ui::Styles
virtual void paintWidget(Graphics* g,
const Widget* widget,
@ -113,8 +130,9 @@ namespace ui {
private:
void paintLayer(Graphics* g,
const Widget* widget,
const Style::Layer& layer,
const std::string& text,
const int mnemonic,
gfx::Rect& rc,
gfx::Color& bgColor);
void measureLayer(const Widget* widget,