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