Revision: 2690
http://skim-app.svn.sourceforge.net/skim-app/?rev=2690&view=rev
Author: hofman
Date: 2007-08-21 07:20:35 -0700 (Tue, 21 Aug 2007)
Log Message:
-----------
Implement type-select for thumbnail tableview and note outlineviews.
Modified Paths:
--------------
trunk/SKMainWindowController.m
trunk/SKNoteOutlineView.h
trunk/SKNoteOutlineView.m
trunk/SKNotesDocument.m
trunk/SKThumbnailTableView.h
trunk/SKThumbnailTableView.m
trunk/Skim.xcodeproj/project.pbxproj
Added Paths:
-----------
trunk/SKTypeSelectHelper.h
trunk/SKTypeSelectHelper.m
Modified: trunk/SKMainWindowController.m
===================================================================
--- trunk/SKMainWindowController.m 2007-08-20 18:21:29 UTC (rev 2689)
+++ trunk/SKMainWindowController.m 2007-08-21 14:20:35 UTC (rev 2690)
@@ -77,6 +77,7 @@
#import "SKColorSwatch.h"
#import "SKStatusBar.h"
#import "SKTransitionController.h"
+#import "SKTypeSelectHelper.h"
#define SEGMENTED_CONTROL_HEIGHT 25.0
#define WINDOW_X_DELTA 0.0
@@ -371,6 +372,18 @@
[self showSnapshotAtPageNumber:[[setup objectForKey:@"page"]
unsignedIntValue] forRect:NSRectFromString([setup objectForKey:@"rect"])
factor:[[setup objectForKey:@"scaleFactor"] floatValue] autoFits:[[setup
objectForKey:@"autoFits"] boolValue] display:[[setup objectForKey:@"hasWindow"]
boolValue]];
}
+ // typeSelectHelpers
+ SKTypeSelectHelper *typeSelectHelper = [[[SKTypeSelectHelper alloc] init]
autorelease];
+ [typeSelectHelper setMatchesImmediately:NO];
+ [typeSelectHelper setMatchOption:SKFullStringMatch];
+ [typeSelectHelper setDataSource:self];
+ [thumbnailTableView setTypeSelectHelper:typeSelectHelper];
+
+ typeSelectHelper = [[[SKTypeSelectHelper alloc] init] autorelease];
+ [typeSelectHelper setMatchOption:SKSubstringMatch];
+ [typeSelectHelper setDataSource:self];
+ [noteOutlineView setTypeSelectHelper:typeSelectHelper];
+
// This update toolbar item and other states
[self handleChangedHistoryNotification:nil];
[self handlePageChangedNotification:nil];
@@ -780,6 +793,7 @@
[pageLabels addObject:label ? label : @""];
}
[self didChangeValueForKey:@"pageLabels"];
+ [[thumbnailTableView typeSelectHelper] rebuildTypeSelectSearchCache];
NSEnumerator *setupEnum = [snapshotDicts objectEnumerator];
NSDictionary *setup;
@@ -3516,6 +3530,35 @@
return menu;
}
+#pragma mark SKTypeSelectHelper datasource protocol
+
+- (NSArray *)typeSelectHelperSelectionItems:(SKTypeSelectHelper
*)typeSelectHelper {
+ if ([typeSelectHelper isEqual:[thumbnailTableView typeSelectHelper]]) {
+ return pageLabels;
+ } else if ([typeSelectHelper isEqual:[noteOutlineView typeSelectHelper]]) {
+ return [[noteArrayController arrangedObjects] valueForKey:@"contents"];
+ }
+ return nil;
+}
+
+- (unsigned int)typeSelectHelperCurrentlySelectedIndex:(SKTypeSelectHelper
*)typeSelectHelper {
+ if ([typeSelectHelper isEqual:[thumbnailTableView typeSelectHelper]]) {
+ return [[thumbnailTableView selectedRowIndexes] lastIndex];
+ } else if ([typeSelectHelper isEqual:[noteOutlineView typeSelectHelper]]) {
+ return [[noteArrayController arrangedObjects] indexOfObject:[self
selectedNote]];
+ }
+ return NSNotFound;
+}
+
+- (void)typeSelectHelper:(SKTypeSelectHelper *)typeSelectHelper
selectItemAtIndex:(unsigned int)itemIndex {
+ if ([typeSelectHelper isEqual:[thumbnailTableView typeSelectHelper]]) {
+ [self setPageNumber:itemIndex + 1];
+ } else if ([typeSelectHelper isEqual:[noteOutlineView typeSelectHelper]]) {
+ int row = [noteOutlineView rowForItem:[[noteArrayController
arrangedObjects] objectAtIndex:itemIndex]];
+ [noteOutlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:row]
byExtendingSelection:NO];
+ }
+}
+
#pragma mark Outline
- (int)outlineRowForPageIndex:(unsigned int)pageIndex {
Modified: trunk/SKNoteOutlineView.h
===================================================================
--- trunk/SKNoteOutlineView.h 2007-08-20 18:21:29 UTC (rev 2689)
+++ trunk/SKNoteOutlineView.h 2007-08-21 14:20:35 UTC (rev 2690)
@@ -38,10 +38,12 @@
#import <Cocoa/Cocoa.h>
[EMAIL PROTECTED] SKTypeSelectHelper;
@interface SKNoteOutlineView : NSOutlineView {
IBOutlet NSWindow *noteTypeSheet;
IBOutlet NSMatrix *noteTypeMatrix;
+ SKTypeSelectHelper *typeSelectHelper;
}
- (NSArray *)noteTypes;
@@ -53,6 +55,9 @@
- (IBAction)selectNoteTypes:(id)sender;
- (IBAction)dismissNoteTypeSheet:(id)sender;
+- (SKTypeSelectHelper *)typeSelectHelper;
+- (void)setTypeSelectHelper:(SKTypeSelectHelper *)newTypeSelectHelper;
+
@end
Modified: trunk/SKNoteOutlineView.m
===================================================================
--- trunk/SKNoteOutlineView.m 2007-08-20 18:21:29 UTC (rev 2689)
+++ trunk/SKNoteOutlineView.m 2007-08-21 14:20:35 UTC (rev 2690)
@@ -39,11 +39,14 @@
#import "SKNoteOutlineView.h"
#import <Quartz/Quartz.h>
#import "NSString_SKExtensions.h"
+#import "SKTypeSelectHelper.h"
@implementation SKNoteOutlineView
- (void)dealloc {
+ [typeSelectHelper setDataSource:nil];
+ [typeSelectHelper release];
[noteTypeSheet release];
[super dealloc];
}
@@ -52,6 +55,22 @@
[self noteTypeMenu]; // this sets the menu for the header view
}
+- (SKTypeSelectHelper *)typeSelectHelper {
+ return typeSelectHelper;
+}
+
+- (void)setTypeSelectHelper:(SKTypeSelectHelper *)newTypeSelectHelper {
+ if (typeSelectHelper != newTypeSelectHelper) {
+ [typeSelectHelper release];
+ typeSelectHelper = [newTypeSelectHelper retain];
+ }
+}
+
+- (void)reloadData{
+ [super reloadData];
+ [typeSelectHelper rebuildTypeSelectSearchCache];
+}
+
- (void)delete:(id)sender {
if ([[self delegate]
respondsToSelector:@selector(outlineViewDeleteSelectedRows:)]) {
if ([[self selectedRowIndexes] count] == 0)
@@ -68,6 +87,8 @@
if ((eventChar == NSDeleteCharacter || eventChar ==
NSDeleteFunctionKey) && modifiers == 0)
[self delete:self];
+ else if (typeSelectHelper && modifiers == 0 && [[NSCharacterSet
alphanumericCharacterSet] characterIsMember:eventChar])
+ [typeSelectHelper processKeyDownCharacter:eventChar];
else
[super keyDown:theEvent];
}
Modified: trunk/SKNotesDocument.m
===================================================================
--- trunk/SKNotesDocument.m 2007-08-20 18:21:29 UTC (rev 2689)
+++ trunk/SKNotesDocument.m 2007-08-21 14:20:35 UTC (rev 2690)
@@ -45,6 +45,8 @@
#import "SKApplicationController.h"
#import "NSValue_SKExtensions.h"
#import "NSString_SKExtensions.h"
+#import "SKTypeSelectHelper.h"
+#import "SKPDFAnnotationNote.h"
@implementation SKNotesDocument
@@ -71,6 +73,11 @@
NSSortDescriptor *contentsSortDescriptor = [[[NSSortDescriptor alloc]
initWithKey:@"contents" ascending:YES
selector:@selector(localizedCaseInsensitiveNumericCompare:)] autorelease];
[arrayController setSortDescriptors:[NSArray
arrayWithObjects:indexSortDescriptor, contentsSortDescriptor, nil]];
[outlineView reloadData];
+
+ SKTypeSelectHelper *typeSelectHelper = [[[SKTypeSelectHelper alloc] init]
autorelease];
+ [typeSelectHelper setMatchOption:SKSubstringMatch];
+ [typeSelectHelper setDataSource:self];
+ [outlineView setTypeSelectHelper:typeSelectHelper];
}
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
@@ -319,4 +326,28 @@
return [item valueForKey:@"type"] ? [item valueForKey:@"contents"] :
[[item valueForKey:@"contents"] string];
}
+#pragma mark SKTypeSelectHelper datasource protocol
+
+- (NSArray *)typeSelectHelperSelectionItems:(SKTypeSelectHelper
*)typeSelectHelper {
+ return [[arrayController arrangedObjects] valueForKey:@"contents"];
+}
+
+- (unsigned int)typeSelectHelperCurrentlySelectedIndex:(SKTypeSelectHelper
*)typeSelectHelper {
+ NSArray *arrangedNotes = [arrayController arrangedObjects];
+ int row = [outlineView selectedRow];
+ id item = nil;
+ if (row == -1)
+ return NSNotFound;
+ item = [outlineView itemAtRow:row];
+ if ([item valueForKey:@"type"])
+ return [arrangedNotes indexOfObject:item];
+ else
+ return [[arrangedNotes valueForKey:@"child"] indexOfObject:item];
+}
+
+- (void)typeSelectHelper:(SKTypeSelectHelper *)typeSelectHelper
selectItemAtIndex:(unsigned int)itemIndex {
+ int row = [outlineView rowForItem:[[arrayController arrangedObjects]
objectAtIndex:itemIndex]];
+ [outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:row]
byExtendingSelection:NO];
+}
+
@end
Modified: trunk/SKThumbnailTableView.h
===================================================================
--- trunk/SKThumbnailTableView.h 2007-08-20 18:21:29 UTC (rev 2689)
+++ trunk/SKThumbnailTableView.h 2007-08-21 14:20:35 UTC (rev 2690)
@@ -39,12 +39,20 @@
#import <Cocoa/Cocoa.h>
[EMAIL PROTECTED] SKTypeSelectHelper;
+
@interface SKThumbnailTableView : NSTableView
{
BOOL isScrolling;
+ SKTypeSelectHelper *typeSelectHelper;
}
+
- (BOOL)isScrolling;
- (BOOL)canCopy;
+
+- (SKTypeSelectHelper *)typeSelectHelper;
+- (void)setTypeSelectHelper:(SKTypeSelectHelper *)newTypeSelectHelper;
+
@end
Modified: trunk/SKThumbnailTableView.m
===================================================================
--- trunk/SKThumbnailTableView.m 2007-08-20 18:21:29 UTC (rev 2689)
+++ trunk/SKThumbnailTableView.m 2007-08-21 14:20:35 UTC (rev 2690)
@@ -38,6 +38,7 @@
#import "SKThumbnailTableView.h"
#import "OBUtilities.h"
+#import "SKTypeSelectHelper.h"
static NSString *SKScrollerWillScrollNotification =
@"SKScrollerWillScrollNotification";
static NSString *SKScrollerDidScrollNotification =
@"SKScrollerDidScrollNotification";
@@ -66,6 +67,8 @@
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
+ [typeSelectHelper setDataSource:nil];
+ [typeSelectHelper release];
[super dealloc];
}
@@ -122,6 +125,34 @@
[super highlightSelectionInClipRect:clipRect];
}
+- (SKTypeSelectHelper *)typeSelectHelper {
+ return typeSelectHelper;
+}
+
+- (void)setTypeSelectHelper:(SKTypeSelectHelper *)newTypeSelectHelper {
+ if (typeSelectHelper != newTypeSelectHelper) {
+ [typeSelectHelper release];
+ typeSelectHelper = [newTypeSelectHelper retain];
+ }
+}
+
+- (void)reloadData{
+ [super reloadData];
+ [typeSelectHelper rebuildTypeSelectSearchCache];
+}
+
+- (void)keyDown:(NSEvent *)theEvent {
+ NSString *characters = [theEvent charactersIgnoringModifiers];
+ unichar eventChar = [characters length] > 0 ? [characters
characterAtIndex:0] : 0;
+ unsigned modifierFlags = [theEvent modifierFlags] &
NSDeviceIndependentModifierFlagsMask;
+
+ if (typeSelectHelper && modifierFlags == 0 && [[NSCharacterSet
alphanumericCharacterSet] characterIsMember:eventChar]) {
+ [typeSelectHelper processKeyDownCharacter:eventChar];
+ } else {
+ [super keyDown:theEvent];
+ }
+}
+
- (void)mouseDown:(NSEvent *)theEvent {
if (([theEvent modifierFlags] & NSCommandKeyMask) && [[self delegate]
respondsToSelector:@selector(tableView:commandSelectRow:)]) {
int row = [self rowAtPoint:[self convertPoint:[theEvent
locationInWindow] fromView:nil]];
Added: trunk/SKTypeSelectHelper.h
===================================================================
--- trunk/SKTypeSelectHelper.h (rev 0)
+++ trunk/SKTypeSelectHelper.h 2007-08-21 14:20:35 UTC (rev 2690)
@@ -0,0 +1,88 @@
+//
+// SKTypeSelectHelper.h
+// Skim
+//
+// Created by Christiaan Hofman on 8/21/07.
+/*
+ This software is Copyright (c) 2007
+ Christiaan Hofman. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ - Neither the name of Christiaan Hofman nor the names of any
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+
+enum {
+ SKPrefixMatch,
+ SKSubstringMatch,
+ SKFullStringMatch
+};
+
[EMAIL PROTECTED] SKTypeSelectHelper : NSObject {
+ id dataSource;
+ BOOL cycleResults;
+ int matchOption;
+ BOOL matchesImmediately;
+
+ NSArray *searchCache;
+ NSMutableString *searchString;
+ NSTimer *timer;
+}
+
+- (id)dataSource;
+- (void)setDataSource:(id)anObject;
+
+- (BOOL)cyclesSimilarResults;
+- (void)setCyclesSimilarResults:(BOOL)newValue;
+
+- (BOOL)matchesImmediately;
+- (void)setMatchesImmediately:(BOOL)newValue;
+
+- (int)matchOption;
+- (void)setMatchOption:(int)newValue;
+
+- (void)rebuildTypeSelectSearchCache;
+
+- (BOOL)isProcessing;
+
+- (void)processKeyDownCharacter:(unichar)character;
+
[EMAIL PROTECTED]
+
+
[EMAIL PROTECTED] NSObject (SKTypeSelectDataSource)
+
+- (NSArray *)typeSelectHelperSelectionItems:(SKTypeSelectHelper
*)typeSelectHelper; // required
+- (unsigned int)typeSelectHelperCurrentlySelectedIndex:(SKTypeSelectHelper
*)typeSelectHelper; // required
+- (void)typeSelectHelper:(SKTypeSelectHelper *)typeSelectHelper
selectItemAtIndex:(unsigned int)itemIndex; // required
+
+- (void)typeSelectHelper:(SKTypeSelectHelper *)typeSelectHelper
updateSearchString:(NSString *)searchString; // optional
+
[EMAIL PROTECTED]
Added: trunk/SKTypeSelectHelper.m
===================================================================
--- trunk/SKTypeSelectHelper.m (rev 0)
+++ trunk/SKTypeSelectHelper.m 2007-08-21 14:20:35 UTC (rev 2690)
@@ -0,0 +1,239 @@
+//
+// SKTypeSelectHelper.m
+// Skim
+//
+// Created by Christiaan Hofman on 8/21/07.
+/*
+ This software is Copyright (c) 2007
+ Christiaan Hofman. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ - Neither the name of Christiaan Hofman nor the names of any
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "SKTypeSelectHelper.h"
+
+
[EMAIL PROTECTED] SKTypeSelectHelper (SKPrivate)
+- (void)typeSelectSearchTimeout;
+- (unsigned int)indexOfMatchedItemAfterIndex:(unsigned int)selectedIndex;
[EMAIL PROTECTED]
+
[EMAIL PROTECTED] SKTypeSelectHelper
+
+// Init and dealloc
+
+- (id)init {
+ if (self = [super init]){
+ cycleResults = YES;
+ matchesImmediately = NO;
+ matchOption = SKPrefixMatch;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [timer invalidate];
+ [timer release];
+ [searchString release];
+ [searchCache release];
+ [super dealloc];
+}
+
+// API
+- (id)dataSource {
+ return dataSource;
+}
+
+- (void)setDataSource:(id)newDataSource {
+ if (dataSource == newDataSource)
+ return;
+
+ dataSource = newDataSource;
+ [self rebuildTypeSelectSearchCache];
+}
+
+- (BOOL)cyclesSimilarResults {
+ return cycleResults;
+}
+
+- (void)setCyclesSimilarResults:(BOOL)newValue {
+ cycleResults = newValue;
+}
+
+- (BOOL)matchesImmediately {
+ return matchesImmediately;
+}
+
+- (void)setMatchesImmediately:(BOOL)newValue {
+ matchesImmediately = newValue;
+}
+
+- (int)matchOption {
+ return matchOption;
+}
+
+- (void)setMatchOption:(int)newValue {
+ matchOption = newValue;
+}
+
+- (void)rebuildTypeSelectSearchCache {
+ if (searchCache)
+ [searchCache release];
+
+ searchCache = [[dataSource typeSelectHelperSelectionItems:self] retain];
+}
+
+- (void)processKeyDownCharacter:(unichar)character {
+ NSString *selectedItem = nil;
+ unsigned int selectedIndex, foundIndex;
+
+ // Create the search string the first time around
+ if (searchString == nil)
+ searchString = [[NSMutableString alloc] init];
+
+ // Append the new character to the search string
+ [searchString appendFormat:@"%C", character];
+
+ if ([dataSource
respondsToSelector:@selector(typeSelectHelper:updateSearchString:)])
+ [dataSource typeSelectHelper:self updateSearchString:searchString];
+
+ // Reset the timer if it hasn't expired yet
+ NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0.7];
+ [timer invalidate];
+ [timer release];
+ timer = nil;
+ timer = [[NSTimer alloc] initWithFireDate:date interval:0 target:self
selector:@selector(typeSelectSearchTimeout:) userInfo:NULL repeats:NO];
+ [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
+
+ if (matchesImmediately) {
+ if (cycleResults) {
+ selectedIndex = [dataSource
typeSelectHelperCurrentlySelectedIndex:self];
+ if (selectedIndex < [searchCache count])
+ selectedItem = [searchCache objectAtIndex:selectedIndex];
+ else
+ selectedIndex = NSNotFound;
+
+ // Avoid flashing a selection all over the place while you're
still typing the thing you have selected
+ if (matchOption == SKFullStringMatch) {
+ if ([selectedItem caseInsensitiveCompare:searchString] ==
NSOrderedSame)
+ return;
+ } else {
+ unsigned int searchStringLength = [searchString length];
+ unsigned int selectedItemLength = [selectedItem length];
+ NSRange range = NSMakeRange(0, matchOption == SKPrefixMatch ?
searchStringLength : selectedItemLength);
+ if (searchStringLength > 1 && selectedItemLength >=
searchStringLength && [selectedItem rangeOfString:searchString
options:NSCaseInsensitiveSearch range:range].location != NSNotFound)
+ return;
+ }
+
+ } else {
+ selectedIndex = NSNotFound;
+ }
+
+ foundIndex = [self indexOfMatchedItemAfterIndex:selectedIndex];
+
+ if (foundIndex != NSNotFound)
+ [dataSource typeSelectHelper:self selectItemAtIndex:foundIndex];
+ }
+}
+
+- (BOOL)isProcessing {
+ return timer != nil;
+}
+
+- (void)typeSelectSearchTimeout:(NSTimer *)aTimer {
+ if (matchesImmediately == NO && [searchString length]) {
+ unsigned int selectedIndex, foundIndex;
+
+ if (cycleResults) {
+ selectedIndex = NSNotFound;
+ } else {
+ selectedIndex = [dataSource
typeSelectHelperCurrentlySelectedIndex:self];
+ if (selectedIndex >= [searchCache count])
+ selectedIndex = NSNotFound;
+ }
+ foundIndex = [self indexOfMatchedItemAfterIndex:selectedIndex];
+ if (foundIndex != NSNotFound)
+ [dataSource typeSelectHelper:self selectItemAtIndex:foundIndex];
+ }
+
+ if ([dataSource
respondsToSelector:@selector(typeSelectHelper:updateSearchString:)])
+ [dataSource typeSelectHelper:self updateSearchString:nil];
+ [timer invalidate];
+ [timer release];
+ timer = nil;
+ [searchString release];
+ searchString = nil;
+}
+
+- (unsigned int)indexOfMatchedItemAfterIndex:(unsigned int)selectedIndex {
+ if (searchCache == nil)
+ [self rebuildTypeSelectSearchCache];
+
+ unsigned int labelCount = [searchCache count];
+
+ if (labelCount == NO)
+ return NSNotFound;
+
+ if (selectedIndex == NSNotFound)
+ selectedIndex = labelCount - 1;
+
+ unsigned int labelIndex = selectedIndex;
+ BOOL looped = NO;
+ unsigned int searchStringLength = [searchString length];
+ int options = NSCaseInsensitiveSearch;
+
+ if (matchOption == SKPrefixMatch)
+ options |= NSAnchoredSearch;
+
+ while (looped == NO) {
+ NSString *label;
+
+ if (++labelIndex == labelCount)
+ labelIndex = 0;
+ if (labelIndex == selectedIndex)
+ looped = YES;
+
+ label = [searchCache objectAtIndex:labelIndex];
+
+ if (matchOption == SKFullStringMatch) {
+ if ([label caseInsensitiveCompare:searchString] == NSOrderedSame)
+ return labelIndex;
+ } else {
+ int location = [label length] < searchStringLength ? NSNotFound :
[label rangeOfString:searchString options:options].location;
+ if (location != NSNotFound) {
+ if (location == 0 || [[NSCharacterSet letterCharacterSet]
characterIsMember:[label characterAtIndex:location - 1]] == NO)
+ return labelIndex;
+ }
+ }
+ }
+
+ return NSNotFound;
+}
+
[EMAIL PROTECTED]
Modified: trunk/Skim.xcodeproj/project.pbxproj
===================================================================
--- trunk/Skim.xcodeproj/project.pbxproj 2007-08-20 18:21:29 UTC (rev
2689)
+++ trunk/Skim.xcodeproj/project.pbxproj 2007-08-21 14:20:35 UTC (rev
2690)
@@ -128,6 +128,7 @@
CE54898F0B35D50E00F8AFB6 /* SKInfoWindowController.m in Sources
*/ = {isa = PBXBuildFile; fileRef = CE54898E0B35D50E00F8AFB6 /*
SKInfoWindowController.m */; };
CE5BC5B10C79A27B00EBDCF7 /* NSTableView_SKExtensions.h in
CopyFiles */ = {isa = PBXBuildFile; fileRef = CE5BC5AF0C79A27B00EBDCF7 /*
NSTableView_SKExtensions.h */; };
CE5BC5B20C79A27B00EBDCF7 /* NSTableView_SKExtensions.m in
Sources */ = {isa = PBXBuildFile; fileRef = CE5BC5B00C79A27B00EBDCF7 /*
NSTableView_SKExtensions.m */; };
+ CE5BD6740C7ADF1500EBDCF7 /* SKTypeSelectHelper.m in Sources */
= {isa = PBXBuildFile; fileRef = CE5BD6720C7ADF1500EBDCF7 /*
SKTypeSelectHelper.m */; };
CE5F42AF0BF89FE00069D89C /* AppleRemote.m in Sources */ = {isa
= PBXBuildFile; fileRef = CE5F42AD0BF89FE00069D89C /* AppleRemote.m */; };
CE5F43730BF8A3410069D89C /* IOKit.framework in Frameworks */ =
{isa = PBXBuildFile; fileRef = CE5F42D30BF8A3400069D89C /* IOKit.framework */;
};
CE67BB260BC44AC9007B6929 /* ZoomValues.strings in Resources */
= {isa = PBXBuildFile; fileRef = CE67BB240BC44AC9007B6929 /* ZoomValues.strings
*/; };
@@ -485,6 +486,8 @@
CE54AA8E0BBC037400008750 /* ReleaseNotes.rtf */ = {isa =
PBXFileReference; lastKnownFileType = text.rtf; path = ReleaseNotes.rtf;
sourceTree = "<group>"; };
CE5BC5AF0C79A27B00EBDCF7 /* NSTableView_SKExtensions.h */ =
{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h;
path = NSTableView_SKExtensions.h; sourceTree = "<group>"; };
CE5BC5B00C79A27B00EBDCF7 /* NSTableView_SKExtensions.m */ =
{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType =
sourcecode.c.objc; path = NSTableView_SKExtensions.m; sourceTree = "<group>"; };
+ CE5BD6710C7ADF1500EBDCF7 /* SKTypeSelectHelper.h */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path =
SKTypeSelectHelper.h; sourceTree = "<group>"; };
+ CE5BD6720C7ADF1500EBDCF7 /* SKTypeSelectHelper.m */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path
= SKTypeSelectHelper.m; sourceTree = "<group>"; };
CE5F42AC0BF89FE00069D89C /* AppleRemote.h */ = {isa =
PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name =
AppleRemote.h; path = vendorsrc/martinkahr/AppleRemoteSource_R80/AppleRemote.h;
sourceTree = "<group>"; };
CE5F42AD0BF89FE00069D89C /* AppleRemote.m */ = {isa =
PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc;
name = AppleRemote.m; path =
vendorsrc/martinkahr/AppleRemoteSource_R80/AppleRemote.m; sourceTree =
"<group>"; };
CE5F42D30BF8A3400069D89C /* IOKit.framework */ = {isa =
PBXFileReference; lastKnownFileType = wrapper.framework; name =
IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree
= "<absolute>"; };
@@ -979,6 +982,8 @@
CE1E2B270BDAB6180011D9DD /* SKPDFSynchronizer.m
*/,
CE48BAD50C089EA300A166C6 /* SKTemplateParser.h
*/,
CE48BAD60C089EA300A166C6 /* SKTemplateParser.m
*/,
+ CE5BD6710C7ADF1500EBDCF7 /*
SKTypeSelectHelper.h */,
+ CE5BD6720C7ADF1500EBDCF7 /*
SKTypeSelectHelper.m */,
);
name = Miscellaneous;
sourceTree = "<group>";
@@ -1468,6 +1473,7 @@
CEAA67260C70A882006BD633 /*
NSURL_SKExtensions.m in Sources */,
CEF839B30C77742A00A3AD51 /*
Files_SKExtensions.m in Sources */,
CE5BC5B20C79A27B00EBDCF7 /*
NSTableView_SKExtensions.m in Sources */,
+ CE5BD6740C7ADF1500EBDCF7 /*
SKTypeSelectHelper.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit