MyGUI  3.0.1
MyGUI_Progress.cpp
Go to the documentation of this file.
1 
7 /*
8  This file is part of MyGUI.
9 
10  MyGUI is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  MyGUI is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
22 */
23 #include "MyGUI_Precompiled.h"
24 #include "MyGUI_Progress.h"
25 #include "MyGUI_ResourceSkin.h"
26 #include "MyGUI_Widget.h"
27 #include "MyGUI_Gui.h"
28 #include "MyGUI_SkinManager.h"
29 
30 namespace MyGUI
31 {
32 
33  const size_t PROGRESS_AUTO_WIDTH = 200;
34  const size_t PROGRESS_AUTO_RANGE = 1000;
35  const float PROGRESS_AUTO_COEF = 400;
36 
38  mTrackWidth(1),
39  mTrackStep(0),
40  mTrackMin(0),
41  mRange(0),
42  mStartPosition(0),
43  mEndPosition(0),
44  mAutoPosition(0.0f),
45  mAutoTrack(false),
46  mFillTrack(false),
47  mStartPoint(Align::Left),
48  mClient(nullptr)
49  {
50  }
51 
52  void Progress::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
53  {
54  Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
55 
56  initialiseWidgetSkin(_info);
57  }
58 
60  {
61  shutdownWidgetSkin();
62  }
63 
65  {
66  shutdownWidgetSkin();
68  initialiseWidgetSkin(_info);
69  }
70 
71  void Progress::initialiseWidgetSkin(ResourceSkin* _info)
72  {
73  for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
74  {
75  if (*(*iter)->_getInternalData<std::string>() == "Client")
76  {
77  MYGUI_DEBUG_ASSERT( ! mClient, "widget already assigned");
78  mClient = (*iter);
79  }
80  }
81  if (nullptr == mClient) mClient = this;
82 
83  const MapString& properties = _info->getProperties();
84  MapString::const_iterator iterS = properties.find("TrackSkin");
85  if (iterS != properties.end()) mTrackSkin = iterS->second;
86  iterS = properties.find("TrackWidth");
87  if (iterS != properties.end()) mTrackWidth = utility::parseInt(iterS->second);
88  iterS = properties.find("TrackMin");
89  if (iterS != properties.end()) mTrackMin = utility::parseInt(iterS->second);
90  if (1 > mTrackWidth) mTrackWidth = 1;
91  iterS = properties.find("TrackStep");
92  if (iterS != properties.end()) mTrackStep = utility::parseInt(iterS->second);
93  else mTrackStep = mTrackWidth;
94  iterS = properties.find("TrackFill");
95  if (iterS != properties.end()) mFillTrack = utility::parseBool(iterS->second);
96  iterS = properties.find("StartPoint");
97  if (iterS != properties.end()) setProgressStartPoint(Align::parse(iterS->second));
98 
99  }
100 
101  void Progress::shutdownWidgetSkin()
102  {
103  mClient = nullptr;
104  }
105 
106  void Progress::setProgressRange(size_t _range)
107  {
108  if (mAutoTrack) return;
109  mRange = _range;
110  if (mEndPosition > mRange) mEndPosition = mRange;
111  if (mStartPosition > mRange) mStartPosition = mRange;
112  updateTrack();
113  }
114 
116  {
117  if (mAutoTrack) return;
118  mEndPosition = _pos;
119  if (mEndPosition > mRange) mEndPosition = mRange;
120  updateTrack();
121  }
122 
124  {
125  if (mAutoTrack == _auto) return;
126  mAutoTrack = _auto;
127 
128  if (mAutoTrack)
129  {
130  Gui::getInstance().eventFrameStart += newDelegate(this, &Progress::frameEntered);
131  mRange = PROGRESS_AUTO_RANGE;
132  mEndPosition = mStartPosition = 0;
133  mAutoPosition = 0.0f;
134  }
135  else
136  {
137  Gui::getInstance().eventFrameStart -= newDelegate(this, &Progress::frameEntered);
138  mRange = mEndPosition = mStartPosition = 0;
139  }
140  updateTrack();
141  }
142 
143  void Progress::frameEntered(float _time)
144  {
145  if (!mAutoTrack) return;
146  mAutoPosition += (PROGRESS_AUTO_COEF * _time);
147  size_t pos = (size_t)mAutoPosition;
148 
149  if (pos > (mRange + PROGRESS_AUTO_WIDTH)) mAutoPosition = 0.0f;
150 
151  if (pos > mRange) mEndPosition = mRange;
152  else mEndPosition = size_t(mAutoPosition);
153 
154  if (pos < PROGRESS_AUTO_WIDTH) mStartPosition = 0;
155  else mStartPosition = pos - PROGRESS_AUTO_WIDTH;
156 
157  updateTrack();
158  }
159 
160  void Progress::setPosition(const IntPoint& _point)
161  {
162  Base::setPosition(_point);
163  }
164 
165  void Progress::setSize(const IntSize& _size)
166  {
167  updateTrack();
168 
169  Base::setSize(_size);
170  }
171 
172  void Progress::setCoord(const IntCoord& _coord)
173  {
174  updateTrack();
175 
176  Base::setCoord(_coord);
177  }
178 
179  void Progress::updateTrack()
180  {
181  // все скрыто
182  if ((0 == mRange) || (0 == mEndPosition))
183  {
184  for (VectorWidgetPtr::iterator iter=mVectorTrack.begin(); iter!=mVectorTrack.end(); ++iter)
185  {
186  (*iter)->setVisible(false);
187  }
188  return;
189  }
190 
191  // тут попроще расчеты
192  if (mFillTrack)
193  {
194  if (mVectorTrack.empty())
195  {
196  Widget* widget = mClient->createWidget<Widget>(mTrackSkin, IntCoord(), Align::Left | Align::VStretch);
197  mVectorTrack.push_back(widget);
198  }
199  else
200  {
201  // первый показываем и ставим норм альфу
202  VectorWidgetPtr::iterator iter=mVectorTrack.begin();
203  (*iter)->setVisible(true);
204  (*iter)->setAlpha(ALPHA_MAX);
205 
206  // все начиная со второго скрываем
207  ++iter;
208  for (; iter!=mVectorTrack.end(); ++iter)
209  {
210  (*iter)->setVisible(false);
211  }
212  }
213 
214  Widget* wid = mVectorTrack.front();
215 
216  // полностью виден
217  if ((0 == mStartPosition) && (mRange == mEndPosition))
218  {
219  setTrackPosition(wid, 0, 0, getClientWidth(), getClientHeight());
220  }
221  // эх
222  else
223  {
224  int pos = (int)mStartPosition * (getClientWidth() - mTrackMin) / (int)mRange;
225  setTrackPosition(wid, pos, 0, ((int)mEndPosition * (getClientWidth() - mTrackMin) / (int)mRange) - pos + mTrackMin, getClientHeight());
226  }
227 
228  return;
229  }
230 
231  // сначала проверяем виджеты для трека
232  int width = getClientWidth() - mTrackWidth + mTrackStep;
233  int count = width / mTrackStep;
234  int ost = (width % mTrackStep);
235  if (ost > 0)
236  {
237  width += mTrackStep - ost;
238  count ++;
239  }
240 
241  while ((int)mVectorTrack.size() < count)
242  {
243  Widget* widget = mClient->createWidget<Widget>(mTrackSkin, IntCoord(/*(int)mVectorTrack.size() * mTrackStep, 0, mTrackWidth, getClientHeight()*/), Align::Left | Align::VStretch);
244  widget->setVisible(false);
245  mVectorTrack.push_back(widget);
246  }
247 
248  // все видно
249  if ((0 == mStartPosition) && (mRange == mEndPosition))
250  {
251  int pos = 0;
252  for (VectorWidgetPtr::iterator iter=mVectorTrack.begin(); iter!=mVectorTrack.end(); ++iter)
253  {
254  (*iter)->setAlpha(ALPHA_MAX);
255  (*iter)->setVisible(true);
256  setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
257  pos++;
258  }
259  }
260  // эх, придется считать
261  else
262  {
263  // сколько не видно
264  int hide_pix = (width * (int)mStartPosition / (int)mRange);
265  int hide_count = hide_pix / mTrackStep;
266  // сколько видно
267  int show_pix = (width * (int)mEndPosition / (int)mRange);
268  int show_count = show_pix / mTrackStep;
269 
270  int pos = 0;
271  for (VectorWidgetPtr::iterator iter=mVectorTrack.begin(); iter!=mVectorTrack.end(); ++iter)
272  {
273  if (0 > show_count)
274  {
275  (*iter)->setVisible(false);
276  }
277  else if (0 == show_count)
278  {
279  (*iter)->setAlpha((float)(show_pix % mTrackStep) / (float)mTrackStep);
280  (*iter)->setVisible(true);
281  setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
282  }
283  else
284  {
285  if (0 < hide_count)
286  {
287  (*iter)->setVisible(false);
288  }
289  else if (0 == hide_count)
290  {
291  (*iter)->setAlpha(1.0f - ((float)(hide_pix % mTrackStep) / (float)mTrackStep));
292  (*iter)->setVisible(true);
293  setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
294  }
295  else
296  {
297  (*iter)->setAlpha(ALPHA_MAX);
298  (*iter)->setVisible(true);
299  setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
300  }
301  }
302  hide_count --;
303  show_count --;
304  pos ++;
305  }
306  }
307  }
308 
309  void Progress::setTrackPosition(Widget* _widget, int _left, int _top, int _width, int _height)
310  {
311  if (mStartPoint.isLeft()) _widget->setCoord(_left, _top, _width, _height);
312  else if (mStartPoint.isRight()) _widget->setCoord(mClient->getWidth() - _left - _width, _top, _width, _height);
313  else if (mStartPoint.isTop()) _widget->setCoord(_top, _left, _height, _width);
314  else if (mStartPoint.isBottom()) _widget->setCoord(_top, mClient->getHeight() - _left - _width, _height, _width);
315  }
316 
318  {
319  if ((_align == Align::Left) || (_align == Align::Right) || (_align == Align::Top) || (_align == Align::Bottom))
320  {
321  mStartPoint = _align;
322  }
323  else
324  {
325  mStartPoint = Align::Left;
326  MYGUI_LOG(Warning, "Progress bar support only Left, Right, Top or Bottom align values");
327  }
328  updateTrack();
329  }
330 
331  void Progress::setProperty(const std::string& _key, const std::string& _value)
332  {
333  if (_key == "Progress_Range") setProgressRange(utility::parseValue<size_t>(_value));
334  else if (_key == "Progress_Position") setProgressPosition(utility::parseValue<size_t>(_value));
335  else if (_key == "Progress_AutoTrack") setProgressAutoTrack(utility::parseValue<bool>(_value));
336  else if (_key == "Progress_StartPoint") setProgressStartPoint(utility::parseValue<Align>(_value));
337  else
338  {
339  Base::setProperty(_key, _value);
340  return;
341  }
342  eventChangeProperty(this, _key, _value);
343  }
344 
345 } // namespace MyGUI