xoreos  0.0.5
gridbox.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include <cassert>
26 
27 #include "src/common/util.h"
28 
29 #include "src/graphics/graphics.h"
30 
32 
35 
36 namespace Engines {
37 
38 namespace NWN {
39 
41  const Common::UString &model, float innerHSpace, float innerVSpace) :
42  WidgetListBox(gui, tag, model), _innerHSpace(innerHSpace),
43  _innerVSpace(innerVSpace) {
44 }
45 
47 }
48 
50  if (widget.getTag().endsWith("#Up")) {
51  scrollUp(1);
52  return;
53  }
54 
55  if (widget.getTag().endsWith("#Down")) {
56  scrollDown(1);
57  return;
58  }
59 
60  if (widget.getTag().endsWith("#Bar")) {
61  if (_itemsByRow == 0)
62  return;
63 
64  // Round up
65  const size_t rowCount = (_items.size() + (_itemsByRow - 1)) / _itemsByRow;
66  const size_t visibleRow = (_visibleItems.size() + (_itemsByRow - 1)) / _itemsByRow;
67 
68  const ptrdiff_t maxStartRow = rowCount - visibleRow;
69  if (maxStartRow <= 0)
70  return;
71 
72  const size_t startRow = _scrollbar->getState() * maxStartRow;
73  const size_t startItem = startRow * _itemsByRow;
74 
75  if (startItem == _startItem)
76  return;
77 
78  _startItem = startItem;
79  updateVisible();
80  return;
81  }
82 
83  WidgetListItem *listItem = dynamic_cast<WidgetListItem *>(&widget);
84  if (listItem) {
85  if (_selectedItem != listItem->getItemNumber()) {
86  _selectedItem = listItem->getItemNumber();
87  setActive(true);
88  playSound("gui_button", Sound::kSoundTypeSFX);
89  }
90  }
91 }
92 
93 void WidgetGridBox::mouseDown(uint8 UNUSED(state), float x, float y) {
94  if (isDisabled() || _visibleItems.empty())
95  return;
96 
97  float wX, wY, wZ;
98  getPosition(wX, wY, wZ);
99 
100  // Check if we clicked on the scrollbar area
101  if (_scrollbar) {
102  if (x > (wX + getWidth() - 20)) {
103  size_t scroll = _visibleItems.size() / _itemsByRow;
104  if (y > _scrollbar->getBarPosition())
105  scrollUp(scroll);
106  else
107  scrollDown(scroll);
108 
109  return;
110  }
111  }
112 }
113 
115  assert(_locked);
116  _locked = false;
117 
118  if (_items.empty()) {
119  GfxMan.unlockFrame();
120  return;
121  }
122 
123  _itemsByRow = MIN<size_t>(_contentWidth / _items.front()->getWidth(), _items.size());
124 
125  const size_t itemsByColumn = MIN<size_t>(_contentHeight / _items.front()->getHeight(), _items.size());
126 
127  const size_t vCount = MIN<size_t>(_itemsByRow * itemsByColumn, _items.size() - _startItem);
128 
129  if ((vCount == 0) || (vCount == _visibleItems.size())) {
130  GfxMan.unlockFrame();
131  return;
132  }
133 
134  assert(_visibleItems.size() < vCount);
135  _visibleItems.reserve(vCount);
136 
137  size_t start = _startItem + _visibleItems.size();
138 
139  const float itemHeight = _items.front()->getHeight();
140  const float itemWidth = _items.front()->getWidth();
141 
142  size_t row = 0, column = 0;
143 
144  while (_visibleItems.size() < vCount) {
145  WidgetListItem *item = _items[start++];
146 
147  // WORKAROUND: The x axis is shifted by 2 pixels in order to correctly render in
148  // the charportrait widget.
149  float itemY = _contentY - (row + 1) * (itemHeight + _innerVSpace) + _innerVSpace;
150  float itemX = _contentX + (column * (itemWidth + _innerHSpace)) - 2.0f;
151  item->setPosition(itemX, itemY, _contentZ - 5.0f);
152  _visibleItems.push_back(item);
153 
154  if (isVisible())
155  _visibleItems.back()->show();
156 
157  ++column;
158 
159  if (column == _itemsByRow) {
160  ++row;
161  column = 0;
162  }
163  }
164 
167 
168  GfxMan.unlockFrame();
169 }
170 
172  if (!_scrollbar)
173  return;
174 
175  if (_visibleItems.empty())
176  _scrollbar->setLength(1.0f);
177  else {
178  _scrollbar->setLength(((float) _visibleItems.size()) / (_items.size() + (_items.size() % _itemsByRow)));
179  }
180 }
181 
183  if (_visibleItems.empty())
184  return;
185 
186  GfxMan.lockFrame();
187 
188  for (size_t i = 0; i < _visibleItems.size(); i++)
189  _visibleItems[i]->hide();
190 
191  if (_visibleItems.size() > _items.size())
192  _visibleItems.resize(_items.size());
193 
194  const float itemHeight = _items.front()->getHeight() + _innerVSpace;
195  const float itemWidth = _items.front()->getWidth() + _innerHSpace;
196 
197  const size_t count = MIN<size_t>(_visibleItems.size(), _items.size() - _startItem);
198 
199  float itemY = _contentY - itemHeight + _innerVSpace;
200 
201  for (size_t i = 0, column = 0; i < count; i++, column++) {
202  WidgetListItem *item = _items[_startItem + i];
203 
204  if (column == _itemsByRow) {
205  itemY -= itemHeight;
206  column = 0;
207  }
208 
209  // WORKAROUND: The x axis is shifted by 2 pixels in order to correctly render in
210  // the charportrait widget.
211  item->setPosition(_contentX + column * itemWidth - 2.0f, itemY, _contentZ - 5.0f);
212  _visibleItems[i] = item;
213 
214  if (isVisible())
215  _visibleItems[i]->show();
216  }
217 
218  GfxMan.unlockFrame();
219 }
220 
221 void WidgetGridBox::scrollUp(size_t n) {
222  if (_visibleItems.empty())
223  return;
224 
225  if (_startItem == 0)
226  return;
227 
228  _startItem -= MIN<size_t>(n * _itemsByRow, _startItem);
229 
230  updateVisible();
232 }
233 
235  if (_visibleItems.empty())
236  return;
237 
238  if (_startItem + _visibleItems.size() >= _items.size())
239  return;
240 
241 
242  _startItem += MIN<size_t>(n * _itemsByRow, (_items.size() + _items.size() %
243  _itemsByRow) - _visibleItems.size() - _startItem);
244 
245  updateVisible();
247 }
248 
249 } // End of namespace NWN
250 
251 } // End of namespace Engines
The global graphics manager.
A class holding an UTF-8 string.
Definition: ustring.h:48
size_t getItemNumber() const
Definition: listbox.cpp:101
uint8_t uint8
Definition: types.h:200
void setActive(bool active)
The widget&#39;s active state.
Definition: widget.cpp:268
virtual void getPosition(float &x, float &y, float &z) const
Get the widget&#39;s position.
Definition: widget.cpp:140
bool endsWith(const UString &with) const
Definition: ustring.cpp:315
void subActive(Widget &widget)
A sub-widget was activated.
Definition: gridbox.cpp:49
WidgetGridBox(::Engines::GUI &gui, const Common::UString &tag, const Common::UString &model, float innerHSpace=0.0f, float InnerVSpace=0.0f)
Definition: gridbox.cpp:40
void scrollDown(size_t n)
Definition: gridbox.cpp:234
bool isVisible() const
Is the widget visible?
Definition: widget.cpp:59
void setLength(float length)
Set the length of the scrollbar, as a fraction of the range.
Definition: scrollbar.cpp:281
void hide()
Hide the widget.
Definition: listbox.cpp:332
An item widget within a NWN listbox widget.
Definition: listbox.h:51
std::vector< WidgetListItem * > _items
Definition: listbox.h:187
A GUI.
Definition: gui.h:43
float getState() const
Get the current state, as a fraction of the range.
Definition: scrollbar.cpp:297
WidgetScrollbar * _scrollbar
Definition: listbox.h:194
virtual void updateScrollbarPosition()
Definition: listbox.cpp:549
#define UNUSED(x)
Definition: system.h:170
Utility templates and functions.
const Common::UString & getTag() const
Get the widget&#39;s tag.
Definition: widget.cpp:45
void mouseDown(uint8 state, float x, float y)
A mouse button was pressed on the widget.
Definition: gridbox.cpp:93
A NWN listbox widget.
Definition: listbox.h:116
void setPosition(float x, float y, float z)
Set the widget&#39;s position.
Definition: nwnwidget.cpp:60
Sound::ChannelHandle playSound(const Common::UString &sound, Sound::SoundType soundType, bool loop, float volume, bool pitchVariance)
Play this sound resource.
Definition: util.cpp:81
A widget in a GUI.
Definition: widget.h:40
A NWN scrollbar model and widget.
bool isDisabled() const
Is the widget disabled?
Definition: widget.cpp:63
float getWidth() const
Get the widget&#39;s width.
Definition: modelwidget.cpp:78
Sound effect.
Definition: types.h:45
Generic Aurora engines utility functions.
void scrollUp(size_t n)
Definition: gridbox.cpp:221
std::vector< WidgetListItem * > _visibleItems
Definition: listbox.h:188
#define GfxMan
Shortcut for accessing the graphics manager.
Definition: graphics.h:299
A NWN gridbox widget.