1 /*
2 Copyright © 2018 Justin Jacobs
3
4 This file is part of FLARE.
5
6 FLARE is free software: you can redistribute it and/or modify it under the terms
7 of the GNU General Public License as published by the Free Software Foundation,
8 either version 3 of the License, or (at your option) any later version.
9
10 FLARE is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
12 PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along with
15 FLARE. If not, see http://www.gnu.org/licenses/
16 */
17
18 /**
19 * class WidgetHorizontalList
20 */
21
22 #include "EngineSettings.h"
23 #include "FontEngine.h"
24 #include "InputState.h"
25 #include "RenderDevice.h"
26 #include "SharedResources.h"
27 #include "TooltipManager.h"
28 #include "WidgetButton.h"
29 #include "WidgetHorizontalList.h"
30
31 const std::string WidgetHorizontalList::DEFAULT_FILE_LEFT = "images/menus/buttons/left.png";
32 const std::string WidgetHorizontalList::DEFAULT_FILE_RIGHT = "images/menus/buttons/right.png";
33
WidgetHorizontalList()34 WidgetHorizontalList::WidgetHorizontalList()
35 : Widget()
36 , button_left(new WidgetButton(DEFAULT_FILE_LEFT))
37 , button_right(new WidgetButton(DEFAULT_FILE_RIGHT))
38 , cursor(0)
39 , changed_without_mouse(false)
40 , enabled(true)
41 {
42 focusable = true;
43 scroll_type = SCROLL_HORIZONTAL;
44 refresh();
45 }
46
47 // void WidgetHorizontalList::activate() {
48 // }
49
setPos(int offset_x,int offset_y)50 void WidgetHorizontalList::setPos(int offset_x, int offset_y) {
51 Widget::setPos(offset_x, offset_y);
52 refresh();
53 }
54
checkClick()55 bool WidgetHorizontalList::checkClick() {
56 return checkClickAt(inpt->mouse.x,inpt->mouse.y);
57 }
58
checkClickAt(int x,int y)59 bool WidgetHorizontalList::checkClickAt(int x, int y) {
60 // enable_tablist_nav = enabled;
61
62 Point mouse(x,y);
63
64 checkTooltip(mouse);
65
66 if (button_left->checkClickAt(mouse.x, mouse.y)) {
67 scrollLeft();
68 return true;
69 }
70 else if (button_right->checkClickAt(mouse.x, mouse.y)) {
71 scrollRight();
72 return true;
73 }
74 else if (changed_without_mouse) {
75 // getNext() or getPrev() was used to change the slider, so treat it as a "click"
76 changed_without_mouse = false;
77 return true;
78 }
79
80
81 return false;
82 }
83
render()84 void WidgetHorizontalList::render() {
85 button_left->local_frame = local_frame;
86 button_left->local_offset = local_offset;
87
88 button_right->local_frame = local_frame;
89 button_right->local_offset = local_offset;
90
91 button_left->render();
92 button_right->render();
93
94 // render label
95 label.local_frame = local_frame;
96 label.local_offset = local_offset;
97 label.render();
98
99 if (in_focus) {
100 Point topLeft;
101 Point bottomRight;
102
103 topLeft.x = pos.x + local_frame.x - local_offset.x;
104 topLeft.y = pos.y + local_frame.y - local_offset.y;
105 bottomRight.x = topLeft.x + pos.w;
106 bottomRight.y = topLeft.y + pos.h;
107
108 // Only draw rectangle if it fits in local frame
109 bool draw = true;
110 if (local_frame.w &&
111 (topLeft.x<local_frame.x || bottomRight.x>(local_frame.x+local_frame.w))) {
112 draw = false;
113 }
114 if (local_frame.h &&
115 (topLeft.y<local_frame.y || bottomRight.y>(local_frame.y+local_frame.h))) {
116 draw = false;
117 }
118 if (draw || 1) {
119 render_device->drawRectangle(topLeft, bottomRight, eset->widgets.selection_rect_color);
120 }
121 }
122 }
123
refresh()124 void WidgetHorizontalList::refresh() {
125 const int text_width = eset->widgets.horizontal_list_text_width;
126 bool is_enabled = !isEmpty() && enabled;
127
128 label.setText(getValue());
129 label.setPos(pos.x + button_left->pos.w + text_width/2, pos.y + button_left->pos.h / 2);
130 label.setMaxWidth(text_width);
131 label.setJustify(FontEngine::JUSTIFY_CENTER);
132 label.setVAlign(LabelInfo::VALIGN_CENTER);
133 label.setColor(is_enabled ? font->getColor(FontEngine::COLOR_WIDGET_NORMAL) : font->getColor(FontEngine::COLOR_WIDGET_DISABLED));
134
135 button_left->setPos(pos.x, pos.y);
136 button_right->setPos(pos.x + button_left->pos.w + text_width, pos.y);
137
138 button_left->enabled = is_enabled;
139 button_right->enabled = is_enabled;
140
141 pos.w = button_left->pos.w + button_right->pos.w + text_width;
142 pos.h = std::max(button_left->pos.h, label.getBounds()->h);
143
144 tooltip_area.x = pos.x + button_left->pos.w;
145 tooltip_area.y = std::min(pos.y, label.getBounds()->y);
146 tooltip_area.w = text_width;
147 tooltip_area.h = std::max(button_left->pos.h, label.getBounds()->h);
148 }
149
checkTooltip(const Point & mouse)150 void WidgetHorizontalList::checkTooltip(const Point& mouse) {
151 if (isEmpty())
152 return;
153
154 if (inpt->usingMouse() && Utils::isWithinRect(tooltip_area, mouse) && !list_items[cursor].tooltip.empty()) {
155 TooltipData tip_data;
156 tip_data.addText(list_items[cursor].tooltip);
157 Point new_mouse(mouse.x + local_frame.x - local_offset.x, mouse.y + local_frame.y - local_offset.y);
158 tooltipm->push(tip_data, new_mouse, TooltipData::STYLE_FLOAT);
159 }
160 }
161
append(const std::string & value,const std::string & tooltip)162 void WidgetHorizontalList::append(const std::string& value, const std::string& tooltip) {
163 HListItem hli;
164 hli.value = value;
165 hli.tooltip = tooltip;
166
167 list_items.push_back(hli);
168 }
169
clear()170 void WidgetHorizontalList::clear() {
171 list_items.clear();
172 }
173
getValue()174 std::string WidgetHorizontalList::getValue() {
175 if (cursor < getSize()) {
176 return list_items[cursor].value;
177 }
178
179 return "";
180 }
181
getSelected()182 unsigned WidgetHorizontalList::getSelected() {
183 if (cursor < getSize())
184 return cursor;
185 else
186 return getSize();
187 }
188
getSize()189 unsigned WidgetHorizontalList::getSize() {
190 return static_cast<unsigned>(list_items.size());
191 }
192
isEmpty()193 bool WidgetHorizontalList::isEmpty() {
194 return list_items.empty();
195 }
196
scrollLeft()197 void WidgetHorizontalList::scrollLeft() {
198 if (isEmpty())
199 return;
200
201 if (cursor == 0)
202 cursor = getSize() - 1;
203 else
204 cursor--;
205
206 refresh();
207 }
208
select(unsigned index)209 void WidgetHorizontalList::select(unsigned index) {
210 if (isEmpty())
211 return;
212
213 if (index < getSize())
214 cursor = index;
215
216 refresh();
217 }
218
scrollRight()219 void WidgetHorizontalList::scrollRight() {
220 if (isEmpty())
221 return;
222
223 if (cursor+1 >= getSize())
224 cursor = 0;
225 else
226 cursor++;
227
228 refresh();
229 }
230
getPrev()231 bool WidgetHorizontalList::getPrev() {
232 if (!isEmpty() && enabled) {
233 scrollLeft();
234 changed_without_mouse = true;
235 }
236 return true;
237 }
238
getNext()239 bool WidgetHorizontalList::getNext() {
240 if (!isEmpty() && enabled) {
241 scrollRight();
242 changed_without_mouse = true;
243 }
244 return true;
245 }
246
~WidgetHorizontalList()247 WidgetHorizontalList::~WidgetHorizontalList() {
248 delete button_left;
249 delete button_right;
250 }
251
252