PageRenderTime 44ms CodeModel.GetById 2ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/gui/hscrollbar.d

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