2013-02-26 16 views
7

Sto provando a creare un'interfaccia utente Reeder/Sparrow per gestire il contenuto della mia app. Attualmente utilizzo un NSSplitView con due NSViews all'interno (quello a sinistra è l'elenco dei contenuti e l'altro a destra è "inspector").Divisore NSSplitView su barra titolo INAppStoreWindow

Quello che mi piacerebbe sapere è come creare il divisore sulla barra del titolo che funge anche da divisore della vista divisa. Sto già utilizzando la sottoclasse INAppStoreWindow.

Qualche idea? Grazie in anticipo

+0

Si prega di inviare uno screenshot dell'effetto che si sta tentando di raggiungere. – trojanfoe

risposta

8

Il modo in cui ho fatto questo è quello di aggiungere una sottoclasse NSSplitView come una visualizzazione secondaria di tileBarView del INAppStoreWindow:

// 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]; 

Le due parti difficili sono sempre questa doppia visualizzazione a comportarsi come una barra del titolo (cioè per consentire comunque di trascinare la finestra in giro) e sincronizzare la vista divisa nella barra del titolo con la vista divisa principale nella finestra, in modo che sembrino la stessa cosa per l'utente.

Per risolvere il primo, devi fare molto di più che restituire SÌ da -mouseDownCanMovewWindow nella sottoclasse NSSplitView della barra del titolo. Se lo fai, nessuna delle sottoview della barra dei riquadri risponderà agli eventi del mouse. Invece, fare questo:

@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 

Il secondo ordine di attività è sincronizzare le due viste divise. Crea la classe del tuo controller (probabilmente il controller della finestra, ma qualsiasi cosa abbia senso nel tuo codice) il delegato sia della tua vista divisa per i contenuti principali che della vista divisa della barra del titolo. Quindi, implementare i due metodi delegati NSSplitView di seguito:

@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]; 
    } 
} 
+0

Grazie! Era proprio quello che stavo cercando! – psicosis

+0

@Andrew, fantastico! Hai reso la mia giornata :) Grazie mille. – siekfried