1 namespace gui::controls;
8 #define SNAPDOWN(x, d) \
11 if(x < 0) x -= ((d) - Abs(x) % (d)); else x -= x % (d); \
14 #define SNAPUP(x, d) \
17 if(x > 0) x += ((d) - Abs(x) % (d)); else x += x % (d); \
20 class ScrollBarBits { bool vertical:1, snap:1, window:1; };
22 public enum ScrollDirection { horizontal, vertical };
23 public enum ScrollBarAction { none, up, down, pageDown, pageUp, setPosition, home, end, setRange, wheelUp, wheelDown };
24 public class ScrollBar : CommonControl
26 class_property(icon) = "<:ecere>controls/scrollBarHorizontal.png";
29 bool Action(ScrollBarAction action, int newPosition, Key key)
33 int sbWidth = guiApp.textMode ? 8 : SB_WIDTH;
34 int oldPosition = position;
35 Window master = this.master;
37 // Setup Range and Thumb Size
38 range = total - seen + 1;
40 SNAPDOWN(range, lineStep);*/
41 range = Max(range, 1);
49 case up: position -= lineStep; break;
50 case down: position += lineStep; break;
51 case pageUp: position -= pageStep; break;
52 case pageDown: position += pageStep; break;
53 case setPosition: position = newPosition; break;
54 case setRange: position = newPosition; break;
55 case home: position = 0; break;
56 case end: position = range-1; break;
57 case wheelUp: position -= lineStep * 3; break;
58 case wheelDown: position += lineStep * 3; break;
62 SNAPUP(position, lineStep);
63 // SNAPDOWN(position, lineStep);
65 if(position < 0) position = 0;
74 NotifyScrolling(master, this, action, position, key);
75 return position != oldPosition;
80 virtual void Window::NotifyScrolling(ScrollBar scrollBar, ScrollBarAction action, int position, Key key);
82 property ScrollDirection direction { property_category "Appearance" set { sbStyle.vertical = value == vertical; } get { return sbStyle.vertical ? vertical : horizontal; } };
83 property bool windowOwned { set { sbStyle.window = value; } /* get { return sbStyle.window; } */ };
84 property bool snap { property_category "Behavior" set { sbStyle.snap = value; } get { return sbStyle.snap; } };
87 property_category "Behavior"
90 total = value + seen - 1;
91 Action(setRange, position, 0);
95 // Improve this, needs to be done in 2 so updates commented out for seen
98 property_category "Behavior"
103 value = Max(1,value);
105 SNAPDOWN(value, lineStep);
107 Action(setRange, position, 0);
114 property_category "Behavior"
119 if(!value) value = seen;
121 Action(setRange, position, 0);
124 get { return total; }
127 property int lineStep { property_category "Behavior" set { if(this) lineStep = value; } get { return lineStep; } };
128 property int pageStep { property_category "Behavior" set { if(this) pageStep = value; } get { return pageStep; } };
129 property int thumbPosition { property_category "Behavior" set { Action(setPosition, value, 0); } get { return position; } };
138 range = total - seen + 1;
142 background = Color { 224,224,224 };
144 ScrollBarBits sbStyle;
145 int lineStep, pageStep;
146 int range, seen, total;
148 bool ButtonMouseLeave(Window control, Modifiers mods)
155 bool ButtonReleased(Window control, int x, int y, Modifiers mods)
158 ButtonMouseLeave(control, mods);
162 bool ButtonMouseOver(Window control, int x, int y, Modifiers mods)
164 if(action == up || action == down)
169 public Button downBtn
171 this, inactive = true;
172 NotifyMouseLeave = ButtonMouseLeave, NotifyReleased = ButtonReleased, NotifyMouseOver = ButtonMouseOver;
174 bool NotifyPushed(Button button, int x, int y, Modifiers mods)
177 Action(action, 0, (Key)mods);
184 this, inactive = true;
185 NotifyMouseLeave = ButtonMouseLeave, NotifyReleased = ButtonReleased, NotifyMouseOver = ButtonMouseOver;
187 bool NotifyPushed(Button button, int x, int y, Modifiers mods)
190 Action(action, 0, (Key)mods);
197 this, stayUp = true, NotifyReleased = ButtonReleased;
199 bool NotifyPushed(Button button, int x, int y, Modifiers mods)
203 action = setPosition;
207 bool NotifyMouseMove(Button control, int x, int y, Modifiers mods)
209 if(action == setPosition && !mods.isSideEffect)
216 height = (clientSize.h - upBtn.size.h - downBtn.size.h - thumbSize);
219 SNAPUP(height, textCellH);
221 position = y - thumbClick.y + thumb.position.y;
223 position = (position - SB_HEIGHT) * (range - 1) / height;
226 SNAPUP(position, textCellH);
231 height = (clientSize.w - upBtn.size.w - downBtn.size.w - thumbSize);
234 SNAPUP(height, textCellW);
236 position = x - thumbClick.x + thumb.position.x;
238 position = (position - upBtn.size.w) * (range - 1) / height;
241 SNAPUP(position, textCellW);
248 SNAPDOWN(position, lineStep);
250 Action(setPosition, position, (Key)mods);
252 Action(setPosition, position, (Key)mods);
261 int position, mousePosition;
262 public int thumbSize;
266 userData = this, delay = 0.5;
272 timer2.DelayExpired(this);
278 userData = this, delay = 0.1;
281 if(action != up && action != down)
285 if(mousePosition < thumbPos)
287 else if(mousePosition >= thumbPos + thumbSize)
292 Action(action, 0, 0);
297 Action(action, 0, 0);
302 ScrollBarAction action;
304 Point pos, thumbClick;
307 void OnRedraw(Surface surface)
309 int sbWidth = SB_WIDTH;
314 surface.DrawingChar(177);
315 surface.SetForeground(Color { 0, 0, 170 });
316 surface.Area(0,0, clientSize.w-1, clientSize.h-1);
319 if((action == pageUp || action == pageDown) && inside)
321 surface.SetBackground(Color { 85, 85, 85 });
325 surface.Area(0, SB_HEIGHT, clientSize.w-1, thumbPos+thumbSize/2-1);
326 else if(action == pageDown)
327 surface.Area(0, thumbPos +thumbSize/2, clientSize.w-1, clientSize.h - SB_HEIGHT-1);
332 surface.Area(sbWidth, 0, thumbPos + thumbSize/2-1, clientSize.h-1);
333 if(action == pageDown)
334 surface.Area(thumbPos+thumbSize/2, 0, clientSize.w - sbWidth - 1, clientSize.h-1);
343 downBtn.size.h = SB_HEIGHT;
344 downBtn.anchor = Anchor { left = 0, right = 0, bottom = 0 };
345 downBtn.bitmap = { fileName = "<:ecere>elements/arrowDown.png" };
348 upBtn.size.h = SB_HEIGHT;
349 upBtn.anchor = Anchor { left = 0, right = 0, bottom = 0 };
350 upBtn.bitmap = { fileName = "<:ecere>elements/arrowUp.png" };
355 downBtn.size.w = SB_HEIGHT;
356 downBtn.anchor = Anchor { top = 0, bottom = 0, right = 0 };
357 downBtn.bitmap = { fileName = "<:ecere>elements/arrowRight.png" };
360 upBtn.size.w = SB_HEIGHT;
361 upBtn.anchor = Anchor { left = 0, top = 0, bottom = 0 };
362 upBtn.bitmap = { fileName = "<:ecere>elements/arrowLeft.png" };
365 Action(setPosition, position, 0);
376 int height = (clientSize.h - upBtn.size.h - downBtn.size.h - thumbSize);
379 SNAPUP(height, textCellH);
381 thumbPos = upBtn.size.h + position * height / (range - 1);
384 SNAPUP(thumbPos, textCellH);
387 thumb.Move(0,thumbPos, size.w,thumbSize);
391 int width = (clientSize.w - upBtn.size.w - downBtn.size.w - thumbSize);
394 SNAPUP(width, textCellW);
396 thumbPos = upBtn.size.w + position * width / (range - 1);
399 SNAPUP(thumbPos, textCellW);
402 thumb.Move(thumbPos, 0, thumbSize, size.h);
407 void OnApplyGraphics()
409 int sbWidth = SB_WIDTH;
413 upBtn.background = Color { 0, 170, 170 };
414 downBtn.background = Color { 0, 170, 170 };
415 thumb.background = Color { 0, 170, 170 };
416 background = Color { 0, 170, 170 };
421 upBtn.background = activeBorder;
422 downBtn.background = activeBorder;
423 thumb.background = activeBorder;
424 background = Color { 224, 224, 224 };
428 downBtn.size.h = SB_HEIGHT;
429 downBtn.anchor = Anchor { left = 0, bottom = 0, right = 0 };
431 upBtn.size.h = SB_HEIGHT;
432 upBtn.anchor = Anchor { left = 0, right = 0, top = 0 };
434 thumb.Move(0,0, Max(clientSize.w, sbWidth), thumbSize);
438 downBtn.size.w = SB_HEIGHT;
439 downBtn.anchor = Anchor { top = 0, bottom = 0, right = 0 };
441 upBtn.size.w = SB_HEIGHT;
442 upBtn.anchor = Anchor { left = 0, top = 0, bottom = 0 };
444 thumb.Move(0,0, thumbSize, Max(clientSize.h, SB_HEIGHT));
450 bool OnResizing(int *w, int *h)
452 int sbWidth = guiApp.textMode ? 8 : SB_WIDTH;
456 *w = Max(*w, sbWidth);
457 *h = Max(*h, SB_HEIGHT * 2 + SB_HEIGHT);
462 *h = Max(*h, SB_HEIGHT);
463 *w = Max(*w, sbWidth * 2 + sbWidth);
472 int sbWidth = guiApp.textMode ? 8 : SB_WIDTH;
477 size = clientSize.h - upBtn.size.h - downBtn.size.h;
479 size = clientSize.w - upBtn.size.w - downBtn.size.w;
480 thumbSize = seen * size / total;
487 thumbSize = Min(thumbSize, clientSize.h - upBtn.size.h - downBtn.size.h - 1);
488 thumbSize = Max(thumbSize, SB_HEIGHT);
492 thumbSize = Min(thumbSize, clientSize.w - upBtn.size.w - downBtn.size.w - 1);
493 thumbSize = Max(thumbSize, sbWidth);
496 else if(sbStyle.vertical)
497 thumbSize = thumb.size.h;
499 thumbSize = thumb.size.w;
502 void OnResize(int w, int h)
507 Action(setPosition, position, 0);
510 // This makes sure our thumb size is recomputed
517 bool OnLeftButtonDown(int x, int y, Modifiers mods)
519 int pos = (sbStyle.vertical) ? y : x;
528 Action(action, 0, (Key)mods);
535 bool OnLeftButtonUp(int x, int y, Modifiers mods)
538 ButtonReleased(null, x, y, mods);
544 bool OnMouseMove(int x, int y, Modifiers mods)
546 mousePosition = sbStyle.vertical ? y : x;
550 bool OnMouseOver(int x, int y, Modifiers mods)
556 bool OnMouseLeave(Modifiers mods)
559 if(action == pageDown || action == pageUp)
564 bool OnKeyDown(Key key, unichar ch)
568 case home: Action(home, 0, key); break;
569 case end: Action(end, 0, key); break;
574 bool OnKeyHit(Key key, unichar ch)
579 case up: Action(up, 0, key); break;
582 Action(down, 0, key);
584 case pageUp: Action(pageUp, 0, key); break;
585 case pageDown: Action(pageDown, 0, key); break;
592 thumb.visible = !disabled;