Dominik Csapak [Tue, 13 Aug 2024 11:42:11 +0000 (13:42 +0200)]
widget: data table: simplify cursor selection
we don't have to check for ctrl here, since just before we clear the
selection if we didn't have ctrl pressed, so `toggle` does the
same as `select` here in that case. Also, this makes it possible
to deselect rows with the simple selection mode.
Dominik Csapak [Tue, 13 Aug 2024 11:42:13 +0000 (13:42 +0200)]
widget: data table: improve checkbox clicking in selection column
by;
* moving the click handler on the whole cell instead of the tiny
checkbox icon
* stopping propagation, this makes it actually work, since otherwise
the row would get clicked and it resulted in the usual 'select only
this row' behavior
Dominik Csapak [Tue, 13 Aug 2024 11:42:10 +0000 (13:42 +0200)]
state: selection: handle multiselect change more gracefully
instead of keeping the respective state, try to be smart about it:
* when changing to multiselect, keep the selection
* when changing from multiselect, clear the map, but keep the selection
if there was only one
otherwise it's possible to let the spinner running by
* pressing the mouse button on the spinner
* moving the cursor outside of the spinner
* letting go
this is a helper struct to better handle focusin/out events.
We had the pattern with DelayedFocusChange in a few components, and they
were basically all doing the same.
To factor out, we have to use a bit of a different approach (see the
comment on the struct itself), since we don't want to introduce an extra
component in the component tree for this (since nothing is really
rendered for that).
It's not saving us much code for now, but with every new component
needing that, we can make sure we have the same behavior.
widget: number field: add spinner repeat behaviour
instead of reacting to each click, react to pointerdown/up
and implement a very basic repeat logic, so that the value
de/increments repeatedly when keep pressing the up/down buttons
widget: dropdown: fix non-editable cursor with renderer
when we have a 'rendered' value, the component tree is different, and
we have to put the 'non-editable' class one level higher for it to have
an effect
this is used with a ContextProvider to provide a visibility information
to children elements, without the need to 'prop drill'.
Currently only used by a selection view, but could be used by all
elements that cache child elements that only show/hide them instead
of letting the dom change.
When using in a generic widget/etc, should react to higher level
visibility contexts.
'Parse number failed' implies that we could not parse the number, but to
know it was too big, we had to parse the number correctly, so this is
confusing. Replacing with 'Input invalid' makes it clearer that what
is actually happening.
widget: number field: prevent invalid settings with scroll/keyboard
By don't in/decreasing the value if it's over the max/under the min
value. To insert a value when scrolling/keyboard even if none was set,
introducing a 'clamp_value' trait fn that simply forwards to the
underlying clamp with T::MIN and T::MAX as defaults. This is then used
to determine the initial value that is set.
until now we used a modal dialog for the picker. While had some
advantages for focus/keyboard handling, it made it impossible to have
and 'editable' field while having the dialog open.
So instead, use a non-modal dialog and rework the focus/keyboard handling
to work as expected.
The biggest change here is how keyboard uses can navigate it:
instead of being 'captured' in the picker once it's open, using
tab/shift+tab simply closes the picker should the focus go outside the
current field
With this changes, having an editable dropdown works as expected, the
field gets the focus by default, the picker remains open until it's
closed or the widget loses focus, and one can open/close the picker
manually with the keyboard or trigger.
by adding a 'show_dialog' binding. For this to work correctly in all
situations, we have to adapt the align code to distinguish between modal
and non-modal dialogs, so we set a custom attribute on the dom element
when opening.
but only when the field is
* not editable (then the user can simply delete the value)
* not disabled (no input possible)
* not empty (nothing to clear)
* not required (empty field is not allowed)
previously we needed two css files per theme, one each for dark and
light mode. We now can make use of only one css file per theme by
setting the respective class on the root element.
Change the theme loader to do that, and change all examples to that as
well.
Dominik Csapak [Fri, 28 Jun 2024 08:50:10 +0000 (10:50 +0200)]
widget: data table: fix lost focus on scroll
when we selected a row/cell and scrolled away so that the element was
not in the dom, we lost focus and subsequent keypresses scrolled the
view, but did not select the next/previous element.
To fix that, we have to catch this case by checking if the element
behind the cursor still is in the visible range, and if not and there
was no new focus target, we refocus the scroll view.
This way we get the key press events again for the table.
Dominik Csapak [Fri, 28 Jun 2024 08:50:09 +0000 (10:50 +0200)]
widget: data table: don't scroll cursor into view when the data changes
in case we have a reloading table, we don't want to jump to the selected
row every time, since this is rather jarring when navigating big lists
that regularly refresh.
Dominik Csapak [Fri, 28 Jun 2024 08:50:08 +0000 (10:50 +0200)]
widget: data table: fix scroll position when items vanish
in case we're scrolled far down a list of elements, and items are
vanishing so that we're now outside the list, reduce the start so
we're now at the end of the list.
Dominik Csapak [Mon, 24 Jun 2024 10:25:52 +0000 (12:25 +0200)]
widget: data table: fix keyboard focus regression
our recent change from `cell_class` to `cell_configuration` broke
keyboard navigation for tables, since the `tabindex` (among others)
attribute was missing on the cells.
To fix this, write a method to add attributes from other attributes, for
the WidgetStdProps, and use that for the cell_configuration instead of
overwriting the existing ones.
Dominik Csapak [Fri, 21 Jun 2024 12:20:01 +0000 (14:20 +0200)]
tree wide: adapt to new margin/padding system
by
* replacing hardcoded padding/margin classes with the builder equivalent
* for indentation we can now simply use multiplication, so we have e.g.
one element for indent level 2 with double the padding instead of
two elements with one level of padding each
* the inputpanel now uses the 'set_style' method instead of extracting
and inserting the style attribute manually
Dominik Csapak [Fri, 21 Jun 2024 12:19:59 +0000 (14:19 +0200)]
widget: data table: replace 'cell_class' with 'cell_configuration'
instead of only allowing to set the classes of cells, we create a new
`CellConfiguration` struct that holds classes, styles, and attributes
which can be configured for the data table cells
this allows us to use the builder style patterns for cells instead
of using hardcoded classes
This also integrates the attributes from the `DataTableCellRenderArgs`
so all of the cell html config is one place
This also adds a 'set_style' method on the `DataTableCellRenderArgs`
Dominik Csapak [Fri, 21 Jun 2024 12:19:57 +0000 (14:19 +0200)]
props: margin: implement new css variable based system
instead of relying on the sass to generate a few hardcoded
classes for consistent padding, have one class in css (for each
side/axis) and use a css variable for the factor to multiply
advantages are that we now have 'unlimited' margin levels
but depends on css variables.
for that to work, we now require the struct to also implement
`AsCssStylesMut` so we can set the variable value in the style directly
Dominik Csapak [Thu, 20 Jun 2024 07:18:31 +0000 (09:18 +0200)]
widget: dialog: use CssStyles for style and implement WidgetStyleBuilder
so we can easily use the 'style'/'width'/etc. builder methods for it
adapt the call sites of dialog to use the new builder methods since
the old 'style' method does not work anymore.
Dominik Csapak [Thu, 20 Jun 2024 07:18:28 +0000 (09:18 +0200)]
props: add WidgetStyleBuilder trait
for having 'style' and 'set_style' functions on components that have
a WidgetBuilder already, makes it easier to set the style of
components, so instead of writing:
making it much more obvious what is happening and easier if setting
multiple styles.
This also adds a shorthand for width and height, with a custom
CssLength enum that represents different css length units
and defaults to px if only a number is given
The CssStyles struct is there to hold the styles and generate the final
attribute string to use in components.
It implements a From trait for AsRef<str>, but that implmenetation is
not fully html/css spec conform as it leaves out some unused syntax.
Dominik Csapak [Tue, 18 Jun 2024 08:46:56 +0000 (10:46 +0200)]
widget: return `Row` from (error_)message instead of Html
with `Row` we are much more flexible, e.g. we can use all
builder style functions for classes/padding/margin/etc. and the only
downside is that sometimes we have to do an `.into()` to convert to Html
And even that is not always necessary since arguments of functions often
take something like: `Into<Html>` which `Row` implements.
Dominik Csapak [Tue, 18 Jun 2024 08:46:54 +0000 (10:46 +0200)]
widget: data table: disable last enabled column
when deselecting columns, we don't want the user to deselect the last
one, since it's not possible to show a menu anymore to reselect any
column.
the only exception currently is when the column has the menu disabled.
we probably don't want to count such columns as 'active' for selection
purposes, but we currently don't have that information here.
Dominik Csapak [Tue, 18 Jun 2024 08:46:53 +0000 (10:46 +0200)]
widget: mini scroll: simply scroll code for mouse scrolling
instead of trying to always have 10 scroll steps for the whole area,
simply scroll the amount the browser gives us, just horizontally instead
of vertically. This gives a more 'native' feel for the scrolling
behavior, regardless if there is a large or small scroll area.
Dominik Csapak [Wed, 20 Dec 2023 12:27:07 +0000 (13:27 +0100)]
tooltip: fix wrong html generation
it seems the keys here are not enough for yew to determine which item is
which, but changing to a container with an 'optional_child' is, so
change to that