first draft of load/save buttons
Some considerations in the design so far: * Desired flows: * start typing into a new pane, then save to a filename * load from a filename, then continue typing/running * save as a second file * Should we autosave? I think not yet, because my editor's undo/redo functionality is not accessible yet on mobile. Android devices can't press 'ctrl', and the hotkeys aren't very discoverable. (I considered menu options for 'undo' and 'redo', but they won't be very ergonomic because my undo/redo functionality is primitive and doesn't support grouping similar operations. Now you're stuck tapping '>>', then 'undo' and losing one character. Then the menu closes and you have to do it all over again.) Another knock against autosave on mobile: autosave on quit is unreliable. At least on my Android devices, LÖVE doesn't trigger love.quit when you swipe away an app. iOS of course has no such notion in the first place. * Menu buttons take up space, and I'm loath to expend 2 more buttons. However, I don't see a good alternative: * We can't use a single button to bind a filename to a pane until we get autosave. * Save on run? It doesn't save a button, but maybe we can keep 'save' up top because we'll want to keep hitting it in the absence of autosave. However, I don't want to lose data just because I started typing out a long program that never got to a runnable point. * I'd like to keep 'save' always up. But newcomers might have more trouble finding things if load and save are separated from each other. Seems like the sort of thing Mike complained about before the current button organization. ==> conclusion: no autosave, 2 buttons, load and save * I want to follow MiniIDE and only save to a single directory (no subdirectories, even). Simplifies the file dialog. * Where should this directory live? Source base risks growing really large and unwieldy over time as we share files between lots of LÖVE apps. At least, Mike has that problem. Save dir is utterly inaccessible to other apps -- including later versions of this one. Once you delete one version of an app (say before installing a new version) the only way to find your files is to wade through lots of cryptic directories inside source dir. And you'd need a new LÖVE app to do that. ==> conclusion: save to a fixed subdir of source base dir. That way only Lua Carousel will save there, but different versions share a common space. * Should examples be savable? If yes, we could have conflicts. If no, it feels like a gotcha when someone starts editing an example. ==> conclusion: allow examples to be saved, but that creates a new copy of them on restart. It'll be weird that the order changes, but seems like the best option. * Where to show the current filename? I don't want to further reduce space for buttons. A smaller font seems necessary here to squeeze the filename into an interstitial of the UI. Still to do: providing a non-existing file to load/save. I plan a command palette UI for filtering or selecting a new file.
This commit is contained in:
parent
54ef90bca7
commit
83ebcaa5c4
|
@ -1,4 +1,5 @@
|
||||||
on.initialize = function()
|
on.initialize = function()
|
||||||
|
App.mkdir(Directory)
|
||||||
populate_missing_handlers()
|
populate_missing_handlers()
|
||||||
love.graphics.setFont(love.graphics.newFont(Font_height))
|
love.graphics.setFont(love.graphics.newFont(Font_height))
|
||||||
Line_height = math.floor(Font_height*1.3)
|
Line_height = math.floor(Font_height*1.3)
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
on.draw = function()
|
on.draw = function()
|
||||||
Global_state.button_handlers = {}
|
Global_state.button_handlers = {}
|
||||||
|
-- modal dialog
|
||||||
|
if Show_file_dialog then
|
||||||
|
draw_file_dialog()
|
||||||
|
return
|
||||||
|
end
|
||||||
Overflow_button = nil
|
Overflow_button = nil
|
||||||
love.graphics.setBackgroundColor(Background_color.r, Background_color.g, Background_color.b)
|
love.graphics.setBackgroundColor(Background_color.r, Background_color.g, Background_color.b)
|
||||||
draw_canvas()
|
draw_canvas()
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
on.keychord_press = function(chord, key)
|
on.keychord_press = function(chord, key)
|
||||||
|
if Show_file_dialog then
|
||||||
|
Show_file_dialog = false
|
||||||
|
return
|
||||||
|
end
|
||||||
if chord == 'C-=' then
|
if chord == 'C-=' then
|
||||||
update_font_settings(Current_pane.editor_state.font_height+2)
|
update_font_settings(Current_pane.editor_state.font_height+2)
|
||||||
elseif chord == 'C--' then
|
elseif chord == 'C--' then
|
||||||
|
|
|
@ -1,11 +1,26 @@
|
||||||
draw_editor_border = function()
|
draw_editor_border = function()
|
||||||
App.color(Normal_color)
|
App.color{r=0.5, g=0.5, b=0.5}
|
||||||
local x1 = Current_pane.editor_state.left-5-Line_number_padding
|
local x1 = Current_pane.editor_state.left-5-Line_number_padding
|
||||||
local y1 = Current_pane.editor_state.top-5
|
local y1 = Current_pane.editor_state.top-5
|
||||||
local x2 = Current_pane.editor_state.right+5
|
local x2 = Current_pane.editor_state.right+5
|
||||||
local y2 = Current_pane.editor_state.bottom+5
|
local y2 = Current_pane.editor_state.bottom+5
|
||||||
-- upper border
|
-- upper border
|
||||||
love.graphics.line(x1,y1, x2,y1)
|
if Current_pane.filename then
|
||||||
|
-- title in between if it exists
|
||||||
|
local old_font = love.graphics.getFont()
|
||||||
|
if Title_font == nil then
|
||||||
|
Title_font = love.graphics.newFont(15) -- 20 pixels between menu and upper border - 5
|
||||||
|
end
|
||||||
|
love.graphics.setFont(Title_font)
|
||||||
|
local tx1 = Current_pane.editor_state.left
|
||||||
|
local tx2 = tx1 + App.width(Current_pane.filename)
|
||||||
|
love.graphics.print(Current_pane.filename, tx1, y1-15+5)
|
||||||
|
love.graphics.setFont(old_font)
|
||||||
|
love.graphics.line(x1,y1, tx1-5,y1)
|
||||||
|
love.graphics.line(math.min(tx2+5,x2), y1, x2,y1)
|
||||||
|
else
|
||||||
|
love.graphics.line(x1,y1, x2,y1)
|
||||||
|
end
|
||||||
love.graphics.line(x1,y1, x1,y1+10)
|
love.graphics.line(x1,y1, x1,y1+10)
|
||||||
love.graphics.line(x2,y1, x2,y1+10)
|
love.graphics.line(x2,y1, x2,y1+10)
|
||||||
-- lower border
|
-- lower border
|
||||||
|
|
|
@ -28,6 +28,8 @@ draw_menu = function()
|
||||||
else
|
else
|
||||||
x, y = show_code_button(x, y, r)
|
x, y = show_code_button(x, y, r)
|
||||||
end
|
end
|
||||||
|
x, y = save_button(x, y, r)
|
||||||
|
x, y = load_button(x, y, r)
|
||||||
x, y = copy_button(x, y, r)
|
x, y = copy_button(x, y, r)
|
||||||
x, y = paste_button(x, y, r)
|
x, y = paste_button(x, y, r)
|
||||||
x, y = clear_pane_button(x, y, r)
|
x, y = clear_pane_button(x, y, r)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- Lua Carousel is almost entirely in a single (adjustable) font, but we make one exception to squeeze in a file name
|
||||||
|
Title_font = nil
|
|
@ -0,0 +1,16 @@
|
||||||
|
save_button = function(x, y, r)
|
||||||
|
return overflowable_button('save', x, y, r,
|
||||||
|
function()
|
||||||
|
print('save')
|
||||||
|
if Current_pane.filename == nil then
|
||||||
|
Directory_contents = nil -- refresh from file system
|
||||||
|
Show_file_dialog = true
|
||||||
|
File_dialog_callback = function(filename)
|
||||||
|
Current_pane.filename = filename
|
||||||
|
one_time_save()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
one_time_save()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
load_button = function(x, y, r)
|
||||||
|
return overflowable_button('load', x, y, r,
|
||||||
|
function()
|
||||||
|
Directory_contents = nil -- refresh from file system
|
||||||
|
Show_file_dialog = true
|
||||||
|
File_dialog_callback = function(filename)
|
||||||
|
Current_pane.filename = filename
|
||||||
|
one_time_load()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
|
@ -0,0 +1,30 @@
|
||||||
|
draw_file_dialog = function()
|
||||||
|
App.color(Menu_background)
|
||||||
|
love.graphics.rectangle('fill',
|
||||||
|
Menu_left+5,
|
||||||
|
Menu_bottom+5,
|
||||||
|
Safe_width-Menu_left-10,
|
||||||
|
Safe_height-Menu_bottom-10)
|
||||||
|
if Directory_contents == nil then
|
||||||
|
-- on the first frame after dialog is enabled
|
||||||
|
refresh_directory_contents()
|
||||||
|
end
|
||||||
|
local x, y = Menu_left+10, Menu_bottom+10
|
||||||
|
for _,filename in ipairs(Directory_contents) do
|
||||||
|
local w = App.width(filename) + 10
|
||||||
|
if x == Menu_left+10 or x+w < Safe_width-Menu_left-10 then
|
||||||
|
styled_button(filename, x,y, function()
|
||||||
|
File_dialog_callback(filename)
|
||||||
|
Show_file_dialog = false
|
||||||
|
File_dialog_callback = nil
|
||||||
|
end)
|
||||||
|
x = x+w+10
|
||||||
|
else
|
||||||
|
x = Menu_left+10
|
||||||
|
y = y+Line_height+10
|
||||||
|
if y > Safe_height-Menu_bottom-10 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
Show_file_dialog = false
|
|
@ -0,0 +1 @@
|
||||||
|
Directory = love.filesystem.getSourceBaseDirectory()..'/carousel_data/'
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- filenames inside directory
|
||||||
|
Directory_contents = nil
|
|
@ -0,0 +1,10 @@
|
||||||
|
refresh_directory_contents = function()
|
||||||
|
Directory_contents = {}
|
||||||
|
local files_info = nativefs.getDirectoryItemsInfo(Directory)
|
||||||
|
for _,file_info in ipairs(files_info) do
|
||||||
|
if file_info.type == 'file' then
|
||||||
|
table.insert(Directory_contents, file_info.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(Directory_contents)
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- Function that is called when a 'filename' is selected from the file dialog, e.g. to load from or save to a file.
|
||||||
|
File_dialog_callback = nil
|
|
@ -0,0 +1,7 @@
|
||||||
|
one_time_save = function()
|
||||||
|
print('saving to '..Current_pane.filename)
|
||||||
|
Current_pane.editor_state.filename = Directory..Current_pane.filename
|
||||||
|
save_to_disk(Current_pane.editor_state)
|
||||||
|
-- Don't autosave yet; undo isn't accessible in mobile devices.
|
||||||
|
Current_pane.editor_state.filename = nil
|
||||||
|
end
|
|
@ -0,0 +1,8 @@
|
||||||
|
one_time_load = function()
|
||||||
|
print('loading '..Current_pane.filename)
|
||||||
|
Current_pane.editor_state.filename = Directory..Current_pane.filename
|
||||||
|
load_from_disk(Current_pane.editor_state)
|
||||||
|
Text.redraw_all(Current_pane.editor_state)
|
||||||
|
-- Disable autosave; undo isn't accessible in mobile devices.
|
||||||
|
Current_pane.editor_state.filename = nil
|
||||||
|
end
|
Loading…
Reference in New Issue