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 [, , , ] 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;