Previously, the set Comparator behaved the same way, regardless of the
value of columnFirst. This is incorrect; the set should be sorted such
that the final item in the set has the greatest cross-dimension.
There was also an off-by-one error in the result of
getHighestCrossDimension(). The highestCrossDimension data member is
exclusive, but the cell values in the occupiedCells set are inclusive.
We need to add 1 to the maximum cell cross-dimension in order to convert
it to an exclusive value.
For some transforms, the program could get stuck in the following loop:
- The content component emits a resized/moved notification, leading to
the initial call to Viewport::updateVisibleArea.
- New positions are computed for the viewport scrollbars, and scrollbar
listeners are notified synchronously that the scrollbars have been
updated.
- The viewport itself listens to the scrollbars, so it receives a
notification and updates the position of the content component.
- The scrollbar position (quantised to an integer) resolves to a
component position (also quantised to an integer) that differs from
the existing position, so the new position is applied.
- The viewport now attempts to set the scrollbars to the correct
position in response, and notifies listeners that the scrollbars
have moved...
Normally, the recursion would exit at the point where the component position
is set to its current position. If we're unlucky, though, converting
from view pos to scrollbar pos, then scrollbar pos back to view pos may
result in a view pos that differs from the original value.
This fix adds a new exit condition from the recursion. On receiving a
scrollbar move notification, we check whether the scrollbar position
computed from the current view position matches the incoming scrollbar
position. If it does, there's no need to compute and apply a new view
position from the incoming scrollbar position.
One issue affected the situation where the provided bounds wouldn't
start at (0, 0). Such bounds are regularly acquired by calling
Rectangle::reduced().
The other issue affected the width calculation of fractional items.
The error wasn't correctly integrated during the computation, and as a
consequence the last fractional element would exhibit all the
accumulated error.
Prior to this commit all Grid calculations were carried out using
floating point numbers. The dimensions of all items would then be
rounded with the same function to calculate the integer dimensions used
for Component layout. This resulted in layout solutions where the width
or height of items with dimensions specified using the absolute Px
quantity could differ from the correctly rounded value of these values.
This commit ensures that the width and height of these items are always
correct and their cumulative error in size is distributed among items
with fractional dimensions.
- Created a new detail namespace
- Moved shared module implementation details into the detail namespace
- Split dependencies so source files only rely on details in the detail namespace
- Removed all code from the juce_gui_basics.cpp file
Until this commit Items with a size of 1 could be rounded to
bounds with a size of 0 or 2 due to floating point errors, leading
to slightly too large or disappearing items. The new approach
preserves the size of items.
An animated drag operation will now stop if the user interacts with
the content area again before the animation is finished. It is also
stopped if the user interacts with the scrollbars.
Previously, positioning such an item would hang while trying to find an
appropriate position for the item, because no position in the grid was
suitable, and implicit cells in the layout direction would be added
until a viable position was found.
We now ensure that there are enough cells in the cross direction to hold
each of the auto-placement items before trying to position those items.
The TextHolderComponent and Viewport::componentHolder don't have any
accessible semantics, so they shouldn't be included in the accessible
component hierarchy.
Some Windows 11 devices have both touch screens and mouse inputs, and
these can be used simultaneously.
The Viewport (and ListBox) now check the input source of each mouse
down. If the source is not a mouse, the viewport will always enter
drag-to-scroll mode, regardless of the result of isScrollOnDragEnabled.
Negative indices should count backwards from the last explicit
row/column number. If the resulting line number would appear before
the first explicit row/column, implicit grid lines should be added
before the first explicit row/column.
Previously, a touch on a component outside the Viewport would interrupt
and cancel a scroll gesture inside the Viewport.
Now, the Viewport will respond to all drag events from the input source
that started the drag, allowing the Viewport to be scrolled with one
input source while adjusting other controls with another input source.
The FontsDemo is useful for testing this behaviour, as it has two
Viewports on a single screen, along with some other controls.