具有 attributedTitle 的 NSMenuItem 在 macOS 10.12.2 Sierra 中不起作用
NSMenuItem with attributedTitle not working in macOS 10.12.2 Sierra
我创建了一个文件名和修改日期的菜单。我使用带有制表位设置的属性字符串对齐它们以适应最长的文件名。这在 macOS 10.8-10.11 上运行良好。
菜单应该是这样的 - 在 macOS 10.11 和 10.12.1 上:
在 Sierra 10.12.2 上它现在看起来像这样:
各平台代码相同:
#define FILEICONSIZE 16.0
#define FILEDATELEADINGSPACE 16.0
...
- (void)rebuildMenu:(NSMenu *)menu fromFiles:(NSMutableArray <FileRepresentation *> *)files
{
NSMenuItem *item = [menu itemWithTitle:NSLocalizedString(@"Open iCloud", nil)];
NSMenu *icloudFilesMenu = item.submenu;
if (!icloudFilesMenu)
return;
static NSImage *icon;
if (!icon) {
icon = [NSImage imageNamed:@"SSDoc"];
icon.size = NSMakeSize(FILEICONSIZE, FILEICONSIZE);
}
[icloudFilesMenu removeAllItems];
NSDictionary *stdAttributes = @{ NSFontAttributeName: [NSFont menuBarFontOfSize:0] };
NSDictionary *ttAttributes = @{ NSFontAttributeName: [NSFont toolTipsFontOfSize:0] };
// get max width of filename
CGFloat maxWidth = 0;
for (FileRepresentation *f in files) {
NSMutableAttributedString *attribTitle;
attribTitle = [[[NSAttributedString alloc] initWithString:f.fileName attributes:stdAttributes] mutableCopy];
[attribTitle addAttribute:NSParagraphStyleAttributeName
value:[NSParagraphStyle defaultParagraphStyle]
range:NSMakeRange(0, f.fileName.length)];
NSRect rect = [attribTitle boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading];
if (rect.size.width > maxWidth)
maxWidth = rect.size.width;
}
maxWidth += FILEDATELEADINGSPACE;
NSMutableParagraphStyle *tabbedStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
tabbedStyle.tabStops = @[[[NSTextTab alloc] initWithTextAlignment:NSLeftTextAlignment location:maxWidth options:@{}]];
// build file menu
for (FileRepresentation *f in files) {
NSMutableAttributedString *attribTitle;
NSString *fname;
fname = [f.fileName stringByAppendingString:@"\t"];
item = [[NSMenuItem alloc] initWithTitle:fname action:@selector(openFile:) keyEquivalent:@""];
attribTitle = [[[NSAttributedString alloc] initWithString:fname attributes:stdAttributes] mutableCopy];
[attribTitle addAttribute:NSParagraphStyleAttributeName
value:tabbedStyle
range:NSMakeRange(0, fname.length)];
// append file date in tool tip font
if (f.modDate) {
NSAttributedString *attribfDate;
NSString *fdate = [((AppController *)[(NSApplication *)NSApp delegate]).fileDateFormatter stringFromDate:f.modDate];
attribfDate = [[NSAttributedString alloc] initWithString:fdate attributes:ttAttributes];
[attribTitle appendAttributedString:attribfDate];
}
item.attributedTitle = attribTitle;
item.target = self;
item.enabled = YES;
item.representedObject = f.url;
item.image = icon;
[icloudFilesMenu addItem:item];
}
}
有什么想法吗?
我发现将 NSParagraphStyle's
firstLineHeadIndent
或 headIndent
属性 设置为大于 0 的数字会使其再次工作。
tabbedStyle.tabStops = ...
tabbedStyle.headIndent = DBL_EPSILON; // A tiny number so the indent is not noticeable
我创建了一个文件名和修改日期的菜单。我使用带有制表位设置的属性字符串对齐它们以适应最长的文件名。这在 macOS 10.8-10.11 上运行良好。
菜单应该是这样的 - 在 macOS 10.11 和 10.12.1 上:
在 Sierra 10.12.2 上它现在看起来像这样:
各平台代码相同:
#define FILEICONSIZE 16.0
#define FILEDATELEADINGSPACE 16.0
...
- (void)rebuildMenu:(NSMenu *)menu fromFiles:(NSMutableArray <FileRepresentation *> *)files
{
NSMenuItem *item = [menu itemWithTitle:NSLocalizedString(@"Open iCloud", nil)];
NSMenu *icloudFilesMenu = item.submenu;
if (!icloudFilesMenu)
return;
static NSImage *icon;
if (!icon) {
icon = [NSImage imageNamed:@"SSDoc"];
icon.size = NSMakeSize(FILEICONSIZE, FILEICONSIZE);
}
[icloudFilesMenu removeAllItems];
NSDictionary *stdAttributes = @{ NSFontAttributeName: [NSFont menuBarFontOfSize:0] };
NSDictionary *ttAttributes = @{ NSFontAttributeName: [NSFont toolTipsFontOfSize:0] };
// get max width of filename
CGFloat maxWidth = 0;
for (FileRepresentation *f in files) {
NSMutableAttributedString *attribTitle;
attribTitle = [[[NSAttributedString alloc] initWithString:f.fileName attributes:stdAttributes] mutableCopy];
[attribTitle addAttribute:NSParagraphStyleAttributeName
value:[NSParagraphStyle defaultParagraphStyle]
range:NSMakeRange(0, f.fileName.length)];
NSRect rect = [attribTitle boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading];
if (rect.size.width > maxWidth)
maxWidth = rect.size.width;
}
maxWidth += FILEDATELEADINGSPACE;
NSMutableParagraphStyle *tabbedStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
tabbedStyle.tabStops = @[[[NSTextTab alloc] initWithTextAlignment:NSLeftTextAlignment location:maxWidth options:@{}]];
// build file menu
for (FileRepresentation *f in files) {
NSMutableAttributedString *attribTitle;
NSString *fname;
fname = [f.fileName stringByAppendingString:@"\t"];
item = [[NSMenuItem alloc] initWithTitle:fname action:@selector(openFile:) keyEquivalent:@""];
attribTitle = [[[NSAttributedString alloc] initWithString:fname attributes:stdAttributes] mutableCopy];
[attribTitle addAttribute:NSParagraphStyleAttributeName
value:tabbedStyle
range:NSMakeRange(0, fname.length)];
// append file date in tool tip font
if (f.modDate) {
NSAttributedString *attribfDate;
NSString *fdate = [((AppController *)[(NSApplication *)NSApp delegate]).fileDateFormatter stringFromDate:f.modDate];
attribfDate = [[NSAttributedString alloc] initWithString:fdate attributes:ttAttributes];
[attribTitle appendAttributedString:attribfDate];
}
item.attributedTitle = attribTitle;
item.target = self;
item.enabled = YES;
item.representedObject = f.url;
item.image = icon;
[icloudFilesMenu addItem:item];
}
}
有什么想法吗?
我发现将 NSParagraphStyle's
firstLineHeadIndent
或 headIndent
属性 设置为大于 0 的数字会使其再次工作。
tabbedStyle.tabStops = ...
tabbedStyle.headIndent = DBL_EPSILON; // A tiny number so the indent is not noticeable