Support deleting GUI Object event handlers following rP666, refs #5387.
[0ad.git] / binaries / data / mods / public / gui / session / Menu.js
blob2560aa1e5896a7d3b62c084c8447e70b018a975f
1 /**
2  * This class constructs and positions the menu buttons and assigns the handlers defined in MenuButtons.
3  */
4 class Menu
6         constructor(pauseControl, playerViewControl, chat)
7         {
8                 this.menuButton = Engine.GetGUIObjectByName("menuButton");
9                 this.menuButton.onPress = this.toggle.bind(this);
10                 registerHotkeyChangeHandler(this.rebuild.bind(this));
12                 this.isOpen = false;
13                 this.lastTick = undefined;
15                 this.menuButtonPanel = Engine.GetGUIObjectByName("menuButtonPanel");
16                 let menuButtons = this.menuButtonPanel.children;
17                 this.margin = menuButtons[0].size.top;
18                 this.buttonHeight = menuButtons[0].size.bottom;
20                 let handlerNames = this.getHandlerNames();
21                 if (handlerNames.length > menuButtons.length)
22                         throw new Error(
23                                 "There are " + handlerNames.length + " menu buttons defined, " +
24                                 "but only " + menuButtons.length  + " objects!");
26                 this.buttons = handlerNames.map((handlerName, i) => {
27                         let handler = new MenuButtons.prototype[handlerName](menuButtons[i], pauseControl, playerViewControl, chat);
28                         this.initButton(handler, menuButtons[i], i);
29                         return handler;
30                 });
32                 this.endPosition = this.margin + this.buttonHeight * (1 + handlerNames.length);
33                 let size = this.menuButtonPanel.size;
34                 size.top = -this.endPosition;
35                 size.bottom = 0;
36                 this.menuButtonPanel.size = size;
37         }
39         rebuild()
40         {
41                 this.menuButton.tooltip = sprintf(translate("Press %(hotkey)s to toggle this menu."), {
42                         "hotkey": colorizeHotkey("%(hotkey)s", this.menuButton.hotkey),
43                 });
44         }
46         /**
47          * This function may be overwritten to change the button order.
48          */
49         getHandlerNames()
50         {
51                 return Object.keys(MenuButtons.prototype);
52         }
54         toggle()
55         {
56                 this.isOpen = !this.isOpen;
57                 this.startAnimation();
58         }
60         close()
61         {
62                 this.isOpen = false;
63                 this.startAnimation();
64         }
66         initButton(handler, button, i)
67         {
68                 button.onPress = () => {
69                         this.close();
70                         handler.onPress();
71                 };
73                 let size = button.size;
74                 size.top = this.buttonHeight * (i + 1) + this.margin;
75                 size.bottom = this.buttonHeight * (i + 2);
76                 button.size = size;
78                 button.hidden = false;
79         }
81         startAnimation()
82         {
83                 this.lastTick = Date.now();
84                 this.menuButtonPanel.onTick = this.onTick.bind(this);
85         }
87         /**
88          * Animate menu panel.
89          */
90         onTick()
91         {
92                 let tickLength = Date.now() - this.lastTick;
93                 this.lastTick = Date.now();
95                 let maxOffset =
96                         this.endPosition + (
97                         this.isOpen ?
98                                 -this.menuButtonPanel.size.bottom :
99                                 +this.menuButtonPanel.size.top);
102                 if (maxOffset <= 0)
103                 {
104                         delete this.menuButtonPanel.onTick;
105                         return;
106                 }
108                 let offset = Math.min(this.Speed * tickLength, maxOffset) * (this.isOpen ? +1 : -1);
109                 let size = this.menuButtonPanel.size;
110                 size.top += offset;
111                 size.bottom += offset;
112                 this.menuButtonPanel.size = size;
113         }
117  * Number of pixels per millisecond to move.
118  */
119 Menu.prototype.Speed = 1.2;