`write_to_file(StringView path)` was based on the `Core::File` overload.
The return type also changed from `bool` to `ErrorOr<void>` to ease
error propagation.
Both widgets now make use of their base class's scrolling timer and
now always accept drag selection updates on mousemove_event().
This guarantees much snappier feeling selections when actively moving
the mouse.
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
Previously, pressing Shift+Tab would indent the line if no selection was
given. While with a selection, it would be unindented. With this change,
pressing Shift+Tab with no selection unindents the current line.
For this, add unindent_line() helper function. This function unindents the
current line by at most one tab width if it starts with whitespace,
regardless of cursor position.
Currently, LibGUI modifies the Ctrl+Alt+Space key event to instead
represent the emoji that was selected through EmojiInputDialog. This is
limited to a single code point.
For multiple code point emoji support, individual widgets now set a hook
to be notified of the emoji selection with a UTF-8 encoded string. This
replaces the previous set_accepts_emoji_input() method.
Noticed that mouse-overing the ruler area in the TextEditor
does not change the cursor to the default cursor, instead, the
beam cursor is used, which does not look nice.
This PR extends the mousemove event and introduces a new
set_editing_cursor() function that takes care of setting the
cursor for the editor area.
This allows lines moved by Ctrl+Shift+[Up, Down] to be registered as a
command, i.e. cancellable by Ctrl+Z.
This patch also introduces the usage of TextDocument::[take,
insert]_line. Those functions forward changes to the visual lines and
then avoid some data mismatch.
Co-authored-by: Jorropo <jorropo.pgm@gmail.com>
If selected text is less than a whole line, usual delete/replace takes
place. Otherwise, if the selected text is a whole line or spans
multiple lines, the selection will be indented.
This is the only Widget that ran its callback in deferred_invoke(). It
seems to be a holdover from when syntax-highlighting ran whenever the
text changed, but that has not been true since
bec2b3086c. Running the callback
immediately has no obvious downsides, but does make it a lot easier to
reason about. (I might have spent an hour confused as to why things
were happening in the wrong order...)
This adds a search API to TextEditor.
The API that is similar to "find_text" of TextDocument (which is used
internally to do the search).
All search results (as well as the current one) are highlighted with
a "span collection", which is pretty neat :^)
TextDocument::set_spans() now also takes a "span collection index"
argument.
TextDocument keeps a map between a span collection index and its spans.
It merges the spans from all collections into a single set of spans
whenever set_spans() is called.
This allows us to style a document with multiple layers of spans, where
as previously we only supported a single layer of spans that was set
from the SyntaxHighlighter.
Fonts now provide their preferred line height based on maximum
height and requested line gap. TTFs provide a preferred line gap
from table metrics while BitmapFonts are hardcoded at the previous
default for now.
Having the delete key handling be done via an action limits our ability
to support key modifiers (e.g. ctrl+delete deleting the word in front of
the cursor).
The fact that it was an action _did_ allow us to have a delete button in
the TextEditor UI. However, this is an odd choice in the first place
that isn't common in other text editors, so I just removed it.
Moving the cursor to a different location, by any means, should
dismiss the autocomplete popup. This is the behavior of virtually
every editor/IDE out there, and it is really annoying (and
confusing) when our autocomplete doesn't behave like that.
Previously if there were no suggestions, we simply wouldn't show the
autocomplete popup at all. This is functional, but when there are no
resultes it does leave the user wondering if it actually worked.
Now, if the user requests autocomplete and we do have requests, it
behaves exactly as before, but if there' aren't any we now show a box
with the message "No suggestions" to show the user that we got the
request, there just isn't anything to suggest.
This is a helpful option to prevent unwanted side effects, distinguish
between user and programmatic input, etc. Sliders and SpinBoxes were
implementing it idiosyncratically, so let's generalize the API and
give Buttons and TextEditors the same ability.
This allows the address bar to "select all" when initially gaining focus
as Firefox and Chrome do. A future improvement on this would be for the
Widget class to mange and provide focus transition as part of the events
instead of the UrlBox class. Currently focus is updated before the event
is provided to the UrlBox class.
This ensures that the user can't copy/cut text from password boxes which
would reveal the password. It also makes sure that the undo/redo actions
stay disabled because it's difficult to reason about what these do
exactly without being able to see the result.
Anyone who inherits from `GUI::Clipboard::ClipboardClient` will receive
clipboard notifications via `clipboard_content_did_change()`.
Update ClipboardHistoryModel, TextEditor and TerminalWidget to inherit
from this class.
While under insert mode, Ctrl-U deletes all characters between the first
non-blank character of the line and the cursor.
Implement delete_from_line_start_to_cursor() in TextEditor. Then, call
the method in VimEditingEngine via its pointer to an instance of
TextEditor.
In Vim, Ctrl-H is effectively equivalent to backspace in insert mode, as
it deletes the previous character.
This commit implements method delete_previous_char() to TextEditor.
delete_char() already exists in EditingEngine, but it deletes the
next character rather than the previous. delete_previous_char() is then
called from within VimEditingEngine.
In Vim's insert mode, Ctrl-W deletes the word before the cursor, like
Ctrl-Backspace. Unlike Ctrl-Backspace, if only whitespace exists between
the end of the word and the cursor, the word will be deleted with the
whitespace.
To do so, this commit introduces two methods: delete_previous_word() for
TextEditor and first_word_before() for TextDocument, where the former
depends on the latter. delete_previous_word() is then called in
VimEditingEngine.