2020-09-21 17:17:34 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-06-06 14:48:05 +00:00
|
|
|
//
|
2020-09-21 17:17:34 +00:00
|
|
|
// EmulationStation Desktop Edition
|
2020-06-21 12:25:28 +00:00
|
|
|
// ComponentList.h
|
2020-06-06 14:48:05 +00:00
|
|
|
//
|
2020-06-21 12:25:28 +00:00
|
|
|
// Used to lay out and navigate lists in GUI menus.
|
2020-06-06 14:48:05 +00:00
|
|
|
//
|
|
|
|
|
2017-10-31 17:12:50 +00:00
|
|
|
#ifndef ES_CORE_COMPONENTS_COMPONENT_LIST_H
|
|
|
|
#define ES_CORE_COMPONENTS_COMPONENT_LIST_H
|
2014-03-01 21:02:44 +00:00
|
|
|
|
|
|
|
#include "IList.h"
|
|
|
|
|
2020-06-06 14:48:05 +00:00
|
|
|
struct ComponentListElement {
|
2021-07-07 18:31:46 +00:00
|
|
|
ComponentListElement(const std::shared_ptr<GuiComponent>& cmp = nullptr,
|
|
|
|
bool resize_w = true,
|
|
|
|
bool inv = true)
|
|
|
|
: component(cmp)
|
|
|
|
, resize_width(resize_w)
|
|
|
|
, invert_when_selected(inv)
|
|
|
|
{
|
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
std::shared_ptr<GuiComponent> component;
|
|
|
|
bool resize_width;
|
|
|
|
bool invert_when_selected;
|
2014-03-01 21:02:44 +00:00
|
|
|
};
|
|
|
|
|
2021-07-07 18:31:46 +00:00
|
|
|
struct ComponentListRow {
|
2020-06-21 12:25:28 +00:00
|
|
|
std::vector<ComponentListElement> elements;
|
|
|
|
|
|
|
|
// The input handler is called when the user enters any input while this row is
|
|
|
|
// highlighted (including up/down).
|
|
|
|
// Return false to let the list try to use it or true if the input has been consumed.
|
|
|
|
// If no input handler is supplied (input_handler == nullptr), the default behavior is
|
|
|
|
// to forward the input to the rightmost element in the currently selected row.
|
|
|
|
std::function<bool(InputConfig*, Input)> input_handler;
|
|
|
|
|
2021-07-07 18:31:46 +00:00
|
|
|
void addElement(const std::shared_ptr<GuiComponent>& component,
|
|
|
|
bool resize_width,
|
|
|
|
bool invert_when_selected = true)
|
2020-06-21 12:25:28 +00:00
|
|
|
{
|
|
|
|
elements.push_back(ComponentListElement(component, resize_width, invert_when_selected));
|
|
|
|
}
|
|
|
|
|
2020-07-15 15:44:27 +00:00
|
|
|
// Utility function for making an input handler for "when the users presses A on this, do func".
|
2021-07-07 18:31:46 +00:00
|
|
|
void makeAcceptInputHandler(const std::function<void()>& func)
|
2020-06-21 12:25:28 +00:00
|
|
|
{
|
|
|
|
input_handler = [func](InputConfig* config, Input input) -> bool {
|
2020-07-13 18:58:25 +00:00
|
|
|
if (config->isMappedTo("a", input) && input.value != 0) {
|
2020-06-21 12:25:28 +00:00
|
|
|
func();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
}
|
2014-03-01 21:02:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class ComponentList : public IList<ComponentListRow, void*>
|
|
|
|
{
|
|
|
|
public:
|
2022-01-19 17:01:54 +00:00
|
|
|
ComponentList();
|
2014-03-01 21:02:44 +00:00
|
|
|
|
2021-10-10 16:15:37 +00:00
|
|
|
enum ScrollIndicator {
|
2022-06-05 10:36:55 +00:00
|
|
|
SCROLL_NONE,
|
2021-10-10 16:15:37 +00:00
|
|
|
SCROLL_UP,
|
|
|
|
SCROLL_UP_DOWN,
|
|
|
|
SCROLL_DOWN
|
|
|
|
};
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
void addRow(const ComponentListRow& row, bool setCursorHere = false);
|
2014-03-01 21:02:44 +00:00
|
|
|
|
2020-12-16 22:59:00 +00:00
|
|
|
void textInput(const std::string& text) override;
|
2020-06-21 12:25:28 +00:00
|
|
|
bool input(InputConfig* config, Input input) override;
|
|
|
|
void update(int deltaTime) override;
|
2021-08-15 17:30:31 +00:00
|
|
|
void render(const glm::mat4& parentTrans) override;
|
2022-01-18 16:40:47 +00:00
|
|
|
std::vector<HelpPrompt> getHelpPrompts() override;
|
2014-03-01 21:02:44 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
void onSizeChanged() override;
|
2021-07-07 18:31:46 +00:00
|
|
|
void onFocusGained() override { mFocused = true; }
|
|
|
|
void onFocusLost() override { mFocused = false; }
|
2014-03-12 03:00:08 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
bool moveCursor(int amt);
|
2021-07-07 18:31:46 +00:00
|
|
|
int getCursorId() const { return mCursor; }
|
2019-08-25 15:23:02 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
float getTotalRowHeight() const;
|
2021-07-07 18:31:46 +00:00
|
|
|
float getRowHeight(int row) const { return getRowHeight(mEntries.at(row).data); }
|
2014-03-12 23:24:34 +00:00
|
|
|
|
2021-10-18 17:24:47 +00:00
|
|
|
// Horizontal looping for row content that doesn't fit on-screen.
|
2022-01-15 18:28:41 +00:00
|
|
|
void setLoopRows(bool state)
|
|
|
|
{
|
|
|
|
stopLooping();
|
|
|
|
mLoopRows = state;
|
|
|
|
}
|
2021-10-18 17:24:47 +00:00
|
|
|
void stopLooping()
|
|
|
|
{
|
|
|
|
mLoopOffset = 0;
|
|
|
|
mLoopOffset2 = 0;
|
|
|
|
mLoopTime = 0;
|
|
|
|
}
|
|
|
|
|
2021-10-15 18:58:40 +00:00
|
|
|
void resetScrollIndicatorStatus()
|
|
|
|
{
|
|
|
|
mScrollIndicatorStatus = SCROLL_NONE;
|
|
|
|
if (mScrollIndicatorChangedCallback != nullptr)
|
2021-10-16 11:21:52 +00:00
|
|
|
mScrollIndicatorChangedCallback(mScrollIndicatorStatus, false);
|
2021-10-15 18:58:40 +00:00
|
|
|
}
|
|
|
|
|
2021-07-07 18:31:46 +00:00
|
|
|
void setCursorChangedCallback(const std::function<void(CursorState state)>& callback)
|
|
|
|
{
|
|
|
|
mCursorChangedCallback = callback;
|
|
|
|
}
|
|
|
|
const std::function<void(CursorState state)>& getCursorChangedCallback() const
|
|
|
|
{
|
|
|
|
return mCursorChangedCallback;
|
|
|
|
}
|
2021-10-10 16:15:37 +00:00
|
|
|
void setScrollIndicatorChangedCallback(
|
2021-10-16 11:21:52 +00:00
|
|
|
const std::function<void(ScrollIndicator state, bool singleRowScroll)>& callback)
|
2021-10-10 16:15:37 +00:00
|
|
|
{
|
|
|
|
mScrollIndicatorChangedCallback = callback;
|
|
|
|
}
|
2014-03-24 22:55:36 +00:00
|
|
|
|
2014-03-01 21:02:44 +00:00
|
|
|
protected:
|
2020-06-21 12:25:28 +00:00
|
|
|
void onCursorChanged(const CursorState& state) override;
|
2014-03-01 21:02:44 +00:00
|
|
|
|
|
|
|
private:
|
2022-03-14 18:51:48 +00:00
|
|
|
Renderer* mRenderer;
|
2020-06-21 12:25:28 +00:00
|
|
|
bool mFocused;
|
2021-10-10 16:15:37 +00:00
|
|
|
bool mSetupCompleted;
|
|
|
|
bool mBottomCameraOffset;
|
2021-10-16 11:21:52 +00:00
|
|
|
bool mSingleRowScroll;
|
2014-03-12 03:00:08 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
void updateCameraOffset();
|
|
|
|
void updateElementPosition(const ComponentListRow& row);
|
|
|
|
void updateElementSize(const ComponentListRow& row);
|
2019-08-25 15:23:02 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
float getRowHeight(const ComponentListRow& row) const;
|
2014-03-23 00:48:48 +00:00
|
|
|
|
2021-07-02 15:44:27 +00:00
|
|
|
float mHorizontalPadding;
|
2020-06-21 12:25:28 +00:00
|
|
|
float mSelectorBarOffset;
|
|
|
|
float mCameraOffset;
|
2014-03-24 22:55:36 +00:00
|
|
|
|
2021-10-18 17:24:47 +00:00
|
|
|
bool mLoopRows;
|
|
|
|
bool mLoopScroll;
|
|
|
|
int mLoopOffset;
|
|
|
|
int mLoopOffset2;
|
|
|
|
int mLoopTime;
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
std::function<void(CursorState state)> mCursorChangedCallback;
|
2021-10-16 11:21:52 +00:00
|
|
|
std::function<void(ScrollIndicator state, bool singleRowScroll)>
|
|
|
|
mScrollIndicatorChangedCallback;
|
2021-10-10 16:15:37 +00:00
|
|
|
|
|
|
|
ScrollIndicator mScrollIndicatorStatus;
|
2014-03-01 21:02:44 +00:00
|
|
|
};
|
2017-10-31 17:12:50 +00:00
|
|
|
|
|
|
|
#endif // ES_CORE_COMPONENTS_COMPONENT_LIST_H
|