aseprite/src/app/ui/resources_listbox.cpp

242 lines
5.5 KiB
C++

/* Aseprite
* Copyright (C) 2014 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/ui/resources_listbox.h"
#include "app/res/resource.h"
#include "app/res/resources_loader.h"
#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/preferred_size_event.h"
#include "ui/view.h"
namespace app {
using namespace ui;
using namespace skin;
class ResourceListItem : public ListItem {
public:
ResourceListItem(Resource* resource)
: ListItem(resource->name()), m_resource(resource) {
}
Resource* resource() const {
return m_resource;
}
protected:
bool onProcessMessage(ui::Message* msg) OVERRIDE {
switch (msg->type()) {
case kMouseLeaveMessage:
case kMouseEnterMessage:
invalidate();
break;
}
return ListItem::onProcessMessage(msg);
}
void onPaint(PaintEvent& ev) OVERRIDE {
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
Graphics* g = ev.getGraphics();
gfx::Rect bounds = getClientBounds();
ui::Color bgcolor, fgcolor;
if (isSelected()) {
bgcolor = theme->getColor(ThemeColor::ListItemSelectedFace);
fgcolor = theme->getColor(ThemeColor::ListItemSelectedText);
}
else {
bgcolor = theme->getColor(ThemeColor::ListItemNormalFace);
fgcolor = theme->getColor(ThemeColor::ListItemNormalText);
}
g->fillRect(bgcolor, bounds);
static_cast<ResourcesListBox*>(getParent())->
paintResource(g, bounds, m_resource);
// for (int i=0; i<m_palette->size(); ++i) {
// raster::color_t c = m_resource->getEntry(i);
// g->fillRect(ui::rgba(
// raster::rgba_getr(c),
// raster::rgba_getg(c),
// raster::rgba_getb(c)), box);
// box.x += box.w;
// }
g->drawString(getText(), fgcolor, ui::ColorNone,
gfx::Point(
bounds.x + jguiscale()*2,
bounds.y + bounds.h/2 - g->measureUIString(getText()).h/2));
}
void onPreferredSize(PreferredSizeEvent& ev) OVERRIDE {
ev.setPreferredSize(
static_cast<ResourcesListBox*>(getParent())->
preferredResourceSize(m_resource));
}
private:
base::UniquePtr<Resource> m_resource;
};
class ResourcesListBox::LoadingItem : public ListItem {
public:
LoadingItem()
: ListItem("Loading")
, m_state(0) {
}
void makeProgress() {
std::string text = "Loading ";
switch ((++m_state) % 4) {
case 0: text += "/"; break;
case 1: text += "-"; break;
case 2: text += "\\"; break;
case 3: text += "|"; break;
}
setText(text);
}
private:
int m_state;
};
ResourcesListBox::ResourcesListBox(ResourcesLoader* resourcesLoader)
: m_resourcesLoader(resourcesLoader)
, m_resourcesTimer(100)
, m_loadingItem(NULL)
{
m_resourcesTimer.Tick.connect(Bind<void>(&ResourcesListBox::onTick, this));
}
Resource* ResourcesListBox::selectedResource()
{
if (ResourceListItem* listItem = dynamic_cast<ResourceListItem*>(getSelectedChild()))
return listItem->resource();
else
return NULL;
}
void ResourcesListBox::paintResource(Graphics* g, const gfx::Rect& bounds, Resource* resource)
{
onPaintResource(g, bounds, resource);
}
gfx::Size ResourcesListBox::preferredResourceSize(Resource* resource)
{
gfx::Size pref(0, 0);
onResourcePreferredSize(resource, pref);
return pref;
}
bool ResourcesListBox::onProcessMessage(ui::Message* msg)
{
switch (msg->type()) {
case kOpenMessage: {
m_resourcesTimer.start();
break;
}
}
return ListBox::onProcessMessage(msg);
}
void ResourcesListBox::onChangeSelectedItem()
{
Resource* resource = selectedResource();
if (resource)
onResourceChange(resource);
}
void ResourcesListBox::onResourceChange(Resource* resource)
{
// Do nothing
}
void ResourcesListBox::onPaintResource(Graphics* g, const gfx::Rect& bounds, Resource* resource)
{
// Do nothing
}
void ResourcesListBox::onTick()
{
if (m_resourcesLoader == NULL) {
stop();
return;
}
if (!m_loadingItem) {
m_loadingItem = new LoadingItem;
addChild(m_loadingItem);
}
m_loadingItem->makeProgress();
base::UniquePtr<Resource> resource;
std::string name;
if (!m_resourcesLoader->next(resource)) {
if (m_resourcesLoader->isDone()) {
stop();
PRINTF("Done\n");
}
return;
}
base::UniquePtr<ResourceListItem> listItem(new ResourceListItem(resource));
insertChild(getItemsCount()-1, listItem);
layout();
View* view = View::getView(this);
if (view)
view->updateView();
resource.release();
listItem.release();
}
void ResourcesListBox::stop()
{
if (m_loadingItem) {
removeChild(m_loadingItem);
delete m_loadingItem;
m_loadingItem = NULL;
invalidate();
}
m_resourcesTimer.stop();
}
} // namespace app