diff --git a/data/extensions/aseprite-theme/dark/sheet.png b/data/extensions/aseprite-theme/dark/sheet.png
index c62a599a5..f92d9ebf1 100644
Binary files a/data/extensions/aseprite-theme/dark/sheet.png and b/data/extensions/aseprite-theme/dark/sheet.png differ
diff --git a/data/extensions/aseprite-theme/dark/theme.xml b/data/extensions/aseprite-theme/dark/theme.xml
index 60acabbe1..112062391 100644
--- a/data/extensions/aseprite-theme/dark/theme.xml
+++ b/data/extensions/aseprite-theme/dark/theme.xml
@@ -7,7 +7,7 @@
-
+
@@ -28,7 +28,7 @@
-
+
@@ -113,7 +113,6 @@
-
@@ -184,18 +183,18 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -207,11 +206,12 @@
-
-
-
-
-
+
+
+
+
+
+
@@ -425,10 +425,10 @@
-
-
-
-
+
+
+
+
@@ -615,7 +615,7 @@
-
-
-
-
-
-
@@ -1018,10 +1018,109 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/extensions/aseprite-theme/sheet.png b/data/extensions/aseprite-theme/sheet.png
index 0f85aeb4c..d32ef086a 100644
Binary files a/data/extensions/aseprite-theme/sheet.png and b/data/extensions/aseprite-theme/sheet.png differ
diff --git a/data/extensions/aseprite-theme/theme.xml b/data/extensions/aseprite-theme/theme.xml
index de277a9ee..3fbffdf72 100644
--- a/data/extensions/aseprite-theme/theme.xml
+++ b/data/extensions/aseprite-theme/theme.xml
@@ -6,7 +6,7 @@
-
+
@@ -27,7 +27,7 @@
-
+
@@ -109,7 +109,6 @@
-
@@ -180,18 +179,18 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -203,11 +202,12 @@
-
-
-
-
-
+
+
+
+
+
+
@@ -421,10 +421,10 @@
-
-
-
-
+
+
+
+
@@ -608,7 +608,7 @@
-
-
-
-
-
-
@@ -752,7 +752,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/widgets/canvas_size.xml b/data/widgets/canvas_size.xml
index 725d12ea7..0e9b4bdee 100644
--- a/data/widgets/canvas_size.xml
+++ b/data/widgets/canvas_size.xml
@@ -14,15 +14,15 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/data/widgets/debugger.xml b/data/widgets/debugger.xml
index d365d3dfb..fed38cd41 100644
--- a/data/widgets/debugger.xml
+++ b/data/widgets/debugger.xml
@@ -5,10 +5,10 @@
-
-
-
-
+
+
+
+
diff --git a/data/widgets/dynamics.xml b/data/widgets/dynamics.xml
index 0542a340c..8afc83c76 100644
--- a/data/widgets/dynamics.xml
+++ b/data/widgets/dynamics.xml
@@ -16,16 +16,16 @@
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/data/widgets/keyboard_shortcuts.xml b/data/widgets/keyboard_shortcuts.xml
index a721696a5..bb4975909 100644
--- a/data/widgets/keyboard_shortcuts.xml
+++ b/data/widgets/keyboard_shortcuts.xml
@@ -67,28 +67,36 @@
diff --git a/data/widgets/new_sprite.xml b/data/widgets/new_sprite.xml
index 2041ef933..dba6e9421 100644
--- a/data/widgets/new_sprite.xml
+++ b/data/widgets/new_sprite.xml
@@ -15,16 +15,16 @@
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/data/widgets/options.xml b/data/widgets/options.xml
index df9f258b3..9b7da391c 100644
--- a/data/widgets/options.xml
+++ b/data/widgets/options.xml
@@ -35,8 +35,8 @@
-
-
+
+
diff --git a/data/widgets/outline.xml b/data/widgets/outline.xml
index c7122501b..49891b9ba 100644
--- a/data/widgets/outline.xml
+++ b/data/widgets/outline.xml
@@ -20,15 +20,15 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/src/app/commands/cmd_canvas_size.cpp b/src/app/commands/cmd_canvas_size.cpp
index 5eef6b793..50a31ce7a 100644
--- a/src/app/commands/cmd_canvas_size.cpp
+++ b/src/app/commands/cmd_canvas_size.cpp
@@ -15,7 +15,6 @@
#include "app/doc_api.h"
#include "app/modules/gui.h"
#include "app/tx.h"
-#include "app/ui/button_set.h"
#include "app/ui/color_bar.h"
#include "app/ui/doc_view.h"
#include "app/ui/editor/editor.h"
diff --git a/src/app/commands/cmd_new_file.cpp b/src/app/commands/cmd_new_file.cpp
index 9fdd2e26d..02b7fa269 100644
--- a/src/app/commands/cmd_new_file.cpp
+++ b/src/app/commands/cmd_new_file.cpp
@@ -20,7 +20,6 @@
#include "app/i18n/strings.h"
#include "app/modules/palettes.h"
#include "app/pref/preferences.h"
-#include "app/ui/button_set.h"
#include "app/ui/workspace.h"
#include "app/ui_context.h"
#include "app/util/clipboard.h"
diff --git a/src/app/commands/cmd_options.cpp b/src/app/commands/cmd_options.cpp
index faf8de681..14d5f0821 100644
--- a/src/app/commands/cmd_options.cpp
+++ b/src/app/commands/cmd_options.cpp
@@ -954,6 +954,7 @@ private:
}
m_themeVars = list;
themeVariants()->setVisible(list ? true: false);
+ themeVariants()->initTheme();
}
void fillExtensionsCombobox(ui::ComboBox* combobox,
diff --git a/src/app/commands/filters/cmd_hue_saturation.cpp b/src/app/commands/filters/cmd_hue_saturation.cpp
index d2c740dd9..c90059ba4 100644
--- a/src/app/commands/filters/cmd_hue_saturation.cpp
+++ b/src/app/commands/filters/cmd_hue_saturation.cpp
@@ -80,6 +80,7 @@ public:
m_sliders.setMode(ColorSliders::Mode::Relative);
m_sliders.ColorChange.connect([this]{ onChangeControls(); });
+ initTheme();
onChangeMode();
}
diff --git a/src/app/commands/filters/filter_target_buttons.cpp b/src/app/commands/filters/filter_target_buttons.cpp
index 0e36b1e01..d30475a7d 100644
--- a/src/app/commands/filters/filter_target_buttons.cpp
+++ b/src/app/commands/filters/filter_target_buttons.cpp
@@ -68,6 +68,7 @@ FilterTargetButtons::FilterTargetButtons(int imgtype, bool withChannels)
// Create the button to select which cels will be modified by the
// filter.
m_cels = addItem(getCelsTargetText(), 4, 1);
+ initTheme();
}
void FilterTargetButtons::setTarget(const int target)
diff --git a/src/app/ui/brush_popup.cpp b/src/app/ui/brush_popup.cpp
index 62e0c543d..c50066908 100644
--- a/src/app/ui/brush_popup.cpp
+++ b/src/app/ui/brush_popup.cpp
@@ -154,7 +154,7 @@ public:
, m_brushes(App::instance()->brushes())
, m_slot(slot) {
auto theme = skin::SkinTheme::get(this);
- setIcon(theme->parts.iconArrowDown(), true);
+ setIcon(theme->parts.iconArrowDown());
}
private:
@@ -283,7 +283,7 @@ class NewBrushOptionsItem : public ButtonSet::Item {
public:
NewBrushOptionsItem() {
auto theme = skin::SkinTheme::get(this);
- setIcon(theme->parts.iconArrowDown(), true);
+ setIcon(theme->parts.iconArrowDown());
}
private:
@@ -362,8 +362,7 @@ BrushPopup::BrushPopup()
for (const auto& brush : brushes.getStandardBrushes()) {
m_standardBrushes.addItem(
new SelectBrushItem(
- BrushSlot(BrushSlot::Flags::BrushType, brush)))
- ->setMono(true);
+ BrushSlot(BrushSlot::Flags::BrushType, brush)), "standard_brush");
}
m_standardBrushes.setTransparent(true);
@@ -428,12 +427,13 @@ void BrushPopup::regenerate(ui::Display* display,
}
m_customBrushes->addItem(new SelectBrushItem(brush, slot));
m_customBrushes->addItem(new BrushShortcutItem(shortcut, slot));
- m_customBrushes->addItem(new BrushOptionsItem(this, slot));
+ m_customBrushes->addItem(new BrushOptionsItem(this, slot), "buttonset_item_icon_mono");
}
m_customBrushes->addItem(new NewCustomBrushItem, 2, 1);
- m_customBrushes->addItem(new NewBrushOptionsItem);
+ m_customBrushes->addItem(new NewBrushOptionsItem, "buttonset_item_icon_mono");
m_customBrushes->setExpansive(true);
+ m_customBrushes->initTheme();
m_box.addChild(m_customBrushes);
// Resize the window and change the hot region.
@@ -460,12 +460,14 @@ void BrushPopup::onBrushChanges()
os::SurfaceRef BrushPopup::createSurfaceForBrush(const BrushRef& origBrush,
const bool useOriginalImage)
{
+ constexpr int kMaxSize = 9;
+
Image* image = nullptr;
BrushRef brush = origBrush;
if (brush) {
- if (brush->type() != kImageBrushType && brush->size() > 10) {
+ if (brush->type() != kImageBrushType && brush->size() > kMaxSize) {
brush.reset(new Brush(*brush));
- brush->setSize(10);
+ brush->setSize(kMaxSize);
}
// Show the original image in the popup (without the image colors
// modified if there were some modification).
@@ -476,8 +478,8 @@ os::SurfaceRef BrushPopup::createSurfaceForBrush(const BrushRef& origBrush,
}
os::SurfaceRef surface = os::instance()->makeRgbaSurface(
- std::min(10, image ? image->width(): 4),
- std::min(10, image ? image->height(): 4));
+ std::min(kMaxSize, (image ? image->width(): 4)),
+ std::min(kMaxSize, (image ? image->height(): 4)));
if (image) {
Palette* palette = get_current_palette();
@@ -493,6 +495,8 @@ os::SurfaceRef BrushPopup::createSurfaceForBrush(const BrushRef& origBrush,
if (image->pixelFormat() == IMAGE_BITMAP)
delete palette;
+
+ surface->applyScale(guiscale());
}
else {
surface->clear();
diff --git a/src/app/ui/button_set.cpp b/src/app/ui/button_set.cpp
index d72dd2c41..361fef8a8 100644
--- a/src/app/ui/button_set.cpp
+++ b/src/app/ui/button_set.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2018-2022 Igara Studio S.A.
+// Copyright (C) 2018-2023 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
@@ -13,6 +13,7 @@
#include "app/modules/gui.h"
#include "app/ui/skin/skin_theme.h"
+#include "fmt/format.h"
#include "gfx/color.h"
#include "os/surface.h"
#include "ui/box.h"
@@ -48,22 +49,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 +68,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 +109,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 +174,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 +200,70 @@ 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* styleIdStr)
+{
+ std::string styleId;
+ if (styleIdStr)
+ styleId = styleIdStr;
+
+ item->InitTheme.connect(
+ [item, styleId] {
+ auto theme = SkinTheme::get(item);
+ ui::Style* style;
+ if (!styleId.empty()) {
+ style = theme->getStyleById(styleId);
+ if (!style)
+ throw base::Exception(fmt::format("Style {} not found", styleId));
+ }
+ else {
+ style = theme->styles.buttonsetItemIcon();
+ if (!item->text().empty()) {
+ style = (item->icon() ? theme->styles.buttonsetItemTextTopIconBottom() :
+ theme->styles.buttonsetItemText());
+ }
+ }
+
+ item->setStyle(style);
+ }
+ );
addChildInCell(item, hspan, vspan, HORIZONTAL | VERTICAL);
return item;
}
diff --git a/src/app/ui/button_set.h b/src/app/ui/button_set.h
index 5a15da0aa..98f3786ed 100644
--- a/src/app/ui/button_set.h
+++ b/src/app/ui/button_set.h
@@ -12,6 +12,7 @@
#include "app/ui/skin/skin_part.h"
#include "obs/signal.h"
#include "ui/grid.h"
+#include "ui/style.h"
#include
@@ -19,24 +20,20 @@ namespace app {
class ButtonSet : public ui::Grid {
public:
- class Item : public ui::Widget {
+ 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 {
@@ -47,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;
diff --git a/src/app/ui/color_bar.cpp b/src/app/ui/color_bar.cpp
index 3f42b1747..67dd48cb3 100644
--- a/src/app/ui/color_bar.cpp
+++ b/src/app/ui/color_bar.cpp
@@ -186,19 +186,35 @@ ColorBar::ColorBar(int align, TooltipManager* tooltipManager)
auto theme = SkinTheme::get(this);
- m_editPal.addItem(theme->parts.timelineOpenPadlockActive());
- m_buttons.addItem(theme->parts.palSort());
- m_buttons.addItem(theme->parts.palPresets());
- m_buttons.addItem(theme->parts.palOptions());
- m_tilesButton.addItem(theme->parts.tiles());
+ auto item = m_editPal.addItem("");
+ item->InitTheme.connect(
+ [this, item](){
+ auto style =
+ (m_editMode ? SkinTheme::instance()->styles.palEditUnlock() :
+ SkinTheme::instance()->styles.palEditLock());
+ item->setStyle(style);
+ });
+ m_buttons.addItem(theme->parts.palSort(), "pal_button");
+ m_buttons.addItem(theme->parts.palPresets(), "pal_button");
+ m_buttons.addItem(theme->parts.palOptions(), "pal_button");
+ item = m_tilesButton.addItem(theme->parts.tiles());
+ item->InitTheme.connect(
+ [this, item]() {
+ auto theme = SkinTheme::instance();
+ const bool editTiles = (canEditTiles() &&
+ m_tilemapMode == TilemapMode::Tiles);
+ auto style = (editTiles ? theme->styles.editTilesMode() :
+ theme->styles.editPixelsMode());
+ item->setStyle(style);
+ });
static_assert(0 == int(TilesetMode::Manual) &&
1 == int(TilesetMode::Auto) &&
2 == int(TilesetMode::Stack), "Tileset mode buttons doesn't match TilesetMode enum values");
- m_tilesetModeButtons.addItem(theme->parts.tilesManual());
- m_tilesetModeButtons.addItem(theme->parts.tilesAuto());
- m_tilesetModeButtons.addItem(theme->parts.tilesStack());
+ m_tilesetModeButtons.addItem(theme->parts.tilesManual(), "pal_button");
+ m_tilesetModeButtons.addItem(theme->parts.tilesAuto(), "pal_button");
+ m_tilesetModeButtons.addItem(theme->parts.tilesStack(), "pal_button");
setTilesetMode(m_tilesetMode);
m_paletteView.setColumns(8);
@@ -516,13 +532,12 @@ bool ColorBar::inEditMode() const
void ColorBar::setEditMode(bool state)
{
- auto theme = SkinTheme::get(this);
- ButtonSet::Item* item = m_editPal.getItem(0);
-
m_editMode = state;
- item->setIcon(state ? theme->parts.timelineOpenPadlockActive():
- theme->parts.timelineClosedPadlockNormal());
- item->setHotColor(state ? theme->colors.editPalFace(): gfx::ColorNone);
+
+ // The item icon/style will be set depending on m_editMode state.
+ ButtonSet::Item* item = m_editPal.getItem(0);
+ item->initTheme();
+ item->invalidate();
// Deselect color entries when we cancel editing
if (!state)
@@ -553,16 +568,11 @@ void ColorBar::setTilemapMode(TilemapMode mode)
void ColorBar::updateFromTilemapMode()
{
- SkinTheme* theme = static_cast(this->theme());
ButtonSet::Item* item = m_tilesButton.getItem(0);
-
const bool canEditTiles = this->canEditTiles();
const bool editTiles = (canEditTiles &&
m_tilemapMode == TilemapMode::Tiles);
-
- item->setHotColor(editTiles ? theme->colors.editPalFace():
- gfx::ColorNone);
- item->setMono(true);
+ item->initTheme();
if (Preferences::instance().colorBar.showColorAndTiles()) {
m_scrollablePalView.setVisible(true);
diff --git a/src/app/ui/color_sliders.cpp b/src/app/ui/color_sliders.cpp
index 7bec9ac41..48c779bc9 100644
--- a/src/app/ui/color_sliders.cpp
+++ b/src/app/ui/color_sliders.cpp
@@ -241,7 +241,6 @@ ColorSliders::ColorSliders()
, m_color(app::Color::fromMask())
{
addChild(&m_grid);
- m_grid.setChildSpacing(0);
// Same order as in Channel enum
static_assert(Channel::Red == (Channel)0, "");
@@ -258,6 +257,12 @@ ColorSliders::ColorSliders()
addSlider(Channel::Gray, "V", 0, 255, -100, 100);
addSlider(Channel::Alpha, "A", 0, 255, -100, 100);
+ InitTheme.connect(
+ [this] {
+ m_grid.setChildSpacing(0);
+ }
+ );
+
m_appConn = App::instance()
->ColorSpaceChange.connect([this]{ invalidate(); });
}
diff --git a/src/app/ui/context_bar.cpp b/src/app/ui/context_bar.cpp
index d0b3e6100..24db7a69d 100644
--- a/src/app/ui/context_bar.cpp
+++ b/src/app/ui/context_bar.cpp
@@ -162,7 +162,7 @@ public:
, m_brushes(App::instance()->brushes()) {
SkinPartPtr part(new SkinPart);
part->setBitmap(0, BrushPopup::createSurfaceForBrush(BrushRef(nullptr)));
- addItem(part);
+ addItem(part, "brush_type");
m_popupWindow.Open.connect(
[this]{
@@ -182,7 +182,11 @@ public:
part->setBitmap(0, BrushPopup::createSurfaceForBrush(brush));
const bool mono = (brush->type() != kImageBrushType);
- getItem(0)->setIcon(part, mono);
+ getItem(0)->setIcon(part);
+ auto style = mono ? SkinTheme::instance()->styles.brushTypeMono() :
+ SkinTheme::instance()->styles.brushType();
+ getItem(0)->setStyle(style);
+
}
void switchPopup() {
@@ -380,7 +384,7 @@ class ContextBar::PaintBucketSettingsField : public ButtonSet {
public:
PaintBucketSettingsField() : ButtonSet(1) {
auto theme = SkinTheme::get(this);
- addItem(theme->parts.timelineGear());
+ addItem(theme->parts.timelineGear(), "context_bar_button");
}
protected:
@@ -454,6 +458,7 @@ protected:
}
});
+ menu.initTheme();
menu.showPopup(gfx::Point(bounds.x, bounds.y2()),
display());
deselectItems();
@@ -466,7 +471,7 @@ public:
InkTypeField(ContextBar* owner) : ButtonSet(1)
, m_owner(owner) {
auto theme = SkinTheme::get(this);
- addItem(theme->parts.inkSimple());
+ addItem(theme->parts.inkSimple(), "ink_type");
}
void setInkType(InkType inkType) {
@@ -863,7 +868,7 @@ class ContextBar::PivotField : public ButtonSet {
public:
PivotField()
: ButtonSet(1) {
- addItem(SkinTheme::get(this)->parts.pivotCenter());
+ addItem(SkinTheme::get(this)->parts.pivotCenter(), "pivot_field");
m_pivotConn = Preferences::instance().selection.pivotPosition.AfterChange.connect(
[this]{ onPivotChange(); });
@@ -883,15 +888,15 @@ private:
CheckBox visible(Strings::context_bar_default_display_pivot());
HBox box;
ButtonSet buttonset(3);
- buttonset.addItem(theme->parts.pivotNorthwest());
- buttonset.addItem(theme->parts.pivotNorth());
- buttonset.addItem(theme->parts.pivotNortheast());
- buttonset.addItem(theme->parts.pivotWest());
- buttonset.addItem(theme->parts.pivotCenter());
- buttonset.addItem(theme->parts.pivotEast());
- buttonset.addItem(theme->parts.pivotSouthwest());
- buttonset.addItem(theme->parts.pivotSouth());
- buttonset.addItem(theme->parts.pivotSoutheast());
+ buttonset.addItem(theme->parts.pivotNorthwest(), "pivot_dir");
+ buttonset.addItem(theme->parts.pivotNorth(), "pivot_dir");
+ buttonset.addItem(theme->parts.pivotNortheast(), "pivot_dir");
+ buttonset.addItem(theme->parts.pivotWest(), "pivot_dir");
+ buttonset.addItem(theme->parts.pivotCenter(), "pivot_dir");
+ buttonset.addItem(theme->parts.pivotEast(), "pivot_dir");
+ buttonset.addItem(theme->parts.pivotSouthwest(), "pivot_dir");
+ buttonset.addItem(theme->parts.pivotSouth(), "pivot_dir");
+ buttonset.addItem(theme->parts.pivotSoutheast(), "pivot_dir");
box.addChild(&buttonset);
menu.addChild(&visible);
@@ -902,6 +907,7 @@ private:
app::gen::PivotPosition pos = Preferences::instance().selection.pivotPosition();
visible.setSelected(isVisible);
buttonset.setSelectedItem(int(pos));
+ buttonset.initTheme();
visible.Click.connect(
[&visible](){
@@ -1144,7 +1150,7 @@ public:
DynamicsField(ContextBar* ctxBar)
: ButtonSet(1)
, m_ctxBar(ctxBar) {
- addItem(SkinTheme::get(this)->parts.dynamics());
+ addItem(SkinTheme::get(this)->parts.dynamics(), "dynamics_field");
}
void switchPopup() {
@@ -1276,8 +1282,8 @@ public:
GradientTypeField() : ButtonSet(2) {
auto theme = SkinTheme::get(this);
- addItem(theme->parts.linearGradient());
- addItem(theme->parts.radialGradient());
+ addItem(theme->parts.linearGradient(), "context_bar_button");
+ addItem(theme->parts.radialGradient(), "context_bar_button");
setSelectedItem(0);
}
@@ -1299,8 +1305,8 @@ public:
DropPixelsField() : ButtonSet(2) {
auto theme = SkinTheme::get(this);
- addItem(theme->parts.dropPixelsOk());
- addItem(theme->parts.dropPixelsCancel());
+ addItem(theme->parts.dropPixelsOk(), "context_bar_button");
+ addItem(theme->parts.dropPixelsCancel(), "context_bar_button");
setOfferCapture(false);
}
@@ -1407,9 +1413,9 @@ public:
SymmetryField() : ButtonSet(3) {
setMultiMode(MultiMode::Set);
auto theme = SkinTheme::get(this);
- addItem(theme->parts.horizontalSymmetry());
- addItem(theme->parts.verticalSymmetry());
- addItem("...");
+ addItem(theme->parts.horizontalSymmetry(), "symmetry_field");
+ addItem(theme->parts.verticalSymmetry(), "symmetry_field");
+ addItem("...", "symmetry_options");
}
void setupTooltips(TooltipManager* tooltipManager) {
@@ -1544,8 +1550,8 @@ public:
m_combobox.setExpansive(true);
m_combobox.setMinSize(gfx::Size(256*guiscale(), 0));
- m_action.addItem(theme->parts.iconUserData())->setMono(true);
- m_action.addItem(theme->parts.iconClose())->setMono(true);
+ m_action.addItem(theme->parts.iconUserData(), "buttonset_item_icon_mono");
+ m_action.addItem(theme->parts.iconClose(), "buttonset_item_icon_mono");
m_action.ItemChange.connect(
[this](ButtonSet::Item* item){
onAction(m_action.selectedItem());
diff --git a/src/app/ui/selection_mode_field.cpp b/src/app/ui/selection_mode_field.cpp
index 8914d7056..bf1f4437c 100644
--- a/src/app/ui/selection_mode_field.cpp
+++ b/src/app/ui/selection_mode_field.cpp
@@ -24,10 +24,10 @@ SelectionModeField::SelectionModeField()
{
auto theme = SkinTheme::get(this);
- addItem(theme->parts.selectionReplace());
- addItem(theme->parts.selectionAdd());
- addItem(theme->parts.selectionSubtract());
- addItem(theme->parts.selectionIntersect());
+ addItem(theme->parts.selectionReplace(), "selection_mode");
+ addItem(theme->parts.selectionAdd(), "selection_mode");
+ addItem(theme->parts.selectionSubtract(), "selection_mode");
+ addItem(theme->parts.selectionIntersect(), "selection_mode");
setSelectedItem((int)Preferences::instance().selection.mode());
}
diff --git a/src/app/ui/skin/skin_theme.cpp b/src/app/ui/skin/skin_theme.cpp
index d0e1f9c9f..aef0eaa9e 100644
--- a/src/app/ui/skin/skin_theme.cpp
+++ b/src/app/ui/skin/skin_theme.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2019-2022 Igara Studio S.A.
+// Copyright (C) 2019-2023 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@@ -44,6 +44,7 @@
#include
#include
+#include
#define BGCOLOR (getWidgetBgColor(widget))
@@ -56,37 +57,76 @@ using namespace ui;
// TODO For backward compatibility, in future versions we should remove this (extensions are preferred)
const char* SkinTheme::kThemesFolderName = "themes";
-// This class offer backward compatibility with old themes, completing
-// or changing styles from the default theme to match the default
-// theme of previous versions, so third-party themes can look like
-// they are running in the old Aseprite without any modification.
-struct app::skin::SkinTheme::BackwardCompatibility {
- bool hasSliderStyle = false;
- void notifyStyleExistence(const char* styleId) {
- if (std::strcmp(styleId, "slider") == 0)
- hasSliderStyle = true;
+// Offers backward compatibility with old themes, copying missing
+// styles (raw XML