mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-16 05:42:32 +00:00
Move all code to draw windows to ui-lib w/new styles
This commit is contained in:
parent
2883a70e25
commit
a62f12ad09
@ -412,24 +412,6 @@
|
|||||||
|
|
||||||
<stylesheet>
|
<stylesheet>
|
||||||
|
|
||||||
<!-- window -->
|
|
||||||
<style id="window">
|
|
||||||
<background color="window_face" part="window" />
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style id="window_title">
|
|
||||||
<background color="window_titlebar_face" />
|
|
||||||
<text color="window_titlebar_text" align="left" valign="middle" />
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style id="menubox">
|
|
||||||
<background color="window_face" part="menu" />
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style id="desktop">
|
|
||||||
<background color="desktop" />
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!-- scrollbar -->
|
<!-- scrollbar -->
|
||||||
<style id="scrollbar">
|
<style id="scrollbar">
|
||||||
<background part="scrollbar_bg" repeat="repeat" />
|
<background part="scrollbar_bg" repeat="repeat" />
|
||||||
@ -835,6 +817,66 @@
|
|||||||
|
|
||||||
<styles>
|
<styles>
|
||||||
|
|
||||||
|
<style id="window_without_title" border="3">
|
||||||
|
<background color="window_face" />
|
||||||
|
<border part="menu" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="window_with_title" border="6" border-top="17">
|
||||||
|
<background color="window_face" />
|
||||||
|
<border part="window" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="window_title_label" margin-top="5" margin-left="5">
|
||||||
|
<background color="window_titlebar_face" />
|
||||||
|
<text color="window_titlebar_text" align="left middle" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="window_close_button" margin-top="3" margin-right="3">
|
||||||
|
<background part="window_button_normal" />
|
||||||
|
<background part="window_button_hot" state="mouse" />
|
||||||
|
<background part="window_button_selected" state="selected" />
|
||||||
|
<icon part="window_close_icon" color="button_normal_text" />
|
||||||
|
<icon part="window_close_icon" color="button_hot_text" state="mouse" />
|
||||||
|
<icon part="window_close_icon" color="button_selected_text" state="selected" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="popup_window">
|
||||||
|
<background color="window_face" />
|
||||||
|
<border part="menu" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="transparent_popup_window">
|
||||||
|
<!-- nothing (transparent) -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="menu">
|
||||||
|
<background color="window_face" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="menubox" extends="menu">
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="menubar" extends="menubox">
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="desktop">
|
||||||
|
<background color="desktop" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="tooltip_window">
|
||||||
|
<background part="tooltip" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="tooltip_window_arrow">
|
||||||
|
<background part="tooltip_arrow" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style id="tooltip_text">
|
||||||
|
<background color="tooltip_face" />
|
||||||
|
<text color="tooltip_text" />
|
||||||
|
</style>
|
||||||
|
|
||||||
<style id="label" padding="1">
|
<style id="label" padding="1">
|
||||||
<text color="text" align="left" />
|
<text color="text" align="left" />
|
||||||
<text color="disabled" align="left" state="disabled" />
|
<text color="disabled" align="left" state="disabled" />
|
||||||
@ -878,7 +920,7 @@
|
|||||||
<border part="editor_selected" state="selected" />
|
<border part="editor_selected" state="selected" />
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style id="workspace_view" border-top="4">
|
<style id="workspace_view" border-top="4" extends="view">
|
||||||
<border part="editor_normal" />
|
<border part="editor_normal" />
|
||||||
<border part="editor_selected" state="focus" />
|
<border part="editor_selected" state="focus" />
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2017 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
@ -80,12 +80,13 @@ ColorPopup::ColorPopup(bool canPin)
|
|||||||
m_topBox.addChild(new Separator("", VERTICAL));
|
m_topBox.addChild(new Separator("", VERTICAL));
|
||||||
m_topBox.addChild(&m_hexColorEntry);
|
m_topBox.addChild(&m_hexColorEntry);
|
||||||
|
|
||||||
|
// TODO fix this hack for close button in popup window
|
||||||
// Move close button (decorative widget) inside the m_topBox
|
// Move close button (decorative widget) inside the m_topBox
|
||||||
{
|
{
|
||||||
Widget* closeButton = nullptr;
|
Widget* closeButton = nullptr;
|
||||||
WidgetsList decorators;
|
WidgetsList decorators;
|
||||||
for (auto child : children()) {
|
for (auto child : children()) {
|
||||||
if (child->isDecorative()) {
|
if (child->type() == kWindowCloseButtonWidget) {
|
||||||
closeButton = child;
|
closeButton = child;
|
||||||
removeChild(child);
|
removeChild(child);
|
||||||
break;
|
break;
|
||||||
@ -93,7 +94,9 @@ ColorPopup::ColorPopup(bool canPin)
|
|||||||
}
|
}
|
||||||
if (closeButton) {
|
if (closeButton) {
|
||||||
m_topBox.addChild(new BoxFiller);
|
m_topBox.addChild(new BoxFiller);
|
||||||
m_topBox.addChild(closeButton);
|
VBox* vbox = new VBox;
|
||||||
|
vbox->addChild(closeButton);
|
||||||
|
m_topBox.addChild(vbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2017 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
#include "app/modules/gfx.h"
|
#include "app/modules/gfx.h"
|
||||||
#include "app/modules/gui.h"
|
#include "app/modules/gui.h"
|
||||||
#include "app/ui/skin/button_icon_impl.h"
|
|
||||||
#include "app/ui/skin/skin_theme.h"
|
#include "app/ui/skin/skin_theme.h"
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "gfx/border.h"
|
#include "gfx/border.h"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2017 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
@ -8,7 +8,6 @@
|
|||||||
#define APP_UI_POPUP_FRAME_PIN_H_INCLUDED
|
#define APP_UI_POPUP_FRAME_PIN_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/button.h"
|
|
||||||
#include "ui/popup_window.h"
|
#include "ui/popup_window.h"
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
@ -241,8 +241,8 @@ bool PreviewEditorWindow::onProcessMessage(ui::Message* msg)
|
|||||||
void PreviewEditorWindow::onClose(ui::CloseEvent& ev)
|
void PreviewEditorWindow::onClose(ui::CloseEvent& ev)
|
||||||
{
|
{
|
||||||
Button* closeButton = dynamic_cast<Button*>(ev.getSource());
|
Button* closeButton = dynamic_cast<Button*>(ev.getSource());
|
||||||
if (closeButton != NULL &&
|
if (closeButton &&
|
||||||
closeButton->id() == SkinTheme::kThemeCloseButtonId) {
|
closeButton->type() == kWindowCloseButtonWidget) {
|
||||||
// Here we don't use "setMiniEditorEnabled" to change the state of
|
// Here we don't use "setMiniEditorEnabled" to change the state of
|
||||||
// "m_isEnabled" because we're coming from a close event of the
|
// "m_isEnabled" because we're coming from a close event of the
|
||||||
// window.
|
// window.
|
||||||
|
@ -50,61 +50,6 @@ using namespace gfx;
|
|||||||
using namespace ui;
|
using namespace ui;
|
||||||
|
|
||||||
const char* SkinTheme::kThemesFolderName = "themes";
|
const char* SkinTheme::kThemesFolderName = "themes";
|
||||||
const char* SkinTheme::kThemeCloseButtonId = "theme_close_button";
|
|
||||||
|
|
||||||
// Controls the "X" button in a window to close it.
|
|
||||||
class WindowCloseButton : public Button {
|
|
||||||
public:
|
|
||||||
WindowCloseButton() : Button("") {
|
|
||||||
setDecorative(true);
|
|
||||||
setId(SkinTheme::kThemeCloseButtonId);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void onSizeHint(SizeHintEvent& ev) override {
|
|
||||||
ev.setSizeHint(SkinTheme::instance()->parts.windowButtonNormal()->size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void onClick(Event& ev) override {
|
|
||||||
Button::onClick(ev);
|
|
||||||
closeWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
void onPaint(PaintEvent& ev) override {
|
|
||||||
static_cast<SkinTheme*>(theme())->paintWindowButton(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool onProcessMessage(Message* msg) override {
|
|
||||||
switch (msg->type()) {
|
|
||||||
|
|
||||||
case kSetCursorMessage:
|
|
||||||
ui::set_mouse_cursor(kArrowCursor);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case kKeyDownMessage:
|
|
||||||
if (window()->isForeground() &&
|
|
||||||
static_cast<KeyMessage*>(msg)->scancode() == kKeyEsc) {
|
|
||||||
setSelected(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kKeyUpMessage:
|
|
||||||
if (window()->isForeground() &&
|
|
||||||
static_cast<KeyMessage*>(msg)->scancode() == kKeyEsc) {
|
|
||||||
if (isSelected()) {
|
|
||||||
setSelected(false);
|
|
||||||
closeWindow();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Button::onProcessMessage(msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char* cursor_names[kCursorTypes] = {
|
static const char* cursor_names[kCursorTypes] = {
|
||||||
"null", // kNoCursor
|
"null", // kNoCursor
|
||||||
@ -534,6 +479,21 @@ void SkinTheme::loadXml(const std::string& skinId)
|
|||||||
*style = ui::Style(base);
|
*style = ui::Style(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Margin
|
||||||
|
{
|
||||||
|
const char* m = xmlStyle->Attribute("margin");
|
||||||
|
const char* l = xmlStyle->Attribute("margin-left");
|
||||||
|
const char* t = xmlStyle->Attribute("margin-top");
|
||||||
|
const char* r = xmlStyle->Attribute("margin-right");
|
||||||
|
const char* b = xmlStyle->Attribute("margin-bottom");
|
||||||
|
gfx::Border margin = ui::Style::UndefinedBorder();
|
||||||
|
if (m || l) margin.left(std::strtol(l ? l: m, nullptr, 10));
|
||||||
|
if (m || t) margin.top(std::strtol(t ? t: m, nullptr, 10));
|
||||||
|
if (m || r) margin.right(std::strtol(r ? r: m, nullptr, 10));
|
||||||
|
if (m || b) margin.bottom(std::strtol(b ? b: m, nullptr, 10));
|
||||||
|
style->setMargin(margin*guiscale());
|
||||||
|
}
|
||||||
|
|
||||||
// Border
|
// Border
|
||||||
{
|
{
|
||||||
const char* m = xmlStyle->Attribute("border");
|
const char* m = xmlStyle->Attribute("border");
|
||||||
@ -541,7 +501,7 @@ void SkinTheme::loadXml(const std::string& skinId)
|
|||||||
const char* t = xmlStyle->Attribute("border-top");
|
const char* t = xmlStyle->Attribute("border-top");
|
||||||
const char* r = xmlStyle->Attribute("border-right");
|
const char* r = xmlStyle->Attribute("border-right");
|
||||||
const char* b = xmlStyle->Attribute("border-bottom");
|
const char* b = xmlStyle->Attribute("border-bottom");
|
||||||
gfx::Border border(-1, -1, -1, -1);
|
gfx::Border border = ui::Style::UndefinedBorder();
|
||||||
if (m || l) border.left(std::strtol(l ? l: m, nullptr, 10));
|
if (m || l) border.left(std::strtol(l ? l: m, nullptr, 10));
|
||||||
if (m || t) border.top(std::strtol(t ? t: m, nullptr, 10));
|
if (m || t) border.top(std::strtol(t ? t: m, nullptr, 10));
|
||||||
if (m || r) border.right(std::strtol(r ? r: m, nullptr, 10));
|
if (m || r) border.right(std::strtol(r ? r: m, nullptr, 10));
|
||||||
@ -556,7 +516,7 @@ void SkinTheme::loadXml(const std::string& skinId)
|
|||||||
const char* t = xmlStyle->Attribute("padding-top");
|
const char* t = xmlStyle->Attribute("padding-top");
|
||||||
const char* r = xmlStyle->Attribute("padding-right");
|
const char* r = xmlStyle->Attribute("padding-right");
|
||||||
const char* b = xmlStyle->Attribute("padding-bottom");
|
const char* b = xmlStyle->Attribute("padding-bottom");
|
||||||
gfx::Border padding(-1, -1, -1, -1);
|
gfx::Border padding = ui::Style::UndefinedBorder();
|
||||||
if (m || l) padding.left(std::strtol(l ? l: m, nullptr, 10));
|
if (m || l) padding.left(std::strtol(l ? l: m, nullptr, 10));
|
||||||
if (m || t) padding.top(std::strtol(t ? t: m, nullptr, 10));
|
if (m || t) padding.top(std::strtol(t ? t: m, nullptr, 10));
|
||||||
if (m || r) padding.right(std::strtol(r ? r: m, nullptr, 10));
|
if (m || r) padding.right(std::strtol(r ? r: m, nullptr, 10));
|
||||||
@ -778,10 +738,15 @@ void SkinTheme::initWidget(Widget* widget)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case kMenuWidget:
|
case kMenuWidget:
|
||||||
|
widget->setStyle(newStyles.menu());
|
||||||
|
break;
|
||||||
|
|
||||||
case kMenuBarWidget:
|
case kMenuBarWidget:
|
||||||
|
widget->setStyle(newStyles.menubar());
|
||||||
|
break;
|
||||||
|
|
||||||
case kMenuBoxWidget:
|
case kMenuBoxWidget:
|
||||||
BORDER(0);
|
widget->setStyle(newStyles.menubox());
|
||||||
widget->setChildSpacing(0);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kMenuItemWidget:
|
case kMenuItemWidget:
|
||||||
@ -854,33 +819,36 @@ void SkinTheme::initWidget(Widget* widget)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case kWindowWidget:
|
case kWindowWidget:
|
||||||
if (!static_cast<Window*>(widget)->isDesktop()) {
|
if (TipWindow* window = dynamic_cast<TipWindow*>(widget)) {
|
||||||
if (widget->hasText()) {
|
window->setStyle(newStyles.tooltipWindow());
|
||||||
BORDER4(6 * scale,
|
window->setArrowStyle(newStyles.tooltipWindowArrow());
|
||||||
(4+6) * scale + widget->textHeight(),
|
window->textBox()->setStyle(SkinTheme::instance()->newStyles.tooltipText());
|
||||||
6 * scale,
|
}
|
||||||
6 * scale);
|
else if (dynamic_cast<TransparentPopupWindow*>(widget)) {
|
||||||
|
widget->setStyle(newStyles.transparentPopupWindow());
|
||||||
if (!widget->hasFlags(INITIALIZED)) {
|
}
|
||||||
Button* button = new WindowCloseButton();
|
else if (dynamic_cast<PopupWindow*>(widget)) {
|
||||||
widget->addChild(button);
|
widget->setStyle(newStyles.popupWindow());
|
||||||
}
|
}
|
||||||
}
|
else if (static_cast<Window*>(widget)->isDesktop()) {
|
||||||
else {
|
widget->setStyle(newStyles.desktop());
|
||||||
BORDER(3 * scale);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BORDER(0);
|
if (widget->hasText()) {
|
||||||
|
widget->setStyle(newStyles.windowWithTitle());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
widget->setStyle(newStyles.windowWithoutTitle());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
widget->setChildSpacing(4 * scale); // TODO this hard-coded 4 should be configurable in skin.xml
|
case kWindowTitleLabelWidget:
|
||||||
|
widget->setStyle(SkinTheme::instance()->newStyles.windowTitleLabel());
|
||||||
|
break;
|
||||||
|
|
||||||
// Tooltip background color
|
case kWindowCloseButtonWidget:
|
||||||
if (dynamic_cast<TipWindow*>(widget))
|
widget->setStyle(SkinTheme::instance()->newStyles.windowCloseButton());
|
||||||
widget->setBgColor(SkinTheme::instance()->colors.tooltipFace());
|
|
||||||
else
|
|
||||||
widget->setBgColor(colors.windowFace());
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -893,19 +861,6 @@ void SkinTheme::getWindowMask(Widget* widget, Region& region)
|
|||||||
region = widget->bounds();
|
region = widget->bounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkinTheme::setDecorativeWidgetBounds(Widget* widget)
|
|
||||||
{
|
|
||||||
if (widget->id() == kThemeCloseButtonId) {
|
|
||||||
Widget* window = widget->parent();
|
|
||||||
gfx::Rect rect(parts.windowButtonNormal()->size());
|
|
||||||
|
|
||||||
rect.offset(window->bounds().x2() - 3*guiscale() - rect.w,
|
|
||||||
window->bounds().y + 3*guiscale());
|
|
||||||
|
|
||||||
widget->setBounds(rect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int SkinTheme::getScrollbarSize()
|
int SkinTheme::getScrollbarSize()
|
||||||
{
|
{
|
||||||
return dimensions.scrollbarSize();
|
return dimensions.scrollbarSize();
|
||||||
@ -1603,160 +1558,6 @@ void SkinTheme::paintViewViewport(PaintEvent& ev)
|
|||||||
g->fillRect(bg, widget->clientBounds());
|
g->fillRect(bg, widget->clientBounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkinTheme::paintWindow(PaintEvent& ev)
|
|
||||||
{
|
|
||||||
Graphics* g = ev.graphics();
|
|
||||||
Window* window = static_cast<Window*>(ev.getSource());
|
|
||||||
Rect pos = window->clientBounds();
|
|
||||||
Rect cpos = window->clientChildrenBounds();
|
|
||||||
|
|
||||||
if (!window->isDesktop()) {
|
|
||||||
// window frame
|
|
||||||
if (window->hasText()) {
|
|
||||||
styles.window()->paint(g, pos, NULL, Style::State());
|
|
||||||
styles.windowTitle()->paint(g,
|
|
||||||
gfx::Rect(cpos.x, pos.y+5*guiscale(), cpos.w, // TODO this hard-coded 5 should be configurable in skin.xml
|
|
||||||
window->textHeight()),
|
|
||||||
window->text().c_str(), Style::State());
|
|
||||||
}
|
|
||||||
// menubox
|
|
||||||
else {
|
|
||||||
styles.menubox()->paint(g, pos, NULL, Style::State());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// desktop
|
|
||||||
else {
|
|
||||||
styles.desktop()->paint(g, pos, NULL, Style::State());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkinTheme::paintPopupWindow(PaintEvent& ev)
|
|
||||||
{
|
|
||||||
Widget* widget = static_cast<Widget*>(ev.getSource());
|
|
||||||
Window* window = static_cast<Window*>(ev.getSource());
|
|
||||||
Graphics* g = ev.graphics();
|
|
||||||
gfx::Rect pos = window->clientBounds();
|
|
||||||
|
|
||||||
if (!is_transparent(BGCOLOR))
|
|
||||||
styles.menubox()->paint(g, pos, NULL, Style::State());
|
|
||||||
|
|
||||||
pos.shrink(window->border());
|
|
||||||
|
|
||||||
g->drawAlignedUIText(window->text(),
|
|
||||||
colors.text(),
|
|
||||||
window->bgColor(), pos,
|
|
||||||
window->align());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkinTheme::paintWindowButton(ui::PaintEvent& ev)
|
|
||||||
{
|
|
||||||
// Merge this code with SkinButton class
|
|
||||||
|
|
||||||
ButtonBase* widget = static_cast<ButtonBase*>(ev.getSource());
|
|
||||||
Graphics* g = ev.graphics();
|
|
||||||
Rect rc = widget->clientBounds();
|
|
||||||
SkinPartPtr part;
|
|
||||||
gfx::Color fg;
|
|
||||||
|
|
||||||
if (widget->isSelected()) {
|
|
||||||
fg = colors.buttonSelectedText();
|
|
||||||
part = parts.windowButtonSelected();
|
|
||||||
}
|
|
||||||
else if (widget->hasMouseOver()) {
|
|
||||||
fg = colors.buttonHotText();
|
|
||||||
part = parts.windowButtonHot();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fg = colors.buttonNormalText();
|
|
||||||
part = parts.windowButtonNormal();
|
|
||||||
}
|
|
||||||
|
|
||||||
g->fillRect(BGCOLOR, rc);
|
|
||||||
g->drawRgbaSurface(part->bitmap(0), rc.x, rc.y);
|
|
||||||
gfx::Size sz(part->bitmap(0)->width(),
|
|
||||||
part->bitmap(0)->height());
|
|
||||||
|
|
||||||
part = parts.windowCloseIcon();
|
|
||||||
g->drawColoredRgbaSurface(part->bitmap(0), fg,
|
|
||||||
rc.x+sz.w/2-part->bitmap(0)->width()/2,
|
|
||||||
rc.y+sz.h/2-part->bitmap(0)->height()/2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkinTheme::paintTooltip(PaintEvent& ev)
|
|
||||||
{
|
|
||||||
ui::TipWindow* widget = static_cast<ui::TipWindow*>(ev.getSource());
|
|
||||||
Graphics* g = ev.graphics();
|
|
||||||
Rect absRc = widget->bounds();
|
|
||||||
Rect rc = widget->clientBounds();
|
|
||||||
gfx::Color fg = colors.tooltipText();
|
|
||||||
gfx::Color bg = colors.tooltipFace();
|
|
||||||
SkinPartPtr tooltipPart = parts.tooltip();
|
|
||||||
|
|
||||||
she::Surface* nw = tooltipPart->bitmapNW();
|
|
||||||
she::Surface* n = tooltipPart->bitmapN();
|
|
||||||
she::Surface* ne = tooltipPart->bitmapNE();
|
|
||||||
she::Surface* e = tooltipPart->bitmapE();
|
|
||||||
she::Surface* se = tooltipPart->bitmapSE();
|
|
||||||
she::Surface* s = tooltipPart->bitmapS();
|
|
||||||
she::Surface* sw = tooltipPart->bitmapSW();
|
|
||||||
she::Surface* w = tooltipPart->bitmapW();
|
|
||||||
|
|
||||||
switch (widget->arrowAlign()) {
|
|
||||||
case TOP | LEFT: nw = parts.tooltipArrow()->bitmapNW(); break;
|
|
||||||
case TOP | RIGHT: ne = parts.tooltipArrow()->bitmapNE(); break;
|
|
||||||
case BOTTOM | LEFT: sw = parts.tooltipArrow()->bitmapSW(); break;
|
|
||||||
case BOTTOM | RIGHT: se = parts.tooltipArrow()->bitmapSE(); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
drawRect(g, rc, nw, n, ne, e, se, s, sw, w);
|
|
||||||
|
|
||||||
// Draw arrow in sides
|
|
||||||
she::Surface* arrow = NULL;
|
|
||||||
gfx::Rect target(widget->target());
|
|
||||||
target = target.createIntersection(gfx::Rect(0, 0, ui::display_w(), ui::display_h()));
|
|
||||||
target.offset(-absRc.origin());
|
|
||||||
|
|
||||||
switch (widget->arrowAlign()) {
|
|
||||||
case TOP:
|
|
||||||
arrow = parts.tooltipArrow()->bitmapN();
|
|
||||||
g->drawRgbaSurface(arrow,
|
|
||||||
target.x+target.w/2-arrow->width()/2,
|
|
||||||
rc.y);
|
|
||||||
break;
|
|
||||||
case BOTTOM:
|
|
||||||
arrow = parts.tooltipArrow()->bitmapS();
|
|
||||||
g->drawRgbaSurface(arrow,
|
|
||||||
target.x+target.w/2-arrow->width()/2,
|
|
||||||
rc.y+rc.h-arrow->height());
|
|
||||||
break;
|
|
||||||
case LEFT:
|
|
||||||
arrow = parts.tooltipArrow()->bitmapW();
|
|
||||||
g->drawRgbaSurface(arrow,
|
|
||||||
rc.x,
|
|
||||||
target.y+target.h/2-arrow->height()/2);
|
|
||||||
break;
|
|
||||||
case RIGHT:
|
|
||||||
arrow = parts.tooltipArrow()->bitmapE();
|
|
||||||
g->drawRgbaSurface(arrow,
|
|
||||||
rc.x+rc.w-arrow->width(),
|
|
||||||
target.y+target.h/2-arrow->height()/2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill background
|
|
||||||
g->fillRect(
|
|
||||||
bg, Rect(rc).shrink(
|
|
||||||
Border(
|
|
||||||
w->width(),
|
|
||||||
n->height(),
|
|
||||||
e->width(),
|
|
||||||
s->height())));
|
|
||||||
|
|
||||||
rc.shrink(widget->border());
|
|
||||||
|
|
||||||
g->drawAlignedUIText(widget->text(), fg, bg, rc, widget->align());
|
|
||||||
}
|
|
||||||
|
|
||||||
gfx::Color SkinTheme::getWidgetBgColor(Widget* widget)
|
gfx::Color SkinTheme::getWidgetBgColor(Widget* widget)
|
||||||
{
|
{
|
||||||
gfx::Color c = widget->bgColor();
|
gfx::Color c = widget->bgColor();
|
||||||
|
@ -39,7 +39,6 @@ namespace app {
|
|||||||
, public app::gen::ThemeFile<SkinTheme> {
|
, public app::gen::ThemeFile<SkinTheme> {
|
||||||
public:
|
public:
|
||||||
static const char* kThemesFolderName;
|
static const char* kThemesFolderName;
|
||||||
static const char* kThemeCloseButtonId;
|
|
||||||
|
|
||||||
static SkinTheme* instance();
|
static SkinTheme* instance();
|
||||||
|
|
||||||
@ -53,7 +52,6 @@ namespace app {
|
|||||||
ui::Cursor* getCursor(ui::CursorType type) override;
|
ui::Cursor* getCursor(ui::CursorType type) override;
|
||||||
void initWidget(ui::Widget* widget) override;
|
void initWidget(ui::Widget* widget) override;
|
||||||
void getWindowMask(ui::Widget* widget, gfx::Region& region) override;
|
void getWindowMask(ui::Widget* widget, gfx::Region& region) override;
|
||||||
void setDecorativeWidgetBounds(ui::Widget* widget) override;
|
|
||||||
int getScrollbarSize() override;
|
int getScrollbarSize() override;
|
||||||
gfx::Size getEntryCaretSize(ui::Widget* widget) override;
|
gfx::Size getEntryCaretSize(ui::Widget* widget) override;
|
||||||
|
|
||||||
@ -74,10 +72,6 @@ namespace app {
|
|||||||
void paintTextBox(ui::PaintEvent& ev) override;
|
void paintTextBox(ui::PaintEvent& ev) override;
|
||||||
void paintViewScrollbar(ui::PaintEvent& ev) override;
|
void paintViewScrollbar(ui::PaintEvent& ev) override;
|
||||||
void paintViewViewport(ui::PaintEvent& ev) override;
|
void paintViewViewport(ui::PaintEvent& ev) override;
|
||||||
void paintWindow(ui::PaintEvent& ev) override;
|
|
||||||
void paintPopupWindow(ui::PaintEvent& ev) override;
|
|
||||||
void paintTooltip(ui::PaintEvent& ev) override;
|
|
||||||
void paintWindowButton(ui::PaintEvent& ev);
|
|
||||||
|
|
||||||
int get_button_selected_offset() const { return 0; } // TODO Configurable in xml
|
int get_button_selected_offset() const { return 0; } // TODO Configurable in xml
|
||||||
|
|
||||||
|
@ -401,7 +401,7 @@ void ToolBar::openPopupWindow(int group_index, ToolGroup* tool_group)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// In case this tool contains more than just one tool, show the popup window
|
// In case this tool contains more than just one tool, show the popup window
|
||||||
m_popupWindow = new PopupWindow("", PopupWindow::ClickBehavior::CloseOnClickOutsideHotRegion);
|
m_popupWindow = new TransparentPopupWindow(PopupWindow::ClickBehavior::CloseOnClickOutsideHotRegion);
|
||||||
m_closeConn = m_popupWindow->Close.connect(base::Bind<void, ToolBar, ToolBar>(&ToolBar::onClosePopup, this));
|
m_closeConn = m_popupWindow->Close.connect(base::Bind<void, ToolBar, ToolBar>(&ToolBar::onClosePopup, this));
|
||||||
m_openedRecently = true;
|
m_openedRecently = true;
|
||||||
|
|
||||||
@ -425,9 +425,6 @@ void ToolBar::openPopupWindow(int group_index, ToolGroup* tool_group)
|
|||||||
Region rgn(gfx::Rect(rc).enlarge(16*guiscale()));
|
Region rgn(gfx::Rect(rc).enlarge(16*guiscale()));
|
||||||
rgn.createUnion(rgn, Region(bounds()));
|
rgn.createUnion(rgn, Region(bounds()));
|
||||||
m_popupWindow->setHotRegion(rgn);
|
m_popupWindow->setHotRegion(rgn);
|
||||||
|
|
||||||
m_popupWindow->setTransparent(true);
|
|
||||||
m_popupWindow->setBgColor(gfx::ColorNone);
|
|
||||||
m_popupWindow->setAutoRemap(false);
|
m_popupWindow->setAutoRemap(false);
|
||||||
m_popupWindow->setBounds(rc);
|
m_popupWindow->setBounds(rc);
|
||||||
toolstrip->setBounds(rc);
|
toolstrip->setBounds(rc);
|
||||||
|
@ -33,7 +33,7 @@ IntEntry::IntEntry(int min, int max, SliderDelegate* sliderDelegate)
|
|||||||
, m_min(min)
|
, m_min(min)
|
||||||
, m_max(max)
|
, m_max(max)
|
||||||
, m_slider(m_min, m_max, m_min, sliderDelegate)
|
, m_slider(m_min, m_max, m_min, sliderDelegate)
|
||||||
, m_popupWindow(NULL)
|
, m_popupWindow(nullptr)
|
||||||
, m_changeFromSlider(false)
|
, m_changeFromSlider(false)
|
||||||
{
|
{
|
||||||
m_slider.setFocusStop(false); // In this way the IntEntry doesn't lost the focus
|
m_slider.setFocusStop(false); // In this way the IntEntry doesn't lost the focus
|
||||||
@ -160,31 +160,26 @@ void IntEntry::openPopup()
|
|||||||
{
|
{
|
||||||
m_slider.setValue(getValue());
|
m_slider.setValue(getValue());
|
||||||
|
|
||||||
|
m_popupWindow = new TransparentPopupWindow(PopupWindow::ClickBehavior::CloseOnClickInOtherWindow);
|
||||||
|
m_popupWindow->setAutoRemap(false);
|
||||||
|
m_popupWindow->addChild(&m_slider);
|
||||||
|
m_popupWindow->Close.connect(&IntEntry::onPopupClose, this);
|
||||||
|
|
||||||
Rect rc = bounds();
|
Rect rc = bounds();
|
||||||
int sliderH = m_slider.sizeHint().h;
|
gfx::Size sz = m_popupWindow->sizeHint();
|
||||||
|
|
||||||
if (rc.y+rc.h+sliderH < ui::display_h())
|
|
||||||
rc.y += rc.h;
|
|
||||||
else
|
|
||||||
rc.y -= sliderH;
|
|
||||||
|
|
||||||
rc.h = sliderH;
|
|
||||||
rc.w = 128*guiscale();
|
rc.w = 128*guiscale();
|
||||||
if (rc.x+rc.w > ui::display_w())
|
if (rc.x+rc.w > ui::display_w())
|
||||||
rc.x = rc.x - rc.w + bounds().w;
|
rc.x = rc.x-rc.w+bounds().w;
|
||||||
|
if (rc.y+rc.h+sz.h < ui::display_h())
|
||||||
m_popupWindow = new PopupWindow("", PopupWindow::ClickBehavior::CloseOnClickInOtherWindow);
|
rc.y += rc.h;
|
||||||
m_popupWindow->setAutoRemap(false);
|
else
|
||||||
m_popupWindow->setTransparent(true);
|
rc.y -= sz.h;
|
||||||
m_popupWindow->setBgColor(gfx::ColorNone);
|
|
||||||
m_popupWindow->setBounds(rc);
|
m_popupWindow->setBounds(rc);
|
||||||
m_popupWindow->Close.connect(&IntEntry::onPopupClose, this);
|
|
||||||
|
|
||||||
Region rgn(rc.createUnion(bounds()));
|
Region rgn(rc.createUnion(bounds()));
|
||||||
rgn.createUnion(rgn, Region(bounds()));
|
rgn.createUnion(rgn, Region(bounds()));
|
||||||
m_popupWindow->setHotRegion(rgn);
|
m_popupWindow->setHotRegion(rgn);
|
||||||
|
|
||||||
m_popupWindow->addChild(&m_slider);
|
|
||||||
m_popupWindow->openWindow();
|
m_popupWindow->openWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,11 +34,17 @@ PopupWindow::PopupWindow(const std::string& text,
|
|||||||
setWantFocus(false);
|
setWantFocus(false);
|
||||||
setAlign(LEFT | TOP);
|
setAlign(LEFT | TOP);
|
||||||
|
|
||||||
if (!withCloseButton)
|
if (!withCloseButton) {
|
||||||
removeDecorativeWidgets();
|
// Remove close button
|
||||||
|
for (auto child : children()) {
|
||||||
|
if (child->type() == kWindowCloseButtonWidget) {
|
||||||
|
delete child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
initTheme();
|
initTheme();
|
||||||
noBorderNoChildSpacing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupWindow::~PopupWindow()
|
PopupWindow::~PopupWindow()
|
||||||
@ -172,50 +178,6 @@ bool PopupWindow::onProcessMessage(Message* msg)
|
|||||||
return Window::onProcessMessage(msg);
|
return Window::onProcessMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopupWindow::onSizeHint(SizeHintEvent& ev)
|
|
||||||
{
|
|
||||||
ScreenGraphics g;
|
|
||||||
g.setFont(font());
|
|
||||||
Size resultSize(0, 0);
|
|
||||||
|
|
||||||
if (hasText())
|
|
||||||
resultSize = g.fitString(text(),
|
|
||||||
(clientBounds() - border()).w,
|
|
||||||
align());
|
|
||||||
|
|
||||||
resultSize.w += border().width();
|
|
||||||
resultSize.h += border().height();
|
|
||||||
|
|
||||||
if (!children().empty()) {
|
|
||||||
Size maxSize(0, 0);
|
|
||||||
Size reqSize;
|
|
||||||
|
|
||||||
for (auto child : children()) {
|
|
||||||
reqSize = child->sizeHint();
|
|
||||||
|
|
||||||
maxSize.w = MAX(maxSize.w, reqSize.w);
|
|
||||||
maxSize.h = MAX(maxSize.h, reqSize.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
resultSize.w = MAX(resultSize.w, maxSize.w + border().width());
|
|
||||||
resultSize.h += maxSize.h;
|
|
||||||
}
|
|
||||||
|
|
||||||
ev.setSizeHint(resultSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PopupWindow::onPaint(PaintEvent& ev)
|
|
||||||
{
|
|
||||||
theme()->paintPopupWindow(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PopupWindow::onInitTheme(InitThemeEvent& ev)
|
|
||||||
{
|
|
||||||
Widget::onInitTheme(ev);
|
|
||||||
|
|
||||||
setBorder(gfx::Border(3 * guiscale()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PopupWindow::onHitTest(HitTestEvent& ev)
|
void PopupWindow::onHitTest(HitTestEvent& ev)
|
||||||
{
|
{
|
||||||
Window::onHitTest(ev);
|
Window::onHitTest(ev);
|
||||||
@ -283,4 +245,12 @@ void PopupWindow::onMakeFixed()
|
|||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransparentPopupWindow::TransparentPopupWindow(ClickBehavior clickBehavior)
|
||||||
|
: PopupWindow("", clickBehavior)
|
||||||
|
{
|
||||||
|
setTransparent(true);
|
||||||
|
setBgColor(gfx::ColorNone);
|
||||||
|
initTheme();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite UI Library
|
// 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.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -42,9 +42,6 @@ namespace ui {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onProcessMessage(Message* msg) override;
|
bool onProcessMessage(Message* msg) override;
|
||||||
void onSizeHint(SizeHintEvent& ev) override;
|
|
||||||
void onPaint(PaintEvent& ev) override;
|
|
||||||
void onInitTheme(InitThemeEvent& ev) override;
|
|
||||||
void onHitTest(HitTestEvent& ev) override;
|
void onHitTest(HitTestEvent& ev) override;
|
||||||
|
|
||||||
virtual void onMakeFloating();
|
virtual void onMakeFloating();
|
||||||
@ -61,6 +58,11 @@ namespace ui {
|
|||||||
bool m_fixed;
|
bool m_fixed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TransparentPopupWindow : public PopupWindow {
|
||||||
|
public:
|
||||||
|
TransparentPopupWindow(ClickBehavior clickBehavior);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,10 +12,17 @@
|
|||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
|
// static
|
||||||
|
gfx::Border Style::UndefinedBorder()
|
||||||
|
{
|
||||||
|
return gfx::Border(-1, -1, -1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
Style::Style(const Style* base)
|
Style::Style(const Style* base)
|
||||||
: m_insertionPoint(0)
|
: m_insertionPoint(0)
|
||||||
, m_border(base ? base->border(): gfx::Border(-1, -1, -1, -1))
|
, m_margin(base ? base->margin(): Style::UndefinedBorder())
|
||||||
, m_padding(base ? base->padding(): gfx::Border(-1, -1, -1, -1))
|
, m_border(base ? base->border(): Style::UndefinedBorder())
|
||||||
|
, m_padding(base ? base->padding(): Style::UndefinedBorder())
|
||||||
{
|
{
|
||||||
if (base)
|
if (base)
|
||||||
m_layers = base->layers();
|
m_layers = base->layers();
|
||||||
|
@ -85,14 +85,18 @@ namespace ui {
|
|||||||
|
|
||||||
typedef std::vector<Layer> Layers;
|
typedef std::vector<Layer> Layers;
|
||||||
|
|
||||||
|
static gfx::Border UndefinedBorder();
|
||||||
|
|
||||||
Style(const Style* base);
|
Style(const Style* base);
|
||||||
|
|
||||||
const std::string& id() const { return m_id; }
|
const std::string& id() const { return m_id; }
|
||||||
|
const gfx::Border& margin() const { return m_margin; }
|
||||||
const gfx::Border& border() const { return m_border; }
|
const gfx::Border& border() const { return m_border; }
|
||||||
const gfx::Border& padding() const { return m_padding; }
|
const gfx::Border& padding() const { return m_padding; }
|
||||||
const Layers& layers() const { return m_layers; }
|
const Layers& layers() const { return m_layers; }
|
||||||
|
|
||||||
void setId(const std::string& id) { m_id = id; }
|
void setId(const std::string& id) { m_id = id; }
|
||||||
|
void setMargin(const gfx::Border& value) { m_margin = value; }
|
||||||
void setBorder(const gfx::Border& value) { m_border = value; }
|
void setBorder(const gfx::Border& value) { m_border = value; }
|
||||||
void setPadding(const gfx::Border& value) { m_padding = value; }
|
void setPadding(const gfx::Border& value) { m_padding = value; }
|
||||||
void addLayer(const Layer& layer);
|
void addLayer(const Layer& layer);
|
||||||
@ -101,6 +105,7 @@ namespace ui {
|
|||||||
std::string m_id; // Just for debugging purposes
|
std::string m_id; // Just for debugging purposes
|
||||||
Layers m_layers;
|
Layers m_layers;
|
||||||
int m_insertionPoint;
|
int m_insertionPoint;
|
||||||
|
gfx::Border m_margin;
|
||||||
gfx::Border m_border;
|
gfx::Border m_border;
|
||||||
gfx::Border m_padding;
|
gfx::Border m_padding;
|
||||||
};
|
};
|
||||||
|
220
src/ui/theme.cpp
220
src/ui/theme.cpp
@ -23,6 +23,7 @@
|
|||||||
#include "ui/system.h"
|
#include "ui/system.h"
|
||||||
#include "ui/view.h"
|
#include "ui/view.h"
|
||||||
#include "ui/widget.h"
|
#include "ui/widget.h"
|
||||||
|
#include "ui/window.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -101,18 +102,58 @@ void Theme::regenerate()
|
|||||||
set_mouse_cursor(type);
|
set_mouse_cursor(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Theme::setDecorativeWidgetBounds(Widget* widget)
|
||||||
|
{
|
||||||
|
switch (widget->type()) {
|
||||||
|
|
||||||
|
case kWindowTitleLabelWidget: {
|
||||||
|
Window* window = widget->window();
|
||||||
|
gfx::Rect labelBounds(widget->sizeHint());
|
||||||
|
gfx::Rect windowBounds(window->bounds());
|
||||||
|
gfx::Border margin;
|
||||||
|
if (widget->style())
|
||||||
|
margin = widget->style()->margin();
|
||||||
|
|
||||||
|
labelBounds.offset(
|
||||||
|
windowBounds.x + margin.left(),
|
||||||
|
windowBounds.y + margin.top());
|
||||||
|
|
||||||
|
widget->setBounds(labelBounds);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kWindowCloseButtonWidget: {
|
||||||
|
Window* window = widget->window();
|
||||||
|
gfx::Rect buttonBounds(widget->sizeHint());
|
||||||
|
gfx::Rect windowBounds(window->bounds());
|
||||||
|
gfx::Border margin(0, 0, 0, 0);
|
||||||
|
if (widget->style())
|
||||||
|
margin = widget->style()->margin();
|
||||||
|
|
||||||
|
buttonBounds.offset(
|
||||||
|
windowBounds.x2() - margin.right() - buttonBounds.w,
|
||||||
|
windowBounds.y + margin.top());
|
||||||
|
|
||||||
|
widget->setBounds(buttonBounds);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Theme::paintWidget(Graphics* g,
|
void Theme::paintWidget(Graphics* g,
|
||||||
const Widget* widget,
|
const Widget* widget,
|
||||||
const Style* style,
|
const Style* style,
|
||||||
gfx::Rect rc)
|
const gfx::Rect& bounds)
|
||||||
{
|
{
|
||||||
ASSERT(g);
|
ASSERT(g);
|
||||||
ASSERT(widget);
|
ASSERT(widget);
|
||||||
ASSERT(style);
|
ASSERT(style);
|
||||||
|
|
||||||
// External background
|
// External background
|
||||||
g->fillRect(widget->bgColor(), rc);
|
g->fillRect(widget->bgColor(), bounds);
|
||||||
|
|
||||||
|
gfx::Rect rc = bounds;
|
||||||
for_each_layer(
|
for_each_layer(
|
||||||
widget, style,
|
widget, style,
|
||||||
[this, g, widget, &rc](const Style::Layer& layer) {
|
[this, g, widget, &rc](const Style::Layer& layer) {
|
||||||
@ -120,6 +161,68 @@ void Theme::paintWidget(Graphics* g,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Theme::paintTooltip(Graphics* g,
|
||||||
|
const Widget* widget,
|
||||||
|
const Style* style,
|
||||||
|
const Style* arrowStyle,
|
||||||
|
const gfx::Rect& bounds,
|
||||||
|
const int arrowAlign,
|
||||||
|
const gfx::Rect& target)
|
||||||
|
{
|
||||||
|
if (style)
|
||||||
|
paintWidget(g, widget, style, bounds);
|
||||||
|
|
||||||
|
// Draw arrow
|
||||||
|
if (arrowStyle) {
|
||||||
|
gfx::Size topLeft;
|
||||||
|
gfx::Size center;
|
||||||
|
gfx::Size bottomRight;
|
||||||
|
calcSlices(widget, arrowStyle,
|
||||||
|
topLeft, center, bottomRight);
|
||||||
|
|
||||||
|
gfx::Rect clip, rc(0, 0,
|
||||||
|
topLeft.w+center.w+bottomRight.w,
|
||||||
|
topLeft.h+center.h+bottomRight.h);
|
||||||
|
|
||||||
|
if (arrowAlign & LEFT) {
|
||||||
|
clip.w = topLeft.w;
|
||||||
|
clip.x = bounds.x;
|
||||||
|
rc.x = bounds.x;
|
||||||
|
}
|
||||||
|
else if (arrowAlign & RIGHT) {
|
||||||
|
clip.w = bottomRight.w;
|
||||||
|
clip.x = bounds.x+bounds.w-clip.w;
|
||||||
|
rc.x = bounds.x2()-rc.w;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
clip.w = center.w;
|
||||||
|
clip.x = target.x+target.w/2-clip.w/2;
|
||||||
|
rc.x = clip.x - topLeft.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrowAlign & TOP) {
|
||||||
|
clip.h = topLeft.h;
|
||||||
|
clip.y = bounds.y;
|
||||||
|
rc.y = bounds.y;
|
||||||
|
}
|
||||||
|
else if (arrowAlign & BOTTOM) {
|
||||||
|
clip.h = bottomRight.h;
|
||||||
|
clip.y = bounds.y+bounds.h-clip.h;
|
||||||
|
rc.y = bounds.y2()-rc.h;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
clip.h = center.h;
|
||||||
|
clip.y = target.y+target.h/2-clip.h/2;
|
||||||
|
rc.y = clip.y - topLeft.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntersectClip intClip(g, clip);
|
||||||
|
if (intClip)
|
||||||
|
paintWidget(g, widget, arrowStyle, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Theme::paintLayer(Graphics* g,
|
void Theme::paintLayer(Graphics* g,
|
||||||
const Widget* widget,
|
const Widget* widget,
|
||||||
const Style::Layer& layer,
|
const Style::Layer& layer,
|
||||||
@ -133,16 +236,26 @@ void Theme::paintLayer(Graphics* g,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (layer.spriteSheet() &&
|
if (layer.spriteSheet() &&
|
||||||
!layer.spriteBounds().isEmpty() &&
|
!layer.spriteBounds().isEmpty()) {
|
||||||
!layer.slicesBounds().isEmpty()) {
|
if (!layer.slicesBounds().isEmpty()) {
|
||||||
Theme::drawSlices(g, layer.spriteSheet(), rc,
|
Theme::drawSlices(g, layer.spriteSheet(), rc,
|
||||||
layer.spriteBounds(),
|
layer.spriteBounds(),
|
||||||
layer.slicesBounds(), true);
|
layer.slicesBounds(), true);
|
||||||
|
|
||||||
rc.x += layer.slicesBounds().x;
|
rc.x += layer.slicesBounds().x;
|
||||||
rc.y += layer.slicesBounds().y;
|
rc.y += layer.slicesBounds().y;
|
||||||
rc.w -= layer.spriteBounds().w - layer.slicesBounds().w;
|
rc.w -= layer.spriteBounds().w - layer.slicesBounds().w;
|
||||||
rc.h -= layer.spriteBounds().h - layer.slicesBounds().h;
|
rc.h -= layer.spriteBounds().h - layer.slicesBounds().h;
|
||||||
|
}
|
||||||
|
// Draw background as a solid piece
|
||||||
|
else {
|
||||||
|
g->drawRgbaSurface(layer.spriteSheet(),
|
||||||
|
layer.spriteBounds().x,
|
||||||
|
layer.spriteBounds().y,
|
||||||
|
rc.x, rc.y,
|
||||||
|
layer.spriteBounds().w,
|
||||||
|
layer.spriteBounds().h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -197,8 +310,9 @@ void Theme::paintLayer(Graphics* g,
|
|||||||
gfx::Size iconSize(icon->width(), icon->height());
|
gfx::Size iconSize(icon->width(), icon->height());
|
||||||
gfx::Point pt;
|
gfx::Point pt;
|
||||||
|
|
||||||
if (layer.align() & LEFT)
|
if (layer.align() & LEFT) {
|
||||||
pt.x = rc.x;
|
pt.x = rc.x;
|
||||||
|
}
|
||||||
else if (layer.align() & RIGHT)
|
else if (layer.align() & RIGHT)
|
||||||
pt.x = rc.x+rc.w-iconSize.w;
|
pt.x = rc.x+rc.w-iconSize.w;
|
||||||
else
|
else
|
||||||
@ -242,12 +356,17 @@ void Theme::measureLayer(const Widget* widget,
|
|||||||
case Style::Layer::Type::kBackground:
|
case Style::Layer::Type::kBackground:
|
||||||
case Style::Layer::Type::kBorder:
|
case Style::Layer::Type::kBorder:
|
||||||
if (layer.spriteSheet() &&
|
if (layer.spriteSheet() &&
|
||||||
!layer.spriteBounds().isEmpty() &&
|
!layer.spriteBounds().isEmpty()) {
|
||||||
!layer.slicesBounds().isEmpty()) {
|
if (!layer.slicesBounds().isEmpty()) {
|
||||||
borderHint.left(std::max(borderHint.left(), layer.slicesBounds().x));
|
borderHint.left(std::max(borderHint.left(), layer.slicesBounds().x));
|
||||||
borderHint.top(std::max(borderHint.top(), layer.slicesBounds().y));
|
borderHint.top(std::max(borderHint.top(), layer.slicesBounds().y));
|
||||||
borderHint.right(std::max(borderHint.right(), layer.spriteBounds().w - layer.slicesBounds().x2()));
|
borderHint.right(std::max(borderHint.right(), layer.spriteBounds().w - layer.slicesBounds().x2()));
|
||||||
borderHint.bottom(std::max(borderHint.bottom(), layer.spriteBounds().h - layer.slicesBounds().y2()));
|
borderHint.bottom(std::max(borderHint.bottom(), layer.spriteBounds().h - layer.slicesBounds().y2()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iconHint.w = std::max(iconHint.w, layer.spriteBounds().w);
|
||||||
|
iconHint.h = std::max(iconHint.h, layer.spriteBounds().h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -284,6 +403,53 @@ gfx::Border Theme::calcBorder(const Widget* widget,
|
|||||||
return borderHint;
|
return borderHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Theme::calcSlices(const Widget* widget,
|
||||||
|
const Style* style,
|
||||||
|
gfx::Size& topLeft,
|
||||||
|
gfx::Size& center,
|
||||||
|
gfx::Size& bottomRight)
|
||||||
|
{
|
||||||
|
ASSERT(widget);
|
||||||
|
ASSERT(style);
|
||||||
|
|
||||||
|
for_each_layer(
|
||||||
|
widget, style,
|
||||||
|
[&topLeft, ¢er, &bottomRight]
|
||||||
|
(const Style::Layer& layer) {
|
||||||
|
if (layer.spriteSheet() &&
|
||||||
|
!layer.spriteBounds().isEmpty() &&
|
||||||
|
!layer.slicesBounds().isEmpty()) {
|
||||||
|
gfx::Rect sprite = layer.spriteBounds();
|
||||||
|
gfx::Rect slices = layer.slicesBounds();
|
||||||
|
topLeft.w = MAX(topLeft.w, slices.x);
|
||||||
|
topLeft.h = MAX(topLeft.h, slices.y);
|
||||||
|
center.w = MAX(center.w, slices.w);
|
||||||
|
center.h = MAX(center.h, slices.h);
|
||||||
|
bottomRight.w = MAX(bottomRight.w, sprite.w - slices.x2());
|
||||||
|
bottomRight.h = MAX(bottomRight.h, sprite.h - slices.y2());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Color Theme::calcBgColor(const Widget* widget,
|
||||||
|
const Style* style)
|
||||||
|
{
|
||||||
|
ASSERT(widget);
|
||||||
|
ASSERT(style);
|
||||||
|
|
||||||
|
gfx::Color bgColor = gfx::ColorNone;
|
||||||
|
|
||||||
|
for_each_layer(
|
||||||
|
widget, style,
|
||||||
|
[&bgColor]
|
||||||
|
(const Style::Layer& layer) {
|
||||||
|
if (layer.type() == Style::Layer::Type::kBackground)
|
||||||
|
bgColor = layer.color();
|
||||||
|
});
|
||||||
|
|
||||||
|
return bgColor;
|
||||||
|
}
|
||||||
|
|
||||||
void Theme::calcWidgetMetrics(const Widget* widget,
|
void Theme::calcWidgetMetrics(const Widget* widget,
|
||||||
const Style* style,
|
const Style* style,
|
||||||
gfx::Size& sizeHint,
|
gfx::Size& sizeHint,
|
||||||
@ -309,15 +475,17 @@ void Theme::calcWidgetMetrics(const Widget* widget,
|
|||||||
iconHint, iconAlign);
|
iconHint, iconAlign);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (style->border().left() >= 0) borderHint.left(style->border().left());
|
gfx::Border undef = Style::UndefinedBorder();
|
||||||
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->border().left() != undef.left()) borderHint.left(style->border().left());
|
||||||
if (style->padding().top() >= 0) paddingHint.top(style->padding().top());
|
if (style->border().top() != undef.top()) borderHint.top(style->border().top());
|
||||||
if (style->padding().right() >= 0) paddingHint.right(style->padding().right());
|
if (style->border().right() != undef.right()) borderHint.right(style->border().right());
|
||||||
if (style->padding().bottom() >= 0) paddingHint.bottom(style->padding().bottom());
|
if (style->border().bottom() != undef.bottom()) borderHint.bottom(style->border().bottom());
|
||||||
|
|
||||||
|
if (style->padding().left() != undef.left()) paddingHint.left(style->padding().left());
|
||||||
|
if (style->padding().top() != undef.top()) paddingHint.top(style->padding().top());
|
||||||
|
if (style->padding().right() != undef.right()) paddingHint.right(style->padding().right());
|
||||||
|
if (style->padding().bottom() != undef.bottom()) paddingHint.bottom(style->padding().bottom());
|
||||||
|
|
||||||
sizeHint = gfx::Size(borderHint.width() + paddingHint.width(),
|
sizeHint = gfx::Size(borderHint.width() + paddingHint.width(),
|
||||||
borderHint.height() + paddingHint.height());
|
borderHint.height() + paddingHint.height());
|
||||||
|
@ -49,7 +49,7 @@ namespace ui {
|
|||||||
virtual Cursor* getCursor(CursorType type) = 0;
|
virtual Cursor* getCursor(CursorType type) = 0;
|
||||||
virtual void initWidget(Widget* widget) = 0;
|
virtual void initWidget(Widget* widget) = 0;
|
||||||
virtual void getWindowMask(Widget* widget, gfx::Region& region) = 0;
|
virtual void getWindowMask(Widget* widget, gfx::Region& region) = 0;
|
||||||
virtual void setDecorativeWidgetBounds(Widget* widget) = 0;
|
virtual void setDecorativeWidgetBounds(Widget* widget);
|
||||||
virtual int getScrollbarSize() = 0;
|
virtual int getScrollbarSize() = 0;
|
||||||
virtual gfx::Size getEntryCaretSize(Widget* widget) = 0;
|
virtual gfx::Size getEntryCaretSize(Widget* widget) = 0;
|
||||||
|
|
||||||
@ -70,19 +70,32 @@ namespace ui {
|
|||||||
virtual void paintTextBox(PaintEvent& ev) = 0;
|
virtual void paintTextBox(PaintEvent& ev) = 0;
|
||||||
virtual void paintViewScrollbar(PaintEvent& ev) = 0;
|
virtual void paintViewScrollbar(PaintEvent& ev) = 0;
|
||||||
virtual void paintViewViewport(PaintEvent& ev) = 0;
|
virtual void paintViewViewport(PaintEvent& ev) = 0;
|
||||||
virtual void paintWindow(PaintEvent& ev) = 0;
|
|
||||||
virtual void paintPopupWindow(PaintEvent& ev) = 0;
|
|
||||||
virtual void paintTooltip(PaintEvent& ev) = 0;
|
|
||||||
|
|
||||||
// Default implementation to draw widgets with new ui::Styles
|
// Default implementation to draw widgets with new ui::Styles
|
||||||
virtual void paintWidget(Graphics* g,
|
virtual void paintWidget(Graphics* g,
|
||||||
const Widget* widget,
|
const Widget* widget,
|
||||||
const Style* style,
|
const Style* style,
|
||||||
gfx::Rect rc);
|
const gfx::Rect& bounds);
|
||||||
|
|
||||||
|
virtual void paintTooltip(Graphics* g,
|
||||||
|
const Widget* widget,
|
||||||
|
const Style* style,
|
||||||
|
const Style* arrowStyle,
|
||||||
|
const gfx::Rect& bounds,
|
||||||
|
const int arrowAlign,
|
||||||
|
const gfx::Rect& target);
|
||||||
|
|
||||||
virtual gfx::Size calcSizeHint(const Widget* widget,
|
virtual gfx::Size calcSizeHint(const Widget* widget,
|
||||||
const Style* style);
|
const Style* style);
|
||||||
virtual gfx::Border calcBorder(const Widget* widget,
|
virtual gfx::Border calcBorder(const Widget* widget,
|
||||||
const Style* style);
|
const Style* style);
|
||||||
|
virtual void calcSlices(const Widget* widget,
|
||||||
|
const Style* style,
|
||||||
|
gfx::Size& topLeft,
|
||||||
|
gfx::Size& center,
|
||||||
|
gfx::Size& bottomRight);
|
||||||
|
virtual gfx::Color calcBgColor(const Widget* widget,
|
||||||
|
const Style* style);
|
||||||
|
|
||||||
static void drawSlices(Graphics* g,
|
static void drawSlices(Graphics* g,
|
||||||
she::Surface* sheet,
|
she::Surface* sheet,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite UI Library
|
// 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.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -19,6 +19,7 @@
|
|||||||
#include "ui/paint_event.h"
|
#include "ui/paint_event.h"
|
||||||
#include "ui/size_hint_event.h"
|
#include "ui/size_hint_event.h"
|
||||||
#include "ui/system.h"
|
#include "ui/system.h"
|
||||||
|
#include "ui/textbox.h"
|
||||||
#include "ui/theme.h"
|
#include "ui/theme.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -123,12 +124,20 @@ void TooltipManager::onTick()
|
|||||||
// TipWindow
|
// TipWindow
|
||||||
|
|
||||||
TipWindow::TipWindow(const std::string& text)
|
TipWindow::TipWindow(const std::string& text)
|
||||||
: PopupWindow(text, ClickBehavior::CloseOnClickInOtherWindow)
|
// Put an empty string in the ctor so the window label isn't build
|
||||||
|
: PopupWindow("", ClickBehavior::CloseOnClickInOtherWindow)
|
||||||
|
, m_arrowStyle(nullptr)
|
||||||
, m_arrowAlign(0)
|
, m_arrowAlign(0)
|
||||||
, m_closeOnKeyDown(true)
|
, m_closeOnKeyDown(true)
|
||||||
|
, m_textBox(new TextBox("", LEFT | TOP))
|
||||||
{
|
{
|
||||||
setTransparent(true);
|
setTransparent(true);
|
||||||
|
|
||||||
|
// Here we build our own custimized label for the window
|
||||||
|
// (a text box).
|
||||||
|
addChild(m_textBox);
|
||||||
|
setText(text);
|
||||||
|
|
||||||
makeFixed();
|
makeFixed();
|
||||||
initTheme();
|
initTheme();
|
||||||
}
|
}
|
||||||
@ -232,50 +241,17 @@ bool TipWindow::onProcessMessage(Message* msg)
|
|||||||
return PopupWindow::onProcessMessage(msg);
|
return PopupWindow::onProcessMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TipWindow::onSizeHint(SizeHintEvent& ev)
|
|
||||||
{
|
|
||||||
ScreenGraphics g;
|
|
||||||
g.setFont(font());
|
|
||||||
Size resultSize =
|
|
||||||
g.fitString(text(),
|
|
||||||
(clientBounds() - border()).w,
|
|
||||||
align());
|
|
||||||
|
|
||||||
resultSize.w += border().width();
|
|
||||||
resultSize.h += border().height();
|
|
||||||
|
|
||||||
if (!children().empty()) {
|
|
||||||
Size maxSize(0, 0);
|
|
||||||
Size reqSize;
|
|
||||||
|
|
||||||
for (auto child : children()) {
|
|
||||||
reqSize = child->sizeHint();
|
|
||||||
|
|
||||||
maxSize.w = MAX(maxSize.w, reqSize.w);
|
|
||||||
maxSize.h = MAX(maxSize.h, reqSize.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
resultSize.w = MAX(resultSize.w, maxSize.w + border().width());
|
|
||||||
resultSize.h += maxSize.h;
|
|
||||||
}
|
|
||||||
|
|
||||||
ev.setSizeHint(resultSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TipWindow::onInitTheme(InitThemeEvent& ev)
|
|
||||||
{
|
|
||||||
Window::onInitTheme(ev);
|
|
||||||
|
|
||||||
setBorder(
|
|
||||||
gfx::Border(6 * guiscale(),
|
|
||||||
6 * guiscale(),
|
|
||||||
6 * guiscale(),
|
|
||||||
7 * guiscale()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TipWindow::onPaint(PaintEvent& ev)
|
void TipWindow::onPaint(PaintEvent& ev)
|
||||||
{
|
{
|
||||||
theme()->paintTooltip(ev);
|
theme()->paintTooltip(
|
||||||
|
ev.graphics(), this, style(), arrowStyle(),
|
||||||
|
clientBounds(), arrowAlign(),
|
||||||
|
gfx::Rect(target()).offset(-bounds().origin()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TipWindow::onBuildTitleLabel()
|
||||||
|
{
|
||||||
|
m_textBox->setText(text());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite UI Library
|
// 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.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
|
class TextBox;
|
||||||
class TipWindow;
|
class TipWindow;
|
||||||
|
|
||||||
class TooltipManager : public Widget {
|
class TooltipManager : public Widget {
|
||||||
@ -58,6 +59,9 @@ namespace ui {
|
|||||||
public:
|
public:
|
||||||
TipWindow(const std::string& text = "");
|
TipWindow(const std::string& text = "");
|
||||||
|
|
||||||
|
Style* arrowStyle() { return m_arrowStyle; }
|
||||||
|
void setArrowStyle(Style* style) { m_arrowStyle = style; }
|
||||||
|
|
||||||
int arrowAlign() const { return m_arrowAlign; }
|
int arrowAlign() const { return m_arrowAlign; }
|
||||||
const gfx::Rect& target() const { return m_target; }
|
const gfx::Rect& target() const { return m_target; }
|
||||||
|
|
||||||
@ -67,16 +71,19 @@ namespace ui {
|
|||||||
// window.
|
// window.
|
||||||
bool pointAt(int arrowAlign, const gfx::Rect& target);
|
bool pointAt(int arrowAlign, const gfx::Rect& target);
|
||||||
|
|
||||||
|
TextBox* textBox() const { return m_textBox; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onProcessMessage(Message* msg) override;
|
bool onProcessMessage(Message* msg) override;
|
||||||
void onSizeHint(SizeHintEvent& ev) override;
|
|
||||||
void onInitTheme(InitThemeEvent& ev) override;
|
|
||||||
void onPaint(PaintEvent& ev) override;
|
void onPaint(PaintEvent& ev) override;
|
||||||
|
void onBuildTitleLabel() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Style* m_arrowStyle;
|
||||||
int m_arrowAlign;
|
int m_arrowAlign;
|
||||||
gfx::Rect m_target;
|
gfx::Rect m_target;
|
||||||
bool m_closeOnKeyDown;
|
bool m_closeOnKeyDown;
|
||||||
|
TextBox* m_textBox;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "ui/hit_test_event.h"
|
#include "ui/hit_test_event.h"
|
||||||
#include "ui/image_view.h"
|
#include "ui/image_view.h"
|
||||||
#include "ui/init_theme_event.h"
|
#include "ui/init_theme_event.h"
|
||||||
|
#include "ui/int_entry.h"
|
||||||
#include "ui/keys.h"
|
#include "ui/keys.h"
|
||||||
#include "ui/label.h"
|
#include "ui/label.h"
|
||||||
#include "ui/layout_io.h"
|
#include "ui/layout_io.h"
|
||||||
|
@ -176,6 +176,10 @@ void Widget::setBgColor(gfx::Color color)
|
|||||||
{
|
{
|
||||||
m_bgColor = color;
|
m_bgColor = color;
|
||||||
onSetBgColor();
|
onSetBgColor();
|
||||||
|
|
||||||
|
if (m_style) {
|
||||||
|
LOG(WARNING) << "Warning setting bgColor to a widget with style\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::setTheme(Theme* theme)
|
void Widget::setTheme(Theme* theme)
|
||||||
@ -188,6 +192,7 @@ void Widget::setStyle(Style* style)
|
|||||||
{
|
{
|
||||||
m_style = style;
|
m_style = style;
|
||||||
m_border = m_theme->calcBorder(this, style);
|
m_border = m_theme->calcBorder(this, style);
|
||||||
|
m_bgColor = m_theme->calcBgColor(this, m_style);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===============================================================
|
// ===============================================================
|
||||||
@ -645,6 +650,7 @@ void Widget::setBoundsQuietly(const gfx::Rect& rc)
|
|||||||
void Widget::setBorder(const Border& br)
|
void Widget::setBorder(const Border& br)
|
||||||
{
|
{
|
||||||
m_border = br;
|
m_border = br;
|
||||||
|
|
||||||
if (m_style) {
|
if (m_style) {
|
||||||
LOG(WARNING) << "Warning setting border to a widget with style\n";
|
LOG(WARNING) << "Warning setting border to a widget with style\n";
|
||||||
}
|
}
|
||||||
@ -1484,9 +1490,8 @@ void Widget::onInitTheme(InitThemeEvent& ev)
|
|||||||
|
|
||||||
void Widget::onSetDecorativeWidgetBounds()
|
void Widget::onSetDecorativeWidgetBounds()
|
||||||
{
|
{
|
||||||
if (m_theme) {
|
if (m_theme)
|
||||||
m_theme->setDecorativeWidgetBounds(this);
|
m_theme->setDecorativeWidgetBounds(this);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::onVisible(bool visible)
|
void Widget::onVisible(bool visible)
|
||||||
|
@ -42,6 +42,8 @@ namespace ui {
|
|||||||
kViewViewportWidget,
|
kViewViewportWidget,
|
||||||
kViewWidget,
|
kViewWidget,
|
||||||
kWindowWidget,
|
kWindowWidget,
|
||||||
|
kWindowTitleLabelWidget,
|
||||||
|
kWindowCloseButtonWidget,
|
||||||
|
|
||||||
// User widgets.
|
// User widgets.
|
||||||
kFirstUserWidget,
|
kFirstUserWidget,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite UI Library
|
// 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.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -11,14 +11,16 @@
|
|||||||
#include "ui/window.h"
|
#include "ui/window.h"
|
||||||
|
|
||||||
#include "gfx/size.h"
|
#include "gfx/size.h"
|
||||||
|
#include "ui/button.h"
|
||||||
#include "ui/graphics.h"
|
#include "ui/graphics.h"
|
||||||
#include "ui/intern.h"
|
#include "ui/intern.h"
|
||||||
|
#include "ui/label.h"
|
||||||
#include "ui/manager.h"
|
#include "ui/manager.h"
|
||||||
#include "ui/message.h"
|
#include "ui/message.h"
|
||||||
#include "ui/message_loop.h"
|
#include "ui/message_loop.h"
|
||||||
#include "ui/move_region.h"
|
#include "ui/move_region.h"
|
||||||
#include "ui/size_hint_event.h"
|
|
||||||
#include "ui/resize_event.h"
|
#include "ui/resize_event.h"
|
||||||
|
#include "ui/size_hint_event.h"
|
||||||
#include "ui/system.h"
|
#include "ui/system.h"
|
||||||
#include "ui/theme.h"
|
#include "ui/theme.h"
|
||||||
|
|
||||||
@ -26,6 +28,8 @@ namespace ui {
|
|||||||
|
|
||||||
using namespace gfx;
|
using namespace gfx;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
WINDOW_NONE = 0,
|
WINDOW_NONE = 0,
|
||||||
WINDOW_MOVE = 1,
|
WINDOW_MOVE = 1,
|
||||||
@ -35,25 +39,88 @@ enum {
|
|||||||
WINDOW_RESIZE_BOTTOM = 16,
|
WINDOW_RESIZE_BOTTOM = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
static gfx::Point clickedMousePos;
|
gfx::Point clickedMousePos;
|
||||||
static gfx::Rect* clickedWindowPos = NULL;
|
gfx::Rect* clickedWindowPos = nullptr;
|
||||||
|
|
||||||
|
class WindowTitleLabel : public Label {
|
||||||
|
public:
|
||||||
|
WindowTitleLabel(const std::string& text) : Label(text) {
|
||||||
|
setDecorative(true);
|
||||||
|
setType(kWindowTitleLabelWidget);
|
||||||
|
initTheme();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Controls the "X" button in a window to close it.
|
||||||
|
class WindowCloseButton : public ButtonBase {
|
||||||
|
public:
|
||||||
|
WindowCloseButton()
|
||||||
|
: ButtonBase("", kWindowCloseButtonWidget,
|
||||||
|
kButtonWidget, kButtonWidget) {
|
||||||
|
setDecorative(true);
|
||||||
|
initTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void onClick(Event& ev) override {
|
||||||
|
ButtonBase::onClick(ev);
|
||||||
|
closeWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool onProcessMessage(Message* msg) override {
|
||||||
|
switch (msg->type()) {
|
||||||
|
|
||||||
|
case kSetCursorMessage:
|
||||||
|
ui::set_mouse_cursor(kArrowCursor);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case kKeyDownMessage:
|
||||||
|
if (window()->isForeground() &&
|
||||||
|
static_cast<KeyMessage*>(msg)->scancode() == kKeyEsc) {
|
||||||
|
setSelected(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kKeyUpMessage:
|
||||||
|
if (window()->isForeground() &&
|
||||||
|
static_cast<KeyMessage*>(msg)->scancode() == kKeyEsc) {
|
||||||
|
if (isSelected()) {
|
||||||
|
setSelected(false);
|
||||||
|
closeWindow();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ButtonBase::onProcessMessage(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
Window::Window(Type type, const std::string& text)
|
Window::Window(Type type, const std::string& text)
|
||||||
: Widget(kWindowWidget)
|
: Widget(kWindowWidget)
|
||||||
|
, m_closer(nullptr)
|
||||||
|
, m_titleLabel(nullptr)
|
||||||
|
, m_closeButton(nullptr)
|
||||||
|
, m_isDesktop(type == DesktopWindow)
|
||||||
|
, m_isMoveable(!m_isDesktop)
|
||||||
|
, m_isSizeable(!m_isDesktop)
|
||||||
|
, m_isOnTop(false)
|
||||||
|
, m_isWantFocus(true)
|
||||||
|
, m_isForeground(false)
|
||||||
|
, m_isAutoRemap(true)
|
||||||
{
|
{
|
||||||
m_closer = NULL;
|
|
||||||
m_isDesktop = (type == DesktopWindow);
|
|
||||||
m_isMoveable = !m_isDesktop;
|
|
||||||
m_isSizeable = !m_isDesktop;
|
|
||||||
m_isOnTop = false;
|
|
||||||
m_isWantFocus = true;
|
|
||||||
m_isForeground = false;
|
|
||||||
m_isAutoRemap = true;
|
|
||||||
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
setAlign(LEFT | MIDDLE);
|
setAlign(LEFT | MIDDLE);
|
||||||
if (type == WithTitleBar)
|
if (type == WithTitleBar) {
|
||||||
setText(text);
|
setText(text);
|
||||||
|
addChild(m_closeButton = new WindowCloseButton);
|
||||||
|
}
|
||||||
|
|
||||||
initTheme();
|
initTheme();
|
||||||
}
|
}
|
||||||
@ -95,12 +162,6 @@ HitTest Window::hitTest(const gfx::Point& point)
|
|||||||
return ev.hit();
|
return ev.hit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::removeDecorativeWidgets()
|
|
||||||
{
|
|
||||||
while (!children().empty())
|
|
||||||
delete children().front();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::onClose(CloseEvent& ev)
|
void Window::onClose(CloseEvent& ev)
|
||||||
{
|
{
|
||||||
// Fire Close signal
|
// Fire Close signal
|
||||||
@ -112,11 +173,18 @@ void Window::onHitTest(HitTestEvent& ev)
|
|||||||
HitTest ht = HitTestNowhere;
|
HitTest ht = HitTestNowhere;
|
||||||
|
|
||||||
// If this window is not movable or we are not completely visible.
|
// If this window is not movable or we are not completely visible.
|
||||||
if (!m_isMoveable ||
|
if (!m_isMoveable) {
|
||||||
// TODO check why this is necessary, there should be a bug in
|
ev.setHit(ht);
|
||||||
// the manager where we are receiving mouse events and are not
|
return;
|
||||||
// the top most window.
|
}
|
||||||
this->manager()->pick(ev.point()) != this) {
|
|
||||||
|
// TODO check why this is necessary, there should be a bug in
|
||||||
|
// the manager where we are receiving mouse events and are not
|
||||||
|
// the top most window.
|
||||||
|
Widget* picked = manager()->pick(ev.point());
|
||||||
|
if (picked &&
|
||||||
|
picked != this &&
|
||||||
|
picked->type() != kWindowTitleLabelWidget) {
|
||||||
ev.setHit(ht);
|
ev.setHit(ht);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -444,19 +512,14 @@ void Window::onSizeHint(SizeHintEvent& ev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasText())
|
if (m_titleLabel)
|
||||||
maxSize.w = MAX(maxSize.w, textWidth());
|
maxSize.w = MAX(maxSize.w, m_titleLabel->sizeHint().w);
|
||||||
|
|
||||||
ev.setSizeHint(maxSize.w + border().width(),
|
ev.setSizeHint(maxSize.w + border().width(),
|
||||||
maxSize.h + border().height());
|
maxSize.h + border().height());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::onPaint(PaintEvent& ev)
|
|
||||||
{
|
|
||||||
theme()->paintWindow(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::onBroadcastMouseMessage(WidgetsList& targets)
|
void Window::onBroadcastMouseMessage(WidgetsList& targets)
|
||||||
{
|
{
|
||||||
targets.push_back(this);
|
targets.push_back(this);
|
||||||
@ -473,10 +536,30 @@ void Window::onBroadcastMouseMessage(WidgetsList& targets)
|
|||||||
|
|
||||||
void Window::onSetText()
|
void Window::onSetText()
|
||||||
{
|
{
|
||||||
|
onBuildTitleLabel();
|
||||||
Widget::onSetText();
|
Widget::onSetText();
|
||||||
initTheme();
|
initTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::onBuildTitleLabel()
|
||||||
|
{
|
||||||
|
if (text().empty()) {
|
||||||
|
if (m_titleLabel) {
|
||||||
|
removeChild(m_titleLabel);
|
||||||
|
delete m_titleLabel;
|
||||||
|
m_titleLabel = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!m_titleLabel) {
|
||||||
|
m_titleLabel = new WindowTitleLabel(text());
|
||||||
|
addChild(m_titleLabel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_titleLabel->setText(text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Window::windowSetPosition(const gfx::Rect& rect)
|
void Window::windowSetPosition(const gfx::Rect& rect)
|
||||||
{
|
{
|
||||||
// Copy the new position rectangle
|
// Copy the new position rectangle
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite UI Library
|
// 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.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
|
class ButtonBase;
|
||||||
|
class Label;
|
||||||
|
|
||||||
class Window : public Widget {
|
class Window : public Widget {
|
||||||
public:
|
public:
|
||||||
enum Type { DesktopWindow, WithTitleBar, WithoutTitleBar };
|
enum Type { DesktopWindow, WithTitleBar, WithoutTitleBar };
|
||||||
@ -51,8 +54,6 @@ namespace ui {
|
|||||||
|
|
||||||
HitTest hitTest(const gfx::Point& point);
|
HitTest hitTest(const gfx::Point& point);
|
||||||
|
|
||||||
void removeDecorativeWidgets();
|
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
obs::signal<void (CloseEvent&)> Close;
|
obs::signal<void (CloseEvent&)> Close;
|
||||||
|
|
||||||
@ -60,7 +61,6 @@ namespace ui {
|
|||||||
virtual bool onProcessMessage(Message* msg) override;
|
virtual bool onProcessMessage(Message* msg) override;
|
||||||
virtual void onResize(ResizeEvent& ev) override;
|
virtual void onResize(ResizeEvent& ev) override;
|
||||||
virtual void onSizeHint(SizeHintEvent& ev) override;
|
virtual void onSizeHint(SizeHintEvent& ev) override;
|
||||||
virtual void onPaint(PaintEvent& ev) override;
|
|
||||||
virtual void onBroadcastMouseMessage(WidgetsList& targets) override;
|
virtual void onBroadcastMouseMessage(WidgetsList& targets) override;
|
||||||
virtual void onSetText() override;
|
virtual void onSetText() override;
|
||||||
|
|
||||||
@ -69,6 +69,7 @@ namespace ui {
|
|||||||
virtual void onHitTest(HitTestEvent& ev);
|
virtual void onHitTest(HitTestEvent& ev);
|
||||||
virtual void onWindowResize();
|
virtual void onWindowResize();
|
||||||
virtual void onWindowMovement();
|
virtual void onWindowMovement();
|
||||||
|
virtual void onBuildTitleLabel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void windowSetPosition(const gfx::Rect& rect);
|
void windowSetPosition(const gfx::Rect& rect);
|
||||||
@ -77,6 +78,8 @@ namespace ui {
|
|||||||
void moveWindow(const gfx::Rect& rect, bool use_blit);
|
void moveWindow(const gfx::Rect& rect, bool use_blit);
|
||||||
|
|
||||||
Widget* m_closer;
|
Widget* m_closer;
|
||||||
|
Label* m_titleLabel;
|
||||||
|
ButtonBase* m_closeButton;
|
||||||
bool m_isDesktop : 1;
|
bool m_isDesktop : 1;
|
||||||
bool m_isMoveable : 1;
|
bool m_isMoveable : 1;
|
||||||
bool m_isSizeable : 1;
|
bool m_isSizeable : 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user