I had forgotten why I had `self::image::Image` and it was causing the
docs to show up out of order. This now makes them all consisent, fixing
the docs issue.
This was a holdover while I was still implementing the PlatformWindow
interface. Cushy widgets shouldn't be able to access winit directly,
otherwise they could cause unwanted effects when not running in a
standalone Cushy app but rather embedded in a game.
Currently passing the entire input area because it's easy. Not closing
the issue because the correct thing to do would be to constrain the
location to a smaller area on the current line (or the current line).
Refs #122
While working on the changelog, I realized I didn't provide a type that
allowed a third party developer to provide a
PlatformWindowImplementation. This type now completes it.
This commit adds my first take at creating a harness for a user's guide
using the new capture functionality. The example has tests that ensure
the align widget creates the expected results.
Somehow I missed that my changes for weak callbacks broke the theme
editor. I thought I had it working with the try_get changes, but I
discovered several flaws in this approach.
In the end, ownership has been transferred to the CallbackHandle, and a
CallbackHandle can relinquish its reference to create weak graphs. This
is how weak_clone now works.
This ensures frames render consistently.
This change only affects the animation recorder. The regular virtual
recorder interface blocks when refresh is called.
Closes#98
This finishes my initial refactoring of the dynamic system to add
support for several dataflows including:
- Pure data sources that can be implemented using an `Owned<T>` at the
root of a graph of `Dynamic<U>`/`DynamicReader<U>`s.
- Read-only data sinks. I thought this would be more useful across other
widgets, but in general, Progress and Label seem like the only types
that this applies to currently.
- The ability to mix/match Dynamic/DynamicReader in tuple-based
for_each/map_each.
For some reason I forgot about 1.0 being an edge case, but I also didn't
think about negatives either. Applying a clamp is the right move here.
Refs #120
Refs #98
This refactor overhauls the reactive system to move all the reactive
methods to traits. The side effect of this change is that now
DynamicReader's API is the same as Dynamic's API, but because it only
implements Source<T>, DynamicReader does not offer any mutation
functions.
While it's unfortunate to have more traits to include to use Cushy, this
seems like the best option, and it offers a path to try to integrate
this into the tuple ForEach/MapEach traits. Unfortunately, my attempt at
doing those in this set of changes led to issues specifying generic
associated lifetimes for the DynamicGuard. But, I was also in the middle
of this larger refactoring, so it might be that a fresh attempt will
succeed.
After adding weak_clone, I realized that all map functions should use
weak references anyways. In the process of implementing this, I ran
tests a lot and found other edge cases where I hadn't properly reasoned
about Drop behavior.
While some of the state cleanup is a bit overkill at the moment, this is
in anticipation of wanting a WeakDynamicReader-like type.
The animation doctest randomly failed on me this morning, and I isolated
it to the order of the two mutexes. There's no reason to hold the
deadlock mutex for more than the check for deadlock, so I switched which
mutex the condvar is synchronizing using to ensure that another thread
couldn't cause a deadlock by dropping a DynamicMutexGuard while the
block_until_updated thread is performing its state check.
There was a small window between when notify_all and the strong count
for the Arc is decreased that a DynamicReader could observe the strong
count still being greater than the reader count, but the drop thread
just hasn't proceeded far enough.
Now the on_disconnect is stored in an option, and its presence denotes
that the disconnect logic has not fired yet. DynamicReader now checks
on_disconnect in addition to the strong count.
This cascaded into a lot more work than expected. However, in general,
if one clones a `WidgetInstance` and shares it between two windows, it
should now work. Widget authors must ensure that when they cache
information, they do so with either a `WidgetCacheKey` or use a
`WindowLocal<T>` if per-window state is desired.
This is demonstrated in the debug-window example, where the counter of
open windows is next to a clone of the same button from the main window
that opens a new window.
While this was a workaround for a docs.rs issue (Px/Lp are not
linked), I decided having the shorter import path would look better in
the examples.
It probably wasn't necessary to update all of the references in the
internal code, but I decided it was worth the consistency.
Closes#112
This removes the last manual byte change I can find. While what the user
reported was that this was causing incorrect selection, using the arrow
keys when in this situation could lead to a panic, because the offset
was not a valid character offset.
Closes#91
There's some details to still figure out, which are in new issues:
- #109: When opening a window, no handle is returned that gives access to the
window from the opener. Technically this can all be wired up manually,
with exception of requeesting the window close.
- #107: How can a window close itself? Once we have a handle type, we still
need a mechanism to allow a button on a window request that the window
closes gracefully. The examples that currently close the window
call exit instad.
This sounds like a regression, but it was masking a "race condition".
DynamicGuard runs the change callbacks on drop in a background thread.
Validations was using the guard to not have to lock twice.
This led to an issue where the invalid count might be non-zero due to
the callbacks not being invoked, preventing the closure from being
invoked even though there are no validation errors.
Introducing compare_swap gives a higher-level API for Validations to
use, and it also ensures the callbacks are able to be run in the current
thread.
The Container code was causing small rounding errors when laying out
that would cause the layout to sometimes me larger by a pixel. I
searched for all locations we are applying padding and added rounding
calls.
Refs #92
This adds upon the work in #94 by allowing the dynamic's value to be set
and it cause the window size to change.
I've ordered the resizing operations so that changes to the property are
prioritized over automatic adjustments. This doesn't change the behavior
for automatic adjustments in any way.
Closes#97
There was a potential race condition described in #97 that I realized I
had seen occasionally when interacting with an element that was
currently being animated. These were in complex situations, so I thought
I had a situation that could have legitimately caused the warning.
However, this warning is preventing a very specific coding "error", and
that program did not have it. The existing implementation would
potentially prevent one thread's change from invoking its callbacks
because another thread was already executing its callbacks.
This change moves that state into a Mutex/Condvar pair that allows
detecting reentry while allowing other threads to block until its their
turn. When it becomes their turn, they can check whether the callbacks
were invoked with the current value or not to prevent callbacks from
being invoked in quick succeession with the same value by multiple
threads.
Realized that I was skipping invisible glyphs during construction of
MeasuredText. Once those were in, most of the issues vanished. A few
small tweaks and now it works surprisingly well.
- Blur no longer expands the shadow geometry, but instead is clamped to
avoid overlapping drawing calls.
- Overlay now handles hit tests correctly with regards to the original
relative widget.
- Align was using an Into conversion that wasn't actually correct,
causing the contents to not actually get aligned in some situations.
Rather than clip or cause shadows to be weirdly shaped, the shape is
adjusted if the blur radius is too large for the given geometry. This
ensures the shadows always draw correctly, but it also forces shadows to
render their full blur + spread gradients.
Font families are now cached. There probably should be a mechanism to
refresh the cache, but we don't currently have a "signal" to notify us
when a font is installed. Presumably, this could be something that
fontdb would eventually add, rather than us building our own.
Closes#48
- On Linux, `fm-match` is used to query for the default fonts.
- DynamicComponents now have their own trait and can now be specified
with a constant or dynamic.
- Roboto Flex is now always loaded when the feature is enabled.
Overriding the default sans serif font prefers the overridden value,
then roboto, then the result of fc-match/fontdb's default.
- Button now supports background colors being set on a transparent
button.