├── .gitignore ├── LICENSE.txt ├── README.md ├── STPathTextField.h ├── STPathTextField.m ├── STPathTextField.podspec ├── STPathTextFieldExample ├── STPathTextFieldExample.xcodeproj │ └── project.pbxproj └── STPathTextFieldExample │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ └── MainMenu.xib │ ├── Info.plist │ └── main.m └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.xcuserstate 2 | UserInterfaceState.xcuserstate 3 | *dsa_priv.pem 4 | Platypus.build 5 | BuildData 6 | .DS_Store 7 | *.swp 8 | *~.nib 9 | *.pbxuser 10 | *.perspective 11 | *.perspectivev3 12 | *.mode1v3 13 | *.mode2v3 14 | *.xcodeproj/xcuserdata/*.xcuserdatad 15 | *.xcodeproj/project.xcworkspace/xcuserdata/*.xcuserdatad 16 | xcuserdata/ 17 | platypus.man.html 18 | *UserInterfaceState.xcuserstate 19 | .DS_Store 20 | build/ 21 | *.pbxuser 22 | !default.pbxuser 23 | *.mode1v3 24 | !default.mode1v3 25 | *.mode2v3 26 | !default.mode2v3 27 | *.perspectivev3 28 | !default.perspectivev3 29 | *.xcworkspace 30 | !default.xcworkspace 31 | xcuserdata 32 | profile 33 | *.moved-aside 34 | DerivedData 35 | .idea/ 36 | Pods 37 | 38 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | # BSD License 2 | # Redistribution and use in source and binary forms, with or without 3 | # modification, are permitted provided that the following conditions are met: 4 | # * Redistributions of source code must retain the above copyright 5 | # notice, this list of conditions and the following disclaimer. 6 | # * Redistributions in binary form must reproduce the above copyright 7 | # notice, this list of conditions and the following disclaimer in the 8 | # documentation and/or other materials provided with the distribution. 9 | # * Neither the name of Sveinbjorn Thordarson nor that of any other 10 | # contributors may be used to endorse or promote products 11 | # derived from this software without specific prior written permission. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # STPathTextField - Objective C class 2 | 3 | STPathTextField is a subclass of NSTextField for receiving and displaying a file system path. It supports path validation and autocompletion. Autocompletion can use "web browser" style - i.e. expansion and selection, or shell autocompletion style - i.e. tab-expansion. 4 | 5 | To use STPathTextField, just add a text field to a window in a nib file, and set its class to STPathTextField. 6 | 7 | Default properties of an STPathTextField are the following: 8 | 9 | ```objective-c 10 | autocompleteStyle = STNoAutocomplete; 11 | colorInvalidPath = YES; 12 | foldersAreValid = NO; 13 | expandTildeInPath = YES; 14 | ``` 15 | 16 | There are three autocomplete styles: 17 | 18 | ```objective-c 19 | typedef enum 20 | { 21 | STNoAutocomplete = 0, 22 | STShellAutocomplete = 1, 23 | STBrowserAutocomplete = 2 24 | } 25 | STPathTextFieldAutocompleteStyle; 26 | 27 | ``` 28 | 29 | ## Screenshot of example app 30 | 31 | -------------------------------------------------------------------------------- /STPathTextField.h: -------------------------------------------------------------------------------- 1 | /* 2 | STPathTextField.h 3 | 4 | Created by Sveinbjorn Thordarson on 6/27/08. 5 | Copyright (C) 2008-2015 Sveinbjorn Thordarson. All rights reserved. 6 | 7 | ************************ ABOUT ***************************** 8 | 9 | STPathTextField is a subclass of NSTextField for receiving 10 | and displaying a file system path. It supports path validation 11 | and autocompletion. Autocompletion can use "web browser" style - 12 | e.g. expansion and selection, or shell autocompletion style - 13 | tab-expansion. 14 | 15 | To use STPathTextField, just add a text field to a window in 16 | Interface Builder, and set its class to STPathTextField. 17 | 18 | See code on how to set the settings for the text field. 19 | Defaults are the following: 20 | 21 | autocompleteStyle = STNoAutocomplete; 22 | colorInvalidPath = YES; 23 | foldersAreValid = NO; 24 | expandTildeInPath = YES; 25 | 26 | There are three settings for autocompleteStyle 27 | 28 | enum 29 | { 30 | STNoAutocomplete = 0, 31 | STShellAutocomplete = 1, 32 | STBrowserAutocomplete = 2 33 | }; 34 | 35 | 36 | # BSD License 37 | # Redistribution and use in source and binary forms, with or without 38 | # modification, are permitted provided that the following conditions are met: 39 | # * Redistributions of source code must retain the above copyright 40 | # notice, this list of conditions and the following disclaimer. 41 | # * Redistributions in binary form must reproduce the above copyright 42 | # notice, this list of conditions and the following disclaimer in the 43 | # documentation and/or other materials provided with the distribution. 44 | # * Neither the name of Sveinbjorn Thordarson nor that of any other 45 | # contributors may be used to endorse or promote products 46 | # derived from this software without specific prior written permission. 47 | # 48 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 49 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 50 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 51 | # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 52 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 53 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 54 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 55 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 56 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 57 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58 | */ 59 | 60 | 61 | #import 62 | 63 | typedef enum 64 | { 65 | STNoAutocomplete = 0, 66 | STShellAutocomplete = 1, 67 | STBrowserAutocomplete = 2 68 | } STPathTextFieldAutocompleteStyle; 69 | 70 | @interface STPathTextField : NSTextField 71 | 72 | @property STPathTextFieldAutocompleteStyle autocompleteStyle; 73 | @property BOOL colorInvalidPath; 74 | @property BOOL foldersAreValid; 75 | @property BOOL expandTildeInPath; 76 | 77 | - (BOOL)hasValidPath; 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /STPathTextField.m: -------------------------------------------------------------------------------- 1 | /* 2 | STPathTextField.m 3 | 4 | Created by Sveinbjorn Thordarson on 6/27/08. 5 | Copyright (C) 2008-2015 Sveinbjorn Thordarson. All rights reserved. 6 | 7 | # BSD License 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # * Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above copyright 13 | # notice, this list of conditions and the following disclaimer in the 14 | # documentation and/or other materials provided with the distribution. 15 | # * Neither the name of Sveinbjorn Thordarson nor that of any other 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 23 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | */ 31 | 32 | #import "STPathTextField.h" 33 | 34 | @implementation STPathTextField 35 | 36 | - (instancetype)initWithCoder:(NSCoder *)coder 37 | { 38 | self = [super initWithCoder:coder]; 39 | if (self) { 40 | [self setDefaults]; 41 | } 42 | return self; 43 | } 44 | 45 | - (instancetype)initWithFrame:(NSRect)frameRect 46 | { 47 | self = [super initWithFrame:frameRect]; 48 | if (self) { 49 | [self setDefaults]; 50 | } 51 | return self; 52 | } 53 | 54 | - (void)setDefaults 55 | { 56 | // default settings for the text field 57 | _autocompleteStyle = STShellAutocomplete; 58 | _colorInvalidPath = YES; 59 | _foldersAreValid = NO; 60 | _expandTildeInPath = YES; 61 | 62 | [self registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; 63 | } 64 | 65 | #pragma mark - 66 | 67 | - (BOOL)hasValidPath 68 | { 69 | BOOL isDir; 70 | NSString *path = self.expandTildeInPath ? [[self stringValue] stringByExpandingTildeInPath] : [self stringValue]; 71 | return ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir] && (!(isDir && !self.foldersAreValid))); 72 | } 73 | 74 | #pragma mark - 75 | 76 | - (void)keyUp:(NSEvent *)event 77 | { 78 | unichar keyCode = [[event characters] characterAtIndex:0]; 79 | 80 | if (self.autocompleteStyle == STBrowserAutocomplete) { 81 | if (keyCode != 13 && keyCode != 9 && keyCode != 127 && keyCode != NSLeftArrowFunctionKey && keyCode != NSRightArrowFunctionKey) { 82 | [self autoComplete:self]; 83 | } 84 | } 85 | 86 | [super keyUp:event]; 87 | [self updateTextColoring]; 88 | } 89 | 90 | - (void)setStringValue:(NSString *)aString 91 | { 92 | [super setStringValue:aString]; 93 | [self textChanged]; 94 | } 95 | 96 | - (void)updateTextColoring 97 | { 98 | if (!self.colorInvalidPath) { 99 | return; 100 | } 101 | 102 | NSColor *textColor = [self hasValidPath] ? [NSColor blackColor]: [NSColor redColor]; 103 | [self setTextColor: textColor]; 104 | } 105 | 106 | - (BOOL)autoComplete:(id)sender 107 | { 108 | NSString *path = [self stringValue]; 109 | NSUInteger len = [path length]; 110 | 111 | // let's not waste time if the string is empty 112 | if (len == 0) { 113 | return NO; 114 | } 115 | 116 | // we only try to expand if this looks like a real path, i.e. starts with / or ~ 117 | unichar firstchar = [path characterAtIndex: 0]; 118 | if (firstchar != '/' && firstchar != '~') { 119 | return NO; 120 | } 121 | 122 | // expand tilde to home dir 123 | if (firstchar == '~' && self.expandTildeInPath) { 124 | path = [[self stringValue] stringByExpandingTildeInPath]; 125 | len = [path length]; 126 | } 127 | 128 | // get suggestion for autocompletion 129 | NSString *autocompletedPath = nil; 130 | [path completePathIntoString:&autocompletedPath caseSensitive:YES matchesIntoArray:nil filterTypes:nil]; 131 | 132 | // stop if no suggestions 133 | if (autocompletedPath == nil) { 134 | return NO; 135 | } 136 | 137 | // stop if suggestion is current value and current value is a valid path 138 | BOOL isDir; 139 | if ([autocompletedPath isEqualToString:[self stringValue]] && 140 | [[NSFileManager defaultManager] fileExistsAtPath:autocompletedPath isDirectory:&isDir] && 141 | !(isDir && !self.foldersAreValid)) { 142 | return NO; 143 | } 144 | 145 | // replace field string with autocompleted string 146 | [self setStringValue: autocompletedPath]; 147 | 148 | // if browser style autocompletion is enabled 149 | // we select the autocomplete extension to the previous string 150 | if (self.autocompleteStyle == STBrowserAutocomplete) { 151 | NSUInteger dlen = [autocompletedPath length]; 152 | [[self currentEditor] setSelectedRange:NSMakeRange(len, dlen)]; 153 | } 154 | 155 | return YES; 156 | } 157 | 158 | // we make sure coloring is correct whenever text changes 159 | - (void)textDidChange:(NSNotification *)aNotification 160 | { 161 | [self textChanged]; 162 | } 163 | 164 | - (void)textChanged 165 | { 166 | if (self.colorInvalidPath) { 167 | [self updateTextColoring]; 168 | } 169 | 170 | if ([self delegate] && [[self delegate] respondsToSelector:@selector(controlTextDidChange:)]) { 171 | [[self delegate] performSelector: @selector(controlTextDidChange:) withObject:nil]; 172 | } 173 | } 174 | 175 | - (BOOL)textView:(NSTextView *)aTextView doCommandBySelector:(SEL)aSelector 176 | { 177 | // intercept tab 178 | if (aSelector == @selector(insertTab:) && self.autocompleteStyle == STShellAutocomplete) { 179 | 180 | NSString *string = [self stringValue]; 181 | BOOL result = NO; 182 | NSRange selectedRange = [aTextView selectedRange]; 183 | 184 | // we only do tab autocomplete if the insertion point is at the end of the field 185 | // and if selection in the field is empty 186 | if (selectedRange.length == 0 && selectedRange.location == [[self stringValue] length]) { 187 | result = [self autoComplete: self]; 188 | } 189 | 190 | // we only let the user tab out of the field if it's empty or has valid path 191 | if ([[self stringValue] length] == 0 || ([self hasValidPath] && [string isEqualToString: [self stringValue]])) { 192 | return NO; 193 | } 194 | 195 | return result; 196 | } 197 | return NO; 198 | // return [super textView: aTextView doCommandBySelector: aSelector]; 199 | } 200 | 201 | #pragma mark - Dragging 202 | 203 | - (NSDragOperation)draggingEntered:(id )sender 204 | { 205 | if ([[[sender draggingPasteboard] types] containsObject:NSFilenamesPboardType]) { 206 | return NSDragOperationLink; 207 | } 208 | return NSDragOperationNone; 209 | } 210 | 211 | - (BOOL)performDragOperation:(id )sender 212 | { 213 | if ([[[sender draggingPasteboard] types] containsObject:NSFilenamesPboardType]) { 214 | NSArray *files = [[sender draggingPasteboard] propertyListForType:NSFilenamesPboardType]; 215 | [self setStringValue:files[0]]; 216 | return YES; 217 | } 218 | return NO; 219 | } 220 | 221 | @end -------------------------------------------------------------------------------- /STPathTextField.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "STPathTextField" 3 | s.version = "1.0.0" 4 | s.summary = "NSTextField subclass for receiving and displaying a file system path, supporting path validation and autocompletion." 5 | s.description = "NSTextField subclass for receiving and displaying a file system path, supporting path validation and autocompletion, expanding tilde in path etc." 6 | s.homepage = "http://github.com/sveinbjornt/STPathTextField" 7 | s.license = { :type => 'BSD' } 8 | s.author = { "Sveinbjorn Thordarson" => "sveinbjornt@gmail.com" } 9 | s.osx.deployment_target = "10.6" 10 | s.source = { :git => "https://github.com/sveinbjornt/STPathTextField.git", :tag => "1.0.1" } 11 | s.source_files = "STPathTextField.{h,m}" 12 | s.exclude_files = "STPathTextFieldExample" 13 | s.public_header_files = "STPathTextField.h" 14 | s.requires_arc = false 15 | end 16 | -------------------------------------------------------------------------------- /STPathTextFieldExample/STPathTextFieldExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | F4F103921B517F0600BCAD40 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F103911B517F0600BCAD40 /* AppDelegate.m */; }; 11 | F4F103941B517F0600BCAD40 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F103931B517F0600BCAD40 /* main.m */; }; 12 | F4F103991B517F0600BCAD40 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4F103971B517F0600BCAD40 /* MainMenu.xib */; }; 13 | F4F103B51B517F6200BCAD40 /* STPathTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F103B11B517F6200BCAD40 /* STPathTextField.m */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXFileReference section */ 17 | F4F1038B1B517F0600BCAD40 /* STPathTextFieldExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = STPathTextFieldExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 18 | F4F1038F1B517F0600BCAD40 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 19 | F4F103901B517F0600BCAD40 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 20 | F4F103911B517F0600BCAD40 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 21 | F4F103931B517F0600BCAD40 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 22 | F4F103981B517F0600BCAD40 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 23 | F4F103AE1B517F6200BCAD40 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE.txt; path = ../LICENSE.txt; sourceTree = ""; }; 24 | F4F103AF1B517F6200BCAD40 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 25 | F4F103B01B517F6200BCAD40 /* STPathTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = STPathTextField.h; path = ../STPathTextField.h; sourceTree = ""; }; 26 | F4F103B11B517F6200BCAD40 /* STPathTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = STPathTextField.m; path = ../STPathTextField.m; sourceTree = ""; }; 27 | F4F103B21B517F6200BCAD40 /* STPathTextField.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = STPathTextField.podspec; path = ../STPathTextField.podspec; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | F4F103881B517F0600BCAD40 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | F4F103821B517F0600BCAD40 = { 42 | isa = PBXGroup; 43 | children = ( 44 | F4F103AE1B517F6200BCAD40 /* LICENSE.txt */, 45 | F4F103AF1B517F6200BCAD40 /* README.md */, 46 | F4F103B21B517F6200BCAD40 /* STPathTextField.podspec */, 47 | F4F103B71B517F6800BCAD40 /* STPathTextField */, 48 | F4F1038D1B517F0600BCAD40 /* Example APp */, 49 | F4F1038C1B517F0600BCAD40 /* Products */, 50 | ); 51 | sourceTree = ""; 52 | }; 53 | F4F1038C1B517F0600BCAD40 /* Products */ = { 54 | isa = PBXGroup; 55 | children = ( 56 | F4F1038B1B517F0600BCAD40 /* STPathTextFieldExample.app */, 57 | ); 58 | name = Products; 59 | sourceTree = ""; 60 | }; 61 | F4F1038D1B517F0600BCAD40 /* Example APp */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | F4F103901B517F0600BCAD40 /* AppDelegate.h */, 65 | F4F103911B517F0600BCAD40 /* AppDelegate.m */, 66 | F4F103971B517F0600BCAD40 /* MainMenu.xib */, 67 | F4F1038F1B517F0600BCAD40 /* Info.plist */, 68 | F4F103931B517F0600BCAD40 /* main.m */, 69 | ); 70 | name = "Example APp"; 71 | path = STPathTextFieldExample; 72 | sourceTree = ""; 73 | }; 74 | F4F103B71B517F6800BCAD40 /* STPathTextField */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | F4F103B01B517F6200BCAD40 /* STPathTextField.h */, 78 | F4F103B11B517F6200BCAD40 /* STPathTextField.m */, 79 | ); 80 | name = STPathTextField; 81 | sourceTree = ""; 82 | }; 83 | /* End PBXGroup section */ 84 | 85 | /* Begin PBXNativeTarget section */ 86 | F4F1038A1B517F0600BCAD40 /* STPathTextFieldExample */ = { 87 | isa = PBXNativeTarget; 88 | buildConfigurationList = F4F103A81B517F0700BCAD40 /* Build configuration list for PBXNativeTarget "STPathTextFieldExample" */; 89 | buildPhases = ( 90 | F4F103871B517F0600BCAD40 /* Sources */, 91 | F4F103881B517F0600BCAD40 /* Frameworks */, 92 | F4F103891B517F0600BCAD40 /* Resources */, 93 | ); 94 | buildRules = ( 95 | ); 96 | dependencies = ( 97 | ); 98 | name = STPathTextFieldExample; 99 | productName = STPathTextFieldExample; 100 | productReference = F4F1038B1B517F0600BCAD40 /* STPathTextFieldExample.app */; 101 | productType = "com.apple.product-type.application"; 102 | }; 103 | /* End PBXNativeTarget section */ 104 | 105 | /* Begin PBXProject section */ 106 | F4F103831B517F0600BCAD40 /* Project object */ = { 107 | isa = PBXProject; 108 | attributes = { 109 | LastUpgradeCheck = 0820; 110 | ORGANIZATIONNAME = "Sveinbjorn Thordarson"; 111 | TargetAttributes = { 112 | F4F1038A1B517F0600BCAD40 = { 113 | CreatedOnToolsVersion = 6.4; 114 | }; 115 | }; 116 | }; 117 | buildConfigurationList = F4F103861B517F0600BCAD40 /* Build configuration list for PBXProject "STPathTextFieldExample" */; 118 | compatibilityVersion = "Xcode 3.2"; 119 | developmentRegion = English; 120 | hasScannedForEncodings = 0; 121 | knownRegions = ( 122 | en, 123 | Base, 124 | ); 125 | mainGroup = F4F103821B517F0600BCAD40; 126 | productRefGroup = F4F1038C1B517F0600BCAD40 /* Products */; 127 | projectDirPath = ""; 128 | projectRoot = ""; 129 | targets = ( 130 | F4F1038A1B517F0600BCAD40 /* STPathTextFieldExample */, 131 | ); 132 | }; 133 | /* End PBXProject section */ 134 | 135 | /* Begin PBXResourcesBuildPhase section */ 136 | F4F103891B517F0600BCAD40 /* Resources */ = { 137 | isa = PBXResourcesBuildPhase; 138 | buildActionMask = 2147483647; 139 | files = ( 140 | F4F103991B517F0600BCAD40 /* MainMenu.xib in Resources */, 141 | ); 142 | runOnlyForDeploymentPostprocessing = 0; 143 | }; 144 | /* End PBXResourcesBuildPhase section */ 145 | 146 | /* Begin PBXSourcesBuildPhase section */ 147 | F4F103871B517F0600BCAD40 /* Sources */ = { 148 | isa = PBXSourcesBuildPhase; 149 | buildActionMask = 2147483647; 150 | files = ( 151 | F4F103B51B517F6200BCAD40 /* STPathTextField.m in Sources */, 152 | F4F103941B517F0600BCAD40 /* main.m in Sources */, 153 | F4F103921B517F0600BCAD40 /* AppDelegate.m in Sources */, 154 | ); 155 | runOnlyForDeploymentPostprocessing = 0; 156 | }; 157 | /* End PBXSourcesBuildPhase section */ 158 | 159 | /* Begin PBXVariantGroup section */ 160 | F4F103971B517F0600BCAD40 /* MainMenu.xib */ = { 161 | isa = PBXVariantGroup; 162 | children = ( 163 | F4F103981B517F0600BCAD40 /* Base */, 164 | ); 165 | name = MainMenu.xib; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXVariantGroup section */ 169 | 170 | /* Begin XCBuildConfiguration section */ 171 | F4F103A61B517F0700BCAD40 /* Debug */ = { 172 | isa = XCBuildConfiguration; 173 | buildSettings = { 174 | ALWAYS_SEARCH_USER_PATHS = NO; 175 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 176 | CLANG_CXX_LIBRARY = "libc++"; 177 | CLANG_ENABLE_MODULES = YES; 178 | CLANG_ENABLE_OBJC_ARC = YES; 179 | CLANG_WARN_BOOL_CONVERSION = YES; 180 | CLANG_WARN_CONSTANT_CONVERSION = YES; 181 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 182 | CLANG_WARN_EMPTY_BODY = YES; 183 | CLANG_WARN_ENUM_CONVERSION = YES; 184 | CLANG_WARN_INFINITE_RECURSION = YES; 185 | CLANG_WARN_INT_CONVERSION = YES; 186 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 187 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 188 | CLANG_WARN_UNREACHABLE_CODE = YES; 189 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 190 | CODE_SIGN_IDENTITY = "-"; 191 | COPY_PHASE_STRIP = NO; 192 | DEBUG_INFORMATION_FORMAT = dwarf; 193 | ENABLE_STRICT_OBJC_MSGSEND = YES; 194 | ENABLE_TESTABILITY = YES; 195 | GCC_C_LANGUAGE_STANDARD = gnu99; 196 | GCC_DYNAMIC_NO_PIC = NO; 197 | GCC_NO_COMMON_BLOCKS = YES; 198 | GCC_OPTIMIZATION_LEVEL = 0; 199 | GCC_PREPROCESSOR_DEFINITIONS = ( 200 | "DEBUG=1", 201 | "$(inherited)", 202 | ); 203 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 204 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 205 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 206 | GCC_WARN_UNDECLARED_SELECTOR = YES; 207 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 208 | GCC_WARN_UNUSED_FUNCTION = YES; 209 | GCC_WARN_UNUSED_VARIABLE = YES; 210 | MACOSX_DEPLOYMENT_TARGET = 10.10; 211 | MTL_ENABLE_DEBUG_INFO = YES; 212 | ONLY_ACTIVE_ARCH = YES; 213 | SDKROOT = macosx; 214 | }; 215 | name = Debug; 216 | }; 217 | F4F103A71B517F0700BCAD40 /* Release */ = { 218 | isa = XCBuildConfiguration; 219 | buildSettings = { 220 | ALWAYS_SEARCH_USER_PATHS = NO; 221 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 222 | CLANG_CXX_LIBRARY = "libc++"; 223 | CLANG_ENABLE_MODULES = YES; 224 | CLANG_ENABLE_OBJC_ARC = YES; 225 | CLANG_WARN_BOOL_CONVERSION = YES; 226 | CLANG_WARN_CONSTANT_CONVERSION = YES; 227 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 228 | CLANG_WARN_EMPTY_BODY = YES; 229 | CLANG_WARN_ENUM_CONVERSION = YES; 230 | CLANG_WARN_INFINITE_RECURSION = YES; 231 | CLANG_WARN_INT_CONVERSION = YES; 232 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 233 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 234 | CLANG_WARN_UNREACHABLE_CODE = YES; 235 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 236 | CODE_SIGN_IDENTITY = "-"; 237 | COPY_PHASE_STRIP = NO; 238 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 239 | ENABLE_NS_ASSERTIONS = NO; 240 | ENABLE_STRICT_OBJC_MSGSEND = YES; 241 | GCC_C_LANGUAGE_STANDARD = gnu99; 242 | GCC_NO_COMMON_BLOCKS = YES; 243 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 244 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 245 | GCC_WARN_UNDECLARED_SELECTOR = YES; 246 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 247 | GCC_WARN_UNUSED_FUNCTION = YES; 248 | GCC_WARN_UNUSED_VARIABLE = YES; 249 | MACOSX_DEPLOYMENT_TARGET = 10.10; 250 | MTL_ENABLE_DEBUG_INFO = NO; 251 | SDKROOT = macosx; 252 | }; 253 | name = Release; 254 | }; 255 | F4F103A91B517F0700BCAD40 /* Debug */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 259 | COMBINE_HIDPI_IMAGES = YES; 260 | INFOPLIST_FILE = STPathTextFieldExample/Info.plist; 261 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 262 | MACOSX_DEPLOYMENT_TARGET = 10.6; 263 | PRODUCT_BUNDLE_IDENTIFIER = "org.sveinbjorn.$(PRODUCT_NAME:rfc1034identifier)"; 264 | PRODUCT_NAME = "$(TARGET_NAME)"; 265 | }; 266 | name = Debug; 267 | }; 268 | F4F103AA1B517F0700BCAD40 /* Release */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 272 | COMBINE_HIDPI_IMAGES = YES; 273 | INFOPLIST_FILE = STPathTextFieldExample/Info.plist; 274 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 275 | MACOSX_DEPLOYMENT_TARGET = 10.6; 276 | PRODUCT_BUNDLE_IDENTIFIER = "org.sveinbjorn.$(PRODUCT_NAME:rfc1034identifier)"; 277 | PRODUCT_NAME = "$(TARGET_NAME)"; 278 | }; 279 | name = Release; 280 | }; 281 | /* End XCBuildConfiguration section */ 282 | 283 | /* Begin XCConfigurationList section */ 284 | F4F103861B517F0600BCAD40 /* Build configuration list for PBXProject "STPathTextFieldExample" */ = { 285 | isa = XCConfigurationList; 286 | buildConfigurations = ( 287 | F4F103A61B517F0700BCAD40 /* Debug */, 288 | F4F103A71B517F0700BCAD40 /* Release */, 289 | ); 290 | defaultConfigurationIsVisible = 0; 291 | defaultConfigurationName = Release; 292 | }; 293 | F4F103A81B517F0700BCAD40 /* Build configuration list for PBXNativeTarget "STPathTextFieldExample" */ = { 294 | isa = XCConfigurationList; 295 | buildConfigurations = ( 296 | F4F103A91B517F0700BCAD40 /* Debug */, 297 | F4F103AA1B517F0700BCAD40 /* Release */, 298 | ); 299 | defaultConfigurationIsVisible = 0; 300 | defaultConfigurationName = Release; 301 | }; 302 | /* End XCConfigurationList section */ 303 | }; 304 | rootObject = F4F103831B517F0600BCAD40 /* Project object */; 305 | } 306 | -------------------------------------------------------------------------------- /STPathTextFieldExample/STPathTextFieldExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // STPathTextFieldExample 4 | // 5 | // Created by Sveinbjorn Thordarson on 11/07/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class STPathTextField; 12 | 13 | @interface AppDelegate : NSObject 14 | 15 | @property IBOutlet STPathTextField *shellStylePathTextField; 16 | @property IBOutlet STPathTextField *browserStylePathTextField; 17 | @property IBOutlet STPathTextField *noAutocompletePathTextField; 18 | 19 | @end 20 | 21 | -------------------------------------------------------------------------------- /STPathTextFieldExample/STPathTextFieldExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // STPathTextFieldExample 4 | // 5 | // Created by Sveinbjorn Thordarson on 11/07/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "STPathTextField.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @property IBOutlet NSWindow *window; 15 | @end 16 | 17 | @implementation AppDelegate 18 | 19 | - (void)awakeFromNib { 20 | 21 | [self.shellStylePathTextField setAutocompleteStyle:STShellAutocomplete]; 22 | [self.shellStylePathTextField setFoldersAreValid:YES]; 23 | 24 | [self.browserStylePathTextField setAutocompleteStyle:STBrowserAutocomplete]; 25 | [self.browserStylePathTextField setFoldersAreValid:YES]; 26 | 27 | [self.noAutocompletePathTextField setAutocompleteStyle:STNoAutocomplete]; 28 | [self.noAutocompletePathTextField setStringValue:@"/some/path/to/nowhere"]; 29 | 30 | [self.shellStylePathTextField setStringValue:@"~/"]; 31 | } 32 | 33 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 34 | // Insert code here to initialize your application 35 | } 36 | 37 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 38 | // Insert code here to tear down your application 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /STPathTextFieldExample/STPathTextFieldExample/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | Default 523 | 524 | 525 | 526 | 527 | 528 | 529 | Left to Right 530 | 531 | 532 | 533 | 534 | 535 | 536 | Right to Left 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | Default 548 | 549 | 550 | 551 | 552 | 553 | 554 | Left to Right 555 | 556 | 557 | 558 | 559 | 560 | 561 | Right to Left 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | -------------------------------------------------------------------------------- /STPathTextFieldExample/STPathTextFieldExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2008-2016 Sveinbjorn Thordarson. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /STPathTextFieldExample/STPathTextFieldExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // STPathTextFieldExample 4 | // 5 | // Created by Sveinbjorn Thordarson on 11/07/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/STPathTextField/35a2d04eb6723d6e5d38178e9acf57215cfa99b1/screenshot.png --------------------------------------------------------------------------------