ImageGridComponent & TextListComponent have had common list functionality

refactored into IList.
This commit is contained in:
Aloshi 2014-02-07 21:45:28 -06:00
parent 7699a4f9be
commit 1aa291ebe7
9 changed files with 261 additions and 362 deletions

View file

@ -244,7 +244,6 @@ set(ES_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentListComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentListComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/DateTimeComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/DateTimeComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/HelpComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/HelpComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/IList.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/NinePatchComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/NinePatchComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/RatingComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/RatingComponent.cpp

View file

@ -62,7 +62,7 @@ bool GuiMenu::input(InputConfig* config, Input input)
Sound::getFromTheme(mTheme, "menu", "menuClose")->play(); Sound::getFromTheme(mTheme, "menu", "menuClose")->play();
delete this; delete this;
return true; return true;
}else if(config->isMappedTo("a", input) && mList.getList().size() > 0) }else if(config->isMappedTo("a", input) && mList.size() > 0)
{ {
mList.getSelected()(); mList.getSelected()();
delete this; delete this;

View file

@ -1,81 +0,0 @@
#include "IList.h"
const IList::ScrollTier IList::SCROLL_SPEED[IList::SCROLL_SPEED_COUNT] = {
{500, 500},
{2600, 150},
{0, 100}
};
IList::IList()
{
mScrollTier = 0;
mScrollVelocity = 0;
mScrollTierAccumulator = 0;
mScrollCursorAccumulator = 0;
}
void IList::listInput(int velocity)
{
mScrollVelocity = velocity;
mScrollTier = 0;
mScrollTierAccumulator = 0;
mScrollCursorAccumulator = 0;
scroll(mScrollVelocity);
}
void IList::listUpdate(int deltaTime)
{
if(mScrollVelocity == 0 || getLength() < 2)
return;
mScrollCursorAccumulator += deltaTime;
mScrollTierAccumulator += deltaTime;
while(mScrollCursorAccumulator >= SCROLL_SPEED[mScrollTier].scrollDelay)
{
mScrollCursorAccumulator -= SCROLL_SPEED[mScrollTier].scrollDelay;
scroll(mScrollVelocity);
}
// are we ready to go even FASTER?
while(mScrollTier < SCROLL_SPEED_COUNT - 1 && mScrollTierAccumulator >= SCROLL_SPEED[mScrollTier].length)
{
mScrollTierAccumulator -= SCROLL_SPEED[mScrollTier].length;
mScrollTier++;
}
}
void IList::scroll(int amt)
{
if(mScrollVelocity == 0 || getLength() < 2)
return;
int cursor = getCursorIndex() + amt;
int absAmt = amt < 0 ? -amt : amt;
// stop at the end if we've been holding down the button for a long time or
// we're scrolling faster than one item at a time (e.g. page up/down)
// otherwise, loop around
if(mScrollTier > 0 || absAmt > 1)
{
if(cursor < 0)
cursor = 0;
else if(cursor >= getLength())
cursor = getLength() - 1;
}else{
if(cursor < 0)
cursor += getLength();
else if(cursor >= getLength())
cursor -= getLength();
}
if(cursor != getCursorIndex())
onScroll(absAmt);
setCursorIndex(cursor);
}
bool IList::isScrolling() const
{
return (mScrollVelocity != 0 && mScrollTier > 0);
}

View file

@ -1,36 +1,210 @@
#pragma once #pragma once
#include <string>
#include <vector>
enum CursorState
{
CURSOR_STOPPED,
CURSOR_SCROLLING
};
struct ScrollTier
{
int length; // how long we stay on this level before going to the next
int scrollDelay; // how long between scrolls
};
const int SCROLL_SPEED_COUNT = 3;
const ScrollTier SCROLL_SPEED[SCROLL_SPEED_COUNT] = {
{500, 500},
{2600, 150},
{0, 100}
};
template <typename EntryData, typename UserData>
class IList class IList
{ {
public: public:
IList(); struct Entry
bool isScrolling() const;
protected:
void listInput(int velocity); // a velocity of 0 = stop scrolling
void listUpdate(int deltaTime);
virtual int getCursorIndex() = 0;
virtual void setCursorIndex(int index) = 0; // (index >= 0 && index < getLength()) is guaranteed to be true
virtual int getLength() = 0;
void scroll(int amt);
virtual void onScroll(int amt) {};
private:
struct ScrollTier
{ {
int length; // how long we stay on this level before going to the next std::string name;
int scrollDelay; // how long between scrolls UserData object;
EntryData data;
}; };
static const int SCROLL_SPEED_COUNT = 3; protected:
static const ScrollTier SCROLL_SPEED[SCROLL_SPEED_COUNT]; int mCursor;
int mScrollTier; int mScrollTier;
int mScrollVelocity; int mScrollVelocity;
int mScrollTierAccumulator; int mScrollTierAccumulator;
int mScrollCursorAccumulator; int mScrollCursorAccumulator;
std::vector<Entry> mEntries;
public:
IList()
{
mCursor = 0;
mScrollTier = 0;
mScrollVelocity = 0;
mScrollTierAccumulator = 0;
mScrollCursorAccumulator = 0;
}
bool isScrolling() const
{
return (mScrollVelocity != 0 && mScrollTier > 0);
}
void stopScrolling()
{
listInput(0);
onCursorChanged(CURSOR_STOPPED);
}
void clear()
{
mEntries.clear();
mCursor = 0;
listInput(0);
onCursorChanged(CURSOR_STOPPED);
}
inline const std::string& getSelectedName()
{
assert(size() > 0);
return mEntries.at(mCursor).name;
}
inline const UserData& getSelected() const
{
assert(size() > 0);
return mEntries.at(mCursor).object;
}
void setCursor(typename std::vector<Entry>::iterator& it)
{
assert(it != mEntries.end());
mCursor = it - mEntries.begin();
onCursorChanged(CURSOR_STOPPED);
}
// returns true if successful (select is in our list), false if not
bool setCursor(const UserData& obj)
{
for(auto it = mEntries.begin(); it != mEntries.end(); it++)
{
if((*it).object == obj)
{
mCursor = it - mEntries.begin();
onCursorChanged(CURSOR_STOPPED);
return true;
}
}
return false;
}
// entry management
void add(Entry e)
{
mEntries.push_back(e);
}
bool remove(const UserData& obj)
{
for(auto it = mEntries.begin(); it != mEntries.end(); it++)
{
if((*it).object == obj)
{
remove(it);
return true;
}
}
return false;
}
inline int size() const { return mEntries.size(); }
protected:
void remove(typename std::vector<Entry>::iterator& it)
{
if(getCursorIndex() > 0 && it - mEntries.begin() <= getCursorIndex())
{
setCursorIndex(mCursor - 1);
onCursorChanged(CURSOR_STOPPED);
}
mEntries.erase(it);
}
void listInput(int velocity) // a velocity of 0 = stop scrolling
{
mScrollVelocity = velocity;
mScrollTier = 0;
mScrollTierAccumulator = 0;
mScrollCursorAccumulator = 0;
scroll(mScrollVelocity);
}
void listUpdate(int deltaTime)
{
if(mScrollVelocity == 0 || size() < 2)
return;
mScrollCursorAccumulator += deltaTime;
mScrollTierAccumulator += deltaTime;
while(mScrollCursorAccumulator >= SCROLL_SPEED[mScrollTier].scrollDelay)
{
mScrollCursorAccumulator -= SCROLL_SPEED[mScrollTier].scrollDelay;
scroll(mScrollVelocity);
}
// are we ready to go even FASTER?
while(mScrollTier < SCROLL_SPEED_COUNT - 1 && mScrollTierAccumulator >= SCROLL_SPEED[mScrollTier].length)
{
mScrollTierAccumulator -= SCROLL_SPEED[mScrollTier].length;
mScrollTier++;
}
}
void scroll(int amt)
{
if(mScrollVelocity == 0 || size() < 2)
return;
int cursor = mCursor + amt;
int absAmt = amt < 0 ? -amt : amt;
// stop at the end if we've been holding down the button for a long time or
// we're scrolling faster than one item at a time (e.g. page up/down)
// otherwise, loop around
if(mScrollTier > 0 || absAmt > 1)
{
if(cursor < 0)
cursor = 0;
else if(cursor >= size())
cursor = size() - 1;
}else{
if(cursor < 0)
cursor += size();
else if(cursor >= size())
cursor -= size();
}
if(cursor != mCursor)
onScroll(absAmt);
mCursor = cursor;
onCursorChanged((mScrollTier > 0) ? CURSOR_SCROLLING : CURSOR_STOPPED);
}
virtual void onCursorChanged(const CursorState& state) {}
virtual void onScroll(int amt) {}
}; };

View file

@ -5,49 +5,25 @@
#include "../components/ImageComponent.h" #include "../components/ImageComponent.h"
#include "../Log.h" #include "../Log.h"
struct ImageGridData
{
std::shared_ptr<TextureResource> texture;
};
template<typename T> template<typename T>
class ImageGridComponent : public GuiComponent, public IList class ImageGridComponent : public GuiComponent, public IList<ImageGridData, T>
{ {
public: public:
ImageGridComponent(Window* window); ImageGridComponent(Window* window);
struct Entry void add(const std::string& name, const std::string& imagePath, const T& obj);
{
std::shared_ptr<TextureResource> texture;
T object;
Entry() {}
Entry(std::shared_ptr<TextureResource> t, const T& o) : texture(t), object(o) {}
};
void add(const std::string& imagePath, const T& obj);
void remove(const T& obj);
void clear();
void setCursor(const T& select);
void setCursor(typename std::vector<Entry>::const_iterator& it);
inline const T& getSelected() const { return mEntries.at(mCursor).object; }
inline const std::vector<Entry>& getList() const { return mEntries; }
enum CursorState {
CURSOR_STOPPED,
CURSOR_SCROLLING
};
void stopScrolling();
void onSizeChanged() override; void onSizeChanged() override;
bool input(InputConfig* config, Input input) override; bool input(InputConfig* config, Input input) override;
void update(int deltaTime) override; void update(int deltaTime) override;
void render(const Eigen::Affine3f& parentTrans) override; void render(const Eigen::Affine3f& parentTrans) override;
protected:
virtual int getCursorIndex() { return mCursor; }
virtual void setCursorIndex(int index) { mCursor = index; onCursorChanged(CURSOR_STOPPED); }
virtual int getLength() { return mEntries.size(); }
private: private:
Eigen::Vector2f getSquareSize(std::shared_ptr<TextureResource> tex = nullptr) const Eigen::Vector2f getSquareSize(std::shared_ptr<TextureResource> tex = nullptr) const
{ {
@ -73,7 +49,7 @@ private:
// calc biggest square size // calc biggest square size
for(auto it = mEntries.begin(); it != mEntries.end(); it++) for(auto it = mEntries.begin(); it != mEntries.end(); it++)
{ {
Eigen::Vector2f chkSize = getSquareSize(it->texture); Eigen::Vector2f chkSize = getSquareSize(it->data.texture);
if(chkSize.x() > squareSize.x()) if(chkSize.x() > squareSize.x())
squareSize[0] = chkSize[0]; squareSize[0] = chkSize[0];
if(chkSize.y() > squareSize.y()) if(chkSize.y() > squareSize.y())
@ -95,13 +71,10 @@ private:
void buildImages(); void buildImages();
void updateImages(); void updateImages();
void onCursorChanged(CursorState state); virtual void onCursorChanged(const CursorState& state);
int mCursor;
bool mEntriesDirty; bool mEntriesDirty;
std::vector<Entry> mEntries;
std::vector<ImageComponent> mImages; std::vector<ImageComponent> mImages;
}; };
@ -109,79 +82,19 @@ template<typename T>
ImageGridComponent<T>::ImageGridComponent(Window* window) : GuiComponent(window) ImageGridComponent<T>::ImageGridComponent(Window* window) : GuiComponent(window)
{ {
mEntriesDirty = true; mEntriesDirty = true;
mCursor = 0;
} }
template<typename T> template<typename T>
void ImageGridComponent<T>::add(const std::string& imagePath, const T& obj) void ImageGridComponent<T>::add(const std::string& name, const std::string& imagePath, const T& obj)
{ {
Entry e(ResourceManager::getInstance()->fileExists(imagePath) ? TextureResource::get(imagePath) : TextureResource::get(":/button.png"), obj); Entry entry;
mEntries.push_back(e); entry.name = name;
entry.object = obj;
entry.data.texture = ResourceManager::getInstance()->fileExists(imagePath) ? TextureResource::get(imagePath) : TextureResource::get(":/button.png");
static_cast<IList< ImageGridData, T >*>(this)->add(entry);
mEntriesDirty = true; mEntriesDirty = true;
} }
template<typename T>
void ImageGridComponent<T>::remove(const T& obj)
{
for(auto it = mEntries.begin(); it != mEntries.end(); it++)
{
if((*it).object == obj)
{
if(mCursor > 0 && it - mEntries.begin() >= mCursor)
{
mCursor--;
onCursorChanged(CURSOR_STOPPED);
}
mEntriesDirty = true;
mEntries.erase(it);
return;
}
}
LOG(LogError) << "Tried to remove an object we couldn't find";
}
template<typename T>
void ImageGridComponent<T>::clear()
{
mEntries.clear();
mCursor = 0;
onCursorChanged(CURSOR_STOPPED);
mEntriesDirty = true;
}
template<typename T>
void ImageGridComponent<T>::setCursor(const T& obj)
{
for(auto it = mEntries.begin(); it != mEntries.end(); it++)
{
if((*it).object == obj)
{
mCursor = it - mEntries.begin();
onCursorChanged(CURSOR_STOPPED);
return;
}
}
LOG(LogError) << "Tried to set cursor to object we couldn't find";
}
template<typename T>
void ImageGridComponent<T>::setCursor(typename std::vector<Entry>::const_iterator& it)
{
assert(it != mEntries.end());
mCursor = it - mEntries.begin();
onCursorChanged(CURSOR_STOPPED);
}
template<typename T>
void ImageGridComponent<T>::stopScrolling()
{
listInput(0);
onCursorChanged(CURSOR_STOPPED);
}
template<typename T> template<typename T>
bool ImageGridComponent<T>::input(InputConfig* config, Input input) bool ImageGridComponent<T>::input(InputConfig* config, Input input)
{ {
@ -239,7 +152,7 @@ void ImageGridComponent<T>::render(const Eigen::Affine3f& parentTrans)
} }
template<typename T> template<typename T>
void ImageGridComponent<T>::onCursorChanged(CursorState state) void ImageGridComponent<T>::onCursorChanged(const CursorState& state)
{ {
updateImages(); updateImages();
} }
@ -305,13 +218,13 @@ void ImageGridComponent<T>::updateImages()
for(unsigned int img = 0; img < mImages.size(); img++) for(unsigned int img = 0; img < mImages.size(); img++)
{ {
ImageComponent& image = mImages.at(img); ImageComponent& image = mImages.at(img);
if(i >= mEntries.size()) if(i >= (unsigned int)size())
{ {
image.setImage(""); image.setImage("");
continue; continue;
} }
Eigen::Vector2f squareSize = getSquareSize(mEntries.at(i).texture); Eigen::Vector2f squareSize = getSquareSize(mEntries.at(i).data.texture);
if(i == mCursor) if(i == mCursor)
{ {
image.setColorShift(0xFFFFFFFF); image.setColorShift(0xFFFFFFFF);
@ -321,7 +234,7 @@ void ImageGridComponent<T>::updateImages()
image.setResize(squareSize.x(), squareSize.y()); image.setResize(squareSize.x(), squareSize.y());
} }
image.setImage(mEntries.at(i).texture); image.setImage(mEntries.at(i).data.texture);
i++; i++;
} }
} }

View file

@ -13,46 +13,26 @@
#include "../ThemeData.h" #include "../ThemeData.h"
#include <functional> #include <functional>
struct TextListData
{
unsigned int colorId;
std::shared_ptr<TextCache> textCache;
};
//A graphical list. Supports multiple colors for rows and scrolling. //A graphical list. Supports multiple colors for rows and scrolling.
template <typename T> template <typename T>
class TextListComponent : public GuiComponent, public IList class TextListComponent : public GuiComponent, public IList<TextListData, T>
{ {
public: public:
TextListComponent(Window* window); TextListComponent(Window* window);
virtual ~TextListComponent();
bool input(InputConfig* config, Input input) override; bool input(InputConfig* config, Input input) override;
void update(int deltaTime) override; void update(int deltaTime) override;
void render(const Eigen::Affine3f& parentTrans) override; void render(const Eigen::Affine3f& parentTrans) override;
void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override; void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
struct ListRow
{
std::string name;
T object;
unsigned int colorId;
std::shared_ptr<TextCache> textCache;
};
void add(const std::string& name, const T& obj, unsigned int colorId); void add(const std::string& name, const T& obj, unsigned int colorId);
void remove(const T& obj);
void clear();
inline const std::string& getSelectedName() const { return mRowVector.at(mCursor).name; }
inline T getSelected() const { return mRowVector.at(mCursor).object; }
inline const std::vector<ListRow>& getList() const { return mRowVector; }
void setCursor(const T& select);
void setCursor(typename std::vector<ListRow>::const_iterator& it);
void stopScrolling();
enum CursorState
{
CURSOR_STOPPED,
CURSOR_SCROLLING
};
enum Alignment enum Alignment
{ {
ALIGN_LEFT, ALIGN_LEFT,
@ -67,8 +47,8 @@ public:
inline void setFont(const std::shared_ptr<Font>& font) inline void setFont(const std::shared_ptr<Font>& font)
{ {
mFont = font; mFont = font;
for(auto it = mRowVector.begin(); it != mRowVector.end(); it++) for(auto it = mEntries.begin(); it != mEntries.end(); it++)
it->textCache.reset(); it->data.textCache.reset();
} }
inline void setSelectorColor(unsigned int color) { mSelectorColor = color; } inline void setSelectorColor(unsigned int color) { mSelectorColor = color; }
@ -78,28 +58,20 @@ public:
inline void setSound(const std::shared_ptr<Sound>& sound) { mScrollSound = sound; } inline void setSound(const std::shared_ptr<Sound>& sound) { mScrollSound = sound; }
protected: protected:
// IList implementations
virtual int getCursorIndex() { return mCursor; }
virtual void setCursorIndex(int index) { mCursor = index; onCursorChanged(isScrolling() ? CURSOR_SCROLLING : CURSOR_STOPPED); }
virtual int getLength() { return mRowVector.size(); }
virtual void onScroll(int amt) { if(mScrollSound) mScrollSound->play(); } virtual void onScroll(int amt) { if(mScrollSound) mScrollSound->play(); }
virtual void onCursorChanged(const CursorState& state);
private: private:
static const int MARQUEE_DELAY = 900; static const int MARQUEE_DELAY = 900;
static const int MARQUEE_SPEED = 16; static const int MARQUEE_SPEED = 16;
static const int MARQUEE_RATE = 3; static const int MARQUEE_RATE = 3;
void onCursorChanged(CursorState state);
int mMarqueeOffset; int mMarqueeOffset;
int mMarqueeTime; int mMarqueeTime;
Alignment mAlignment; Alignment mAlignment;
float mHorizontalMargin; float mHorizontalMargin;
std::vector<ListRow> mRowVector;
int mCursor;
std::function<void(CursorState state)> mCursorChangedCallback; std::function<void(CursorState state)> mCursorChangedCallback;
std::shared_ptr<Font> mFont; std::shared_ptr<Font> mFont;
@ -114,8 +86,6 @@ template <typename T>
TextListComponent<T>::TextListComponent(Window* window) : TextListComponent<T>::TextListComponent(Window* window) :
GuiComponent(window) GuiComponent(window)
{ {
mCursor = 0;
mMarqueeOffset = 0; mMarqueeOffset = 0;
mMarqueeTime = -MARQUEE_DELAY; mMarqueeTime = -MARQUEE_DELAY;
@ -129,11 +99,6 @@ TextListComponent<T>::TextListComponent(Window* window) :
mColors[1] = 0x00FF00FF; mColors[1] = 0x00FF00FF;
} }
template <typename T>
TextListComponent<T>::~TextListComponent()
{
}
template <typename T> template <typename T>
void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans) void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans)
{ {
@ -141,6 +106,13 @@ void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans)
std::shared_ptr<Font>& font = mFont; std::shared_ptr<Font>& font = mFont;
if(size() == 0)
{
Renderer::setMatrix(trans);
font->drawText("The list is empty.", Eigen::Vector2f(0, 0), 0xFF0000FF);
return;
}
const int cutoff = 0; const int cutoff = 0;
const int entrySize = font->getHeight() + 5; const int entrySize = font->getHeight() + 5;
@ -149,26 +121,20 @@ void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans)
//number of entries that can fit on the screen simultaniously //number of entries that can fit on the screen simultaniously
int screenCount = (int)mSize.y() / entrySize; int screenCount = (int)mSize.y() / entrySize;
if((int)mRowVector.size() >= screenCount) if(size() >= screenCount)
{ {
startEntry = mCursor - (int)(screenCount * 0.5); startEntry = mCursor - (int)(screenCount * 0.5);
if(startEntry < 0) if(startEntry < 0)
startEntry = 0; startEntry = 0;
if(startEntry >= (int)mRowVector.size() - screenCount) if(startEntry >= size() - screenCount)
startEntry = mRowVector.size() - screenCount; startEntry = size() - screenCount;
} }
float y = (float)cutoff; float y = (float)cutoff;
if(mRowVector.size() == 0)
{
font->drawCenteredText("The list is empty.", 0, y, 0xFF0000FF);
return;
}
int listCutoff = startEntry + screenCount; int listCutoff = startEntry + screenCount;
if(listCutoff > (int)mRowVector.size()) if(listCutoff > size())
listCutoff = mRowVector.size(); listCutoff = size();
Eigen::Vector3f dim(getSize().x(), getSize().y(), 0); Eigen::Vector3f dim(getSize().x(), getSize().y(), 0);
dim = trans * dim - trans.translation(); dim = trans * dim - trans.translation();
@ -183,18 +149,18 @@ void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans)
Renderer::drawRect(0, (int)y, (int)getSize().x(), font->getHeight(), mSelectorColor); Renderer::drawRect(0, (int)y, (int)getSize().x(), font->getHeight(), mSelectorColor);
} }
ListRow& row = mRowVector.at((unsigned int)i); Entry& entry = mEntries.at((unsigned int)i);
unsigned int color; unsigned int color;
if(mCursor == i && mSelectedColor) if(mCursor == i && mSelectedColor)
color = mSelectedColor; color = mSelectedColor;
else else
color = mColors[row.colorId]; color = mColors[entry.data.colorId];
if(!row.textCache) if(!entry.data.textCache)
row.textCache = std::unique_ptr<TextCache>(font->buildTextCache(row.name, 0, 0, 0x000000FF)); entry.data.textCache = std::unique_ptr<TextCache>(font->buildTextCache(entry.name, 0, 0, 0x000000FF));
row.textCache->setColor(color); entry.data.textCache->setColor(color);
Eigen::Vector3f offset(0, y, 0); Eigen::Vector3f offset(0, y, 0);
@ -204,12 +170,12 @@ void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans)
offset[0] = mHorizontalMargin; offset[0] = mHorizontalMargin;
break; break;
case ALIGN_CENTER: case ALIGN_CENTER:
offset[0] = (mSize.x() - row.textCache->metrics.size.x()) / 2; offset[0] = (mSize.x() - entry.data.textCache->metrics.size.x()) / 2;
if(offset[0] < 0) if(offset[0] < 0)
offset[0] = 0; offset[0] = 0;
break; break;
case ALIGN_RIGHT: case ALIGN_RIGHT:
offset[0] = (mSize.x() - row.textCache->metrics.size.x()); offset[0] = (mSize.x() - entry.data.textCache->metrics.size.x());
offset[0] -= mHorizontalMargin; offset[0] -= mHorizontalMargin;
if(offset[0] < 0) if(offset[0] < 0)
offset[0] = 0; offset[0] = 0;
@ -224,7 +190,7 @@ void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans)
drawTrans.translate(offset); drawTrans.translate(offset);
Renderer::setMatrix(drawTrans); Renderer::setMatrix(drawTrans);
font->renderTextCache(row.textCache.get()); font->renderTextCache(entry.data.textCache.get());
y += entrySize; y += entrySize;
} }
@ -237,7 +203,7 @@ void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans)
template <typename T> template <typename T>
bool TextListComponent<T>::input(InputConfig* config, Input input) bool TextListComponent<T>::input(InputConfig* config, Input input)
{ {
if(mRowVector.size() > 0) if(size() > 0)
{ {
if(input.value != 0) if(input.value != 0)
{ {
@ -279,10 +245,10 @@ template <typename T>
void TextListComponent<T>::update(int deltaTime) void TextListComponent<T>::update(int deltaTime)
{ {
listUpdate(deltaTime); listUpdate(deltaTime);
if(!isScrolling()) if(!isScrolling() && size() > 0)
{ {
//if we're not scrolling and this object's text goes outside our size, marquee it! //if we're not scrolling and this object's text goes outside our size, marquee it!
std::string text = getSelectedName(); const std::string& text = mEntries.at((unsigned int)mCursor).name;
Eigen::Vector2f textSize = mFont->sizeText(text); Eigen::Vector2f textSize = mFont->sizeText(text);
@ -307,68 +273,15 @@ void TextListComponent<T>::add(const std::string& name, const T& obj, unsigned i
{ {
assert(color < COLOR_ID_COUNT); assert(color < COLOR_ID_COUNT);
ListRow row = {name, obj, color}; Entry entry;
mRowVector.push_back(row); entry.name = name;
entry.object = obj;
entry.data.colorId = color;
static_cast<IList< TextListData, T >*>(this)->add(entry);
} }
template <typename T> template <typename T>
void TextListComponent<T>::remove(const T& obj) void TextListComponent<T>::onCursorChanged(const CursorState& state)
{
for(auto it = mRowVector.begin(); it != mRowVector.end(); it++)
{
if((*it).object == obj)
{
if(mCursor > 0 && it - mRowVector.begin() >= mCursor)
{
mCursor--;
onCursorChanged(CURSOR_STOPPED);
}
mRowVector.erase(it);
return;
}
}
LOG(LogError) << "Tried to remove an object we couldn't find";
}
template <typename T>
void TextListComponent<T>::clear()
{
mRowVector.clear();
mCursor = 0;
mMarqueeOffset = 0;
mMarqueeTime = -MARQUEE_DELAY;
onCursorChanged(CURSOR_STOPPED);
}
template <typename T>
void TextListComponent<T>::setCursor(const T& obj)
{
for(auto it = mRowVector.begin(); it != mRowVector.end(); it++)
{
if((*it).object == obj)
{
mCursor = it - mRowVector.begin();
onCursorChanged(CURSOR_STOPPED);
return;
}
}
LOG(LogError) << "Tried to set cursor to object we couldn't find";
}
template <typename T>
void TextListComponent<T>::setCursor(typename std::vector<ListRow>::const_iterator& it)
{
assert(it != mRowVector.end());
mCursor = it - mRowVector.begin();
onCursorChanged(CURSOR_STOPPED);
}
template <typename T>
void TextListComponent<T>::onCursorChanged(CursorState state)
{ {
mMarqueeOffset = 0; mMarqueeOffset = 0;
mMarqueeTime = -MARQUEE_DELAY; mMarqueeTime = -MARQUEE_DELAY;
@ -377,13 +290,6 @@ void TextListComponent<T>::onCursorChanged(CursorState state)
mCursorChangedCallback(state); mCursorChangedCallback(state);
} }
template <typename T>
void TextListComponent<T>::stopScrolling()
{
listInput(0);
onCursorChanged(CURSOR_STOPPED);
}
template <typename T> template <typename T>
void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
{ {

View file

@ -53,14 +53,8 @@ FileData* BasicGameListView::getCursor()
void BasicGameListView::setCursor(FileData* cursor) void BasicGameListView::setCursor(FileData* cursor)
{ {
typedef TextListComponent<FileData*>::ListRow Row; if(!mList.setCursor(cursor))
const std::vector<Row>& list = mList.getList();
auto found = std::find_if(list.begin(), list.end(), [&](const Row& row) { return (row.object == cursor); });
if(found != list.end())
{ {
mList.setCursor(found);
}else{
populateList(cursor->getParent()->getChildren()); populateList(cursor->getParent()->getChildren());
mList.setCursor(cursor); mList.setCursor(cursor);
} }

View file

@ -21,7 +21,7 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) :
mList.setPosition(mSize.x() * (0.50f + padding), mList.getPosition().y()); mList.setPosition(mSize.x() * (0.50f + padding), mList.getPosition().y());
mList.setSize(mSize.x() * (0.50f - 2*padding), mList.getSize().y()); mList.setSize(mSize.x() * (0.50f - 2*padding), mList.getSize().y());
mList.setAlignment(TextListComponent<FileData*>::ALIGN_LEFT); mList.setAlignment(TextListComponent<FileData*>::ALIGN_LEFT);
mList.setCursorChangedCallback([&](TextListComponent<FileData*>::CursorState state) { updateInfoPanel(); }); mList.setCursorChangedCallback([&](const CursorState& state) { updateInfoPanel(); });
// image // image
mImage.setOrigin(0.5f, 0.5f); mImage.setOrigin(0.5f, 0.5f);
@ -179,7 +179,7 @@ void DetailedGameListView::initMDValues()
void DetailedGameListView::updateInfoPanel() void DetailedGameListView::updateInfoPanel()
{ {
FileData* file = (mList.getList().size() == 0 || mList.isScrolling()) ? NULL : mList.getSelected(); FileData* file = (mList.size() == 0 || mList.isScrolling()) ? NULL : mList.getSelected();
bool fadingOut; bool fadingOut;
if(file == NULL) if(file == NULL)

View file

@ -20,14 +20,8 @@ FileData* GridGameListView::getCursor()
void GridGameListView::setCursor(FileData* file) void GridGameListView::setCursor(FileData* file)
{ {
typedef ImageGridComponent<FileData*>::Entry Entry; if(!mGrid.setCursor(file))
auto& list = mGrid.getList();
auto found = std::find_if(list.begin(), list.end(), [&] (const Entry& e) { return (e.object == file); });
if(found != list.end())
{ {
mGrid.setCursor(found);
}else{
populateList(file->getParent()->getChildren()); populateList(file->getParent()->getChildren());
mGrid.setCursor(file); mGrid.setCursor(file);
} }
@ -46,7 +40,7 @@ void GridGameListView::populateList(const std::vector<FileData*>& files)
mGrid.clear(); mGrid.clear();
for(auto it = files.begin(); it != files.end(); it++) for(auto it = files.begin(); it != files.end(); it++)
{ {
mGrid.add((*it)->getThumbnailPath(), *it); mGrid.add((*it)->getName(), (*it)->getThumbnailPath(), *it);
} }
} }