Update ButtonSet to use theme's styles

This commit is contained in:
Martín Capello 2022-12-15 13:03:23 -03:00 committed by David Capello
parent 40426075f2
commit 3ab993d1d6
3 changed files with 90 additions and 139 deletions

View File

@ -1013,5 +1013,31 @@
<text color="slider_empty_text" align="center middle" />
<text color="slider_empty_text" align="center middle" state="focus" />
</style>
<style id="buttonset" gap-rows="-3" gap-columns="-1" />
<style id="buttonset_item" font="mini">
<background-border part="buttonset_item_normal" />
<background-border part="buttonset_item_hot" state="selected" />
<background-border part="buttonset_item_hot" state="mouse" />
<background-border part="buttonset_item_hot_focused" state="selected focus" />
<background-border part="buttonset_item_hot_focused" state="mouse focus" />
<background-border part="buttonset_item_pushed" state="capture selected" />
<background-border part="buttonset_item_pushed" state="mouse capture" />
<background-border part="buttonset_item_focused" state="focus" />
</style>
<style id="buttonset_item_icon" extends="buttonset_item">
<icon />
<icon state="disabled" color="disabled" />
<icon state="capture selected" color="button_selected_text" />
</style>
<style id="buttonset_item_text" extends="buttonset_item" padding="1">
<text color="button_normal_text" y="1" />
<text color="button_hot_text" state="selected" y="1" />
<text color="button_hot_text" state="mouse" y="1" />
<text color="button_selected_text" state="mouse capture" y="1" />
<text color="button_selected_text" state="capture selected" y="1" />
<text color="background" x="1" y="2" state="disabled" />
<newlayer />
<text color="disabled" state="disabled" align="top" y="1" />
</style>
</styles>
</theme>

View File

