mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-29 13:24:48 +00:00
Add a clear-focus()
function on all elements that have a focus()
function
This is the counter-part, which removes focus from the element if it's currently focused. The window - if focused - may still be focused towards the windowing system.
This commit is contained in:
parent
e10e97c944
commit
31767eb6ab
21 changed files with 268 additions and 23 deletions
|
@ -25,6 +25,7 @@ All notable changes to this project are documented in this file.
|
|||
- Fixed compiler panic with state property change involving a state in a parent component. (#5038)
|
||||
- Fixed interpreter overwriting property named `index`. (#4961)
|
||||
- Fixed compiler panic when a callback aliases itself. (#4938)
|
||||
- Added `clear-focus()` function to focusable elements, to allow for programmatic focus clearing.
|
||||
|
||||
## Widgets
|
||||
|
||||
|
|
|
@ -93,10 +93,10 @@ public:
|
|||
items, &inner);
|
||||
}
|
||||
|
||||
void set_focus_item(const ItemTreeRc &component_rc, uint32_t item_index)
|
||||
void set_focus_item(const ItemTreeRc &component_rc, uint32_t item_index, bool set_focus)
|
||||
{
|
||||
cbindgen_private::ItemRc item_rc { component_rc, item_index };
|
||||
cbindgen_private::slint_windowrc_set_focus_item(&inner, &item_rc);
|
||||
cbindgen_private::slint_windowrc_set_focus_item(&inner, &item_rc, set_focus);
|
||||
}
|
||||
|
||||
template<typename Component>
|
||||
|
|
|
@ -216,6 +216,7 @@ or it will be mapped to a private unicode character. The mapping of these non-pr
|
|||
|
||||
- **`focus()`** Call this function to transfer keyboard focus to this `FocusScope`,
|
||||
to receive future [`KeyEvent`](structs.md#keyevent)s.
|
||||
- **`clear-focus()`** Call this function to remove keyboard focus from this `FocusScope` if it currently has the focus.
|
||||
|
||||
### Callbacks
|
||||
|
||||
|
@ -680,6 +681,7 @@ When not part of a layout, its width or height defaults to 100% of the parent el
|
|||
### Functions
|
||||
|
||||
- **`focus()`** Call this function to focus the text input and make it receive future keyboard events.
|
||||
- **`clear-focus()`** Call this function to remove keyboard focus from this `TextInput` if it currently has the focus.
|
||||
- **`set-selection-offsets(int, int)`** Selects the text between two UTF-8 offsets.
|
||||
- **`select-all()`** Selects all text.
|
||||
- **`clear-selection()`** Clears the selection.
|
||||
|
|
|
@ -19,6 +19,7 @@ a widget able to handle several lines of text.
|
|||
### Functions
|
||||
|
||||
- **`focus()`** Call this function to focus the LineEdit and make it receive future keyboard events.
|
||||
- **`clear-focus()`** Call this function to remove keyboard focus from this `LineEdit` if it currently has the focus.
|
||||
- **`set-selection-offsets(int, int)`** Selects the text between two UTF-8 offsets.
|
||||
- **`select-all()`** Selects all text.
|
||||
- **`clear-selection()`** Clears the selection.
|
||||
|
|
|
@ -19,6 +19,7 @@ shortcut will be implemented in a future version: <https://github.com/slint-ui/s
|
|||
### Functions
|
||||
|
||||
- **`focus()`** Call this function to focus the TextEdit and make it receive future keyboard events.
|
||||
- **`clear-focus()`** Call this function to remove keyboard focus from this `TextEdit` if it currently has the focus.
|
||||
- **`set-selection-offsets(int, int)`** Selects the text between two UTF-8 offsets.
|
||||
- **`select-all()`** Selects all text.
|
||||
- **`clear-selection()`** Clears the selection.
|
||||
|
|
|
@ -209,7 +209,7 @@ impl Item for NativeSlider {
|
|||
click_count: _,
|
||||
} => {
|
||||
if !self.has_focus() {
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc);
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc, true);
|
||||
}
|
||||
data.pressed_x = if vertical { pos.y as f32 } else { pos.x as f32 };
|
||||
data.pressed = 1;
|
||||
|
|
|
@ -222,7 +222,7 @@ impl Item for NativeSpinBox {
|
|||
|
||||
if let MouseEvent::Pressed { .. } = event {
|
||||
if !self.has_focus() {
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc);
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc, true);
|
||||
}
|
||||
}
|
||||
InputEventResult::EventAccepted
|
||||
|
|
|
@ -440,7 +440,7 @@ impl Item for NativeTab {
|
|||
if matches!(event, MouseEvent::Released { button, .. } if !click_on_press && button == PointerEventButton::Left)
|
||||
|| matches!(event, MouseEvent::Pressed { button, .. } if click_on_press && button == PointerEventButton::Left)
|
||||
{
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc);
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc, true);
|
||||
self.current.set(self.tab_index());
|
||||
InputEventResult::EventAccepted
|
||||
} else {
|
||||
|
|
|
@ -126,7 +126,7 @@ impl AccessKitAdapter {
|
|||
Action::Default => AccessibilityAction::Default,
|
||||
Action::Focus => {
|
||||
if let Some(item) = self.item_rc_for_node_id(request.target) {
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(&item);
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(&item, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ pub enum BuiltinFunction {
|
|||
Log,
|
||||
Pow,
|
||||
SetFocusItem,
|
||||
ClearFocusItem,
|
||||
ShowPopupWindow,
|
||||
ClosePopupWindow,
|
||||
SetSelectionOffsets,
|
||||
|
@ -133,6 +134,10 @@ impl BuiltinFunction {
|
|||
return_type: Box::new(Type::Void),
|
||||
args: vec![Type::ElementReference],
|
||||
},
|
||||
BuiltinFunction::ClearFocusItem => Type::Function {
|
||||
return_type: Box::new(Type::Void),
|
||||
args: vec![Type::ElementReference],
|
||||
},
|
||||
BuiltinFunction::ShowPopupWindow | BuiltinFunction::ClosePopupWindow => {
|
||||
Type::Function {
|
||||
return_type: Box::new(Type::Void),
|
||||
|
@ -292,7 +297,7 @@ impl BuiltinFunction {
|
|||
| BuiltinFunction::Log
|
||||
| BuiltinFunction::Pow
|
||||
| BuiltinFunction::ATan => true,
|
||||
BuiltinFunction::SetFocusItem => false,
|
||||
BuiltinFunction::SetFocusItem | BuiltinFunction::ClearFocusItem => false,
|
||||
BuiltinFunction::ShowPopupWindow | BuiltinFunction::ClosePopupWindow => false,
|
||||
BuiltinFunction::SetSelectionOffsets => false,
|
||||
BuiltinFunction::ItemMemberFunction(..) => false,
|
||||
|
@ -349,7 +354,7 @@ impl BuiltinFunction {
|
|||
| BuiltinFunction::Log
|
||||
| BuiltinFunction::Pow
|
||||
| BuiltinFunction::ATan => true,
|
||||
BuiltinFunction::SetFocusItem => false,
|
||||
BuiltinFunction::SetFocusItem | BuiltinFunction::ClearFocusItem => false,
|
||||
BuiltinFunction::ShowPopupWindow | BuiltinFunction::ClosePopupWindow => false,
|
||||
BuiltinFunction::SetSelectionOffsets => false,
|
||||
BuiltinFunction::ItemMemberFunction(..) => false,
|
||||
|
|
|
@ -3100,11 +3100,20 @@ fn compile_builtin_function_call(
|
|||
if let [llr::Expression::PropertyReference(pr)] = arguments {
|
||||
let window = access_window_field(ctx);
|
||||
let focus_item = access_item_rc(pr, ctx);
|
||||
format!("{}.set_focus_item({});", window, focus_item)
|
||||
format!("{}.set_focus_item({}, true);", window, focus_item)
|
||||
} else {
|
||||
panic!("internal error: invalid args to SetFocusItem {:?}", arguments)
|
||||
}
|
||||
}
|
||||
BuiltinFunction::ClearFocusItem => {
|
||||
if let [llr::Expression::PropertyReference(pr)] = arguments {
|
||||
let window = access_window_field(ctx);
|
||||
let focus_item = access_item_rc(pr, ctx);
|
||||
format!("{}.set_focus_item({}, false);", window, focus_item)
|
||||
} else {
|
||||
panic!("internal error: invalid args to ClearFocusItem {:?}", arguments)
|
||||
}
|
||||
}
|
||||
/* std::from_chars is unfortunately not yet implemented in gcc
|
||||
BuiltinFunction::StringIsFloat => {
|
||||
"[](const auto &a){ double v; auto r = std::from_chars(std::begin(a), std::end(a), v); return r.ptr == std::end(a); }"
|
||||
|
|
|
@ -2396,12 +2396,23 @@ fn compile_builtin_function_call(
|
|||
let window_tokens = access_window_adapter_field(ctx);
|
||||
let focus_item = access_item_rc(pr, ctx);
|
||||
quote!(
|
||||
sp::WindowInner::from_pub(#window_tokens.window()).set_focus_item(#focus_item)
|
||||
sp::WindowInner::from_pub(#window_tokens.window()).set_focus_item(#focus_item, true)
|
||||
)
|
||||
} else {
|
||||
panic!("internal error: invalid args to SetFocusItem {:?}", arguments)
|
||||
}
|
||||
}
|
||||
BuiltinFunction::ClearFocusItem => {
|
||||
if let [Expression::PropertyReference(pr)] = arguments {
|
||||
let window_tokens = access_window_adapter_field(ctx);
|
||||
let focus_item = access_item_rc(pr, ctx);
|
||||
quote!(
|
||||
sp::WindowInner::from_pub(#window_tokens.window()).set_focus_item(#focus_item, false)
|
||||
)
|
||||
} else {
|
||||
panic!("internal error: invalid args to ClearFocusItem {:?}", arguments)
|
||||
}
|
||||
}
|
||||
BuiltinFunction::ShowPopupWindow => {
|
||||
if let [Expression::NumberLiteral(popup_index), x, y, close_on_click, Expression::PropertyReference(parent_ref)] =
|
||||
arguments
|
||||
|
|
|
@ -81,7 +81,7 @@ fn builtin_function_cost(function: &BuiltinFunction) -> isize {
|
|||
BuiltinFunction::ATan => 10,
|
||||
BuiltinFunction::Log => 10,
|
||||
BuiltinFunction::Pow => 10,
|
||||
BuiltinFunction::SetFocusItem => isize::MAX,
|
||||
BuiltinFunction::SetFocusItem | BuiltinFunction::ClearFocusItem => isize::MAX,
|
||||
BuiltinFunction::ShowPopupWindow | BuiltinFunction::ClosePopupWindow => isize::MAX,
|
||||
BuiltinFunction::SetSelectionOffsets => isize::MAX,
|
||||
BuiltinFunction::ItemMemberFunction(..) => isize::MAX,
|
||||
|
|
|
@ -35,7 +35,7 @@ pub fn replace_forward_focus_bindings_with_focus_functions(
|
|||
// Phase 2: Filter out focus-forward bindings that aren't callable
|
||||
local_forwards.remove_uncallable_forwards();
|
||||
|
||||
// Phase 3: For `focus-forward` in the root element, create a `focus()` function that's callable from the outside
|
||||
// Phase 3: For `focus-forward` in the root element, create `focus()` and `clear-focus()` functions that are callable from the outside
|
||||
if let Some((root_focus_forward, focus_forward_location)) =
|
||||
local_forwards.focus_forward_for_element(&component.root_element)
|
||||
{
|
||||
|
@ -59,6 +59,27 @@ pub fn replace_forward_focus_bindings_with_focus_functions(
|
|||
.bindings
|
||||
.insert("focus".into(), RefCell::new(set_focus_code.into()));
|
||||
}
|
||||
|
||||
if let Some(clear_focus_code) =
|
||||
call_clear_focus_function(&root_focus_forward, Some(&focus_forward_location))
|
||||
{
|
||||
component.root_element.borrow_mut().property_declarations.insert(
|
||||
"clear-focus".into(),
|
||||
PropertyDeclaration {
|
||||
property_type: Type::Function {
|
||||
return_type: Type::Void.into(),
|
||||
args: vec![],
|
||||
},
|
||||
visibility: PropertyVisibility::Public,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
component
|
||||
.root_element
|
||||
.borrow_mut()
|
||||
.bindings
|
||||
.insert("clear-focus".into(), RefCell::new(clear_focus_code.into()));
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 4: All calls to `.focus()` may need to be changed with `focus-forward` resolved or changed from the built-in
|
||||
|
@ -249,3 +270,47 @@ fn call_focus_function(
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn call_clear_focus_function(
|
||||
element: &ElementRc,
|
||||
source_location: Option<&SourceLocation>,
|
||||
) -> Option<Expression> {
|
||||
let declares_focus_function = {
|
||||
let mut element = element.clone();
|
||||
loop {
|
||||
if element.borrow().property_declarations.contains_key("clear-focus") {
|
||||
break true;
|
||||
}
|
||||
let base = element.borrow().base_type.clone();
|
||||
match base {
|
||||
ElementType::Component(compo) => element = compo.root_element.clone(),
|
||||
_ => break false,
|
||||
}
|
||||
}
|
||||
};
|
||||
let builtin_focus_function =
|
||||
element.borrow().builtin_type().map_or(false, |ty| ty.accepts_focus);
|
||||
|
||||
if declares_focus_function {
|
||||
Some(Expression::FunctionCall {
|
||||
function: Box::new(Expression::FunctionReference(
|
||||
NamedReference::new(element, "clear-focus"),
|
||||
None,
|
||||
)),
|
||||
arguments: vec![],
|
||||
source_location: source_location.cloned(),
|
||||
})
|
||||
} else if builtin_focus_function {
|
||||
let source_location = source_location.cloned();
|
||||
Some(Expression::FunctionCall {
|
||||
function: Box::new(Expression::BuiltinFunctionReference(
|
||||
BuiltinFunction::ClearFocusItem,
|
||||
source_location.clone(),
|
||||
)),
|
||||
arguments: vec![Expression::ElementReference(Rc::downgrade(element))],
|
||||
source_location,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ fn load_component(component: &Rc<i_slint_compiler::object_tree::Component>) -> C
|
|||
)
|
||||
}),
|
||||
);
|
||||
// Synthesize focus() as styles written in .slint will have it but the qt style exposes NativeXX directly.
|
||||
// Synthesize focus() and `clear-focus()` as styles written in .slint will have it but the qt style exposes NativeXX directly.
|
||||
if b.accepts_focus {
|
||||
result.properties.insert(
|
||||
"focus".into(),
|
||||
|
@ -102,6 +102,14 @@ fn load_component(component: &Rc<i_slint_compiler::object_tree::Component>) -> C
|
|||
pure: false,
|
||||
},
|
||||
);
|
||||
result.properties.insert(
|
||||
"clear-focus".into(),
|
||||
PropertyInfo {
|
||||
ty: Type::Function { return_type: Type::Void.into(), args: vec![] },
|
||||
vis: PropertyVisibility::Public,
|
||||
pure: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ pub fn reserved_properties() -> impl Iterator<Item = (&'static str, Type, Proper
|
|||
("absolute-position", logical_point_type(), PropertyVisibility::Output),
|
||||
("forward-focus", Type::ElementReference, PropertyVisibility::Constexpr),
|
||||
("focus", BuiltinFunction::SetFocusItem.ty(), PropertyVisibility::Public),
|
||||
("clear-focus", BuiltinFunction::ClearFocusItem.ty(), PropertyVisibility::Public),
|
||||
(
|
||||
"dialog-button-role",
|
||||
Type::Enumeration(BUILTIN_ENUMS.with(|e| e.DialogButtonRole.clone())),
|
||||
|
@ -206,6 +207,7 @@ pub fn reserved_property(name: &str) -> PropertyLookupResult {
|
|||
pub fn reserved_member_function(name: &str) -> Option<BuiltinFunction> {
|
||||
for (m, e) in [
|
||||
("focus", BuiltinFunction::SetFocusItem), // match for callable "focus" property
|
||||
("clear-focus", BuiltinFunction::ClearFocusItem), // match for callable "clear-focus" property
|
||||
] {
|
||||
if m == name {
|
||||
return Some(e);
|
||||
|
|
|
@ -775,7 +775,7 @@ impl Item for FocusScope {
|
|||
self_rc: &ItemRc,
|
||||
) -> InputEventResult {
|
||||
if self.enabled() && matches!(event, MouseEvent::Pressed { .. }) && !self.has_focus() {
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc);
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc, true);
|
||||
InputEventResult::EventAccepted
|
||||
} else {
|
||||
InputEventResult::EventIgnored
|
||||
|
|
|
@ -1476,7 +1476,7 @@ impl TextInput {
|
|||
self_rc: &ItemRc,
|
||||
) {
|
||||
if !self.has_focus() {
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc);
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc, true);
|
||||
} else if !self.read_only() {
|
||||
if let Some(w) = window_adapter.internal(crate::InternalToken) {
|
||||
w.input_method_request(InputMethodRequest::Enable(
|
||||
|
|
|
@ -691,13 +691,24 @@ impl WindowInner {
|
|||
}
|
||||
|
||||
/// Sets the focus to the item pointed to by item_ptr. This will remove the focus from any
|
||||
/// currently focused item.
|
||||
pub fn set_focus_item(&self, focus_item: &ItemRc) {
|
||||
/// currently focused item. If set_focus is false, the focus is cleared.
|
||||
pub fn set_focus_item(&self, new_focus_item: &ItemRc, set_focus: bool) {
|
||||
if self.prevent_focus_change.get() {
|
||||
return;
|
||||
}
|
||||
if !set_focus {
|
||||
let current_focus_item = self.focus_item.borrow().clone();
|
||||
if let Some(current_focus_item_rc) = current_focus_item.upgrade() {
|
||||
if current_focus_item_rc != *new_focus_item {
|
||||
// can't clear focus unless called with currently focused item.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let old = self.take_focus_item();
|
||||
let new = self.move_focus(focus_item.clone(), next_focus_item);
|
||||
let new =
|
||||
if set_focus { self.move_focus(new_focus_item.clone(), next_focus_item) } else { None };
|
||||
let window_adapter = self.window_adapter();
|
||||
if let Some(window_adapter) = window_adapter.internal(crate::InternalToken) {
|
||||
window_adapter.handle_focus_change(old, new);
|
||||
|
@ -1250,9 +1261,10 @@ pub mod ffi {
|
|||
pub unsafe extern "C" fn slint_windowrc_set_focus_item(
|
||||
handle: *const WindowAdapterRcOpaque,
|
||||
focus_item: &ItemRc,
|
||||
set_focus: bool,
|
||||
) {
|
||||
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(focus_item)
|
||||
WindowInner::from_pub(window_adapter.window()).set_focus_item(focus_item, set_focus)
|
||||
}
|
||||
|
||||
/// Associates the window with the given component.
|
||||
|
|
|
@ -527,16 +527,56 @@ fn call_builtin_function(
|
|||
enclosing_component.self_weak().get().unwrap().upgrade().unwrap();
|
||||
|
||||
component.access_window(|window| {
|
||||
window.set_focus_item(&corelib::items::ItemRc::new(
|
||||
vtable::VRc::into_dyn(focus_item_comp),
|
||||
item_info.item_index(),
|
||||
))
|
||||
window.set_focus_item(
|
||||
&corelib::items::ItemRc::new(
|
||||
vtable::VRc::into_dyn(focus_item_comp),
|
||||
item_info.item_index(),
|
||||
),
|
||||
true,
|
||||
)
|
||||
});
|
||||
Value::Void
|
||||
} else {
|
||||
panic!("internal error: argument to SetFocusItem must be an element")
|
||||
}
|
||||
}
|
||||
BuiltinFunction::ClearFocusItem => {
|
||||
if arguments.len() != 1 {
|
||||
panic!("internal error: incorrect argument count to SetFocusItem")
|
||||
}
|
||||
let component = match local_context.component_instance {
|
||||
ComponentInstance::InstanceRef(c) => c,
|
||||
ComponentInstance::GlobalComponent(_) => {
|
||||
panic!("Cannot access the focus item from a global component")
|
||||
}
|
||||
};
|
||||
if let Expression::ElementReference(focus_item) = &arguments[0] {
|
||||
generativity::make_guard!(guard);
|
||||
|
||||
let focus_item = focus_item.upgrade().unwrap();
|
||||
let enclosing_component =
|
||||
enclosing_component_for_element(&focus_item, component, guard);
|
||||
let description = enclosing_component.description;
|
||||
|
||||
let item_info = &description.items[focus_item.borrow().id.as_str()];
|
||||
|
||||
let focus_item_comp =
|
||||
enclosing_component.self_weak().get().unwrap().upgrade().unwrap();
|
||||
|
||||
component.access_window(|window| {
|
||||
window.set_focus_item(
|
||||
&corelib::items::ItemRc::new(
|
||||
vtable::VRc::into_dyn(focus_item_comp),
|
||||
item_info.item_index(),
|
||||
),
|
||||
false,
|
||||
)
|
||||
});
|
||||
Value::Void
|
||||
} else {
|
||||
panic!("internal error: argument to ClearFocusItem must be an element")
|
||||
}
|
||||
}
|
||||
BuiltinFunction::ShowPopupWindow => {
|
||||
if arguments.len() != 1 {
|
||||
panic!("internal error: incorrect argument count to ShowPopupWindow")
|
||||
|
|
88
tests/cases/focus/clear_focus.slint
Normal file
88
tests/cases/focus/clear_focus.slint
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.2 OR LicenseRef-Slint-commercial
|
||||
|
||||
export component TestCase inherits Window {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
|
||||
le1 := TextInput {
|
||||
x: 0px;
|
||||
y: 0px;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
le2 := TextInput {
|
||||
y: 100px;
|
||||
x: 0px;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
out property le1-has-focus <=> le1.has-focus;
|
||||
out property le2-has-focus <=> le2.has-focus;
|
||||
out property <bool> te-focused: TextInputInterface.text-input-focused;
|
||||
|
||||
callback clear-le1-focus();
|
||||
clear-le1-focus => {
|
||||
le1.clear-focus();
|
||||
}
|
||||
|
||||
callback clear-le2-focus();
|
||||
clear-le2-focus => {
|
||||
le2.clear-focus();
|
||||
}
|
||||
|
||||
callback focus-le1();
|
||||
focus-le1 => {
|
||||
le1.focus();
|
||||
}
|
||||
|
||||
callback focus-le2();
|
||||
focus-le2 => {
|
||||
le2.focus();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
|
||||
```rust
|
||||
let instance = TestCase::new().unwrap();
|
||||
|
||||
assert_eq!(instance.get_le1_has_focus(), false);
|
||||
assert_eq!(instance.get_le2_has_focus(), false);
|
||||
//assert_eq!(instance.get_te_focused(), false);
|
||||
|
||||
// Focus first line edit
|
||||
eprintln!("send event");
|
||||
slint_testing::send_mouse_click(&instance, 50., 50.);
|
||||
|
||||
assert_eq!(instance.get_le1_has_focus(), true);
|
||||
assert_eq!(instance.get_le2_has_focus(), false);
|
||||
assert_eq!(instance.get_te_focused(), true);
|
||||
|
||||
// Focus second line edit programmatically
|
||||
eprintln!("set programmatically");
|
||||
instance.invoke_focus_le2();
|
||||
|
||||
assert_eq!(instance.get_le1_has_focus(), false);
|
||||
assert_eq!(instance.get_le2_has_focus(), true);
|
||||
assert_eq!(instance.get_te_focused(), true);
|
||||
|
||||
// Clear focus (should fail because item is not focused)
|
||||
instance.invoke_clear_le1_focus();
|
||||
|
||||
assert_eq!(instance.get_le1_has_focus(), false);
|
||||
assert_eq!(instance.get_le2_has_focus(), true);
|
||||
assert_eq!(instance.get_te_focused(), true);
|
||||
|
||||
// Clear focus on currently focused item
|
||||
instance.invoke_clear_le2_focus();
|
||||
|
||||
assert_eq!(instance.get_le1_has_focus(), false);
|
||||
assert_eq!(instance.get_le2_has_focus(), false);
|
||||
assert_eq!(instance.get_te_focused(), false);
|
||||
```
|
||||
|
||||
*/
|
Loading…
Add table
Add a link
Reference in a new issue