Skip to content

Commit

Permalink
WidgetHorizontalList: Can now display 2 or fewer options at once
Browse files Browse the repository at this point in the history
This is a better solution for players not using gamepads (i.e. most
players), as it removes the need to cycle through the options with the
arrow buttons.
  • Loading branch information
dorkster committed Aug 14, 2023
1 parent 430ea86 commit 29d4dd5
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 28 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.txt
Expand Up @@ -5,6 +5,7 @@ Engine features:
* Add wander_radius and waypoints support for map NPCs
* Add scaling based on item level/player level/primary stats to several Item attributes, such as 'bonus' and 'price'.
* Add 'loot_drops_max' property to Items for limiting the number of drops in a single loot event.
* Horizontal list widgets can now display 2 or fewer options at once

Engine fixes:

Expand Down
1 change: 1 addition & 0 deletions src/MenuConfig.cpp
Expand Up @@ -301,6 +301,7 @@ MenuConfig::MenuConfig (bool _is_game_state)
keybinds_lb.push_back(new WidgetLabel());
keybinds_lstb.push_back(new WidgetHorizontalList());
keybinds_lstb.back()->has_action = true;
keybinds_lstb.back()->max_visible_actions = 1;
}

// set up loot tooltip setting
Expand Down
2 changes: 1 addition & 1 deletion src/Version.cpp
Expand Up @@ -30,7 +30,7 @@ FLARE. If not, see http://www.gnu.org/licenses/

#include <SDL.h>

Version VersionInfo::ENGINE(1, 14, 21);
Version VersionInfo::ENGINE(1, 14, 22);
Version VersionInfo::MIN(0, 0, 0);
Version VersionInfo::MAX(USHRT_MAX, USHRT_MAX, USHRT_MAX);

Expand Down
111 changes: 86 additions & 25 deletions src/WidgetHorizontalList.cpp
Expand Up @@ -35,15 +35,22 @@ WidgetHorizontalList::WidgetHorizontalList()
: Widget()
, button_left(new WidgetButton(DEFAULT_FILE_LEFT))
, button_right(new WidgetButton(DEFAULT_FILE_RIGHT))
, button_action(new WidgetButton(WidgetButton::DEFAULT_FILE))
, cursor(0)
, changed_without_mouse(false)
, action_triggered(false)
, activated(false)
, enabled(true)
, has_action(false)
, max_visible_actions(2)
{
scroll_type = SCROLL_HORIZONTAL;
// we want the dimensions of a regular button, so load a temporary one here
WidgetButton *temp = new WidgetButton(WidgetButton::DEFAULT_FILE);
if (temp) {
action_button_size.x = temp->pos.w;
action_button_size.y = temp->pos.h;
delete temp;
}

refresh();
}

Expand Down Expand Up @@ -79,13 +86,20 @@ bool WidgetHorizontalList::checkClickAt(int x, int y) {
changed_without_mouse = false;
return true;
}
else if (has_action && button_action->checkClickAt(mouse.x, mouse.y)) {
action_triggered = true;
return true;
}
else if (has_action && activated) {
activated = false;
button_action->activate();
list_items[cursor].button->activate();
}
else if (has_action) {
size_t start,end;
getVisibleButtonRange(start, end);
for (size_t i = start; i < end; ++i) {
if (list_items[i].button->checkClickAt(mouse.x, mouse.y)) {
cursor = static_cast<unsigned>(i);
action_triggered = true;
return true;
}
}
}

return false;
Expand All @@ -110,13 +124,19 @@ void WidgetHorizontalList::render() {
button_right->local_frame = local_frame;
button_right->local_offset = local_offset;

button_left->render();
button_right->render();
if (!multipleActionsVisible()) {
button_left->render();
button_right->render();
}

if (has_action) {
button_action->local_frame = local_frame;
button_action->local_offset = local_offset;
button_action->render();
size_t start,end;
getVisibleButtonRange(start, end);
for (size_t i = start; i < end; ++i) {
list_items[i].button->local_frame = local_frame;
list_items[i].button->local_offset = local_offset;
list_items[i].button->render();
}
}
else {
// render label
Expand Down Expand Up @@ -149,34 +169,54 @@ void WidgetHorizontalList::render() {
}
}
else if (in_focus && has_action && enabled) {
button_action->in_focus = true;
for (size_t i = 0; i < list_items.size(); ++i) {
list_items[i].button->in_focus = (cursor == i ? true : false);
}
}
else {
button_action->in_focus = false;
if (has_action) {
for (size_t i = 0; i < list_items.size(); ++i) {
list_items[i].button->in_focus = false;
}
}
}
}

