MyGUI  3.2.1
MyGUI_ProgressBar.cpp
Go to the documentation of this file.
00001 /*
00002  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
00003  * Distributed under the MIT License
00004  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
00005  */
00006 
00007 #include "MyGUI_Precompiled.h"
00008 #include "MyGUI_ProgressBar.h"
00009 #include "MyGUI_ResourceSkin.h"
00010 #include "MyGUI_Widget.h"
00011 #include "MyGUI_Gui.h"
00012 #include "MyGUI_SkinManager.h"
00013 
00014 namespace MyGUI
00015 {
00016 
00017     const size_t PROGRESS_AUTO_WIDTH = 200;
00018     const size_t PROGRESS_AUTO_RANGE = 1000;
00019     const float PROGRESS_AUTO_COEF = 400;
00020 
00021     ProgressBar::ProgressBar() :
00022         mTrackWidth(1),
00023         mTrackStep(0),
00024         mTrackMin(0),
00025         mRange(0),
00026         mStartPosition(0),
00027         mEndPosition(0),
00028         mAutoPosition(0.0f),
00029         mAutoTrack(false),
00030         mFillTrack(false),
00031         mClient(nullptr)
00032     {
00033     }
00034 
00035     void ProgressBar::initialiseOverride()
00036     {
00037         Base::initialiseOverride();
00038 
00040         assignWidget(mClient, "TrackPlace");
00041 
00042         if (nullptr == mClient)
00043         {
00044             //OBSOLETE
00045             assignWidget(mClient, "Client");
00046 
00047             if (nullptr == mClient)
00048                 mClient = this;
00049         }
00050 
00051         if (isUserString("TrackSkin"))
00052             mTrackSkin = getUserString("TrackSkin");
00053 
00054         if (isUserString("TrackWidth"))
00055             mTrackWidth = utility::parseValue<int>(getUserString("TrackWidth"));
00056 
00057         //OBSOLETE
00058         if (isUserString("TrackMin"))
00059             mTrackMin = utility::parseValue<int>(getUserString("TrackMin"));
00060 
00061         else
00062             mTrackMin = mTrackWidth;
00063 
00064         if (isUserString("TrackStep"))
00065             mTrackStep = utility::parseValue<int>(getUserString("TrackStep"));
00066 
00067         if (isUserString("TrackFill"))
00068             mFillTrack = utility::parseValue<bool>(getUserString("TrackFill"));
00069 
00070         if (!isUserString("TrackStep"))
00071             mTrackStep = mTrackWidth;
00072 
00073         if (1 > mTrackWidth)
00074             mTrackWidth = 1;
00075     }
00076 
00077     void ProgressBar::shutdownOverride()
00078     {
00079         mClient = nullptr;
00080 
00081         Base::shutdownOverride();
00082     }
00083 
00084     void ProgressBar::setProgressRange(size_t _range)
00085     {
00086         if (mAutoTrack) return;
00087         mRange = _range;
00088         if (mEndPosition > mRange) mEndPosition = mRange;
00089         if (mStartPosition > mRange) mStartPosition = mRange;
00090         updateTrack();
00091     }
00092 
00093     void ProgressBar::setProgressPosition(size_t _pos)
00094     {
00095         if (mAutoTrack) return;
00096         mEndPosition = _pos;
00097         if (mEndPosition > mRange) mEndPosition = mRange;
00098         updateTrack();
00099     }
00100 
00101     void ProgressBar::setProgressAutoTrack(bool _auto)
00102     {
00103         if (mAutoTrack == _auto) return;
00104         mAutoTrack = _auto;
00105 
00106         if (mAutoTrack)
00107         {
00108             Gui::getInstance().eventFrameStart += newDelegate(this, &ProgressBar::frameEntered);
00109             mRange = PROGRESS_AUTO_RANGE;
00110             mEndPosition = mStartPosition = 0;
00111             mAutoPosition = 0.0f;
00112         }
00113         else
00114         {
00115             Gui::getInstance().eventFrameStart -= newDelegate(this, &ProgressBar::frameEntered);
00116             mRange = mEndPosition = mStartPosition = 0;
00117         }
00118         updateTrack();
00119     }
00120 
00121     void ProgressBar::frameEntered(float _time)
00122     {
00123         if (!mAutoTrack) return;
00124         mAutoPosition += (PROGRESS_AUTO_COEF * _time);
00125         size_t pos = (size_t)mAutoPosition;
00126 
00127         if (pos > (mRange + PROGRESS_AUTO_WIDTH)) mAutoPosition = 0.0f;
00128 
00129         if (pos > mRange) mEndPosition = mRange;
00130         else mEndPosition = size_t(mAutoPosition);
00131 
00132         if (pos < PROGRESS_AUTO_WIDTH) mStartPosition = 0;
00133         else mStartPosition = pos - PROGRESS_AUTO_WIDTH;
00134 
00135         updateTrack();
00136     }
00137 
00138     void ProgressBar::setPosition(const IntPoint& _point)
00139     {
00140         Base::setPosition(_point);
00141     }
00142 
00143     void ProgressBar::setSize(const IntSize& _size)
00144     {
00145         Base::setSize(_size);
00146 
00147         updateTrack();
00148     }
00149 
00150     void ProgressBar::setCoord(const IntCoord& _coord)
00151     {
00152         Base::setCoord(_coord);
00153 
00154         updateTrack();
00155     }
00156 
00157     void ProgressBar::updateTrack()
00158     {
00159         // все скрыто
00160         if ((0 == mRange) || (0 == mEndPosition))
00161         {
00162             for (VectorWidgetPtr::iterator iter = mVectorTrack.begin(); iter != mVectorTrack.end(); ++iter)
00163             {
00164                 (*iter)->setVisible(false);
00165             }
00166             return;
00167         }
00168 
00169         // тут попроще расчеты
00170         if (mFillTrack)
00171         {
00172             if (mVectorTrack.empty())
00173             {
00174                 Widget* widget = mClient->createWidget<Widget>(mTrackSkin, IntCoord(), Align::Left | Align::VStretch);
00175                 mVectorTrack.push_back(widget);
00176             }
00177             else
00178             {
00179                 // первый показываем и ставим норм альфу
00180                 VectorWidgetPtr::iterator iter = mVectorTrack.begin();
00181                 (*iter)->setVisible(true);
00182                 (*iter)->setAlpha(ALPHA_MAX);
00183 
00184                 // все начиная со второго скрываем
00185                 ++iter;
00186                 for (; iter != mVectorTrack.end(); ++iter)
00187                 {
00188                     (*iter)->setVisible(false);
00189                 }
00190             }
00191 
00192             Widget* wid = mVectorTrack.front();
00193 
00194             // полностью виден
00195             if ((0 == mStartPosition) && (mRange == mEndPosition))
00196             {
00197                 setTrackPosition(wid, 0, 0, getClientWidth(), getClientHeight());
00198             }
00199             // эх
00200             else
00201             {
00202                 int pos = (int)mStartPosition * (getClientWidth() - mTrackMin) / (int)mRange;
00203                 setTrackPosition(wid, pos, 0, ((int)mEndPosition * (getClientWidth() - mTrackMin) / (int)mRange) - pos + mTrackMin, getClientHeight());
00204             }
00205 
00206             return;
00207         }
00208 
00209         // сначала проверяем виджеты для трека
00210         int width = getClientWidth() - mTrackWidth + mTrackStep;
00211         int count = width / mTrackStep;
00212         int ost = (width % mTrackStep);
00213         if (ost > 0)
00214         {
00215             width += mTrackStep - ost;
00216             count ++;
00217         }
00218 
00219         while ((int)mVectorTrack.size() < count)
00220         {
00221             Widget* widget = mClient->createWidget<Widget>(mTrackSkin, IntCoord(/*(int)mVectorTrack.size() * mTrackStep, 0, mTrackWidth, getClientHeight()*/), Align::Left | Align::VStretch);
00222             widget->setVisible(false);
00223             mVectorTrack.push_back(widget);
00224         }
00225 
00226         // все видно
00227         if ((0 == mStartPosition) && (mRange == mEndPosition))
00228         {
00229             int pos = 0;
00230             for (VectorWidgetPtr::iterator iter = mVectorTrack.begin(); iter != mVectorTrack.end(); ++iter)
00231             {
00232                 (*iter)->setAlpha(ALPHA_MAX);
00233                 (*iter)->setVisible(true);
00234                 setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
00235                 pos++;
00236             }
00237         }
00238         // эх, придется считать
00239         else
00240         {
00241             // сколько не видно
00242             int hide_pix = (width * (int)mStartPosition / (int)mRange);
00243             int hide_count = hide_pix / mTrackStep;
00244             // сколько видно
00245             int show_pix = (width * (int)mEndPosition / (int)mRange);
00246             int show_count = show_pix / mTrackStep;
00247 
00248             int pos = 0;
00249             for (VectorWidgetPtr::iterator iter = mVectorTrack.begin(); iter != mVectorTrack.end(); ++iter)
00250             {
00251                 if (0 > show_count)
00252                 {
00253                     (*iter)->setVisible(false);
00254                 }
00255                 else if (0 == show_count)
00256                 {
00257                     (*iter)->setAlpha((float)(show_pix % mTrackStep) / (float)mTrackStep);
00258                     (*iter)->setVisible(true);
00259                     setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
00260                 }
00261                 else
00262                 {
00263                     if (0 < hide_count)
00264                     {
00265                         (*iter)->setVisible(false);
00266                     }
00267                     else if (0 == hide_count)
00268                     {
00269                         (*iter)->setAlpha(1.0f - ((float)(hide_pix % mTrackStep) / (float)mTrackStep));
00270                         (*iter)->setVisible(true);
00271                         setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
00272                     }
00273                     else
00274                     {
00275                         (*iter)->setAlpha(ALPHA_MAX);
00276                         (*iter)->setVisible(true);
00277                         setTrackPosition(*iter, pos * mTrackStep, 0, mTrackWidth, getClientHeight());
00278                     }
00279                 }
00280                 hide_count --;
00281                 show_count --;
00282                 pos ++;
00283             }
00284         }
00285     }
00286 
00287     void ProgressBar::setTrackPosition(Widget* _widget, int _left, int _top, int _width, int _height)
00288     {
00289         if (mFlowDirection == FlowDirection::LeftToRight) _widget->setCoord(_left, _top, _width, _height);
00290         else if (mFlowDirection == FlowDirection::RightToLeft) _widget->setCoord(mClient->getWidth() - _left - _width, _top, _width, _height);
00291         else if (mFlowDirection == FlowDirection::TopToBottom) _widget->setCoord(_top, _left, _height, _width);
00292         else if (mFlowDirection == FlowDirection::BottomToTop) _widget->setCoord(_top, mClient->getHeight() - _left - _width, _height, _width);
00293     }
00294 
00295     int ProgressBar::getClientWidth()
00296     {
00297         return mFlowDirection.isHorizontal() ? mClient->getWidth() : mClient->getHeight();
00298     }
00299 
00300     int ProgressBar::getClientHeight()
00301     {
00302         return mFlowDirection.isHorizontal() ? mClient->getHeight() : mClient->getWidth();
00303     }
00304 
00305     void ProgressBar::setFlowDirection(FlowDirection _value)
00306     {
00307         mFlowDirection = _value;
00308         updateTrack();
00309     }
00310 
00311     void ProgressBar::setPropertyOverride(const std::string& _key, const std::string& _value)
00312     {
00314         if (_key == "Range")
00315             setProgressRange(utility::parseValue<size_t>(_value));
00316 
00318         else if (_key == "RangePosition")
00319             setProgressPosition(utility::parseValue<size_t>(_value));
00320 
00322         else if (_key == "AutoTrack")
00323             setProgressAutoTrack(utility::parseValue<bool>(_value));
00324 
00326         else if (_key == "FlowDirection")
00327             setFlowDirection(utility::parseValue<FlowDirection>(_value));
00328 
00329         else
00330         {
00331             Base::setPropertyOverride(_key, _value);
00332             return;
00333         }
00334 
00335         eventChangeProperty(this, _key, _value);
00336     }
00337 
00338     size_t ProgressBar::getProgressRange() const
00339     {
00340         return mRange;
00341     }
00342 
00343     size_t ProgressBar::getProgressPosition() const
00344     {
00345         return mEndPosition;
00346     }
00347 
00348     bool ProgressBar::getProgressAutoTrack() const
00349     {
00350         return mAutoTrack;
00351     }
00352 
00353     FlowDirection ProgressBar::getFlowDirection() const
00354     {
00355         return mFlowDirection;
00356     }
00357 
00358     void ProgressBar::setPosition(int _left, int _top)
00359     {
00360         setPosition(IntPoint(_left, _top));
00361     }
00362 
00363     void ProgressBar::setSize(int _width, int _height)
00364     {
00365         setSize(IntSize(_width, _height));
00366     }
00367 
00368     void ProgressBar::setCoord(int _left, int _top, int _width, int _height)
00369     {
00370         setCoord(IntCoord(_left, _top, _width, _height));
00371     }
00372 
00373 } // namespace MyGUI