mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 10:50:00 +00:00
Expose element type names and ids in Rust and C++
This commit is contained in:
parent
4eef2d4936
commit
a752851d0f
5 changed files with 191 additions and 75 deletions
|
@ -23,7 +23,7 @@ inline void init()
|
|||
/// Use find_by_accessible_label() to obtain all elements matching the given accessible label.
|
||||
class ElementHandle
|
||||
{
|
||||
cbindgen_private::ItemWeak inner;
|
||||
cbindgen_private::ElementHandle inner;
|
||||
|
||||
public:
|
||||
/// Find all elements matching the given accessible label.
|
||||
|
@ -39,7 +39,7 @@ public:
|
|||
SharedVector<ElementHandle> result;
|
||||
cbindgen_private::slint_testing_element_find_by_accessible_label(
|
||||
&vrc, &label_view,
|
||||
reinterpret_cast<SharedVector<cbindgen_private::ItemWeak> *>(&result));
|
||||
reinterpret_cast<SharedVector<cbindgen_private::ElementHandle> *>(&result));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -56,17 +56,63 @@ public:
|
|||
SharedVector<ElementHandle> result;
|
||||
cbindgen_private::slint_testing_element_find_by_element_id(
|
||||
&vrc, &element_id_view,
|
||||
reinterpret_cast<SharedVector<cbindgen_private::ItemWeak> *>(&result));
|
||||
reinterpret_cast<SharedVector<cbindgen_private::ElementHandle> *>(&result));
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Returns true if the underlying element still exists; false otherwise.
|
||||
bool is_valid() const { return private_api::upgrade_item_weak(inner).has_value(); }
|
||||
bool is_valid() const { return private_api::upgrade_item_weak(inner.item).has_value(); }
|
||||
|
||||
/// Helper struct for use with element_type_names_and_ids() to describe an element's type name
|
||||
/// and qualified id;
|
||||
struct ElementTypeNameAndId
|
||||
{
|
||||
/// The type name this element instantiates, such as `Rectangle` or `MyComponent`
|
||||
SharedString type_name;
|
||||
/// The id of the element qualified with the surrounding component.
|
||||
SharedString id;
|
||||
|
||||
friend bool operator==(const ElementTypeNameAndId &lhs,
|
||||
const ElementTypeNameAndId &rhs) = default;
|
||||
};
|
||||
|
||||
/// Returns a vector over a struct of element type names and their ids. Returns an empty vector
|
||||
/// if the element is not valid anymore.
|
||||
///
|
||||
/// Elements can have multiple type names and ids, due to inheritance.
|
||||
/// In the following example, the `PushButton` element returns for `element_type_names_and_ids`
|
||||
/// the following ElementTypeNameAndId structs:
|
||||
/// entries:
|
||||
/// * type_name: "PushButton", id: "App::mybutton"
|
||||
/// * type_name: "ButtonBase", id: "PushButton::root"
|
||||
/// * type_name: "", id: "ButtonBase::root"
|
||||
///
|
||||
/// ```slint,no-preview
|
||||
/// component ButtonBase {
|
||||
/// // ...
|
||||
/// }
|
||||
/// component PushButton inherits ButtonBase {
|
||||
/// }
|
||||
/// export component App {
|
||||
/// mybutton := PushButton {}
|
||||
/// }
|
||||
/// ```
|
||||
SharedVector<ElementTypeNameAndId> element_type_names_and_ids() const
|
||||
{
|
||||
SharedVector<SharedString> type_names;
|
||||
SharedVector<SharedString> ids;
|
||||
cbindgen_private::slint_testing_element_type_names_and_ids(&inner, &type_names, &ids);
|
||||
SharedVector<ElementTypeNameAndId> result(type_names.size());
|
||||
for (std::size_t i = 0; i < type_names.size(); ++i) {
|
||||
result[i] = { type_names[i], ids[i] };
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Returns the accessible-label of that element, if any.
|
||||
std::optional<SharedString> accessible_label() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
SharedString result;
|
||||
if (item->item_tree.vtable()->accessible_string_property(
|
||||
item->item_tree.borrow(), item->index,
|
||||
|
@ -80,7 +126,7 @@ public:
|
|||
/// Returns the accessible-value of that element, if any.
|
||||
std::optional<SharedString> accessible_value() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
SharedString result;
|
||||
if (item->item_tree.vtable()->accessible_string_property(
|
||||
item->item_tree.borrow(), item->index,
|
||||
|
@ -94,7 +140,7 @@ public:
|
|||
/// Returns the accessible-description of that element, if any.
|
||||
std::optional<SharedString> accessible_description() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
SharedString result;
|
||||
if (item->item_tree.vtable()->accessible_string_property(
|
||||
item->item_tree.borrow(), item->index,
|
||||
|
@ -108,7 +154,7 @@ public:
|
|||
/// Returns the accessible-value-maximum of that element, if any.
|
||||
std::optional<float> accessible_value_maximum() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
SharedString result;
|
||||
if (item->item_tree.vtable()->accessible_string_property(
|
||||
item->item_tree.borrow(), item->index,
|
||||
|
@ -125,7 +171,7 @@ public:
|
|||
/// Returns the accessible-value-minimum of that element, if any.
|
||||
std::optional<float> accessible_value_minimum() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
SharedString result;
|
||||
if (item->item_tree.vtable()->accessible_string_property(
|
||||
item->item_tree.borrow(), item->index,
|
||||
|
@ -142,7 +188,7 @@ public:
|
|||
/// Returns the accessible-value-step of that element, if any.
|
||||
std::optional<float> accessible_value_step() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
SharedString result;
|
||||
if (item->item_tree.vtable()->accessible_string_property(
|
||||
item->item_tree.borrow(), item->index,
|
||||
|
@ -159,7 +205,7 @@ public:
|
|||
/// Returns the accessible-checked of that element, if any.
|
||||
std::optional<bool> accessible_checked() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
SharedString result;
|
||||
if (item->item_tree.vtable()->accessible_string_property(
|
||||
item->item_tree.borrow(), item->index,
|
||||
|
@ -176,7 +222,7 @@ public:
|
|||
/// Returns the accessible-checkable of that element, if any.
|
||||
std::optional<bool> accessible_checkable() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
SharedString result;
|
||||
if (item->item_tree.vtable()->accessible_string_property(
|
||||
item->item_tree.borrow(), item->index,
|
||||
|
@ -195,7 +241,7 @@ public:
|
|||
/// Setting the value will invoke the `accessible-action-set-value` callback.
|
||||
void set_accessible_value(SharedString value) const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
union SetValueHelper {
|
||||
cbindgen_private::AccessibilityAction action;
|
||||
SetValueHelper(SharedString value)
|
||||
|
@ -216,7 +262,7 @@ public:
|
|||
/// (`accessible-action-increment`).
|
||||
void invoke_accessible_increment_action() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
union IncreaseActionHelper {
|
||||
cbindgen_private::AccessibilityAction action;
|
||||
IncreaseActionHelper()
|
||||
|
@ -235,7 +281,7 @@ public:
|
|||
/// (`accessible-action-decrement`).
|
||||
void invoke_accessible_decrement_action() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
union DecreaseActionHelper {
|
||||
cbindgen_private::AccessibilityAction action;
|
||||
DecreaseActionHelper()
|
||||
|
@ -254,7 +300,7 @@ public:
|
|||
/// (`accessible-action-default`).
|
||||
void invoke_accessible_default_action() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
union DefaultActionHelper {
|
||||
cbindgen_private::AccessibilityAction action;
|
||||
DefaultActionHelper()
|
||||
|
@ -272,7 +318,7 @@ public:
|
|||
/// Returns the size of this element
|
||||
LogicalSize size() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
auto rect =
|
||||
item->item_tree.vtable()->item_geometry(item->item_tree.borrow(), item->index);
|
||||
return LogicalSize({ rect.width, rect.height });
|
||||
|
@ -283,7 +329,7 @@ public:
|
|||
/// Returns the absolute position of this element
|
||||
LogicalPosition absolute_position() const
|
||||
{
|
||||
if (auto item = private_api::upgrade_item_weak(inner)) {
|
||||
if (auto item = private_api::upgrade_item_weak(inner.item)) {
|
||||
cbindgen_private::LogicalRect rect =
|
||||
item->item_tree.vtable()->item_geometry(item->item_tree.borrow(), item->index);
|
||||
cbindgen_private::LogicalPoint abs =
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
||||
|
||||
use i_slint_core::accessibility::AccessibleStringProperty;
|
||||
use i_slint_core::item_tree::{ItemTreeRc, ItemWeak};
|
||||
use i_slint_core::item_tree::ItemTreeRc;
|
||||
use i_slint_core::slice::Slice;
|
||||
use i_slint_core::SharedVector;
|
||||
use i_slint_core::{SharedString, SharedVector};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_testing_init_backend() {
|
||||
|
@ -15,11 +14,11 @@ pub extern "C" fn slint_testing_init_backend() {
|
|||
pub extern "C" fn slint_testing_element_find_by_accessible_label(
|
||||
root: &ItemTreeRc,
|
||||
label: &Slice<u8>,
|
||||
out: &mut SharedVector<ItemWeak>,
|
||||
out: &mut SharedVector<crate::search_api::ElementHandle>,
|
||||
) {
|
||||
let Ok(label) = core::str::from_utf8(label.as_slice()) else { return };
|
||||
*out = crate::search_api::search_item(root, |item| {
|
||||
item.accessible_string_property(AccessibleStringProperty::Label).is_some_and(|x| x == label)
|
||||
*out = crate::search_api::search_item(root, |elem| {
|
||||
elem.accessible_label().is_some_and(|x| x == label)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -27,10 +26,24 @@ pub extern "C" fn slint_testing_element_find_by_accessible_label(
|
|||
pub extern "C" fn slint_testing_element_find_by_element_id(
|
||||
root: &ItemTreeRc,
|
||||
element_id: &Slice<u8>,
|
||||
out: &mut SharedVector<ItemWeak>,
|
||||
out: &mut SharedVector<crate::search_api::ElementHandle>,
|
||||
) {
|
||||
let Ok(element_id) = core::str::from_utf8(element_id.as_slice()) else { return };
|
||||
*out = crate::search_api::search_item(root, |item| {
|
||||
item.element_ids().iter().any(|i| i == element_id)
|
||||
*out = crate::search_api::search_item(root, |elem| {
|
||||
elem.element_type_names_and_ids().unwrap().any(|(_, eid)| eid == element_id)
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_testing_element_type_names_and_ids(
|
||||
element: &crate::search_api::ElementHandle,
|
||||
type_names: &mut SharedVector<SharedString>,
|
||||
ids: &mut SharedVector<SharedString>,
|
||||
) {
|
||||
if let Some(it) = element.element_type_names_and_ids() {
|
||||
for (type_name, id) in it {
|
||||
type_names.push(type_name);
|
||||
ids.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,17 +9,16 @@ use i_slint_core::{SharedString, SharedVector};
|
|||
|
||||
pub(crate) fn search_item(
|
||||
item_tree: &ItemTreeRc,
|
||||
mut filter: impl FnMut(&ItemRc) -> bool,
|
||||
) -> SharedVector<ItemWeak> {
|
||||
mut filter: impl FnMut(&ElementHandle) -> bool,
|
||||
) -> SharedVector<ElementHandle> {
|
||||
let mut result = SharedVector::default();
|
||||
i_slint_core::item_tree::visit_items(
|
||||
item_tree,
|
||||
TraversalOrder::BackToFront,
|
||||
|parent_tree, _, index, _| {
|
||||
let item_rc = ItemRc::new(parent_tree.clone(), index);
|
||||
if filter(&item_rc) {
|
||||
result.push(item_rc.downgrade());
|
||||
}
|
||||
let elements = ElementHandle::collect_elements(item_rc);
|
||||
result.extend(elements.filter(|elem| filter(elem)));
|
||||
ItemVisitorResult::Continue(())
|
||||
},
|
||||
(),
|
||||
|
@ -34,12 +33,19 @@ pub(crate) fn search_item(
|
|||
/// Obtain instances of `ElementHandle` by querying your application through
|
||||
/// [`Self::find_by_accessible_label()`].
|
||||
#[derive(Clone)]
|
||||
pub struct ElementHandle(ItemWeak);
|
||||
#[repr(C)]
|
||||
pub struct ElementHandle {
|
||||
item: ItemWeak,
|
||||
}
|
||||
|
||||
impl ElementHandle {
|
||||
fn collect_elements(item: ItemRc) -> impl Iterator<Item = ElementHandle> {
|
||||
core::iter::once(ElementHandle { item: item.downgrade() })
|
||||
}
|
||||
|
||||
/// Returns true if the element still exists in the in UI and is valid to access; false otherwise.
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.0.upgrade().is_some()
|
||||
self.item.upgrade().is_some()
|
||||
}
|
||||
|
||||
/// This function searches through the entire tree of elements of `component`, looks for
|
||||
|
@ -51,11 +57,9 @@ impl ElementHandle {
|
|||
) -> impl Iterator<Item = Self> {
|
||||
// dirty way to get the ItemTreeRc:
|
||||
let item_tree = WindowInner::from_pub(component.window()).component();
|
||||
let result = search_item(&item_tree, |item| {
|
||||
item.accessible_string_property(AccessibleStringProperty::Label)
|
||||
.is_some_and(|x| x == label)
|
||||
});
|
||||
result.into_iter().map(ElementHandle)
|
||||
let result =
|
||||
search_item(&item_tree, |elem| elem.accessible_label().is_some_and(|x| x == label));
|
||||
result.into_iter()
|
||||
}
|
||||
|
||||
/// This function searches through the entire tree of elements of `component`, looks for
|
||||
|
@ -66,8 +70,10 @@ impl ElementHandle {
|
|||
) -> impl Iterator<Item = Self> {
|
||||
// dirty way to get the ItemTreeRc:
|
||||
let item_tree = WindowInner::from_pub(component.window()).component();
|
||||
let result = search_item(&item_tree, |item| item.element_ids().iter().any(|i| i == id));
|
||||
result.into_iter().map(|x| ElementHandle(x))
|
||||
let result = search_item(&item_tree, |elem| {
|
||||
elem.element_type_names_and_ids().unwrap().any(|(_, eid)| eid == id)
|
||||
});
|
||||
result.into_iter()
|
||||
}
|
||||
|
||||
/// This function searches through the entire tree of elements of `component`, looks for
|
||||
|
@ -78,10 +84,56 @@ impl ElementHandle {
|
|||
) -> impl Iterator<Item = Self> {
|
||||
// dirty way to get the ItemTreeRc:
|
||||
let item_tree = WindowInner::from_pub(component.window()).component();
|
||||
let result = search_item(&item_tree, |item| {
|
||||
item.element_type_names().iter().any(|i| i == type_name)
|
||||
let result = search_item(&item_tree, |elem| {
|
||||
elem.element_type_names_and_ids().unwrap().any(|(tn, _)| tn == type_name)
|
||||
});
|
||||
result.into_iter().map(|x| ElementHandle(x))
|
||||
result.into_iter()
|
||||
}
|
||||
|
||||
/// Returns an iterator over tuples of element type names and their ids. Returns None if the
|
||||
/// element is not valid anymore.
|
||||
///
|
||||
/// Elements can have multiple type names and ids, due to inheritance.
|
||||
/// In the following example, the `PushButton` element returns for `element_type_names_and_ids`
|
||||
/// the following tuples:
|
||||
/// entries:
|
||||
/// * ("PushButton", "App::mybutton")
|
||||
/// * ("ButtonBase", "PushButton::root")
|
||||
/// * ("", "ButtonBase::root")
|
||||
///
|
||||
/// ```slint,no-preview
|
||||
/// component ButtonBase {
|
||||
/// // ...
|
||||
/// }
|
||||
/// component PushButton inherits ButtonBase {
|
||||
/// }
|
||||
/// export component App {
|
||||
/// mybutton := PushButton {}
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// # i_slint_backend_testing::init_no_event_loop();
|
||||
/// # slint::slint!{
|
||||
/// # component ButtonBase { }
|
||||
/// # component PushButton inherits ButtonBase { }
|
||||
/// # export component App {
|
||||
/// # mybutton := PushButton {}
|
||||
/// # }
|
||||
/// # }
|
||||
/// let app = App::new().unwrap();
|
||||
/// let button = i_slint_backend_testing::ElementHandle::find_by_element_id(&app, "App::mybutton")
|
||||
/// .next().unwrap();
|
||||
/// assert_eq!(button.element_type_names_and_ids().unwrap().collect::<Vec<_>>(),
|
||||
/// [("PushButton".into(), "App::mybutton".into()),
|
||||
/// ("ButtonBase".into(), "PushButton::root".into()),
|
||||
/// ("".into(), "ButtonBase::root".into())
|
||||
/// ]);
|
||||
/// ```
|
||||
pub fn element_type_names_and_ids(
|
||||
&self,
|
||||
) -> Option<impl Iterator<Item = (SharedString, SharedString)>> {
|
||||
self.item.upgrade().map(|item| item.element_type_names_and_ids().into_iter())
|
||||
}
|
||||
|
||||
/// Invokes the default accessible action on the element. For example a `MyButton` element might declare
|
||||
|
@ -102,14 +154,14 @@ impl ElementHandle {
|
|||
/// }
|
||||
/// ```
|
||||
pub fn invoke_accessible_default_action(&self) {
|
||||
if let Some(item) = self.0.upgrade() {
|
||||
if let Some(item) = self.item.upgrade() {
|
||||
item.accessible_action(&AccessibilityAction::Default)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value of the element's `accessible-value` property, if present.
|
||||
pub fn accessible_value(&self) -> Option<SharedString> {
|
||||
self.0
|
||||
self.item
|
||||
.upgrade()
|
||||
.and_then(|item| item.accessible_string_property(AccessibleStringProperty::Value))
|
||||
}
|
||||
|
@ -117,14 +169,14 @@ impl ElementHandle {
|
|||
/// Sets the value of the element's `accessible-value` property. Note that you can only set this
|
||||
/// property if it is declared in your Slint code.
|
||||
pub fn set_accessible_value(&self, value: impl Into<SharedString>) {
|
||||
if let Some(item) = self.0.upgrade() {
|
||||
if let Some(item) = self.item.upgrade() {
|
||||
item.accessible_action(&AccessibilityAction::SetValue(value.into()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value of the element's `accessible-value-maximum` property, if present.
|
||||
pub fn accessible_value_maximum(&self) -> Option<f32> {
|
||||
self.0.upgrade().and_then(|item| {
|
||||
self.item.upgrade().and_then(|item| {
|
||||
item.accessible_string_property(AccessibleStringProperty::ValueMaximum)
|
||||
.and_then(|item| item.parse().ok())
|
||||
})
|
||||
|
@ -132,7 +184,7 @@ impl ElementHandle {
|
|||
|
||||
/// Returns the value of the element's `accessible-value-minimum` property, if present.
|
||||
pub fn accessible_value_minimum(&self) -> Option<f32> {
|
||||
self.0.upgrade().and_then(|item| {
|
||||
self.item.upgrade().and_then(|item| {
|
||||
item.accessible_string_property(AccessibleStringProperty::ValueMinimum)
|
||||
.and_then(|item| item.parse().ok())
|
||||
})
|
||||
|
@ -140,7 +192,7 @@ impl ElementHandle {
|
|||
|
||||
/// Returns the value of the element's `accessible-value-step` property, if present.
|
||||
pub fn accessible_value_step(&self) -> Option<f32> {
|
||||
self.0.upgrade().and_then(|item| {
|
||||
self.item.upgrade().and_then(|item| {
|
||||
item.accessible_string_property(AccessibleStringProperty::ValueStep)
|
||||
.and_then(|item| item.parse().ok())
|
||||
})
|
||||
|
@ -148,21 +200,21 @@ impl ElementHandle {
|
|||
|
||||
/// Returns the value of the `accessible-label` property, if present.
|
||||
pub fn accessible_label(&self) -> Option<SharedString> {
|
||||
self.0
|
||||
self.item
|
||||
.upgrade()
|
||||
.and_then(|item| item.accessible_string_property(AccessibleStringProperty::Label))
|
||||
}
|
||||
|
||||
/// Returns the value of the `accessible-description` property, if present
|
||||
pub fn accessible_description(&self) -> Option<SharedString> {
|
||||
self.0
|
||||
self.item
|
||||
.upgrade()
|
||||
.and_then(|item| item.accessible_string_property(AccessibleStringProperty::Description))
|
||||
}
|
||||
|
||||
/// Returns the value of the `accessible-checked` property, if present
|
||||
pub fn accessible_checked(&self) -> Option<bool> {
|
||||
self.0
|
||||
self.item
|
||||
.upgrade()
|
||||
.and_then(|item| item.accessible_string_property(AccessibleStringProperty::Checked))
|
||||
.and_then(|item| item.parse().ok())
|
||||
|
@ -170,7 +222,7 @@ impl ElementHandle {
|
|||
|
||||
/// Returns the value of the `accessible-checkable` property, if present
|
||||
pub fn accessible_checkable(&self) -> Option<bool> {
|
||||
self.0
|
||||
self.item
|
||||
.upgrade()
|
||||
.and_then(|item| item.accessible_string_property(AccessibleStringProperty::Checkable))
|
||||
.and_then(|item| item.parse().ok())
|
||||
|
@ -179,7 +231,7 @@ impl ElementHandle {
|
|||
/// Returns the size of the element in logical pixels. This corresponds to the value of the `width` and
|
||||
/// `height` properties in Slint code. Returns a zero size if the element is not valid.
|
||||
pub fn size(&self) -> i_slint_core::api::LogicalSize {
|
||||
self.0
|
||||
self.item
|
||||
.upgrade()
|
||||
.map(|item| {
|
||||
let g = item.geometry();
|
||||
|
@ -191,7 +243,7 @@ impl ElementHandle {
|
|||
/// Returns the position of the element within the entire window. This corresponds to the value of the
|
||||
/// `absolute-position` property in Slint code. Returns a zero position if the element is not valid.
|
||||
pub fn absolute_position(&self) -> i_slint_core::api::LogicalPosition {
|
||||
self.0
|
||||
self.item
|
||||
.upgrade()
|
||||
.map(|item| {
|
||||
let g = item.geometry();
|
||||
|
@ -204,7 +256,7 @@ impl ElementHandle {
|
|||
/// Invokes the element's `accessible-action-increment` callback, if declared. On widgets such as spinboxes, this
|
||||
/// typically increments the value.
|
||||
pub fn invoke_accessible_increment_action(&self) {
|
||||
if let Some(item) = self.0.upgrade() {
|
||||
if let Some(item) = self.item.upgrade() {
|
||||
item.accessible_action(&AccessibilityAction::Increment)
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +264,7 @@ impl ElementHandle {
|
|||
/// Invokes the element's `accessible-action-decrement` callback, if declared. On widgets such as spinboxes, this
|
||||
/// typically decrements the value.
|
||||
pub fn invoke_accessible_decrement_action(&self) {
|
||||
if let Some(item) = self.0.upgrade() {
|
||||
if let Some(item) = self.item.upgrade() {
|
||||
item.accessible_action(&AccessibilityAction::Decrement)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ use crate::lengths::{LogicalPoint, LogicalRect};
|
|||
use crate::slice::Slice;
|
||||
use crate::window::WindowAdapterRc;
|
||||
use crate::SharedString;
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec::Vec;
|
||||
use core::pin::Pin;
|
||||
use vtable::*;
|
||||
|
@ -369,30 +368,22 @@ impl ItemRc {
|
|||
comp_ref_pin.as_ref().supported_accessibility_actions(self.index)
|
||||
}
|
||||
|
||||
pub fn element_ids(&self) -> Vec<String> {
|
||||
pub fn element_type_names_and_ids(&self) -> Vec<(SharedString, SharedString)> {
|
||||
let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
|
||||
let mut result = SharedString::new();
|
||||
comp_ref_pin.as_ref().item_element_infos(self.index, &mut result);
|
||||
result
|
||||
.as_str()
|
||||
.split(";")
|
||||
.filter_map(|encoded_elem_info| {
|
||||
encoded_elem_info.split(',').nth(1).map(ToString::to_string)
|
||||
.map(|encoded_elem_info| {
|
||||
let mut decoder = encoded_elem_info.split(',');
|
||||
let type_name = decoder.next().unwrap().into();
|
||||
let id = decoder.next().map(Into::into).unwrap_or_default();
|
||||
(type_name, id)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn element_type_names(&self) -> Vec<String> {
|
||||
let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
|
||||
let mut result = SharedString::new();
|
||||
comp_ref_pin.as_ref().item_element_infos(self.index, &mut result);
|
||||
result
|
||||
.as_str()
|
||||
.split(";")
|
||||
.map(|encoded_elem_info| encoded_elem_info.split(',').next().unwrap().to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn geometry(&self) -> LogicalRect {
|
||||
let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
|
||||
comp_ref_pin.as_ref().item_geometry(self.index)
|
||||
|
|
|
@ -39,7 +39,12 @@ assert!(button.is_valid());
|
|||
assert_eq!(button.accessible_label().unwrap(), "third");
|
||||
assert!(button_search.next().is_none());
|
||||
|
||||
assert_eq!(slint_testing::ElementHandle::find_by_element_id(&instance, "TestCase::second").count(), 1);
|
||||
assert_eq!(slint_testing::ElementHandle::find_by_element_id(&instance, "TestCase::second").flat_map(|elem| elem.element_type_names_and_ids().unwrap()).collect::<Vec<_>>(),
|
||||
vec![
|
||||
("Button".into(), "TestCase::second".into()),
|
||||
("ButtonBase".into(), "Button::root".into()),
|
||||
("Text".into(), "ButtonBase::root".into()),
|
||||
]);
|
||||
|
||||
let texts = slint_testing::ElementHandle::find_by_element_type_name(&instance, "Text").filter_map(|elem| elem.accessible_label()).collect::<Vec<_>>();
|
||||
assert_eq!(texts, vec!["optimized", "extra", "plain", "extra", "third", "extra"]);
|
||||
|
@ -61,6 +66,15 @@ button = button_search[2];
|
|||
assert(button.is_valid());
|
||||
assert_eq(button.accessible_label().value(), "third");
|
||||
|
||||
assert_eq(slint::testing::ElementHandle::find_by_element_id(handle, "TestCase::second").size(), 1);
|
||||
auto id_search_result = slint::testing::ElementHandle::find_by_element_id(handle, "TestCase::second");
|
||||
assert_eq(id_search_result.size(), 1);
|
||||
auto type_names_and_ids = id_search_result[0].element_type_names_and_ids();
|
||||
assert_eq(type_names_and_ids.size(), 3);
|
||||
assert_eq(type_names_and_ids[0].type_name, "Button");
|
||||
assert_eq(type_names_and_ids[0].id, "TestCase::second");
|
||||
assert_eq(type_names_and_ids[1].type_name, "ButtonBase");
|
||||
assert_eq(type_names_and_ids[1].id, "Button::root");
|
||||
assert_eq(type_names_and_ids[2].type_name, "Text");
|
||||
assert_eq(type_names_and_ids[2].id, "ButtonBase::root");
|
||||
```
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue