Revision: 25848
          http://sourceforge.net/p/bibdesk/svn/25848
Author:   hofman
Date:     2021-05-03 17:10:00 +0000 (Mon, 03 May 2021)
Log Message:
-----------
Move preference icon view code to preference controller, it is built up from 
standard views

Modified Paths:
--------------
    trunk/bibdesk/BDSKPreferenceController.h
    trunk/bibdesk/BDSKPreferenceController.m

Modified: trunk/bibdesk/BDSKPreferenceController.h
===================================================================
--- trunk/bibdesk/BDSKPreferenceController.h    2021-05-03 16:44:38 UTC (rev 
25847)
+++ trunk/bibdesk/BDSKPreferenceController.h    2021-05-03 17:10:00 UTC (rev 
25848)
@@ -39,7 +39,6 @@
 #import <Cocoa/Cocoa.h>
 #import "NSTouchBar_BDSKForwardDeclarations.h"
 
-@class BDSKPreferenceIconView;
 
 @interface BDSKPreferenceController : NSWindowController <NSToolbarDelegate, 
NSWindowDelegate, NSTouchBarDelegate> {
     NSView *controlView;
@@ -52,7 +51,8 @@
     NSTextField *titleField;
     NSButton *tbRevertButton;
     NSButton *tbRevertAllButton;
-    BDSKPreferenceIconView *iconView;
+    NSView *iconView;
+    CALayer *spotlightLayer;
     NSMutableArray *categories;
     NSMutableDictionary *categoryDicts;
     NSMutableDictionary *records;
@@ -61,6 +61,7 @@
     NSMutableDictionary *toolbarItems;
     NSString *helpBookName;
     NSMutableDictionary *identifierSearchTerms;
+    NSMutableDictionary *iconButtons;
 }
 
 + (id)sharedPreferenceController;

Modified: trunk/bibdesk/BDSKPreferenceController.m
===================================================================
--- trunk/bibdesk/BDSKPreferenceController.m    2021-05-03 16:44:38 UTC (rev 
25847)
+++ trunk/bibdesk/BDSKPreferenceController.m    2021-05-03 17:10:00 UTC (rev 
25848)
@@ -39,9 +39,11 @@
 #import "BDSKPreferenceController.h"
 #import "BDSKPreferenceRecord.h"
 #import "BDSKPreferencePane.h"
-#import "BDSKPreferenceIconView.h"
+#import "BDSKColoredView.h"
 #import <Sparkle/Sparkle.h>
 #import "NSAnimationContext_BDSKExtensions.h"
+#import "NSColor_BDSKExtensions.h"
+#import <Quartz/Quartz.h>
 
 #define BDSKPreferencesWindowFrameAutosaveName @"BDSKPreferencesWindow"
 
@@ -67,6 +69,30 @@
 }
 #endif
 
+#define MINIMUM_ICON_WIDTH 0.0
+#define MINIMUM_ICON_HEIGHT 0.0
+#define MAXIMUM_ICON_WIDTH 100.0
+#define MAXIMUM_ICON_HEIGHT 200.0
+#define TOP_MARGIN 1.0
+#define BOTTOM_MARGIN 0.0
+#define TOP_CAPTION_MARGIN 4.0
+#define SIDE_CAPTION_MARGIN 12.0
+#define SIDE_ICON_MARGIN 16.0
+#define COLLAPSE_SIDE_ICON_MARGIN YES
+#define ICON_SPACING 2.0
+#define COLLAPSE_ICON_SPACING YES
+#define TOP_ICON_MARGIN 8.0
+#define BOTTOM_ICON_MARGIN 12.0
+#define DIVIDER_HEIGHT 1.0
+#define MASK_ALPHA 0.3
+#define MAXIMUM_BLUR 10
+
+#if SDK_BEFORE(10_14)
+@interface NSColor (BDSKMojaveDeclarations)
++ (NSColor *)separatorColor;
+@end
+#endif
+
 @interface BDSKPreferenceController (BDSKPrivate)
 + (void)makeImages;
 - (void)iconViewShowPane:(id)sender;
