Можно ли нарисовать в области меток NSToolbar? - PullRequest
13 голосов
/ 29 мая 2011

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

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

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

Ответы [ 6 ]

5 голосов
/ 01 июня 2011

Представление статуса XCode не NSToolbarItem - это пользовательский NSView, вставленный в NSToolbar.

4 голосов
/ 08 августа 2012

Вы должны создать подкласс 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 пункта выше, прежде чем передать его элементу панели инструментов. Если он больше, панель инструментов будет слишком высокой.

4 голосов
/ 30 июля 2012

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

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

Вы получите enter image description here

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) 

enter image description here

И вид деятельности исчез:)

Однако в полноэкранном режиме.Он не добавляет его в NSToolbarView, он добавляет его в NSNextStepFrame, который является суперпредставлением NSToolbarView.Панель инструментов не содержится в суперпредставлении окна просмотра в полноэкранном режиме.Я думаю, что это как-то связано с полноэкранным поведением и пробелами.

1 голос
/ 22 января 2012

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

-(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];
}
1 голос
/ 05 июля 2011

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

0 голосов
/ 20 февраля 2012

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: метод).

...