mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-01 10:21:04 +00:00
Convert InkShadesField in a combobox-like widget to store several shades (#85)
Changes: * Added new ui::IconButton widget to create widgets with one skin icon that is colored depending on the button state. * ContextBar::InkShadesField was divided into a couple widgets (ShadeWidget and IconButton to drop-down a little menu with saved shades) * Fixed CommonLockedSurface::drawColoredRgbaSurface() impl. * Removed invalid gfx::setr/g/b/a() functions.
This commit is contained in:
parent
25a331c43a
commit
cf7c4754cc
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@ -406,6 +406,8 @@
|
|||||||
<part id="no_symmetry" x="144" y="240" w="13" h="13" />
|
<part id="no_symmetry" x="144" y="240" w="13" h="13" />
|
||||||
<part id="horizontal_symmetry" x="160" y="240" w="13" h="13" />
|
<part id="horizontal_symmetry" x="160" y="240" w="13" h="13" />
|
||||||
<part id="vertical_symmetry" x="176" y="240" w="13" h="13" />
|
<part id="vertical_symmetry" x="176" y="240" w="13" h="13" />
|
||||||
|
<part id="icon_arrow_down" x="144" y="256" w="7" h="4" />
|
||||||
|
<part id="icon_close" x="153" y="256" w="7" h="7" />
|
||||||
</parts>
|
</parts>
|
||||||
|
|
||||||
<stylesheet>
|
<stylesheet>
|
||||||
|
@ -363,6 +363,7 @@ add_library(app-lib
|
|||||||
ui/frame_tag_window.cpp
|
ui/frame_tag_window.cpp
|
||||||
ui/hex_color_entry.cpp
|
ui/hex_color_entry.cpp
|
||||||
ui/home_view.cpp
|
ui/home_view.cpp
|
||||||
|
ui/icon_button.cpp
|
||||||
ui/input_chain.cpp
|
ui/input_chain.cpp
|
||||||
ui/keyboard_shortcuts.cpp
|
ui/keyboard_shortcuts.cpp
|
||||||
ui/main_menu_bar.cpp
|
ui/main_menu_bar.cpp
|
||||||
|
@ -52,7 +52,7 @@ void SwitchColorsCommand::onExecute(Context* context)
|
|||||||
const auto& toolPref(Preferences::instance().tool(tool));
|
const auto& toolPref(Preferences::instance().tool(tool));
|
||||||
if (toolPref.ink() == tools::InkType::SHADING) {
|
if (toolPref.ink() == tools::InkType::SHADING) {
|
||||||
App::instance()->getMainWindow()->
|
App::instance()->getMainWindow()->
|
||||||
getContextBar()->reverseShadesColors();
|
getContextBar()->reverseShadeColors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
src/app/shade.h
Normal file
22
src/app/shade.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2001-2015 David Capello
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License version 2 as
|
||||||
|
// published by the Free Software Foundation.
|
||||||
|
|
||||||
|
#ifndef APP_SHADE_H_INCLUDED
|
||||||
|
#define APP_SHADE_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "app/color.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
typedef std::vector<app::Color> Shade;
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
||||||
|
#endif
|
@ -18,6 +18,7 @@
|
|||||||
#include "app/modules/gui.h"
|
#include "app/modules/gui.h"
|
||||||
#include "app/modules/palettes.h"
|
#include "app/modules/palettes.h"
|
||||||
#include "app/pref/preferences.h"
|
#include "app/pref/preferences.h"
|
||||||
|
#include "app/shade.h"
|
||||||
#include "app/tools/controller.h"
|
#include "app/tools/controller.h"
|
||||||
#include "app/tools/ink.h"
|
#include "app/tools/ink.h"
|
||||||
#include "app/tools/ink_type.h"
|
#include "app/tools/ink_type.h"
|
||||||
@ -28,6 +29,8 @@
|
|||||||
#include "app/ui/brush_popup.h"
|
#include "app/ui/brush_popup.h"
|
||||||
#include "app/ui/button_set.h"
|
#include "app/ui/button_set.h"
|
||||||
#include "app/ui/color_button.h"
|
#include "app/ui/color_button.h"
|
||||||
|
#include "app/ui/icon_button.h"
|
||||||
|
#include "app/ui/skin/button_icon_impl.h"
|
||||||
#include "app/ui/skin/skin_theme.h"
|
#include "app/ui/skin/skin_theme.h"
|
||||||
#include "app/ui/skin/style.h"
|
#include "app/ui/skin/style.h"
|
||||||
#include "app/ui_context.h"
|
#include "app/ui_context.h"
|
||||||
@ -429,122 +432,288 @@ protected:
|
|||||||
ContextBar* m_owner;
|
ContextBar* m_owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContextBar::InkShadesField : public Widget {
|
class ContextBar::InkShadesField : public HBox {
|
||||||
typedef std::vector<app::Color> Colors;
|
|
||||||
public:
|
|
||||||
|
|
||||||
InkShadesField() : Widget(kGenericWidget) {
|
class ShadeWidget : public Widget {
|
||||||
setText("Select colors in the palette");
|
public:
|
||||||
}
|
enum ClickType { DragAndDrop, Select };
|
||||||
|
|
||||||
void reverseColors() {
|
Signal0<void> Click;
|
||||||
std::reverse(m_colors.begin(), m_colors.end());
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
doc::Remap* createShadesRemap(bool left) {
|
ShadeWidget(const Shade& colors, ClickType click)
|
||||||
base::UniquePtr<doc::Remap> remap;
|
: Widget(kGenericWidget)
|
||||||
Colors colors = getColors();
|
, m_click(click)
|
||||||
|
, m_shade(colors)
|
||||||
|
, m_hotIndex(-1)
|
||||||
|
, m_boxSize(12) {
|
||||||
|
setText("Select colors in the palette");
|
||||||
|
}
|
||||||
|
|
||||||
if (colors.size() > 0) {
|
void reverseShadeColors() {
|
||||||
remap.reset(new doc::Remap(get_current_palette()->size()));
|
std::reverse(m_shade.begin(), m_shade.end());
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0; i<remap->size(); ++i)
|
doc::Remap* createShadeRemap(bool left) {
|
||||||
remap->map(i, i);
|
base::UniquePtr<doc::Remap> remap;
|
||||||
|
Shade colors = getShade();
|
||||||
|
|
||||||
if (left) {
|
if (colors.size() > 0) {
|
||||||
for (int i=1; i<int(colors.size()); ++i)
|
remap.reset(new doc::Remap(get_current_palette()->size()));
|
||||||
remap->map(colors[i].getIndex(), colors[i-1].getIndex());
|
|
||||||
|
for (int i=0; i<remap->size(); ++i)
|
||||||
|
remap->map(i, i);
|
||||||
|
|
||||||
|
if (left) {
|
||||||
|
for (int i=1; i<int(colors.size()); ++i)
|
||||||
|
remap->map(colors[i].getIndex(), colors[i-1].getIndex());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i=0; i<int(colors.size())-1; ++i)
|
||||||
|
remap->map(colors[i].getIndex(), colors[i+1].getIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return remap.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
int size() const {
|
||||||
|
int colors = 0;
|
||||||
|
for (const auto& color : m_shade) {
|
||||||
|
if (color.getIndex() >= 0 &&
|
||||||
|
color.getIndex() < get_current_palette()->size())
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
Shade getShade() const {
|
||||||
|
Shade colors;
|
||||||
|
for (const auto& color : m_shade) {
|
||||||
|
if (color.getIndex() >= 0 &&
|
||||||
|
color.getIndex() < get_current_palette()->size())
|
||||||
|
colors.push_back(color);
|
||||||
|
}
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShade(const Shade& shade) {
|
||||||
|
m_shade = shade;
|
||||||
|
invalidate();
|
||||||
|
getParent()->getParent()->layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void onChangeColorBarSelection() {
|
||||||
|
if (!isVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
doc::PalettePicks picks;
|
||||||
|
ColorBar::instance()->getPaletteView()->getSelectedEntries(picks);
|
||||||
|
|
||||||
|
m_shade.resize(picks.picks());
|
||||||
|
|
||||||
|
int i = 0, j = 0;
|
||||||
|
for (bool pick : picks) {
|
||||||
|
if (pick)
|
||||||
|
m_shade[j++] = app::Color::fromIndex(i);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
getParent()->getParent()->layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool onProcessMessage(ui::Message* msg) override {
|
||||||
|
switch (msg->type()) {
|
||||||
|
|
||||||
|
case kOpenMessage:
|
||||||
|
ColorBar::instance()->ChangeSelection.connect(
|
||||||
|
Bind<void>(&ShadeWidget::onChangeColorBarSelection, this));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMouseEnterMessage:
|
||||||
|
case kMouseLeaveMessage:
|
||||||
|
invalidate();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMouseUpMessage: {
|
||||||
|
if (m_click == Select) {
|
||||||
|
setSelected(true);
|
||||||
|
Click();
|
||||||
|
closeWindow();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kMouseMoveMessage: {
|
||||||
|
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||||
|
gfx::Point mousePos = mouseMsg->position() - getBounds().getOrigin();
|
||||||
|
gfx::Rect bounds = getClientBounds();
|
||||||
|
int hot = -1;
|
||||||
|
|
||||||
|
bounds.shrink(3*guiscale());
|
||||||
|
if (bounds.contains(mousePos)) {
|
||||||
|
int count = size();
|
||||||
|
hot = (mousePos.x - bounds.x) / m_boxSize;
|
||||||
|
hot = MID(0, hot, count-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hotIndex != hot) {
|
||||||
|
m_hotIndex = hot;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kMouseDownMessage: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Widget::onProcessMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreferredSize(PreferredSizeEvent& ev) override {
|
||||||
|
int size = this->size();
|
||||||
|
if (size < 2)
|
||||||
|
ev.setPreferredSize(Size((16+m_boxSize)*guiscale()+getTextWidth(), 18*guiscale()));
|
||||||
|
else
|
||||||
|
ev.setPreferredSize(Size(6+m_boxSize*size, 18)*guiscale());
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPaint(PaintEvent& ev) override {
|
||||||
|
SkinTheme* theme = SkinTheme::instance();
|
||||||
|
Graphics* g = ev.getGraphics();
|
||||||
|
gfx::Rect bounds = getClientBounds();
|
||||||
|
|
||||||
|
gfx::Color bg = getBgColor();
|
||||||
|
if (m_click == Select && hasMouseOver())
|
||||||
|
bg = theme->colors.menuitemHighlightFace();
|
||||||
|
g->fillRect(bg, bounds);
|
||||||
|
|
||||||
|
Shade colors = getShade();
|
||||||
|
if (colors.size() >= 2) {
|
||||||
|
int w = (6+m_boxSize*colors.size())*guiscale();
|
||||||
|
if (bounds.w > w)
|
||||||
|
bounds.w = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
skin::Style::State state;
|
||||||
|
if (hasMouseOver()) state += Style::hover();
|
||||||
|
theme->styles.view()->paint(g, bounds, nullptr, state);
|
||||||
|
|
||||||
|
bounds.shrink(3*guiscale());
|
||||||
|
|
||||||
|
gfx::Rect box(bounds.x, bounds.y, m_boxSize*guiscale(), bounds.h);
|
||||||
|
|
||||||
|
if (colors.size() >= 2) {
|
||||||
|
for (int i=0; i<int(colors.size()); ++i) {
|
||||||
|
if (i == int(colors.size())-1)
|
||||||
|
box.w = bounds.x+bounds.w-box.x;
|
||||||
|
|
||||||
|
draw_color(g, box, colors[i]);
|
||||||
|
box.x += box.w;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i=0; i<int(colors.size())-1; ++i)
|
g->fillRect(theme->colors.editorFace(), bounds);
|
||||||
remap->map(colors[i].getIndex(), colors[i+1].getIndex());
|
g->drawAlignedUIString(getText(), theme->colors.face(), gfx::ColorNone, bounds,
|
||||||
|
ui::CENTER | ui::MIDDLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return remap.release();
|
ClickType m_click;
|
||||||
|
Shade m_shade;
|
||||||
|
int m_hotIndex;
|
||||||
|
int m_boxSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
InkShadesField() :
|
||||||
|
m_button(SkinTheme::instance()->parts.iconArrowDown()->getBitmap(0)),
|
||||||
|
m_shade(Shade(), ShadeWidget::DragAndDrop) {
|
||||||
|
SkinTheme* theme = SkinTheme::instance();
|
||||||
|
m_shade.setBgColor(theme->colors.workspace());
|
||||||
|
m_button.setBgColor(theme->colors.workspace());
|
||||||
|
|
||||||
|
noBorderNoChildSpacing();
|
||||||
|
addChild(&m_button);
|
||||||
|
addChild(&m_shade);
|
||||||
|
|
||||||
|
m_button.setFocusStop(false);
|
||||||
|
m_button.Click.connect(Bind<void>(&InkShadesField::onShowMenu, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverseShadeColors() {
|
||||||
|
m_shade.reverseShadeColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
doc::Remap* createShadeRemap(bool left) {
|
||||||
|
return m_shade.createShadeRemap(left);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void onShowMenu() {
|
||||||
|
gfx::Rect bounds = m_button.getBounds();
|
||||||
|
|
||||||
Colors getColors() const {
|
Menu menu;
|
||||||
Colors colors;
|
MenuItem
|
||||||
for (const auto& color : m_colors) {
|
reverse("Reverse Shade"),
|
||||||
if (color.getIndex() >= 0 &&
|
save("Save Shade");
|
||||||
color.getIndex() < get_current_palette()->size())
|
menu.addChild(&reverse);
|
||||||
colors.push_back(color);
|
menu.addChild(&save);
|
||||||
}
|
|
||||||
return colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onChangeColorBarSelection() {
|
bool hasShade = (m_shade.size() >= 2);
|
||||||
if (!isVisible())
|
reverse.setEnabled(hasShade);
|
||||||
return;
|
save.setEnabled(hasShade);
|
||||||
|
reverse.Click.connect(Bind<void>(&InkShadesField::reverseShadeColors, this));
|
||||||
|
save.Click.connect(Bind<void>(&InkShadesField::onSaveShade, this));
|
||||||
|
|
||||||
doc::PalettePicks picks;
|
if (!m_shades.empty()) {
|
||||||
ColorBar::instance()->getPaletteView()->getSelectedEntries(picks);
|
SkinTheme* theme = SkinTheme::instance();
|
||||||
|
|
||||||
m_colors.resize(picks.picks());
|
menu.addChild(new MenuSeparator);
|
||||||
|
|
||||||
int i = 0, j = 0;
|
int i = 0;
|
||||||
for (bool pick : picks) {
|
for (const Shade& shade : m_shades) {
|
||||||
if (pick)
|
auto shadeWidget = new ShadeWidget(shade, ShadeWidget::Select);
|
||||||
m_colors[j++] = app::Color::fromIndex(i);
|
shadeWidget->setExpansive(true);
|
||||||
++i;
|
shadeWidget->setBgColor(theme->colors.menuitemNormalFace());
|
||||||
}
|
shadeWidget->Click.connect(
|
||||||
|
[&]{
|
||||||
|
m_shade.setShade(shade);
|
||||||
|
});
|
||||||
|
|
||||||
getParent()->layout();
|
auto close = new IconButton(theme->parts.iconClose()->getBitmap(0));
|
||||||
}
|
close->setBgColor(theme->colors.menuitemNormalFace());
|
||||||
|
close->Click.connect(
|
||||||
|
Bind<void>(
|
||||||
|
[this, i, close]{
|
||||||
|
m_shades.erase(m_shades.begin()+i);
|
||||||
|
close->closeWindow();
|
||||||
|
}));
|
||||||
|
|
||||||
bool onProcessMessage(ui::Message* msg) override {
|
auto item = new HBox();
|
||||||
if (msg->type() == kOpenMessage) {
|
item->noBorderNoChildSpacing();
|
||||||
ColorBar::instance()->ChangeSelection.connect(
|
item->addChild(shadeWidget);
|
||||||
Bind<void>(&InkShadesField::onChangeColorBarSelection, this));
|
item->addChild(close);
|
||||||
}
|
menu.addChild(item);
|
||||||
return Widget::onProcessMessage(msg);
|
++i;
|
||||||
}
|
|
||||||
|
|
||||||
void onPreferredSize(PreferredSizeEvent& ev) override {
|
|
||||||
int size = getColors().size();
|
|
||||||
if (size < 2)
|
|
||||||
ev.setPreferredSize(Size(16*guiscale()+getTextWidth(), 18*guiscale()));
|
|
||||||
else
|
|
||||||
ev.setPreferredSize(Size(6+12*size, 18)*guiscale());
|
|
||||||
}
|
|
||||||
|
|
||||||
void onPaint(PaintEvent& ev) override {
|
|
||||||
SkinTheme* theme = SkinTheme::instance();
|
|
||||||
Graphics* g = ev.getGraphics();
|
|
||||||
gfx::Rect bounds = getClientBounds();
|
|
||||||
|
|
||||||
skin::Style::State state;
|
|
||||||
if (hasMouseOver()) state += Style::hover();
|
|
||||||
|
|
||||||
g->fillRect(theme->colors.workspace(), bounds);
|
|
||||||
theme->styles.view()->paint(g, bounds, nullptr, state);
|
|
||||||
|
|
||||||
bounds.shrink(3*guiscale());
|
|
||||||
|
|
||||||
gfx::Rect box(bounds.x, bounds.y, 12*guiscale(), bounds.h);
|
|
||||||
Colors colors = getColors();
|
|
||||||
|
|
||||||
if (colors.size() >= 2) {
|
|
||||||
for (int i=0; i<int(colors.size()); ++i) {
|
|
||||||
if (i == int(colors.size())-1)
|
|
||||||
box.w = bounds.x+bounds.w-box.x;
|
|
||||||
|
|
||||||
draw_color(g, box, colors[i]);
|
|
||||||
box.x += box.w;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
g->fillRect(theme->colors.editorFace(), bounds);
|
menu.showPopup(gfx::Point(bounds.x, bounds.y+bounds.h));
|
||||||
g->drawAlignedUIString(getText(), theme->colors.face(), gfx::ColorNone, bounds,
|
m_button.invalidate();
|
||||||
ui::CENTER | ui::MIDDLE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<app::Color> m_colors;
|
void onSaveShade() {
|
||||||
|
m_shades.push_back(m_shade.getShade());
|
||||||
|
}
|
||||||
|
|
||||||
|
IconButton m_button;
|
||||||
|
ShadeWidget m_shade;
|
||||||
|
std::vector<Shade> m_shades;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContextBar::InkOpacityField : public IntEntry
|
class ContextBar::InkOpacityField : public IntEntry
|
||||||
@ -1502,14 +1671,14 @@ doc::BrushRef ContextBar::createBrushFromPreferences(ToolPreferences::Brush* bru
|
|||||||
return brush;
|
return brush;
|
||||||
}
|
}
|
||||||
|
|
||||||
doc::Remap* ContextBar::createShadesRemap(bool left)
|
doc::Remap* ContextBar::createShadeRemap(bool left)
|
||||||
{
|
{
|
||||||
return m_inkShades->createShadesRemap(left);
|
return m_inkShades->createShadeRemap(left);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextBar::reverseShadesColors()
|
void ContextBar::reverseShadeColors()
|
||||||
{
|
{
|
||||||
m_inkShades->reverseColors();
|
m_inkShades->reverseShadeColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -70,8 +70,8 @@ namespace app {
|
|||||||
static doc::BrushRef createBrushFromPreferences(
|
static doc::BrushRef createBrushFromPreferences(
|
||||||
ToolPreferences::Brush* brushPref = nullptr);
|
ToolPreferences::Brush* brushPref = nullptr);
|
||||||
|
|
||||||
doc::Remap* createShadesRemap(bool left);
|
doc::Remap* createShadeRemap(bool left);
|
||||||
void reverseShadesColors();
|
void reverseShadeColors();
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
Signal0<void> BrushChange;
|
Signal0<void> BrushChange;
|
||||||
|
@ -169,7 +169,7 @@ public:
|
|||||||
|
|
||||||
if (m_toolPref.ink() == tools::InkType::SHADING) {
|
if (m_toolPref.ink() == tools::InkType::SHADING) {
|
||||||
m_shadingRemap.reset(
|
m_shadingRemap.reset(
|
||||||
App::instance()->getMainWindow()->getContextBar()->createShadesRemap(
|
App::instance()->getMainWindow()->getContextBar()->createShadeRemap(
|
||||||
button == tools::ToolLoop::Left));
|
button == tools::ToolLoop::Left));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
68
src/app/ui/icon_button.cpp
Normal file
68
src/app/ui/icon_button.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2001-2015 David Capello
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License version 2 as
|
||||||
|
// published by the Free Software Foundation.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "app/ui/icon_button.h"
|
||||||
|
|
||||||
|
#include "app/ui/skin/skin_theme.h"
|
||||||
|
#include "she/surface.h"
|
||||||
|
#include "ui/message.h"
|
||||||
|
#include "ui/paint_event.h"
|
||||||
|
#include "ui/preferred_size_event.h"
|
||||||
|
#include "ui/system.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
using namespace ui;
|
||||||
|
using namespace app::skin;
|
||||||
|
|
||||||
|
IconButton::IconButton(she::Surface* icon)
|
||||||
|
: Button("")
|
||||||
|
, m_icon(icon)
|
||||||
|
{
|
||||||
|
setBgColor(SkinTheme::instance()->colors.menuitemNormalFace());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconButton::onPreferredSize(PreferredSizeEvent& ev)
|
||||||
|
{
|
||||||
|
ev.setPreferredSize(
|
||||||
|
gfx::Size(m_icon->width(),
|
||||||
|
m_icon->height()) + 4*guiscale());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconButton::onPaint(PaintEvent& ev)
|
||||||
|
{
|
||||||
|
SkinTheme* theme = SkinTheme::instance();
|
||||||
|
Graphics* g = ev.getGraphics();
|
||||||
|
gfx::Color fg, bg;
|
||||||
|
|
||||||
|
if (isSelected()) {
|
||||||
|
fg = theme->colors.menuitemHighlightText();
|
||||||
|
bg = theme->colors.menuitemHighlightFace();
|
||||||
|
}
|
||||||
|
else if (isEnabled() && hasMouseOver()) {
|
||||||
|
fg = theme->colors.menuitemHotText();
|
||||||
|
bg = theme->colors.menuitemHotFace();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fg = theme->colors.menuitemNormalText();
|
||||||
|
bg = getBgColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
g->fillRect(bg, g->getClipBounds());
|
||||||
|
|
||||||
|
gfx::Rect bounds = getClientBounds();
|
||||||
|
g->drawColoredRgbaSurface(
|
||||||
|
m_icon, fg,
|
||||||
|
bounds.x+bounds.w/2-m_icon->width()/2,
|
||||||
|
bounds.y+bounds.h/2-m_icon->height()/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace app
|
31
src/app/ui/icon_button.h
Normal file
31
src/app/ui/icon_button.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2001-2015 David Capello
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License version 2 as
|
||||||
|
// published by the Free Software Foundation.
|
||||||
|
|
||||||
|
#ifndef APP_UI_ICON_BUTTON_H_INCLUDED
|
||||||
|
#define APP_UI_ICON_BUTTON_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/button.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
class IconButton : public ui::Button {
|
||||||
|
public:
|
||||||
|
IconButton(she::Surface* icon);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// bool onProcessMessage(ui::Message* msg) override;
|
||||||
|
void onPreferredSize(ui::PreferredSizeEvent& ev) override;
|
||||||
|
void onPaint(ui::PaintEvent& ev) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
she::Surface* m_icon;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
||||||
|
#endif
|
@ -940,7 +940,7 @@ void Tabs::createFloatingOverlay(Tab* tab)
|
|||||||
gfx::Color c = lock->getPixel(x, y);
|
gfx::Color c = lock->getPixel(x, y);
|
||||||
c = (c != gfx::rgba(255, 0, 255, 0) &&
|
c = (c != gfx::rgba(255, 0, 255, 0) &&
|
||||||
c != gfx::rgba(255, 0, 255, 255) ?
|
c != gfx::rgba(255, 0, 255, 255) ?
|
||||||
gfx::seta(c, 255):
|
gfx::rgba(gfx::getr(c), gfx::getg(c), gfx::getb(c), 255):
|
||||||
gfx::ColorNone);
|
gfx::ColorNone);
|
||||||
lock->putPixel(c, x, y);
|
lock->putPixel(c, x, y);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite Gfx Library
|
// Aseprite Gfx Library
|
||||||
// Copyright (C) 2001-2014 David Capello
|
// Copyright (C) 2001-2015 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.
|
||||||
@ -32,11 +32,6 @@ namespace gfx {
|
|||||||
inline ColorComponent getb(Color c) { return (c >> ColorBShift) & 0xff; }
|
inline ColorComponent getb(Color c) { return (c >> ColorBShift) & 0xff; }
|
||||||
inline ColorComponent geta(Color c) { return (c >> ColorAShift) & 0xff; }
|
inline ColorComponent geta(Color c) { return (c >> ColorAShift) & 0xff; }
|
||||||
|
|
||||||
inline Color setr(Color c, ColorComponent v) { return Color((c & ~ColorRShift) | (v << ColorRShift)); }
|
|
||||||
inline Color setg(Color c, ColorComponent v) { return Color((c & ~ColorGShift) | (v << ColorGShift)); }
|
|
||||||
inline Color setb(Color c, ColorComponent v) { return Color((c & ~ColorBShift) | (v << ColorBShift)); }
|
|
||||||
inline Color seta(Color c, ColorComponent v) { return Color((c & ~ColorAShift) | (v << ColorAShift)); }
|
|
||||||
|
|
||||||
inline bool is_transparent(Color c) { return geta(c) == 0; }
|
inline bool is_transparent(Color c) { return geta(c) == 0; }
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
|
@ -15,43 +15,39 @@
|
|||||||
|
|
||||||
namespace she {
|
namespace she {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#define INT_MULT(a, b, t) \
|
#define MUL_UN8(a, b, t) \
|
||||||
((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
|
((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
|
||||||
|
|
||||||
gfx::Color blend(const gfx::Color back, gfx::Color front)
|
gfx::Color blend(const gfx::Color backdrop, gfx::Color src)
|
||||||
{
|
{
|
||||||
|
if (gfx::geta(backdrop) == 0)
|
||||||
|
return src;
|
||||||
|
else if (gfx::geta(src) == 0)
|
||||||
|
return backdrop;
|
||||||
|
|
||||||
|
int Br, Bg, Bb, Ba;
|
||||||
|
int Sr, Sg, Sb, Sa;
|
||||||
|
int Rr, Rg, Rb, Ra;
|
||||||
|
|
||||||
|
Br = gfx::getr(backdrop);
|
||||||
|
Bg = gfx::getg(backdrop);
|
||||||
|
Bb = gfx::getb(backdrop);
|
||||||
|
Ba = gfx::geta(backdrop);
|
||||||
|
|
||||||
|
Sr = gfx::getr(src);
|
||||||
|
Sg = gfx::getg(src);
|
||||||
|
Sb = gfx::getb(src);
|
||||||
|
Sa = gfx::geta(src);
|
||||||
|
|
||||||
int t;
|
int t;
|
||||||
|
Ra = Ba + Sa - MUL_UN8(Ba, Sa, t);
|
||||||
|
Rr = Br + (Sr-Br) * Sa / Ra;
|
||||||
|
Rg = Bg + (Sg-Bg) * Sa / Ra;
|
||||||
|
Rb = Bb + (Sb-Bb) * Sa / Ra;
|
||||||
|
|
||||||
if (gfx::geta(back) == 0) {
|
return gfx::rgba(Rr, Rg, Rb, Ra);
|
||||||
return front;
|
|
||||||
}
|
|
||||||
else if (gfx::geta(front) == 0) {
|
|
||||||
return back;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int B_r, B_g, B_b, B_a;
|
|
||||||
int F_r, F_g, F_b, F_a;
|
|
||||||
int D_r, D_g, D_b, D_a;
|
|
||||||
|
|
||||||
B_r = gfx::getr(back);
|
|
||||||
B_g = gfx::getg(back);
|
|
||||||
B_b = gfx::getb(back);
|
|
||||||
B_a = gfx::geta(back);
|
|
||||||
|
|
||||||
F_r = gfx::getr(front);
|
|
||||||
F_g = gfx::getg(front);
|
|
||||||
F_b = gfx::getb(front);
|
|
||||||
F_a = gfx::geta(front);
|
|
||||||
|
|
||||||
D_a = B_a + F_a - INT_MULT(B_a, F_a, t);
|
|
||||||
D_r = B_r + (F_r-B_r) * F_a / D_a;
|
|
||||||
D_g = B_g + (F_g-B_g) * F_a / D_a;
|
|
||||||
D_b = B_b + (F_b-B_b) * F_a / D_a;
|
|
||||||
|
|
||||||
return gfx::rgba(D_r, D_g, D_b, D_a);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anoynmous namespace
|
} // anoynmous namespace
|
||||||
@ -79,9 +75,13 @@ public:
|
|||||||
if (gfx::geta(bg) > 0)
|
if (gfx::geta(bg) > 0)
|
||||||
dstColor = blend(dstColor, bg);
|
dstColor = blend(dstColor, bg);
|
||||||
|
|
||||||
int srcAlpha = (((*ptr) & format.alphaMask) >> format.alphaShift);
|
uint32_t src = (((*ptr) & format.alphaMask) >> format.alphaShift);
|
||||||
if (srcAlpha > 0)
|
if (src > 0) {
|
||||||
dstColor = blend(dstColor, gfx::seta(fg, srcAlpha));
|
src = gfx::rgba(gfx::getr(fg),
|
||||||
|
gfx::getg(fg),
|
||||||
|
gfx::getb(fg), src);
|
||||||
|
dstColor = blend(dstColor, src);
|
||||||
|
}
|
||||||
|
|
||||||
putPixel(dstColor, clip.dst.x+u, clip.dst.y+v);
|
putPixel(dstColor, clip.dst.x+u, clip.dst.y+v);
|
||||||
++ptr;
|
++ptr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user