1 /******************************************************************************
2 *
3 * Copyright (C) 2004-2007, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * ID: vis.menu 18.07.07 0.0.A.
11 *
12 * Author: Alexander Krivonogov ( gentee )
13 *
14 ******************************************************************************/
15
16 define {
17 SHORTKEY_MAX = 0x7C
18 }
19
20 type shortkey
21 {
22 uint mstate
23 uint key
24 uint next
25 /*uint altmstate
26 uint altkey
27 uint altnext*/
28 str pcaption
29 }
30
31 global {
32 hash hshortkey of uint
33 }
34 func shortkey_init <entry>
35 {
36 uint i
37 collection names = %{ "Shift", "Ctrl", "Alt", "Win", "Win", "BkSp", "Enter", "Esc", "Space", "PgUp", "PgDn", "End", "Home", "Left", "Up", "Right", "Down", "Ins", "Del", "Tab"}
38 collection keys = %{ 0x10 , 0x11, 0x12, 0x5b, 0x5c, 0x08 , 0x0D , 0x1B , 0x20 , 0x21 , 0x22 , 0x23 , 0x24 , 0x25 , 0x26, 0x27 , 0x28 , 0x2D , 0x2E, 0x09 }
39 hshortkey.ignorecase()
40 fornum i = 0, *names
41 {
42 hshortkey[names[i]->str] = keys[i]
43 }
44 fornum i = 1, 11
45 {
46 hshortkey[ "F\(i)" ] = 0x6F + i
47 }
48 fornum i = 0, 10
49 {
50 hshortkey[ "\(i)" ] = 0x30 + i
51 }
52 fornum i = 'A', 'Z' + 1
53 {
54 hshortkey[ "".appendch( i ) ] = i
55 }
56
57 }
58
59 property ustr shortkey.caption<result>()
60 {
61 result = .pcaption
62 }
63
64 method shortkey.setkey( uint key mstate )
65 {
66 str caption
67 subfunc add( str sadd )
68 {
69 if *caption : caption@"+"
70 caption@sadd
71 }
72 .pcaption.clear()
73 .key = key
74 .mstate = mstate
75 if .mstate & $mstShift : add( "Shift" )
76 if .mstate & $mstCtrl : add( "Ctrl" )
77 if .mstate & $mstAlt : add( "Alt" )
78 if .mstate & $mstWin : add( "Win" )
79 if key < 16 || key > 18
80 {
81 foreach name, hshortkey.keys
82 {
83 if hshortkey[name] == .key
84 {
85 add( name )
86 .pcaption = caption
87 break;
88 }
89 }
90 }
91 }
92
93 property shortkey.caption( str value )
94 {
95 uint i, key, mstate
96 arrstr s
97 value.split( s, '+', $SPLIT_NOSYS )
98 if *s
99 {
100 fornum i = 0, *s - 1
101 {
102 switch hshortkey[s[i]]
103 {
104 case 0x10: mstate |= $mstShift
105 case 0x11: mstate |= $mstCtrl
106 case 0x12: mstate |= $mstAlt
107 case 0x5b, 0x5c: mstate |= $mstWin
108 }
109 }
110 switch key = hshortkey[s[i]]
111 {
112 case 0x10, 0x11, 0x12, 0x5b, 0x5c: key = 0
113 }
114 if key
115 {
116 .setkey( key, mstate )
117 }
118 }
119 else
120 {
121 .key = 0
122 .mstate = 0
123 .pcaption.clear()
124 }
125 }
126
127
128
129 /* Компонента vCustomMenu, порождена от vComp, является заготовкой для
130 vMenu, vMenuItem, vPopupMenu
131 */
132
133 type vCustomMenu <index=vComp inherit = vComp> {
134 //Hidden Fields
135 uint phMenu //Хэндл меню
136 uint pFake
137 }
138
139 /* Компонента vCustomMainMenu, порождена от vCustomMenu, может содержать vMenuItem
140 */
141 type vCustomMainMenu <inherit = vCustomMenu> {
142 reserved tblkey[ $SHORTKEY_MAX * 8]
143 }
144
145 extern {
146 method vCustomMenu.mInsert <alias=vCustomMenu_mInsert>( vComp comp )
147 method vCustomMainMenu vCustomMenu.iMainMenu()
148 /* method vCustomMainMenu.FreeShortKey( vCustomMenu item )
149 method vCustomMainMenu.SetShortKey( vCustomMenu item )*/
150 }
151
152
153 /* Компонента vMenu, порождена от vCustomMainMenu, может содержать vMenuItem
154 */
155 type vMenu <inherit = vCustomMainMenu> {
156 }
157
158 include {
159 "menuitem.g"
160 }
161
162 method vCustomMainMenu.FreeShortKey( vMenuItem item )
163 {
164 uint key
165 if ( key = item.pShortKey.key ) && key < $SHORTKEY_MAX
166 {
167 uint addr
168 uint previtem as
169 (( addr = &.tblkey + ( key << 3 ))->uint )->vMenuItem
170 if &previtem == &item
171 {
172 addr->uint = item.pShortKey.next
173 }
174 else
175 {
176 while &previtem
177 {
178 if previtem.pShortKey.next == &item
179 {
180 previtem.pShortKey.next = item.pShortKey.next
181 break
182 }
183 previtem as previtem.pShortKey.next->vMenuItem
184 }
185 }
186 }
187 }
188
189 method vCustomMainMenu.SetShortKey( vMenuItem item )
190 {
191 uint key
192 if ( key = item.pShortKey.key ) && key < $SHORTKEY_MAX
193 {
194 uint addr
195 uint nextitem as
196 ( (addr = &.tblkey + ( key << 3 ))->uint )->vMenuItem
197 addr->uint = &item
198 item.pShortKey.next = &nextitem
199 }
200 }
201
202 method uint vCustomMainMenu.CheckShortKey( uint mstate key )
203 {
204 if key && key < $SHORTKEY_MAX
205 {
206 uint nextitem as
207 ( &.tblkey + (key << 3 ) )->uint->vMenuItem
208 while &nextitem
209 {
210 if nextitem.Enabled && nextitem.pShortKey.mstate == mstate
211 {
212 nextitem.mMenuClick()
213 //nextitem.OnClick.Run( nextitem )
214 return 1
215 }
216 nextitem as nextitem.pShortKey.next
217 }
218 }
219 return 0
220 }
221
222 /*Метод vMenuItem.iMainMenu()
223 Получить основное меню
224 */
225 method vCustomMainMenu vCustomMenu.iMainMenu()
226 {
227 uint mainmenu as this
228 while mainmenu.Owner.TypeIs( vCustomMenu )
229 {
230 mainmenu as mainmenu.Owner
231 }
232 return mainmenu as vCustomMainMenu
233 }
234
235
236 /*------------------------------------------------------------------------------
237 Properties
238 */
239 /*Количество элементов uint *vMenu
240 Возвращает количество закладок
241 */
242 operator uint *( vCustomMenu menu )
243 {
244 return *menu.Comps
245 }
246
247 /*Индекс vMenuItem vMenu[index]
248 Возвращает закладку с текущим номером
249 */
250 method vMenuItem vCustomMenu.index( uint index )
251 {
252 if index != -1 && index < *.Comps
253 {
254 return .Comps[ index ]->vMenuItem
255 }
256 return 0->vMenuItem
257 }
258
259 /*------------------------------------------------------------------------------
260 Virtual methods
261 */
262 method vCustomMenu.mInsert /*<alias = vCustomMenu_mInsert> */( vComp comp )
263 {
264 /*if !this.TypeIs( vMenu )
265 {
266 int i
267 for i=30*(*.Comps/30), i >= 0, i -= 30
268 {
269 RemoveMenu( .phMenu, i, 0x00000400 )
270 }
271 }*/
272 if !this.TypeIs( vMenu )
273 {
274 if !.pFake
275 {
276 .pFake = &App.CreateComp( vFakeMenuItem )
277 .pFake->vFakeMenuItem.pMenu = &this
278 }
279 }
280 if comp.TypeIs( vMenuItem ) && comp->vMenuItem.pVisible
281 {
282 uint i, pos
283 fornum i=0, *.Comps
284 {
285 if .Comps[i]->vMenuItem.pVisible : pos++
286 }
287 this->vComp.mInsert( comp )
288 MENUITEMINFO mi
289 mi.cbSize = sizeof( MENUITEMINFO )
290 mi.fMask = $MIIM_ID | $MIIM_DATA
291 mi.wID = &comp
292 mi.dwItemData = pos
293 InsertMenuItem( .phMenu, 1, 0, mi )
294 comp->vMenuItem.iUpdate()
295 this.iMainMenu().SetShortKey( comp->vMenuItem )
296 if !this.TypeIs( vMenu )
297 {
298 //MENUITEMINFO mi
299 mi.cbSize = sizeof( MENUITEMINFO )
300 mi.fMask = $MIIM_ID | $MIIM_TYPE | $MIIM_DATA
301 mi.fType = $MFT_SEPARATOR | $MFT_OWNERDRAW
302 mi.dwItemData = pos
303 mi.wID = .pFake
304 InsertMenuItem( .phMenu, 1, 0, mi )
305 }
306 }
307 /*if !this.TypeIs( vMenu )
308 {
309 if .pFake
310 {
311 RemoveMenu( .phMenu, .pFake, 0 )
312 }
313 else
314 {
315 .pFake = &App.CreateComp( vFakeMenuItem )
316 }
317 /*uint i
318 for i=0, i < *.Comps, i += 30
319 {
320 MENUITEMINFO mi
321 mi.cbSize = sizeof( MENUITEMINFO )
322 mi.fMask = $MIIM_ID | $MIIM_TYPE
323 mi.fType = $MFT_OWNERDRAW
324 mi.wID = .pFake
325 .pFake->vFakeMenuItem.pMenu = &this
326 InsertMenuItem( .phMenu, i, 1, mi )
327 }
328 MENUITEMINFO mi
329 mi.cbSize = sizeof( MENUITEMINFO )
330 mi.fMask = $MIIM_ID | $MIIM_TYPE
331 mi.fType = $MFT_SEPARATOR | $MFT_OWNERDRAW
332 mi.wID = .pFake
333 .pFake->vFakeMenuItem.pMenu = &this
334 InsertMenuItem( .phMenu, GetMenuItemCount( .phMenu ) - 1, 1, mi )
335 }*/
336 }
337
338 method vCustomMenu.mRemove <alias = vCustomMenu_mRemove> ( vComp comp )
339 {
340 if comp.TypeIs( vMenuItem )
341 {
342 if !this.TypeIs( vMenu )
343 {
344 uint i, pos
345 fornum i=0, *.Comps
346 {
347 if .Comps[i] == &comp
348 {
349 RemoveMenu( .phMenu, pos * 2 + 1, 0x400 )
350 }
351 if .Comps[i]->vMenuItem.pVisible : pos++
352 }
353 }
354 RemoveMenu( .phMenu, &comp, 0 )
355 }
356 this->vComp.mRemove( comp )
357 }
358
359 /*method vMenu.Activate( vComp owner)
360 {
361 if &owner && owner.TypeIs( vForm )
362 {
363 SetMenu( owner->vForm.hwnd, .phMenu )
364 DrawMenuBar( owner->vForm.hwnd )
365 }
366 //}
367 }*/
368
369 /*method vMenu.mSetOwner <alias = vMenu_mSetOwner>( vComp newowner )
370 {
371 if this.pOwner
372 {
373 SetMenu( .Owner->vForm.hwnd, 0 )
374 DrawMenuBar( .Owner->vForm.hwnd )
375 }
376 this->vComp.mSetOwner( newowner )
377 //.Activate( .Owner )
378 if &.Owner && .Owner.TypeIs( vForm )
379 {
380 SetMenu( .Owner->vForm.hwnd, .phMenu )
381 DrawMenuBar( .Owner->vForm.hwnd )
382 }
383 }*/
384
385 /*------------------------------------------------------------------------------
386 Registration
387 */
388 method vCustomMenu vCustomMenu.init( )
389 {
390 this.pTypeId = vCustomMenu
391 return this
392 }
393
394 method vCustomMenu vCustomMainMenu.init( )
395 {
396 this.pTypeId = vCustomMainMenu
397 return this
398 }
399
400
401 method vMenu vMenu.init( )
402 {
403 this.pTypeId = vMenu
404 this.phMenu = CreateMenu()
405 return this
406 }
407
408 method vCustomMenu.delete( )
409 {
410 if this.phMenu
411 {
412 DestroyMenu( this.phMenu )
413 }
414 }
415
416
417 func init_vMenu <entry>()
418 {
419 regcomp( vCustomMenu, "vCustomMenu", vComp, $vComp_last,
420 %{ %{$mInsert, vCustomMenu_mInsert },
421 %{$mRemove, vCustomMenu_mRemove }
422 },
423 0->collection )
424
425 regcomp( vMenu, "vMenu", vCustomMenu, $vComp_last,
426 /*%{ %{$mSetOwner, vMenu_mSetOwner }
427 },*/
428 0->collection,
429 0->collection )
430
431 regcomp( vMenuItem, "vMenuItem", vCustomMenu, $vCtrl_last,
432 %{ %{$mInsert, vMenuItem_mInsert },/*
433 %{$mSetOwner, vMenuItem_mSetOwner },*/
434 %{$mMenuClick, vMenuItem_mMenuClick },
435 %{$mLangChanged, vMenuItem_mLangChanged }
436 /*,
437 %{$mWinDrawItem, vMenuItem_mWinDrawItem },
438 %{$mWinMeasureItem, vMenuItem_mWinMeasureItem }*/
439 },
440 0->collection )
441
442 regcomp( vFakeMenuItem, "vFakeMenuItem", vComp, $vCtrl_last,
443 %{
444 %{$mWinDrawItem, vFakeMenuItem_mWinDrawItem },
445 %{$mWinMeasureItem, vFakeMenuItem_mWinMeasureItem }
446 },
447 0->collection )
448
449 ifdef $DESIGNING {
450 cm.AddComp( vMenu, 1, "Windows", "menu" )
451
452 cm.AddComp( vMenuItem )
453 cm.AddProps( vMenuItem, %{
454 "Caption", ustr, 0,
455 "Visible", uint, 0,
456 "Enabled", uint, 0,
457 "Separator", uint, 0,
458 "Checked", uint, 0,
459 "RadioCheck", uint, 0,
460 "AutoCheck", uint, 0,
461 "ShortKey", ustr, 0,
462 "Image", ustr, 0,
463 "Ellipsis", uint, 0
464 })
465
466 cm.AddEvents( vMenuItem, %{
467 "OnClick" , "evparEvent"
468 })
469
470
471 }
472
473 }
474
475
476
477