Revision: 28656
http://sourceforge.net/p/bibdesk/svn/28656
Author: hofman
Date: 2024-01-23 15:28:04 +0000 (Tue, 23 Jan 2024)
Log Message:
-----------
Add progress indicators as subviews. Avoids redrawing the icons. Let the
progress indicators manage the timer. Animate changing the progress.
Modified Paths:
--------------
trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.h
trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m
trunk/bibdesk_vendorsrc/amaxwell/FileView/FVProgressIndicator.h
trunk/bibdesk_vendorsrc/amaxwell/FileView/FVProgressIndicator.m
Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.h
===================================================================
--- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.h 2024-01-23
09:38:09 UTC (rev 28655)
+++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.h 2024-01-23
15:28:04 UTC (rev 28656)
@@ -258,7 +258,6 @@
NSDictionary *_contentBinding;
NSMutableArray *_downloads;
NSMutableDictionary *_progressIndicators;
- CFRunLoopTimerRef _progressTimer;
NSMutableArray *_accessibilityIcons;
NSMutableSet *_modificationSet;
NSLock *_modificationLock;
Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m
===================================================================
--- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m 2024-01-23
09:38:09 UTC (rev 28655)
+++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m 2024-01-23
15:28:04 UTC (rev 28656)
@@ -226,7 +226,6 @@
- (void)_showArrowsForIconAtIndex:(NSUInteger)anIndex;
- (void)_hideArrows;
- (void)_cancelDownloads;
-- (void)_invalidateProgressTimer;
- (void)_downloadURLAtIndex:(NSUInteger)anIndex replace:(BOOL)replace;
- (void)_handleFinderLabelChanged:(NSNotification *)note;
- (void)_updateBinding:(NSString *)binding;
@@ -419,9 +418,6 @@
// a dictionary of progress indicators
_progressIndicators = nil;
- // timer to update the view when a download's length is indeterminate
- _progressTimer = NULL;
-
// set of _FVFileKey instances
_modificationSet = [NSMutableSet new];
_modificationLock = [NSLock new];
@@ -453,7 +449,6 @@
- (void)dealloc
{
- [self _invalidateProgressTimer];
CFRunLoopTimerInvalidate(_zombieTimer);
CFRelease(_zombieTimer);
// this variable is accessed in super's dealloc, so set it to NULL
@@ -1657,6 +1652,31 @@
[self _resetTrackingRectsAndToolTips];
}
+- (NSRect)_rectOfProgressIndicatorForIconAtIndex:(NSUInteger)anIndex;
+{
+ NSUInteger r, c;
+ NSRect frame = NSZeroRect;
+ if ([self _getGridRow:&r column:&c ofIndex:anIndex]) {
+ frame = [self _rectOfIconInRow:r column:c];
+ NSPoint center = NSMakePoint(NSMidX(frame), NSMidY(frame));
+
+ CGFloat size = NSHeight(frame) / 2;
+ frame.size.height = size;
+ frame.size.width = size;
+ frame.origin.x = center.x - NSWidth(frame) / 2;
+ frame.origin.y = center.y - NSHeight(frame) / 2;
+ }
+ return frame;
+}
+
+- (void)_updateProgressIndicatorFrames {
+ if ([_progressIndicators count] > 0) {
+ [_progressIndicators enumerateKeysAndObjectsUsingBlock:^(NSURL *url,
FVProgressIndicator *progressIndicator, BOOL *stop){
+ [progressIndicator setFrame:[self
_rectOfProgressIndicatorForIconAtIndex:[progressIndicator indexInView]]];
+ }];
+ }
+}
+
- (void)_resetViewLayout;
{
// When the tracking rects are active while the view is layed out,
mouseEntered may be called even if the mouse does not move. So we remove them
before doing the layout. We will reinstall them at the end of this method.
@@ -1665,6 +1685,9 @@
// Problem exposed in BibDesk: select all, scroll halfway down in file
pane, then change selection to a single row. FVFileView content didn't update
correctly, even though reloadIcons was called. Logging drawRect: indicated
that the wrong region was being updated, but calling _recalculateGridSize here
fixed it.
[self _recalculateGridSize];
+ // We may have to change the frames of the progress indicators.
+ [self _updateProgressIndicatorFrames];
+
// grid may have changed, so do a full redisplay
[self setNeedsDisplay:YES];
@@ -1849,8 +1872,15 @@
}
for (NSURL *url in [_progressIndicators allKeys]) {
- if ([_orderedURLs containsObject:url] == NO)
- [self removeProgressIndicatorForURL:url
atIndex:[[_progressIndicators objectForKey:url] indexInView]];
+ FVProgressIndicator *progressIndicator = [_progressIndicators
objectForKey:url];
+ NSUInteger anIndex = [progressIndicator indexInView];
+ if ([_orderedURLs containsObject:url] == NO) {
+ [self removeProgressIndicatorForURL:url atIndex:anIndex];
+ } else if (anIndex >= [self numberOfIcons] || [[self
URLAtIndex:anIndex] isEqual:url] == NO) {
+ anIndex = [_orderedURLs indexOfObject:url];
+ [progressIndicator setIndexInView:anIndex];
+ [progressIndicator setFrame:[self
_rectOfProgressIndicatorForIconAtIndex:anIndex]];
+ }
}
[self _resetViewLayout];
@@ -2482,23 +2512,6 @@
CGColorRelease(shadowColor);
}
-- (NSRect)_rectOfProgressIndicatorForIconAtIndex:(NSUInteger)anIndex;
-{
- NSUInteger r, c;
- NSRect frame = NSZeroRect;
- if ([self _getGridRow:&r column:&c ofIndex:anIndex]) {
- frame = [self _rectOfIconInRow:r column:c];
- NSPoint center = NSMakePoint(NSMidX(frame), NSMidY(frame));
-
- CGFloat size = NSHeight(frame) / 2;
- frame.size.height = size;
- frame.size.width = size;
- frame.origin.x = center.x - NSWidth(frame) / 2;
- frame.origin.y = center.y - NSHeight(frame) / 2;
- }
- return frame;
-}
-
- (void)_fillBackgroundColorOrGradientInRect:(NSRect)rect
forBounds:(NSRect)bounds
{
// any solid color background should override the gradient code
@@ -2604,15 +2617,6 @@
else if (NSIsEmptyRect(_rubberBandRect) == NO) {
[self _drawRubberbandRect];
}
-
- if ([_progressIndicators count]) {
- [_progressIndicators enumerateKeysAndObjectsUsingBlock:^(NSURL
*url, FVProgressIndicator *progressIndicator, BOOL *stop){
- NSUInteger anIndex = [progressIndicator indexInView];
- // we only draw a if there's an active download for this
URL/index pair
- if (anIndex < [self numberOfIcons] && [[self
URLAtIndex:anIndex] isEqual:url])
- [progressIndicator drawWithFrame:[self
_rectOfProgressIndicatorForIconAtIndex:anIndex]];
- }];
- }
}
#if DEBUG_GRID
[[NSColor grayColor] set];
@@ -4095,27 +4099,6 @@
#pragma mark Download support
-- (void)_invalidateProgressTimer
-{
- if (_progressTimer) {
- CFRunLoopTimerInvalidate(_progressTimer);
- CFRelease(_progressTimer);
- _progressTimer = NULL;
- }
-}
-
-- (void)_progressTimerFired:(CFRunLoopTimerRef)timer
-{
- NSUInteger r, c;
- for (FVProgressIndicator *progressIndicator in [_progressIndicators
allValues]) {
- if ([progressIndicator style] == FVProgressIndicatorIndeterminate) {
- [progressIndicator animate];
- if ([self _getGridRow:&r column:&c ofIndex:[progressIndicator
indexInView]])
- [self _setNeedsDisplayForIconInRow:r column:c];
- }
- }
-}
-
- (void)downloadUpdated:(FVDownload *)download
{
[self updateProgressIndicator:[download currentProgress] forURL:[download
downloadURL] atIndex:[download indexInView]];
@@ -4221,7 +4204,6 @@
- (void)updateProgressIndicator:(double)progress forURL:(NSURL *)aURL
atIndex:(NSUInteger)anIndex {
FVProgressIndicator *progressIndicator = [_progressIndicators
objectForKey:aURL];
- NSUInteger r, c;
if (progressIndicator == nil) {
progressIndicator = [[FVProgressIndicator alloc] init];
[progressIndicator setIndexInView:anIndex];
@@ -4228,41 +4210,29 @@
if (_progressIndicators == nil)
_progressIndicators = [[NSMutableDictionary alloc] init];
[_progressIndicators setObject:progressIndicator forKey:aURL];
+ [progressIndicator setFrame:[self
_rectOfProgressIndicatorForIconAtIndex:anIndex]];
+ [self addSubview:progressIndicator];
} else if (anIndex != [progressIndicator indexInView]) {
- NSUInteger oldIndex = [progressIndicator indexInView];
[progressIndicator setIndexInView:anIndex];
- if (oldIndex < [self numberOfIcons] && [self _getGridRow:&r column:&c
ofIndex:oldIndex])
- [self _setNeedsDisplayForIconInRow:r column:c];
+ [progressIndicator setFrame:[self
_rectOfProgressIndicatorForIconAtIndex:anIndex]];
}
if (progress < 0.0) {
[progressIndicator setStyle:FVProgressIndicatorIndeterminate];
- if (_progressTimer == NULL) {
- // runloop will retain this timer, but we'll retain it too and
release in -dealloc
- _progressTimer =
FVCreateWeakTimerWithTimeInterval(PROGRESS_TIMER_INTERVAL,
CFAbsoluteTimeGetCurrent() + PROGRESS_TIMER_INTERVAL, self,
@selector(_progressTimerFired:));
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), _progressTimer,
kCFRunLoopDefaultMode);
- }
} else {
[progressIndicator setStyle:FVProgressIndicatorDeterminate];
- [progressIndicator setCurrentProgress:progress];
+ [[progressIndicator animator] setCurrentProgress:progress];
}
- if ([self _getGridRow:&r column:&c ofIndex:anIndex])
- [self _setNeedsDisplayForIconInRow:r column:c];
}
- (void)removeProgressIndicatorForURL:(NSURL *)aURL
atIndex:(NSUInteger)anIndex {
+ [[_progressIndicators objectForKey:aURL] removeFromSuperview];
[_progressIndicators removeObjectForKey:aURL];
- if ([_progressIndicators count] == 0 || [[[_progressIndicators allValues]
valueForKey:@"style"] containsObject:[NSNumber
numberWithInteger:FVProgressIndicatorIndeterminate]] == NO)
- [self _invalidateProgressTimer];
- NSUInteger r, c;
- if ([self _getGridRow:&r column:&c ofIndex:anIndex])
- [self _setNeedsDisplayForIconInRow:r column:c];
}
- (void)resetProgressIndicators {
if ([_progressIndicators count] > 0) {
+ [[_progressIndicators allValues]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
[_progressIndicators removeAllObjects];
- [self _invalidateProgressTimer];
- [self setNeedsDisplay:YES];
}
for (FVDownload *download in _downloads) {
[self updateProgressIndicator:[download currentProgress]
forURL:[download downloadURL] atIndex:[download indexInView]];
Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVProgressIndicator.h
===================================================================
--- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVProgressIndicator.h
2024-01-23 09:38:09 UTC (rev 28655)
+++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVProgressIndicator.h
2024-01-23 15:28:04 UTC (rev 28656)
@@ -51,7 +51,7 @@
FVProgressIndicatorDeterminate = 0
};
-@interface FVProgressIndicator : NSObject
+@interface FVProgressIndicator : NSView
{
@private
CGFloat _currentProgress;
@@ -58,6 +58,7 @@
NSInteger _currentStep;
FVProgressIndicatorStyle _style;
NSUInteger _indexInView;
+ CFRunLoopTimerRef _progressTimer;
}
@property (nonatomic) CGFloat currentProgress;
@@ -67,8 +68,4 @@
@property (nonatomic) NSUInteger indexInView;
-- (void)animate;
-
-- (void)drawWithFrame:(NSRect)aRect;
-
@end
Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVProgressIndicator.m
===================================================================
--- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVProgressIndicator.m
2024-01-23 09:38:09 UTC (rev 28655)
+++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVProgressIndicator.m
2024-01-23 15:28:04 UTC (rev 28656)
@@ -37,8 +37,15 @@
*/
#import "FVProgressIndicator.h"
+#import <QuartzCore/QuartzCore.h>
+#import "FVUtilities.h"
+@interface FVProgressIndicator ()
+- (void)_startProgressTimer;
+- (void)_invalidateProgressTimer;
+@end
+
@implementation FVProgressIndicator
@synthesize currentProgress=_currentProgress;
@@ -45,17 +52,25 @@
@synthesize style=_style;
@synthesize indexInView=_indexInView;
-static NSInteger numSteps = 8;
++ (id)defaultAnimationForKey:(NSString *)key {
+ if ([key isEqualToString:@"currentProgress"])
+ return [CABasicAnimation animation];
+ return [super defaultAnimationForKey:key];
+}
+static NSInteger _numSteps = 8;
+static CGFloat _progressTimeInterval = 0.1;
+
+ (void)initialize {
FVINITIALIZE(FVProgressIndicator);
- if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_15)
- numSteps = 12;
+ if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_15) {
+ _numSteps = 12;
+ _progressTimeInterval = 1.0/24.0;
+ }
}
-- (id)init
-{
+- (id)init {
self = [super init];
if (self) {
_currentProgress = 0;
@@ -65,36 +80,72 @@
return self;
}
-- (void)animate
-{
- if (_style == FVProgressIndicatorIndeterminate)
- _currentStep = (_currentStep + 1) % numSteps;
+- (void)dealloc {
+ [self _invalidateProgressTimer];
}
-- (void)drawWithFrame:(NSRect)aRect
-{
+- (void)setStyle:(FVProgressIndicatorStyle)style {
+ if (style != _style) {
+ _style = style;
+ [self setNeedsDisplay:YES];
+ if (_style == FVProgressIndicatorIndeterminate)
+ [self _startProgressTimer];
+ else
+ [self _invalidateProgressTimer];
+ }
+}
+
+- (void)setCurrentProgress:(CGFloat)currentProgress {
+ _currentProgress = currentProgress;
+ [self setNeedsDisplay:YES];
+}
+
+- (void)_progressTimerFired:(CFRunLoopTimerRef)timer {
+ if (_style == FVProgressIndicatorIndeterminate) {
+ _currentStep = (_currentStep + 1) % _numSteps;
+ [self setNeedsDisplay:YES];
+ }
+}
+
+- (void)_startProgressTimer {
+ if (_progressTimer == NULL && [self window]) {
+ // runloop will retain this timer, but we'll retain it too and release
in -dealloc
+ _progressTimer =
FVCreateWeakTimerWithTimeInterval(_progressTimeInterval, _progressTimeInterval
* floor(CFAbsoluteTimeGetCurrent() / _progressTimeInterval + 1.0), self,
@selector(_progressTimerFired:));
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), _progressTimer,
kCFRunLoopDefaultMode);
+ }
+}
+
+- (void)_invalidateProgressTimer {
+ if (_progressTimer) {
+ CFRunLoopTimerInvalidate(_progressTimer);
+ CFRelease(_progressTimer);
+ _progressTimer = NULL;
+ }
+}
+
+- (void)drawRect:(NSRect)dirtyRect {
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(context);
- CGRect progressRect = NSRectToCGRect(aRect);
+ CGRect progressRect = NSRectToCGRect([self bounds]);
CGPoint ctr = CGPointMake(CGRectGetMidX(progressRect),
CGRectGetMidY(progressRect));
CGFloat h = CGRectGetHeight(progressRect) / 64.0;
if (_style == FVProgressIndicatorIndeterminate) {
// indeterminate download length
- CGFloat angle = M_PI * 2.0 / numSteps;
+ CGFloat angle = M_PI * 2.0 / _numSteps;
CGContextTranslateCTM(context, ctr.x, ctr.y);
CGContextRotateCTM(context, _currentStep * angle);
CGContextTranslateCTM(context, -ctr.x, -ctr.y);
NSInteger i;
- for (i = 0; i < numSteps; i++) {
- CGColorRef strokeColor = CGColorCreateGenericGray(0.0, (1.0 -
(CGFloat)i / numSteps) * (numSteps - 4.0) / 8.0);
+ for (i = 0; i < _numSteps; i++) {
+ CGColorRef strokeColor = CGColorCreateGenericGray(0.0, (1.0 -
(CGFloat)i / _numSteps) * (_numSteps - 4.0) / 8.0);
CGContextSetStrokeColorWithColor(context, strokeColor);
CGColorRelease(strokeColor);
- CGContextSetLineWidth(context, (12.0 - numSteps / 2.0) * h);
+ CGContextSetLineWidth(context, (12.0 - _numSteps / 2.0) * h);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextBeginPath(context);
- CGContextMoveToPoint(context, ctr.x, ctr.y - (14.0 + numSteps /
4.0) * h);
- CGContextAddLineToPoint(context, ctr.x, ctr.y - (26.0 + numSteps /
4.0) * h);
+ CGContextMoveToPoint(context, ctr.x, ctr.y - (14.0 + _numSteps /
4.0) * h);
+ CGContextAddLineToPoint(context, ctr.x, ctr.y - (26.0 + _numSteps
/ 4.0) * h);
CGContextStrokePath(context);
CGContextTranslateCTM(context, ctr.x, ctr.y);
CGContextRotateCTM(context, -angle);
@@ -139,4 +190,16 @@
CGContextRestoreGState(context);
}
+- (void)viewWillMoveToWindow:(NSWindow *)newWindow {
+ [super viewWillMoveToWindow:newWindow];
+ if (newWindow == nil)
+ [self _invalidateProgressTimer];
+}
+
+- (void)viewDidMoveToWindow {
+ [super viewDidMoveToWindow];
+ if (_style == FVProgressIndicatorIndeterminate)
+ [self _startProgressTimer];
+}
+
@end
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit