1 Menu_background_color
= {r
=0.6, g
=0.8, b
=0.6}
2 Menu_border_color
= {r
=0.6, g
=0.7, b
=0.6}
3 Menu_command_color
= {r
=0.2, g
=0.2, b
=0.2}
4 Menu_highlight_color
= {r
=0.5, g
=0.7, b
=0.3}
6 function source
.draw_menu_bar()
7 if App
.run_tests
then return end -- disable in tests
8 App
.color(Menu_background_color
)
9 love
.graphics
.rectangle('fill', 0,0, App
.screen
.width
, Menu_status_bar_height
)
10 App
.color(Menu_border_color
)
11 love
.graphics
.rectangle('line', 0,0, App
.screen
.width
, Menu_status_bar_height
)
12 App
.color(Menu_command_color
)
14 if Show_file_navigator
then
15 source
.draw_file_navigator()
18 add_hotkey_to_menu('ctrl+e: run')
19 if Focus
== 'edit' then
20 add_hotkey_to_menu('ctrl+g: switch file')
21 if Show_log_browser_side
then
22 add_hotkey_to_menu('ctrl+l: hide log browser')
24 add_hotkey_to_menu('ctrl+l: show log browser')
26 add_hotkey_to_menu('ctrl+k: clear logs')
27 if Editor_state
.expanded
then
28 add_hotkey_to_menu('alt+b: collapse debug prints')
30 add_hotkey_to_menu('alt+b: expand debug prints')
32 add_hotkey_to_menu('alt+d: create/edit debug print')
33 add_hotkey_to_menu('ctrl+f: find in file')
34 add_hotkey_to_menu('alt+left alt+right: prev/next word')
35 elseif Focus
== 'log_browser' then
38 assert(false, 'unknown focus "'..Focus
..'"')
40 add_hotkey_to_menu('ctrl+z ctrl+y: undo/redo')
41 add_hotkey_to_menu('ctrl+x ctrl+c ctrl+v: cut/copy/paste')
42 add_hotkey_to_menu('ctrl+= ctrl+- ctrl+0: zoom')
45 function add_hotkey_to_menu(s
)
46 local width
= App
.width(s
)
47 if Menu_cursor
> App
.screen
.width
- 30 then
50 App
.color(Menu_command_color
)
51 App
.screen
.print(s
, Menu_cursor
,5)
52 Menu_cursor
= Menu_cursor
+ width
+ 30
55 function source
.draw_file_navigator()
56 App
.color(Menu_command_color
)
57 App
.screen
.print(File_navigation
.filter
, 5, 5)
58 draw_cursor(5 + App
.width(File_navigation
.filter
), 5)
59 if File_navigation
.num_lines
== nil then
60 File_navigation
.num_lines
= source
.num_lines_for_file_navigator(File_navigation
.candidates
)
62 App
.color(Menu_background_color
)
63 love
.graphics
.rectangle('fill', 0,Menu_status_bar_height
, App
.screen
.width
, File_navigation
.num_lines
* Editor_state
.line_height
+ --[[highlight padding]] 2)
64 local x
,y
= 5, Menu_status_bar_height
65 for i
,filename
in ipairs(File_navigation
.candidates
) do
66 x
,y
= add_file_to_menu(x
,y
, filename
, i
== File_navigation
.index
)
67 if Menu_cursor
>= App
.screen
.width
- 5 then
73 function draw_cursor(x
, y
)
75 if math
.floor(Cursor_time
*2)%2 == 0 then
76 App
.color(Cursor_color
)
77 love
.graphics
.rectangle('fill', x
,y
, 3,Editor_state
.line_height
)
81 function source
.file_navigator_candidates()
82 if File_navigation
.filter
== '' then
83 return File_navigation
.all_candidates
86 for _
,filename
in ipairs(File_navigation
.all_candidates
) do
87 if starts_with(filename
, File_navigation
.filter
) then
88 table.insert(result
, filename
)
94 function source
.num_lines_for_file_navigator(candidates
)
97 for i
,filename
in ipairs(candidates
) do
98 local width
= App
.width(filename
)
99 if x
+ width
> App
.screen
.width
- 5 then
109 function add_file_to_menu(x
,y
, s
, cursor_highlight
)
110 local width
= App
.width(s
)
111 if x
+ width
> App
.screen
.width
- 5 then
112 y
= y
+ Editor_state
.line_height
115 local color
= Menu_background_color
116 if cursor_highlight
then
117 color
= Menu_highlight_color
119 button(Editor_state
, 'menu', {x
=x
-5, y
=y
-2, w
=width
+5*2, h
=Editor_state
.line_height
+2*2, bg
=color
,
120 onpress1
= function()
124 App
.color(Menu_command_color
)
125 App
.screen
.print(s
, x
,y
)
130 function navigate_to_file(s
)
131 move_candidate_to_front(s
)
132 source
.switch_to_file(s
..'.lua')
133 love
.window
.setTitle('lines.love - source - '..Editor_state
.filename
)
134 reset_file_navigator()
137 function move_candidate_to_front(s
)
138 local index
= array
.find(File_navigation
.all_candidates
, s
)
139 assert(index
, 'file missing from manifest')
140 table.remove(File_navigation
.all_candidates
, index
)
141 table.insert(File_navigation
.all_candidates
, 1, s
)
144 function reset_file_navigator()
145 Show_file_navigator
= false
146 File_navigation
.index
= 1
147 File_navigation
.filter
= ''
148 File_navigation
.candidates
= File_navigation
.all_candidates
151 function keychord_press_on_file_navigator(chord
, key
)
152 log(2, 'file navigator: '..chord
)
153 log(2, {name
='file_navigator_state', files
=File_navigation
.candidates
, index
=File_navigation
.index
})
154 if chord
== 'escape' then
155 reset_file_navigator()
156 elseif chord
== 'return' then
157 navigate_to_file(File_navigation
.candidates
[File_navigation
.index
])
158 elseif chord
== 'backspace' then
159 local len
= utf8
.len(File_navigation
.filter
)
160 local byte_offset
= Text
.offset(File_navigation
.filter
, len
)
161 File_navigation
.filter
= string.sub(File_navigation
.filter
, 1, byte_offset
-1)
162 File_navigation
.index
= 1
163 File_navigation
.candidates
= source
.file_navigator_candidates()
164 elseif chord
== 'left' then
165 if File_navigation
.index
> 1 then
166 File_navigation
.index
= File_navigation
.index
-1
168 elseif chord
== 'right' then
169 if File_navigation
.index
< #File_navigation
.candidates
then
170 File_navigation
.index
= File_navigation
.index
+1
172 elseif chord
== 'down' then
173 file_navigator_down()
174 elseif chord
== 'up' then
179 function log_render
.file_navigator_state(o
, x
,y
, w
)
180 -- duplicate structure of source.draw_file_navigator
181 local num_lines
= source
.num_lines_for_file_navigator(o
.files
)
182 local h
= num_lines
* Editor_state
.line_height
183 App
.color(Menu_background_color
)
184 love
.graphics
.rectangle('fill', x
,y
, w
,h
)
185 -- compute the x,y,width of the current index (in offsets from top left)
188 for i
,filename
in ipairs(o
.files
) do
189 width
= App
.width(filename
)
190 if x2
+ width
> App
.screen
.width
- 5 then
191 y2
= y2
+ Editor_state
.line_height
199 -- figure out how much of the menu to display
200 local menu_xmin
= math
.max(0, x2
-w
/2)
201 local menu_xmax
= math
.min(App
.screen
.width
, x2
+w
/2)
202 -- now selectively print out entries
203 local x3
,y3
= 0,y
-- x3 is relative, y3 is absolute
205 for i
,filename
in ipairs(o
.files
) do
206 width
= App
.width(filename
)
207 if x3
+ width
> App
.screen
.width
- 5 then
208 y3
= y3
+ Editor_state
.line_height
212 App
.color(Menu_highlight_color
)
213 love
.graphics
.rectangle('fill', x
+ x3
-menu_xmin
- 5, y3
-2, width
+5*2, Editor_state
.line_height
+2*2)
215 if x3
>= menu_xmin
and x3
+ width
< menu_xmax
then
216 App
.color(Menu_command_color
)
217 App
.screen
.print(filename
, x
+ x3
-menu_xmin
, y3
)
225 function file_navigator_up()
226 local y
, x
, width
= file_coord(File_navigation
.index
)
227 local index
= file_index(y
-Editor_state
.line_height
, x
, width
)
229 File_navigation
.index
= index
233 function file_navigator_down()
234 local y
, x
, width
= file_coord(File_navigation
.index
)
235 local index
= file_index(y
+Editor_state
.line_height
, x
, width
)
237 File_navigation
.index
= index
241 function file_coord(index
)
242 local y
,x
= Menu_status_bar_height
, 5
243 for i
,filename
in ipairs(File_navigation
.candidates
) do
244 local width
= App
.width(filename
)
245 if x
+ width
> App
.screen
.width
- 5 then
246 y
= y
+ Editor_state
.line_height
256 function file_index(fy
, fx
, fwidth
)
257 log_start('file index')
258 log(2, ('for %d %d %d'):format(fy
, fx
, fwidth
))
259 local y
,x
= Menu_status_bar_height
, 5
260 local best_guess
, best_guess_x
, best_guess_width
261 for i
,filename
in ipairs(File_navigation
.candidates
) do
262 local width
= App
.width(filename
)
263 if x
+ width
> App
.screen
.width
- 5 then
264 y
= y
+ Editor_state
.line_height
268 log(2, ('%d: correct row; considering %d %s %d %d'):format(y
, i
, filename
, x
, width
))
269 if best_guess
== nil then
273 best_guess_width
= width
274 elseif math
.abs(fx
+ fwidth
/2 - x
- width
/2) < math
.abs(fx
+ fwidth
/2 - best_guess_x
- best_guess_width
/2) then
277 best_guess_width
= width
279 log(2, ('best guess now %d %s %d %d'):format(best_guess
, File_navigation
.candidates
[best_guess
], best_guess_x
, best_guess_width
))
283 log_end('file index')
287 function text_input_on_file_navigator(t
)
288 File_navigation
.filter
= File_navigation
.filter
..t
289 File_navigation
.candidates
= source
.file_navigator_candidates()