mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 18:58:36 +00:00
Add support for manually closing PopupWindows
This patch adds a `close()` function that can be called to close a popup window, and a `close-to-click` boolean that can be set to false to disable the default behavior.
This commit is contained in:
parent
a0a5294e49
commit
0f54b9599b
20 changed files with 349 additions and 24 deletions
|
@ -20,6 +20,7 @@ All notable changes to this project are documented in this file.
|
|||
- Added boolean `font-italic` property to `Text` and `TextInput`.
|
||||
- Added `select-all()`, `cut()`, `copy()`, and `paste() to `TextInput`, `LineEdit`, and `TextEdit`.
|
||||
- Added functions on color: `transparentize`, `mix`, and `with-alpha`.
|
||||
- Added a `close()` function and a `close-on-click` boolean property to `PopupWindow`.
|
||||
|
||||
### Rust
|
||||
|
||||
|
|
|
@ -331,6 +331,7 @@ fn gen_corelib(
|
|||
"slint_windowrc_set_focus_item",
|
||||
"slint_windowrc_set_component",
|
||||
"slint_windowrc_show_popup",
|
||||
"slint_windowrc_close_popup",
|
||||
"slint_windowrc_set_rendering_notifier",
|
||||
"slint_windowrc_request_redraw",
|
||||
"slint_windowrc_on_close_requested",
|
||||
|
|
|
@ -161,13 +161,16 @@ public:
|
|||
}
|
||||
|
||||
template<typename Component, typename Parent>
|
||||
void show_popup(const Parent *parent_component, cbindgen_private::Point p,
|
||||
void show_popup(const Parent *parent_component, cbindgen_private::Point p, bool close_on_click,
|
||||
cbindgen_private::ItemRc parent_item) const
|
||||
{
|
||||
auto popup = Component::create(parent_component).into_dyn();
|
||||
cbindgen_private::slint_windowrc_show_popup(&inner, &popup, p, &parent_item);
|
||||
cbindgen_private::slint_windowrc_show_popup(&inner, &popup, p, close_on_click,
|
||||
&parent_item);
|
||||
}
|
||||
|
||||
void close_popup() const { cbindgen_private::slint_windowrc_close_popup(&inner); }
|
||||
|
||||
template<std::invocable<RenderingState, GraphicsAPI> F>
|
||||
std::optional<SetRenderingNotifierError> set_rendering_notifier(F callback) const
|
||||
{
|
||||
|
|
|
@ -495,9 +495,15 @@ Use this element to show a popup window like a tooltip or a popup menu.
|
|||
|
||||
Note: It isn't allowed to access properties of elements within the popup from outside of the `PopupWindow`.
|
||||
|
||||
### Properties
|
||||
|
||||
- **`close-on-click`** (_in_ _bool_): By default, a PopupWindow closes when the user clicks. Set this
|
||||
to false to prevent that behavior and close it manually using the `close()` function. (default value: true)
|
||||
|
||||
### Functions
|
||||
|
||||
- **`show()`** Show the popup on the screen.
|
||||
- **`close()`** Closes the popup. Use this if you set the `close-on-click` property to false.
|
||||
|
||||
### Example
|
||||
|
||||
|
|
|
@ -138,6 +138,17 @@ cpp! {{
|
|||
}
|
||||
isMouseButtonDown = false;
|
||||
|
||||
void *parent_of_popup_to_close = nullptr;
|
||||
if (auto p = dynamic_cast<const SlintWidget*>(parent())) {
|
||||
void *parent_window = p->rust_window;
|
||||
bool close_popup = rust!(Slint_mouseReleaseEventPopup [parent_window: &QtWindow as "void*"] -> bool as "bool" {
|
||||
parent_window.close_popup_after_click()
|
||||
});
|
||||
if (close_popup) {
|
||||
parent_of_popup_to_close = parent_window;
|
||||
}
|
||||
}
|
||||
|
||||
QPoint pos = event->pos();
|
||||
int button = event->button();
|
||||
rust!(Slint_mouseReleaseEvent [rust_window: &QtWindow as "void*", pos: qttypes::QPoint as "QPoint", button: u32 as "int" ] {
|
||||
|
@ -145,11 +156,9 @@ cpp! {{
|
|||
let button = from_qt_button(button);
|
||||
rust_window.mouse_event(MouseEvent::Released{ position, button, click_count: 0 })
|
||||
});
|
||||
if (auto p = dynamic_cast<const SlintWidget*>(parent())) {
|
||||
// FIXME: better way to close the popup
|
||||
void *parent_window = p->rust_window;
|
||||
rust!(Slint_mouseReleaseEventPopup [parent_window: &QtWindow as "void*", pos: qttypes::QPoint as "QPoint"] {
|
||||
parent_window.close_popup();
|
||||
if (parent_of_popup_to_close) {
|
||||
rust!(Slint_mouseReleaseEventClosePopup [parent_of_popup_to_close: &QtWindow as "void*"] {
|
||||
parent_of_popup_to_close.close_popup();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1497,6 +1506,10 @@ impl QtWindow {
|
|||
fn close_popup(&self) {
|
||||
WindowInner::from_pub(&self.window).close_popup();
|
||||
}
|
||||
|
||||
fn close_popup_after_click(&self) -> bool {
|
||||
WindowInner::from_pub(&self.window).close_popup_after_click()
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowAdapter for QtWindow {
|
||||
|
|
|
@ -387,6 +387,7 @@ export component PopupWindow {
|
|||
in property <length> anchor_y;
|
||||
in property <length> anchor_height;
|
||||
in property <length> anchor_width;*/
|
||||
in property <bool> close-on-click: true;
|
||||
//show() is hardcoded in typeregister.rs
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ pub enum BuiltinFunction {
|
|||
Pow,
|
||||
SetFocusItem,
|
||||
ShowPopupWindow,
|
||||
ClosePopupWindow,
|
||||
/// A function that belongs to an item (such as TextInput's select-all function).
|
||||
ItemMemberFunction(String),
|
||||
/// the "42".to_float()
|
||||
|
@ -123,10 +124,12 @@ impl BuiltinFunction {
|
|||
return_type: Box::new(Type::Void),
|
||||
args: vec![Type::ElementReference],
|
||||
},
|
||||
BuiltinFunction::ShowPopupWindow => Type::Function {
|
||||
return_type: Box::new(Type::Void),
|
||||
args: vec![Type::ElementReference],
|
||||
},
|
||||
BuiltinFunction::ShowPopupWindow | BuiltinFunction::ClosePopupWindow => {
|
||||
Type::Function {
|
||||
return_type: Box::new(Type::Void),
|
||||
args: vec![Type::ElementReference],
|
||||
}
|
||||
}
|
||||
BuiltinFunction::ItemMemberFunction(..) => Type::Function {
|
||||
return_type: Box::new(Type::Void),
|
||||
args: vec![Type::ElementReference],
|
||||
|
@ -225,7 +228,7 @@ impl BuiltinFunction {
|
|||
| BuiltinFunction::Pow
|
||||
| BuiltinFunction::ATan => true,
|
||||
BuiltinFunction::SetFocusItem => false,
|
||||
BuiltinFunction::ShowPopupWindow => false,
|
||||
BuiltinFunction::ShowPopupWindow | BuiltinFunction::ClosePopupWindow => false,
|
||||
BuiltinFunction::ItemMemberFunction(..) => false,
|
||||
BuiltinFunction::StringToFloat | BuiltinFunction::StringIsFloat => true,
|
||||
BuiltinFunction::ColorBrighter
|
||||
|
@ -276,7 +279,7 @@ impl BuiltinFunction {
|
|||
| BuiltinFunction::Pow
|
||||
| BuiltinFunction::ATan => true,
|
||||
BuiltinFunction::SetFocusItem => false,
|
||||
BuiltinFunction::ShowPopupWindow => false,
|
||||
BuiltinFunction::ShowPopupWindow | BuiltinFunction::ClosePopupWindow => false,
|
||||
BuiltinFunction::ItemMemberFunction(..) => false,
|
||||
BuiltinFunction::StringToFloat | BuiltinFunction::StringIsFloat => true,
|
||||
BuiltinFunction::ColorBrighter
|
||||
|
|
|
@ -2744,7 +2744,7 @@ fn compile_builtin_function_call(
|
|||
format!("{}.text_input_focused()", access_window_field(ctx))
|
||||
}
|
||||
BuiltinFunction::ShowPopupWindow => {
|
||||
if let [llr::Expression::NumberLiteral(popup_index), x, y, llr::Expression::PropertyReference(parent_ref)] =
|
||||
if let [llr::Expression::NumberLiteral(popup_index), x, y, close_on_click, llr::Expression::PropertyReference(parent_ref)] =
|
||||
arguments
|
||||
{
|
||||
let mut parent_ctx = ctx;
|
||||
|
@ -2764,13 +2764,18 @@ fn compile_builtin_function_call(
|
|||
let parent_component = access_item_rc(parent_ref, ctx);
|
||||
let x = compile_expression(x, ctx);
|
||||
let y = compile_expression(y, ctx);
|
||||
let close_on_click = compile_expression(close_on_click, ctx);
|
||||
format!(
|
||||
"{window}.show_popup<{popup_window_id}>({component_access}, {{ static_cast<float>({x}), static_cast<float>({y}) }}, {{ {parent_component} }})"
|
||||
"{window}.show_popup<{popup_window_id}>({component_access}, {{ static_cast<float>({x}), static_cast<float>({y}) }}, {close_on_click}, {{ {parent_component} }})"
|
||||
)
|
||||
} else {
|
||||
panic!("internal error: invalid args to ShowPopupWindow {:?}", arguments)
|
||||
}
|
||||
}
|
||||
BuiltinFunction::ClosePopupWindow => {
|
||||
let window = access_window_field(ctx);
|
||||
format!("{window}.close_popup()")
|
||||
}
|
||||
BuiltinFunction::ItemMemberFunction(name) => {
|
||||
if let [llr::Expression::PropertyReference(pr)] = arguments {
|
||||
let item = access_member(pr, ctx);
|
||||
|
|
|
@ -2233,7 +2233,7 @@ fn compile_builtin_function_call(
|
|||
}
|
||||
}
|
||||
BuiltinFunction::ShowPopupWindow => {
|
||||
if let [Expression::NumberLiteral(popup_index), x, y, Expression::PropertyReference(parent_ref)] =
|
||||
if let [Expression::NumberLiteral(popup_index), x, y, close_on_click, Expression::PropertyReference(parent_ref)] =
|
||||
arguments
|
||||
{
|
||||
let mut parent_ctx = ctx;
|
||||
|
@ -2252,6 +2252,7 @@ fn compile_builtin_function_call(
|
|||
let parent_component = access_item_rc(parent_ref, ctx);
|
||||
let x = compile_expression(x, ctx);
|
||||
let y = compile_expression(y, ctx);
|
||||
let close_on_click = compile_expression(close_on_click, ctx);
|
||||
let window_adapter_tokens = access_window_adapter_field(ctx);
|
||||
quote!(
|
||||
slint::private_unstable_api::re_exports::WindowInner::from_pub(#window_adapter_tokens.window()).show_popup(
|
||||
|
@ -2261,6 +2262,7 @@ fn compile_builtin_function_call(
|
|||
instance.into()
|
||||
}),
|
||||
Point::new(#x as slint::private_unstable_api::re_exports::Coord, #y as slint::private_unstable_api::re_exports::Coord),
|
||||
#close_on_click,
|
||||
#parent_component
|
||||
)
|
||||
)
|
||||
|
@ -2268,6 +2270,12 @@ fn compile_builtin_function_call(
|
|||
panic!("internal error: invalid args to ShowPopupWindow {:?}", arguments)
|
||||
}
|
||||
}
|
||||
BuiltinFunction::ClosePopupWindow => {
|
||||
let window_adapter_tokens = access_window_adapter_field(ctx);
|
||||
quote!(
|
||||
slint::private_unstable_api::re_exports::WindowInner::from_pub(#window_adapter_tokens.window()).close_popup()
|
||||
)
|
||||
}
|
||||
BuiltinFunction::ItemMemberFunction(name) => {
|
||||
if let [Expression::PropertyReference(pr)] = arguments {
|
||||
let item = access_member(pr, ctx);
|
||||
|
|
|
@ -355,7 +355,13 @@ fn lower_show_popup(args: &[tree_Expression], ctx: &ExpressionContext) -> llr_Ex
|
|||
);
|
||||
llr_Expression::BuiltinFunctionCall {
|
||||
function: BuiltinFunction::ShowPopupWindow,
|
||||
arguments: vec![llr_Expression::NumberLiteral(popup_index as _), x, y, item_ref],
|
||||
arguments: vec![
|
||||
llr_Expression::NumberLiteral(popup_index as _),
|
||||
x,
|
||||
y,
|
||||
llr_Expression::BoolLiteral(popup.close_on_click),
|
||||
item_ref,
|
||||
],
|
||||
}
|
||||
} else {
|
||||
panic!("invalid arguments to ShowPopupWindow");
|
||||
|
|
|
@ -87,7 +87,7 @@ fn builtin_function_cost(function: &BuiltinFunction) -> isize {
|
|||
BuiltinFunction::Log => 10,
|
||||
BuiltinFunction::Pow => 10,
|
||||
BuiltinFunction::SetFocusItem => isize::MAX,
|
||||
BuiltinFunction::ShowPopupWindow => isize::MAX,
|
||||
BuiltinFunction::ShowPopupWindow | BuiltinFunction::ClosePopupWindow => isize::MAX,
|
||||
BuiltinFunction::ItemMemberFunction(..) => isize::MAX,
|
||||
BuiltinFunction::StringToFloat => 50,
|
||||
BuiltinFunction::StringIsFloat => 50,
|
||||
|
|
|
@ -203,6 +203,7 @@ pub struct PopupWindow {
|
|||
pub component: Rc<Component>,
|
||||
pub x: NamedReference,
|
||||
pub y: NamedReference,
|
||||
pub close_on_click: bool,
|
||||
pub parent_element: ElementRc,
|
||||
}
|
||||
|
||||
|
|
|
@ -344,6 +344,7 @@ fn duplicate_popup(
|
|||
PopupWindow {
|
||||
x: p.x.clone(),
|
||||
y: p.y.clone(),
|
||||
close_on_click: p.close_on_click.clone(),
|
||||
component: duplicate_sub_component(&p.component, &parent, mapping, priority_delta),
|
||||
parent_element: mapping
|
||||
.get(&element_key(p.parent_element.clone()))
|
||||
|
|
|
@ -68,6 +68,28 @@ fn lower_popup_window(
|
|||
parent_element.borrow_mut().has_popup_child = true;
|
||||
|
||||
popup_window_element.borrow_mut().base_type = window_type.clone();
|
||||
popup_window_element.borrow_mut().property_declarations.insert(
|
||||
"close-on-click".into(),
|
||||
PropertyDeclaration { property_type: Type::Bool, ..PropertyDeclaration::default() },
|
||||
);
|
||||
|
||||
let close_on_click =
|
||||
match popup_window_element.borrow_mut().bindings.remove("close-on-click").map_or_else(
|
||||
|| Ok(true),
|
||||
|binding| match binding.borrow().expression {
|
||||
Expression::BoolLiteral(value) => Ok(value),
|
||||
_ => Err(binding.borrow().span.clone()),
|
||||
},
|
||||
) {
|
||||
Ok(coc) => coc,
|
||||
Err(location) => {
|
||||
diag.push_error(
|
||||
"The close-on-click property only supports constants at the moment".into(),
|
||||
&location,
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let popup_comp = Rc::new(Component {
|
||||
root_element: popup_window_element.clone(),
|
||||
|
@ -105,6 +127,7 @@ fn lower_popup_window(
|
|||
component: popup_comp,
|
||||
x: coord_x,
|
||||
y: coord_y,
|
||||
close_on_click,
|
||||
parent_element: parent_element.clone(),
|
||||
});
|
||||
}
|
||||
|
|
14
internal/compiler/tests/syntax/elements/popup.slint
Normal file
14
internal/compiler/tests/syntax/elements/popup.slint
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||
|
||||
|
||||
export Bar := Rectangle {
|
||||
in property <bool> external;
|
||||
PopupWindow {
|
||||
close-on-click: true;
|
||||
}
|
||||
PopupWindow {
|
||||
close-on-click: root.external;
|
||||
// ^error{The close-on-click property only supports constants at the moment}
|
||||
}
|
||||
}
|
|
@ -259,7 +259,16 @@ impl TypeRegister {
|
|||
.unwrap()
|
||||
.member_functions
|
||||
.insert("show".into(), BuiltinFunction::ShowPopupWindow);
|
||||
Rc::get_mut(b).unwrap().properties.insert(
|
||||
"close".into(),
|
||||
BuiltinPropertyInfo::new(BuiltinFunction::ClosePopupWindow.ty()),
|
||||
);
|
||||
Rc::get_mut(b)
|
||||
.unwrap()
|
||||
.member_functions
|
||||
.insert("close".into(), BuiltinFunction::ClosePopupWindow);
|
||||
}
|
||||
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
|
|
@ -257,6 +257,9 @@ struct PopupWindow {
|
|||
location: PopupWindowLocation,
|
||||
/// The component that is responsible for providing the popup content.
|
||||
component: ComponentRc,
|
||||
/// If true, Slint will close the popup after any mouse click within the popup.
|
||||
/// Set to false and call close() on the PopupWindow to close it manually.
|
||||
close_on_click: bool,
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
|
@ -397,6 +400,8 @@ impl WindowInner {
|
|||
// handle multiple press release
|
||||
event = self.click_state.check_repeat(event);
|
||||
|
||||
let close_popup_after_click = self.close_popup_after_click();
|
||||
|
||||
let embedded_popup_component =
|
||||
self.active_popup.borrow().as_ref().and_then(|popup| match popup.location {
|
||||
PopupWindowLocation::TopLevel(_) => None,
|
||||
|
@ -439,9 +444,7 @@ impl WindowInner {
|
|||
self.mouse_input_state.take(),
|
||||
));
|
||||
|
||||
if embedded_popup_component.is_some() {
|
||||
//FIXME: currently the ComboBox is the only thing that uses the popup, and it should close automatically
|
||||
// on release. But ideally, there would be API to close the popup rather than always closing it on release
|
||||
if embedded_popup_component.is_some() && close_popup_after_click {
|
||||
if matches!(event, MouseEvent::Released { .. }) {
|
||||
self.close_popup();
|
||||
}
|
||||
|
@ -721,6 +724,7 @@ impl WindowInner {
|
|||
&self,
|
||||
popup_componentrc: &ComponentRc,
|
||||
position: Point,
|
||||
close_on_click: bool,
|
||||
parent_item: &ItemRc,
|
||||
) {
|
||||
let position = parent_item.map_to_window(
|
||||
|
@ -774,11 +778,15 @@ impl WindowInner {
|
|||
}
|
||||
};
|
||||
|
||||
self.active_popup
|
||||
.replace(Some(PopupWindow { location, component: popup_componentrc.clone() }));
|
||||
self.active_popup.replace(Some(PopupWindow {
|
||||
location,
|
||||
component: popup_componentrc.clone(),
|
||||
close_on_click,
|
||||
}));
|
||||
}
|
||||
|
||||
/// Removes any active popup.
|
||||
/// TODO: this function should take a component ref as parameter, to close a specific popup - i.e. when popup menus create a hierarchy of popups.
|
||||
pub fn close_popup(&self) {
|
||||
if let Some(current_popup) = self.active_popup.replace(None) {
|
||||
if let PopupWindowLocation::ChildWindow(offset) = current_popup.location {
|
||||
|
@ -798,6 +806,11 @@ impl WindowInner {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if the currently active popup is configured to close on click. None if there is no active popup.
|
||||
pub fn close_popup_after_click(&self) -> bool {
|
||||
self.active_popup.borrow().as_ref().map_or(false, |popup| popup.close_on_click)
|
||||
}
|
||||
|
||||
/// Returns the scale factor set on the window, as provided by the windowing system.
|
||||
pub fn scale_factor(&self) -> f32 {
|
||||
self.pinned_fields.as_ref().project_ref().scale_factor.get()
|
||||
|
@ -1015,12 +1028,19 @@ pub mod ffi {
|
|||
handle: *const WindowAdapterRcOpaque,
|
||||
popup: &ComponentRc,
|
||||
position: crate::graphics::Point,
|
||||
close_on_click: bool,
|
||||
parent_item: &ItemRc,
|
||||
) {
|
||||
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
|
||||
WindowInner::from_pub(window_adapter.window()).show_popup(popup, position, parent_item);
|
||||
WindowInner::from_pub(window_adapter.window()).show_popup(
|
||||
popup,
|
||||
position,
|
||||
close_on_click,
|
||||
parent_item,
|
||||
);
|
||||
}
|
||||
/// Close the current popup
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_windowrc_close_popup(handle: *const WindowAdapterRcOpaque) {
|
||||
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
|
||||
WindowInner::from_pub(window_adapter.window()).close_popup();
|
||||
|
|
|
@ -1745,6 +1745,7 @@ impl<'a, 'id> InstanceRef<'a, 'id> {
|
|||
pub fn show_popup(
|
||||
popup: &object_tree::PopupWindow,
|
||||
pos: i_slint_core::graphics::Point,
|
||||
close_on_click: bool,
|
||||
parent_comp: ComponentRefPin,
|
||||
parent_window_adapter: &Rc<dyn WindowAdapter>,
|
||||
parent_item: &ItemRc,
|
||||
|
@ -1757,6 +1758,7 @@ pub fn show_popup(
|
|||
WindowInner::from_pub(parent_window_adapter.window()).show_popup(
|
||||
&vtable::VRc::into_dyn(inst),
|
||||
pos,
|
||||
close_on_click,
|
||||
parent_item,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -572,6 +572,7 @@ fn call_builtin_function(
|
|||
x.try_into().unwrap(),
|
||||
y.try_into().unwrap(),
|
||||
),
|
||||
popup.close_on_click,
|
||||
component.borrow(),
|
||||
window_adapter_ref(component).unwrap(),
|
||||
&parent_item,
|
||||
|
@ -581,6 +582,18 @@ fn call_builtin_function(
|
|||
panic!("internal error: argument to SetFocusItem must be an element")
|
||||
}
|
||||
}
|
||||
BuiltinFunction::ClosePopupWindow => {
|
||||
let component = match local_context.component_instance {
|
||||
ComponentInstance::InstanceRef(c) => c,
|
||||
ComponentInstance::GlobalComponent(_) => {
|
||||
panic!("Cannot show popup from a global component")
|
||||
}
|
||||
};
|
||||
|
||||
window_ref(component).unwrap().close_popup();
|
||||
|
||||
Value::Void
|
||||
}
|
||||
BuiltinFunction::ItemMemberFunction(name) => {
|
||||
if arguments.len() != 1 {
|
||||
panic!("internal error: incorrect argument count to item member function call")
|
||||
|
|
195
tests/cases/elements/popupwindow_close.slint
Normal file
195
tests/cases/elements/popupwindow_close.slint
Normal file
|
@ -0,0 +1,195 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||
|
||||
export component TestCase {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
|
||||
in-out property <bool> popup-created;
|
||||
in-out property <int> click-count;
|
||||
in-out property <int> popup-selector: 0;
|
||||
|
||||
default-popup := PopupWindow {
|
||||
width: parent.width;
|
||||
height: parent.height;
|
||||
Text {
|
||||
text: "I'm a default";
|
||||
}
|
||||
init => {
|
||||
root.popup-created = true;
|
||||
}
|
||||
}
|
||||
|
||||
self-closing-popup := PopupWindow {
|
||||
close-on-click: false;
|
||||
width: parent.width;
|
||||
height: parent.height;
|
||||
Text {
|
||||
text: "I'm a self-closing popup";
|
||||
}
|
||||
TouchArea {
|
||||
clicked => {
|
||||
self-closing-popup.close();
|
||||
}
|
||||
}
|
||||
init => {
|
||||
root.popup-created = true;
|
||||
}
|
||||
}
|
||||
|
||||
never-closing-popup := PopupWindow {
|
||||
close-on-click: false;
|
||||
width: parent.width;
|
||||
height: parent.height;
|
||||
Text {
|
||||
text: "I'm a popup that never closes";
|
||||
}
|
||||
TouchArea {
|
||||
clicked => {
|
||||
}
|
||||
}
|
||||
init => {
|
||||
root.popup-created = true;
|
||||
}
|
||||
}
|
||||
|
||||
TouchArea {
|
||||
clicked => {
|
||||
root.click-count = root.click-count + 1;
|
||||
if (root.popup-selector == 0) {
|
||||
root.popup-selector = 3;
|
||||
default-popup.show();
|
||||
} else if (root.popup-selector == 1) {
|
||||
root.popup-selector = 3;
|
||||
self-closing-popup.show();
|
||||
} else if (root.popup-selector == 2) {
|
||||
root.popup-selector = 3;
|
||||
never-closing-popup.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
```rust
|
||||
let instance = TestCase::new().unwrap();
|
||||
|
||||
assert_eq!(instance.get_click_count(), 0);
|
||||
assert_eq!(instance.get_popup_created(), false);
|
||||
|
||||
instance.set_popup_selector(0);
|
||||
instance.set_popup_created(false);
|
||||
instance.set_click_count(0);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq!(instance.get_click_count(), 1);
|
||||
assert_eq!(instance.get_popup_created(), true);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq!(instance.get_click_count(), 1);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq!(instance.get_click_count(), 2);
|
||||
|
||||
instance.set_popup_selector(1);
|
||||
instance.set_popup_created(false);
|
||||
instance.set_click_count(0);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq!(instance.get_click_count(), 1);
|
||||
assert_eq!(instance.get_popup_created(), true);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq!(instance.get_click_count(), 1);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq!(instance.get_click_count(), 2);
|
||||
|
||||
instance.set_popup_selector(2);
|
||||
instance.set_popup_created(false);
|
||||
instance.set_click_count(0);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq!(instance.get_click_count(), 1);
|
||||
assert_eq!(instance.get_popup_created(), true);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq!(instance.get_click_count(), 1);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq!(instance.get_click_count(), 1);
|
||||
```
|
||||
|
||||
```cpp
|
||||
auto handle = TestCase::create();
|
||||
const TestCase &instance = *handle;
|
||||
|
||||
assert_eq(instance.get_click_count(), 0);
|
||||
assert_eq(instance.get_popup_created(), false);
|
||||
|
||||
instance.set_popup_selector(0);
|
||||
instance.set_popup_created(false);
|
||||
instance.set_click_count(0);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq(instance.get_click_count(), 1);
|
||||
assert_eq(instance.get_popup_created(), true);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq(instance.get_click_count(), 1);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq(instance.get_click_count(), 2);
|
||||
|
||||
instance.set_popup_selector(1);
|
||||
instance.set_popup_created(false);
|
||||
instance.set_click_count(0);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq(instance.get_click_count(), 1);
|
||||
assert_eq(instance.get_popup_created(), true);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq(instance.get_click_count(), 1);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq(instance.get_click_count(), 2);
|
||||
|
||||
instance.set_popup_selector(2);
|
||||
instance.set_popup_created(false);
|
||||
instance.set_click_count(0);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq(instance.get_click_count(), 1);
|
||||
assert_eq(instance.get_popup_created(), true);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq(instance.get_click_count(), 1);
|
||||
slint_testing::send_mouse_click(&instance, 5., 5.);
|
||||
assert_eq(instance.get_click_count(), 1);
|
||||
```
|
||||
|
||||
```js
|
||||
var instance = new slint.TestCase({});
|
||||
|
||||
assert.equal(instance.click_count, 0);
|
||||
assert.equal(instance.popup_created, false);
|
||||
|
||||
instance.popup_selector = 0;
|
||||
instance.popup_created = false;
|
||||
instance.click_count = 0;
|
||||
instance.send_mouse_click(5., 5.);
|
||||
assert.equal(instance.click_count, 1);
|
||||
assert.equal(instance.popup_created, true);
|
||||
instance.send_mouse_click(5., 5.);
|
||||
assert.equal(instance.click_count, 1);
|
||||
instance.send_mouse_click(5., 5.);
|
||||
assert.equal(instance.click_count, 2);
|
||||
|
||||
instance.popup_selector = 1;
|
||||
instance.popup_created = false;
|
||||
instance.click_count = 0;
|
||||
instance.send_mouse_click(5., 5.);
|
||||
assert.equal(instance.click_count, 1);
|
||||
assert.equal(instance.popup_created, true);
|
||||
instance.send_mouse_click(5., 5.);
|
||||
assert.equal(instance.click_count, 1);
|
||||
instance.send_mouse_click(5., 5.);
|
||||
assert.equal(instance.click_count, 2);
|
||||
|
||||
instance.popup_selector = 2;
|
||||
instance.popup_created = false;
|
||||
instance.click_count = 0;
|
||||
instance.send_mouse_click(5., 5.);
|
||||
assert.equal(instance.click_count, 1);
|
||||
assert.equal(instance.popup_created, true);
|
||||
instance.send_mouse_click(5., 5.);
|
||||
assert.equal(instance.click_count, 1);
|
||||
instance.send_mouse_click(5., 5.);
|
||||
assert.equal(instance.click_count, 1);
|
||||
```
|
||||
|
||||
*/
|
Loading…
Add table
Add a link
Reference in a new issue