Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Results collapse/expand, rev to version 1.1

  • Loading branch information...
commit 44f1579b11e876eed1ba03044d6ab945f7a68d30 1 parent da63102
@protocool authored
View
8 AckMate.xcodeproj/project.pbxproj
@@ -24,6 +24,8 @@
69C43B0B112A361C007AC1C1 /* JPAckProcess+Parsing.m.rl in Sources */ = {isa = PBXBuildFile; fileRef = 69C43B05112A361C007AC1C1 /* JPAckProcess+Parsing.m.rl */; };
69C43B0C112A361C007AC1C1 /* JPAckResultSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 69C43B07112A361C007AC1C1 /* JPAckResultSource.m */; };
69C43B0D112A361C007AC1C1 /* JPAckWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 69C43B09112A361C007AC1C1 /* JPAckWindowController.m */; };
+ 69D7008D118115CA008A6125 /* ackmateCollapse.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 69D7008B118115CA008A6125 /* ackmateCollapse.pdf */; };
+ 69D7008E118115CA008A6125 /* ackmateExpand.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 69D7008C118115CA008A6125 /* ackmateExpand.pdf */; };
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
/* End PBXBuildFile section */
@@ -91,6 +93,8 @@
69C43B07112A361C007AC1C1 /* JPAckResultSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPAckResultSource.m; sourceTree = "<group>"; };
69C43B08112A361C007AC1C1 /* JPAckWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPAckWindowController.h; sourceTree = "<group>"; };
69C43B09112A361C007AC1C1 /* JPAckWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPAckWindowController.m; sourceTree = "<group>"; };
+ 69D7008B118115CA008A6125 /* ackmateCollapse.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = ackmateCollapse.pdf; path = ../../ackmate/AckMate/bundle_extras/ackmateCollapse.pdf; sourceTree = SOURCE_ROOT; };
+ 69D7008C118115CA008A6125 /* ackmateExpand.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = ackmateExpand.pdf; path = ../../ackmate/AckMate/bundle_extras/ackmateExpand.pdf; sourceTree = SOURCE_ROOT; };
8D5B49B6048680CD000E48DA /* AckMate.tmplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AckMate.tmplugin; sourceTree = BUILT_PRODUCTS_DIR; };
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
@@ -188,6 +192,8 @@
69B8C4BC112A370200EB45AF /* bundle_extras */ = {
isa = PBXGroup;
children = (
+ 69D7008B118115CA008A6125 /* ackmateCollapse.pdf */,
+ 69D7008C118115CA008A6125 /* ackmateExpand.pdf */,
69B8C4BD112A371A00EB45AF /* ackmate_ack.autogenerated */,
);
path = bundle_extras;
@@ -307,6 +313,8 @@
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */,
69B8C4BE112A371A00EB45AF /* ackmate_ack.autogenerated in Resources */,
69B8C4E6112A383600EB45AF /* JPAckWindow.xib in Resources */,
+ 69D7008D118115CA008A6125 /* ackmateCollapse.pdf in Resources */,
+ 69D7008E118115CA008A6125 /* ackmateExpand.pdf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
2  Info.plist
@@ -19,7 +19,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.0.2</string>
+ <string>1.1.0</string>
<key>NSPrincipalClass</key>
<string>AckMatePlugin</string>
</dict>
View
6 README.mdown
@@ -4,6 +4,12 @@
*This plugin is only compatible with Mac OS X 10.5 and above.*
+## Donations
+
+Like many of you, I do this sort of thing to keep my family warm, clothed, and fed. Every hour I spend on AckMate is an hour that I'm not billing for.
+
+If you find AckMate useful, a small [donation](http://pledgie.com/campaigns/9779) is a great way to show your appreciation.
+
## Binary Installation
* Download the latest release from the [downloads section](http://github.com/protocool/AckMate/downloads)
View
BIN  bundle_extras/ackmateCollapse.pdf
Binary file not shown
View
BIN  bundle_extras/ackmateExpand.pdf
Binary file not shown
View
9 source/controllers/AckMatePlugin.m
@@ -23,6 +23,15 @@ - (id)initWithPlugInController:(id <TMPlugInController>)aController
ackWindows = [[NSMutableDictionary alloc] initWithCapacity:0];
[self installMenuItems];
[self loadPluginPreferences];
+
+ // Load up our bundle images
+ NSBundle* pluginBundle = [NSBundle bundleForClass:[self class]];
+ NSString* collapseImagePath = [pluginBundle pathForResource:@"ackmateCollapse" ofType:@"pdf"];
+ NSImage* collapseImage = [[NSImage alloc] initWithContentsOfFile:collapseImagePath];
+ [collapseImage setName:@"ackmateCollapse"];
+ NSString* expandImagePath = [pluginBundle pathForResource:@"ackmateExpand" ofType:@"pdf"];
+ NSImage* expandImage = [[NSImage alloc] initWithContentsOfFile:expandImagePath];
+ [expandImage setName:@"ackmateExpand"];
}
return self;
}
View
9 source/controllers/JPAckResultSource.h
@@ -3,23 +3,24 @@
#import <Cocoa/Cocoa.h>
-@class JPAckResult;
+@class JPAckResultRep;
@class JPAckWindowController;
+@class JPAckResultTableView;
@interface JPAckResultSource : NSObject {
NSUInteger matchedFiles;
NSUInteger matchedLines;
- NSMutableArray* resultLines;
+ NSMutableArray* resultRows;
NSDictionary* headingAttributes;
NSDictionary* bodyAttributes;
NSDictionary* bodyNowrapAttributes;
NSDictionary* bodyHighlightAttributes;
- IBOutlet NSTableView* resultView;
+ IBOutlet JPAckResultTableView* resultView;
IBOutlet JPAckWindowController* windowController;
- JPAckResult* currentResultFile;
+ JPAckResultRep* currentResultFileRep;
NSString* resultStats;
BOOL searchingSelection;
View
214 source/controllers/JPAckResultSource.m
@@ -4,12 +4,14 @@
#import "JPAckWindowController.h"
#import "JPAckResultSource.h"
#import "JPAckResultRep.h"
+#import "JPAckResultTableView.h"
#import "JPAckResultCell.h"
@interface JPAckResultSource ()
@property(nonatomic, copy) NSString* longestLineNumber;
-@property(nonatomic, retain) NSMutableArray* resultLines;
+@property(nonatomic, retain) NSMutableArray* resultRows;
@property(nonatomic, copy, readwrite) NSString* resultStats;
+- (void)toggleFileRep:(JPAckResultRep*)rep atIndex:(NSInteger)index;
- (void)configureFontAttributes;
- (CGFloat)lineContentWidth;
- (void)adjustForLongestLineNumber:(NSString*)linenumber;
@@ -23,18 +25,18 @@ @implementation JPAckResultSource
@synthesize longestLineNumber;
@synthesize searchRoot;
@synthesize resultStats;
-@synthesize resultLines;
+@synthesize resultRows;
@synthesize matchedFiles;
@synthesize matchedLines;
- (void)awakeFromNib
{
- currentResultFile = nil;
+ currentResultFileRep = nil;
resultStats = nil;
searchRoot = nil;
longestLineNumber = nil;
- self.resultLines = [NSMutableArray array];
+ self.resultRows = [NSMutableArray array];
[resultView setIntercellSpacing:NSMakeSize(0,0)];
@@ -51,9 +53,9 @@ - (void)clearContents
alternateRow = NO;
matchedFiles = 0;
matchedLines = 0;
- currentResultFile = nil;
+ currentResultFileRep = nil;
self.resultStats = nil;
- [self.resultLines removeAllObjects];
+ [self.resultRows removeAllObjects];
[resultView reloadData];
// reset column 0 to be 3 chars wide in the current font
@@ -80,7 +82,7 @@ - (void)parsedError:(NSString*)errorString
{
alternateRow = NO;
JPAckResult* jpar = [JPAckResult resultErrorWithString:errorString];
- [self.resultLines addObject:[JPAckResultRep withResultObject:jpar alternate:alternateRow]];
+ [self.resultRows addObject:[JPAckResultRep withResultObject:jpar alternate:alternateRow]];
[resultView noteNumberOfRowsChanged];
}
@@ -90,8 +92,9 @@ - (void)parsedFilename:(NSString*)filename
matchedFiles++;
[self updateStats];
- currentResultFile = [JPAckResult resultFileWithName:[filename substringFromIndex:[self.searchRoot length]]];
- [self.resultLines addObject:[JPAckResultRep withResultObject:currentResultFile alternate:NO]];
+ JPAckResult* fileResult = [JPAckResult resultFileWithName:[filename substringFromIndex:[self.searchRoot length]]];
+ currentResultFileRep = [JPAckResultRep withResultObject:fileResult alternate:NO];
+ [self.resultRows addObject:currentResultFileRep];
[resultView noteNumberOfRowsChanged];
}
@@ -99,25 +102,33 @@ - (void)parsedContextBreak
{
alternateRow = NO;
JPAckResult* jpar = [JPAckResult resultContextBreak];
- [self.resultLines addObject:[JPAckResultRep withResultObject:jpar alternate:NO]];
- [resultView noteNumberOfRowsChanged];
+ JPAckResultRep* jparrep = [JPAckResultRep withResultObject:jpar parent:currentResultFileRep alternate:NO];
+ if (![currentResultFileRep collapsed])
+ {
+ [self.resultRows addObject:jparrep];
+ [resultView noteNumberOfRowsChanged];
+ }
}
- (void)parsedContextLine:(NSString*)lineNumber content:(NSString*)content
{
- if (currentResultFile)
+ if (currentResultFileRep)
{
JPAckResult* jpar = [JPAckResult resultContextLineWithNumber:lineNumber content:content];
- [self.resultLines addObject:[JPAckResultRep withResultObject:jpar parent:currentResultFile alternate:alternateRow]];
- alternateRow = !alternateRow;
- [resultView noteNumberOfRowsChanged];
+ JPAckResultRep* jparrep = [JPAckResultRep withResultObject:jpar parent:currentResultFileRep alternate:alternateRow];
+ if (![currentResultFileRep collapsed])
+ {
+ [self.resultRows addObject:jparrep];
+ [resultView noteNumberOfRowsChanged];
+ }
[self adjustForLongestLineNumber:lineNumber];
+ alternateRow = !alternateRow;
}
}
- (void)parsedMatchLine:(NSString*)lineNumber ranges:(NSArray*)ranges content:(NSString*)content
{
- if (currentResultFile)
+ if (currentResultFileRep)
{
NSMutableArray* matchRanges = (ranges) ? [NSMutableArray arrayWithCapacity:[ranges count]] : nil;
matchedLines++;
@@ -126,10 +137,14 @@ - (void)parsedMatchLine:(NSString*)lineNumber ranges:(NSArray*)ranges content:(N
[matchRanges addObject:[NSValue valueWithRange:NSRangeFromString(rangeString)]];
JPAckResult* jpar = [JPAckResult resultMatchingLineWithNumber:lineNumber content:content ranges:matchRanges];
- [self.resultLines addObject:[JPAckResultRep withResultObject:jpar parent:currentResultFile alternate:alternateRow]];
- alternateRow = !alternateRow;
- [resultView noteNumberOfRowsChanged];
+ JPAckResultRep* jparrep = [JPAckResultRep withResultObject:jpar parent:currentResultFileRep alternate:alternateRow];
+ if (![currentResultFileRep collapsed])
+ {
+ [self.resultRows addObject:jparrep];
+ [resultView noteNumberOfRowsChanged];
+ }
[self adjustForLongestLineNumber:lineNumber];
+ alternateRow = !alternateRow;
}
}
@@ -155,7 +170,7 @@ - (CGFloat)lineContentWidth
- (NSInteger)tableView:(NSTableView *)tableView spanningColumnForRow:(NSInteger)row
{
- JPAckResultType rt = [[self.resultLines objectAtIndex:row] resultType];
+ JPAckResultType rt = [[self.resultRows objectAtIndex:row] resultType];
if (rt == JPResultTypeFilename || rt == JPResultTypeError)
return 1;
@@ -164,7 +179,7 @@ - (NSInteger)tableView:(NSTableView *)tableView spanningColumnForRow:(NSInteger)
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
- JPAckResultRep* resultRep = [self.resultLines objectAtIndex:row];
+ JPAckResultRep* resultRep = [self.resultRows objectAtIndex:row];
switch([resultRep resultType])
{
@@ -190,23 +205,28 @@ - (BOOL)tableView:(NSTableView *)tableView shouldShowCellExpansionForTableColumn
return NO;
}
-- (BOOL)tableView:(NSTableView *)tableView activateSelectedRow:(NSInteger)row atPoint:(NSPoint)point
+- (BOOL)tableView:(NSTableView *)tableView activateSelectedRow:(NSInteger)row atPoint:(NSPoint)pointHint
{
- JPAckResultRep* rep = [self.resultLines objectAtIndex:row];
+ JPAckResultRep* rep = [self.resultRows objectAtIndex:row];
JPAckResult* resultObject = [rep resultObject];
- if (resultObject.resultType == JPResultTypeContext || resultObject.resultType == JPResultTypeMatchingLine)
+ if (resultObject.resultType == JPResultTypeFilename)
{
- NSString* filenameToOpen = [[rep parentObject] lineContent];
+ [self toggleFileRep:rep atIndex:row];
+ return YES;
+ }
+ else if (resultObject.resultType == JPResultTypeContext || resultObject.resultType == JPResultTypeMatchingLine)
+ {
+ NSString* filenameToOpen = [[[rep parentObject] resultObject] lineContent];
NSRange selectionRange = NSMakeRange(0,0);
// I feel like such a bandit... oh well.
- if (NSPointInRect(point, [tableView frameOfCellAtColumn:1 row:row]) && [resultObject matchRanges])
+ if (NSPointInRect(pointHint, [tableView frameOfCellAtColumn:1 row:row]) && [resultObject matchRanges])
{
// Quickly load up the field editor so we can find out where the click was
[tableView editColumn:1 row:row withEvent:nil select:NO];
NSTextView* tv = (NSTextView*)[tableView currentEditor];
- NSPoint adjustedPoint = [tv convertPoint:point fromView:tableView];
+ NSPoint adjustedPoint = [tv convertPoint:pointHint fromView:tableView];
NSUInteger clickIndex = [tv characterIndexForInsertionAtPoint:adjustedPoint];
NSRange closestRange = NSMakeRange(NSNotFound, 0);
@@ -251,18 +271,18 @@ - (BOOL)tableView:(NSTableView *)tableView activateSelectedRow:(NSInteger)row at
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row
{
- JPAckResultType itemtype = [[self.resultLines objectAtIndex:row] resultType];
- return (itemtype == JPResultTypeMatchingLine || itemtype == JPResultTypeContext);
+ JPAckResultType itemtype = [[self.resultRows objectAtIndex:row] resultType];
+ return ((itemtype == JPResultTypeMatchingLine || itemtype == JPResultTypeContext) && !([[NSApp currentEvent] modifierFlags] & NSControlKeyMask));
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
- return [self.resultLines count];
+ return [self.resultRows count];
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
- JPAckResultRep* rep = [self.resultLines objectAtIndex:row];
+ JPAckResultRep* rep = [self.resultRows objectAtIndex:row];
JPAckResultType resultType = [rep resultType];
id value = nil;
@@ -297,13 +317,13 @@ - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColum
- (BOOL)tableView:(NSTableView *)tableView isStickyRow:(NSInteger)row
{
- return ([[self.resultLines objectAtIndex:row] resultType] == JPResultTypeFilename);
+ return ([[self.resultRows objectAtIndex:row] resultType] == JPResultTypeFilename);
}
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)row
{
- JPAckResultRep* rep = [self.resultLines objectAtIndex:row];
- [(JPAckResultCell*)aCell configureType:[rep resultType] alternate:[rep alternate] contentColumn:([aTableColumn identifier] != amLineNumberColumn)];
+ JPAckResultRep* rep = [self.resultRows objectAtIndex:row];
+ [(JPAckResultCell*)aCell configureType:[rep resultType] alternate:[rep alternate] collapsed:[rep collapsed] contentColumn:([aTableColumn identifier] != amLineNumberColumn)];
}
- (BOOL)tableView:(NSTableView *)tableView shouldTrackCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
@@ -319,6 +339,130 @@ - (BOOL)tableView:(NSTableView*)tableView shouldEditTableColumn:(NSTableColumn*)
return NO;
}
+- (NSMenu*)tableView:(NSTableView *)tableView contextMenuForRow:(NSInteger)row;
+{
+ JPAckResultRep* clickRep = [self.resultRows objectAtIndex:row];
+ JPAckResultRep* fileRep = [clickRep parentObject] ? [clickRep parentObject] : clickRep;
+
+ if ([fileRep resultType] != JPResultTypeFilename)
+ return nil;
+
+ NSMenu* mfe = [[[NSMenu alloc] initWithTitle:@""] autorelease];
+ NSString* fileName = [[[fileRep resultObject] lineContent] lastPathComponent];
+ NSString* title = [NSString stringWithFormat:@"%@ %@", ([fileRep collapsed]) ? @"Expand" : @"Collapse", fileName];
+ NSMenuItem *toggleThis = [[[NSMenuItem alloc] initWithTitle:title action:@selector(toggleCollapsingItem:) keyEquivalent:@""] autorelease];
+ [toggleThis setTarget:self];
+ [toggleThis setRepresentedObject:fileRep];
+ [mfe addItem:toggleThis];
+ [mfe addItem:[NSMenuItem separatorItem]];
+
+ NSMenuItem *expandAll = [[[NSMenuItem alloc] initWithTitle:@"Expand All" action:@selector(expandAll:) keyEquivalent:@""] autorelease];
+ [expandAll setTarget:self];
+ [expandAll setRepresentedObject:fileRep];
+ [mfe addItem:expandAll];
+ NSMenuItem *collapseAll = [[[NSMenuItem alloc] initWithTitle:@"Collapse All" action:@selector(collapseAll:) keyEquivalent:@""] autorelease];
+ [collapseAll setTarget:self];
+ [collapseAll setRepresentedObject:fileRep];
+ [mfe addItem:collapseAll];
+
+ return mfe;
+}
+
+- (void)toggleCollapsingItem:(id)sender
+{
+ JPAckResultRep* rep = [sender representedObject];
+ NSUInteger repindex = [self.resultRows indexOfObject:rep];
+ if (repindex == NSNotFound)
+ return;
+ [self toggleFileRep:rep atIndex:repindex];
+}
+
+- (void)toggleFileRep:(JPAckResultRep*)rep atIndex:(NSInteger)index
+{
+ NSInteger selRow = [resultView selectedRow];
+ NSIndexSet* effectiveSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(index + 1, [[rep children] count])];
+
+ if ([rep collapsed])
+ [self.resultRows insertObjects:[rep children] atIndexes:effectiveSet];
+ else
+ [self.resultRows removeObjectsAtIndexes:effectiveSet];
+
+ [resultView noteNumberOfRowsChanged];
+
+ if (![rep collapsed]) // as in, not marked as collapsed yet - so we *removed* rows
+ {
+ if (selRow != -1 && selRow > [effectiveSet lastIndex])
+ [resultView selectRowIndexes:[NSIndexSet indexSetWithIndex:(selRow - [[rep children] count])] byExtendingSelection:NO];
+ else if (selRow != -1 && [effectiveSet containsIndex:selRow])
+ [resultView deselectAll:self];
+ }
+ else if (selRow != -1 && selRow > index) // we expanded, do we need to shuffle selection along?
+ [resultView selectRowIndexes:[NSIndexSet indexSetWithIndex:(selRow + [[rep children] count])] byExtendingSelection:NO];
+
+ [rep setCollapsed:![rep collapsed]]; // *now* it's okay to flip the state
+ [resultView scrollRowToVisible:index];
+}
+
+- (void)collapseAll:(id)sender
+{
+ NSUInteger contextRow = [self.resultRows indexOfObject:[sender representedObject]];
+ CGFloat contextOffset = 0.0;
+ if (contextRow != NSNotFound)
+ contextOffset = [resultView viewportOffsetForRow:contextRow];
+
+ NSMutableArray* collapsedResults = [NSMutableArray array];
+ for (JPAckResultRep* rep in self.resultRows)
+ {
+ if (![rep parentObject]) {
+ [collapsedResults addObject:rep];
+ [rep setCollapsed:YES];
+ }
+ }
+ [resultView deselectAll:self];
+ self.resultRows = collapsedResults;
+ [resultView noteNumberOfRowsChanged];
+
+ contextRow = [self.resultRows indexOfObject:[sender representedObject]];
+ if (contextRow != NSNotFound)
+ [resultView scrollRowToVisible:contextRow withViewportOffset:contextOffset];
+}
+
+- (void)expandAll:(id)sender
+{
+ NSUInteger contextRow = [self.resultRows indexOfObject:[sender representedObject]];
+ CGFloat contextOffset = 0.0;
+ if (contextRow != NSNotFound)
+ contextOffset = [resultView viewportOffsetForRow:contextRow];
+
+ JPAckResultRep* selectedRep = nil;
+ NSInteger selRow = [resultView selectedRow];
+ if (selRow != -1)
+ selectedRep = [self.resultRows objectAtIndex:selRow];
+
+ NSMutableArray* expandedResults = [NSMutableArray array];
+ for (JPAckResultRep* rep in self.resultRows)
+ {
+ [expandedResults addObject:rep];
+ if (![rep parentObject] && [rep collapsed]) {
+ [rep setCollapsed:NO];
+ [expandedResults addObjectsFromArray:[rep children]];
+ }
+ }
+ self.resultRows = expandedResults;
+ [resultView noteNumberOfRowsChanged];
+
+ if (selectedRep) // restore previous selection
+ {
+ NSUInteger newIndex = [self.resultRows indexOfObject:selectedRep];
+ if (newIndex != NSNotFound)
+ [resultView selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex] byExtendingSelection:NO];
+ }
+
+ contextRow = [self.resultRows indexOfObject:[sender representedObject]];
+ if (contextRow != NSNotFound)
+ [resultView scrollRowToVisible:contextRow withViewportOffset:contextOffset];
+}
+
- (void)configureFontAttributes
{
NSFontManager* fm = [NSFontManager sharedFontManager];
@@ -384,7 +528,7 @@ - (void)dealloc
{
[searchRoot release], searchRoot = nil;
[resultStats release], resultStats = nil;
- [resultLines release], resultLines = nil;
+ [resultRows release], resultRows = nil;
[longestLineNumber release], longestLineNumber = nil;
[headingAttributes release], headingAttributes = nil;
View
11 source/external/NSTableView+NoodleExtensions.h
@@ -53,7 +53,10 @@ enum
Does an animated scroll to the current sticky row. Clicking on the sticky
row header will trigger this.
*/
-- (IBAction)scrollToStickyRow:(id)sender;
+- (IBAction)peformClickOnStickyRow:(id)sender;
+
+// subclass overrides for custom handling
+- (void)clickedStickyRow:(NSInteger)row;
/*
Returns what kind of transition you want when the row becomes sticky. Fade-in
@@ -103,6 +106,9 @@ enum
@interface NSObject (NoodleStickyRowDelegate)
+// So that the sticky header also shows context menus
+- (NSMenu*)tableView:(NSTableView *)tableView contextMenuForRow:(NSInteger)rowIndex;
+
/*
Allows the delegate to specify if a row is sticky. By default, group rows
are sticky. The delegate can override that by implementing this method.
@@ -121,3 +127,6 @@ enum
@end
+@interface StickyRowButton : NSButton {
+}
+@end
View
31 source/external/NSTableView+NoodleExtensions.m
@@ -74,17 +74,34 @@ - (void)drawStickyRowHeader
}
}
-- (IBAction)scrollToStickyRow:(id)sender
+- (IBAction)peformClickOnStickyRow:(id)sender
{
NSInteger row;
row = [self _previousStickyRow];
if (row != -1)
{
- [self scrollRowToVisible:row];
+ [self clickedStickyRow:row];
}
}
+- (void)clickedStickyRow:(NSInteger)row
+{
+ [self scrollRowToVisible:row];
+}
+
+- (NSMenu*)contextMenuForStickyRow:(id)sender
+{
+ NSInteger row;
+
+ row = [self _previousStickyRow];
+ if (row != -1)
+ {
+ return [[self delegate] tableView:self contextMenuForRow:row];
+ }
+ return nil;
+}
+
- (id)_stickyRowHeaderView
{
NSButton *view;
@@ -93,7 +110,7 @@ - (id)_stickyRowHeaderView
if (view == nil)
{
- view = [[NSButton alloc] initWithFrame:NSZeroRect];
+ view = [[StickyRowButton alloc] initWithFrame:NSZeroRect];
[view setEnabled:YES];
[view setBordered:NO];
[view setImagePosition:NSImageOnly];
@@ -106,7 +123,7 @@ - (id)_stickyRowHeaderView
[view setTag:NOODLE_STICKY_ROW_VIEW_TAG];
[view setTarget:self];
- [view setAction:@selector(scrollToStickyRow:)];
+ [view setAction:@selector(peformClickOnStickyRow:)];
[self addSubview:view];
[view release];
@@ -449,3 +466,9 @@ - (BOOL)isRowSticky:(NSInteger)rowIndex
@end
+@implementation StickyRowButton
+- (NSMenu*)menuForEvent:(NSEvent*)event
+{
+ return [[self target] contextMenuForStickyRow:self];
+}
+@end
View
14 source/models/JPAckResultRep.h
@@ -5,22 +5,28 @@
#import "JPAckResult.h"
@interface JPAckResultRep: NSObject {
- JPAckResult* parentObject;
+ JPAckResultRep* parentObject;
JPAckResult* resultObject;
-
+ NSMutableArray* childObjects;
+
CGFloat constrainedWidth;
CGFloat calculatedHeight;
BOOL alternate;
+ BOOL collapsed;
}
-@property(nonatomic, readonly) JPAckResult* parentObject;
+@property(nonatomic, readonly) JPAckResultRep* parentObject;
@property(nonatomic, readonly) JPAckResult* resultObject;
@property(nonatomic, assign) CGFloat constrainedWidth;
@property(nonatomic, assign) CGFloat calculatedHeight;
@property(nonatomic, readonly) BOOL alternate;
+@property(nonatomic, assign) BOOL collapsed;
-+ (id)withResultObject:(JPAckResult*)ro parent:(JPAckResult*)po alternate:(BOOL)alt;
++ (id)withResultObject:(JPAckResult*)ro parent:(JPAckResultRep*)po alternate:(BOOL)alt;
+ (id)withResultObject:(JPAckResult*)ro alternate:(BOOL)alt;
+- (NSArray*)children;
+- (void)addChild:(JPAckResultRep*)childObject;
+
- (JPAckResultType)resultType;
@end
View
24 source/models/JPAckResultRep.m
@@ -4,7 +4,7 @@
#import "JPAckResultRep.h"
@interface JPAckResultRep ()
-- (id)initWithResultObject:(JPAckResult*)resultObject_ parent:(JPAckResult*)parentObject_ alternate:(BOOL)alternate_;
+- (id)initWithResultObject:(JPAckResult*)resultObject_ parent:(JPAckResultRep*)parentObject_ alternate:(BOOL)alternate_;
@end;
@implementation JPAckResultRep
@@ -14,8 +14,9 @@ @implementation JPAckResultRep
@synthesize constrainedWidth;
@synthesize calculatedHeight;
@synthesize alternate;
+@synthesize collapsed;
-+ (id)withResultObject:(JPAckResult*)ro parent:(JPAckResult*)po alternate:(BOOL)alt
++ (id)withResultObject:(JPAckResult*)ro parent:(JPAckResultRep*)po alternate:(BOOL)alt
{
return [[[JPAckResultRep alloc] initWithResultObject:ro parent:po alternate:alt] autorelease];
}
@@ -25,13 +26,16 @@ + (id)withResultObject:(JPAckResult*)ro alternate:(BOOL)alt
return [[[JPAckResultRep alloc] initWithResultObject:ro parent:nil alternate:alt] autorelease];
}
-- (id)initWithResultObject:(JPAckResult*)resultObject_ parent:(JPAckResult*)parentObject_ alternate:(BOOL)alternate_
+- (id)initWithResultObject:(JPAckResult*)resultObject_ parent:(JPAckResultRep*)parentObject_ alternate:(BOOL)alternate_
{
if (self = [super init])
{
parentObject = [parentObject_ retain];
resultObject = [resultObject_ retain];
alternate = alternate_;
+
+ if (parentObject)
+ [parentObject addChild:self];
}
return self;
}
@@ -46,10 +50,24 @@ - (JPAckResultType)resultType
return resultObject.resultType;
}
+- (NSArray*)children
+{
+ return childObjects;
+}
+
+- (void)addChild:(JPAckResultRep*)childObject
+{
+ if (!childObjects)
+ childObjects = [[NSMutableArray alloc] initWithCapacity:1];
+
+ [childObjects addObject:childObject];
+}
+
- (void)dealloc
{
[parentObject release], parentObject = nil;
[resultObject release], resultObject = nil;
+ [childObjects release], childObjects = nil;
[super dealloc];
}
View
6 source/views/JPAckResultCell.h
@@ -4,6 +4,9 @@
#import <Cocoa/Cocoa.h>
#import "JPAckResultRep.h"
+// disclosure triangle size
+#define DISCLOSURE_TRIANGLE_DIMENSION 16
+
// left/right padding for the cell
#define RESULT_ROW_PADDING 15.0
@@ -24,8 +27,9 @@
JPAckResultType resultType;
BOOL alternate;
BOOL contentColumn;
+ BOOL collapsed;
CGFloat lineNumberWidth;
}
--(void)configureType:(JPAckResultType)resultType_ alternate:(BOOL)alternate_ contentColumn:(BOOL)contentColumn_;
+-(void)configureType:(JPAckResultType)resultType_ alternate:(BOOL)alternate_ collapsed:(BOOL)collapsed_ contentColumn:(BOOL)contentColumn_;
@end
View
15 source/views/JPAckResultCell.m
@@ -5,6 +5,7 @@
#import "JPAckResultTableView.h"
#import "JPAckResultRep.h"
#import "SDFoundation.h"
+#import "NSImage-NoodleExtensions.h"
@interface JPAckResultCell ()
- (void)drawFillWithFrame:(NSRect)cellFrame inView:(NSView*)controlView;
@@ -48,6 +49,14 @@ - (void)drawFillWithFrame:(NSRect)cellFrame inView:(NSView*)controlView
NSRectFill(lcrect);
}
+ // After the fill has been drawn, blat the disclosure triangle on there
+ if (contentColumn && resultType == JPResultTypeFilename)
+ {
+ NSPoint imageOrigin = lcrect.origin;
+ imageOrigin.x += RESULT_CONTENT_INTERIOR_PADDING;
+ imageOrigin.y += ceil((lcrect.size.height - DISCLOSURE_TRIANGLE_DIMENSION) / 2);
+ [[NSImage imageNamed:(collapsed) ? @"ackmateExpand" : @"ackmateCollapse"] drawAdjustedAtPoint:imageOrigin fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
+ }
}
- (NSColor*)highlightColorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView
@@ -97,17 +106,21 @@ - (NSRect)drawingRectForBounds:(NSRect)theRect honestly:(BOOL)honestly
if (honestly) return drect;
if(resultType == JPResultTypeFilename)
+ {
+ SDDivideRect(drect, nil, &drect, DISCLOSURE_TRIANGLE_DIMENSION, NSMinXEdge);
SDDivideRect(drect, nil, &drect, RESULT_ROW_PADDING, NSMinYEdge);
+ }
return NSInsetRect(drect, RESULT_CONTENT_INTERIOR_PADDING, RESULT_TEXT_YINSET);
}
--(void)configureType:(JPAckResultType)resultType_ alternate:(BOOL)alternate_ contentColumn:(BOOL)contentColumn_
+-(void)configureType:(JPAckResultType)resultType_ alternate:(BOOL)alternate_ collapsed:(BOOL)collapsed_ contentColumn:(BOOL)contentColumn_
{
resultType = resultType_;
alternate = alternate_;
contentColumn = contentColumn_;
+ collapsed = collapsed_;
if (resultType == JPResultTypeMatchingLine || resultType == JPResultTypeFilename || resultType == JPResultTypeError)
[self setTextColor:[NSColor controlTextColor]];
View
3  source/views/JPAckResultTableView.h
@@ -8,7 +8,8 @@
}
- (NSInteger)spanningColumnForRow:(NSInteger)rowIndex;
-
+- (CGFloat)viewportOffsetForRow:(NSInteger)rowIndex;
+- (void)scrollRowToVisible:(NSInteger)rowIndex withViewportOffset:(CGFloat)offset;
@end
@interface NSObject (JPAckResultTableViewDelegate)
View
54 source/views/JPAckResultTableView.m
@@ -9,6 +9,7 @@
@interface JPAckResultTableView ()
- (void)activationAction:(id)sender;
- (BOOL)activateRow:(NSInteger)row atPoint:(NSPoint)point;
+- (NSInteger)rowTrulyAtPoint:(NSPoint)point;
@end
@implementation JPAckResultTableView
@@ -21,11 +22,19 @@ - (void)awakeFromNib
- (void)activationAction:(id)sender
{
- NSInteger crow = [self clickedRow];
+ if ([[NSApp currentEvent] modifierFlags] & NSControlKeyMask)
+ return; // never for context menu
+
NSPoint mouseLocation = [self convertPoint:[[self window] convertScreenToBase:[NSEvent mouseLocation]] fromView:nil];
+ NSInteger row = [self rowTrulyAtPoint:mouseLocation];
+
+ if (row == NSNotFound)
+ return;
- if (crow != -1 && [self isRowSelected:crow] && NSPointInRect(mouseLocation, [self rectOfRow:crow]))
- [self activateRow:crow atPoint:mouseLocation];
+ if ([[self delegate] tableView:self isStickyRow:row])
+ [self clickedStickyRow:row];
+ else if ([self isRowSelected:row])
+ [self activateRow:row atPoint:mouseLocation];
}
- (BOOL)activateRow:(NSInteger)row atPoint:(NSPoint)point;
@@ -37,6 +46,33 @@ - (BOOL)activateRow:(NSInteger)row atPoint:(NSPoint)point;
return NO;
}
+- (void)clickedStickyRow:(NSInteger)row
+{
+ [[self delegate] tableView:self activateSelectedRow:row atPoint:NSMakePoint(0,0)]; //dummy point hint - sticky row was clicked, not the real row
+}
+
+- (NSInteger)rowTrulyAtPoint:(NSPoint)point
+{
+ NSInteger mouseRow = [self rowAtPoint:point];
+ if (mouseRow == NSNotFound)
+ return NSNotFound;
+
+ NSRect rowRect = NSIntersectionRect([self rectOfRow:mouseRow], [self visibleRect]);
+
+ if (NSMouseInRect(point, rowRect, [self isFlipped]))
+ return mouseRow;
+
+ return NSNotFound;
+}
+
+- (NSMenu*)menuForEvent:(NSEvent*)event
+{
+ NSPoint mousePoint = [self convertPoint:[event locationInWindow] fromView:nil];
+ NSInteger row = [self rowTrulyAtPoint:mousePoint];
+
+ return (row != NSNotFound) ? [[self delegate] tableView:self contextMenuForRow:row] : nil;
+}
+
- (void)sizeLastColumnToFit
{
// Brute-force the column resizing - blech.
@@ -97,6 +133,18 @@ - (void)setFrameSize:(NSSize)newSize
[self noteHeightOfRowsWithIndexesChanged:refreshIndexes];
}
+- (CGFloat)viewportOffsetForRow:(NSInteger)rowIndex
+{
+ return [self rectOfRow:rowIndex].origin.y - [self visibleRect].origin.y;
+}
+
+- (void)scrollRowToVisible:(NSInteger)rowIndex withViewportOffset:(CGFloat)offset
+{
+ NSPoint sp = [self rectOfRow:rowIndex].origin;
+ sp.y -= ((offset > 0.0) ? offset : 0);
+ [self scrollPoint:sp];
+}
+
- (void)viewDidEndLiveResize
{
NSIndexSet* refreshIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self numberOfRows])];
Please sign in to comment.
Something went wrong with that request. Please try again.