00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "MyGUI_Precompiled.h"
00024 #include "MyGUI_VScroll.h"
00025 #include "MyGUI_InputManager.h"
00026 #include "MyGUI_Button.h"
00027 #include "MyGUI_ResourceSkin.h"
00028
00029 namespace MyGUI
00030 {
00031
00032 const int SCROLL_MOUSE_WHEEL = 50;
00033
00034 VScroll::VScroll() :
00035 mWidgetStart(nullptr),
00036 mWidgetEnd(nullptr),
00037 mWidgetTrack(nullptr),
00038 mWidgetFirstPart(nullptr),
00039 mWidgetSecondPart(nullptr),
00040 mSkinRangeStart(0),
00041 mSkinRangeEnd(0),
00042 mScrollRange(0),
00043 mScrollPosition(0),
00044 mScrollPage(0),
00045 mScrollViewPage(0),
00046 mMinTrackSize(0),
00047 mMoveToClick(false)
00048 {
00049 }
00050
00051 void VScroll::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
00052 {
00053 Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
00054
00055 initialiseWidgetSkin(_info);
00056 }
00057
00058 VScroll::~VScroll()
00059 {
00060 shutdownWidgetSkin();
00061 }
00062
00063 void VScroll::baseChangeWidgetSkin(ResourceSkin* _info)
00064 {
00065 shutdownWidgetSkin();
00066 Base::baseChangeWidgetSkin(_info);
00067 initialiseWidgetSkin(_info);
00068 }
00069
00070 void VScroll::initialiseWidgetSkin(ResourceSkin* _info)
00071 {
00072
00073 mScrollPage = 1;
00074 mScrollViewPage = 1;
00075
00076 for (VectorWidgetPtr::iterator iter = mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
00077 {
00078 if (*(*iter)->_getInternalData<std::string>() == "Start")
00079 {
00080 MYGUI_DEBUG_ASSERT( ! mWidgetStart, "widget already assigned");
00081 mWidgetStart = (*iter)->castType<Button>();
00082 mWidgetStart->eventMouseButtonPressed = newDelegate(this, &VScroll::notifyMousePressed);
00083 mWidgetStart->eventMouseWheel = newDelegate(this, &VScroll::notifyMouseWheel);
00084 }
00085 else if (*(*iter)->_getInternalData<std::string>() == "End")
00086 {
00087 MYGUI_DEBUG_ASSERT( ! mWidgetEnd, "widget already assigned");
00088 mWidgetEnd = (*iter)->castType<Button>();
00089 mWidgetEnd->eventMouseButtonPressed = newDelegate(this, &VScroll::notifyMousePressed);
00090 mWidgetEnd->eventMouseWheel = newDelegate(this, &VScroll::notifyMouseWheel);
00091 }
00092 else if (*(*iter)->_getInternalData<std::string>() == "Track")
00093 {
00094 MYGUI_DEBUG_ASSERT( ! mWidgetTrack, "widget already assigned");
00095 mWidgetTrack = (*iter)->castType<Button>();
00096 mWidgetTrack->eventMouseDrag = newDelegate(this, &VScroll::notifyMouseDrag);
00097 mWidgetTrack->eventMouseButtonPressed = newDelegate(this, &VScroll::notifyMousePressed);
00098 mWidgetTrack->eventMouseButtonReleased = newDelegate(this, &VScroll::notifyMouseReleased);
00099 mWidgetTrack->eventMouseWheel = newDelegate(this, &VScroll::notifyMouseWheel);
00100 mWidgetTrack->setVisible(false);
00101 }
00102 else if (*(*iter)->_getInternalData<std::string>() == "FirstPart")
00103 {
00104 MYGUI_DEBUG_ASSERT( ! mWidgetFirstPart, "widget already assigned");
00105 mWidgetFirstPart = (*iter)->castType<Button>();
00106 mWidgetFirstPart->eventMouseButtonPressed = newDelegate(this, &VScroll::notifyMousePressed);
00107 mWidgetFirstPart->eventMouseWheel = newDelegate(this, &VScroll::notifyMouseWheel);
00108 }
00109 else if (*(*iter)->_getInternalData<std::string>() == "SecondPart")
00110 {
00111 MYGUI_DEBUG_ASSERT( ! mWidgetSecondPart, "widget already assigned");
00112 mWidgetSecondPart = (*iter)->castType<Button>();
00113 mWidgetSecondPart->eventMouseButtonPressed = newDelegate(this, &VScroll::notifyMousePressed);
00114 mWidgetSecondPart->eventMouseWheel = newDelegate(this, &VScroll::notifyMouseWheel);
00115 }
00116 }
00117
00118
00119
00120
00121
00122 const MapString& properties = _info->getProperties();
00123 MapString::const_iterator iter = properties.find("TrackRangeMargins");
00124 if (iter != properties.end())
00125 {
00126 IntSize range = IntSize::parse(iter->second);
00127 mSkinRangeStart = range.width;
00128 mSkinRangeEnd = range.height;
00129 }
00130 else
00131 {
00132 mSkinRangeStart = 0;
00133 mSkinRangeEnd = 0;
00134 }
00135 iter = properties.find("MinTrackSize");
00136 if (iter != properties.end()) mMinTrackSize = utility::parseInt(iter->second);
00137 else mMinTrackSize = 0;
00138
00139 iter = properties.find("MoveToClick");
00140 if (iter != properties.end()) mMoveToClick = utility::parseBool(iter->second);
00141 }
00142
00143 void VScroll::shutdownWidgetSkin()
00144 {
00145 mWidgetStart = nullptr;
00146 mWidgetEnd = nullptr;
00147 mWidgetTrack = nullptr;
00148 mWidgetFirstPart = nullptr;
00149 mWidgetSecondPart = nullptr;
00150 }
00151
00152 void VScroll::updateTrack()
00153 {
00154 if (mWidgetTrack == nullptr)
00155 return;
00156
00157 _forcePeek(mWidgetTrack);
00158
00159 int pos = getLineSize();
00160
00161
00162 if ((mScrollRange < 2) || (pos <= mWidgetTrack->getHeight()))
00163 {
00164 mWidgetTrack->setVisible(false);
00165 if ( nullptr != mWidgetFirstPart ) mWidgetFirstPart->setSize(mWidgetFirstPart->getWidth(), pos/2);
00166 if ( nullptr != mWidgetSecondPart ) mWidgetSecondPart->setCoord(mWidgetSecondPart->getLeft(), pos/2 + (int)mSkinRangeStart, mWidgetSecondPart->getWidth(), pos - pos/2);
00167 return;
00168 }
00169
00170 if (!mWidgetTrack->isVisible())
00171 {
00172 mWidgetTrack->setVisible(true);
00173 }
00174
00175
00176 pos = (int)(((size_t)(pos-getTrackSize()) * mScrollPosition) / (mScrollRange-1) + mSkinRangeStart);
00177
00178 mWidgetTrack->setPosition(mWidgetTrack->getLeft(), pos);
00179 if ( nullptr != mWidgetFirstPart )
00180 {
00181 int height = pos + mWidgetTrack->getHeight()/2 - mWidgetFirstPart->getTop();
00182 mWidgetFirstPart->setSize(mWidgetFirstPart->getWidth(), height);
00183 }
00184 if ( nullptr != mWidgetSecondPart )
00185 {
00186 int top = pos + mWidgetTrack->getHeight()/2;
00187 int height = mWidgetSecondPart->getHeight() + mWidgetSecondPart->getTop() - top;
00188 mWidgetSecondPart->setCoord(mWidgetSecondPart->getLeft(), top, mWidgetSecondPart->getWidth(), height);
00189 }
00190 }
00191
00192 void VScroll::TrackMove(int _left, int _top)
00193 {
00194 if (mWidgetTrack == nullptr)
00195 return;
00196
00197 const IntPoint& point = InputManager::getInstance().getLastLeftPressed();
00198
00199
00200 int start = mPreActionOffset.top + (_top - point.top);
00201 if (start < (int)mSkinRangeStart) start = (int)mSkinRangeStart;
00202 else if (start > (mCoord.height - (int)mSkinRangeEnd - mWidgetTrack->getHeight())) start = (mCoord.height - (int)mSkinRangeEnd - mWidgetTrack->getHeight());
00203 if (mWidgetTrack->getTop() != start) mWidgetTrack->setPosition(mWidgetTrack->getLeft(), start);
00204
00205
00206
00207 int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange-1) * 2);
00208
00209 pos = pos * (int)(mScrollRange-1) / (getLineSize() - getTrackSize());
00210
00211
00212 if (pos < 0) pos = 0;
00213 else if (pos >= (int)mScrollRange) pos = (int)mScrollRange - 1;
00214 if (pos == (int)mScrollPosition) return;
00215
00216 mScrollPosition = pos;
00217
00218 eventScrollChangePosition(this, (int)mScrollPosition);
00219 }
00220
00221 void VScroll::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id)
00222 {
00223
00224 eventMouseButtonPressed(this, _left, _top, _id);
00225
00226 if (MouseButton::Left != _id) return;
00227
00228 if (mMoveToClick && mWidgetTrack != _sender)
00229 {
00230 mPreActionOffset = InputManager::getInstance().getLastLeftPressed();
00231 const IntPoint& point = InputManager::getInstance().getMousePositionByLayer() - getAbsolutePosition();
00232
00233 TrackMove(point.left, point.top);
00234
00235 }
00236 else if (_sender == mWidgetStart)
00237 {
00238
00239 if (mScrollPosition == 0) return;
00240
00241
00242 if (mScrollPosition > mScrollPage) mScrollPosition -= mScrollPage;
00243 else mScrollPosition = 0;
00244
00245
00246 eventScrollChangePosition(this, (int)mScrollPosition);
00247 updateTrack();
00248
00249 }
00250 else if (_sender == mWidgetEnd)
00251 {
00252
00253 if ( (mScrollRange < 2) || (mScrollPosition >= (mScrollRange-1)) ) return;
00254
00255
00256 if ((mScrollPosition + mScrollPage) < (mScrollRange-1)) mScrollPosition += mScrollPage;
00257 else mScrollPosition = mScrollRange - 1;
00258
00259
00260 eventScrollChangePosition(this, (int)mScrollPosition);
00261 updateTrack();
00262
00263 }
00264 else if (_sender == mWidgetFirstPart)
00265 {
00266
00267 if (mScrollPosition == 0) return;
00268
00269
00270 if (mScrollPosition > mScrollViewPage) mScrollPosition -= mScrollViewPage;
00271 else mScrollPosition = 0;
00272
00273
00274 eventScrollChangePosition(this, (int)mScrollPosition);
00275 updateTrack();
00276
00277 }
00278 else if (_sender == mWidgetSecondPart)
00279 {
00280
00281 if ( (mScrollRange < 2) || (mScrollPosition >= (mScrollRange-1)) ) return;
00282
00283
00284 if ((mScrollPosition + mScrollViewPage) < (mScrollRange-1)) mScrollPosition += mScrollViewPage;
00285 else mScrollPosition = mScrollRange - 1;
00286
00287
00288 eventScrollChangePosition(this, (int)mScrollPosition);
00289 updateTrack();
00290
00291 }
00292 else if (_sender == mWidgetTrack)
00293 {
00294 mPreActionOffset.left = _sender->getLeft();
00295 mPreActionOffset.top = _sender->getTop();
00296 }
00297 }
00298
00299 void VScroll::notifyMouseReleased(Widget* _sender, int _left, int _top, MouseButton _id)
00300 {
00301 updateTrack();
00302 }
00303
00304 void VScroll::notifyMouseDrag(Widget* _sender, int _left, int _top)
00305 {
00306 TrackMove(_left, _top);
00307 }
00308
00309 void VScroll::setScrollRange(size_t _range)
00310 {
00311 if (_range == mScrollRange) return;
00312 mScrollRange = _range;
00313 mScrollPosition = (mScrollPosition < mScrollRange) ? mScrollPosition : 0;
00314 updateTrack();
00315 }
00316
00317 void VScroll::setScrollPosition(size_t _position)
00318 {
00319 if (_position == mScrollPosition) return;
00320 if (_position >= mScrollRange) _position = 0;
00321 mScrollPosition = _position;
00322 updateTrack();
00323 }
00324
00325 void VScroll::setPosition(const IntPoint& _point)
00326 {
00327 Base::setPosition(_point);
00328 }
00329
00330 void VScroll::setSize(const IntSize& _size)
00331 {
00332 Base::setSize(_size);
00333
00334 updateTrack();
00335 }
00336
00337 void VScroll::setCoord(const IntCoord& _coord)
00338 {
00339 Base::setCoord(_coord);
00340
00341 updateTrack();
00342 }
00343
00344 void VScroll::setTrackSize(int _size)
00345 {
00346 if (mWidgetTrack != nullptr)
00347 mWidgetTrack->setSize(mWidgetTrack->getWidth(), ((int)_size < (int)mMinTrackSize)? (int)mMinTrackSize : (int)_size);
00348 updateTrack();
00349 }
00350
00351 int VScroll::getTrackSize()
00352 {
00353 return mWidgetTrack == nullptr ? 1 : mWidgetTrack->getHeight();
00354 }
00355
00356 int VScroll::getLineSize()
00357 {
00358 return mCoord.height - (int)(mSkinRangeStart + mSkinRangeEnd);
00359 }
00360
00361 void VScroll::onMouseWheel(int _rel)
00362 {
00363 notifyMouseWheel(nullptr, _rel);
00364
00365 Base::onMouseWheel(_rel);
00366 }
00367
00368 void VScroll::notifyMouseWheel(Widget* _sender, int _rel)
00369 {
00370 if (mScrollRange < 2) return;
00371
00372 int offset = mScrollPosition;
00373 if (_rel < 0) offset += SCROLL_MOUSE_WHEEL;
00374 else offset -= SCROLL_MOUSE_WHEEL;
00375
00376 if (offset < 0) offset = 0;
00377 else if (offset > (int)(mScrollRange - 1)) offset = mScrollRange - 1;
00378
00379 if ((size_t)offset != mScrollPosition)
00380 {
00381 mScrollPosition = offset;
00382
00383 eventScrollChangePosition(this, (int)mScrollPosition);
00384 updateTrack();
00385 }
00386 }
00387
00388 void VScroll::setProperty(const std::string& _key, const std::string& _value)
00389 {
00390 if (_key == "Scroll_Range") setScrollRange(utility::parseValue<size_t>(_value));
00391 else if (_key == "Scroll_Position") setScrollPosition(utility::parseValue<size_t>(_value));
00392 else if (_key == "Scroll_Page") setScrollPage(utility::parseValue<size_t>(_value));
00393 else if (_key == "Scroll_ViewPage") setScrollViewPage(utility::parseValue<size_t>(_value));
00394 else if (_key == "Scroll_MoveToClick") setMoveToClick(utility::parseValue<bool>(_value));
00395 else
00396 {
00397 Base::setProperty(_key, _value);
00398 return;
00399 }
00400 eventChangeProperty(this, _key, _value);
00401 }
00402
00403 }