Refactor node mutation (again)
This commit is contained in:
parent
18ccf1fd10
commit
49bbcf9b2e
5 changed files with 32 additions and 42 deletions
|
@ -158,19 +158,8 @@ impl ContextImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
fn mutate_accesskit_node(
|
fn accesskit_node(&mut self, id: Id, parent_id: Option<Id>) -> &mut accesskit::Node {
|
||||||
&mut self,
|
let update = self.output.accesskit_update.as_mut().unwrap();
|
||||||
id: Id,
|
|
||||||
parent_id: Option<Id>,
|
|
||||||
f: impl FnOnce(&mut accesskit::Node),
|
|
||||||
) {
|
|
||||||
let update = match &mut self.output.accesskit_update {
|
|
||||||
Some(update) => update,
|
|
||||||
None => {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let nodes = &mut update.nodes;
|
let nodes = &mut update.nodes;
|
||||||
let node_map = &mut self.frame_state.accesskit_nodes;
|
let node_map = &mut self.frame_state.accesskit_nodes;
|
||||||
let index = node_map.get(&id).copied().unwrap_or_else(|| {
|
let index = node_map.get(&id).copied().unwrap_or_else(|| {
|
||||||
|
@ -184,7 +173,7 @@ impl ContextImpl {
|
||||||
parent.children.push(accesskit_id);
|
parent.children.push(accesskit_id);
|
||||||
index
|
index
|
||||||
});
|
});
|
||||||
f(Arc::get_mut(&mut nodes[index].1).unwrap());
|
Arc::get_mut(&mut nodes[index].1).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,9 +484,9 @@ impl Context {
|
||||||
// Make sure anything that can receive focus has an AccessKit node.
|
// Make sure anything that can receive focus has an AccessKit node.
|
||||||
// TODO(mwcampbell): For nodes that are filled from widget info,
|
// TODO(mwcampbell): For nodes that are filled from widget info,
|
||||||
// some information is written to the node twice.
|
// some information is written to the node twice.
|
||||||
self.mutate_accesskit_node(id, None, |node| {
|
if let Some(mut node) = self.accesskit_node(id, None) {
|
||||||
response.fill_accesskit_node_common(node);
|
response.fill_accesskit_node_common(&mut node);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let clicked_elsewhere = response.clicked_elsewhere();
|
let clicked_elsewhere = response.clicked_elsewhere();
|
||||||
|
@ -1586,19 +1575,20 @@ impl Context {
|
||||||
|
|
||||||
/// ## Accessibility
|
/// ## Accessibility
|
||||||
impl Context {
|
impl Context {
|
||||||
/// Create an AccessKit node with the specified ID if one doesn't already
|
/// If AccessKit support is active for the current frame, get or create
|
||||||
/// exist, then call the provided function with a mutable reference
|
/// a node with the specified ID and return a mutable reference to it.
|
||||||
/// to the node. Node that the `parent_id` parameter is ignored if the node
|
/// `parent_id is ignored if the node already exists.
|
||||||
/// already exists. If AccessKit isn't active for this frame, this method
|
|
||||||
/// does nothing.
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
pub fn mutate_accesskit_node(
|
pub fn accesskit_node(
|
||||||
&self,
|
&self,
|
||||||
id: Id,
|
id: Id,
|
||||||
parent_id: Option<Id>,
|
parent_id: Option<Id>,
|
||||||
f: impl FnOnce(&mut accesskit::Node),
|
) -> Option<RwLockWriteGuard<'_, accesskit::Node>> {
|
||||||
) {
|
let ctx = self.write();
|
||||||
self.write().mutate_accesskit_node(id, parent_id, f);
|
ctx.output
|
||||||
|
.accesskit_update
|
||||||
|
.is_some()
|
||||||
|
.then(move || RwLockWriteGuard::map(ctx, |c| c.accesskit_node(id, parent_id)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether AccessKit is active for the current frame.
|
/// Returns whether AccessKit is active for the current frame.
|
||||||
|
|
|
@ -529,17 +529,17 @@ impl Response {
|
||||||
self.output_event(event);
|
self.output_event(event);
|
||||||
} else {
|
} else {
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
self.ctx.mutate_accesskit_node(self.id, None, |node| {
|
if let Some(mut node) = self.ctx.accesskit_node(self.id, None) {
|
||||||
self.fill_accesskit_node_from_widget_info(node, make_info());
|
self.fill_accesskit_node_from_widget_info(&mut node, make_info());
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn output_event(&self, event: crate::output::OutputEvent) {
|
pub fn output_event(&self, event: crate::output::OutputEvent) {
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
self.ctx.mutate_accesskit_node(self.id, None, |node| {
|
if let Some(mut node) = self.ctx.accesskit_node(self.id, None) {
|
||||||
self.fill_accesskit_node_from_widget_info(node, event.widget_info().clone());
|
self.fill_accesskit_node_from_widget_info(&mut node, event.widget_info().clone());
|
||||||
});
|
}
|
||||||
self.ctx.output().events.push(event);
|
self.ctx.output().events.push(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,9 +606,9 @@ impl Response {
|
||||||
/// Associate a label with a control for accessibility.
|
/// Associate a label with a control for accessibility.
|
||||||
pub fn labelled_by(self, id: Id) -> Self {
|
pub fn labelled_by(self, id: Id) -> Self {
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
self.ctx.mutate_accesskit_node(self.id, None, |node| {
|
if let Some(mut node) = self.ctx.accesskit_node(self.id, None) {
|
||||||
node.labelled_by.push(id.accesskit_id());
|
node.labelled_by.push(id.accesskit_id());
|
||||||
});
|
}
|
||||||
#[cfg(not(feature = "accesskit"))]
|
#[cfg(not(feature = "accesskit"))]
|
||||||
{
|
{
|
||||||
let _ = id;
|
let _ = id;
|
||||||
|
|
|
@ -541,7 +541,7 @@ impl<'a> Widget for DragValue<'a> {
|
||||||
response.widget_info(|| WidgetInfo::drag_value(value));
|
response.widget_info(|| WidgetInfo::drag_value(value));
|
||||||
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
ui.ctx().mutate_accesskit_node(response.id, None, |node| {
|
if let Some(mut node) = ui.ctx().accesskit_node(response.id, None) {
|
||||||
use accesskit::Action;
|
use accesskit::Action;
|
||||||
// If either end of the range is unbounded, it's better
|
// If either end of the range is unbounded, it's better
|
||||||
// to leave the corresponding AccessKit field set to None,
|
// to leave the corresponding AccessKit field set to None,
|
||||||
|
@ -585,7 +585,7 @@ impl<'a> Widget for DragValue<'a> {
|
||||||
let value_text = format!("{}{}{}", prefix, value_text, suffix);
|
let value_text = format!("{}{}{}", prefix, value_text, suffix);
|
||||||
node.value = Some(value_text.into());
|
node.value = Some(value_text.into());
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
|
@ -740,7 +740,7 @@ impl<'a> Slider<'a> {
|
||||||
response.widget_info(|| WidgetInfo::slider(value, self.text.text()));
|
response.widget_info(|| WidgetInfo::slider(value, self.text.text()));
|
||||||
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
ui.ctx().mutate_accesskit_node(response.id, None, |node| {
|
if let Some(mut node) = ui.ctx().accesskit_node(response.id, None) {
|
||||||
use accesskit::Action;
|
use accesskit::Action;
|
||||||
node.min_numeric_value = Some(*self.range.start());
|
node.min_numeric_value = Some(*self.range.start());
|
||||||
node.max_numeric_value = Some(*self.range.end());
|
node.max_numeric_value = Some(*self.range.end());
|
||||||
|
@ -753,7 +753,7 @@ impl<'a> Slider<'a> {
|
||||||
if value > *clamp_range.start() {
|
if value > *clamp_range.start() {
|
||||||
node.actions |= Action::Decrement;
|
node.actions |= Action::Decrement;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
let slider_response = response.clone();
|
let slider_response = response.clone();
|
||||||
|
|
||||||
|
|
|
@ -665,7 +665,7 @@ impl<'t> TextEdit<'t> {
|
||||||
let parent_id = response.id;
|
let parent_id = response.id;
|
||||||
for (i, row) in galley.rows.iter().enumerate() {
|
for (i, row) in galley.rows.iter().enumerate() {
|
||||||
let id = parent_id.with(i);
|
let id = parent_id.with(i);
|
||||||
ui.ctx().mutate_accesskit_node(id, Some(parent_id), |node| {
|
if let Some(mut node) = ui.ctx().accesskit_node(id, Some(parent_id)) {
|
||||||
node.role = Role::InlineTextBox;
|
node.role = Role::InlineTextBox;
|
||||||
let rect = row.rect.translate(text_draw_pos.to_vec2());
|
let rect = row.rect.translate(text_draw_pos.to_vec2());
|
||||||
node.bounds = Some(accesskit::kurbo::Rect {
|
node.bounds = Some(accesskit::kurbo::Rect {
|
||||||
|
@ -717,10 +717,10 @@ impl<'t> TextEdit<'t> {
|
||||||
node.character_positions = Some(character_positions.into());
|
node.character_positions = Some(character_positions.into());
|
||||||
node.character_widths = Some(character_widths.into());
|
node.character_widths = Some(character_widths.into());
|
||||||
node.word_lengths = word_lengths.into();
|
node.word_lengths = word_lengths.into();
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.ctx().mutate_accesskit_node(parent_id, None, |node| {
|
if let Some(mut node) = ui.ctx().accesskit_node(parent_id, None) {
|
||||||
if let Some(cursor_range) = &cursor_range {
|
if let Some(cursor_range) = &cursor_range {
|
||||||
let anchor = &cursor_range.secondary.rcursor;
|
let anchor = &cursor_range.secondary.rcursor;
|
||||||
let focus = &cursor_range.primary.rcursor;
|
let focus = &cursor_range.primary.rcursor;
|
||||||
|
@ -737,7 +737,7 @@ impl<'t> TextEdit<'t> {
|
||||||
}
|
}
|
||||||
|
|
||||||
node.default_action_verb = Some(accesskit::DefaultActionVerb::Focus);
|
node.default_action_verb = Some(accesskit::DefaultActionVerb::Focus);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditOutput {
|
TextEditOutput {
|
||||||
|
|
Loading…
Reference in a new issue