1
0
Fork 0
fgdata/Nasal/canvas/gui/Widget.nas
TheFGFSEagle 372d68a775 Canvas slider widget:
Added value display
Add ticks, round mouse dragging result to nearest multiple of step size,
implement scroll handler
Add keybindings for adjusting slider value
2023-02-28 12:47:00 +00:00

229 lines
4.9 KiB
Text

gui.Widget = {
#
new: func(derived)
{
var m = canvas.Widget.new({
parents: [derived, gui.Widget],
_focused: 0,
_focus_policy: gui.Widget.NoFocus,
_hover: 0,
_enabled: 1,
_view: nil,
_pos: [0, 0],
_size: [32, 32],
_bindings: []
});
m.setLayoutMinimumSize([16, 16]);
m.setLayoutSizeHint([32, 32]);
m.setLayoutMaximumSize([m._MAX_SIZE, m._MAX_SIZE]);
m.setSetGeometryFunc(m._impl.setGeometry);
return m;
},
setFixedSize: func(x, y)
{
me.setMinimumSize([x, y]);
me.setSizeHint([x, y]);
me.setMaximumSize([x, y]);
return me;
},
setEnabled: func(enabled)
{
if( me._enabled == enabled )
return me;
me._enabled = enabled;
me.clearFocus();
me._onStateChange();
return me;
},
# Move the widget to the given position (relative to its parent)
move: func(x, y)
{
me._pos[0] = x;
me._pos[1] = y;
if( me._view != nil )
me._view._root.setTranslation(x, y);
return me;
},
#
setSize: func(w, h)
{
me._size[0] = w;
me._size[1] = h;
if( me._view != nil )
me._view.setSize(me, w, h);
return me;
},
# Set geometry of widget (usually used by layouting system)
#
# @param geom [<x>, <y>, <width>, <height>]
setGeometry: func(geom)
{
me.move(geom[0], geom[1]);
me.setSize(geom[2], geom[3]);
me._onStateChange();
return me;
},
#
setFocus: func
{
if( me._focused )
return me;
var canvas = me.getCanvas();
if( canvas._impl['_focused_widget'] != nil )
canvas._focused_widget.clearFocus();
if( !me._enabled )
return me;
me._focused = 1;
canvas._focused_widget = me;
if( me._view != nil )
me._view._root.setFocus();
me._trigger("focus-in");
me._onStateChange();
return me;
},
#
clearFocus: func
{
if( !me._focused )
return me;
me._focused = 0;
me.getCanvas()._focused_widget = nil;
me.getCanvas().clearFocusElement();
me._trigger("focus-out");
me._onStateChange();
return me;
},
#
hasActiveFocus:func
{
return me.getCanvas()._focused_widget == me;
},
#
listen: func(type, cb)
{
me._view._root.addEventListener("cb." ~ type, cb);
return me;
},
onRemove: func
{
if( me._view != nil )
{
me._view._root.del();
me._view = nil;
}
if( me._focused and me.getCanvas() )
me.getCanvas()._focused_widget = nil;
},
# protected:
_MAX_SIZE: 32768, # size for "no size-limit"
_onStateChange: func
{
if( me._view != nil and me._view.update != nil )
me._view.update(me);
},
visibilityChanged: func(visible)
{
me._view._root.setVisible(visible);
},
bindShortcut: func(s, f)
{
if (!isa(s, keyboard.Shortcut)) {
s = keyboard.Shortcut.new(s);
}
foreach (var b; me._bindings) {
if (b.shortcut.equals(s)) {
b.f = f;
return;
}
}
append(me._bindings, keyboard.Binding.new(s, f));
# add listener when first binding is added
# if this happens before the view is set, we instead do it in _setView below
if ((size(me._bindings) == 1) and me._view) {
me._view._root.addEventListener("keydown", func(e) me._onKeyPressed(e));
}
},
_onKeyPressed: func(e) {
foreach (var b; me._bindings) {
if (b.shortcut.match(keyboard.findKeyName(e.keyCode), e.shiftKey, e.ctrlKey, e.altKey, e.metaKey)) {
b.fire(e);
}
}
},
_setView: func(view)
{
me._view = view;
var root = view._root;
var canvas = root.getCanvas();
me.setCanvas(canvas);
canvas.addEventListener("wm.focus-in", func {
me._onStateChange();
});
canvas.addEventListener("wm.focus-out", func {
me._onStateChange();
});
root.addEventListener("mouseenter", func {
me._hover = 1;
me._trigger("mouse-enter");
me._onStateChange();
});
root.addEventListener("mousedown", func {
if( me._focus_policy & me.ClickFocus )
me.setFocus();
});
root.addEventListener("mouseleave", func {
me._hover = 0;
me._trigger("mouse-leave");
me._onStateChange();
});
# if we have keyboard bindings defined, add the listener for them
if (size(me._bindings)) {
root.addEventListener("keydown", func(e) me._onKeyPressed(e));
}
},
_trigger: func(type, data = nil)
{
if( me._view != nil )
me._view._root.dispatchEvent(
canvas.CustomEvent.new("cb." ~ type, {detail: data})
);
return me;
},
_windowFocus: func
{
var canvas = me.getCanvas();
return canvas != nil ? canvas.data("focused") : 0;
}
};
# enum FocusPolicy:
gui.Widget.NoFocus = 0;
gui.Widget.TabFocus = 1;
gui.Widget.ClickFocus = 2;
gui.Widget.StrongFocus = gui.Widget.TabFocus
| gui.Widget.ClickFocus;