diff --git a/src/app/ui/palettes_listbox.cpp b/src/app/ui/palettes_listbox.cpp index 4c9e03d97..2f19fb636 100644 --- a/src/app/ui/palettes_listbox.cpp +++ b/src/app/ui/palettes_listbox.cpp @@ -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(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(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(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) diff --git a/src/app/ui/palettes_listbox.h b/src/app/ui/palettes_listbox.h index d66e226bb..5352ee7fb 100644 --- a/src/app/ui/palettes_listbox.h +++ b/src/app/ui/palettes_listbox.h @@ -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 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 diff --git a/src/app/ui/resources_listbox.cpp b/src/app/ui/resources_listbox.cpp index 641604781..a96dbe754 100644 --- a/src/app/ui/resources_listbox.cpp +++ b/src/app/ui/resources_listbox.cpp @@ -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(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(parent())-> + paintResource(g, bounds, m_resource); - void onPaint(PaintEvent& ev) override { - SkinTheme* theme = static_cast(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(parent())-> - paintResource(g, bounds, m_resource); + resourceSizeHint(m_resource)); +} - // for (int i=0; isize(); ++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(parent())-> - resourceSizeHint(m_resource)); - } - -private: - base::UniquePtr 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 listItem(new ResourceListItem(resource)); + base::UniquePtr listItem(onCreateResourceItem(resource)); insertChild(getItemsCount()-1, listItem); layout(); diff --git a/src/app/ui/resources_listbox.h b/src/app/ui/resources_listbox.h index f91607aae..1bd932f8d 100644 --- a/src/app/ui/resources_listbox.h +++ b/src/app/ui/resources_listbox.h @@ -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 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(); diff --git a/src/doc/file/gpl_file.cpp b/src/doc/file/gpl_file.cpp index 87b3dbc26..2dc742807 100644 --- a/src/doc/file/gpl_file.cpp +++ b/src/doc/file/gpl_file.cpp @@ -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 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(); } diff --git a/src/doc/palette.cpp b/src/doc/palette.cpp index 8a74168f7..c1342ecb6 100644 --- a/src/doc/palette.cpp +++ b/src/doc/palette.cpp @@ -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; diff --git a/src/doc/palette.h b/src/doc/palette.h index dda0a277c..9e109efcc 100644 --- a/src/doc/palette.h +++ b/src/doc/palette.h @@ -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 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