comparison mac/dw.m @ 654:80e253df49fd

Implementing the menubar and hopefully popup menus.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 23 Feb 2011 18:51:15 +0000
parents 36c6669422d2
children 27eb39d2577b
comparison
equal deleted inserted replaced
653:36c6669422d2 654:80e253df49fd
114 } 114 }
115 } 115 }
116 return -1; 116 return -1;
117 } 117 }
118 118
119 NSApplication *DWApp;
120 NSRunLoop *DWRunLoop;
121 NSMenu *DWMainMenu;
122 #if !defined(GARBAGE_COLLECT)
123 NSAutoreleasePool *pool;
124 #endif
125
119 /* So basically to implement our event handlers... 126 /* So basically to implement our event handlers...
120 * it looks like we are going to have to subclass 127 * it looks like we are going to have to subclass
121 * basically everything. Was hoping to add methods 128 * basically everything. Was hoping to add methods
122 * to the superclasses but it looks like you can 129 * to the superclasses but it looks like you can
123 * only add methods and no variables, which isn't 130 * only add methods and no variables, which isn't
158 -(void)mouseDown:(NSEvent *)theEvent { _event_handler(self, theEvent, 3); } 165 -(void)mouseDown:(NSEvent *)theEvent { _event_handler(self, theEvent, 3); }
159 -(void)mouseUp:(NSEvent *)theEvent { _event_handler(self, theEvent, 4); } 166 -(void)mouseUp:(NSEvent *)theEvent { _event_handler(self, theEvent, 4); }
160 @end 167 @end
161 168
162 /* Subclass for a top-level window */ 169 /* Subclass for a top-level window */
163 @interface DWView : DWBox { } 170 @interface DWView : DWBox
171 {
172 NSMenu *windowmenu;
173 }
164 -(BOOL)windowShouldClose:(id)sender; 174 -(BOOL)windowShouldClose:(id)sender;
175 -(void)setMenu:(NSMenu *)input;
176 -(void)windowDidBecomeMain:(id)sender;
177 -(void)menuHandler:(id)sender;
165 @end 178 @end
166 179
167 @implementation DWView 180 @implementation DWView
168 -(BOOL)windowShouldClose:(id)sender 181 -(BOOL)windowShouldClose:(id)sender
169 { 182 {
172 return YES; 185 return YES;
173 } 186 }
174 - (void)viewDidMoveToWindow 187 - (void)viewDidMoveToWindow
175 { 188 {
176 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowResized:) name:NSWindowDidResizeNotification object:[self window]]; 189 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowResized:) name:NSWindowDidResizeNotification object:[self window]];
190 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeMain:) name:NSWindowDidBecomeMainNotification object:[self window]];
177 } 191 }
178 - (void)dealloc 192 - (void)dealloc
179 { 193 {
180 [[NSNotificationCenter defaultCenter] removeObserver:self]; 194 [[NSNotificationCenter defaultCenter] removeObserver:self];
181 [super dealloc]; 195 [super dealloc];
183 - (void)windowResized:(NSNotification *)notification; 197 - (void)windowResized:(NSNotification *)notification;
184 { 198 {
185 NSSize size = [self frame].size; 199 NSSize size = [self frame].size;
186 _do_resize(&box, size.width, size.height); 200 _do_resize(&box, size.width, size.height);
187 } 201 }
202 -(void)windowDidBecomeMain:(id)sender
203 {
204 if(windowmenu)
205 {
206 NSLog(@"Setting local menu");
207 [DWApp setMainMenu:windowmenu];
208 }
209 else
210 {
211 NSLog(@"Setting global menu");
212 [DWApp setMainMenu:DWMainMenu];
213 }
214
215 }
216 -(void)setMenu:(NSMenu *)input { windowmenu = input; NSLog(@"Setting window menu"); }
217 -(void)menuHandler:(id)sender { _event_handler(sender, nil, 8); }
188 @end 218 @end
189 219
190 /* Subclass for a button type */ 220 /* Subclass for a button type */
191 @interface DWButton : NSButton 221 @interface DWButton : NSButton
192 { 222 {
403 @implementation DWMLE 433 @implementation DWMLE
404 -(void *)userdata { return userdata; } 434 -(void *)userdata { return userdata; }
405 -(void)setUserdata:(void *)input { userdata = input; } 435 -(void)setUserdata:(void *)input { userdata = input; }
406 @end 436 @end
407 437
408 NSApplication *DWApp; 438 /* Subclass for a MLE type */
409 NSRunLoop *DWRunLoop; 439 @interface DWContainer : NSTableView
410 #if !defined(GARBAGE_COLLECT) 440 {
411 NSAutoreleasePool *pool; 441 void *userdata;
412 #endif 442 }
443 -(void *)userdata;
444 -(void)setUserdata:(void *)input;
445 @end
446
447 @implementation DWContainer
448 -(void *)userdata { return userdata; }
449 -(void)setUserdata:(void *)input { userdata = input; }
450 @end
413 451
414 typedef struct 452 typedef struct
415 { 453 {
416 ULONG message; 454 ULONG message;
417 char name[30]; 455 char name[30];
947 } 985 }
948 } 986 }
949 } 987 }
950 } 988 }
951 989
990 NSMenu *_generate_main_menu()
991 {
992 /* This only works on 10.6 so we have a backup method */
993 NSString * applicationName = [[NSRunningApplication currentApplication] localizedName];
994 if(applicationName == nil)
995 {
996 applicationName = [[NSProcessInfo processInfo] processName];
997 }
998
999 /* Create the main menu */
1000 NSMenu * mainMenu = [[[NSMenu alloc] initWithTitle:@"MainMenu"] autorelease];
1001
1002 NSMenuItem * mitem = [mainMenu addItemWithTitle:@"Apple" action:NULL keyEquivalent:@""];
1003 NSMenu * menu = [[[NSMenu alloc] initWithTitle:@"Apple"] autorelease];
1004
1005 [DWApp performSelector:@selector(setAppleMenu:) withObject:menu];
1006
1007 /* Setup the Application menu */
1008 NSMenuItem * item = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"About", nil), applicationName]
1009 action:@selector(orderFrontStandardAboutPanel:)
1010 keyEquivalent:@""];
1011 [item setTarget:DWApp];
1012
1013 [menu addItem:[NSMenuItem separatorItem]];
1014
1015 item = [menu addItemWithTitle:NSLocalizedString(@"Preferences...", nil)
1016 action:NULL
1017 keyEquivalent:@","];
1018
1019 [menu addItem:[NSMenuItem separatorItem]];
1020
1021 item = [menu addItemWithTitle:NSLocalizedString(@"Services", nil)
1022 action:NULL
1023 keyEquivalent:@""];
1024 NSMenu * servicesMenu = [[[NSMenu alloc] initWithTitle:@"Services"] autorelease];
1025 [menu setSubmenu:servicesMenu forItem:item];
1026 [DWApp setServicesMenu:servicesMenu];
1027
1028 [menu addItem:[NSMenuItem separatorItem]];
1029
1030 item = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"Hide", nil), applicationName]
1031 action:@selector(hide:)
1032 keyEquivalent:@"h"];
1033 [item setTarget:DWApp];
1034
1035 item = [menu addItemWithTitle:NSLocalizedString(@"Hide Others", nil)
1036 action:@selector(hideOtherApplications:)
1037 keyEquivalent:@"h"];
1038 [item setKeyEquivalentModifierMask:NSCommandKeyMask | NSAlternateKeyMask];
1039 [item setTarget:DWApp];
1040
1041 item = [menu addItemWithTitle:NSLocalizedString(@"Show All", nil)
1042 action:@selector(unhideAllApplications:)
1043 keyEquivalent:@""];
1044 [item setTarget:DWApp];
1045
1046 [menu addItem:[NSMenuItem separatorItem]];
1047
1048 item = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"Quit", nil), applicationName]
1049 action:@selector(terminate:)
1050 keyEquivalent:@"q"];
1051 [item setTarget:DWApp];
1052
1053 [mainMenu setSubmenu:menu forItem:mitem];
1054
1055 return mainMenu;
1056 }
1057
952 /* 1058 /*
953 * Initializes the Dynamic Windows engine. 1059 * Initializes the Dynamic Windows engine.
954 * Parameters: 1060 * Parameters:
955 * newthread: True if this is the only thread. 1061 * newthread: True if this is the only thread.
956 * False if there is already a message loop running. 1062 * False if there is already a message loop running.
962 /* Create a run loop for doing manual loops */ 1068 /* Create a run loop for doing manual loops */
963 DWRunLoop = [NSRunLoop alloc]; 1069 DWRunLoop = [NSRunLoop alloc];
964 #if !defined(GARBAGE_COLLECT) 1070 #if !defined(GARBAGE_COLLECT)
965 pool = [[NSAutoreleasePool alloc] init]; 1071 pool = [[NSAutoreleasePool alloc] init];
966 #endif 1072 #endif
967 1073 DWMainMenu = _generate_main_menu();
968 /* This only works on 10.6 so we have a backup method */ 1074 [DWApp setMainMenu:DWMainMenu];
969 NSString * applicationName = [[NSRunningApplication currentApplication] localizedName]; 1075
970 if(applicationName == nil)
971 {
972 applicationName = [[NSProcessInfo processInfo] processName];
973 }
974
975 /* Create the main menu */
976 NSMenu * mainMenu = [[[NSMenu alloc] initWithTitle:@"MainMenu"] autorelease];
977
978 NSMenuItem * mitem = [mainMenu addItemWithTitle:@"Apple" action:NULL keyEquivalent:@""];
979 NSMenu * menu = [[[NSMenu alloc] initWithTitle:@"Apple"] autorelease];
980
981 [DWApp setMainMenu:mainMenu];
982
983 [DWApp performSelector:@selector(setAppleMenu:) withObject:menu];
984
985 /* Setup the Application menu */
986 NSMenuItem * item = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"About", nil), applicationName]
987 action:@selector(orderFrontStandardAboutPanel:)
988 keyEquivalent:@""];
989 [item setTarget:DWApp];
990
991 [menu addItem:[NSMenuItem separatorItem]];
992
993 item = [menu addItemWithTitle:NSLocalizedString(@"Preferences...", nil)
994 action:NULL
995 keyEquivalent:@","];
996
997 [menu addItem:[NSMenuItem separatorItem]];
998
999 item = [menu addItemWithTitle:NSLocalizedString(@"Services", nil)
1000 action:NULL
1001 keyEquivalent:@""];
1002 NSMenu * servicesMenu = [[[NSMenu alloc] initWithTitle:@"Services"] autorelease];
1003 [menu setSubmenu:servicesMenu forItem:item];
1004 [DWApp setServicesMenu:servicesMenu];
1005
1006 [menu addItem:[NSMenuItem separatorItem]];
1007
1008 item = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"Hide", nil), applicationName]
1009 action:@selector(hide:)
1010 keyEquivalent:@"h"];
1011 [item setTarget:DWApp];
1012
1013 item = [menu addItemWithTitle:NSLocalizedString(@"Hide Others", nil)
1014 action:@selector(hideOtherApplications:)
1015 keyEquivalent:@"h"];
1016 [item setKeyEquivalentModifierMask:NSCommandKeyMask | NSAlternateKeyMask];
1017 [item setTarget:DWApp];
1018
1019 item = [menu addItemWithTitle:NSLocalizedString(@"Show All", nil)
1020 action:@selector(unhideAllApplications:)
1021 keyEquivalent:@""];
1022 [item setTarget:DWApp];
1023
1024 [menu addItem:[NSMenuItem separatorItem]];
1025
1026 item = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"Quit", nil), applicationName]
1027 action:@selector(terminate:)
1028 keyEquivalent:@"q"];
1029 [item setTarget:DWApp];
1030
1031 [mainMenu setSubmenu:menu forItem:mitem];
1032 return 0; 1076 return 0;
1033 } 1077 }
1034 1078
1035 /* 1079 /*
1036 * Runs a message loop for Dynamic Windows. 1080 * Runs a message loop for Dynamic Windows.
2499 * id: An ID to be used for getting the resource from the 2543 * id: An ID to be used for getting the resource from the
2500 * resource file. 2544 * resource file.
2501 */ 2545 */
2502 HWND API dw_container_new(ULONG id, int multi) 2546 HWND API dw_container_new(ULONG id, int multi)
2503 { 2547 {
2504 NSLog(@"dw_container_new() unimplemented\n"); 2548 DWContainer *cont = [[DWContainer alloc] init];
2505 return HWND_DESKTOP; 2549 if(multi)
2550 {
2551 [cont setAllowsMultipleSelection:YES];
2552 }
2553 else
2554 {
2555 [cont setAllowsMultipleSelection:NO];
2556 }
2557 return cont;
2506 } 2558 }
2507 2559
2508 /* 2560 /*
2509 * Sets up the container columns. 2561 * Sets up the container columns.
2510 * Parameters: 2562 * Parameters:
2515 * separator: The column number that contains the main separator. 2567 * separator: The column number that contains the main separator.
2516 * (this item may only be used in OS/2) 2568 * (this item may only be used in OS/2)
2517 */ 2569 */
2518 int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator) 2570 int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator)
2519 { 2571 {
2520 NSLog(@"dw_container_setup() unimplemented\n"); 2572 int z;
2521 return 0; 2573 DWContainer *cont = handle;
2574
2575 for(z=0;z<count;z++)
2576 {
2577 NSTableColumn *column = [[NSTableColumn alloc] init];
2578 [[column headerCell] setStringValue:[ NSString stringWithUTF8String:titles[z] ]];
2579 [cont addTableColumn:column];
2580 }
2581 return TRUE;
2522 } 2582 }
2523 2583
2524 /* 2584 /*
2525 * Sets up the filesystem columns, note: filesystem always has an icon/filename field. 2585 * Sets up the filesystem columns, note: filesystem always has an icon/filename field.
2526 * Parameters: 2586 * Parameters:
2529 * titles: An array of strings with column text titles. 2589 * titles: An array of strings with column text titles.
2530 * count: The number of columns (this should match the arrays). 2590 * count: The number of columns (this should match the arrays).
2531 */ 2591 */
2532 int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count) 2592 int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count)
2533 { 2593 {
2534 NSLog(@"dw_filesystem_setup() unimplemented\n"); 2594 char **newtitles = malloc(sizeof(char *) * (count + 1));
2535 return 0; 2595 unsigned long *newflags = malloc(sizeof(unsigned long) * (count + 1));
2596
2597 newtitles[0] = "Filename";
2598
2599 newflags[0] = DW_CFA_STRINGANDICON | DW_CFA_LEFT | DW_CFA_HORZSEPARATOR;
2600
2601 memcpy(&newtitles[1], titles, sizeof(char *) * count);
2602 memcpy(&newflags[1], flags, sizeof(unsigned long) * count);
2603
2604 dw_container_setup(handle, newflags, newtitles, count + 1, 0);
2605
2606 free(newtitles);
2607 free(newflags);
2608 return TRUE;
2536 } 2609 }
2537 2610
2538 /* 2611 /*
2539 * Allocates memory used to populate a container. 2612 * Allocates memory used to populate a container.
2540 * Parameters: 2613 * Parameters:
3154 * id: An ID to be used for getting the resource from the 3227 * id: An ID to be used for getting the resource from the
3155 * resource file. 3228 * resource file.
3156 */ 3229 */
3157 HMENUI API dw_menu_new(ULONG id) 3230 HMENUI API dw_menu_new(ULONG id)
3158 { 3231 {
3159 NSMenu *menu = [[[NSMenu alloc] initWithTitle:@"Apple"] autorelease]; 3232 NSMenu *menu = [[[NSMenu alloc] init] autorelease];
3233 [menu setAutoenablesItems:NO];
3160 return menu; 3234 return menu;
3161 } 3235 }
3162 3236
3163 /* 3237 /*
3164 * Create a menubar on a window. 3238 * Create a menubar on a window.
3165 * Parameters: 3239 * Parameters:
3166 * location: Handle of a window frame to be attached to. 3240 * location: Handle of a window frame to be attached to.
3167 */ 3241 */
3168 HMENUI API dw_menubar_new(HWND location) 3242 HMENUI API dw_menubar_new(HWND location)
3169 { 3243 {
3170 NSLog(@"dw_menubar_new() unimplemented\n"); 3244 NSWindow *window = location;
3171 return HWND_DESKTOP; 3245 NSMenu *windowmenu = _generate_main_menu();
3246 [[window contentView] setMenu:windowmenu];
3247 return (HMENUI)windowmenu;
3172 } 3248 }
3173 3249
3174 /* 3250 /*
3175 * Destroys a menu created with dw_menubar_new or dw_menu_new. 3251 * Destroys a menu created with dw_menubar_new or dw_menu_new.
3176 * Parameters: 3252 * Parameters:
3219 dest[cur] = src[z]; 3295 dest[cur] = src[z];
3220 cur++; 3296 cur++;
3221 } 3297 }
3222 else 3298 else
3223 { 3299 {
3224 dest[cur] = '_';
3225 accel = src[z+1]; 3300 accel = src[z+1];
3226 cur++;
3227 } 3301 }
3228 } 3302 }
3229 dest[cur] = 0; 3303 dest[cur] = 0;
3230 return accel; 3304 return accel;
3231 } 3305 }
3240 * end: If TRUE memu is positioned at the end of the menu. 3314 * end: If TRUE memu is positioned at the end of the menu.
3241 * check: If TRUE menu is "check"able. 3315 * check: If TRUE menu is "check"able.
3242 * flags: Extended attributes to set on the menu. 3316 * flags: Extended attributes to set on the menu.
3243 * submenu: Handle to an existing menu to be a submenu or NULL. 3317 * submenu: Handle to an existing menu to be a submenu or NULL.
3244 */ 3318 */
3245 HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu) 3319 HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG itemid, ULONG flags, int end, int check, HMENUI submenux)
3246 { 3320 {
3247 NSMenu *menu = menux; 3321 NSMenu *menu = menux;
3322 NSMenu *submenu = submenux;
3248 NSMenuItem *item = NULL; 3323 NSMenuItem *item = NULL;
3249 if(strlen(title) == 0) 3324 if(strlen(title) == 0)
3250 { 3325 {
3251 [menu addItem:[NSMenuItem separatorItem]]; 3326 [menu addItem:[NSMenuItem separatorItem]];
3252 } 3327 }
3253 else 3328 else
3254 { 3329 {
3255 char accel[2]; 3330 char accel[2];
3256 char *newtitle = malloc(strlen(title)+1); 3331 char *newtitle = malloc(strlen(title)+1);
3332 NSString *nstr;
3257 3333
3258 accel[0] = _removetilde(newtitle, title); 3334 accel[0] = _removetilde(newtitle, title);
3259 accel[1] = 0; 3335 accel[1] = 0;
3260 3336
3261 item = [menu addItemWithTitle:[ NSString stringWithUTF8String:newtitle ] 3337 nstr = [ NSString stringWithUTF8String:newtitle ];
3262 action:NULL
3263 keyEquivalent:[ NSString stringWithUTF8String:accel ]];
3264 free(newtitle); 3338 free(newtitle);
3339
3340 item = [menu addItemWithTitle: nstr
3341 action:@selector(menuHandler:)
3342 keyEquivalent:[ NSString stringWithUTF8String:accel ]];
3343 [item setTag:itemid];
3344 if(flags & DW_MIS_CHECKED)
3345 {
3346 [item setState:NSOnState];
3347 }
3348 if(flags & DW_MIS_DISABLED)
3349 {
3350 [item setEnabled:NO];
3351 }
3352
3353 if(submenux)
3354 {
3355 [submenu setTitle:nstr];
3356 [menu setSubmenu:submenu forItem:item];
3357 }
3265 return item; 3358 return item;
3266 } 3359 }
3267 return item; 3360 return item;
3268 } 3361 }
3269 3362
3273 * Parameters: 3366 * Parameters:
3274 * menu: The handle the the existing menu. 3367 * menu: The handle the the existing menu.
3275 * id: Menuitem id. 3368 * id: Menuitem id.
3276 * check: TRUE for checked FALSE for not checked. 3369 * check: TRUE for checked FALSE for not checked.
3277 */ 3370 */
3278 void API dw_menu_item_set_check(HMENUI menux, unsigned long id, int check) 3371 void API dw_menu_item_set_check(HMENUI menux, unsigned long itemid, int check)
3279 { 3372 {
3280 NSLog(@"dw_menu_item_set_check() unimplemented\n"); 3373 id menu = menux;
3374 NSMenuItem *menuitem = (NSMenuItem *)[menu itemWithTag:itemid];
3375
3376 if(menuitem != nil)
3377 {
3378 if(check)
3379 {
3380 [menuitem setState:NSOnState];
3381 }
3382 else
3383 {
3384 [menuitem setState:NSOffState];
3385 }
3386 }
3281 } 3387 }
3282 3388
3283 /* 3389 /*
3284 * Sets the state of a menu item. 3390 * Sets the state of a menu item.
3285 * Parameters: 3391 * Parameters:
3286 * menu: The handle to the existing menu. 3392 * menu: The handle to the existing menu.
3287 * id: Menuitem id. 3393 * id: Menuitem id.
3288 * flags: DW_MIS_ENABLED/DW_MIS_DISABLED 3394 * flags: DW_MIS_ENABLED/DW_MIS_DISABLED
3289 * DW_MIS_CHECKED/DW_MIS_UNCHECKED 3395 * DW_MIS_CHECKED/DW_MIS_UNCHECKED
3290 */ 3396 */
3291 void API dw_menu_item_set_state( HMENUI menux, unsigned long id, unsigned long state) 3397 void API dw_menu_item_set_state(HMENUI menux, unsigned long itemid, unsigned long state)
3292 { 3398 {
3293 NSLog(@"dw_menu_item_set_state() unimplemented\n"); 3399 id menu = menux;
3400 NSMenuItem *menuitem = (NSMenuItem *)[menu itemWithTag:itemid];
3401
3402 NSLog(@"MenuItem: %x", menuitem);
3403 if(menuitem != nil)
3404 {
3405 if(state & DW_MIS_CHECKED)
3406 {
3407 [menuitem setState:NSOnState];
3408 }
3409 else if(state & DW_MIS_UNCHECKED)
3410 {
3411 [menuitem setState:NSOffState];
3412 }
3413 if(state & DW_MIS_ENABLED)
3414 {
3415 [menuitem setEnabled:YES];
3416 }
3417 else if(state & DW_MIS_DISABLED)
3418 {
3419 [menuitem setEnabled:NO];
3420 }
3421 }
3294 } 3422 }
3295 3423
3296 /* Gets the notebook page from associated ID */ 3424 /* Gets the notebook page from associated ID */
3297 DWNotebookPage *_notepage_from_id(DWNotebook *notebook, unsigned long pageid) 3425 DWNotebookPage *_notepage_from_id(DWNotebook *notebook, unsigned long pageid)
3298 { 3426 {