Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Draw tab triggers and key equivalents in menu
The old techniques used to set key equivalents no longer work. Unfortunately, this technique is only a workaround and is not pixel-for-pixel identical due to the way NSMenuItem lays itself out when rendering a key equivalent; but I think it's the best that can be done for now.
- Loading branch information
Showing
3 changed files
with
131 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#import <bundles/bundles.h> | ||
|
||
struct BundleItemMenuItemAlignment | ||
{ | ||
BundleItemMenuItemAlignment () : maxAlignmentWidth(0), maxRightWidth(0) {} | ||
CGFloat maxAlignmentWidth; | ||
CGFloat maxRightWidth; | ||
}; | ||
|
||
@interface BundleItemMenuItem : NSMenuItem | ||
{ | ||
BOOL hasRightPart; | ||
} | ||
+ (BundleItemMenuItem*)menuItemWithBundleItem:(bundles::item_ptr const&)bundleItem alignmentData:(BundleItemMenuItemAlignment&)alignment; | ||
- (void)updateAlignment:(BundleItemMenuItemAlignment&)alignment; | ||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
#import "BundleItemMenuItem.h" | ||
#import <OakFoundation/NSString Additions.h> | ||
#import <ns/ns.h> | ||
|
||
@interface BundleItemMenuItem () | ||
- (BundleItemMenuItem*)initWithBundleItem:(bundles::item_ptr const&)bundleItem alignmentData:(BundleItemMenuItemAlignment&)alignment; | ||
- (void)setAttributedTitleWithTitle:(NSAttributedString*)itemTitle equivLeft:(NSAttributedString*)equivLeft equivRight:(NSAttributedString*)equivRight alignmentData:(BundleItemMenuItemAlignment&)alignment; | ||
@end | ||
|
||
@implementation BundleItemMenuItem | ||
+ (BundleItemMenuItem*)menuItemWithBundleItem:(bundles::item_ptr const&)bundleItem alignmentData:(BundleItemMenuItemAlignment&)alignment | ||
{ | ||
return [[[self alloc] initWithBundleItem:bundleItem alignmentData:alignment] autorelease]; | ||
} | ||
|
||
- (BundleItemMenuItem*)initWithBundleItem:(bundles::item_ptr const&)bundleItem alignmentData:(BundleItemMenuItemAlignment&)alignment | ||
{ | ||
if ((self = [super init])) | ||
{ | ||
NSDictionary* fontAttrs = @{ NSFontAttributeName : [NSFont menuFontOfSize:14] /* passing 0 should return the default size, but it doesn’t */ }; | ||
NSDictionary* smallFontAttrs = @{ NSFontAttributeName : [NSFont menuFontOfSize:11] }; | ||
NSAttributedString* title = [[NSAttributedString alloc] initWithString:[NSString stringWithCxxString:bundleItem->name()] attributes:fontAttrs]; | ||
NSAttributedString* equivLeft = nil; | ||
NSAttributedString* equivRight = nil; | ||
|
||
std::string const tabTrigger(bundleItem->value_for_field(bundles::kFieldTabTrigger)); | ||
std::string const keyEquiv(bundleItem->value_for_field(bundles::kFieldKeyEquivalent)); | ||
|
||
if(tabTrigger != NULL_STR) | ||
{ | ||
equivLeft = [[[NSAttributedString alloc] initWithString:[NSString stringWithCxxString:(" "+tabTrigger+"\u21E5 ")] attributes:smallFontAttrs] autorelease]; | ||
} | ||
else if(keyEquiv != NULL_STR) | ||
{ | ||
size_t keyStart = 0; | ||
std::string const glyphStr(ns::glyphs_for_event_string(keyEquiv, &keyStart)); | ||
|
||
equivLeft = [[[NSAttributedString alloc] initWithString:[NSString stringWithCxxString:glyphStr.substr(0, keyStart)] attributes:fontAttrs] autorelease]; | ||
equivRight = [[[NSAttributedString alloc] initWithString:[NSString stringWithCxxString:glyphStr.substr(keyStart)] attributes:fontAttrs] autorelease]; | ||
} | ||
|
||
[self setAttributedTitleWithTitle:title equivLeft:equivLeft equivRight:equivRight alignmentData:alignment]; | ||
} | ||
|
||
return self; | ||
} | ||
|
||
- (void)setAttributedTitleWithTitle:(NSAttributedString*)itemTitle equivLeft:(NSAttributedString*)equivLeft equivRight:(NSAttributedString*)equivRight alignmentData:(BundleItemMenuItemAlignment&)alignment | ||
{ | ||
NSMutableAttributedString* title = [[[NSMutableAttributedString alloc] initWithAttributedString:itemTitle] autorelease]; | ||
[title beginEditing]; | ||
|
||
CGFloat alignmentWidth = [itemTitle size].width; | ||
CGFloat rightWidth = [equivRight size].width; | ||
CGFloat leftWidth = [equivLeft size].width; | ||
|
||
if(equivLeft) | ||
{ | ||
[title appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\t"] autorelease]]; | ||
[title appendAttributedString:equivLeft]; | ||
|
||
alignmentWidth += leftWidth + 20; | ||
|
||
if(equivRight) | ||
{ | ||
[title appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\t"] autorelease]]; | ||
[title appendAttributedString:equivRight]; | ||
hasRightPart = YES; | ||
} | ||
} | ||
|
||
if(alignmentWidth > alignment.maxAlignmentWidth) | ||
alignment.maxAlignmentWidth = alignmentWidth; | ||
|
||
if(rightWidth > alignment.maxRightWidth) | ||
alignment.maxRightWidth = rightWidth; | ||
|
||
[title endEditing]; | ||
[self setAttributedTitle:title]; | ||
} | ||
|
||
- (void)updateAlignment:(BundleItemMenuItemAlignment&)alignment | ||
{ | ||
NSMutableParagraphStyle* pStyle = [[NSMutableParagraphStyle new] autorelease]; | ||
if(hasRightPart) | ||
{ | ||
[pStyle setTabStops:@[ | ||
[[[NSTextTab alloc] initWithType:NSRightTabStopType location:alignment.maxAlignmentWidth] autorelease], | ||
[[[NSTextTab alloc] initWithType:NSLeftTabStopType location:alignment.maxAlignmentWidth + 0.01] autorelease] | ||
]]; | ||
} | ||
else | ||
{ | ||
[pStyle setTabStops:@[ | ||
[[[NSTextTab alloc] initWithType:NSRightTabStopType location:alignment.maxAlignmentWidth + alignment.maxRightWidth] autorelease] | ||
]]; | ||
} | ||
|
||
NSMutableAttributedString* title = [[self attributedTitle] mutableCopy]; | ||
This comment has been minimized.
Sorry, something went wrong. |
||
[title addAttribute:NSParagraphStyleAttributeName value:pStyle range:NSMakeRange(0, [title length])]; | ||
|
||
[self setAttributedTitle:title]; | ||
} | ||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
#import "BundleMenuDelegate.h" | ||
#import "BundleItemMenuItem.h" | ||
#import <OakAppKit/NSMenu Additions.h> | ||
#import <OakAppKit/NSMenuItem Additions.h> | ||
#import <OakFoundation/NSString Additions.h> | ||
|
@@ -33,6 +34,9 @@ - (void)menuNeedsUpdate:(NSMenu*)aMenu | |
D(DBF_BundleMenu, bug("\n");); | ||
[aMenu removeAllItems]; | ||
[subdelegates removeAllObjects]; | ||
|
||
BundleItemMenuItemAlignment alignmentData; | ||
NSMutableArray* menuItems = [NSMutableArray array]; | ||
|
||
citerate(item, umbrellaItem->menu()) | ||
{ | ||
|
@@ -56,14 +60,18 @@ - (void)menuNeedsUpdate:(NSMenu*)aMenu | |
|
||
default: | ||
{ | ||
NSMenuItem* menuItem = [aMenu addItemWithTitle:[NSString stringWithCxxString:(*item)->name()] action:@selector(doBundleItem:) keyEquivalent:@""]; | ||
[menuItem setKeyEquivalentCxxString:(*item)->value_for_field(bundles::kFieldKeyEquivalent)]; | ||
[menuItem setTabTriggerCxxString:(*item)->value_for_field(bundles::kFieldTabTrigger)]; | ||
BundleItemMenuItem* menuItem = [BundleItemMenuItem menuItemWithBundleItem:*item alignmentData:alignmentData]; | ||
[menuItem setRepresentedObject:[NSString stringWithCxxString:(*item)->uuid()]]; | ||
[aMenu addItem:menuItem]; | ||
This comment has been minimized.
Sorry, something went wrong.
sorbits
Member
|
||
|
||
[menuItems addObject:menuItem]; | ||
} | ||
break; | ||
} | ||
} | ||
|
||
for(BundleItemMenuItem* menuItem in menuItems) | ||
[menuItem updateAlignment:alignmentData]; | ||
} | ||
|
||
- (void)menuWillOpen:(NSMenu*)aMenu | ||
|
Whoops, leaked this. Will fix in next commit.