Browse files

- Initial checkin.

  • Loading branch information...
0 parents commit 3a8900a04820ae053009eb5529176b23a756cb30 @MrNoodle committed Sep 29, 2009
Showing with 17,439 additions and 0 deletions.
  1. +2 −0 English.lproj/InfoPlist.strings
  2. +41 −0 Examples/LineNumberView/Controller.h
  3. +49 −0 Examples/LineNumberView/Controller.m
  4. +1 −0 Examples/LineNumberView/Credits.rtf
  5. BIN Examples/LineNumberView/English.lproj/InfoPlist.strings
  6. +2,933 −0 Examples/LineNumberView/English.lproj/MainMenu.xib
  7. +28 −0 Examples/LineNumberView/LineNumberView-Info.plist
  8. +38 −0 Examples/LineNumberView/MarkerLineNumberView.h
  9. +127 −0 Examples/LineNumberView/MarkerLineNumberView.m
  10. +130 −0 Examples/LineNumberView/Read Me.rtf
  11. +14 −0 Examples/LineNumberView/main.m
  12. +22 −0 Examples/ModalResponder/Controller.h
  13. +62 −0 Examples/ModalResponder/Controller.m
  14. +1 −0 Examples/ModalResponder/Credits.rtf
  15. BIN Examples/ModalResponder/English.lproj/InfoPlist.strings
  16. +3,350 −0 Examples/ModalResponder/English.lproj/MainMenu.xib
  17. +28 −0 Examples/ModalResponder/ModalResponder-Info.plist
  18. +34 −0 Examples/ModalResponder/Read Me.rtf
  19. +14 −0 Examples/ModalResponder/main.m
  20. +39 −0 Examples/StickyRowTableView Revue/Controller.h
  21. +95 −0 Examples/StickyRowTableView Revue/Controller.m
  22. +1 −0 Examples/StickyRowTableView Revue/Credits.rtf
  23. BIN Examples/StickyRowTableView Revue/English.lproj/InfoPlist.strings
  24. +4,245 −0 Examples/StickyRowTableView Revue/English.lproj/MainMenu.xib
  25. +110 −0 Examples/StickyRowTableView Revue/Read Me.rtf
  26. +28 −0 Examples/StickyRowTableView Revue/StickyRowTableView Revue-Info.plist
  27. +14 −0 Examples/StickyRowTableView Revue/main.m
  28. +12 −0 Examples/Window Effects/Controller.h
  29. +23 −0 Examples/Window Effects/Controller.m
  30. BIN Examples/Window Effects/English.lproj/InfoPlist.strings
  31. +2,611 −0 Examples/Window Effects/English.lproj/MainMenu.xib
  32. +28 −0 Examples/Window Effects/Window Effects-Info.plist
  33. +14 −0 Examples/Window Effects/main.m
  34. +28 −0 Info.plist
  35. +76 −0 NSImage-NoodleExtensions.h
  36. +89 −0 NSImage-NoodleExtensions.m
  37. +34 −0 NSObject-NoodlePerformWhenIdle.h
  38. +114 −0 NSObject-NoodlePerformWhenIdle.m
  39. +50 −0 NSResponder-NoodleModalExtensions.h
  40. +87 −0 NSResponder-NoodleModalExtensions.m
  41. +45 −0 NSWindow-NoodleEffects.h
  42. +158 −0 NSWindow-NoodleEffects.m
  43. +43 −0 NoodleIPhoneTableView.h
  44. +158 −0 NoodleIPhoneTableView.m
  45. +1,044 −0 NoodleKit.xcodeproj/project.pbxproj
  46. +7 −0 NoodleKit_Prefix.pch
  47. +49 −0 NoodleLineNumberMarker.h
  48. +102 −0 NoodleLineNumberMarker.m
  49. +69 −0 NoodleLineNumberView.h
  50. +575 −0 NoodleLineNumberView.m
  51. +129 −0 NoodleStickyRowTableView.h
  52. +409 −0 NoodleStickyRowTableView.m
  53. +63 −0 Read Me.rtf
  54. +16 −0 version.plist
