PageRenderTime 76ms CodeModel.GetById 10ms app.highlight 60ms RepoModel.GetById 2ms app.codeStats 0ms

/gui/vscrollbar.d

http://github.com/wilkie/djehuty
D | 681 lines | 439 code | 191 blank | 51 comment | 124 complexity | 071f80323257b0e34810b9114a968b69 MD5 | raw file
  1module gui.vscrollbar;
  2
  3import gui.widget;
  4
  5import core.color;
  6import core.definitions;
  7import core.string;
  8import core.event;
  9
 10import graphics.graphics;
 11
 12import synch.timer;
 13
 14template ControlPrintCSTRList() {
 15	const char[] ControlPrintCSTRList = `
 16	this(int x, int y, int width, int height) {
 17		super(x,y,width,height);
 18	}
 19	`;
 20}
 21
 22
 23// Description: This control provides a standard vertical scroll bar.
 24class VScrollBar : Widget {
 25public:
 26
 27	enum Signal : uint {
 28		Selected,
 29		Unselected,
 30		Scrolled,
 31	}
 32
 33	this(int x, int y, int width, int height) {
 34		super(x,y,width,height);
 35
 36		m_min = 0;
 37		m_max = 30;
 38		m_value = 0;
 39
 40		m_small_change = 1;
 41		m_large_change = 10;
 42
 43		m_clroutline = Color.fromRGB(0x80,0x80,0x80);
 44		m_clrarea = Color.fromRGB(0xe0, 0xe0, 0xe0);
 45		m_clrbutton = Color.fromRGB(0xc0, 0xc0, 0xc0);
 46		m_clrhighlight = Color.fromRGB(0xdd, 0xdd, 0xdd);
 47		m_clrnormal = Color.fromRGB(0,0,0);
 48		m_clrthumb = Color.fromRGB(0xc0, 0xc0, 0xc0);
 49		m_clrhover = Color.fromRGB(0xdd, 0xdd, 0xdd);
 50
 51		_readyTimer = new Timer();
 52		_clickTimer = new Timer();
 53
 54		_clickTimer.setInterval(50);
 55		_readyTimer.setInterval(100);
 56
 57		push(_readyTimer);
 58		push(_clickTimer);
 59	}
 60
 61	override void onAdd() {
 62		m_whatishovered = 0;
 63		m_isclicked=0;
 64	}
 65
 66	override bool onSignal(Dispatcher dsp, uint signal) {
 67		if (dsp is _readyTimer) {
 68			readyTimerProc();
 69		}
 70		else if (dsp is _clickTimer) {
 71			clickTimerProc();
 72		}
 73		return true;
 74	}
 75
 76	override void onDraw(ref Graphics g) {
 77		//a scroll bar is just a few rectangles (4)
 78		//one rectangle for the min arrow, one for max arrow
 79		//one more for the body
 80		//one more for the thumb
 81
 82		long total_value_space = m_large_change + (m_max - m_min);
 83
 84		double percent = cast(double)m_large_change / cast(double)total_value_space;
 85
 86		m_area = (this.height - (this.width*2))+2;
 87
 88		m_thumb_size = cast(int)(cast(double)m_area * percent);
 89
 90		if (m_thumb_size < 10) { m_thumb_size = 10; }
 91
 92		m_area -= m_thumb_size;
 93
 94		percent = cast(double)(m_value - m_min) / cast(double)(m_max - m_min);
 95		m_thumb_pos_y = cast(int)(cast(double)m_area * percent) + this.top + this.width-1;
 96		m_thumb_pos_b = m_thumb_pos_y + m_thumb_size;
 97
 98		//BODY
 99
100		Brush brsh = new Brush(m_clrarea);
101		Pen pen = new Pen(m_clroutline);
102
103		g.pen = pen;
104		g.brush = brsh;
105
106		g.drawRect(this.left, this.top, this.width,this.height);
107
108		brsh.setColor(m_clrbutton);
109
110		g.drawRect(this.left, this.top, this.width, this.width);
111		g.drawRect(this.left, this.bottom-this.width, this.width, this.width);
112
113		//THUMB
114
115		brsh.setColor(m_clrthumb);
116
117		g.drawRect(this.left, m_thumb_pos_y, this.width, m_thumb_size);
118
119		//Draw triangle images...
120
121		//draw UP BUTTON
122
123		brsh.setColor(m_clrnormal);
124		pen.setColor(m_clrnormal);
125
126		Pen pen_hlight = new Pen(m_clrhighlight);
127		Brush brsh_hlight = new Brush(m_clrhighlight);
128
129		if (m_whatishovered == 1) {
130			g.brush = (brsh_hlight);
131			g.pen = (pen_hlight);
132		}
133
134		int base, height;
135
136		height = (this.width / 4); //height
137
138		//from the 'height' we can draw a perfect triangle
139
140		base = (height*2) - 1; //base
141
142		int xH,yB; //main directional point of triangle:
143
144		xH = this.left + ((this.width - base)/2);
145		yB = this.top + ((this.width - height) /2);
146
147		base--;
148		height--;
149
150		Coord pnt[3] = [ Coord(xH+(base/2),yB), Coord(xH,yB+height), Coord(xH+base,yB+height) ];
151
152		if (m_isclicked == 1) {
153			pnt[0].x+=1;
154			pnt[0].y+=1;
155			pnt[1].x+=1;
156			pnt[1].y+=1;
157			pnt[2].x+=1;
158			pnt[2].y+=1;
159		}
160
161		//DRAW_TRIANGLE(pnt);
162
163		//draw DOWN BUTTON
164
165		yB = this.bottom - ((this.width - height + 1)/2);
166
167		Coord pnt2[3] = [ Coord(xH+(base/2),yB), Coord(xH,yB-height), Coord(xH+base,yB-height) ];
168
169		if (m_whatishovered == 2) {
170			g.brush = (brsh_hlight);
171			g.pen = (pen_hlight);
172		}
173		else {
174			if (m_whatishovered == 1) {
175				g.brush = (brsh);
176				g.pen = (pen);
177			}
178		}
179
180		if (m_isclicked == 2) {
181			pnt2[0].x+=1;
182			pnt2[0].y+=1;
183			pnt2[1].x+=1;
184			pnt2[1].y+=1;
185			pnt2[2].x+=1;
186			pnt2[2].y+=1;
187		}
188
189		//DRAW_TRIANGLE(pnt2);
190
191		pen.setColor(m_clroutline);
192
193		//THUMB BAR LINE DESIGN
194
195		g.pen = (pen);
196
197		int new_x = this.left + 2;
198		int new_r = this.right - 2;
199
200		if (m_thumb_size > 80 + base+4) {
201			for (height = 10; height < 40; height+=4) {
202				g.drawLine(new_x, height+m_thumb_pos_y, new_r, height+m_thumb_pos_y);
203			}
204
205			//highlight pen
206			g.pen = (pen_hlight);
207
208			for (height = 11; height < 41; height+=4) {
209				g.drawLine(new_x, height+m_thumb_pos_y, new_r, height+m_thumb_pos_y);
210			}
211
212			//outline pen
213			g.pen = (pen);
214
215			for (height = m_thumb_size - 39; height < m_thumb_size - 9; height+=4) {
216				g.drawLine(new_x, height+m_thumb_pos_y, new_r, height+m_thumb_pos_y);
217			}
218
219			//highlight pen
220			g.pen = (pen_hlight);
221
222			for (height = m_thumb_size - 38; height < m_thumb_size - 8; height+=4) {
223				g.drawLine(new_x, height+m_thumb_pos_y, new_r, height+m_thumb_pos_y);
224			}
225
226			//draw rectangle
227
228			yB = m_thumb_pos_y + ((m_thumb_size - base) / 2);
229
230			if (m_whatishovered == 3) {
231				g.brush = (brsh_hlight);
232
233				g.drawRect(xH, yB, base, base);
234
235				pen.setColor(m_clrnormal);
236			}
237			else {
238				pen.setColor(m_clrnormal);
239
240				g.brush = (brsh);
241				g.pen = (pen);
242
243				g.drawRect(xH, yB, base, base);
244			}
245		}
246		else if (m_thumb_size > 25) {
247			//find the rectangle's position
248			//draw lines outward from that...
249
250			yB = m_thumb_pos_y + ((m_thumb_size - base) / 2);
251
252			//height = 10; height < 40
253
254			//total_value_space is a counter; counts the number of lines that will fit
255			for (total_value_space=0, height = yB + base + 2; height < m_thumb_pos_y + m_thumb_size - 9; height+=4, total_value_space++) {
256				g.drawLine(new_x, height, new_r, height);
257			}
258			for (height = yB-3 ; total_value_space > 0; height-=4, total_value_space--) {
259				g.drawLine(new_x, height, new_r, height);
260			}
261
262			//highlight pen
263			g.pen = (pen_hlight);
264
265			for (total_value_space=0, height = yB + base+3; height < m_thumb_pos_y + m_thumb_size - 8; height+=4, total_value_space++) {
266				g.drawLine(new_x, height, new_r, height);
267			}
268			for (height = yB-2; total_value_space > 0; height-=4, total_value_space--) {
269				g.drawLine(new_x, height, new_r, height);
270			}
271
272			if (m_whatishovered == 3) {
273				g.brush = (brsh_hlight);
274
275				g.drawRect(xH, yB, base, base);
276
277				pen.setColor(m_clrnormal);
278			}
279			else {
280				pen.setColor(m_clrnormal);
281
282				g.brush = (brsh);
283				g.pen = (pen);
284
285				g.drawRect(xH, yB, base, base);
286			}
287		}
288		else if(m_thumb_size > 15) {
289			yB = m_thumb_pos_y + ((m_thumb_size - base) / 2);
290
291			if (m_whatishovered == 3) {
292				g.brush = (brsh_hlight);
293				g.pen = (pen_hlight);
294
295				g.drawRect(xH, yB, base, base);
296
297				pen.setColor(m_clrnormal);
298			}
299			else {
300				pen.setColor(m_clrnormal);
301
302				g.brush = (brsh);
303				g.pen = (pen);
304
305				g.drawRect(xH, yB, base, base);
306			}
307		}
308
309		g.brush = (brsh);
310		g.pen = (pen_hlight);
311
312		new_x--;
313		new_r++;
314
315		//UP BUTTON
316		if (m_isclicked == 1) {
317			g.pen = (pen);
318
319			g.drawLine(new_x, this.top+1, new_r, this.top+1);
320			g.drawLine(new_x, this.top+1, new_x, this.top+this.width-1);
321
322			g.pen = (pen_hlight);
323		}
324		else
325		{
326			g.drawLine(new_x, this.top+1, new_r, this.top+1);
327			g.drawLine(new_x, this.top+1, new_x, this.top+this.width-1);
328		}
329
330		//DOWN BUTTON
331		if (m_isclicked == 2) {
332			g.pen = (pen);
333
334			g.drawLine(new_x, this.bottom-this.width+1, new_r, this.bottom-this.width+1);
335			g.drawLine(new_x, this.bottom-this.width+1, new_x, this.bottom-1);
336
337			g.pen = (pen_hlight);
338		}
339		else {
340			g.drawLine(new_x, this.bottom-this.width+1, new_r, this.bottom-this.width+1);
341			g.drawLine(new_x, this.bottom-this.width+1, new_x, this.bottom-1);
342		}
343
344		//THUMB BAR
345		if (m_isclicked == 3) {
346			g.pen = (pen);
347
348			g.drawLine(new_x, m_thumb_pos_y+1, new_r, m_thumb_pos_y+1);
349			g.drawLine(new_x, m_thumb_pos_y+1, new_x, m_thumb_pos_b-1);
350
351			g.pen = (pen_hlight);
352		}
353		else {
354			g.drawLine(new_x, m_thumb_pos_y+1, new_r, m_thumb_pos_y+1);
355			g.drawLine(new_x, m_thumb_pos_y+1, new_x, m_thumb_pos_b-1);
356		}
357	}
358
359	override bool onMouseMove(ref Mouse mouseProps) {
360		if (m_isclicked == 3) {
361			//thumb bar is moving
362
363			//move thumb bar and set value accordingly
364
365			mouseProps.y -= m_thumb_offset;
366
367			//y is now the y position of where the thumb would be now
368
369			if (mouseProps.y < this.top + this.width) {
370				mouseProps.y = this.top + this.width;
371			}
372
373			if (mouseProps.y > this.top + this.width + m_area) {
374				mouseProps.y = this.top + this.width + m_area;
375			}
376
377			//compute value
378
379			long old_value = m_value;
380			m_value = ( cast(int) ( ( cast(float)(mouseProps.y - this.top-this.width) / cast(float)(m_area) ) * cast(float)(m_max - m_min) ) ) + m_min;
381
382			if (m_value != old_value) {
383				raiseSignal(Signal.Scrolled);
384				return true;
385			} else {
386				return false;
387			}
388		}
389
390		//check if something is being hovered over
391		if (mouseProps.y > this.top && mouseProps.y < this.bottom && mouseProps.x > this.left && mouseProps.x < this.right) {
392			if (mouseProps.y - this.top < this.width) {
393				//up button
394				if (m_isclicked == 0 || m_isclicked == 1) {
395					if (m_whatishovered != 1) {
396						m_whatishovered = 1;
397
398						return true;
399					}
400				}
401
402				return false;
403			}
404			else if (mouseProps.y > this.bottom - this.width) {
405				//down button
406				if (m_isclicked == 0 || m_isclicked == 2) {
407					if (m_whatishovered != 2) {
408						m_whatishovered = 2;
409
410						return true;
411					}
412				}
413
414				return false;
415			}
416			else if (mouseProps.y > m_thumb_pos_y && mouseProps.y < m_thumb_pos_b) {
417				//thumb bar
418				if (m_isclicked == 0 || m_isclicked == 3) {
419					if (m_whatishovered != 3) {
420						m_whatishovered = 3;
421						return true;
422					}
423				}
424
425				return false;
426			}
427			else if (mouseProps.y < m_thumb_pos_y) {
428				// inner area UP
429
430				m_last_x = mouseProps.x;
431				m_last_y = mouseProps.y;
432
433				if (m_isclicked == 0 || m_isclicked == 4) {
434					if (m_whatishovered != 4) {
435						if (m_whatishovered != 0) {
436							m_whatishovered = 4;
437							return true;
438						}
439
440						m_whatishovered = 4;
441					}
442				}
443
444				return false;
445			}
446			else {
447				//inner area DOWN
448
449				m_last_x = mouseProps.x;
450				m_last_y = mouseProps.y;
451
452				if (m_isclicked == 0 || m_isclicked == 5) {
453					if (m_whatishovered != 5) {
454						if (m_whatishovered != 0) {
455							m_whatishovered = 5;
456							return true;
457						}
458
459						m_whatishovered = 5;
460					}
461				}
462
463				return false;
464			}
465		}
466
467		//nothing
468		if (m_whatishovered != 0) {
469			m_whatishovered = 0;
470
471			return true;
472		}
473
474		return false;
475	}
476
477	override bool onMouseLeave() {
478		if (m_isclicked == 3) {
479			return false;
480		}
481
482		if (m_whatishovered != 0) {
483			m_whatishovered = 0;
484			return true;
485		}
486
487		return false;
488	}
489
490	override bool onPrimaryMouseDown(ref Mouse mouseProps) {
491		if (m_whatishovered != 0) {
492			m_isclicked = m_whatishovered;
493
494			requestCapture();
495
496			if (m_isclicked == 3) {
497				//thumb bar clicked
498
499				//the number of pixels from the left edge of thumb bar is mouse = m_thumb_offset
500				m_thumb_offset = mouseProps.y - m_thumb_pos_y;
501			}
502			else {
503				//buttons / inner area clicked
504
505
506				//stop timers if running
507				_clickTimer.stop();
508				_readyTimer.stop();
509
510				_Move();
511
512				_readyTimer.start();
513			}
514
515			return true;
516		}
517
518		return false;
519	}
520
521	override bool onPrimaryMouseUp(ref Mouse mouseProps) {
522		if (m_isclicked > 0) {
523			if (m_isclicked == 3) {
524				m_isclicked = 0;
525
526				onMouseMove(mouseProps);
527			}
528
529			requestRelease();
530
531			_clickTimer.stop();
532			_readyTimer.stop();
533
534			m_isclicked = 0;
535			return true;
536		}
537
538		return false;
539	}
540
541protected:
542
543	void readyTimerProc() {
544		//create real timer
545		_readyTimer.stop();
546		_clickTimer.start();
547
548		_window.redraw();
549	}
550
551	void clickTimerProc() {
552		_Move();
553
554		_window.redraw();
555	}
556
557	void _Move() {
558		float percent;
559
560		//look at what is currently being hovered over
561		switch (m_whatishovered) {
562		case 1: //left button
563			m_value -= m_small_change;
564			if (m_value<m_min) { m_value = m_min; }
565
566			raiseSignal(Signal.Scrolled);
567
568			break;
569		case 2: //right button
570			m_value += m_small_change;
571			if (m_value>m_max) { m_value = m_max; }
572
573			raiseSignal(Signal.Scrolled);
574
575			break;
576		case 4: //inner area UP
577			m_value -= m_large_change;
578			if (m_value<m_min) { m_value = m_min; }
579
580			//must check to see if we are hovering over the thumb bar
581
582			percent = cast(float)m_large_change / cast(float)(m_large_change + (m_max - m_min));
583
584			m_area = (this.height - (this.width*2))+2;
585
586			m_thumb_size = cast(int)(cast(float)m_area * percent);
587
588			if (m_thumb_size < 10) { m_thumb_size = 10; }
589
590			m_area -= m_thumb_size;
591
592			percent = cast(float)(m_value - m_min) / cast(float)(m_max - m_min);
593			m_thumb_pos_y = cast(int)(cast(float)m_area * percent) + this.top + this.width-1;
594			m_thumb_pos_b = m_thumb_pos_y + m_thumb_size;
595
596			//compare last mouse coords with this state
597
598			if (m_last_y > m_thumb_pos_y && m_last_y < m_thumb_pos_b) {
599				//hmm
600				//stop: we are hovering the thumb bar
601
602				m_whatishovered = 3;
603
604				_clickTimer.stop();
605			}
606
607			raiseSignal(Signal.Scrolled);
608
609			break;
610
611		case 5: //inner area DOWN
612			m_value += m_large_change;
613			if (m_value>m_max) { m_value = m_max; }
614
615			//must check to see if we are hovering over the thumb bar
616
617			percent = cast(float)m_large_change / cast(float)(m_large_change + (m_max - m_min));
618
619			m_area = (this.height - (this.width*2))+2;
620
621			m_thumb_size = cast(int)(cast(float)m_area * percent);
622
623			if (m_thumb_size < 10) { m_thumb_size = 10; }
624
625			m_area -= m_thumb_size;
626
627			percent = cast(float)(m_value - m_min) / cast(float)(m_max - m_min);
628			m_thumb_pos_y = cast(int)(cast(float)m_area * percent) + this.top + this.width-1;
629			m_thumb_pos_b = m_thumb_pos_y + m_thumb_size;
630
631			//compare last mouse coords with this state
632
633			if (m_last_y >= m_thumb_pos_y && m_last_y <= m_thumb_pos_b) {
634				//hmm
635				//stop: we are hovering the thumb bar
636
637				m_whatishovered = 3;
638
639				_clickTimer.stop();
640			}
641
642			raiseSignal(Signal.Scrolled);
643
644			break;
645
646		default:
647			break;
648		}
649	}
650
651	Color m_clroutline;
652	Color m_clrarea;
653	Color m_clrbutton;
654	Color m_clrthumb;
655	Color m_clrhighlight;
656	Color m_clrhover;
657	Color m_clrnormal;
658
659	int m_thumb_pos_y; //y (top) coord
660	int m_thumb_pos_b; //b (bottom) coord
661	int m_thumb_size;
662	int m_area;
663
664	Timer _clickTimer;
665	Timer _readyTimer;
666
667	int m_whatishovered;
668	int m_isclicked;
669
670	int m_thumb_offset;
671
672	int m_last_x;
673	int m_last_y;
674
675	long m_min=0;
676	long m_max=30;
677	long m_value=0;
678
679	long m_large_change=5;
680	long m_small_change=1;
681}