mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
gg: add text rendering, keyboard event handling for JS and other fixes (#12932)
This commit is contained in:
348
vlib/gg/gg.js.v
348
vlib/gg/gg.js.v
@ -36,7 +36,7 @@ pub struct Event {
|
||||
pub mut:
|
||||
frame_count u64
|
||||
typ DOMEventType
|
||||
key_code DOMKeyCode
|
||||
key_code KeyCode
|
||||
char_code u32
|
||||
key_repeat bool
|
||||
modifiers u32
|
||||
@ -252,7 +252,13 @@ pub:
|
||||
enable_dragndrop bool // enable file dropping (drag'n'drop), default is false
|
||||
max_dropped_files int = 1 // max number of dropped files to process (default: 1)
|
||||
max_dropped_file_path_length int = 2048 // max length in bytes of a dropped UTF-8 file path (default: 2048)
|
||||
canvas JS.HTMLCanvasElement
|
||||
canvas string
|
||||
}
|
||||
|
||||
const size = Size{0, 0}
|
||||
|
||||
pub fn window_size() Size {
|
||||
return gg.size
|
||||
}
|
||||
|
||||
pub struct Context {
|
||||
@ -284,9 +290,33 @@ pub mut:
|
||||
pressed_keys [key_code_max]bool // an array representing all currently pressed keys
|
||||
pressed_keys_edge [key_code_max]bool // true when the previous state of pressed_keys,
|
||||
context JS.CanvasRenderingContext2D [noinit]
|
||||
canvas JS.HTMLCanvasElement [noinit]
|
||||
// *before* the current event was different
|
||||
}
|
||||
|
||||
fn get_canvas(elem JS.HTMLElement) &JS.HTMLCanvasElement {
|
||||
match elem {
|
||||
JS.HTMLCanvasElement {
|
||||
return elem
|
||||
}
|
||||
else {
|
||||
panic('gg: element is not an HTMLCanvasElement')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_context(canvas JS.HTMLCanvasElement) JS.CanvasRenderingContext2D {
|
||||
ctx := canvas.getContext('2d'.str, js_undefined()) or { panic('cannot get context') }
|
||||
match ctx {
|
||||
JS.CanvasRenderingContext2D {
|
||||
return ctx
|
||||
}
|
||||
else {
|
||||
panic('failed to get 2D context')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_context(cfg Config) &Context {
|
||||
mut g := &Context{}
|
||||
|
||||
@ -294,24 +324,30 @@ pub fn new_context(cfg Config) &Context {
|
||||
g.width = cfg.width
|
||||
g.height = cfg.height
|
||||
g.ui_mode = cfg.ui_mode
|
||||
mut sz := gg.size
|
||||
sz.height = g.height
|
||||
sz.width = g.width
|
||||
g.config = cfg
|
||||
if isnil(cfg.user_data) {
|
||||
g.user_data = g
|
||||
}
|
||||
g.window = dom.window()
|
||||
ctx := cfg.canvas.getContext('2d'.str, js_undefined()) or { panic('') }
|
||||
match ctx {
|
||||
JS.CanvasRenderingContext2D {
|
||||
g.context = ctx
|
||||
}
|
||||
else {
|
||||
panic('gg: cannot get 2D context')
|
||||
}
|
||||
document := dom.document
|
||||
canvas_elem := document.getElementById(cfg.canvas.str) or {
|
||||
panic('gg: cannot get canvas element')
|
||||
}
|
||||
canvas := get_canvas(canvas_elem)
|
||||
g.canvas = canvas
|
||||
g.context = get_context(g.canvas)
|
||||
|
||||
mouse_down_event_handler := fn [mut g] (event JS.Event) {
|
||||
match event {
|
||||
JS.MouseEvent {
|
||||
e := g.handle_mouse_event(event)
|
||||
e := g.handle_mouse_event(event, .mouse_down)
|
||||
if !isnil(g.config.event_fn) {
|
||||
f := g.config.event_fn
|
||||
f(e, g.config.user_data)
|
||||
}
|
||||
if !isnil(g.config.click_fn) {
|
||||
f := g.config.click_fn
|
||||
f(e.mouse_x, e.mouse_y, e.mouse_button, g.config.user_data)
|
||||
@ -324,7 +360,11 @@ pub fn new_context(cfg Config) &Context {
|
||||
mouse_up_event_handler := fn [mut g] (event JS.Event) {
|
||||
match event {
|
||||
JS.MouseEvent {
|
||||
e := g.handle_mouse_event(event)
|
||||
e := g.handle_mouse_event(event, .mouse_up)
|
||||
if !isnil(g.config.event_fn) {
|
||||
f := g.config.event_fn
|
||||
f(e, g.config.user_data)
|
||||
}
|
||||
if !isnil(g.config.unclick_fn) {
|
||||
f := g.config.unclick_fn
|
||||
f(e.mouse_x, e.mouse_y, e.mouse_button, g.config.user_data)
|
||||
@ -336,7 +376,11 @@ pub fn new_context(cfg Config) &Context {
|
||||
mouse_move_event_handler := fn [mut g] (event JS.Event) {
|
||||
match event {
|
||||
JS.MouseEvent {
|
||||
e := g.handle_mouse_event(event)
|
||||
e := g.handle_mouse_event(event, .mouse_move)
|
||||
if !isnil(g.config.event_fn) {
|
||||
f := g.config.event_fn
|
||||
f(e, g.config.user_data)
|
||||
}
|
||||
if !isnil(g.config.move_fn) {
|
||||
f := g.config.move_fn
|
||||
f(e.mouse_x, e.mouse_y, g.config.user_data)
|
||||
@ -349,7 +393,11 @@ pub fn new_context(cfg Config) &Context {
|
||||
mouse_leave_event_handler := fn [mut g] (event JS.Event) {
|
||||
match event {
|
||||
JS.MouseEvent {
|
||||
e := g.handle_mouse_event(event)
|
||||
e := g.handle_mouse_event(event, .mouse_leave)
|
||||
if !isnil(g.config.event_fn) {
|
||||
f := g.config.event_fn
|
||||
f(e, g.config.user_data)
|
||||
}
|
||||
if !isnil(g.config.leave_fn) {
|
||||
f := g.config.leave_fn
|
||||
f(e, g.config.user_data)
|
||||
@ -362,7 +410,11 @@ pub fn new_context(cfg Config) &Context {
|
||||
mouse_enter_event_handler := fn [mut g] (event JS.Event) {
|
||||
match event {
|
||||
JS.MouseEvent {
|
||||
e := g.handle_mouse_event(event)
|
||||
e := g.handle_mouse_event(event, .mouse_enter)
|
||||
if !isnil(g.config.event_fn) {
|
||||
f := g.config.event_fn
|
||||
f(e, g.config.user_data)
|
||||
}
|
||||
if !isnil(g.config.enter_fn) {
|
||||
f := g.config.enter_fn
|
||||
f(e, g.config.user_data)
|
||||
@ -371,11 +423,32 @@ pub fn new_context(cfg Config) &Context {
|
||||
else {}
|
||||
}
|
||||
}
|
||||
cfg.canvas.addEventListener('mousedown'.str, mouse_down_event_handler, JS.EventListenerOptions{})
|
||||
|
||||
keydown_event_handler := fn [mut g] (event JS.Event) {
|
||||
println('keyboard')
|
||||
match event {
|
||||
JS.KeyboardEvent {
|
||||
e := g.handle_keyboard_event(event, .key_down)
|
||||
|
||||
if !isnil(g.config.event_fn) {
|
||||
f := g.config.event_fn
|
||||
f(e, g.config.user_data)
|
||||
}
|
||||
if !isnil(g.config.keydown_fn) {
|
||||
f := g.config.keydown_fn
|
||||
// todo: modifiers
|
||||
f(e.key_code, .super, g.config.user_data)
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
g.canvas.addEventListener('mousedown'.str, mouse_down_event_handler, JS.EventListenerOptions{})
|
||||
dom.window().addEventListener('mouseup'.str, mouse_up_event_handler, JS.EventListenerOptions{})
|
||||
cfg.canvas.addEventListener('mousemove'.str, mouse_move_event_handler, JS.EventListenerOptions{})
|
||||
cfg.canvas.addEventListener('mouseleave'.str, mouse_leave_event_handler, JS.EventListenerOptions{})
|
||||
cfg.canvas.addEventListener('mouseenter'.str, mouse_enter_event_handler, JS.EventListenerOptions{})
|
||||
g.canvas.addEventListener('mousemove'.str, mouse_move_event_handler, JS.EventListenerOptions{})
|
||||
g.canvas.addEventListener('mouseleave'.str, mouse_leave_event_handler, JS.EventListenerOptions{})
|
||||
g.canvas.addEventListener('mouseenter'.str, mouse_enter_event_handler, JS.EventListenerOptions{})
|
||||
dom.document.addEventListener('keydown'.str, keydown_event_handler, JS.EventListenerOptions{})
|
||||
return g
|
||||
}
|
||||
|
||||
@ -400,6 +473,9 @@ pub fn (mut ctx Context) draw_line(x1 f32, y1 f32, x2 f32, y2 f32, c gx.Color) {
|
||||
ctx.context.closePath()
|
||||
}
|
||||
|
||||
pub fn (mut ctx Context) quit() {
|
||||
}
|
||||
|
||||
pub fn (mut ctx Context) draw_rect(x f32, y f32, w f32, h f32, c gx.Color) {
|
||||
ctx.context.beginPath()
|
||||
ctx.context.fillStyle = c.to_css_string().str
|
||||
@ -423,10 +499,10 @@ fn gg_animation_frame_fn(mut g Context) {
|
||||
})
|
||||
}
|
||||
|
||||
fn (mut g Context) handle_mouse_event(event JS.MouseEvent) Event {
|
||||
fn (mut g Context) handle_mouse_event(event JS.MouseEvent, typ DOMEventType) Event {
|
||||
mut e := Event{}
|
||||
|
||||
e.typ = .mouse_down
|
||||
e.typ = typ
|
||||
e.frame_count = g.frame
|
||||
|
||||
match int(event.button) {
|
||||
@ -457,3 +533,233 @@ fn (mut g Context) handle_mouse_event(event JS.MouseEvent) Event {
|
||||
g.mouse_dy = int(event.movementY)
|
||||
return e
|
||||
}
|
||||
|
||||
fn (mut g Context) handle_keyboard_event(event JS.KeyboardEvent, typ DOMEventType) Event {
|
||||
mut e := Event{}
|
||||
e.typ = typ
|
||||
e.frame_count = g.frame
|
||||
|
||||
match string(event.code) {
|
||||
'Space' {
|
||||
e.key_code = .space
|
||||
}
|
||||
'Minus' {
|
||||
e.key_code = .minus
|
||||
}
|
||||
'Quote' {
|
||||
e.key_code = .apostrophe
|
||||
}
|
||||
'Comma' {
|
||||
e.key_code = .comma
|
||||
}
|
||||
'Period' {
|
||||
e.key_code = .period
|
||||
}
|
||||
'Digit0' {
|
||||
e.key_code = ._0
|
||||
}
|
||||
'Digit1' {
|
||||
e.key_code = ._1
|
||||
}
|
||||
'Digit2' {
|
||||
e.key_code = ._2
|
||||
}
|
||||
'Digit3' {
|
||||
e.key_code = ._3
|
||||
}
|
||||
'Digit4' {
|
||||
e.key_code = ._4
|
||||
}
|
||||
'Digit5' {
|
||||
e.key_code = ._5
|
||||
}
|
||||
'Digit6' {
|
||||
e.key_code = ._6
|
||||
}
|
||||
'Digit7' {
|
||||
e.key_code = ._7
|
||||
}
|
||||
'Digit8' {
|
||||
e.key_code = ._8
|
||||
}
|
||||
'Digit9' {
|
||||
e.key_code = ._9
|
||||
}
|
||||
'Semicolon' {
|
||||
e.key_code = .semicolon
|
||||
}
|
||||
'Equal' {
|
||||
e.key_code = .equal
|
||||
}
|
||||
'KeyA' {
|
||||
e.key_code = .a
|
||||
}
|
||||
'KeyB' {
|
||||
e.key_code = .b
|
||||
}
|
||||
'KeyC' {
|
||||
e.key_code = .c
|
||||
}
|
||||
'KeyD' {
|
||||
e.key_code = .d
|
||||
}
|
||||
'KeyE' {
|
||||
e.key_code = .e
|
||||
}
|
||||
'KeyF' {
|
||||
e.key_code = .f
|
||||
}
|
||||
'KeyG' {
|
||||
e.key_code = .g
|
||||
}
|
||||
'KeyH' {
|
||||
e.key_code = .h
|
||||
}
|
||||
'KeyI' {
|
||||
e.key_code = .i
|
||||
}
|
||||
'KeyJ' {
|
||||
e.key_code = .j
|
||||
}
|
||||
'KeyK' {
|
||||
e.key_code = .k
|
||||
}
|
||||
'KeyL' {
|
||||
e.key_code = .l
|
||||
}
|
||||
'KeyM' {
|
||||
e.key_code = .m
|
||||
}
|
||||
'KeyN' {
|
||||
e.key_code = .n
|
||||
}
|
||||
'KeyO' {
|
||||
e.key_code = .o
|
||||
}
|
||||
'KeyP' {
|
||||
e.key_code = .p
|
||||
}
|
||||
'KeyQ' {
|
||||
e.key_code = .q
|
||||
}
|
||||
'KeyR' {
|
||||
e.key_code = .r
|
||||
}
|
||||
'KeyS' {
|
||||
e.key_code = .s
|
||||
}
|
||||
'KeyT' {
|
||||
e.key_code = .t
|
||||
}
|
||||
'KeyU' {
|
||||
e.key_code = .u
|
||||
}
|
||||
'KeyV' {
|
||||
e.key_code = .v
|
||||
}
|
||||
'KeyW' {
|
||||
e.key_code = .w
|
||||
}
|
||||
'KeyX' {
|
||||
e.key_code = .x
|
||||
}
|
||||
'KeyY' {
|
||||
e.key_code = .y
|
||||
}
|
||||
'KeyZ' {
|
||||
e.key_code = .z
|
||||
}
|
||||
'BracketLeft' {
|
||||
e.key_code = .left_bracket
|
||||
}
|
||||
'BracketRight' {
|
||||
e.key_code = .right_bracket
|
||||
}
|
||||
'Backslash' {
|
||||
e.key_code = .backslash
|
||||
}
|
||||
'Backquote' {
|
||||
e.key_code = .grave_accent
|
||||
}
|
||||
'Escape' {
|
||||
e.key_code = .escape
|
||||
}
|
||||
'Enter' {
|
||||
e.key_code = .enter
|
||||
}
|
||||
'Tab' {
|
||||
e.key_code = .tab
|
||||
}
|
||||
'Backspace' {
|
||||
e.key_code = .backspace
|
||||
}
|
||||
'Insert' {
|
||||
e.key_code = .insert
|
||||
}
|
||||
'Delete' {
|
||||
e.key_code = .delete
|
||||
}
|
||||
'ArrowRight' {
|
||||
e.key_code = .right
|
||||
}
|
||||
'ArrowLeft' {
|
||||
e.key_code = .left
|
||||
}
|
||||
'ArrowUp' {
|
||||
e.key_code = .up
|
||||
}
|
||||
'ArrowDown' {
|
||||
e.key_code = .down
|
||||
}
|
||||
'PageUp' {
|
||||
e.key_code = .page_up
|
||||
}
|
||||
'PageDown' {
|
||||
e.key_code = .page_down
|
||||
}
|
||||
'Home' {
|
||||
e.key_code = .home
|
||||
}
|
||||
'End' {
|
||||
e.key_code = .end
|
||||
}
|
||||
'CapsLock' {
|
||||
e.key_code = .caps_lock
|
||||
}
|
||||
'ScrollLock' {
|
||||
e.key_code = .scroll_lock
|
||||
}
|
||||
'NumLock' {
|
||||
e.key_code = .num_lock
|
||||
}
|
||||
'PrintScreen' {
|
||||
e.key_code = .print_screen
|
||||
}
|
||||
'Pause' {
|
||||
e.key_code = .pause
|
||||
}
|
||||
'ShiftLeft' {
|
||||
e.key_code = .left_shift
|
||||
}
|
||||
'ShiftRight' {
|
||||
e.key_code = .right_shift
|
||||
}
|
||||
'AltLeft' {
|
||||
e.key_code = .left_alt
|
||||
}
|
||||
'AltRight' {
|
||||
e.key_code = .right_alt
|
||||
}
|
||||
'ControlLeft' {
|
||||
e.key_code = .left_control
|
||||
}
|
||||
'ControlRight' {
|
||||
e.key_code = .right_control
|
||||
}
|
||||
else {
|
||||
panic('todo: more keycodes (${string(event.code)})')
|
||||
}
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
|
Reference in New Issue
Block a user