Previously, it was "relying" on the cursor blink timer to update
the visual selection.
This caused some delay after the whole line was selected by
triple-clicking specifically the last word in a line.
Now, the widget is updated after triple-clicking.
This gets a lot of unecessary includes out of Widget.cpp. Doing this
didn't work before, but improvements in the C library and using dynamic
libraries have likely un-broken it :^).
Also, move the registration global object to an anonymous namespace. No
reason it has to be an extern symbol.
This aims to be a "smart" autocomplete that tries to present the user
with useful suggestions without being in the way (too much).
Here is its current configuration:
- Show suggestions 800ms after something is inserted in the editor
- if something else is inserted in that period, reset it back to 800ms
to allow the user to type uninterrupted
- cancel any shown autocomplete (and the timer) on external changes
(paste, cut, etc)
We previously had a cached bold variant font in Gfx::Font that was very
haphazardly located by filename pattern. This patches replaces that
mechanism with a proper Gfx::FontDatabase lookup for the same font but
with bold weight (700).
This makes it possible to construct a read-only (or display-only)
TextEditor in GML:
@GUI::TextEditor {
mode: "ReadOnly"
text: "Well hello friends! :^)"
}
Now that fonts know their own weight, we no longer need highlighters to
tell us which font to use. Instead, they can just say "this should be
bold" and we'll find the right font ourselves.
Instead of TextEditor knowing about the ComboBox button on the right
hand side, we now make ComboBox inherit from GUI::Frame, and make the
inner text editor widget frameless.
This allows us to place the button ourselves inside ComboBox without
any frame artifacts, and TextEditor no longer needs to keep track of
the geometry of that button.
When clicking empty space (beneath any used lines) in the TextEditor,
the cursor would jump to the start of the last line, rather than the
correct column, or the end of the line where appropriate. This was
because in the for_each_visual_line callback would return
IterationDecision::Continue if the clicked point wasn't in the line's
rect. Thus the callback would continue on each iteration and at the
end, would set the cursor to the default column of 0. To fix this I
added a bool to the callback's signature which tells the callback if
the for_each_visual_line method is on the last visual line. The
callback now does not return IterationDecision:Continue if
for_each_visual_line method is on the last line and the correct column
is then calculated with the line passed.
Every widget now has a GUI::FocusPolicy that determines how it can
receive focus:
- NoFocus: The widget is not focusable (default)
- TabFocus: The widget can be focused using the tab key.
- ClickFocus: The widget can be focused by clicking on it.
- StrongFocus: Both of the above.
For widgets that have a focus proxy, getting/setting the focus policy
will affect the proxy instead.
This matches behavior on Linux, macOS, Windows, and it makes it possible
to hit ctrl-L arrow-right ctrl-backspace to edit the last component of
an URL in browser, or of the current path in File Manager.
Also make it so that ctrl-left/right does a word movement that starts
at the edge of the selection. This matches Linux and macOS, but not
Windows (which instead does a word movement relative to the cursor,
not the selection edge).
The language server keeps track of the content of currently edited
files by receiving updates about edit actions.
Also, C++ autocompletion is no longer tied to HackStudio itself and
moved to be part of the language server.
This patch adds an optional mode where TextEditor highlights trailing
whitespace characters on each line with a nice reddish dither pattern.
We should probably make this themable and I'm sure it could be nicer
somehow, but this is just a first cut and I do kinda like it. :^)
This patch adds GUI::FocusEvent which has a GUI::FocusSource.
The focus source is one of three things:
- Programmatic
- Mouse
- Keyboard
This allows receivers of focus events to implement different behaviors
depending on how they receive/lose focus.
Instead of setting m_cursor directly to reset the cursor position,
TextEditor::set_document() now uses set_cursor() which will call cursor
change callback functions, if any.
This fixes a bug in HackStudio where the cursor information text would
not update immediately after changing the active TextDocument, even
though the cursor is always visibly being reset to 0, 0.
Adds a new highlighting effect to the actively selected row in
ComboBox ListView. ComboBoxEditor can now be controlled with
page up, page down, and the up and down arrow keys. ESC and loss
of focus now cause comboboxes to close. Now activates on mouseup
as well as return.