It's easy to enable the "inspector bar" for text views so that a bar appears at the top of the screen with various formatting buttons. (Although I had some confusion until I learned to make sure I was selecting the text view in a scroll view, and not the scroll view itself). I can either programmatically use [textView setUsesInspectorBar:YES] or go to the Attributes Inspector and check the "Inspector Bar" box in the "Uses" section.
My question is, how can I further control the inspector bar? I'm having trouble finding information on it in the XCode documentation or online. I'd like to be able to position it in a different place on the screen. Being able to pick and choose which specific controls are in the bar would be great too.
The answer is, you aren't meant to further control the inspector bar. There's nothing in the documentation because, well, there's nothing. Apple's saying, use it or don't use it.
However, if you dig into it a bit, you will find that the inspector bar is a very interesting control. It's not displayed as part of the text view, but rather (privately) embedded in the "window view" itself. When I say "window view," I mean the superview of the content view.
If you list the subviews of that "window view":
NSLog(@"%@", [self.testTextView.window.contentView superview].subviews);
You end up with:
2012-08-02 15:59:30.145 Example[16702:303] (
"<_NSThemeCloseWidget: 0x100523dc0>", // the close button
"<_NSThemeWidget: 0x100525ce0>", // the minimize button?
"<_NSThemeWidget: 0x100524e90>", // the maximize button?
"<NSView: 0x100512ad0>", // the content view
"<__NSInspectorBarView: 0x100529d50>", // the inspector view
"(<NSToolbarView: 0x10054e650>: FD2E0533-AB18-4E7E-905A-AC816CB80A26)" // the toolbar
)
As you can see, AppKit
puts the inspector bar at the same level as other top level window controls. Now this is getting into the land of private APIs, but simply tinkering with the "window view" shouldn't get any apps rejected.
You can try to get a reference to the __NSInspectorBarView
from here. It seems like it is always the subview right after the content view, so something like this may work:
NSArray *topLevelViews = [self.testTextView.window.contentView superview].subviews;
NSUInteger indexOfContentView = [topLevelViews indexOfObject:self.testTextView.window.contentView];
if (indexOfContentView + 1 < topLevelViews.count) {
NSView *inspectorBar = [topLevelViews objectAtIndex:indexOfContentView + 1];
NSLog(@"%@", inspectorBar);
}
NSLog(@"%@", topLevelViews);
Since this immediately breaks if Apple changes the ordering of the top level views, it may not be a good idea for an application for production. Another idea is:
NSView *inspectorBarView = nil;
for (NSView *topLevelView in topLevelViews) {
if ([topLevelView isKindOfClass:NSClassFromString(@"__NSInspectorBarView")]) {
inspectorBarView = topLevelView;
}
}
NSLog(@"%@", inspectorBarView);
I don't know if the use of NSClassFromString()
will pass App Store review guidelines, however, since once again, it's dependent on private APIs.
That being said, once you get a reference to the inspector bar view, things still don't work too well. You can try repositioning it at the bottom:
if (inspectorBarView) {
NSRect newFrame = inspectorBarView.frame;
newFrame.origin = NSZeroPoint;
[inspectorBarView setAutoresizingMask:NSViewMaxYMargin | NSViewMaxXMargin];
[inspectorBarView setFrame:newFrame];
}
But you end up with a misdrawn toolbar, so more work would be necessary there:
My ideas would be to try to shift the content view's height up to cover up the gray left-over area (which would have to be done every time the window is resized, maybe tinkering with autoresizing masks may make it easier) and custom draw a background for the inspector bar at the bottom.
EDIT
Oh, and you should file a feature request for this too. bugreport.apple.com
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With