Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CList.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2013 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
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  *
9  * 0 A.D. is distributed in the hope that it will be useful,
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
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*
19 CList
20 */
21 
22 #include "precompiled.h"
23 
24 #include "CList.h"
25 
26 #include "CGUIScrollBarVertical.h"
27 
29 #include "ps/CLogger.h"
31 
32 
33 //-------------------------------------------------------------------
34 // Constructor / Destructor
35 //-------------------------------------------------------------------
37  m_Modified(false)
38 {
39  // Add sprite_disabled! TODO
40 
41  AddSetting(GUIST_float, "buffer_zone");
42  //AddSetting(GUIST_CGUIString, "caption"); will it break removing this? If I know my system, then no, but test just in case TODO (Gee).
43  AddSetting(GUIST_CStrW, "font");
44  AddSetting(GUIST_bool, "scrollbar");
45  AddSetting(GUIST_CStr, "scrollbar_style");
46  AddSetting(GUIST_CStrW, "sound_disabled");
47  AddSetting(GUIST_CStrW, "sound_selected");
48  AddSetting(GUIST_CGUISpriteInstance, "sprite");
49  AddSetting(GUIST_CGUISpriteInstance, "sprite_selectarea");
50  AddSetting(GUIST_int, "cell_id");
51  AddSetting(GUIST_EAlign, "text_align");
52  AddSetting(GUIST_CColor, "textcolor");
53  AddSetting(GUIST_CColor, "textcolor_selected");
54  AddSetting(GUIST_int, "selected"); // Index selected. -1 is none.
55  AddSetting(GUIST_CStrW, "tooltip");
56  AddSetting(GUIST_CStr, "tooltip_style");
57  // Each list item has both a name (in 'list') and an associated data string (in 'list_data')
58  AddSetting(GUIST_CGUIList, "list");
59  AddSetting(GUIST_CGUIList, "list_data"); // TODO: this should be a list of raw strings, not of CGUIStrings
60 
61  GUI<bool>::SetSetting(this, "scrollbar", false);
62 
63  // Nothing is selected as default.
64  GUI<int>::SetSetting(this, "selected", -1);
65 
66  // Add scroll-bar
68  bar->SetRightAligned(true);
69  bar->SetUseEdgeButtons(true);
70  AddScrollBar(bar);
71 }
72 
74 {
75 }
76 
78 {
79  if (!GetGUI())
80  return;
81 
82  m_Modified = true;
83  CGUIList *pList;
84  GUI<CGUIList>::GetSettingPointer(this, "list", pList);
85 
86  //ENSURE(m_GeneratedTexts.size()>=1);
87 
88  m_ItemsYPositions.resize( pList->m_Items.size()+1 );
89 
90  // Delete all generated texts. Some could probably be saved,
91  // but this is easier, and this function will never be called
92  // continuously, or even often, so it'll probably be okay.
93  std::vector<SGUIText*>::iterator it;
94  for (it=m_GeneratedTexts.begin(); it!=m_GeneratedTexts.end(); ++it)
95  {
96  if (*it)
97  delete *it;
98  }
99  m_GeneratedTexts.clear();
100 
101  CStrW font;
102  if (GUI<CStrW>::GetSetting(this, "font", font) != PSRETURN_OK || font.empty())
103  // Use the default if none is specified
104  // TODO Gee: (2004-08-14) Don't define standard like this. Do it with the default style.
105  font = L"default";
106 
107  //CGUIString caption;
108  bool scrollbar;
109  //GUI<CGUIString>::GetSetting(this, "caption", caption);
110  GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
111 
112  float width = GetListRect().GetWidth();
113  // remove scrollbar if applicable
114  if (scrollbar && GetScrollBar(0).GetStyle())
115  width -= GetScrollBar(0).GetStyle()->m_Width;
116 
117  float buffer_zone=0.f;
118  GUI<float>::GetSetting(this, "buffer_zone", buffer_zone);
119 
120  // Generate texts
121  float buffered_y = 0.f;
122 
123  for (int i=0; i<(int)pList->m_Items.size(); ++i)
124  {
125  // Create a new SGUIText. Later on, input it using AddText()
126  SGUIText *text = new SGUIText();
127 
128  *text = GetGUI()->GenerateText(pList->m_Items[i], font, width, buffer_zone, this);
129 
130  m_ItemsYPositions[i] = buffered_y;
131  buffered_y += text->m_Size.cy;
132 
133  AddText(text);
134  }
135 
136  m_ItemsYPositions[pList->m_Items.size()] = buffered_y;
137 
138  //if (! scrollbar)
139  // CalculateTextPosition(m_CachedActualSize, m_TextPos, *m_GeneratedTexts[0]);
140 
141  // Setup scrollbar
142  if (scrollbar)
143  {
145  GetScrollBar(0).SetScrollSpace( GetListRect().GetHeight() );
146 
147  CRect rect = GetListRect();
148  GetScrollBar(0).SetX( rect.right );
149  GetScrollBar(0).SetY( rect.top );
151  GetScrollBar(0).SetLength( rect.bottom - rect.top );
152  }
153 }
154 
156 {
158  //IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead!
159 
160  m_Modified = false;
161  switch (Message.type)
162  {
164  if (Message.value == "list")
165  {
166  SetupText();
167  }
168 
169  // If selected is changed, call "SelectionChange"
170  if (Message.value == "selected")
171  {
172  // TODO: Check range
173 
174  // TODO only works if lower-case, shouldn't it be made case sensitive instead?
175  ScriptEvent("selectionchange");
176  }
177 
178  if (Message.value == "scrollbar")
179  {
180  SetupText();
181  }
182 
183  // Update scrollbar
184  if (Message.value == "scrollbar_style")
185  {
186  CStr scrollbar_style;
187  GUI<CStr>::GetSetting(this, Message.value, scrollbar_style);
188 
189  GetScrollBar(0).SetScrollBarStyle( scrollbar_style );
190 
191  SetupText();
192  }
193 
194  break;
195 
197  {
198  bool enabled;
199  GUI<bool>::GetSetting(this, "enabled", enabled);
200  if (!enabled)
201  {
202  CStrW soundPath;
203  if (g_SoundManager && GUI<CStrW>::GetSetting(this, "sound_disabled", soundPath) == PSRETURN_OK && !soundPath.empty())
204  g_SoundManager->PlayAsUI(soundPath.c_str(), false);
205  break;
206  }
207 
208  bool scrollbar;
209  CGUIList *pList;
210  GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
211  GUI<CGUIList>::GetSettingPointer(this, "list", pList);
212  float scroll=0.f;
213  if (scrollbar)
214  {
215  scroll = GetScrollBar(0).GetPos();
216  }
217 
218  CRect rect = GetListRect();
219  CPos mouse = GetMousePos();
220  mouse.y += scroll;
221  int set=-1;
222  for (int i=0; i<(int)pList->m_Items.size(); ++i)
223  {
224  if (mouse.y >= rect.top + m_ItemsYPositions[i] &&
225  mouse.y < rect.top + m_ItemsYPositions[i+1] &&
226  // mouse is not over scroll-bar
227  !(mouse.x >= GetScrollBar(0).GetOuterRect().left &&
228  mouse.x <= GetScrollBar(0).GetOuterRect().right))
229  {
230  set = i;
231  }
232  }
233 
234  if (set != -1)
235  {
236  GUI<int>::SetSetting(this, "selected", set);
238 
239  CStrW soundPath;
240  if (g_SoundManager && GUI<CStrW>::GetSetting(this, "sound_selected", soundPath) == PSRETURN_OK && !soundPath.empty())
241  g_SoundManager->PlayAsUI(soundPath.c_str(), false);
242  }
243  } break;
244 
246  {
248  // Since the scroll was changed, let's simulate a mouse movement
249  // to check if scrollbar now is hovered
251  HandleMessage(msg);
252  break;
253  }
254  case GUIM_MOUSE_WHEEL_UP:
255  {
257  // Since the scroll was changed, let's simulate a mouse movement
258  // to check if scrollbar now is hovered
260  HandleMessage(msg);
261  break;
262  }
263  case GUIM_LOAD:
264  {
265  CStr scrollbar_style;
266  GUI<CStr>::GetSetting(this, "scrollbar_style", scrollbar_style);
267  GetScrollBar(0).SetScrollBarStyle( scrollbar_style );
268  }
269  break;
270 
271  default:
272  break;
273  }
274 
276 }
277 
279 {
280  int szChar = ev->ev.key.keysym.sym;
281 
282  switch (szChar)
283  {
284  case SDLK_HOME:
287  break;
288 
289  case SDLK_END:
292  break;
293 
294  case SDLK_UP:
297  break;
298 
299  case SDLK_DOWN:
302  break;
303 
304  case SDLK_PAGEUP:
306  break;
307 
308  case SDLK_PAGEDOWN:
310  break;
311 
312  default: // Do nothing
313  return IN_PASS;
314  }
315 
316  return IN_HANDLED;
317 }
318 
319 void CList::Draw()
320 {
321  int selected;
322  GUI<int>::GetSetting(this, "selected", selected);
323 
324  DrawList(selected, "sprite", "sprite_selectarea", "textcolor");
325 }
326 
327 void CList::DrawList(const int &selected,
328  const CStr& _sprite,
329  const CStr& _sprite_selected,
330  const CStr& _textcolor)
331 {
332  float bz = GetBufferedZ();
333 
334  // First call draw on ScrollBarOwner
335  bool scrollbar;
336  GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
337 
338  if (scrollbar)
339  {
340  // Draw scrollbar
342  }
343 
344  if (GetGUI())
345  {
346  CRect rect = GetListRect();
347 
348  CGUISpriteInstance *sprite=NULL, *sprite_selectarea=NULL;
349  int cell_id;
350  GUI<CGUISpriteInstance>::GetSettingPointer(this, _sprite, sprite);
351  GUI<CGUISpriteInstance>::GetSettingPointer(this, _sprite_selected, sprite_selectarea);
352  GUI<int>::GetSetting(this, "cell_id", cell_id);
353 
354  CGUIList *pList;
355  GUI<CGUIList>::GetSettingPointer(this, "list", pList);
356 
357  GetGUI()->DrawSprite(*sprite, cell_id, bz, rect);
358 
359  float scroll=0.f;
360  if (scrollbar)
361  {
362  scroll = GetScrollBar(0).GetPos();
363  }
364 
365  if (selected != -1)
366  {
367  ENSURE(selected >= 0 && selected+1 < (int)m_ItemsYPositions.size());
368 
369  // Get rectangle of selection:
370  CRect rect_sel(rect.left, rect.top + m_ItemsYPositions[selected] - scroll,
371  rect.right, rect.top + m_ItemsYPositions[selected+1] - scroll);
372 
373  if (rect_sel.top <= rect.bottom &&
374  rect_sel.bottom >= rect.top)
375  {
376  if (rect_sel.bottom > rect.bottom)
377  rect_sel.bottom = rect.bottom;
378  if (rect_sel.top < rect.top)
379  rect_sel.top = rect.top;
380 
381  if (scrollbar)
382  {
383  // Remove any overlapping area of the scrollbar.
384  if (rect_sel.right > GetScrollBar(0).GetOuterRect().left &&
385  rect_sel.right <= GetScrollBar(0).GetOuterRect().right)
386  rect_sel.right = GetScrollBar(0).GetOuterRect().left;
387 
388  if (rect_sel.left >= GetScrollBar(0).GetOuterRect().left &&
389  rect_sel.left < GetScrollBar(0).GetOuterRect().right)
390  rect_sel.left = GetScrollBar(0).GetOuterRect().right;
391  }
392 
393  GetGUI()->DrawSprite(*sprite_selectarea, cell_id, bz+0.05f, rect_sel);
394  }
395  }
396 
397  CColor color;
398  GUI<CColor>::GetSetting(this, _textcolor, color);
399 
400  for (int i=0; i<(int)pList->m_Items.size(); ++i)
401  {
402  if (m_ItemsYPositions[i+1] - scroll < 0 ||
403  m_ItemsYPositions[i] - scroll > rect.GetHeight())
404  continue;
405 
406  // Clipping area (we'll have to substract the scrollbar)
407  CRect cliparea = GetListRect();
408 
409  if (scrollbar)
410  {
411  if (cliparea.right > GetScrollBar(0).GetOuterRect().left &&
412  cliparea.right <= GetScrollBar(0).GetOuterRect().right)
413  cliparea.right = GetScrollBar(0).GetOuterRect().left;
414 
415  if (cliparea.left >= GetScrollBar(0).GetOuterRect().left &&
416  cliparea.left < GetScrollBar(0).GetOuterRect().right)
417  cliparea.left = GetScrollBar(0).GetOuterRect().right;
418  }
419 
420  DrawText(i, color, rect.TopLeft() - CPos(0.f, scroll - m_ItemsYPositions[i]), bz+0.1f, cliparea);
421  }
422  }
423 }
424 
425 void CList::AddItem(const CStrW& str, const CStrW& data)
426 {
427  CGUIList *pList, *pListData;
428  GUI<CGUIList>::GetSettingPointer(this, "list", pList);
429  GUI<CGUIList>::GetSettingPointer(this, "list_data", pListData);
430 
431  CGUIString gui_string;
432  gui_string.SetValue(str);
433  pList->m_Items.push_back( gui_string );
434 
435  CGUIString data_string;
436  data_string.SetValue(data);
437  pListData->m_Items.push_back( data_string );
438 
439  // TODO Temp
440  SetupText();
441 }
442 
444 {
445  int elmt_item = pFile->GetElementID("item");
446 
447  if (child.GetNodeName() == elmt_item)
448  {
449  AddItem(child.GetText().FromUTF8(), child.GetText().FromUTF8());
450 
451  return true;
452  }
453  else
454  {
455  return false;
456  }
457 }
458 
460 {
461  int selected;
462  GUI<int>::GetSetting(this, "selected", selected);
463 
464  CGUIList *pList;
465  GUI<CGUIList>::GetSettingPointer(this, "list", pList);
466 
467  if (selected != (int)pList->m_Items.size()-1)
468  {
469  ++selected;
470  GUI<int>::SetSetting(this, "selected", selected);
471 
472  CStrW soundPath;
473  if (g_SoundManager && GUI<CStrW>::GetSetting(this, "sound_selected", soundPath) == PSRETURN_OK && !soundPath.empty())
474  g_SoundManager->PlayAsUI(soundPath.c_str(), false);
475  }
476 }
477 
479 {
480  int selected;
481  GUI<int>::GetSetting(this, "selected", selected);
482 
483  if (selected != 0)
484  {
485  --selected;
486  GUI<int>::SetSetting(this, "selected", selected);
487 
488  CStrW soundPath;
489  if (g_SoundManager && GUI<CStrW>::GetSetting(this, "sound_selected", soundPath) == PSRETURN_OK && !soundPath.empty())
490  g_SoundManager->PlayAsUI(soundPath.c_str(), false);
491  }
492 }
493 
495 {
496  int selected;
497  GUI<int>::GetSetting(this, "selected", selected);
498 
499  if (selected != 0)
500  {
501  GUI<int>::SetSetting(this, "selected", 0);
502  }
503 }
504 
506 {
507  int selected;
508  GUI<int>::GetSetting(this, "selected", selected);
509 
510  CGUIList *pList;
511  GUI<CGUIList>::GetSettingPointer(this, "list", pList);
512 
513  if (selected != (int)pList->m_Items.size()-1)
514  {
515  GUI<int>::SetSetting(this, "selected", (int)pList->m_Items.size()-1);
516  }
517 }
518 
520 {
521  int selected;
522  bool scrollbar;
523  float scroll;
524  GUI<int>::GetSetting(this, "selected", selected);
525  GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
526 
527  CRect rect = GetListRect();
528 
529  // No scrollbar, no scrolling (at least it's not made to work properly).
530  if (!scrollbar)
531  return;
532 
533  scroll = GetScrollBar(0).GetPos();
534 
535  // Check upper boundary
536  if (m_ItemsYPositions[selected] < scroll)
537  {
538  GetScrollBar(0).SetPos(m_ItemsYPositions[selected]);
539  return; // this means, if it wants to align both up and down at the same time
540  // this will have precedence.
541  }
542 
543  // Check lower boundary
544  if (m_ItemsYPositions[selected+1]-rect.GetHeight() > scroll)
545  {
546  GetScrollBar(0).SetPos(m_ItemsYPositions[selected+1]-rect.GetHeight());
547  }
548 }
void SetScrollRange(float range)
Set content length.
void SetUseEdgeButtons(bool b)
Set use edge buttons.
void DrawSprite(const CGUISpriteInstance &Sprite, int CellID, const float &Z, const CRect &Rect, const CRect &Clipping=CRect())
Draw GUI Sprite.
Definition: CGUI.cpp:467
CStr value
Optional data.
Definition: GUIbase.h:127
virtual InReaction ManuallyHandleEvent(const SDL_Event_ *ev)
Handle events manually to catch keyboard inputting.
Definition: CList.cpp:278
SDL_KeyboardEvent key
Definition: wsdl.h:305
void DrawList(const int &selected, const CStr &_sprite, const CStr &_sprite_selected, const CStr &_textcolor)
Definition: CList.cpp:327
const PSRETURN PSRETURN_OK
Definition: Errors.h:103
float top
Definition: Overlay.h:159
void ScriptEvent(const CStr &Action)
Execute the script for a particular action.
Definition: IGUIObject.cpp:480
void SetZ(float z)
Set Z Position.
ISoundManager * g_SoundManager
Definition: Overlay.h:34
float m_Width
Width of bar, also both sides of the edge buttons.
Definition: IGUIScrollBar.h:67
virtual IGUIScrollBar & GetScrollBar(const int &index)
Get Scroll Bar reference (it should be transparent it&#39;s actually pointers).
int GetElementID(const char *Name) const
Definition: XeroXMB.cpp:104
float left
Returning CPos representing each corner.
Definition: Overlay.h:159
void SetY(float y)
Set Y Position.
static PSRETURN GetSetting(const IGUIObject *pObject, const CStr &Setting, T &Value)
Retrieves a setting by name from object pointer.
Definition: GUIutil.cpp:344
virtual void AddItem(const CStrW &str, const CStrW &data)
Adds an item last to the list.
Definition: CList.cpp:425
virtual void PlayAsUI(const VfsPath &itemPath, bool looping)=0
void SetupText()
Sets up text, should be called every time changes has been made that can change the visual...
Definition: CList.cpp:77
void SetLength(float length)
Set Length of scroll bar.
virtual void HandleMessage(SGUIMessage &Message)
Definition: CList.cpp:155
virtual void AddScrollBar(IGUIScrollBar *scrollbar)
Add a scroll-bar.
virtual void Draw()
Draws the List box.
Definition: CList.cpp:319
virtual float GetBufferedZ() const
Returns not the Z value, but the actual buffered Z value, i.e.
Definition: IGUIObject.cpp:406
float GetWidth() const
Definition: Overlay.cpp:232
virtual void Draw()
Draws the object.
SDL_Event ev
Definition: libsdl.h:56
Includes static functions that needs one template argument.
Definition: GUIutil.h:103
void SetX(float x)
Set X Position.
virtual void ScrollPlus()
Increase scroll one step.
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
CStr8 GetText() const
Definition: XeroXMB.cpp:196
virtual void ScrollMinus()
Decrease scroll one step.
CList()
Definition: CList.cpp:36
InReaction
Definition: input.h:34
Definition: input.h:40
CSize m_Size
Width and height of the whole output, used when setting up scrollbars and such.
Definition: GUItext.h:162
std::vector< float > m_ItemsYPositions
List of each element&#39;s relative y position.
Definition: CList.h:144
virtual void HandleMessage(SGUIMessage &Message)
std::vector< CGUIString > m_Items
List of items (as text), the post-processed result is stored in the IGUITextOwner structure of this c...
Definition: CGUIList.h:33
Vertical implementation of IGUIScrollBar.
void AddSetting(const EGUISettingType &Type, const CStr &Name)
Add a setting to m_Settings.
Definition: IGUIObject.cpp:172
void SetScrollBarStyle(const CStr &style)
Set Scroll bar style string.
void SetValue(const CStrW &str)
Set the value, the string will automatically be parsed when set.
Definition: GUItext.cpp:303
Made to represent screen positions and delta values.
Definition: Overlay.h:167
void SetScrollSpace(float space)
Set space that is visible in the scrollable control.
float GetPos() const
Get scroll-position.
virtual ~CList()
Definition: CList.cpp:73
float right
Definition: Overlay.h:159
CPos GetMousePos() const
Get Mouse from CGUI.
Definition: IGUIObject.cpp:207
virtual CRect GetListRect() const
Definition: CList.h:129
virtual void DrawText(int index, const CColor &color, const CPos &pos, float z, const CRect &clipping=CRect())
Draws the Text.
CGUI * GetGUI()
Definition: IGUIObject.h:388
void SetRightAligned(const bool &align)
Set Right Aligned.
virtual void ScrollMinusPlenty()
Decrease scroll three steps.
static PSRETURN SetSetting(IGUIObject *pObject, const CStr &Setting, const T &Value, const bool &SkipMessage=false)
Sets a value by name using a real datatype as input.
Definition: GUIutil.cpp:366
virtual void SelectNextElement()
Easy select elements functions.
Definition: CList.cpp:459
float y
Definition: Overlay.h:195
virtual void SetPos(float f)
Set scroll-position by hand.
float GetHeight() const
Definition: Overlay.cpp:237
SDL_keysym keysym
Definition: wsdl.h:196
virtual CRect GetOuterRect() const =0
Get the rectangle of the outline of the scrollbar, every component of the scroll-bar should be inside...
const SGUIScrollBarStyle * GetStyle() const
Get style used by the scrollbar.
virtual void SelectLastElement()
Definition: CList.cpp:505
virtual void ScrollPlusPlenty()
Increase scroll three steps.
virtual void SelectFirstElement()
Definition: CList.cpp:494
virtual bool HandleAdditionalChildren(const XMBElement &child, CXeromyces *pFile)
Handle the &lt;item&gt; tag.
Definition: CList.cpp:443
float cy
Definition: Overlay.h:234
std::vector< SGUIText * > m_GeneratedTexts
Texts that are generated and ready to be rendered.
Message send to IGUIObject::HandleMessage() in order to give life to Objects manually with a derived ...
Definition: GUIbase.h:106
EGUIMessageType type
Describes what the message regards.
Definition: GUIbase.h:122
float bottom
Definition: Overlay.h:159
virtual void HandleMessage(SGUIMessage &Message)
SDLKey sym
Definition: wsdl.h:188
float x
Position.
Definition: Overlay.h:195
void AddText(SGUIText *text)
Adds a text object.
void UpdateAutoScroll()
Definition: CList.cpp:519
String class, substitute for CStr, but that parses the tags and builds up a list of all text that wil...
Definition: GUItext.h:176
SGUIText GenerateText(const CGUIString &Text, const CStrW &Font, const float &Width, const float &BufferZone, const IGUIObject *pObject=NULL)
Generate a SGUIText object from the inputted string.
Definition: CGUI.cpp:644
bool m_Modified
Definition: CList.h:148
virtual void SelectPrevElement()
Definition: CList.cpp:478
CPos TopLeft() const
Get Position equivalent to top/left corner.
Definition: Overlay.cpp:247
static PSRETURN GetSettingPointer(const IGUIObject *pObject, const CStr &Setting, T *&Value)
Definition: GUIutil.cpp:317
An SGUIText object is a parsed string, divided into text-rendering components.
Definition: GUItext.h:62
int GetNodeName() const
Definition: XeroXMB.cpp:166
Rectangle class used for screen rectangles.
Definition: Overlay.h:71