mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-14 04:19:12 +00:00
Show a tooltip with author+link of each palette (fix #540)
This commit is contained in:
parent
64f2384bfc
commit
2e3bbe2968
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -13,23 +13,99 @@
|
||||
#include "app/modules/palettes.h"
|
||||
#include "app/res/palette_resource.h"
|
||||
#include "app/res/palettes_loader_delegate.h"
|
||||
#include "app/ui/icon_button.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/launcher.h"
|
||||
#include "doc/palette.h"
|
||||
#include "she/surface.h"
|
||||
#include "ui/graphics.h"
|
||||
#include "ui/listitem.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/paint_event.h"
|
||||
#include "ui/resize_event.h"
|
||||
#include "ui/size_hint_event.h"
|
||||
#include "ui/tooltips.h"
|
||||
#include "ui/view.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace ui;
|
||||
using namespace app::skin;
|
||||
|
||||
static bool is_url_char(int chr)
|
||||
{
|
||||
return ((chr >= 'a' && chr <= 'z') ||
|
||||
(chr >= 'A' && chr <= 'Z') ||
|
||||
(chr >= '0' && chr <= '9') ||
|
||||
(chr == ':' || chr == '/' || chr == '@' ||
|
||||
chr == '?' || chr == '!' || chr == '#' ||
|
||||
chr == '-' || chr == '_' || chr == '~' ||
|
||||
chr == '.' || chr == ',' || chr == ';' ||
|
||||
chr == '*' || chr == '+' || chr == '=' ||
|
||||
chr == '[' || chr == ']' ||
|
||||
chr == '(' || chr == ')' ||
|
||||
chr == '$' || chr == '\''));
|
||||
}
|
||||
|
||||
class PalettesListItem : public ResourceListItem {
|
||||
|
||||
class CommentButton : public IconButton {
|
||||
public:
|
||||
CommentButton(const std::string& comment)
|
||||
: IconButton(SkinTheme::instance()->parts.iconUserData()->bitmap(0))
|
||||
, m_comment(comment) {
|
||||
}
|
||||
|
||||
private:
|
||||
void onClick(Event& ev) override {
|
||||
IconButton::onClick(ev);
|
||||
|
||||
int j, i = m_comment.find("http");
|
||||
if (i != std::string::npos) {
|
||||
for (j=i+4; j<m_comment.size() && is_url_char(m_comment[j]); ++j)
|
||||
;
|
||||
base::launcher::open_url(m_comment.substr(i, j-i));
|
||||
}
|
||||
}
|
||||
|
||||
std::string m_comment;
|
||||
};
|
||||
|
||||
public:
|
||||
PalettesListItem(Resource* resource, TooltipManager* tooltips)
|
||||
: ResourceListItem(resource)
|
||||
, m_comment(nullptr)
|
||||
{
|
||||
std::string comment = static_cast<PaletteResource*>(resource)->palette()->comment();
|
||||
if (!comment.empty()) {
|
||||
addChild(m_comment = new CommentButton(comment));
|
||||
|
||||
m_comment->setBgColor(SkinTheme::instance()->colors.listitemNormalFace());
|
||||
tooltips->addTooltipFor(m_comment, comment, LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void onResize(ResizeEvent& ev) override {
|
||||
ResourceListItem::onResize(ev);
|
||||
|
||||
if (m_comment) {
|
||||
auto reqSz = m_comment->sizeHint();
|
||||
m_comment->setBounds(
|
||||
gfx::Rect(ev.bounds().x+ev.bounds().w-reqSz.w,
|
||||
ev.bounds().y+ev.bounds().h/2-reqSz.h/2,
|
||||
reqSz.w, reqSz.h));
|
||||
}
|
||||
}
|
||||
|
||||
CommentButton* m_comment;
|
||||
};
|
||||
|
||||
PalettesListBox::PalettesListBox()
|
||||
: ResourcesListBox(new ResourcesLoader(new PalettesLoaderDelegate))
|
||||
{
|
||||
addChild(&m_tooltips);
|
||||
}
|
||||
|
||||
doc::Palette* PalettesListBox::selectedPalette()
|
||||
@ -41,10 +117,13 @@ doc::Palette* PalettesListBox::selectedPalette()
|
||||
return static_cast<PaletteResource*>(resource)->palette();
|
||||
}
|
||||
|
||||
ResourceListItem* PalettesListBox::onCreateResourceItem(Resource* resource)
|
||||
{
|
||||
return new PalettesListItem(resource, &m_tooltips);
|
||||
}
|
||||
|
||||
void PalettesListBox::onResourceChange(Resource* resource)
|
||||
{
|
||||
ResourcesListBox::onResourceChange(resource);
|
||||
|
||||
doc::Palette* palette = static_cast<PaletteResource*>(resource)->palette();
|
||||
PalChange(palette);
|
||||
}
|
||||
@ -67,11 +146,6 @@ void PalettesListBox::onPaintResource(Graphics* g, const gfx::Rect& bounds, Reso
|
||||
|
||||
box.x += box.w;
|
||||
}
|
||||
|
||||
// g->drawString(getText(), fgcolor, gfx::ColorNone, false,
|
||||
// gfx::Point(
|
||||
// bounds.x + guiscale()*2,
|
||||
// bounds.y + bounds.h/2 - g->measureUIString(getText()).h/2));
|
||||
}
|
||||
|
||||
void PalettesListBox::onResourceSizeHint(Resource* resource, gfx::Size& size)
|
||||
|
@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "app/ui/resources_listbox.h"
|
||||
#include "ui/tooltips.h"
|
||||
|
||||
namespace doc {
|
||||
class Palette;
|
||||
@ -25,9 +26,12 @@ namespace app {
|
||||
obs::signal<void(doc::Palette*)> PalChange;
|
||||
|
||||
protected:
|
||||
virtual ResourceListItem* onCreateResourceItem(Resource* resource) override;
|
||||
virtual void onResourceChange(Resource* resource) override;
|
||||
virtual void onPaintResource(ui::Graphics* g, const gfx::Rect& bounds, Resource* resource) override;
|
||||
virtual void onResourceSizeHint(Resource* resource, gfx::Size& size) override;
|
||||
|
||||
ui::TooltipManager m_tooltips;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "base/bind.h"
|
||||
#include "ui/graphics.h"
|
||||
#include "ui/listitem.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/paint_event.h"
|
||||
#include "ui/size_hint_event.h"
|
||||
@ -26,73 +25,61 @@ namespace app {
|
||||
using namespace ui;
|
||||
using namespace skin;
|
||||
|
||||
class ResourceListItem : public ListItem {
|
||||
public:
|
||||
ResourceListItem(Resource* resource)
|
||||
: ListItem(resource->name()), m_resource(resource) {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ResourceListItem
|
||||
|
||||
ResourceListItem::ResourceListItem(Resource* resource)
|
||||
: ListItem(resource->name()), m_resource(resource)
|
||||
{
|
||||
}
|
||||
|
||||
bool ResourceListItem::onProcessMessage(ui::Message* msg)
|
||||
{
|
||||
switch (msg->type()) {
|
||||
case kMouseLeaveMessage:
|
||||
case kMouseEnterMessage:
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
return ListItem::onProcessMessage(msg);
|
||||
}
|
||||
|
||||
void ResourceListItem::onPaint(PaintEvent& ev)
|
||||
{
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
|
||||
Graphics* g = ev.graphics();
|
||||
gfx::Rect bounds = clientBounds();
|
||||
gfx::Color bgcolor, fgcolor;
|
||||
|
||||
if (isSelected()) {
|
||||
bgcolor = theme->colors.listitemSelectedFace();
|
||||
fgcolor = theme->colors.listitemSelectedText();
|
||||
}
|
||||
else {
|
||||
bgcolor = theme->colors.listitemNormalFace();
|
||||
fgcolor = theme->colors.listitemNormalText();
|
||||
}
|
||||
|
||||
Resource* resource() const {
|
||||
return m_resource;
|
||||
}
|
||||
g->fillRect(bgcolor, bounds);
|
||||
|
||||
protected:
|
||||
bool onProcessMessage(ui::Message* msg) override {
|
||||
switch (msg->type()) {
|
||||
case kMouseLeaveMessage:
|
||||
case kMouseEnterMessage:
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
return ListItem::onProcessMessage(msg);
|
||||
}
|
||||
static_cast<ResourcesListBox*>(parent())->
|
||||
paintResource(g, bounds, m_resource);
|
||||
|
||||
void onPaint(PaintEvent& ev) override {
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
|
||||
Graphics* g = ev.graphics();
|
||||
gfx::Rect bounds = clientBounds();
|
||||
gfx::Color bgcolor, fgcolor;
|
||||
|
||||
if (isSelected()) {
|
||||
bgcolor = theme->colors.listitemSelectedFace();
|
||||
fgcolor = theme->colors.listitemSelectedText();
|
||||
}
|
||||
else {
|
||||
bgcolor = theme->colors.listitemNormalFace();
|
||||
fgcolor = theme->colors.listitemNormalText();
|
||||
}
|
||||
|
||||
g->fillRect(bgcolor, bounds);
|
||||
g->drawString(text(), fgcolor, gfx::ColorNone,
|
||||
gfx::Point(
|
||||
bounds.x + guiscale()*2,
|
||||
bounds.y + bounds.h/2 - g->measureUIString(text()).h/2));
|
||||
}
|
||||
|
||||
void ResourceListItem::onSizeHint(SizeHintEvent& ev)
|
||||
{
|
||||
ev.setSizeHint(
|
||||
static_cast<ResourcesListBox*>(parent())->
|
||||
paintResource(g, bounds, m_resource);
|
||||
resourceSizeHint(m_resource));
|
||||
}
|
||||
|
||||
// for (int i=0; i<m_palette->size(); ++i) {
|
||||
// doc::color_t c = m_resource->getEntry(i);
|
||||
|
||||
// g->fillRect(gfx::rgba(
|
||||
// doc::rgba_getr(c),
|
||||
// doc::rgba_getg(c),
|
||||
// doc::rgba_getb(c)), box);
|
||||
|
||||
// box.x += box.w;
|
||||
// }
|
||||
|
||||
g->drawString(text(), fgcolor, gfx::ColorNone,
|
||||
gfx::Point(
|
||||
bounds.x + guiscale()*2,
|
||||
bounds.y + bounds.h/2 - g->measureUIString(text()).h/2));
|
||||
}
|
||||
|
||||
void onSizeHint(SizeHintEvent& ev) override {
|
||||
ev.setSizeHint(
|
||||
static_cast<ResourcesListBox*>(parent())->
|
||||
resourceSizeHint(m_resource));
|
||||
}
|
||||
|
||||
private:
|
||||
base::UniquePtr<Resource> m_resource;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ResourcesListBox::LoadingItem
|
||||
|
||||
class ResourcesListBox::LoadingItem : public ListItem {
|
||||
public:
|
||||
@ -118,6 +105,9 @@ private:
|
||||
int m_state;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ResourcesListBox
|
||||
|
||||
ResourcesListBox::ResourcesListBox(ResourcesLoader* resourcesLoader)
|
||||
: m_resourcesLoader(resourcesLoader)
|
||||
, m_resourcesTimer(100)
|
||||
@ -166,14 +156,9 @@ void ResourcesListBox::onChange()
|
||||
onResourceChange(resource);
|
||||
}
|
||||
|
||||
void ResourcesListBox::onResourceChange(Resource* resource)
|
||||
ResourceListItem* ResourcesListBox::onCreateResourceItem(Resource* resource)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
void ResourcesListBox::onPaintResource(Graphics* g, const gfx::Rect& bounds, Resource* resource)
|
||||
{
|
||||
// Do nothing
|
||||
return new ResourceListItem(resource);
|
||||
}
|
||||
|
||||
void ResourcesListBox::onTick()
|
||||
@ -201,7 +186,7 @@ void ResourcesListBox::onTick()
|
||||
return;
|
||||
}
|
||||
|
||||
base::UniquePtr<ResourceListItem> listItem(new ResourceListItem(resource));
|
||||
base::UniquePtr<ResourceListItem> listItem(onCreateResourceItem(resource));
|
||||
insertChild(getItemsCount()-1, listItem);
|
||||
layout();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -11,29 +11,49 @@
|
||||
#include "app/res/resources_loader.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "ui/listbox.h"
|
||||
#include "ui/listitem.h"
|
||||
#include "ui/timer.h"
|
||||
|
||||
namespace app {
|
||||
class ResourceListItem;
|
||||
|
||||
class ResourceListItem : public ui::ListItem {
|
||||
public:
|
||||
ResourceListItem(Resource* resource);
|
||||
|
||||
Resource* resource() const { return m_resource; }
|
||||
|
||||
protected:
|
||||
bool onProcessMessage(ui::Message* msg) override;
|
||||
void onPaint(ui::PaintEvent& ev) override;
|
||||
void onSizeHint(ui::SizeHintEvent& ev) override;
|
||||
|
||||
private:
|
||||
base::UniquePtr<Resource> m_resource;
|
||||
};
|
||||
|
||||
class ResourcesListBox : public ui::ListBox {
|
||||
public:
|
||||
friend class ResourceListItem;
|
||||
|
||||
ResourcesListBox(ResourcesLoader* resourcesLoader);
|
||||
|
||||
Resource* selectedResource();
|
||||
|
||||
void paintResource(ui::Graphics* g, const gfx::Rect& bounds, Resource* resource);
|
||||
gfx::Size resourceSizeHint(Resource* resource);
|
||||
|
||||
protected:
|
||||
virtual bool onProcessMessage(ui::Message* msg) override;
|
||||
virtual void onChange() override;
|
||||
virtual void onResourceChange(Resource* resource) = 0;
|
||||
virtual ResourceListItem* onCreateResourceItem(Resource* resource);
|
||||
|
||||
// abstract
|
||||
virtual void onResourceChange(Resource* resource) = 0;
|
||||
virtual void onPaintResource(ui::Graphics* g, const gfx::Rect& bounds, Resource* resource) = 0;
|
||||
virtual void onResourceSizeHint(Resource* resource, gfx::Size& size) = 0;
|
||||
|
||||
private:
|
||||
void paintResource(ui::Graphics* g, const gfx::Rect& bounds, Resource* resource);
|
||||
gfx::Size resourceSizeHint(Resource* resource);
|
||||
|
||||
void onTick();
|
||||
void stop();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2001-2015 David Capello
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -36,15 +36,25 @@ Palette* load_gpl_file(const char *filename)
|
||||
if (line != "GIMP Palette") return NULL;
|
||||
|
||||
base::UniquePtr<Palette> pal(new Palette(frame_t(0), 0));
|
||||
std::string comment;
|
||||
|
||||
while (std::getline(f, line)) {
|
||||
// Trim line.
|
||||
base::trim_string(line, line);
|
||||
|
||||
// Remove comments
|
||||
if (line.empty() || line[0] == '#')
|
||||
// Remove empty lines
|
||||
if (line.empty())
|
||||
continue;
|
||||
|
||||
// Concatenate comments
|
||||
if (line[0] == '#') {
|
||||
line = line.substr(1);
|
||||
base::trim_string(line, line);
|
||||
comment += line;
|
||||
comment.push_back('\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove properties (TODO add these properties in the palette)
|
||||
if (!std::isdigit(line[0]))
|
||||
continue;
|
||||
@ -60,6 +70,12 @@ Palette* load_gpl_file(const char *filename)
|
||||
pal->addEntry(rgba(r, g, b, 255));
|
||||
}
|
||||
|
||||
base::trim_string(comment, comment);
|
||||
if (!comment.empty()) {
|
||||
LOG("%s comment: %s\n", filename, comment.c_str());
|
||||
pal->setComment(comment);
|
||||
}
|
||||
|
||||
return pal.release();
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ Palette::Palette(frame_t frame, int ncolors)
|
||||
|
||||
Palette::Palette(const Palette& palette)
|
||||
: Object(palette)
|
||||
, m_comment(palette.m_comment)
|
||||
{
|
||||
m_frame = palette.m_frame;
|
||||
m_colors = palette.m_colors;
|
||||
@ -41,6 +42,7 @@ Palette::Palette(const Palette& palette)
|
||||
|
||||
Palette::Palette(const Palette& palette, const Remap& remap)
|
||||
: Object(palette)
|
||||
, m_comment(palette.m_comment)
|
||||
{
|
||||
m_frame = palette.m_frame;
|
||||
|
||||
|
@ -32,11 +32,17 @@ namespace doc {
|
||||
int size() const { return (int)m_colors.size(); }
|
||||
void resize(int ncolors);
|
||||
|
||||
std::string filename() const { return m_filename; }
|
||||
const std::string& filename() const { return m_filename; }
|
||||
const std::string& comment() const { return m_comment; }
|
||||
|
||||
void setFilename(const std::string& filename) {
|
||||
m_filename = filename;
|
||||
}
|
||||
|
||||
void setComment(const std::string& comment) {
|
||||
m_comment = comment;
|
||||
}
|
||||
|
||||
int getModifications() const { return m_modifications; }
|
||||
|
||||
// Return true if the palette has alpha != 255 in some entry
|
||||
@ -91,6 +97,7 @@ namespace doc {
|
||||
std::vector<color_t> m_colors;
|
||||
int m_modifications;
|
||||
std::string m_filename; // If the palette is associated with a file.
|
||||
std::string m_comment; // Some extra comment from the .gpl file (author, website, etc.).
|
||||
};
|
||||
|
||||
} // namespace doc
|
||||
|
Loading…
x
Reference in New Issue
Block a user