summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2017-12-16 00:57:23 +0800
committerruki <[email protected]>2017-12-15 23:44:19 +0800
commite5ed897840214b66fd746292fff15c56606d3251 (patch)
tree6a5820bfcb1acf95536b673cd79587aff198dab5
parentd81f894af27987981ef3fe39e013ad3f1fadfbcf (diff)
add event to ui
-rw-r--r--xmake/core/sandbox/modules/import/core/ui/event.lua26
-rw-r--r--xmake/core/ui/application.lua6
-rw-r--r--xmake/core/ui/event.lua62
-rw-r--r--xmake/core/ui/group.lua36
-rw-r--r--xmake/core/ui/menubar.lua21
-rw-r--r--xmake/core/ui/program.lua154
-rw-r--r--xmake/core/ui/statusbar.lua30
-rw-r--r--xmake/core/ui/view.lua28
8 files changed, 361 insertions, 2 deletions
diff --git a/xmake/core/sandbox/modules/import/core/ui/event.lua b/xmake/core/sandbox/modules/import/core/ui/event.lua
new file mode 100644
index 000000000..7a533cca7
--- /dev/null
+++ b/xmake/core/sandbox/modules/import/core/ui/event.lua
@@ -0,0 +1,26 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015 - 2017, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file event.lua
+--
+
+-- return module: event
+return require("ui/event")
diff --git a/xmake/core/ui/application.lua b/xmake/core/ui/application.lua
index 2572e7e1d..8caf4a01e 100644
--- a/xmake/core/ui/application.lua
+++ b/xmake/core/ui/application.lua
@@ -99,6 +99,12 @@ function application:statusbar()
return self._STATUSBAR
end
+-- do event
+function application:do_event(e)
+ program.do_event(self, e)
+ -- TODO
+end
+
-- run application
function application.run(name, ...)
diff --git a/xmake/core/ui/event.lua b/xmake/core/ui/event.lua
new file mode 100644
index 000000000..82beb7959
--- /dev/null
+++ b/xmake/core/ui/event.lua
@@ -0,0 +1,62 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015 - 2017, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file event.lua
+--
+
+--[[ Console User Interface (cui) ]-----------------------------------------
+Author: Tiago Dionizio (tiago.dionizio AT gmail.com)
+$Id: event.lua 18 2007-06-21 20:43:52Z tngd $
+--------------------------------------------------------------------------]]
+
+-- load modules
+local object = require("ui/object")
+
+-- define module
+local event = event or object { _init = {"type", "command", "extra"} }
+
+-- register event types
+function event:register(tag, ...)
+ local base = self[tag] or 0
+ local enums = {...}
+ local n = #enums
+ for i = 1, n do
+ self[enums[i]] = i + base
+ end
+ self[tag] = base + n
+end
+
+-- register event types, event.ev_keyboard = 1, event.ev_mouse = 2, ... , event.ev_idle = 5, event.ev_max = 5
+event:register("ev_max", "ev_keyboard", "ev_mouse", "ev_command", "ev_broadcast", "ev_idle")
+
+-- define keyboard event
+--
+-- keyname = key name
+-- keycode = key code
+-- keymeta = ALT key was pressed
+--
+event.keyboard = object {_init = { "key_code", "key_name", "key_meta" }, type = event.ev_keyboard}
+
+-- define idle event
+event.idle = object {_init = {}, type = event.ev_idle}
+
+-- return module
+return event
diff --git a/xmake/core/ui/group.lua b/xmake/core/ui/group.lua
index 80f0d991c..45baa8e14 100644
--- a/xmake/core/ui/group.lua
+++ b/xmake/core/ui/group.lua
@@ -30,6 +30,7 @@ $Id: group.lua 18 2007-06-21 20:43:52Z tngd $
-- load modules
local view = require("ui/view")
local rect = require("ui/rect")
+local event = require("ui/event")
local point = require("ui/point")
local curses = require("ui/curses")
local dlist = require("base/dlist")
@@ -240,8 +241,43 @@ function group:select_next(forward, start)
end
end
+-- do event
+function group:do_event(e)
+ -- TODO
+end
+
-- execute group
function group:execute()
+
+ -- show this group
+ self:show(true)
+
+ -- do message loop
+ local e = nil
+ local sleep = true
+ local app = self:application()
+ while true do
+
+ -- get the current event
+ e = self:event()
+
+ -- do event
+ if e then
+ self:do_event(e)
+ sleep = false
+ else
+ -- do idle event
+ app:do_event(event.idle())
+ end
+
+ -- wait some time, 50ms
+ if sleep then
+ curses.napms(50)
+ end
+ end
+
+ -- hide this group
+ self:show(false)
end
-- draw group
diff --git a/xmake/core/ui/menubar.lua b/xmake/core/ui/menubar.lua
index 1bc7e9eb6..1148909aa 100644
--- a/xmake/core/ui/menubar.lua
+++ b/xmake/core/ui/menubar.lua
@@ -28,14 +28,21 @@ $Id: menubar.lua 18 2007-06-21 20:43:52Z tngd $
--------------------------------------------------------------------------]]
-- load modules
-local view = require("ui/view")
+local log = require("ui/log")
+local view = require("ui/view")
+local curses = require("ui/curses")
-- define module
local menubar = menubar or view()
-- init menubar
function menubar:init(name, bounds)
+
+ -- init view
view.init(self, name, bounds)
+
+ -- init color
+ self:attr_set("color", curses.color_pair("red", "white"))
end
-- exit menubar
@@ -43,5 +50,17 @@ function menubar:exit()
view.exit(self)
end
+-- draw view
+function menubar:draw()
+ local c = self:canvas()
+ c:attr(self:attr("color")):move(0, 0):write(string.rep(' ', self:width() * self:height()))
+ c:move(1, 0):write('Menu Bar')
+end
+
+-- do event
+function menubar:do_event(e)
+ view.do_event(self, e)
+end
+
-- return module
return menubar
diff --git a/xmake/core/ui/program.lua b/xmake/core/ui/program.lua
index 75c08fc79..af3cb09bf 100644
--- a/xmake/core/ui/program.lua
+++ b/xmake/core/ui/program.lua
@@ -30,6 +30,7 @@ $Id: program.lua 18 2007-06-21 20:43:52Z tngd $
-- load modules
local rect = require("ui/rect")
local group = require("ui/group")
+local event = require("ui/event")
local curses = require("ui/curses")
-- define module
@@ -118,6 +119,28 @@ function program:argv()
return self._ARGV
end
+-- get the current event
+function program:event()
+
+ -- get input key
+ local key_code, key_name, key_meta = self:_input_key()
+ if key_code then
+ if key_name == "Resize" or key_name == "CtrlL" then
+ self:change_bounds(Rect{0, 0, curses.columns(), curses.lines()})
+ self:refresh()
+ elseif key_name == "Refresh" then
+ self:refresh()
+ else
+ return event.keyboard{key_code, key_name, key_meta}
+ end
+ end
+end
+
+-- put an event to view
+function program:event_put(e)
+ -- TODO
+end
+
-- run program loop
function program:loop(argv)
@@ -128,5 +151,136 @@ function program:loop(argv)
self:execute()
end
+-- get key map
+function program:_key_map()
+ if not self._KEYMAP then
+ self._KEYMAP =
+ {
+ [ 1] = "CtrlA", [ 2] = "CtrlB", [ 3] = "CtrlC",
+ [ 4] = "CtrlD", [ 5] = "CtrlE", [ 6] = "CtrlF",
+ [ 7] = "CtrlG", [ 8] = "CtrlH", [ 9] = "CtrlI",
+ [10] = "CtrlJ", [11] = "CtrlK", [12] = "CtrlL",
+ [13] = "CtrlM", [14] = "CtrlN", [15] = "CtrlO",
+ [16] = "CtrlP", [17] = "CtrlQ", [18] = "CtrlR",
+ [19] = "CtrlS", [20] = "CtrlT", [21] = "CtrlU",
+ [22] = "CtrlV", [23] = "CtrlW", [24] = "CtrlX",
+ [25] = "CtrlY", [26] = "CtrlZ",
+
+ [ 8] = "Backspace",
+ [ 9] = "Tab",
+ [ 10] = "Enter",
+ [ 13] = "Enter",
+ [ 27] = "Esc",
+ [ 31] = "CtrlBackspace",
+ [127] = "Backspace",
+
+ [curses.KEY_DOWN ] = "Down",
+ [curses.KEY_UP ] = "Up",
+ [curses.KEY_LEFT ] = "Left",
+ [curses.KEY_RIGHT ] = "Right",
+ [curses.KEY_HOME ] = "Home",
+ [curses.KEY_END ] = "End",
+ [curses.KEY_NPAGE ] = "PageDown",
+ [curses.KEY_PPAGE ] = "PageUp",
+ [curses.KEY_IC ] = "Insert",
+ [curses.KEY_DC ] = "Delete",
+ [curses.KEY_BACKSPACE ] = "Backspace",
+ [curses.KEY_F1 ] = "F1",
+ [curses.KEY_F2 ] = "F2",
+ [curses.KEY_F3 ] = "F3",
+ [curses.KEY_F4 ] = "F4",
+ [curses.KEY_F5 ] = "F5",
+ [curses.KEY_F6 ] = "F6",
+ [curses.KEY_F7 ] = "F7",
+ [curses.KEY_F8 ] = "F8",
+ [curses.KEY_F9 ] = "F9",
+ [curses.KEY_F10 ] = "F10",
+ [curses.KEY_F11 ] = "F11",
+ [curses.KEY_F12 ] = "F12",
+
+ [curses.KEY_RESIZE ] = "Resize",
+ [curses.KEY_REFRESH ] = "Refresh",
+
+ [curses.KEY_BTAB ] = "ShiftTab",
+ [curses.KEY_SDC ] = "ShiftDelete",
+ [curses.KEY_SIC ] = "ShiftInsert",
+ [curses.KEY_SEND ] = "ShiftEnd",
+ [curses.KEY_SHOME ] = "ShiftHome",
+ [curses.KEY_SLEFT ] = "ShiftLeft",
+ [curses.KEY_SRIGHT ] = "ShiftRight",
+ }
+ end
+ return self._KEYMAP
+end
+
+-- get input key
+function program:_input_key()
+
+ -- get main window
+ local main_window = self:main_window()
+
+ -- get input character
+ local ch = main_window:getch()
+ if not ch then
+ return
+ end
+
+ -- this is the time limit in ms within Esc-key sequences are detected as
+ -- Alt-letter sequences. useful when we can't generate Alt-letter sequences
+ -- directly. sometimes this pause may be longer than expected since the
+ -- curses driver may also pause waiting for another key (ncurses-5.3)
+ local esc_delay = 400
+
+ -- get key map
+ local key_map = self:_key_map()
+
+ -- is alt?
+ local alt = ch == 27
+ if alt then
+
+ -- get the next input character
+ ch = main_window:getch()
+ if not ch then
+
+ -- since there is no way to know the time with millisecond precision
+ -- we pause the the program until we get a key or the time limit
+ -- is reached
+ local t = 0
+ while true do
+ ch = main_window:getch()
+ if ch or t >= esc_delay then
+ break
+ end
+
+ -- wait some time, 50ms
+ curses.napms(50)
+ t = t + 50
+ end
+
+ -- nothing was typed... return Esc
+ if not ch then
+ return 27, "Esc", false
+ end
+ end
+ if ch > 96 and ch < 123 then
+ ch = ch - 32
+ end
+ end
+
+ -- map character to key
+ local key = key_map[ch]
+ local key_name = nil
+ if key then
+ key_name = alt and "Alt".. key or key
+ elseif (ch < 256) then
+ key_name = alt and "Alt".. string.char(ch) or string.char(ch)
+ else
+ return ch, '(noname)', alt
+ end
+
+ -- return key info
+ return ch, key_name, alt
+end
+
-- return module
return program
diff --git a/xmake/core/ui/statusbar.lua b/xmake/core/ui/statusbar.lua
index bd61c2f91..fbdc46ff8 100644
--- a/xmake/core/ui/statusbar.lua
+++ b/xmake/core/ui/statusbar.lua
@@ -28,14 +28,21 @@ $Id: statusbar.lua 18 2007-06-21 20:43:52Z tngd $
--------------------------------------------------------------------------]]
-- load modules
-local view = require("ui/view")
+local view = require("ui/view")
+local curses = require("ui/curses")
-- define module
local statusbar = statusbar or view()
-- init statusbar
function statusbar:init(name, bounds)
+
+ -- init view
view.init(self, name, bounds)
+
+ -- init attributes
+ self:attr_set("key", curses.color_pair("red", "white"))
+ self:attr_set("text", curses.color_pair("black", "white"))
end
-- exit statusbar
@@ -43,5 +50,26 @@ function statusbar:exit()
view.exit(self)
end
+-- draw view
+function statusbar:draw()
+
+ -- get canvas
+ local c = self:canvas()
+ c:move(0, 0)
+
+ -- draw status
+ local x = 0
+ local kattr = self:attr("key")
+ local tattr = self:attr("text")
+ if x < self:width() then
+ c:attr(tattr):write(string.rep(' ', self:width() - x))
+ end
+end
+
+-- do event
+function statusbar:do_event(e)
+ view.do_event(self, e)
+end
+
-- return module
return statusbar
diff --git a/xmake/core/ui/view.lua b/xmake/core/ui/view.lua
index 73539a854..58be1774f 100644
--- a/xmake/core/ui/view.lua
+++ b/xmake/core/ui/view.lua
@@ -80,6 +80,10 @@ function view:init(name, bounds)
options.validate = false -- validate
self._OPTIONS = options
+ -- init attributes
+ local attrs = object()
+ self._ATTRS = attrs
+
-- init name
self._NAME = name
@@ -222,6 +226,20 @@ function view:show(visible)
end
end
+-- do event (abstract)
+function view:do_event(e)
+end
+
+-- get the current event
+function view:event()
+ return self:parent() and self:parent():event()
+end
+
+-- put an event to view
+function view:event_put(e)
+ return self:parent() and self:parent():event_put(e)
+end
+
-- get state
function view:state(name)
return self._STATE[name]
@@ -263,6 +281,16 @@ function view:option_set(name, enable)
self._OPTIONS[name] = enable
end
+-- get attribute
+function view:attr(name)
+ return self._ATTRS[name]
+end
+
+-- set attribute
+function view:attr_set(name, attr)
+ self._ATTRS[name] = attr
+end
+
-- update screen
function view:_update_screen()