Revision: 16200
http://sourceforge.net/p/skim-app/code/16200
Author: hofman
Date: 2026-05-02 17:44:29 +0000 (Sat, 02 May 2026)
Log Message:
-----------
Display find results wrapping possibly on mutliple lines, with a max of 5
lines, with variable height rows
Modified Paths:
--------------
trunk/LeftSideView.xib
trunk/NSParagraphStyle_SKExtensions.h
trunk/NSParagraphStyle_SKExtensions.m
trunk/PDFSelection_SKExtensions.h
trunk/PDFSelection_SKExtensions.m
trunk/SKMainWindowController.h
trunk/SKMainWindowController.m
trunk/SKMainWindowController_UI.m
trunk/SKTableView.h
trunk/SKTableView.m
Modified: trunk/LeftSideView.xib
===================================================================
--- trunk/LeftSideView.xib 2026-05-01 20:54:31 UTC (rev 16199)
+++ trunk/LeftSideView.xib 2026-05-02 17:44:29 UTC (rev 16200)
@@ -394,9 +394,10 @@
</textField>
</subviews>
<constraints>
+ <constraint firstItem="5CV-AT-Wi3"
firstAttribute="top" secondItem="rTN-Wm-aea" secondAttribute="top"
priority="260" constant="3" id="17P-N4-VSY"/>
<constraint firstItem="5CV-AT-Wi3"
firstAttribute="leading" secondItem="rTN-Wm-aea" secondAttribute="leading"
constant="2" id="1af-hZ-zDh"/>
<constraint
firstAttribute="trailing" secondItem="5CV-AT-Wi3" secondAttribute="trailing"
constant="2" id="SHs-Ad-Ow7"/>
- <constraint firstItem="5CV-AT-Wi3"
firstAttribute="centerY" secondItem="rTN-Wm-aea" secondAttribute="centerY"
id="vbK-eq-WEx"/>
+ <constraint firstItem="5CV-AT-Wi3"
firstAttribute="centerY" relation="lessThanOrEqual" secondItem="rTN-Wm-aea"
secondAttribute="centerY" id="vbK-eq-WEx"/>
</constraints>
<connections>
<outlet property="textField"
destination="5CV-AT-Wi3" id="phD-a5-G8O"/>
@@ -409,7 +410,7 @@
<color key="textColor"
name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor"
white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
</tableHeaderCell>
- <textFieldCell key="dataCell"
lineBreakMode="truncatingTail" alignment="left" id="115">
+ <textFieldCell key="dataCell"
truncatesLastVisibleLine="YES" sendsActionOnEndEditing="YES" alignment="left"
id="115">
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="labelColor"
catalog="System" colorSpace="catalog"/>
<color key="backgroundColor"
name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
@@ -420,9 +421,9 @@
<rect key="frame" x="61" y="0.0"
width="127" height="17"/>
<autoresizingMask
key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
- <textField
verticalHuggingPriority="750" horizontalCompressionResistancePriority="250"
allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO"
id="EK0-Iy-KhJ">
- <rect key="frame" x="0.0"
y="1" width="127" height="15"/>
- <textFieldCell key="cell"
lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="left"
id="t89-Nc-Fkj">
+ <textField
verticalHuggingPriority="750" horizontalCompressionResistancePriority="250"
verticalCompressionResistancePriority="250" allowsExpansionToolTips="YES"
translatesAutoresizingMaskIntoConstraints="NO" id="EK0-Iy-KhJ">
+ <rect key="frame" x="0.0"
y="3" width="127" height="11"/>
+ <textFieldCell key="cell"
truncatesLastVisibleLine="YES" sendsActionOnEndEditing="YES" alignment="left"
id="t89-Nc-Fkj">
<font key="font"
metaFont="cellTitle"/>
<color key="textColor"
name="labelColor" catalog="System" colorSpace="catalog"/>
<color
key="backgroundColor" name="textBackgroundColor" catalog="System"
colorSpace="catalog"/>
@@ -433,8 +434,9 @@
</textField>
</subviews>
<constraints>
- <constraint firstItem="EK0-Iy-KhJ"
firstAttribute="centerY" secondItem="yHY-cQ-hrW" secondAttribute="centerY"
id="I0A-CW-rEo"/>
- <constraint
firstAttribute="trailing" secondItem="EK0-Iy-KhJ" secondAttribute="trailing"
priority="251" constant="2" id="Ihy-Fe-pIN"/>
+ <constraint
firstAttribute="trailing" secondItem="EK0-Iy-KhJ" secondAttribute="trailing"
constant="2" id="Ihy-Fe-pIN"/>
+ <constraint firstItem="EK0-Iy-KhJ"
firstAttribute="top" secondItem="yHY-cQ-hrW" secondAttribute="top" constant="3"
id="TmG-Ui-8dT"/>
+ <constraint
firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="EK0-Iy-KhJ"
secondAttribute="bottom" constant="3" id="Vqb-Ta-cSY"/>
<constraint firstItem="EK0-Iy-KhJ"
firstAttribute="leading" secondItem="yHY-cQ-hrW" secondAttribute="leading"
constant="2" id="lWu-vh-s2s"/>
</constraints>
<connections>
@@ -449,7 +451,7 @@
<rect key="frame" x="0.0"
y="0.0" width="127" height="17"/>
</visualEffectView>
<textField
verticalHuggingPriority="750" horizontalCompressionResistancePriority="250"
allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO"
id="6Fy-Cz-Uit">
- <rect key="frame" x="0.0"
y="1" width="127" height="15"/>
+ <rect key="frame" x="1" y="1"
width="125" height="15"/>
<textFieldCell key="cell"
lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="center"
id="W4J-nI-eOk">
<font key="font"
metaFont="cellTitle"/>
<color key="textColor"
name="labelColor" catalog="System" colorSpace="catalog"/>
@@ -465,9 +467,9 @@
<constraint
firstAttribute="trailing" secondItem="JPg-TA-CTy" secondAttribute="trailing"
id="3ix-Qp-JTR"/>
<constraint firstItem="JPg-TA-CTy"
firstAttribute="leading" secondItem="J7W-Ii-xfs" secondAttribute="leading"
id="7mF-oe-xcQ"/>
<constraint firstItem="JPg-TA-CTy"
firstAttribute="top" secondItem="J7W-Ii-xfs" secondAttribute="top"
id="HXm-ID-lvc"/>
- <constraint firstItem="6Fy-Cz-Uit"
firstAttribute="leading" secondItem="J7W-Ii-xfs" secondAttribute="leading"
constant="2" id="Ov9-R3-f5H"/>
+ <constraint firstItem="6Fy-Cz-Uit"
firstAttribute="leading" secondItem="J7W-Ii-xfs" secondAttribute="leading"
constant="3" id="Ov9-R3-f5H"/>
<constraint
firstAttribute="bottom" secondItem="JPg-TA-CTy" secondAttribute="bottom"
id="P9C-56-Pl1"/>
- <constraint
firstAttribute="trailing" secondItem="6Fy-Cz-Uit" secondAttribute="trailing"
priority="251" constant="2" id="awE-wD-FnJ"/>
+ <constraint
firstAttribute="trailing" secondItem="6Fy-Cz-Uit" secondAttribute="trailing"
priority="251" constant="3" id="awE-wD-FnJ"/>
</constraints>
<connections>
<outlet property="textField"
destination="6Fy-Cz-Uit" id="dNo-ri-DUe"/>
Modified: trunk/NSParagraphStyle_SKExtensions.h
===================================================================
--- trunk/NSParagraphStyle_SKExtensions.h 2026-05-01 20:54:31 UTC (rev
16199)
+++ trunk/NSParagraphStyle_SKExtensions.h 2026-05-02 17:44:29 UTC (rev
16200)
@@ -43,6 +43,7 @@
@interface NSParagraphStyle (SKExtensions)
@property (class, nonatomic, readonly) NSParagraphStyle
*defaultClippingParagraphStyle;
@property (class, nonatomic, readonly) NSParagraphStyle
*defaultTruncatingTailParagraphStyle;
+@property (class, nonatomic, readonly) NSParagraphStyle
*defaultWrappingParagraphStyle;
@end
NS_ASSUME_NONNULL_END
Modified: trunk/NSParagraphStyle_SKExtensions.m
===================================================================
--- trunk/NSParagraphStyle_SKExtensions.m 2026-05-01 20:54:31 UTC (rev
16199)
+++ trunk/NSParagraphStyle_SKExtensions.m 2026-05-02 17:44:29 UTC (rev
16200)
@@ -61,4 +61,16 @@
return defaultTruncatingTailParagraphStyle;
}
++ (NSParagraphStyle *)defaultWrappingParagraphStyle {
+ static NSParagraphStyle *defaultWrappingParagraphStyle = nil;
+ if (defaultWrappingParagraphStyle == nil) {
+ NSMutableParagraphStyle *tmpParagraphStyle = [[NSParagraphStyle
defaultParagraphStyle] mutableCopy];
+ [tmpParagraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
+ if (@available(macOS 11.0, *))
+ [tmpParagraphStyle
setLineBreakStrategy:NSLineBreakStrategyStandard];
+ defaultWrappingParagraphStyle = [tmpParagraphStyle copy];
+ }
+ return defaultWrappingParagraphStyle;
+}
+
@end
Modified: trunk/PDFSelection_SKExtensions.h
===================================================================
--- trunk/PDFSelection_SKExtensions.h 2026-05-01 20:54:31 UTC (rev 16199)
+++ trunk/PDFSelection_SKExtensions.h 2026-05-02 17:44:29 UTC (rev 16200)
@@ -49,6 +49,8 @@
@property (nonatomic, nullable, readonly) NSString *cleanedString;
@property (nonatomic, nullable, readonly) NSAttributedString *contextString;
+- (void)invalidateContextString;
+
@property (nonatomic, nullable, readonly) PDFDestination *destination;
- (NSUInteger)safeIndexOfFirstCharacterOnPage:(PDFPage *)page;
Modified: trunk/PDFSelection_SKExtensions.m
===================================================================
--- trunk/PDFSelection_SKExtensions.m 2026-05-01 20:54:31 UTC (rev 16199)
+++ trunk/PDFSelection_SKExtensions.m 2026-05-02 17:44:29 UTC (rev 16200)
@@ -45,6 +45,7 @@
#import "NSPointerArray_SKExtensions.h"
#import "NSColor_SKExtensions.h"
#import "NSCharacterSet_SKExtensions.h"
+#import <objc/objc-runtime.h>
#define SKIncludeNewlinesFromEnclosedTextKey
@"SKIncludeNewlinesFromEnclosedText"
@@ -52,6 +53,8 @@
#define HYPHEN_CHARACTER (unichar)0x002D
#define SOFT_HYPHEN_CHARACTER (unichar)0x00AD
+static char SKContextStringKey;
+
@interface NSTextStorage (SKNSSubTextStoragePrivateDeclarations)
- (NSRange)range;
@end
@@ -115,7 +118,7 @@
return [self compactedCleanedString];
}
-- (NSAttributedString *)contextString {
+- (NSAttributedString *)_contextString {
NSMutableAttributedString *attributedSample;
NSString *searchString = [self compactedCleanedString] ?: @"";
PDFSelection *extendedSelection;
@@ -124,7 +127,7 @@
NSString *ellipse = [NSString stringWithFormat:@"%C",
ELLIPSIS_CHARACTER];
NSRange foundRange;
CGFloat fontSize = [[NSUserDefaults standardUserDefaults]
doubleForKey:SKTableFontSizeKey] - 2.0;
- NSDictionary *attributes = [[NSDictionary alloc]
initWithObjectsAndKeys:[NSFont systemFontOfSize:fontSize], NSFontAttributeName,
[NSParagraphStyle defaultTruncatingTailParagraphStyle],
NSParagraphStyleAttributeName, nil];
+ NSDictionary *attributes = [[NSDictionary alloc]
initWithObjectsAndKeys:[NSFont systemFontOfSize:fontSize], NSFontAttributeName,
[NSParagraphStyle defaultWrappingParagraphStyle],
NSParagraphStyleAttributeName, nil];
PDFPage *page = [self safeFirstPage];
NSString *pageString = [page string];
NSUInteger length = [pageString length];
@@ -173,6 +176,21 @@
return attributedSample;
}
+- (NSAttributedString *)contextString {
+ NSAttributedString *contextString = objc_getAssociatedObject(self,
&SKContextStringKey);
+ if (contextString == nil) {
+ contextString = [self _contextString];
+ objc_setAssociatedObject(self, &SKContextStringKey, contextString,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ }
+ return contextString;
+}
+
+- (void)invalidateContextString {
+ [self willChangeValueForKey:@"contextString"];
+ objc_setAssociatedObject(self, &SKContextStringKey, nil,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ [self didChangeValueForKey:@"contextString"];
+}
+
- (PDFDestination *)destination {
PDFDestination *destination = nil;
PDFPage *page = [self safeFirstPage];
Modified: trunk/SKMainWindowController.h
===================================================================
--- trunk/SKMainWindowController.h 2026-05-01 20:54:31 UTC (rev 16199)
+++ trunk/SKMainWindowController.h 2026-05-02 17:44:29 UTC (rev 16200)
@@ -194,6 +194,7 @@
unsigned int needsCleanup:1;
unsigned int thumbnailsNeedUpdateAfterPresentaton:1;
unsigned int thumbnailsUpdatedDuringPresentaton:1;
+ unsigned int findRowHeightsNeedUpdate:1;
} mwcFlags;
}
Modified: trunk/SKMainWindowController.m
===================================================================
--- trunk/SKMainWindowController.m 2026-05-01 20:54:31 UTC (rev 16199)
+++ trunk/SKMainWindowController.m 2026-05-02 17:44:29 UTC (rev 16200)
@@ -2673,10 +2673,10 @@
[secondaryPdfView setNeedsDisplay:YES];
[self allThumbnailsNeedUpdate];
} else if ([keyPath isEqualToString:SKTableFontSizeKey]) {
+ if ([searchResults count] > 1)
+ [[searchResults subarrayWithRange:NSMakeRange(1,
[searchResults count] - 1)]
makeObjectsPerformSelector:@selector(invalidateContextString)];
[self updateTableFont];
[self updatePageColumnWidthForTableViews:[NSArray
arrayWithObjects:leftSideController.tocOutlineView,
rightSideController.noteOutlineView, leftSideController.findTableView,
leftSideController.groupedFindTableView, nil]];
- if ([searchResults count] > 1)
- [leftSideController.findTableView
reloadDataForRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1,
[searchResults count] - 1)] columnIndexes:[NSIndexSet
indexSetWithIndexesInRange:NSMakeRange(0, 2)]];
}
} else if (context == &SKMainWindowAppObservationContext) {
Modified: trunk/SKMainWindowController_UI.m
===================================================================
--- trunk/SKMainWindowController_UI.m 2026-05-01 20:54:31 UTC (rev 16199)
+++ trunk/SKMainWindowController_UI.m 2026-05-02 17:44:29 UTC (rev 16200)
@@ -100,6 +100,7 @@
#define AUTHOR_COLUMNID @"author"
#define DATE_COLUMNID @"date"
#define IMAGE_COLUMNID @"image"
+#define RESULTS_COLUMNID @"results"
#define RELEVANCE_COLUMNID @"relevance"
#define HEADER_IDENTIFIER @"header"
@@ -115,8 +116,9 @@
#define DEFAULT_TEXT_ROW_HEIGHT 85.0
#define DEFAULT_MARKUP_ROW_HEIGHT 50.0
-#define EXTRA_FIND_ROW_WIDTH 4.0
+#define EXTRA_FIND_ROW_HEIGHT 6.0
#define FIND_HEADER_ROW_HEIGHT 16.0
+#define MAX_FIND_LINES 5
@interface SKMainWindowController (SKPrivateMain)
@@ -531,17 +533,33 @@
}
return NO;
}
-
+
- (void)tableViewColumnDidResize:(NSNotification *)aNotification {
- if ([[[[aNotification userInfo] objectForKey:@"NSTableColumn"] identifier]
isEqualToString:IMAGE_COLUMNID]) {
- NSTableView *tv = [aNotification object];
+ NSString *tcID = [[[aNotification userInfo] objectForKey:@"NSTableColumn"]
identifier];
+ if ([tcID isEqualToString:IMAGE_COLUMNID]) {
+ SKTableView *tv = [aNotification object];
if ([tv isEqual:leftSideController.thumbnailTableView] || [tv
isEqual:rightSideController.snapshotTableView]) {
- [self
performSelectorOnce:@selector(invalidateRowHeightsForTableView:) withObject:tv
afterDelay:0.0];
- [(SKTableView *)tv noteHeightOfRowsChangedAnimating:NO];
+ [tv noteHeightOfRowsChangedAnimating:NO];
}
+ } else if ([tcID isEqualToString:RESULTS_COLUMNID]) {
+ SKTableView *tv = [aNotification object];
+ if ([tv isEqual:leftSideController.findTableView]) {
+ if ([tv inLiveResize])
+ mwcFlags.findRowHeightsNeedUpdate = YES;
+ else
+ [tv noteHeightOfRowsChangedAnimating:NO];
+ }
}
}
+- (void)tableViewDidEndLiveResize:(NSTableView *)tv {
+ if ([tv isEqual:leftSideController.findTableView] &&
mwcFlags.findRowHeightsNeedUpdate) {
+ if ([searchResults count] > 1)
+ [leftSideController.findTableView
noteHeightOfRowsWithIndexesChanged:[NSIndexSet
indexSetWithIndexesInRange:NSMakeRange(1, [searchResults count] - 1)]];
+ mwcFlags.findRowHeightsNeedUpdate = NO;
+ }
+}
+
- (CGFloat)tableView:(NSTableView *)tv heightOfRow:(NSInteger)row {
NSSize thumbSize = NSZeroSize;
CGFloat thumbHeight = 0.0, rowHeight = [tv rowHeight];
@@ -552,7 +570,15 @@
thumbSize = [[(SKSnapshotWindowController
*)[[rightSideController.snapshotArrayController arrangedObjects]
objectAtIndex:row] thumbnail] size];
thumbHeight = snapshotThumbnailSize;
} else if ([tv isEqual:leftSideController.findTableView]) {
- return row == 0 ? FIND_HEADER_ROW_HEIGHT : rowHeight +
EXTRA_FIND_ROW_WIDTH;
+ if (row == 0)
+ return FIND_HEADER_ROW_HEIGHT;
+ NSTableColumn *tc = [tv tableColumnWithIdentifier:RESULTS_COLUMNID];
+ NSTextFieldCell *cell = [tc dataCell];
+ [cell setObjectValue:[[[leftSideController.findArrayController
arrangedObjects] objectAtIndex:row] contextString]];
+ CGFloat height = [cell cellSizeForBounds:NSMakeRect(0.0, 0.0, [tc
width], CGFLOAT_MAX)].height;
+ if (height > MAX_FIND_LINES * (rowHeight - 3.0))
+ height = fmin(height, MAX_FIND_LINES * [cell
cellSizeForBounds:NSMakeRect(0.0, 0.0, CGFLOAT_MAX, CGFLOAT_MAX)].height);
+ return fmax(rowHeight, height + EXTRA_FIND_ROW_HEIGHT);
} else if ([tv isEqual:leftSideController.groupedFindTableView]) {
return row == 0 ? FIND_HEADER_ROW_HEIGHT : rowHeight;
} else {
Modified: trunk/SKTableView.h
===================================================================
--- trunk/SKTableView.h 2026-05-01 20:54:31 UTC (rev 16199)
+++ trunk/SKTableView.h 2026-05-02 17:44:29 UTC (rev 16200)
@@ -67,6 +67,8 @@
- (void)tableView:(NSTableView *)aTableView
typeSelectHelperDidFailToFindMatchForSearchString:(NSString *)searchString;
- (void)tableView:(NSTableView *)aTableView
typeSelectHelperUpdateSearchString:(NSString *)searchString;
+- (void)tableViewDidEndLiveResize:(NSTableView *)aTableView;
+
@end
typedef NS_ENUM(NSInteger, SKTableImageToolTipLayout) {
Modified: trunk/SKTableView.m
===================================================================
--- trunk/SKTableView.m 2026-05-01 20:54:31 UTC (rev 16199)
+++ trunk/SKTableView.m 2026-05-02 17:44:29 UTC (rev 16200)
@@ -274,11 +274,18 @@
[self enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView,
NSInteger row){ [rowView setEmphasized:NO]; }];
}
+- (void)viewDidEndLiveResize {
+ [super viewDidEndLiveResize];
+ if ([[self delegate]
respondsToSelector:@selector(tableViewDidEndLiveResize:)])
+ [[self delegate] tableViewDidEndLiveResize:self];
+}
+
- (void)draggingSession:(NSDraggingSession *)session
endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation {
if ([[SKTableView superclass] instancesRespondToSelector:_cmd])
[super draggingSession:session endedAtPoint:screenPoint
operation:operation];
[[session draggingPasteboard] clearContents];
}
+
#pragma mark Tracking
- (BOOL)hasRowImageToolTips {
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit