Support deleting GUI Object event handlers following rP666, refs #5387.
[0ad.git] / binaries / data / mods / public / gui / pregame / MainMenuItemHandler.js
blobae2e467a99da5c60db00c85fb3a5bc3c8aff717b
1 /**
2  * This class sets up the main menu buttons, animates submenu that opens when
3  * clicking on category buttons, assigns the defined actions and hotkeys to every button.
4  */
5 class MainMenuItemHandler
7         constructor(menuItems)
8         {
9                 this.menuItems = menuItems;
10                 this.lastTickTime = Date.now();
12                 this.mainMenu = Engine.GetGUIObjectByName("mainMenu");
13                 this.mainMenuButtons = Engine.GetGUIObjectByName("mainMenuButtons");
14                 this.submenu = Engine.GetGUIObjectByName("submenu");
15                 this.submenuButtons = Engine.GetGUIObjectByName("submenuButtons");
16                 this.MainMenuPanelRightBorderTop = Engine.GetGUIObjectByName("MainMenuPanelRightBorderTop");
17                 this.MainMenuPanelRightBorderBottom = Engine.GetGUIObjectByName("MainMenuPanelRightBorderBottom");
19                 this.setupMenuButtons(this.mainMenuButtons.children, this.menuItems);
20                 this.setupHotkeys(this.menuItems);
22                 Engine.GetGUIObjectByName("closeMenuButton").onPress = this.closeSubmenu.bind(this);
23         }
25         setupMenuButtons(buttons, menuItems)
26         {
27                 buttons.forEach((button, i) => {
28                         let item = menuItems[i];
29                         button.hidden = !item;
30                         if (button.hidden)
31                                 return;
33                         button.size = new GUISize(
34                                 0, (this.ButtonHeight + this.Margin) * i,
35                                 0, (this.ButtonHeight + this.Margin) * i + this.ButtonHeight,
36                                 0, 0, 100, 0);
37                         button.caption = item.caption;
38                         button.tooltip = item.tooltip;
39                         button.enabled = item.enabled === undefined || item.enabled;
40                         button.onPress = () => {
41                                 this.closeSubmenu();
43                                 if (item.onPress)
44                                         item.onPress();
45                                 else
46                                         this.openSubmenu(i);
47                         };
48                         button.hidden = false;
49                 });
51                 if (buttons.length < menuItems.length)
52                         error("GUI page has space for " + buttons.length + " menu buttons, but " + menuItems.length + " items are provided!");
53         }
55         setupHotkeys(menuItems)
56         {
57                 for (let i in menuItems)
58                 {
59                         let item = menuItems[i];
60                         if (item.onPress && item.hotkey)
61                                 Engine.SetGlobalHotkey(item.hotkey, () => {
62                                         this.closeSubmenu();
63                                         item.onPress();
64                                 });
66                         if (item.submenu)
67                                 this.setupHotkeys(item.submenu);
68                 }
69         }
71         openSubmenu(i)
72         {
73                 this.setupMenuButtons(this.submenuButtons.children, this.menuItems[i].submenu);
75                 let top = this.mainMenuButtons.size.top + this.mainMenuButtons.children[i].size.top;
77                 this.submenu.size = new GUISize(
78                         this.submenu.size.left, top - this.Margin,
79                         this.submenu.size.right, top + (this.ButtonHeight + this.Margin) * this.menuItems[i].submenu.length);
81                 this.submenu.hidden = false;
83                 {
84                         let size = this.MainMenuPanelRightBorderTop.size;
85                         size.bottom = this.submenu.size.top + this.Margin;
86                         size.rbottom = 0;
87                         this.MainMenuPanelRightBorderTop.size = size;
88                 }
90                 {
91                         let size = this.MainMenuPanelRightBorderBottom.size;
92                         size.top = this.submenu.size.bottom;
93                         this.MainMenuPanelRightBorderBottom.size = size;
94                 }
96                 // Start animation
97                 this.lastTickTime = Date.now();
98                 this.mainMenu.onTick = this.onTick.bind(this);
99         }
101         closeSubmenu()
102         {
103                 this.submenu.hidden = true;
104                 this.submenu.size = this.mainMenu.size;
106                 let size = this.MainMenuPanelRightBorderTop.size;
107                 size.top = 0;
108                 size.bottom = 0;
109                 size.rbottom = 100;
110                 this.MainMenuPanelRightBorderTop.size = size;
111         }
113         onTick()
114         {
115                 let now = Date.now();
116                 if (now == this.lastTickTime)
117                         return;
119                 let maxOffset = this.mainMenu.size.right - this.submenu.size.left;
120                 let offset = Math.min(this.MenuSpeed * (now - this.lastTickTime), maxOffset);
122                 this.lastTickTime = now;
124                 if (this.submenu.hidden || !offset)
125                 {
126                         delete this.mainMenu.onTick;
127                         return;
128                 }
130                 let size = this.submenu.size;
131                 size.left += offset;
132                 size.right += offset;
133                 this.submenu.size = size;
134         }
138  * Vertical size per button.
139  */
140 MainMenuItemHandler.prototype.ButtonHeight = 28;
143  * Distance between consecutive buttons.
144  */
145 MainMenuItemHandler.prototype.Margin = 4;
148  * Collapse / expansion speed in pixels per milliseconds used when animating the button menu size.
149  */
150 MainMenuItemHandler.prototype.MenuSpeed = 1.2;