mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
ImageGridComponent & TextListComponent have had common list functionality
refactored into IList.
This commit is contained in:
parent
7699a4f9be
commit
1aa291ebe7
|
@ -244,7 +244,6 @@ set(ES_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentListComponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/DateTimeComponent.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/NinePatchComponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/RatingComponent.cpp
|
||||
|
|
|
@ -62,7 +62,7 @@ bool GuiMenu::input(InputConfig* config, Input input)
|
|||
Sound::getFromTheme(mTheme, "menu", "menuClose")->play();
|
||||
delete this;
|
||||
return true;
|
||||
}else if(config->isMappedTo("a", input) && mList.getList().size() > 0)
|
||||
}else if(config->isMappedTo("a", input) && mList.size() > 0)
|
||||
{
|
||||
mList.getSelected()();
|
||||
delete this;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -1,36 +1,210 @@
|
|||
#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
|
||||
{
|
||||
public:
|
||||
IList();
|
||||
|
||||
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
|
||||
struct Entry
|
||||
{
|
||||
int length; // how long we stay on this level before going to the next
|
||||
int scrollDelay; // how long between scrolls
|
||||
std::string name;
|
||||
UserData object;
|
||||
EntryData data;
|
||||
};
|
||||
|
||||
static const int SCROLL_SPEED_COUNT = 3;
|
||||
static const ScrollTier SCROLL_SPEED[SCROLL_SPEED_COUNT];
|
||||
protected:
|
||||
int mCursor;
|
||||
|
||||
int mScrollTier;
|
||||
int mScrollVelocity;
|
||||
|
||||
int mScrollTierAccumulator;
|
||||
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) {}
|
||||
};
|
||||
|
|
|
@ -5,49 +5,25 @@
|
|||
#include "../components/ImageComponent.h"
|
||||
#include "../Log.h"
|
||||
|
||||
struct ImageGridData
|
||||
{
|
||||
std::shared_ptr<TextureResource> texture;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ImageGridComponent : public GuiComponent, public IList
|
||||
class ImageGridComponent : public GuiComponent, public IList<ImageGridData, T>
|
||||
{
|
||||
public:
|
||||
ImageGridComponent(Window* window);
|
||||
|
||||
struct Entry
|
||||
{
|
||||
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 add(const std::string& name, const std::string& imagePath, const T& obj);
|
||||
|
||||
void onSizeChanged() override;
|
||||
|
||||
bool input(InputConfig* config, Input input) override;
|
||||
void update(int deltaTime) 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:
|
||||
Eigen::Vector2f getSquareSize(std::shared_ptr<TextureResource> tex = nullptr) const
|
||||
{
|
||||
|
@ -73,7 +49,7 @@ private:
|
|||
// calc biggest square size
|
||||
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())
|
||||
squareSize[0] = chkSize[0];
|
||||
if(chkSize.y() > squareSize.y())
|
||||
|
@ -95,13 +71,10 @@ private:
|
|||
void buildImages();
|
||||
void updateImages();
|
||||
|
||||
void onCursorChanged(CursorState state);
|
||||
|
||||
int mCursor;
|
||||
virtual void onCursorChanged(const CursorState& state);
|
||||
|
||||
bool mEntriesDirty;
|
||||
|
||||
std::vector<Entry> mEntries;
|
||||
std::vector<ImageComponent> mImages;
|
||||
};
|
||||
|
||||
|
@ -109,79 +82,19 @@ template<typename T>
|
|||
ImageGridComponent<T>::ImageGridComponent(Window* window) : GuiComponent(window)
|
||||
{
|
||||
mEntriesDirty = true;
|
||||
mCursor = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
mEntries.push_back(e);
|
||||
Entry entry;
|
||||
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;
|
||||
}
|
||||
|
||||
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>
|
||||
bool ImageGridComponent<T>::input(InputConfig* config, Input input)
|
||||
{
|
||||
|
@ -239,7 +152,7 @@ void ImageGridComponent<T>::render(const Eigen::Affine3f& parentTrans)
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void ImageGridComponent<T>::onCursorChanged(CursorState state)
|
||||
void ImageGridComponent<T>::onCursorChanged(const CursorState& state)
|
||||
{
|
||||
updateImages();
|
||||
}
|
||||
|
@ -305,13 +218,13 @@ void ImageGridComponent<T>::updateImages()
|
|||
for(unsigned int img = 0; img < mImages.size(); img++)
|
||||
{
|
||||
ImageComponent& image = mImages.at(img);
|
||||
if(i >= mEntries.size())
|
||||
if(i >= (unsigned int)size())
|
||||
{
|
||||
image.setImage("");
|
||||
continue;
|
||||
}
|
||||
|
||||
Eigen::Vector2f squareSize = getSquareSize(mEntries.at(i).texture);
|
||||
Eigen::Vector2f squareSize = getSquareSize(mEntries.at(i).data.texture);
|
||||
if(i == mCursor)
|
||||
{
|
||||
image.setColorShift(0xFFFFFFFF);
|
||||
|
@ -321,7 +234,7 @@ void ImageGridComponent<T>::updateImages()
|
|||
image.setResize(squareSize.x(), squareSize.y());
|
||||
}
|
||||
|
||||
image.setImage(mEntries.at(i).texture);
|
||||
image.setImage(mEntries.at(i).data.texture);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,46 +13,26 @@
|
|||
#include "../ThemeData.h"
|
||||
#include <functional>
|
||||
|
||||
struct TextListData
|
||||
{
|
||||
unsigned int colorId;
|
||||
std::shared_ptr<TextCache> textCache;
|
||||
};
|
||||
|
||||
//A graphical list. Supports multiple colors for rows and scrolling.
|
||||
template <typename T>
|
||||
class TextListComponent : public GuiComponent, public IList
|
||||
class TextListComponent : public GuiComponent, public IList<TextListData, T>
|
||||
{
|
||||
public:
|
||||
TextListComponent(Window* window);
|
||||
virtual ~TextListComponent();
|
||||
|
||||
|
||||
bool input(InputConfig* config, Input input) override;
|
||||
void update(int deltaTime) 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;
|
||||
|
||||
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 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
|
||||
{
|
||||
ALIGN_LEFT,
|
||||
|
@ -67,8 +47,8 @@ public:
|
|||
inline void setFont(const std::shared_ptr<Font>& font)
|
||||
{
|
||||
mFont = font;
|
||||
for(auto it = mRowVector.begin(); it != mRowVector.end(); it++)
|
||||
it->textCache.reset();
|
||||
for(auto it = mEntries.begin(); it != mEntries.end(); it++)
|
||||
it->data.textCache.reset();
|
||||
}
|
||||
|
||||
inline void setSelectorColor(unsigned int color) { mSelectorColor = color; }
|
||||
|
@ -78,28 +58,20 @@ public:
|
|||
inline void setSound(const std::shared_ptr<Sound>& sound) { mScrollSound = sound; }
|
||||
|
||||
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 onCursorChanged(const CursorState& state);
|
||||
|
||||
private:
|
||||
static const int MARQUEE_DELAY = 900;
|
||||
static const int MARQUEE_SPEED = 16;
|
||||
static const int MARQUEE_RATE = 3;
|
||||
|
||||
void onCursorChanged(CursorState state);
|
||||
|
||||
int mMarqueeOffset;
|
||||
int mMarqueeTime;
|
||||
|
||||
Alignment mAlignment;
|
||||
float mHorizontalMargin;
|
||||
|
||||
std::vector<ListRow> mRowVector;
|
||||
int mCursor;
|
||||
|
||||
std::function<void(CursorState state)> mCursorChangedCallback;
|
||||
|
||||
std::shared_ptr<Font> mFont;
|
||||
|
@ -114,8 +86,6 @@ template <typename T>
|
|||
TextListComponent<T>::TextListComponent(Window* window) :
|
||||
GuiComponent(window)
|
||||
{
|
||||
mCursor = 0;
|
||||
|
||||
mMarqueeOffset = 0;
|
||||
mMarqueeTime = -MARQUEE_DELAY;
|
||||
|
||||
|
@ -129,11 +99,6 @@ TextListComponent<T>::TextListComponent(Window* window) :
|
|||
mColors[1] = 0x00FF00FF;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TextListComponent<T>::~TextListComponent()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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;
|
||||
|
||||
if(size() == 0)
|
||||
{
|
||||
Renderer::setMatrix(trans);
|
||||
font->drawText("The list is empty.", Eigen::Vector2f(0, 0), 0xFF0000FF);
|
||||
return;
|
||||
}
|
||||
|
||||
const int cutoff = 0;
|
||||
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
|
||||
int screenCount = (int)mSize.y() / entrySize;
|
||||
|
||||
if((int)mRowVector.size() >= screenCount)
|
||||
if(size() >= screenCount)
|
||||
{
|
||||
startEntry = mCursor - (int)(screenCount * 0.5);
|
||||
if(startEntry < 0)
|
||||
startEntry = 0;
|
||||
if(startEntry >= (int)mRowVector.size() - screenCount)
|
||||
startEntry = mRowVector.size() - screenCount;
|
||||
if(startEntry >= size() - screenCount)
|
||||
startEntry = size() - screenCount;
|
||||
}
|
||||
|
||||
float y = (float)cutoff;
|
||||
|
||||
if(mRowVector.size() == 0)
|
||||
{
|
||||
font->drawCenteredText("The list is empty.", 0, y, 0xFF0000FF);
|
||||
return;
|
||||
}
|
||||
|
||||
int listCutoff = startEntry + screenCount;
|
||||
if(listCutoff > (int)mRowVector.size())
|
||||
listCutoff = mRowVector.size();
|
||||
if(listCutoff > size())
|
||||
listCutoff = size();
|
||||
|
||||
Eigen::Vector3f dim(getSize().x(), getSize().y(), 0);
|
||||
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);
|
||||
}
|
||||
|
||||
ListRow& row = mRowVector.at((unsigned int)i);
|
||||
Entry& entry = mEntries.at((unsigned int)i);
|
||||
|
||||
unsigned int color;
|
||||
if(mCursor == i && mSelectedColor)
|
||||
color = mSelectedColor;
|
||||
else
|
||||
color = mColors[row.colorId];
|
||||
color = mColors[entry.data.colorId];
|
||||
|
||||
if(!row.textCache)
|
||||
row.textCache = std::unique_ptr<TextCache>(font->buildTextCache(row.name, 0, 0, 0x000000FF));
|
||||
if(!entry.data.textCache)
|
||||
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);
|
||||
|
||||
|
@ -204,12 +170,12 @@ void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans)
|
|||
offset[0] = mHorizontalMargin;
|
||||
break;
|
||||
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)
|
||||
offset[0] = 0;
|
||||
break;
|
||||
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;
|
||||
if(offset[0] < 0)
|
||||
offset[0] = 0;
|
||||
|
@ -224,7 +190,7 @@ void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans)
|
|||
drawTrans.translate(offset);
|
||||
Renderer::setMatrix(drawTrans);
|
||||
|
||||
font->renderTextCache(row.textCache.get());
|
||||
font->renderTextCache(entry.data.textCache.get());
|
||||
|
||||
y += entrySize;
|
||||
}
|
||||
|
@ -237,7 +203,7 @@ void TextListComponent<T>::render(const Eigen::Affine3f& parentTrans)
|
|||
template <typename T>
|
||||
bool TextListComponent<T>::input(InputConfig* config, Input input)
|
||||
{
|
||||
if(mRowVector.size() > 0)
|
||||
if(size() > 0)
|
||||
{
|
||||
if(input.value != 0)
|
||||
{
|
||||
|
@ -279,10 +245,10 @@ template <typename T>
|
|||
void TextListComponent<T>::update(int 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!
|
||||
std::string text = getSelectedName();
|
||||
const std::string& text = mEntries.at((unsigned int)mCursor).name;
|
||||
|
||||
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);
|
||||
|
||||
ListRow row = {name, obj, color};
|
||||
mRowVector.push_back(row);
|
||||
Entry entry;
|
||||
entry.name = name;
|
||||
entry.object = obj;
|
||||
entry.data.colorId = color;
|
||||
static_cast<IList< TextListData, T >*>(this)->add(entry);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TextListComponent<T>::remove(const T& obj)
|
||||
{
|
||||
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)
|
||||
void TextListComponent<T>::onCursorChanged(const CursorState& state)
|
||||
{
|
||||
mMarqueeOffset = 0;
|
||||
mMarqueeTime = -MARQUEE_DELAY;
|
||||
|
@ -377,13 +290,6 @@ void TextListComponent<T>::onCursorChanged(CursorState state)
|
|||
mCursorChangedCallback(state);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TextListComponent<T>::stopScrolling()
|
||||
{
|
||||
listInput(0);
|
||||
onCursorChanged(CURSOR_STOPPED);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
|
||||
{
|
||||
|
|
|
@ -53,14 +53,8 @@ FileData* BasicGameListView::getCursor()
|
|||
|
||||
void BasicGameListView::setCursor(FileData* cursor)
|
||||
{
|
||||
typedef TextListComponent<FileData*>::ListRow Row;
|
||||
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())
|
||||
if(!mList.setCursor(cursor))
|
||||
{
|
||||
mList.setCursor(found);
|
||||
}else{
|
||||
populateList(cursor->getParent()->getChildren());
|
||||
mList.setCursor(cursor);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) :
|
|||
mList.setPosition(mSize.x() * (0.50f + padding), mList.getPosition().y());
|
||||
mList.setSize(mSize.x() * (0.50f - 2*padding), mList.getSize().y());
|
||||
mList.setAlignment(TextListComponent<FileData*>::ALIGN_LEFT);
|
||||
mList.setCursorChangedCallback([&](TextListComponent<FileData*>::CursorState state) { updateInfoPanel(); });
|
||||
mList.setCursorChangedCallback([&](const CursorState& state) { updateInfoPanel(); });
|
||||
|
||||
// image
|
||||
mImage.setOrigin(0.5f, 0.5f);
|
||||
|
@ -179,7 +179,7 @@ void DetailedGameListView::initMDValues()
|
|||
|
||||
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;
|
||||
if(file == NULL)
|
||||
|
|
|
@ -20,14 +20,8 @@ FileData* GridGameListView::getCursor()
|
|||
|
||||
void GridGameListView::setCursor(FileData* file)
|
||||
{
|
||||
typedef ImageGridComponent<FileData*>::Entry Entry;
|
||||
auto& list = mGrid.getList();
|
||||
auto found = std::find_if(list.begin(), list.end(), [&] (const Entry& e) { return (e.object == file); });
|
||||
|
||||
if(found != list.end())
|
||||
if(!mGrid.setCursor(file))
|
||||
{
|
||||
mGrid.setCursor(found);
|
||||
}else{
|
||||
populateList(file->getParent()->getChildren());
|
||||
mGrid.setCursor(file);
|
||||
}
|
||||
|
@ -46,7 +40,7 @@ void GridGameListView::populateList(const std::vector<FileData*>& files)
|
|||
mGrid.clear();
|
||||
for(auto it = files.begin(); it != files.end(); it++)
|
||||
{
|
||||
mGrid.add((*it)->getThumbnailPath(), *it);
|
||||
mGrid.add((*it)->getName(), (*it)->getThumbnailPath(), *it);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue