transitions

This commit is contained in:
kepler155c@gmail.com 2016-12-14 12:36:28 -05:00
parent 46d0c8d43d
commit 48f16ce2c7
2 changed files with 234 additions and 44 deletions

View File

@ -15,9 +15,9 @@ return function()
local selectFile = UI.Page({ local selectFile = UI.Page({
x = 3, x = 3,
y = 3, y = 2,
ex = -3, rex = -3,
ey = -3, rey = -3,
backgroundColor = colors.brown, backgroundColor = colors.brown,
titleBar = UI.TitleBar({ titleBar = UI.TitleBar({
title = 'Select file', title = 'Select file',
@ -27,16 +27,16 @@ return function()
grid = UI.ScrollingGrid({ grid = UI.ScrollingGrid({
x = 2, x = 2,
y = 2, y = 2,
ex = -2, rex = -2,
ey = -4, rey = -4,
path = '', path = '',
sortColumn = 'name', sortColumn = 'name',
columns = columns, columns = columns,
}), }),
path = UI.TextEntry({ path = UI.TextEntry({
x = 2, x = 2,
oy = -1, ry = -1,
ex = -11, rex = -11,
limit = 256, limit = 256,
accelerators = { accelerators = {
enter = 'path_enter', enter = 'path_enter',
@ -44,8 +44,8 @@ return function()
}), }),
cancel = UI.Button({ cancel = UI.Button({
text = 'Cancel', text = 'Cancel',
ox = -8, rx = -8,
oy = -1, ry = -1,
event = 'cancel', event = 'cancel',
}), }),
}) })

View File

@ -267,9 +267,6 @@ function Manager:inputEvent(parent, event)
if parent:emit({ type = acc, element = parent }) then if parent:emit({ type = acc, element = parent }) then
return true return true
end end
-- if parent:eventHandler({ type = acc, element = parent }) then
-- return true
-- end
end end
if parent.eventHandler then if parent.eventHandler then
if parent:eventHandler(event) then if parent:eventHandler(event) then
@ -521,18 +518,26 @@ end
function UI.Window:setParent() function UI.Window:setParent()
self.oh, self.ow = self.height, self.width self.oh, self.ow = self.height, self.width
if self.ox then if self.rx then
self.x = self.parent.width + self.ox if self.rx > 0 then
self.x = self.rx
else
self.x = self.parent.width + self.rx
end
end end
if self.oy then if self.ry then
self.y = self.parent.height + self.oy if self.ry > 0 then
self.y = self.ry
else
self.y = self.parent.height + self.ry
end
end end
if self.ex then if self.rex then
self.width = self.parent.width - self.x + self.ex + 2 self.width = self.parent.width - self.x + self.rex + 2
end end
if self.ey then if self.rey then
self.height = self.parent.height - self.y + self.ey + 2 self.height = self.parent.height - self.y + self.rey + 2
end end
if not self.width then if not self.width then
@ -583,21 +588,29 @@ end
function UI.Window:resize() function UI.Window:resize()
if self.ox then if self.rx then
self.x = self.parent.width + self.ox if self.rx > 0 then
self.x = self.rx
else
self.x = self.parent.width + self.rx
end
end end
if self.oy then if self.ry then
self.y = self.parent.height + self.oy if self.ry > 0 then
self.y = self.ry
else
self.y = self.parent.height + self.ry
end
end end
if self.ex then if self.rex then
self.width = self.parent.width - self.x + self.ex + 2 self.width = self.parent.width - self.x + self.rex + 2
elseif not self.ow and self.parent then elseif not self.ow and self.parent then
self.width = self.parent.width - self.x + 1 self.width = self.parent.width - self.x + 1
end end
if self.ey then if self.rey then
self.oh = self.parent.height - self.y + self.ey + 2 self.height = self.parent.height - self.y + self.rey + 2
elseif not self.oh and self.parent then elseif not self.oh and self.parent then
self.height = self.parent.height - self.y + 1 self.height = self.parent.height - self.y + 1
end end
@ -700,11 +713,16 @@ function UI.Window:print(text, bg, fg, indent)
end end
end end
for _,line in pairs(Util.split(text)) do local lines = Util.split(text)
for k,line in pairs(lines) do
local lx = 1 local lx = 1
while true do while true do
local word = nextWord(line, lx) local word = nextWord(line, lx)
if not word then if not word then
if lines[k + 1] then
self.cursorX = indent
self.cursorY = self.cursorY + 1
end
break break
end end
local w = word local w = word
@ -783,6 +801,14 @@ function UI.Window:scrollIntoView()
end end
end end
function UI.Window:setTransition(effect, y, height)
if self.parent then
y = y or 1
height = height or self.height
self.parent:setTransition(effect, y + self.y - 1, height)
end
end
function UI.Window:emit(event) function UI.Window:emit(event)
local parent = self local parent = self
--debug(self.UIElement .. ' emitting ' .. event.type) --debug(self.UIElement .. ' emitting ' .. event.type)
@ -809,6 +835,7 @@ UI.Device.defaults = {
textColor = colors.white, textColor = colors.white,
textScale = 1, textScale = 1,
lines = { }, lines = { },
transitionsEnabled = true,
} }
function UI.Device:init(args) function UI.Device:init(args)
@ -834,6 +861,7 @@ end
function UI.Device:resize() function UI.Device:resize()
self.width, self.height = self.device.getSize() self.width, self.height = self.device.getSize()
self.lines = { }
UI.Window.resize(self) UI.Window.resize(self)
end end
@ -863,14 +891,112 @@ function UI.Device:reset()
self.device.setCursorPos(1, 1) self.device.setCursorPos(1, 1)
end end
function UI.Device:sync() function UI.Device:setTransition(effect, y, height)
for y, line in pairs(self.lines) do if not self.transition then
if line.dirty then self.transition = effect
self.device.setCursorPos(1, y) for i = y, y + height - 1 do
self.device.blit(line.text, line.fg, line.bg) local line = self.lines[i]
line.dirty = false if line then
line.transition = true
end
end end
end end
end
function UI.Device:runTransition(transition)
if transition == 'left' or transition == 'right' then
for y, line in ipairs(self.lines) do
if not line.transition then
self.device.setCursorPos(1, y)
self.device.blit(line.text, line.fg, line.bg)
end
end
local c = os.clock()
local steps = math.floor(self.width * .34) -- 150 ms
for i = 1, self.width do
for y, line in pairs(self.lines) do
if line.transition then
if transition == 'left' then
local text = self.lastScreen[y].text .. line.text
local bg = self.lastScreen[y].bg .. line.bg
local fg = self.lastScreen[y].fg .. line.fg
self.device.setCursorPos(1 - i, y)
self.device.blit(text, fg, bg)
else
local text = line.text .. self.lastScreen[y].text
local bg = line.bg .. self.lastScreen[y].bg
local fg = line.fg .. self.lastScreen[y].fg
self.device.setCursorPos(-self.width + i + 1, y)
self.device.blit(text, fg, bg)
end
end
end
if (i + math.floor(steps / 2)) % steps == 0 then
if c == os.clock() then
os.sleep(0)
c = os.clock()
end
end
end
elseif transition == 'explode' then
local half = math.floor(self.width / 2)
local c = os.clock()
local steps = math.floor(self.width * .5)
for i = 1, half do
for y, line in pairs(self.lines) do
local width = i * 2
local mid = half - i + 1
self.device.setCursorPos(mid, y)
self.device.blit(
line.text:sub(mid, mid + width),
line.fg:sub(mid, mid + width),
line.bg:sub(mid, mid + width))
end
if (i + math.floor(steps / 2)) % steps == 0 then
if c == os.clock() then
os.sleep(0)
c = os.clock()
end
end
end
end
for y, line in ipairs(self.lines) do
line.dirty = false
line.transition = false
end
end
function UI.Device:sync()
local transition
if self.transition then
for y, line in pairs(self.lines) do
if line.dirty then
transition = self.transition
break
end
end
self.transition = nil
end
if transition and self.transitionsEnabled then
self:runTransition(transition)
else
for y, line in pairs(self.lines) do
if line.dirty then
self.device.setCursorPos(1, y)
self.device.blit(line.text, line.fg, line.bg)
line.dirty = false
end
end
end
self.lastScreen = Util.deepCopy(self.lines)
if self:getCursorBlink() then if self:getCursorBlink() then
self.device.setCursorPos(self.cursorX, self.cursorY) self.device.setCursorPos(self.cursorX, self.cursorY)
end end
@ -1596,12 +1722,16 @@ function UI.ViewportWindow:setScrollPosition(offset)
max = math.max(child.y + child.height - 1, max) max = math.max(child.y + child.height - 1, max)
end end
end end
self.offy = math.min(self.offy, max - self.height) self.offy = math.min(self.offy, math.max(max, self.height) - self.height)
if self.offy ~= oldOffset then if self.offy ~= oldOffset then
self:draw() self:draw()
end end
end end
function UI.ViewportWindow:reset()
self.offy = 0
end
function UI.ViewportWindow:eventHandler(event) function UI.ViewportWindow:eventHandler(event)
if event.type == 'scroll_down' then if event.type == 'scroll_down' then
@ -1731,7 +1861,7 @@ function UI.MenuBar:init(args)
if self.showBackButton then if self.showBackButton then
table.insert(self.children, UI.Button({ table.insert(self.children, UI.Button({
x = UI.term.width - 2, x = UI.term.width - 2,
width = 4, width = 3,
backgroundColor = self.backgroundColor, backgroundColor = self.backgroundColor,
textColor = self.textColor, textColor = self.textColor,
text = '^-', text = '^-',
@ -1758,7 +1888,6 @@ function UI.MenuBar:eventHandler(event)
end end
end end
end end
return false
end end
--[[-- DropMenu --]]-- --[[-- DropMenu --]]--
@ -1834,6 +1963,7 @@ function UI.DropMenu:eventHandler(event)
else else
return UI.MenuBar.eventHandler(self, event) return UI.MenuBar.eventHandler(self, event)
end end
return true
end end
--[[-- TabBar --]]-- --[[-- TabBar --]]--
@ -1849,17 +1979,24 @@ function UI.TabBar:init(args)
end end
function UI.TabBar:selectTab(text) function UI.TabBar:selectTab(text)
for _,child in pairs(self.children) do local selected, lastSelected
if child.text == text then for k,child in pairs(self.children) do
child.selected = true if child.selected then
lastSelected = k
end
child.selected = child.text == text
if child.selected then
selected = k
child.backgroundColor = self.selectedBackgroundColor child.backgroundColor = self.selectedBackgroundColor
child.backgroundFocusColor = self.selectedBackgroundColor child.backgroundFocusColor = self.selectedBackgroundColor
else else
child.selected = false
child.backgroundColor = self.backgroundColor child.backgroundColor = self.backgroundColor
child.backgroundFocusColor = self.backgroundColor child.backgroundFocusColor = self.backgroundColor
end end
end end
if selected and lastSelected and selected ~= lastSelected then
self:emit({ type = 'tab_change', current = selected, last = lastSelected })
end
UI.MenuBar.draw(self) UI.MenuBar.draw(self)
end end
@ -1929,9 +2066,62 @@ function UI.Tabs:eventHandler(event)
break break
end end
end end
return true elseif event.type == 'tab_change' then
for _,tab in ipairs(self.children) do
if tab ~= self.tabBar then
if event.current > event.last then
tab:setTransition('left')
else
tab:setTransition('right')
end
break
end
end
end
end
--[[-- WindowScroller --]]--
UI.WindowScroller = class(UI.Window)
UI.WindowScroller.defaults = {
UIElement = 'WindowScroller',
children = { },
}
function UI.WindowScroller:init(args)
local defaults = UI:getDefaults(UI.WindowScroller, args)
UI.Window.init(self, defaults)
end
function UI.WindowScroller:enable()
self.enabled = true
if #self.children > 0 then
self.children[1]:enable()
end
end
function UI.WindowScroller:nextChild()
for i = 1, #self.children do
if self.children[i].enabled then
if i < #self.children then
self:setTransition('left')
self.children[i]:disable()
self.children[i + 1]:enable()
end
break
end
end
end
function UI.WindowScroller:prevChild()
for i = 1, #self.children do
if self.children[i].enabled then
if i - 1 > 0 then
self:setTransition('right')
self.children[i]:disable()
self.children[i - 1]:enable()
end
break
end
end end
return UI.Window.eventHandler(self, event)
end end
--[[-- Notification --]]-- --[[-- Notification --]]--