With this, if clicking the gutter until the scrubber's below the
mouse and then releasing the mouse, the scrubber is correctly
highlighted after releasing the mouse.
While left-mouse is pressed on any component (arrows, gutter, scrubber),
don't draw hover states for components other than the pressed component.
For example, while clicking the arrow-down button and then dragging
around, the arrow-up button and the scrubber now aren't highlighted.
This also means that during a gutter drag session, the scrubber
isn't highlighted while it's under the mouse cursor. That makes
sense, since we get the gutter drag behavior, not the scrubber
drag behavior, in this case.
The highlight is supposed to indicate "clickability", but if the
mouse is already down, they can't be clicked.
Now that I check for it, this seems to match the scrollbar behavior
on Windows.
And remove the now-redundant members m_scrubbing, m_scrubber_in_use,
and m_automatic_scrolling_kind.
This also made it clear that we weren't canceling the autoscroll
timer if the scrollbar got disabled while it was scrolling, so
this fixes that too.
Note that m_hovered_component is only updated on mouse move, not while
just keeping left down. It's arguably wrong to update it on mouse move
while the mouse is down, I'll probably change things so that it doesn't
update there either.
The behavior on click-in-gutter-keep-left-down-then-move-mouse varies
a surprising amount between platforms. This implements the macOS
behavior where the scrubber follows the mouse direction while scrolling
by pages. (To be precise, it's the macOS behavior of Finder and Preview,
Safari has Windows's scrollbar behavior).
On Windows, the first click locks in the scroll direction and then
dragging the mouse off the scrubber in that direction makes the
scroll continue, but dragging it off the other direction has no effect.
I see no reason for that behavior.
Rather than disable and re-enable the timer, always keep it active
and make it do collision checks to decide if it should have an effect.
This is because set_automatic_scrolling_active(true) calls the
timeout callback immediately before starting the timer, and
when clicking the gutter this callback could disable the timer
again (if the first page scroll put the scrubber under the cursor).
Intead of making set_automatic_scrolling_active() work when it's
called reentrantly (which is easy: just swap the order of
on_automatic_scrolling_timer_fired() and timer->start() so that
on_automatic_scrolling_timer_fired() can immediately stop the
timer again, but it's confusing), make the timer check if it
should do anything.
This is keyed off m_last_mouse_position instead of
m_hovered_component because m_hovered_component is a visual state
and we arguably shouldn't modify it while the left mouse button
is down (as it indicated what part is activated on click).
Most callers of set_automatic_scrolling_active() also change
m_automatic_scrolling_kind, and it makes it possible to make timer
behavior dependent on the autoscroll kind later.
It's slightly less code, and m_scrubber_in_use is now set correctly
when shift-clicking, keeping the mouse button down, and then
dragging the throbber.
The shift-click brings the scrubber under the cursor, and then
the scrubber_rect().contains() condition is true and both scrubber
drags and shift-click-drags are handled the same naturally.
This patchset adds a few getters/setters to AbstractTableView to make
its looks more customisable:
- Header width & text alignment
- Default column width
- Ability to disable selected row highlighting
GUI::TabWidget has long has a TabPosition::Bottom option, but we still
rendered the tab buttons the same as TabPosition::Top.
This patch implements a custom look for bottom-side tabs. I've done my
best to match the look of the top-side ones, but there might be some
improvements we can make here. :^)
When a resize_aspect_ratio is specified, and window will only be resized
to a multiple of that ratio. When resize_aspect_ratio is set, windows
cannot be tiled.
We can't rely on a plain global WeakPtr during application teardown
since destruction order is not defined. Instead, use a NeverDestroyed
to hold the GUI::Application weak pointer. This way it will always
be reliable.
Fixes#3251.
Refactors the Calendar widget into LibGUI and updates the Calendar
app interface. Calendar widget lets layout engine manage most of
its geometry now and has a few new features like tile click
navigation, hover highlighting and a togglable year/month mode.
The Node API was obnoxiously requiring you to pass the model into it
all the time, simply because nodes could not find their way back to
the containing model. This patch adds a back-reference to the model
and simplifies the API.
I noticed that nothing actually applies the wallpaper on startup.
I wasn't sure where to put the responsibility, so I gave it to
the desktop mode file manager.
Also adds a save_config option to set_wallpaper so it doesn't
needlessly save the config.
Instead of SortingProxyModel having a column+order, we move that state
to AbstractView. When you click on a column header, the view tells the
model to resort the relevant column with the new order.
This is implemented in SortingProxyModel by simply walking all the
reified source/proxy mappings and resorting their row indexes.
We now create multiple levels of internal mappings between source
and proxy indexes, to support tree models.
This breaks selection update after resort, which we'll have to
deal with somehow.
This patch adds SortingProxyModel::less_than(ModelIndex, ModelIndex)
which is now used to implement the sort order. This allows you to
subclass SortingProxyModel if you want to tweak how sorting works.
Get rid of the awkward case sensitivity logic in SortingProxyModel
since that can now be done outside. Turns out nobody was actually
using it anyway, but it seems like something we will want to do
in the future someday.
Windows have an initial off-screen rect, so when a dialog is created and
shown before its parent window, in which it is centered, it would be
invisible to the user.
Fixes#3172.