function draw_window x y w h focussed data { filled_rectangle 0 0 255 255 0 0 255 255 0 0 255 255 0 0 255 255 x y w h }
function draw_button x y w h focussed data { number r g b if (== focussed TRUE) yellow white = r 255 = g 255 = b 0 :yellow = r 255 = g 255 = b 255 :white number tw th font_width font tw [data "text"] font_height font th
number xx yy = xx (+ x (/ w 2)) - xx (/ tw 2) = yy (+ y (/ h 2)) - yy (/ th 2)
filled_rectangle 0 0 255 255 0 0 255 255 0 255 255 255 0 255 255 255 x y w h rectangle r g b 255 x y w h 2 font_draw font r g b 255 [data "text"] xx yy }
function null_event type a b c d x y w h focussed data { }
function button_event type a b c d x y w h focussed data { if (&& (== type EVENT_MOUSE_DOWN) (== a 1)) play number on_button call_result on_button owned x y w h c d if (== on_button TRUE) really_play mml_play [data "sfx"] 1 0 :really_play :play
if (&& (== TRUE focussed) (|| (&& (== type EVENT_KEY_DOWN) (== KEY_RETURN a)) (&& (== type EVENT_JOY_DOWN) (== a JOY_A)))) play_it mml_play [data "sfx"] 1 0 :play_it }
function mkbutton text sfx { map m map_set m "text" text map_set m "sfx" sfx map_set m "draw" draw_button map_set m "event" button_event return m }
function owned wx wy ww wh x y { if (|| (< x wx) (< y wy) (>= x (+ wx ww)) (>= y (+ wy wh))) nope return FALSE :nope return TRUE }
function gui_event id type a b c d x y w h focussed data { call [data "event"] type a b c d x y w h focussed data }
function gui_draw id x y w h focussed data { call [data "draw"] x y w h focussed data }
I've added button depression in git. Note: the userdata (data in the above snipped) should be a reference (~data) if you want to store any state like I did for button depression (remembering the depressed state of the button requires data to be a reference to change it.)
function draw_window x y w h focussed data { filled_rectangle 0 0 255 255 0 0 255 255 0 0 255 255 0 0 255 255 x y w h }
function draw_button x y w h focussed data { number r g b if (== focussed TRUE) yellow white = r 255 = g 255 = b 0 :yellow = r 255 = g 255 = b 255 :white number tw th font_width font tw [data "text"] font_height font th
number xx yy = xx (+ x (/ w 2)) - xx (/ tw 2) = yy (+ y (/ h 2)) - yy (/ th 2)
number ox oy if (== [data "down"] TRUE) offset no_offset = ox 2 = oy 2 :offset = ox 0 = oy 0 :no_offset
+ x ox + y oy + xx ox + yy oy
filled_rectangle 0 0 255 255 0 0 255 255 0 255 255 255 0 255 255 255 x y w h rectangle r g b 255 x y w h 2 font_draw font r g b 255 [data "text"] xx yy }
function button_event type a b c d x y w h focussed ~data { number pressed = pressed 0
if (&& (== type EVENT_MOUSE_DOWN) (== a 1) (== b FALSE)) down number on_button call_result on_button owned x y w h c d if (== on_button TRUE) really_down map_set data "down" TRUE :really_down :down
if (&& (== [data "down"] TRUE) (== type EVENT_MOUSE_UP)) up number on_button call_result on_button owned x y w h c d if (== on_button TRUE) really_up = pressed 1 :really_up map_set data "down" FALSE :up
if (&& (== TRUE focussed) (== FALSE b) (|| (&& (== type EVENT_KEY_DOWN) (== KEY_RETURN a)) (&& (== type EVENT_JOY_DOWN) (== a JOY_A)))) down2 map_set data "down" TRUE :down2 if (&& (== [data "down"] TRUE) (== TRUE focussed) (|| (&& (== type EVENT_KEY_UP) (== KEY_RETURN a)) (&& (== type EVENT_JOY_UP) (== a JOY_A)))) play_it = pressed 1 map_set data "down" FALSE :play_it
if (== pressed 1) press call [ops [data "text"]] data :press }
function mkbutton text { map m map_set m "text" text map_set m "draw" draw_button map_set m "event" button_event map_set m "down" FALSE return m }
function owned wx wy ww wh x y { if (|| (< x wx) (< y wy) (>= x (+ wx ww)) (>= y (+ wy wh))) nope return FALSE :nope return TRUE }
function null_event type a b c d x y w h focussed ~data { }
function gui_event id type a b c d x y w h focussed ~data { call [data "event"] type a b c d x y w h focussed data }
function gui_draw id x y w h focussed data { call [data "draw"] x y w h focussed data }
function draw { number w font_width font w buf font_draw font 255 255 255 255 buf (- 790 w) 50 }
function i_num data { if (== peq 1) set = buf [data "text"] = peq 0 return :set
number found string_matches found buf "[\\.]"
if (&& (== found TRUE) (== [data "text"] ".")) nodup return :nodup
+ buf [data "text"] }
function i_op data { = peq 0 call i_eq data = lastop [data "text"] = last buf = peq 1 }
function i_neg data { number found string_matches found buf "^-"
if (== found TRUE) pos negative string_substr buf 1 :pos string_format buf "-%" buf :negative }
function i_eq data { if (== peq 1) clear_it calc = buf "0" = last "" = lastop "=" :clear_it number a b = a buf = b last if (== lastop "+") __add (== lastop "-") __sub (== lastop "*") __mul (== lastop "/") __div + a b :__add - b a = a b :__sub * a b :__mul / b a = a b :__div string_format buf "%" a = last "" = lastop "=" = peq 1 :calc }