#endif
#endif
-public class RepButton : Button
-{
-public:
- bool pressing;
- isRemote = true;
- inactive = true;
-
- property Seconds delay { set { timer2.delay = value; } }
- property Seconds delay0 { set { timer.delay = value; } }
-
- bool OnKeyHit(Key key, unichar ch)
- {
- return true;
- }
-
- bool OnKeyDown(Key key, unichar ch)
- {
- if(key == hotKey)
- {
- NotifyPushed(master, this, 0,0, key.modifiers);
- return false;
- }
- return true;
- }
-
- bool OnKeyUp(Key key, unichar ch)
- {
- if(key == hotKey)
- {
- NotifyReleased(master, this, 0,0, key.modifiers);
- return false;
- }
- return true;
- }
-
- bool NotifyPushed(RepButton button, int x, int y, Modifiers mods)
- {
- button.pressing = true;
- button.NotifyClicked(this, button, x, y, mods);
- button.timer.Start();
- return true;
- }
-
- bool NotifyMouseLeave(RepButton button, Modifiers mods)
- {
- button.timer.Stop();
- button.timer2.Stop();
- return true;
- }
-
- bool NotifyReleased(RepButton button, int x, int y, Modifiers mods)
- {
- button.pressing = false;
- button.NotifyMouseLeave(this, button, mods);
- return false;
- }
-
- bool NotifyMouseOver(RepButton button, int x, int y, Modifiers mods)
- {
- if(button.pressing)
- button.timer2.Start();
- return true;
- }
-
- Timer timer
- {
- this, delay = 0.1;
-
- bool DelayExpired()
- {
- timer.Stop();
- timer2.Start();
- timer2.DelayExpired(this);
- return true;
- }
- };
- Timer timer2
- {
- this, delay = 0.1;
- bool DelayExpired()
- {
- NotifyClicked(master, this, 0, 0, 0);
- return true;
- }
- };
-}
+// class RepButton WAS ALREADY DEFINED IN date.ec! The version here broke CalendarControl behavior.
static define stackerScrolling = 16;
class StackerBits
{
- bool reverse:1, scrollable:1, flipSpring:1, autoSize:1;
+ bool reverse:1, scrollable:1, flipSpring:1, autoSize:1, endButtons:1;
// internals
bool holdChildMonitoring:1;
property Window flipper { set { flipper = value; } get { return flipper; } };
property bool flipSpring { set { bits.flipSpring = value; } get { return bits.flipSpring; } };
- property bool autoSize { set { bits.autoSize = value; } get { return bits.autoSize; } };
+ property bool autoSize
+ {
+ set
+ {
+ bits.autoSize = value;
+ if(value)
+ {
+ // Auto Size implementation conflicts with this base Window property, resulting in overhead and potential glitches:
+ // dontAutoScrollArea = false;
+ modifyVirtualArea = false;
+ }
+ }
+ get { return bits.autoSize; }
+ };
property int margin { set { margin = value; } get { return margin; } };
+ property bool endButtons
+ {
+ set
+ {
+ if(bits.endButtons && scrollable && !value)
+ {
+ left.visible = false;
+ right.visible = false;
+ }
+ bits.endButtons = value;
+ if(value && scrollable)
+ {
+ left.visible = true;
+ right.visible = true;
+ }
+ }
+ get { return bits.endButtons; }
+ };
private:
StackerBits bits;
Array<Window> controls { };
Window flipper;
+ void OnVScroll(ScrollBarAction action, int position, Key key)
+ {
+ if(bits.endButtons)
+ {
+ bool ld = false, rd = false;
+ left.disabled = false;
+ right.disabled = false;
+ if(direction == horizontal)
+ {
+ if(position == 0) ld = true;
+ if(position + clientSize.w >= scrollArea.w) rd = true;
+ }
+ else
+ {
+ if(position == 0) ld = true;
+ if(position + clientSize.h >= scrollArea.h) rd = true;
+ }
+ if(left.disabled != ld) { left.disabled = ld; left.OnLeftButtonUp(-1,0,0); }
+ if(right.disabled != rd) { right.disabled = rd; right.OnLeftButtonUp(-1,0,0); }
+ }
+ }
+
RepButton left
{
- nonClient = true, parent = this, visible = false, bevelOver = true, keyRepeat = true, opacity = 0;
+ nonClient = true, parent = this, visible = false, bevelOver = true, keyRepeat = true, opacity = 0; delay0 = 0.1;
bool NotifyClicked(Button button, int x, int y, Modifiers mods)
{
};
RepButton right
{
- nonClient = true, parent = this, visible = false, bevelOver = true, keyRepeat = true, opacity = 0;
+ nonClient = true, parent = this, visible = false, bevelOver = true, keyRepeat = true, opacity = 0; delay0 = 0.1;
bool NotifyClicked(Button button, int x, int y, Modifiers mods)
{
void GetDecorationsSize(MinMaxValue * w, MinMaxValue * h)
{
Window::GetDecorationsSize(w, h);
- if(scrollable)
+ if(bits.scrollable && bits.endButtons && left.visible)
{
- if(direction == vertical) *h += left.size.w + right.size.w + 8; else *w += left.size.h + right.size.h + 8;
+ if(direction == vertical) *h += left.size.h + right.size.h + 8; else *w += left.size.w + right.size.w + 8;
}
}
void SetWindowArea(int * x, int * y, MinMaxValue * w, MinMaxValue * h, MinMaxValue * cw, MinMaxValue * ch)
{
Window::SetWindowArea(x, y, w, h, cw, ch);
- if(scrollable)
+ if(bits.scrollable && bits.endButtons && left.visible)
{
- if(direction == vertical) *y += left.size.w + 4; else *x += left.size.h + 4;
+ if(direction == vertical) *y += left.size.h + 4; else *x += left.size.w + 4;
}
}
controls.Free();
}
+ bool OnCreate()
+ {
+ bits.holdChildMonitoring = true;
+ return true;
+ }
+
bool OnPostCreate()
{
+ bits.holdChildMonitoring = false;
OnResize(clientSize.w, clientSize.h);
if(direction == vertical)
{
- left.bitmap = { "<:ecere>elements/arrowTop.png" };
+ left.bitmap = { "<:ecere>elements/arrowUp.png" };
left.anchor = { top = 2, left = 2, right = 2 };
- right.bitmap = { "<:ecere>elements/arrowBottom.png" };
+ right.bitmap = { "<:ecere>elements/arrowDown.png" };
right.anchor = { bottom = 2, left = 2, right = 2 };
}
else
gap = 5;
direction = vertical;
+ endButtons = true;
void OnChildAddedOrRemoved(Window child, bool removed)
{
- if(!bits.holdChildMonitoring)
- UpdateControls();
+ if(!child.nonClient)
+ {
+ if(removed)
+ {
+ if((child.destroyed && !destroyed) || child.parent != this)
+ {
+ Iterator<Window> it { controls };
+ if(it.Find(child))
+ {
+ it.Remove();
+ delete child;
+ }
+ }
+ }
+ else
+ {
+ if((child.created || (!created && child.autoCreate)) && !child.destroyed && child.parent == this)
+ {
+ if(!controls.Find(child))
+ {
+ controls.Add(child);
+ incref child;
+ }
+ }
+ }
+ if(!bits.holdChildMonitoring)
+ DoResize(size.w, size.h);
+ }
}
void OnChildVisibilityToggled(Window child, bool visible)
{
DoResize(size.w, size.h); // todo: improve with DoPartialResize(size.w, size.h, client);
+ // size = size; // TRIGGER SCROLLING UPDATE (Currently required since we aren't using Window scrollbars)
}
void OnChildResized(Window child, int x, int y, int w, int h)
{
DoResize(size.w, size.h); // todo: improve with DoPartialResize(size.w, size.h, client);
+ // size = size; // TRIGGER SCROLLING UPDATE (Currently required since we aren't using Window scrollbars)
}
- void UpdateControls()
+ /*void UpdateControls()
{
Window child;
Array<Window> newControls { };
- for(c : controls)
+ for(c : controls; !c.nonClient)
{
- for(child = firstChild; child; child = child.next)
+ child = null;
+ if(!c.destroyed)
{
- if(child.nonClient) continue;
- if(c == child)
+ for(child = firstChild; child; child = child.next)
{
- newControls.Add(child);
- break;
+ if(c == child)
+ {
+ newControls.Add(child);
+ break;
+ }
}
}
if(!child)
}
for(child = firstChild; child; child = child.next)
{
- if(child.nonClient) continue;
+ if(child.nonClient || child.destroyed || !child.created) continue;
if(!newControls.Find(child))
{
newControls.Add(child);
delete controls;
controls = newControls;
newControls = null;
- }
+ }*/
void OnResize(int width, int height)
{
- if(!inAutoSize)
+ if(!bits.holdChildMonitoring && !inAutoSize)
DoResize(width, height);
}
void DoResize(int width, int height)
{
+ if(left.visible)
+ {
+ // Take into consideration the space we would gain back by getting rid of the scrolling buttons
+ if(direction == horizontal)
+ width += 2 * (left.size.w + 4);
+ else
+ height += 2 * (left.size.h + 4);
+ }
// TOIMPROVE: this needs to maintain an order and allow for dynamically adding
// children. inserting in the order should also be possible.
// TOIMPROVE: in Window.ec... it should be possible to change the order of children
if(created)
{
- int y, c;
+ int y = margin, c;
bool r = bits.reverse;
int inc = bits.reverse ? -1 : 1;
- Window child;
Window flip = null;
- y = margin;
- for(c = bits.reverse ? controls.count-1 : 0; c<controls.count && c>-1; c += inc)
+ for(c = r ? controls.count-1 : 0; c<controls.count && c>-1; c += inc)
{
Anchor anchor;
- child = controls[c];
+ Window child = controls[c];
if(flip && child == flip) break;
if(child.nonClient || !child.visible) continue;
anchor = child.anchor;
if(direction == vertical)
{
- if(bits.reverse)
+ if(r)
{
if(!anchor.bottom.type || anchor.bottom.distance != y)
child.anchor.bottom = y;
}
else
{
- if(bits.reverse)
+ if(r)
{
if(!anchor.right.type || anchor.right.distance != y)
child.anchor.right = y;
}
y += child.size.w + gap;
}
- Flip(flipper, child, controls, margin, &bits, &inc, &c, &y, &flip);
+ // If this child is the flipper, we flip
+ if(flipper && !flip && child == flipper)
+ {
+ flip = child;
+ if(r) { r = false; inc = 1; c = -1; }
+ else { r = true; inc =-1; c = controls.count; }
+ y = margin;
+ }
}
if(flip)
{
if(direction == vertical)
{
- if(bits.reverse) flip.anchor.bottom = y;
- else flip.anchor.top = y;
+ if(r) flip.anchor.bottom = y;
+ else flip.anchor.top = y;
}
else
{
- if(bits.reverse) flip.anchor.right = y;
- else flip.anchor.left = y;
+ if(r) flip.anchor.right = y;
+ else flip.anchor.left = y;
}
}
}
else
//this.clientSize.w = y - gap + margin;
this.size.w = y - gap + margin + (this.size.w - this.clientSize.w);
- //Update(null);
inAutoSize = false;
}
if(bits.scrollable && y > ((direction == horizontal) ? width : height))
{
scrollArea = (direction == horizontal) ? { y, 0 } : { 0, y };
- left.visible = true;
- right.visible = true;
+ if(bits.endButtons)
+ {
+ left.visible = true;
+ right.visible = true;
+ }
}
else
{
if(bits.scrollable)
{
// FOR WHEN SCROLLING OCCURED
- for(child : controls)
+ for(child : controls; !child.nonClient && child.visible)
child.anchor = child.anchor;
if(direction == horizontal)
public void DestroyChildren()
{
- Window child, next;
-
- bits.holdChildMonitoring = true;
- for(child = firstChild; child; child = next)
+ // This safe loop with 'left' will jam if the Stacker is destroyed
+ if(!destroyed && created)
{
- next = child ? child.next : null;
- if(!child.nonClient)
+ bool left = true;
+ while(left)
{
- child.Destroy(0);
- child.parent = null;
+ left = false;
+ for(w : controls)
+ {
+ if(!w.destroyed && w.created)
+ {
+ w.Destroy(0);
+ left = true;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // If the stacker is already destroyed, just clear everything
+ Iterator<Window> it { controls };
+ while(it.pointer = null, it.Next())
+ {
+ Window w = it.data;
+ it.Remove();
+ w.Destroy(0);
+ delete w;
}
}
- bits.holdChildMonitoring = false;
}
public void MakeControlVisible(Window control)
return result;
}
}
-
-static void Flip(Window flipper, Window child, Array<Window> controls, int margin, StackerBits * bits, int * inc, int * c, int * y, Window * flip)
-{
- if(flipper && !*flip && child == flipper)
- {
- *flip = child;
- (*bits).reverse = !(*bits).reverse;
- *inc = (*bits).reverse ? -1 : 1;
- *c = (*bits).reverse ? controls.count : -1;
- *y = margin;
- }
-}