@@ -74,9 +100,9 @@
 - (void)setupToolbar;
 - (void)loadPreferences;
 - (void)loadPanes;
-- (BDSKPreferenceIconView *)iconView;
+- (NSView *)iconView;
+- (void)showSpotlightsForIdentifiers:(NSArray *)identifiers;
 - (void)changeContentView:(NSView *)view from:(NSView *)oldView 
display:(BOOL)display;
-- (NSArray *)identifiersForSearchTerm:(NSString *)searchTerm;
 @end
 
 
@@ -151,10 +177,6 @@
     
     [[window contentView] setWantsLayer:YES];
     
-    iconView = [[BDSKPreferenceIconView alloc] 
initWithPreferenceController:self];
-    [iconView setAction:@selector(iconViewShowPane:)];
-    [iconView setTarget:self];
-    
     CGFloat width = [iconView fittingSize].width;
     for (BDSKPreferencePane *pane in [panes objectEnumerator])
         width = fmax(width, [[pane view] fittingSize].width);
@@ -162,7 +184,7 @@
     frame.size.width = width;
     [window setFrame:frame display:NO];
     
-    [self changeContentView:iconView from:nil display:NO];
+    [self changeContentView:[self iconView] from:nil display:NO];
     
     [self setSelectedPaneIdentifier:@""];
     
@@ -255,7 +277,7 @@
 }
 
 - (void)iconViewShowPane:(id)sender {
-    [self selectPaneWithIdentifier:[sender clickedIdentifier]];
+    [self selectPaneWithIdentifier:[[sender cell] representedObject]];
 }
 
 - (IBAction)showNextPreviousPane:(id)sender {
@@ -280,11 +302,16 @@
 - (IBAction)search:(id)sender {
     NSString *searchTerm = [searchField stringValue];
     if ([searchTerm length] > 0) {
-        [iconView showSpotlightsForIdentifiers:[self 
identifiersForSearchTerm:searchTerm]];
+        NSMutableArray *identifiers = [NSMutableArray array];
+        [identifierSearchTerms enumerateKeysAndObjectsUsingBlock:^(NSString 
*identifier, NSString *string, BOOL *stop){
+            if ([string rangeOfString:searchTerm 
options:NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch].location != 
NSNotFound)
+                [identifiers addObject:identifier];
+        }];
+        [self showSpotlightsForIdentifiers:identifiers];
         if ([[self selectedPaneIdentifier] isEqualToString:@""] == NO)
             [self selectPaneWithIdentifier:@""];
     } else {
-        [iconView showSpotlightsForIdentifiers:nil];
+        [self showSpotlightsForIdentifiers:nil];
     }
 }
 
@@ -473,6 +500,57 @@
        return identifiers;
 }
 
