forked from ChrisS85/CGUI
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathCMenu.ahk
366 lines (336 loc) · 10.2 KB
/
CMenu.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
/*
Class: CMenu
CMenu represents a menu which can contain other menus and <CMenu.CMenuItem>
*/
Class CMenu
{
static Menus := [] ;All menu objects are stored statically in CMenu for easier callback routing. This means that all submenus must have unique names.
_ := {Checked : 0, Enabled : 1, Default : 0}
/*
Function: __New
Creates a new Menu object. Name must be unique through the whole application.
*/
__New(Name)
{
this.Name := Name
if(!CGUI_Assert(!this.Menus.HasKey(Name), "Menu Name" Name " is not unique! Submenus must have unique names!"))
return
this.Menus[Name] := this
;Add a temporary menu entry and delete it again to create an empty menu
Menu, % this.Name, Add, Test, CMenu_Callback
Menu, % this.Name, Delete, Test
}
/*
Function: AddSubMenu
Adds a submenu to this menu.
Parameters:
Text - The name under which the submenu will appear in this menu
NameOrMenuObject - Either the name of a new menu or an existing CMenu instance.
*/
AddSubMenu(Text, NameOrMenuObject)
{
if(!CGUI_Assert(!this.IsDisposed, "This menu is disposed and nothing can be added to it anymore."))
return
if(CGUI_TypeOf(NameOrMenuObject) = "CMenu")
Menu := NameOrMenuObject
else if(!IsObject(NameOrMenuObject))
Menu := new this(NameOrMenuObject)
else
CGUI_Assert(0, "Invalid parameter NameOrMenuObject: " NameOrMenuObject " in CMenu.AddSubmenu()", -1)
if(CGUI_TypeOf(Menu) = "CMenu")
{
Menu._.Insert("Text", Text)
Menu.Insert("Parent", this.Name)
this.Insert(Menu)
Menu, % this.Name, Add, %Text%, % ":" Menu.Name
}
else
CGUI_Assert(0, "Failed to create submenu")
}
/*
Function: AddMenuItem
Adds a menu item to this menu. The menu item object is <CMenu.CMenuItem>
Parameters:
Text - The text of the menu item in this menu.
Callback - A function that will be called when the menu item is clicked. This function is usually located within a derived class of CGUI. If the Menu is shown through CGUI.ShowMenu() or added as menu bar to a window this parameter can simply be the name of the function contained in the derived class of CGUI.
*/
AddMenuItem(Text, Callback = "")
{
if(!CGUI_Assert(!this.IsDisposed, "This menu is disposed and nothing can be added to it anymore."))
return
this.Insert(new this.CMenuItem(Text, this.Name, Callback))
}
/*
Function: AddSeparator
Adds a separator to the menu
*/
AddSeparator()
{
if(!CGUI_Assert(!this.IsDisposed, "This menu is disposed and nothing can be added to it anymore."))
return
Menu, % this.Name, Add
}
/*
Function: DeleteMenuItem
Deletes a menu item from the menu. ObjectIndexOrName can either be a menu/submenu object, the index of the item in this menu or its name.
If ObjectIndexOrName is a menu item, it will be disposed. If it is a submenu, it will not be disposed so it can be reused elsewhere.
Returns: The deleted menu item
*/
DeleteMenuItem(ObjectIndexOrName)
{
if(!CGUI_Assert(!this.IsDisposed, "This menu is disposed and it's no longer possible to delete menu items from it."))
return
if(IsObject(CGUI_TypeOf(ObjectIndexOrName)))
Menu := ObjectIndexOrName
else if ObjectIndexOrName is Integer
Menu := this[ObjectIndexOrName]
else
Loop % this.MaxIndex()
if(A_Index = ObjectIndexOrName)
{
Menu := this[A_Index]
break
}
if(CGUI_TypeOf(Menu) = "CMenu")
{
Menu.Remove("Text")
Menu, % this.Name, Delete, % Menu.Text
this.Remove(CGUI_IndexOf(this, Menu))
}
else if(CGUI_TypeOf(Menu) = "CMenu.CMenuItem")
{
Menu, % this.Name, Delete, % Menu.Text
this.Remove(CGUI_IndexOf(this, Menu))
Menu.IsDisposed := true
}
}
/*
Function: DisposeMenu()
Disposes the menu so that it can be deleted and its resources are freed. After calling this function the menu won't be usable anymore.
*/
DisposeMenu()
{
if(!CGUI_Assert(!this.IsDisposed, "This menu is already disposed."))
return
this.Menus.Remove(this.Name)
Menu, % this.Name, Delete
this.IsDisposed := true
}
RouteCallback()
{
Item := this.Menus[A_ThisMenu][A_ThisMenuItemPos]
if(IsObject(Item) && Item.HasKey("Callback"))
{
GUI := CGUI.GUIList[A_GUI ? A_GUI : this.LastGUI]
if(GUI)
GUI[Item.Callback]()
else
{
func := Item.Callback
%func%()
}
}
}
/*
Function: Show
Shows the menu. For most cases, this function is not called directly. Instead, use <CGUI.ShowMenu>.
Parameters:
GUINum - The GUI number of the window owning this menu. This is required if the callback functions are contained in a class deriving from CGUI. Leave it empty to use global callback functions
X - X position of the menu.
Y - Y position of the menu.
*/
Show(GUINum, X="", Y="")
{
if(!CGUI_Assert(!this.IsDisposed, "This menu is disposed and can not be shown anymore."))
return
this.Base.LastGUI := GUINum
Menu,% this.Name, Show, %X%, %Y%
}
/*
Function: SetIcon
Sets the icon of this menu item.
Parameters:
Icon - The path to the icon file.
IconNumber - The number of the icon in a group
IconWidth - The width of an icon (>0), a resource identifier (<0) or the actual size of the icon (=0). Use the latter if you have transparency issues.
*/
SetIcon(Icon, IconNumber = 1, IconWidth = 0)
{
this._.Icon := Icon
this._.IconNumber := IconNumber
this._.IconWidth := IconWidth
Menu, % this.Parent, Icon, % this.Name, %Icon%, %IconNumber%, %IconWidth%
}
/*
Property: Text
The text under which this menu appears as a submenu in another menu.
Property: Enabled
Sets whether this submenu is enabled/disabled.
Property: Checked
Sets whether this submenu has a checkmark.
Property: Default
Sets whether this submenu is rendered with bold font.
Property: Icon
The path to the icon of the menu item.
Property: IconNumber
The number of the menu item icon in a grouped icon file.
Property: IconWidth
The width of an icon (>0), a resource identifier (<0) or the actual size of the icon (=0). Use the latter if you have transparency issues.
*/
__Set(Name, Value)
{
Handled := true
if(Name = "Text")
{
if(CGUI_Assert(CGUI_TypeOf(this.Menus[this.Parent]) = "CMenu", "Can't set Text on a menu object that is no submenu.") && CGUI_Assert(!this.IsDisposed, "This menu is disposed and can not be changed anymore."))
{
Menu, % this.Parent, Rename, % this.Text, %Value%
this.Insert("Text", Value)
}
}
else if(Name = "Enabled")
{
this._.Enabled := Value
if(Value)
Menu, % this.Parent, Enable, % this.Text
else
Menu, % this.Parent, Disable, % this.Text
}
else if(Name = "Checked")
{
this._.Checked := Value
if(Value)
Menu, % this.Parent, Check, % this.Text
else
Menu, % this.Parent, UnCheck, % this.Text
}
else if(Name = "Default")
{
if(Value)
{
Menu, % this.Parent, Default, % this.Text
Loop % this.Menus[this.Parent].MaxIndex() ;Set all other default properties in this menu to false
if(this.Menus[this.Parent][A_Index]._.Default)
this.Menus[this.Parent][A_Index]._.Default := false
}
else
Menu, % this.Menu, NoDefault
this._.Insert("Default", Value)
}
else if(Name = "Icon")
this.SetIcon(Value)
else if(Name = "IconNumber")
this.SetIcon(this.Icon, Value, this._.HasKey("IconWidth") ? this._.IconWidth : 0)
else if(Name = "IconWidth")
this.SetIcon(this.Icon, this._.HasKey("IconNumber") ? this._.IconNumber : 1, Value)
else
Handled := false
if(Handled)
return Value
}
/*
Class: CMenu.CMenuItem
A menu item in a <CMenu>. This class is not instantiated directly. Instead, use <CMenu.AddMenuItem>.
*/
Class CMenuItem
{
_ := {Checked : 0, Enabled : 1, Default : 0}
__New(Text, Menu, Callback="")
{
this._.Insert("Text", Text)
this.Callback := Callback
this.Menu := Menu
Menu, % this.Menu, Add, %Text%, CMenu_Callback
}
__Get(Name)
{
if(this._.HasKey(Name))
return this._[Name]
}
/*
Function: SetIcon
Sets the icon of this menu item.
Parameters:
Icon - The path to the icon file.
IconNumber - The number of the icon in a group
IconWidth - The width of an icon (>0), a resource identifier (<0) or the actual size of the icon (=0). Use the latter if you have transparency issues.
*/
SetIcon(Icon, IconNumber = 1, IconWidth = 0)
{
this._.Icon := Icon
this._.IconNumber := IconNumber
this._.IconWidth := IconWidth
Menu, % this.Menu, Icon, % this.Text, %Icon%, %IconNumber%, %IconWidth%
}
/*
Property: Text
The text of this menu item.
Property: Enabled
Sets whether this menu item is enabled/disabled.
Property: Checked
Sets whether this menu item has a checkmark.
Property: Default
Sets whether this menu item is rendered with bold font.
Property: Icon
The path to the icon of the menu item.
Property: IconNumber
The number of the menu item icon in a grouped icon file.
Property: IconWidth
The width of an icon (>0), a resource identifier (<0) or the actual size of the icon (=0). Use the latter if you have transparency issues.
*/
__Set(Name, Value)
{
Handled := true
if(Name = "Text")
{
if(CGUI_Assert(!this.IsDisposed, "This menu is disposed and can not be changed anymore."))
{
Menu, % this.Menu, Rename, % this.Text, %Value%
this._.Insert("Text", Value)
}
}
else if(Name = "Enabled")
{
this._.Insert("Enabled", Value)
if(Value)
Menu, % this.Menu, Enable, % this.Text
else
Menu, % this.Menu, Disable, % this.Text
}
else if(Name = "Checked")
{
this._.Insert("Checked", Value)
if(Value)
Menu, % this.Menu, Check, % this.Text
else
Menu, % this.Menu, UnCheck, % this.Text
}
else if(Name = "Default")
{
if(Value)
{
Menu, % this.Menu, Default, % this.Text
Loop % CMenu.Menus[this.Menu].MaxIndex() ;Set all other default properties in this menu to false
if(CMenu.Menus[this.Menu][A_Index]._.Default)
CMenu.Menus[this.Menu][A_Index]._.Default := false
}
else
Menu, % this.Menu, NoDefault
this._.Insert("Default", Value)
}
else if(Name = "Icon")
this.SetIcon(Value)
else if(Name = "IconNumber")
this.SetIcon(this.Icon, Value, this._.HasKey("IconWidth") ? this._.IconWidth : 0)
else if(Name = "IconWidth")
this.SetIcon(this.Icon, this._.HasKey("IconNumber") ? this._.IconNumber : 1, Value)
else
Handled := false
if(Handled)
return Value
}
}
}
CMenu_Callback:
CMenu.RouteCallback()
return