objective-c - INAppStoreWindow 标题栏上的 NSSplitView 分隔符

标签 objective-c macos cocoa nssplitview

我正在尝试创建类似 Reeder/Sparrow 的 UI 来处理我的应用程序的内容。目前我使用一个 NSSplitView,里面有两个 NSView(左边的一个是内容列表,右边的另一个是“检查器”)。

我想知道的是如何在标题栏上创建分隔线,它也充当 Split View的分隔线。 我已经在使用 INAppStoreWindow子类。

有什么想法吗?提前致谢

最佳答案

我这样做的方法是添加一个 NSSplitView 子类作为 INAppStoreWindow 的 tileBarView 的 subview :

// This code comes from the INAppStoreWindow readme
INAppStoreWindow *appStoreWindow = (INAppStoreWindow *)[self window];

// self.titleView is a an IBOutlet to an NSView that has been configured in IB with everything you want in the title bar
self.windowTitleBarView.frame = appStoreWindow.titleBarView.bounds;
self.windowTitleBarView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[appStoreWindow.titleBarView addSubview:self.windowTitleBarView];

两个棘手的部分是让这个 Split View表现得像一个标题栏(即仍然允许您拖动窗口),并将标题栏中的 Split View与窗口中的主 Split View同步,所以对用户来说,它们看起来是一样的。

要解决第一个问题,您要做的不仅仅是从标题栏 NSSplitView 子类中的 -mouseDownCanMovewWindow 返回 YES。如果你这样做了,tile bar 的所有 subview 都不会响应鼠标事件。相反,这样做:

@implementation MyTitleBarSplitView

- (BOOL)mouseDownCanMoveWindow
{
    return NO;
}

// Code below adapted from http://www.cocoabuilder.com/archive/cocoa/219261-conditional-mousedowncanmovewindow-for-nsview.html
- (void)mouseDown:(NSEvent*)theEvent 
{
    NSWindow *window = [self window];
    NSPoint mouseLocation = [theEvent locationInWindow];
    NSRect dividerRect = NSMakeRect(NSMaxX([[[self subviews] objectAtIndex:0] frame]), 
                                    NSMinY([self bounds]), 
                                    [self dividerThickness], 
                                    NSHeight([self bounds]));
    dividerRect = NSInsetRect(dividerRect, -2, 0);
    NSPoint mouseLocationInMyCoords = [self convertPoint:mouseLocation fromView:nil];
    if (![self mouse:mouseLocationInMyCoords inRect:dividerRect]) 
    {
        mouseLocation = [window convertBaseToScreen:mouseLocation];
        NSPoint origin = [window frame].origin;
        // Now we loop handling mouse events until we get a mouse up event.
        while ((theEvent = [NSApp nextEventMatchingMask:NSLeftMouseDownMask|NSLeftMouseDraggedMask|NSLeftMouseUpMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES])&&([theEvent type]!=NSLeftMouseUp)) 
        {
            @autoreleasepool 
            {
                NSPoint currentLocation = [window convertBaseToScreen:[theEvent locationInWindow]];
                origin.x += currentLocation.x-mouseLocation.x;
                origin.y += currentLocation.y-mouseLocation.y;
                // Move the window by the mouse displacement since the last event.
                [window setFrameOrigin:origin];
                mouseLocation = currentLocation;
            }
        }
        [self mouseUp:theEvent];
        return;
    }

    [super mouseDown:theEvent];
}

@end

第二个任务是同步两个 Split View。使您的 Controller 类(可能是窗口 Controller ,但在您的代码中有意义的任何东西)成为您的主要内容 Split View和标题栏 Split View的委托(delegate)。然后,实现下面的两个 NSSplitView 委托(delegate)方法:

@implementation MyController
{
    BOOL updatingLinkedSplitview;
}

- (CGFloat)splitView:(NSSplitView *)splitView constrainSplitPosition:(CGFloat)proposedPosition ofSubviewAt:(NSInteger)dividerIndex
{
    // If already updating a split view, return early to avoid infinite loop and stack overflow
    if (updatingLinkedSplitview) return proposedPosition;

    if (splitView == self.mainSplitView)
    {
        // Main splitview is being resized, so manually resize the title bar split view
        updatingLinkedSplitview = YES;
        [self.titleBarSplitView setPosition:proposedPosition ofDividerAtIndex:dividerIndex];
        updatingLinkedSplitview = NO;
    }
    else if (splitView == self.titleBarSplitView)
    {
        // Title bar splitview is being resized, so manually resize the main split view
        updatingLinkedSplitview = YES;
        [self.mainSplitView setPosition:proposedPosition ofDividerAtIndex:dividerIndex];
        updatingLinkedSplitview = NO;
    }

    return proposedPosition;
}

- (void)splitView:(NSSplitView *)splitView resizeSubviewsWithOldSize:(NSSize)oldSize
{
    // This is to synchronize the splitter positions when the window is first loaded
    if (splitView == self.titleBarSplitView)
    {
        NSRect leftFrame = NSMakeRect(NSMinX([self.leftTitleBarView frame]),
                                      NSMinY([self.leftTitleBarView frame]),
                                      NSWidth([self.leftMainSplitView frame]),
                                      NSHeight([self.leftTitleBarView frame]));
        NSRect rightFrame = NSMakeRect(NSMaxX(leftFrame) + [splitView dividerThickness],
                                      NSMinY([self.rightTitleBarView frame]),
                                      NSWidth([self.rightMainSplitView frame]),
                                      NSHeight([self.rightTitleBarView frame]));

        [self.leftTitleBarView setFrame:leftFrame];
        [self.rightTitleBarView setFrame:rightFrame];
    }
}

关于objective-c - INAppStoreWindow 标题栏上的 NSSplitView 分隔符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15092738/

相关文章:

objective-c - 使用异步 NSURLConnection 获取本地文件是否过度?

ios - 我在哪里可以获得向上/向下箭头的 iOS 工具栏图标?

macos - 有没有人设置tomcat来使用mod_jk运行虚拟主机

objective-c - 创建垂直选项卡式 OS X Cocoa View

Objective-C:使用 NSString 变量将消息发送到各种对象之一

iphone - 是否可以在静态库中使用 StoreKit(应用内购买)?

ios - 找不到文件 - GoogleUtilities/Libraries/libGTM_NSData+zlib.a

iphone - 什么时候释放 NSThread 是安全的?

objective-c - SecCertificateAddToKeychain - 导入中的格式未知

c - 假设 pid_t 始终是 int 类型(如标准中所定义)是否安全?