Skip to content

Commit 09c571c

Browse files
committed
examples: Add example for custom AccessibleText implementations
1 parent 58d662d commit 09c571c

File tree

5 files changed

+148
-1
lines changed

5 files changed

+148
-1
lines changed

examples/Cargo.toml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ libloading = { version = "0.8.5", optional = true }
1515
im-rc = { version = "15", optional = true }
1616
async-channel = { version = "2.3", optional = true }
1717
tokio = { version = "1", features = ["full"], optional = true }
18-
reqwest = { version = "0.12", features = ["json", "rustls-tls"], default-features = false, optional = true }
18+
reqwest = { version = "0.12", features = [
19+
"json",
20+
"rustls-tls",
21+
], default-features = false, optional = true }
1922
serde = { version = "1.0", features = ["derive"], optional = true }
2023

2124
gtk.workspace = true
@@ -36,12 +39,18 @@ v4_6 = ["gtk/v4_6"]
3639
v4_10 = ["gtk/v4_10"]
3740
v4_12 = ["gtk/v4_12"]
3841
v4_14 = ["gtk/v4_14"]
42+
v4_16 = ["gtk/v4_16"]
3943

4044
[[bin]]
4145
name = "about_dialog"
4246
path = "about_dialog/main.rs"
4347
required-features = ["v4_6"]
4448

49+
[[bin]]
50+
name = "accessible_text"
51+
path = "accessible_text/main.rs"
52+
required_features = ["v4_16"]
53+
4554
[[bin]]
4655
name = "basics"
4756
path = "basics/main.rs"

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ cargo run --bin basics
1616

1717
- [Basic example](./basics/)
1818
- [About Dialog](./about_dialog/)
19+
- [Implementing the Accessible Text Interface](./accessible_text/)
1920
- [Using the Builder pattern](./builder_pattern/)
2021
- [Clipboard](./clipboard/)
2122
- [Clock example](./clock/)

examples/accessible_text/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Implementing the Accessible Text Interface
2+
3+
This example creates a custom text editing widget that implements the Accessible Text Interface. This interface is used for providing screen reader accessibility to custom widgets.
4+
5+
To test this implementation, enable the screen reader (Orca is enabled via Super+Alt+S) and edit / navigate the text.
6+
7+
The widget mostly just delegates its implementation to the parent `TextView`.

examples/accessible_text/main.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
mod text_view;
2+
3+
use gtk::{glib, prelude::*};
4+
use text_view::AccessibleTextView;
5+
6+
fn main() -> glib::ExitCode {
7+
let application = gtk::Application::builder()
8+
.application_id("com.github.gtk-rs.examples.accessible_text")
9+
.build();
10+
application.connect_activate(build_ui);
11+
application.run()
12+
}
13+
14+
fn build_ui(application: &gtk::Application) {
15+
let window = gtk::ApplicationWindow::new(application);
16+
17+
window.set_title(Some("Accessible Text Example"));
18+
window.set_default_size(260, 140);
19+
20+
let text_view: AccessibleTextView = glib::Object::new();
21+
window.set_child(Some(&text_view));
22+
23+
window.present();
24+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use gtk::glib;
2+
use gtk::subclass::prelude::*;
3+
4+
mod imp {
5+
use glib::GStr;
6+
use gtk::{graphene, ACCESSIBLE_ATTRIBUTE_OVERLINE, ACCESSIBLE_ATTRIBUTE_OVERLINE_SINGLE};
7+
8+
use super::*;
9+
10+
#[derive(Default)]
11+
pub struct AccessibleTextView {}
12+
13+
#[glib::object_subclass]
14+
impl ObjectSubclass for AccessibleTextView {
15+
const NAME: &'static str = "AccessibleTextView";
16+
type Type = super::AccessibleTextView;
17+
type ParentType = gtk::TextView;
18+
type Interfaces = (gtk::AccessibleText,);
19+
}
20+
21+
impl ObjectImpl for AccessibleTextView {}
22+
impl WidgetImpl for AccessibleTextView {}
23+
impl AccessibleTextImpl for AccessibleTextView {
24+
fn attributes(
25+
&self,
26+
offset: u32,
27+
) -> Vec<(gtk::AccessibleTextRange, glib::GString, glib::GString)> {
28+
let attributes = self.parent_attributes(offset);
29+
println!("attributes({offset}) -> {attributes:?}");
30+
attributes
31+
}
32+
33+
fn caret_position(&self) -> u32 {
34+
let pos = self.parent_caret_position();
35+
println!("caret_position() -> {pos}");
36+
pos
37+
}
38+
39+
fn contents(&self, start: u32, end: u32) -> Option<glib::Bytes> {
40+
let content = self.parent_contents(start, end);
41+
println!(
42+
"contents({start}, {end}) -> {:?}",
43+
content
44+
.as_ref()
45+
.map(|c| std::str::from_utf8(c.as_ref()).unwrap())
46+
);
47+
content
48+
}
49+
50+
fn contents_at(
51+
&self,
52+
offset: u32,
53+
granularity: gtk::AccessibleTextGranularity,
54+
) -> Option<(u32, u32, glib::Bytes)> {
55+
let contents = self.parent_contents_at(offset, granularity);
56+
println!(
57+
"contents_at offset({offset}, {granularity:?}) -> {:?}",
58+
contents
59+
.as_ref()
60+
.map(|(s, e, c)| (s, e, std::str::from_utf8(c.as_ref()).unwrap()))
61+
);
62+
contents
63+
}
64+
65+
fn default_attributes(&self) -> Vec<(glib::GString, glib::GString)> {
66+
let mut attrs = self.parent_default_attributes();
67+
68+
// Attributes can be added and removed
69+
attrs.push((
70+
ACCESSIBLE_ATTRIBUTE_OVERLINE.to_owned(),
71+
ACCESSIBLE_ATTRIBUTE_OVERLINE_SINGLE.to_owned(),
72+
));
73+
println!("default_attributes() -> {attrs:?}");
74+
attrs
75+
}
76+
77+
fn selection(&self) -> Vec<gtk::AccessibleTextRange> {
78+
let selection = self.parent_selection();
79+
println!("selection() -> {selection:?}");
80+
selection
81+
}
82+
83+
fn extents(&self, start: u32, end: u32) -> Option<graphene::Rect> {
84+
let extents = self.parent_extents(start, end);
85+
println!("extents({start}, {end}) -> {extents:?}");
86+
extents
87+
}
88+
89+
fn offset(&self, point: &graphene::Point) -> Option<u32> {
90+
let offset = self.parent_offset(point);
91+
println!("offset({:?}) -> {offset:?}", point);
92+
offset
93+
}
94+
}
95+
96+
impl TextViewImpl for AccessibleTextView {}
97+
impl AccessibleTextView {}
98+
}
99+
100+
glib::wrapper! {
101+
pub struct AccessibleTextView(ObjectSubclass<imp::AccessibleTextView>)
102+
@extends gtk::Widget, gtk::TextView,
103+
@implements gtk::Accessible, gtk::AccessibleText, gtk::Buildable, gtk::ConstraintTarget, gtk::Scrollable;
104+
}
105+
106+
impl AccessibleTextView {}

0 commit comments

Comments
 (0)