Convert label and view into new styles

In this way the WidgetLoader looks for new styles only.
master
David Capello 2017-02-14 14:55:45 -03:00
parent 17151cddcd
commit 7cb41729ab
29 changed files with 327 additions and 455 deletions

View File

@ -412,35 +412,6 @@
<stylesheet>
<!-- label -->
<style id="label">
<text color="text" />
</style>
<style id="label:disabled">
<text color="disabled" />
</style>
<!-- link -->
<style id="link">
<text color="link_text" />
</style>
<style id="link:hover">
<text color="link_hover" />
</style>
<!-- browser_link -->
<style id="browser_link" base="link">
<text padding-top="1" />
</style>
<!-- view -->
<style id="view">
<background part="sunken_normal" />
</style>
<style id="view:active">
<background part="sunken_focused" />
</style>
<!-- window -->
<style id="window">
<background color="window_face" part="window" />
@ -824,42 +795,6 @@
<icon part="tab_home_icon_active" />
</style>
<!-- workspace_label -->
<style id="workspace_label">
<text color="workspace_text" />
</style>
<!-- workspace_link -->
<style id="workspace_link">
<text color="workspace_link" valign="middle" />
</style>
<style id="workspace_link:hover">
<text color="workspace_link_hover" />
</style>
<!-- workspace_link -->
<style id="workspace_update_link" base="workspace_link">
<background part="button_normal" color="button_normal_face" />
<icon part="warning_box" align="right" x="-4" y="4" />
<text padding-left="4" />
</style>
<style id="workspace_update_link:hover">
<background part="button_hot" color="button_hot_face" />
<text color="button_hot_text" />
</style>
<style id="workspace_update_link:clicked">
<background part="button_selected" color="button_selected_face" />
<text color="button_selected_text" />
</style>
<!-- workspace_view -->
<style id="workspace_view">
<background part="editor_normal" />
</style>
<style id="workspace_view:active">
<background part="editor_selected" />
</style>
<!-- recent_file -->
<style id="recent_file">
<background color="background" />
@ -900,6 +835,59 @@
<styles>
<style id="label" padding="1">
<text color="text" align="left" />
<text color="disabled" align="left" state="disabled" />
</style>
<style id="link">
<text color="link_text" align="left" />
<text color="link_hover" align="left" state="mouse" />
</style>
<style id="browser_link" extends="link" padding-top="1">
</style>
<style id="workspace_label">
<text color="workspace_text" align="left" />
</style>
<style id="workspace_link">
<text color="workspace_link" align="left" />
<text color="workspace_link_hover" align="left" state="mouse" />
</style>
<style id="workspace_update_link" padding-right="16">
<background part="button_normal" />
<background part="button_hot" state="mouse" />
<background part="button_selected" state="selected" />
<icon part="warning_box" align="right" />
<text color="button_normal_text" />
<text color="button_hot_text" state="mouse" />
<text color="button_selected_text" state="selected" />
</style>
<style id="view">
<background color="window_face" />
<border part="sunken_normal" />
<border part="sunken_focused" state="focus" />
</style>
<style id="editor_view">
<border part="editor_normal" />
<border part="editor_selected" state="selected" />
</style>
<style id="workspace_view" border-top="4">
<border part="editor_normal" />
<border part="editor_selected" state="focus" />
</style>
<style id="colorbar_view">
<border part="editor_normal" />
<border part="editor_selected" state="focus" />
</style>
<style id="button">
<background part="button_normal" />
<background part="button_hot" state="mouse" />

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2016 David Capello
// Copyright (C) 2016-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -449,9 +449,7 @@ private:
if (word.size() > 4 &&
std::strncmp(word.c_str(), "http", 4) == 0) {
label = new LinkLabel(word);
label->setProperty(
SkinStylePropertyPtr(
new SkinStyleProperty(SkinTheme::instance()->styles.browserLink())));
label->setStyle(SkinTheme::instance()->newStyles.browserLink());
}
else
label = new Label(word);
@ -478,9 +476,7 @@ private:
void addLink(const std::string& url, const std::string& text) {
auto label = new LinkLabel(url, text);
label->setProperty(
SkinStylePropertyPtr(
new SkinStyleProperty(SkinTheme::instance()->styles.browserLink())));
label->setStyle(SkinTheme::instance()->newStyles.browserLink());
if (url.find(':') == std::string::npos) {
label->setUrl("");
@ -521,8 +517,7 @@ BrowserView::BrowserView()
m_view.attachToView(m_textBox);
m_view.setExpansive(true);
m_view.setProperty(SkinStylePropertyPtr(
new SkinStyleProperty(theme->styles.workspaceView())));
m_view.setStyle(theme->newStyles.workspaceView());
m_textBox->FileChange.connect(
[]{

View File

@ -103,24 +103,7 @@ protected:
ColorBar::ScrollableView::ScrollableView()
{
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
int l = theme->parts.editorSelected()->bitmapW()->width();
int t = theme->parts.editorSelected()->bitmapN()->height();
int r = theme->parts.editorSelected()->bitmapE()->width();
int b = theme->parts.editorSelected()->bitmapS()->height();
setBorder(gfx::Border(l, t, r, b));
}
void ColorBar::ScrollableView::onPaint(ui::PaintEvent& ev)
{
ui::Graphics* g = ev.graphics();
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
theme->drawRect(
g, clientBounds(),
(hasFocus() ? theme->parts.editorSelected().get():
theme->parts.editorNormal().get()),
false); // Do not fill the center portion
setStyle(theme->newStyles.colorbarView());
}
//////////////////////////////////////////////////////////////////////

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.
@ -133,8 +133,6 @@ namespace app {
class ScrollableView : public ui::View {
public:
ScrollableView();
protected:
void onPaint(ui::PaintEvent& ev) override;
};
class WarningIcon;

View File

@ -665,7 +665,7 @@ class ContextBar::InkShadesField : public HBox {
skin::Style::State state;
if (hasMouseOver()) state += Style::hover();
theme->styles.view()->paint(g, bounds, nullptr, state);
theme->paintWidget(g, this, theme->newStyles.view(), bounds);
bounds.shrink(3*guiscale());

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.
@ -80,7 +80,7 @@ DataRecoveryView::DataRecoveryView(crash::DataRecovery* dataRecovery)
m_listBox.setMultiselect(true);
m_view.setExpansive(true);
m_view.attachToView(&m_listBox);
m_view.setProperty(SkinStylePropertyPtr(new SkinStyleProperty(theme->styles.workspaceView())));
m_view.setStyle(theme->newStyles.workspaceView());
HBox* hbox = new HBox;
hbox->setBorder(gfx::Border(2, 0, 2, 0)*guiscale());

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.
@ -77,11 +77,10 @@ DevConsoleView::DevConsoleView()
m_bottomBox.addChild(&m_label);
m_bottomBox.addChild(m_entry);
m_view.setProperty(SkinStylePropertyPtr(
new SkinStyleProperty(theme->styles.workspaceView())));
m_view.setStyle(theme->newStyles.workspaceView());
m_view.attachToView(&m_textBox);
m_view.setExpansive(true);
m_entry->setExpansive(true);
m_entry->ExecuteCommand.connect(&DevConsoleView::onExecuteCommand, this);
}

View File

@ -41,13 +41,9 @@ EditorView::EditorView(EditorView::Type type)
, m_type(type)
{
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
int l = theme->parts.editorSelected()->bitmapW()->width();
int t = theme->parts.editorSelected()->bitmapN()->height();
int r = theme->parts.editorSelected()->bitmapE()->width();
int b = theme->parts.editorSelected()->bitmapS()->height();
setBorder(gfx::Border(l, t, r, b));
setBgColor(gfx::rgba(0, 0, 0)); // TODO Move this color to theme.xml
setStyle(theme->newStyles.editorView());
setupScrollbars();
m_scrollSettingsConn =
@ -57,31 +53,24 @@ EditorView::EditorView(EditorView::Type type)
void EditorView::onPaint(PaintEvent& ev)
{
Graphics* g = ev.graphics();
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
bool selected = false;
switch (m_type) {
// Only show the view selected if it is the current editor
case CurrentEditorMode:
selected = (editor()->isActive());
if (editor()->isActive())
enableFlags(SELECTED);
else
disableFlags(SELECTED);
break;
// Always show selected
case AlwaysSelected:
selected = true;
enableFlags(SELECTED);
break;
}
g->fillRect(bgColor(), clientBounds());
theme->drawRect(
g, clientBounds(),
(selected ?
theme->parts.editorSelected().get():
theme->parts.editorNormal().get()),
false); // Do not fill the center portion
View::onPaint(ev);
}
void EditorView::onResize(ResizeEvent& ev)

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.
@ -152,15 +152,7 @@ void HomeView::onNewUpdate(const std::string& url, const std::string& version)
checkUpdate()->setText("New " PACKAGE " v" + version + " available!");
checkUpdate()->setUrl(url);
checkUpdate()->setProperty(
SkinStylePropertyPtr(new SkinStyleProperty(theme->styles.workspaceUpdateLink())));
// TODO this should be in a skin.xml's <style>
gfx::Size iconSize = theme->styles.workspaceUpdateLink()->sizeHint(
nullptr, Style::State());
checkUpdate()->setBorder(gfx::Border(6*guiscale())+gfx::Border(
0, 0, iconSize.w, 0));
checkUpdate()->setStyle(theme->newStyles.workspaceUpdateLink());
checkUpdate()->setVisible(true);
layout();

View File

@ -602,10 +602,32 @@ void SkinTheme::loadXml(const std::string& skinId)
layer.setFlags(flags);
}
// Align
const char* alignValue = xmlLayer->Attribute("align");
if (alignValue) {
std::string alignString(alignValue);
int align = 0;
if (alignString.find("left") != std::string::npos) align |= LEFT;
if (alignString.find("center") != std::string::npos) align |= CENTER;
if (alignString.find("right") != std::string::npos) align |= RIGHT;
if (alignString.find("top") != std::string::npos) align |= TOP;
if (alignString.find("middle") != std::string::npos) align |= MIDDLE;
if (alignString.find("bottom") != std::string::npos) align |= BOTTOM;
if (alignString.find("wordwrap") != std::string::npos) align |= WORDWRAP;
layer.setAlign(align);
}
// Color
const char* colorId = xmlLayer->Attribute("color");
if (colorId) {
layer.setColor(getColorById(colorId));
auto it = m_colors_by_id.find(colorId);
if (it != m_colors_by_id.end())
layer.setColor(it->second);
else {
throw base::Exception("Color <%s color='%s' ...> was not found in '%s'\n",
layerName.c_str(), colorId,
xml_filename.c_str());
}
}
// Sprite sheet
@ -732,7 +754,11 @@ void SkinTheme::initWidget(Widget* widget)
break;
case kLabelWidget:
BORDER(1 * scale);
widget->setStyle(newStyles.label());
break;
case kLinkLabelWidget:
widget->setStyle(newStyles.link());
break;
case kListBoxWidget:
@ -812,13 +838,9 @@ void SkinTheme::initWidget(Widget* widget)
break;
case kViewWidget:
BORDER4(
parts.sunkenNormal()->bitmapW()->width()-1*scale,
parts.sunkenNormal()->bitmapN()->height(),
parts.sunkenNormal()->bitmapE()->width()-1*scale,
parts.sunkenNormal()->bitmapS()->height()-1*scale);
widget->setChildSpacing(0);
widget->setBgColor(colors.windowFace());
widget->setStyle(newStyles.view());
break;
case kViewScrollbarWidget:
@ -1150,53 +1172,6 @@ void SkinTheme::drawEntryText(ui::Graphics* g, ui::Entry* widget)
}
}
void SkinTheme::paintLabel(PaintEvent& ev)
{
Graphics* g = ev.graphics();
Label* widget = static_cast<Label*>(ev.getSource());
Style* style = styles.label();
gfx::Color bg = BGCOLOR;
Rect text, rc = widget->clientBounds();
SkinStylePropertyPtr styleProp = widget->getProperty(SkinStyleProperty::Name);
if (styleProp)
style = styleProp->getStyle();
if (!is_transparent(bg))
g->fillRect(bg, rc);
rc.shrink(widget->border());
Style::State state;
if (!widget->isEnabled()) state += Style::disabled();
widget->getTextIconInfo(NULL, &text);
style->paint(g, text, widget->text().c_str(), state);
}
void SkinTheme::paintLinkLabel(PaintEvent& ev)
{
Graphics* g = ev.graphics();
Widget* widget = static_cast<Widget*>(ev.getSource());
Style* style = styles.link();
Rect text, rc = widget->clientBounds();
gfx::Color bg = BGCOLOR;
SkinStylePropertyPtr styleProp = widget->getProperty(SkinStyleProperty::Name);
if (styleProp)
style = styleProp->getStyle();
Style::State state;
if (widget->hasMouseOver()) state += Style::hover();
if (widget->isSelected()) state += Style::clicked();
if (!widget->isEnabled()) state += Style::disabled();
if (!is_transparent(bg))
g->fillRect(bg, rc);
style->paint(g, rc, widget->text().c_str(), state);
}
void SkinTheme::paintListBox(PaintEvent& ev)
{
Graphics* g = ev.graphics();
@ -1569,27 +1544,6 @@ void SkinTheme::paintTextBox(ui::PaintEvent& ev)
BGCOLOR, colors.textboxText());
}
void SkinTheme::paintView(PaintEvent& ev)
{
Graphics* g = ev.graphics();
View* widget = static_cast<View*>(ev.getSource());
gfx::Rect bounds = widget->clientBounds();
gfx::Color bg = BGCOLOR;
Style* style = styles.view();
SkinStylePropertyPtr styleProp = widget->getProperty(SkinStyleProperty::Name);
if (styleProp)
style = styleProp->getStyle();
Style::State state;
if (widget->hasMouseOver()) state += Style::hover();
if (!is_transparent(bg))
g->fillRect(bg, bounds);
style->paint(g, bounds, nullptr, state);
}
void SkinTheme::paintViewScrollbar(PaintEvent& ev)
{
ScrollBar* widget = static_cast<ScrollBar*>(ev.getSource());

View File

@ -62,8 +62,6 @@ namespace app {
void paintCheckBox(ui::PaintEvent& ev) override;
void paintEntry(ui::PaintEvent& ev) override;
void paintGrid(ui::PaintEvent& ev) override;
void paintLabel(ui::PaintEvent& ev) override;
void paintLinkLabel(ui::PaintEvent& ev) override;
void paintListBox(ui::PaintEvent& ev) override;
void paintListItem(ui::PaintEvent& ev) override;
void paintMenu(ui::PaintEvent& ev) override;
@ -74,7 +72,6 @@ namespace app {
void paintSlider(ui::PaintEvent& ev) override;
void paintComboBoxEntry(ui::PaintEvent& ev) override;
void paintTextBox(ui::PaintEvent& ev) override;
void paintView(ui::PaintEvent& ev) override;
void paintViewScrollbar(ui::PaintEvent& ev) override;
void paintViewViewport(ui::PaintEvent& ev) override;
void paintWindow(ui::PaintEvent& ev) override;

View File

@ -25,6 +25,7 @@
#include "app/xml_document.h"
#include "app/xml_exception.h"
#include "base/bind.h"
#include "base/exception.h"
#include "base/fs.h"
#include "base/memory.h"
#include "she/system.h"
@ -575,18 +576,11 @@ void WidgetLoader::fillWidgetWithXmlElementAttributes(const TiXmlElement* elem,
if (styleid) {
SkinTheme* theme = static_cast<SkinTheme*>(root->theme());
// New styles
ui::Style* style = theme->getNewStyle(styleid);
if (style)
widget->setStyle(style);
else {
skin::Style* style = theme->getStyle(styleid);
if (style) {
SkinStylePropertyPtr prop(new SkinStyleProperty(style));
widget->setProperty(prop);
}
}
else
throw base::Exception("Style %s not found", styleid);
}
// Assign widget mnemonic from the character preceded by a '&'

View File

@ -1,4 +1,4 @@
# ASEPRITE
# Aseprite UI Library
# Copyright (C) 2001-2017 David Capello
if(WIN32)
@ -13,7 +13,6 @@ add_library(ui-lib
combobox.cpp
component.cpp
cursor.cpp
custom_label.cpp
entry.cpp
event.cpp
fit_bounds.cpp

View File

@ -274,10 +274,8 @@ void ButtonBase::onSizeHint(SizeHintEvent& ev)
{
// If there is a style specified in this widget, use the new generic
// widget to calculate the size hint.
if (style()) {
Widget::onSizeHint(ev);
return;
}
if (style())
return Widget::onSizeHint(ev);
gfx::Rect box;
gfx::Size iconSize = (m_iconInterface ? m_iconInterface->size(): gfx::Size(0, 0));

View File

@ -1,25 +0,0 @@
// Aseprite UI Library
// Copyright (C) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "ui/custom_label.h"
namespace ui {
CustomLabel::CustomLabel(const std::string& text)
: Label(text)
{
}
bool CustomLabel::onProcessMessage(Message* msg)
{
return Label::onProcessMessage(msg);
}
} // namespace ui

View File

@ -1,27 +0,0 @@
// Aseprite UI Library
// Copyright (C) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef UI_CUSTOM_LABEL_H_INCLUDED
#define UI_CUSTOM_LABEL_H_INCLUDED
#pragma once
#include "ui/label.h"
namespace ui {
class CustomLabel : public Label
{
public:
CustomLabel(const std::string& text);
protected:
bool onProcessMessage(Message* msg) override;
};
} // namespace ui
#endif

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -24,25 +24,4 @@ Label::Label(const std::string& text)
initTheme();
}
void Label::onSizeHint(SizeHintEvent& ev)
{
gfx::Size sz(0, 0);
if (hasText()) {
// Labels are not UIString
sz.w = font()->textLength(text().c_str());
sz.h = textHeight();
}
sz.w += border().width();
sz.h += border().height();
ev.setSizeHint(sz);
}
void Label::onPaint(PaintEvent& ev)
{
theme()->paintLabel(ev);
}
} // namespace ui

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -16,10 +16,6 @@ namespace ui {
class Label : public Widget {
public:
Label(const std::string& text);
protected:
void onSizeHint(SizeHintEvent& ev) override;
void onPaint(PaintEvent& ev) override;
};
} // namespace ui

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -19,15 +19,19 @@
namespace ui {
LinkLabel::LinkLabel(const std::string& urlOrText)
: CustomLabel(urlOrText)
: Label(urlOrText)
, m_url(urlOrText)
{
setType(kLinkLabelWidget);
initTheme();
}
LinkLabel::LinkLabel(const std::string& url, const std::string& text)
: CustomLabel(text)
: Label(text)
, m_url(url)
{
setType(kLinkLabelWidget);
initTheme();
}
void LinkLabel::setUrl(const std::string& url)
@ -82,12 +86,7 @@ bool LinkLabel::onProcessMessage(Message* msg)
break;
}
return CustomLabel::onProcessMessage(msg);
}
void LinkLabel::onPaint(PaintEvent& ev)
{
theme()->paintLinkLabel(ev);
return Label::onProcessMessage(msg);
}
void LinkLabel::onClick()

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -9,13 +9,13 @@
#pragma once
#include "obs/signal.h"
#include "ui/custom_label.h"
#include "ui/label.h"
#include <string>
namespace ui {
class LinkLabel : public CustomLabel {
class LinkLabel : public Label {
public:
LinkLabel(const std::string& urlOrText = "");
LinkLabel(const std::string& url, const std::string& text);
@ -27,7 +27,6 @@ namespace ui {
protected:
bool onProcessMessage(Message* msg) override;
void onPaint(PaintEvent& ev) override;
virtual void onClick();
std::string m_url;

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -241,6 +241,7 @@ void PopupWindow::onHitTest(HitTestEvent& ev)
}
else if (type == kBoxWidget ||
type == kLabelWidget ||
type == kLinkLabelWidget ||
type == kGridWidget ||
type == kSeparatorWidget) {
ev.setHit(isMoveable() ? HitTestCaption: HitTestClient);

View File

@ -12,6 +12,7 @@
#include "gfx/color.h"
#include "gfx/rect.h"
#include "gfx/size.h"
#include "ui/base.h"
#include <string>
#include <vector>
@ -46,6 +47,7 @@ namespace ui {
Layer()
: m_type(Type::kNone)
, m_flags(0)
, m_align(CENTER | MIDDLE)
, m_color(gfx::ColorNone)
, m_icon(nullptr)
, m_spriteSheet(nullptr) {
@ -53,6 +55,7 @@ namespace ui {
Type type() const { return m_type; }
int flags() const { return m_flags; }
int align() const { return m_align; }
gfx::Color color() const { return m_color; }
she::Surface* icon() const { return m_icon; }
@ -62,6 +65,7 @@ namespace ui {
void setType(const Type type) { m_type = type; }
void setFlags(const int flags) { m_flags = flags; }
void setAlign(const int align) { m_align = align; }
void setColor(gfx::Color color) { m_color = color; }
void setIcon(she::Surface* icon) { m_icon = icon; }
void setSpriteSheet(she::Surface* spriteSheet) { m_spriteSheet = spriteSheet; }
@ -71,6 +75,7 @@ namespace ui {
private:
Type m_type;
int m_flags;
int m_align;
gfx::Color m_color;
she::Surface* m_icon;
she::Surface* m_spriteSheet;

View File

@ -29,7 +29,48 @@
namespace ui {
static Theme* current_theme = NULL;
namespace {
Theme* current_theme = nullptr;
int compare_layer_flags(int a, int b)
{
// TODO improve this
return a - b;
}
void for_each_layer(Widget* widget,
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->hasMouseOver() ? Style::Layer::kMouse: 0) |
(widget->hasFocus() ? Style::Layer::kFocus: 0);
const Style::Layer* bestLayer = nullptr;
for (const auto& layer : style->layers()) {
if (bestLayer &&
bestLayer->type() != layer.type()) {
callback(*bestLayer);
bestLayer = nullptr;
}
if ((!layer.flags()
|| (layer.flags() & flags) == layer.flags())
&& (!bestLayer
|| (bestLayer && compare_layer_flags(bestLayer->flags(), layer.flags()) <= 0))) {
bestLayer = &layer;
}
}
if (bestLayer)
callback(*bestLayer);
}
} // anonymous namespace
Theme::Theme()
: m_guiscale(1)
@ -60,45 +101,23 @@ void Theme::regenerate()
set_mouse_cursor(type);
}
void Theme::paintWidget(PaintEvent& ev)
void Theme::paintWidget(Graphics* g,
Widget* widget,
const Style* style,
gfx::Rect rc)
{
Widget* widget = static_cast<Widget*>(ev.getSource());
const Style* style = widget->style();
if (!style) {
// Without a ui::Style we don't know how to draw the widget
return;
}
Graphics* g = ev.graphics();
gfx::Rect rc = widget->clientBounds();
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);
ASSERT(g);
ASSERT(widget);
ASSERT(style);
// External background
g->fillRect(widget->bgColor(), rc);
const Style::Layer* bestLayer = nullptr;
for (const auto& layer : style->layers()) {
if (bestLayer &&
bestLayer->type() != layer.type()) {
paintLayer(g, widget, *bestLayer, rc);
bestLayer = nullptr;
}
if ((!layer.flags()
|| (layer.flags() & flags) == layer.flags())
&& (!bestLayer
|| (bestLayer && compareLayerFlags(bestLayer->flags(), layer.flags()) <= 0))) {
bestLayer = &layer;
}
}
if (bestLayer)
paintLayer(g, widget, *bestLayer, rc);
for_each_layer(
widget, style,
[this, g, widget, &rc](const Style::Layer& layer) {
paintLayer(g, widget, layer, rc);
});
}
void Theme::paintLayer(Graphics* g, Widget* widget,
@ -148,29 +167,53 @@ void Theme::paintLayer(Graphics* g, Widget* widget,
case Style::Layer::Type::kText:
if (layer.color() != gfx::ColorNone) {
gfx::Size textSize = g->measureUIText(widget->text());
gfx::Point pt;
if (layer.align() & LEFT)
pt.x = rc.x;
else if (layer.align() & RIGHT)
pt.x = rc.x+rc.w-textSize.w;
else
pt.x = rc.x+rc.w/2-textSize.w/2;
if (layer.align() & TOP)
pt.y = rc.y;
else if (layer.align() & BOTTOM)
pt.y = rc.y+rc.h-textSize.h;
else
pt.y = rc.y+rc.h/2-textSize.h/2;
g->drawUIText(widget->text(),
layer.color(),
gfx::ColorNone,
gfx::Point(rc.x+rc.w/2-textSize.w/2,
rc.y+rc.h/2-textSize.h/2),
widget->mnemonic());
pt, widget->mnemonic());
}
break;
case Style::Layer::Type::kIcon: {
she::Surface* icon = layer.icon();
if (icon) {
if (layer.color() != gfx::ColorNone) {
g->drawColoredRgbaSurface(icon,
layer.color(),
rc.x+rc.w/2-icon->width()/2,
rc.y+rc.h/2-icon->height()/2);
}
else {
g->drawRgbaSurface(icon,
rc.x+rc.w/2-icon->width()/2,
rc.y+rc.h/2-icon->height()/2);
}
gfx::Size iconSize(icon->width(), icon->height());
gfx::Point pt;
if (layer.align() & LEFT)
pt.x = rc.x;
else if (layer.align() & RIGHT)
pt.x = rc.x+rc.w-iconSize.w;
else
pt.x = rc.x+rc.w/2-iconSize.w/2;
if (layer.align() & TOP)
pt.y = rc.y;
else if (layer.align() & BOTTOM)
pt.y = rc.y+rc.h-iconSize.h;
else
pt.y = rc.y+rc.h/2-iconSize.h/2;
if (layer.color() != gfx::ColorNone)
g->drawColoredRgbaSurface(icon, layer.color(), pt.x, pt.y);
else
g->drawRgbaSurface(icon, pt.x, pt.y);
}
break;
}
@ -178,66 +221,19 @@ void Theme::paintLayer(Graphics* g, Widget* widget,
}
}
void Theme::calcSizeHint(SizeHintEvent& ev)
gfx::Size Theme::calcSizeHint(Widget* widget, const Style* style)
{
Widget* widget = static_cast<Widget*>(ev.getSource());
const Style* style = widget->style();
if (!style)
return;
gfx::Border hintBorder(0, 0, 0, 0);
gfx::Border hintPadding(0, 0, 0, 0);
gfx::Size hintText(0, 0);
gfx::Size hintIcon(0, 0);
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()) {
if (bestLayer &&
bestLayer->type() != layer.type()) {
measureLayer(widget, *bestLayer,
hintBorder, hintText, hintIcon);
bestLayer = nullptr;
}
if ((!layer.flags()
|| (layer.flags() & flags) == layer.flags())
&& (!bestLayer
|| (bestLayer && compareLayerFlags(bestLayer->flags(), layer.flags()) < 0))) {
bestLayer = &layer;
}
}
if (bestLayer)
measureLayer(widget, *bestLayer,
hintBorder, hintText, hintIcon);
if (style->border().left() >= 0) hintBorder.left(style->border().left());
if (style->border().top() >= 0) hintBorder.top(style->border().top());
if (style->border().right() >= 0) hintBorder.right(style->border().right());
if (style->border().bottom() >= 0) hintBorder.bottom(style->border().bottom());
if (style->padding().left() >= 0) hintPadding.left(style->padding().left());
if (style->padding().top() >= 0) hintPadding.top(style->padding().top());
if (style->padding().right() >= 0) hintPadding.right(style->padding().right());
if (style->padding().bottom() >= 0) hintPadding.bottom(style->padding().bottom());
gfx::Size sz(hintBorder.width() + hintPadding.width() + hintIcon.w + hintText.w,
hintBorder.height() + hintPadding.height() + std::max(hintIcon.h, hintText.h));
ev.setSizeHint(sz);
gfx::Size sizeHint;
gfx::Border borderHint;
calcWidgetMetrics(widget, style, sizeHint, borderHint);
return sizeHint;
}
void Theme::measureLayer(Widget* widget,
const Style::Layer& layer,
gfx::Border& hintBorder,
gfx::Size& hintText,
gfx::Size& hintIcon)
gfx::Border& borderHint,
gfx::Size& textHint, int& textAlign,
gfx::Size& iconHint, int& iconAlign)
{
switch (layer.type()) {
@ -246,10 +242,10 @@ void Theme::measureLayer(Widget* widget,
if (layer.spriteSheet() &&
!layer.spriteBounds().isEmpty() &&
!layer.slicesBounds().isEmpty()) {
hintBorder.left(std::max(hintBorder.left(), layer.slicesBounds().x));
hintBorder.top(std::max(hintBorder.top(), layer.slicesBounds().y));
hintBorder.right(std::max(hintBorder.right(), layer.spriteBounds().w - layer.slicesBounds().x2()));
hintBorder.bottom(std::max(hintBorder.bottom(), layer.spriteBounds().h - layer.slicesBounds().y2()));
borderHint.left(std::max(borderHint.left(), layer.slicesBounds().x));
borderHint.top(std::max(borderHint.top(), layer.slicesBounds().y));
borderHint.right(std::max(borderHint.right(), layer.spriteBounds().w - layer.slicesBounds().x2()));
borderHint.bottom(std::max(borderHint.bottom(), layer.spriteBounds().h - layer.slicesBounds().y2()));
}
break;
@ -258,16 +254,18 @@ void Theme::measureLayer(Widget* widget,
gfx::Size textSize(Graphics::measureUITextLength(widget->text(),
widget->font()),
widget->font()->height());
hintText.w = std::max(hintText.w, textSize.w);
hintText.h = std::max(hintText.h, textSize.h);
textHint.w = std::max(textHint.w, textSize.w);
textHint.h = std::max(textHint.h, textSize.h);
textAlign = layer.align();
}
break;
case Style::Layer::Type::kIcon: {
she::Surface* icon = layer.icon();
if (icon) {
hintIcon.w = std::max(hintIcon.w, icon->width());
hintIcon.h = std::max(hintIcon.h, icon->height());
iconHint.w = std::max(iconHint.w, icon->width());
iconHint.h = std::max(iconHint.h, icon->height());
iconAlign = layer.align();
}
break;
}
@ -275,9 +273,61 @@ void Theme::measureLayer(Widget* widget,
}
}
int Theme::compareLayerFlags(int a, int b)
gfx::Border Theme::calcBorder(Widget* widget, const Style* style)
{
return a - b;
gfx::Size sizeHint;
gfx::Border borderHint;
calcWidgetMetrics(widget, style, sizeHint, borderHint);
return borderHint;
}
void Theme::calcWidgetMetrics(Widget* widget,
const Style* style,
gfx::Size& sizeHint,
gfx::Border& borderHint)
{
ASSERT(widget);
ASSERT(style);
borderHint = gfx::Border(0, 0, 0, 0);
gfx::Border paddingHint(0, 0, 0, 0);
gfx::Size textHint(0, 0);
gfx::Size iconHint(0, 0);
int textAlign = CENTER | MIDDLE;
int iconAlign = CENTER | MIDDLE;
for_each_layer(
widget, style,
[this, widget, &borderHint, &textHint, &textAlign, &iconHint, &iconAlign]
(const Style::Layer& layer) {
measureLayer(widget, layer,
borderHint,
textHint, textAlign,
iconHint, iconAlign);
});
if (style->border().left() >= 0) borderHint.left(style->border().left());
if (style->border().top() >= 0) borderHint.top(style->border().top());
if (style->border().right() >= 0) borderHint.right(style->border().right());
if (style->border().bottom() >= 0) borderHint.bottom(style->border().bottom());
if (style->padding().left() >= 0) paddingHint.left(style->padding().left());
if (style->padding().top() >= 0) paddingHint.top(style->padding().top());
if (style->padding().right() >= 0) paddingHint.right(style->padding().right());
if (style->padding().bottom() >= 0) paddingHint.bottom(style->padding().bottom());
sizeHint = gfx::Size(borderHint.width() + paddingHint.width(),
borderHint.height() + paddingHint.height());
if ((textAlign & (LEFT | CENTER | RIGHT)) == (iconAlign & (LEFT | CENTER | RIGHT)))
sizeHint.w += std::max(textHint.w, iconHint.w);
else
sizeHint.w += textHint.w + iconHint.w;
if ((textAlign & (TOP | MIDDLE | BOTTOM)) == (iconAlign & (TOP | MIDDLE | BOTTOM)))
sizeHint.h += std::max(textHint.h, iconHint.h);
else
sizeHint.h += textHint.h + iconHint.h;
}
//////////////////////////////////////////////////////////////////////

View File

@ -58,8 +58,6 @@ namespace ui {
virtual void paintCheckBox(PaintEvent& ev) = 0;
virtual void paintEntry(PaintEvent& ev) = 0;
virtual void paintGrid(PaintEvent& ev) = 0;
virtual void paintLabel(PaintEvent& ev) = 0;
virtual void paintLinkLabel(PaintEvent& ev) = 0;
virtual void paintListBox(PaintEvent& ev) = 0;
virtual void paintListItem(PaintEvent& ev) = 0;
virtual void paintMenu(PaintEvent& ev) = 0;
@ -70,7 +68,6 @@ namespace ui {
virtual void paintSlider(PaintEvent& ev) = 0;
virtual void paintComboBoxEntry(PaintEvent& ev) = 0;
virtual void paintTextBox(PaintEvent& ev) = 0;
virtual void paintView(PaintEvent& ev) = 0;
virtual void paintViewScrollbar(PaintEvent& ev) = 0;
virtual void paintViewViewport(PaintEvent& ev) = 0;
virtual void paintWindow(PaintEvent& ev) = 0;
@ -78,8 +75,14 @@ namespace ui {
virtual void paintTooltip(PaintEvent& ev) = 0;
// Default implementation to draw widgets with new ui::Styles
virtual void paintWidget(PaintEvent& ev);
virtual void calcSizeHint(SizeHintEvent& ev);
virtual void paintWidget(Graphics* g,
Widget* widget,
const Style* style,
gfx::Rect rc);
virtual gfx::Size calcSizeHint(Widget* widget,
const Style* style);
virtual gfx::Border calcBorder(Widget* widget,
const Style* style);
static void drawSlices(Graphics* g,
she::Surface* sheet,
@ -100,10 +103,13 @@ namespace ui {
gfx::Rect& rc);
void measureLayer(Widget* widget,
const Style::Layer& layer,
gfx::Border& hintBorder,
gfx::Size& hintText,
gfx::Size& hintIcon);
int compareLayerFlags(int a, int b);
gfx::Border& borderHint,
gfx::Size& textHint, int& textAlign,
gfx::Size& iconHint, int& iconAlign);
void calcWidgetMetrics(Widget* widget,
const Style* style,
gfx::Size& sizeHint,
gfx::Border& borderHint);
int m_guiscale;
};

View File

@ -17,7 +17,6 @@
#include "ui/component.h"
#include "ui/cursor.h"
#include "ui/cursor_type.h"
#include "ui/custom_label.h"
#include "ui/entry.h"
#include "ui/event.h"
#include "ui/fit_bounds.h"

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -216,15 +216,10 @@ void View::onResize(ResizeEvent& ev)
void View::onSizeHint(SizeHintEvent& ev)
{
Size viewSize = m_viewport.sizeHint();
viewSize.w += border().width();
viewSize.h += border().height();
ev.setSizeHint(viewSize);
}
void View::onPaint(PaintEvent& ev)
{
theme()->paintView(ev);
Widget::onSizeHint(ev);
gfx::Size sz = ev.sizeHint();
sz += m_viewport.sizeHint();
ev.setSizeHint(sz);
}
void View::onSetViewScroll(const gfx::Point& pt)

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2013, 2015, 2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -56,7 +56,6 @@ namespace ui {
bool onProcessMessage(Message* msg) override;
void onResize(ResizeEvent& ev) override;
void onSizeHint(SizeHintEvent& ev) override;
void onPaint(PaintEvent& ev) override;
virtual void onSetViewScroll(const gfx::Point& pt);
virtual void onScrollRegion(ScrollRegionEvent& ev);

View File

@ -187,6 +187,7 @@ void Widget::setTheme(Theme* theme)
void Widget::setStyle(Style* style)
{
m_style = style;
m_border = m_theme->calcBorder(this, style);
}
// ===============================================================
@ -643,6 +644,9 @@ void Widget::setBoundsQuietly(const gfx::Rect& rc)
void Widget::setBorder(const Border& br)
{
m_border = br;
if (m_style) {
LOG(WARNING) << "Warning setting border to a widget with style\n";
}
}
void Widget::setChildSpacing(int childSpacing)
@ -654,6 +658,10 @@ void Widget::noBorderNoChildSpacing()
{
m_border = gfx::Border(0, 0, 0, 0);
m_childSpacing = 0;
if (m_style) {
LOG(WARNING) << "Warning setting border to a widget with style\n";
}
}
void Widget::getRegion(gfx::Region& region)
@ -1424,7 +1432,7 @@ void Widget::onInvalidateRegion(const Region& region)
void Widget::onSizeHint(SizeHintEvent& ev)
{
if (m_style) {
m_theme->calcSizeHint(ev);
ev.setSizeHint(m_theme->calcSizeHint(this, style()));
}
else {
ev.setSizeHint(m_minSize);
@ -1454,7 +1462,8 @@ void Widget::onResize(ResizeEvent& ev)
void Widget::onPaint(PaintEvent& ev)
{
if (m_style)
m_theme->paintWidget(ev);
m_theme->paintWidget(ev.graphics(), this, style(),
clientBounds());
}
void Widget::onBroadcastMouseMessage(WidgetsList& targets)

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2013, 2015 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -24,6 +24,7 @@ namespace ui {
kGridWidget,
kImageViewWidget,
kLabelWidget,
kLinkLabelWidget,
kListBoxWidget,
kListItemWidget,
kManagerWidget,