diff options
| author | ruki <[email protected]> | 2017-12-16 00:57:23 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2017-12-15 23:44:19 +0800 |
| commit | e5ed897840214b66fd746292fff15c56606d3251 (patch) | |
| tree | 6a5820bfcb1acf95536b673cd79587aff198dab5 | |
| parent | d81f894af27987981ef3fe39e013ad3f1fadfbcf (diff) | |
add event to ui
| -rw-r--r-- | xmake/core/sandbox/modules/import/core/ui/event.lua | 26 | ||||
| -rw-r--r-- | xmake/core/ui/application.lua | 6 | ||||
| -rw-r--r-- | xmake/core/ui/event.lua | 62 | ||||
| -rw-r--r-- | xmake/core/ui/group.lua | 36 | ||||
| -rw-r--r-- | xmake/core/ui/menubar.lua | 21 | ||||
| -rw-r--r-- | xmake/core/ui/program.lua | 154 | ||||
| -rw-r--r-- | xmake/core/ui/statusbar.lua | 30 | ||||
| -rw-r--r-- | xmake/core/ui/view.lua | 28 |
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() |
