OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.12 / macosx / tkMacOSXMenus.c
1 /*
2  * tkMacOSXMenus.c --
3  *
4  *      These calls set up the default menus for Tk.
5  *
6  * Copyright (c) 1995-1996 Sun Microsystems, Inc.
7  * Copyright 2001-2009, Apple Inc.
8  * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
9  *
10  * See the file "license.terms" for information on usage and redistribution
11  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12  */
13
14 #include "tkMacOSXPrivate.h"
15 #include "tkMenu.h"
16 #include "tkMacOSXConstants.h"
17
18 static void             GenerateEditEvent(const char *name);
19 static Tcl_Obj *        GetWidgetDemoPath(Tcl_Interp *interp);
20
21 \f
22 #pragma mark TKApplication(TKMenus)
23
24 @implementation TKApplication(TKMenus)
25 - (void) _setupMenus
26 {
27     if (_defaultMainMenu) {
28         return;
29     }
30     TkMenuInit();
31
32     NSString *applicationName = [[NSBundle mainBundle]
33             objectForInfoDictionaryKey:@"CFBundleName"];
34
35     if (!applicationName) {
36         applicationName = [[NSProcessInfo processInfo] processName];
37     }
38
39     NSString *aboutName = (applicationName &&
40             ![applicationName isEqualToString:@"Wish"] &&
41             ![applicationName hasPrefix:@"tclsh"]) ?
42             applicationName : @"Tcl & Tk";
43
44     _servicesMenu = [NSMenu menuWithTitle:@"Services"];
45     _defaultApplicationMenuItems = [[NSArray arrayWithObjects:
46             [NSMenuItem separatorItem],
47             [NSMenuItem itemWithTitle:
48                    [NSString stringWithFormat:@"Preferences%C", 0x2026]
49                    action:@selector(preferences:) keyEquivalent:@","],
50             [NSMenuItem separatorItem],
51             [NSMenuItem itemWithTitle:@"Services" submenu:_servicesMenu],
52             [NSMenuItem separatorItem],
53             [NSMenuItem itemWithTitle:
54                    [NSString stringWithFormat:@"Hide %@", applicationName]
55                    action:@selector(hide:) keyEquivalent:@"h"],
56             [NSMenuItem itemWithTitle:@"Hide Others"
57                    action:@selector(hideOtherApplications:) keyEquivalent:@"h"
58                    keyEquivalentModifierMask:
59                    NSCommandKeyMask|NSAlternateKeyMask],
60             [NSMenuItem itemWithTitle:@"Show All"
61                    action:@selector(unhideAllApplications:)],
62             [NSMenuItem separatorItem],
63             [NSMenuItem itemWithTitle:
64                    [NSString stringWithFormat:@"Quit %@", applicationName]
65                    action: @selector(terminate:) keyEquivalent:@"q"],
66             nil] retain];
67     _defaultApplicationMenu = [TKMenu menuWithTitle:applicationName
68             menuItems:_defaultApplicationMenuItems];
69     [_defaultApplicationMenu insertItem:
70             [NSMenuItem itemWithTitle:
71                     [NSString stringWithFormat:@"About %@", aboutName]
72                     action:@selector(orderFrontStandardAboutPanel:)] atIndex:0];
73     _defaultFileMenuItems =
74             [[NSArray arrayWithObjects:
75             [NSMenuItem itemWithTitle:
76                    [NSString stringWithFormat:@"Source%C", 0x2026]
77                    action:@selector(tkSource:)],
78             [NSMenuItem itemWithTitle:@"Run Widget Demo"
79                    action:@selector(tkDemo:)],
80             [NSMenuItem itemWithTitle:@"Close" action:@selector(performClose:)
81                    target:nil keyEquivalent:@"w"],
82             nil] retain];
83     _demoMenuItem = [_defaultFileMenuItems objectAtIndex:1];
84     TKMenu *fileMenu = [TKMenu menuWithTitle:@"File"
85             menuItems: _defaultFileMenuItems];
86     TKMenu *editMenu = [TKMenu menuWithTitle:@"Edit" menuItems:
87             [NSArray arrayWithObjects:
88             [NSMenuItem itemWithTitle:@"Undo" action:@selector(undo:)
89                    target:nil keyEquivalent:@"z"],
90             [NSMenuItem itemWithTitle:@"Redo" action:@selector(redo:)
91                    target:nil keyEquivalent:@"y"],
92             [NSMenuItem separatorItem],
93             [NSMenuItem itemWithTitle:@"Cut" action:@selector(cut:)
94                    target:nil keyEquivalent:@"x"],
95             [NSMenuItem itemWithTitle:@"Copy" action:@selector(copy:)
96                    target:nil keyEquivalent:@"c"],
97             [NSMenuItem itemWithTitle:@"Paste" action:@selector(paste:)
98                    target:nil keyEquivalent:@"v"],
99             [NSMenuItem itemWithTitle:@"Delete" action:@selector(delete:)
100                    target:nil],
101             nil]];
102
103     _defaultWindowsMenuItems = [NSArray arrayWithObjects:
104             [NSMenuItem itemWithTitle:@"Minimize"
105                    action:@selector(performMiniaturize:) target:nil
106                    keyEquivalent:@"m"],
107             [NSMenuItem itemWithTitle:@"Zoom" action:@selector(performZoom:)
108                    target:nil],
109             nil];
110
111     /*
112      * On OS X 10.12 we get duplicate tab control items if we create them here.
113      */
114
115     if ([NSApp macOSVersion] > 101200) {
116         _defaultWindowsMenuItems = [_defaultWindowsMenuItems
117              arrayByAddingObjectsFromArray:
118              [NSArray arrayWithObjects:
119                     [NSMenuItem separatorItem],
120                     [NSMenuItem itemWithTitle:@"Show Previous Tab"
121                            action:@selector(selectPreviousTab:)
122                            target:nil
123                            keyEquivalent:@"\t"
124                            keyEquivalentModifierMask:
125                                NSControlKeyMask|NSShiftKeyMask],
126                     [NSMenuItem itemWithTitle:@"Show Next Tab"
127                            action:@selector(selectNextTab:)
128                            target:nil
129                            keyEquivalent:@"\t"
130                            keyEquivalentModifierMask:NSControlKeyMask],
131                     [NSMenuItem itemWithTitle:@"Move Tab To New Window"
132                            action:@selector(moveTabToNewWindow:)
133                            target:nil],
134                     [NSMenuItem itemWithTitle:@"Merge All Windows"
135                            action:@selector(mergeAllWindows:)
136                            target:nil],
137                     [NSMenuItem separatorItem],
138                     nil]];
139     }
140     _defaultWindowsMenuItems = [_defaultWindowsMenuItems arrayByAddingObject:
141             [NSMenuItem itemWithTitle:@"Bring All to Front"
142                    action:@selector(arrangeInFront:)]];
143     [_defaultWindowsMenuItems retain];
144     TKMenu *windowsMenu = [TKMenu menuWithTitle:@"Window" menuItems:
145                                       _defaultWindowsMenuItems];
146     _defaultHelpMenuItems = [[NSArray arrayWithObjects:
147             [NSMenuItem itemWithTitle:
148                    [NSString stringWithFormat:@"%@ Help", applicationName]
149                    action:@selector(showHelp:) keyEquivalent:@"?"],
150             nil] retain];
151     TKMenu *helpMenu = [TKMenu menuWithTitle:@"Help" menuItems:
152             _defaultHelpMenuItems];
153     [self setServicesMenu:_servicesMenu];
154     [self setWindowsMenu:windowsMenu];
155     _defaultMainMenu = [[TKMenu menuWithTitle:@"" submenus:[NSArray
156             arrayWithObjects:_defaultApplicationMenu, fileMenu, editMenu,
157             windowsMenu, helpMenu, nil]] retain];
158     [_defaultMainMenu setSpecial:tkMainMenu];
159     [_defaultApplicationMenu setSpecial:tkApplicationMenu];
160     [windowsMenu setSpecial:tkWindowsMenu];
161     [helpMenu setSpecial:tkHelpMenu];
162     [self tkSetMainMenu:nil];
163 }
164
165 - (void) dealloc
166 {
167     [_defaultMainMenu release];
168     [_defaultHelpMenuItems release];
169     [_defaultWindowsMenuItems release];
170     [_defaultApplicationMenuItems release];
171     [_defaultFileMenuItems release];
172     [super dealloc];
173 }
174
175 - (BOOL) validateUserInterfaceItem: (id <NSValidatedUserInterfaceItem>) anItem
176 {
177     SEL action = [anItem action];
178
179     if (sel_isEqual(action, @selector(preferences:))) {
180         return (_eventInterp && Tcl_FindCommand(_eventInterp,
181                 "::tk::mac::ShowPreferences", NULL, 0));
182     } else if (sel_isEqual(action, @selector(tkDemo:))) {
183         BOOL haveDemo = NO;
184
185         if (_eventInterp) {
186             Tcl_Obj *path = GetWidgetDemoPath(_eventInterp);
187
188             if (path) {
189                 Tcl_IncrRefCount(path);
190                 haveDemo = (Tcl_FSAccess(path, R_OK) == 0);
191                 Tcl_DecrRefCount(path);
192             }
193         }
194         return haveDemo;
195     } else {
196         return [super validateUserInterfaceItem:anItem];
197     }
198 }
199
200 - (void) orderFrontStandardAboutPanel: (id) sender
201 {
202     if (!_eventInterp || !Tcl_FindCommand(_eventInterp, "tkAboutDialog",
203             NULL, 0) || (GetCurrentEventKeyModifiers() & optionKey)) {
204         [super orderFrontStandardAboutPanel:nil];
205     } else {
206         int code = Tcl_EvalEx(_eventInterp, "tkAboutDialog", -1,
207                 TCL_EVAL_GLOBAL);
208
209         if (code != TCL_OK) {
210             Tcl_BackgroundException(_eventInterp, code);
211         }
212         Tcl_ResetResult(_eventInterp);
213     }
214 }
215
216 - (void) showHelp: (id) sender
217 {
218     if (!_eventInterp || !Tcl_FindCommand(_eventInterp,
219             "::tk::mac::ShowHelp", NULL, 0)) {
220         [super showHelp:sender];
221     } else {
222         int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ShowHelp", -1,
223                 TCL_EVAL_GLOBAL);
224
225         if (code != TCL_OK) {
226             Tcl_BackgroundException(_eventInterp, code);
227         }
228         Tcl_ResetResult(_eventInterp);
229     }
230 }
231
232 - (void) tkSource: (id) sender
233 {
234     if (_eventInterp) {
235         if (Tcl_EvalEx(_eventInterp, "tk_getOpenFile -filetypes {"
236                 "{{TCL Scripts} {.tcl} TEXT} {{Text Files} {} TEXT}}",
237                 -1, TCL_EVAL_GLOBAL) == TCL_OK) {
238             Tcl_Obj *path = Tcl_GetObjResult(_eventInterp);
239             int len;
240
241             Tcl_GetStringFromObj(path, &len);
242             if (len) {
243                 Tcl_IncrRefCount(path);
244
245                 int code = Tcl_FSEvalFileEx(_eventInterp, path, NULL);
246
247                 if (code != TCL_OK) {
248                     Tcl_BackgroundException(_eventInterp, code);
249                 }
250                 Tcl_DecrRefCount(path);
251             }
252         }
253         Tcl_ResetResult(_eventInterp);
254     }
255 }
256
257 - (void) tkDemo: (id) sender
258 {
259     if (_eventInterp) {
260         Tcl_Obj *path = GetWidgetDemoPath(_eventInterp);
261
262         if (path) {
263             Tcl_IncrRefCount(path);
264
265             [_demoMenuItem setHidden:YES];
266             int code = Tcl_FSEvalFileEx(_eventInterp, path, NULL);
267
268             if (code != TCL_OK) {
269                 Tcl_BackgroundException(_eventInterp, code);
270             }
271             Tcl_DecrRefCount(path);
272             Tcl_ResetResult(_eventInterp);
273         }
274     }
275 }
276 @end
277 \f
278 #pragma mark TKContentView(TKMenus)
279
280 @implementation TKContentView(TKMenus)
281
282 - (BOOL) validateUserInterfaceItem: (id <NSValidatedUserInterfaceItem>) anItem
283 {
284     return YES;
285 }
286
287 #define EDIT_ACTION(a, e) \
288     - (void) a: (id) sender \
289     { \
290         if ([sender isKindOfClass:[NSMenuItem class]]) { \
291             GenerateEditEvent(#e); \
292         } \
293     }
294 EDIT_ACTION(cut, Cut)
295 EDIT_ACTION(copy, Copy)
296 EDIT_ACTION(paste, Paste)
297 EDIT_ACTION(delete, Clear)
298 EDIT_ACTION(undo, Undo)
299 EDIT_ACTION(redo, Redo)
300 #undef EDIT_ACTION
301 @end
302
303 #pragma mark -
304 \f
305 /*
306  *----------------------------------------------------------------------
307  *
308  * GetWidgetDemoPath --
309  *
310  *      Get path to the widget demo.
311  *
312  * Results:
313  *      pathObj with ref count 0.
314  *
315  * Side effects:
316  *      None.
317  *
318  *----------------------------------------------------------------------
319  */
320
321 static Tcl_Obj *
322 GetWidgetDemoPath(
323     Tcl_Interp *interp)
324 {
325     Tcl_Obj *libpath, *result = NULL;
326
327     libpath = Tcl_GetVar2Ex(interp, "tk_library", NULL, TCL_GLOBAL_ONLY);
328     if (libpath) {
329         Tcl_Obj *demo[2] = {    Tcl_NewStringObj("demos", 5),
330                                 Tcl_NewStringObj("widget", 6) };
331
332         Tcl_IncrRefCount(libpath);
333         result = Tcl_FSJoinToPath(libpath, 2, demo);
334         Tcl_DecrRefCount(libpath);
335     } else {
336         Tcl_ResetResult(interp);
337     }
338     return result;
339 }
340 \f
341 /*
342  *----------------------------------------------------------------------
343  *
344  * TkMacOSXHandleMenuSelect --
345  *
346  *      Handles events that occur in the Menu bar.
347  *
348  * Results:
349  *      None.
350  *
351  * Side effects:
352  *      None.
353  *
354  *----------------------------------------------------------------------
355  */
356
357 void
358 TkMacOSXHandleMenuSelect(
359     short theMenu,
360     unsigned short theItem,
361     int optionKeyPressed)
362 {
363     Tcl_Panic("TkMacOSXHandleMenuSelect: Obsolete, no more Carbon!");
364 }
365 \f
366 /*
367  *----------------------------------------------------------------------
368  *
369  * TkMacOSXInitMenus --
370  *
371  *      This procedure initializes the Macintosh menu bar.
372  *
373  * Results:
374  *      None.
375  *
376  * Side effects:
377  *      None.
378  *
379  *----------------------------------------------------------------------
380  */
381
382 void
383 TkMacOSXInitMenus(
384     Tcl_Interp *interp)
385 {
386     [NSApp _setupMenus];
387 }
388 \f
389 /*
390  *----------------------------------------------------------------------
391  *
392  * GenerateEditEvent --
393  *
394  *      Takes an edit menu item and posts the corasponding a virtual event to
395  *      Tk's event queue.
396  *
397  * Results:
398  *      None.
399  *
400  * Side effects:
401  *      May place events of queue.
402  *
403  *----------------------------------------------------------------------
404  */
405
406 static void
407 GenerateEditEvent(
408     const char *name)
409 {
410     XVirtualEvent event;
411     int x, y;
412     TkWindow *winPtr = TkMacOSXGetTkWindow([NSApp keyWindow]);
413     Tk_Window tkwin;
414
415     if (!winPtr) {
416         return;
417     }
418     tkwin = (Tk_Window)winPtr->dispPtr->focusPtr;
419     if (!tkwin) {
420         return;
421     }
422     bzero(&event, sizeof(XVirtualEvent));
423     event.type = VirtualEvent;
424     event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
425     event.send_event = false;
426     event.display = Tk_Display(tkwin);
427     event.event = Tk_WindowId(tkwin);
428     event.root = XRootWindow(Tk_Display(tkwin), 0);
429     event.subwindow = None;
430     event.time = TkpGetMS();
431     XQueryPointer(NULL, winPtr->window, NULL, NULL,
432             &event.x_root, &event.y_root, &x, &y, &event.state);
433     Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
434     event.same_screen = true;
435     event.name = Tk_GetUid(name);
436     Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
437 }
438
439 #pragma mark -
440 \f
441 #pragma mark NSMenu & NSMenuItem Utilities
442
443 @implementation NSMenu(TKUtils)
444
445 + (id) menuWithTitle: (NSString *) title
446 {
447     NSMenu *m = [[self alloc] initWithTitle:title];
448
449     return [m autorelease];
450 }
451
452 + (id) menuWithTitle: (NSString *) title menuItems: (NSArray *) items
453 {
454     NSMenu *m = [[self alloc] initWithTitle:title];
455
456     for (NSMenuItem *i in items) {
457         [m addItem:i];
458     }
459     return [m autorelease];
460 }
461
462 + (id) menuWithTitle: (NSString *) title submenus: (NSArray *) submenus
463 {
464     NSMenu *m = [[self alloc] initWithTitle:title];
465
466     for (NSMenu *i in submenus) {
467         [m addItem:[NSMenuItem itemWithSubmenu:i]];
468     }
469     return [m autorelease];
470 }
471
472 - (NSMenuItem *) itemWithSubmenu: (NSMenu *) submenu
473 {
474     return [self itemAtIndex:[self indexOfItemWithSubmenu:submenu]];
475 }
476
477 - (NSMenuItem *) itemInSupermenu
478 {
479     NSMenu *supermenu = [self supermenu];
480
481     return (supermenu ? [supermenu itemWithSubmenu:self] : nil);
482 }
483 @end
484
485 @implementation NSMenuItem(TKUtils)
486
487 + (id) itemWithSubmenu: (NSMenu *) submenu
488 {
489     NSMenuItem *i = [[self alloc] initWithTitle:[submenu title] action:NULL
490             keyEquivalent:@""];
491
492     [i setSubmenu:submenu];
493     return [i autorelease];
494 }
495
496 + (id) itemWithTitle: (NSString *) title submenu: (NSMenu *) submenu
497 {
498     NSMenuItem *i = [[self alloc] initWithTitle:title action:NULL
499             keyEquivalent:@""];
500
501     [i setSubmenu:submenu];
502     return [i autorelease];
503 }
504
505 + (id) itemWithTitle: (NSString *) title action: (SEL) action
506 {
507     NSMenuItem *i = [[self alloc] initWithTitle:title action:action
508             keyEquivalent:@""];
509
510     [i setTarget:NSApp];
511     return [i autorelease];
512 }
513
514 + (id) itemWithTitle: (NSString *) title action: (SEL) action
515         target: (id) target
516 {
517     NSMenuItem *i = [[self alloc] initWithTitle:title action:action
518             keyEquivalent:@""];
519
520     [i setTarget:target];
521     return [i autorelease];
522 }
523
524 + (id) itemWithTitle: (NSString *) title action: (SEL) action
525         keyEquivalent: (NSString *) keyEquivalent
526 {
527     NSMenuItem *i = [[self alloc] initWithTitle:title action:action
528             keyEquivalent:keyEquivalent];
529
530     [i setTarget:NSApp];
531     return [i autorelease];
532 }
533
534 + (id) itemWithTitle: (NSString *) title action: (SEL) action
535         target: (id) target keyEquivalent: (NSString *) keyEquivalent
536 {
537     NSMenuItem *i = [[self alloc] initWithTitle:title action:action
538             keyEquivalent:keyEquivalent];
539
540     [i setTarget:target];
541     return [i autorelease];
542 }
543
544 + (id) itemWithTitle: (NSString *) title action: (SEL) action
545         keyEquivalent: (NSString *) keyEquivalent
546         keyEquivalentModifierMask: (NSUInteger) keyEquivalentModifierMask
547 {
548     NSMenuItem *i = [[self alloc] initWithTitle:title action:action
549             keyEquivalent:keyEquivalent];
550
551     [i setTarget:NSApp];
552     [i setKeyEquivalentModifierMask:keyEquivalentModifierMask];
553     return [i autorelease];
554 }
555
556 + (id) itemWithTitle: (NSString *) title action: (SEL) action
557         target: (id) target keyEquivalent: (NSString *) keyEquivalent
558         keyEquivalentModifierMask: (NSUInteger) keyEquivalentModifierMask
559 {
560     NSMenuItem *i = [[self alloc] initWithTitle:title action:action
561             keyEquivalent:keyEquivalent];
562
563     [i setTarget:target];
564     [i setKeyEquivalentModifierMask:keyEquivalentModifierMask];
565     return [i autorelease];
566 }
567 @end
568 \f
569 /*
570  * Local Variables:
571  * mode: objc
572  * c-basic-offset: 4
573  * fill-column: 79
574  * coding: utf-8
575  * End:
576  */