MyGUI  3.2.1
MyGUI_ProgressBar.cpp
Go to the documentation of this file.
1 /*
2  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3  * Distributed under the MIT License
4  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5  */
6 
7 #include "MyGUI_Precompiled.h"
8 #include "MyGUI_ProgressBar.h"
9 #include "MyGUI_ResourceSkin.h"
10 #include "MyGUI_Widget.h"
11 #include "MyGUI_Gui.h"
12 #include "MyGUI_SkinManager.h"
13 
14 namespace MyGUI
15 {
16 
17  const size_t PROGRESS_AUTO_WIDTH = 200;
18  const size_t PROGRESS_AUTO_RANGE = 1000;
19  const float PROGRESS_AUTO_COEF = 400;
20 
22  mTrackWidth(1),
23  mTrackStep(0),
24  mTrackMin(0),
25  mRange(0),
26  mStartPosition(0),
27  mEndPosition(0),
28  mAutoPosition(0.0f),
29  mAutoTrack(false),
30  mFillTrack(false),
31  mClient(nullptr)
32  {
33  }
34 
36  {
37  Base::initialiseOverride();
38 
40  assignWidget(mClient, "TrackPlace");
41 
42  if (nullptr == mClient)
43  {
44  //OBSOLETE
45  assignWidget(mClient, "Client");
46 
47  if (nullptr == mClient)
48  mClient = this;
49  }
50 
51  if (isUserString("TrackSkin"))
52  mTrackSkin = getUserString("TrackSkin");
53 
54  if (isUserString("TrackWidth"))
55  mTrackWidth = utility::parseValue<int>(getUserString("TrackWidth"));
56 
57  //OBSOLETE
58  if (isUserString("TrackMin"))
59  mTrackMin = utility::parseValue<int>(getUserString("TrackMin"));
60 
61  else
62  mTrackMin = mTrackWidth;
63 
64  if (isUserString("TrackStep"))
65  mTrackStep = utility::parseValue<int>(getUserString("TrackStep"));
66 
67  if (isUserString("TrackFill"))
68  mFillTrack = utility::parseValue<bool>(getUserString("TrackFill"));
69 
70  if (!isUserString("TrackStep"))
71  mTrackStep = mTrackWidth;
72 
73  if (1 > mTrackWidth)
74  mTrackWidth = 1;
75  }
76 
78  {
79  mClient = nullptr;
80 
81  Base::shutdownOverride();
82  }
83 
84  void ProgressBar::setProgressRange(size_t _range)
85  {
86  if (mAutoTrack) return;
87  mRange = _range;
88  if (mEndPosition > mRange) mEndPosition = mRange;
89  if (mStartPosition > mRange) mStartPosition = mRange;
90  updateTrack();
91  }
92 
94  {
95  if (mAutoTrack) return;
96  mEndPosition = _pos;
97  if (mEndPosition > mRange) mEndPosition = mRange;
98  updateTrack();
99  }
100 
102  {
103  if (mAutoTrack == _auto) return;
104  mAutoTrack = _auto;
105 
106  if (mAutoTrack)
107  {
108  Gui::getInstance().eventFrameStart += newDelegate(this, &ProgressBar::frameEntered);
109  mRange = PROGRESS_AUTO_RANGE;
110  mEndPosition = mStartPosition = 0;
111  mAutoPosition = 0.0f;
112  }
113  else
114  {
115  Gui::getInstance().eventFrameStart -= newDelegate(this, &ProgressBar::frameEntered);
116  mRange = mEndPosition = mStartPosition = 0;
117  }
118  updateTrack();
119  }
120 
121  void ProgressBar::frameEntered(float _time)
122  {
123  if (!mAutoTrack) return;
124  mAutoPosition += (PROGRESS_AUTO_COEF * _time);
125  size_t pos = (size_t)mAutoPosition;
126 
127  if (pos > (mRange + PROGRESS_AUTO_WIDTH)) mAutoPosition = 0.0f;
128 
129  if (pos > mRange) mEndPosition = mRange;
130  else mEndPosition = size_t(mAutoPosition);
131 
132  if (pos < PROGRESS_AUTO_WIDTH) mStartPosition = 0;
133  else mStartPosition = pos - PROGRESS_AUTO_WIDTH;
134 
135  updateTrack();
136  }
137 
138  void ProgressBar::setPosition(const IntPoint& _point)
139  {
140  Base::setPosition(_point);
141  }
142 
143  void ProgressBar::setSize(const IntSize& _size)
144  {
145  Base::setSize(_size);
146 
147  updateTrack();
148  }
149 
150  void ProgressBar::setCoord(const IntCoord& _coord)
151  {
152  Base::setCoord(_coord);
153 
154  updateTrack();
155  }
156 
157  void ProgressBar::updateTrack()
158  {
159  // все скрыто
160  if ((0 == mRange) || (0 == mEndPosition))
161  {
162  for (VectorWidgetPtr::iterator iter = mVectorTrack.begin(); iter != mVectorTrack.end(); ++iter)
163  {
164  (*iter)->setVisible(false);
165  }
166  return;
167  }
168 
169  // тут попроще расчеты
170  if (mFillTrack)
171  {
172  if (mVectorTrack.empty())
173  {
174  Widget* widget = mClient->createWidget<Widget>(mTrackSkin, IntCoord(), Align::Left | Align::VStretch);
175  mVectorTrack.push_back(widget);
176  }
177  else
178  {
179  // первый показываем и ставим норм альфу
180  VectorWidgetPtr::iterator iter = mVectorTrack.begin();
181  (*iter)->setVisible(true);
182  (*iter)->setAlpha(ALPHA_MAX);
183 
184  // все начиная со второго скрываем
185  ++iter;
186  for (; iter != mVectorTrack.end(); ++iter)
187  {
188  (*iter)->setVisible(false);
189  }
190  }
191 
192  Widget* wid = mVectorTrack.front();
193 
194  // полностью виден
195  if ((0 == mStartPosition) && (mRange == mEndPosition))
196  {
197  setTrackPosition(wid, 0, 0, getClientWidth(), getClientHeight());
198  }
199  // эх
200  else
201  {
202  int pos = (int)mStartPosition * (getClientWidth() - mTrackMin) / (int)mRange;
203  setTrackPosition(wid, pos, 0, ((int)mEndPosition * (getClientWidth() - mTrackMin) / (int)mRange) - pos + mTrackMin, getClientHeight());
204  }
205 
206  return;
207  }
208 
209  // сначала проверяем виджеты для трека
210  int width = getClientWidth() - mTrackWidth + mTrackStep;
211  int count = width / mTrackStep;
212  int ost = (width % mTrackStep);
213  if (ost > 0)
214  {
215  width += mTrackStep - ost;
216  count ++;
217  }
218 
219  while ((int)mVectorTrack.size() < count)
220  {
221  Widget* widget = mClient->createWidget<Widget>(mTrackSkin, IntCoord(/*(int)mVectorTrack.size() * mTrackStep, 0, mTrackWidth, getClientHeight()*/), Align::Left | Align::VStretch);
222  widget->setVisible(false);
223  mVectorTrack.push_back(widget);
224  }
225 
226  // все видно
227  if ((0 == mStartPosition) && (mRange == mEndPosition))
228  {
229  int pos = 0;
230  for (VectorWidgetPtr::iterator iter = mVectorTrack.begin(); iter != mVectorTrack.end(); ++iter)
231  {
232  (*iter)->setAlpha(ALPHA_MAX);
233  (*iter)->setVisible(true);
234  setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
235  pos++;
236  }
237  }
238  // эх, придется считать
239  else
240  {
241  // сколько не видно
242  int hide_pix = (width * (int)mStartPosition / (int)mRange);
243  int hide_count = hide_pix / mTrackStep;
244  // сколько видно
245  int show_pix = (width * (int)mEndPosition / (int)mRange);
246  int show_count = show_pix / mTrackStep;
247 
248  int pos = 0;
249  for (VectorWidgetPtr::iterator iter = mVectorTrack.begin(); iter != mVectorTrack.end(); ++iter)
250  {
251  if (0 > show_count)
252  {
253  (*iter)->setVisible(false);
254  }
255  else if (0 == show_count)
256  {
257  (*iter)->setAlpha((float)(show_pix % mTrackStep) / (float)mTrackStep);
258  (*iter)->setVisible(true);
259  setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
260  }
261  else
262  {
263  if (0 < hide_count)
264  {
265  (*iter)->setVisible(false);
266  }
267  else if (0 == hide_count)
268  {
269  (*iter)->setAlpha(1.0f - ((float)(hide_pix % mTrackStep) / (float)mTrackStep));
270  (*iter)->setVisible(true);
271  setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
272  }
273  else
274  {
275  (*iter)->setAlpha(ALPHA_MAX);
276  (*iter)->setVisible(true);
277  setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
278  }
279  }
280  hide_count --;
281  show_count --;
282  pos ++;
283  }
284  }
285  }
286 
287  void ProgressBar::setTrackPosition(Widget* _widget, int _left, int _top, int _width, int _height)
288  {
289  if (mFlowDirection == FlowDirection::LeftToRight) _widget->setCoord(_left, _top, _width, _height);
290  else if (mFlowDirection == FlowDirection::RightToLeft) _widget->setCoord(mClient->getWidth() - _left - _width, _top, _width, _height);
291  else if (mFlowDirection == FlowDirection::TopToBottom) _widget->setCoord(_top, _left, _height, _width);
292  else if (mFlowDirection == FlowDirection::BottomToTop) _widget->setCoord(_top, mClient->getHeight() - _left - _width, _height, _width);
293  }
294 
295  int ProgressBar::getClientWidth()
296  {
297  return mFlowDirection.isHorizontal() ? mClient->getWidth() : mClient->getHeight();
298  }
299 
300  int ProgressBar::getClientHeight()
301  {
302  return mFlowDirection.isHorizontal() ? mClient->getHeight() : mClient->getWidth();
303  }
304 
306  {
307  mFlowDirection = _value;
308  updateTrack();
309  }
310 
311  void ProgressBar::setPropertyOverride(const std::string& _key, const std::string& _value)
312  {
314  if (_key == "Range")
315  setProgressRange(utility::parseValue<size_t>(_value));
316 
318  else if (_key == "RangePosition")
319  setProgressPosition(utility::parseValue<size_t>(_value));
320 
322  else if (_key == "AutoTrack")
323  setProgressAutoTrack(utility::parseValue<bool>(_value));
324 
326  else if (_key == "FlowDirection")
327  setFlowDirection(utility::parseValue<FlowDirection>(_value));
328 
329  else
330  {
331  Base::setPropertyOverride(_key, _value);
332  return;
333  }
334 
335  eventChangeProperty(this, _key, _value);
336  }
337 
339  {
340  return mRange;
341  }
342 
344  {
345  return mEndPosition;
346  }
347 
349  {
350  return mAutoTrack;
351  }
352 
354  {
355  return mFlowDirection;
356  }
357 
358  void ProgressBar::setPosition(int _left, int _top)
359  {
360  setPosition(IntPoint(_left, _top));
361  }
362 
363  void ProgressBar::setSize(int _width, int _height)
364  {
365  setSize(IntSize(_width, _height));
366  }
367 
368  void ProgressBar::setCoord(int _left, int _top, int _width, int _height)
369  {
370  setCoord(IntCoord(_left, _top, _width, _height));
371  }
372 
373 } // namespace MyGUI