summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2017-12-22 00:51:41 +0800
committerruki <[email protected]>2017-12-21 23:10:09 +0800
commitfe6f634879645e86609dfb014bab5546bfe0e7fc (patch)
tree5c0c436390c8bc7aa3f209558b1f155d3f0a71a8
parentbf0ea773b29ca4a85430dcb5ab024ed27a8eeb0c (diff)
rewrite refresh view
-rw-r--r--xmake/core/ui/desktop.lua18
-rw-r--r--xmake/core/ui/group.lua154
-rw-r--r--xmake/core/ui/menubar.lua5
-rw-r--r--xmake/core/ui/program.lua58
-rw-r--r--xmake/core/ui/statusbar.lua3
-rw-r--r--xmake/core/ui/view.lua100
6 files changed, 168 insertions, 170 deletions
diff --git a/xmake/core/ui/desktop.lua b/xmake/core/ui/desktop.lua
index 899053d48..9bf1e98ea 100644
--- a/xmake/core/ui/desktop.lua
+++ b/xmake/core/ui/desktop.lua
@@ -28,6 +28,7 @@ $Id: desktop.lua 18 2007-06-21 20:43:52Z tngd $
--------------------------------------------------------------------------]]
-- load modules
+local log = require("ui/log")
local group = require("ui/group")
-- define module
@@ -35,7 +36,12 @@ local desktop = desktop or group()
-- init desktop
function desktop:init(name, bounds)
+
+ -- init group
group.init(self, name, bounds)
+
+ -- init color
+ self:attr_set("color", curses.color_pair("white", "blue"))
end
-- exit desktop
@@ -43,5 +49,17 @@ function desktop:exit()
group.exit(self)
end
+-- draw view
+function desktop:draw()
+
+ -- trace
+ log:print("%s: draw ..", self)
+
+ -- draw it
+ local c = self:canvas()
+ c:attr(self:attr("color")):move(0, 0):write(string.rep(' ', self:width() * self:height()))
+end
+
+
-- return module
return desktop
diff --git a/xmake/core/ui/group.lua b/xmake/core/ui/group.lua
index 06f2a1864..80f7c22b7 100644
--- a/xmake/core/ui/group.lua
+++ b/xmake/core/ui/group.lua
@@ -100,9 +100,6 @@ function group:insert(v)
-- check
assert(not v:parent() or v:parent() == self)
- -- lock
- self:lock()
-
-- this view has been inserted into this group? remove it first
if v:parent() == self then
self:remove(v)
@@ -133,12 +130,6 @@ function group:insert(v)
if v:option("selectable") then
self:select(v)
end
-
- -- show this view
- v:show(true)
-
- -- unlock
- self:unlock()
end
-- remove view
@@ -257,130 +248,63 @@ function group:event_on(e)
end
end
--- execute group
-function group:execute()
-
- -- show this group
- self:show(true)
-
- -- refresh first
- self:refresh()
-
- -- do message loop
- local e = nil
- local sleep = true
- local app = self:application()
- while true do
+-- draw group
+function group:draw()
- -- get the current event
- e = self:event()
+ -- draw it
+ if self:state("redraw") then
- -- do event
- if e then
- self:event_on(e)
- sleep = false
- else
- -- do idle event
- app:event_on(event.idle())
- end
+ -- draw group background first
+ view.draw(self)
- -- wait some time, 50ms
- if sleep then
- curses.napms(50)
+ -- draw all child views
+ for v in self:views() do
+ if v:state("visible") then
+ v:draw()
+ v:state_set("redraw", false)
+ end
end
- end
-
- -- hide this group
- self:show(false)
-end
--- draw group
-function group:draw()
+ -- clear mark
+ self:state_set("redraw", false)
+ else
- -- draw sub views
- for v in self:views() do
- if v:state("visible") then
- v:draw()
+ -- only draw child views
+ for v in self:views() do
+ if v:state("visible") and v:state("redraw") then
+ v:draw()
+ v:state_set("redraw", false)
+ end
end
end
end
--- redraw group
-function group:redraw(on_parent)
+-- refresh group
+function group:refresh()
- -- lock
- self:lock()
+ -- need not refresh? do not refresh it
+ if not self:state("refresh") then
+ return
+ end
- -- redraw all child views
+ -- refresh all child views
for v in self:views() do
- if v:state("visible") then
-
- -- cause groups to redraw
- v:redraw(false)
-
- -- draw this child view
- self:_draw_child(v)
+ if v:state("refresh") then
+ v:refresh()
+ v:state_set("refresh", false)
end
end
- -- redraw view
- view.redraw(self, on_parent)
-
- -- unlock
- self:unlock()
-end
-
--- refresh group in parent window
-function group:refresh()
- self:lock()
- self:draw()
- self:redraw(true)
- self:unlock()
-end
-
--- draw this child view
-function group:_draw_child(v)
+ -- refresh it
+ view.refresh(self)
- -- draw it if this child view is in a vaild bounds
- local bounds = v:bounds()
- local r = bounds():intersect(rect{0, 0, self:width(), self:height()})
- if r.ex > r.sx and r.ey > r.sy then
-
- -- TODO
- -- copy this child view to group window
- local sx = bounds.sx; sx = sx > 0 and 0 or -sx
- local sy = bounds.sy; sy = sy > 0 and 0 or -sy
- v:window():copy(self:window(), sy, sx, r.sy, r.sx, r.ey - 1, r.ex - 1)
- end
+ -- clear mark
+ self:state_set("refresh", false)
end
--- draw overlapping views about this child view
-function group:_draw_overlap(v)
-
- -- lock
- self:lock()
-
- -- draw all overlapping areas
- local bounds = v:bounds()
- while v do
-
- -- check for overlapping areas
- if v:state("visible") and v:bounds():is_intersect(bounds) then
-
- -- draw this child view
- self:_draw_child(v)
-
- -- if they overlap, join them.
- -- use the resulting rectangle to check for overlapping areas on the following windows
- bounds:union(v:bounds())
- end
-
- -- get the next view
- v = self:next(v)
- end
-
- -- unlock
- self:unlock()
+-- dump all views
+function group:dump()
+ log:print("%s", self:_tostring(1))
end
-- tostring(group, level)
@@ -405,7 +329,7 @@ end
-- tostring(group)
function group:__tostring()
- return self:_tostring(1)
+ return string.format("<group(%s) %s>", self:name(), tostring(self:bounds()))
end
diff --git a/xmake/core/ui/menubar.lua b/xmake/core/ui/menubar.lua
index af0e2b593..fa9fc910c 100644
--- a/xmake/core/ui/menubar.lua
+++ b/xmake/core/ui/menubar.lua
@@ -55,6 +55,11 @@ end
-- draw view
function menubar:draw()
+
+ -- trace
+ log:print("%s: draw ..", self)
+
+ -- draw it
local c = self:canvas()
c:attr(self:attr("color")):move(0, 0):write(string.rep(' ', self:width() * self:height()))
c:move(1, 0):write(self:title())
diff --git a/xmake/core/ui/program.lua b/xmake/core/ui/program.lua
index af3cb09bf..8d30903c0 100644
--- a/xmake/core/ui/program.lua
+++ b/xmake/core/ui/program.lua
@@ -28,6 +28,7 @@ $Id: program.lua 18 2007-06-21 20:43:52Z tngd $
--------------------------------------------------------------------------]]
-- load modules
+local log = require("ui/log")
local rect = require("ui/rect")
local group = require("ui/group")
local event = require("ui/event")
@@ -147,8 +148,61 @@ function program:loop(argv)
-- save the current arguments
self._ARGV = argv
- -- execute group
- self:execute()
+ -- do message loop
+ local e = nil
+ local sleep = true
+ while true do
+
+ -- get the current event
+ e = self:event()
+
+ -- do event
+ if e then
+ self:event_on(e)
+ sleep = false
+ else
+ -- do idle event
+ self:event_on(event.idle())
+ end
+
+ -- draw views
+ self:draw()
+
+ -- refresh views
+ self:refresh()
+
+ -- wait some time, 50ms
+ if sleep then
+ curses.napms(50)
+ end
+ end
+end
+
+-- refresh program
+function program:refresh()
+
+ -- need not refresh? do not refresh it
+ if not self:state("refresh") then
+ return
+ end
+
+ -- refresh views
+ group.refresh(self)
+
+ -- trace
+ log:print("%s: refresh ..", self)
+
+ -- get main window
+ local main_window = curses.main_window()
+
+ -- refresh main window
+ self:window():copy(main_window, 0, 0, 0, 0, self:height() - 1, self:width() - 1)
+
+ -- mark as refresh
+ main_window:noutrefresh()
+
+ -- do update
+ curses.doupdate()
end
-- get key map
diff --git a/xmake/core/ui/statusbar.lua b/xmake/core/ui/statusbar.lua
index 0c00c730c..97c05f916 100644
--- a/xmake/core/ui/statusbar.lua
+++ b/xmake/core/ui/statusbar.lua
@@ -54,6 +54,9 @@ end
-- draw view
function statusbar:draw()
+ -- trace
+ log:print("%s: draw ..", self)
+
-- get canvas
local c = self:canvas()
c:move(0, 0)
diff --git a/xmake/core/ui/view.lua b/xmake/core/ui/view.lua
index 5c32f59e2..fc63ec181 100644
--- a/xmake/core/ui/view.lua
+++ b/xmake/core/ui/view.lua
@@ -29,6 +29,7 @@ $Id: view.lua 18 2007-06-21 20:43:52Z tngd $
-- load modules
local log = require("ui/log")
+local rect = require("ui/rect")
local object = require("ui/object")
local canvas = require("ui/canvas")
local curses = require("ui/curses")
@@ -36,9 +37,6 @@ local curses = require("ui/curses")
-- define module
local view = view or object()
--- the screen lock/update counter
-local screen_lock = 0
-
-- new view instance
function view:new(name, bounds, ...)
@@ -60,9 +58,11 @@ function view:init(name, bounds)
-- init state
local state = object()
- state.visible = false -- view visibility
+ state.visible = true -- view visibility
state.selected = false -- current selected window inside group
state.focused = false -- true if parent is also focused
+ state.redraw = true -- need redraw
+ state.refresh = true -- need refresh
self._STATE = state
-- init options
@@ -179,42 +179,32 @@ end
-- draw view
function view:draw()
-log:print("view draw: %s", self:name())
+
+ -- trace
+ log:print("%s: draw ..", self)
+
+ -- clear view
self:canvas():clear()
end
--- refresh view in parent window
+-- refresh view
function view:refresh()
- self:draw()
- self:redraw(true)
-end
--- redraw view
-function view:redraw(on_parent)
+ -- refresh to the parent view
+ local parent = self:parent()
+ if parent then
- -- redraw this child view on parent view (group)
- if on_parent and self:parent() then
- self:lock()
- local v = self
- while v:parent() do
- v:parent():_draw_overlap(v)
- v = v:parent()
- end
- self:unlock()
- end
-end
+ -- clip bounds with the parent view
+ local bounds = self:bounds()
+ local r = bounds():intersect(rect{0, 0, parent:width(), parent:height()})
+ if not r:empty() then
--- lock view
-function view:lock()
- screen_lock = screen_lock + 1
-end
+ -- trace
+ log:print("%s: refresh to %s(%d, %d, %d, %d) ..", self, parent:name(), r.sx, r.sy, r.ex, r.ey)
--- unlock view
-function view:unlock()
- assert(screen_lock > 0)
- screen_lock = screen_lock - 1
- if screen_lock == 0 then
- self:_update_screen()
+ -- copy this view to parent view
+ self:window():copy(parent:window(), 0, 0, r.sy, r.sx, r.ey - 1, r.ex - 1)
+ end
end
end
@@ -225,6 +215,14 @@ function view:show(visible)
end
end
+-- invalidate view to redraw it
+function view:invalidate()
+
+ -- need redraw and refresh it
+ self:_mark_redraw()
+ self:_mark_refresh()
+end
+
-- on event (abstract)
function view:event_on(e)
end
@@ -295,37 +293,33 @@ function view:attr_set(name, value)
self._ATTRS[name] = value
end
--- update screen
-function view:_update_screen()
+-- need redraw view
+function view:_mark_redraw()
- -- get application
- local app = self:application()
- assert(app, "cannot get application from view(" .. self:name() .. ")")
+ -- need redraw it
+ self:state_set("redraw", true)
- -- is visible? disable to update screen before finishing application initialization
- if not app:state("visible") then
- return
+ -- need redraw it's parent view if this view is invisible
+ if not self:state("visible") and self:parent() then
+ self:parent():_mark_redraw()
end
+end
- -- trace
- log:print("view(%s): update screen ..", self:name())
-
- -- get main window
- local main_window = curses.main_window()
-
- -- update screen
- app:window():copy(main_window, 0, 0, 0, 0, app:height() - 1, app:width() - 1)
+-- need refresh view
+function view:_mark_refresh()
- -- mark as refresh
- main_window:noutrefresh()
+ -- need refresh it
+ self:state_set("refresh", true)
- -- do update
- curses.doupdate()
+ -- need refresh it's parent view
+ if self:parent() then
+ self:parent():_mark_refresh()
+ end
end
-- tostring(view)
function view:__tostring()
- return string.format("<%s %s>", self:name(), tostring(self:bounds()))
+ return string.format("<view(%s) %s>", self:name(), tostring(self:bounds()))
end
-- return module