| [28135] | 1 | /* Copyright (C) 2024 Wildfire Games.
|
|---|
| [27965] | 2 | * This file is part of 0 A.D.
|
|---|
| [6830] | 3 | *
|
|---|
| [27965] | 4 | * 0 A.D. is free software: you can redistribute it and/or modify
|
|---|
| [6830] | 5 | * it under the terms of the GNU General Public License as published by
|
|---|
| 6 | * the Free Software Foundation, either version 2 of the License, or
|
|---|
| 7 | * (at your option) any later version.
|
|---|
| 8 | *
|
|---|
| [27965] | 9 | * 0 A.D. is distributed in the hope that it will be useful,
|
|---|
| [6830] | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 12 | * GNU General Public License for more details.
|
|---|
| 13 | *
|
|---|
| 14 | * You should have received a copy of the GNU General Public License
|
|---|
| [27965] | 15 | * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|---|
| [6830] | 16 | */
|
|---|
| 17 |
|
|---|
| [3802] | 18 | #include "precompiled.h"
|
|---|
| [13521] | 19 |
|
|---|
| [3802] | 20 | #include "CList.h"
|
|---|
| [13521] | 21 |
|
|---|
| [22931] | 22 | #include "gui/CGUI.h"
|
|---|
| [22558] | 23 | #include "gui/CGUIScrollBarVertical.h"
|
|---|
| [23028] | 24 | #include "gui/SettingTypes/CGUIColor.h"
|
|---|
| 25 | #include "gui/SettingTypes/CGUIList.h"
|
|---|
| [13521] | 26 | #include "lib/external_libraries/libsdl.h"
|
|---|
| [22863] | 27 | #include "lib/timer.h"
|
|---|
| [3802] | 28 |
|
|---|
| [23403] | 29 | const CStr CList::EventNameSelectionChange = "SelectionChange";
|
|---|
| 30 | const CStr CList::EventNameHoverChange = "HoverChange";
|
|---|
| 31 | const CStr CList::EventNameMouseLeftClickItem = "MouseLeftClickItem";
|
|---|
| 32 | const CStr CList::EventNameMouseLeftDoubleClickItem = "MouseLeftDoubleClickItem";
|
|---|
| 33 |
|
|---|
| [22741] | 34 | CList::CList(CGUI& pGUI)
|
|---|
| [23005] | 35 | : IGUIObject(pGUI),
|
|---|
| [23020] | 36 | IGUITextOwner(*static_cast<IGUIObject*>(this)),
|
|---|
| 37 | IGUIScrollBarOwner(*static_cast<IGUIObject*>(this)),
|
|---|
| [23005] | 38 | m_Modified(false),
|
|---|
| 39 | m_PrevSelectedItem(-1),
|
|---|
| 40 | m_LastItemClickTime(0),
|
|---|
| [25392] | 41 | m_BufferZone(this, "buffer_zone"),
|
|---|
| 42 | m_Font(this, "font"),
|
|---|
| 43 | m_ScrollBar(this, "scrollbar", false),
|
|---|
| 44 | m_ScrollBarStyle(this, "scrollbar_style"),
|
|---|
| 45 | m_ScrollBottom(this, "scroll_bottom", false),
|
|---|
| 46 | m_SoundDisabled(this, "sound_disabled"),
|
|---|
| 47 | m_SoundSelected(this, "sound_selected"),
|
|---|
| 48 | m_Sprite(this, "sprite"),
|
|---|
| [25587] | 49 | m_SpriteOverlay(this, "sprite_overlay"),
|
|---|
| [25392] | 50 | // Add sprite_disabled! TODO
|
|---|
| 51 | m_SpriteSelectArea(this, "sprite_selectarea"),
|
|---|
| [25587] | 52 | m_SpriteSelectAreaOverlay(this, "sprite_selectarea_overlay"),
|
|---|
| [25392] | 53 | m_TextColor(this, "textcolor"),
|
|---|
| 54 | m_TextColorSelected(this, "textcolor_selected"),
|
|---|
| 55 | m_Selected(this, "selected", -1), // Index selected. -1 is none.
|
|---|
| 56 | m_AutoScroll(this, "auto_scroll", false),
|
|---|
| 57 | m_Hovered(this, "hovered", -1),
|
|---|
| 58 | // Each list item has both a name (in 'list') and an associated data string (in 'list_data')
|
|---|
| 59 | m_List(this, "list"),
|
|---|
| 60 | m_ListData(this, "list_data")
|
|---|
| [3802] | 61 | {
|
|---|
| 62 | // Add scroll-bar
|
|---|
| [25693] | 63 | auto bar = std::make_unique<CGUIScrollBarVertical>(pGUI);
|
|---|
| [3802] | 64 | bar->SetRightAligned(true);
|
|---|
| [25693] | 65 | AddScrollBar(std::move(bar));
|
|---|
| [3802] | 66 | }
|
|---|
| 67 |
|
|---|
| 68 | CList::~CList()
|
|---|
| 69 | {
|
|---|
| 70 | }
|
|---|
| 71 |
|
|---|
| 72 | void CList::SetupText()
|
|---|
| 73 | {
|
|---|
| [24306] | 74 | SetupText(false);
|
|---|
| 75 | }
|
|---|
| 76 |
|
|---|
| 77 | void CList::SetupText(bool append)
|
|---|
| 78 | {
|
|---|
| [12244] | 79 | m_Modified = true;
|
|---|
| [3802] | 80 |
|
|---|
| [24306] | 81 | if (!append)
|
|---|
| 82 | // Delete all generated texts.
|
|---|
| 83 | // TODO: try to be cleverer if we want to update items before the end.
|
|---|
| 84 | m_GeneratedTexts.clear();
|
|---|
| [3802] | 85 |
|
|---|
| 86 | float width = GetListRect().GetWidth();
|
|---|
| [24306] | 87 |
|
|---|
| 88 | bool bottom = false;
|
|---|
| [23005] | 89 | if (m_ScrollBar && GetScrollBar(0).GetStyle())
|
|---|
| [24306] | 90 | {
|
|---|
| 91 | if (m_ScrollBottom && GetScrollBar(0).GetPos() > GetScrollBar(0).GetMaxPos() - 1.5f)
|
|---|
| 92 | bottom = true;
|
|---|
| 93 |
|
|---|
| 94 | // remove scrollbar if applicable
|
|---|
| [3802] | 95 | width -= GetScrollBar(0).GetStyle()->m_Width;
|
|---|
| [24306] | 96 | }
|
|---|
| [3802] | 97 |
|
|---|
| 98 | // Generate texts
|
|---|
| 99 | float buffered_y = 0.f;
|
|---|
| [16931] | 100 |
|
|---|
| [24317] | 101 | if (append && !m_ItemsYPositions.empty())
|
|---|
| [24312] | 102 | buffered_y = m_ItemsYPositions.back();
|
|---|
| [24306] | 103 |
|
|---|
| [25392] | 104 | m_ItemsYPositions.resize(m_List->m_Items.size() + 1);
|
|---|
| [24312] | 105 |
|
|---|
| [25392] | 106 | for (size_t i = append ? m_List->m_Items.size() - 1 : 0; i < m_List->m_Items.size(); ++i)
|
|---|
| [3802] | 107 | {
|
|---|
| [22679] | 108 | CGUIText* text;
|
|---|
| [3802] | 109 |
|
|---|
| [25392] | 110 | if (!m_List->m_Items[i].GetOriginalString().empty())
|
|---|
| 111 | text = &AddText(m_List->m_Items[i], m_Font, width, m_BufferZone);
|
|---|
| [19306] | 112 | else
|
|---|
| 113 | {
|
|---|
| 114 | // Minimum height of a space character of the current font size
|
|---|
| 115 | CGUIString align_string;
|
|---|
| 116 | align_string.SetValue(L" ");
|
|---|
| [23009] | 117 | text = &AddText(align_string, m_Font, width, m_BufferZone);
|
|---|
| [19306] | 118 | }
|
|---|
| [17276] | 119 |
|
|---|
| [3802] | 120 | m_ItemsYPositions[i] = buffered_y;
|
|---|
| [25143] | 121 | buffered_y += text->GetSize().Height;
|
|---|
| [3802] | 122 | }
|
|---|
| 123 |
|
|---|
| [25392] | 124 | m_ItemsYPositions[m_List->m_Items.size()] = buffered_y;
|
|---|
| [3802] | 125 |
|
|---|
| 126 | // Setup scrollbar
|
|---|
| [23005] | 127 | if (m_ScrollBar)
|
|---|
| [3802] | 128 | {
|
|---|
| [16931] | 129 | GetScrollBar(0).SetScrollRange(m_ItemsYPositions.back());
|
|---|
| 130 | GetScrollBar(0).SetScrollSpace(GetListRect().GetHeight());
|
|---|
| [7649] | 131 |
|
|---|
| 132 | CRect rect = GetListRect();
|
|---|
| [16931] | 133 | GetScrollBar(0).SetX(rect.right);
|
|---|
| 134 | GetScrollBar(0).SetY(rect.top);
|
|---|
| 135 | GetScrollBar(0).SetZ(GetBufferedZ());
|
|---|
| 136 | GetScrollBar(0).SetLength(rect.bottom - rect.top);
|
|---|
| [24306] | 137 |
|
|---|
| 138 | if (bottom)
|
|---|
| 139 | GetScrollBar(0).SetPos(GetScrollBar(0).GetMaxPos());
|
|---|
| [3802] | 140 | }
|
|---|
| 141 | }
|
|---|
| 142 |
|
|---|
| [23020] | 143 | void CList::ResetStates()
|
|---|
| 144 | {
|
|---|
| 145 | IGUIObject::ResetStates();
|
|---|
| 146 | IGUIScrollBarOwner::ResetStates();
|
|---|
| 147 | }
|
|---|
| 148 |
|
|---|
| 149 | void CList::UpdateCachedSize()
|
|---|
| 150 | {
|
|---|
| 151 | IGUIObject::UpdateCachedSize();
|
|---|
| 152 | IGUITextOwner::UpdateCachedSize();
|
|---|
| 153 | }
|
|---|
| 154 |
|
|---|
| [16931] | 155 | void CList::HandleMessage(SGUIMessage& Message)
|
|---|
| [3802] | 156 | {
|
|---|
| [23020] | 157 | IGUIObject::HandleMessage(Message);
|
|---|
| [3802] | 158 | IGUIScrollBarOwner::HandleMessage(Message);
|
|---|
| 159 | //IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead!
|
|---|
| 160 |
|
|---|
| [12244] | 161 | m_Modified = false;
|
|---|
| [3802] | 162 | switch (Message.type)
|
|---|
| 163 | {
|
|---|
| 164 | case GUIM_SETTINGS_UPDATED:
|
|---|
| 165 | if (Message.value == "list")
|
|---|
| 166 | SetupText();
|
|---|
| 167 |
|
|---|
| 168 | // If selected is changed, call "SelectionChange"
|
|---|
| 169 | if (Message.value == "selected")
|
|---|
| 170 | {
|
|---|
| 171 | // TODO: Check range
|
|---|
| 172 |
|
|---|
| [23005] | 173 | if (m_AutoScroll)
|
|---|
| [20958] | 174 | UpdateAutoScroll();
|
|---|
| 175 |
|
|---|
| [23403] | 176 | ScriptEvent(EventNameSelectionChange);
|
|---|
| [3802] | 177 | }
|
|---|
| 178 |
|
|---|
| [7649] | 179 | if (Message.value == "scrollbar")
|
|---|
| [3802] | 180 | SetupText();
|
|---|
| 181 |
|
|---|
| 182 | // Update scrollbar
|
|---|
| [7649] | 183 | if (Message.value == "scrollbar_style")
|
|---|
| [3802] | 184 | {
|
|---|
| [23005] | 185 | GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
|
|---|
| [3802] | 186 | SetupText();
|
|---|
| 187 | }
|
|---|
| 188 |
|
|---|
| 189 | break;
|
|---|
| 190 |
|
|---|
| 191 | case GUIM_MOUSE_PRESS_LEFT:
|
|---|
| 192 | {
|
|---|
| [23005] | 193 | if (!m_Enabled)
|
|---|
| [13521] | 194 | {
|
|---|
| [23005] | 195 | PlaySound(m_SoundDisabled);
|
|---|
| [7649] | 196 | break;
|
|---|
| [13521] | 197 | }
|
|---|
| [7649] | 198 |
|
|---|
| [19588] | 199 | int hovered = GetHoveredItem();
|
|---|
| 200 | if (hovered == -1)
|
|---|
| 201 | break;
|
|---|
| [25392] | 202 | m_Selected.Set(hovered, true);
|
|---|
| [19588] | 203 | UpdateAutoScroll();
|
|---|
| [23005] | 204 | PlaySound(m_SoundSelected);
|
|---|
| [3802] | 205 |
|
|---|
| [19588] | 206 | if (timer_Time() - m_LastItemClickTime < SELECT_DBLCLICK_RATE && hovered == m_PrevSelectedItem)
|
|---|
| [23403] | 207 | this->SendMouseEvent(GUIM_MOUSE_DBLCLICK_LEFT_ITEM, EventNameMouseLeftDoubleClickItem);
|
|---|
| [19841] | 208 | else
|
|---|
| [23403] | 209 | this->SendMouseEvent(GUIM_MOUSE_PRESS_LEFT_ITEM, EventNameMouseLeftClickItem);
|
|---|
| [19841] | 210 |
|
|---|
| [19588] | 211 | m_LastItemClickTime = timer_Time();
|
|---|
| 212 | m_PrevSelectedItem = hovered;
|
|---|
| 213 | break;
|
|---|
| 214 | }
|
|---|
| [13521] | 215 |
|
|---|
| [19588] | 216 | case GUIM_MOUSE_LEAVE:
|
|---|
| 217 | {
|
|---|
| [23005] | 218 | if (m_Hovered == -1)
|
|---|
| [19588] | 219 | break;
|
|---|
| [17274] | 220 |
|
|---|
| [25392] | 221 | m_Hovered.Set(-1, true);
|
|---|
| [23403] | 222 | ScriptEvent(EventNameHoverChange);
|
|---|
| [14458] | 223 | break;
|
|---|
| 224 | }
|
|---|
| [3802] | 225 |
|
|---|
| [19588] | 226 | case GUIM_MOUSE_OVER:
|
|---|
| 227 | {
|
|---|
| 228 | int hovered = GetHoveredItem();
|
|---|
| [23005] | 229 | if (hovered == m_Hovered)
|
|---|
| [19588] | 230 | break;
|
|---|
| 231 |
|
|---|
| [25392] | 232 | m_Hovered.Set(hovered, true);
|
|---|
| [23403] | 233 | ScriptEvent(EventNameHoverChange);
|
|---|
| [19588] | 234 | break;
|
|---|
| 235 | }
|
|---|
| 236 |
|
|---|
| [3802] | 237 | case GUIM_LOAD:
|
|---|
| [16931] | 238 | {
|
|---|
| [23005] | 239 | GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
|
|---|
| [3802] | 240 | break;
|
|---|
| [16931] | 241 | }
|
|---|
| [3802] | 242 |
|
|---|
| 243 | default:
|
|---|
| 244 | break;
|
|---|
| 245 | }
|
|---|
| 246 |
|
|---|
| 247 | IGUITextOwner::HandleMessage(Message);
|
|---|
| 248 | }
|
|---|
| 249 |
|
|---|
| [24215] | 250 | InReaction CList::ManuallyHandleKeys(const SDL_Event_* ev)
|
|---|
| [3802] | 251 | {
|
|---|
| [15909] | 252 | InReaction result = IN_PASS;
|
|---|
| [3802] | 253 |
|
|---|
| [15909] | 254 | if (ev->ev.type == SDL_KEYDOWN)
|
|---|
| [3802] | 255 | {
|
|---|
| [15909] | 256 | int szChar = ev->ev.key.keysym.sym;
|
|---|
| [3802] | 257 |
|
|---|
| [15909] | 258 | switch (szChar)
|
|---|
| 259 | {
|
|---|
| 260 | case SDLK_HOME:
|
|---|
| 261 | SelectFirstElement();
|
|---|
| 262 | UpdateAutoScroll();
|
|---|
| 263 | result = IN_HANDLED;
|
|---|
| 264 | break;
|
|---|
| [3802] | 265 |
|
|---|
| [15909] | 266 | case SDLK_END:
|
|---|
| 267 | SelectLastElement();
|
|---|
| 268 | UpdateAutoScroll();
|
|---|
| 269 | result = IN_HANDLED;
|
|---|
| 270 | break;
|
|---|
| [3802] | 271 |
|
|---|
| [15909] | 272 | case SDLK_UP:
|
|---|
| 273 | SelectPrevElement();
|
|---|
| 274 | UpdateAutoScroll();
|
|---|
| 275 | result = IN_HANDLED;
|
|---|
| 276 | break;
|
|---|
| [3802] | 277 |
|
|---|
| [15909] | 278 | case SDLK_DOWN:
|
|---|
| 279 | SelectNextElement();
|
|---|
| 280 | UpdateAutoScroll();
|
|---|
| 281 | result = IN_HANDLED;
|
|---|
| 282 | break;
|
|---|
| [3802] | 283 |
|
|---|
| [15909] | 284 | case SDLK_PAGEUP:
|
|---|
| 285 | GetScrollBar(0).ScrollMinusPlenty();
|
|---|
| 286 | result = IN_HANDLED;
|
|---|
| 287 | break;
|
|---|
| [3802] | 288 |
|
|---|
| [15909] | 289 | case SDLK_PAGEDOWN:
|
|---|
| 290 | GetScrollBar(0).ScrollPlusPlenty();
|
|---|
| 291 | result = IN_HANDLED;
|
|---|
| 292 | break;
|
|---|
| 293 |
|
|---|
| 294 | default: // Do nothing
|
|---|
| 295 | result = IN_PASS;
|
|---|
| 296 | }
|
|---|
| [3802] | 297 | }
|
|---|
| 298 |
|
|---|
| [15909] | 299 | return result;
|
|---|
| [3802] | 300 | }
|
|---|
| 301 |
|
|---|
| [25591] | 302 | void CList::Draw(CCanvas2D& canvas)
|
|---|
| [3802] | 303 | {
|
|---|
| [25591] | 304 | DrawList(canvas, m_Selected, m_Sprite, m_SpriteOverlay, m_SpriteSelectArea, m_SpriteSelectAreaOverlay, m_TextColor);
|
|---|
| [3802] | 305 | }
|
|---|
| 306 |
|
|---|
| [25591] | 307 | void CList::DrawList(CCanvas2D& canvas, const int& selected, const CGUISpriteInstance& sprite, const CGUISpriteInstance& spriteOverlay,
|
|---|
| [25587] | 308 | const CGUISpriteInstance& spriteSelectArea, const CGUISpriteInstance& spriteSelectAreaOverlay, const CGUIColor& textColor)
|
|---|
| [3802] | 309 | {
|
|---|
| [25524] | 310 | CRect rect = GetListRect();
|
|---|
| [3802] | 311 |
|
|---|
| [25591] | 312 | m_pGUI.DrawSprite(sprite, canvas, rect);
|
|---|
| [3802] | 313 |
|
|---|
| [25524] | 314 | float scroll = 0.f;
|
|---|
| 315 | if (m_ScrollBar)
|
|---|
| 316 | scroll = GetScrollBar(0).GetPos();
|
|---|
| [3802] | 317 |
|
|---|
| [25587] | 318 | bool drawSelected = false;
|
|---|
| 319 | CRect rectSel;
|
|---|
| [25524] | 320 | if (selected >= 0 && selected+1 < (int)m_ItemsYPositions.size())
|
|---|
| 321 | {
|
|---|
| 322 | // Get rectangle of selection:
|
|---|
| [25587] | 323 | rectSel = CRect(
|
|---|
| [25524] | 324 | rect.left, rect.top + m_ItemsYPositions[selected] - scroll,
|
|---|
| 325 | rect.right, rect.top + m_ItemsYPositions[selected+1] - scroll);
|
|---|
| [3802] | 326 |
|
|---|
| [25587] | 327 | if (rectSel.top <= rect.bottom &&
|
|---|
| 328 | rectSel.bottom >= rect.top)
|
|---|
| [3802] | 329 | {
|
|---|
| [25587] | 330 | if (rectSel.bottom > rect.bottom)
|
|---|
| 331 | rectSel.bottom = rect.bottom;
|
|---|
| 332 | if (rectSel.top < rect.top)
|
|---|
| 333 | rectSel.top = rect.top;
|
|---|
| [25524] | 334 | if (m_ScrollBar)
|
|---|
| [3802] | 335 | {
|
|---|
| [25524] | 336 | // Remove any overlapping area of the scrollbar.
|
|---|
| [25587] | 337 | if (rectSel.right > GetScrollBar(0).GetOuterRect().left &&
|
|---|
| 338 | rectSel.right <= GetScrollBar(0).GetOuterRect().right)
|
|---|
| 339 | rectSel.right = GetScrollBar(0).GetOuterRect().left;
|
|---|
| [3802] | 340 |
|
|---|
| [25587] | 341 | if (rectSel.left >= GetScrollBar(0).GetOuterRect().left &&
|
|---|
| 342 | rectSel.left < GetScrollBar(0).GetOuterRect().right)
|
|---|
| 343 | rectSel.left = GetScrollBar(0).GetOuterRect().right;
|
|---|
| [25524] | 344 | }
|
|---|
| [3802] | 345 |
|
|---|
| [25591] | 346 | m_pGUI.DrawSprite(spriteSelectArea, canvas, rectSel);
|
|---|
| [25587] | 347 | drawSelected = true;
|
|---|
| [3802] | 348 | }
|
|---|
| [25524] | 349 | }
|
|---|
| [3802] | 350 |
|
|---|
| [25524] | 351 | for (size_t i = 0; i < m_List->m_Items.size(); ++i)
|
|---|
| 352 | {
|
|---|
| 353 | if (m_ItemsYPositions[i+1] - scroll < 0 ||
|
|---|
| 354 | m_ItemsYPositions[i] - scroll > rect.GetHeight())
|
|---|
| 355 | continue;
|
|---|
| [3802] | 356 |
|
|---|
| [25524] | 357 | // Clipping area (we'll have to substract the scrollbar)
|
|---|
| 358 | CRect cliparea = GetListRect();
|
|---|
| [3802] | 359 |
|
|---|
| [25524] | 360 | if (m_ScrollBar)
|
|---|
| 361 | {
|
|---|
| 362 | if (cliparea.right > GetScrollBar(0).GetOuterRect().left &&
|
|---|
| 363 | cliparea.right <= GetScrollBar(0).GetOuterRect().right)
|
|---|
| 364 | cliparea.right = GetScrollBar(0).GetOuterRect().left;
|
|---|
| [3802] | 365 |
|
|---|
| [25524] | 366 | if (cliparea.left >= GetScrollBar(0).GetOuterRect().left &&
|
|---|
| 367 | cliparea.left < GetScrollBar(0).GetOuterRect().right)
|
|---|
| 368 | cliparea.left = GetScrollBar(0).GetOuterRect().right;
|
|---|
| 369 | }
|
|---|
| [3802] | 370 |
|
|---|
| [28135] | 371 | const CGUIColor& finalTextColor = (drawSelected && static_cast<size_t>(selected) == i && *m_TextColorSelected) ? m_TextColorSelected : textColor;
|
|---|
| 372 |
|
|---|
| 373 | DrawText(canvas, i, finalTextColor, rect.TopLeft() - CVector2D(0.f, scroll - m_ItemsYPositions[i]), cliparea);
|
|---|
| [3802] | 374 | }
|
|---|
| [25303] | 375 |
|
|---|
| [25587] | 376 | // Draw scrollbars on top of the content
|
|---|
| [25303] | 377 | if (m_ScrollBar)
|
|---|
| [25591] | 378 | IGUIScrollBarOwner::Draw(canvas);
|
|---|
| [25587] | 379 |
|
|---|
| 380 | // Draw the overlays last
|
|---|
| [25591] | 381 | m_pGUI.DrawSprite(spriteOverlay, canvas, rect);
|
|---|
| [25587] | 382 | if (drawSelected)
|
|---|
| [25591] | 383 | m_pGUI.DrawSprite(spriteSelectAreaOverlay, canvas, rectSel);
|
|---|
| [3802] | 384 | }
|
|---|
| 385 |
|
|---|
| [24306] | 386 | void CList::AddItem(const CGUIString& str, const CGUIString& data)
|
|---|
| [3802] | 387 | {
|
|---|
| [22693] | 388 | // Do not send a settings-changed message
|
|---|
| [25392] | 389 | m_List.GetMutable().m_Items.push_back(str);
|
|---|
| 390 | m_ListData.GetMutable().m_Items.push_back(data);
|
|---|
| [22693] | 391 |
|
|---|
| [24312] | 392 | SetupText(true);
|
|---|
| [3802] | 393 | }
|
|---|
| 394 |
|
|---|
| [25225] | 395 | void CList::AddItem(const CGUIString& strAndData)
|
|---|
| 396 | {
|
|---|
| 397 | AddItem(strAndData, strAndData);
|
|---|
| 398 | }
|
|---|
| 399 |
|
|---|
| [25378] | 400 | bool CList::HandleAdditionalChildren(const XMBData& xmb, const XMBElement& child)
|
|---|
| [3802] | 401 | {
|
|---|
| [25378] | 402 | int elmt_item = xmb.GetElementID("item");
|
|---|
| [3802] | 403 |
|
|---|
| [5017] | 404 | if (child.GetNodeName() == elmt_item)
|
|---|
| [3802] | 405 | {
|
|---|
| [24306] | 406 | CGUIString vlist;
|
|---|
| 407 | vlist.SetValue(child.GetText().FromUTF8());
|
|---|
| 408 | AddItem(vlist, vlist);
|
|---|
| [3802] | 409 | return true;
|
|---|
| 410 | }
|
|---|
| [16931] | 411 |
|
|---|
| 412 | return false;
|
|---|
| [3802] | 413 | }
|
|---|
| 414 |
|
|---|
| 415 | void CList::SelectNextElement()
|
|---|
| 416 | {
|
|---|
| [25392] | 417 | if (m_Selected != static_cast<int>(m_List->m_Items.size()) - 1)
|
|---|
| [3802] | 418 | {
|
|---|
| [25392] | 419 | m_Selected.Set(m_Selected + 1, true);
|
|---|
| [23005] | 420 | PlaySound(m_SoundSelected);
|
|---|
| [3802] | 421 | }
|
|---|
| 422 | }
|
|---|
| [16931] | 423 |
|
|---|
| [3802] | 424 | void CList::SelectPrevElement()
|
|---|
| 425 | {
|
|---|
| [23005] | 426 | if (m_Selected > 0)
|
|---|
| [3802] | 427 | {
|
|---|
| [25392] | 428 | m_Selected.Set(m_Selected - 1, true);
|
|---|
| [23005] | 429 | PlaySound(m_SoundSelected);
|
|---|
| [3802] | 430 | }
|
|---|
| 431 | }
|
|---|
| 432 |
|
|---|
| 433 | void CList::SelectFirstElement()
|
|---|
| 434 | {
|
|---|
| [23005] | 435 | if (m_Selected >= 0)
|
|---|
| [25392] | 436 | m_Selected.Set(0, true);
|
|---|
| [3802] | 437 | }
|
|---|
| [16931] | 438 |
|
|---|
| [3802] | 439 | void CList::SelectLastElement()
|
|---|
| 440 | {
|
|---|
| [25392] | 441 | const int index = static_cast<int>(m_List->m_Items.size()) - 1;
|
|---|
| [3802] | 442 |
|
|---|
| [23005] | 443 | if (m_Selected != index)
|
|---|
| [25392] | 444 | m_Selected.Set(index, true);
|
|---|
| [3802] | 445 | }
|
|---|
| 446 |
|
|---|
| 447 | void CList::UpdateAutoScroll()
|
|---|
| 448 | {
|
|---|
| 449 | // No scrollbar, no scrolling (at least it's not made to work properly).
|
|---|
| [23005] | 450 | if (!m_ScrollBar || m_Selected < 0 || static_cast<std::size_t>(m_Selected) >= m_ItemsYPositions.size())
|
|---|
| [3802] | 451 | return;
|
|---|
| 452 |
|
|---|
| [22693] | 453 | float scroll = GetScrollBar(0).GetPos();
|
|---|
| [3802] | 454 |
|
|---|
| 455 | // Check upper boundary
|
|---|
| [23005] | 456 | if (m_ItemsYPositions[m_Selected] < scroll)
|
|---|
| [3802] | 457 | {
|
|---|
| [23005] | 458 | GetScrollBar(0).SetPos(m_ItemsYPositions[m_Selected]);
|
|---|
| [3802] | 459 | return; // this means, if it wants to align both up and down at the same time
|
|---|
| 460 | // this will have precedence.
|
|---|
| 461 | }
|
|---|
| 462 |
|
|---|
| 463 | // Check lower boundary
|
|---|
| [18935] | 464 | CRect rect = GetListRect();
|
|---|
| [23005] | 465 | if (m_ItemsYPositions[m_Selected+1]-rect.GetHeight() > scroll)
|
|---|
| 466 | GetScrollBar(0).SetPos(m_ItemsYPositions[m_Selected+1]-rect.GetHeight());
|
|---|
| [3802] | 467 | }
|
|---|
| [19588] | 468 |
|
|---|
| 469 | int CList::GetHoveredItem()
|
|---|
| 470 | {
|
|---|
| [23005] | 471 | const float scroll = m_ScrollBar ? GetScrollBar(0).GetPos() : 0.f;
|
|---|
| [19588] | 472 |
|
|---|
| [22641] | 473 | const CRect& rect = GetListRect();
|
|---|
| [25152] | 474 | CVector2D mouse = m_pGUI.GetMousePos();
|
|---|
| 475 | mouse.Y += scroll;
|
|---|
| [19588] | 476 |
|
|---|
| 477 | // Mouse is over scrollbar
|
|---|
| [23005] | 478 | if (m_ScrollBar && GetScrollBar(0).IsVisible() &&
|
|---|
| [25152] | 479 | mouse.X >= GetScrollBar(0).GetOuterRect().left &&
|
|---|
| 480 | mouse.X <= GetScrollBar(0).GetOuterRect().right)
|
|---|
| [19588] | 481 | return -1;
|
|---|
| 482 |
|
|---|
| [25392] | 483 | for (size_t i = 0; i < m_List->m_Items.size(); ++i)
|
|---|
| [25152] | 484 | if (mouse.Y >= rect.top + m_ItemsYPositions[i] &&
|
|---|
| 485 | mouse.Y < rect.top + m_ItemsYPositions[i + 1])
|
|---|
| [19588] | 486 | return i;
|
|---|
| 487 |
|
|---|
| 488 | return -1;
|
|---|
| 489 | }
|
|---|