Tabs above document file browser header in tab bar

Integrate visually file manager header in tab bar when tabs above document
option in on. If tabs above document are off then use default gradient L&F.

Bottom divider for file browser header view is not integrated in header for
easier control if it is shown or not.
This commit is contained in:
Adam Strzelecki
2014-09-28 23:18:32 +02:00
committed by Allan Odgaard
parent 1c3b5c170a
commit b137014777
8 changed files with 107 additions and 52 deletions

View File

@@ -1772,6 +1772,8 @@ namespace
if(self.projectPath && !_fileBrowserHistory)
self.fileBrowser.url = [NSURL fileURLWithPath:self.projectPath];
[self updateFileBrowserStatus:self];
if(self.layoutView.tabsAboveDocument)
[self.tabBarView expand];
}
if(!makeVisibleFlag && [[self.window firstResponder] isKindOfClass:[NSView class]] && [(NSView*)[self.window firstResponder] isDescendantOf:self.layoutView.fileBrowserView])

View File

@@ -10,4 +10,5 @@
@property (nonatomic) NSSize htmlOutputSize;
@property (nonatomic) BOOL htmlOutputOnRight;
@property (nonatomic) BOOL tabsAboveDocument;
@end

View File

@@ -11,11 +11,9 @@ NSString* const kUserDefaultsHTMLOutputSizeKey = @"htmlOutputSize";
@interface ProjectLayoutView ()
@property (nonatomic) NSView* fileBrowserDivider;
@property (nonatomic) NSView* htmlOutputDivider;
@property (nonatomic) NSView* fileBrowserTopDivider;
@property (nonatomic) NSLayoutConstraint* fileBrowserWidthConstraint;
@property (nonatomic) NSLayoutConstraint* htmlOutputSizeConstraint;
@property (nonatomic) NSMutableArray* myConstraints;
@property (nonatomic) BOOL tabsAboveDocument;
@property (nonatomic) BOOL mouseDownRecursionGuard;
@end
@@ -109,7 +107,6 @@ NSString* const kUserDefaultsHTMLOutputSizeKey = @"htmlOutputSize";
if(_tabsAboveDocument != flag)
{
_tabsAboveDocument = flag;
_fileBrowserTopDivider = [self replaceView:_fileBrowserTopDivider withView:flag ? OakCreateHorizontalLine([NSColor colorWithString:@"#3F3F3F"], [NSColor colorWithString:@"#878787"]) : nil];
[self setNeedsUpdateConstraints:YES];
}
}
@@ -129,7 +126,6 @@ NSString* const kUserDefaultsHTMLOutputSizeKey = @"htmlOutputSize";
@"documentView" : _documentView,
@"fileBrowserView" : _fileBrowserView ?: [NSNull null],
@"fileBrowserDivider" : _fileBrowserDivider ?: [NSNull null],
@"fileBrowserTopDivider" : _fileBrowserTopDivider ?: [NSNull null],
@"htmlOutputView" : _htmlOutputView ?: [NSNull null],
@"htmlOutputDivider" : _htmlOutputDivider ?: [NSNull null],
};
@@ -143,9 +139,9 @@ NSString* const kUserDefaultsHTMLOutputSizeKey = @"htmlOutputSize";
// left + right
if(_tabsAboveDocument && _fileBrowserView && _fileBrowserOnRight)
CONSTRAINT(@"H:|[tabBarView][fileBrowserDivider]", 0);
CONSTRAINT(@"H:|[tabBarView]-(-1)-[fileBrowserDivider]", 0);
else if(_tabsAboveDocument && _fileBrowserView)
CONSTRAINT(@"H:[fileBrowserDivider][tabBarView]|", 0);
CONSTRAINT(@"H:[fileBrowserDivider]-(-1)-[tabBarView]|", 0);
else
CONSTRAINT(@"H:|[tabBarView]|", 0);
@@ -188,44 +184,11 @@ NSString* const kUserDefaultsHTMLOutputSizeKey = @"htmlOutputSize";
[_myConstraints addObject:self.fileBrowserWidthConstraint];
// top
CONSTRAINT(@"V:|[tabBarView][fileBrowserDivider]", 0);
if(_tabsAboveDocument)
{
CONSTRAINT(@"V:|[fileBrowserTopDivider][fileBrowserView]", 0);
CONSTRAINT(@"V:|[fileBrowserTopDivider][fileBrowserDivider]", 0);
// left
if(_fileBrowserOnRight && _htmlOutputView && _htmlOutputOnRight)
{
CONSTRAINT(@"H:[htmlOutputView][fileBrowserTopDivider]", 0);
}
else if(_fileBrowserOnRight)
{
CONSTRAINT(@"H:[documentView][fileBrowserTopDivider]", 0);
}
else
{
CONSTRAINT(@"H:|[fileBrowserTopDivider]", 0);
}
// right
if(_fileBrowserOnRight)
{
CONSTRAINT(@"H:[fileBrowserTopDivider]|", 0);
}
else
{
CONSTRAINT(@"H:[fileBrowserTopDivider][documentView]", 0);
}
// Setup file browsers header to match height of tab bar view
if(_fileBrowserHeaderView)
[_myConstraints addObject:[NSLayoutConstraint constraintWithItem:_fileBrowserHeaderView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_tabBarView attribute:NSLayoutAttributeHeight multiplier:1 constant:-2]];
}
CONSTRAINT(@"V:|[fileBrowserView]", 0);
else
{
CONSTRAINT(@"V:|[tabBarView][fileBrowserView]", 0);
CONSTRAINT(@"V:|[tabBarView][fileBrowserDivider]", 0);
}
// bottom
if(_htmlOutputView && !_htmlOutputOnRight)

