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, WidgetPtr _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 MYGUI_ASSERT(nullptr != mWidgetTrack, "Child Button Track not found in skin (Scroll must have Track)");
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 _forcePeek(mWidgetTrack);
00155
00156 int pos = getLineSize();
00157
00158
00159 if ((mScrollRange < 2) || (pos <= mWidgetTrack->getHeight())) {
00160 mWidgetTrack->setVisible(false);
00161 if ( nullptr != mWidgetFirstPart ) mWidgetFirstPart->setSize(mWidgetFirstPart->getWidth(), pos/2);
00162 if ( nullptr != mWidgetSecondPart ) mWidgetSecondPart->setCoord(mWidgetSecondPart->getLeft(), pos/2 + (int)mSkinRangeStart, mWidgetSecondPart->getWidth(), pos - pos/2);
00163 return;
00164 }
00165
00166 if (false == mWidgetTrack->isVisible())
00167 {
00168 mWidgetTrack->setVisible(true);
00169 }
00170
00171
00172 pos = (int)(((size_t)(pos-getTrackSize()) * mScrollPosition) / (mScrollRange-1) + mSkinRangeStart);
00173
00174 mWidgetTrack->setPosition(mWidgetTrack->getLeft(), pos);
00175 if ( nullptr != mWidgetFirstPart )
00176 {
00177 int height = pos + mWidgetTrack->getHeight()/2 - mWidgetFirstPart->getTop();
00178 mWidgetFirstPart->setSize(mWidgetFirstPart->getWidth(), height);
00179 }
00180 if ( nullptr != mWidgetSecondPart )
00181 {
00182 int top = pos + mWidgetTrack->getHeight()/2;
00183 int height = mWidgetSecondPart->getHeight() + mWidgetSecondPart->getTop() - top;
00184 mWidgetSecondPart->setCoord(mWidgetSecondPart->getLeft(), top, mWidgetSecondPart->getWidth(), height);
00185 }
00186 }
00187
00188 void VScroll::TrackMove(int _left, int _top)
00189 {
00190 const IntPoint& point = InputManager::getInstance().getLastLeftPressed();
00191
00192
00193 int start = mPreActionOffset.top + (_top - point.top);
00194 if (start < (int)mSkinRangeStart) start = (int)mSkinRangeStart;
00195 else if (start > (mCoord.height - (int)mSkinRangeEnd - mWidgetTrack->getHeight())) start = (mCoord.height - (int)mSkinRangeEnd - mWidgetTrack->getHeight());
00196 if (mWidgetTrack->getTop() != start) mWidgetTrack->setPosition(mWidgetTrack->getLeft(), start);
00197
00198
00199
00200 int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange-1) * 2);
00201
00202 pos = pos * (int)(mScrollRange-1) / (getLineSize() - getTrackSize());
00203
00204
00205 if (pos < 0) pos = 0;
00206 else if (pos >= (int)mScrollRange) pos = (int)mScrollRange - 1;
00207 if (pos == (int)mScrollPosition) return;
00208
00209 mScrollPosition = pos;
00210
00211 eventScrollChangePosition(this, (int)mScrollPosition);
00212 }
00213
00214 void VScroll::notifyMousePressed(WidgetPtr _sender, int _left, int _top, MouseButton _id)
00215 {
00216
00217 eventMouseButtonPressed(this, _left, _top, _id);
00218
00219 if (MouseButton::Left != _id) return;
00220
00221 if (mMoveToClick && mWidgetTrack != _sender)
00222 {
00223 mPreActionOffset = InputManager::getInstance().getLastLeftPressed();
00224 const IntPoint& point = InputManager::getInstance().getMousePosition() - getAbsolutePosition();
00225
00226 TrackMove(point.left, point.top);
00227
00228 }
00229 else if (_sender == mWidgetStart)
00230 {
00231
00232 if (mScrollPosition == 0) return;
00233
00234
00235 if (mScrollPosition > mScrollPage) mScrollPosition -= mScrollPage;
00236 else mScrollPosition = 0;
00237
00238
00239 eventScrollChangePosition(this, (int)mScrollPosition);
00240 updateTrack();
00241
00242 }
00243 else if (_sender == mWidgetEnd)
00244 {
00245
00246 if ( (mScrollRange < 2) || (mScrollPosition >= (mScrollRange-1)) ) return;
00247
00248
00249 if ((mScrollPosition + mScrollPage) < (mScrollRange-1)) mScrollPosition += mScrollPage;
00250 else mScrollPosition = mScrollRange - 1;
00251
00252
00253 eventScrollChangePosition(this, (int)mScrollPosition);
00254 updateTrack();
00255
00256 }
00257 else if (_sender == mWidgetFirstPart)
00258 {
00259
00260 if (mScrollPosition == 0) return;
00261
00262
00263 if (mScrollPosition > mScrollViewPage) mScrollPosition -= mScrollViewPage;
00264 else mScrollPosition = 0;
00265
00266
00267 eventScrollChangePosition(this, (int)mScrollPosition);
00268 updateTrack();
00269
00270 }
00271 else if (_sender == mWidgetSecondPart)
00272 {
00273
00274 if ( (mScrollRange < 2) || (mScrollPosition >= (mScrollRange-1)) ) return;
00275
00276
00277 if ((mScrollPosition + mScrollViewPage) < (mScrollRange-1)) mScrollPosition += mScrollViewPage;
00278 else mScrollPosition = mScrollRange - 1;
00279
00280
00281 eventScrollChangePosition(this, (int)mScrollPosition);
00282 updateTrack();
00283
00284 }
00285 else if (_sender == mWidgetTrack)
00286 {
00287 mPreActionOffset.left = _sender->getLeft();
00288 mPreActionOffset.top = _sender->getTop();
00289 }
00290 }
00291
00292 void VScroll::notifyMouseReleased(WidgetPtr _sender, int _left, int _top, MouseButton _id)
00293 {
00294 updateTrack();
00295 }
00296
00297 void VScroll::notifyMouseDrag(WidgetPtr _sender, int _left, int _top)
00298 {
00299 TrackMove(_left, _top);
00300 }
00301
00302 void VScroll::setScrollRange(size_t _range)
00303 {
00304 if (_range == mScrollRange) return;
00305 mScrollRange = _range;
00306 mScrollPosition = (mScrollPosition < mScrollRange) ? mScrollPosition : 0;
00307 updateTrack();
00308 }
00309
00310 void VScroll::setScrollPosition(size_t _position)
00311 {
00312 if (_position == mScrollPosition) return;
00313 if (_position >= mScrollRange) _position = 0;
00314 mScrollPosition = _position;
00315 updateTrack();
00316 }
00317
00318 void VScroll::setPosition(const IntPoint& _point)
00319 {
00320 Base::setPosition(_point);
00321 }
00322
00323 void VScroll::setSize(const IntSize& _size)
00324 {
00325 Base::setSize(_size);
00326
00327 updateTrack();
00328 }
00329
00330 void VScroll::setCoord(const IntCoord& _coord)
00331 {
00332 Base::setCoord(_coord);
00333
00334 updateTrack();
00335 }
00336
00337 void VScroll::setTrackSize(int _size)
00338 {
00339 mWidgetTrack->setSize(mWidgetTrack->getWidth(), ((int)_size < (int)mMinTrackSize)? (int)mMinTrackSize : (int)_size);
00340 updateTrack();
00341 }
00342
00343 int VScroll::getTrackSize()
00344 {
00345 return mWidgetTrack->getHeight();
00346 }
00347
00348 int VScroll::getLineSize()
00349 {
00350 return mCoord.height - (int)(mSkinRangeStart + mSkinRangeEnd);
00351 }
00352
00353 void VScroll::onMouseWheel(int _rel)
00354 {
00355 notifyMouseWheel(nullptr, _rel);
00356
00357 Base::onMouseWheel(_rel);
00358 }
00359
00360 void VScroll::notifyMouseWheel(WidgetPtr _sender, int _rel)
00361 {
00362 if (mScrollRange < 2) return;
00363
00364 int offset = mScrollPosition;
00365 if (_rel < 0) offset += SCROLL_MOUSE_WHEEL;
00366 else offset -= SCROLL_MOUSE_WHEEL;
00367
00368 if (offset < 0) offset = 0;
00369 else if (offset > (int)(mScrollRange - 1)) offset = mScrollRange - 1;
00370
00371 if ((size_t)offset != mScrollPosition) {
00372 mScrollPosition = offset;
00373
00374 eventScrollChangePosition(this, (int)mScrollPosition);
00375 updateTrack();
00376 }
00377 }
00378
00379 void VScroll::setProperty(const std::string& _key, const std::string& _value)
00380 {
00381 if (_key == "Scroll_Range") setScrollRange(utility::parseValue<size_t>(_value));
00382 else if (_key == "Scroll_Position") setScrollPosition(utility::parseValue<size_t>(_value));
00383 else if (_key == "Scroll_Page") setScrollPage(utility::parseValue<size_t>(_value));
00384 else if (_key == "Scroll_ViewPage") setScrollViewPage(utility::parseValue<size_t>(_value));
00385 else if (_key == "Scroll_MoveToClick") setMoveToClick(utility::parseValue<bool>(_value));
00386 else Base::setProperty(_key, _value);
00387 }
00388
00389 }