freya_components/
context_menu.rs1use freya_core::{
2 integration::ScopeId,
3 prelude::*,
4};
5use torin::prelude::CursorPoint;
6
7use crate::menu::Menu;
8
9#[derive(Clone, Copy, PartialEq)]
10pub(crate) enum ContextMenuCloseRequest {
11 None,
12 Pending,
13}
14
15#[derive(Clone, Copy, PartialEq)]
33pub struct ContextMenu {
34 pub(crate) location: State<CursorPoint>,
35 pub(crate) menu: State<Option<(CursorPoint, Menu)>>,
36 pub(crate) close_request: State<ContextMenuCloseRequest>,
37}
38
39impl ContextMenu {
40 pub fn get() -> Self {
41 match try_consume_root_context() {
42 Some(rt) => rt,
43 None => {
44 let context_menu_state = ContextMenu {
45 location: State::create_in_scope(CursorPoint::default(), ScopeId::ROOT),
46 menu: State::create_in_scope(None, ScopeId::ROOT),
47 close_request: State::create_in_scope(
48 ContextMenuCloseRequest::None,
49 ScopeId::ROOT,
50 ),
51 };
52 provide_context_for_scope_id(context_menu_state, ScopeId::ROOT);
53 context_menu_state
54 }
55 }
56 }
57
58 pub fn is_open() -> bool {
59 Self::get().menu.read().is_some()
60 }
61
62 pub fn open(menu: Menu) {
66 let mut this = Self::get();
67 this.menu.set(Some(((this.location)(), menu)));
68 this.close_request.set(ContextMenuCloseRequest::None);
69 }
70
71 pub fn open_from_event(event: &Event<PressEventData>, menu: Menu) {
77 let mut this = Self::get();
78 this.menu.set(Some(((this.location)(), menu)));
79
80 let close_request = match event.data() {
81 PressEventData::Mouse(mouse) if mouse.button == Some(MouseButton::Left) => {
82 ContextMenuCloseRequest::Pending
83 }
84 _ => ContextMenuCloseRequest::None,
85 };
86 this.close_request.set(close_request);
87 }
88
89 pub fn close() {
90 Self::get().menu.set(None);
91 }
92}