1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
local core = require "core"
local config = require "core.config"
local common = require "core.common"
local View = require "core.view"
local style = require "core.style"
local BORDER_WIDTH = common.round(2 * SCALE)
local BORDER_PADDING = common.round(5 * SCALE)
local noop = function() end
local NagView = View:extend()
function NagView:new()
NagView.super.new(self)
self.size.y = 0
self.force_focus = false
self.title = "Warning"
self.message = ""
self.options = {}
self.submit = noop
end
function NagView:get_title()
return self.title
end
function NagView:each_option()
return coroutine.wrap(function()
for i = #self.options, 1, -1 do
coroutine.yield(i, self.options[i])
end
end)
end
function NagView:get_options_height()
local max = 0
for _, opt in ipairs(self.options) do
local lh = style.font:get_height(opt.text)
if lh > max then max = lh end
end
return max
end
function NagView:get_line_height()
local maxlh = math.max(style.font:get_height(self.message), self:get_options_height())
return 2 * BORDER_WIDTH + 2 * BORDER_PADDING + maxlh + 2 * style.padding.y
end
function NagView:update()
NagView.super.update(self)
local dest = core.active_view == self and self:get_line_height() or 0
self:move_towards(self.size, "y", dest)
end
function NagView:draw_overlay()
local ox, oy = self:get_content_offset()
oy = oy + self.size.y
local w, h = core.root_view.size.x, core.root_view.size.y - oy
core.root_view:defer_draw(function()
renderer.draw_rect(ox, oy, w, h, style.nagbar_dim)
end)
end
function NagView:each_visible_option()
return coroutine.wrap(function()
local halfh = math.floor(self.size.y / 2)
local ox, oy = self:get_content_offset()
ox = ox + self.size.x - style.padding.x
for i, opt in self:each_option() do
local lw, lh = opt.font:get_width(opt.text), opt.font:get_height(opt.text)
local bw, bh = (lw + 2 * BORDER_WIDTH + 2 * BORDER_PADDING), (lh + 2 * BORDER_WIDTH + 2 * BORDER_PADDING)
local halfbh = math.floor(bh / 2)
local bx, by = math.max(0, ox - bw), math.max(0, oy + halfh - halfbh)
local fw, fh = bw - 2 * BORDER_WIDTH, bh - 2 * BORDER_WIDTH
local fx, fy = bx + BORDER_WIDTH, by + BORDER_WIDTH
coroutine.yield(i, opt, bx,by,bw,bh, fx,fy,fw,fh)
ox = ox - bw - style.padding.x
end
end)
end
function NagView:on_mouse_moved(mx, my, ...)
NagView.super.on_mouse_moved(self, mx, my, ...)
local selected = false
for i, _, x,y,w,h in self:each_visible_option() do
if mx >= x and my >= y and mx < x + w and my < y + h then
self.selected = i
selected = true
break
end
end
if not selected then self.selected = nil end
end
function NagView:on_mouse_pressed(...)
if not NagView.super.on_mouse_pressed(self, ...) and self.selected then
self.force_focus = false
core.set_active_view(core.last_active_view)
self.submit(self.options[self.selected])
end
end
function NagView:draw()
if self.size.y <= 0 then return end
self:draw_overlay()
self:draw_background(style.nagbar)
-- draw message
local ox, oy = self:get_content_offset()
common.draw_text(style.font, style.nagbar_text, self.message, "left", ox + style.padding.x, oy, self.size.x, self.size.y)
-- draw buttons
for i, opt, bx,by,bw,bh, fx,fy,fw,fh in self:each_visible_option() do
local fill = i == self.selected and style.nagbar_text or style.nagbar
local text_color = i == self.selected and style.nagbar or style.nagbar_text
renderer.draw_rect(bx,by,bw,bh, style.nagbar_text)
if i ~= self.selected then
renderer.draw_rect(fx,fy,fw,fh, fill)
end
common.draw_text(opt.font, text_color, opt.text, "center", fx,fy,fw,fh)
end
end
function NagView:show(title, message, options, on_select, on_cancel)
self.title = title or "Warning"
self.message = message or "Empty?"
self.options = options or {}
if on_cancel then table.insert(options, { key = "cancel", font = style.icon_font, text = "C" }) end
self.force_focus = true
self.submit = function(item)
self.submit = noop -- reset the submit function
if item.key == "cancel" and on_cancel then
on_cancel()
elseif on_select then
on_select(item)
end
end
core.set_active_view(self)
end
return NagView
|