2015-12-13 11:52:16 -06:00
|
|
|
// 13 december 2015
|
2015-12-13 11:53:37 -06:00
|
|
|
|
|
|
|
package ui
|
2015-12-13 11:52:16 -06:00
|
|
|
|
2015-12-16 13:03:47 -06:00
|
|
|
// #include <stdlib.h>
|
2015-12-13 11:52:16 -06:00
|
|
|
// #include "ui.h"
|
|
|
|
// extern void doAreaHandlerDraw(uiAreaHandler *, uiArea *, uiAreaDrawParams *);
|
2015-12-17 13:21:17 -06:00
|
|
|
// extern void doAreaHandlerMouseEvent(uiAreaHandler *, uiArea *, uiAreaMouseEvent *);
|
|
|
|
// extern void doAreaHandlerMouseCrossed(uiAreaHandler *, uiArea *, int);
|
|
|
|
// extern void doAreaHandlerDragBroken(uiAreaHandler *, uiArea *);
|
|
|
|
// extern int doAreaHandlerKeyEvent(uiAreaHandler *, uiArea *, uiAreaKeyEvent *);
|
2015-12-15 09:07:51 -06:00
|
|
|
// static inline uiAreaHandler *allocAreaHandler(void)
|
2015-12-13 11:52:16 -06:00
|
|
|
// {
|
|
|
|
// uiAreaHandler *ah;
|
|
|
|
//
|
|
|
|
// ah = (uiAreaHandler *) malloc(sizeof (uiAreaHandler));
|
|
|
|
// if (ah == NULL)
|
|
|
|
// return NULL;
|
|
|
|
// ah->Draw = doAreaHandlerDraw;
|
2015-12-17 13:21:17 -06:00
|
|
|
// ah->MouseEvent = doAreaHandlerMouseEvent;
|
|
|
|
// ah->MouseCrossed = doAreaHandlerMouseCrossed;
|
|
|
|
// ah->DragBroken = doAreaHandlerDragBroken;
|
|
|
|
// ah->KeyEvent = doAreaHandlerKeyEvent;
|
2015-12-13 11:52:16 -06:00
|
|
|
// return ah;
|
|
|
|
// }
|
|
|
|
// static inline void freeAreaHandler(uiAreaHandler *ah)
|
|
|
|
// {
|
|
|
|
// free(ah);
|
|
|
|
// }
|
|
|
|
import "C"
|
|
|
|
|
|
|
|
// no need to lock this; only the GUI thread can access it
|
|
|
|
var areahandlers = make(map[*C.uiAreaHandler]AreaHandler)
|
|
|
|
|
|
|
|
// AreaHandler defines the functionality needed for handling events
|
|
|
|
// from an Area.
|
|
|
|
type AreaHandler interface {
|
|
|
|
// TODO document all these
|
|
|
|
Draw(a *Area, dp *AreaDrawParams)
|
2015-12-17 13:21:17 -06:00
|
|
|
MouseEvent(a *Area, me *AreaMouseEvent)
|
|
|
|
MouseCrossed(a *Area, left bool)
|
|
|
|
DragBroken(a *Area)
|
|
|
|
KeyEvent(a *Area, ke *AreaKeyEvent) (handled bool)
|
2015-12-13 11:52:16 -06:00
|
|
|
}
|
|
|
|
|
2015-12-19 18:33:06 -06:00
|
|
|
func registerAreaHandler(ah AreaHandler) *C.uiAreaHandler {
|
2015-12-13 11:52:16 -06:00
|
|
|
uah := C.allocAreaHandler()
|
|
|
|
areahandlers[uah] = ah
|
|
|
|
return uah
|
|
|
|
}
|
|
|
|
|
|
|
|
func unregisterAreaHandler(uah *C.uiAreaHandler) {
|
|
|
|
delete(areahandlers, uah)
|
|
|
|
C.freeAreaHandler(uah)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AreaDrawParams defines the TODO.
|
|
|
|
type AreaDrawParams struct {
|
|
|
|
// TODO document all these
|
|
|
|
Context *DrawContext
|
2015-12-17 13:21:17 -06:00
|
|
|
AreaWidth float64
|
|
|
|
AreaHeight float64
|
2015-12-13 11:52:16 -06:00
|
|
|
ClipX float64
|
|
|
|
ClipY float64
|
|
|
|
ClipWidth float64
|
|
|
|
ClipHeight float64
|
|
|
|
}
|
|
|
|
|
2015-12-16 13:03:47 -06:00
|
|
|
//export doAreaHandlerDraw
|
2015-12-13 11:52:16 -06:00
|
|
|
func doAreaHandlerDraw(uah *C.uiAreaHandler, ua *C.uiArea, udp *C.uiAreaDrawParams) {
|
|
|
|
ah := areahandlers[uah]
|
|
|
|
a := areas[ua]
|
|
|
|
dp := &AreaDrawParams{
|
|
|
|
Context: &DrawContext{udp.Context},
|
2015-12-17 13:21:17 -06:00
|
|
|
AreaWidth: float64(udp.AreaWidth),
|
|
|
|
AreaHeight: float64(udp.AreaHeight),
|
2015-12-13 11:52:16 -06:00
|
|
|
ClipX: float64(udp.ClipX),
|
|
|
|
ClipY: float64(udp.ClipY),
|
|
|
|
ClipWidth: float64(udp.ClipWidth),
|
|
|
|
ClipHeight: float64(udp.ClipHeight),
|
|
|
|
}
|
|
|
|
ah.Draw(a, dp)
|
|
|
|
}
|
2015-12-17 13:21:17 -06:00
|
|
|
|
|
|
|
// TODO document all these
|
|
|
|
type AreaMouseEvent struct {
|
|
|
|
X float64
|
|
|
|
Y float64
|
|
|
|
AreaWidth float64
|
|
|
|
AreaHeight float64
|
|
|
|
Down uint
|
|
|
|
Up uint
|
|
|
|
Count uint
|
|
|
|
Modifiers Modifiers
|
|
|
|
Held []uint
|
|
|
|
}
|
|
|
|
|
|
|
|
func appendBits(out []uint, held C.uint64_t) []uint {
|
|
|
|
n := uint(1)
|
|
|
|
for i := 0; i < 64; i++ {
|
|
|
|
if held & 1 != 0 {
|
|
|
|
out = append(out, n)
|
|
|
|
}
|
|
|
|
held >>= 1
|
|
|
|
n++
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
//export doAreaHandlerMouseEvent
|
|
|
|
func doAreaHandlerMouseEvent(uah *C.uiAreaHandler, ua *C.uiArea, ume *C.uiAreaMouseEvent) {
|
|
|
|
ah := areahandlers[uah]
|
|
|
|
a := areas[ua]
|
|
|
|
me := &AreaMouseEvent{
|
|
|
|
X: float64(ume.X),
|
|
|
|
Y: float64(ume.Y),
|
|
|
|
AreaWidth: float64(ume.AreaWidth),
|
|
|
|
AreaHeight: float64(ume.AreaHeight),
|
|
|
|
Down: uint(ume.Down),
|
|
|
|
Up: uint(ume.Up),
|
|
|
|
Count: uint(ume.Count),
|
|
|
|
Modifiers: Modifiers(ume.Modifiers),
|
|
|
|
Held: make([]uint, 0, 64),
|
|
|
|
}
|
|
|
|
me.Held = appendBits(me.Held, ume.Held1To64)
|
|
|
|
ah.MouseEvent(a, me)
|
|
|
|
}
|
|
|
|
|
|
|
|
//export doAreaHandlerMouseCrossed
|
|
|
|
func doAreaHandlerMouseCrossed(uah *C.uiAreaHandler, ua *C.uiArea, left C.int) {
|
|
|
|
ah := areahandlers[uah]
|
|
|
|
a := areas[ua]
|
|
|
|
ah.MouseCrossed(a, tobool(left))
|
|
|
|
}
|
|
|
|
|
|
|
|
//export doAreaHandlerDragBroken
|
|
|
|
func doAreaHandlerDragBroken(uah *C.uiAreaHandler, ua *C.uiArea) {
|
|
|
|
ah := areahandlers[uah]
|
|
|
|
a := areas[ua]
|
|
|
|
ah.DragBroken(a)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO document all these
|
|
|
|
type AreaKeyEvent struct {
|
|
|
|
Key rune
|
|
|
|
ExtKey ExtKey
|
|
|
|
Modifier Modifiers
|
|
|
|
Modifiers Modifiers
|
|
|
|
Up bool
|
|
|
|
}
|
|
|
|
|
|
|
|
//export doAreaHandlerKeyEvent
|
|
|
|
func doAreaHandlerKeyEvent(uah *C.uiAreaHandler, ua *C.uiArea, uke *C.uiAreaKeyEvent) C.int {
|
|
|
|
ah := areahandlers[uah]
|
|
|
|
a := areas[ua]
|
|
|
|
ke := &AreaKeyEvent{
|
|
|
|
Key: rune(uke.Key),
|
|
|
|
ExtKey: ExtKey(uke.ExtKey),
|
|
|
|
Modifier: Modifiers(uke.Modifier),
|
|
|
|
Modifiers: Modifiers(uke.Modifiers),
|
|
|
|
Up: tobool(uke.Up),
|
|
|
|
}
|
|
|
|
return frombool(ah.KeyEvent(a, ke))
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO document
|
|
|
|
//
|
|
|
|
// Note: these must be numerically identical to their libui equivalents.
|
|
|
|
type Modifiers uint
|
|
|
|
const (
|
|
|
|
Ctrl Modifiers = 1 << iota
|
|
|
|
Alt
|
|
|
|
Shift
|
|
|
|
Super
|
|
|
|
)
|
|
|
|
|
|
|
|
// TODO document
|
|
|
|
//
|
|
|
|
// Note: these must be numerically identical to their libui equivalents.
|
|
|
|
type ExtKey int
|
|
|
|
const (
|
|
|
|
Escape ExtKey = iota + 1
|
|
|
|
Insert // equivalent to "Help" on Apple keyboards
|
|
|
|
Delete
|
|
|
|
Home
|
|
|
|
End
|
|
|
|
PageUp
|
|
|
|
PageDown
|
|
|
|
Up
|
|
|
|
Down
|
|
|
|
Left
|
|
|
|
Right
|
|
|
|
F1 // F1..F12 are guaranteed to be consecutive
|
|
|
|
F2
|
|
|
|
F3
|
|
|
|
F4
|
|
|
|
F5
|
|
|
|
F6
|
|
|
|
F7
|
|
|
|
F8
|
|
|
|
F9
|
|
|
|
F10
|
|
|
|
F11
|
|
|
|
F12
|
|
|
|
N0 // numpad keys; independent of Num Lock state
|
|
|
|
N1 // N0..N9 are guaranteed to be consecutive
|
|
|
|
N2
|
|
|
|
N3
|
|
|
|
N4
|
|
|
|
N5
|
|
|
|
N6
|
|
|
|
N7
|
|
|
|
N8
|
|
|
|
N9
|
|
|
|
NDot
|
|
|
|
NEnter
|
|
|
|
NAdd
|
|
|
|
NSubtract
|
|
|
|
NMultiply
|
|
|
|
NDivide
|
|
|
|
)
|