The FooSettings apps have quite a lot of boilerplate just around
creating a tabbed window with the same styling and the same row of
buttons along the bottom. So, let's extract that out into a class we can
reuse! :^)
You create a SettingsWindow instead of a regular Window, passing a title
and a flag to determine if a "Defaults" button is shown. Then call
add_tab() to add tabs to it. Tabs are widgets extending
SettingsWindow::Tab, which has methods for saving and resetting the
values.
This isn't a complete conversion to ErrorOr<void>, but a good chunk.
The end goal here is to propagate buffer allocation failures to the
caller, and allow the use of TRY() with formatting functions.
Also add slightly richer parse errors now that we can include a string
literal with returned errors.
This will allow us to use TRY() when working with JSON data.
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.
This makes teardown faster since we don't have to wait for responses to
each destroy_window request. It also avoids doing IPC during teardown,
which is a general source of problems.
Implement, and use internally, content_margins() from Widget.
Since AbstractScrollableWidget already has a method called content_size,
the convenience method, with the same name, in Widget has to be
explicitly called.
Even though they are called content_margins,
they are actually only ever used to determine where
a Widget is supposed to be grabbable.
So all methods and members are renamed accordingly.
Derivatives of Core::Object should be constructed through
ClassName::construct(), to avoid handling ref-counted objects with
refcount zero. Fixing the visibility means that misuses like this are
more difficult.
Previously there was a situation where the autocomplete box would
appear to "jump" to the side. This was due to the following race
condition:
1. Start typing, thus triggering the autocomplete timer to start
2. Manually trigger autocomplete before the timer finishes
3. Continue typing
4. The autocomplete timer now fires
When the timer fires it causes the autocomplete box to show, which, if
it is already shown, has the effect of moving the box to the current
cursor position.
Previously the autocomplete box would always close after applying a
suggestion. This is the desired behavior in almost all cases, but there
are some situations (like autocompleting paths) where it would be nicer
to keep the autocomplete box open after applying the suggestion.