32 pt.x = top; |
34 pt.x = top; |
33 pt.y = bottom - 1; |
35 pt.y = bottom - 1; |
34 return pt; |
36 return pt; |
35 } |
37 } |
36 |
38 |
37 /***************************************************** |
39 /** Special handling for the scrollbar widget type. |
38 * Special handling for the scrollbar widget type. |
|
39 * Handles the special scrolling buttons and other |
40 * Handles the special scrolling buttons and other |
40 * scrolling. |
41 * scrolling. |
41 * Parameters: |
42 * @param w Window on which a scroll was performed. |
42 * w - Window. |
43 * @param wi Pointer to the scrollbar widget. |
43 * wi - Pointer to the scrollbar widget. |
44 * @param x The X coordinate of the mouse click. |
44 * x - The X coordinate of the mouse click. |
45 * @param y The Y coordinate of the mouse click. */ |
45 * y - The Y coordinate of the mouse click. |
|
46 */ |
|
47 |
|
48 void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y) |
46 void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y) |
49 { |
47 { |
50 int mi, ma, pos; |
48 int mi, ma, pos; |
51 Scrollbar *sb; |
49 Scrollbar *sb; |
52 |
50 |
53 switch (wi->type) { |
51 switch (wi->type) { |
54 case WWT_SCROLLBAR: { |
52 case WWT_SCROLLBAR: { |
55 // vertical scroller |
53 /* vertical scroller */ |
56 w->flags4 &= ~WF_HSCROLL; |
54 w->flags4 &= ~WF_HSCROLL; |
57 w->flags4 &= ~WF_SCROLL2; |
55 w->flags4 &= ~WF_SCROLL2; |
58 mi = wi->top; |
56 mi = wi->top; |
59 ma = wi->bottom; |
57 ma = wi->bottom; |
60 pos = y; |
58 pos = y; |
61 sb = &w->vscroll; |
59 sb = &w->vscroll; |
62 break; |
60 break; |
63 } |
61 } |
64 case WWT_SCROLL2BAR: { |
62 case WWT_SCROLL2BAR: { |
65 // 2nd vertical scroller |
63 /* 2nd vertical scroller */ |
66 w->flags4 &= ~WF_HSCROLL; |
64 w->flags4 &= ~WF_HSCROLL; |
67 w->flags4 |= WF_SCROLL2; |
65 w->flags4 |= WF_SCROLL2; |
68 mi = wi->top; |
66 mi = wi->top; |
69 ma = wi->bottom; |
67 ma = wi->bottom; |
70 pos = y; |
68 pos = y; |
71 sb = &w->vscroll2; |
69 sb = &w->vscroll2; |
72 break; |
70 break; |
73 } |
71 } |
74 case WWT_HSCROLLBAR: { |
72 case WWT_HSCROLLBAR: { |
75 // horizontal scroller |
73 /* horizontal scroller */ |
76 w->flags4 &= ~WF_SCROLL2; |
74 w->flags4 &= ~WF_SCROLL2; |
77 w->flags4 |= WF_HSCROLL; |
75 w->flags4 |= WF_HSCROLL; |
78 mi = wi->left; |
76 mi = wi->left; |
79 ma = wi->right; |
77 ma = wi->right; |
80 pos = x; |
78 pos = x; |
82 break; |
80 break; |
83 } |
81 } |
84 default: return; //this should never happen |
82 default: return; //this should never happen |
85 } |
83 } |
86 if (pos <= mi+9) { |
84 if (pos <= mi+9) { |
87 // Pressing the upper button? |
85 /* Pressing the upper button? */ |
88 w->flags4 |= WF_SCROLL_UP; |
86 w->flags4 |= WF_SCROLL_UP; |
89 if (_scroller_click_timeout == 0) { |
87 if (_scroller_click_timeout == 0) { |
90 _scroller_click_timeout = 6; |
88 _scroller_click_timeout = 6; |
91 if (sb->pos != 0) sb->pos--; |
89 if (sb->pos != 0) sb->pos--; |
92 } |
90 } |
93 _left_button_clicked = false; |
91 _left_button_clicked = false; |
94 } else if (pos >= ma-10) { |
92 } else if (pos >= ma-10) { |
95 // Pressing the lower button? |
93 /* Pressing the lower button? */ |
96 w->flags4 |= WF_SCROLL_DOWN; |
94 w->flags4 |= WF_SCROLL_DOWN; |
97 |
95 |
98 if (_scroller_click_timeout == 0) { |
96 if (_scroller_click_timeout == 0) { |
99 _scroller_click_timeout = 6; |
97 _scroller_click_timeout = 6; |
100 if ((byte)(sb->pos + sb->cap) < sb->count) |
98 if ((byte)(sb->pos + sb->cap) < sb->count) |
101 sb->pos++; |
99 sb->pos++; |
102 } |
100 } |
103 _left_button_clicked = false; |
101 _left_button_clicked = false; |
104 } else { |
102 } else { |
105 // |
|
106 Point pt = HandleScrollbarHittest(sb, mi, ma); |
103 Point pt = HandleScrollbarHittest(sb, mi, ma); |
107 |
104 |
108 if (pos < pt.x) { |
105 if (pos < pt.x) { |
109 sb->pos = max(sb->pos - sb->cap, 0); |
106 sb->pos = max(sb->pos - sb->cap, 0); |
110 } else if (pos > pt.y) { |
107 } else if (pos > pt.y) { |
125 } |
122 } |
126 |
123 |
127 /** Returns the index for the widget located at the given position |
124 /** Returns the index for the widget located at the given position |
128 * relative to the window. It includes all widget-corner pixels as well. |
125 * relative to the window. It includes all widget-corner pixels as well. |
129 * @param *w Window to look inside |
126 * @param *w Window to look inside |
130 * @param x,y Window client coordinates |
127 * @param x The Window client X coordinate |
|
128 * @param y The Window client y coordinate |
131 * @return A widget index, or -1 if no widget was found. |
129 * @return A widget index, or -1 if no widget was found. |
132 */ |
130 */ |
133 int GetWidgetFromPos(const Window *w, int x, int y) |
131 int GetWidgetFromPos(const Window *w, int x, int y) |
134 { |
132 { |
135 uint index; |
133 uint index; |
136 int found_index = -1; |
134 int found_index = -1; |
137 |
135 |
138 // Go through the widgets and check if we find the widget that the coordinate is |
136 /* Go through the widgets and check if we find the widget that the coordinate is |
139 // inside. |
137 * inside. */ |
140 for (index = 0; index < w->widget_count; index++) { |
138 for (index = 0; index < w->widget_count; index++) { |
141 const Widget *wi = &w->widget[index]; |
139 const Widget *wi = &w->widget[index]; |
142 if (wi->type == WWT_EMPTY || wi->type == WWT_FRAME) continue; |
140 if (wi->type == WWT_EMPTY || wi->type == WWT_FRAME) continue; |
143 |
141 |
144 if (x >= wi->left && x <= wi->right && y >= wi->top && y <= wi->bottom && |
142 if (x >= wi->left && x <= wi->right && y >= wi->top && y <= wi->bottom && |
292 } |
290 } |
293 |
291 |
294 goto draw_default; |
292 goto draw_default; |
295 } |
293 } |
296 |
294 |
297 // vertical scrollbar |
295 /* vertical scrollbar */ |
298 case WWT_SCROLLBAR: { |
296 case WWT_SCROLLBAR: { |
299 Point pt; |
297 Point pt; |
300 int c1,c2; |
298 int c1,c2; |
301 |
299 |
302 assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere! |
300 assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere! |
303 |
301 |
304 // draw up/down buttons |
302 /* draw up/down buttons */ |
305 clicked = ((w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_UP); |
303 clicked = ((w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_UP); |
306 DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->color, (clicked) ? FR_LOWERED : FR_NONE); |
304 DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->color, (clicked) ? FR_LOWERED : FR_NONE); |
307 DoDrawString(UPARROW, r.left + 2 + clicked, r.top + clicked, 0x10); |
305 DoDrawString(UPARROW, r.left + 2 + clicked, r.top + clicked, 0x10); |
308 |
306 |
309 clicked = (((w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_DOWN)); |
307 clicked = (((w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_DOWN)); |
311 DoDrawString(DOWNARROW, r.left + 2 + clicked, r.bottom - 9 + clicked, 0x10); |
309 DoDrawString(DOWNARROW, r.left + 2 + clicked, r.bottom - 9 + clicked, 0x10); |
312 |
310 |
313 c1 = _colour_gradient[wi->color&0xF][3]; |
311 c1 = _colour_gradient[wi->color&0xF][3]; |
314 c2 = _colour_gradient[wi->color&0xF][7]; |
312 c2 = _colour_gradient[wi->color&0xF][7]; |
315 |
313 |
316 // draw "shaded" background |
314 /* draw "shaded" background */ |
317 GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c2); |
315 GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c2); |
318 GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c1 | (1 << PALETTE_MODIFIER_GREYOUT)); |
316 GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c1 | (1 << PALETTE_MODIFIER_GREYOUT)); |
319 |
317 |
320 // draw shaded lines |
318 /* draw shaded lines */ |
321 GfxFillRect(r.left+2, r.top+10, r.left+2, r.bottom-10, c1); |
319 GfxFillRect(r.left+2, r.top+10, r.left+2, r.bottom-10, c1); |
322 GfxFillRect(r.left+3, r.top+10, r.left+3, r.bottom-10, c2); |
320 GfxFillRect(r.left+3, r.top+10, r.left+3, r.bottom-10, c2); |
323 GfxFillRect(r.left+7, r.top+10, r.left+7, r.bottom-10, c1); |
321 GfxFillRect(r.left+7, r.top+10, r.left+7, r.bottom-10, c1); |
324 GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2); |
322 GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2); |
325 |
323 |
331 Point pt; |
329 Point pt; |
332 int c1,c2; |
330 int c1,c2; |
333 |
331 |
334 assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere! |
332 assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere! |
335 |
333 |
336 // draw up/down buttons |
334 /* draw up/down buttons */ |
337 clicked = ((w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_UP | WF_SCROLL2)); |
335 clicked = ((w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_UP | WF_SCROLL2)); |
338 DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->color, (clicked) ? FR_LOWERED : FR_NONE); |
336 DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->color, (clicked) ? FR_LOWERED : FR_NONE); |
339 DoDrawString(UPARROW, r.left + 2 + clicked, r.top + clicked, 0x10); |
337 DoDrawString(UPARROW, r.left + 2 + clicked, r.top + clicked, 0x10); |
340 |
338 |
341 clicked = ((w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_DOWN | WF_SCROLL2)); |
339 clicked = ((w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_DOWN | WF_SCROLL2)); |
343 DoDrawString(DOWNARROW, r.left + 2 + clicked, r.bottom - 9 + clicked, 0x10); |
341 DoDrawString(DOWNARROW, r.left + 2 + clicked, r.bottom - 9 + clicked, 0x10); |
344 |
342 |
345 c1 = _colour_gradient[wi->color&0xF][3]; |
343 c1 = _colour_gradient[wi->color&0xF][3]; |
346 c2 = _colour_gradient[wi->color&0xF][7]; |
344 c2 = _colour_gradient[wi->color&0xF][7]; |
347 |
345 |
348 // draw "shaded" background |
346 /* draw "shaded" background */ |
349 GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c2); |
347 GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c2); |
350 GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c1 | (1 << PALETTE_MODIFIER_GREYOUT)); |
348 GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c1 | (1 << PALETTE_MODIFIER_GREYOUT)); |
351 |
349 |
352 // draw shaded lines |
350 /* draw shaded lines */ |
353 GfxFillRect(r.left+2, r.top+10, r.left+2, r.bottom-10, c1); |
351 GfxFillRect(r.left+2, r.top+10, r.left+2, r.bottom-10, c1); |
354 GfxFillRect(r.left+3, r.top+10, r.left+3, r.bottom-10, c2); |
352 GfxFillRect(r.left+3, r.top+10, r.left+3, r.bottom-10, c2); |
355 GfxFillRect(r.left+7, r.top+10, r.left+7, r.bottom-10, c1); |
353 GfxFillRect(r.left+7, r.top+10, r.left+7, r.bottom-10, c1); |
356 GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2); |
354 GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2); |
357 |
355 |
358 pt = HandleScrollbarHittest(&w->vscroll2, r.top, r.bottom); |
356 pt = HandleScrollbarHittest(&w->vscroll2, r.top, r.bottom); |
359 DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_MIDDLE | WF_SCROLL2) ? FR_LOWERED : FR_NONE); |
357 DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_MIDDLE | WF_SCROLL2) ? FR_LOWERED : FR_NONE); |
360 break; |
358 break; |
361 } |
359 } |
362 |
360 |
363 // horizontal scrollbar |
361 /* horizontal scrollbar */ |
364 case WWT_HSCROLLBAR: { |
362 case WWT_HSCROLLBAR: { |
365 Point pt; |
363 Point pt; |
366 int c1,c2; |
364 int c1,c2; |
367 |
365 |
368 assert(r.bottom - r.top == 11); // XXX - to ensure the same sizes are used everywhere! |
366 assert(r.bottom - r.top == 11); // XXX - to ensure the same sizes are used everywhere! |
376 DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - 8 + clicked, r.top + 1 + clicked); |
374 DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - 8 + clicked, r.top + 1 + clicked); |
377 |
375 |
378 c1 = _colour_gradient[wi->color&0xF][3]; |
376 c1 = _colour_gradient[wi->color&0xF][3]; |
379 c2 = _colour_gradient[wi->color&0xF][7]; |
377 c2 = _colour_gradient[wi->color&0xF][7]; |
380 |
378 |
381 // draw "shaded" background |
379 /* draw "shaded" background */ |
382 GfxFillRect(r.left+10, r.top, r.right-10, r.bottom, c2); |
380 GfxFillRect(r.left+10, r.top, r.right-10, r.bottom, c2); |
383 GfxFillRect(r.left+10, r.top, r.right-10, r.bottom, c1 | (1 << PALETTE_MODIFIER_GREYOUT)); |
381 GfxFillRect(r.left+10, r.top, r.right-10, r.bottom, c1 | (1 << PALETTE_MODIFIER_GREYOUT)); |
384 |
382 |
385 // draw shaded lines |
383 /* draw shaded lines */ |
386 GfxFillRect(r.left+10, r.top+2, r.right-10, r.top+2, c1); |
384 GfxFillRect(r.left+10, r.top+2, r.right-10, r.top+2, c1); |
387 GfxFillRect(r.left+10, r.top+3, r.right-10, r.top+3, c2); |
385 GfxFillRect(r.left+10, r.top+3, r.right-10, r.top+3, c2); |
388 GfxFillRect(r.left+10, r.top+7, r.right-10, r.top+7, c1); |
386 GfxFillRect(r.left+10, r.top+7, r.right-10, r.top+7, c1); |
389 GfxFillRect(r.left+10, r.top+8, r.right-10, r.top+8, c2); |
387 GfxFillRect(r.left+10, r.top+8, r.right-10, r.top+8, c2); |
390 |
388 |
391 // draw actual scrollbar |
389 /* draw actual scrollbar */ |
392 pt = HandleScrollbarHittest(&w->hscroll, r.left, r.right); |
390 pt = HandleScrollbarHittest(&w->hscroll, r.left, r.right); |
393 DrawFrameRect(pt.x, r.top, pt.y, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == (WF_SCROLL_MIDDLE | WF_HSCROLL) ? FR_LOWERED : FR_NONE); |
391 DrawFrameRect(pt.x, r.top, pt.y, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == (WF_SCROLL_MIDDLE | WF_HSCROLL) ? FR_LOWERED : FR_NONE); |
394 |
392 |
395 break; |
393 break; |
396 } |
394 } |
402 if (wi->data != 0) x2 = DrawString(r.left + 6, r.top, wi->data, 0); |
400 if (wi->data != 0) x2 = DrawString(r.left + 6, r.top, wi->data, 0); |
403 |
401 |
404 c1 = _colour_gradient[wi->color][3]; |
402 c1 = _colour_gradient[wi->color][3]; |
405 c2 = _colour_gradient[wi->color][7]; |
403 c2 = _colour_gradient[wi->color][7]; |
406 |
404 |
407 //Line from upper left corner to start of text |
405 /*Line from upper left corner to start of text */ |
408 GfxFillRect(r.left, r.top+4, r.left+4,r.top+4, c1); |
406 GfxFillRect(r.left, r.top+4, r.left+4,r.top+4, c1); |
409 GfxFillRect(r.left+1, r.top+5, r.left+4,r.top+5, c2); |
407 GfxFillRect(r.left+1, r.top+5, r.left+4,r.top+5, c2); |
410 |
408 |
411 // Line from end of text to upper right corner |
409 /* Line from end of text to upper right corner */ |
412 GfxFillRect(x2, r.top+4, r.right-1,r.top+4,c1); |
410 GfxFillRect(x2, r.top+4, r.right-1,r.top+4,c1); |
413 GfxFillRect(x2, r.top+5, r.right-2,r.top+5,c2); |
411 GfxFillRect(x2, r.top+5, r.right-2,r.top+5,c2); |
414 |
412 |
415 // Line from upper left corner to bottom left corner |
413 /* Line from upper left corner to bottom left corner */ |
416 GfxFillRect(r.left, r.top+5, r.left, r.bottom-1, c1); |
414 GfxFillRect(r.left, r.top+5, r.left, r.bottom-1, c1); |
417 GfxFillRect(r.left+1, r.top+6, r.left+1, r.bottom-2, c2); |
415 GfxFillRect(r.left+1, r.top+6, r.left+1, r.bottom-2, c2); |
418 |
416 |
419 //Line from upper right corner to bottom right corner |
417 /*Line from upper right corner to bottom right corner */ |
420 GfxFillRect(r.right-1, r.top+5, r.right-1, r.bottom-2, c1); |
418 GfxFillRect(r.right-1, r.top+5, r.right-1, r.bottom-2, c1); |
421 GfxFillRect(r.right, r.top+4, r.right, r.bottom-1, c2); |
419 GfxFillRect(r.right, r.top+4, r.right, r.bottom-1, c2); |
422 |
420 |
423 GfxFillRect(r.left+1, r.bottom-1, r.right-1, r.bottom-1, c1); |
421 GfxFillRect(r.left+1, r.bottom-1, r.right-1, r.bottom-1, c1); |
424 GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2); |
422 GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2); |
499 |
497 |
500 item = y / 10; |
498 item = y / 10; |
501 if (item >= WP(w,dropdown_d).num_items || (HASBIT(WP(w,dropdown_d).disabled_state, item) && !HASBIT(WP(w,dropdown_d).hidden_state, item)) || WP(w,dropdown_d).items[item] == 0) |
499 if (item >= WP(w,dropdown_d).num_items || (HASBIT(WP(w,dropdown_d).disabled_state, item) && !HASBIT(WP(w,dropdown_d).hidden_state, item)) || WP(w,dropdown_d).items[item] == 0) |
502 return - 1; |
500 return - 1; |
503 |
501 |
504 // Skip hidden items -- +1 for each hidden item before the clicked item. |
502 /* Skip hidden items -- +1 for each hidden item before the clicked item. */ |
505 for (counter = 0; item >= counter; ++counter) |
503 for (counter = 0; item >= counter; ++counter) |
506 if (HASBIT(WP(w,dropdown_d).hidden_state, counter)) item++; |
504 if (HASBIT(WP(w,dropdown_d).hidden_state, counter)) item++; |
507 |
505 |
508 return item; |
506 return item; |
509 } |
507 } |
733 w->widget[c].left = w->widget[b].right + 1; |
731 w->widget[c].left = w->widget[b].right + 1; |
734 } |
732 } |
735 |
733 |
736 /** Evenly distribute some widgets when resizing horizontally (often a button row) |
734 /** Evenly distribute some widgets when resizing horizontally (often a button row) |
737 * When only two arguments are given, the widgets are presumed to be on a line and only the ends are given |
735 * When only two arguments are given, the widgets are presumed to be on a line and only the ends are given |
738 * @param w widow to modify |
736 * @param w Window to modify |
739 * @param left The leftmost widget to resize |
737 * @param left The leftmost widget to resize |
740 * @param right The rightmost widget to resize. Since right side of it is used, remember to set it to RESIZE_RIGHT |
738 * @param right The rightmost widget to resize. Since right side of it is used, remember to set it to RESIZE_RIGHT |
741 */ |
739 */ |
742 void ResizeButtons(Window *w, byte left, byte right) |
740 void ResizeButtons(Window *w, byte left, byte right) |
743 { |
741 { |