Skip to content

Commit 3909afb

Browse files
felinirabilelmoussaoui
authored andcommitted
examples: Add example for custom AccessibleText implementations
1 parent e3a4199 commit 3909afb

File tree

5 files changed

+144
-1
lines changed

5 files changed

+144
-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 = glib::Object::new::<AccessibleTextView>();
21+
window.set_child(Some(&text_view));
22+
23+
window.present();
24+
}

examples/accessible_text/text_view.rs

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

0 commit comments

Comments
 (0)