Revision: 29129 http://sourceforge.net/p/bibdesk/svn/29129 Author: hofman Date: 2025-04-18 09:32:25 +0000 (Fri, 18 Apr 2025) Log Message: ----------- Calculate iconSize and padding or numberOfColumns and numberOfRows without setting them, so we can change them once and change iconSize only when it changes, avoiding unnecessary updates
Modified Paths: -------------- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m =================================================================== --- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m 2025-04-17 16:18:00 UTC (rev 29128) +++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m 2025-04-18 09:32:25 UTC (rev 29129) @@ -1214,33 +1214,33 @@ return ceil( [self _rowHeight] * _numberOfRows + [self _topMargin] + [self _bottomMargin] ); } -- (void)_setPaddingAndIconSizeFromContentWidth:(CGFloat)width { +- (void)_getIconSize:(NSSize *)iconSize padding:(NSSize *)padding fittingContentWidth:(CGFloat)width { // calculate the column width, inverting the calculation in _frameWidth // make sure fractional widths won't bring back scrollers CGFloat colWidth = ( floor(width) - 2 * DEFAULT_MARGIN.width ) / _numberOfColumns; // guess the iconScale, ignoring the rounding of the variable padding as that can't be inverted CGFloat iconScale = fmax( MIN_AUTO_ICON_SCALE, ( colWidth - DEFAULT_PADDING.width ) / ( DEFAULT_ICON_SIZE.width + PADDING_STRETCH )); - _padding = [self _paddingForScale:iconScale]; + *padding = [self _paddingForScale:iconScale]; // recalculate exactly based on this padding - iconScale = fmax( MIN_AUTO_ICON_SCALE, floor( colWidth - _padding.width ) / DEFAULT_ICON_SIZE.width ); - _iconSize = NSMakeSize(iconScale * DEFAULT_ICON_SIZE.width, iconScale * DEFAULT_ICON_SIZE.height); + iconScale = fmax( MIN_AUTO_ICON_SCALE, floor( colWidth - padding->width ) / DEFAULT_ICON_SIZE.width ); + *iconSize = NSMakeSize(iconScale * DEFAULT_ICON_SIZE.width, iconScale * DEFAULT_ICON_SIZE.height); } -- (void)_setPaddingAndIconSizeFromContentHeight:(CGFloat)height { +- (void)_getIconSize:(NSSize *)iconSize padding:(NSSize *)padding fittingContentHeight:(CGFloat)height { // calculate the row height, inverting the calculation in _frameHeight // make sure fractional heights won't bring back scrollers CGFloat rowHeight = ( floor(height) - DEFAULT_MARGIN.height ) / _numberOfRows; // guess the iconScale, ignoring the rounding of the variable padding as that can't be inverted CGFloat iconScale = fmax( MIN_AUTO_ICON_SCALE, ( rowHeight - DEFAULT_PADDING.height - [self _textHeight] ) / ( DEFAULT_ICON_SIZE.height + PADDING_STRETCH ) ); - _padding = [self _paddingForScale:iconScale]; + *padding = [self _paddingForScale:iconScale]; // recalculate exactly based on this padding - iconScale = fmax( MIN_AUTO_ICON_SCALE, floor( rowHeight - _padding.height ) / DEFAULT_ICON_SIZE.height ); - _iconSize = NSMakeSize(iconScale * DEFAULT_ICON_SIZE.width, iconScale * DEFAULT_ICON_SIZE.height); + iconScale = fmax( MIN_AUTO_ICON_SCALE, floor( rowHeight - padding->height ) / DEFAULT_ICON_SIZE.height ); + *iconSize = NSMakeSize(iconScale * DEFAULT_ICON_SIZE.width, iconScale * DEFAULT_ICON_SIZE.height); } -- (void)_setColumnsAndRowsFromContentWidth:(CGFloat)width { - _numberOfColumns = MAX( 1, (NSInteger)floor( ( width - 2 * DEFAULT_MARGIN.width ) / [self _columnWidth] ) ); - _numberOfRows = ( [self numberOfIcons] + _numberOfColumns - 1 ) / _numberOfColumns; +- (void)_getColumns:(NSInteger *)numberOfColumns rows:(NSInteger *)numberOfRows fittingContentWidth:(CGFloat)width { + *numberOfColumns = MAX( 1, (NSInteger)floor( ( width - 2 * DEFAULT_MARGIN.width ) / [self _columnWidth] ) ); + *numberOfRows = ( [self numberOfIcons] + *numberOfColumns - 1 ) / *numberOfColumns; } static CGFloat _scrollerWidthForScroller(NSScroller *scroller) { @@ -1284,102 +1284,123 @@ _numberOfColumns = 1; _numberOfRows = [self numberOfIcons]; - [self willChangeValueForKey:@"iconScale"]; + NSSize iconSize = _iconSize; + NSSize padding = _padding; // if we have an auto-hiding vertical scroller, we may or may not have scroll bars, which affects the effective width if (autoHidesScrollers && [scrollView hasVerticalScroller]) { + // the _frameWidth for the MIN_AUTO_SCALE CGFloat minWidth = ceil( [self _paddingForScale:MIN_AUTO_ICON_SCALE].width + MIN_AUTO_ICON_SCALE * DEFAULT_ICON_SIZE.width + 2 * DEFAULT_MARGIN.width ); // first assume we need a vertical scroller... contentSize = _contentSizeForScrollViewHavingVerticalScroller(scrollView, minWidth, YES); - [self _setPaddingAndIconSizeFromContentWidth:contentSize.width]; + [self _getIconSize:&iconSize padding:&padding fittingContentWidth:contentSize.width]; - if (contentSize.height > [self _frameHeight]) { + if (contentSize.height > ceil( (iconSize.height + padding.height) * _numberOfRows - DEFAULT_MARGIN.height )) { // we have sufficient height to fit all icons, so recalculate without vertical scroller contentSize = _contentSizeForScrollViewHavingVerticalScroller(scrollView, minWidth, NO); - [self _setPaddingAndIconSizeFromContentWidth:contentSize.width]; + [self _getIconSize:&iconSize padding:&padding fittingContentWidth:contentSize.width]; - if (_numberOfRows > 0 && contentSize.height < [self _frameHeight]) { + if (_numberOfRows > 0 && contentSize.height < ceil( (iconSize.height + padding.height) * _numberOfRows - DEFAULT_MARGIN.height )) { // the height with this wider icons becomes too much, so we now recalculate by fitting the height, still without vertical scroller // this should come out in between the previous two calculations - [self _setPaddingAndIconSizeFromContentHeight:contentSize.height]; + [self _getIconSize:&iconSize padding:&padding fittingContentHeight:contentSize.height]; } } } else { - [self _setPaddingAndIconSizeFromContentWidth:contentSize.width]; + [self _getIconSize:&iconSize padding:&padding fittingContentWidth:contentSize.width]; } - [self didChangeValueForKey:@"iconScale"]; + if (NSEqualSizes(iconSize, _iconSize) == NO) { + [self willChangeValueForKey:@"iconScale"]; + _iconSize = iconSize; + [self didChangeValueForKey:@"iconScale"]; - CGLayerRelease(_selectionOverlay); - _selectionOverlay = NULL; - + CGLayerRelease(_selectionOverlay); + _selectionOverlay = NULL; + } + + _padding = padding; + } else if (_fvFlags.displayMode == FVDisplayModeRow) { _numberOfColumns = [self numberOfIcons]; _numberOfRows = 1; - [self willChangeValueForKey:@"iconScale"]; - + NSSize iconSize = _iconSize; + NSSize padding = _padding; + // if we have an auto-hiding horizontal scroller, we may or may not have scroll bars, which affects the effective height if (autoHidesScrollers && [scrollView hasHorizontalScroller]) { + // the _frameHeight for the MIN_AUTO_SCALE CGFloat minHeight = ceil( [self _paddingForScale:MIN_AUTO_ICON_SCALE].height + MIN_AUTO_ICON_SCALE * DEFAULT_ICON_SIZE.height + DEFAULT_MARGIN.height ); // first assume we need a horizontal scroller... contentSize = _contentSizeForScrollViewHavingHorizontalScroller(scrollView, minHeight, YES); - [self _setPaddingAndIconSizeFromContentHeight:contentSize.height]; + [self _getIconSize:&iconSize padding:&padding fittingContentHeight:contentSize.height]; - if (contentSize.width > [self _frameWidth]) { + if (contentSize.width > ceil( (iconSize.width + padding.width) * _numberOfColumns - 2 * DEFAULT_MARGIN.width )) { // we have sufficient width to fit all icons, so recalculate without horizontal scroller contentSize = _contentSizeForScrollViewHavingHorizontalScroller(scrollView, minHeight, NO); - [self _setPaddingAndIconSizeFromContentHeight:contentSize.height]; + [self _getIconSize:&iconSize padding:&padding fittingContentHeight:contentSize.height]; - if (_numberOfColumns > 0 && contentSize.width < [self _frameWidth]) { + if (_numberOfColumns > 0 && contentSize.width < ceil( (iconSize.width + padding.width) * _numberOfColumns - 2 * DEFAULT_MARGIN.width )) { // the width with this wider icons becomes too much, so we now recalculate by fitting the width, still without horizontal scroller // this should come out in between the previous two calculations - [self _setPaddingAndIconSizeFromContentWidth:contentSize.width]; + [self _getIconSize:&iconSize padding:&padding fittingContentWidth:contentSize.width]; } } } else { - [self _setPaddingAndIconSizeFromContentHeight:contentSize.height]; + [self _getIconSize:&iconSize padding:&padding fittingContentHeight:contentSize.height]; } - [self didChangeValueForKey:@"iconScale"]; + if (NSEqualSizes(iconSize, _iconSize) == NO) { + [self willChangeValueForKey:@"iconScale"]; + _iconSize = iconSize; + [self didChangeValueForKey:@"iconScale"]; + + CGLayerRelease(_selectionOverlay); + _selectionOverlay = NULL; + } - CGLayerRelease(_selectionOverlay); - _selectionOverlay = NULL; + padding = _padding; } else { + NSInteger numberOfColumns = _numberOfColumns; + NSInteger numberOfRows = _numberOfRows; + _padding = [self _paddingForScale:[self iconScale]]; // if we have an auto-hiding vertical scroller, we may or may not have scroll bars, which affects the effective width if (autoHidesScrollers && [scrollView hasVerticalScroller]) { - // set the number of columns to 1 to calculate the minimal required width - _numberOfColumns = 1; - CGFloat minWidth = [self _frameWidth]; + // the _frameWidth for a single column + CGFloat minWidth = ceil( [self _columnWidth] + 2 * DEFAULT_MARGIN.width ); // first assume we don't need a vertical scroller... contentSize = _contentSizeForScrollViewHavingVerticalScroller(scrollView, minWidth, NO); - [self _setColumnsAndRowsFromContentWidth:contentSize.width]; + [self _getColumns:&numberOfColumns rows:&numberOfRows fittingContentWidth:contentSize.width]; - if (contentSize.height < [self _frameHeight]) { + if (contentSize.height < ceil( [self _rowHeight] * numberOfRows + [self _topMargin] + [self _bottomMargin] )) { // we have insufficient height to fit all icons, so recalculate with vertical scroller contentSize = _contentSizeForScrollViewHavingVerticalScroller(scrollView, minWidth, YES); - [self _setColumnsAndRowsFromContentWidth:contentSize.width]; + [self _getColumns:&numberOfColumns rows:&numberOfRows fittingContentWidth:contentSize.width]; } } else { - [self _setColumnsAndRowsFromContentWidth:contentSize.width]; + [self _getColumns:&numberOfColumns rows:&numberOfRows fittingContentWidth:contentSize.width]; } + + _numberOfColumns = numberOfColumns; + _numberOfRows = numberOfRows; } if (scrollView) { 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