#!/usr/bin/env lua
-- MoonFLTK example: keyboard.lua
--
-- Derived from the FLTK test/keyboard.cxx example (http://www.fltk.org)
--

fl = require("moonfltk")

function MyWindow()
   local my_window = fl.window_sub(495, 215, arg[0])
   my_window:override_handle(function(event)
      if event == 'mousewheel' then
         roller_x:value( roller_x:value() + fl.event_dx() * roller_x:step() )
         roller_y:value( roller_y:value() + fl.event_dy() * roller_y:step() )
         return true
      end
      return false
   end)

   my_window:box('flat box')
   my_window:color(fl.BACKGROUND_COLOR)
   my_window:selection_color(fl.BACKGROUND_COLOR)
   my_window:labeltype('none')
   my_window:labelfont(0)
   my_window:labelsize(14)
   my_window:labelcolor(fl.FOREGROUND_COLOR)
   my_window:align(fl.ALIGN_TOP)
   my_window:when(fl.WHEN_RELEASE)
   local o = fl.button(15, 70, 20, 20, "Esc ")
   o:labelsize(8)
   o:callback(key_cb, 'escape')
   o = fl.button(50, 70, 20, 20, "F1")
   o:labelsize(10)
   o:callback(key_cb, 'f1')
   o = fl.button(70, 70, 20, 20, "F2")
   o:labelsize(10)
   o:callback(key_cb, 'f2')
   o = fl.button(90, 70, 20, 20, "F3")
   o:labelsize(10)
   o:callback(key_cb, 'f3')
   o = fl.button(110, 70, 20, 20, "F4")
   o:labelsize(10)
   o:callback(key_cb, 'f4')
   o = fl.button(140, 70, 20, 20, "F5")
   o:labelsize(10)
   o:callback(key_cb, 'f5')
   o = fl.button(160, 70, 20, 20, "F6")
   o:labelsize(10)
   o:callback(key_cb, 'f6')
   o = fl.button(180, 70, 20, 20, "F7")
   o:labelsize(10)
   o:callback(key_cb, 'f7')
   o = fl.button(200, 70, 20, 20, "F8")
   o:labelsize(10)
   o:callback(key_cb, 'f8')
   o = fl.button(230, 70, 20, 20, "F9")
   o:labelsize(10)
   o:callback(key_cb, 'f9')
   o = fl.button(250, 70, 20, 20, "F10")
   o:labelsize(10)
   o:callback(key_cb, 'f10')
   o = fl.button(270, 70, 20, 20, "F11")
   o:labelsize(10)
   o:callback(key_cb, 'f11')
   o = fl.button(290, 70, 20, 20, "F12")
   o:labelsize(10)
   o:callback(key_cb, 'f12')
   o = fl.button(325, 70, 20, 20, "Print ")
   o:labelsize(8)
   o:callback(key_cb, 'print')
   o = fl.button(345, 70, 20, 20, "Sclk ")
   o:labelsize(8)
   o:callback(key_cb, 'scroll lock')
   o = fl.button(365, 70, 20, 20, "Paus ")
   o:labelsize(8)
   o:callback(key_cb, 'pause')
   o = fl.button(15, 100, 20, 20, "`")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(35, 100, 20, 20, "1")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(55, 100, 20, 20, "2")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(75, 100, 20, 20, "3")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(95, 100, 20, 20, "4")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(115, 100, 20, 20, "5")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(135, 100, 20, 20, "6")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(155, 100, 20, 20, "7")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(175, 100, 20, 20, "8")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(195, 100, 20, 20, "9")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(215, 100, 20, 20, "0")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(235, 100, 20, 20, "-")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(255, 100, 20, 20, "=")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(275, 100, 35, 20, "Bksp")
   o:labeltype('shadow')
   o:labelsize(8)
   o:callback(key_cb, 'backspace')
   o:align(fl.ALIGN_LEFT|fl.ALIGN_INSIDE)
   o = fl.button(325, 100, 20, 20, "Ins ")
   o:labelsize(8)
   o:callback(key_cb, 'insert')
   o = fl.button(345, 100, 20, 20, "Home")
   o:labelsize(8)
   o:callback(key_cb, 'home')
   o = fl.button(365, 100, 20, 20, "pgup ")
   o:labelsize(8)
   o:callback(key_cb, 'page up')
   o = fl.button(400, 100, 20, 20, "Num")
   o:labelsize(8)
   o:callback(key_cb, 'num lock')
   o = fl.button(420, 100, 20, 20, "/")
   o:labelsize(10)
   o:callback(key_cb, 'kp /')
   o = fl.button(440, 100, 20, 20, "*")
   o:labelsize(10)
   o:callback(key_cb, 'kp *')
   o = fl.button(460, 100, 20, 20, "-")
   o:labelsize(10)
   o:callback(key_cb, 'kp -')
   o = fl.button(15, 120, 27, 20, "Tab")
   o:labelsize(8)
   o:callback(key_cb, 'tab')
   o:align(fl.ALIGN_LEFT|fl.ALIGN_INSIDE)
   o = fl.button(42, 120, 20, 20, "Q")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(62, 120, 20, 20, "W")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(82, 120, 20, 20, "E")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(102, 120, 20, 20, "R")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(122, 120, 20, 20, "T")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(142, 120, 20, 20, "Y")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(162, 120, 20, 20, "U")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(182, 120, 20, 20, "I")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(202, 120, 20, 20, "O")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(222, 120, 20, 20, "P")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(242, 120, 20, 20, "[")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(262, 120, 20, 20, "]")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(282, 120, 28, 20, "\\")
   o:labelsize(10)
   o:callback(key_cb)
   o:align(fl.ALIGN_LEFT|fl.ALIGN_INSIDE)
   o = fl.button(325, 120, 20, 20, "Del ")
   o:labelsize(8)
   o:callback(key_cb, 'delete')
   o = fl.button(345, 120, 20, 20, "End ")
   o:labelsize(8)
   o:callback(key_cb, 'end')
   o = fl.button(365, 120, 20, 20, "pgdn ")
   o:labelsize(8)
   o:callback(key_cb, 'page down')
   o = fl.button(400, 120, 20, 20, "7")
   o:labelsize(10)
   o:callback(key_cb, 'kp 7')
   o = fl.button(420, 120, 20, 20, "8")
   o:labelsize(10)
   o:callback(key_cb, 'kp 8')
   o = fl.button(440, 120, 20, 20, "9")
   o:labelsize(10)
   o:callback(key_cb, 'kp 9')
   o = fl.button(460, 120, 20, 40, "+")
   o:labelsize(10)
   o:callback(key_cb, 'kp +')
   o:align(fl.ALIGN_TOP|fl.ALIGN_INSIDE)
   o = fl.button(15, 140, 36, 20, "Lock")
   o:labelsize(8)
   o:callback(key_cb, 'caps lock')
   o:align(fl.ALIGN_LEFT|fl.ALIGN_INSIDE)
   o = fl.button(51, 140, 20, 20, "A")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(71, 140, 20, 20, "S")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(91, 140, 20, 20, "D")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(111, 140, 20, 20, "F")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(131, 140, 20, 20, "G")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(151, 140, 20, 20, "H")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(171, 140, 20, 20, "J")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(191, 140, 20, 20, "K")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(211, 140, 20, 20, "L")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(231, 140, 20, 20, ";")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(251, 140, 20, 20, "\'")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(271, 140, 39, 20, "Enter")
   o:labelsize(8)
   o:callback(key_cb, 'enter')
   o:align(fl.ALIGN_LEFT|fl.ALIGN_INSIDE)
   o = fl.button(400, 140, 20, 20, "4")
   o:labelsize(10)
   o:callback(key_cb, 'kp 4')
   o = fl.button(420, 140, 20, 20, "5")
   o:labelsize(10)
   o:callback(key_cb, 'kp 5')
   o = fl.button(440, 140, 20, 20, "6")
   o:labelsize(10)
   o:callback(key_cb, 'kp 6')
   o = fl.button(15, 160, 45, 20, "Shift")
   o:labelsize(8)
   o:callback(key_cb, 'shift l')
   o:align(fl.ALIGN_LEFT|fl.ALIGN_INSIDE)
   o = fl.button(60, 160, 20, 20, "Z")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(80, 160, 20, 20, "X")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(100, 160, 20, 20, "C")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(120, 160, 20, 20, "V")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(140, 160, 20, 20, "B")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(160, 160, 20, 20, "N")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(180, 160, 20, 20, "M")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(200, 160, 20, 20, ",")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(220, 160, 20, 20, ".")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(240, 160, 20, 20, "/")
   o:labelsize(10)
   o:callback(key_cb)
   o = fl.button(260, 160, 50, 20, "Shift")
   o:labelsize(8)
   o:callback(key_cb, 'shift r')
   o:align(fl.ALIGN_LEFT|fl.ALIGN_INSIDE)
   o = fl.button(345, 160, 20, 20, "@8->")
   o:labeltype('shadow')
   o:labelsize(10)
   o:labelcolor(fl.DARK1)
   o:callback(key_cb, 'up')
   o = fl.button(400, 160, 20, 20, "1")
   o:labelsize(10)
   o:callback(key_cb, 'kp 1')
   o = fl.button(420, 160, 20, 20, "2")
   o:labelsize(10)
   o:callback(key_cb, 'kp 2')
   o = fl.button(440, 160, 20, 20, "3")
   o:labelsize(10)
   o:callback(key_cb, 'kp 3')
   o = fl.button(460, 160, 20, 40)
   o:callback(key_cb, 'kp enter')
   o = fl.button(15, 180, 30, 20, "Ctrl")
   o:labelsize(8)
   o:callback(key_cb, 'control l')
   o:align(fl.ALIGN_LEFT|fl.ALIGN_INSIDE)
   o = fl.button(45, 180, 30, 20, "Meta ")
   o:labelsize(8)
   o:callback(key_cb, 'meta l')
   o = fl.button(75, 180, 30, 20, "Alt ")
   o:labelsize(8)
   o:callback(key_cb, 'alt l')
   o = fl.button(105, 180, 85, 20, " ") --space
   o:labelsize(10)
   o:callback(key_cb, ' ')
   o = fl.button(190, 180, 30, 20, "Alt ")
   o:labelsize(8)
   o:callback(key_cb, 'alt r')
   o = fl.button(220, 180, 30, 20, "Meta ")
   o:labelsize(8)
   o:callback(key_cb, 'meta r')
   o = fl.button(250, 180, 30, 20, "Menu ")
   o:labelsize(8)
   o:callback(key_cb, 'menu')
   o = fl.button(280, 180, 30, 20, "Ctrl")
   o:labelsize(8)
   o:callback(key_cb, 'control r')
   o:align(fl.ALIGN_LEFT|fl.ALIGN_INSIDE)
   o = fl.button(325, 180, 20, 20, "@4->")
   o:labeltype('shadow')
   o:labelsize(10)
   o:labelcolor(fl.DARK1)
   o:callback(key_cb, 'left')
   o = fl.button(345, 180, 20, 20, "@2->")
   o:labeltype('shadow')
   o:labelsize(10)
   o:labelcolor(fl.DARK1)
   o:callback(key_cb, 'down')
   o = fl.button(365, 180, 20, 20, "@6->")
   o:labeltype('shadow')
   o:labelsize(10)
   o:labelcolor(fl.DARK1)
   o:callback(key_cb, 'right')
   o = fl.button(400, 180, 40, 20, "0")
   o:labelsize(10)
   o:callback(key_cb, 'kp 0')
   o:align(fl.ALIGN_LEFT|fl.ALIGN_INSIDE)
   o = fl.button(440, 180, 20, 20, ".")
   o:labelsize(10)
   o:callback(key_cb, 'kp .')
-- Modifiers
   o = fl.button(400, 15, 20, 10, "shift")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, "Shift")
   o = fl.button(420, 15, 20, 10, "lock")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, "Caps Lock")
   o = fl.button(440, 15, 20, 10, "ctrl")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, 'Ctrl')
   o = fl.button(460, 15, 20, 10, "alt")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, 'Alt')
   o = fl.button(400, 25, 20, 10, "num")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, 'Num Lock')
--[[
   o = fl.button(420, 25, 20, 10, "?")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, "0x20") -- not defined 
--]]
   o = fl.button(440, 25, 20, 10, "meta ")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, 'Meta')
   o = fl.button(460, 25, 20, 10, "sclk")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, 'Scroll Lock')
   o = fl.button(400, 35, 20, 10, "b1")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, 'Button1')
   o = fl.button(420, 35, 20, 10, "b2")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, 'Button2')
   o = fl.button(440, 35, 20, 10, "b3")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, 'Button3')
   o = fl.button(460, 35, 20, 10, "whl")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, "Button4")
   o = fl.button(400, 45, 20, 10, "?")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, "Button5")
   o = fl.button(420, 45, 20, 10, "?")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, "Button6")
   o = fl.button(440, 45, 20, 10, "?")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, "Button7")
   o = fl.button(460, 45, 20, 10, "?")
   o:box('thin up box')
   o:selection_color(3)
   o:labelsize(8)
   o:callback(shift_cb, "Button8")
   key_output = fl.output(15, 20, 170, 30, "fl.event_key():")
   key_output:labelsize(9)
   key_output:align(fl.ALIGN_TOP_LEFT)
   o = fl.box(400, 15, 80, 40, "fl.event_state():")
   o:labelsize(9)
   o:align(fl.ALIGN_TOP_LEFT)
   text_output = fl.output(195, 20, 190, 30, "fl.event_text():")
   text_output:labelsize(9)
   text_output:align(fl.ALIGN_TOP_LEFT)
   o = fl.button(400, 70, 20, 20, "Help")
   o:labelsize(8)
   o:callback(key_cb, 'help')
   o = fl.button(420, 70, 20, 20, "=")
   o:labelsize(10)
   o:callback(key_cb, 'kp =')
   roller_x = fl.dial(440, 70, 20, 20, "x:")
   roller_x:box('round up box')
   roller_x:selection_color(fl.BACKGROUND_COLOR)
   roller_x:labelsize(9)
   roller_x:step(0.1)
   roller_x:callback(wheel_cb)
   roller_x:align(fl.ALIGN_TOP_LEFT)
   roller_y = fl.dial(460, 70, 20, 20, "y:")
   roller_y:box('round up box')
   roller_y:selection_color(fl.BACKGROUND_COLOR)
   roller_y:labelsize(9)
   roller_y:step(0.1)
   roller_y:callback(wheel_cb)
   roller_y:align(fl.ALIGN_TOP_LEFT)

   my_window:done()

   return my_window
end

-- these are used to identify which buttons are which:
function key_cb() end
function shift_cb() end
function wheel_cb() end

-- main ---------------------------------------------
fl.handler(function(e) return e == 'shortcut' end) -- eat all keystrokes
window = MyWindow()
window:show(arg[0], arg)

while fl.wait() do 
   -- update all the buttons with the current key and shift state:
   for i = 1, window:children() do
      local b = window:child(i)
      if b:callback() == key_cb then
         local a = b:argument()
         if not a then a = b:label():sub(1,1) end
         local state = fl.event_key(a)
         if b:value() ~= state then b:value(state) end
      elseif b:callback() == shift_cb then
         local a = b:argument()
         local state = fl.event_state(a)
         if b:value() ~= state then b:value(state) end
      end
   end

   local keyname = fl.event_key()
   if key_output:value() ~= keyname then
      key_output:value(keyname)
   end

   local str = fl.event_text()
   if text_output:value() ~= str then
      text_output:value(str)
   end
end
