1 /*
2    Copyright (c) by Valery Goryachev (Wal)
3 */
4 
5 
6 #include "swl.h"
7 
8 namespace wal
9 {
10 
11 
12 #define SB_WIDTH 16
13 
14 	int uiClassScrollBar = GetUiID( "ScrollBar" );
UiGetClassId()15 	int ScrollBar::UiGetClassId() {   return uiClassScrollBar; }
16 
Draw3DButtonW1(GC & gc,crect r,unsigned bg,bool up)17 	void Draw3DButtonW1( GC& gc, crect r, unsigned bg, bool up )
18 	{
19 		static unsigned hp1, lp1;
20 		static unsigned lastBg = 0;
21 		static bool initialized = false;
22 
23 		if ( !initialized || lastBg != bg )
24 		{
25 			hp1 = ColorTone( bg, 200 );
26 			lp1 = ColorTone( bg, -150 );
27 			lastBg = bg;
28 			initialized = true;
29 		}
30 
31 		unsigned php1, plp1;
32 
33 		if ( up )
34 		{
35 			php1 = hp1;
36 			plp1 = lp1;
37 		}
38 		else
39 		{
40 			php1 = lp1;
41 			plp1 = hp1;
42 		}
43 
44 		gc.SetLine( plp1 );
45 		gc.MoveTo( r.right - 1, r.top );
46 		gc.LineTo( r.right - 1, r.bottom - 1 );
47 		gc.LineTo( r.left, r.bottom - 1 );
48 		gc.SetLine( php1 );
49 		gc.LineTo( r.left, r.top );
50 		gc.LineTo( r.right - 1, r.top );
51 	}
52 
53 	/*
54 	types:
55 	   1 -left 2 - right 3 - horisontal slider
56 	   4 - up 5 - down   6 - vert. slider
57 	*/
SBCDrawButton(GC & gc,crect rect,int type,unsigned bg,bool pressed)58 	void SBCDrawButton( GC& gc, crect rect, int type, unsigned bg, bool pressed )
59 	{
60 		static unsigned short up[] = {6, 0x10, 0x38, 0x7c, 0xee, 0x1c7, 0x82};
61 		static unsigned short down[] = {6, 0x82, 0x1c7, 0xee, 0x7c, 0x38, 0x10,};
62 		static unsigned short left[] = {9, 0x10, 0x38, 0x1c, 0x0e, 0x07, 0x0e, 0x1c, 0x38, 0x10};
63 		static unsigned short right[] = {9, 0x02, 0x07, 0x0E, 0x1c, 0x38, 0x1c, 0x0e, 0x07, 0x02};
64 		DrawBorder( gc, rect, ColorTone( bg, -100 ) );
65 		rect.Dec();
66 		Draw3DButtonW1( gc, rect, bg, !pressed );
67 		//rect.Dec();
68 		rect.Dec();
69 		gc.SetFillColor( bg );
70 		gc.FillRect( rect );
71 		int xPlus = 0;
72 		int yPlus = 0;
73 
74 		if ( pressed )
75 		{
76 			// xPlus = 1;
77 			yPlus = 1;
78 		}
79 
80 		unsigned color = ColorTone( bg, -200 );
81 
82 		switch ( type )
83 		{
84 			case 1:
85 				DrawPixelList( gc, left, rect.left + ( rect.Width() - 6 ) / 2 + xPlus, rect.top + ( rect.Height() - 9 ) / 2 + yPlus, color );
86 				break;
87 
88 			case 2:
89 				DrawPixelList( gc, right, rect.left + ( rect.Width() - 6 ) / 2 + xPlus, rect.top + ( rect.Height() - 9 ) / 2 + yPlus, color );
90 				break;
91 
92 			case 4:
93 				DrawPixelList( gc, up, rect.left + ( rect.Width() - 9 ) / 2 + xPlus, rect.top + ( rect.Height() - 6 ) / 2 + yPlus, color );
94 				break;
95 
96 			case 5:
97 				DrawPixelList( gc, down, rect.left + ( rect.Width() - 9 ) / 2 + xPlus, rect.top + ( rect.Height() - 6 ) / 2 + yPlus, color );
98 				break;
99 		};
100 	}
101 
ScrollBar(int nId,Win * parent,bool _vertical,bool _autoHide,crect * rect)102 	ScrollBar::ScrollBar( int nId, Win* parent, bool _vertical, bool _autoHide, crect* rect )
103 		:  Win( Win::WT_CHILD, 0, parent, rect, nId ),
104 		   vertical( _vertical ),
105 		   si( 100, 10, 0 ),
106 		   len( 0 ),
107 		   bsize( 0 ),
108 		   bpos( 0 ),
109 		   trace( false ),
110 		   traceBPoint( 0 ),
111 		   autoHide( _autoHide ),
112 		   b1Pressed( false ),
113 		   b2Pressed( false ),
114 		   managedWin( 0 )
115 	{
116 		LSize ls;
117 		int l = SB_WIDTH * 2;// + 2;// + 5;
118 		int h = SB_WIDTH;// + 2;
119 
120 		if ( vertical )
121 		{
122 			ls.Set( cpoint( h, l ) );
123 			ls.y.maximal = 16000;
124 		}
125 		else
126 		{
127 			ls.Set( cpoint( l, h ) );
128 			ls.x.maximal = 16000;
129 		}
130 
131 		SetLSize( ls );
132 		SetScrollInfo( nullptr );
133 //	crect r = ClientRect();
134 //	EventSize(&cevent_size(cpoint(r.Width(),r.Height())));
135 	}
136 
Paint(GC & gc,const crect & paintRect)137 	void ScrollBar::Paint( GC& gc, const crect& paintRect )
138 	{
139 		crect cr = ClientRect();
140 		unsigned bgColor = UiGetColor( uiBackground, 0, 0, 0xD8E9EC );/*GetColor(IC_SCROLL_BG)*/;
141 		unsigned btnColor = UiGetColor( uiButtonColor, 0, 0, 0xD8E9EC ); //GetColor(IC_SCROLL_BUTTON);
142 		gc.SetFillColor( bgColor );
143 		gc.FillRect( cr );
144 		DrawBorder( gc, cr, UiGetColor( uiColor, 0, 0, 0xD8E9EC )/*GetColor(IC_SCROLL_BORDER)*/ );
145 
146 		if ( !b1Rect.IsEmpty() ) { SBCDrawButton( gc, b1Rect, vertical ? 4 : 1, btnColor, b1Pressed ); }
147 
148 		if ( !b2Rect.IsEmpty() ) { SBCDrawButton( gc, b2Rect, vertical ? 5 : 2, btnColor, b2Pressed ); }
149 
150 		if ( !b3Rect.IsEmpty() ) { SBCDrawButton( gc, b3Rect, vertical ? 6 : 3, btnColor, false ); }
151 	}
152 
SetScrollInfo(ScrollInfo * s)153 	void ScrollBar::SetScrollInfo( ScrollInfo* s )
154 	{
155 		ScrollInfo ns;
156 
157 		if ( s ) { ns = *s; }
158 		else
159 		{
160 			ns.m_Size = ns.m_PageSize = ns.m_Pos = 0;
161 		}
162 
163 		if ( ns.m_Size < 0 ) { ns.m_Size = 0; }
164 
165 		if ( ns.m_PageSize < 0 ) { ns.m_PageSize = 0; }
166 
167 		if ( ns.m_Pos < 0 ) { ns.m_Pos = 0; }
168 
169 		if ( si == ns ) { return; }
170 
171 		si = ns;
172 
173 		Recalc();
174 
175 		if ( si.m_AlwaysHidden )
176 		{
177 			Hide();
178 
179 			if ( Parent() ) { Parent()->RecalcLayouts(); }
180 		}
181 		else if ( autoHide )
182 		{
183 			bool v = IsVisible();
184 
185 			if ( si.m_Size <= si.m_PageSize && si.m_Pos <= 0 )
186 			{
187 				if ( v )
188 				{
189 					Hide();
190 
191 					if ( Parent() ) { Parent()->RecalcLayouts(); }
192 				}
193 			}
194 			else
195 			{
196 				if ( !v )
197 				{
198 					Show();
199 
200 					if ( Parent() ) { Parent()->RecalcLayouts(); }
201 				}
202 			}
203 		}
204 		else
205 		{
206 			Show();
207 
208 			if ( Parent() ) { Parent()->RecalcLayouts(); }
209 		}
210 
211 		Invalidate();
212 	}
213 
Recalc(cpoint * newSize)214 	void ScrollBar::Recalc( cpoint* newSize )
215 	{
216 		cpoint cs;
217 
218 		if ( newSize ) { cs = *newSize; }
219 		else
220 		{
221 			crect r = ClientRect();
222 			cs.Set( r.Width(), r.Height() );
223 		}
224 
225 		int s = vertical ?   cs.y :   cs.x;
226 		b1Rect.Set( 0, 0, SB_WIDTH, SB_WIDTH );
227 
228 		if ( vertical )
229 		{
230 			b2Rect.Set( 0, s - SB_WIDTH, SB_WIDTH, s );
231 		}
232 		else
233 		{
234 			b2Rect.Set( s - SB_WIDTH , 0 , s, SB_WIDTH );
235 		}
236 
237 		len = s - SB_WIDTH * 2; // - 2;
238 
239 		b3Rect.Zero();
240 
241 		bpos = 0;
242 
243 		if ( len <= 0 ) { return; }
244 
245 		if ( si.m_Size <= 0 ) { return; }
246 
247 		if ( si.m_PageSize <= 0 || si.m_PageSize >= si.m_Size ) { return; }
248 
249 		bsize = int( ( int64_t( len ) * si.m_PageSize ) / si.m_Size );
250 
251 		if ( bsize < 5 ) { bsize = 5; }
252 
253 		if ( len <= bsize ) { return; }
254 
255 		int space = ( len - bsize );
256 
257 		bpos = int( ( int64_t( space ) * si.m_Pos ) / ( si.m_Size - si.m_PageSize ) );
258 
259 		if ( bpos > space ) { bpos = space; }
260 
261 		int n = SB_WIDTH + bpos;
262 
263 		if ( vertical )
264 		{
265 			b3Rect.Set( 0, n, SB_WIDTH, n + bsize );
266 		}
267 		else
268 		{
269 			b3Rect.Set( n , 0 , n + bsize, SB_WIDTH );
270 		}
271 	}
272 
EventSize(cevent_size * pEvent)273 	void ScrollBar::EventSize( cevent_size* pEvent )
274 	{
275 		Recalc( &( pEvent->Size() ) );
276 	}
277 
Command(int id,int subId,Win * win,void * data)278 	bool ScrollBar::Command( int id, int subId, Win* win, void* data )
279 	{
280 		if ( id != CMD_SCROLL_INFO || win != managedWin ) { return false; }
281 
282 		if ( ( vertical && subId != SCMD_SCROLL_VCHANGE ) || ( !vertical && subId != SCMD_SCROLL_HCHANGE ) ) { return false; }
283 
284 		SetScrollInfo( ( ScrollInfo* )data );
285 		return true;
286 	}
287 
SendManagedCmd(int subId,void * data)288 	void ScrollBar::SendManagedCmd( int subId, void* data )
289 	{
290 		if ( managedWin )
291 		{
292 			managedWin->Command( CMD_SCROLL_INFO, subId, this, data );
293 		}
294 		else if ( Parent() )
295 		{
296 			Parent()->Command( CMD_SCROLL_INFO, subId, this, data );
297 		}
298 	}
299 
EventTimer(int tid)300 	void ScrollBar::EventTimer( int tid )
301 	{
302 		SendManagedCmd( tid, 0 );
303 	}
304 
EventMouse(cevent_mouse * pEvent)305 	bool ScrollBar::EventMouse( cevent_mouse* pEvent )
306 	{
307 		switch ( pEvent->Type() )
308 		{
309 
310 			case EV_MOUSE_MOVE:
311 				if ( trace )
312 				{
313 					int p = vertical ? ( pEvent->Point().y - b1Rect.bottom )
314 					        : ( pEvent->Point().x - b1Rect.right );
315 					p -= traceBPoint;
316 					int n = len - bsize;
317 
318 					if ( n <= 0 ) { break; }
319 
320 					//if (p>=n) p = n-1;
321 					//if (p<0) p = 0;
322 
323 					int n1 = int( si.m_Size - si.m_PageSize );
324 					int x = ( int64_t( p ) * n1 ) / n;
325 
326 					if ( x >= n1 ) { x = n1; }
327 
328 					if ( x < 0 ) { x = 0; }
329 
330 					SendManagedCmd( SCMD_SCROLL_TRACK, &x ); //(void*)x);
331 				}
332 
333 				break;
334 
335 			case EV_MOUSE_DOUBLE:
336 			case EV_MOUSE_PRESS:
337 				if ( pEvent->Button() != MB_L )
338 				{
339 					break;
340 				}
341 
342 				{
343 					int subId = 0;
344 
345 					if ( b1Rect.In( pEvent->Point() ) )
346 					{
347 						b1Pressed = true;
348 						subId = ( vertical ) ? SCMD_SCROLL_LINE_UP : SCMD_SCROLL_LINE_LEFT;
349 					}
350 					else if ( b2Rect.In( pEvent->Point() ) )
351 					{
352 						b2Pressed = true;
353 						subId = ( vertical ) ? SCMD_SCROLL_LINE_DOWN : SCMD_SCROLL_LINE_RIGHT;
354 					}
355 					else if ( b3Rect.In( pEvent->Point() ) )
356 					{
357 						traceBPoint = ( vertical ) ? ( pEvent->Point().y - b3Rect.top ) : ( pEvent->Point().x - b3Rect.left );
358 						trace = true;
359 						SetCapture( &captureSD );
360 						break;
361 					}
362 					else if ( !b3Rect.IsEmpty() )
363 					{
364 						if ( vertical )
365 						{
366 							if ( pEvent->Point().y < b3Rect.top )
367 							{
368 								subId = SCMD_SCROLL_PAGE_UP;
369 							}
370 							else
371 							{
372 								subId = SCMD_SCROLL_PAGE_DOWN;
373 							}
374 						}
375 						else
376 						{
377 							if ( pEvent->Point().x < b3Rect.left )
378 							{
379 								subId = SCMD_SCROLL_PAGE_LEFT;
380 							}
381 							else
382 							{
383 								subId = SCMD_SCROLL_PAGE_RIGHT;
384 							}
385 						}
386 					}
387 
388 					if ( subId != 0 )
389 					{
390 						SetCapture( &captureSD );
391 						SendManagedCmd( subId, 0 );
392 						SetTimer( subId, 100 );
393 					}
394 				}
395 
396 				this->Invalidate();
397 				break;
398 
399 			case EV_MOUSE_RELEASE:
400 				if ( pEvent->Button() != MB_L )
401 				{
402 					break;
403 				}
404 
405 				if ( IsCaptured() )
406 				{
407 					b1Pressed = false ;
408 					b2Pressed = false ;
409 					ReleaseCapture( &captureSD );
410 					DelAllTimers();
411 					Invalidate();
412 					trace = false;
413 				}
414 
415 				break;
416 
417 			default:
418 				;
419 		}
420 
421 		return true;
422 	}
423 
~ScrollBar()424 	ScrollBar::~ScrollBar() {}
425 
426 
427 }; //namespace wal
428