Ответ 1
Просмотр состояния Xcode не является NSToolbarItem
является пользовательским NSView
, вставленным в NSToolbar
.
У меня есть NSToolbarItem
, который использует представление, подобное виду состояния Xcode. В настоящее время он не имеет метки, но я не могу понять способ рисования в области, где обычно будет нарисована метка элемента. Я хотел бы, чтобы представление распространилось на эту область так же, как и на вид статуса Xcode. Я знаю, что самая нижняя часть пикселей NSToolbar
выходит за границы, но я видел, как другие приложения вставляют в область метки. Любые идеи?
Изменить: для пояснения это вид состояния, о котором я говорю в Xcode:
Я хочу, чтобы границы моего представления проходили мимо области меток панели инструментов так же, как и представление в Xcode.
Просмотр состояния Xcode не является NSToolbarItem
является пользовательским NSView
, вставленным в NSToolbar
.
Если вы зарегистрируете
NSLog(@" %@", [[self.window.contentView superview] subviews]);
Вы получите
NSToolbarView не выполняет авторазрешение подзапросов, поэтому у вас есть проблемы с его центрированием.
И [self.window.contentView superview]
не содержит панель инструментов в полноэкранном режиме.
Вы можете добавить представление, которое хотите в центре панели инструментов, к [self.window.contentView superview]
, если оно не находится в полноэкранном режиме, и поместите его правильно. Он будет автоматизировать и оставаться в центре.
При переключении на полноэкранный режим удалите его из [self.window.contentView superview]
и добавьте его в NSToolbarView по центру таким образом, чтобы он оставался на панели инструментов, и он также перемещается вниз с помощью панели инструментов, когда вы показываете строку состояния.
Вы можете получить представление панели инструментов, итерации через subviews или с помощью частного метода
[[self.window toolbar] performSelector:@selector(_toolbarView)];
Обновление: Я немного поработал с отладчиком, и я узнал, что это то, что делает Xcode. По крайней мере, пока не в полноэкранном режиме.
thealch3m1st$ sudo lldb
(lldb) process attach -p 11478
Process 11478 stopped
Executable module set to "/Applications/Xcode.app/Contents/MacOS/Xcode".
Architecture set to: x86_64.
(lldb) po [NSApplication sharedApplication]
(id) $0 = 0x000000040013f5e0 <IDEApplication: 0x40013f5e0>
(lldb) po [$0 mainWindow]
(id) $1 = 0x0000000000000000 <nil>
(lldb) po [$0 windows]
(id) $2 = 0x0000000408278460 <__NSArrayM 0x408278460>(
<IDEWelcomeWindow: 0x40141c1e0>,
<IDEWorkspaceWindow: 0x401ef2780>,
<NSComboBoxWindow: 0x402019be0>,
<NSWindow: 0x4022adc60>,
<IDEOrganizerWindow: 0x402951b20>
)
(lldb) po [$0 windows]
(id) $3 = 0x0000000408820300 <__NSArrayM 0x408820300>(
<IDEWelcomeWindow: 0x40141c1e0>,
<IDEWorkspaceWindow: 0x401ef2780>,
<NSComboBoxWindow: 0x402019be0>,
<NSWindow: 0x4022adc60>,
<IDEOrganizerWindow: 0x402951b20>
)
(lldb) [$3 objectAtIndex:1]
error: '[$3' is not a valid command.
(lldb) po [$3 objectAtIndex:1]
(id) $4 = 0x0000000401ef2780 <IDEWorkspaceWindow: 0x401ef2780>
(lldb) po [$4 contentView]
(id) $5 = 0x0000000401ef0920 <NSView: 0x401ef0920>
(lldb) po [$5 superview]
(id) $6 = 0x0000000401ef2e20 <NSThemeFrame: 0x401ef2e20>
(lldb) po [$6 subviews]
(id) $7 = 0x0000000401ef3800 <__NSArrayM 0x401ef3800>(
<_NSThemeCloseWidget: 0x401ef3120>,
<_NSThemeWidget: 0x401ef3b80>,
<_NSThemeWidget: 0x401ef40e0>,
<NSView: 0x401ef0920>,
<IDEActivityView: 0x4020cd700>,
<_NSThemeFullScreenButton: 0x402017b20>,
(<NSToolbarView: 0x4020192e0>: Xcode.IDEKit.ToolbarDefinition.Workspace),
<DVTDualProxyWindowTitleView: 0x40225e0a0>,
<NSThemeDocumentButton: 0x402698020>
)
(lldb) po [$7 objectAtIndex:4]
(id) $8 = 0x00000004020cd700 <IDEActivityView: 0x4020cd700>
(lldb) [$8 setHidden:YES]
error: '[$8' is not a valid command.
(lldb) po [$8 setHidden:YES]
(id) $9 = 0x0000000000000000 <nil>
(lldb) continue
Process 11478 resuming
(lldb)
И вид активности исчез:)
Пока на полном экране. Он не добавляет его в NSToolbarView, он добавляет его в NSNextStepFrame, который является надстройкой NSToolbarView. В полноэкранном режиме панель инструментов не содержится в окне просмотра содержимого окна. Я думаю, что это имеет какое-то отношение к полноэкранному поведению и пространствам.
Вы должны подклассифицировать NSToolbarItem:
- (id)initWithItemIdentifier:(NSString *)itemIdentifier {
self = [super initWithItemIdentifier:itemIdentifier];
if (self) {
self.hideLabel = NO;
}
return self;
}
- (NSView *)view {
NSView *view = [super view];
if (self.hideLabel) {
CGRect frame = view.frame;
frame.size.height = 45.0f;
frame.origin.y = 8.0f;
view.frame = frame;
}
return view;
}
- (NSString *)label {
return self.hideLabel ? @"" : [super label];
}
Создайте панель инструментов:
NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"Toolbar"];
toolbar.delegate = self;
self.window.toolbar = toolbar;
Используйте NSToolbarDelegate, чтобы заполнить панель инструментов:
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar {
return [NSArray arrayWithObjects:@"Button", @"LCD", NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, nil];
}
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar {
return [NSArray arrayWithObjects:@"Button", NSToolbarFlexibleSpaceItemIdentifier, @"LCD", NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, nil];
}
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag {
MyToolbarItem *item = [[MyToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
if ([itemIdentifier isEqualToString:@"LCD"]) {
item.view = self.lcdView;
item.hideLabel = YES;
} else if ([itemIdentifier isEqualToString:@"Button"]) {
item.label = NSLocalizedString(@"Button", nil);
item.image = [NSImage imageNamed:@"Button"];
item.hideLabel = NO;
}
return item;
}
В представлении lcd должно быть (в данном случае) 32 очка выше, прежде чем передать его на элемент панели инструментов. Если он больше, панель инструментов будет слишком высокой.
Вид состояния Xcode фактически представляет собой отдельное окно, плавающее над панелью инструментов. (Это легко проверить: нажмите ⇧⌘4 и нажмите пробел, чтобы снять снимок экрана и наведите указатель мыши на него.)
Этот код устанавливает окно, плавающее поверх панели инструментов.
-(void)applicationWillFinishLaunching:(NSNotification *)aNotification {
NSRect winframe = [self.window frame];
NSRect viewrect = NSMakeRect(0, 0, 400, 50);
NSRect winrect = viewrect;
winrect.origin.x = NSMidX(winframe) - NSMidX(winrect);
winrect.origin.y = NSHeight(winframe) - NSHeight(winrect) - 18;
NSWindow* win = [[[NSWindow alloc] initWithContentRect:winrect styleMask: NSBorderlessWindowMask backing: NSBackingStoreBuffered defer: NO] autorelease];
[win setBackgroundColor:[NSColor clearColor]];
[win setOpaque:NO];
[win setIgnoresMouseEvents:YES];
MyStatusView* v = [[[MyStatusView alloc] initWithFrame:viewrect] autorelease];
[win setContentView: v];
[self.window addChildWindow:win ordered:NSWindowAbove];
}
iTunes-XCode-LCD, который распространяется в области ярлыков, не является NSToolbarItem
. Поскольку NSToolbar
не является NSView
, вы не можете добавить subview к экземпляру NSToolbar
.
Но вы можете добавить пользовательский вид непосредственно в оконный фрейм, к которому можно получить доступ через путь свойства contentView.superview
экземпляра NSWindow
!
т.е. создайте свой собственный подкласс NSWindowController и поместите такой код в метод windowDidLoad:
- (void)windowDidLoad
{
[super windowDidLoad];
NSImage *image = [NSImage imageNamed:@"lcd"];
NSRect lcdFrameRect = NSMakeRect(self.window.frame.size.width / 2 - image.size.width/2, self.window.frame.size.height - image.size.height - 20,
image.size.width, image.size.height);
NSImageView *lcdView = [[NSImageView alloc] initWithFrame: lcdFrameRect];
[lcdView setImage: image];
lcdView.autoresizingMask = NSViewMinYMargin | NSViewMinXMargin | NSViewMaxXMargin;
NSView * contentView = self.window.contentView;
[contentView.superview addSubview: lcdView];
}
Этот код не будет работать в полноэкранном режиме Lion, так как окно кадра не отображается в полноэкранном режиме. Чтобы исправить это, представление можно перемещать в плавающем окне, дочернем из основного (просто проверьте метод NSWindow addChildWindow: ordered:).