Addressed request for change in NSMenu.m, and moved function of

-[_organizeMenu] to GSTheme-[organizeMenu:isHorizontal].
This commit is contained in:
Kyle J Cardoza 2023-09-22 18:57:15 -04:00
parent 096327e87b
commit 225eea02d5
3 changed files with 223 additions and 227 deletions

View file

@ -1539,16 +1539,12 @@ withRepeatedImage: (NSImage*)image
forMenuItem: (NSMenuItem *)menuItem;
/**
* Used to determine whether or not the theme handles organizing the app's main
* menu. The default implementation returns NO.
* Used by the theme to organize the main menu. The default implementation
* organizes the main menu in the same way that NSMenu's old default behaviour
* did, generating an "app name" menu for horizontal display.
*/
- (BOOL) organizesMainMenu;
/**
* Used by the theme to organize the main menu. The default implementation does
* nothing, because it will never be called.
*/
- (void) organizeMainMenu: (NSMenu *)menu;
- (void) organizeMenu: (NSMenu *)menu
isHorizontal: (BOOL)horizontal;
@end

View file

@ -33,6 +33,7 @@
#import "AppKit/NSWindow.h"
#import "AppKit/NSMenuView.h"
#import "AppKit/NSApplication.h"
#import "AppKit/NSImage.h"
#import "GNUstepGUI/GSTheme.h"
#import "GNUstepGUI/GSWindowDecorationView.h"
@ -58,6 +59,14 @@
}
@end
@interface NSMenu (GNUstepPrivate)
- (BOOL) _isMain;
- (void) _organizeMenu;
@end
@implementation GSTheme (Menu)
- (void) setMenu: (NSMenu *)menu
forWindow: (NSWindow *)window
@ -199,14 +208,215 @@
return title;
}
- (BOOL) organizesMainMenu
- (void) organizeMenu: (NSMenu *)menu
isHorizontal: (BOOL)horizontal
{
return NO;
}
NSString *infoString = _(@"Info");
NSString *servicesString = _(@"Services");
int i;
- (void) organizeMainMenu: (NSMenu *)menu
{
// Do nothing, just return.
if ([menu _isMain])
{
NSString *appTitle;
NSMenu *appMenu;
id <NSMenuItem> appItem;
appTitle = [[[NSBundle mainBundle] localizedInfoDictionary]
objectForKey: @"ApplicationName"];
if (nil == appTitle)
{
appTitle = [[NSProcessInfo processInfo] processName];
}
appItem = [menu itemWithTitle: appTitle];
appMenu = [appItem submenu];
if (horizontal == YES)
{
NSMutableArray *itemsToMove;
itemsToMove = [NSMutableArray new];
if (appMenu == nil)
{
[menu insertItemWithTitle: appTitle
action: NULL
keyEquivalent: @""
atIndex: 0];
appItem = [menu itemAtIndex: 0];
appMenu = [NSMenu new];
[menu setSubmenu: appMenu forItem: appItem];
RELEASE(appMenu);
}
else
{
int index = [menu indexOfItem: appItem];
if (index != 0)
{
RETAIN (appItem);
[menu removeItemAtIndex: index];
[menu insertItem: appItem atIndex: 0];
RELEASE (appItem);
}
}
if ([[GSTheme theme] menuShouldShowIcon])
{
NSImage *ti;
float bar;
ti = [[NSApp applicationIconImage] copy];
if (ti == nil)
{
ti = [[NSImage imageNamed: @"GNUstep"] copy];
}
[ti setScalesWhenResized: YES];
bar = [NSMenuView menuBarHeight] - 4;
[ti setSize: NSMakeSize(bar, bar)];
[appItem setImage: ti];
RELEASE(ti);
}
// Collect all simple items plus "Info" and "Services"
for (i = 1; i < [[menu itemArray] count]; i++)
{
NSMenuItem *anItem = [[menu itemArray] objectAtIndex: i];
NSString *title = [anItem title];
NSMenu *submenu = [anItem submenu];
if (submenu == nil)
{
[itemsToMove addObject: anItem];
}
else
{
// The menu may not be localized, so we have to
// check both the English and the local version.
if ([title isEqual: @"Info"] ||
[title isEqual: @"Services"] ||
[title isEqual: infoString] ||
[title isEqual: servicesString])
{
[itemsToMove addObject: anItem];
}
}
}
for (i = 0; i < [itemsToMove count]; i++)
{
NSMenuItem *anItem = [itemsToMove objectAtIndex: i];
[menu removeItem: anItem];
[appMenu addItem: anItem];
}
RELEASE(itemsToMove);
}
else
{
[appItem setImage: nil];
if (appMenu != nil)
{
NSArray *array = [NSArray arrayWithArray: [appMenu itemArray]];
/*
* Everything above the Serives menu goes into the info submenu,
* the rest into the main menu.
*/
int k = [appMenu indexOfItemWithTitle: servicesString];
// The menu may not be localized, so we have to
// check both the English and the local version.
if (k == -1)
k = [appMenu indexOfItemWithTitle: @"Services"];
if ((k > 0) && ([[array objectAtIndex: k - 1] isSeparatorItem]))
k--;
if (k == 1)
{
// Exactly one info item
NSMenuItem *anItem = [array objectAtIndex: 0];
[appMenu removeItem: anItem];
[menu insertItem: anItem atIndex: 0];
}
else if (k > 1)
{
id <NSMenuItem> infoItem;
NSMenu *infoMenu;
// Multiple info items, add a submenu for them
[menu insertItemWithTitle: infoString
action: NULL
keyEquivalent: @""
atIndex: 0];
infoItem = [menu itemAtIndex: 0];
infoMenu = [NSMenu new];
[menu setSubmenu: infoMenu forItem: infoItem];
RELEASE(infoMenu);
for (i = 0; i < k; i++)
{
NSMenuItem *anItem = [array objectAtIndex: i];
[appMenu removeItem: anItem];
[infoMenu addItem: anItem];
}
}
else
{
// No service menu, or it is the first item.
// We still look for an info item.
NSMenuItem *anItem = [array objectAtIndex: 0];
NSString *title = [anItem title];
// The menu may not be localized, so we have to
// check both the English and the local version.
if ([title isEqual: @"Info"] ||
[title isEqual: infoString])
{
[appMenu removeItem: anItem];
[menu insertItem: anItem atIndex: 0];
k = 1;
}
else
{
k = 0;
}
}
// Copy the remaining entries.
for (i = k; i < [array count]; i++)
{
NSMenuItem *anItem = [array objectAtIndex: i];
[appMenu removeItem: anItem];
[menu addItem: anItem];
}
[menu removeItem: appItem];
}
}
}
// recurse over all submenus
for (i = 0; i < [[menu itemArray] count]; i++)
{
NSMenuItem *anItem = [[menu itemArray] objectAtIndex: i];
NSMenu *submenu = [anItem submenu];
if (submenu != nil)
{
if ([submenu isTransient])
{
[submenu closeTransient];
}
[submenu close];
[submenu _organizeMenu];
}
}
[[menu menuRepresentation] update];
[menu sizeToFit];
}
@end