View File

@@ -18,6 +18,7 @@ PUBLIC @interface OakTabBarView : OakBackgroundFillView
@property (nonatomic, weak) id <OakTabBarViewDelegate> delegate;
@property (nonatomic, weak) id <OakTabBarViewDataSource> dataSource;
@property (nonatomic, readonly) NSUInteger countOfVisibleTabs;
- (void)expand;
- (void)reloadData;
- (void)setSelectedTab:(NSUInteger)anIndex;

View File

@@ -161,6 +161,11 @@ static NSString* const OakTabItemPasteboardType = @"OakTabItemPasteboardType";
self.expanded = _expanded || [[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsDisableTabBarCollapsingKey];
}
- (void)expand
{
self.expanded = YES;
}
- (void)setExpanded:(BOOL)flag
{
if(_expanded == flag)

View File

@@ -3,7 +3,7 @@
@class OakRolloverButton;
@interface OakTabBarStyle : NSObject
PUBLIC @interface OakTabBarStyle : NSObject
+ (instancetype)sharedInstance;
@property (nonatomic) CGFloat tabViewSpacing;

View File

@@ -252,7 +252,6 @@ static NSMutableSet* SymmetricDifference (NSMutableSet* aSet, NSMutableSet* anot
NSDictionary* views = @{
@"header" : _headerView,
@"headerDivider" : OakCreateHorizontalLine([NSColor colorWithCalibratedWhite:0.500 alpha:1], [NSColor colorWithCalibratedWhite:0.750 alpha:1]),
@"browser" : scrollView,
@"actionsDivider" : OakCreateHorizontalLine([NSColor colorWithCalibratedWhite:0.500 alpha:1], [NSColor colorWithCalibratedWhite:0.750 alpha:1]),
@"actions" : _actionsView,
@@ -264,8 +263,8 @@ static NSMutableSet* SymmetricDifference (NSMutableSet* aSet, NSMutableSet* anot
[_view addSubview:view];
}
[_view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[browser(==header,==headerDivider,==actionsDivider,==actions)]|" options:0 metrics:nil views:views]];
[_view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[header][headerDivider][browser][actionsDivider][actions]|" options:NSLayoutFormatAlignAllLeft metrics:nil views:views]];
[_view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[browser(==header,==actionsDivider,==actions)]|" options:0 metrics:nil views:views]];
[_view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[header][browser][actionsDivider][actions]|" options:NSLayoutFormatAlignAllLeft metrics:nil views:views]];
}
- (void)setupViewWithState:(NSDictionary*)fileBrowserState

View File

@@ -1,5 +1,6 @@
#import "OFBHeaderView.h"
#import <OakAppKit/OakAppKit.h>
#import <OakAppKit/OakTabItemView.h>
#import <OakAppKit/OakUIConstructionFunctions.h>
#import <Preferences/Keys.h>
@@ -19,10 +20,18 @@ static NSButton* OakCreateImageButton (NSString* imageName)
return res;
}
@interface OFBHeaderViewPopupButtonCell : NSPopUpButtonCell
@property (nonatomic) NSDictionary* activeAttributes;
@property (nonatomic) NSDictionary* inactiveAttributes;
@end
static NSPopUpButton* OakCreateFolderPopUpButton ()
{
NSPopUpButton* res = [[NSPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:YES];
[[res cell] setBackgroundStyle:NSBackgroundStyleLight];
OFBHeaderViewPopupButtonCell* cell = [[OFBHeaderViewPopupButtonCell alloc] initTextCell:@"" pullsDown:YES];
[res setCell:cell];
[cell setBezelStyle:NSRecessedBezelStyle];
[cell setArrowPosition:NSPopUpArrowAtBottom];
[res setContentCompressionResistancePriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationHorizontal];
[res setContentHuggingPriority:NSLayoutPriorityFittingSizeCompression forOrientation:NSLayoutConstraintOrientationHorizontal];
[res setContentHuggingPriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationVertical];
@@ -31,7 +40,53 @@ static NSPopUpButton* OakCreateFolderPopUpButton ()
}
@interface OFBHeaderView ()
@property (nonatomic) BOOL matchTabBarHeight;
@property (nonatomic) BOOL inTabBar;
@property (nonatomic) NSView* bottomDivider;
@end
@implementation OFBHeaderViewPopupButtonCell
- (id)initTextCell:(NSString*)title pullsDown:(BOOL)pullsDown
{
if(self = [super initTextCell:title pullsDown:pullsDown])
{
NSShadow* shadow = [NSShadow new];
[shadow setShadowColor:[NSColor colorWithCalibratedWhite:1 alpha:0.5]];
[shadow setShadowOffset:NSMakeSize(0, -1)];
[shadow setShadowBlurRadius:1];
NSMutableParagraphStyle* parStyle = [NSMutableParagraphStyle new];
[parStyle setLineBreakMode:NSLineBreakByTruncatingMiddle];
NSFont* font = [NSFont boldSystemFontOfSize:12];
_activeAttributes = @{
NSParagraphStyleAttributeName : parStyle,
NSFontAttributeName : font,
NSForegroundColorAttributeName : [NSColor colorWithCalibratedWhite:0.2 alpha:1],
NSShadowAttributeName : shadow,
};
_inactiveAttributes = @{
NSParagraphStyleAttributeName : parStyle,
NSFontAttributeName : font,
NSForegroundColorAttributeName : [NSColor colorWithCalibratedWhite:0.5 alpha:1],
NSShadowAttributeName : shadow,
};
}
return self;
}
- (NSRect)drawTitle:(NSAttributedString*)title withFrame:(NSRect)frame inView:(NSView*)controlView
{
OFBHeaderView* headerView = (OFBHeaderView*)controlView.superview;
if(headerView.inTabBar)
{
NSDictionary* attrs = headerView.active ? _activeAttributes : _inactiveAttributes;
frame.origin.y += 1;
frame.size.height -= 1;
return [super drawTitle:[[NSAttributedString alloc] initWithString:title.string attributes:attrs] withFrame:frame inView:controlView];
}
return [super drawTitle:title withFrame:frame inView:controlView];
}
@end
@implementation OFBHeaderView
@@ -51,11 +106,14 @@ static NSPopUpButton* OakCreateFolderPopUpButton ()
[self.goBackButton.cell accessibilitySetOverrideValue:self.goBackButton.toolTip forAttribute:NSAccessibilityDescriptionAttribute];
[self.goForwardButton.cell accessibilitySetOverrideValue:self.goForwardButton.toolTip forAttribute:NSAccessibilityDescriptionAttribute];
_bottomDivider = OakCreateHorizontalLine([NSColor colorWithCalibratedWhite:0.500 alpha:1], [NSColor colorWithCalibratedWhite:0.750 alpha:1]);
NSDictionary* views = @{
@"folder" : self.folderPopUpButton,
@"divider" : OakCreateDividerImageView(),
@"back" : self.goBackButton,
@"forward" : self.goForwardButton,
@"folder" : self.folderPopUpButton,
@"divider" : OakCreateDividerImageView(),
@"back" : self.goBackButton,
@"forward" : self.goForwardButton,
@"bottomDivider" : _bottomDivider,
};
for(NSView* view in [views allValues])
@@ -65,11 +123,37 @@ static NSPopUpButton* OakCreateFolderPopUpButton ()
}
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(-3)-[folder(>=75)]-(3)-[divider]-(2)-[back(==22)]-(2)-[forward(==back)]-(3)-|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[folder(==divider,==back,==forward)]|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[bottomDivider]|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[folder(==divider,==back,==forward)][bottomDivider]|" options:0 metrics:nil views:views]];
[self userDefaultsDidChange:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) name:NSUserDefaultsDidChangeNotification object:[NSUserDefaults standardUserDefaults]];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)userDefaultsDidChange:(NSNotification*)aNotification
{
self.inTabBar = [[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsTabsAboveDocumentKey];
}
- (void)setInTabBar:(BOOL)flag
{
if(_inTabBar != flag)
{
_inTabBar = flag;
_bottomDivider.hidden = flag;
if(flag)
[[OakTabBarStyle sharedInstance] setupTabBarView:self];
else [self setupHeaderBackground];
}
}
- (NSSize)intrinsicContentSize
{
return NSMakeSize(NSViewNoInstrinsicMetric, 24);