2 English.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
41 Examples/LineNumberView/Controller.h
@@ -0,0 +1,41 @@
+//
+// Controller.h
+// Line View Test
+//
+// Created by Paul Kim on 9/28/08.
+// Copyright (c) 2008 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@class NoodleLineNumberView;
+
+@interface Controller : NSObject
+{
+ IBOutlet NSScrollView *scrollView;
+ IBOutlet NSTextView *scriptView;
+ NoodleLineNumberView *lineNumberView;
+}
+
+@end
49 Examples/LineNumberView/Controller.m
@@ -0,0 +1,49 @@
+//
+// Controller.m
+// Line View Test
+//
+// Created by Paul Kim on 9/28/08.
+// Copyright (c) 2008 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import "Controller.h"
+#import "NoodleLineNumberView.h"
+#import "NoodleLineNumberMarker.h"
+#import "MarkerLineNumberView.h"
+
+@implementation Controller
+
+
+- (void)awakeFromNib
+{
+ lineNumberView = [[MarkerLineNumberView alloc] initWithScrollView:scrollView];
+ [scrollView setVerticalRulerView:lineNumberView];
+ [scrollView setHasHorizontalRuler:NO];
+ [scrollView setHasVerticalRuler:YES];
+ [scrollView setRulersVisible:YES];
+
+ [scriptView setFont:[NSFont userFixedPitchFontOfSize:[NSFont smallSystemFontSize]]];
+}
+
+@end
1 Examples/LineNumberView/Credits.rtf
BIN Examples/LineNumberView/English.lproj/InfoPlist.strings
Binary file not shown.
2,933 Examples/LineNumberView/English.lproj/MainMenu.xib
2,933 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
28 Examples/LineNumberView/LineNumberView-Info.plist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.noodlesoft.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
38 Examples/LineNumberView/MarkerLineNumberView.h
@@ -0,0 +1,38 @@
+//
+// MarkerTextView.h
+// Line View Test
+//
+// Created by Paul Kim on 10/4/08.
+// Copyright (c) 2008 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "NoodleLineNumberView.h"
+
+@interface MarkerLineNumberView : NoodleLineNumberView
+{
+ NSImage *markerImage;
+}
+
+@end
127 Examples/LineNumberView/MarkerLineNumberView.m
@@ -0,0 +1,127 @@
+//
+// MarkerTextView.m
+// Line View Test
+//
+// Created by Paul Kim on 10/4/08.
+// Copyright (c) 2008 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import "MarkerLineNumberView.h"
+#import "NoodleLineNumberMarker.h"
+
+#define CORNER_RADIUS 3.0
+#define MARKER_HEIGHT 13.0
+
+@implementation MarkerLineNumberView
+
+- (void)dealloc
+{
+ [markerImage release];
+
+ [super dealloc];
+}
+
+- (void)setRuleThickness:(CGFloat)thickness
+{
+ [super setRuleThickness:thickness];
+
+ // Overridden to reset the size of the marker image forcing it to redraw with the new width.
+ // If doing this in a non-subclass of NoodleLineNumberView, you can set it to post frame
+ // notifications and listen for them.
+ [markerImage setSize:NSMakeSize(thickness, MARKER_HEIGHT)];
+}
+
+- (void)drawMarkerImageIntoRep:(id)rep
+{
+ NSBezierPath *path;
+ NSRect rect;
+
+ rect = NSMakeRect(1.0, 2.0, [rep size].width - 2.0, [rep size].height - 3.0);
+
+ path = [NSBezierPath bezierPath];
+ [path moveToPoint:NSMakePoint(NSMaxX(rect), NSMinY(rect) + NSHeight(rect) / 2)];
+ [path lineToPoint:NSMakePoint(NSMaxX(rect) - 5.0, NSMaxY(rect))];
+
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect) + CORNER_RADIUS, NSMaxY(rect) - CORNER_RADIUS) radius:CORNER_RADIUS startAngle:90 endAngle:180];
+
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect) + CORNER_RADIUS, NSMinY(rect) + CORNER_RADIUS) radius:CORNER_RADIUS startAngle:180 endAngle:270];
+ [path lineToPoint:NSMakePoint(NSMaxX(rect) - 5.0, NSMinY(rect))];
+ [path closePath];
+
+ [[NSColor colorWithCalibratedRed:0.003 green:0.56 blue:0.85 alpha:1.0] set];
+ [path fill];
+
+ [[NSColor colorWithCalibratedRed:0 green:0.44 blue:0.8 alpha:1.0] set];
+
+ [path setLineWidth:2.0];
+ [path stroke];
+}
+
+- (NSImage *)markerImageWithSize:(NSSize)size
+{
+ if (markerImage == nil)
+ {
+ NSCustomImageRep *rep;
+
+ markerImage = [[NSImage alloc] initWithSize:size];
+ rep = [[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawMarkerImageIntoRep:) delegate:self];
+ [rep setSize:size];
+ [markerImage addRepresentation:rep];
+ [rep release];
+ }
+ return markerImage;
+}
+
+- (void)mouseDown:(NSEvent *)theEvent
+{
+ NSPoint location;
+ NSUInteger line;
+
+ location = [self convertPoint:[theEvent locationInWindow] fromView:nil];
+ line = [self lineNumberForLocation:location.y];
+
+ if (line != NSNotFound)
+ {
+ NoodleLineNumberMarker *marker;
+
+ marker = [self markerAtLine:line];
+
+ if (marker != nil)
+ {
+ [self removeMarker:marker];
+ }
+ else
+ {
+ marker = [[NoodleLineNumberMarker alloc] initWithRulerView:self
+ lineNumber:line
+ image:[self markerImageWithSize:NSMakeSize([self ruleThickness], MARKER_HEIGHT)]
+ imageOrigin:NSMakePoint(0, MARKER_HEIGHT / 2)];
+ [self addMarker:marker];
+ [marker release];
+ }
+ [self setNeedsDisplay:YES];
+ }
+}
+
+@end
130 Examples/LineNumberView/Read Me.rtf
@@ -0,0 +1,130 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf110
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Monaco;}
+{\colortbl;\red255\green255\blue255;}
+{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}
+{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}
+{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3}
+{\list\listtemplateid4\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid301\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid4}
+{\list\listtemplateid5\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid401\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid5}
+{\list\listtemplateid6\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid501\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid6}
+{\list\listtemplateid7\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid601\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid7}}
+{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}{\listoverride\listid5\listoverridecount0\ls5}{\listoverride\listid6\listoverridecount0\ls6}{\listoverride\listid7\listoverridecount0\ls7}}
+\vieww16040\viewh15820\viewkind0
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\b\fs24 \cf0 Line View Test
+\b0 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+This is a sample project and test harness for NoodleLineNumberView.\
+\
+NoodleLineNumberView is an NSRulerView subclass that will show line numbers when the document view of the scrollview is an NSTextView. It numbers logical lines, not visual ones. NoodleLineNumberMarker works in tandem with NoodleLineNumberView to display markers at specific lines.\
+\
+A discussion of this project can be found at: {\field{\*\fldinst{HYPERLINK "http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/"}}{\fldrslt http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/}}\
+\
+Notes:\
+\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls1\ilvl0\cf0 {\listtext \'95 }The view will expand it's width to accommodate the widths of the labels as needed.\
+{\listtext \'95 }The included subclass (MarkerLineNumberView) shows how to deal with markers. It also shows how to use an NSCustomImageRep to do the drawing. This allows you to reset the size of the image and have the drawing adjust as needed (this happens if the line number view changes width because the line numbers gained or lost a digit). If you decide to implement most of this stuff in an external class (not a subclass), you can set the line number view to post frame changed notifications and listen for them.\
+{\listtext \'95 }Note that markers are tied to numerical lines, not semantic ones. So, if you have a marker at line 50 and insert a new line at line 49, the marker will not shift to line 51 to point at the same line of text but will stay at line 50 pointing at whatever text is there now. Contrast with XCode where the markers move with insertions and deletions of lines (at least as best as it can). This is logic that you'll have to supply yourself.\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+To integrate NoodleLineNumberView, just create one and set it as the vertical ruler of the scrollview. Depending on the order of operations, you may need to set the client view of the NoodleLineNumberView to the NSTextView manually.\
+\
+This project actually uses a subclass of NoodleLineNumberView called MarkerLineNumberView. This class shows how one can integrate adding markers. Just click in the line number view to toggle a marker. It's more of an example than a reusable class since your markers may look different and you may have a different UI for adding them. Nonetheless, it shows the basics of how to do it.\
+\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\b \cf0 Possible Performance Improvements\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\b0 \cf0 \
+For performance, NoodleLineView keeps an array of the character indices for the start of each line. This gets recalculated whenever the text changes but at least it's cached for redisplays (such as scrolling around). It also only redraw the labels for the lines that are showing.\
+\
+It seems peppy enough for me, testing on a Powerbook 12" (G4) on Leopard. If you feel the need to optimize it further (I advise you Shark it first instead of making assumptions, though), here are some areas that could be improved:\
+\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls2\ilvl0\cf0 {\listtext \'95 }Right now, the character indices are recalculated every time the text changes. I only listen for a
+\f1 NSTextDidChangeNotification
+\f0 which is pretty coarse as there's no notion of what changed. You need to hook in deeper to get finer grained details of what characters were affected and see if the line indices need to be recalculated at all (check for whether a line ending was added or removed) or what particular lines should be recalculated (if a line was changed, only recalculate the lines after it).\
+{\listtext \'95 }The layout coordinates of each line can also be cached. If you tie into NSLayoutManager's delegate methods, you can find out when the layout has been invalidated. This would be helpful for cases where the view is scrolled or otherwise redisplayed without having the layout changed. Invalidations would happen in cases like when the view is resized in which case, you recalculate and recache. I have my doubts about whether this will save much but Shark it and find out.\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+The first two were not done because I wanted this subclass to be self-contained and not interfere with any delegates that may already be in place.\
+\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\b \cf0 Contact
+\b0 \
+\
+Just go {\field{\*\fldinst{HYPERLINK "http://www.noodlesoft.com/about.php"}}{\fldrslt www.noodlesoft.com}} and shoot me an email. Or visit the blog article linked above and leave a comment. Bugs, suggestions and other feedback appreciated.\
+\
+\
+
+\b License
+\b0 \
+\
+I am releasing this under the MIT license.\
+\
+____________________________________\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\f1 \cf0 Copyright (c) 2008-2009 Noodlesoft, LLC. All Rights Reserved.\
+\
+Permission is hereby granted, free of charge, to any person\
+obtaining a copy of this software and associated documentation\
+files (the "Software"), to deal in the Software without\
+restriction, including without limitation the rights to use,\
+copy, modify, merge, publish, distribute, sublicense, and/or sell\
+copies of the Software, and to permit persons to whom the\
+Software is furnished to do so, subject to the following\
+conditions:\
+\
+The above copyright notice and this permission notice shall be\
+included in all copies or substantial portions of the Software.\
+\
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\
+OTHER DEALINGS IN THE SOFTWARE.\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls3\ilvl0
+\f0\b \cf0 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+Changelog
+\b0 \
+\
+0.4.1:\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls4\ilvl0\cf0 {\listtext \'95 }Fixed display glitch when scrolling after the line number view resizes when linked against/running on 10.4. Apparently, NSRulerView's
+\f1 setRuleThickness:
+\f0 does not like non-integral values.\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+0.4:\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls5\ilvl0\cf0 {\listtext \'95 }Changed default font to use label font. Not sure if semantically, that's what XCode uses but it matches for the time being.\
+{\listtext \'95 }Fixed display bugs introduced in 0.3 when line number view resizes itself.\
+{\listtext \'95 }Added methods for setting various colors. The alternate text color is the color used by the line number label when a marker is drawn under it.\
+{\listtext \'95 }Miscellaneous tweaks.\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+0.3:\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls6\ilvl0\cf0 {\listtext \'95 }Now listens for NSTextStorage's NSTextStorageDidProcessEditingNotification instead of NSTextDidChangeNotification. The former includes programmatic changes to the text.\
+{\listtext \'95 }Was not taking text storage's inset into account when lining up labels. OSAScriptView, for one, had a non-zero inset. Should be fixed now.\
+{\listtext \'95 }Calculates lines lazily allowing multiple programmatic text changes to be batched up.\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+0.2:\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls7\ilvl0\cf0 {\listtext \'95 }Initial public release\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+}
14 Examples/LineNumberView/main.m
@@ -0,0 +1,14 @@
+//
+// main.m
+// Line View Test
+//
+// Created by Paul Kim on 10/5/08.
+// Copyright Noodlesoft, LLC 2008. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ return NSApplicationMain(argc, (const char **) argv);
+}
22 Examples/ModalResponder/Controller.h
@@ -0,0 +1,22 @@
+//
+// Controller.h
+// ModalResponderTest
+//
+// Created by Paul Kim on 3/6/08.
+// Copyright 2008-2009 Noodlesoft, LLC. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface Controller : NSObject
+{
+ IBOutlet id window;
+ IBOutlet id alert;
+ IBOutlet id field;
+}
+
+- (IBAction)doModal:sender;
+- (IBAction)doSheet:sender;
+
+@end
62 Examples/ModalResponder/Controller.m
@@ -0,0 +1,62 @@
+//
+// Controller.m
+// ModalResponderTest
+//
+// Created by Paul Kim on 3/6/08.
+// Copyright 2008-2009 Noodlesoft, LLC. All rights reserved.
+//
+
+#import "Controller.h"
+
+
+@implementation Controller
+
+- (IBAction)doModal:sender
+{
+ NSInteger returnCode;
+
+ [field setStringValue:@""];
+
+ returnCode = [NSApp runModalForWindow:alert];
+
+ if (returnCode == NSOKButton)
+ {
+ [field setStringValue:@"OK!"];
+ }
+ else
+ {
+ [field setStringValue:@"Cancel"];
+ }
+}
+
+
+- (IBAction)doSheet:sender
+{
+ [field setStringValue:@""];
+
+ [NSApp beginSheet:alert modalForWindow:window modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:nil];
+ //PENDING
+/*
+ NSLog(@"ALERT: %@", alert);
+ NSLog(@"PARENT: %@", [alert parentWindow]);
+ NSLog(@"SHEET: %@", [[alert parentWindow] attachedSheet]);
+ NSLog(@"WINDOW: %@", window);
+ NSLog(@"CHILD: %@", [window childWindows]);
+ NSLog(@"ALERT CHILD: %@", [alert childWindows]);
+ NSLog(@"ATTACHED: %@", [window attachedSheet]);
+*/
+}
+
+- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
+{
+ if (returnCode == NSOKButton)
+ {
+ [field setStringValue:@"OK!"];
+ }
+ else
+ {
+ [field setStringValue:@"Cancel"];
+ }
+}
+
+@end
1 Examples/ModalResponder/Credits.rtf
BIN Examples/ModalResponder/English.lproj/InfoPlist.strings
Binary file not shown.
3,350 Examples/ModalResponder/English.lproj/MainMenu.xib
3,350 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
28 Examples/ModalResponder/ModalResponder-Info.plist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.noodlesoft.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
34 Examples/ModalResponder/Read Me.rtf
@@ -0,0 +1,34 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf110
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Monaco;\f2\fmodern\fcharset0 Courier;
+}
+{\colortbl;\red255\green255\blue255;}
+\margl1440\margr1440\vieww15820\viewh15260\viewkind0
+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural
+
+\f0\b\fs24 \cf0 ModalResponder
+\b0 \
+\
+This is a simple demo of an NSResponder category which deals with modal windows and sheets. If you are creating a modal window or sheet that has "OK" and "Cancel" buttons, you most likely end up writing some glue method that just orders the window out and returns a code. This category makes it so that all you have to do is hook up the buttons to either the
+\f1\fs22 -confirmModal:
+\f0\fs24 or
+\f1\fs22 -cancelModal:
+\f0\fs24 actions on the First Responder in Interface Builder. The methods will set a return code of NSOKButton and NSCancelButton respectively. No extra glue though you may have to add the methods to NSResponder in IB.\
+\
+For more details check out the related blog post at http://www.noodlesoft.com/blog/2008/03/10/modal-glue/\
+\
+Enjoy.\
+\
+Paul Kim\
+http://www.noodlesoft.com\
+\
+========================================\
+\
+This code is provided for free under the terms of the MIT license:\
+\
+\pard\pardeftab720\sl360\sa180\ql\qnatural
+
+\f2 \cf0 Copyright (c) 2008-2009 Noodlesoft, LLC. All Rights Reserved\
+Permission is hereby granted, free of charge, to any person obtaining a copy\uc0\u8232 of this software and associated documentation files (the "Software"), to deal\u8232 in the Software without restriction, including without limitation the rights\u8232 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\u8232 copies of the Software, and to permit persons to whom the Software is\u8232 furnished to do so, subject to the following conditions:\
+The above copyright notice and this permission notice shall be included in\uc0\u8232 all copies or substantial portions of the Software.\
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\uc0\u8232 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\u8232 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\u8232 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\u8232 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\u8232 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\u8232 THE SOFTWARE.\
+}
14 Examples/ModalResponder/main.m
@@ -0,0 +1,14 @@
+//
+// main.m
+// ModalResponderTest
+//
+// Created by Paul Kim on 3/6/08.
+// Copyright __MyCompanyName__ 2008. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ return NSApplicationMain(argc, (const char **) argv);
+}
39 Examples/StickyRowTableView Revue/Controller.h
@@ -0,0 +1,39 @@
+//
+// Controller.h
+//
+// Created by Paul Kim on 8/21/09.
+// Copyright 2009 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface Controller : NSObject
+{
+ IBOutlet NSTableView *_stickyRowTableView;
+ IBOutlet NSTableView *_iPhoneTableView;
+ NSMutableArray *_names;
+}
+
+@end
95 Examples/StickyRowTableView Revue/Controller.m
@@ -0,0 +1,95 @@
+//
+// Controller.m
+//
+// Created by Paul Kim on 8/21/09.
+// Copyright 2009 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import "Controller.h"
+
+@implementation Controller
+
+- (void)awakeFromNib
+{
+ NSString *fileContents;
+ NSUInteger i, count;
+ NSString *temp, *prefix, *currentPrefix;
+ NSArray *words;
+
+ fileContents = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames" usedEncoding:NULL error:NULL];
+ words = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
+
+ [self willChangeValueForKey:@"names"];
+
+ words = [words sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
+ _names = [[NSMutableArray alloc] init];
+
+ count = [words count];
+ currentPrefix = nil;
+ for (i = 0; i < count; i++)
+ {
+ temp = [words objectAtIndex:i];
+
+ if ([temp length] > 0)
+ {
+ prefix = [temp substringToIndex:1];
+
+ if ((currentPrefix == nil) ||
+ ([currentPrefix caseInsensitiveCompare:prefix] != NSOrderedSame))
+ {
+ currentPrefix = [prefix uppercaseString];
+ [_names addObject:currentPrefix];
+ }
+ [_names addObject:temp];
+ }
+ }
+
+ [_stickyRowTableView reloadData];
+ [_iPhoneTableView reloadData];
+}
+
+- (BOOL)_isHeader:(NSInteger)rowIndex
+{
+ return ((rowIndex == 0) ||
+ [[[_names objectAtIndex:rowIndex] substringToIndex:1] caseInsensitiveCompare:[[_names objectAtIndex:rowIndex - 1] substringToIndex:1]] != NSOrderedSame);
+}
+
+#pragma mark NSTableDataSource methods
+
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
+{
+ return [_names count];
+}
+
+- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
+{
+ return [_names objectAtIndex:rowIndex];
+}
+
+- (BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row
+{
+ return [self _isHeader:row];
+}
+
+@end
1 Examples/StickyRowTableView Revue/Credits.rtf
BIN Examples/StickyRowTableView Revue/English.lproj/InfoPlist.strings
Binary file not shown.
4,245 Examples/StickyRowTableView Revue/English.lproj/MainMenu.xib
4,245 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
110 Examples/StickyRowTableView Revue/Read Me.rtf
@@ -0,0 +1,110 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf110
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Monaco;}
+{\colortbl;\red255\green255\blue255;}
+{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}
+{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}
+{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3}
+{\list\listtemplateid4\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid301\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid4}
+{\list\listtemplateid5\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid401\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid5}}
+{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}{\listoverride\listid5\listoverridecount0\ls5}}
+\margl1440\margr1440\vieww19360\viewh17460\viewkind0
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\b\fs24 \cf0 NoodleStickyRowTableView Test
+\b0 \
+version 0.18369\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+This is a sample project and test harness for NoodleStickyRowTableView.\
+\
+NoodleStickyRowTableView is an NSTableView subclass where group rows (this can be overridden) will "stick" to the top of the view when they scroll off. This is like how section headers will stick to the top in UITableViews on the iPhone.\
+\
+Almost all of it is accomplished via an NSTableView category. The reason it was done this way was so that (a) you could integrate it into your own NSTableView subclass easily and (b) you could gain the functionality in NSOutlineView and its subclasses as well. To get the basic functionality, all you need to do is subclass
+\f1 -drawRect:
+\f0 and call
+\f1 -drawStickyRowHeader
+\f0 after your call to
+\f1 super
+\f0 . Look at the very minimal NoodleStickyRowTableView class for details.\
+\
+This project also includes NoodleIPhoneTableView which overrides a bit more to simulate the look and feel of UITableView.\
+\
+A blog post on this can be found at: {\field{\*\fldinst{HYPERLINK "http://www.noodlesoft.com/blog/2009/09/25/sticky-section-headers-in-nstableview"}}{\fldrslt http://www.noodlesoft.com/blog/2009/09/25/sticky-section-headers-in-nstableview}}\
+\
+Notes:\
+\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls1\ilvl0\cf0 {\listtext \'95 }As noted in the article linked above, limitations in being able to get a visual cache of a group row forced me to compromise and use a custom look for the sticky rows in the default implementation. As shown in the NoodleIPhoneTableView class, you can override all the drawing but it requires a bit more work.\
+{\listtext \'95 }The sticky row header is implemented using an NSButton. The row is drawn into an image that is set on the button. The button is adjusted as needed, including whether it is enabled and therefore able to accept mouse clicks.\
+{\listtext \'95 }To keep things in a category, the auxiliary button is put in the view hierarchy. It is tagged so that it can be retrieved later. This is further exploited where, for optimization purposes, the alternate image property of NSButton, which would otherwise go unused, is used as a cache.\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\b \cf0 Possible Improvements\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\b0 \cf0 \
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls2\ilvl0\cf0 {\listtext \'95 }You can keep track of the last sticky row that was cached and reuse its image if it hasn't changed. I had actually implemented this but the performance gains were actually very minimal. For purposes of clarity, I took the code out but you can implement this if you need to eek out the last bit of performance.\
+{\listtext \'95 }The fade-in transition is position based (it fades in as you scroll down). It might be better to make it time-based.\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\b \cf0 Contact
+\b0 \
+\
+Just go {\field{\*\fldinst{HYPERLINK "http://www.noodlesoft.com/about.php"}}{\fldrslt www.noodlesoft.com}} and shoot me an email. Or visit the blog article linked above and leave a comment. Bugs, suggestions and other feedback appreciated.\
+\
+\
+
+\b License
+\b0 \
+\
+I am releasing this under the MIT license.\
+\
+____________________________________\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\f1 \cf0 Copyright (c) 2009 Noodlesoft, LLC. All Rights Reserved.\
+\
+Permission is hereby granted, free of charge, to any person\
+obtaining a copy of this software and associated documentation\
+files (the "Software"), to deal in the Software without\
+restriction, including without limitation the rights to use,\
+copy, modify, merge, publish, distribute, sublicense, and/or sell\
+copies of the Software, and to permit persons to whom the\
+Software is furnished to do so, subject to the following\
+conditions:\
+\
+The above copyright notice and this permission notice shall be\
+included in all copies or substantial portions of the Software.\
+\
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\
+OTHER DEALINGS IN THE SOFTWARE.\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls3\ilvl0
+\f0\b \cf0 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+Changelog
+\b0 \
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls4\ilvl0\cf0 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+0.18369:\
+\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural
+\ls5\ilvl0\cf0 {\listtext \'95 }Initial public release\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+\cf0 \
+}
28 Examples/StickyRowTableView Revue/StickyRowTableView Revue-Info.plist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.noodlesoft.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
14 Examples/StickyRowTableView Revue/main.m
@@ -0,0 +1,14 @@
+//
+// main.m
+// NoodleStickyRowTableViewTest
+//
+// Created by Paul Kim on 8/23/09.
+// Copyright Noodlesoft, LLC 2009. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ return NSApplicationMain(argc, (const char **) argv);
+}
12 Examples/Window Effects/Controller.h
@@ -0,0 +1,12 @@
+/* Controller */
+
+#import <Cocoa/Cocoa.h>
+
+@interface Controller : NSObject
+{
+ IBOutlet id _window;
+}
+
+- (IBAction)toggleWindow:sender;
+
+@end
23 Examples/Window Effects/Controller.m
@@ -0,0 +1,23 @@
+#import "Controller.h"
+#import "NSWindow-NoodleEffects.h"
+
+@implementation Controller
+
+- (IBAction)toggleWindow:sender
+{
+ NSRect rect;
+
+ rect = [sender convertRect:[sender bounds] toView:nil];
+ rect.origin = [[sender window] convertBaseToScreen:rect.origin];
+
+ if ([_window isVisible])
+ {
+ [_window zoomOffToRect:rect];
+ }
+ else
+ {
+ [_window zoomOnFromRect:rect];
+ }
+}
+
+@end
BIN Examples/Window Effects/English.lproj/InfoPlist.strings
Binary file not shown.
2,611 Examples/Window Effects/English.lproj/MainMenu.xib
2,611 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
28 Examples/Window Effects/Window Effects-Info.plist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.noodlesoft.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
14 Examples/Window Effects/main.m
@@ -0,0 +1,14 @@
+//
+// main.m
+// WindowZoom
+//
+// Created by Paul Kim on 6/18/07.
+// Copyright __MyCompanyName__ 2007. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ return NSApplicationMain(argc, (const char **) argv);
+}
28 Info.plist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.noodlesoft.${PRODUCT_NAME:rfc1034Identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>NSPrincipalClass</key>
+ <string></string>
+</dict>
+</plist>
76 NSImage-NoodleExtensions.h
@@ -0,0 +1,76 @@
+//
+// NSImage-NoodleExtensions.h
+// NoodleKit
+//
+// Created by Paul Kim on 3/24/07.
+// Copyright 2007-2009 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#import <Cocoa/Cocoa.h>
+
+
+/*
+ This category provides methods for dealing with flipped images. These should draw images correctly regardless of
+ whether the current context or the current image are flipped. Unless you know what you are doing, these should be used
+ in lieu of the normal NSImage drawing/compositing methods.
+
+ For more details, check out the related blog post at http://www.noodlesoft.com/blog/2009/02/02/understanding-flipped-coordinate-systems/
+ */
+
+@interface NSImage (NoodleExtensions)
+
+/*!
+ @method drawAdjustedAtPoint:fromRect:operation:fraction:
+ @abstract Draws all or part of the image at the specified point in the current coordinate system. Unlike other methods in NSImage, this will orient the image properly in flipped coordinate systems.
+ @param point The location in the current coordinate system at which to draw the image.
+ @param srcRect The source rectangle specifying the portion of the image you want to draw. The coordinates of this rectangle are specified in the image's own coordinate system. If you pass in NSZeroRect, the entire image is drawn.
+ @param op The compositing operation to use when drawing the image. See the NSCompositingOperation constants.
+ @param delta The opacity of the image, specified as a value from 0.0 to 1.0. Specifying a value of 0.0 draws the image as fully transparent while a value of 1.0 draws the image as fully opaque. Values greater than 1.0 are interpreted as 1.0.
+ @discussion The image content is drawn at its current resolution and is not scaled unless the CTM of the current coordinate system itself contains a scaling factor. The image is otherwise positioned and oriented using the current coordinate system, except that it takes the flipped status into account, drawing right-side-up in a such a case.
+
+ Unlike the compositeToPoint:fromRect:operation: and compositeToPoint:fromRect:operation:fraction: methods, this method checks the rectangle you pass to the srcRect parameter and makes sure it does not lie outside the image bounds.
+ */
+- (void)drawAdjustedAtPoint:(NSPoint)aPoint fromRect:(NSRect)srcRect operation:(NSCompositingOperation)op fraction:(CGFloat)delta;
+
+/*!
+ @method drawAdjustedInRect:fromRect:operation:fraction:
+ @abstract Draws all or part of the image in the specified rectangle in the current coordinate system. Unlike other methods in NSImage, this will orient the image properly in flipped coordinate systems.
+ @param dstRect The rectangle in which to draw the image, specified in the current coordinate system.
+ @param srcRect The source rectangle specifying the portion of the image you want to draw. The coordinates of this rectangle must be specified using the image's own coordinate system. If you pass in NSZeroRect, the entire image is drawn.
+ @param op The compositing operation to use when drawing the image. See the NSCompositingOperation constants.
+ @param delta The opacity of the image, specified as a value from 0.0 to 1.0. Specifying a value of 0.0 draws the image as fully transparent while a value of 1.0 draws the image as fully opaque. Values greater than 1.0 are interpreted as 1.0.
+ @discussion If the srcRect and dstRect rectangles have different sizes, the source portion of the image is scaled to fit the specified destination rectangle. The image is otherwise positioned and oriented using the current coordinate system, except that it takes the flipped status into account, drawing right-side-up in a such a case.
+
+ Unlike the compositeToPoint:fromRect:operation: and compositeToPoint:fromRect:operation:fraction: methods, this method checks the rectangle you pass to the srcRect parameter and makes sure it does not lie outside the image bounds.
+ */
+- (void)drawAdjustedInRect:(NSRect)dstRect fromRect:(NSRect)srcRect operation:(NSCompositingOperation)op fraction:(CGFloat)delta;
+
+/*!
+ @method unflippedImage
+ @abstract Returns a version of the receiver but unflipped.
+ @discussion This does not actually flip the image but returns an image with the same orientation but with an unflipped coordinate system internally (isFlipped returns NO). If the image is already unflipped, this method returns self.
+ */
+- (NSImage *)unflippedImage;
+
+
+@end
89 NSImage-NoodleExtensions.m
@@ -0,0 +1,89 @@
+//
+// NSImage-NoodleExtensions.m
+// NoodleKit
+//
+// Created by Paul Kim on 3/24/07.
+// Copyright 2007-2009 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#import "NSImage-NoodleExtensions.h"
+
+
+@implementation NSImage (NoodleExtensions)
+
+- (void)drawAdjustedAtPoint:(NSPoint)aPoint fromRect:(NSRect)srcRect operation:(NSCompositingOperation)op fraction:(CGFloat)delta
+{
+ NSSize size = [self size];
+
+ [self drawAdjustedInRect:NSMakeRect(aPoint.x, aPoint.y, size.width, size.height) fromRect:srcRect operation:op fraction:delta];
+}
+
+- (void)drawAdjustedInRect:(NSRect)dstRect fromRect:(NSRect)srcRect operation:(NSCompositingOperation)op fraction:(CGFloat)delta
+{
+ NSGraphicsContext *context;
+ BOOL contextIsFlipped;
+
+ context = [NSGraphicsContext currentContext];
+ contextIsFlipped = [context isFlipped];
+
+ if (contextIsFlipped)
+ {
+ NSAffineTransform *transform;
+
+ [context saveGraphicsState];
+
+ // Flip the coordinate system back.
+ transform = [NSAffineTransform transform];
+ [transform translateXBy:0 yBy:NSMaxY(dstRect)];
+ [transform scaleXBy:1 yBy:-1];
+ [transform concat];
+
+ // The transform above places the y-origin right where the image should be drawn.
+ dstRect.origin.y = 0.0;
+ }
+
+ [self drawInRect:dstRect fromRect:srcRect operation:op fraction:delta];
+
+ if (contextIsFlipped)
+ {
+ [context restoreGraphicsState];
+ }
+}
+
+- (NSImage *)unflippedImage
+{
+ if ([self isFlipped])
+ {
+ NSImage *newImage;
+
+ newImage = [[[NSImage alloc] initWithSize:[self size]] autorelease];
+ [newImage lockFocus];
+ [self drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];
+ [newImage unlockFocus];
+
+ return newImage;
+ }
+ return self;
+}
+
+@end
34 NSObject-NoodlePerformWhenIdle.h
@@ -0,0 +1,34 @@
+//
+// NSObject-IdleExtensions.h
+// NoodleKit
+//
+// Created by Paul Kim on 12/30/07.
+// Copyright 2007 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Cocoa/Cocoa.h>
+
+@interface NSObject (NoodlePerformWhenIdle)
+
+- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterSystemIdleTime:(NSTimeInterval)delay;
+
+- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterSystemIdleTime:(NSTimeInterval)delay withinTimeLimit:(NSTimeInterval)maxTime;
+
+@end
114 NSObject-NoodlePerformWhenIdle.m
@@ -0,0 +1,114 @@
+//
+// NSObject-IdleExtensions.m
+// NoodleKit
+//
+// Created by Paul Kim on 12/30/07.
+// Copyright 2007 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "NSObject-NoodlePerformWhenIdle.h"
+#import <ApplicationServices/ApplicationServices.h>
+
+@implementation NSObject (NoodlePerformWhenIdle)
+
+// Heard somewhere that this prototype may be missing in some cases so adding it here just in case.
+CG_EXTERN CFTimeInterval CGEventSourceSecondsSinceLastEventType( CGEventSourceStateID source, CGEventType eventType ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+
+// Semi-private method. Used by the public methods
+- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterSystemIdleTime:(NSTimeInterval)delay withinTimeLimit:(NSTimeInterval)maxTime startTime:(NSTimeInterval)startTime
+{
+ CFTimeInterval idleTime;
+ NSTimeInterval timeSinceInitialCall;
+
+ if (maxTime > 0)
+ {
+ timeSinceInitialCall = [NSDate timeIntervalSinceReferenceDate] - startTime;
+
+ if (timeSinceInitialCall >= maxTime)
+ {
+ [self performSelector:aSelector withObject:anArgument];
+ return;
+ }
+ }
+
+ idleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType);
+ if (idleTime < delay)
+ {
+ NSTimeInterval fireTime;
+ NSMethodSignature *signature;
+ NSInvocation *invocation;
+
+ signature = [self methodSignatureForSelector:@selector(performSelector:withObject:afterSystemIdleTime:withinTimeLimit:startTime:)];
+ invocation = [NSInvocation invocationWithMethodSignature:signature];
+ [invocation setSelector:@selector(performSelector:withObject:afterSystemIdleTime:withinTimeLimit:startTime:)];
+ [invocation setTarget:self];
+ [invocation setArgument:&aSelector atIndex:2];
+ [invocation setArgument:&anArgument atIndex:3];
+ [invocation setArgument:&delay atIndex:4];
+ [invocation setArgument:&maxTime atIndex:5];
+ [invocation setArgument:&startTime atIndex:6];
+
+ fireTime = delay - idleTime;
+ if (maxTime > 0)
+ {
+ fireTime = MIN(fireTime, maxTime - timeSinceInitialCall);
+ }
+
+ // Not idle for long enough. Set a timer and check back later
+ [NSTimer scheduledTimerWithTimeInterval:fireTime invocation:invocation repeats:NO];
+ }
+ else
+ {
+ [self performSelector:aSelector withObject:anArgument];
+ }
+}
+
+
+- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterSystemIdleTime:(NSTimeInterval)delay
+{
+ [self performSelector:aSelector withObject:anArgument afterSystemIdleTime:delay withinTimeLimit:-1];
+}
+
+
+- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterSystemIdleTime:(NSTimeInterval)delay withinTimeLimit:(NSTimeInterval)maxTime
+{
+ SInt32 version;
+
+ // NOTE: Even though CGEventSourceSecondsSinceLastEventType exists on Tiger,
+ // it appears to hang on some Tiger systems. For now, only enabling for Leopard or later.
+ if ((Gestalt(gestaltSystemVersion, &version) == noErr) && (version >= 0x1050))
+ {
+ NSTimeInterval startTime;
+
+ startTime = [NSDate timeIntervalSinceReferenceDate];
+
+ [self performSelector:aSelector withObject:anArgument afterSystemIdleTime:delay withinTimeLimit:maxTime startTime:startTime];
+ }
+ else
+ {
+ // For pre-10.5, just call it after a delay. Change this if you want to throw an exception
+ // instead.
+ [self performSelector:aSelector withObject:anArgument afterDelay:delay];
+ }
+}
+
+
+@end
50 NSResponder-NoodleModalExtensions.h
@@ -0,0 +1,50 @@
+//
+// NSResponder-ModalExtensions.h
+// NoodleKit
+//
+// Created by Paul Kim on 3/6/08.
+// Copyright 2008-2009 Noodlesoft, LLC. All rights reserved.
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// ncopies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Cocoa/Cocoa.h>
+
+/*
+ These categories provide simple methods to handle alert dialogs (window or sheet form). Hook your "OK" and "Cancel"
+ buttons to these methods to the first responder in IB and you're done. The modal session will return NSOKButton or
+ NSCancelButton. I'll leave it to you to figure out which one does what.
+
+ For more details, check out the related blog post at http://www.noodlesoft.com/blog/2008/03/10/modal-glue/
+ */
+
+
+@interface NSResponder (NoodleModalExtensions)
+
+- (void)confirmModal:(id)sender;
+- (void)cancelModal:(id)sender;
+
+@end
+
+@interface NSWindow (NoodleModalExtensions)
+
+- (void)confirmModal:(id)sender;
+- (void)cancelModal:(id)sender;
+
+@end
87 NSResponder-NoodleModalExtensions.m
@@ -0,0 +1,87 @@
+//
+// NSResponder-ModalExtensions.m
+// NoodleKit
+//
+// Created by Paul Kim on 3/6/08.
+// Copyright 2008-2009 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// ncopies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "NSResponder-NoodleModalExtensions.h"
+
+
+@implementation NSResponder (NoodleModalExtensions)
+
+
+- (void)confirmModal:(id)sender
+{
+ [[self nextResponder] confirmModal:sender];
+}
+
+- (void)cancelModal:(id)sender
+{
+ [[self nextResponder] cancelModal:sender];
+}
+
+@end
+
+@implementation NSWindow (NoodleModalExtensions)
+
+- (BOOL)stopModalWindowOrSheetWithCode:(NSInteger)returnCode sender:(id)sender
+{
+ if ([NSApp modalWindow] == self)
+ {
+ [self orderOut:sender];
+ [NSApp stopModalWithCode:returnCode];
+ return YES;
+ }
+ else if ([self isSheet])
+ {
+ [self orderOut:sender];
+ [NSApp endSheet:self returnCode:returnCode];
+ return YES;
+ }
+ else if ([self attachedSheet] != nil)
+ {
+ NSWindow *sheet;
+
+ sheet = [self attachedSheet];
+ [sheet orderOut:sender];
+ [NSApp endSheet:sheet returnCode:returnCode];
+ }
+ return NO;
+}
+
+- (void)confirmModal:(id)sender
+{
+ if (![self stopModalWindowOrSheetWithCode:NSOKButton sender:sender])
+ {
+ [[self nextResponder] confirmModal:sender];
+ }
+}
+
+- (void)cancelModal:(id)sender
+{
+ if (![self stopModalWindowOrSheetWithCode:NSCancelButton sender:sender])
+ {
+ [[self nextResponder] cancelModal:self];
+ }
+}
+
+@end
45 NSWindow-NoodleEffects.h
@@ -0,0 +1,45 @@
+//
+// NSWindow-Zoom.h
+// NoodleKit
+//
+// Created by Paul Kim on 6/18/07.
+// Copyright 2007-2009 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import <Cocoa/Cocoa.h>
+
+/*
+ Provides a "zoom" animation for windows when ordering on and off screen.
+
+ For more details, check out the related blog posts at http://www.noodlesoft.com/blog/2007/06/30/animation-in-the-time-of-tiger-part-1/ and http://www.noodlesoft.com/blog/2007/09/20/animation-in-the-time-of-tiger-part-3/
+ */
+
+@interface NSWindow (NoodleEffects)
+
+- (void)animateToFrame:(NSRect)frameRect duration:(NSTimeInterval)duration;
+
+- (void)zoomOnFromRect:(NSRect)startRect;
+- (void)zoomOffToRect:(NSRect)endRect;
+
+@end
158 NSWindow-NoodleEffects.m
@@ -0,0 +1,158 @@
+//
+// NSWindow-Zoom.m
+// NoodleKit
+//
+// Created by Paul Kim on 6/18/07.
+// Copyright 2007-2009 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import "NSWindow-NoodleEffects.h"
+#import <Carbon/Carbon.h>
+
+
+@implementation NSWindow (NoodleEffects)
+
+- (void)animateToFrame:(NSRect)frameRect duration:(NSTimeInterval)duration
+{
+ NSViewAnimation *animation;
+
+ animation = [[NSViewAnimation alloc] initWithViewAnimations:
+ [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
+ self, NSViewAnimationTargetKey,
+ [NSValue valueWithRect:frameRect], NSViewAnimationEndFrameKey, nil]]];
+
+ [animation setDuration:duration];
+ [animation setAnimationBlockingMode:NSAnimationBlocking];
+ [animation setAnimationCurve:NSAnimationLinear];
+ [animation startAnimation];
+
+ [animation release];
+}
+
+- (NSWindow *)_createZoomWindowWithRect:(NSRect)rect
+{
+ NSWindow *zoomWindow;
+ NSImageView *imageView;
+ NSImage *image;
+ NSRect frame;
+ BOOL isOneShot;
+
+ frame = [self frame];
+
+ isOneShot = [self isOneShot];
+ if (isOneShot)
+ {
+ [self setOneShot:NO];
+ }
+
+ if ([self windowNumber] <= 0)
+ {
+ CGFloat alpha;
+
+ // Force creation of window device by putting it on-screen. We make it transparent to minimize the chance of
+ // visible flicker.
+ alpha = [self alphaValue];
+ [self setAlphaValue:0.0];
+ [self orderBack:self];
+ [self orderOut:self];
+ [self setAlphaValue:alpha];
+ }
+
+ image = [[NSImage alloc] initWithSize:frame.size];
+ [image lockFocus];
+ // Grab the window's pixels
+ NSCopyBits([self gState], NSMakeRect(0.0, 0.0, frame.size.width, frame.size.height), NSZeroPoint);
+ [image unlockFocus];
+ [image setDataRetained:YES];
+ [image setCacheMode:NSImageCacheNever];
+
+ zoomWindow = [[NSWindow alloc] initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
+ [zoomWindow setBackgroundColor:[NSColor colorWithDeviceWhite:0.0 alpha:0.0]];
+ [zoomWindow setHasShadow:[self hasShadow]];
+ [zoomWindow setLevel:[self level]];
+ [zoomWindow setOpaque:NO];
+ [zoomWindow setReleasedWhenClosed:YES];
+ [zoomWindow useOptimizedDrawing:YES];
+
+ imageView = [[NSImageView alloc] initWithFrame:[zoomWindow contentRectForFrameRect:frame]];
+ [imageView setImage:image];
+ [imageView setImageFrameStyle:NSImageFrameNone];
+ [imageView setImageScaling:NSScaleToFit];
+ [imageView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
+
+ [zoomWindow setContentView:imageView];
+ [image release];
+ [imageView release];
+
+ // Reset one shot flag
+ [self setOneShot:isOneShot];
+
+ return zoomWindow;
+}
+
+- (void)zoomOnFromRect:(NSRect)startRect
+{
+ NSRect frame;
+ NSWindow *zoomWindow;
+
+ if ([self isVisible])
+ {
+ return;
+ }
+
+ frame = [self frame];
+
+ zoomWindow = [self _createZoomWindowWithRect:startRect];
+
+ [zoomWindow orderFront:self];
+
+ [zoomWindow animateToFrame:frame duration:[zoomWindow animationResizeTime:frame] * 0.4];
+
+ [self makeKeyAndOrderFront:self];
+ [zoomWindow close];
+}
+
+- (void)zoomOffToRect:(NSRect)endRect
+{
+ NSRect frame;
+ NSWindow *zoomWindow;
+
+ frame = [self frame];
+
+ if (![self isVisible])
+ {
+ return;
+ }
+
+ zoomWindow = [self _createZoomWindowWithRect:frame];
+
+ [zoomWindow orderFront:self];
+ [self orderOut:self];
+
+ [zoomWindow animateToFrame:endRect duration:[zoomWindow animationResizeTime:endRect] * 0.4];
+
+ [zoomWindow close];
+}
+
+@end
43 NoodleIPhoneTableView.h
@@ -0,0 +1,43 @@
+//
+// NoodleIPhoneTableView.h
+// NoodleKit
+//
+// Created by Paul Kim on 9/22/09.
+// Copyright 2009 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import <Cocoa/Cocoa.h>
+
+/*
+ Simulates UITableView's look and feel.
+
+ For more details, see the related blog post at http://www.noodlesoft.com/blog/2009/09/25/sticky-section-headers-in-nstableview/
+ */
+
+@interface NoodleIPhoneTableView : NSTableView
+{
+ BOOL _isDrawingStickyRow;
+}
+
+@end
158 NoodleIPhoneTableView.m
@@ -0,0 +1,158 @@
+//
+// NoodleIPhoneTableView.m
+// NoodleKit
+//
+// Created by Paul Kim on 9/22/09.
+// Copyright 2009 Noodlesoft, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import "NoodleIPhoneTableView.h"
+#import "NoodleStickyRowTableView.h"
+
+@implementation NoodleIPhoneTableView
+
+- (id)initWithFrame:(NSRect)frameRect
+{
+ if ((self = [super initWithFrame:frameRect]) != nil)
+ {
+ [self setGridColor:[NSColor colorWithCalibratedWhite:0.849 alpha:1.0]];
+ [self setGridStyleMask:NSTableViewSolidHorizontalGridLineMask];
+ }
+ return self;
+}
+
+- (id)initWithCoder:(NSCoder *)decoder
+{
+ if ((self = [super initWithCoder:decoder]) != nil)
+ {
+ [self setGridColor:[NSColor colorWithCalibratedWhite:0.849 alpha:1.0]];
+ [self setGridStyleMask:NSTableViewSolidHorizontalGridLineMask];
+ }
+ return self;
+}
+
+- (void)drawRect:(NSRect)rect
+{
+ [super drawRect:rect];
+
+ [self drawStickyRowHeader];
+}
+
+// Since we are going to ensure that the regular and sticky versions of a row
+// look the same, no transition is needed here.
+- (NoodleStickyRowTransition)stickyRowHeaderTransition
+{
+ return NoodleStickyRowTransitionNone;
+}
+
+- (void)drawRow:(NSInteger)rowIndex clipRect:(NSRect)clipRect
+{
+ if ([self isRowSticky:rowIndex])
+ {
+ NSRect rowRect, cellRect;
+ NSUInteger colIndex, count;
+ NSCell *cell;
+ NSGradient *gradient;
+ NSAttributedString *attrString;
+ NSShadow *textShadow;
+ NSBezierPath *path;
+ NSDictionary *attributes;
+
+ rowRect = [self rectOfRow:rowIndex];
+
+ if (!_isDrawingStickyRow)
+ {
+ // Note that NSTableView will still draw the special background that it does
+ // for group row so we re-draw the background over it.
+ [self drawBackgroundInClipRect:rowRect];
+
+ if (NSIntersectsRect(rowRect, [self stickyRowHeaderRect]))
+ {
+ // You can barely notice it but if the sticky view is showing, the actual
+ // row it represents is still seen underneath. We check for this and don't
+ // draw the row in such a case.
+ return;
+ }
+ }
+
+ gradient = [[NSGradient alloc] initWithStartingColor:
+ [NSColor colorWithCalibratedRed:0.490 green:0.556 blue:0.600 alpha:0.9]
+ endingColor:[NSColor colorWithCalibratedRed:0.665 green:0.706 blue:0.738 alpha:0.9]];
+
+ [gradient drawInRect:rowRect angle:90];
+ [gradient release];
+
+ textShadow = [[NSShadow alloc] init];
+ [textShadow setShadowOffset:NSMakeSize(1.0, -1.0)];
+ [textShadow setShadowColor:[NSColor colorWithCalibratedWhite:0.5 alpha:1.0]];
+ [textShadow setShadowBlurRadius:0.0];
+
+ attributes = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSFont fontWithName:@"Helvetica" size:16.0],
+ NSFontAttributeName,
+ textShadow,
+ NSShadowAttributeName,
+ [NSColor whiteColor],
+ NSForegroundColorAttributeName,
+ nil];
+ [textShadow release];
+
+ count = [self numberOfColumns];
+ for (colIndex = 0; colIndex < count; colIndex++)
+ {
+ cell = [self preparedCellAtColumn:colIndex row:rowIndex];
+
+ attrString = [[NSAttributedString alloc] initWithString:[cell stringValue] attributes:attributes];
+
+ cellRect = [self frameOfCellAtColumn:colIndex row:rowIndex];
+
+ [cell setAttributedStringValue:attrString];
+ [cell drawWithFrame:cellRect inView:self];
+
+ [attrString release];
+ }
+
+ [[NSColor colorWithCalibratedWhite:0.5 alpha:1.0] set];
+ path = [NSBezierPath bezierPath];
+ [path moveToPoint:NSMakePoint(NSMinX(rowRect), NSMinY(rowRect))];
+ [path lineToPoint:NSMakePoint(NSMaxX(rowRect), NSMinY(rowRect))];
+ [path moveToPoint:NSMakePoint(NSMinX(rowRect), NSMaxY(rowRect))];
+ [path lineToPoint:NSMakePoint(NSMaxX(rowRect), NSMaxY(rowRect))];
+ [path stroke];
+ }
+ else
+ {
+ [super drawRow:rowIndex clipRect:clipRect];
+ }
+}
+
+- (void)drawStickyRow:(NSInteger)row clipRect:(NSRect)clipRect
+{
+ _isDrawingStickyRow = YES;
+ [self drawRow:row clipRect:clipRect];
+ _isDrawingStickyRow = NO;
+}
+
+
+@end
1,044 NoodleKit.xcodeproj/project.pbxproj
@@ -0,0 +1,1044 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 322DEBAE1072594300CB7080 /* NoodleKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
+ 322DEBAF1072594D00CB7080 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
+ 322DEBB31072595B00CB7080 /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 322DEBB11072595B00CB7080 /* Controller.m */; };
+ 322DEBB41072595B00CB7080 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 322DEBB21072595B00CB7080 /* main.m */; };
+ 322DEBB81072598E00CB7080 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 322DEBB61072598E00CB7080 /* MainMenu.xib */; };
+ 322DECB310727B3C00CB7080 /* NoodleKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
+ 322DECC610727B9300CB7080 /* NoodleKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
+ 32782FB110713A4C0041F09C /* NoodleLineNumberView.h in Headers */ = {isa = PBXBuildFile; fileRef = 32782FAF10713A4C0041F09C /* NoodleLineNumberView.h */; };
+ 32782FB210713A4C0041F09C /* NoodleLineNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 32782FB010713A4C0041F09C /* NoodleLineNumberView.m */; };
+ 32782FB610713B640041F09C /* NoodleLineNumberMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 32782FB410713B640041F09C /* NoodleLineNumberMarker.h */; };
+ 32782FB710713B640041F09C /* NoodleLineNumberMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 32782FB510713B640041F09C /* NoodleLineNumberMarker.m */; };
+ 32782FD610713C1E0041F09C /* NSResponder-NoodleModalExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 32782FD410713C1E0041F09C /* NSResponder-NoodleModalExtensions.h */; };
+ 32782FD710713C1E0041F09C /* NSResponder-NoodleModalExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 32782FD510713C1E0041F09C /* NSResponder-NoodleModalExtensions.m */; };
+ 32782FDE10713DA00041F09C /* NoodleIPhoneTableView.h in Headers */ = {isa = PBXBuildFile; fileRef = 32782FD810713DA00041F09C /* NoodleIPhoneTableView.h */; };
+ 32782FDF10713DA00041F09C /* NoodleIPhoneTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 32782FD910713DA00041F09C /* NoodleIPhoneTableView.m */; };
+ 32782FE010713DA00041F09C /* NoodleStickyRowTableView.h in Headers */ = {isa = PBXBuildFile; fileRef = 32782FDA10713DA00041F09C /* NoodleStickyRowTableView.h */; };
+ 32782FE110713DA00041F09C /* NoodleStickyRowTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 32782FDB10713DA00041F09C /* NoodleStickyRowTableView.m */; };
+ 32782FE210713DA00041F09C /* NSImage-NoodleExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 32782FDC10713DA00041F09C /* NSImage-NoodleExtensions.h */; };
+ 32782FE310713DA00041F09C /* NSImage-NoodleExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 32782FDD10713DA00041F09C /* NSImage-NoodleExtensions.m */; };
+ 32782FE610713DD60041F09C /* NSObject-NoodlePerformWhenIdle.h in Headers */ = {isa = PBXBuildFile; fileRef = 32782FE410713DD60041F09C /* NSObject-NoodlePerformWhenIdle.h */; };
+ 32782FE710713DD60041F09C /* NSObject-NoodlePerformWhenIdle.m in Sources */ = {isa = PBXBuildFile; fileRef = 32782FE510713DD60041F09C /* NSObject-NoodlePerformWhenIdle.m */; };
+ 3278303A107140600041F09C /* NSWindow-NoodleEffects.h in Headers */ = {isa = PBXBuildFile; fileRef = 32783038107140600041F09C /* NSWindow-NoodleEffects.h */; };
+ 3278303B107140600041F09C /* NSWindow-NoodleEffects.m in Sources */ = {isa = PBXBuildFile; fileRef = 32783039107140600041F09C /* NSWindow-NoodleEffects.m */; };
+ 32783093107152680041F09C /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 32783091107152680041F09C /* MainMenu.xib */; };
+ 32783097107152A90041F09C /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 32783096107152A90041F09C /* Controller.m */; };
+ 32783099107152E30041F09C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 32783098107152E30041F09C /* main.m */; };
+ 327830AB107153500041F09C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
+ 327830F3107155D70041F09C /* NoodleKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
+ 3278311A107156CB0041F09C /* NoodleKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
+ 32783133107159280041F09C /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 32783132107159280041F09C /* Credits.rtf */; };
+ 3278315510715AC90041F09C /* NoodleKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
+ 3278315910715AEA0041F09C /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 3278315810715AEA0041F09C /* Controller.m */; };
+ 3278315C10715AF60041F09C /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3278315A10715AF60041F09C /* MainMenu.xib */; };
+ 3278315E10715AFC0041F09C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3278315D10715AFC0041F09C /* main.m */; };
+ 3278316210715B210041F09C /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 3278316110715B210041F09C /* Credits.rtf */; };
+ 3278316410715B440041F09C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
+ 3278316810715B680041F09C /* NoodleKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
+ 327831AE107160460041F09C /* NoodleKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */; };
+ 327831B0107160510041F09C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
+ 327831B7107160690041F09C /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 327831B4107160690041F09C /* Controller.m */; };
+ 327831B8107160690041F09C /* MarkerLineNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 327831B6107160690041F09C /* MarkerLineNumberView.m */; };
+ 327831BB1071607D0041F09C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 327831BA1071607D0041F09C /* main.m */; };
+ 327831BE1071608F0041F09C /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 327831BC1071608F0041F09C /* MainMenu.xib */; };
+ 327831DD107161EB0041F09C /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 327831DC107161EB0041F09C /* Credits.rtf */; };
+ 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
+ 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 322DEBAC1072594000CB7080 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+ remoteInfo = NoodleKit;
+ };
+ 3278318710715CEB0041F09C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+ remoteInfo = NoodleKit;
+ };
+ 3278318910715CF30041F09C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+ remoteInfo = NoodleKit;
+ };
+ 327831AC107160410041F09C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+ remoteInfo = NoodleKit;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 322DECB910727B4C00CB7080 /* Copy Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 322DECB310727B3C00CB7080 /* NoodleKit.framework in Copy Frameworks */,
+ );
+ name = "Copy Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 322DECC910727BA700CB7080 /* Copy Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 322DECC610727B9300CB7080 /* NoodleKit.framework in Copy Frameworks */,
+ );
+ name = "Copy Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 327831031071564E0041F09C /* Copy Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 3278311A107156CB0041F09C /* NoodleKit.framework in Copy Frameworks */,
+ );
+ name = "Copy Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 3278316610715B5F0041F09C /* Copy Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 3278316810715B680041F09C /* NoodleKit.framework in Copy Frameworks */,
+ );
+ name = "Copy Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+ 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+ 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+ 322DEBA61072593A00CB7080 /* Window Effects.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Window Effects.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 322DEBA81072593A00CB7080 /* Window Effects-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Window Effects-Info.plist"; path = "Window Effects/Window Effects-Info.plist"; sourceTree = "<group>"; };
+ 322DEBB01072595B00CB7080 /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Controller.h; path = "Window Effects/Controller.h"; sourceTree = "<group>"; };
+ 322DEBB11072595B00CB7080 /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Controller.m; path = "Window Effects/Controller.m"; sourceTree = "<group>"; };
+ 322DEBB21072595B00CB7080 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = "Window Effects/main.m"; sourceTree = "<group>"; };
+ 322DEBB71072598E00CB7080 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = "Examples/Window Effects/English.lproj/MainMenu.xib"; sourceTree = "<group>"; };
+ 32782FAF10713A4C0041F09C /* NoodleLineNumberView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleLineNumberView.h; sourceTree = "<group>"; };
+ 32782FB010713A4C0041F09C /* NoodleLineNumberView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoodleLineNumberView.m; sourceTree = "<group>"; };
+ 32782FB410713B640041F09C /* NoodleLineNumberMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleLineNumberMarker.h; sourceTree = "<group>"; };
+ 32782FB510713B640041F09C /* NoodleLineNumberMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoodleLineNumberMarker.m; sourceTree = "<group>"; };
+ 32782FD410713C1E0041F09C /* NSResponder-NoodleModalExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSResponder-NoodleModalExtensions.h"; sourceTree = "<group>"; };
+ 32782FD510713C1E0041F09C /* NSResponder-NoodleModalExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSResponder-NoodleModalExtensions.m"; sourceTree = "<group>"; };
+ 32782FD810713DA00041F09C /* NoodleIPhoneTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleIPhoneTableView.h; sourceTree = "<group>"; };
+ 32782FD910713DA00041F09C /* NoodleIPhoneTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoodleIPhoneTableView.m; sourceTree = "<group>"; };
+ 32782FDA10713DA00041F09C /* NoodleStickyRowTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleStickyRowTableView.h; sourceTree = "<group>"; };
+ 32782FDB10713DA00041F09C /* NoodleStickyRowTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoodleStickyRowTableView.m; sourceTree = "<group>"; };
+ 32782FDC10713DA00041F09C /* NSImage-NoodleExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSImage-NoodleExtensions.h"; sourceTree = "<group>"; };
+ 32782FDD10713DA00041F09C /* NSImage-NoodleExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSImage-NoodleExtensions.m"; sourceTree = "<group>"; };
+ 32782FE410713DD60041F09C /* NSObject-NoodlePerformWhenIdle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject-NoodlePerformWhenIdle.h"; sourceTree = "<group>"; };
+ 32782FE510713DD60041F09C /* NSObject-NoodlePerformWhenIdle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject-NoodlePerformWhenIdle.m"; sourceTree = "<group>"; };
+ 32783038107140600041F09C /* NSWindow-NoodleEffects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSWindow-NoodleEffects.h"; sourceTree = "<group>"; };
+ 32783039107140600041F09C /* NSWindow-NoodleEffects.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSWindow-NoodleEffects.m"; sourceTree = "<group>"; };
+ 32783085107151B60041F09C /* ModalResponderTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ModalResponderTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 32783087107151B60041F09C /* ModalResponder-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ModalResponder-Info.plist"; sourceTree = "<group>"; };
+ 32783092107152680041F09C /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ModalResponder/English.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ 32783095107152A90041F09C /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = "<group>"; };
+ 32783096107152A90041F09C /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = "<group>"; };
+ 32783098107152E30041F09C /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 32783132107159280041F09C /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
+ 3278314F10715AB80041F09C /* StickyRowTableView Revue.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "StickyRowTableView Revue.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 3278315710715AEA0041F09C /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = "<group>"; };
+ 3278315810715AEA0041F09C /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = "<group>"; };
+ 3278315B10715AF60041F09C /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ 3278315D10715AFC0041F09C /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 3278315F10715B050041F09C /* StickyRowTableView Revue-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "StickyRowTableView Revue-Info.plist"; sourceTree = "<group>"; };
+ 3278316110715B210041F09C /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
+ 327831A6107160380041F09C /* LineNumberView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LineNumberView.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 327831A8107160380041F09C /* LineNumberView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "LineNumberView-Info.plist"; sourceTree = "<group>"; };
+ 327831B3107160690041F09C /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = "<group>"; };
+ 327831B4107160690041F09C /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = "<group>"; };
+ 327831B5107160690041F09C /* MarkerLineNumberView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkerLineNumberView.h; sourceTree = "<group>"; };
+ 327831B6107160690041F09C /* MarkerLineNumberView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MarkerLineNumberView.m; sourceTree = "<group>"; };
+ 327831BA1071607D0041F09C /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 327831BD1071608F0041F09C /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = Examples/LineNumberView/English.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ 327831DC107161EB0041F09C /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
+ 32DBCF5E0370ADEE00C91783 /* NoodleKit_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleKit_Prefix.pch; sourceTree = "<group>"; };
+ 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NoodleKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 322DEBA41072593A00CB7080 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 322DEBAF1072594D00CB7080 /* Cocoa.framework in Frameworks */,
+ 322DEBAE1072594300CB7080 /* NoodleKit.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 32783083107151B60041F09C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 327830F3107155D70041F09C /* NoodleKit.framework in Frameworks */,
+ 327830AB107153500041F09C /* Cocoa.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 3278314D10715AB80041F09C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3278316410715B440041F09C /* Cocoa.framework in Frameworks */,
+ 3278315510715AC90041F09C /* NoodleKit.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 327831A4107160380041F09C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 327831B0107160510041F09C /* Cocoa.framework in Frameworks */,
+ 327831AE107160460041F09C /* NoodleKit.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8DC2EF560486A6940098B216 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DFFF38A50411DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DC2EF5B0486A6940098B216 /* NoodleKit.framework */,
+ 32783085107151B60041F09C /* ModalResponderTest.app */,
+ 3278314F10715AB80041F09C /* StickyRowTableView Revue.app */,
+ 327831A6107160380041F09C /* LineNumberView.app */,
+ 322DEBA61072593A00CB7080 /* Window Effects.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0867D691FE84028FC02AAC07 /* NoodleKit */ = {
+ isa = PBXGroup;
+ children = (
+ 08FB77AEFE84172EC02AAC07 /* Classes */,
+ 32C88DFF0371C24200C91783 /* Other Sources */,
+ 089C1665FE841158C02AAC07 /* Resources */,
+ 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+ 3278307F1071513F0041F09C /* Examples */,
+ 034768DFFF38A50411DB9C8B /* Products */,
+ );
+ name = NoodleKit;
+ sourceTree = "<group>";
+ };
+ 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */,
+ 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */,
+ );
+ name = "External Frameworks and Libraries";
+ sourceTree = "<group>";
+ };
+ 089C1665FE841158C02AAC07 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 8DC2EF5A0486A6940098B216 /* Info.plist */,
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 08FB77AEFE84172EC02AAC07 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ 32782FE410713DD60041F09C /* NSObject-NoodlePerformWhenIdle.h */,
+ 32782FE510713DD60041F09C /* NSObject-NoodlePerformWhenIdle.m */,
+ 32782FD410713C1E0041F09C /* NSResponder-NoodleModalExtensions.h */,
+ 32782FD510713C1E0041F09C /* NSResponder-NoodleModalExtensions.m */,
+ 32782FDC10713DA00041F09C /* NSImage-NoodleExtensions.h */,
+ 32782FDD10713DA00041F09C /* NSImage-NoodleExtensions.m */,
+ 32783038107140600041F09C /* NSWindow-NoodleEffects.h */,
+ 32783039107140600041F09C /* NSWindow-NoodleEffects.m */,
+ 32782FB410713B640041F09C /* NoodleLineNumberMarker.h */,
+ 32782FB510713B640041F09C /* NoodleLineNumberMarker.m */,
+ 32782FAF10713A4C0041F09C /* NoodleLineNumberView.h */,
+ 32782FB010713A4C0041F09C /* NoodleLineNumberView.m */,
+ 32782FD810713DA00041F09C /* NoodleIPhoneTableView.h */,
+ 32782FD910713DA00041F09C /* NoodleIPhoneTableView.m */,
+ 32782FDA10713DA00041F09C /* NoodleStickyRowTableView.h */,
+ 32782FDB10713DA00041F09C /* NoodleStickyRowTableView.m */,
+ );
+ name = Classes;
+ sourceTree = "<group>";
+ };
+ 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */,
+ );
+ name = "Linked Frameworks";
+ sourceTree = "<group>";
+ };
+ 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 0867D6A5FE840307C02AAC07 /* AppKit.framework */,
+ D2F7E79907B2D74100F64583 /* CoreData.framework */,
+ 0867D69BFE84028FC02AAC07 /* Foundation.framework */,
+ );
+ name = "Other Frameworks";
+ sourceTree = "<group>";
+ };
+ 322DEB9E1072591900CB7080 /* Window Effects */ = {
+ isa = PBXGroup;
+ children = (
+ 322DEBB01072595B00CB7080 /* Controller.h */,
+ 322DEBB11072595B00CB7080 /* Controller.m */,
+ 322DEBB21072595B00CB7080 /* main.m */,
+ 322DEBA81072593A00CB7080 /* Window Effects-Info.plist */,
+ 322DEBB61072598E00CB7080 /* MainMenu.xib */,
+ );
+ name = "Window Effects";
+ sourceTree = "<group>";
+ };
+ 3278307F1071513F0041F09C /* Examples */ = {
+ isa = PBXGroup;
+ children = (
+ 327831A110715FC90041F09C /* LineNumberView */,
+ 327830941071527D0041F09C /* ModalResponder */,
+ 3278314A10715A970041F09C /* StickyRowTableView Revue */,
+ 322DEB9E1072591900CB7080 /* Window Effects */,
+ );
+ path = Examples;
+ sourceTree = "<group>";
+ };
+ 327830941071527D0041F09C /* ModalResponder */ = {
+ isa = PBXGroup;
+ children = (
+ 32783095107152A90041F09C /* Controller.h */,
+ 32783096107152A90041F09C /* Controller.m */,
+ 32783098107152E30041F09C /* main.m */,
+ 32783087107151B60041F09C /* ModalResponder-Info.plist */,
+ 32783132107159280041F09C /* Credits.rtf */,
+ 32783091107152680041F09C /* MainMenu.xib */,
+ );
+ path = ModalResponder;
+ sourceTree = "<group>";
+ };
+ 3278314A10715A970041F09C /* StickyRowTableView Revue */ = {
+ isa = PBXGroup;
+ children = (
+ 3278315710715AEA0041F09C /* Controller.h */,
+ 3278315810715AEA0041F09C /* Controller.m */,
+ 3278315D10715AFC0041F09C /* main.m */,
+ 3278315F10715B050041F09C /* StickyRowTableView Revue-Info.plist */,
+ 3278316110715B210041F09C /* Credits.rtf */,
+ 3278315A10715AF60041F09C /* MainMenu.xib */,
+ );
+ path = "StickyRowTableView Revue";
+ sourceTree = "<group>";
+ };
+ 327831A110715FC90041F09C /* LineNumberView */ = {
+ isa = PBXGroup;
+ children = (
+ 327831B3107160690041F09C /* Controller.h */,
+ 327831B4107160690041F09C /* Controller.m */,
+ 327831B5107160690041F09C /* MarkerLineNumberView.h */,
+ 327831B6107160690041F09C /* MarkerLineNumberView.m */,
+ 327831BA1071607D0041F09C /* main.m */,
+ 327831A8107160380041F09C /* LineNumberView-Info.plist */,
+ 327831DC107161EB0041F09C /* Credits.rtf */,
+ 327831BC1071608F0041F09C /* MainMenu.xib */,
+ );
+ path = LineNumberView;
+ sourceTree = "<group>";
+ };
+ 32C88DFF0371C24200C91783 /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 32DBCF5E0370ADEE00C91783 /* NoodleKit_Prefix.pch */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 8DC2EF500486A6940098B216 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 32782FB110713A4C0041F09C /* NoodleLineNumberView.h in Headers */,
+ 32782FB610713B640041F09C /* NoodleLineNumberMarker.h in Headers */,
+ 32782FD610713C1E0041F09C /* NSResponder-NoodleModalExtensions.h in Headers */,
+ 32782FDE10713DA00041F09C /* NoodleIPhoneTableView.h in Headers */,
+ 32782FE010713DA00041F09C /* NoodleStickyRowTableView.h in Headers */,
+ 32782FE210713DA00041F09C /* NSImage-NoodleExtensions.h in Headers */,
+ 32782FE610713