+#pragma mark Touch Bar
+
+- (NSTouchBar *)makeTouchBar {
+    NSTouchBar *touchBar = [[[NSClassFromString(@"NSTouchBar") alloc] init] 
autorelease];
+    [touchBar setDelegate:self];
+    [touchBar setDefaultItemIdentifiers:[NSArray 
arrayWithObjects:BDSKTouchBarItemIdentifierPreviousNext, 
BDSKTouchBarItemIdentifierShowAll, @"NSTouchBarItemIdentifierFixedSpaceSmall", 
BDSKTouchBarItemIdentifierReset, BDSKTouchBarItemIdentifierResetAll, nil]];
+    return touchBar;
+}
+
+- (NSTouchBarItem *)touchBar:(NSTouchBar *)aTouchBar 
makeItemForIdentifier:(NSString *)identifier {
+    NSTouchBarItem *item = nil;
+    if ([identifier isEqualToString:BDSKTouchBarItemIdentifierPreviousNext]) {
+        NSArray *images = [NSArray arrayWithObjects:[NSImage 
imageNamed:NSImageNameTouchBarGoBackTemplate], [NSImage 
imageNamed:NSImageNameTouchBarGoForwardTemplate], nil];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+        NSSegmentedControl *button = [NSSegmentedControl 
segmentedControlWithImages:images trackingMode:NSSegmentSwitchTrackingMomentary 
target:self action:@selector(showNextPreviousPane:)];
+        if (RUNNING_AFTER(10_9))
+            [button setSegmentStyle:NSSegmentStyleSeparated];
+#pragma clang diagnostic pop
+        item = [[[NSClassFromString(@"NSCustomTouchBarItem") alloc] 
initWithIdentifier:identifier] autorelease];
+        [(NSCustomTouchBarItem *)item setView:button];
+    } else if ([identifier isEqualToString:BDSKTouchBarItemIdentifierShowAll]) 
{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+        NSButton *button = [NSButton buttonWithImage:[NSImage 
imageNamed:@"NSTouchBarIconViewTemplate"] target:self 
action:@selector(showAll:)];
+#pragma clang diagnostic pop
+        item = [[[NSClassFromString(@"NSCustomTouchBarItem") alloc] 
initWithIdentifier:identifier] autorelease];
+        [(NSCustomTouchBarItem *)item setView:button];
+    } else if ([identifier isEqualToString:BDSKTouchBarItemIdentifierReset]) {
+        if (tbRevertButton == nil) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+            tbRevertButton = [[NSButton 
buttonWithTitle:NSLocalizedString(@"Reset", @"Button title") target:self 
action:@selector(revertPaneDefaults:)] retain];
+#pragma clang diagnostic pop
+            [tbRevertButton setEnabled:[[[self selectedPane] initialValues] 
count] > 0];
+        }
+        item = [[[NSClassFromString(@"NSCustomTouchBarItem") alloc] 
initWithIdentifier:identifier] autorelease];
+        [(NSCustomTouchBarItem *)item setView:tbRevertButton];
+    } else if ([identifier 
isEqualToString:BDSKTouchBarItemIdentifierResetAll]) {
+        if (tbRevertAllButton == nil) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+            tbRevertAllButton = [[NSButton 
buttonWithTitle:NSLocalizedString(@"Reset All", @"Button title") target:self 
action:@selector(revertAllDefaults:)] retain];
+#pragma clang diagnostic pop
+        }
+        item = [[[NSClassFromString(@"NSCustomTouchBarItem") alloc] 
initWithIdentifier:identifier] autorelease];
+        [(NSCustomTouchBarItem *)item setView:tbRevertAllButton];
+    }
+    return item;
+}
+
 #pragma mark Private
 
 // we redraw the images for Files and Templates using the doc icon for the 
user system
@@ -569,12 +647,6 @@
     }
 }
 
-- (BDSKPreferenceIconView *)iconView {
-    if (iconView == nil)
-        [self window];
-    return iconView;
-}
-
 - (void)changeContentView:(NSView *)view from:(NSView *)oldView 
display:(BOOL)display {
     NSWindow *window = [self window];
     NSView *contentView = [window contentView];
@@ -650,64 +722,189 @@
     }
 }
 
-#pragma mark Touch Bar
+#pragma mark Icon View
 
-- (NSArray *)identifiersForSearchTerm:(NSString *)searchTerm {
-    NSMutableArray *identifiers = [NSMutableArray array];
-    [identifierSearchTerms enumerateKeysAndObjectsUsingBlock:^(NSString 
*identifier, NSString *string, BOOL *stop){
-        if ([string rangeOfString:searchTerm options:NSCaseInsensitiveSearch | 
NSDiacriticInsensitiveSearch].location != NSNotFound)
-            [identifiers addObject:identifier];
-    }];
-    return identifiers;
-}
+// @@ Dark Mode
 
