Revision: 28657 http://sourceforge.net/p/bibdesk/svn/28657 Author: hofman Date: 2024-01-23 17:45:32 +0000 (Tue, 23 Jan 2024) Log Message: ----------- Add arrow buttons as subviews. Avoids redrawing the icons.
Modified Paths: -------------- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVArrowButtonCell.h trunk/bibdesk_vendorsrc/amaxwell/FileView/FVArrowButtonCell.m trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.h trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVArrowButtonCell.h =================================================================== --- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVArrowButtonCell.h 2024-01-23 15:28:04 UTC (rev 28656) +++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVArrowButtonCell.h 2024-01-23 17:45:32 UTC (rev 28657) @@ -45,11 +45,21 @@ FVArrowLeft = 1 }; +@interface FVArrowButton : NSButton { +} + +- (id)initWithArrowDirection:(FVArrowDirection)anArrowDirection; + +@property (nonatomic) CGFloat arrowAlpha; + +@end + /** @internal @brief Circular arrow button. FVArrowButtonCell is a circle with an arrow inside, used as a page change button. Modeled after the page change button that Finder shows for PDF files on 10.5 in column mode preview. */ @interface FVArrowButtonCell : NSButtonCell { FVArrowDirection _arrowDirection; + CGFloat _arrowAlpha; } /** Designated initializer. @@ -67,6 +77,8 @@ @param alpha 1.0 for opaque, 0.0 for transparent. */ - (void)drawWithFrame:(NSRect)frame inView:(NSView *)controlView alpha:(CGFloat)alpha; +@property (nonatomic) CGFloat arrowAlpha; + @end /** @typedef NSUInteger FVArrowDirection Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVArrowButtonCell.m =================================================================== --- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVArrowButtonCell.m 2024-01-23 15:28:04 UTC (rev 28656) +++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVArrowButtonCell.m 2024-01-23 17:45:32 UTC (rev 28657) @@ -37,6 +37,7 @@ */ #import "FVArrowButtonCell.h" +#import <QuartzCore/QuartzCore.h> #if !defined(MAC_OS_X_VERSION_10_12) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 #define NSEventMaskLeftMouseUp NSLeftMouseUpMask @@ -44,9 +45,40 @@ #define NSEventTypeLeftMouseDragged NSLeftMouseDragged #endif +@implementation FVArrowButton + +@dynamic arrowAlpha; + ++ (id)defaultAnimationForKey:(NSAnimatablePropertyKey)key { + if ([key isEqualToString:@"arrowAlpha"]) + return [CABasicAnimation animation]; + return [super defaultAnimationForKey:key]; +} + ++ (Class)cellClass { return [FVArrowButtonCell self]; } + +- (id)initWithArrowDirection:(FVArrowDirection)anArrowDirection { + self = [super initWithFrame:NSZeroRect]; + if (self) { + [self setCell:[[FVArrowButtonCell alloc] initWithArrowDirection:anArrowDirection]]; + } + return self; +} + +- (CGFloat)arrowAlpha { + return [(FVArrowButtonCell *)[self cell] arrowAlpha]; +} + +- (void)setArrowAlpha:(CGFloat)arrowAlpha { + [(FVArrowButtonCell *)[self cell] setArrowAlpha:arrowAlpha]; + [self setNeedsDisplay:YES]; +} + +@end + @implementation FVArrowButtonCell -+ (BOOL)prefersTrackingUntilMouseUp { return YES; } +@synthesize arrowAlpha=_arrowAlpha; - (id)initTextCell:(NSString *)aString { return [self initWithArrowDirection:FVArrowRight]; @@ -61,6 +93,7 @@ [self setBordered:NO]; [self setContinuous:YES]; _arrowDirection = anArrowDirection; + _arrowAlpha = 1.0; } return self; } @@ -91,7 +124,7 @@ - (void)drawWithFrame:(NSRect)frame inView:(NSView *)controlView; { - [self drawWithFrame:frame inView:controlView alpha:1.0]; + [self drawWithFrame:frame inView:controlView alpha:_arrowAlpha]; } - (void)drawWithFrame:(NSRect)frame inView:(NSView *)controlView alpha:(CGFloat)alpha; @@ -134,30 +167,4 @@ CGContextRestoreGState(ctxt); } -- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp { - NSPoint mouseLoc = [controlView convertPoint:[theEvent locationInWindow] fromView:nil]; - BOOL isInside = NSMouseInRect(mouseLoc, cellFrame, [controlView isFlipped]); - if (isInside) { - BOOL keepOn = YES; - while (keepOn) { - if (isInside) { - // NSButtonCell does not highlight itself, it tracks until a click or the mouse exits - [self highlight:YES withFrame:cellFrame inView:controlView]; - isInside = [super trackMouse:theEvent inRect:cellFrame ofView:controlView untilMouseUp:NO]; - [self highlight:NO withFrame:cellFrame inView:controlView]; - keepOn = isInside ? NO : untilMouseUp; - } - if (keepOn) { - // we're dragging outside the button, wait for a mouseup or move back inside - theEvent = [[controlView window] nextEventMatchingMask: NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged]; - mouseLoc = [controlView convertPoint:[theEvent locationInWindow] fromView:nil]; - isInside = NSMouseInRect(mouseLoc, cellFrame, [controlView isFlipped]); - keepOn = ([theEvent type] == NSEventTypeLeftMouseDragged); - } - } - return isInside; - } else - return NO; -} - @end Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.h =================================================================== --- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.h 2024-01-23 15:28:04 UTC (rev 28656) +++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.h 2024-01-23 17:45:32 UTC (rev 28657) @@ -194,7 +194,7 @@ @end -@class FVSliderWindow, FVOperationQueue, FVBackgroundView; +@class FVSliderWindow, FVOperationQueue, FVBackgroundView, FVArrowButton; /** FVFileView is the primary class in the framework. @@ -231,7 +231,6 @@ unsigned int isRescaling:1; unsigned int scheduledLiveResize:1; unsigned int updatingFromSlider:1; - unsigned int hasArrows:1; unsigned int needsReload:1; unsigned int controllingSharedPreviewer:1; unsigned int controllingQLPreviewPanel:1; @@ -246,11 +245,8 @@ NSTextFieldCell *_titleCell; NSTextFieldCell *_subtitleCell; NSMutableArray *_trackingAreas; - NSButtonCell *_leftArrow; - NSButtonCell *_rightArrow; - NSRect _leftArrowFrame; - NSRect _rightArrowFrame; - CGFloat _arrowAlpha; + FVArrowButton *_leftArrow; + FVArrowButton *_rightArrow; FVSliderWindow *_sliderWindow; NSTrackingArea *_topSliderArea; NSTrackingArea *_bottomSliderArea; Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m =================================================================== --- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m 2024-01-23 15:28:04 UTC (rev 28656) +++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m 2024-01-23 17:45:32 UTC (rev 28657) @@ -211,8 +211,6 @@ @property (nonatomic, copy) NSArray *iconURLs; -@property (nonatomic) CGFloat arrowAlpha; - // only declare methods here to shut the compiler up if we can't rearrange - (FVIcon *)iconAtIndex:(NSUInteger)anIndex; - (FVIcon *)_cachedIconForURL:(NSURL *)aURL; @@ -260,7 +258,6 @@ @synthesize dataSource; @synthesize delegate; @dynamic numberOfIcons; -@synthesize arrowAlpha=_arrowAlpha; + (void)initialize { @@ -390,19 +387,14 @@ [_subtitleCell setLineBreakMode:NSLineBreakByTruncatingTail]; [_subtitleCell setAlignment:NSTextAlignmentCenter]; - _leftArrow = [[FVArrowButtonCell alloc] initWithArrowDirection:FVArrowLeft]; + _leftArrow = [[FVArrowButton alloc] initWithArrowDirection:FVArrowLeft]; [_leftArrow setTarget:self]; [_leftArrow setAction:@selector(leftArrowAction:)]; - _rightArrow = [[FVArrowButtonCell alloc] initWithArrowDirection:FVArrowRight]; + _rightArrow = [[FVArrowButton alloc] initWithArrowDirection:FVArrowRight]; [_rightArrow setTarget:self]; [_rightArrow setAction:@selector(rightArrowAction:)]; - _leftArrowFrame = NSZeroRect; - _rightArrowFrame = NSZeroRect; - _arrowAlpha = 0.0; - _fvFlags.hasArrows = NO; - _minScale = 0.5; _maxScale = 16.0; @@ -2603,13 +2595,6 @@ if (isDrawingToScreen) { - if (_fvFlags.hasArrows || _arrowAlpha > 0.0) { - if (NSIntersectsRect(rect, _leftArrowFrame)) - [(FVArrowButtonCell *)_leftArrow drawWithFrame:_leftArrowFrame inView:self alpha:_arrowAlpha]; - if (NSIntersectsRect(rect, _rightArrowFrame)) - [(FVArrowButtonCell *)_rightArrow drawWithFrame:_rightArrowFrame inView:self alpha:_arrowAlpha]; - } - // drop highlight and rubber band are mutually exclusive if (_dropIndex != NSNotFound || _fvFlags.dropOperation == FVDropOn) { [self _drawDropHighlight]; @@ -3036,7 +3021,7 @@ [self _updateButtonsForIcon:anIcon]; NSUInteger r, c; // _getGridRow should always succeed; either arrow frame would work here, since both are in the same icon - if ([self _getGridRow:&r column:&c atPoint:_leftArrowFrame.origin]) { + if ([self _getGridRow:&r column:&c atPoint:[_leftArrow frame].origin]) { NSSize size = [self respondsToSelector:@selector(convertSizeToBacking:)] ? [self convertSizeToBacking:_iconSize] : _iconSize; // render immediately so the placeholder path doesn't draw if ([anIcon needsRenderForSize:size]) @@ -3047,7 +3032,7 @@ - (void)leftArrowAction:(id)sender { - FVIcon *anIcon = [_leftArrow representedObject]; + FVIcon *anIcon = [[_leftArrow cell] representedObject]; [anIcon showPreviousPage]; [self _redisplayIconAfterPageChanged:anIcon]; } @@ -3054,16 +3039,11 @@ - (void)rightArrowAction:(id)sender { - FVIcon *anIcon = [_rightArrow representedObject]; + FVIcon *anIcon = [[_rightArrow cell] representedObject]; [anIcon showNextPage]; [self _redisplayIconAfterPageChanged:anIcon]; } -- (void)setArrowAlpha:(CGFloat)arrowAlpha { - _arrowAlpha = arrowAlpha; - [self setNeedsDisplayInRect:NSUnionRect(_leftArrowFrame, _rightArrowFrame)]; -} - - (void)_showArrowsForIconAtIndex:(NSUInteger)anIndex { NSUInteger r, c; @@ -3077,11 +3057,11 @@ if ([anIcon pageCount] > 1) { - if (_arrowAlpha > 0.0) { - if (anIcon != [_leftArrow representedObject]) - _arrowAlpha = 0.0; - // make sure we redraw whatever area previously had the arrows - [self setNeedsDisplayInRect:NSUnionRect(_leftArrowFrame, _rightArrowFrame)]; + if ([_leftArrow arrowAlpha] > 0.0) { + if (anIcon != [[_leftArrow cell] representedObject]) { + [_leftArrow setArrowAlpha:0.0]; + [_rightArrow setArrowAlpha:0.0]; + } } NSRect iconRect = [self _rectOfIconInRow:r column:c]; @@ -3092,22 +3072,26 @@ side = fmax(fmin(side, 32.0), 10.0); sep = fmin(0.5 * side - 4.0, 4.0); // 2 pixels between arrows horizontally, and 4 pixels between bottom of arrow and bottom of iconRect - _leftArrowFrame = _rightArrowFrame = NSMakeRect(ceil(NSMidX(iconRect) + 0.5 * sep), NSMaxY(iconRect) - side - sep, side, side); - _leftArrowFrame.origin.x -= side + sep; + NSRect arrowFrame = NSMakeRect(ceil(NSMidX(iconRect) + 0.5 * sep), NSMaxY(iconRect) - side - sep, side, side); + [_rightArrow setFrame:arrowFrame]; + arrowFrame.origin.x -= side + sep; + [_leftArrow setFrame:arrowFrame]; - [_leftArrow setRepresentedObject:anIcon]; - [_rightArrow setRepresentedObject:anIcon]; - _fvFlags.hasArrows = YES; - + [[_leftArrow cell] setRepresentedObject:anIcon]; + [[_rightArrow cell] setRepresentedObject:anIcon]; + // set enabled states [self _updateButtonsForIcon:anIcon]; - [self _setNeedsDisplayForIconInRow:r column:c]; - if (_arrowAlpha < 1.0) { + [self addSubview:_leftArrow]; + [self addSubview:_rightArrow]; + + if ([_leftArrow arrowAlpha] < 1.0) { [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){ [context setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; [context setDuration:0.3]; - [[self animator] setArrowAlpha:1.0]; + [[_leftArrow animator] setArrowAlpha:1.0]; + [[_rightArrow animator] setArrowAlpha:1.0]; } completionHandler:^{}]; } } @@ -3116,15 +3100,20 @@ - (void)_hideArrows { - if (_fvFlags.hasArrows) { - _fvFlags.hasArrows = NO; - [_leftArrow setRepresentedObject:nil]; - [_rightArrow setRepresentedObject:nil]; + if ([[_leftArrow cell] representedObject]) { + [[_leftArrow cell] setRepresentedObject:nil]; + [[_rightArrow cell] setRepresentedObject:nil]; [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){ [context setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; [context setDuration:0.3]; - [[self animator] setArrowAlpha:0.0]; - } completionHandler:^{}]; + [[_leftArrow animator] setArrowAlpha:0.0]; + [[_rightArrow animator] setArrowAlpha:0.0]; + } completionHandler:^{ + if ([[_leftArrow cell] representedObject] == nil) { + [_leftArrow removeFromSuperview]; + [_rightArrow removeFromSuperview]; + } + }]; } } @@ -3256,14 +3245,8 @@ NSUInteger flags = [event modifierFlags]; NSUInteger r, c, i; - if (_fvFlags.hasArrows && NSMouseInRect(p, _leftArrowFrame, [self isFlipped])) { - [_leftArrow trackMouse:event inRect:_leftArrowFrame ofView:self untilMouseUp:YES]; - } - else if (_fvFlags.hasArrows && NSMouseInRect(p, _rightArrowFrame, [self isFlipped])) { - [_rightArrow trackMouse:event inRect:_rightArrowFrame ofView:self untilMouseUp:YES]; - } // mark this icon for highlight if necessary - else if ([self _getGridRow:&r column:&c atPoint:p]) { + if ([self _getGridRow:&r column:&c atPoint:p]) { // remember _indexForGridRow:column: returns NSNotFound if you're in an empty slot of an existing row/column, but that's a deselect event so we still need to remove all selection indexes and mark for redisplay i = [self _indexForGridRow:r column:c]; 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