This patch removes a hack that forced any pending repaints to happen
immediately whenever you moved the mouse over a window.
The purpose of that mechanism was to ensure that quick button presses
still show up visually, and since that is now accomplished via
Widget::repaint(), we no longer need this.
This ensures that rapidly clicking a button doesn't look like it's
"swallowing" some of the mouse events.
This already worked okay due to a hack in Window, but this will allow us
to get rid of that hack.
In most situations, Widget::update() is preferable, since that allows us
to coalesce repaints and avoid redundant work, reducing system load.
However, there are some cases where you really want a paint to happen
right away, to make sure that the user has a chance to see a short-lived
visual state.
Before this change, using the Tab key would cycle through all the
individual buttons in an exclusive group (e.g radio buttons.)
This felt wrong, since a group of exclusive buttons is really a single
logical input with a limited number of possible choices.
This patch makes such groups behave as a single focusable unit instead,
by dynamically updating the focus policies so that only the currently
checked button is focusable.
We also allow keyboard navigation within the button group via the arrow
keys. This had to be specialized in GUI::AbstractButton, since the
default behavior of arrow keys is to traverse the focus chain.
Showing the selection in non-focused text editors was not really useful,
since refocusing the widget would clear or change the selection
immediately anyway.
Note that TextEditors in inactive windows can still be the focused
widget within that window, and will still be painted with an "inactive"
looking selection.
The FilePicker has implemented its common locations tray as a composite
widget built from a GUI::Frame with a bunch of GUI::Button inside it.
The problem with that is that it creates a long and annoying chain of
keyboard-focusable widgets.
This patch adds GUI::Tray, which is a dedicated single widget that
implements the same UI element, but without child widgets.
Toolbar buttons are meant for quick mouse access to common actions,
while quick keyboard access is normally achieved via keyboard shortcuts
and underlined menu items.
This makes interfaces with many toolbar buttons (e.g GUI::FilePicker)
a lot nicer to navigate via keyboard.
Previously, you could get crashes when you tried to search for a font
size in the Font Picker or a screen resolution in Display Settings.
This is because their list models aren't made of strings
and Variant::as_string() only accepts strings.
d0fb511d75 set the maximized window value
in the File Manager before a window was created, which resulted in crash
everytime you tried to open the program that was closed while it was
maximized. ugh
Here we do more-or-less what GUI::Window::set_rect() does, except we
don't add it to the WindowServer::create_window() IPC call.
That's because the Window Server knows nothing about menus at this
point and just assumes they don't need to be visible.
So if we try to maximize the window then, it could be slightly taller
and a titlebar could be hidden.
So even though it looks how it looks like, it does work and it doesn't
show in the startup size, as described in the mentioned commit (the call
is put a few lines before the initial update()). :^)
There used to be the silly bug that when the cursor was already at the
end of a span (e.g. because the user just pressed Ctrl-Right), then
Ctrl-Right had no effect.
This bug does not appear with Ctrl-Left because due to the order in
which the spans are iterated, the effective result is always correct.
This patch also makes it more apparent that the algorithm is
unnecessarily inefficient.
Previously, the initial call to update_selection() was missing, so if no
text was already selected, then Ctrl-Shift-End would only move the
cursor to the document end, but not select any text.
This adds automatic scrolling when dragging items in TreeViews and other
widgets that inherit from AbstractView when the overloaded
accepts_drag() returns true. This is implemented in FileSystemModel to
allow directories and files to be dragged.
FontPickerWeightModel is no longer necessary as variants contain
weight as part of a complete typeface description. This fixes fonts
not inventorying correctly in picker when they contained more than
bold and regular typefaces. Weight mapping has been moved into
LibGfx/FontStyleMapping.h
Large enough content ranges produced unclamped scrubbers sized zero,
effectively clamped by their integer type. This led to zero sized
page_increments and scrubbers which didn't budge on gutter events.
This fixes broken gutters in FontEditor and TextEditor for large
files.
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 commit adds a timer to AbstractScrollableWidget that can be used
when implementing automatic scrolling. By overriding
on_automatic_scrolling_timer_fired() we can calculate the scrolling
delta when dragging objects, and redraw as needed. A helper function,
automatic_scroll_delta_from_position() gives us a delta that
we can use to calculate speed and direction. By default
m_autoscroll_threshold is 20 pixels from the edge, and gives a linear
change in scroll delta.
When a file deletion event happens, we now iterate over all views of the
FileSystemModel and remove any selection & cursor indices that hold
dangling references do the deleted filesystem node.
This fixes#9602.
Prior this change, the button was updated on user selection change
in the file view.
This isn't quite right, as you could remove the text from the text box
or (even worse) start typing a filename there and the button state
wouldn't change.
This commit adds a `ColorSelectOverlay` class, and uses it to
allow the user to pick a color from the screen. The API for
`ColorSelectOverlay` is inspired from the `SelectableOverlay`
in `Utilities/shot.cpp`. In particular, it opens up it's own
window, so that we can have control over the cursor over the
whole screen.
There's one thing notably different: In addition to returning the
final selected color from the `exec()` function, it also provides
an `on_color_changed()` hook, which can be used to (optionally)
get live updated as the mouse is moving around.
This is a bit odd, but allows us to use the preview widget of the
color picker to see the current color under the mouse (which will
be selected upon clicking). When trying to select the color from
text / other small elements, this is very useful.
The existing behaviour is that filename_textbox is cleared if a node of
the wrong type is selected. Here we reflect that state update in the
state of the ok_button.
This change helps the user to avoid confirming (and seeing an alert) if
they press "Open" after clicking on an invalid node.
This change splits the do_search() into find_next_search_match() and
highlight_search() to allow the given index be independently highlighted
when needed.