-- (NSTouchBar *)makeTouchBar {
-    NSTouchBar *touchBar = [[[NSClassFromString(@"NSTouchBar") alloc] init] 
autorelease];
-    [touchBar setDelegate:self];
-    [touchBar setDefaultItemIdentifiers:[NSArray 
arrayWithObjects:BDSKTouchBarItemIdentifierPreviousNext, 
BDSKTouchBarItemIdentifierShowAll, @"NSTouchBarItemIdentifierFixedSpaceSmall", 
BDSKTouchBarItemIdentifierReset, BDSKTouchBarItemIdentifierResetAll, nil]];
-    return touchBar;
-}
-
-- (NSTouchBarItem *)touchBar:(NSTouchBar *)aTouchBar 
makeItemForIdentifier:(NSString *)identifier {
-    NSTouchBarItem *item = nil;
-    if ([identifier isEqualToString:BDSKTouchBarItemIdentifierPreviousNext]) {
-        NSArray *images = [NSArray arrayWithObjects:[NSImage 
imageNamed:NSImageNameTouchBarGoBackTemplate], [NSImage 
imageNamed:NSImageNameTouchBarGoForwardTemplate], nil];
+- (void)setupIconView {
+    iconButtons = [[NSMutableDictionary alloc] init];
+    
+    iconView = [[NSView alloc] init];
+    
+    NSButton *firstButton = nil;
+    BDSKColoredView *prevBgView = nil;
+    NSMutableArray *constraints = [NSMutableArray array];
+    NSColor *backgroundColor = [NSColor colorWithCalibratedAquaWhite:0.0 
alpha:0.03 darkAquaWhite:1.0 alpha:0.03];
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wpartial-availability"
-        NSSegmentedControl *button = [NSSegmentedControl 
segmentedControlWithImages:images trackingMode:NSSegmentSwitchTrackingMomentary 
target:self action:@selector(showNextPreviousPane:)];
-        if (RUNNING_AFTER(10_9))
-            [button setSegmentStyle:NSSegmentStyleSeparated];
+    NSColor *dividerColor = [NSColor 
respondsToSelector:@selector(separatorColor)] ? [NSColor separatorColor] : 
[[NSColor controlTextColor] colorWithAlphaComponent:0.1];
 #pragma clang diagnostic pop
-        item = [[[NSClassFromString(@"NSCustomTouchBarItem") alloc] 
initWithIdentifier:identifier] autorelease];
-        [(NSCustomTouchBarItem *)item setView:button];
-    } else if ([identifier isEqualToString:BDSKTouchBarItemIdentifierShowAll]) 
{
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpartial-availability"
-        NSButton *button = [NSButton buttonWithImage:[NSImage 
imageNamed:@"NSTouchBarIconViewTemplate"] target:self 
action:@selector(showAll:)];
-#pragma clang diagnostic pop
-        item = [[[NSClassFromString(@"NSCustomTouchBarItem") alloc] 
initWithIdentifier:identifier] autorelease];
-        [(NSCustomTouchBarItem *)item setView:button];
-    } else if ([identifier isEqualToString:BDSKTouchBarItemIdentifierReset]) {
-        if (tbRevertButton == nil) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpartial-availability"
-            tbRevertButton = [[NSButton 
buttonWithTitle:NSLocalizedString(@"Reset", @"Button title") target:self 
action:@selector(revertPaneDefaults:)] retain];
-#pragma clang diagnostic pop
-            [tbRevertButton setEnabled:[[[self selectedPane] initialValues] 
count] > 0];
+    BOOL drawsBackground = NO;
+    
+    for (NSString *category in [self categories]) {
+        BDSKColoredView *bgView = [[[BDSKColoredView alloc] init] autorelease];
+        if (drawsBackground)
+            [bgView setBackgroundColor:backgroundColor];
+        drawsBackground = NO == drawsBackground;
+        [bgView setTranslatesAutoresizingMaskIntoConstraints:NO];
+        [iconView addSubview:bgView];
+        
+        NSMutableArray *constraints2 = [NSMutableArray array];
+        
+        [constraints addObject:[NSLayoutConstraint constraintWithItem:bgView 
attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual 
toItem:iconView attribute:NSLayoutAttributeLeading multiplier:1.0 
constant:0.0]];
+        [constraints addObject:[NSLayoutConstraint constraintWithItem:iconView 
attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual 
toItem:bgView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0]];
+        
+        if (prevBgView) {
+            BDSKColoredView *dividerView = nil;
+            dividerView = [[[BDSKColoredView alloc] init] autorelease];
+            [dividerView setBackgroundColor:dividerColor];
+            [dividerView addConstraint:[NSLayoutConstraint 
constraintWithItem:dividerView attribute:NSLayoutAttributeHeight 
relatedBy:NSLayoutRelationEqual toItem:nil 
attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 
constant:DIVIDER_HEIGHT]];
+            [dividerView setTranslatesAutoresizingMaskIntoConstraints:NO];
+            [iconView addSubview:dividerView];
+            
+            [constraints addObject:[NSLayoutConstraint 
constraintWithItem:dividerView attribute:NSLayoutAttributeLeading 
relatedBy:NSLayoutRelationEqual toItem:iconView 
attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0]];
+            [constraints addObject:[NSLayoutConstraint 
constraintWithItem:iconView attribute:NSLayoutAttributeTrailing 
relatedBy:NSLayoutRelationEqual toItem:dividerView 
attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0]];
+            [constraints addObject:[NSLayoutConstraint 
constraintWithItem:dividerView attribute:NSLayoutAttributeTop 
relatedBy:NSLayoutRelationEqual toItem:prevBgView 
attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
+            [constraints addObject:[NSLayoutConstraint 
constraintWithItem:bgView attribute:NSLayoutAttributeTop 
relatedBy:NSLayoutRelationEqual toItem:dividerView 
attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
+        } else {
+            [constraints addObject:[NSLayoutConstraint 
constraintWithItem:bgView attribute:NSLayoutAttributeTop 
relatedBy:NSLayoutRelationEqual toItem:iconView attribute:NSLayoutAttributeTop 
multiplier:1.0 constant:TOP_MARGIN]];
         }
-        item = [[[NSClassFromString(@"NSCustomTouchBarItem") alloc] 
initWithIdentifier:identifier] autorelease];
-        [(NSCustomTouchBarItem *)item setView:tbRevertButton];
-    } else if ([identifier 
isEqualToString:BDSKTouchBarItemIdentifierResetAll]) {
-        if (tbRevertAllButton == nil) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpartial-availability"
-            tbRevertAllButton = [[NSButton 
buttonWithTitle:NSLocalizedString(@"Reset All", @"Button title") target:self 
action:@selector(revertAllDefaults:)] retain];
-#pragma clang diagnostic pop
+        
+        NSTextField *captionField = [[[NSTextField alloc] init] autorelease];
+        [captionField setBordered:NO];
+        [captionField setEditable:NO];
+        [captionField setDrawsBackground:NO];
+        [captionField setFont:[NSFont boldSystemFontOfSize:0.0]];
+        [captionField setStringValue:[self localizedTitleForCategory:category] 
?: @""];
+        [captionField setTranslatesAutoresizingMaskIntoConstraints:NO];
+        [bgView addSubview:captionField];
+        
+        [constraints2 addObject:[NSLayoutConstraint 
constraintWithItem:captionField attribute:NSLayoutAttributeLeading 
relatedBy:NSLayoutRelationEqual toItem:bgView 
attribute:NSLayoutAttributeLeading multiplier:1.0 
constant:SIDE_CAPTION_MARGIN]];
+        [constraints2 addObject:[NSLayoutConstraint constraintWithItem:bgView 
attribute:NSLayoutAttributeTrailing 
relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:captionField 
attribute:NSLayoutAttributeTrailing multiplier:1.0 
constant:SIDE_CAPTION_MARGIN]];
+        [constraints2 addObject:[NSLayoutConstraint 
constraintWithItem:captionField attribute:NSLayoutAttributeTop 
relatedBy:NSLayoutRelationEqual toItem:bgView attribute:NSLayoutAttributeTop 
multiplier:1.0 constant:TOP_CAPTION_MARGIN]];
+        
+        NSButton *prevButton = nil;
+        for (NSString *identifier in [self panesForCategory:category]) {
+            
+            NSButton *button = [[NSButton alloc] init];
+            [button setImage:[self iconForIdentifier:identifier]];
+            [button setTitle:[self localizedLabelForIdentifier:identifier]];
+            [button setToolTip:[self 
localizedToolTipForIdentifier:identifier]];
+            [button setFont:[NSFont labelFontOfSize:12.0]];
+            [button setImagePosition:NSImageAbove];
+            [button setBordered:NO];
+            [button setButtonType:NSMomentaryChangeButton];
+            [button setTarget:self];
+            [button setAction:@selector(iconViewShowPane:)];
+            [[button cell] setRepresentedObject:identifier];
+            [iconButtons setObject:button forKey:identifier];
+            [button setTranslatesAutoresizingMaskIntoConstraints:NO];
+            [bgView addSubview:button];
+            [button release];
+            
+            if (firstButton) {
+                NSMutableArray *constraints3 = bgView == [firstButton 
superview] ? constraints2 : constraints;
+                [constraints3 addObject:[NSLayoutConstraint 
constraintWithItem:button attribute:NSLayoutAttributeWidth 
relatedBy:NSLayoutRelationEqual toItem:firstButton 
attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];
+                [constraints3 addObject:[NSLayoutConstraint 
constraintWithItem:button attribute:NSLayoutAttributeHeight 
relatedBy:NSLayoutRelationEqual toItem:firstButton 
attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0]];
+            } else {
+                firstButton = button;
+            }
+            if (prevButton) {
+                [constraints2 addObject:[NSLayoutConstraint 
constraintWithItem:button attribute:NSLayoutAttributeLeading 
relatedBy:NSLayoutRelationEqual toItem:prevButton 
attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:ICON_SPACING]];
+                [constraints2 addObject:[NSLayoutConstraint 
constraintWithItem:prevButton attribute:NSLayoutAttributeTop 
relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeTop 
multiplier:1.0 constant:0.0]];
+            } else {
+                [constraints2 addObject:[NSLayoutConstraint 
constraintWithItem:button attribute:NSLayoutAttributeLeading 
relatedBy:NSLayoutRelationEqual toItem:bgView 
attribute:NSLayoutAttributeLeading multiplier:1.0 constant:SIDE_ICON_MARGIN]];
+                [constraints2 addObject:[NSLayoutConstraint 
constraintWithItem:button attribute:NSLayoutAttributeTop 
relatedBy:NSLayoutRelationEqual toItem:captionField 
attribute:NSLayoutAttributeBottom multiplier:1.0 constant:TOP_ICON_MARGIN]];
+                [constraints2 addObject:[NSLayoutConstraint 
constraintWithItem:bgView attribute:NSLayoutAttributeBottom 
relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeBottom 
multiplier:1.0 constant:BOTTOM_ICON_MARGIN]];
+            }
+            
+            prevButton = button;
         }
-        item = [[[NSClassFromString(@"NSCustomTouchBarItem") alloc] 
initWithIdentifier:identifier] autorelease];
-        [(NSCustomTouchBarItem *)item setView:tbRevertAllButton];
+        
+        [constraints2 addObject:[NSLayoutConstraint constraintWithItem:bgView 
attribute:NSLayoutAttributeTrailing 
relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:prevButton 
attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:SIDE_ICON_MARGIN]];
+        [constraints2 addObject:[NSLayoutConstraint constraintWithItem:bgView 
attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual 
toItem:prevButton attribute:NSLayoutAttributeTrailing multiplier:1.0 
constant:SIDE_ICON_MARGIN]];
+        [[constraints2 lastObject] setPriority:99.0];
+        
+        [bgView addConstraints:constraints2];
+        
+        prevBgView = bgView;
     }
-    return item;
+    [constraints addObject:[NSLayoutConstraint constraintWithItem:iconView 
attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual 
toItem:prevBgView attribute:NSLayoutAttributeBottom multiplier:1.0 
constant:BOTTOM_MARGIN]];
+    [iconView addConstraints:constraints];
+    [iconView setTranslatesAutoresizingMaskIntoConstraints:NO];
 }
 
+- (NSView *)iconView {
+    if (iconView == nil)
+        [self setupIconView];
+    return iconView;
+}
+
+- (CGImageRef)createSpotlightImageForIdentifiers:(NSArray *)identifiers {
+    CGFloat blurPadding = MAXIMUM_BLUR * 2.0;
+    CGFloat scale = [iconView convertSizeToBacking:NSMakeSize(1.0, 1.0)].width;
+    CGAffineTransform t = 
CGAffineTransformTranslate(CGAffineTransformMakeScale(scale, scale), 
blurPadding, blurPadding);
+    CGRect bounds = NSRectToCGRect([iconView bounds]);
+    // we make the bounds larger so the blurred edges will fall outside the 
view
+    CGRect maskRect = CGRectInset(bounds, -blurPadding, -blurPadding);
+    
+    CGColorSpaceRef colorSpace = 
CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+    CGContextRef context = CGBitmapContextCreate(NULL, 
CGRectGetWidth(maskRect) * scale, CGRectGetHeight(maskRect) * scale, 8, 0, 
colorSpace, kCGImageAlphaPremultipliedLast);
+    CGColorSpaceRelease(colorSpace);
+    CGColorRef color = CGColorCreateGenericRGB(0.0, 0.0, 0.0, MASK_ALPHA);
+    CGContextSetFillColorWithColor(context, color);
+    CGColorRelease(color);
+    
+    // we need to scale and shift because canvas of the image is at positive 
values in backing space
+    CGContextConcatCTM(context, t);
+    CGContextAddRect(context, maskRect);
+    for (NSString *identifier in identifiers) {
+        NSButton *button = [iconButtons objectForKey:identifier];
+        NSRect rect = [iconView convertRect:[button bounds] fromView:button];
+        CGFloat diameter = fmax(NSHeight(rect), NSWidth(rect));
+        CGRect circleRect = CGRectMake(NSMidX(rect) - 0.5 * diameter, 
NSMidY(rect) - 0.5 * diameter, diameter, diameter);
+        CGContextAddEllipseInRect(context, circleRect);
+    }
+    CGContextEOFillPath(context);
+    
+    CGImageRef cgImage = CGBitmapContextCreateImage(context);
+    CGContextRelease(context);
+    
+    CIImage *ciImage = [CIImage imageWithCGImage:cgImage];
+    CGImageRelease(cgImage);
+    // apply the blur filter to soften the edges of the circles
+    CIFilter *gaussianBlurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
+    // sys prefs uses fuzzier circles for more matches; filter range 0 -- 100, 
values 0 -- 10 are reasonable?
+    [gaussianBlurFilter setValue:[NSNumber numberWithDouble:MIN([identifiers 
count], MAXIMUM_BLUR) * scale] forKey:kCIInputRadiusKey];
+    // see NSCIImageRep.h for this and other useful methods that aren't 
documented
+    [gaussianBlurFilter setValue:ciImage forKey:kCIInputImageKey];
+    ciImage = [gaussianBlurFilter valueForKey:kCIOutputImageKey];
+    
+    return [[CIContext context] createCGImage:ciImage 
fromRect:CGRectApplyAffineTransform(bounds, t)];
+}
+
+- (void)showSpotlightsForIdentifiers:(NSArray *)identifiers {
+    if (identifiers == nil) {
+        
+        [spotlightLayer setContents:nil];
+        
+    } else {
+        
+        if (spotlightLayer == nil) {
+            spotlightLayer = [[CALayer alloc] init];
+            [spotlightLayer setFrame:[iconView bounds]];
+            [spotlightLayer setAutoresizingMask:kCALayerWidthSizable | 
kCALayerHeightSizable];
+            [spotlightLayer setZPosition:1.0];
+            [iconView setWantsLayer:YES];
+            [iconView displayIfNeeded];
+            [[iconView layer] addSublayer:spotlightLayer];
+        }
+        
+        CGImageRef image = [self 
createSpotlightImageForIdentifiers:identifiers];
+        [spotlightLayer setContents:(id)image];
+        CGImageRelease(image);
+        
+    }
+}
+
 @end

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
Bibdesk-commit mailing list
Bibdesk-commit@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit

Reply via email to