View file

@ -261,218 +261,8 @@ static BOOL menuBarVisible = YES;
- (void) _organizeMenu
{
NSString *infoString = _(@"Info");
NSString *servicesString = _(@"Services");
int i;
if ([self _isMain])
{
NSString *appTitle;
NSMenu *appMenu;
id <NSMenuItem> appItem;
appTitle = [[[NSBundle mainBundle] localizedInfoDictionary]
objectForKey: @"ApplicationName"];
if (nil == appTitle)
{
appTitle = [[NSProcessInfo processInfo] processName];
}
appItem = [self itemWithTitle: appTitle];
appMenu = [appItem submenu];
if ([[GSTheme theme] organizesMainMenu])
{
[[GSTheme theme] organizeMainMenu: self];
return;
}
if (_menu.horizontal == YES)
{
NSMutableArray *itemsToMove;
itemsToMove = [NSMutableArray new];
if (appMenu == nil)
{
[self insertItemWithTitle: appTitle
action: NULL
keyEquivalent: @""
atIndex: 0];
appItem = [self itemAtIndex: 0];
appMenu = [NSMenu new];
[self setSubmenu: appMenu forItem: appItem];
RELEASE(appMenu);
}
else
{
int index = [self indexOfItem: appItem];
if (index != 0)
{
RETAIN (appItem);
[self removeItemAtIndex: index];
[self insertItem: appItem atIndex: 0];
RELEASE (appItem);
}
}
if ([[GSTheme theme] menuShouldShowIcon])
{
NSImage *ti;
float bar;
ti = [[NSApp applicationIconImage] copy];
if (ti == nil)
{
ti = [[NSImage imageNamed: @"GNUstep"] copy];
}
[ti setScalesWhenResized: YES];
bar = [NSMenuView menuBarHeight] - 4;
[ti setSize: NSMakeSize(bar, bar)];
[appItem setImage: ti];
RELEASE(ti);
}
// Collect all simple items plus "Info" and "Services"
for (i = 1; i < [_items count]; i++)
{
NSMenuItem *anItem = [_items objectAtIndex: i];
NSString *title = [anItem title];
NSMenu *submenu = [anItem submenu];
if (submenu == nil)
{
[itemsToMove addObject: anItem];
}
else
{
// The menu may not be localized, so we have to
// check both the English and the local version.
if ([title isEqual: @"Info"] ||
[title isEqual: @"Services"] ||
[title isEqual: infoString] ||
[title isEqual: servicesString])
{
[itemsToMove addObject: anItem];
}
}
}
for (i = 0; i < [itemsToMove count]; i++)
{
NSMenuItem *anItem = [itemsToMove objectAtIndex: i];
[self removeItem: anItem];
[appMenu addItem: anItem];
}
RELEASE(itemsToMove);
}
else
{
[appItem setImage: nil];
if (appMenu != nil)
{
NSArray *array = [NSArray arrayWithArray: [appMenu itemArray]];
/*
* Everything above the Serives menu goes into the info submenu,
* the rest into the main menu.
*/
int k = [appMenu indexOfItemWithTitle: servicesString];
// The menu may not be localized, so we have to
// check both the English and the local version.
if (k == -1)
k = [appMenu indexOfItemWithTitle: @"Services"];
if ((k > 0) && ([[array objectAtIndex: k - 1] isSeparatorItem]))
k--;
if (k == 1)
{
// Exactly one info item
NSMenuItem *anItem = [array objectAtIndex: 0];
[appMenu removeItem: anItem];
[self insertItem: anItem atIndex: 0];
}
else if (k > 1)
{
id <NSMenuItem> infoItem;
NSMenu *infoMenu;
// Multiple info items, add a submenu for them
[self insertItemWithTitle: infoString
action: NULL
keyEquivalent: @""
atIndex: 0];
infoItem = [self itemAtIndex: 0];
infoMenu = [NSMenu new];
[self setSubmenu: infoMenu forItem: infoItem];
RELEASE(infoMenu);
for (i = 0; i < k; i++)
{
NSMenuItem *anItem = [array objectAtIndex: i];
[appMenu removeItem: anItem];
[infoMenu addItem: anItem];
}
}
else
{
// No service menu, or it is the first item.
// We still look for an info item.
NSMenuItem *anItem = [array objectAtIndex: 0];
NSString *title = [anItem title];
// The menu may not be localized, so we have to
// check both the English and the local version.
if ([title isEqual: @"Info"] ||
[title isEqual: infoString])
{
[appMenu removeItem: anItem];
[self insertItem: anItem atIndex: 0];
k = 1;
}
else
{
k = 0;
}
}
// Copy the remaining entries.
for (i = k; i < [array count]; i++)
{
NSMenuItem *anItem = [array objectAtIndex: i];
[appMenu removeItem: anItem];
[self addItem: anItem];
}
[self removeItem: appItem];
}
}
}
// recurse over all submenus
for (i = 0; i < [_items count]; i++)
{
NSMenuItem *anItem = [_items objectAtIndex: i];
NSMenu *submenu = [anItem submenu];
if (submenu != nil)
{
if ([submenu isTransient])
{
[submenu closeTransient];
}
[submenu close];
[submenu _organizeMenu];
}
}
[[self menuRepresentation] update];
[self sizeToFit];
[[GSTheme theme] organizeMenu: self
isHorizontal: _menu.horizontal];
}
- (void) _setGeometry