void WidgetHorizontalList::refresh() {
scroll_type = multipleActionsVisible() ? SCROLL_VERTICAL : SCROLL_HORIZONTAL;

int content_width = eset->widgets.horizontal_list_text_width;
bool is_enabled = !isEmpty() && enabled;

button_left->enabled = is_enabled;
button_right->enabled = is_enabled;
button_action->enabled = is_enabled;
button_left->enabled = is_enabled && !multipleActionsVisible();
button_right->enabled = is_enabled && !multipleActionsVisible();

button_left->setPos(pos.x, pos.y);

if (has_action) {
content_width = button_action->pos.w;
content_width = action_button_size.x;

button_action->setPos(pos.x + button_left->pos.w, pos.y + (button_left->pos.h / 2) - (button_action->pos.h / 2));
for (size_t i = 0; i < list_items.size(); ++i) {
list_items[i].button->enabled = is_enabled;

button_action->setLabel(getValue());
if (cursor < list_items.size()) {
button_action->tooltip = list_items[cursor].tooltip;
}
int y_offset = pos.y + (button_left->pos.h / 2);
if (multipleActionsVisible()) {
int action_count = static_cast<int>(std::min(max_visible_actions, list_items.size()));
y_offset += (-action_button_size.y * action_count / 2) + action_button_size.y * static_cast<int>(i);
}
else {
y_offset += (-action_button_size.y / 2);
}

pos.h = std::max(button_left->pos.h, button_action->pos.h);
list_items[i].button->setPos(pos.x + button_left->pos.w, y_offset);

list_items[i].button->setLabel(list_items[i].value);
if (cursor < list_items.size()) {
list_items[i].button->tooltip = list_items[i].tooltip;
}

pos.h = std::max(button_left->pos.h, list_items[i].button->pos.h);
}
}
else {
label.setText(getValue());
Expand Down Expand Up @@ -219,10 +259,16 @@ void WidgetHorizontalList::append(const std::string& value, const std::string& t
hli.value = value;
hli.tooltip = tooltip;

// these get deleted when calling clear()
hli.button = new WidgetButton(WidgetButton::DEFAULT_FILE);

list_items.push_back(hli);
}

void WidgetHorizontalList::clear() {
for (size_t i = 0; i < list_items.size(); ++i) {
delete list_items[i].button;
}
list_items.clear();
cursor = 0;
}
Expand Down Expand Up @@ -306,9 +352,24 @@ bool WidgetHorizontalList::getNext() {
return true;
}

bool WidgetHorizontalList::multipleActionsVisible() {
return has_action && max_visible_actions > 1 && max_visible_actions >= list_items.size();
}

void WidgetHorizontalList::getVisibleButtonRange(size_t& start, size_t& end) {
if (!multipleActionsVisible()) {
start = cursor;
end = cursor+1;
}
else {
start = 0;
end = list_items.size();
}
}

WidgetHorizontalList::~WidgetHorizontalList() {
clear();
delete button_left;
delete button_right;
delete button_action;
}

10 changes: 8 additions & 2 deletions src/WidgetHorizontalList.h
Expand Up @@ -35,26 +35,31 @@ class WidgetHorizontalList : public Widget {

class HListItem {
public:
HListItem() {}
HListItem()
: button(NULL)
{}
~HListItem() {}

std::string value;
std::string tooltip;
WidgetButton *button;
};

void checkTooltip(const Point& mouse);
void getVisibleButtonRange(size_t& start, size_t& end);
bool multipleActionsVisible();

WidgetLabel label;
WidgetButton *button_left;
WidgetButton *button_right;
WidgetButton *button_action;

unsigned cursor;
bool changed_without_mouse;
bool action_triggered;
bool activated;
std::vector<HListItem> list_items;
Rect tooltip_area;
Point action_button_size;

public:
explicit WidgetHorizontalList();
Expand Down Expand Up @@ -86,6 +91,7 @@ class WidgetHorizontalList : public Widget {

bool enabled;
bool has_action;
size_t max_visible_actions;
};

#endif

0 comments on commit 29d4dd5

Please sign in to comment.