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.
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.
We now suggest classes even if the line does not start with an @.
After all, we now have fuzzy matching, so why *shouldn't* "color"
match @GUI::ColorInput as well as background_color?
A lot of the code in this area is duplicated, which is not great. In
fact this also fixes a bug where suggested partially matched props
would include read-only properties, since that check had only been
added to one of the two loops.
Previously this section of code would blindly add *anything* as a child
as long as it has been registered as an object. Since there is no
guarentee that those objects are, in fact, Widgets, this feels like a
logical fallacy.
For example, up until this change, this is perfectly valid GML:
```
@GUI::Widget {
layout: @GUI::VerticalBoxLayout {
}
@GUI::VerticalBoxLayout {
}
}
```
What exactly does it do? Who knows! It doesn't seem to *break*, but I
think we can all agree it shouldn't be valid.
Instead, we now actually verify that the registered class inherets from
GUI::Widget before adding it as a child. We also error if it's not,
which should hopefully help new GML writers from forgetting to write
'layout: ' before the layout definition and being confused as to why
it's not working.
There are only two layouts at the moment, but that could (and probably
will) change in the future. Why limit ourselves by hardcoding these
checks when we can do it dynamically instead?
This check was removed as it will now never trigger.
The completion has the suffix ': ' on it, and the key does not.
Therefore if the user has not yet typed the ':', it will not be equal,
and after they do the check on line 167 will fail so the entry won't be
in the list to begin with.
Previously we had a special case in order to auto-append quotes or
angle brackets to #include statements. After the previous commit this
is no longer necessary.