mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-08 11:31:47 +00:00
docking: screen-reader resize values follow the column width on either edge
On a dock at the right edge the column handle passed accessibility values through the physical axis, so SetValue 300 gave width 180 and Increment shrank the column. ResizeHandle::reversed applies accessibility actions in value space; the pointer and arrow keys stay physical.
This commit is contained in:
1 parent
c084db9c78
commit
0781c48870
3 files changed
+41
-4
No files matched your search
@@ -539,3 +539,27 @@ fn a_dock_wider_than_the_window_shrinks_to_fit_and_resizes() {
|
||||
assert!(total < 800.0, "{total}");
|
||||
assert!((d.hit(&Hit::Divider(Divider::Column(1))).unwrap().center().x - (divider.x - 30.0)).abs() < 1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn screen_reader_values_follow_the_column_width_on_either_edge() {
|
||||
use egui::accesskit::{Action as A, ActionData, ActionRequest, TreeId};
|
||||
for (side, right_to_left) in [(Side::End, false), (Side::Start, true), (Side::Start, false)] {
|
||||
let mut d = testing::DockDriver::new(docked(side, &[&[&[2]]]), TestContent::default()).with_style(move |s| s.right_to_left = right_to_left);
|
||||
d.ctx.enable_accesskit();
|
||||
d.settle();
|
||||
let id = DockArea::<u32>::hit_id(d.id, &Hit::Divider(Divider::Column(2)));
|
||||
let request = |action, data| Event::AccessKitActionRequest(ActionRequest { action, target_tree: TreeId::ROOT, target_node: id.accesskit_id(), data });
|
||||
let case = format!("{side:?}, right to left {right_to_left}");
|
||||
let out = d.frame(vec![request(A::SetValue, Some(ActionData::NumericValue(300.0)))]);
|
||||
assert_eq!(out.actions, vec![Action::ResizeColumn { panel: 2, width: 300.0 }], "{case}");
|
||||
let out = d.frame(vec![request(A::Increment, None)]);
|
||||
assert_eq!(out.actions, vec![Action::ResizeColumn { panel: 2, width: 248.0 }], "{case}");
|
||||
// Arrow keys stay physical: right moves the divider right.
|
||||
d.ctx.memory_mut(|m| m.request_focus(id));
|
||||
d.frame(vec![]);
|
||||
let out = d.frame(vec![key(egui::Key::ArrowRight)]);
|
||||
let wider = d.hit(&Hit::Divider(Divider::Column(2))).unwrap().center().x < 400.0;
|
||||
let width = if wider { 248.0 } else { 232.0 };
|
||||
assert_eq!(out.actions, vec![Action::ResizeColumn { panel: 2, width }], "{case}");
|
||||
}
|
||||
}
|
||||
@@ -209,6 +209,7 @@ impl<P: Clone + Eq + Hash + Debug + Send + Sync + 'static> Renderer<'_, P> {
|
||||
self.handle_style(),
|
||||
)
|
||||
.value(width, lo..=hi)
|
||||
.reversed(inward < 0.0)
|
||||
.show(ui);
|
||||
self.register_interaction(ui.ctx(), response.response.id);
|
||||
let next = (width + inward * response.delta).clamp(lo, hi);
|
||||
|
||||
@@ -37,11 +37,12 @@ pub struct ResizeHandle<'a> {
|
||||
hit_margin: f32,
|
||||
step: f32,
|
||||
value: Option<(f32, RangeInclusive<f32>)>,
|
||||
reversed: bool,
|
||||
}
|
||||
|
||||
impl<'a> ResizeHandle<'a> {
|
||||
pub fn new(id: Id, axis: SplitAxis, rect: Rect, label: &'a str, style: ResizeHandleStyle) -> Self {
|
||||
Self { id, axis, rect, label, style, hit_margin: 3.0, step: 8.0, value: None }
|
||||
Self { id, axis, rect, label, style, hit_margin: 3.0, step: 8.0, value: None, reversed: false }
|
||||
}
|
||||
|
||||
/// Expand the hit rectangle along the movement axis, in logical points. Default: 3.
|
||||
@@ -63,6 +64,14 @@ impl<'a> ResizeHandle<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
/// The value grows against the axis, as for a column docked on the right edge that widens
|
||||
/// as its divider moves left. Accessibility actions then work on the value; the pointer
|
||||
/// and arrow keys stay physical, and `delta` stays along the axis.
|
||||
pub fn reversed(mut self, reversed: bool) -> Self {
|
||||
self.reversed = reversed;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn show(self, ui: &mut Ui) -> ResizeResponse {
|
||||
let hit = self.rect.expand2(match self.axis {
|
||||
SplitAxis::Horizontal => Vec2::new(self.hit_margin, 0.0),
|
||||
@@ -116,27 +125,30 @@ impl<'a> ResizeHandle<'a> {
|
||||
}
|
||||
});
|
||||
}
|
||||
let mut change = 0.0;
|
||||
ui.input_mut(|input| {
|
||||
input.consume_accesskit_action_requests(response.id, |request| match request.action {
|
||||
accesskit::Action::Increment => {
|
||||
delta += self.step;
|
||||
change += self.step;
|
||||
true
|
||||
}
|
||||
accesskit::Action::Decrement => {
|
||||
delta -= self.step;
|
||||
change -= self.step;
|
||||
true
|
||||
}
|
||||
accesskit::Action::SetValue => {
|
||||
if let (Some((value, range)), Some(accesskit::ActionData::NumericValue(new_value))) = (&self.value, &request.data)
|
||||
&& new_value.is_finite()
|
||||
{
|
||||
delta = (new_value.clamp(f64::from(*range.start()), f64::from(*range.end())) - f64::from(*value)) as f32;
|
||||
change = (new_value.clamp(f64::from(*range.start()), f64::from(*range.end())) - f64::from(*value)) as f32;
|
||||
delta = 0.0;
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
});
|
||||
});
|
||||
delta += if self.reversed { -change } else { change };
|
||||
}
|
||||
if !delta.is_finite() {
|
||||
delta = 0.0;
|
||||
|
||||
Reference in new issue
Block a user