@ -48,22 +48,15 @@ WidgetType buttonset_item_type()
ButtonSet::Item::Item()
: Widget(buttonset_item_type())
, m_icon(NULL)
, m_hotColor(gfx::ColorNone)
{
setup_mini_font(this);
setAlign(CENTER | MIDDLE);
setFocusStop(true);
}
void ButtonSet::Item::setHotColor(gfx::Color color)
{
m_hotColor = color;
}
void ButtonSet::Item::setIcon(const SkinPartPtr& icon, bool mono)
void ButtonSet::Item::setIcon(const SkinPartPtr& icon)
{
m_icon = icon;
m_mono = mono;
invalidate();
}
@ -74,97 +67,17 @@ ButtonSet* ButtonSet::Item::buttonSet()
void ButtonSet::Item::onPaint(ui::PaintEvent& ev)
{
auto theme = SkinTheme::get(this);
Graphics* g = ev.graphics();
gfx::Rect rc = clientBounds();
gfx::Color fg;
SkinPartPtr nw;
gfx::Rect boxRc, textRc, iconRc;
gfx::Size iconSize;
if (m_icon)
iconSize = m_icon->size();
if (style()) {
gfx::Rect rc = clientBounds();
Grid::Info info = buttonSet()->getChildInfo(this);
bool isLastCol = (info.col + info.hspan >= info.grid_cols);
bool isLastRow = (info.row + info.vspan >= info.grid_rows);
// When gaps are negative we need to compensate client bounds size so the painting is based on a
// complete button, and not just the part not overlapped.
if (buttonSet()->m_colgap < 0 && !isLastCol) rc.w -= buttonSet()->m_colgap;
if (buttonSet()->m_rowgap < 0 && !isLastRow) rc.h -= buttonSet()->m_rowgap;
getTextIconInfo(
&boxRc, &textRc, &iconRc,
CENTER | (hasText() ? BOTTOM: MIDDLE),
iconSize.w, iconSize.h);
Grid::Info info = buttonSet()->getChildInfo(this);
bool isLastCol = (info.col+info.hspan >= info.grid_cols);
bool isLastRow = (info.row+info.vspan >= info.grid_rows);
if (m_icon || isLastRow) {
textRc.y -= 2*guiscale();
iconRc.y -= 1*guiscale();
if (isLastRow && info.row > 0) iconRc.y -= 2*guiscale();
}
if (!gfx::is_transparent(bgColor()))
g->fillRect(bgColor(), g->getClipBounds());
if (isSelected() || hasMouseOver()) {
if (hasCapture()) {
nw = theme->parts.buttonsetItemPushed();
fg = theme->colors.buttonSelectedText();
}
else {
nw = (hasFocus() ? theme->parts.buttonsetItemHotFocused():
theme->parts.buttonsetItemHot());
fg = theme->colors.buttonHotText();
}
}
else {
nw = (hasFocus() ? theme->parts.buttonsetItemFocused():
theme->parts.buttonsetItemNormal());
fg = theme->colors.buttonNormalText();
}
if (!isLastCol)
rc.w += 1*guiscale();
if (!isLastRow) {
if (nw == theme->parts.buttonsetItemHotFocused())
rc.h += 2*guiscale();
else
rc.h += 3*guiscale();
}
theme->drawRect(g, rc, nw.get(),
gfx::is_transparent(m_hotColor));
if (!gfx::is_transparent(m_hotColor)) {
gfx::Rect rc2(rc);
gfx::Rect sprite(nw->spriteBounds());
gfx::Rect slices(nw->slicesBounds());
rc2.shrink(
gfx::Border(
slices.x-1, // TODO this "-1" is an ugly hack for the pal edit
// button, replace all this with styles
slices.y-1,
sprite.w-slices.w-slices.x-1,
sprite.h-slices.h-slices.y));
g->fillRect(m_hotColor, rc2);
}
if (m_icon) {
os::Surface* bmp = m_icon->bitmap(0);
if (!isEnabled())
g->drawColoredRgbaSurface(bmp, theme->colors.disabled(),
iconRc.x, iconRc.y);
else if (isSelected() && hasCapture())
g->drawColoredRgbaSurface(bmp, theme->colors.buttonSelectedText(),
iconRc.x, iconRc.y);
else if (m_mono)
g->drawColoredRgbaSurface(bmp, theme->colors.buttonNormalText(),
iconRc.x, iconRc.y);
else
g->drawRgbaSurface(bmp, iconRc.x, iconRc.y);
}
if (hasText()) {
g->setFont(AddRef(font()));
g->drawUIText(text(), fg, gfx::ColorNone, textRc.origin(), 0);
theme()->paintWidget(ev.graphics(), this, style(), rc);
}
}
@ -195,6 +108,7 @@ bool ButtonSet::Item::onProcessMessage(ui::Message* msg)
break;
case ui::kMouseDownMessage:
if (!isEnabled()) return true;
// Only for single-item and trigerred on mouse up ButtonSets: We
// save the current selected item to restore it just in case the
// user leaves the ButtonSet without releasing the mouse button
@ -259,38 +173,13 @@ bool ButtonSet::Item::onProcessMessage(ui::Message* msg)
case ui::kMouseLeaveMessage:
case ui::kMouseEnterMessage:
if (!isEnabled()) return true;
invalidate();
break;
}
return Widget::onProcessMessage(msg);
}
void ButtonSet::Item::onSizeHint(ui::SizeHintEvent& ev)
{
gfx::Size iconSize;
if (m_icon) {
iconSize = m_icon->size();
iconSize.w = std::max(iconSize.w, 16*guiscale());
iconSize.h = std::max(iconSize.h, 16*guiscale());
}
gfx::Rect boxRc;
getTextIconInfo(
&boxRc, NULL, NULL,
CENTER | (hasText() ? BOTTOM: MIDDLE),
iconSize.w, iconSize.h);
gfx::Size sz = boxRc.size();
if (hasText())
sz += 8*guiscale();
Grid::Info info = buttonSet()->getChildInfo(this);
if (info.row == info.grid_rows-1)
sz.h += 3*guiscale();
ev.setSizeHint(sz);
}
void ButtonSet::Item::onClick()
{
buttonSet()->onItemChange(this);
@ -310,28 +199,66 @@ ButtonSet::ButtonSet(int columns)
InitTheme.connect(
[this]{
noBorderNoChildSpacing();
// Set default buttonset style if it wasn't already set.
if (style() == SkinTheme::instance()->styles.grid()) {
setStyle(SkinTheme::instance()->styles.buttonset());
}
});
initTheme();
}
ButtonSet::Item* ButtonSet::addItem(const std::string& text, int hspan, int vspan)
ButtonSet::Item* ButtonSet::addItem(const std::string& text, const char* styleId)
{
return addItem(text, 1, 1, styleId);
}
ButtonSet::Item* ButtonSet::addItem(const std::string& text, int hspan, int vspan, const char* styleId)
{
Item* item = new Item();
item->setText(text);
addItem(item, hspan, vspan);
addItem(item, hspan, vspan, styleId);
return item;
}
ButtonSet::Item* ButtonSet::addItem(const skin::SkinPartPtr& icon, int hspan, int vspan)
ButtonSet::Item* ButtonSet::addItem(const skin::SkinPartPtr& icon, const char* styleId)
{
return addItem(icon, 1, 1, styleId);
}
ButtonSet::Item* ButtonSet::addItem(const skin::SkinPartPtr& icon, int hspan, int vspan, const char* styleId)
{
Item* item = new Item();
item->setIcon(icon);
addItem(item, hspan, vspan);
addItem(item, hspan, vspan, styleId);
return item;
}
ButtonSet::Item* ButtonSet::addItem(Item* item, int hspan, int vspan)
ButtonSet::Item* ButtonSet::addItem(Item* item, const char* styleId)
{
return addItem(item, 1, 1, styleId);
}
ButtonSet::Item* ButtonSet::addItem(Item* item, int hspan, int vspan, const char* styleId)
{
item->InitTheme.connect(
[item, styleId] {
ui::Style* style;
if (styleId) {
auto theme = SkinTheme::get(item);
style = theme->getStyleById(styleId);
if (!style)
throw base::Exception("Style %s not found", styleId);
}
else {
style = SkinTheme::instance()->styles.buttonsetItemIcon();
if (!item->text().empty()) {
style = item->icon() ? SkinTheme::instance()->styles.buttonsetItemTextTopIconBottom() :
SkinTheme::instance()->styles.buttonsetItemText();
}
}
item->setStyle(style);
}
);
addChildInCell(item, hspan, vspan, HORIZONTAL | VERTICAL);
return item;
}

