Можно ли нарисовать в области меток NSToolbar?

У меня есть NSToolbarItem это использует представление, подобное представлению статуса XCode. В настоящее время у него нет метки, но я не могу найти способ нарисовать область, где обычно рисуется метка элемента. Я хотел бы, чтобы представление расширилось в эту область точно так же, как представление статуса Xcode. Я знаю самую нижнюю часть пикселей NSToolbar находится за пределами границ, но я видел, как другие приложения рисуют в области меток. Есть идеи?

Edit: для пояснения, это представление статуса, на которое я ссылаюсь в Xcode:

Я хочу, чтобы границы моего представления расширялись за пределы области надписей на панели инструментов так же, как это делается в Xcode.

6 ответов

Представление статуса XCode не является NSToolbarItem это обычай NSView вставлен в NSToolbar,

Если вы войдете

    NSLog(@" %@", [[self.window.contentView superview] subviews]);

Ты получишь

NSToolbarView не изменяет размеры своего подпредставления автоматически, поэтому у вас есть проблемы с его центрированием. А также [self.window.contentView superview] не содержит панель инструментов в полноэкранном режиме.

Вы можете добавить нужный вам вид в центре панели инструментов к [self.window.contentView superview] когда не в полноэкранном режиме и расположите его правильно. Это будет автоматически изменять размер и оставаться в центре. При переключении в полноэкранный режим удалите его из [self.window.contentView superview] и добавьте его в NSToolbarView в центре таким образом, чтобы он оставался на панели инструментов, и он также перемещается вниз вместе с панелью инструментов при открытии строки состояния.

Вы можете получить представление панели инструментов, просматривая подпредставления или используя приватный метод

[[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;
}

Жидкокристаллическое представление должно быть (в этом случае) 32 пунктами высоко, прежде чем передать его элементу панели инструментов. Если он больше, панель инструментов будет слишком высокой.

Этот код устанавливает окно, плавающее поверх панели инструментов.

-(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];
}

Представление статуса XCode - фактически отдельное окно, плавающее по панели инструментов. (Это легко проверить: нажмите ⇧⌘4 и нажмите пробел, чтобы сделать снимок экрана с окном, и наведите на него курсор мыши.)

ITunes-XCode-LCD, который располагается в области надписей, не является NSToolbarItem, поскольку NSToolbar не является NSViewВы не можете добавить подпредставление к 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:order: метод).

Другие вопросы по тегам