2022-07-12 07:03:27 +01:00
|
|
|
-- some constants people might like to tweak
|
|
|
|
Text_color = {r=0, g=0, b=0}
|
|
|
|
Cursor_color = {r=1, g=0, b=0}
|
|
|
|
Stroke_color = {r=0, g=0, b=0}
|
|
|
|
Current_stroke_color = {r=0.7, g=0.7, b=0.7} -- in process of being drawn
|
|
|
|
Current_name_background_color = {r=1, g=0, b=0, a=0.1} -- name currently being edited
|
|
|
|
Focus_stroke_color = {r=1, g=0, b=0} -- what mouse is hovering over
|
|
|
|
Highlight_color = {r=0.7, g=0.7, b=0.9} -- selected text
|
|
|
|
Icon_color = {r=0.7, g=0.7, b=0.7} -- color of current mode icon in drawings
|
|
|
|
Help_color = {r=0, g=0.5, b=0}
|
|
|
|
Help_background_color = {r=0, g=0.5, b=0, a=0.1}
|
|
|
|
|
2022-07-13 02:29:00 +01:00
|
|
|
Margin_top = 15
|
|
|
|
Margin_left = 25
|
|
|
|
Margin_right = 25
|
|
|
|
|
2022-07-16 16:48:02 +01:00
|
|
|
Drawing_padding_top = 10
|
|
|
|
Drawing_padding_bottom = 10
|
|
|
|
Drawing_padding_height = Drawing_padding_top + Drawing_padding_bottom
|
|
|
|
|
2022-07-13 05:38:29 +01:00
|
|
|
Same_point_distance = 4 -- pixel distance at which two points are considered the same
|
|
|
|
|
2022-07-12 06:14:59 +01:00
|
|
|
edit = {}
|
|
|
|
|
2024-09-01 03:05:58 +01:00
|
|
|
function edit.new(top, left, right, bottom, font, font_height)
|
2022-07-12 22:18:50 +01:00
|
|
|
local result = {
|
2024-07-21 06:46:04 +01:00
|
|
|
top = math.floor(top),
|
2024-06-23 01:09:15 +01:00
|
|
|
left = math.floor(left),
|
|
|
|
right = math.floor(right),
|
2024-07-21 06:46:04 +01:00
|
|
|
bottom = math.floor(bottom),
|
2024-06-23 01:09:15 +01:00
|
|
|
width = right-left,
|
|
|
|
|
|
|
|
font = font,
|
|
|
|
font_height = font_height,
|
2024-08-29 01:58:05 +01:00
|
|
|
line_height = math.floor(font_height*1.3),
|
2024-06-23 01:09:15 +01:00
|
|
|
|
|
|
|
-- The editor is for editing an array of lines. A line is either text or a drawing.
|
|
|
|
-- The array of lines can never be empty; there must be at least one line for positioning a cursor at.
|
|
|
|
--
|
|
|
|
-- A text line is a table with:
|
2022-07-12 22:18:50 +01:00
|
|
|
-- mode = 'text',
|
|
|
|
-- string data,
|
2024-06-23 01:09:15 +01:00
|
|
|
-- A drawing line is a table with:
|
2022-07-12 22:18:50 +01:00
|
|
|
-- mode = 'drawing'
|
|
|
|
-- a (h)eight,
|
|
|
|
-- an array of points, and
|
|
|
|
-- an array of shapes
|
2024-06-23 01:09:15 +01:00
|
|
|
-- A shape is a table containing:
|
|
|
|
-- a mode
|
|
|
|
-- an array points for mode 'freehand' (raw x,y coords; freehand drawings don't pollute the points array of a drawing)
|
|
|
|
-- an array vertices for mode 'polygon', 'rectangle', 'square'
|
|
|
|
-- p1, p2 for mode 'line'
|
|
|
|
-- center, radius for mode 'circle'
|
|
|
|
-- center, radius, start_angle, end_angle for mode 'arc'
|
|
|
|
-- Unless otherwise specified, coord fields are normalized; a drawing is always 256 units wide
|
|
|
|
-- The field names are carefully chosen so that switching modes in midstream
|
|
|
|
-- remembers previously entered points where that makes sense.
|
2022-07-18 05:05:01 +01:00
|
|
|
lines = {{mode='text', data=''}}, -- array of lines
|
2022-07-12 06:14:59 +01:00
|
|
|
|
2024-06-23 01:09:15 +01:00
|
|
|
-- We need to track a couple of _locations_:
|
|
|
|
screen_top = nil, -- location at top of screen, to start drawing from
|
|
|
|
cursor = nil, -- location where editing will occur
|
|
|
|
-- Valid location values:
|
|
|
|
-- {mode='text', line=, pos=}
|
2024-07-21 17:14:01 +01:00
|
|
|
-- {mode='drawing', line=}
|
2024-06-23 01:09:15 +01:00
|
|
|
|
2022-07-12 22:18:50 +01:00
|
|
|
selection1 = {},
|
|
|
|
-- some extra state to compute selection between mouse press and release
|
|
|
|
old_cursor1 = nil,
|
|
|
|
old_selection1 = nil,
|
|
|
|
mousepress_shift = nil,
|
2022-07-12 06:14:59 +01:00
|
|
|
|
2023-11-18 19:30:57 +00:00
|
|
|
current_drawing_mode = 'line', -- one of the available shape modes
|
2022-07-12 22:18:50 +01:00
|
|
|
previous_drawing_mode = nil, -- extra state for some ephemeral modes like moving/deleting/naming points
|
2022-07-12 06:14:59 +01:00
|
|
|
|
2024-07-21 19:45:04 +01:00
|
|
|
filename = love.filesystem.getSourceBaseDirectory()..'/lines.txt', -- '/' should work even on Windows
|
2022-07-12 22:18:50 +01:00
|
|
|
next_save = nil,
|
2022-07-12 06:14:59 +01:00
|
|
|
|
2022-07-12 22:18:50 +01:00
|
|
|
-- undo
|
|
|
|
history = {},
|
|
|
|
next_history = 1,
|
2024-06-23 01:16:46 +01:00
|
|
|
drawing_before = nil, -- extra state for drawing operations
|
2022-07-12 06:14:59 +01:00
|
|
|
|
2022-07-12 22:18:50 +01:00
|
|
|
-- search
|
|
|
|
search_term = nil,
|
|
|
|
search_backup = nil, -- stuff to restore when cancelling search
|
|
|
|
}
|
|
|
|
return result
|
2024-08-30 08:47:04 +01:00
|
|
|
end
|
2022-07-12 06:14:59 +01:00
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.scroll_to_top(editor)
|
|
|
|
assert(#editor.lines > 0)
|
|
|
|
if editor.lines[1].mode == 'text' then
|
|
|
|
editor.screen_top = {mode='text', line=1, pos=1}
|
|
|
|
editor.cursor = {mode='text', line=1, pos=1}
|
2024-06-23 01:09:15 +01:00
|
|
|
else
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.screen_top = {mode='drawing', line=1}
|
|
|
|
editor.cursor = {mode='drawing', line=1}
|
2023-03-17 16:36:38 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.valid_loc(editor, loc)
|
|
|
|
assert(#editor.lines > 0)
|
2024-06-23 01:09:15 +01:00
|
|
|
if loc == nil then return end
|
2024-09-01 02:48:40 +01:00
|
|
|
if loc.line > #editor.lines then return end
|
|
|
|
return editor.lines[loc.line].mode == loc.mode
|
2022-07-24 07:36:04 +01:00
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.draw(editor)
|
|
|
|
editor.button_handlers = {}
|
|
|
|
love.graphics.setFont(editor.font)
|
2024-07-20 08:24:12 +01:00
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
local cursor_or_mouse_loc = editor.cursor
|
|
|
|
if editor.mouse_down then
|
|
|
|
local loc = edit.mouse_loc(editor)
|
2024-07-20 05:22:27 +01:00
|
|
|
if loc.mode == 'text' then
|
|
|
|
cursor_or_mouse_loc = loc
|
|
|
|
end
|
2024-07-09 05:19:47 +01:00
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
local y = editor.top
|
|
|
|
for line_index, line in array.each(editor.lines, editor.screen_top.line) do
|
2024-09-02 03:54:26 +01:00
|
|
|
local rect
|
|
|
|
if line_index == editor.screen_top.line then
|
|
|
|
rect = edit.get_rect(editor, editor.screen_top)
|
|
|
|
else
|
|
|
|
rect = edit.get_rect(editor, {mode=line.mode, line=line_index, pos=1})
|
|
|
|
end
|
|
|
|
if rect.screen_line_rects then
|
|
|
|
-- text line
|
|
|
|
if #line.data == 0 then
|
|
|
|
-- empty line; just add a button to insert a new drawing
|
2024-09-01 02:48:40 +01:00
|
|
|
button(editor, 'draw', {x=editor.left-Margin_left+4, y=y+4, w=12,h=12, bg={r=1,g=1,b=0},
|
2022-07-17 16:05:22 +01:00
|
|
|
icon = icon.insert_drawing,
|
|
|
|
onpress1 = function()
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.drawing_before = snapshot(editor, line_index-1, line_index)
|
|
|
|
table.insert(editor.lines, line_index, {mode='drawing', y=y, h=256/2, points={}, shapes={}, pending={}})
|
|
|
|
editor.cursor = {mode='drawing', line=line_index}
|
|
|
|
if line_index == editor.screen_top.line then
|
|
|
|
editor.screen_top = {mode='drawing', line=line_index}
|
2024-08-18 18:46:28 +01:00
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
schedule_save(editor)
|
|
|
|
record_undo_event(editor, {before=editor.drawing_before, after=snapshot(editor, line_index-1, line_index+1)})
|
|
|
|
editor.drawing_before = nil
|
2022-07-17 16:05:22 +01:00
|
|
|
end,
|
|
|
|
})
|
2024-07-09 05:19:47 +01:00
|
|
|
else
|
2024-09-02 03:54:26 +01:00
|
|
|
for _,s in ipairs(rect.screen_line_rects) do
|
|
|
|
for _,c in ipairs(s.char_rects) do
|
|
|
|
if in_selection(editor, line_index, c.pos, cursor_or_mouse_loc)
|
|
|
|
or in_search(editor, line_index, c.pos)
|
|
|
|
then
|
|
|
|
App.color(Highlight_color)
|
|
|
|
love.graphics.rectangle('fill', editor.left+c.x, y+c.y, c.dx,c.dy)
|
2024-07-09 05:19:47 +01:00
|
|
|
end
|
2024-09-02 03:54:26 +01:00
|
|
|
if c.data then
|
|
|
|
App.color(Text_color)
|
|
|
|
love.graphics.print(c.data, editor.left+c.x, y+c.y)
|
|
|
|
end
|
|
|
|
if line_index == editor.cursor.line then
|
2024-09-16 07:14:04 +01:00
|
|
|
if c.pos == editor.cursor.pos then
|
2024-09-02 03:54:26 +01:00
|
|
|
Text.draw_cursor(editor, editor.left+c.x, y+c.y)
|
2024-07-21 19:45:04 +01:00
|
|
|
end
|
2024-07-09 05:19:47 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
2024-07-16 02:00:20 +01:00
|
|
|
-- draw cursor if it's at end of line
|
2024-09-02 03:54:26 +01:00
|
|
|
if line_index == editor.cursor.line and editor.cursor.pos == utf8.len(line.data)+1 then
|
|
|
|
local s = rect.screen_line_rects
|
|
|
|
local c = s[#s].char_rects
|
|
|
|
Text.draw_cursor(editor, editor.left+c[#c].x, y+c[#c].y)
|
|
|
|
end
|
2022-07-12 06:14:59 +01:00
|
|
|
else
|
2024-09-02 03:54:26 +01:00
|
|
|
-- drawing
|
|
|
|
Drawing.draw(editor, line_index, y+Drawing_padding_top)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
2024-09-02 03:54:26 +01:00
|
|
|
y = y + rect.dy
|
2024-09-01 02:48:40 +01:00
|
|
|
if y + editor.line_height > editor.bottom then
|
2024-07-09 05:19:47 +01:00
|
|
|
break
|
|
|
|
end
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
if editor.search_term then
|
|
|
|
Text.draw_search_bar(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.update(editor, dt)
|
|
|
|
Drawing.update(editor, dt)
|
|
|
|
if editor.next_save and editor.next_save < Current_time then
|
|
|
|
save_to_disk(editor)
|
|
|
|
editor.next_save = nil
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function schedule_save(editor)
|
|
|
|
if editor.next_save == nil then
|
|
|
|
editor.next_save = Current_time + 3 -- short enough that you're likely to still remember what you did
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.quit(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
-- make sure to save before quitting
|
2024-09-01 02:48:40 +01:00
|
|
|
if editor.next_save then
|
|
|
|
save_to_disk(editor)
|
2023-01-28 18:21:34 +00:00
|
|
|
-- give some time for the OS to flush everything to disk
|
|
|
|
love.timer.sleep(0.1)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.mouse_press(editor, mx,my, mouse_button)
|
|
|
|
if editor.search_term then return end
|
|
|
|
editor.mouse_down = mouse_button
|
|
|
|
if mouse_press_consumed_by_any_button(editor, mx,my, mouse_button) then
|
2022-08-23 17:40:48 +01:00
|
|
|
-- press on a button and it returned 'true' to short-circuit
|
|
|
|
return
|
|
|
|
end
|
2022-07-12 06:14:59 +01:00
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
local loc = edit.to_loc(editor, mx,my)
|
2024-07-20 05:22:27 +01:00
|
|
|
if loc == nil then
|
2024-09-19 01:45:39 +01:00
|
|
|
return -- don't move cursor
|
2023-06-03 18:36:05 +01:00
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.cursor = loc
|
2024-07-20 05:22:27 +01:00
|
|
|
if loc.mode == 'text' then
|
|
|
|
-- prepare for a drag selecting text
|
|
|
|
-- delicate dance between cursor/selection and old cursor/selection
|
2024-07-08 06:29:37 +01:00
|
|
|
-- scenarios:
|
|
|
|
-- regular press+release: sets cursor, clears selection
|
|
|
|
-- shift press+release:
|
|
|
|
-- sets selection to old cursor if not set otherwise leaves it untouched
|
|
|
|
-- sets cursor
|
|
|
|
-- press and hold to start a selection: sets selection on press, cursor on release
|
|
|
|
-- press and hold, then press shift: ignore shift
|
|
|
|
-- i.e. mouse_release should never look at shift state
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.old_cursor1 = editor.cursor
|
|
|
|
editor.old_selection1 = editor.selection1
|
|
|
|
editor.mousepress_shift = shift_down()
|
|
|
|
editor.selection1 = deepcopy(loc)
|
2024-07-20 05:22:27 +01:00
|
|
|
else
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.drawing_before = snapshot(editor, loc.line)
|
|
|
|
Drawing.mouse_press(editor, loc.line, mx,my, mouse_button)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.mouse_release(editor, mx,my, mouse_button)
|
|
|
|
if editor.search_term then return end
|
|
|
|
editor.mouse_down = nil
|
2023-09-20 21:39:29 +01:00
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
local loc = edit.to_loc(editor, mx,my)
|
2024-07-20 05:22:27 +01:00
|
|
|
if loc.mode == 'text' then
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.cursor = loc
|
|
|
|
edit.clean_up_mouse_press(editor)
|
2024-07-20 05:22:27 +01:00
|
|
|
else
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.selection1 = {}
|
|
|
|
Drawing.mouse_release(editor, mx,my, mouse_button)
|
|
|
|
schedule_save(editor)
|
|
|
|
if editor.drawing_before then
|
|
|
|
record_undo_event(editor, {before=editor.drawing_before, after=snapshot(editor, editor.cursor.line)})
|
|
|
|
editor.drawing_before = nil
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.clean_up_mouse_press(editor)
|
|
|
|
if editor.mousepress_shift then
|
|
|
|
if editor.old_selection1.line == nil then
|
|
|
|
editor.selection1 = editor.old_cursor1
|
2023-09-20 21:39:29 +01:00
|
|
|
else
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.selection1 = editor.old_selection1
|
2023-09-20 21:39:29 +01:00
|
|
|
end
|
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.old_cursor1, editor.old_selection1, editor.mousepress_shift = nil
|
|
|
|
if edit.eq(editor.cursor, editor.selection1) then
|
|
|
|
editor.selection1 = {}
|
2023-09-20 21:39:29 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.mouse_wheel_move(editor, dx,dy)
|
2023-03-24 04:00:09 +00:00
|
|
|
if dy > 0 then
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.cursor = deepcopy(editor.screen_top)
|
2023-03-24 04:00:09 +00:00
|
|
|
for i=1,math.floor(dy) do
|
2024-09-01 02:48:40 +01:00
|
|
|
Text.up(editor)
|
2023-03-24 04:00:09 +00:00
|
|
|
end
|
2023-03-24 04:38:33 +00:00
|
|
|
elseif dy < 0 then
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.cursor = edit.to_loc(editor, editor.left, editor.bottom-1)
|
|
|
|
assert(editor.cursor)
|
2023-03-24 04:00:09 +00:00
|
|
|
for i=1,math.floor(-dy) do
|
2024-09-01 02:48:40 +01:00
|
|
|
Text.down(editor)
|
2023-03-24 04:00:09 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.text_input(editor, t)
|
|
|
|
if editor.search_term then
|
|
|
|
editor.search_term = editor.search_term..t
|
|
|
|
Text.search_next(editor)
|
2024-08-29 01:52:13 +01:00
|
|
|
return
|
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
if edit.to_coord(editor, editor.cursor) == nil then return end -- cursor is off screen
|
2024-08-29 01:52:13 +01:00
|
|
|
-- to be precise, the top-left corner of the cursor is off screen
|
|
|
|
-- for drawings the cursor is large, which can still be a bit strange
|
|
|
|
-- large selections can also be strange, though the actual cursor would still be small
|
2024-09-01 02:48:40 +01:00
|
|
|
if editor.cursor.mode == 'drawing' and editor.current_drawing_mode == 'name' then
|
2024-08-29 01:52:13 +01:00
|
|
|
-- TODO: there's a bug here where the point being named may be off screen
|
|
|
|
-- To hit that bug you'd have to press C-n to go into point naming mode
|
|
|
|
-- while the cursor is on screen, then move the page somehow without going
|
|
|
|
-- out of naming mode.
|
2024-09-01 02:48:40 +01:00
|
|
|
local before = snapshot(editor, editor.cursor.line)
|
|
|
|
local drawing = editor.lines[editor.cursor.line]
|
2022-07-12 06:14:59 +01:00
|
|
|
local p = drawing.points[drawing.pending.target_point]
|
|
|
|
p.name = p.name..t
|
2024-09-01 02:48:40 +01:00
|
|
|
record_undo_event(editor, {before=before, after=snapshot(editor, editor.cursor.line)})
|
2022-07-12 06:14:59 +01:00
|
|
|
else
|
2024-09-01 02:48:40 +01:00
|
|
|
Text.text_input(editor, t)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
schedule_save(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.keychord_press(editor, chord, key)
|
|
|
|
local cursor_on_screen = edit.to_coord(editor, editor.cursor)
|
|
|
|
if editor.selection1.line and editor.cursor.mode == 'text' and
|
2024-08-29 01:52:13 +01:00
|
|
|
cursor_on_screen and
|
2022-07-12 06:14:59 +01:00
|
|
|
-- printable character created using shift key => delete selection
|
|
|
|
-- (we're not creating any ctrl-shift- or alt-shift- combinations using regular/printable keys)
|
2024-06-22 19:00:32 +01:00
|
|
|
(not shift_down() or utf8.len(key) == 1) and
|
|
|
|
chord ~= 'C-a' and chord ~= 'C-c' and chord ~= 'C-x' and chord ~= 'backspace' and chord ~= 'delete' and chord ~= 'C-z' and chord ~= 'C-y' and not is_cursor_movement(key) then
|
2024-09-01 03:01:33 +01:00
|
|
|
Text.delete_selection_and_record_undo_event(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
if editor.search_term then
|
2022-07-12 06:14:59 +01:00
|
|
|
if chord == 'escape' then
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.search_term = nil
|
|
|
|
editor.cursor = editor.search_backup.cursor
|
|
|
|
editor.screen_top = editor.search_backup.screen_top
|
|
|
|
editor.search_backup = nil
|
2022-07-12 06:14:59 +01:00
|
|
|
elseif chord == 'return' then
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.search_term = nil
|
|
|
|
editor.search_backup = nil
|
2022-07-12 06:14:59 +01:00
|
|
|
elseif chord == 'backspace' then
|
2024-09-01 02:48:40 +01:00
|
|
|
local len = utf8.len(editor.search_term)
|
|
|
|
local byte_offset = Text.offset(editor.search_term, len)
|
|
|
|
editor.search_term = string.sub(editor.search_term, 1, byte_offset-1)
|
|
|
|
editor.cursor = deepcopy(editor.search_backup.cursor)
|
|
|
|
editor.screen_top = deepcopy(editor.search_backup.screen_top)
|
|
|
|
Text.search_next(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
elseif chord == 'down' then
|
2024-09-01 02:48:40 +01:00
|
|
|
Text.right(editor)
|
|
|
|
Text.search_next(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
elseif chord == 'up' then
|
2024-09-01 02:48:40 +01:00
|
|
|
Text.search_previous(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
return
|
|
|
|
elseif chord == 'C-f' then
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.search_term = ''
|
|
|
|
editor.search_backup = {
|
|
|
|
cursor=deepcopy(editor.cursor),
|
|
|
|
screen_top=deepcopy(editor.screen_top),
|
2022-09-05 19:28:03 +01:00
|
|
|
}
|
2022-08-18 18:09:20 +01:00
|
|
|
-- zoom
|
2022-07-12 06:14:59 +01:00
|
|
|
elseif chord == 'C-=' then
|
2024-09-01 02:48:40 +01:00
|
|
|
edit.update_font_settings(editor, editor.font_height+2)
|
2022-07-12 06:14:59 +01:00
|
|
|
elseif chord == 'C--' then
|
2024-09-01 02:48:40 +01:00
|
|
|
if editor.font_height > 2 then
|
|
|
|
edit.update_font_settings(editor, editor.font_height-2)
|
2023-03-18 02:58:49 +00:00
|
|
|
end
|
2022-07-12 06:14:59 +01:00
|
|
|
elseif chord == 'C-0' then
|
2024-09-01 02:48:40 +01:00
|
|
|
edit.update_font_settings(editor, 20)
|
2022-08-18 18:09:20 +01:00
|
|
|
-- undo
|
2022-07-12 06:14:59 +01:00
|
|
|
elseif chord == 'C-z' then
|
2024-09-01 02:48:40 +01:00
|
|
|
local event = undo_event(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
if event then
|
|
|
|
local src = event.before
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.screen_top = deepcopy(src.screen_top)
|
|
|
|
editor.cursor = deepcopy(src.cursor)
|
|
|
|
editor.selection1 = deepcopy(src.selection)
|
|
|
|
patch(editor.lines, event.after, event.before)
|
|
|
|
schedule_save(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
elseif chord == 'C-y' then
|
2024-09-01 02:48:40 +01:00
|
|
|
local event = redo_event(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
if event then
|
|
|
|
local src = event.after
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.screen_top = deepcopy(src.screen_top)
|
|
|
|
editor.cursor = deepcopy(src.cursor)
|
|
|
|
editor.selection1 = deepcopy(src.selection)
|
|
|
|
patch(editor.lines, event.before, event.after)
|
|
|
|
schedule_save(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
-- clipboard
|
2024-08-29 01:52:13 +01:00
|
|
|
elseif chord == 'C-a' and cursor_on_screen then
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.selection1 = {line=1, pos=1}
|
|
|
|
editor.cursor = {mode='text', line=#editor.lines, pos=utf8.len(editor.lines[#editor.lines].data)+1}
|
2022-07-12 06:14:59 +01:00
|
|
|
elseif chord == 'C-c' then
|
2024-09-01 02:48:40 +01:00
|
|
|
local s = Text.selection(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
if s then
|
2024-06-20 05:39:47 +01:00
|
|
|
love.system.setClipboardText(s)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
2024-08-29 01:52:13 +01:00
|
|
|
elseif chord == 'C-x' and cursor_on_screen then
|
2024-09-01 03:01:33 +01:00
|
|
|
local s = Text.cut_selection_and_record_undo_event(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
if s then
|
2024-06-20 05:39:47 +01:00
|
|
|
love.system.setClipboardText(s)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
schedule_save(editor)
|
2024-08-29 01:52:13 +01:00
|
|
|
elseif chord == 'C-v' and cursor_on_screen then
|
2022-07-12 06:14:59 +01:00
|
|
|
-- We don't have a good sense of when to scroll, so we'll be conservative
|
|
|
|
-- and sometimes scroll when we didn't quite need to.
|
2024-09-01 02:48:40 +01:00
|
|
|
local before_line = editor.cursor.line
|
|
|
|
local before = snapshot(editor, before_line)
|
2024-06-20 05:39:47 +01:00
|
|
|
local clipboard_data = love.system.getClipboardText()
|
2022-07-12 06:14:59 +01:00
|
|
|
for _,code in utf8.codes(clipboard_data) do
|
|
|
|
local c = utf8.char(code)
|
|
|
|
if c == '\n' then
|
2024-09-01 02:48:40 +01:00
|
|
|
Text.insert_return(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
else
|
2024-09-01 02:48:40 +01:00
|
|
|
Text.insert_at_cursor(editor, c)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
maybe_snap_cursor_to_bottom_of_screen(editor)
|
|
|
|
record_undo_event(editor, {before=before, after=snapshot(editor, before_line, editor.cursor.line)})
|
|
|
|
schedule_save(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
-- dispatch to drawing or text
|
2024-06-20 05:39:47 +01:00
|
|
|
elseif love.mouse.isDown(1) or chord:sub(1,2) == 'C-' then
|
2024-09-01 02:48:40 +01:00
|
|
|
if editor.cursor.mode == 'drawing' then
|
|
|
|
local before = snapshot(editor, editor.cursor.line)
|
|
|
|
Drawing.keychord_press(editor, chord)
|
|
|
|
record_undo_event(editor, {before=before, after=snapshot(editor, editor.cursor.line)})
|
|
|
|
schedule_save(editor)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
2024-06-20 05:39:47 +01:00
|
|
|
elseif chord == 'escape' and not love.mouse.isDown(1) then
|
2024-09-01 02:48:40 +01:00
|
|
|
for _,line in ipairs(editor.lines) do
|
2022-07-12 06:14:59 +01:00
|
|
|
if line.mode == 'drawing' then
|
|
|
|
line.show_help = false
|
|
|
|
end
|
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
elseif editor.cursor.mode == 'drawing' and editor.current_drawing_mode == 'name' then
|
2022-07-12 06:14:59 +01:00
|
|
|
if chord == 'return' then
|
2024-09-01 02:48:40 +01:00
|
|
|
editor.current_drawing_mode = editor.previous_drawing_mode
|
|
|
|
editor.previous_drawing_mode = nil
|
2022-07-12 06:14:59 +01:00
|
|
|
else
|
2024-09-01 02:48:40 +01:00
|
|
|
local before = snapshot(editor, editor.cursor.line)
|
|
|
|
local drawing = editor.lines[editor.cursor.line]
|
2022-07-12 06:14:59 +01:00
|
|
|
local p = drawing.points[drawing.pending.target_point]
|
|
|
|
if chord == 'escape' then
|
|
|
|
p.name = nil
|
2024-09-01 02:48:40 +01:00
|
|
|
record_undo_event(editor, {before=before, after=snapshot(editor, editor.cursor.line)})
|
2022-07-12 06:14:59 +01:00
|
|
|
elseif chord == 'backspace' then
|
|
|
|
local len = utf8.len(p.name)
|
2023-03-26 16:17:31 +01:00
|
|
|
if len > 0 then
|
|
|
|
local byte_offset = Text.offset(p.name, len-1)
|
|
|
|
if len == 1 then byte_offset = 0 end
|
|
|
|
p.name = string.sub(p.name, 1, byte_offset)
|
2024-09-01 02:48:40 +01:00
|
|
|
record_undo_event(editor, {before=before, after=snapshot(editor, editor.cursor.line)})
|
2023-03-26 16:17:31 +01:00
|
|
|
end
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
end
|
2024-09-01 02:48:40 +01:00
|
|
|
schedule_save(editor)
|
2024-08-29 01:52:13 +01:00
|
|
|
elseif cursor_on_screen then
|
2024-09-01 02:48:40 +01:00
|
|
|
Text.keychord_press(editor, chord)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.key_release(editor, key, scancode)
|
2022-07-12 06:14:59 +01:00
|
|
|
end
|
2022-07-12 23:39:11 +01:00
|
|
|
|
2024-09-01 02:48:40 +01:00
|
|
|
function edit.update_font_settings(editor, font_height)
|
|
|
|
editor.font_height = font_height
|
|
|
|
editor.font = love.graphics.newFont(editor.font_height)
|
|
|
|
editor.line_height = math.floor(font_height*1.3)
|
2022-07-16 06:15:07 +01:00
|
|
|
end
|