1 #ifdef BUILDING_ECERE_COM
2 namespace gui::controls;
7 public import static "ecere"
13 public class RepButton : Button
20 property Seconds delay { set { timer2.delay = value; } }
21 property Seconds delay0 { set { timer.delay = value; } }
23 bool OnKeyHit(Key key, unichar ch)
28 bool OnKeyDown(Key key, unichar ch)
32 NotifyPushed(master, this, 0,0, key.modifiers);
38 bool OnKeyUp(Key key, unichar ch)
42 NotifyReleased(master, this, 0,0, key.modifiers);
48 bool NotifyPushed(RepButton button, int x, int y, Modifiers mods)
50 button.pressing = true;
51 button.NotifyClicked(this, button, x, y, mods);
56 bool NotifyMouseLeave(RepButton button, Modifiers mods)
63 bool NotifyReleased(RepButton button, int x, int y, Modifiers mods)
65 button.pressing = false;
66 button.NotifyMouseLeave(this, button, mods);
70 bool NotifyMouseOver(RepButton button, int x, int y, Modifiers mods)
73 button.timer2.Start();
85 timer2.DelayExpired(this);
94 NotifyClicked(master, this, 0, 0, 0);
100 static define stackerScrolling = 16;
104 bool reverse:1, scrollable:1, flipSpring:1, autoSize:1;
107 bool holdChildMonitoring:1;
110 public class Stacker : Window
114 property ScrollDirection direction { set { direction = value; } get { return direction; } };
115 property int gap { set { gap = value; } get { return gap; } };
116 property bool reverse { set { bits.reverse = value; } get { return bits.reverse; } };
118 property bool scrollable
122 if(value != bits.scrollable)
124 bits.scrollable = value;
125 // how to recall these?
126 //GetDecorationsSize(...);
127 //SetWindowArea(...);
128 OnResize(clientSize.w, clientSize.h);
131 get { return bits.scrollable; }
134 property Array<Window> controls { get { return controls; } };
136 property Window flipper { set { flipper = value; } get { return flipper; } };
137 property bool flipSpring { set { bits.flipSpring = value; } get { return bits.flipSpring; } };
138 property bool autoSize { set { bits.autoSize = value; } get { return bits.autoSize; } };
139 property int margin { set { margin = value; } get { return margin; } };
143 ScrollDirection direction;
146 Array<Window> controls { };
151 nonClient = true, parent = this, visible = false, bevelOver = true, keyRepeat = true, opacity = 0;
153 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
155 if(direction == horizontal)
157 scroll.x -= stackerScrolling;
158 if(scroll.x == 0) { left.disabled = true; left.OnLeftButtonUp(-1,0,0); }
162 scroll.y -= stackerScrolling;
163 if(scroll.y == 0) { left.disabled = true; left.OnLeftButtonUp(-1,0,0); }
165 right.disabled = false;
166 size = size; // TRIGGER SCROLLING UPDATE (Currently required since we aren't using Window scrollbars)
172 nonClient = true, parent = this, visible = false, bevelOver = true, keyRepeat = true, opacity = 0;
174 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
176 if(direction == horizontal)
178 scroll.x += stackerScrolling;
179 if(scroll.x + clientSize.w >= scrollArea.w) { right.disabled = true; right.OnLeftButtonUp(-1,0,0); }
183 scroll.y += stackerScrolling;
184 if(scroll.y + clientSize.h >= scrollArea.h) { right.disabled = true; right.OnLeftButtonUp(-1,0,0); }
186 left.disabled = false;
187 size = size; // TRIGGER SCROLLING UPDATE (Currently required since we aren't using Window scrollbars)
194 void GetDecorationsSize(MinMaxValue * w, MinMaxValue * h)
196 Window::GetDecorationsSize(w, h);
199 if(direction == vertical) *h += left.size.h + right.size.h + 8; else *w += left.size.w + right.size.w + 8;
203 void SetWindowArea(int * x, int * y, MinMaxValue * w, MinMaxValue * h, MinMaxValue * cw, MinMaxValue * ch)
205 Window::SetWindowArea(x, y, w, h, cw, ch);
208 if(direction == vertical) *y += left.size.h + 4; else *x += left.size.w + 4;
219 OnResize(clientSize.w, clientSize.h);
221 if(direction == vertical)
223 left.bitmap = { "<:ecere>elements/arrowTop.png" };
224 left.anchor = { top = 2, left = 2, right = 2 };
226 right.bitmap = { "<:ecere>elements/arrowBottom.png" };
227 right.anchor = { bottom = 2, left = 2, right = 2 };
231 left.bitmap = { "<:ecere>elements/arrowLeft.png" };
232 left.anchor = { left = 2, top = 2, bottom = 2 };
234 right.bitmap = { "<:ecere>elements/arrowRight.png" };
235 right.anchor = { right = 2, top = 2, bottom = 2 };
241 direction = vertical;
243 void OnChildAddedOrRemoved(Window child, bool removed)
245 if(!bits.holdChildMonitoring)
248 void OnChildVisibilityToggled(Window child, bool visible)
250 DoResize(size.w, size.h); // todo: improve with DoPartialResize(size.w, size.h, client);
251 size = size; // TRIGGER SCROLLING UPDATE (Currently required since we aren't using Window scrollbars)
253 void OnChildResized(Window child, int x, int y, int w, int h)
255 DoResize(size.w, size.h); // todo: improve with DoPartialResize(size.w, size.h, client);
256 size = size; // TRIGGER SCROLLING UPDATE (Currently required since we aren't using Window scrollbars)
259 void UpdateControls()
262 Array<Window> newControls { };
265 for(child = firstChild; child; child = child.next)
267 if(child.nonClient) continue;
270 newControls.Add(child);
280 for(child = firstChild; child; child = child.next)
282 if(child.nonClient) continue;
283 if(!newControls.Find(child))
285 newControls.Add(child);
290 controls = newControls;
294 void OnResize(int width, int height)
297 DoResize(width, height);
300 void DoResize(int width, int height)
302 // TOIMPROVE: this needs to maintain an order and allow for dynamically adding
303 // children. inserting in the order should also be possible.
304 // TOIMPROVE: in Window.ec... it should be possible to change the order of children
305 // at runtime. it should also be possible to choose where dynamically
306 // created children are inserted.
311 bool r = bits.reverse;
312 int inc = bits.reverse ? -1 : 1;
317 for(c = bits.reverse ? controls.count-1 : 0; c<controls.count && c>-1; c += inc)
321 if(flip && child == flip) break;
322 if(child.nonClient || !child.visible) continue;
323 anchor = child.anchor;
324 if(direction == vertical)
328 if(!anchor.bottom.type || anchor.bottom.distance != y)
329 child.anchor.bottom = y;
333 if(!anchor.top.type || anchor.top.distance != y)
334 child.anchor.top = y;
336 y += child.size.h + gap;
342 if(!anchor.right.type || anchor.right.distance != y)
343 child.anchor.right = y;
347 if(!anchor.left.type || anchor.left.distance != y)
348 child.anchor.left = y;
350 y += child.size.w + gap;
352 Flip(flipper, child, controls, margin, &bits, &inc, &c, &y, &flip);
359 if(direction == vertical)
361 if(bits.reverse) flip.anchor.bottom = y;
362 else flip.anchor.top = y;
366 if(bits.reverse) flip.anchor.right = y;
367 else flip.anchor.left = y;
371 else if(bits.autoSize)
374 if(direction == vertical)
375 //this.clientSize.h = y - gap + margin;
376 this.size.h = y - gap + margin + (this.size.h - this.clientSize.h);
378 //this.clientSize.w = y - gap + margin;
379 this.size.w = y - gap + margin + (this.size.w - this.clientSize.w);
384 if(bits.scrollable && y > ((direction == horizontal) ? width : height))
386 scrollArea = (direction == horizontal) ? { y, 0 } : { 0, y };
388 right.visible = true;
392 left.visible = false;
393 right.visible = false;
394 scrollArea = { 0, 0 };
399 // FOR WHEN SCROLLING OCCURED
400 for(child : controls)
401 child.anchor = child.anchor;
403 if(direction == horizontal)
405 left.disabled = (scroll.x == 0);
406 right.disabled = (scroll.x + clientSize.w >= scrollArea.w);
410 left.disabled = (scroll.y == 0);
411 right.disabled = (scroll.y + clientSize.h >= scrollArea.h);
413 if(left.disabled && left.buttonState == down) left.OnLeftButtonUp(-1,0,0);
414 if(right.disabled && right.buttonState == down) right.OnLeftButtonUp(-1,0,0);
419 public void DestroyChildren()
423 bits.holdChildMonitoring = true;
424 for(child = firstChild; child; child = next)
426 next = child ? child.next : null;
433 bits.holdChildMonitoring = false;
436 public void MakeControlVisible(Window control)
438 if(direction == horizontal)
441 if(control.position.x - stackerScrolling < scroll.x)
443 x = control.position.x;
444 if(clientSize.w > control.size.w)
445 x -=(clientSize.w - control.size.w - stackerScrolling) / 2;
446 scroll.x = Max(x, 0);
449 else if(control.position.x + control.size.w + stackerScrolling > scroll.x + clientSize.w)
451 x = control.position.x;
452 if(clientSize.w > control.size.w)
453 x -=(clientSize.w - control.size.w + stackerScrolling) / 2;
454 scroll.x = Max(x, 0);
461 if(control.position.y - stackerScrolling < scroll.y)
463 y = control.position.y;
464 if(clientSize.h > control.size.h)
465 y -=(clientSize.h - control.size.h - stackerScrolling) / 2;
466 scroll.y = Max(y, 0);
469 else if(control.position.y + control.size.h + stackerScrolling > scroll.y + clientSize.h)
471 y = control.position.y;
472 if(clientSize.h > control.size.h)
473 y -=(clientSize.h - control.size.h + stackerScrolling) / 2;
474 scroll.y = Max(y, 0);
480 public Window GetNextStackedItem(Window current, bool previous, Class filter)
482 Window result = null;
485 bool direction = !(reverse^previous);
487 for(c = (!direction) ? controls.count-1 : 0; c<controls.count && c>-1; c += (!direction) ? -1 : 1)
490 if(child.nonClient || !child.created || !child.visible) continue;
491 if(filter && !eClass_IsDerived(child._class, filter)) continue;
497 for(c = direction ? controls.count-1 : 0; c<controls.count && c>-1; c += direction ? -1 : 1)
500 if(child.nonClient || !child.created || !child.visible) continue;
501 if(!eClass_IsDerived(child._class, filter)) continue;
514 static void Flip(Window flipper, Window child, Array<Window> controls, int margin, StackerBits * bits, int * inc, int * c, int * y, Window * flip)
516 if(flipper && !*flip && child == flipper)
519 (*bits).reverse = !(*bits).reverse;
520 *inc = (*bits).reverse ? -1 : 1;
521 *c = (*bits).reverse ? controls.count : -1;