1 /*
2  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3  * Distributed under the MIT License
4  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5  */
6 
7 #include "MyGUI_Precompiled.h"
8 #include "MyGUI_ScrollViewBase.h"
9 #include "MyGUI_ScrollBar.h"
10 
11 namespace MyGUI
12 {
13 
ScrollViewBase()14 	ScrollViewBase::ScrollViewBase() :
15 		mVScroll(nullptr),
16 		mHScroll(nullptr),
17 		mScrollViewClient(nullptr),
18 		mVisibleHScroll(true),
19 		mVisibleVScroll(true),
20 		mVRange(0),
21 		mHRange(0),
22 		mChangeContentByResize(false)
23 	{
24 	}
25 
updateScrollSize()26 	void ScrollViewBase::updateScrollSize()
27 	{
28 		if (mScrollViewClient == nullptr)
29 			return;
30 
31 		eraseContent();
32 		IntSize contentSize = getContentSize();
33 		IntSize viewSize = getViewSize();
34 
35 		// вертикальный контент не помещается
36 		if (contentSize.height > viewSize.height)
37 		{
38 			if (mVScroll != nullptr)
39 			{
40 				if (!mVScroll->getVisible() && mVisibleVScroll)
41 				{
42 					mVScroll->setVisible(true);
43 					mScrollViewClient->setSize(mScrollViewClient->getWidth() - mVScroll->getWidth(), mScrollViewClient->getHeight());
44 
45 					// размер может измениться
46 					if (mChangeContentByResize)
47 					{
48 						eraseContent();
49 						contentSize = getContentSize();
50 						viewSize = getViewSize();
51 					}
52 
53 					if (mHScroll != nullptr)
54 					{
55 						mHScroll->setSize(mHScroll->getWidth() - mVScroll->getWidth(), mHScroll->getHeight());
56 
57 						// если показали вертикальный скрол бар, уменьшилось вью по горизонтали,
58 						// пересчитываем горизонтальный скрол на предмет показа
59 						if ((contentSize.width > viewSize.width) && ( ! mHScroll->getVisible()) && (mVisibleHScroll))
60 						{
61 							mHScroll->setVisible(true);
62 							mScrollViewClient->setSize(mScrollViewClient->getWidth(), mScrollViewClient->getHeight() - mHScroll->getHeight());
63 							mVScroll->setSize(mVScroll->getWidth(), mVScroll->getHeight() - mHScroll->getHeight());
64 
65 							// размер может измениться
66 							if (mChangeContentByResize)
67 							{
68 								eraseContent();
69 								contentSize = getContentSize();
70 								viewSize = getViewSize();
71 							}
72 
73 						}
74 					}
75 				}
76 			}
77 		}
78 		// вертикальный контент помещается
79 		else
80 		{
81 			if (mVScroll != nullptr)
82 			{
83 				if (mVScroll->getVisible())
84 				{
85 					mVScroll->setVisible(false);
86 					mScrollViewClient->setSize(mScrollViewClient->getWidth() + mVScroll->getWidth(), mScrollViewClient->getHeight());
87 
88 					// размер может измениться
89 					if (mChangeContentByResize)
90 					{
91 						eraseContent();
92 						contentSize = getContentSize();
93 						viewSize = getViewSize();
94 					}
95 
96 					if (mHScroll != nullptr)
97 					{
98 						mHScroll->setSize(mHScroll->getWidth() + mVScroll->getWidth(), mHScroll->getHeight());
99 
100 						// если скрыли вертикальный скрол бар, увеличилось вью по горизонтали,
101 						// пересчитываем горизонтальный скрол на предмет скрытия
102 						if ((contentSize.width <= viewSize.width) && (mHScroll->getVisible()))
103 						{
104 							mHScroll->setVisible(false);
105 							mScrollViewClient->setSize(mScrollViewClient->getWidth(), mScrollViewClient->getHeight() + mHScroll->getHeight());
106 							mVScroll->setSize(mVScroll->getWidth(), mVScroll->getHeight() + mHScroll->getHeight());
107 
108 							// размер может измениться
109 							if (mChangeContentByResize)
110 							{
111 								eraseContent();
112 								contentSize = getContentSize();
113 								viewSize = getViewSize();
114 							}
115 
116 						}
117 					}
118 				}
119 			}
120 		}
121 
122 
123 		// горизонтальный контент не помещается
124 		if (contentSize.width > viewSize.width)
125 		{
126 			if (mHScroll != nullptr)
127 			{
128 				if (!mHScroll->getVisible() && mVisibleHScroll)
129 				{
130 					mHScroll->setVisible(true);
131 					mScrollViewClient->setSize(mScrollViewClient->getWidth(), mScrollViewClient->getHeight() - mHScroll->getHeight());
132 
133 					// размер может измениться
134 					if (mChangeContentByResize)
135 					{
136 						eraseContent();
137 						contentSize = getContentSize();
138 						viewSize = getViewSize();
139 					}
140 
141 					if (mVScroll != nullptr)
142 					{
143 						mVScroll->setSize(mVScroll->getWidth(), mVScroll->getHeight() - mHScroll->getHeight());
144 
145 						// если показали горизонтальный скрол бар, уменьшилось вью по вертикали,
146 						// пересчитываем вертикальный скрол на предмет показа
147 						if ((contentSize.height > viewSize.height) && ( ! mVScroll->getVisible()) && (mVisibleVScroll))
148 						{
149 							mVScroll->setVisible(true);
150 							mScrollViewClient->setSize(mScrollViewClient->getWidth() - mVScroll->getWidth(), mScrollViewClient->getHeight());
151 							mHScroll->setSize(mHScroll->getWidth() - mVScroll->getWidth(), mHScroll->getHeight());
152 
153 							// размер может измениться
154 							if (mChangeContentByResize)
155 							{
156 								eraseContent();
157 								contentSize = getContentSize();
158 								viewSize = getViewSize();
159 							}
160 
161 						}
162 					}
163 				}
164 			}
165 		}
166 		// горизонтальный контент помещается
167 		else
168 		{
169 			if (mHScroll != nullptr)
170 			{
171 				if (mHScroll->getVisible())
172 				{
173 					mHScroll->setVisible(false);
174 					mScrollViewClient->setSize(mScrollViewClient->getWidth(), mScrollViewClient->getHeight() + mHScroll->getHeight());
175 
176 					// размер может измениться
177 					if (mChangeContentByResize)
178 					{
179 						eraseContent();
180 						contentSize = getContentSize();
181 						viewSize = getViewSize();
182 					}
183 
184 					if (mVScroll != nullptr)
185 					{
186 						mVScroll->setSize(mVScroll->getWidth(), mVScroll->getHeight() + mHScroll->getHeight());
187 
188 						// если скрыли горизонтальный скрол бар, увеличилось вью по вертикали,
189 						// пересчитываем вертикальный скрол на предмет скрытия
190 						if ((contentSize.height <= viewSize.height) && (mVScroll->getVisible()))
191 						{
192 							mVScroll->setVisible(false);
193 							mScrollViewClient->setSize(mScrollViewClient->getWidth() + mVScroll->getWidth(), mScrollViewClient->getHeight());
194 							mHScroll->setSize(mHScroll->getWidth() + mVScroll->getWidth(), mHScroll->getHeight());
195 
196 							// размер может измениться
197 							if (mChangeContentByResize)
198 							{
199 								eraseContent();
200 								contentSize = getContentSize();
201 								viewSize = getViewSize();
202 							}
203 						}
204 					}
205 				}
206 			}
207 		}
208 
209 		mVRange = (viewSize.height >= contentSize.height) ? 0 : contentSize.height - viewSize.height;
210 		mHRange = (viewSize.width >= contentSize.width) ? 0 : contentSize.width - viewSize.width;
211 
212 		if (mVScroll != nullptr)
213 		{
214 			size_t page = getVScrollPage();
215 			mVScroll->setScrollPage(page);
216 			mVScroll->setScrollViewPage(viewSize.height > (int)page ? viewSize.height : page);
217 			mVScroll->setScrollRange(mVRange + 1);
218 			if (contentSize.height) mVScroll->setTrackSize(int (float(mVScroll->getLineSize() * viewSize.height) / float(contentSize.height)));
219 		}
220 		if (mHScroll != nullptr)
221 		{
222 			size_t page = getHScrollPage();
223 			mHScroll->setScrollPage(page);
224 			mHScroll->setScrollViewPage(viewSize.width > (int)page ? viewSize.width : page);
225 			mHScroll->setScrollRange(mHRange + 1);
226 			if (contentSize.width) mHScroll->setTrackSize(int (float(mHScroll->getLineSize() * viewSize.width) / float(contentSize.width)));
227 		}
228 	}
229 
updateScrollPosition()230 	void ScrollViewBase::updateScrollPosition()
231 	{
232 		// размер контекста
233 		IntSize contentSize = getContentSize();
234 		// текущее смещение контекста
235 		IntPoint contentPoint = getContentPosition();
236 		// расчетное смещение
237 		IntPoint offset = contentPoint;
238 
239 		IntSize viewSize = getViewSize();
240 
241 		Align align = getContentAlign();
242 
243 		if (contentSize.width > viewSize.width)
244 		{
245 			// максимальный выход влево
246 			if ((offset.left + viewSize.width) > contentSize.width)
247 			{
248 				offset.left = contentSize.width - viewSize.width;
249 			}
250 			// максимальный выход вправо
251 			else if (offset.left < 0)
252 			{
253 				offset.left = 0;
254 			}
255 		}
256 		else
257 		{
258 			if (align.isLeft())
259 			{
260 				offset.left = 0;
261 			}
262 			else if (align.isRight())
263 			{
264 				offset.left = contentSize.width - viewSize.width;
265 			}
266 			else
267 			{
268 				offset.left = (contentSize.width - viewSize.width) / 2;
269 			}
270 		}
271 
272 		if (contentSize.height > viewSize.height)
273 		{
274 			// максимальный выход вверх
275 			if ((offset.top + viewSize.height) > contentSize.height)
276 			{
277 				offset.top = contentSize.height - viewSize.height;
278 			}
279 			// максимальный выход вниз
280 			else if (offset.top < 0)
281 			{
282 				offset.top = 0;
283 			}
284 		}
285 		else
286 		{
287 			if (align.isTop())
288 			{
289 				offset.top = 0;
290 			}
291 			else if (align.isBottom())
292 			{
293 				offset.top = contentSize.height - viewSize.height;
294 			}
295 			else
296 			{
297 				offset.top = (contentSize.height - viewSize.height) / 2;
298 			}
299 		}
300 
301 		if (offset != contentPoint)
302 		{
303 			if (nullptr != mVScroll) mVScroll->setScrollPosition(offset.top);
304 			if (nullptr != mHScroll) mHScroll->setScrollPosition(offset.left);
305 			setContentPosition(offset);
306 		}
307 	}
308 
getContentSize()309 	IntSize ScrollViewBase::getContentSize()
310 	{
311 		return IntSize();
312 	}
313 
getContentPosition()314 	IntPoint ScrollViewBase::getContentPosition()
315 	{
316 		return IntPoint();
317 	}
318 
setContentPosition(const IntPoint & _value)319 	void ScrollViewBase::setContentPosition(const IntPoint& _value)
320 	{
321 	}
322 
getViewSize()323 	IntSize ScrollViewBase::getViewSize()
324 	{
325 		return IntSize();
326 	}
327 
getHScrollPage()328 	size_t ScrollViewBase::getHScrollPage()
329 	{
330 		return 1;
331 	}
332 
getVScrollPage()333 	size_t ScrollViewBase::getVScrollPage()
334 	{
335 		return 1;
336 	}
337 
getContentAlign()338 	Align ScrollViewBase::getContentAlign()
339 	{
340 		return Align::Center;
341 	}
342 
eraseContent()343 	void ScrollViewBase::eraseContent()
344 	{
345 	}
346 
347 } // namespace MyGUI
348