1 module rpui.widgets.list_menu_item.widget;
2 
3 import rpui.events;
4 import rpui.widget_events;
5 import rpui.input;
6 import rpui.math;
7 import rpui.primitives;
8 import rpui.widget;
9 import rpui.widgets.button.widget;
10 import rpui.widgets.list_menu.widget;
11 import rpui.widgets.list_menu_item.renderer;
12 import rpui.widgets.drop_list_menu.drop_menu_delegate;
13 
14 interface MenuActions {
15     void hideMenu();
16 
17     MenuActions parentActions();
18 }
19 
20 class ListMenuItem : Button, MenuActions {
21     @field string shortcut = "";
22 
23     private ListMenu parentMenu = null;
24     package ListMenu menu = null;
25     private DropMenuDelegate dropMenuDelegate;
26 
27     this(in string style = "ListMenuItem") {
28         super(style);
29 
30         this.renderer = new ListMenuItemRenderer();
31         this.textAlign = Align.left;
32         this.widthType = SizeType.matchParent;
33         this.focusable = false;
34     }
35 
36     protected override void onPostCreate() {
37         super.onPostCreate();
38 
39         if (menu !is null)
40             return;
41 
42         // Because item places in wrapper called Cell.
43         parentMenu = cast(ListMenu) parent.parent;
44         assert(parentMenu !is null);
45 
46         if (parentMenu.isPopup) {
47             uselessIconArea = 1;
48         }
49 
50         events.subscribe!ClickEvent(&onClick);
51         attachShortcut();
52 
53         if (children.empty)
54             return;
55 
56         menu = cast(ListMenu)(children.front);
57 
58         if (menu is null)
59             return;
60 
61         menu.isVisible = false;
62         menu.focusable = false;
63         view.moveWidgetToFront(menu);
64 
65         dropMenuDelegate.attach(menu, this);
66 
67         // submenuDisplayTimeout = createTimeout(menu.displayDelay, delegate() {
68             if (isEnter) {
69                 dropMenuDelegate.dropMenu(vec2(size.x, 0) + menu.measure.rightPopupOffset);
70             }
71         // });
72     }
73 
74     void attachShortcut() {
75         if (shortcut.length == 0)
76             return;
77 
78         if (shortcut[0] == '@') {
79             const shortcutPath = shortcut[1 .. $];
80             view.shortcuts.attachByPath(shortcutPath, () => events.notify(ClickEvent()));
81         } else {
82             view.shortcuts.attach(shortcut, () => events.notify(ClickEvent()));
83         }
84     }
85 
86     override void onProgress(in ProgressEvent event) {
87         super.onProgress(event);
88 
89         // submenuDisplayTimeout.onProgress(app.deltaTime);
90 
91         if (isEnter) {
92             parentMenu.hideAllSubMenusExcept(this);
93         }
94 
95         // if (isEnter && !submenuDisplayTimeout.isStarted()) {
96             // submenuDisplayTimeout.start();
97         // }
98 
99         if (dropMenuDelegate.isAttached()) {
100             dropMenuDelegate.onProgress(vec2(size.x, 0) + menu.measure.rightPopupOffset);
101             overrideIsEnter = dropMenuDelegate.isInVisibilityArea && menu.isVisible;
102         }
103     }
104 
105     private void onClick() {
106         if (menu is null)
107             hideRootMenu();
108 
109         if (dropMenuDelegate.isAttached()) {
110             dropMenuDelegate.dropMenu(vec2(size.x, 0) + menu.measure.rightPopupOffset);
111         }
112     }
113 
114     override void focus() {
115         /* Ignore */
116     }
117 
118     override void hideMenu() {
119         if (dropMenuDelegate.isAttached()) {
120             dropMenuDelegate.hideMenu();
121         }
122     }
123 
124     private void hideRootMenu() {
125         MenuActions currentMenuActions = this;
126         MenuActions parentMenuActions = parentActions();
127 
128         while (parentMenuActions !is null) {
129             currentMenuActions = parentMenuActions;
130             parentMenuActions = parentMenuActions.parentActions();
131         }
132 
133         currentMenuActions.hideMenu();
134     }
135 
136     override MenuActions parentActions() {
137         auto actions = cast(MenuActions) parentMenu.owner;
138         return actions;
139     }
140 }