View File

@ -23,22 +23,17 @@ namespace app {
class Item : public ui::Widget, public ui::Style::Layer::IconSurfaceProvider {
public:
Item();
void setHotColor(gfx::Color color);
void setIcon(const skin::SkinPartPtr& icon, bool mono = false);
void setMono(const bool mono) { m_mono = mono; }
void setIcon(const skin::SkinPartPtr& icon);
os::Surface* iconSurface() const override { return m_icon ? m_icon->bitmap(0) : nullptr; }
skin::SkinPartPtr icon() const { return m_icon; }
ButtonSet* buttonSet();
protected:
void onPaint(ui::PaintEvent& ev) override;
bool onProcessMessage(ui::Message* msg) override;
void onSizeHint(ui::SizeHintEvent& ev) override;
virtual void onClick();
virtual void onRightClick();
private:
skin::SkinPartPtr m_icon;
bool m_mono;
gfx::Color m_hotColor;
};
enum class MultiMode {
@ -49,9 +44,12 @@ namespace app {
ButtonSet(int columns);
Item* addItem(const std::string& text, int hspan = 1, int vspan = 1);
Item* addItem(const skin::SkinPartPtr& icon, int hspan = 1, int vspan = 1);
Item* addItem(Item* item, int hspan = 1, int vspan = 1);
Item* addItem(const std::string& text, const char* styleId);
Item* addItem(const std::string& text, int hspan = 1, int vspan = 1, const char* styleId = nullptr);
Item* addItem(const skin::SkinPartPtr& icon, const char* styleId);
Item* addItem(const skin::SkinPartPtr& icon, int hspan = 1, int vspan = 1, const char* styleId = nullptr);
Item* addItem(Item* item, const char* styleId);
Item* addItem(Item* item, int hspan = 1, int vspan = 1, const char* styleId = nullptr);
Item* getItem(int index);
int getItemIndex(const Item* item) const;