195 Commits

Author SHA1 Message Date
Alex Zielenski 850926d703 Merge pull request #19 from alexzielenski/dev
merge tag
2014-02-06 16:33:16 -05:00
Alex Zielenski 58dabb398d 0.0.1 2014-02-06 16:31:42 -05:00
Alex Zielenski f52c1c6a75 Merge pull request #18 from alexzielenski/dev
Rewrite
2014-02-06 16:29:15 -05:00
Alex Zielenski 841768db52 solve all the problems 2014-02-06 16:08:50 -05:00
Alex Zielenski dc7dc481bf show hotspot in edit window 2014-02-05 21:40:24 -05:00
Alex Zielenski 6d0a380446 fix newDocument and openDocument actions 2014-02-05 20:04:02 -05:00
Alex Zielenski b7099afc70 hook up menu actions to the nsresponder chain 2014-02-05 20:01:12 -05:00
Alex Zielenski 46b000a884 refine undo/save 2014-02-05 19:40:23 -05:00
Alex Zielenski e96e06b4f7 menu items for saving 2014-02-05 19:40:03 -05:00
Alex Zielenski 2affa1c58e make the edit window prompt for saving 2014-02-05 19:16:45 -05:00
Alex Zielenski 51e8fac9d5 dont strip debug symbols during copy files 2014-02-05 18:39:37 -05:00
Alex Zielenski 09954c40b9 Copy a cursor to import into the library, dont resave it 2014-02-05 18:39:23 -05:00
Alex Zielenski 1387af7fa3 make "Unknown" an unselectable cursor type 2014-02-05 18:03:22 -05:00
Alex Zielenski 91edae4ad0 return a UUID for unknown identififers 2014-02-05 18:00:57 -05:00
Alex Zielenski b898b62917 Make the dump really dump EVERYTHING 2014-02-05 17:55:53 -05:00
Alex Zielenski acf11018ea Finalize cursor editing: can now make a cursor within the app 2014-02-05 17:24:04 -05:00
Alex Zielenski c68021a972 enable undo for setting the image reps 2014-02-05 14:17:29 -05:00
Alex Zielenski 3418740504 Add undo support for cursor properties 2014-02-05 14:11:01 -05:00
Alex Zielenski 2d198be181 constrain split view position 2014-02-05 13:15:30 -05:00
Alex Zielenski e7dc0293f2 dont let the window get too small for the previews 2014-02-05 13:08:20 -05:00
Alex Zielenski 563be20d2a remove unnecessary code 2014-02-05 13:07:55 -05:00
Alex Zielenski 8d34a82d21 some intermediate undo support and document saving 2014-02-05 13:03:54 -05:00
Alex Zielenski 1a31be93d0 manage the sort order in the view controller not the library controller 2014-02-05 12:27:11 -05:00
Alex Zielenski d3397878d3 make MCCursorLibrary and MCLibraryController have their own undo managers 2014-02-05 12:26:41 -05:00
Alex Zielenski 6e387daae7 make mousecape import/open .cape files 2014-02-05 10:36:05 -05:00
Alex Zielenski 8f64d3c9b7 reapply cursor when display configuration changes 2014-02-05 10:09:08 -05:00
Alex Zielenski ed060272a1 Add preview of cursor in edit window and rewrite MCSpriteLayer 2014-02-05 10:08:57 -05:00
Alex Zielenski dd6f844319 set up some more edit bindings and move all code into the src folder 2014-02-03 16:59:12 -05:00
Alex Zielenski eb24d1eeb1 scroll newly added rows to visible 2014-02-03 15:49:31 -05:00
Alex Zielenski 3e18a4e798 bind cape edit controls 2014-02-03 12:15:37 -05:00
Alex Zielenski 655c9065e6 show library window on any reopen 2014-02-03 12:15:17 -05:00
Alex Zielenski 585d4c09d4 dont load the helper tool into the loginwindow 2014-02-03 11:16:51 -05:00
Alex Zielenski 42a61192e2 Add basic edit window that shows a list of cursors and has view swapping 2014-02-03 11:15:38 -05:00
Alex Zielenski f3c08457d9 allow cmd-E for edit item 2014-02-03 11:15:18 -05:00
Alex Zielenski b9f5bde38c use nsset for mccursorlibrary 2014-02-03 11:15:01 -05:00
Alex Zielenski 7c7afb495b make the command line tool set the preferences 2014-02-03 09:09:24 -05:00
Alex Zielenski b13740318e import into library 2014-02-03 09:08:50 -05:00
Alex Zielenski b5c5549d5f remove item in trash if it already exists 2014-02-03 08:36:45 -05:00
Alex Zielenski 88aa1e5400 add undo/redo support for adding and removing capes 2014-02-03 08:36:33 -05:00
Alex Zielenski 01e199b106 save applied cape in prefs 2014-02-03 08:35:08 -05:00
Alex Zielenski 0bab67d694 make mighty mouse imports have the name of the cursor in its identifier 2014-02-03 08:34:18 -05:00
Alex Zielenski ba7e903f53 import mighty mouse cursors 2014-02-03 08:18:23 -05:00
Alex Zielenski 6f859fd576 make the library controller not a singleton and have it follow a delegate design pattern. 2014-02-03 08:18:15 -05:00
Alex Zielenski 9a8dfb04a3 add empty edit window classes 2014-02-03 08:16:56 -05:00
Alex Zielenski e17bc7fc62 reopen window on app reactivate 2014-02-02 23:52:44 -05:00
Alex Zielenski b5e8622ab8 remove observer on dealloc 2014-02-02 23:52:35 -05:00
Alex Zielenski eceeefe3e6 fix move to trash 2014-02-02 23:20:04 -05:00
Alex Zielenski ae320a1505 sort library list and fix up animations 2014-02-02 23:17:56 -05:00
Alex Zielenski 4201b666e8 make separate methods for scaling 2014-02-02 23:17:37 -05:00
Alex Zielenski 9363cce71f hook up some menubar actions 2014-02-02 22:14:48 -05:00
Alex Zielenski a054c6889e add menu items, use nsarraycontroller for the view, set up accessory view 2014-02-02 19:24:29 -05:00
Alex Zielenski 19846a9cd5 make defaultCursors a constant nsstring c array 2014-02-02 18:44:41 -05:00
Alex Zielenski 3f5f811493 restore old cursors before applying new ones 2014-02-02 18:31:42 -05:00
Alex Zielenski dfe8cf8275 simple cursor library that allows application but no previews yet 2014-02-02 18:30:42 -05:00
Alex Zielenski 4c1233483b add library window with blank table 2014-02-02 12:14:15 -05:00
Alex Zielenski 10435d4600 Toggle helper tool installation with menu item 2014-02-02 11:23:53 -05:00
Alex Zielenski cfa5729df8 remove useless code 2014-02-02 11:07:27 -05:00
Alex Zielenski 7798dd8f08 Unit Tests! 2014-02-02 11:06:46 -05:00
Alex Zielenski 8b552a85fb MCCursor and MCCursorLibrary partially rewritten from old version 2014-02-02 11:06:39 -05:00
Alex Zielenski 9c8774671d remove launchagent and add example cape file 2014-02-02 11:06:10 -05:00
Alex Zielenski 37afc5f590 add mcdefs and mcprefs to mousecape prefix 2014-02-02 11:05:49 -05:00
Alex Zielenski 2897088494 Add name map to mcdefs 2014-02-02 11:05:28 -05:00
Alex Zielenski 34100867f3 add install mousecloak menu item 2014-02-02 00:03:10 -05:00
Alex Zielenski 1549efdabd make MCPrefs more versatile 2014-02-02 00:02:53 -05:00
Alex Zielenski 722323ed9d Add installer for LaunchAgent and add listen option to mousecloak and get it working 2014-02-02 00:02:41 -05:00
Alex Zielenski 478a0b7854 auto increment build number 2014-02-01 17:28:22 -05:00
Alex Zielenski 027266bd8a return id for MCDefaults 2014-02-01 17:28:07 -05:00
Alex Zielenski d13e9aaf4a oops, forgot this 2014-02-01 17:03:32 -05:00
Alex Zielenski afbd49b99e Add MCPrefs 2014-02-01 17:01:08 -05:00
Alex Zielenski 5da72d5115 Delete everything. Split mousecloak up 2014-02-01 15:26:40 -05:00
Alex Zielenski c88abba14e Disable some animations and use rac_bind for the animating imageview 2014-02-01 07:58:49 -05:00
Alex Zielenski b2bd6b2d8b make DTScrollView a subclass of BTRScrollView 2014-02-01 07:58:18 -05:00
Alex Zielenski 607bdc537b use BTRClipView/ScrolLView instead of RBL 2014-02-01 07:57:36 -05:00
Alex Zielenski b7e10cfa5a add license 2014-02-01 07:56:31 -05:00
Alex Zielenski 67281750cf dont animate mcspritelayer 2014-02-01 07:56:09 -05:00
Alex Zielenski ed0dfd052a option for mousecloak to get the persist applied cape 2014-02-01 07:55:23 -05:00
Alex Zielenski c2806a8304 xcode 4.6 compatible 2013-09-08 10:15:07 -04:00
Alex Zielenski 6a3be3760f broke some autolayout for compatibility with older versions of xcode 2013-09-08 10:14:54 -04:00
Alex Zielenski 7a20759734 crazy hack to validate identifier of cursor libraries 2013-07-02 17:27:24 -04:00
Alex Zielenski 69d464f260 Automatic hiDPI detection. Still undone: doesn't notify observers correctly yet but it's a start 2013-07-02 15:48:42 -04:00
Alex Zielenski f3c67f75d5 stop detail fields resizing 2013-07-02 12:14:04 -04:00
Alex Zielenski 596361abee disable open recent menu 2013-07-01 21:55:59 -04:00
Alex Zielenski eebf178a5e remove mousecloak menu item 2013-07-01 21:51:21 -04:00
Alex Zielenski f79427f1d7 Mighty mouse imports 2013-07-01 21:41:48 -04:00
Alex Zielenski a458a29086 move library files when identifier changes and resort the documents array when the name changes 2013-07-01 17:43:37 -04:00
Alex Zielenski b2ffbb46fa Use more user-friendly popup button 2013-07-01 17:23:44 -04:00
Alex Zielenski 0a21c09e5f Add Sparkle updating and more warnings (then fix them) 2013-07-01 16:40:09 -04:00
Alex Zielenski f03eb7c966 auto-increment build count 2013-06-30 10:44:29 -04:00
Alex Zielenski 67ed22c712 use nonatomic properties 2013-06-30 10:44:18 -04:00
Alex Zielenski 5d98b43f47 Make -addDocument return a BOOL 2013-06-30 10:43:28 -04:00
Alex Zielenski 71e3adf5b8 remove complicated RAC property 2013-06-30 10:42:34 -04:00
Alex Zielenski f62c58aaab Fix weird display bug on 10.8 2013-06-30 10:42:11 -04:00
Alex Zielenski 5a95e24fba stop creating a new document every app launch 2013-06-30 10:41:50 -04:00
Alex Zielenski 4cfb16776f cursor editor drag & drop 2013-06-30 10:41:30 -04:00
Alex Zielenski 7c2ca245b9 dont show the library window until the app has finished launching 2013-06-29 19:08:40 -04:00
Alex Zielenski 04a8966e1a set pods sdk to 10.8 2013-06-29 16:00:32 -04:00
Alex Zielenski 6cf2eb6337 fix out of bounds exception 2013-06-29 16:00:28 -04:00
Alex Zielenski a0316a6f63 Set applied cursor to nil of it is removed from the library 2013-06-29 15:29:44 -04:00
Alex Zielenski e07cf979f3 remove unnecessary dispatching 2013-06-29 13:29:41 -04:00
Alex Zielenski 899f753add MCCursorLine uses only key reps, not all 2013-06-29 13:29:22 -04:00
Alex Zielenski ef9851ea0c Derive some more properties in MCCursor 2013-06-29 13:29:09 -04:00
Alex Zielenski cb2099f285 remove debug code 2013-06-29 13:12:41 -04:00
Alex Zielenski 71367e4178 Make sure to actually dispose of the hundreds of disposables we are making. Leaking observation info is very bad. Also, start to vary cursor size when the frame count changes if wanted. 2013-06-29 12:36:10 -04:00
Alex Zielenski 6abfa0a736 Directly add documents, dont let it go through the notification 2013-06-29 12:34:45 -04:00
Alex Zielenski 6a10142e2f Move library imports to the correct path 2013-06-27 22:03:49 -04:00
Alex Zielenski acf4dce056 Undo for adding/removing cursor representations. Add remove capability to edit cursor view 2013-06-27 22:03:36 -04:00
Alex Zielenski 7adadaa47f make author name bigger 2013-06-27 17:59:29 -04:00
Alex Zielenski f212365517 Use MCSegmentedControl to visualize the individual representations. More work needs to be done, however 2013-06-27 17:57:38 -04:00
Alex Zielenski 861fdfc646 instantiate cursors 2013-06-27 17:28:12 -04:00
Alex Zielenski 621994220e fix cursor importing 2013-06-27 17:27:31 -04:00
Alex Zielenski 3247e2cbb8 better representation choice algorithm 2013-06-27 15:17:21 -04:00
Alex Zielenski 4b57b33890 Fix image view display bug 2013-06-27 13:20:55 -04:00
Alex Zielenski 503f627edd add MCSegmentedControl for later 2013-06-27 13:09:55 -04:00
Alex Zielenski 5906fc9b0b Change MCCursorLibrary from NSDictionary to NSOrderedSet to enable the possibility of undoing adding and removing cursor objects 2013-06-27 11:10:37 -04:00
Alex Zielenski c8506d25dd stop observing old cursor arrays when they change 2013-06-27 08:22:01 -04:00
Alex Zielenski 233d21c97c more undo support in the edit window 2013-06-26 22:25:40 -04:00
Alex Zielenski 1069e45825 More menu items, undo redo, RAC stuff. I don't even know at this point. I'm just tweaking things around. 2013-06-26 21:48:25 -04:00
Alex Zielenski 30497f809b Polish up some menu actions. Add animations for cursor removal and adding. Better thread management. Use 10.8 methods 2013-06-26 15:33:38 -04:00
Alex Zielenski 22bfd54555 set current cursor on main thread 2013-06-26 13:31:43 -04:00
Alex Zielenski 37f4397202 Merge pull request #3 from alexzielenski/reactivecocoa
Okay ill delete this branch once and for all
2013-06-26 10:24:50 -07:00
Alex Zielenski 3194cdc05d looks like xcode hasn't really been updating everything 2013-06-26 13:23:56 -04:00
Alex Zielenski b531ccf7d9 Remove MCDetailViewController 2013-06-26 13:23:22 -04:00
Alex Zielenski c3df2502bb Merge pull request #2 from alexzielenski/reactivecocoa
Forgot to delete this branch
2013-06-26 10:17:47 -07:00
Alex Zielenski 5163f4709f Reorganize MCLibraryViewController and MCLibraryWindowController. Implement more menu items and open on importing 2013-06-26 13:17:03 -04:00
Alex Zielenski 8ed13fdfbd Merge pull request #1 from alexzielenski/reactivecocoa
Reactivecocoa
2013-06-26 07:30:33 -07:00
Alex Zielenski d42b20a425 Fix the save button. Start to reconfigure some menu items after the big rewrite 2013-06-26 10:30:12 -04:00
Alex Zielenski 5f004c33d0 Big update. Use NSDocument architecture and add some window controllers. Migrate some more stuff to RAC too 2013-06-25 23:30:04 -04:00
Alex Zielenski ff82851b46 User interface tweaks & use NSOrderedSet 2013-06-24 18:34:39 -04:00
Alex Zielenski 95cdfee037 include scope in the prefix 2013-06-22 21:46:10 -04:00
Alex Zielenski b01f203f91 remove unnecessary code 2013-06-22 21:44:12 -04:00
Alex Zielenski 26bd60311e Fix initial cursor issue. Set applied library to nil if it is removed 2013-06-22 21:43:41 -04:00
Alex Zielenski b91864bb5d use XIB bindings for the table values 2013-06-20 20:57:49 -04:00
Alex Zielenski c1495c8eb3 stop crashing on cape import 2013-06-17 21:23:51 -04:00
Alex Zielenski 4312a808e7 Update project to Xcode 5 settings. Fix auto-layout, fix the issues with the apply image not showing 2013-06-16 20:24:14 -04:00
Alex Zielenski 25db7d1950 Limit horizontal scrolls to their bounds for performance gain 2013-04-01 16:45:58 -04:00
Alex Zielenski b4a0d31b9d auto layout causes some scroll lag 2013-04-01 13:54:13 -04:00
Alex Zielenski 5d44e0280d Maybe I should push this local stuff 2013-04-01 10:49:03 -04:00
Alex Zielenski d7d4f9d11c I be on that other shit 2013-03-16 21:08:58 -04:00
Alex Zielenski c5b7e96226 Fix some performance issues hopefully 2013-02-25 22:58:40 -05:00
Alex Zielenski a0ac5729e3 Do some of this logic on the main thread 2013-02-25 20:30:58 -05:00
Alex Zielenski 57357b9629 have to assign weakself 2013-02-25 20:21:01 -05:00
Alex Zielenski 361e348006 Add reactive cocoa and switch lots of shit to it 2013-02-25 20:18:50 -05:00
Alex Zielenski 99881a5042 bleh 2013-02-25 16:06:22 -05:00
Alex Zielenski 523ed4a25c Add TODOs and refactor 2013-02-25 15:19:22 -05:00
Alex Zielenski dddd2dece1 Move preferences constant keys to their own header 2013-02-25 15:19:12 -05:00
Alex Zielenski d39c437f87 rename plist to mousecape 2013-02-24 21:18:24 -05:00
Alex Zielenski 6ed9554846 Draw hotspot on image view 2013-02-24 20:48:58 -05:00
Alex Zielenski 4072edaa6c Use prettyName in the edit list rather than the identifiers 2013-02-24 20:48:41 -05:00
Alex Zielenski b45cc2540d Add NSFormatter subclasses instead of using NSValueTransformer 2013-02-24 20:48:27 -05:00
Alex Zielenski 073fe0d1da Add dynamic -prettyName to MCCursor instead of hard -name 2013-02-24 20:47:51 -05:00
Alex Zielenski f735b127be Use prettyName in the edit list 2013-02-24 20:47:14 -05:00
Alex Zielenski 3549893d3c remove some unused code and move bindings to xib 2013-02-24 19:08:43 -05:00
Alex Zielenski eb6aa1a9b4 add heart psd 2013-02-24 19:08:33 -05:00
Alex Zielenski 67c6e08d1e Yeah big update 2013-02-24 18:44:30 -05:00
Alex Zielenski f2aef4906a Fix bad copying logic 2013-02-24 14:00:20 -05:00
Alex Zielenski 0b24d73e43 only error on constraints in debug 2013-02-24 13:08:45 -05:00
Alex Zielenski 5aaaa1db68 To-one association from cursors to their libraries for easier identifier relationships 2013-02-24 13:08:34 -05:00
Alex Zielenski 1ae999aa12 a 2013-02-24 02:05:11 -05:00
Alex Zielenski 88fe4c828e work on edit window 2013-02-24 02:04:55 -05:00
Alex Zielenski 01fe16455a stop logging mouse cloak output 2013-02-19 21:03:23 -05:00
Alex Zielenski 265d2cdc28 make representations mutable in mccursor 2013-02-19 21:03:06 -05:00
Alex Zielenski f2c9b449b1 add view controllers to window nib 2013-02-19 21:02:58 -05:00
Alex Zielenski ba15970f26 Integrate cape editor 2013-02-19 21:02:40 -05:00
Alex Zielenski 8d162b08ee Boilerplate for editcursor 2013-02-19 21:02:04 -05:00
Alex Zielenski a9c5144536 Add special row view for the cape row in the editor 2013-02-19 21:01:49 -05:00
Alex Zielenski bac703378a Add bezel and lastRepresentation property of scaled image view 2013-02-19 21:01:35 -05:00
Alex Zielenski 3605904709 Scaled image view for later 2013-02-19 20:04:55 -05:00
Alex Zielenski a0a2a81d82 Make NSImage+BestRep into a category 2013-02-19 20:04:34 -05:00
Alex Zielenski ca41ac6070 Allow users to disable animations 2013-02-19 16:20:52 -05:00
Alex Zielenski c7c919f466 Add edit window 2013-02-19 16:20:38 -05:00
Alex Zielenski 30f36d95fe dismiss sidekick window before showing an error and detect if a sidekick is HD or not 2013-02-18 11:01:01 -05:00
Alex Zielenski 6472428735 move positioning of generalpreferences.xib to the bottom of the sidebar 2013-02-18 11:00:29 -05:00
Alex Zielenski 587a3d5af3 tweak some namings in cursor map 2013-02-18 10:59:33 -05:00
Alex Zielenski facf4209d7 add cursor scale functionality to MCCloakCuntroller 2013-02-18 10:59:08 -05:00
Alex Zielenski a176c4700b Add cursor scale slider into prefs 2013-02-18 10:58:51 -05:00
Alex Zielenski 5faee760c1 maximum frame size on sprite layers 2013-02-18 10:58:24 -05:00
Alex Zielenski 670873021d maybe try NSUInteger instead of CFIndex for frame count 2013-02-18 10:58:07 -05:00
Alex Zielenski 2c62ca7ab3 remove extraneous macros 2013-02-18 10:57:47 -05:00
Alex Zielenski 189c11a90c move HD image view sometimes 2013-02-18 10:57:36 -05:00
Alex Zielenski 73ee3a6d0e decrease font size 2013-02-18 10:57:16 -05:00
Alex Zielenski f8b0a19fd0 breaks on 10.7 2013-02-18 10:56:55 -05:00
Alex Zielenski a3120681e4 Use the identifiers for filenames and enforce unique identifiers 2013-02-17 16:27:56 -05:00
Alex Zielenski 46c6b98dc5 Inherit plist 2013-02-17 16:27:42 -05:00
Alex Zielenski 9d2f4fa7b3 Fix leaky KVO 2013-02-17 16:27:34 -05:00
Alex Zielenski cc296af677 Applied cursor persistence 2013-02-17 16:27:26 -05:00
Alex Zielenski 239c044aca Specify HD icons 2013-02-17 16:26:43 -05:00
Alex Zielenski 48aa941e2c Update cursor map 2013-02-17 14:07:17 -05:00
Alex Zielenski c8670b8495 Add to library menu item 2013-02-17 14:07:09 -05:00
Alex Zielenski 9e39d372b9 Fix HiDPI rep choosing 2013-02-17 14:06:51 -05:00
Alex Zielenski 07cf88a7fc Remove debug thing 2013-02-17 14:06:36 -05:00
Alex Zielenski d9501d6b64 remove .idea 2013-02-17 10:38:39 -05:00
Alex Zielenski 1bc9b60a8a push to git 2013-02-17 10:37:03 -05:00
Alex Zielenski ab2f9d7739 Forgot animating image view 2013-02-11 19:39:50 -05:00
Alex Zielenski 913b92aabb Yeah 2013-02-11 19:39:33 -05:00
Alex Zielenski d0d2ae0da0 Initial Commit 2013-02-08 13:23:26 -05:00
147 changed files with 55647 additions and 13230 deletions
-18
View File
@@ -1,18 +0,0 @@
# .gitignore in use by Joris Kluivers
*.DS_Store
# Xcode
*.pbxuser
*.mode1v3
*.move2v3
*.perspectivev3
*.xcuserstate
project.xcworkspace/
xcuserdata/
build/
# Generated
*.o
*.pyc
+10
View File
@@ -0,0 +1,10 @@
Copyright (c) 2013-2014, Alex Zielenski
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Any redistribution, use, or modification is done solely for personal benefit and not for any commercial purpose or for monetary gain
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-594
View File
@@ -1,594 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
0E7C3CC514F9FB1A0003A5FE /* cursor.png in Resources */ = {isa = PBXBuildFile; fileRef = 0E7C3CC414F9FB1A0003A5FE /* cursor.png */; };
FA02424614FF0993006E6FE1 /* MMAdvancedEditViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = FA02424314FF0993006E6FE1 /* MMAdvancedEditViewController.h */; };
FA02424714FF0993006E6FE1 /* MMAdvancedEditViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FA02424414FF0993006E6FE1 /* MMAdvancedEditViewController.m */; };
FA02424814FF0993006E6FE1 /* AdvancedEdit.xib in Resources */ = {isa = PBXBuildFile; fileRef = FA02424514FF0993006E6FE1 /* AdvancedEdit.xib */; };
FA05ED1115571D7800BEC0AC /* MMCursorLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = FA05ED0F15571D7800BEC0AC /* MMCursorLibrary.h */; };
FA05ED1215571D7800BEC0AC /* MMCursorLibrary.m in Sources */ = {isa = PBXBuildFile; fileRef = FA05ED1015571D7800BEC0AC /* MMCursorLibrary.m */; };
FA07748014F9A70A00A1B91B /* MMAnimatingImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = FA07746C14F9976100A1B91B /* MMAnimatingImageView.m */; };
FA07748114F9A70E00A1B91B /* MMAnimatingImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = FA07746B14F9976100A1B91B /* MMAnimatingImageView.h */; };
FA21EF981550C642002D688E /* MMCursorViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = FA21EF961550C642002D688E /* MMCursorViewController.h */; };
FA21EF991550C642002D688E /* MMCursorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FA21EF971550C642002D688E /* MMCursorViewController.m */; };
FA319D3C14F353C50064E7CC /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA319D3B14F353C50064E7CC /* Accelerate.framework */; };
FA6F2D2114F3150E0098AE57 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA6F2D2014F3150E0098AE57 /* CoreFoundation.framework */; };
FA6F2D2414F3150E0098AE57 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = FA6F2D2314F3150E0098AE57 /* main.c */; };
FA6F2D2614F3150E0098AE57 /* magicmouse.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FA6F2D2514F3150E0098AE57 /* magicmouse.1 */; };
FA6F2D2C14F3154E0098AE57 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA6F2D2A14F315490098AE57 /* ApplicationServices.framework */; };
FAD37AFF14F9836E00B7F09C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA6F2CFD14F315000098AE57 /* Cocoa.framework */; };
FAD37B0114F9836E00B7F09C /* PreferencePanes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAD37B0014F9836E00B7F09C /* PreferencePanes.framework */; };
FAD37B1714F983B900B7F09C /* MMPrefPane.h in Headers */ = {isa = PBXBuildFile; fileRef = FAD37B1414F983B900B7F09C /* MMPrefPane.h */; };
FAD37B1814F983B900B7F09C /* MMPrefPane.m in Sources */ = {isa = PBXBuildFile; fileRef = FAD37B1514F983B900B7F09C /* MMPrefPane.m */; };
FAD37B1914F983B900B7F09C /* Magic_Mouse.tiff in Resources */ = {isa = PBXBuildFile; fileRef = FAD37B1614F983B900B7F09C /* Magic_Mouse.tiff */; };
FAD37B2414F983D700B7F09C /* Magic_Mouse.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAD37B2214F983D700B7F09C /* Magic_Mouse.xib */; };
FAD37B2C14F983E800B7F09C /* Magic Mouse-Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = FAD37B2A14F983E800B7F09C /* Magic Mouse-Prefix.pch */; };
FAD37B2F14F983F000B7F09C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAD37B2D14F983F000B7F09C /* InfoPlist.strings */; };
FADA4A4D14FAEA4F00517F22 /* MMAnimatingImageTableCellView.h in Headers */ = {isa = PBXBuildFile; fileRef = FADA4A4B14FAEA4F00517F22 /* MMAnimatingImageTableCellView.h */; };
FADA4A4E14FAEA4F00517F22 /* MMAnimatingImageTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = FADA4A4C14FAEA4F00517F22 /* MMAnimatingImageTableCellView.m */; };
FADA4A5414FB017400517F22 /* NSCursor_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = FADA4A5314FB017400517F22 /* NSCursor_Private.h */; };
FAEBD4AD1551DBAA00F4B4D9 /* MMAdvancedEditWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = FAEBD4AA1551DBAA00F4B4D9 /* MMAdvancedEditWindowController.h */; };
FAEBD4AE1551DBAA00F4B4D9 /* MMAdvancedEditWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEBD4AB1551DBAA00F4B4D9 /* MMAdvancedEditWindowController.m */; };
FAEBD4AF1551DBAA00F4B4D9 /* EditWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAEBD4AC1551DBAA00F4B4D9 /* EditWindow.xib */; };
FAFC6EAE14F9AD0D00379751 /* magicmouse in Copy magicmouse */ = {isa = PBXBuildFile; fileRef = FA6F2D1E14F3150E0098AE57 /* magicmouse */; };
FAFC6EB414F9C1C300379751 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAFC6EB214F9C1C300379751 /* Security.framework */; };
FAFC6EB514F9C1C300379751 /* SecurityInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAFC6EB314F9C1C300379751 /* SecurityInterface.framework */; };
FAFC6EB814F9E3F500379751 /* MMCursorAggregate.h in Headers */ = {isa = PBXBuildFile; fileRef = FAFC6EB614F9E3F500379751 /* MMCursorAggregate.h */; };
FAFC6EB914F9E3F500379751 /* MMCursorAggregate.m in Sources */ = {isa = PBXBuildFile; fileRef = FAFC6EB714F9E3F500379751 /* MMCursorAggregate.m */; };
FAFC6EBA14F9EA9F00379751 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA319D3B14F353C50064E7CC /* Accelerate.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
FADA4A5514FB05C900517F22 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = FA6F2CF014F314FF0098AE57 /* Project object */;
proxyType = 1;
remoteGlobalIDString = FA6F2D1D14F3150E0098AE57;
remoteInfo = magicmouse;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
FA6F2D1C14F3150E0098AE57 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
FA6F2D2614F3150E0098AE57 /* magicmouse.1 in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
FAFC6EAD14F9ACEF00379751 /* Copy magicmouse */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 6;
files = (
FAFC6EAE14F9AD0D00379751 /* magicmouse in Copy magicmouse */,
);
name = "Copy magicmouse";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0E7C3CC414F9FB1A0003A5FE /* cursor.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = cursor.png; path = ../cursor.png; sourceTree = "<group>"; };
FA02424314FF0993006E6FE1 /* MMAdvancedEditViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMAdvancedEditViewController.h; path = src/Controllers/MMAdvancedEditViewController.h; sourceTree = "<group>"; };
FA02424414FF0993006E6FE1 /* MMAdvancedEditViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMAdvancedEditViewController.m; path = src/Controllers/MMAdvancedEditViewController.m; sourceTree = "<group>"; };
FA02424514FF0993006E6FE1 /* AdvancedEdit.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = AdvancedEdit.xib; path = src/Controllers/AdvancedEdit.xib; sourceTree = "<group>"; };
FA05ED0F15571D7800BEC0AC /* MMCursorLibrary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMCursorLibrary.h; path = src/Controllers/MMCursorLibrary.h; sourceTree = "<group>"; };
FA05ED1015571D7800BEC0AC /* MMCursorLibrary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMCursorLibrary.m; path = src/Controllers/MMCursorLibrary.m; sourceTree = "<group>"; };
FA07746B14F9976100A1B91B /* MMAnimatingImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMAnimatingImageView.h; path = src/Views/MMAnimatingImageView.h; sourceTree = "<group>"; };
FA07746C14F9976100A1B91B /* MMAnimatingImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMAnimatingImageView.m; path = src/Views/MMAnimatingImageView.m; sourceTree = "<group>"; };
FA07747014F9A25400A1B91B /* CarbonHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CarbonHelpers.h; sourceTree = "<group>"; };
FA07747114F9A25400A1B91B /* CGSAccessibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSAccessibility.h; sourceTree = "<group>"; };
FA07747214F9A25400A1B91B /* CGSCIFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSCIFilter.h; sourceTree = "<group>"; };
FA07747314F9A25400A1B91B /* CGSConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSConnection.h; sourceTree = "<group>"; };
FA07747414F9A25400A1B91B /* CGSCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSCursor.h; sourceTree = "<group>"; };
FA07747514F9A25400A1B91B /* CGSDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSDebug.h; sourceTree = "<group>"; };
FA07747614F9A25400A1B91B /* CGSDisplays.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSDisplays.h; sourceTree = "<group>"; };
FA07747714F9A25400A1B91B /* CGSHotKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSHotKeys.h; sourceTree = "<group>"; };
FA07747814F9A25400A1B91B /* CGSInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSInternal.h; sourceTree = "<group>"; };
FA07747914F9A25400A1B91B /* CGSMisc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSMisc.h; sourceTree = "<group>"; };
FA07747A14F9A25400A1B91B /* CGSNotifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSNotifications.h; sourceTree = "<group>"; };
FA07747B14F9A25400A1B91B /* CGSRegion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSRegion.h; sourceTree = "<group>"; };
FA07747C14F9A25400A1B91B /* CGSSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSSession.h; sourceTree = "<group>"; };
FA07747D14F9A25400A1B91B /* CGSTransitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSTransitions.h; sourceTree = "<group>"; };
FA07747E14F9A25400A1B91B /* CGSWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSWindow.h; sourceTree = "<group>"; };
FA07747F14F9A25400A1B91B /* CGSWorkspace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSWorkspace.h; sourceTree = "<group>"; };
FA21EF961550C642002D688E /* MMCursorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMCursorViewController.h; path = src/Controllers/MMCursorViewController.h; sourceTree = "<group>"; };
FA21EF971550C642002D688E /* MMCursorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMCursorViewController.m; path = src/Controllers/MMCursorViewController.m; sourceTree = "<group>"; };
FA319D3B14F353C50064E7CC /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
FA6F2CFD14F315000098AE57 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
FA6F2D0014F315000098AE57 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
FA6F2D0114F315000098AE57 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
FA6F2D0214F315000098AE57 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
FA6F2D1E14F3150E0098AE57 /* magicmouse */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = magicmouse; sourceTree = BUILT_PRODUCTS_DIR; };
FA6F2D2014F3150E0098AE57 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
FA6F2D2314F3150E0098AE57 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
FA6F2D2514F3150E0098AE57 /* magicmouse.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = magicmouse.1; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.man; };
FA6F2D2A14F315490098AE57 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; };
FAD37AF614F9830600B7F09C /* MMDefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMDefs.h; sourceTree = "<group>"; };
FAD37AFE14F9836E00B7F09C /* Magic Mouse.prefPane */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Magic Mouse.prefPane"; sourceTree = BUILT_PRODUCTS_DIR; };
FAD37B0014F9836E00B7F09C /* PreferencePanes.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PreferencePanes.framework; path = System/Library/Frameworks/PreferencePanes.framework; sourceTree = SDKROOT; };
FAD37B1414F983B900B7F09C /* MMPrefPane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMPrefPane.h; sourceTree = "<group>"; };
FAD37B1514F983B900B7F09C /* MMPrefPane.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMPrefPane.m; sourceTree = "<group>"; };
FAD37B1614F983B900B7F09C /* Magic_Mouse.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Magic_Mouse.tiff; sourceTree = "<group>"; };
FAD37B2314F983D700B7F09C /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/Magic_Mouse.xib; sourceTree = "<group>"; };
FAD37B2914F983E800B7F09C /* Magic Mouse-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Magic Mouse-Info.plist"; sourceTree = "<group>"; };
FAD37B2A14F983E800B7F09C /* Magic Mouse-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Magic Mouse-Prefix.pch"; sourceTree = "<group>"; };
FAD37B2E14F983F000B7F09C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
FADA4A4B14FAEA4F00517F22 /* MMAnimatingImageTableCellView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMAnimatingImageTableCellView.h; path = src/Views/MMAnimatingImageTableCellView.h; sourceTree = "<group>"; };
FADA4A4C14FAEA4F00517F22 /* MMAnimatingImageTableCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMAnimatingImageTableCellView.m; path = src/Views/MMAnimatingImageTableCellView.m; sourceTree = "<group>"; };
FADA4A5314FB017400517F22 /* NSCursor_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSCursor_Private.h; sourceTree = "<group>"; };
FAEBD4AA1551DBAA00F4B4D9 /* MMAdvancedEditWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMAdvancedEditWindowController.h; path = src/Controllers/MMAdvancedEditWindowController.h; sourceTree = "<group>"; };
FAEBD4AB1551DBAA00F4B4D9 /* MMAdvancedEditWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMAdvancedEditWindowController.m; path = src/Controllers/MMAdvancedEditWindowController.m; sourceTree = "<group>"; };
FAEBD4AC1551DBAA00F4B4D9 /* EditWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = EditWindow.xib; path = src/Controllers/EditWindow.xib; sourceTree = "<group>"; };
FAFC6EB214F9C1C300379751 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
FAFC6EB314F9C1C300379751 /* SecurityInterface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityInterface.framework; path = System/Library/Frameworks/SecurityInterface.framework; sourceTree = SDKROOT; };
FAFC6EB614F9E3F500379751 /* MMCursorAggregate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMCursorAggregate.h; sourceTree = "<group>"; };
FAFC6EB714F9E3F500379751 /* MMCursorAggregate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMCursorAggregate.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
FA6F2D1B14F3150E0098AE57 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FA319D3C14F353C50064E7CC /* Accelerate.framework in Frameworks */,
FA6F2D2114F3150E0098AE57 /* CoreFoundation.framework in Frameworks */,
FA6F2D2C14F3154E0098AE57 /* ApplicationServices.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FAD37AF914F9836E00B7F09C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FAFC6EB414F9C1C300379751 /* Security.framework in Frameworks */,
FAFC6EB514F9C1C300379751 /* SecurityInterface.framework in Frameworks */,
FAD37AFF14F9836E00B7F09C /* Cocoa.framework in Frameworks */,
FAFC6EBA14F9EA9F00379751 /* Accelerate.framework in Frameworks */,
FAD37B0114F9836E00B7F09C /* PreferencePanes.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
FA05ED1A1557286500BEC0AC /* Views */ = {
isa = PBXGroup;
children = (
FA07746B14F9976100A1B91B /* MMAnimatingImageView.h */,
FA07746C14F9976100A1B91B /* MMAnimatingImageView.m */,
FADA4A4B14FAEA4F00517F22 /* MMAnimatingImageTableCellView.h */,
FADA4A4C14FAEA4F00517F22 /* MMAnimatingImageTableCellView.m */,
);
name = Views;
sourceTree = "<group>";
};
FA07746F14F9A25400A1B91B /* CGSInternal */ = {
isa = PBXGroup;
children = (
FA07747014F9A25400A1B91B /* CarbonHelpers.h */,
FA07747114F9A25400A1B91B /* CGSAccessibility.h */,
FA07747214F9A25400A1B91B /* CGSCIFilter.h */,
FA07747314F9A25400A1B91B /* CGSConnection.h */,
FA07747414F9A25400A1B91B /* CGSCursor.h */,
FA07747514F9A25400A1B91B /* CGSDebug.h */,
FA07747614F9A25400A1B91B /* CGSDisplays.h */,
FA07747714F9A25400A1B91B /* CGSHotKeys.h */,
FA07747814F9A25400A1B91B /* CGSInternal.h */,
FA07747914F9A25400A1B91B /* CGSMisc.h */,
FA07747A14F9A25400A1B91B /* CGSNotifications.h */,
FA07747B14F9A25400A1B91B /* CGSRegion.h */,
FA07747C14F9A25400A1B91B /* CGSSession.h */,
FA07747D14F9A25400A1B91B /* CGSTransitions.h */,
FA07747E14F9A25400A1B91B /* CGSWindow.h */,
FA07747F14F9A25400A1B91B /* CGSWorkspace.h */,
);
path = CGSInternal;
sourceTree = "<group>";
};
FA6F2CEE14F314FF0098AE57 = {
isa = PBXGroup;
children = (
FA6F2D2214F3150E0098AE57 /* magicmouse */,
FAD37B0214F9836E00B7F09C /* Magic Mouse */,
FA6F2CFC14F315000098AE57 /* Frameworks */,
FA6F2CFA14F315000098AE57 /* Products */,
);
sourceTree = "<group>";
};
FA6F2CFA14F315000098AE57 /* Products */ = {
isa = PBXGroup;
children = (
FA6F2D1E14F3150E0098AE57 /* magicmouse */,
FAD37AFE14F9836E00B7F09C /* Magic Mouse.prefPane */,
);
name = Products;
sourceTree = "<group>";
};
FA6F2CFC14F315000098AE57 /* Frameworks */ = {
isa = PBXGroup;
children = (
FAFC6EB214F9C1C300379751 /* Security.framework */,
FAFC6EB314F9C1C300379751 /* SecurityInterface.framework */,
FA319D3B14F353C50064E7CC /* Accelerate.framework */,
FA6F2D2A14F315490098AE57 /* ApplicationServices.framework */,
FA6F2CFD14F315000098AE57 /* Cocoa.framework */,
FA6F2D2014F3150E0098AE57 /* CoreFoundation.framework */,
FAD37B0014F9836E00B7F09C /* PreferencePanes.framework */,
FA6F2CFF14F315000098AE57 /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
FA6F2CFF14F315000098AE57 /* Other Frameworks */ = {
isa = PBXGroup;
children = (
FA6F2D0014F315000098AE57 /* AppKit.framework */,
FA6F2D0114F315000098AE57 /* CoreData.framework */,
FA6F2D0214F315000098AE57 /* Foundation.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
FA6F2D2214F3150E0098AE57 /* magicmouse */ = {
isa = PBXGroup;
children = (
FAD37AF614F9830600B7F09C /* MMDefs.h */,
FA07746F14F9A25400A1B91B /* CGSInternal */,
FA6F2D2314F3150E0098AE57 /* main.c */,
FA6F2D2514F3150E0098AE57 /* magicmouse.1 */,
);
path = magicmouse;
sourceTree = "<group>";
};
FAD37B0214F9836E00B7F09C /* Magic Mouse */ = {
isa = PBXGroup;
children = (
FADA4A5314FB017400517F22 /* NSCursor_Private.h */,
FAD37B1414F983B900B7F09C /* MMPrefPane.h */,
FAD37B1514F983B900B7F09C /* MMPrefPane.m */,
FA21EF961550C642002D688E /* MMCursorViewController.h */,
FA21EF971550C642002D688E /* MMCursorViewController.m */,
FAFC6EB614F9E3F500379751 /* MMCursorAggregate.h */,
FAFC6EB714F9E3F500379751 /* MMCursorAggregate.m */,
FA02424314FF0993006E6FE1 /* MMAdvancedEditViewController.h */,
FA02424414FF0993006E6FE1 /* MMAdvancedEditViewController.m */,
FAEBD4AA1551DBAA00F4B4D9 /* MMAdvancedEditWindowController.h */,
FAEBD4AB1551DBAA00F4B4D9 /* MMAdvancedEditWindowController.m */,
FA05ED0F15571D7800BEC0AC /* MMCursorLibrary.h */,
FA05ED1015571D7800BEC0AC /* MMCursorLibrary.m */,
FA05ED1A1557286500BEC0AC /* Views */,
FAD37B0314F9836E00B7F09C /* Supporting Files */,
);
path = "Magic Mouse";
sourceTree = "<group>";
};
FAD37B0314F9836E00B7F09C /* Supporting Files */ = {
isa = PBXGroup;
children = (
0E7C3CC414F9FB1A0003A5FE /* cursor.png */,
FAD37B1614F983B900B7F09C /* Magic_Mouse.tiff */,
FA02424514FF0993006E6FE1 /* AdvancedEdit.xib */,
FAEBD4AC1551DBAA00F4B4D9 /* EditWindow.xib */,
FAD37B2214F983D700B7F09C /* Magic_Mouse.xib */,
FAD37B2D14F983F000B7F09C /* InfoPlist.strings */,
FAD37B2914F983E800B7F09C /* Magic Mouse-Info.plist */,
FAD37B2A14F983E800B7F09C /* Magic Mouse-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
FAD37AFA14F9836E00B7F09C /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
FAD37B1714F983B900B7F09C /* MMPrefPane.h in Headers */,
FAD37B2C14F983E800B7F09C /* Magic Mouse-Prefix.pch in Headers */,
FA07748114F9A70E00A1B91B /* MMAnimatingImageView.h in Headers */,
FAFC6EB814F9E3F500379751 /* MMCursorAggregate.h in Headers */,
FADA4A4D14FAEA4F00517F22 /* MMAnimatingImageTableCellView.h in Headers */,
FADA4A5414FB017400517F22 /* NSCursor_Private.h in Headers */,
FA02424614FF0993006E6FE1 /* MMAdvancedEditViewController.h in Headers */,
FA21EF981550C642002D688E /* MMCursorViewController.h in Headers */,
FAEBD4AD1551DBAA00F4B4D9 /* MMAdvancedEditWindowController.h in Headers */,
FA05ED1115571D7800BEC0AC /* MMCursorLibrary.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
FA6F2D1D14F3150E0098AE57 /* magicmouse */ = {
isa = PBXNativeTarget;
buildConfigurationList = FA6F2D2714F3150E0098AE57 /* Build configuration list for PBXNativeTarget "magicmouse" */;
buildPhases = (
FA6F2D1A14F3150E0098AE57 /* Sources */,
FA6F2D1B14F3150E0098AE57 /* Frameworks */,
FA6F2D1C14F3150E0098AE57 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = magicmouse;
productName = magicmouse;
productReference = FA6F2D1E14F3150E0098AE57 /* magicmouse */;
productType = "com.apple.product-type.tool";
};
FAD37AFD14F9836E00B7F09C /* Magic Mouse */ = {
isa = PBXNativeTarget;
buildConfigurationList = FAD37B1114F9836E00B7F09C /* Build configuration list for PBXNativeTarget "Magic Mouse" */;
buildPhases = (
FAD37AF814F9836E00B7F09C /* Sources */,
FAD37AF914F9836E00B7F09C /* Frameworks */,
FAD37AFA14F9836E00B7F09C /* Headers */,
FAD37AFB14F9836E00B7F09C /* Resources */,
FAFC6EAD14F9ACEF00379751 /* Copy magicmouse */,
FA129BAC151297FF00F28572 /* ShellScript */,
);
buildRules = (
);
dependencies = (
FADA4A5614FB05C900517F22 /* PBXTargetDependency */,
);
name = "Magic Mouse";
productName = "Magic Mouse";
productReference = FAD37AFE14F9836E00B7F09C /* Magic Mouse.prefPane */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
FA6F2CF014F314FF0098AE57 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0440;
ORGANIZATIONNAME = "Alex Zielenski";
};
buildConfigurationList = FA6F2CF314F314FF0098AE57 /* Build configuration list for PBXProject "Magic Mouse" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = FA6F2CEE14F314FF0098AE57;
productRefGroup = FA6F2CFA14F315000098AE57 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
FA6F2D1D14F3150E0098AE57 /* magicmouse */,
FAD37AFD14F9836E00B7F09C /* Magic Mouse */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
FAD37AFB14F9836E00B7F09C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FAD37B1914F983B900B7F09C /* Magic_Mouse.tiff in Resources */,
FAD37B2414F983D700B7F09C /* Magic_Mouse.xib in Resources */,
FAD37B2F14F983F000B7F09C /* InfoPlist.strings in Resources */,
0E7C3CC514F9FB1A0003A5FE /* cursor.png in Resources */,
FA02424814FF0993006E6FE1 /* AdvancedEdit.xib in Resources */,
FAEBD4AF1551DBAA00F4B4D9 /* EditWindow.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
FA129BAC151297FF00F28572 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "#!/bin/bash\nbuildNumber=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" \"Magic Mouse/Magic Mouse-Info.plist\")\nbuildNumber=$(($buildNumber + 1))\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $buildNumber\" \"Magic Mouse/Magic Mouse-Info.plist\"";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
FA6F2D1A14F3150E0098AE57 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FA6F2D2414F3150E0098AE57 /* main.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FAD37AF814F9836E00B7F09C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FAD37B1814F983B900B7F09C /* MMPrefPane.m in Sources */,
FA07748014F9A70A00A1B91B /* MMAnimatingImageView.m in Sources */,
FAFC6EB914F9E3F500379751 /* MMCursorAggregate.m in Sources */,
FADA4A4E14FAEA4F00517F22 /* MMAnimatingImageTableCellView.m in Sources */,
FA02424714FF0993006E6FE1 /* MMAdvancedEditViewController.m in Sources */,
FA21EF991550C642002D688E /* MMCursorViewController.m in Sources */,
FAEBD4AE1551DBAA00F4B4D9 /* MMAdvancedEditWindowController.m in Sources */,
FA05ED1215571D7800BEC0AC /* MMCursorLibrary.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
FADA4A5614FB05C900517F22 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FA6F2D1D14F3150E0098AE57 /* magicmouse */;
targetProxy = FADA4A5514FB05C900517F22 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
FAD37B2214F983D700B7F09C /* Magic_Mouse.xib */ = {
isa = PBXVariantGroup;
children = (
FAD37B2314F983D700B7F09C /* en */,
);
name = Magic_Mouse.xib;
sourceTree = "<group>";
};
FAD37B2D14F983F000B7F09C /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
FAD37B2E14F983F000B7F09C /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
FA6F2D1514F315000098AE57 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
COPY_PHASE_STRIP = NO;
DEPLOYMENT_LOCATION = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "";
SDKROOT = macosx10.7;
};
name = Debug;
};
FA6F2D1614F315000098AE57 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEPLOYMENT_LOCATION = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
OTHER_LDFLAGS = "";
SDKROOT = macosx10.7;
};
name = Release;
};
FA6F2D2814F3150E0098AE57 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
FA6F2D2914F3150E0098AE57 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
FAD37B1214F9836E00B7F09C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DEPLOYMENT_LOCATION = YES;
DSTROOT = /;
GCC_ENABLE_OBJC_GC = supported;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Magic Mouse/Magic Mouse-Prefix.pch";
INFOPLIST_FILE = "Magic Mouse/Magic Mouse-Info.plist";
INSTALL_PATH = "$(HOME)/Library/PreferencePanes";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = prefPane;
};
name = Debug;
};
FAD37B1314F9836E00B7F09C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DEPLOYMENT_LOCATION = YES;
DSTROOT = /;
GCC_ENABLE_OBJC_GC = supported;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Magic Mouse/Magic Mouse-Prefix.pch";
INFOPLIST_FILE = "Magic Mouse/Magic Mouse-Info.plist";
INSTALL_PATH = "$(HOME)/Library/PreferencePanes";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = prefPane;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
FA6F2CF314F314FF0098AE57 /* Build configuration list for PBXProject "Magic Mouse" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FA6F2D1514F315000098AE57 /* Debug */,
FA6F2D1614F315000098AE57 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FA6F2D2714F3150E0098AE57 /* Build configuration list for PBXNativeTarget "magicmouse" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FA6F2D2814F3150E0098AE57 /* Debug */,
FA6F2D2914F3150E0098AE57 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FAD37B1114F9836E00B7F09C /* Build configuration list for PBXNativeTarget "Magic Mouse" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FAD37B1214F9836E00B7F09C /* Debug */,
FAD37B1314F9836E00B7F09C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = FA6F2CF014F314FF0098AE57 /* Project object */;
}
@@ -1,10 +0,0 @@
<?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>HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
<true/>
<key>SnapshotAutomaticallyBeforeSignificantChanges</key>
<false/>
</dict>
</plist>
@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0440"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FAD37AFD14F9836E00B7F09C"
BuildableName = "Magic Mouse.prefPane"
BlueprintName = "Magic Mouse"
ReferencedContainer = "container:Magic Mouse.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<PathRunnable
FilePath = "/Applications/System Preferences.app">
</PathRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "/Users/Alex/Library/PreferencePanes/Magic Mouse.prefPane"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FAD37AFD14F9836E00B7F09C"
BuildableName = "Magic Mouse.prefPane"
BlueprintName = "Magic Mouse"
ReferencedContainer = "container:Magic Mouse.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -1,32 +0,0 @@
<?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>SchemeUserState</key>
<dict>
<key>Magic Mouse.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
<key>magicmouse.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>FA6F2D1D14F3150E0098AE57</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>FAD37AFD14F9836E00B7F09C</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
-61
View File
@@ -1,61 +0,0 @@
//
// MMCursorAggregate.h
// Magic Mouse
//
// Created by Alex Zielenski on 2/25/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface MMCursor : NSObject
@property (nonatomic, retain) NSBitmapImageRep *image;
@property (nonatomic, assign) CGFloat frameDuration;
@property (nonatomic, assign) NSInteger frameCount;
@property (nonatomic, assign) NSSize size;
@property (nonatomic, assign) NSPoint hotSpot;
@property (nonatomic, copy) NSString *tableIdentifier;
@property (nonatomic, copy) NSString *defaultKey;
@property (nonatomic, copy) NSString *customKey;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *cursorIdentifier;
// creating a cursor from a dictionary
+ (MMCursor *)cursorWithDictionary:(NSDictionary *)dict;
- (id)initWithCursorDictionary:(NSDictionary *)dict;
// Creating a dictionary from the cursor
- (NSDictionary *)cursorDictionary;
- (NSDictionary *)infoDictionary;
@end
@interface MMCursorAggregate : NSObject {
@private
NSMutableDictionary *_cursors;
}
@property (nonatomic, copy, readonly) NSString *path;
@property (nonatomic, retain) NSDictionary *cursors;
@property (nonatomic, retain) NSString *minimumVersion;
@property (nonatomic, retain) NSString *creatorVersion;
// creating an aggregate from a file
+ (MMCursorAggregate *)aggregateWithContentsOfFile:(NSString *)path;
- (id)initWithContentsOfFile:(NSString *)path;
+ (MMCursorAggregate *)aggregateWithDictionary:(NSDictionary *)dict;
- (id)initWithAggregateDictionary:(NSDictionary *)dict;
// A domain would be the internal reverse-dns identifier used to tag cursors like com.apple.coregraphics.Arrow
- (void)setCursor:(MMCursor *)cursor forDomain:(NSString *)domain;
- (void)removeCursorForDomain:(NSString *)domain;
// Retrieves (if it exists) a cursor in the _cursors ivar with the specified table identifier
- (MMCursor *)cursorForTableIdentifier:(NSString *)identifier;
- (NSDictionary *)dictionaryRepresentation;
@end
-320
View File
@@ -1,320 +0,0 @@
//
// MMCursorAggregate.m
// Magic Mouse
//
// Created by Alex Zielenski on 2/25/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import "MMCursorAggregate.h"
#import "MMDefs.h"
#import <Accelerate/Accelerate.h>
@interface MMCursorAggregate ()
@property (nonatomic, copy, readwrite) NSString *path;
@end
@implementation MMCursorAggregate
@synthesize path = _path;
@synthesize cursors = _cursors;
@synthesize minimumVersion = _minimumVersion;
@synthesize creatorVersion = _creatorVersion;
// creating an aggregate from a file
+ (MMCursorAggregate *)aggregateWithContentsOfFile:(NSString *)path
{
return [[[self alloc] initWithContentsOfFile:path] autorelease];
}
- (id)initWithContentsOfFile:(NSString *)path
{
if ((self = [self initWithAggregateDictionary:[NSDictionary dictionaryWithContentsOfFile:path]]))
self.path = path;
return self;
}
+ (MMCursorAggregate *)aggregateWithDictionary:(NSDictionary *)dict {
return [[[self alloc] initWithAggregateDictionary:dict] autorelease];
}
//!*****************************************************************************************************************************************//
//!** The cursor files are merely plists. They have a root dict with a minimum version, and creator version, and a child dictionary with **//
//!** an Identifiers dictionary and a Cursor data dictionary. each contain neccssary information to override the internal system cursors. **//
//!*****************************************************************************************************************************************//
- (id)initWithAggregateDictionary:(NSDictionary *)dict {
if ((self = [self init])) {
NSDictionary *cursors = [dict objectForKey:(NSString *)kCursorsKey];
NSDictionary *cursorData = [cursors objectForKey:(NSString *)kCursorDataKey];
NSDictionary *global = [cursors objectForKey:(NSString *)kCursorInfoKey];
NSDictionary *identifiers = [global objectForKey:(NSString *)kCursorInfoIdentifiersKey];
for (NSString *key in identifiers) {
NSDictionary *info = [identifiers objectForKey:key];
NSDictionary *data = [cursorData objectForKey:[info objectForKey:(NSString *)kCursorInfoCustomKey]];
MMCursor *cursor = [MMCursor cursorWithDictionary:data];
cursor.cursorIdentifier = key;
cursor.defaultKey = [info objectForKey:(NSString *)kCursorInfoDefaultKey];
cursor.customKey = [info objectForKey:(NSString *)kCursorInfoCustomKey];
cursor.name = [info objectForKey:(NSString *)kCursorInfoNameKey];
cursor.tableIdentifier = [info objectForKey:(NSString *)kCursorInfoTableIdentifierKey];
[self setCursor:cursor forDomain:key];
}
self.minimumVersion = [dict objectForKey:(NSString *)kMinimumVersionKey];
self.creatorVersion = [dict objectForKey:(NSString *)kCreatorVersionKey];
}
return self;
}
- (id)init {
if ((self = [super init])) {
_cursors = [NSMutableDictionary dictionary];
self.minimumVersion = @"1.02";
self.creatorVersion = @"1.02";
}
return self;
}
- (void)dealloc {
self.cursors = nil;
[super dealloc];
}
- (void)setCursor:(MMCursor *)cursor forDomain:(NSString *)domain {
if (!domain||!cursor)
return;
[_cursors setObject:cursor forKey:domain];
}
- (void)removeCursorForDomain:(NSString *)domain {
if (!domain)
return;
[_cursors removeObjectForKey:domain];
}
- (MMCursor *)cursorForTableIdentifier:(NSString *)identifier {
NSArray *ar = [self.cursors.allValues filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"tableIdentifier == %@", identifier]];
if (ar.count>0)
return [ar objectAtIndex:0];
return nil;
}
- (NSDictionary *)dictionaryRepresentation {
NSMutableDictionary *root = [[NSMutableDictionary alloc] init];
NSMutableDictionary *cursors = [[NSMutableDictionary alloc] initWithCapacity:2];
NSMutableDictionary *cursorData = [[NSMutableDictionary alloc] init];
NSMutableDictionary *global = [[NSMutableDictionary alloc] init];
NSMutableDictionary *identifiers = [[NSMutableDictionary alloc] init];
for (NSString *key in self.cursors) {
MMCursor *cursor = [self.cursors objectForKey:key];
[identifiers setObject:cursor.infoDictionary forKey:key];
[cursorData setObject:cursor.cursorDictionary forKey:cursor.customKey];
}
[global setObject:identifiers forKey:(NSString *)kCursorInfoIdentifiersKey];
[cursors setObject:cursorData forKey:(NSString *)kCursorDataKey];
[cursors setObject:global forKey:(NSString *)kCursorInfoKey];
[root setObject:cursors forKey:(NSString *)kCursorsKey];
[root setObject:self.minimumVersion forKey:(NSString *)kMinimumVersionKey];
[root setObject:self.creatorVersion forKey:(NSString *)kCreatorVersionKey];
[identifiers release];
[cursorData release];
[global release];
[cursors release];
return [root autorelease];
}
@end
@implementation MMCursor
@synthesize image = _image;
@synthesize frameCount = _frameCount;
@synthesize frameDuration = _frameDuration;
@synthesize size = _size;
@synthesize hotSpot = _hotSpot;
@synthesize tableIdentifier = _tableIdentifier;
@synthesize defaultKey = _defaultKey;
@synthesize customKey = _customKey;
@synthesize name = _name;
@synthesize cursorIdentifier = _cursorIdentifier;
+ (MMCursor *)cursorWithDictionary:(NSDictionary *)dict {
return [[[self alloc] initWithCursorDictionary:dict] autorelease];
}
- (id)init {
if ((self = [super init])) {
// Some default values
self.name = @"";
self.customKey = @"";
self.defaultKey = @"";
self.tableIdentifier = @"";
self.frameCount = 1;
self.frameDuration = 0.0299999993294477;
}
return self;
}
- (void)dealloc {
self.image = nil;
self.tableIdentifier = nil;
self.defaultKey = nil;
self.customKey = nil;
self.name = nil;
self.cursorIdentifier = nil;
[super dealloc];
}
//!*******************************************************************************************************************************************//
//!** The dictionary passed would be one of the subdictionaries in the cursor data field. This method retrieves all the required info for **//
//!** creating a bitmap from keys in this dictionary. Other values from the identifiers dictionary are added in the parent cursor aggregate.**//
//!*******************************************************************************************************************************************//
- (id)initWithCursorDictionary:(NSDictionary *)dict {
if ((self = [self init])) {
NSData *rawData = [dict objectForKey:(NSString *)kCursorDataDataKey];
NSNumber *width = [dict objectForKey:(NSString *)kCursorDataPixelsWideKey];
NSNumber *height = [dict objectForKey:(NSString *)kCursorDataPixelsHighKey];
NSNumber *hotSpotX = [dict objectForKey:(NSString *)kCursorDataHotspotXKey];
NSNumber *hotSpotY = [dict objectForKey:(NSString *)kCursorDataHotspotYKey];
NSNumber *bytesPerRow = [dict objectForKey:(NSString *)kCursorDataBytesPerRowKey];
NSNumber *bitsPerSample = [dict objectForKey:(NSString *)kCursorDataBitsPerSampleKey];
NSNumber *bitsPerPixel = [dict objectForKey:(NSString *)kCursorDataBitsPerPixelKey];
// NSNumber *samplesPerPixel = [dict objectForKey:(NSString *)kCursorDataSamplesPerPixelKey]; // This key is not needed
NSNumber *frameCount = [dict objectForKey:(NSString *)kCursorDataFrameCountKey];
NSNumber *frameDuration = [dict objectForKey:(NSString *)kCursorDataFrameDurationKey];
self.frameCount = frameCount.integerValue;
self.frameDuration = frameDuration.doubleValue;
self.size = NSMakeSize(width.integerValue, height.integerValue);
self.hotSpot = NSMakePoint(hotSpotX.floatValue, hotSpotY.floatValue);
// Convert the raw data into a presentable format.
// For some crazy reason, It won't let me create the image straight using the NSBitmapImageRep. (32big & Alpha first).
// I will use CGimage and convert it for now
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((CFDataRef)rawData);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGImageRef cursorImage = CGImageCreate(self.size.width,
self.size.height * self.frameCount,
bitsPerSample.intValue,
bitsPerPixel.intValue,
bytesPerRow.intValue,
colorspace,
kCGBitmapByteOrder32Big | kCGImageAlphaFirst,
dataProvider, NULL, false, kCGRenderingIntentDefault);
CGColorSpaceRelease(colorspace);
CGDataProviderRelease(dataProvider);
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithCGImage:cursorImage];
self.image = rep;
CGImageRelease(cursorImage);
[rep release];
}
return self;
}
//!*****************************************************************************************************************************************//
//!** In this method the values are taken from the MMCursor properties and converted for use in the plist. Specifically, the raw pixel **//
//!** data gets reformatted to ARGB 32-big pixel format to ensure consistency among all of the cursors so that magic mouse can read it. **//
//!*****************************************************************************************************************************************//
- (NSDictionary *)cursorDictionary {
// Creates and returns a dictionary representation for use with magic mouse
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:11];
// Convert the image to raw data
unsigned char *bytePtr = [self.image bitmapData];
BOOL alphaFirst = (self.image.bitmapFormat & NSAlphaFirstBitmapFormat) == NSAlphaFirstBitmapFormat;
BOOL premultiplied = (self.image.bitmapFormat & NSAlphaNonpremultipliedBitmapFormat) == NSAlphaNonpremultipliedBitmapFormat;
BOOL littleByteOrder = (self.image.bitmapFormat & kCGBitmapByteOrder32Little) == kCGBitmapByteOrder32Little;
vImage_Buffer src;
src.data = (void*)bytePtr;
src.rowBytes = self.image.bytesPerRow;
src.width = self.image.size.width;
src.height = self.image.size.height;
uint8_t permuteMap[4];
//! Arrange the bytes to 32 big order and alpha non-premultiplied first. It is imperative that all of tha raw data follows the same format
//! (ARGB, 32-big byte order) otherwise consequences will ensue.
if (alphaFirst) {
if (littleByteOrder) {
// BGRA to ARGB
permuteMap[0] = 3;
permuteMap[1] = 2;
permuteMap[2] = 1;
permuteMap[3] = 0;
} else {
// ARGB to ARGB
permuteMap[0] = 0;
permuteMap[1] = 1;
permuteMap[2] = 2;
permuteMap[3] = 3;
}
} else {
if (littleByteOrder) {
// ABGR to ARGB
permuteMap[0] = 0;
permuteMap[1] = 3;
permuteMap[2] = 2;
permuteMap[3] = 1;
} else {
// RGBA to ARGB
permuteMap[0] = 3;
permuteMap[1] = 0;
permuteMap[2] = 1;
permuteMap[3] = 2;
}
}
// Permute the data using the "scramble" values above
vImagePermuteChannels_ARGB8888(&src, &src, permuteMap, 0);
if (premultiplied) {
// The final data must also remain unpremultiplied, so undo this if the image is unpremultiplied.
vImageUnpremultiplyData_ARGB8888(&src, &src, 0);
}
// Finally set the values to their appropriate key.
NSData *rawData = [NSData dataWithBytes:src.data length:src.rowBytes * src.height];
[dict setObject:rawData forKey:(NSString *)kCursorDataDataKey];
[dict setObject:[NSNumber numberWithInteger:self.image.bytesPerRow] forKey:(NSString *)kCursorDataBytesPerRowKey];
[dict setObject:[NSNumber numberWithInteger:self.image.samplesPerPixel] forKey:(NSString *)kCursorDataSamplesPerPixelKey];
[dict setObject:[NSNumber numberWithInteger:self.image.bitsPerPixel] forKey:(NSString *)kCursorDataBitsPerPixelKey];
[dict setObject:[NSNumber numberWithInteger:self.image.bitsPerSample] forKey:(NSString *)kCursorDataBitsPerSampleKey];
[dict setObject:[NSNumber numberWithFloat:self.frameDuration] forKey:(NSString *)kCursorDataFrameDurationKey];
[dict setObject:[NSNumber numberWithInteger:self.frameCount] forKey:(NSString *)kCursorDataFrameCountKey];
[dict setObject:[NSNumber numberWithInteger:self.size.width] forKey:(NSString *)kCursorDataPixelsWideKey];
[dict setObject:[NSNumber numberWithInteger:self.size.height] forKey:(NSString *)kCursorDataPixelsHighKey];
[dict setObject:[NSNumber numberWithInteger:self.hotSpot.x] forKey:(NSString *)kCursorDataHotspotXKey];
[dict setObject:[NSNumber numberWithInteger:self.hotSpot.y] forKey:(NSString *)kCursorDataHotspotYKey];
return dict;
}
//!*****************************************************************************************************************************************//
//!** This method creates the dictionary for use in the Identifiers dictionary. (As opposed to cursor data above). These values are **//
//!** assigned during initialization in the cursor aggregate and are used to see which cursor image replaces what and where to display it **//
//!*****************************************************************************************************************************************//
- (NSDictionary *)infoDictionary {
return [NSDictionary dictionaryWithObjectsAndKeys:
self.defaultKey, (NSString *)kCursorInfoDefaultKey,
self.customKey, (NSString*)kCursorInfoCustomKey,
self.name, (NSString *)kCursorInfoNameKey,
self.tableIdentifier, (NSString*)kCursorInfoTableIdentifierKey, nil];
}
@end
-46
View File
@@ -1,46 +0,0 @@
//
// MMPrefPane.h
// Magic Mouse
//
// Created by Alex Zielenski on 2/25/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import <PreferencePanes/PreferencePanes.h>
#import <SecurityInterface/SFAuthorizationView.h>
#import "MMCursorAggregate.h"
#import "MMCursorViewController.h"
#import "MMAdvancedEditWindowController.h"
#import "MMCursorLibrary.h"
@interface MMPrefPane : NSPreferencePane <NSTabViewDelegate, NSMenuDelegate>
@property (nonatomic, assign) IBOutlet SFAuthorizationView *authView;
@property (nonatomic, assign) IBOutlet NSPopUpButton *cursorPicker;
@property (nonatomic, assign) CGFloat cursorScale;
@property (nonatomic, retain) MMCursorAggregate *currentCursor;
@property (nonatomic, retain) IBOutlet MMCursorViewController *cursorViewController;
@property (nonatomic, retain) MMAdvancedEditWindowController *advancedEditWindowController;
@property (nonatomic, retain) MMCursorLibrary *cursorLibrary;
- (void)mainViewDidLoad;
- (void)initializeData;
- (void)initializeCursorData;
- (BOOL)isUnlocked;
// Interface actions
- (IBAction)applyCursors:(NSButton *)sender;
- (IBAction)resetCursors:(NSButton *)sender;
- (IBAction)visitWebsite:(NSButton *)sender;
- (IBAction)donate:(NSButton *)sender;
- (IBAction)uninstall:(NSButton *)sender;
- (IBAction)importCursor:(NSMenuItem *)sender;
- (IBAction)exportCursor:(NSMenuItem *)sender;
- (IBAction)advancedEdit:(NSMenuItem *)sender;
- (void)chooseCursor:(id)sender;
- (void)dumpCursorsToFile:(NSString*)filePath;
@end
-390
View File
@@ -1,390 +0,0 @@
//
// MMPrefPane.m
// Magic Mouse
//
// Created by Alex Zielenski on 2/25/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import "MMPrefPane.h"
#import "NSCursor_Private.h"
#import "MMAdvancedEditViewController.h"
@interface MMPrefPane () {
CGFloat _cursorScale;
dispatch_queue_t _actionQueue;
}
@property (nonatomic, assign) IBOutlet NSPopUpButton *_cursorThemes;
@property (nonatomic, assign) IBOutlet NSPopUpButton *_actionMenu;
@end
// Why does CFPreferences suck so much hard nuts?
@implementation MMPrefPane
#pragma mark - Private Properties
@synthesize _cursorThemes;
@synthesize _actionMenu;
#pragma mark - Public Properties
@dynamic cursorScale;
@dynamic currentCursor;
@synthesize authView = _authView;
@synthesize cursorViewController = _cursorViewController;
@synthesize advancedEditWindowController = _advancedEditWindowController;
@synthesize cursorLibrary = _cursorLibrary;
@synthesize cursorPicker = _cursorPicker;
#pragma mark - Lifecycle
- (void)dealloc {
[self.cursorViewController unbind:@"enabled"];
self.authView = nil;
self.cursorViewController = nil;
self.advancedEditWindowController = nil;
[super dealloc];
}
- (void)mainViewDidLoad {
NSArray *supports = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,
NSUserDomainMask,
YES);
NSString *appSupport = [[supports objectAtIndex:0] stringByAppendingPathComponent:@"MagicMouse"];
NSFileManager *manager = [NSFileManager defaultManager];
[manager createDirectoryAtPath:appSupport withIntermediateDirectories:YES attributes:nil error:nil];
self.cursorLibrary = [MMCursorLibrary libraryWithPath:appSupport];
_actionQueue = dispatch_queue_create("com.alexzielenski.magicmouse.action.queue", 0);
[self initializeCursorData];
self.advancedEditWindowController = [[[MMAdvancedEditWindowController alloc] initWithWindowNibName:@"EditWindow"] autorelease];
// Gather some authorization rights for the lock.
AuthorizationItem items = {kAuthorizationRightExecute, 0, NULL, 0};
AuthorizationRights rights = {1, &items};
self.authView.authorizationRights = &rights;
self.authView.delegate = self;
self.authView.autoupdate = YES;
// Update the lock for our new rights
[self.authView updateStatus:nil];
// Action Menu Force it to have the gear
[self._actionMenu.cell setUsesItemFromMenu:NO];
NSMenuItem *item = [[[NSMenuItem alloc] initWithTitle:@"" action:NULL keyEquivalent:@""] autorelease];
item.image = [NSImage imageNamed:@"NSActionTemplate"];
item.onStateImage = nil;
item.mixedStateImage = nil;
[self._actionMenu.cell setMenuItem:item];
[self.cursorViewController bind:@"enabled" toObject:self withKeyPath:@"isUnlocked" options:nil];
self.cursorPicker.action = @selector(chooseCursor:);
self.cursorPicker.target = self;
self.cursorPicker.menu.delegate = self;
// Size to fit
[self chooseCursor:self.cursorPicker];
[self menuNeedsUpdate:self.cursorPicker.menu];
[self.cursorPicker selectItemAtIndex:0];
}
- (void)willSelect {
// Renew data every time the prefpane opens
[self initializeData];
}
- (void)initializeData {
[self willChangeValueForKey:@"cursorScale"];
// Get the current cursor scale. It needs to be synchronous so that the text field is always in sync
NSTask *task = [[NSTask alloc] init];
task.launchPath = kMMToolPath;
task.arguments = [NSArray arrayWithObject:@"-s"];
task.standardOutput = [NSPipe pipe];
[task launch];
[task waitUntilExit];
// We need a way to view the output because the tool logs the current cursor scale.
NSFileHandle *outFileHandle = [task.standardOutput fileHandleForReading];
NSData *data = [outFileHandle availableData];
NSString *output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
_cursorScale = output.doubleValue;
[self didChangeValueForKey:@"cursorScale"];
[output release];
[task release];
// Dump the current cursors to a temporary location for the initial table view.
NSString *cursorDump = [NSTemporaryDirectory() stringByAppendingPathComponent:@"magicmousecursordump.plist"];
[self dumpCursorsToFile:cursorDump];
self.currentCursor = [MMCursorAggregate aggregateWithContentsOfFile:cursorDump];
}
- (void)initializeCursorData {
// These methods tell CoreGraphics to register the images internally. I don't know how it does itbut it does.
[[NSCursor contextualMenuCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor arrowCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor IBeamCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor pointingHandCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor closedHandCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor openHandCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor resizeLeftCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor resizeRightCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor resizeLeftRightCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor resizeUpCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor resizeDownCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor resizeUpDownCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor crosshairCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor disappearingItemCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor operationNotAllowedCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor busyButClickableCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor contextualMenuCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor IBeamCursorForVerticalLayout] _getImageAndHotSpotFromCoreCursor];
[[NSCursor dragCopyCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor dragLinkCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _genericDragCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _handCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _closedHandCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _moveCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _waitCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _crosshairCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _horizontalResizeCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _verticalResizeCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _bottomLeftResizeCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _topLeftResizeCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _bottomRightResizeCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _topRightResizeCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _resizeLeftCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _resizeRightCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _resizeLeftRightCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _zoomInCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _zoomOutCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeEastCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeEastWestCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeNorthCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeNorthEastCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeNorthEastSouthWestCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeNorthSouthCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeNorthWestCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeNorthWestSouthEastCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeSouthCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeSouthEastCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeSouthWestCursor] _getImageAndHotSpotFromCoreCursor];
[[NSCursor _windowResizeWestCursor] _getImageAndHotSpotFromCoreCursor];
}
#pragma mark - Accessors
#import <objc/runtime.h>
static char MMCurrentCursor;
- (CGFloat)cursorScale {
return _cursorScale;
}
- (void)setCursorScale:(CGFloat)cursorScale {
// Tell the observers it change, write it out to prefs, and use magicmouse tool to change the scale
[self willChangeValueForKey:@"cursorScale"];
_cursorScale = cursorScale;
[self didChangeValueForKey:@"cursorScale"];
NSNumber *scaleNum = [NSNumber numberWithDouble:cursorScale];
NSTask *task = [[NSTask alloc] init];
task.launchPath = kMMToolPath;
task.arguments = [NSArray arrayWithObjects:@"-s", scaleNum.stringValue, nil];
task.standardOutput = [NSPipe pipe]; // We don't want to spam the console with the output from this
[task launch];
[task waitUntilExit];
[task release];
}
- (MMCursorAggregate *)currentCursor {
return objc_getAssociatedObject(self, &MMCurrentCursor);
}
- (void)setCurrentCursor:(MMCursorAggregate *)currentCursor {
[self willChangeValueForKey:@"currentCursor"];
objc_setAssociatedObject(self, &MMCurrentCursor, currentCursor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self didChangeValueForKey:@"currentCursor"];
[self.cursorViewController.tableView reloadData];
}
- (BOOL)isUnlocked {
return YES;//([_authView authorizationState] == SFAuthorizationViewUnlockedState);
}
#pragma mark - User Interface Actions
- (IBAction)applyCursors:(NSButton *)sender {
// Save the current cursor to a temporary location and then apply it with the command line tool.
NSString *location = self.cursorViewController.cursor.path;
if (!location) {
[NSTemporaryDirectory() stringByAppendingPathComponent:@"MagicMouseTemporary.MightyMouse"];
[self.cursorViewController.cursor.dictionaryRepresentation writeToFile:location atomically:NO];
}
dispatch_async(_actionQueue, ^{
NSTask *task = [[NSTask alloc] init];
task.launchPath = kMMToolPath;
task.arguments = [NSArray arrayWithObject:location];
task.standardOutput = [NSPipe pipe];
[task launch];
[task waitUntilExit];
[task release];
// Update the cursor
//! TODO: Find some way to update the cursor live
[NSCursor _clearOverrideCursorAndSetArrow];
[NSCursor _makeCursors];
[NSCursor _clearOverrideCursorAndSetArrow];
});
}
- (IBAction)resetCursors:(NSButton *)sender {
[self initializeData];
[self.cursorViewController.tableView reloadData];
}
- (IBAction)visitWebsite:(NSButton *)sender {
[[NSWorkspace sharedWorkspace] openURL:kMMWebsiteURL];
}
- (IBAction)donate:(NSButton *)sender {
[[NSWorkspace sharedWorkspace] openURL:kMMDonateURL];
}
- (IBAction)uninstall:(NSButton *)sender {
// Delete the prefpane, remove the launch daemon, remove the preferences
}
- (IBAction)importCursor:(NSMenuItem *)sender {
NSOpenPanel *sp = [NSOpenPanel openPanel];
sp.title = @"Import Cursor";
sp.message = @"Select a cursor to import into your library.";
sp.prompt = @"Import";
sp.allowedFileTypes = [NSArray arrayWithObject:@"MightyMouse"];
[sp beginSheetModalForWindow:[NSApp mainWindow]
completionHandler:^(NSInteger result){
if (result == NSFileHandlingPanelOKButton) {
// self.currentCursor = [MMCursorAggregate aggregateWithDictionary:[NSDictionary dictionaryWithContentsOfURL:sp.URL]];
[self.cursorLibrary addCursorAtPath:sp.URL.path];
}
}];
}
- (IBAction)exportCursor:(NSMenuItem *)sender {
NSSavePanel *sp = [NSSavePanel savePanel];
sp.title = @"Export Cursor";
sp.message = @"Select where to export the cursor.";
sp.prompt = @"Export";
sp.allowedFileTypes = [NSArray arrayWithObject:@"MightyMouse"];
[sp beginSheetModalForWindow:[NSApp mainWindow]
completionHandler:^(NSInteger result){
if (result == NSFileHandlingPanelOKButton) {
[self.cursorViewController.cursor.dictionaryRepresentation writeToURL:sp.URL atomically:YES];
}
}];
}
- (void)chooseCursor:(NSPopUpButton *)sender
{
[sender sizeToFit];
sender.frameOrigin = NSMakePoint(round(NSWidth(sender.superview.bounds) / 2 - NSWidth(sender.frame) / 2), sender.frame.origin.y);
}
- (IBAction)advancedEdit:(NSMenuItem *)sender {
[self.advancedEditWindowController displayForWindow:[NSApp mainWindow] cursor:self.cursorViewController.cursor];
}
- (void)dumpCursorsToFile:(NSString*)filePath {
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
// Ask the tool to dump the cursors
NSTask *task = [[NSTask alloc] init];
task.launchPath = kMMToolPath;
task.arguments = [NSArray arrayWithObjects:@"-d", filePath, nil];
[task launch];
[task waitUntilExit];
[task release];
}
#pragma mark - NSMenuDelegate
- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
{
return self.cursorLibrary.cursors.count + 1; // For the currently applied cursor, of course.
}
- (void)menuNeedsUpdate:(NSMenu *)menu
{
NSInteger count = [self numberOfItemsInMenu:menu];
while ([menu numberOfItems] < count)
[menu insertItem:[[NSMenuItem new] autorelease] atIndex:0];
while ([menu numberOfItems] > count)
[menu removeItemAtIndex:0];
for (NSInteger index = 0; index < count; index++)
[self menu:menu updateItem:[menu itemAtIndex:index] atIndex:index shouldCancel:NO];
}
- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
{
if (shouldCancel)
return NO;
if (index == 0) {
[item setTitle:@"Current"];
return YES;
}
MMCursorAggregate *cursor = [self.cursorLibrary.cursors.allObjects objectAtIndex:0];
item.title = cursor.path.lastPathComponent.stringByDeletingPathExtension;
return YES;
}
#pragma mark - Authorization Delegate
- (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view {
[self willChangeValueForKey:@"isUnlocked"];
// Let observers know.
[self didChangeValueForKey:@"isUnlocked"];
}
- (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view {
[self willChangeValueForKey:@"isUnlocked"];
// Let observers know.
[self didChangeValueForKey:@"isUnlocked"];
}
@end
-14
View File
@@ -1,14 +0,0 @@
//
// Prefix header for all source files of the 'Magic Mouse' target in the 'Magic Mouse' project
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#import "MMDefs.h"
#define kMMPrefsBundle [NSBundle bundleForClass:NSClassFromString(@"MMPrefPane")]
#define kMMToolPath [kMMPrefsBundle pathForAuxiliaryExecutable:@"magicmouse"]
#define kMMDonateURL [NSURL URLWithString:@"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H6B999S6C3UX2"]
#define kMMWebsiteURL [NSURL URLWithString:@"http://alexzielenski.com"]
#define kMMCursorLibraryPath @"/Library/Application Support/Magic Mouse/"
#endif
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-502
View File
@@ -1,502 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1070</int>
<string key="IBDocument.SystemVersion">11D50b</string>
<string key="IBDocument.InterfaceBuilderVersion">2182</string>
<string key="IBDocument.AppKitVersion">1138.32</string>
<string key="IBDocument.HIToolboxVersion">568.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">2182</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>NSView</string>
<string>NSCustomObject</string>
<string>NSScrollView</string>
<string>NSWindowTemplate</string>
<string>NSTextFieldCell</string>
<string>NSTextField</string>
<string>NSCustomView</string>
<string>NSTableCellView</string>
<string>NSTableColumn</string>
<string>NSScroller</string>
<string>NSTableView</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="NSCustomObject" id="1001">
<string key="NSClassName">MMAdvancedEditWindowController</string>
</object>
<object class="NSCustomObject" id="1003">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSCustomObject" id="1004">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSWindowTemplate" id="1005">
<int key="NSWindowStyleMask">1</int>
<int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{878, 652}, {687, 185}}</string>
<int key="NSWTFlags">1618478080</int>
<string key="NSWindowTitle">Window</string>
<string key="NSWindowClass">NSPanel</string>
<nil key="NSViewClass"/>
<nil key="NSUserInterfaceItemIdentifier"/>
<object class="NSView" key="NSWindowView" id="1006">
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSScrollView" id="475901191">
<reference key="NSNextResponder" ref="1006"/>
<int key="NSvFlags">276</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSClipView" id="204896890">
<reference key="NSNextResponder" ref="475901191"/>
<int key="NSvFlags">2304</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSTableView" id="512185058">
<reference key="NSNextResponder" ref="204896890"/>
<int key="NSvFlags">256</int>
<string key="NSFrameSize">{185, 159}</string>
<reference key="NSSuperview" ref="204896890"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="1009513133"/>
<string key="NSReuseIdentifierKey">_NS:13</string>
<bool key="NSEnabled">YES</bool>
<object class="_NSCornerView" key="NSCornerView">
<nil key="NSNextResponder"/>
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{224, 0}, {16, 17}}</string>
<reference key="NSNextKeyView" ref="204896890"/>
<string key="NSReuseIdentifierKey">_NS:19</string>
</object>
<array class="NSMutableArray" key="NSTableColumns">
<object class="NSTableColumn" id="103963955">
<double key="NSWidth">181.6484375</double>
<double key="NSMinWidth">40</double>
<double key="NSMaxWidth">1000</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
<int key="NSCellFlags">75628096</int>
<int key="NSCellFlags2">2048</int>
<string key="NSContents"/>
<object class="NSFont" key="NSSupport">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">11</double>
<int key="NSfFlags">3100</int>
</object>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC4zMzMzMzI5ODU2AA</bytes>
</object>
<object class="NSColor" key="NSTextColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">headerTextColor</string>
<object class="NSColor" key="NSColor" id="737459690">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MAA</bytes>
</object>
</object>
</object>
<object class="NSTextFieldCell" key="NSDataCell" id="203816845">
<int key="NSCellFlags">337772096</int>
<int key="NSCellFlags2">2048</int>
<string key="NSContents">Text Cell</string>
<object class="NSFont" key="NSSupport" id="701966091">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">13</double>
<int key="NSfFlags">1044</int>
</object>
<reference key="NSControlView" ref="512185058"/>
<object class="NSColor" key="NSBackgroundColor" id="349783698">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlBackgroundColor</string>
<object class="NSColor" key="NSColor" id="12693693">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
</object>
</object>
<object class="NSColor" key="NSTextColor" id="952723118">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlTextColor</string>
<reference key="NSColor" ref="737459690"/>
</object>
</object>
<int key="NSResizingMask">3</int>
<bool key="NSIsResizeable">YES</bool>
<bool key="NSIsEditable">YES</bool>
<reference key="NSTableView" ref="512185058"/>
</object>
</array>
<double key="NSIntercellSpacingWidth">3</double>
<double key="NSIntercellSpacingHeight">2</double>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
</object>
<object class="NSColor" key="NSGridColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">gridColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC41AA</bytes>
</object>
</object>
<double key="NSRowHeight">17</double>
<int key="NSTvFlags">1455423488</int>
<reference key="NSDelegate"/>
<reference key="NSDataSource"/>
<int key="NSColumnAutoresizingStyle">4</int>
<int key="NSDraggingSourceMaskForLocal">15</int>
<int key="NSDraggingSourceMaskForNonLocal">0</int>
<bool key="NSAllowsTypeSelect">YES</bool>
<int key="NSTableViewDraggingDestinationStyle">0</int>
<int key="NSTableViewGroupRowStyle">1</int>
</object>
</array>
<string key="NSFrame">{{1, 1}, {185, 159}}</string>
<reference key="NSSuperview" ref="475901191"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="512185058"/>
<string key="NSReuseIdentifierKey">_NS:11</string>
<reference key="NSDocView" ref="512185058"/>
<reference key="NSBGColor" ref="349783698"/>
<int key="NScvFlags">4</int>
</object>
<object class="NSScroller" id="977722590">
<reference key="NSNextResponder" ref="475901191"/>
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{224, 17}, {15, 102}}</string>
<reference key="NSSuperview" ref="475901191"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="419371071"/>
<string key="NSReuseIdentifierKey">_NS:58</string>
<reference key="NSTarget" ref="475901191"/>
<string key="NSAction">_doScroller:</string>
<double key="NSPercent">0.99305555555555558</double>
</object>
<object class="NSScroller" id="419371071">
<reference key="NSNextResponder" ref="475901191"/>
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{1, 295}, {185, 15}}</string>
<reference key="NSSuperview" ref="475901191"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="979016753"/>
<string key="NSReuseIdentifierKey">_NS:60</string>
<int key="NSsFlags">1</int>
<reference key="NSTarget" ref="475901191"/>
<string key="NSAction">_doScroller:</string>
<double key="NSPercent">0.9946236559139785</double>
</object>
</array>
<string key="NSFrame">{{20, 12}, {187, 161}}</string>
<reference key="NSSuperview" ref="1006"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="204896890"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<int key="NSsFlags">133682</int>
<reference key="NSVScroller" ref="977722590"/>
<reference key="NSHScroller" ref="419371071"/>
<reference key="NSContentView" ref="204896890"/>
<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
</object>
<object class="NSCustomView" id="979016753">
<reference key="NSNextResponder" ref="1006"/>
<int key="NSvFlags">274</int>
<string key="NSFrame">{{205, 0}, {482, 185}}</string>
<reference key="NSSuperview" ref="1006"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<string key="NSClassName">NSView</string>
</object>
</array>
<string key="NSFrameSize">{687, 185}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="475901191"/>
</object>
<string key="NSScreenRect">{{0, 0}, {2560, 1418}}</string>
<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
<bool key="NSWindowIsRestorable">NO</bool>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">window</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="1005"/>
</object>
<int key="connectionID">3</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">_contentView</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="979016753"/>
</object>
<int key="connectionID">36</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">tableView</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="512185058"/>
</object>
<int key="connectionID">37</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">delegate</string>
<reference key="source" ref="1005"/>
<reference key="destination" ref="1001"/>
</object>
<int key="connectionID">4</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">dataSource</string>
<reference key="source" ref="512185058"/>
<reference key="destination" ref="1001"/>
</object>
<int key="connectionID">38</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">delegate</string>
<reference key="source" ref="512185058"/>
<reference key="destination" ref="1001"/>
</object>
<int key="connectionID">39</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">textField</string>
<object class="NSTableCellView" key="source" id="1009513133">
<nil key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSTextField" id="807929000">
<reference key="NSNextResponder" ref="1009513133"/>
<int key="NSvFlags">266</int>
<string key="NSFrameSize">{182, 17}</string>
<reference key="NSSuperview" ref="1009513133"/>
<reference key="NSNextKeyView" ref="977722590"/>
<string key="NSAntiCompressionPriority">{250, 750}</string>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="132867833">
<int key="NSCellFlags">67239488</int>
<int key="NSCellFlags2">272631808</int>
<string key="NSContents">Table View Cell</string>
<reference key="NSSupport" ref="701966091"/>
<reference key="NSControlView" ref="807929000"/>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlColor</string>
<reference key="NSColor" ref="12693693"/>
</object>
<reference key="NSTextColor" ref="952723118"/>
</object>
</object>
</array>
<string key="NSFrame">{{1, 1}, {182, 17}}</string>
<reference key="NSNextKeyView" ref="807929000"/>
</object>
<reference key="destination" ref="807929000"/>
</object>
<int key="connectionID">24</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="1001"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="1003"/>
<reference key="parent" ref="0"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="1004"/>
<reference key="parent" ref="0"/>
<string key="objectName">Application</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">1</int>
<reference key="object" ref="1005"/>
<array class="NSMutableArray" key="children">
<reference ref="1006"/>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="1006"/>
<array class="NSMutableArray" key="children">
<reference ref="475901191"/>
<reference ref="979016753"/>
</array>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">5</int>
<reference key="object" ref="475901191"/>
<array class="NSMutableArray" key="children">
<reference ref="512185058"/>
<reference ref="419371071"/>
<reference ref="977722590"/>
</array>
<reference key="parent" ref="1006"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">6</int>
<reference key="object" ref="512185058"/>
<array class="NSMutableArray" key="children">
<reference ref="103963955"/>
</array>
<reference key="parent" ref="475901191"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">7</int>
<reference key="object" ref="419371071"/>
<reference key="parent" ref="475901191"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">9</int>
<reference key="object" ref="977722590"/>
<reference key="parent" ref="475901191"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">10</int>
<reference key="object" ref="103963955"/>
<array class="NSMutableArray" key="children">
<reference ref="203816845"/>
<reference ref="1009513133"/>
</array>
<reference key="parent" ref="512185058"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">13</int>
<reference key="object" ref="203816845"/>
<reference key="parent" ref="103963955"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">21</int>
<reference key="object" ref="1009513133"/>
<array class="NSMutableArray" key="children">
<reference ref="807929000"/>
</array>
<reference key="parent" ref="103963955"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">22</int>
<reference key="object" ref="807929000"/>
<array class="NSMutableArray" key="children">
<reference ref="132867833"/>
</array>
<reference key="parent" ref="1009513133"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">23</int>
<reference key="object" ref="132867833"/>
<reference key="parent" ref="807929000"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">35</int>
<reference key="object" ref="979016753"/>
<reference key="parent" ref="1006"/>
<string key="objectName">Advanced Edit</string>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES" key="1.IBNSWindowAutoPositionCentersHorizontal"/>
<boolean value="YES" key="1.IBNSWindowAutoPositionCentersVertical"/>
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="1.IBWindowTemplateEditedContentRect">{{357, 418}, {480, 270}}</string>
<boolean value="NO" key="1.NSWindowTemplate.visibleAtLaunch"/>
<string key="10.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES" key="10.isInViewBasedMode"/>
<array key="10.prototypeCellViews">
<reference ref="1009513133"/>
</array>
<string key="13.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="21.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="21.userInterfaceItemIdentifier">AdvancedEditWindow</string>
<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="23.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<dictionary class="NSMutableDictionary" key="35.IBAttributePlaceholdersKey"/>
<string key="35.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES" key="6.ibExternalAutomaticallyCalculatesRowSizeFromViewHeight"/>
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="9.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">39</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">MMAdvancedEditWindowController</string>
<string key="superclassName">NSWindowController</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="_contentView">NSView</string>
<string key="tableView">NSTableView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="_contentView">
<string key="name">_contentView</string>
<string key="candidateClassName">NSView</string>
</object>
<object class="IBToOneOutletInfo" key="tableView">
<string key="name">tableView</string>
<string key="candidateClassName">NSTableView</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MMAdvancedEditWindowController.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
</data>
</archive>
@@ -1,48 +0,0 @@
//
// MMQuickEditViewController.h
// Magic Mouse
//
// Created by Alex Zielenski on 2/29/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MMCursorAggregate.h"
#import "MMAnimatingImageView.h"
/*! This is the class that will be used for display the popover for quick edits after drags, and it will be used
for the advanced editing table. It is able to edit the important properties of MMCursor */
// Block for when done/cancel is clicked
typedef void(^MMAdvancedEditDidEndBlock)(BOOL doneClicked); // doneClicked = if it was done, NO if it was cancelled
@interface MMAdvancedEditViewController : NSViewController <MMAnimatingImageViewDelegate> {
MMCursor *_cursor;
}
/* Properties and outlets for the views */
@property (nonatomic, retain) IBOutlet NSTextField *nameField;
@property (nonatomic, retain) IBOutlet NSTextField *xField;
@property (nonatomic, retain) IBOutlet NSTextField *yField;
@property (nonatomic, retain) IBOutlet NSTextField *frameCountField;
@property (nonatomic, retain) IBOutlet NSTextField *frameDurationField;
@property (nonatomic, retain) IBOutlet NSTextField *identifierField;
@property (nonatomic, retain) IBOutlet MMAnimatingImageView *imageView;
@property (nonatomic, retain) IBOutlet NSButton *doneButton;
@property (nonatomic, retain) IBOutlet NSButton *cancelButton;
@property (nonatomic, retain) MMCursor *cursor;
@property (nonatomic, assign) BOOL appliesChangesImmediately;
@property (nonatomic, copy) MMAdvancedEditDidEndBlock didEndBlock;
// Actions called by the views when values are changed. I don't want to use bindings directly to have
// the power to cancel in the end.
- (IBAction)nameChange:(NSTextField *)sender;
- (IBAction)xChange:(NSTextField *)sender;
- (IBAction)yChange:(NSTextField *)sender;
- (IBAction)frameCountChange:(id)sender;
- (IBAction)frameDurationChange:(id)sender;
- (IBAction)identifierChange:(NSTextField *)sender;
- (IBAction)done:(NSButton *)sender;
- (IBAction)cancel:(NSButton *)sender;
@end
@@ -1,145 +0,0 @@
//
// MMQuickEditViewController.m
// Magic Mouse
//
// Created by Alex Zielenski on 2/29/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import "MMAdvancedEditViewController.h"
@implementation MMAdvancedEditViewController
@synthesize nameField = _nameField;
@synthesize xField = _xField;
@synthesize yField = _yField;
@synthesize frameCountField = _frameCountField;
@synthesize frameDurationField = _frameDurationField;
@synthesize identifierField = _identifierField;
@synthesize imageView = _imageView;
@synthesize doneButton = _doneButton;
@synthesize cancelButton = _cancelButton;
@synthesize appliesChangesImmediately = _appliesChangesImmediately;
@synthesize didEndBlock = _didEndBlock;
@dynamic cursor;
- (void)dealloc {
self.cursor = nil;
[super dealloc];
}
#pragma mark - Accessors
- (MMCursor *)cursor {
return _cursor;
}
- (void)setCursor:(MMCursor *)cursor {
[self willChangeValueForKey:@"cursor"];
if (_cursor)
[_cursor release];
_cursor = [cursor retain];
[self didChangeValueForKey:@"cursor"];
if (_cursor) {
// Set all of our fields to their values based upon this here cursor
self.nameField.stringValue = self.cursor.name;
self.xField.integerValue = self.cursor.hotSpot.x;
self.yField.integerValue = self.cursor.hotSpot.y;
self.frameCountField.integerValue = self.cursor.frameCount;
self.frameDurationField.doubleValue = self.cursor.frameDuration;
self.identifierField.stringValue = self.cursor.cursorIdentifier;
self.imageView.image = self.cursor.image;
self.imageView.frameCount = self.cursor.frameCount;
self.imageView.frameDuration = self.cursor.frameDuration;
} else {
self.nameField.stringValue = @"";
self.xField.integerValue = 0;
self.yField.integerValue = 0;
self.frameCountField.integerValue = 1;
self.frameDurationField.doubleValue = 1.0;
self.identifierField.stringValue = @"";
self.imageView.image = nil;
}
[self.imageView resetAnimation];
}
#pragma mark - Actions
- (IBAction)nameChange:(NSTextField *)sender {
if (self.appliesChangesImmediately) {
self.cursor.name = sender.stringValue;
}
}
- (IBAction)xChange:(NSTextField *)sender {
if (self.appliesChangesImmediately) {
self.cursor.hotSpot = NSMakePoint(sender.floatValue, self.cursor.hotSpot.y);
}
}
- (IBAction)yChange:(NSTextField *)sender {
if (self.appliesChangesImmediately) {
self.cursor.hotSpot = NSMakePoint(self.cursor.hotSpot.x, sender.floatValue);
}
}
- (IBAction)frameCountChange:(id)sender { // The image view needs to be updated when there is a a framecount/duration change
if (self.appliesChangesImmediately) {
self.cursor.frameCount = [sender integerValue];
}
self.imageView.frameCount = self.frameCountField.integerValue;
[self.imageView resetAnimation];
}
- (IBAction)frameDurationChange:(id)sender {
if (self.appliesChangesImmediately) {
self.cursor.frameDuration = [sender doubleValue];
}
self.imageView.frameDuration = self.frameDurationField.doubleValue;
[self.imageView resetAnimation];
}
- (IBAction)identifierChange:(NSTextField *)sender {
if (self.appliesChangesImmediately) {
self.cursor.cursorIdentifier = sender.stringValue;
}
}
- (IBAction)done:(NSButton *)sender {
NSAssert(self.didEndBlock != NULL, @"For done: to be called & implemented, didEndBlock must not be NULL");
self.cursor.name = self.nameField.stringValue;
self.cursor.hotSpot = NSMakePoint(self.xField.floatValue, self.yField.floatValue);
self.cursor.frameCount = self.frameCountField.integerValue;
self.cursor.frameDuration = self.frameDurationField.doubleValue;
self.cursor.cursorIdentifier = self.identifierField.stringValue;
self.cursor.image = self.imageView.image;
self.didEndBlock(YES);
}
- (IBAction)cancel:(NSButton *)sender {
NSAssert(self.didEndBlock != NULL, @"For cancel: to be called & implemented, didEndBlock must not be NULL");
self.didEndBlock(NO);
}
#pragma mark - MMAnimatedImageViewDelegate
- (NSDragOperation)imageView:(MMAnimatingImageView *)imageView draggingEntered:(id <NSDraggingInfo>)drop {
return NSDragOperationCopy;
}
- (BOOL)imageView:(MMAnimatingImageView *)imageView shouldPrepareForDragOperation:(id <NSDraggingInfo>)drop {
return YES;
}
- (BOOL)imageView:(MMAnimatingImageView *)imageView shouldPerformDragOperation:(id <NSDraggingInfo>)drop {
return YES;
}
- (void)imageView:(MMAnimatingImageView *)imageView didAcceptDroppedImages:(NSArray *)images {
if (self.appliesChangesImmediately) {
self.cursor.image = [images objectAtIndex:0];
}
[imageView resetAnimation];
}
@end
@@ -1,20 +0,0 @@
//
// MMAdvancedEditWindowController.h
// Magic Mouse
//
// Created by Alex Zielenski on 5/2/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MMCursorAggregate.h"
@interface MMAdvancedEditWindowController : NSWindowController <NSTableViewDelegate, NSTableViewDataSource>
@property (nonatomic, retain) IBOutlet NSTableView *tableView;
@property (nonatomic, retain) MMCursorAggregate *cursor;
@property (nonatomic, assign) NSWindow *parentWindow;
- (void)displayForWindow:(NSWindow *)window cursor:(MMCursorAggregate *)cursor;;
@end
@@ -1,111 +0,0 @@
//
// MMAdvancedEditWindowController.m
// Magic Mouse
//
// Created by Alex Zielenski on 5/2/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import "MMAdvancedEditWindowController.h"
#import "MMAdvancedEditViewController.h"
@interface MMAdvancedEditWindowController ()
@property (nonatomic, assign) IBOutlet NSView *_contentView;
@property (nonatomic, retain) MMAdvancedEditViewController *_advancedEditViewController;
@end
@implementation MMAdvancedEditWindowController
#pragma mark - Private Properties
@synthesize _contentView;
@synthesize _advancedEditViewController;
#pragma mark - Public Properties
@synthesize tableView = _tableView;
@synthesize cursor = _cursor;
@synthesize parentWindow = _parentWindow;
#pragma mark - Lifecycle
- (id)initWithWindow:(NSWindow *)window {
self = [super initWithWindow:window];
if (self) {
// Initialization code here.
}
return self;
}
- (void)dealloc {
self._contentView = nil;
self.tableView = nil;
self.cursor = nil;
self._advancedEditViewController = nil;
[super dealloc];
}
- (void)windowDidLoad {
[super windowDidLoad];
self._advancedEditViewController = [[[MMAdvancedEditViewController alloc] initWithNibName:@"AdvancedEdit" bundle:kMMPrefsBundle] autorelease];
self._advancedEditViewController.view.frame = self._contentView.bounds;
self._advancedEditViewController.appliesChangesImmediately = NO;
self._advancedEditViewController.didEndBlock = ^(BOOL doneButton) {
if (doneButton) {
} else {
}
[self.window orderOut:self];
[NSApp endSheet:self.window];
};
[self._contentView addSubview:self._advancedEditViewController.view];
}
- (void)displayForWindow:(NSWindow *)window cursor:(MMCursorAggregate *)cursor {
self.cursor = cursor;
self.parentWindow = window;
[self showWindow:self];
}
- (void)showWindow:(id)sender {
[NSApp beginSheet:self.window
modalForWindow:self.parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:nil];
if (self.cursor.cursors.count > 0)
[self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
}
#pragma mark - NSTableViewDataSource
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return self.cursor.cursors.count;
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSTableCellView *cellView = [tableView makeViewWithIdentifier:@"AdvancedEditWindow" owner:self];
MMCursor *currentCursor = [self.cursor.cursors.allValues objectAtIndex:row];
cellView.textField.stringValue = currentCursor.name;
return cellView;
}
#pragma mark - NSTableViewDelegate
- (void)tableViewSelectionDidChange:(NSNotification *)notification {
MMCursor *cursor = [self.cursor.cursors.allValues objectAtIndex:self.tableView.selectedRow];
self._advancedEditViewController.cursor = cursor;
}
@end
@@ -1,23 +0,0 @@
//
// MMCursorLibrary.h
// Magic Mouse
//
// Created by Alex Zielenski on 5/6/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MMCursorAggregate.h"
@interface MMCursorLibrary : NSObject
@property (copy, readonly) NSString *libraryPath;
@property (retain, readonly) NSMutableSet *cursors; // Yeah, don't actually modify this
+ (MMCursorLibrary *)libraryWithPath:(NSString *)path;
- (id)initWithPath:(NSString *)path;
- (BOOL)addCursorAtPath:(NSString *)path;
- (void)removeCursor:(MMCursorAggregate *)cursor;
- (void)saveCursor:(MMCursorAggregate *)cursor;
@end
@@ -1,145 +0,0 @@
//
// MMCursorLibrary.m
// Magic Mouse
//
// Created by Alex Zielenski on 5/6/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import "MMCursorLibrary.h"
@interface MMCursorLibrary () {
NSMutableSet *_cursors;
}
@property (retain, readwrite) NSMutableSet *cursors;
@property (copy, readwrite) NSString *libraryPath;
- (BOOL)_validateLibraryPath:(NSString *)path;
- (void)_addCursorAtPath:(NSString *)path;
- (void)_syncWithLibrary;
@end
@implementation MMCursorLibrary
@synthesize libraryPath = _libraryPath;
@synthesize cursors = _cursors;
+ (MMCursorLibrary *)libraryWithPath:(NSString *)path
{
return [[[self alloc] initWithPath:path] autorelease];
}
- (id)initWithPath:(NSString *)path
{
if (![self _validateLibraryPath:path]) {
NSLog(@"Invalid Library Path.");
[self release];
return nil;
}
if ((self = [super init])) {
self.cursors = [NSMutableSet set];
self.libraryPath = path;
[self _syncWithLibrary];
}
return self;
}
- (BOOL)addCursorAtPath:(NSString *)path
{
if ([[self.cursors valueForKey:path] containsObject:path])
return NO;
[self _addCursorAtPath:path];
return YES;
}
- (void)removeCursor:(MMCursorAggregate *)cursor
{
if (![self.cursors containsObject:cursor])
return;
[self willChangeValueForKey:@"cursors"];
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtPath:cursor.path error:&error];
if (!error)
[self.cursors removeObject:cursor];
else {
NSLog(@"Error Removing Cursor");
NSLog(@"%@", error);
}
[self didChangeValueForKey:@"cursors"];
}
- (void)saveCursor:(MMCursorAggregate *)cursor
{
if (![self.cursors containsObject:cursor]) {
NSLog(@"Cursor (%@) is not a member of this library", cursor);
return;
}
if (!cursor.path) {
NSLog(@"Cursor (%@) was not instantiated with its path.", cursor);
return;
}
[cursor.dictionaryRepresentation writeToFile:cursor.path atomically:NO];
}
- (BOOL)_validateLibraryPath:(NSString *)path
{
if (!path)
return NO;
NSFileManager *manager = [NSFileManager defaultManager];
BOOL isDir = NO;
BOOL exists = [manager fileExistsAtPath:path isDirectory:&isDir];
if (!exists || !isDir)
return NO;
return ([manager isReadableFileAtPath:path] && [manager isWritableFileAtPath:path]);
}
- (void)_syncWithLibrary
{
NSFileManager *manager = [NSFileManager defaultManager];
NSSet *paths = [self.cursors valueForKeyPath:@"path"];
NSError *error = nil;
NSArray *cursors = [manager contentsOfDirectoryAtPath:self.libraryPath error:&error];
if (error) {
NSLog(@"%@", error);
return;
}
for (NSString *filename in cursors) {
NSString *path = [self.libraryPath stringByAppendingPathComponent:filename];
if ([paths containsObject:path])
continue;
[self _addCursorAtPath:path];
}
}
- (void)_addCursorAtPath:(NSString *)path
{
[self willChangeValueForKey:@"cursors"];
MMCursorAggregate *agg = [MMCursorAggregate aggregateWithContentsOfFile:path];
[self.cursors addObject:agg];
[self didChangeValueForKey:@"cursors"];
}
@end
@@ -1,19 +0,0 @@
//
// MMCursorViewController.h
// Magic Mouse
//
// Created by Alex Zielenski on 5/1/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MMAnimatingImageTableCellView.h"
#import "MMCursorAggregate.h"
@interface MMCursorViewController : NSViewController <NSTableViewDelegate, NSTableViewDataSource, MMAnimatingImageViewDelegate>
@property (nonatomic, retain) MMCursorAggregate *cursor;
@property (nonatomic, assign) IBOutlet NSTableView *tableView;
@property (nonatomic, assign, getter = isEnabled) BOOL enabled;
@end
@@ -1,171 +0,0 @@
//
// MMCursorViewController.m
// Magic Mouse
//
// Created by Alex Zielenski on 5/1/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import "MMCursorViewController.h"
#import "MMAdvancedEditViewController.h"
@interface MMCursorViewController ()
- (MMAdvancedEditViewController *)_displayPopoverForColumn:(NSInteger)column;
@end
@implementation MMCursorViewController
#pragma mark - Public Properties
@synthesize tableView = _tableView;
@synthesize cursor = _cursor;
@synthesize enabled = _enabled;
#pragma mark - Lifecycle
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code here.
}
return self;
}
- (void)dealloc {
self.cursor = nil;
[super dealloc];
}
// return the controller just incase we want to do extra things to it
- (MMAdvancedEditViewController *)_displayPopoverForColumn:(NSInteger)columnIdx {
if (columnIdx < 0 || columnIdx >= self.tableView.tableColumns.count)
return nil;
// Find the column that was dragged into
NSTableColumn *column = [self.tableView.tableColumns objectAtIndex:columnIdx];
// Get the associated MMCursor* for the cell
MMCursor *cursor = [self.cursor cursorForTableIdentifier:column.identifier];
if (!cursor) {
NSLog(@"No cursor for column (%@, %lu)?", column.identifier, (unsigned long)columnIdx);
return nil;
}
// There is guaranteed to be atleast one image and (and no more than one for now)
MMAdvancedEditViewController *advancedEdit = [[MMAdvancedEditViewController alloc] initWithNibName:@"AdvancedEdit"
bundle:kMMPrefsBundle];
// create a popover to display
NSPopover *popover = [[[NSPopover alloc] init] autorelease];
popover.contentViewController = advancedEdit;
popover.behavior = NSPopoverBehaviorApplicationDefined;
popover.appearance = NSPopoverAppearanceMinimal;
NSView *imageView = [self.tableView viewAtColumn:columnIdx row:0 makeIfNecessary:NO];
if (!imageView)
return nil;
// load the nib
[popover showRelativeToRect:imageView.bounds
ofView:imageView
preferredEdge:NSMinYEdge];
[advancedEdit release]; // decrease the retain count so that the popover is the only owner
advancedEdit.cursor = cursor;
advancedEdit.appliesChangesImmediately = NO; // we only want changes applied when the user clicks "Done"
advancedEdit.identifierField.editable = NO; // make the identifier field uneditable. (read the highlighted comment below)
advancedEdit.nameField.editable = NO; // same as above
[advancedEdit.imageView resetAnimation];
advancedEdit.didEndBlock = ^(BOOL finished) {
[self.tableView reloadData]; // reload the table for updated data
[popover close];
};
return advancedEdit;
}
#pragma mark - NSTableViewDataSource
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
// We only have 1 row, but 9 columns
return 1;
}
#pragma mark - NSTableViewDelegate
//!*****************************************************************************************************************************************//
//!** Each table column has an identifier that would correspond with an identifier built into one of the cursors ("TableIdentifier" key). **//
//!** We use that identifier to retrieve the cursor and display it accoringly. **//
//!*****************************************************************************************************************************************//
- (NSTableCellView *)tableView:(NSTableView*)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
// This identifier is set in the xib
static NSString *cellIdentifier = @"MMCursorCell";
MMAnimatingImageTableCellView *cellView = [tableView makeViewWithIdentifier:cellIdentifier owner:self];
MMCursor *cursor = [self.cursor cursorForTableIdentifier:tableColumn.identifier];
if (cursor) {
cellView.animatingImageView.image = cursor.image;
cellView.animatingImageView.frameCount = cursor.frameCount;
cellView.animatingImageView.frameDuration = cursor.frameDuration;
cellView.animatingImageView.delegate = self;
// We set our values, now we need to reset the animation to reflect our changes
[cellView.animatingImageView resetAnimation];
}
return cellView;
}
// Disable tableview selection
- (BOOL)tableView:(NSTableView *)aTableView shouldSelectRow:(NSInteger)rowIndex {
return NO;
}
#pragma mark - MMAnimatingImageCellViewDelegate
- (NSDragOperation)imageView:(MMAnimatingImageView *)imageView draggingEntered:(id <NSDraggingInfo>)drop {
return (self.isEnabled) ? NSDragOperationCopy : NSDragOperationNone;
}
- (BOOL)imageView:(MMAnimatingImageView *)imageView shouldPrepareForDragOperation:(id <NSDraggingInfo>)drop {
return self.isEnabled;
}
- (BOOL)imageView:(MMAnimatingImageView *)imageView shouldPerformDragOperation:(id <NSDraggingInfo>)drop {
return self.isEnabled;
}
//!**********************************************************************************************************************************************/
//!** When the user drops an image onto a table item, we show then a quick edit popover for them to be able to quickly customize some of **/
//!** the settings. If they click "Done" these changes are applied. We make the identifier field uneditable because we don't want the user **/
//!** changing the identifier value for any of the cursors in the table since they have preset identifier values that must stay static to work **/
//!**********************************************************************************************************************************************/
- (void)imageView:(MMAnimatingImageView *)imageView didAcceptDroppedImages:(NSArray *)images {
NSUInteger columnIdx = [_tableView columnAtPoint:imageView.superview.frame.origin];
if (columnIdx == -1) {
NSLog(@"No column found at specified point (%@) after drag operation.", NSStringFromPoint(imageView.superview.frame.origin));
return;
}
// set the dragged image to the image of the animating image view on the popover
MMAdvancedEditViewController *vc = [self _displayPopoverForColumn:columnIdx];
vc.imageView.image = [images objectAtIndex:0];
vc.imageView.frameDuration = 1;
vc.imageView.frameCount = 1;
vc.frameCountField.integerValue = 1;
vc.frameDurationField.integerValue = 1;
}
@end
@@ -1,17 +0,0 @@
//
// MMAnimatingImageTableCellView.h
// Magic Mouse
//
// Created by Alex Zielenski on 2/26/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import <AppKit/AppKit.h>
#import "MMAnimatingImageView.h"
// This is just a simple table cell subclass with an animating image view property. No big deal
@interface MMAnimatingImageTableCellView : NSTableCellView <NSDraggingDestination>
@property (nonatomic, retain) IBOutlet MMAnimatingImageView *animatingImageView;
@end
@@ -1,13 +0,0 @@
//
// MMAnimatingImageTableCellView.m
// Magic Mouse
//
// Created by Alex Zielenski on 2/26/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import "MMAnimatingImageTableCellView.h"
@implementation MMAnimatingImageTableCellView
@synthesize animatingImageView;
@end
@@ -1,170 +0,0 @@
//
// MMAnimatingImageView.m
// Magic Mouse
//
// Created by Alex Zielenski on 2/25/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import "MMAnimatingImageView.h"
@interface MMAnimatingImageView (Private)
- (void)timerAction:(NSTimer*)timer;
@end
@implementation MMAnimatingImageView
@synthesize image = _image;
@synthesize frameCount = _frameCount;
@synthesize frameDuration = _frameDuration;
@synthesize delegate = _delegate;
- (id)init {
if ((self = [super init])) {
// We cannot have a frame count of 0.
_frameCount = 1;
_frameDuration = 1;
[self registerTypes];
}
return self;
}
// Assorted init methods
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
_frameCount = 1;
_frameDuration = 1;
[self registerTypes];
}
return self;
}
- (id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect])) {
_frameCount = 1;
_frameDuration = 1;
[self registerTypes];
}
return self;
}
// I guess we can safely reset the animation when the view is moved to a new superview
- (void)viewDidMoveToSuperview {
[self resetAnimation];
}
- (void)dealloc {
if (frameTimer)
[frameTimer invalidate];
frameTimer = nil;
[super dealloc];
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
if (self.image && self.frameCount > 0) {
[self.image drawInRect:NSMakeRect(round(NSMidX(self.bounds)-imageSize.width/2), round(NSMidY(self.bounds)-imageSize.height/2), imageSize.width, imageSize.height)
fromRect:currentImageFrame
operation:NSCompositeSourceOver
fraction:1.0
respectFlipped:YES
hints:nil];
}
}
- (void)resetAnimation {
if (frameTimer)
[frameTimer invalidate];
size_t imageWidth = self.image.pixelsWide;
size_t imageHeight = self.image.pixelsHigh/self.frameCount;
// Read from bottom to top
currentFrame = self.frameCount-1;
imageSize = NSMakeSize(imageWidth, imageHeight);
[self timerAction:nil];
if (self.frameCount>1) {
frameTimer = [NSTimer timerWithTimeInterval:self.frameDuration
target:self
selector:@selector(timerAction:)
userInfo:nil
repeats:YES];
// Keep the images animating even during runloop blocking events.
[[NSRunLoop mainRunLoop] addTimer:frameTimer forMode:NSRunLoopCommonModes];
}
}
- (void)timerAction:(NSTimer *)timer {
if (currentFrame < 0)
currentFrame = self.frameCount-1;
currentImageFrame = NSMakeRect(0,
imageSize.height * currentFrame--,
imageSize.width,
imageSize.height);
[self setNeedsDisplay:YES];
}
// Tell OSX that our view can accept images to be dragged in
- (void)registerTypes {
[self registerForDraggedTypes:[NSArray arrayWithObjects:NSPasteboardTypeTIFF, NSPasteboardTypePNG, NSFilenamesPboardType, nil]];
}
#pragma mark - NSDragDestination
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
// Only thing we have to do here is confirm that the dragged file is an image. We use NSImage's +canInitWithPasteboard: and we also check to see there is only one item being dragged
if ([self.delegate conformsToProtocol:@protocol(MMAnimatingImageViewDelegate)] && // No point in accepting the drop if the delegate doesn't support it/exist
[NSImage canInitWithPasteboard:sender.draggingPasteboard] && // Only Accept Images
sender.draggingPasteboard.pasteboardItems.count == 1) { // Only accept one item
return [self.delegate imageView:self draggingEntered:sender];
}
return NSDragOperationNone;
}
// Give the delegate some more control
- (BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender {
if ([self.delegate conformsToProtocol:@protocol(MMAnimatingImageViewDelegate)]) {
return [self.delegate imageView:self shouldPerformDragOperation:sender];
}
return NO;
}
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
if ([self.delegate conformsToProtocol:@protocol(MMAnimatingImageViewDelegate)] && // Only do the operation if a delegate exists to actually set the image.
[self.delegate imageView:self shouldPerformDragOperation:sender]) { // Only do the operation if a delegate wants us to do the operation.
// Get the image from the pasteboard
NSImage *im = [[NSImage alloc] initWithPasteboard:sender.draggingPasteboard];
// Make an array of the valid drops (NSBitmapImageRep)
NSMutableArray *acceptedDrops = [[NSMutableArray alloc] initWithCapacity:im.representations.count];
for (NSImageRep *rep in im.representations) {
if (![rep isKindOfClass:[NSBitmapImageRep class]]) // We don't want PDFs
continue;
[acceptedDrops addObject:rep];
}
if (acceptedDrops.count > 0) {
// We already confirmed that the delegate conforms to the protocol above. Now we can let the delegate
// decide what to do with the dropped images.
[self.delegate imageView:self didAcceptDroppedImages:acceptedDrops];
}
[acceptedDrops release];
[im release];
return YES;
}
return NO;
}
@end
@@ -0,0 +1,999 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
FA04886C189F58B1001F3AB5 /* Edit.xib in Resources */ = {isa = PBXBuildFile; fileRef = FA048868189F58B1001F3AB5 /* Edit.xib */; };
FA04886D189F58B1001F3AB5 /* Library.xib in Resources */ = {isa = PBXBuildFile; fileRef = FA04886A189F58B1001F3AB5 /* Library.xib */; };
FA35983F189DA3BC00288163 /* MCPrefs.m in Sources */ = {isa = PBXBuildFile; fileRef = FA35983E189DA3BC00288163 /* MCPrefs.m */; };
FA359840189DA3C100288163 /* MCPrefs.m in Sources */ = {isa = PBXBuildFile; fileRef = FA35983E189DA3BC00288163 /* MCPrefs.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FA359849189DC40100288163 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA359848189DC40100288163 /* Security.framework */; };
FA35984B189DC48800288163 /* mousecloak in Copy Tools */ = {isa = PBXBuildFile; fileRef = FAC69FAD189D608900BC829D /* mousecloak */; };
FA35984D189DC55A00288163 /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA35984C189DC55A00288163 /* ServiceManagement.framework */; };
FA359852189E035900288163 /* listen.m in Sources */ = {isa = PBXBuildFile; fileRef = FA359851189E035900288163 /* listen.m */; };
FA359853189E040D00288163 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA359844189DBA3800288163 /* SystemConfiguration.framework */; };
FA8FF76B189D664400750E51 /* restore.m in Sources */ = {isa = PBXBuildFile; fileRef = FA8FF76A189D664400750E51 /* restore.m */; };
FA8FF76E189D66CB00750E51 /* backup.m in Sources */ = {isa = PBXBuildFile; fileRef = FA8FF76D189D66CB00750E51 /* backup.m */; };
FA8FF771189D66D800750E51 /* apply.m in Sources */ = {isa = PBXBuildFile; fileRef = FA8FF770189D66D800750E51 /* apply.m */; };
FA8FF774189D67B100750E51 /* create.m in Sources */ = {isa = PBXBuildFile; fileRef = FA8FF773189D67B100750E51 /* create.m */; };
FAAEF8F4189EB32700145DF8 /* BTRClipView.m in Sources */ = {isa = PBXBuildFile; fileRef = FAAEF8F1189EB32700145DF8 /* BTRClipView.m */; };
FAAEF8F5189EB32700145DF8 /* BTRScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = FAAEF8F3189EB32700145DF8 /* BTRScrollView.m */; };
FAAEF8F7189EB34700145DF8 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAAEF8F6189EB34700145DF8 /* QuartzCore.framework */; };
FAAEF94E189EFC9300145DF8 /* create.m in Sources */ = {isa = PBXBuildFile; fileRef = FA8FF773189D67B100750E51 /* create.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FAAEF94F189EFC9600145DF8 /* backup.m in Sources */ = {isa = PBXBuildFile; fileRef = FA8FF76D189D66CB00750E51 /* backup.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FAAEF950189EFC9800145DF8 /* apply.m in Sources */ = {isa = PBXBuildFile; fileRef = FA8FF770189D66D800750E51 /* apply.m */; };
FAAEF951189F0CC300145DF8 /* restore.m in Sources */ = {isa = PBXBuildFile; fileRef = FA8FF76A189D664400750E51 /* restore.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FAAEF957189F4ED300145DF8 /* scale.m in Sources */ = {isa = PBXBuildFile; fileRef = FAAEF956189F4ED300145DF8 /* scale.m */; };
FAAEF958189F4F8200145DF8 /* scale.m in Sources */ = {isa = PBXBuildFile; fileRef = FAAEF956189F4ED300145DF8 /* scale.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FAC69F65189D603C00BC829D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAC69F64189D603C00BC829D /* Cocoa.framework */; };
FAC69F6F189D603C00BC829D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAC69F6D189D603C00BC829D /* InfoPlist.strings */; };
FAC69F71189D603C00BC829D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC69F70189D603C00BC829D /* main.m */; };
FAC69F75189D603C00BC829D /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = FAC69F73189D603C00BC829D /* Credits.rtf */; };
FAC69F78189D603C00BC829D /* MCAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC69F77189D603C00BC829D /* MCAppDelegate.m */; };
FAC69F7B189D603C00BC829D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAC69F79189D603C00BC829D /* MainMenu.xib */; };
FAC69F7D189D603C00BC829D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FAC69F7C189D603C00BC829D /* Images.xcassets */; };
FAC69F84189D603C00BC829D /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAC69F83189D603C00BC829D /* XCTest.framework */; };
FAC69F85189D603C00BC829D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAC69F64189D603C00BC829D /* Cocoa.framework */; };
FAC69F8D189D603C00BC829D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAC69F8B189D603C00BC829D /* InfoPlist.strings */; };
FAC69F8F189D603C00BC829D /* MousecapeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC69F8E189D603C00BC829D /* MousecapeTests.m */; };
FAC69FB1189D608900BC829D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC69FB0189D608900BC829D /* main.m */; };
FAC69FB5189D608900BC829D /* mousecloak.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FAC69FB4189D608900BC829D /* mousecloak.1 */; };
FAC69FD4189D609B00BC829D /* GBCommandLineParser.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC69FCF189D609B00BC829D /* GBCommandLineParser.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
FAC69FD5189D609B00BC829D /* GBOptionsHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC69FD1189D609B00BC829D /* GBOptionsHelper.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
FAC69FD6189D609B00BC829D /* GBSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC69FD3189D609B00BC829D /* GBSettings.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
FAC69FDA189D632B00BC829D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAC69F64189D603C00BC829D /* Cocoa.framework */; };
FAC69FDC189D636700BC829D /* MCDefs.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC69FDB189D636700BC829D /* MCDefs.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FAC69FDD189D636700BC829D /* MCDefs.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC69FDB189D636700BC829D /* MCDefs.m */; };
FAEE652918A047E8003AA182 /* NSFileManager+DirectoryLocations.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE650A18A047E8003AA182 /* NSFileManager+DirectoryLocations.m */; };
FAEE652A18A047E8003AA182 /* NSOrderedSet+AZSortedInsert.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE650C18A047E8003AA182 /* NSOrderedSet+AZSortedInsert.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FAEE652B18A047E8003AA182 /* MCEditCapeController.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE650F18A047E8003AA182 /* MCEditCapeController.m */; };
FAEE652C18A047E8003AA182 /* MCEditDetailController.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE651118A047E8003AA182 /* MCEditDetailController.m */; };
FAEE652D18A047E8003AA182 /* MCEditListController.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE651318A047E8003AA182 /* MCEditListController.m */; };
FAEE652E18A047E8003AA182 /* MCEditWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE651518A047E8003AA182 /* MCEditWindowController.m */; };
FAEE652F18A047E8003AA182 /* MCLibraryController.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE651718A047E8003AA182 /* MCLibraryController.m */; };
FAEE653018A047E8003AA182 /* MCLibraryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE651918A047E8003AA182 /* MCLibraryViewController.m */; };
FAEE653118A047E8003AA182 /* MCLibraryWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE651B18A047E8003AA182 /* MCLibraryWindowController.m */; };
FAEE653218A047E8003AA182 /* MCCursor.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE651E18A047E8003AA182 /* MCCursor.m */; };
FAEE653318A047E8003AA182 /* MCCursorLibrary.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE652018A047E8003AA182 /* MCCursorLibrary.m */; };
FAEE653418A047E8003AA182 /* MCFormatters.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE652318A047E8003AA182 /* MCFormatters.m */; };
FAEE653518A047E8003AA182 /* MCCapeCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE652618A047E8003AA182 /* MCCapeCellView.m */; };
FAEE653618A047E8003AA182 /* MMAnimatingImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE652818A047E8003AA182 /* MMAnimatingImageView.m */; };
FAEE653918A048EA003AA182 /* MCSpriteLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEE653818A048EA003AA182 /* MCSpriteLayer.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
FA359846189DBEB700288163 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = FAC69F59189D603C00BC829D /* Project object */;
proxyType = 1;
remoteGlobalIDString = FAC69FAC189D608900BC829D;
remoteInfo = mousecloak;
};
FAC69F86189D603C00BC829D /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = FAC69F59189D603C00BC829D /* Project object */;
proxyType = 1;
remoteGlobalIDString = FAC69F60189D603C00BC829D;
remoteInfo = Mousecape;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
FA35984A189DC47800288163 /* Copy Tools */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 6;
files = (
FA35984B189DC48800288163 /* mousecloak in Copy Tools */,
);
name = "Copy Tools";
runOnlyForDeploymentPostprocessing = 0;
};
FAC69FAB189D608900BC829D /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
FAC69FB5189D608900BC829D /* mousecloak.1 in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
FA048869189F58B1001F3AB5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/Edit.xib; sourceTree = "<group>"; };
FA04886B189F58B1001F3AB5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/Library.xib; sourceTree = "<group>"; };
FA254779189D85890038E1D9 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; };
FA35983D189DA3BC00288163 /* MCPrefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPrefs.h; sourceTree = "<group>"; };
FA35983E189DA3BC00288163 /* MCPrefs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCPrefs.m; sourceTree = "<group>"; };
FA359844189DBA3800288163 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
FA359848189DC40100288163 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
FA35984C189DC55A00288163 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };
FA359850189E035200288163 /* listen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = listen.h; sourceTree = "<group>"; };
FA359851189E035900288163 /* listen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = listen.m; sourceTree = "<group>"; };
FA8FF769189D663B00750E51 /* restore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = restore.h; sourceTree = "<group>"; };
FA8FF76A189D664400750E51 /* restore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = restore.m; sourceTree = "<group>"; };
FA8FF76C189D66C400750E51 /* backup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = backup.h; sourceTree = "<group>"; };
FA8FF76D189D66CB00750E51 /* backup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = backup.m; sourceTree = "<group>"; };
FA8FF76F189D66D100750E51 /* apply.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = apply.h; sourceTree = "<group>"; };
FA8FF770189D66D800750E51 /* apply.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = apply.m; sourceTree = "<group>"; };
FA8FF772189D67AA00750E51 /* create.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = create.h; sourceTree = "<group>"; };
FA8FF773189D67B100750E51 /* create.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = create.m; sourceTree = "<group>"; };
FAAEF8F0189EB32700145DF8 /* BTRClipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTRClipView.h; sourceTree = "<group>"; };
FAAEF8F1189EB32700145DF8 /* BTRClipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTRClipView.m; sourceTree = "<group>"; };
FAAEF8F2189EB32700145DF8 /* BTRScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTRScrollView.h; sourceTree = "<group>"; };
FAAEF8F3189EB32700145DF8 /* BTRScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTRScrollView.m; sourceTree = "<group>"; };
FAAEF8F6189EB34700145DF8 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
FAAEF955189F4ECC00145DF8 /* scale.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = scale.h; sourceTree = "<group>"; };
FAAEF956189F4ED300145DF8 /* scale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = scale.m; sourceTree = "<group>"; };
FAC69F61189D603C00BC829D /* Mousecape.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Mousecape.app; sourceTree = BUILT_PRODUCTS_DIR; };
FAC69F64189D603C00BC829D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
FAC69F67189D603C00BC829D /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
FAC69F68189D603C00BC829D /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
FAC69F69189D603C00BC829D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
FAC69F6C189D603C00BC829D /* Mousecape-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Mousecape-Info.plist"; sourceTree = "<group>"; };
FAC69F6E189D603C00BC829D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
FAC69F70189D603C00BC829D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
FAC69F72189D603C00BC829D /* Mousecape-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Mousecape-Prefix.pch"; sourceTree = "<group>"; };
FAC69F74189D603C00BC829D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
FAC69F76189D603C00BC829D /* MCAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCAppDelegate.h; sourceTree = "<group>"; };
FAC69F77189D603C00BC829D /* MCAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCAppDelegate.m; sourceTree = "<group>"; };
FAC69F7A189D603C00BC829D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
FAC69F7C189D603C00BC829D /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
FAC69F82189D603C00BC829D /* MousecapeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MousecapeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
FAC69F83189D603C00BC829D /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
FAC69F8A189D603C00BC829D /* MousecapeTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MousecapeTests-Info.plist"; sourceTree = "<group>"; };
FAC69F8C189D603C00BC829D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
FAC69F8E189D603C00BC829D /* MousecapeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MousecapeTests.m; sourceTree = "<group>"; };
FAC69F9D189D605300BC829D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
FAC69FAD189D608900BC829D /* mousecloak */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mousecloak; sourceTree = BUILT_PRODUCTS_DIR; };
FAC69FB0189D608900BC829D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
FAC69FB3189D608900BC829D /* mousecloak-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "mousecloak-Prefix.pch"; sourceTree = "<group>"; };
FAC69FB4189D608900BC829D /* mousecloak.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = mousecloak.1; sourceTree = "<group>"; };
FAC69FBA189D609B00BC829D /* CarbonHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CarbonHelpers.h; sourceTree = "<group>"; };
FAC69FBB189D609B00BC829D /* CGSAccessibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSAccessibility.h; sourceTree = "<group>"; };
FAC69FBC189D609B00BC829D /* CGSCIFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSCIFilter.h; sourceTree = "<group>"; };
FAC69FBD189D609B00BC829D /* CGSConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSConnection.h; sourceTree = "<group>"; };
FAC69FBE189D609B00BC829D /* CGSCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSCursor.h; sourceTree = "<group>"; };
FAC69FBF189D609B00BC829D /* CGSDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSDebug.h; sourceTree = "<group>"; };
FAC69FC0189D609B00BC829D /* CGSDisplays.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSDisplays.h; sourceTree = "<group>"; };
FAC69FC1189D609B00BC829D /* CGSHotKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSHotKeys.h; sourceTree = "<group>"; };
FAC69FC2189D609B00BC829D /* CGSInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSInternal.h; sourceTree = "<group>"; };
FAC69FC3189D609B00BC829D /* CGSMisc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSMisc.h; sourceTree = "<group>"; };
FAC69FC4189D609B00BC829D /* CGSNotifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSNotifications.h; sourceTree = "<group>"; };
FAC69FC5189D609B00BC829D /* CGSRegion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSRegion.h; sourceTree = "<group>"; };
FAC69FC6189D609B00BC829D /* CGSSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSSession.h; sourceTree = "<group>"; };
FAC69FC7189D609B00BC829D /* CGSTransitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSTransitions.h; sourceTree = "<group>"; };
FAC69FC8189D609B00BC829D /* CGSWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSWindow.h; sourceTree = "<group>"; };
FAC69FC9189D609B00BC829D /* CGSWorkspace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGSWorkspace.h; sourceTree = "<group>"; };
FAC69FCA189D609B00BC829D /* MCDefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCDefs.h; sourceTree = "<group>"; };
FAC69FCB189D609B00BC829D /* NSCursor_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSCursor_Private.h; sourceTree = "<group>"; };
FAC69FCE189D609B00BC829D /* GBCommandLineParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GBCommandLineParser.h; sourceTree = "<group>"; };
FAC69FCF189D609B00BC829D /* GBCommandLineParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GBCommandLineParser.m; sourceTree = "<group>"; };
FAC69FD0189D609B00BC829D /* GBOptionsHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GBOptionsHelper.h; sourceTree = "<group>"; };
FAC69FD1189D609B00BC829D /* GBOptionsHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GBOptionsHelper.m; sourceTree = "<group>"; };
FAC69FD2189D609B00BC829D /* GBSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GBSettings.h; sourceTree = "<group>"; };
FAC69FD3189D609B00BC829D /* GBSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GBSettings.m; sourceTree = "<group>"; };
FAC69FD7189D623C00BC829D /* Mousecape-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Mousecape-Prefix.pch"; sourceTree = "<group>"; };
FAC69FDB189D636700BC829D /* MCDefs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCDefs.m; sourceTree = "<group>"; };
FAEE650918A047E8003AA182 /* NSFileManager+DirectoryLocations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFileManager+DirectoryLocations.h"; sourceTree = "<group>"; };
FAEE650A18A047E8003AA182 /* NSFileManager+DirectoryLocations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFileManager+DirectoryLocations.m"; sourceTree = "<group>"; };
FAEE650B18A047E8003AA182 /* NSOrderedSet+AZSortedInsert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSOrderedSet+AZSortedInsert.h"; sourceTree = "<group>"; };
FAEE650C18A047E8003AA182 /* NSOrderedSet+AZSortedInsert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSOrderedSet+AZSortedInsert.m"; sourceTree = "<group>"; };
FAEE650E18A047E8003AA182 /* MCEditCapeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCEditCapeController.h; sourceTree = "<group>"; };
FAEE650F18A047E8003AA182 /* MCEditCapeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCEditCapeController.m; sourceTree = "<group>"; };
FAEE651018A047E8003AA182 /* MCEditDetailController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCEditDetailController.h; sourceTree = "<group>"; };
FAEE651118A047E8003AA182 /* MCEditDetailController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCEditDetailController.m; sourceTree = "<group>"; };
FAEE651218A047E8003AA182 /* MCEditListController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCEditListController.h; sourceTree = "<group>"; };
FAEE651318A047E8003AA182 /* MCEditListController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCEditListController.m; sourceTree = "<group>"; };
FAEE651418A047E8003AA182 /* MCEditWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCEditWindowController.h; sourceTree = "<group>"; };
FAEE651518A047E8003AA182 /* MCEditWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCEditWindowController.m; sourceTree = "<group>"; };
FAEE651618A047E8003AA182 /* MCLibraryController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCLibraryController.h; sourceTree = "<group>"; };
FAEE651718A047E8003AA182 /* MCLibraryController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCLibraryController.m; sourceTree = "<group>"; };
FAEE651818A047E8003AA182 /* MCLibraryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCLibraryViewController.h; sourceTree = "<group>"; };
FAEE651918A047E8003AA182 /* MCLibraryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCLibraryViewController.m; sourceTree = "<group>"; };
FAEE651A18A047E8003AA182 /* MCLibraryWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCLibraryWindowController.h; sourceTree = "<group>"; };
FAEE651B18A047E8003AA182 /* MCLibraryWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCLibraryWindowController.m; sourceTree = "<group>"; };
FAEE651D18A047E8003AA182 /* MCCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCCursor.h; sourceTree = "<group>"; };
FAEE651E18A047E8003AA182 /* MCCursor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCCursor.m; sourceTree = "<group>"; };
FAEE651F18A047E8003AA182 /* MCCursorLibrary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCCursorLibrary.h; sourceTree = "<group>"; };
FAEE652018A047E8003AA182 /* MCCursorLibrary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCCursorLibrary.m; sourceTree = "<group>"; };
FAEE652218A047E8003AA182 /* MCFormatters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCFormatters.h; sourceTree = "<group>"; };
FAEE652318A047E8003AA182 /* MCFormatters.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCFormatters.m; sourceTree = "<group>"; };
FAEE652518A047E8003AA182 /* MCCapeCellView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCCapeCellView.h; sourceTree = "<group>"; };
FAEE652618A047E8003AA182 /* MCCapeCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCCapeCellView.m; sourceTree = "<group>"; };
FAEE652718A047E8003AA182 /* MMAnimatingImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMAnimatingImageView.h; sourceTree = "<group>"; };
FAEE652818A047E8003AA182 /* MMAnimatingImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMAnimatingImageView.m; sourceTree = "<group>"; };
FAEE653718A048EA003AA182 /* MCSpriteLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSpriteLayer.h; sourceTree = "<group>"; };
FAEE653818A048EA003AA182 /* MCSpriteLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCSpriteLayer.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
FAC69F5E189D603C00BC829D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FAAEF8F7189EB34700145DF8 /* QuartzCore.framework in Frameworks */,
FA35984D189DC55A00288163 /* ServiceManagement.framework in Frameworks */,
FA359849189DC40100288163 /* Security.framework in Frameworks */,
FAC69F65189D603C00BC829D /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FAC69F7F189D603C00BC829D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FAC69F85189D603C00BC829D /* Cocoa.framework in Frameworks */,
FAC69F84189D603C00BC829D /* XCTest.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FAC69FAA189D608900BC829D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FA359853189E040D00288163 /* SystemConfiguration.framework in Frameworks */,
FAC69FDA189D632B00BC829D /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
FAAEF8EE189EB32700145DF8 /* external */ = {
isa = PBXGroup;
children = (
FAAEF8EF189EB32700145DF8 /* BTRKit */,
);
path = external;
sourceTree = "<group>";
};
FAAEF8EF189EB32700145DF8 /* BTRKit */ = {
isa = PBXGroup;
children = (
FAAEF8F0189EB32700145DF8 /* BTRClipView.h */,
FAAEF8F1189EB32700145DF8 /* BTRClipView.m */,
FAAEF8F2189EB32700145DF8 /* BTRScrollView.h */,
FAAEF8F3189EB32700145DF8 /* BTRScrollView.m */,
);
path = BTRKit;
sourceTree = "<group>";
};
FAC69F58189D603C00BC829D = {
isa = PBXGroup;
children = (
FAC69F6A189D603C00BC829D /* Mousecape */,
FAC69F88189D603C00BC829D /* MousecapeTests */,
FAC69FAF189D608900BC829D /* mousecloak */,
FAC69F63189D603C00BC829D /* Frameworks */,
FAC69F62189D603C00BC829D /* Products */,
);
sourceTree = "<group>";
};
FAC69F62189D603C00BC829D /* Products */ = {
isa = PBXGroup;
children = (
FAC69F61189D603C00BC829D /* Mousecape.app */,
FAC69F82189D603C00BC829D /* MousecapeTests.xctest */,
FAC69FAD189D608900BC829D /* mousecloak */,
);
name = Products;
sourceTree = "<group>";
};
FAC69F63189D603C00BC829D /* Frameworks */ = {
isa = PBXGroup;
children = (
FAAEF8F6189EB34700145DF8 /* QuartzCore.framework */,
FA35984C189DC55A00288163 /* ServiceManagement.framework */,
FA359848189DC40100288163 /* Security.framework */,
FA359844189DBA3800288163 /* SystemConfiguration.framework */,
FA254779189D85890038E1D9 /* ApplicationServices.framework */,
FAC69F64189D603C00BC829D /* Cocoa.framework */,
FAC69F83189D603C00BC829D /* XCTest.framework */,
FAC69F9D189D605300BC829D /* Foundation.framework */,
FAC69F66189D603C00BC829D /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
FAC69F66189D603C00BC829D /* Other Frameworks */ = {
isa = PBXGroup;
children = (
FAC69F67189D603C00BC829D /* AppKit.framework */,
FAC69F68189D603C00BC829D /* CoreData.framework */,
FAC69F69189D603C00BC829D /* Foundation.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
FAC69F6A189D603C00BC829D /* Mousecape */ = {
isa = PBXGroup;
children = (
FAEE650818A047E8003AA182 /* categories */,
FAEE650D18A047E8003AA182 /* controllers */,
FAEE651C18A047E8003AA182 /* models */,
FAEE652118A047E8003AA182 /* subclasses */,
FAEE652418A047E8003AA182 /* views */,
FAAEF8EE189EB32700145DF8 /* external */,
FAC69F76189D603C00BC829D /* MCAppDelegate.h */,
FAC69F77189D603C00BC829D /* MCAppDelegate.m */,
FAC69FD7189D623C00BC829D /* Mousecape-Prefix.pch */,
FA048868189F58B1001F3AB5 /* Edit.xib */,
FA04886A189F58B1001F3AB5 /* Library.xib */,
FAC69F79189D603C00BC829D /* MainMenu.xib */,
FAC69F7C189D603C00BC829D /* Images.xcassets */,
FAC69F6B189D603C00BC829D /* Supporting Files */,
);
path = Mousecape;
sourceTree = "<group>";
};
FAC69F6B189D603C00BC829D /* Supporting Files */ = {
isa = PBXGroup;
children = (
FAC69F6C189D603C00BC829D /* Mousecape-Info.plist */,
FAC69F6D189D603C00BC829D /* InfoPlist.strings */,
FAC69F70189D603C00BC829D /* main.m */,
FAC69F72189D603C00BC829D /* Mousecape-Prefix.pch */,
FAC69F73189D603C00BC829D /* Credits.rtf */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
FAC69F88189D603C00BC829D /* MousecapeTests */ = {
isa = PBXGroup;
children = (
FAC69F8E189D603C00BC829D /* MousecapeTests.m */,
FAC69F89189D603C00BC829D /* Supporting Files */,
);
path = MousecapeTests;
sourceTree = "<group>";
};
FAC69F89189D603C00BC829D /* Supporting Files */ = {
isa = PBXGroup;
children = (
FAC69F8A189D603C00BC829D /* MousecapeTests-Info.plist */,
FAC69F8B189D603C00BC829D /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
FAC69FAF189D608900BC829D /* mousecloak */ = {
isa = PBXGroup;
children = (
FAC69FB9189D609B00BC829D /* CGSInternal */,
FAC69FCC189D609B00BC829D /* vendor */,
FAC69FCA189D609B00BC829D /* MCDefs.h */,
FAC69FDB189D636700BC829D /* MCDefs.m */,
FA35983D189DA3BC00288163 /* MCPrefs.h */,
FA35983E189DA3BC00288163 /* MCPrefs.m */,
FAC69FB0189D608900BC829D /* main.m */,
FA8FF769189D663B00750E51 /* restore.h */,
FA8FF76A189D664400750E51 /* restore.m */,
FA8FF76C189D66C400750E51 /* backup.h */,
FA8FF76D189D66CB00750E51 /* backup.m */,
FA8FF76F189D66D100750E51 /* apply.h */,
FA8FF770189D66D800750E51 /* apply.m */,
FA8FF772189D67AA00750E51 /* create.h */,
FA8FF773189D67B100750E51 /* create.m */,
FA359850189E035200288163 /* listen.h */,
FA359851189E035900288163 /* listen.m */,
FAAEF955189F4ECC00145DF8 /* scale.h */,
FAAEF956189F4ED300145DF8 /* scale.m */,
FAC69FCB189D609B00BC829D /* NSCursor_Private.h */,
FAC69FB4189D608900BC829D /* mousecloak.1 */,
FAC69FB2189D608900BC829D /* Supporting Files */,
);
path = mousecloak;
sourceTree = "<group>";
};
FAC69FB2189D608900BC829D /* Supporting Files */ = {
isa = PBXGroup;
children = (
FAC69FB3189D608900BC829D /* mousecloak-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
FAC69FB9189D609B00BC829D /* CGSInternal */ = {
isa = PBXGroup;
children = (
FAC69FBA189D609B00BC829D /* CarbonHelpers.h */,
FAC69FBB189D609B00BC829D /* CGSAccessibility.h */,
FAC69FBC189D609B00BC829D /* CGSCIFilter.h */,
FAC69FBD189D609B00BC829D /* CGSConnection.h */,
FAC69FBE189D609B00BC829D /* CGSCursor.h */,
FAC69FBF189D609B00BC829D /* CGSDebug.h */,
FAC69FC0189D609B00BC829D /* CGSDisplays.h */,
FAC69FC1189D609B00BC829D /* CGSHotKeys.h */,
FAC69FC2189D609B00BC829D /* CGSInternal.h */,
FAC69FC3189D609B00BC829D /* CGSMisc.h */,
FAC69FC4189D609B00BC829D /* CGSNotifications.h */,
FAC69FC5189D609B00BC829D /* CGSRegion.h */,
FAC69FC6189D609B00BC829D /* CGSSession.h */,
FAC69FC7189D609B00BC829D /* CGSTransitions.h */,
FAC69FC8189D609B00BC829D /* CGSWindow.h */,
FAC69FC9189D609B00BC829D /* CGSWorkspace.h */,
);
path = CGSInternal;
sourceTree = "<group>";
};
FAC69FCC189D609B00BC829D /* vendor */ = {
isa = PBXGroup;
children = (
FAC69FCD189D609B00BC829D /* GBCli */,
);
path = vendor;
sourceTree = "<group>";
};
FAC69FCD189D609B00BC829D /* GBCli */ = {
isa = PBXGroup;
children = (
FAC69FCE189D609B00BC829D /* GBCommandLineParser.h */,
FAC69FCF189D609B00BC829D /* GBCommandLineParser.m */,
FAC69FD0189D609B00BC829D /* GBOptionsHelper.h */,
FAC69FD1189D609B00BC829D /* GBOptionsHelper.m */,
FAC69FD2189D609B00BC829D /* GBSettings.h */,
FAC69FD3189D609B00BC829D /* GBSettings.m */,
);
path = GBCli;
sourceTree = "<group>";
};
FAEE650818A047E8003AA182 /* categories */ = {
isa = PBXGroup;
children = (
FAEE650918A047E8003AA182 /* NSFileManager+DirectoryLocations.h */,
FAEE650A18A047E8003AA182 /* NSFileManager+DirectoryLocations.m */,
FAEE650B18A047E8003AA182 /* NSOrderedSet+AZSortedInsert.h */,
FAEE650C18A047E8003AA182 /* NSOrderedSet+AZSortedInsert.m */,
);
name = categories;
path = src/categories;
sourceTree = "<group>";
};
FAEE650D18A047E8003AA182 /* controllers */ = {
isa = PBXGroup;
children = (
FAEE650E18A047E8003AA182 /* MCEditCapeController.h */,
FAEE650F18A047E8003AA182 /* MCEditCapeController.m */,
FAEE651018A047E8003AA182 /* MCEditDetailController.h */,
FAEE651118A047E8003AA182 /* MCEditDetailController.m */,
FAEE651218A047E8003AA182 /* MCEditListController.h */,
FAEE651318A047E8003AA182 /* MCEditListController.m */,
FAEE651418A047E8003AA182 /* MCEditWindowController.h */,
FAEE651518A047E8003AA182 /* MCEditWindowController.m */,
FAEE651618A047E8003AA182 /* MCLibraryController.h */,
FAEE651718A047E8003AA182 /* MCLibraryController.m */,
FAEE651818A047E8003AA182 /* MCLibraryViewController.h */,
FAEE651918A047E8003AA182 /* MCLibraryViewController.m */,
FAEE651A18A047E8003AA182 /* MCLibraryWindowController.h */,
FAEE651B18A047E8003AA182 /* MCLibraryWindowController.m */,
);
name = controllers;
path = src/controllers;
sourceTree = "<group>";
};
FAEE651C18A047E8003AA182 /* models */ = {
isa = PBXGroup;
children = (
FAEE651D18A047E8003AA182 /* MCCursor.h */,
FAEE651E18A047E8003AA182 /* MCCursor.m */,
FAEE651F18A047E8003AA182 /* MCCursorLibrary.h */,
FAEE652018A047E8003AA182 /* MCCursorLibrary.m */,
);
name = models;
path = src/models;
sourceTree = "<group>";
};
FAEE652118A047E8003AA182 /* subclasses */ = {
isa = PBXGroup;
children = (
FAEE652218A047E8003AA182 /* MCFormatters.h */,
FAEE652318A047E8003AA182 /* MCFormatters.m */,
);
name = subclasses;
path = src/subclasses;
sourceTree = "<group>";
};
FAEE652418A047E8003AA182 /* views */ = {
isa = PBXGroup;
children = (
FAEE652518A047E8003AA182 /* MCCapeCellView.h */,
FAEE652618A047E8003AA182 /* MCCapeCellView.m */,
FAEE652718A047E8003AA182 /* MMAnimatingImageView.h */,
FAEE652818A047E8003AA182 /* MMAnimatingImageView.m */,
FAEE653718A048EA003AA182 /* MCSpriteLayer.h */,
FAEE653818A048EA003AA182 /* MCSpriteLayer.m */,
);
name = views;
path = src/views;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
FAC69F60189D603C00BC829D /* Mousecape */ = {
isa = PBXNativeTarget;
buildConfigurationList = FAC69F92189D603C00BC829D /* Build configuration list for PBXNativeTarget "Mousecape" */;
buildPhases = (
FAC69F5D189D603C00BC829D /* Sources */,
FAC69F5F189D603C00BC829D /* Resources */,
FAC69F5E189D603C00BC829D /* Frameworks */,
FA359841189DAAF900288163 /* Build Number */,
FA35984A189DC47800288163 /* Copy Tools */,
);
buildRules = (
);
dependencies = (
FA359847189DBEB700288163 /* PBXTargetDependency */,
);
name = Mousecape;
productName = Mousecape;
productReference = FAC69F61189D603C00BC829D /* Mousecape.app */;
productType = "com.apple.product-type.application";
};
FAC69F81189D603C00BC829D /* MousecapeTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = FAC69F95189D603C00BC829D /* Build configuration list for PBXNativeTarget "MousecapeTests" */;
buildPhases = (
FAC69F7E189D603C00BC829D /* Sources */,
FAC69F7F189D603C00BC829D /* Frameworks */,
FAC69F80189D603C00BC829D /* Resources */,
);
buildRules = (
);
dependencies = (
FAC69F87189D603C00BC829D /* PBXTargetDependency */,
);
name = MousecapeTests;
productName = MousecapeTests;
productReference = FAC69F82189D603C00BC829D /* MousecapeTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
FAC69FAC189D608900BC829D /* mousecloak */ = {
isa = PBXNativeTarget;
buildConfigurationList = FAC69FB6189D608A00BC829D /* Build configuration list for PBXNativeTarget "mousecloak" */;
buildPhases = (
FAC69FA9189D608900BC829D /* Sources */,
FAC69FAA189D608900BC829D /* Frameworks */,
FAC69FAB189D608900BC829D /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = mousecloak;
productName = mousecloak;
productReference = FAC69FAD189D608900BC829D /* mousecloak */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
FAC69F59189D603C00BC829D /* Project object */ = {
isa = PBXProject;
attributes = {
CLASSPREFIX = MC;
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = "Alex Zielenski";
TargetAttributes = {
FAC69F60189D603C00BC829D = {
DevelopmentTeam = 3GD8ABJ22W;
};
FAC69F81189D603C00BC829D = {
TestTargetID = FAC69F60189D603C00BC829D;
};
};
};
buildConfigurationList = FAC69F5C189D603C00BC829D /* Build configuration list for PBXProject "Mousecape" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = FAC69F58189D603C00BC829D;
productRefGroup = FAC69F62189D603C00BC829D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
FAC69F60189D603C00BC829D /* Mousecape */,
FAC69F81189D603C00BC829D /* MousecapeTests */,
FAC69FAC189D608900BC829D /* mousecloak */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
FAC69F5F189D603C00BC829D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FAC69F6F189D603C00BC829D /* InfoPlist.strings in Resources */,
FA04886D189F58B1001F3AB5 /* Library.xib in Resources */,
FA04886C189F58B1001F3AB5 /* Edit.xib in Resources */,
FAC69F7D189D603C00BC829D /* Images.xcassets in Resources */,
FAC69F75189D603C00BC829D /* Credits.rtf in Resources */,
FAC69F7B189D603C00BC829D /* MainMenu.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FAC69F80189D603C00BC829D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FAC69F8D189D603C00BC829D /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
FA359841189DAAF900288163 /* Build Number */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Build Number";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "#!/bin/bash\n\nbuildPlist=${INFOPLIST_FILE}\nCFBundleVersion=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" $buildPlist)\nBuildNumberINCR=$((CFBundleVersion + 1))\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $BuildNumberINCR\" $buildPlist\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
FAC69F5D189D603C00BC829D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FAEE653018A047E8003AA182 /* MCLibraryViewController.m in Sources */,
FAEE653618A047E8003AA182 /* MMAnimatingImageView.m in Sources */,
FAEE653318A047E8003AA182 /* MCCursorLibrary.m in Sources */,
FAC69F78189D603C00BC829D /* MCAppDelegate.m in Sources */,
FAEE653918A048EA003AA182 /* MCSpriteLayer.m in Sources */,
FAEE652F18A047E8003AA182 /* MCLibraryController.m in Sources */,
FAEE653118A047E8003AA182 /* MCLibraryWindowController.m in Sources */,
FAAEF94E189EFC9300145DF8 /* create.m in Sources */,
FAEE652C18A047E8003AA182 /* MCEditDetailController.m in Sources */,
FAAEF94F189EFC9600145DF8 /* backup.m in Sources */,
FAAEF951189F0CC300145DF8 /* restore.m in Sources */,
FAAEF950189EFC9800145DF8 /* apply.m in Sources */,
FAEE652918A047E8003AA182 /* NSFileManager+DirectoryLocations.m in Sources */,
FAEE652D18A047E8003AA182 /* MCEditListController.m in Sources */,
FAC69F71189D603C00BC829D /* main.m in Sources */,
FAEE653218A047E8003AA182 /* MCCursor.m in Sources */,
FAAEF958189F4F8200145DF8 /* scale.m in Sources */,
FAEE653418A047E8003AA182 /* MCFormatters.m in Sources */,
FAAEF8F4189EB32700145DF8 /* BTRClipView.m in Sources */,
FAAEF8F5189EB32700145DF8 /* BTRScrollView.m in Sources */,
FAC69FDC189D636700BC829D /* MCDefs.m in Sources */,
FAEE652E18A047E8003AA182 /* MCEditWindowController.m in Sources */,
FA359840189DA3C100288163 /* MCPrefs.m in Sources */,
FAEE652B18A047E8003AA182 /* MCEditCapeController.m in Sources */,
FAEE652A18A047E8003AA182 /* NSOrderedSet+AZSortedInsert.m in Sources */,
FAEE653518A047E8003AA182 /* MCCapeCellView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FAC69F7E189D603C00BC829D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FAC69F8F189D603C00BC829D /* MousecapeTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FAC69FA9189D608900BC829D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FAC69FB1189D608900BC829D /* main.m in Sources */,
FA8FF76E189D66CB00750E51 /* backup.m in Sources */,
FAC69FD6189D609B00BC829D /* GBSettings.m in Sources */,
FA359852189E035900288163 /* listen.m in Sources */,
FAC69FD5189D609B00BC829D /* GBOptionsHelper.m in Sources */,
FA35983F189DA3BC00288163 /* MCPrefs.m in Sources */,
FAAEF957189F4ED300145DF8 /* scale.m in Sources */,
FA8FF76B189D664400750E51 /* restore.m in Sources */,
FA8FF771189D66D800750E51 /* apply.m in Sources */,
FAC69FDD189D636700BC829D /* MCDefs.m in Sources */,
FAC69FD4189D609B00BC829D /* GBCommandLineParser.m in Sources */,
FA8FF774189D67B100750E51 /* create.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
FA359847189DBEB700288163 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FAC69FAC189D608900BC829D /* mousecloak */;
targetProxy = FA359846189DBEB700288163 /* PBXContainerItemProxy */;
};
FAC69F87189D603C00BC829D /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FAC69F60189D603C00BC829D /* Mousecape */;
targetProxy = FAC69F86189D603C00BC829D /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
FA048868189F58B1001F3AB5 /* Edit.xib */ = {
isa = PBXVariantGroup;
children = (
FA048869189F58B1001F3AB5 /* Base */,
);
name = Edit.xib;
sourceTree = "<group>";
};
FA04886A189F58B1001F3AB5 /* Library.xib */ = {
isa = PBXVariantGroup;
children = (
FA04886B189F58B1001F3AB5 /* Base */,
);
name = Library.xib;
sourceTree = "<group>";
};
FAC69F6D189D603C00BC829D /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
FAC69F6E189D603C00BC829D /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
FAC69F73189D603C00BC829D /* Credits.rtf */ = {
isa = PBXVariantGroup;
children = (
FAC69F74189D603C00BC829D /* en */,
);
name = Credits.rtf;
sourceTree = "<group>";
};
FAC69F79189D603C00BC829D /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
FAC69F7A189D603C00BC829D /* Base */,
);
name = MainMenu.xib;
sourceTree = "<group>";
};
FAC69F8B189D603C00BC829D /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
FAC69F8C189D603C00BC829D /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
FAC69F90189D603C00BC829D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"PROJECT_DIR=\\\"\"$(PROJECT_DIR)\"\\\"",
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.8;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx10.8;
};
name = Debug;
};
FAC69F91189D603C00BC829D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PREPROCESSOR_DEFINITIONS = "PROJECT_DIR=\\\"\"$(PROJECT_DIR)\"\\\"";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.8;
SDKROOT = macosx10.8;
};
name = Release;
};
FAC69F93189D603C00BC829D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Developer ID Application";
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Mousecape/Mousecape-Prefix.pch";
INFOPLIST_FILE = "Mousecape/Mousecape-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
FAC69F94189D603C00BC829D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Developer ID Application";
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Mousecape/Mousecape-Prefix.pch";
INFOPLIST_FILE = "Mousecape/Mousecape-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
FAC69F96189D603C00BC829D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Mousecape.app/Contents/MacOS/Mousecape";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Mousecape/Mousecape-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "MousecapeTests/MousecapeTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
FAC69F97189D603C00BC829D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Mousecape.app/Contents/MacOS/Mousecape";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Mousecape/Mousecape-Prefix.pch";
INFOPLIST_FILE = "MousecapeTests/MousecapeTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
FAC69FB7189D608A00BC829D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_ARC = NO;
CODE_SIGN_IDENTITY = "Developer ID Application";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "mousecloak/mousecloak-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(PROJECT_DIR)/mousecloak/vendor",
);
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
FAC69FB8189D608A00BC829D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_ARC = NO;
CODE_SIGN_IDENTITY = "Developer ID Application";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "mousecloak/mousecloak-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(PROJECT_DIR)/mousecloak/vendor",
);
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
FAC69F5C189D603C00BC829D /* Build configuration list for PBXProject "Mousecape" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FAC69F90189D603C00BC829D /* Debug */,
FAC69F91189D603C00BC829D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FAC69F92189D603C00BC829D /* Build configuration list for PBXNativeTarget "Mousecape" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FAC69F93189D603C00BC829D /* Debug */,
FAC69F94189D603C00BC829D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FAC69F95189D603C00BC829D /* Build configuration list for PBXNativeTarget "MousecapeTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FAC69F96189D603C00BC829D /* Debug */,
FAC69F97189D603C00BC829D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FAC69FB6189D608A00BC829D /* Build configuration list for PBXNativeTarget "mousecloak" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FAC69FB7189D608A00BC829D /* Debug */,
FAC69FB8189D608A00BC829D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = FAC69F59189D603C00BC829D /* Project object */;
}
@@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "self:Magic Mouse.xcodeproj">
location = "self:Mousecape.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,41 @@
<?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>IDESourceControlProjectFavoriteDictionaryKey</key>
<false/>
<key>IDESourceControlProjectIdentifier</key>
<string>BF07C3E0-6EFD-4BF5-8AB0-F3D236F6FEEA</string>
<key>IDESourceControlProjectName</key>
<string>Mousecape</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>FC2A2851-1AE3-4D52-8AFC-6A9D2EF109B1</key>
<string>ssh://github.com/alexzielenski/Mousecape.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>Mousecape/Mousecape.xcodeproj/project.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>FC2A2851-1AE3-4D52-8AFC-6A9D2EF109B1</key>
<string>../../..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>ssh://github.com/alexzielenski/Mousecape.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>110</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>FC2A2851-1AE3-4D52-8AFC-6A9D2EF109B1</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>FC2A2851-1AE3-4D52-8AFC-6A9D2EF109B1</string>
<key>IDESourceControlWCCName</key>
<string>Mousecape</string>
</dict>
</array>
</dict>
</plist>
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
type = "1"
version = "1.0">
version = "2.0">
</Bucket>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0440"
LastUpgradeVersion = "0500"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -14,28 +14,38 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FA6F2D1D14F3150E0098AE57"
BuildableName = "magicmouse"
BlueprintName = "magicmouse"
ReferencedContainer = "container:Magic Mouse.xcodeproj">
BlueprintIdentifier = "FAC69F60189D603C00BC829D"
BuildableName = "Mousecape.app"
BlueprintName = "Mousecape"
ReferencedContainer = "container:Mousecape.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FAC69F81189D603C00BC829D"
BuildableName = "MousecapeTests.xctest"
BlueprintName = "MousecapeTests"
ReferencedContainer = "container:Mousecape.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FA6F2D1D14F3150E0098AE57"
BuildableName = "magicmouse"
BlueprintName = "magicmouse"
ReferencedContainer = "container:Magic Mouse.xcodeproj">
BlueprintIdentifier = "FAC69F60189D603C00BC829D"
BuildableName = "Mousecape.app"
BlueprintName = "Mousecape"
ReferencedContainer = "container:Mousecape.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
@@ -51,18 +61,12 @@
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FA6F2D1D14F3150E0098AE57"
BuildableName = "magicmouse"
BlueprintName = "magicmouse"
ReferencedContainer = "container:Magic Mouse.xcodeproj">
BlueprintIdentifier = "FAC69F60189D603C00BC829D"
BuildableName = "Mousecape.app"
BlueprintName = "Mousecape"
ReferencedContainer = "container:Mousecape.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "/Users/Alex/Desktop/svanslos.plist"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
@@ -75,10 +79,10 @@
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FA6F2D1D14F3150E0098AE57"
BuildableName = "magicmouse"
BlueprintName = "magicmouse"
ReferencedContainer = "container:Magic Mouse.xcodeproj">
BlueprintIdentifier = "FAC69F60189D603C00BC829D"
BuildableName = "Mousecape.app"
BlueprintName = "Mousecape"
ReferencedContainer = "container:Mousecape.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0500"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -13,10 +14,10 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FA6F2D1D14F3150E0098AE57"
BuildableName = "magicmouse"
BlueprintName = "magicmouse"
ReferencedContainer = "container:Magic Mouse.xcodeproj">
BlueprintIdentifier = "FAC69FAC189D608900BC829D"
BuildableName = "mousecloak"
BlueprintName = "mousecloak"
ReferencedContainer = "container:Mousecape.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -31,10 +32,10 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FA6F2D1D14F3150E0098AE57"
BuildableName = "magicmouse"
BlueprintName = "magicmouse"
ReferencedContainer = "container:Magic Mouse.xcodeproj">
BlueprintIdentifier = "FAC69FAC189D608900BC829D"
BuildableName = "mousecloak"
BlueprintName = "mousecloak"
ReferencedContainer = "container:Mousecape.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
@@ -50,10 +51,10 @@
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FA6F2D1D14F3150E0098AE57"
BuildableName = "magicmouse"
BlueprintName = "magicmouse"
ReferencedContainer = "container:Magic Mouse.xcodeproj">
BlueprintIdentifier = "FAC69FAC189D608900BC829D"
BuildableName = "mousecloak"
BlueprintName = "mousecloak"
ReferencedContainer = "container:Mousecape.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
@@ -68,10 +69,10 @@
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FA6F2D1D14F3150E0098AE57"
BuildableName = "magicmouse"
BlueprintName = "magicmouse"
ReferencedContainer = "container:Magic Mouse.xcodeproj">
BlueprintIdentifier = "FAC69FAC189D608900BC829D"
BuildableName = "mousecloak"
BlueprintName = "mousecloak"
ReferencedContainer = "container:Mousecape.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
@@ -4,35 +4,35 @@
<dict>
<key>SchemeUserState</key>
<dict>
<key>Magic Mouse.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
<key>magicmouse.xcscheme</key>
<key>Mousecape.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>mousecloak.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>FA67E4B614FAD1E300F1D69E</key>
<key>FAC69F60189D603C00BC829D</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>FA6F2CF814F315000098AE57</key>
<key>FAC69F81189D603C00BC829D</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>FA6F2D1D14F3150E0098AE57</key>
<key>FAC69F9B189D605300BC829D</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>FAD37AFD14F9836E00B7F09C</key>
<key>FAC69FAC189D608900BC829D</key>
<dict>
<key>primary</key>
<true/>
+679
View File
@@ -0,0 +1,679 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment defaultVersion="1080" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="MCEditWindowController">
<connections>
<outlet property="detailView" destination="fzz-Li-KC6" id="o4X-5d-9UA"/>
<outlet property="editCapeController" destination="Bu6-lg-x1j" id="K0b-fF-JHE"/>
<outlet property="editDetailController" destination="tMj-cQ-hK0" id="i1B-Pa-vlp"/>
<outlet property="editListController" destination="oUs-Nv-PHw" id="C2e-6f-Mpe"/>
<outlet property="window" destination="1" id="3"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" wantsToBeColor="NO" animationBehavior="default" id="1">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="525" height="297"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1418"/>
<value key="minSize" type="size" width="500" height="310"/>
<view key="contentView" id="2">
<rect key="frame" x="0.0" y="0.0" width="525" height="297"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<splitView canDrawConcurrently="YES" dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3cj-R9-WKK">
<rect key="frame" x="0.0" y="0.0" width="525" height="297"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<customView id="IHY-vi-Wpr">
<rect key="frame" x="0.0" y="0.0" width="135" height="297"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView canDrawConcurrently="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2UQ-R4-qJn">
<rect key="frame" x="0.0" y="22" width="135" height="275"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" copiesOnScroll="NO" id="ame-2S-JV7">
<rect key="frame" x="0.0" y="0.0" width="135" height="275"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" rowSizeStyle="automatic" viewBased="YES" id="MU4-Yh-0PJ">
<rect key="frame" x="0.0" y="0.0" width="135" height="275"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn editable="NO" width="132" minWidth="40" maxWidth="1000" id="B1d-Yp-OOR">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="EOd-L3-If3">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
<prototypeCellViews>
<tableCellView identifier="MCCursorLibrary" id="ti0-Bq-1rU">
<rect key="frame" x="1" y="1" width="132" height="32"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="tn7-kB-Fvu">
<rect key="frame" x="6" y="8" width="120" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="8we-kW-bNk">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="backgroundStyle">
<integer key="value" value="2"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</textFieldCell>
<connections>
<binding destination="ti0-Bq-1rU" name="value" keyPath="objectValue.name" id="t1G-Uv-n0y"/>
</connections>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="tn7-kB-Fvu" secondAttribute="trailing" constant="8" id="ilO-BE-fhh"/>
<constraint firstAttribute="centerY" secondItem="tn7-kB-Fvu" secondAttribute="centerY" id="xFa-kX-vgG"/>
<constraint firstItem="tn7-kB-Fvu" firstAttribute="leading" secondItem="ti0-Bq-1rU" secondAttribute="leading" constant="8" id="zRO-gF-Fjk"/>
</constraints>
<connections>
<outlet property="textField" destination="tn7-kB-Fvu" id="EIu-dF-vgX"/>
</connections>
</tableCellView>
<tableCellView identifier="MCCursor" id="ldl-Zk-KLa">
<rect key="frame" x="1" y="35" width="132" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="W6i-Uv-3TI">
<rect key="frame" x="6" y="0.0" width="120" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="8bB-Ws-20v">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="ldl-Zk-KLa" name="value" keyPath="objectValue.name" id="OuH-uQ-nFp"/>
</connections>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="centerY" secondItem="W6i-Uv-3TI" secondAttribute="centerY" id="JPw-Qf-DNs"/>
<constraint firstItem="W6i-Uv-3TI" firstAttribute="leading" secondItem="ldl-Zk-KLa" secondAttribute="leading" constant="8" id="WvV-tP-TPf"/>
<constraint firstAttribute="trailing" secondItem="W6i-Uv-3TI" secondAttribute="trailing" constant="8" id="zV0-3Z-fAD"/>
</constraints>
<connections>
<outlet property="textField" destination="W6i-Uv-3TI" id="rCr-ZD-nty"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
<connections>
<outlet property="dataSource" destination="oUs-Nv-PHw" id="ur0-Pm-oqJ"/>
<outlet property="delegate" destination="oUs-Nv-PHw" id="GMA-yd-uCn"/>
<outlet property="nextKeyView" destination="fzz-Li-KC6" id="Mg7-QD-IZj"/>
</connections>
</tableView>
</subviews>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="ARR-bd-5zK">
<rect key="frame" x="0.0" y="-16" width="0.0" height="16"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="3rZ-7d-Mro">
<rect key="frame" x="-16" y="0.0" width="16" height="0.0"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<button translatesAutoresizingMaskIntoConstraints="NO" id="0ps-WH-ASN">
<rect key="frame" x="0.0" y="0.0" width="22" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="width" constant="22" id="Fdb-xA-sn9"/>
<constraint firstAttribute="height" constant="22" id="iNY-lh-RsQ"/>
</constraints>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSAddTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="xv7-ZP-O2C">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="addAction:" target="oUs-Nv-PHw" id="QeK-Mq-YfI"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="w4h-lB-jLi">
<rect key="frame" x="22" y="0.0" width="22" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="width" constant="22" id="L21-Ci-myo"/>
<constraint firstAttribute="height" constant="22" id="M80-94-gpJ"/>
</constraints>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSRemoveTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="HjH-hq-TxT">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="removeAction:" target="oUs-Nv-PHw" id="JjR-lV-zwz"/>
</connections>
</button>
<box autoresizesSubviews="NO" verticalHuggingPriority="750" title="Box" boxType="separator" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="UJO-Hw-fRK">
<rect key="frame" x="0.0" y="19" width="135" height="5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="NYz-xn-F0g"/>
</constraints>
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<font key="titleFont" metaFont="system"/>
</box>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="UJO-Hw-fRK" secondAttribute="trailing" id="1nr-pf-XFQ"/>
<constraint firstAttribute="bottom" secondItem="UJO-Hw-fRK" secondAttribute="bottom" constant="21" id="6Ak-tM-Cac"/>
<constraint firstItem="0ps-WH-ASN" firstAttribute="width" secondItem="w4h-lB-jLi" secondAttribute="width" id="97v-Rq-d09"/>
<constraint firstAttribute="bottom" secondItem="0ps-WH-ASN" secondAttribute="bottom" id="Afn-3d-zKF"/>
<constraint firstItem="UJO-Hw-fRK" firstAttribute="leading" secondItem="IHY-vi-Wpr" secondAttribute="leading" id="C8U-9e-Hyh"/>
<constraint firstAttribute="trailing" secondItem="2UQ-R4-qJn" secondAttribute="trailing" id="LC4-J4-2bn"/>
<constraint firstItem="2UQ-R4-qJn" firstAttribute="top" secondItem="IHY-vi-Wpr" secondAttribute="top" id="NyE-Z9-XCc"/>
<constraint firstItem="0ps-WH-ASN" firstAttribute="leading" secondItem="IHY-vi-Wpr" secondAttribute="leading" id="kvW-tW-AQF"/>
<constraint firstItem="w4h-lB-jLi" firstAttribute="leading" secondItem="0ps-WH-ASN" secondAttribute="trailing" id="oqH-vB-hO8"/>
<constraint firstItem="0ps-WH-ASN" firstAttribute="bottom" secondItem="w4h-lB-jLi" secondAttribute="bottom" id="sWe-gf-GX0"/>
<constraint firstItem="2UQ-R4-qJn" firstAttribute="leading" secondItem="IHY-vi-Wpr" secondAttribute="leading" id="thB-tX-fKx"/>
<constraint firstItem="0ps-WH-ASN" firstAttribute="height" secondItem="w4h-lB-jLi" secondAttribute="height" id="uJj-nv-0fc"/>
<constraint firstAttribute="bottom" secondItem="2UQ-R4-qJn" secondAttribute="bottom" constant="22" id="vLX-hs-yVP"/>
</constraints>
</customView>
<customView fixedFrame="YES" id="fzz-Li-KC6">
<rect key="frame" x="136" y="0.0" width="389" height="297"/>
<autoresizingMask key="autoresizingMask"/>
</customView>
</subviews>
<holdingPriorities>
<real value="250"/>
<real value="250"/>
</holdingPriorities>
<connections>
<outlet property="delegate" destination="-2" id="lwv-X3-bDm"/>
</connections>
</splitView>
</subviews>
<constraints>
<constraint firstItem="3cj-R9-WKK" firstAttribute="leading" secondItem="2" secondAttribute="leading" id="4E6-iP-FpE"/>
<constraint firstItem="3cj-R9-WKK" firstAttribute="top" secondItem="2" secondAttribute="top" id="Eam-bF-EPz"/>
<constraint firstAttribute="trailing" secondItem="3cj-R9-WKK" secondAttribute="trailing" id="IT0-Rw-fmh"/>
<constraint firstAttribute="bottom" secondItem="3cj-R9-WKK" secondAttribute="bottom" id="znR-CB-aDB"/>
</constraints>
</view>
<connections>
<binding destination="oUs-Nv-PHw" name="title" keyPath="cursorLibrary.name" id="RKE-nQ-CzI"/>
<outlet property="delegate" destination="-2" id="4"/>
</connections>
</window>
<viewController title="List" id="oUs-Nv-PHw" customClass="MCEditListController">
<connections>
<outlet property="tableView" destination="MU4-Yh-0PJ" id="TRg-C6-MaW"/>
<outlet property="view" destination="MU4-Yh-0PJ" id="xHm-2x-mvT"/>
</connections>
</viewController>
<viewController title="Detail" id="tMj-cQ-hK0" customClass="MCEditDetailController">
<connections>
<outlet property="rep1000View" destination="4hN-Nm-B7Z" id="8iU-1v-yGH"/>
<outlet property="rep100View" destination="j7v-U4-eMe" id="X5D-KB-JVI"/>
<outlet property="rep200View" destination="ggE-Pd-aWo" id="oJ3-3i-3SZ"/>
<outlet property="rep500View" destination="G3t-wd-E5Y" id="u1Y-3n-iRc"/>
<outlet property="typePopUpButton" destination="yz7-y5-TxE" id="0Lj-Ty-Oea"/>
<outlet property="view" destination="o0X-1i-ZgL" id="fn8-Is-pBo"/>
</connections>
</viewController>
<viewController title="Cape" id="Bu6-lg-x1j" customClass="MCEditCapeController">
<connections>
<outlet property="view" destination="WMR-Vn-IHF" id="tlm-o5-run"/>
</connections>
</viewController>
<customView id="WMR-Vn-IHF" userLabel="Cape">
<rect key="frame" x="0.0" y="0.0" width="504" height="321"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="X2i-rg-HDg">
<rect key="frame" x="18" y="259" width="65" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Author:" id="Oyi-AW-60U">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="yyn-IO-TkO">
<rect key="frame" x="18" y="209" width="65" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Version:" id="98i-gH-tf4">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ELX-ej-rTb">
<rect key="frame" x="18" y="234" width="65" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Identifier:" id="Xzj-Uq-4bW">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="CTE-6h-rbf">
<rect key="frame" x="18" y="284" width="65" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Name:" id="oMS-dL-nZj">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bim-1a-xuh">
<rect key="frame" x="89" y="281" width="395" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="07X-ce-vmv">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="Bu6-lg-x1j" name="value" keyPath="cursorLibrary.name" id="QlS-r9-svX"/>
<outlet property="nextKeyView" destination="xy3-2B-C0h" id="kJW-OZ-1NO"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xy3-2B-C0h">
<rect key="frame" x="89" y="256" width="395" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="fmY-Bj-OnI">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="Bu6-lg-x1j" name="value" keyPath="cursorLibrary.author" id="CfA-df-u6f"/>
<outlet property="nextKeyView" destination="XYx-UL-WbM" id="74w-oc-ff2"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XYx-UL-WbM">
<rect key="frame" x="89" y="231" width="395" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="sjK-hK-kfo">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="Bu6-lg-x1j" name="value" keyPath="cursorLibrary.identifier" id="Vdx-1W-Guz">
<dictionary key="options">
<bool key="NSValidatesImmediately" value="YES"/>
</dictionary>
</binding>
<outlet property="nextKeyView" destination="car-it-RsL" id="uaw-jj-8AW"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="car-it-RsL">
<rect key="frame" x="89" y="206" width="395" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="qW0-CC-89l">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="oUs-Nv-PHw" name="value" keyPath="cursorLibrary.version" id="pHV-5a-ce5"/>
<outlet property="nextKeyView" destination="MJr-Jz-5Cq" id="sfZ-oa-g3c"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="i5v-yD-weq">
<rect key="frame" x="18" y="184" width="65" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Retina:" id="HFS-GR-guB">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="MJr-Jz-5Cq">
<rect key="frame" x="87" y="182" width="18" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="overlaps" state="on" inset="2" id="Ma9-Ke-hYa">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="Bu6-lg-x1j" name="value" keyPath="cursorLibrary.hiDPI" id="jnk-dy-w9m"/>
<outlet property="nextKeyView" destination="bim-1a-xuh" id="flN-6L-Vpz"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="car-it-RsL" firstAttribute="leading" secondItem="bim-1a-xuh" secondAttribute="leading" id="0xF-zq-ScD"/>
<constraint firstAttribute="trailing" secondItem="XYx-UL-WbM" secondAttribute="trailing" constant="20" id="2FH-UV-gN8"/>
<constraint firstItem="car-it-RsL" firstAttribute="width" secondItem="xy3-2B-C0h" secondAttribute="width" id="5Ga-DV-3Po"/>
<constraint firstItem="car-it-RsL" firstAttribute="width" secondItem="XYx-UL-WbM" secondAttribute="width" id="78w-Rp-5Kn"/>
<constraint firstItem="bim-1a-xuh" firstAttribute="top" secondItem="WMR-Vn-IHF" secondAttribute="top" constant="18" id="7md-u2-mQL"/>
<constraint firstAttribute="trailing" secondItem="car-it-RsL" secondAttribute="trailing" constant="20" id="8og-5G-f3t"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="leading" secondItem="yyn-IO-TkO" secondAttribute="leading" id="A71-62-pAd"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="trailing" secondItem="X2i-rg-HDg" secondAttribute="trailing" id="B5V-w4-E4R"/>
<constraint firstItem="xy3-2B-C0h" firstAttribute="top" secondItem="bim-1a-xuh" secondAttribute="bottom" constant="3" id="Ba8-n2-AJY"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="trailing" secondItem="ELX-ej-rTb" secondAttribute="trailing" id="CUf-rI-rpu"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="width" secondItem="X2i-rg-HDg" secondAttribute="width" id="D9Z-q0-phl"/>
<constraint firstItem="ELX-ej-rTb" firstAttribute="top" secondItem="X2i-rg-HDg" secondAttribute="bottom" constant="8" id="DLd-62-Iep"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="width" secondItem="ELX-ej-rTb" secondAttribute="width" id="DNc-Oi-qtL"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="leading" secondItem="X2i-rg-HDg" secondAttribute="leading" id="Dzm-RT-QGr"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="leading" secondItem="ELX-ej-rTb" secondAttribute="leading" id="H6H-IO-OIS"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="trailing" secondItem="yyn-IO-TkO" secondAttribute="trailing" id="Iox-22-dSy"/>
<constraint firstItem="yyn-IO-TkO" firstAttribute="top" secondItem="ELX-ej-rTb" secondAttribute="bottom" constant="8" id="IxV-Aj-Agw"/>
<constraint firstItem="yyn-IO-TkO" firstAttribute="trailing" secondItem="i5v-yD-weq" secondAttribute="trailing" id="JJ3-CQ-MYe"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="top" secondItem="WMR-Vn-IHF" secondAttribute="top" constant="20" symbolic="YES" id="Nav-P8-ewc"/>
<constraint firstItem="car-it-RsL" firstAttribute="leading" secondItem="xy3-2B-C0h" secondAttribute="leading" id="Ofe-x8-Iz6"/>
<constraint firstItem="yyn-IO-TkO" firstAttribute="width" secondItem="i5v-yD-weq" secondAttribute="width" id="Pbq-09-PEz"/>
<constraint firstAttribute="trailing" secondItem="xy3-2B-C0h" secondAttribute="trailing" constant="20" id="QaY-Yd-7ki"/>
<constraint firstAttribute="trailing" secondItem="bim-1a-xuh" secondAttribute="trailing" constant="20" id="Qgd-dL-t4L"/>
<constraint firstItem="XYx-UL-WbM" firstAttribute="top" secondItem="xy3-2B-C0h" secondAttribute="bottom" constant="3" id="S7k-zO-aLb"/>
<constraint firstItem="car-it-RsL" firstAttribute="width" secondItem="bim-1a-xuh" secondAttribute="width" id="Scq-gg-9Mp"/>
<constraint firstItem="bim-1a-xuh" firstAttribute="leading" secondItem="CTE-6h-rbf" secondAttribute="trailing" constant="8" symbolic="YES" id="V76-cY-GEg"/>
<constraint firstItem="car-it-RsL" firstAttribute="trailing" secondItem="XYx-UL-WbM" secondAttribute="trailing" id="YTL-Eq-h2J"/>
<constraint firstItem="X2i-rg-HDg" firstAttribute="top" secondItem="CTE-6h-rbf" secondAttribute="bottom" constant="8" id="b3A-aW-7fb"/>
<constraint firstItem="i5v-yD-weq" firstAttribute="top" secondItem="yyn-IO-TkO" secondAttribute="bottom" constant="8" id="dGT-5B-B1c"/>
<constraint firstItem="car-it-RsL" firstAttribute="leading" secondItem="MJr-Jz-5Cq" secondAttribute="leading" id="e2s-Um-zcp"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="leading" secondItem="WMR-Vn-IHF" secondAttribute="leading" constant="20" symbolic="YES" id="g0a-i4-KIf"/>
<constraint firstItem="car-it-RsL" firstAttribute="top" secondItem="XYx-UL-WbM" secondAttribute="bottom" constant="3" id="ol9-vF-CGP"/>
<constraint firstItem="MJr-Jz-5Cq" firstAttribute="top" secondItem="car-it-RsL" secondAttribute="bottom" constant="8" id="rTY-Fr-65b"/>
<constraint firstItem="CTE-6h-rbf" firstAttribute="width" secondItem="yyn-IO-TkO" secondAttribute="width" id="sb9-dg-qOh"/>
<constraint firstItem="car-it-RsL" firstAttribute="trailing" secondItem="xy3-2B-C0h" secondAttribute="trailing" id="wpN-fF-mXb"/>
<constraint firstItem="car-it-RsL" firstAttribute="trailing" secondItem="bim-1a-xuh" secondAttribute="trailing" id="wtJ-Bc-d9Z"/>
<constraint firstItem="car-it-RsL" firstAttribute="leading" secondItem="XYx-UL-WbM" secondAttribute="leading" id="yFH-4V-CiS"/>
</constraints>
<connections>
<outlet property="nextKeyView" destination="bim-1a-xuh" id="YxQ-sZ-TFh"/>
</connections>
</customView>
<customView id="o0X-1i-ZgL" userLabel="Detail">
<rect key="frame" x="0.0" y="0.0" width="509" height="321"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Dm8-Mj-s5f">
<rect key="frame" x="18" y="284" width="107" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Type:" id="dy9-JM-4d7">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="D5V-CV-BuE">
<rect key="frame" x="18" y="259" width="107" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Frames:" id="G4c-OI-avP">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="zEj-zS-uzh">
<rect key="frame" x="18" y="234" width="107" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Frame Duration:" id="5Wb-pc-8jV">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="aso-MD-Alm">
<rect key="frame" x="18" y="209" width="107" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Hot Spot:" id="dcq-3r-2DB">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="yz7-y5-TxE">
<rect key="frame" x="131" y="277" width="358" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="gKl-8J-X0X">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" title="OtherViews" id="j3S-Me-3x5"/>
</popUpButtonCell>
<connections>
<binding destination="tMj-cQ-hK0" name="selectedValue" keyPath="cursor.identifier" id="2aq-Lm-1Lm">
<dictionary key="options">
<string key="NSMultipleValuesPlaceholder">Unknown</string>
<string key="NSNotApplicablePlaceholder">Unknown</string>
<string key="NSNoSelectionPlaceholder">Unknown</string>
<string key="NSNullPlaceholder">Unknown</string>
<string key="NSValueTransformerName">MCCursorTypeValueTransformer</string>
</dictionary>
</binding>
<outlet property="nextKeyView" destination="rms-zC-s1M" id="yfu-3L-R4w"/>
</connections>
</popUpButton>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rms-zC-s1M">
<rect key="frame" x="131" y="254" width="358" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="1" drawsBackground="YES" id="tKY-dX-ibT">
<numberFormatter key="formatter" formatterBehavior="default10_4" positiveFormat="#" negativeFormat="#" usesGroupingSeparator="NO" groupingSize="0" minimumIntegerDigits="0" maximumIntegerDigits="42" minimumFractionDigits="0" maximumFractionDigits="0" id="JEt-qW-Py5">
<real key="roundingIncrement" value="0.0"/>
<real key="minimum" value="1"/>
<real key="maximum" value="24"/>
<metadata>
<bool key="localizesFormat" value="YES"/>
</metadata>
</numberFormatter>
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="tMj-cQ-hK0" name="value" keyPath="cursor.frameCount" id="E0q-ga-ftR"/>
<outlet property="nextKeyView" destination="VbK-WJ-M0L" id="y5I-kM-hNq"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VbK-WJ-M0L">
<rect key="frame" x="131" y="229" width="358" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="0.0" drawsBackground="YES" id="pqX-MB-QME">
<numberFormatter key="formatter" formatterBehavior="custom10_4" positiveFormat="#.################" negativeFormat="#.################" usesGroupingSeparator="NO" groupingSize="0" minimumIntegerDigits="0" maximumIntegerDigits="42" minimumFractionDigits="0" maximumFractionDigits="16" id="QTS-o7-aVO">
<real key="roundingIncrement" value="0.0"/>
<real key="minimum" value="0.0"/>
<metadata>
<bool key="localizesFormat" value="YES"/>
</metadata>
</numberFormatter>
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="tMj-cQ-hK0" name="value" keyPath="cursor.frameDuration" id="I6z-BZ-xhp"/>
<outlet property="nextKeyView" destination="Qcr-83-Tz0" id="gYj-Hj-Txi"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Qcr-83-Tz0">
<rect key="frame" x="131" y="204" width="358" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="{0,0}" drawsBackground="YES" id="BWu-hw-sDX">
<customFormatter key="formatter" id="hAv-1z-0Jg" customClass="MCPointFormatter"/>
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="tMj-cQ-hK0" name="value" keyPath="cursor.hotSpot" id="aFb-fI-aHw"/>
<outlet property="nextKeyView" destination="yz7-y5-TxE" id="Gtw-PH-Eo8"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="75v-aw-FbU">
<rect key="frame" x="143" y="98" width="24" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="1x" id="FZ3-qB-kDI">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Hoi-Pr-5wz">
<rect key="frame" x="199" y="98" width="24" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="2x" id="WI8-sV-4D6">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="CWo-oD-OZX">
<rect key="frame" x="255" y="98" width="24" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="5x" id="4fS-Q1-prn">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ryz-mP-wNx">
<rect key="frame" x="307" y="98" width="32" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="10x" id="8fp-Ws-ruA">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="j7v-U4-eMe" customClass="MMAnimatingImageView">
<rect key="frame" x="131" y="123" width="48" height="48"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="width" constant="48" id="MeC-cf-abQ"/>
<constraint firstAttribute="height" constant="48" id="VAO-nl-ZmQ"/>
</constraints>
<connections>
<outlet property="delegate" destination="tMj-cQ-hK0" id="YBU-cQ-gUX"/>
</connections>
</customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="ggE-Pd-aWo" customClass="MMAnimatingImageView">
<rect key="frame" x="187" y="123" width="48" height="48"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<connections>
<outlet property="delegate" destination="tMj-cQ-hK0" id="Q6h-vm-kaw"/>
</connections>
</customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="G3t-wd-E5Y" customClass="MMAnimatingImageView">
<rect key="frame" x="243" y="123" width="48" height="48"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<connections>
<outlet property="delegate" destination="tMj-cQ-hK0" id="VPL-GA-4fS"/>
</connections>
</customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="4hN-Nm-B7Z" customClass="MMAnimatingImageView">
<rect key="frame" x="299" y="123" width="48" height="48"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<connections>
<outlet property="delegate" destination="tMj-cQ-hK0" id="fp1-eX-JUN"/>
</connections>
</customView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="OAt-gN-EX5">
<rect key="frame" x="18" y="184" width="107" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Size:" id="FrC-7p-0Bq">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wdB-yr-r6Y">
<rect key="frame" x="131" y="179" width="358" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="{0,0}" drawsBackground="YES" id="OmM-g8-Kyd">
<customFormatter key="formatter" id="wEf-m3-oYM" customClass="MCSizeFormatter"/>
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="tMj-cQ-hK0" name="value" keyPath="cursor.size" id="dXp-5z-YR6"/>
<outlet property="nextKeyView" destination="yz7-y5-TxE" id="IBE-mt-pxg"/>
</connections>
</textField>
</subviews>
<constraints>
<constraint firstItem="CWo-oD-OZX" firstAttribute="top" secondItem="G3t-wd-E5Y" secondAttribute="bottom" constant="8" id="3wX-8h-O6z"/>
<constraint firstItem="D5V-CV-BuE" firstAttribute="top" secondItem="rms-zC-s1M" secondAttribute="top" id="43J-XT-GHl"/>
<constraint firstItem="Dm8-Mj-s5f" firstAttribute="top" secondItem="yz7-y5-TxE" secondAttribute="top" id="4iw-ff-qi7"/>
<constraint firstItem="aso-MD-Alm" firstAttribute="top" secondItem="zEj-zS-uzh" secondAttribute="bottom" constant="8" symbolic="YES" id="5Wt-dl-pef"/>
<constraint firstItem="rms-zC-s1M" firstAttribute="leading" secondItem="VbK-WJ-M0L" secondAttribute="leading" id="5dM-sY-h4p"/>
<constraint firstItem="j7v-U4-eMe" firstAttribute="leading" secondItem="wdB-yr-r6Y" secondAttribute="leading" id="7xA-ei-9JR"/>
<constraint firstItem="zEj-zS-uzh" firstAttribute="leading" secondItem="D5V-CV-BuE" secondAttribute="leading" id="8Cv-6e-Tzx"/>
<constraint firstItem="G3t-wd-E5Y" firstAttribute="height" secondItem="4hN-Nm-B7Z" secondAttribute="height" id="8qD-iY-MRu"/>
<constraint firstItem="G3t-wd-E5Y" firstAttribute="width" secondItem="ggE-Pd-aWo" secondAttribute="width" id="ASq-Gp-wuC"/>
<constraint firstItem="OAt-gN-EX5" firstAttribute="top" secondItem="wdB-yr-r6Y" secondAttribute="top" id="Adr-uG-x9t"/>
<constraint firstItem="4hN-Nm-B7Z" firstAttribute="leading" secondItem="G3t-wd-E5Y" secondAttribute="trailing" constant="8" id="AlK-6b-Sni"/>
<constraint firstItem="j7v-U4-eMe" firstAttribute="top" secondItem="wdB-yr-r6Y" secondAttribute="bottom" constant="8" id="BW4-UU-kQB"/>
<constraint firstItem="75v-aw-FbU" firstAttribute="centerX" secondItem="j7v-U4-eMe" secondAttribute="centerX" id="ClP-It-NEr"/>
<constraint firstItem="D5V-CV-BuE" firstAttribute="top" secondItem="Dm8-Mj-s5f" secondAttribute="bottom" constant="8" symbolic="YES" id="EWh-4Q-i3w"/>
<constraint firstItem="rms-zC-s1M" firstAttribute="leading" secondItem="D5V-CV-BuE" secondAttribute="trailing" constant="8" symbolic="YES" id="JaG-3Y-FgQ"/>
<constraint firstItem="Hoi-Pr-5wz" firstAttribute="centerX" secondItem="ggE-Pd-aWo" secondAttribute="centerX" id="Lm2-Ms-dVL"/>
<constraint firstItem="rms-zC-s1M" firstAttribute="trailing" secondItem="yz7-y5-TxE" secondAttribute="trailing" id="MKf-wc-NLL"/>
<constraint firstItem="G3t-wd-E5Y" firstAttribute="top" secondItem="ggE-Pd-aWo" secondAttribute="top" id="NM5-rE-34J"/>
<constraint firstItem="Qcr-83-Tz0" firstAttribute="leading" secondItem="aso-MD-Alm" secondAttribute="trailing" constant="8" symbolic="YES" id="NO1-Yp-z3e"/>
<constraint firstItem="G3t-wd-E5Y" firstAttribute="width" secondItem="j7v-U4-eMe" secondAttribute="width" id="NvM-wM-1NF"/>
<constraint firstItem="OAt-gN-EX5" firstAttribute="width" secondItem="aso-MD-Alm" secondAttribute="width" id="PX5-Da-w21"/>
<constraint firstItem="Dm8-Mj-s5f" firstAttribute="top" secondItem="o0X-1i-ZgL" secondAttribute="top" constant="20" symbolic="YES" id="R6W-ih-OYh"/>
<constraint firstItem="zEj-zS-uzh" firstAttribute="leading" secondItem="aso-MD-Alm" secondAttribute="leading" id="RsR-Ul-Ou2"/>
<constraint firstItem="D5V-CV-BuE" firstAttribute="leading" secondItem="Dm8-Mj-s5f" secondAttribute="leading" id="S08-SQ-GJR"/>
<constraint firstItem="Qcr-83-Tz0" firstAttribute="top" secondItem="aso-MD-Alm" secondAttribute="top" id="SxH-Ps-hpM"/>
<constraint firstItem="VbK-WJ-M0L" firstAttribute="leading" secondItem="zEj-zS-uzh" secondAttribute="trailing" constant="8" symbolic="YES" id="UXO-ZW-ccB"/>
<constraint firstItem="ggE-Pd-aWo" firstAttribute="leading" secondItem="j7v-U4-eMe" secondAttribute="trailing" constant="8" id="VHK-Y8-lMy"/>
<constraint firstItem="VbK-WJ-M0L" firstAttribute="trailing" secondItem="rms-zC-s1M" secondAttribute="trailing" id="Vxm-cc-Nuz"/>
<constraint firstItem="wdB-yr-r6Y" firstAttribute="leading" secondItem="OAt-gN-EX5" secondAttribute="trailing" constant="8" symbolic="YES" id="WLf-wT-t5d"/>
<constraint firstItem="zEj-zS-uzh" firstAttribute="top" secondItem="D5V-CV-BuE" secondAttribute="bottom" constant="8" symbolic="YES" id="X0Y-Zf-ilJ"/>
<constraint firstItem="wdB-yr-r6Y" firstAttribute="trailing" secondItem="Qcr-83-Tz0" secondAttribute="trailing" id="Yac-TY-Rux"/>
<constraint firstItem="75v-aw-FbU" firstAttribute="top" secondItem="j7v-U4-eMe" secondAttribute="bottom" constant="8" id="Yah-L4-Jlp"/>
<constraint firstItem="Dm8-Mj-s5f" firstAttribute="leading" secondItem="o0X-1i-ZgL" secondAttribute="leading" constant="20" symbolic="YES" id="ZQi-nH-fRj"/>
<constraint firstItem="CWo-oD-OZX" firstAttribute="centerX" secondItem="G3t-wd-E5Y" secondAttribute="centerX" id="ZcC-5o-S4M"/>
<constraint firstItem="G3t-wd-E5Y" firstAttribute="width" secondItem="4hN-Nm-B7Z" secondAttribute="width" id="bMf-aA-2io"/>
<constraint firstItem="Qcr-83-Tz0" firstAttribute="trailing" secondItem="VbK-WJ-M0L" secondAttribute="trailing" id="e7u-an-cyO"/>
<constraint firstItem="Ryz-mP-wNx" firstAttribute="top" secondItem="4hN-Nm-B7Z" secondAttribute="bottom" constant="8" id="eDV-Li-crv"/>
<constraint firstItem="yz7-y5-TxE" firstAttribute="leading" secondItem="Dm8-Mj-s5f" secondAttribute="trailing" constant="8" symbolic="YES" id="etw-9O-zNS"/>
<constraint firstItem="VbK-WJ-M0L" firstAttribute="leading" secondItem="Qcr-83-Tz0" secondAttribute="leading" id="gnA-Qx-Vmj"/>
<constraint firstItem="G3t-wd-E5Y" firstAttribute="height" secondItem="ggE-Pd-aWo" secondAttribute="height" id="huK-Kq-0Iu"/>
<constraint firstItem="G3t-wd-E5Y" firstAttribute="leading" secondItem="ggE-Pd-aWo" secondAttribute="trailing" constant="8" id="i75-6i-VPd"/>
<constraint firstItem="OAt-gN-EX5" firstAttribute="top" secondItem="aso-MD-Alm" secondAttribute="bottom" constant="8" id="itU-V0-MaU"/>
<constraint firstItem="Ryz-mP-wNx" firstAttribute="centerX" secondItem="4hN-Nm-B7Z" secondAttribute="centerX" id="jGh-SC-Nxg"/>
<constraint firstItem="zEj-zS-uzh" firstAttribute="top" secondItem="VbK-WJ-M0L" secondAttribute="top" id="k7D-La-IeE"/>
<constraint firstItem="wdB-yr-r6Y" firstAttribute="top" secondItem="Qcr-83-Tz0" secondAttribute="bottom" constant="3" id="kIE-fx-9LE"/>
<constraint firstItem="G3t-wd-E5Y" firstAttribute="height" secondItem="j7v-U4-eMe" secondAttribute="height" id="kyf-78-kT0"/>
<constraint firstItem="G3t-wd-E5Y" firstAttribute="top" secondItem="j7v-U4-eMe" secondAttribute="top" id="lhV-oy-6Mm"/>
<constraint firstItem="OAt-gN-EX5" firstAttribute="leading" secondItem="aso-MD-Alm" secondAttribute="leading" id="lp9-nD-Nnz"/>
<constraint firstItem="wdB-yr-r6Y" firstAttribute="width" secondItem="Qcr-83-Tz0" secondAttribute="width" id="lyT-KO-eXf"/>
<constraint firstItem="yz7-y5-TxE" firstAttribute="leading" secondItem="rms-zC-s1M" secondAttribute="leading" id="thH-qo-cIr"/>
<constraint firstItem="G3t-wd-E5Y" firstAttribute="top" secondItem="4hN-Nm-B7Z" secondAttribute="top" id="tvs-VW-0YR"/>
<constraint firstAttribute="trailing" secondItem="yz7-y5-TxE" secondAttribute="trailing" constant="20" symbolic="YES" id="wma-6s-J2b"/>
<constraint firstItem="Hoi-Pr-5wz" firstAttribute="top" secondItem="ggE-Pd-aWo" secondAttribute="bottom" constant="8" id="wr2-0t-CVH"/>
</constraints>
<connections>
<outlet property="nextKeyView" destination="yz7-y5-TxE" id="WHy-Vl-LGY"/>
</connections>
</customView>
</objects>
<resources>
<image name="NSAddTemplate" width="8" height="8"/>
<image name="NSRemoveTemplate" width="8" height="8"/>
</resources>
</document>
+223
View File
@@ -0,0 +1,223 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment defaultVersion="1080" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="MCLibraryWindowController">
<connections>
<outlet property="appliedAccessory" destination="3Ui-b0-Yod" id="2Ik-Bo-djE"/>
<outlet property="libraryViewController" destination="zL4-Ay-t4Q" id="DE1-rb-MWQ"/>
<outlet property="window" destination="1" id="3"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<window title="Mousecape" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" wantsToBeColor="NO" frameAutosaveName="LibraryWindow" animationBehavior="default" id="1">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="196" y="240" width="711" height="311"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1418"/>
<value key="minSize" type="size" width="502" height="310"/>
<view key="contentView" id="2">
<rect key="frame" x="0.0" y="0.0" width="711" height="311"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView canDrawConcurrently="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="29" horizontalPageScroll="10" verticalLineScroll="29" verticalPageScroll="10" translatesAutoresizingMaskIntoConstraints="NO" id="2Io-MC-n6O" customClass="BTRScrollView">
<rect key="frame" x="0.0" y="0.0" width="711" height="311"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" copiesOnScroll="NO" id="VhH-tn-4Sf" customClass="BTRClipView">
<rect key="frame" x="0.0" y="0.0" width="711" height="311"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" rowSizeStyle="automatic" viewBased="YES" id="dPn-85-uPK">
<rect key="frame" x="0.0" y="0.0" width="711" height="311"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="12"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="708" minWidth="40" maxWidth="9999" id="CBK-sD-upn">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="bXC-ob-CUQ">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
<prototypeCellViews>
<tableCellView id="syZ-Eq-Lt2" customClass="MCCapeCellView">
<rect key="frame" x="1" y="6" width="708" height="64"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="Hfe-RO-hVE">
<rect key="frame" x="18" y="47" width="99" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="0kt-g0-cQb">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="syZ-Eq-Lt2" name="value" keyPath="objectValue.name" id="YHc-x9-wXk"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bEa-BS-ghQ">
<rect key="frame" x="117" y="47" width="48" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Subtitle" id="NXa-Ze-OX2">
<font key="font" metaFont="smallSystemBold"/>
<color key="textColor" name="headerColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="syZ-Eq-Lt2" name="value" keyPath="objectValue.author" id="D3x-S0-YIW"/>
</connections>
</textField>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="jdV-zx-iTs">
<rect key="frame" x="634" y="44" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="applied" id="bwh-k2-aAS"/>
</imageView>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="QMa-EX-Son">
<rect key="frame" x="658" y="43" width="30" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="HD" id="LsJ-S8-jwy"/>
<connections>
<binding destination="syZ-Eq-Lt2" name="value" keyPath="objectValue.hiDPI" id="LcB-QZ-MhG">
<dictionary key="options">
<string key="NSValueTransformerName">MCHDValueTransformer</string>
</dictionary>
</binding>
</connections>
</imageView>
</subviews>
<constraints>
<constraint firstItem="Hfe-RO-hVE" firstAttribute="leading" secondItem="syZ-Eq-Lt2" secondAttribute="leading" constant="20" symbolic="YES" id="OHp-3c-ujO"/>
<constraint firstItem="QMa-EX-Son" firstAttribute="leading" secondItem="jdV-zx-iTs" secondAttribute="trailing" constant="8" symbolic="YES" id="QfE-A7-Oc8"/>
<constraint firstItem="bEa-BS-ghQ" firstAttribute="leading" secondItem="Hfe-RO-hVE" secondAttribute="trailing" constant="4" id="WVM-Wd-XXI"/>
<constraint firstItem="jdV-zx-iTs" firstAttribute="centerY" secondItem="QMa-EX-Son" secondAttribute="centerY" id="YLI-IS-v1N"/>
<constraint firstItem="bEa-BS-ghQ" firstAttribute="baseline" secondItem="Hfe-RO-hVE" secondAttribute="baseline" id="bCc-gQ-FVG"/>
<constraint firstAttribute="trailing" secondItem="QMa-EX-Son" secondAttribute="trailing" constant="20" symbolic="YES" id="oL8-Zy-vvE"/>
<constraint firstItem="QMa-EX-Son" firstAttribute="top" secondItem="syZ-Eq-Lt2" secondAttribute="top" constant="3" id="oPR-SR-Gh8"/>
<constraint firstItem="Hfe-RO-hVE" firstAttribute="top" secondItem="syZ-Eq-Lt2" secondAttribute="top" id="wWd-7q-n1a"/>
</constraints>
<connections>
<outlet property="appliedImageView" destination="jdV-zx-iTs" id="4DM-pV-X1T"/>
<outlet property="subtitleField" destination="bEa-BS-ghQ" id="yeA-RV-Aoi"/>
<outlet property="textField" destination="Hfe-RO-hVE" id="LWw-Ls-hnr"/>
<outlet property="titleField" destination="Hfe-RO-hVE" id="y7O-VO-62y"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
<connections>
<outlet property="dataSource" destination="zL4-Ay-t4Q" id="0iM-HK-P70"/>
<outlet property="delegate" destination="zL4-Ay-t4Q" id="riV-4x-e3X"/>
<outlet property="menu" destination="zpf-M9-Nd1" id="lfG-VA-TTS"/>
</connections>
</tableView>
</subviews>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="uK0-YP-77b">
<rect key="frame" x="1" y="1" width="0.0" height="16"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="q1a-eU-6AV">
<rect key="frame" x="-15" y="17" width="16" height="0.0"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="2Io-MC-n6O" secondAttribute="bottom" id="Cbd-gK-nbr"/>
<constraint firstItem="2Io-MC-n6O" firstAttribute="top" secondItem="2" secondAttribute="top" id="GZN-yG-wKe"/>
<constraint firstAttribute="trailing" secondItem="2Io-MC-n6O" secondAttribute="trailing" id="Nej-8C-Hrd"/>
<constraint firstItem="2Io-MC-n6O" firstAttribute="leading" secondItem="2" secondAttribute="leading" id="chC-8B-nJc"/>
</constraints>
</view>
<connections>
<outlet property="delegate" destination="-2" id="4"/>
</connections>
</window>
<viewController title="Library" id="zL4-Ay-t4Q" customClass="MCLibraryViewController">
<connections>
<outlet property="contextMenu" destination="zpf-M9-Nd1" id="jgh-ez-9dF"/>
<outlet property="tableView" destination="dPn-85-uPK" id="Gbg-WA-ju6"/>
<outlet property="view" destination="2" id="zf4-7d-uPj"/>
</connections>
</viewController>
<menu id="zpf-M9-Nd1">
<items>
<menuItem title="Apply" id="aI1-E0-bnW">
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
<connections>
<action selector="applyAction:" target="zL4-Ay-t4Q" id="4KV-AP-8YO"/>
</connections>
</menuItem>
<menuItem title="Edit" tag="1" keyEquivalent="e" id="HJc-SX-JjZ">
<connections>
<action selector="editAction:" target="zL4-Ay-t4Q" id="R94-y0-i5l"/>
</connections>
</menuItem>
<menuItem title="Duplicate" tag="2" keyEquivalent="S" id="PhG-Ll-nqz">
<connections>
<action selector="duplicateAction:" target="zL4-Ay-t4Q" id="dYH-lp-gER"/>
</connections>
</menuItem>
<menuItem title="Remove" tag="3" id="Aig-wl-ivn">
<string key="keyEquivalent" base64-UTF8="YES">
CA
</string>
<connections>
<action selector="removeAction:" target="zL4-Ay-t4Q" id="WYv-bz-sLl"/>
</connections>
</menuItem>
</items>
</menu>
<customView id="3Ui-b0-Yod" userLabel="Accessory">
<rect key="frame" x="0.0" y="0.0" width="251" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="cSP-XN-7we">
<rect key="frame" x="-2" y="3" width="245" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" controlSize="small" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="right" title="Applied Cursor: None" usesSingleLineMode="YES" id="vZ3-2R-psO">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="backgroundStyle">
<integer key="value" value="2"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</textFieldCell>
<connections>
<binding destination="zL4-Ay-t4Q" name="value" keyPath="libraryController.appliedCape.name" id="tSr-qw-vw1">
<dictionary key="options">
<string key="NSValueTransformerName">MCAppliedCapeValueTransformer</string>
</dictionary>
</binding>
</connections>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="cSP-XN-7we" secondAttribute="trailing" constant="10" id="OsL-1s-qgU"/>
<constraint firstItem="cSP-XN-7we" firstAttribute="centerY" secondItem="3Ui-b0-Yod" secondAttribute="centerY" id="U7A-WI-2JG"/>
<constraint firstItem="cSP-XN-7we" firstAttribute="leading" secondItem="3Ui-b0-Yod" secondAttribute="leading" id="eoA-bD-pz5"/>
</constraints>
</customView>
</objects>
<resources>
<image name="HD" width="30" height="18"/>
<image name="applied" width="16" height="16"/>
</resources>
</document>
+412
View File
@@ -0,0 +1,412 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment defaultVersion="1080" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="Mousecape" id="56">
<menu key="submenu" title="Mousecape" systemMenu="apple" id="57">
<items>
<menuItem title="About Mousecape" id="58">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="236">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Preferences…" keyEquivalent="," id="129"/>
<menuItem title="Check for Updates..." id="igk-i0-oH0">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Install Helper Tool" id="Ui2-VN-tbP">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleInstall:" target="494" id="Rfq-DA-Ni8"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="143">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Services" id="131">
<menu key="submenu" title="Services" systemMenu="services" id="130"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide Mousecape" keyEquivalent="h" id="134">
<connections>
<action selector="hide:" target="-1" id="367"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="145">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="368"/>
</connections>
</menuItem>
<menuItem title="Show All" id="150">
<connections>
<action selector="unhideAllApplications:" target="-1" id="370"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit Mousecape" keyEquivalent="q" id="136">
<connections>
<action selector="terminate:" target="-3" id="449"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="83">
<menu key="submenu" title="File" id="81">
<items>
<menuItem title="New Cape" keyEquivalent="n" id="82">
<connections>
<action selector="newDocument:" target="-1" id="I3c-Gd-Cqc"/>
</connections>
</menuItem>
<menuItem title="Import Cape" keyEquivalent="o" id="kdx-d9-Lek">
<connections>
<action selector="openDocument:" target="-1" id="2Qd-t2-zEv"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="79">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Close" keyEquivalent="w" id="73">
<connections>
<action selector="performClose:" target="-1" id="193"/>
</connections>
</menuItem>
<menuItem title="Save…" keyEquivalent="s" id="75">
<connections>
<action selector="saveDocument:" target="-1" id="362"/>
</connections>
</menuItem>
<menuItem title="Revert to Saved" id="112">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="revertDocumentToSaved:" target="-1" id="364"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="217">
<menu key="submenu" title="Edit" id="205">
<items>
<menuItem title="Undo" keyEquivalent="z" id="207">
<connections>
<action selector="undo:" target="-1" id="223"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="215">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="redo:" target="-1" id="231"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="206">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Cut" keyEquivalent="x" id="199">
<connections>
<action selector="cut:" target="-1" id="228"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="197">
<connections>
<action selector="copy:" target="-1" id="224"/>
</connections>
</menuItem>
<menuItem title="Paste" keyEquivalent="v" id="203">
<connections>
<action selector="paste:" target="-1" id="226"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="485">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="-1" id="486"/>
</connections>
</menuItem>
<menuItem title="Delete" id="202">
<connections>
<action selector="delete:" target="-1" id="235"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="198">
<connections>
<action selector="selectAll:" target="-1" id="232"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="214">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Find" id="218">
<menu key="submenu" title="Find" id="220">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
<connections>
<action selector="performFindPanelAction:" target="-1" id="241"/>
</connections>
</menuItem>
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="534">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="535"/>
</connections>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="208">
<connections>
<action selector="performFindPanelAction:" target="-1" id="487"/>
</connections>
</menuItem>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="488"/>
</connections>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" id="221">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="489"/>
</connections>
</menuItem>
<menuItem title="Jump to Selection" keyEquivalent="j" id="210">
<connections>
<action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="216">
<menu key="submenu" title="Spelling and Grammar" id="200">
<items>
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="204">
<connections>
<action selector="showGuessPanel:" target="-1" id="230"/>
</connections>
</menuItem>
<menuItem title="Check Document Now" keyEquivalent=";" id="201">
<connections>
<action selector="checkSpelling:" target="-1" id="225"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="453"/>
<menuItem title="Check Spelling While Typing" id="219">
<connections>
<action selector="toggleContinuousSpellChecking:" target="-1" id="222"/>
</connections>
</menuItem>
<menuItem title="Check Grammar With Spelling" id="346">
<connections>
<action selector="toggleGrammarChecking:" target="-1" id="347"/>
</connections>
</menuItem>
<menuItem title="Correct Spelling Automatically" id="454">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="456"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="348">
<menu key="submenu" title="Substitutions" id="349">
<items>
<menuItem title="Show Substitutions" id="457">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="458"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="459"/>
<menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350">
<connections>
<action selector="toggleSmartInsertDelete:" target="-1" id="355"/>
</connections>
</menuItem>
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351">
<connections>
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="356"/>
</connections>
</menuItem>
<menuItem title="Smart Dashes" id="460">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="461"/>
</connections>
</menuItem>
<menuItem title="Smart Links" tag="3" keyEquivalent="G" id="354">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="toggleAutomaticLinkDetection:" target="-1" id="357"/>
</connections>
</menuItem>
<menuItem title="Text Replacement" id="462">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticTextReplacement:" target="-1" id="463"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Transformations" id="450">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformations" id="451">
<items>
<menuItem title="Make Upper Case" id="452">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="uppercaseWord:" target="-1" id="464"/>
</connections>
</menuItem>
<menuItem title="Make Lower Case" id="465">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowercaseWord:" target="-1" id="468"/>
</connections>
</menuItem>
<menuItem title="Capitalize" id="466">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="capitalizeWord:" target="-1" id="467"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="211">
<menu key="submenu" title="Speech" id="212">
<items>
<menuItem title="Start Speaking" id="196">
<connections>
<action selector="startSpeaking:" target="-1" id="233"/>
</connections>
</menuItem>
<menuItem title="Stop Speaking" id="195">
<connections>
<action selector="stopSpeaking:" target="-1" id="227"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Capes" id="g8O-f8-aKi">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Capes" id="ttR-pS-Pk1">
<items>
<menuItem title="Apply Cape" id="ieJ-T1-eH7">
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
<connections>
<action selector="applyCape:" target="-1" id="vf2-1W-mzE"/>
</connections>
</menuItem>
<menuItem title="Edit Cape" keyEquivalent="e" id="5qb-Dw-38q">
<connections>
<action selector="editCape:" target="-1" id="iz5-Ek-fyU"/>
</connections>
</menuItem>
<menuItem title="Remove Cape" id="LHh-1u-bK8">
<string key="keyEquivalent" base64-UTF8="YES">
CA
</string>
<connections>
<action selector="removeCape:" target="-1" id="1E1-e1-eeH"/>
</connections>
</menuItem>
<menuItem title="Duplicate Cape" keyEquivalent="S" id="d9b-6w-ubr">
<connections>
<action selector="duplicateCape:" target="-1" id="pOn-FS-ePg"/>
</connections>
</menuItem>
<menuItem title="Check for Updates" hidden="YES" keyEquivalent="u" id="XTi-86-ese">
<connections>
<action selector="checkCape:" target="-1" id="yBL-WC-dbi"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="EOT-Rk-oU3"/>
<menuItem title="Restore Defaults" keyEquivalent="r" id="uCE-YB-8VL">
<connections>
<action selector="restoreCape:" target="494" id="2ve-Ez-ktd"/>
</connections>
</menuItem>
<menuItem title="Import MightyMouse" keyEquivalent="i" id="l3B-n8-21Z">
<connections>
<action selector="convertCape:" target="494" id="vs2-8F-92y"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="19">
<menu key="submenu" title="Window" systemMenu="window" id="24">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="23">
<connections>
<action selector="performMiniaturize:" target="-1" id="37"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="239">
<connections>
<action selector="performZoom:" target="-1" id="240"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="92">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Bring All to Front" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="490">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="Mousecape Help" keyEquivalent="?" id="492">
<connections>
<action selector="showHelp:" target="-1" id="493"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<customObject id="494" customClass="MCAppDelegate">
<connections>
<outlet property="toggleHelperItem" destination="Ui2-VN-tbP" id="31d-Xd-wNX"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager"/>
</objects>
</document>
@@ -0,0 +1,58 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,18 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "HDTemplate.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "HDTemplate@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,18 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "SDTemplate.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "SDTemplate@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

@@ -0,0 +1,18 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "applied.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "applied@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

@@ -0,0 +1,18 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "dz.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "dz@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

+15
View File
@@ -0,0 +1,15 @@
//
// MCAppDelegate.h
// Mousecape
//
// Created by Alex Zielenski on 2/1/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MCLibraryWindowController.h"
@interface MCAppDelegate : NSObject <NSApplicationDelegate>
@property (assign) IBOutlet NSMenuItem *toggleHelperItem;
@property (strong) MCLibraryWindowController *libraryWindowController;
- (IBAction)toggleInstall:(NSMenuItem *)sender;
@end
+158
View File
@@ -0,0 +1,158 @@
//
// MCAppDelegate.m
// Mousecape
//
// Created by Alex Zielenski on 2/1/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCAppDelegate.h"
#import <Security/Security.h>
#import <ServiceManagement/ServiceManagement.h>
#import "MCCursorLibrary.h"
#import "create.h"
static AuthorizationRef obtainRights();
@interface MCAppDelegate ()
- (void)configureHelperToolMenuItem;
@end
@implementation MCAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[self configureHelperToolMenuItem];
self.libraryWindowController = [[MCLibraryWindowController alloc] initWithWindowNibName:@"Library"];
[self.libraryWindowController showWindow:self];
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag {
[self.libraryWindowController showWindow:sender];
return YES;
}
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
BOOL open = [filename.pathExtension.lowercaseString isEqualToString:@"cape"];
NSURL *url = [NSURL fileURLWithPath:filename];
if (open) {
[self.libraryWindowController.libraryViewController.libraryController importCapeAtURL:url];
}
return open;
}
- (void)configureHelperToolMenuItem {
NSString *mouseCloakDest = @"/usr/local/bin/mousecloak";
NSString *agentDest = [@"/Library/LaunchAgents" stringByAppendingPathComponent: @"com.alexzielenski.mousecloak.listener.plist"];
NSFileManager *manager = [NSFileManager defaultManager];
[self.toggleHelperItem setTag: ([manager fileExistsAtPath:mouseCloakDest] && [manager fileExistsAtPath:agentDest])];
[self.toggleHelperItem setTitle:self.toggleHelperItem.tag ? @"Uninstall Helper Tool" : @"Ininstall Helper Tool"];
}
- (IBAction)toggleInstall:(NSMenuItem *)sender {
AuthorizationRef authRef = obtainRights();
if (authRef == NULL) {
NSLog(@"Failed to obtain authorization right.");
return;
}
NSString *mouseCloakDest = @"/usr/local/bin/mousecloak";
NSString *mouseCloakPath = [[NSBundle mainBundle] pathForAuxiliaryExecutable:@"mousecloak"];
NSString *agentDest = [@"/Library/LaunchAgents" stringByAppendingPathComponent: @"com.alexzielenski.mousecloak.listener.plist"];
NSString *agentPath = [NSTemporaryDirectory() stringByAppendingPathComponent: agentDest.lastPathComponent];
NSString *loadCommand = [NSString stringWithFormat:@"launchctl load %s", agentDest.UTF8String];
NSString *unloadCommand = [NSString stringWithFormat:@"launchctl unload %s", agentDest.UTF8String];
if (self.toggleHelperItem.tag) { // Uninstall
system(unloadCommand.UTF8String);
NSDictionary *removeTools = @{ @"Label": @"com.alexzielenski.mousecloak.remove", @"ProgramArguments": @[ @"/bin/rm", mouseCloakDest, agentDest ], @"RunAtLoad": @YES };
SMJobSubmit(kSMDomainSystemLaunchd, (__bridge CFDictionaryRef)removeTools, authRef, NULL);
SMJobRemove(kSMDomainSystemLaunchd, (__bridge CFStringRef)removeTools[@"Label"], authRef, true, NULL);
} else {
NSDictionary *copyTool = @{ @"Label": @"com.alexzielenski.mousecloak.install", @"ProgramArguments": @[ @"/bin/ln", @"-f", @"-s", mouseCloakPath, mouseCloakDest ], @"RunAtLoad": @YES };
SMJobSubmit(kSMDomainSystemLaunchd, (__bridge CFDictionaryRef)copyTool, authRef, NULL);
SMJobRemove(kSMDomainSystemLaunchd, (__bridge CFStringRef)copyTool[@"Label"], authRef, true, NULL);
NSDictionary *launchAgent = @{ @"Label": @"com.alexzielenski.mousecloak.listener", @"ProgramArguments": @[ mouseCloakDest, @"--listen" ], @"LimitLoadToSessionType": @[ @"Aqua" ], @"RunAtLoad": @YES, @"KeepAlive": @YES };
[launchAgent writeToFile:agentPath atomically:NO];
NSDictionary *copyJob = @{ @"Label": @"com.alexzielenski.mousecloak.install2", @"ProgramArguments": @[ @"/bin/cp", @"-f", agentPath, agentDest ], @"RunAtLoad": @YES };
SMJobSubmit(kSMDomainSystemLaunchd, (__bridge CFDictionaryRef)copyJob, authRef, NULL);
SMJobRemove(kSMDomainSystemLaunchd, (__bridge CFStringRef)copyJob[@"Label"], authRef, true, NULL);
system(loadCommand.UTF8String);
}
AuthorizationFree(authRef, kAuthorizationFlagDestroyRights);
[self configureHelperToolMenuItem];
}
#pragma mark - Interface Actions
- (IBAction)restoreCape:(id)sender {
[self.libraryWindowController.libraryViewController.libraryController restoreCape];
}
- (IBAction)convertCape:(id)sender {
NSOpenPanel *panel = [NSOpenPanel openPanel];
panel.allowedFileTypes = @[ @"MightyMouse" ];
panel.title = @"Import";
panel.message = @"Choose a MightyMouse file to import";
panel.prompt = @"Import";
if ([panel runModal] == NSFileHandlingPanelOKButton) {
NSString *name = panel.URL.lastPathComponent.stringByDeletingPathExtension;
NSDictionary *metadata = @{
@"name": name,
@"version": @1.0,
@"author": @"Unknown",
@"identifier": [NSString stringWithFormat:@"local.import.%@.%f", name, [NSDate timeIntervalSinceReferenceDate]]
};
NSDictionary *cape = createCapeFromMightyMouse([NSDictionary dictionaryWithContentsOfURL:panel.URL], metadata);
MCCursorLibrary *library = [MCCursorLibrary cursorLibraryWithDictionary:cape];
[self.libraryWindowController.libraryViewController.libraryController importCape:library];
}
}
- (IBAction)newDocument:(id)sender {
[self.libraryWindowController.libraryViewController.libraryController importCape:[[MCCursorLibrary alloc] init]];
}
- (IBAction)openDocument:(id)sender {
NSOpenPanel *panel = [NSOpenPanel openPanel];
panel.allowedFileTypes = @[ @"cape" ];
panel.title = @"Import";
panel.message = @"Choose a Mousecape to import";
panel.prompt = @"Import";
if ([panel runModal] == NSFileHandlingPanelOKButton) {
[self.libraryWindowController.libraryViewController.libraryController importCapeAtURL:panel.URL];
}
}
@end
static AuthorizationRef obtainRights() {
AuthorizationRef authRef = NULL;
// Creating auth item to bless helper tool and install framework
AuthorizationItem authItem = {kSMRightBlessPrivilegedHelper, 0, NULL, 0};
AuthorizationItem modify = {kSMRightModifySystemDaemons, 0, NULL, 0};
AuthorizationItem items[2] = { authItem, modify };
// Creating a set of authorization rights
AuthorizationRights authRights = {2, items};
// Specifying authorization options for authorization
AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights;
// Open dialog and prompt user for password
OSStatus status = AuthorizationCreate(&authRights, kAuthorizationEmptyEnvironment, flags, &authRef);
if (status == errAuthorizationSuccess)
return authRef;
return NULL;
}
+80
View File
@@ -0,0 +1,80 @@
<?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>en</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>cape</string>
</array>
<key>CFBundleTypeName</key>
<string>Mouse Cape</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.alexzielenski.mousecape.cape</string>
</array>
<key>LSTypeIsPackage</key>
<integer>0</integer>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.alexzielenski.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.0.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>967</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2014 Alex Zielenski. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.xml</string>
<string>com.apple.property-list</string>
</array>
<key>UTTypeDescription</key>
<string>Mouse Cape</string>
<key>UTTypeIdentifier</key>
<string>com.alexzielenski.mousecape.cape</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>com.apple.ostype</key>
<array>
<string>CAPE</string>
</array>
<key>public.filename-extension</key>
<array>
<string>cape</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>
+11
View File
@@ -0,0 +1,11 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#import "MCDefs.h"
#import "MCPrefs.h"
#endif
+29
View File
@@ -0,0 +1,29 @@
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
{\colortbl;\red255\green255\blue255;}
\paperw9840\paperh8400
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
\f0\b\fs24 \cf0 Engineering:
\b0 \
Some people\
\
\b Human Interface Design:
\b0 \
Some other people\
\
\b Testing:
\b0 \
Hopefully not nobody\
\
\b Documentation:
\b0 \
Whoever\
\
\b With special thanks to:
\b0 \
Mom\
}
+48
View File
@@ -0,0 +1,48 @@
/*
Created by Jonathan Willing on 8/28/13.
Copyright (c) 2013, ButterKit. All rights reserved.
Licensed under the MIT license <http://opensource.org/licenses/MIT>
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>
// A NSClipView subclass with a buttery -scrollToRect: animation.
@interface BTRClipView : NSClipView
// Calls -scrollRectToVisible:, optionally animated.
//
// If animated, the animation will be performed with an ease-out timing function.
// Any calls to this method while an animation is still in flight will update the
// current animation and adjust the deceleration as needed.
//
// Any input to the scroll view that would cause an adjustment to the bounds (such as
// a trackpad scroll) will cancel any animations in progress.
- (BOOL)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated;
// Calls -scrollRectToVisible:animated: with an optional completion block. The scrolled
// completion parameter is whether any scrolling was performed.
- (BOOL)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated completion:(void (^)(BOOL scrolled))completion;
// Any time the origin changes with an animation as discussed above, the deceleration
// rate will be used to create an ease-out animation.
//
// Values should range from (0, 1]. Smaller deceleration rates will provide
// generally fast animations, whereas larger rates will create lengthy animations.
//
// Defaults to 0.78.
@property (nonatomic, assign) CGFloat decelerationRate;
@end
+221
View File
@@ -0,0 +1,221 @@
/*
Created by Jonathan Willing on 8/28/13.
Copyright (c) 2013, ButterKit. All rights reserved.
Licensed under the MIT license <http://opensource.org/licenses/MIT>
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 "BTRClipView.h"
// The default deceleration constant used for the ease-out curve in the animation.
static const CGFloat BTRClipViewDecelerationRate = 0.78;
@interface BTRClipView ()
// Used to drive the animation through repeated callbacks.
// A display link is used instead of a timer so that we don't get dropped frames and tearing.
// Lazily created when needed, released in dealloc. Stopped automatically when scrolling is not occurring.
@property (nonatomic, assign) CVDisplayLinkRef displayLink;
// Used to determine whether to animate in `scrollToPoint:`.
@property (nonatomic, assign) BOOL shouldAnimateOriginChange;
// Used when animating with the display link as the final origin for the animation.
@property (nonatomic, assign) CGPoint destinationOrigin;
// The scroll view which has this clip view set as the content view.
@property (nonatomic, assign) NSScrollView *containingScrollView;
// The optional completion block which is called at the end of the scroll animation.
@property (nonatomic, copy) void (^scrollCompletion)(BOOL success);
@end
@implementation BTRClipView
- (instancetype)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self == nil) return nil;
self.wantsLayer = YES;
self.decelerationRate = BTRClipViewDecelerationRate;
return self;
}
- (void)dealloc {
CVDisplayLinkRelease(_displayLink);
[NSNotificationCenter.defaultCenter removeObserver:self];
}
#pragma mark View Heirarchy
- (void)viewWillMoveToWindow:(NSWindow *)newWindow {
if (self.window != nil) {
[NSNotificationCenter.defaultCenter removeObserver:self name:NSWindowDidChangeScreenNotification object:self.window];
}
[super viewWillMoveToWindow:newWindow];
if (newWindow != nil) {
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(updateCVDisplay:) name:NSWindowDidChangeScreenNotification object:newWindow];
}
}
#pragma mark Display link
static CVReturn BTRScrollingCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) {
@autoreleasepool {
BTRClipView *clipView = (__bridge id)displayLinkContext;
dispatch_async(dispatch_get_main_queue(), ^{
[clipView updateOrigin];
});
}
return kCVReturnSuccess;
}
- (CVDisplayLinkRef)displayLink {
if (_displayLink == NULL) {
CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
CVDisplayLinkSetOutputCallback(_displayLink, &BTRScrollingCallback, (__bridge void *)self);
[self updateCVDisplay:nil];
}
return _displayLink;
}
- (void)updateCVDisplay:(NSNotification *)note {
NSScreen *screen = self.window.screen;
if (screen == nil) {
NSDictionary *screenDictionary = NSScreen.mainScreen.deviceDescription;
NSNumber *screenID = screenDictionary[@"NSScreenNumber"];
CGDirectDisplayID displayID = screenID.unsignedIntValue;
CVDisplayLinkSetCurrentCGDisplay(_displayLink, displayID);
} else {
CVDisplayLinkSetCurrentCGDisplay(_displayLink, kCGDirectMainDisplay);
}
}
#pragma mark Scrolling
- (void)scrollToPoint:(NSPoint)newOrigin {
// We should only attempt to animate ourselves if we know this point we're scrolling to
// was the point determined from a -scrollToRect:animated: call.
if (self.shouldAnimateOriginChange) {
self.shouldAnimateOriginChange = NO;
self.destinationOrigin = newOrigin;
[self beginScrolling];
} else {
// Otherwise, we stop any scrolling that is currently occurring (if needed) and let
// super's implementation handle a normal scroll.
[self endScrolling];
[super scrollToPoint:newOrigin];
}
}
- (BOOL)scrollRectToVisible:(NSRect)aRect animated:(BOOL)animated {
self.shouldAnimateOriginChange = animated;
return [super scrollRectToVisible:aRect];
}
- (BOOL)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated completion:(void (^)(BOOL sucess))completion {
self.scrollCompletion = completion;
BOOL success = [self scrollRectToVisible:rect animated:animated];
if (!animated || !success) {
[self handleCompletionIfNeededWithSuccess:success];
}
return success;
}
- (void)beginScrolling {
if (CVDisplayLinkIsRunning(self.displayLink)) {
return;
}
CVDisplayLinkStart(self.displayLink);
}
- (void)endScrolling {
if (!CVDisplayLinkIsRunning(self.displayLink)) {
return;
}
CVDisplayLinkStop(self.displayLink);
}
// Sanitize the deceleration rate to [0, 1] so nothing unexpected happens.
- (void)setDecelerationRate:(CGFloat)decelerationRate {
if (decelerationRate > 1) {
decelerationRate = 1;
}
else if (decelerationRate < 0) {
decelerationRate = 0;
}
_decelerationRate = decelerationRate;
}
- (NSScrollView *)containingScrollView {
if (_containingScrollView == nil) {
_containingScrollView = self.enclosingScrollView;
if (_containingScrollView == nil && [self.superview isKindOfClass:NSScrollView.class]) {
_containingScrollView = (NSScrollView *)self.superview;
}
}
return _containingScrollView;
}
- (void)updateOrigin {
if (self.window == nil) {
[self endScrolling];
return;
}
CGPoint o = self.bounds.origin;
CGPoint lastOrigin = o;
CGFloat deceleration = self.decelerationRate;
// Calculate the next origin on a basic ease-out curve.
o.x = o.x * deceleration + self.destinationOrigin.x * (1 - self.decelerationRate);
o.y = o.y * deceleration + self.destinationOrigin.y * (1 - self.decelerationRate);
// Calling -scrollToPoint: instead of manually adjusting the bounds lets us get the expected
// overlay scroller behavior for free.
[super scrollToPoint:o];
// Make this call so that we can force an update of the scroller positions.
[self.containingScrollView reflectScrolledClipView:self];
if ((fabs(o.x - lastOrigin.x) < 0.1 && fabs(o.y - lastOrigin.y) < 0.1)) {
[self endScrolling];
// Make sure we always finish out the animation with the actual coordinates
[super scrollToPoint:o];
[self handleCompletionIfNeededWithSuccess:YES];
}
}
#pragma mark Completion handling
- (void)handleCompletionIfNeededWithSuccess:(BOOL)success {
if (self.scrollCompletion != nil) {
self.scrollCompletion(success);
self.scrollCompletion = nil;
}
}
@end
+33
View File
@@ -0,0 +1,33 @@
/*
Created by Jonathan Willing on 8/28/13.
Copyright (c) 2013, ButterKit. All rights reserved.
Licensed under the MIT license <http://opensource.org/licenses/MIT>
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 "BTRClipView.h"
// A NSScrollView subclass which uses an instance of BTRClipView
// as the clip view instead of NSClipView.
//
// Layer-backed by default.
@interface BTRScrollView : NSScrollView
// Returns the scroll view's content view that is an instance of BTRClipView, or
// nil if it does not exist.
- (BTRClipView *)clipView;
@end
+62
View File
@@ -0,0 +1,62 @@
/*
Created by Jonathan Willing on 8/28/13.
Copyright (c) 2013, ButterKit. All rights reserved.
Licensed under the MIT license <http://opensource.org/licenses/MIT>
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 "BTRScrollView.h"
#import "BTRClipView.h"
@implementation BTRScrollView
#pragma mark Lifecycle
- (id)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:frameRect];
if (self == nil) return nil;
[self swapClipView];
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
if (![self.contentView isKindOfClass:BTRClipView.class]) {
[self swapClipView];
}
}
- (BTRClipView *)clipView {
if ([self.contentView isKindOfClass:BTRClipView.class]) {
return (BTRClipView *)self.contentView;
}
return nil;
}
#pragma mark Clip view swapping
- (void)swapClipView {
self.wantsLayer = YES;
id documentView = self.documentView;
BTRClipView *clipView = [[BTRClipView alloc] initWithFrame:self.contentView.frame];
self.contentView = clipView;
self.documentView = documentView;
}
@end
+13
View File
@@ -0,0 +1,13 @@
//
// main.m
// Mousecape
//
// Created by Alex Zielenski on 2/1/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
int main(int argc, const char * argv[]) {
@autoreleasepool {
return NSApplicationMain(argc, argv);
}
}
@@ -0,0 +1,36 @@
//
// NSFileManager+DirectoryLocations.h
//
// Created by Matt Gallagher on 06 May 2010
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software. Permission is granted to anyone to
// use this software for any purpose, including commercial applications, and to
// alter it and redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source
// distribution.
//
#import <Foundation/Foundation.h>
//
// DirectoryLocations is a set of global methods for finding the fixed location
// directoriess.
//
@interface NSFileManager (DirectoryLocations)
- (NSString *)findOrCreateDirectory:(NSSearchPathDirectory)searchPathDirectory
inDomain:(NSSearchPathDomainMask)domainMask
appendPathComponent:(NSString *)appendComponent
error:(NSError **)errorOut;
- (NSString *)applicationSupportDirectory;
@end
@@ -0,0 +1,155 @@
//
// NSFileManager+DirectoryLocations.m
//
// Created by Matt Gallagher on 06 May 2010
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software. Permission is granted to anyone to
// use this software for any purpose, including commercial applications, and to
// alter it and redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source
// distribution.
//
#import "NSFileManager+DirectoryLocations.h"
enum
{
DirectoryLocationErrorNoPathFound,
DirectoryLocationErrorFileExistsAtLocation
};
NSString * const DirectoryLocationDomain = @"DirectoryLocationDomain";
@implementation NSFileManager (DirectoryLocations)
//
// findOrCreateDirectory:inDomain:appendPathComponent:error:
//
// Method to tie together the steps of:
// 1) Locate a standard directory by search path and domain mask
// 2) Select the first path in the results
// 3) Append a subdirectory to that path
// 4) Create the directory and intermediate directories if needed
// 5) Handle errors by emitting a proper NSError object
//
// Parameters:
// searchPathDirectory - the search path passed to NSSearchPathForDirectoriesInDomains
// domainMask - the domain mask passed to NSSearchPathForDirectoriesInDomains
// appendComponent - the subdirectory appended
// errorOut - any error from file operations
//
// returns the path to the directory (if path found and exists), nil otherwise
//
- (NSString *)findOrCreateDirectory:(NSSearchPathDirectory)searchPathDirectory
inDomain:(NSSearchPathDomainMask)domainMask
appendPathComponent:(NSString *)appendComponent
error:(NSError **)errorOut
{
//
// Search for the path
//
NSArray* paths = NSSearchPathForDirectoriesInDomains(
searchPathDirectory,
domainMask,
YES);
if ([paths count] == 0)
{
if (errorOut)
{
NSDictionary *userInfo =
[NSDictionary dictionaryWithObjectsAndKeys:
NSLocalizedStringFromTable(
@"No path found for directory in domain.",
@"Errors",
nil),
NSLocalizedDescriptionKey,
[NSNumber numberWithInteger:searchPathDirectory],
@"NSSearchPathDirectory",
[NSNumber numberWithInteger:domainMask],
@"NSSearchPathDomainMask",
nil];
*errorOut =
[NSError
errorWithDomain:DirectoryLocationDomain
code:DirectoryLocationErrorNoPathFound
userInfo:userInfo];
}
return nil;
}
//
// Normally only need the first path returned
//
NSString *resolvedPath = [paths objectAtIndex:0];
//
// Append the extra path component
//
if (appendComponent)
{
resolvedPath = [resolvedPath
stringByAppendingPathComponent:appendComponent];
}
//
// Create the path if it doesn't exist
//
NSError *error = nil;
BOOL success = [self
createDirectoryAtPath:resolvedPath
withIntermediateDirectories:YES
attributes:nil
error:&error];
if (!success)
{
if (errorOut)
{
*errorOut = error;
}
return nil;
}
//
// If we've made it this far, we have a success
//
if (errorOut)
{
*errorOut = nil;
}
return resolvedPath;
}
//
// applicationSupportDirectory
//
// Returns the path to the applicationSupportDirectory (creating it if it doesn't
// exist).
//
- (NSString *)applicationSupportDirectory
{
NSString *executableName =
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"];
NSError *error;
NSString *result =
[self
findOrCreateDirectory:NSApplicationSupportDirectory
inDomain:NSUserDomainMask
appendPathComponent:executableName
error:&error];
if (!result)
{
NSLog(@"Unable to find or create application support directory:\n%@", error);
}
return result;
}
@end
@@ -0,0 +1,27 @@
//
// NSOrderedSet+AZSortedInsert.h
// Mousecape
//
// Created by Alex Zielenski on 6/26/13.
// Copyright (c) 2013 Alex Zielenski. All rights reserved.
//
#import <Foundation/Foundation.h>
// Adapted from NSArray+CWSortedInsert
@interface NSOrderedSet (AZSortedInsert)
- (NSUInteger)indexForInsertingObject:(id)anObject sortedUsingfunction:(NSInteger (*)(id, id, void *))compare context:(void *)context;
- (NSUInteger)indexForInsertingObject:(id)anObject sortedUsingComparator:(NSComparator)comparator;
- (NSUInteger)indexForInsertingObject:(id)anObject sortedUsingSelector:(SEL)aSelector;
- (NSUInteger)indexForInsertingObject:(id)anObject sortedUsingDescriptors:(NSArray *)descriptors;
@end
@interface NSMutableOrderedSet (AZSortedInsert)
- (void)insertObject:(id)anObject sortedUsingfunction:(NSInteger (*)(id, id, void *))compare context:(void *)context;
- (void)insertObject:(id)anObject sortedUsingSelector:(SEL)aSelector;
- (void)insertObject:(id)anObject sortedUsingDescriptors:(NSArray *)descriptors;
@end
@@ -0,0 +1,89 @@
//
// NSOrderedSet+AZSortedInsert.m
// Mousecape
//
// Created by Alex Zielenski on 6/26/13.
// Copyright (c) 2013 Alex Zielenski. All rights reserved.
//
#import "NSOrderedSet+AZSortedInsert.h"
#import <objc/message.h>
@implementation NSOrderedSet (AZSortedInsert)
- (NSUInteger)indexForInsertingObject:(id)anObject sortedUsingfunction:(NSInteger (*)(id, id, void *))compare context:(void *)context; {
NSUInteger index = 0;
NSUInteger topIndex = [self count];
IMP objectAtIndexImp = [self methodForSelector:@selector(objectAtIndex:)];
while (index < topIndex) {
NSUInteger midIndex = (index + topIndex) / 2;
id testObject = objectAtIndexImp(self, @selector(objectAtIndex:), midIndex);
if (compare(anObject, testObject, context) > 0) {
index = midIndex + 1;
} else {
topIndex = midIndex;
}
}
return index;
}
static NSComparisonResult cw_SelectorCompare(id a, id b, void* aSelector) {
return (NSComparisonResult)objc_msgSend(a, (SEL)aSelector, b);
}
static NSComparisonResult az_comparatorCompare(id a, id b, NSComparator comparator) {
return comparator(a, b);
}
- (NSUInteger)indexForInsertingObject:(id)anObject sortedUsingSelector:(SEL)aSelector; {
return [self indexForInsertingObject:anObject sortedUsingfunction:&cw_SelectorCompare context:aSelector];
}
- (NSUInteger)indexForInsertingObject:(id)anObject sortedUsingComparator:(NSComparator)comparator {
return [self indexForInsertingObject:anObject sortedUsingfunction:(NSInteger (*)(id, id, void *))&az_comparatorCompare context:comparator];
}
static IMP cw_compareObjectToObjectImp = NULL;
static IMP cw_ascendingImp = NULL;
+ (void)initialize; {
cw_compareObjectToObjectImp = [NSSortDescriptor instanceMethodForSelector:@selector(compareObject:toObject:)];
cw_ascendingImp = [NSSortDescriptor instanceMethodForSelector:@selector(ascending)];
}
static NSComparisonResult cw_DescriptorCompare(id a, id b, void* descriptors) {
NSComparisonResult result = NSOrderedSame;
for (NSSortDescriptor* sortDescriptor in (NSArray *)descriptors) {
result = (NSComparisonResult)cw_compareObjectToObjectImp(sortDescriptor, @selector(compareObject:toObject:), a, b);
if (result != NSOrderedSame) {
break;
}
}
return result;
}
- (NSUInteger)indexForInsertingObject:(id)anObject sortedUsingDescriptors:(NSArray *)descriptors;
{
return [self indexForInsertingObject:anObject sortedUsingfunction:&cw_DescriptorCompare context:descriptors];
}
@end
@implementation NSMutableOrderedSet (AZSortedInsert)
- (void)insertObject:(id)anObject sortedUsingfunction:(NSInteger (*)(id, id, void *))compare context:(void *)context; {
NSUInteger index = [self indexForInsertingObject:anObject sortedUsingfunction:compare context:context];
[self insertObject:anObject atIndex:index];
}
- (void)insertObject:(id)anObject sortedUsingSelector:(SEL)aSelector; {
NSUInteger index = [self indexForInsertingObject:anObject sortedUsingfunction:&cw_SelectorCompare context:aSelector];
[self insertObject:anObject atIndex:index];
}
- (void)insertObject:(id)anObject sortedUsingDescriptors:(NSArray *)descriptors; {
NSUInteger index = [self indexForInsertingObject:anObject sortedUsingDescriptors:descriptors];
[self insertObject:anObject atIndex:index];
}
@end
@@ -0,0 +1,14 @@
//
// MCEditCapeController.h
// Mousecape
//
// Created by Alex Zielenski on 2/3/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MCCursorLibrary.h"
@interface MCEditCapeController : NSViewController
@property (strong) MCCursorLibrary *cursorLibrary;
@end
@@ -0,0 +1,31 @@
//
// MCEditCapeController.m
// Mousecape
//
// Created by Alex Zielenski on 2/3/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCEditCapeController.h"
@interface MCEditCapeController ()
@end
@implementation MCEditCapeController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Initialization code here.
}
return self;
}
- (BOOL)validateValue:(inout __autoreleasing id *)ioValue forKeyPath:(NSString *)inKeyPath error:(out NSError *__autoreleasing *)outError {
#warning TODO: check if library has this identifier
NSLog(@"validate %@", inKeyPath);
return YES;
}
@end
@@ -0,0 +1,23 @@
//
// MCEditDetailController.h
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MCCursor.h"
#import "MMAnimatingImageView.h"
@interface MCEditDetailController : NSViewController <MMAnimatingImageViewDelegate>
@property (strong) MCCursor *cursor;
@property (assign) IBOutlet NSPopUpButton *typePopUpButton;
@property (assign) IBOutlet MMAnimatingImageView *rep100View;
@property (assign) IBOutlet MMAnimatingImageView *rep200View;
@property (assign) IBOutlet MMAnimatingImageView *rep500View;
@property (assign) IBOutlet MMAnimatingImageView *rep1000View;
@end
@interface MCCursorTypeValueTransformer : NSValueTransformer
@end
@@ -0,0 +1,96 @@
//
// MCEditDetailController.m
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCEditDetailController.h"
@interface MCEditDetailController ()
@end
@implementation MCEditDetailController
- (void)awakeFromNib {
[self.typePopUpButton addItemsWithTitles:[cursorMap().allValues sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]];
NSImage *dropzone = [NSImage imageNamed:@"dropzone"];
self.rep100View.placeholderImage = dropzone;
self.rep200View.placeholderImage = dropzone;
self.rep500View.placeholderImage = dropzone;
self.rep1000View.placeholderImage = dropzone;
self.rep100View.scale = 1.0;
self.rep200View.scale = 2.0;
self.rep500View.scale = 5.0;
self.rep1000View.scale = 10.0;
self.rep100View.shouldShowHotSpot = YES;
self.rep200View.shouldShowHotSpot = YES;
self.rep500View.shouldShowHotSpot = YES;
self.rep1000View.shouldShowHotSpot = YES;
[self.rep100View bind:@"image" toObject:self withKeyPath:@"cursor.cursorImage100" options:nil];
[self.rep100View bind:@"frameCount" toObject:self withKeyPath:@"cursor.frameCount" options:nil];
[self.rep100View bind:@"frameDuration" toObject:self withKeyPath:@"cursor.frameDuration" options:nil];
[self.rep100View bind:@"hotSpot" toObject:self withKeyPath:@"cursor.hotSpot" options:nil];
[self.rep200View bind:@"image" toObject:self withKeyPath:@"cursor.cursorImage200" options:nil];
[self.rep200View bind:@"frameCount" toObject:self withKeyPath:@"cursor.frameCount" options:nil];
[self.rep200View bind:@"frameDuration" toObject:self withKeyPath:@"cursor.frameDuration" options:nil];
[self.rep200View bind:@"hotSpot" toObject:self withKeyPath:@"cursor.hotSpot" options:nil];
[self.rep500View bind:@"image" toObject:self withKeyPath:@"cursor.cursorImage500" options:nil];
[self.rep500View bind:@"frameCount" toObject:self withKeyPath:@"cursor.frameCount" options:nil];
[self.rep500View bind:@"frameDuration" toObject:self withKeyPath:@"cursor.frameDuration" options:nil];
[self.rep500View bind:@"hotSpot" toObject:self withKeyPath:@"cursor.hotSpot" options:nil];
[self.rep1000View bind:@"image" toObject:self withKeyPath:@"cursor.cursorImage1000" options:nil];
[self.rep1000View bind:@"frameCount" toObject:self withKeyPath:@"cursor.frameCount" options:nil];
[self.rep1000View bind:@"frameDuration" toObject:self withKeyPath:@"cursor.frameDuration" options:nil];
[self.rep1000View bind:@"hotSpot" toObject:self withKeyPath:@"cursor.hotSpot" options:nil];
}
#pragma mark - MMAnimatingImageView
- (NSDragOperation)imageView:(MMAnimatingImageView *)imageView draggingEntered:(id <NSDraggingInfo>)drop {
return NSDragOperationCopy;
}
- (BOOL)imageView:(MMAnimatingImageView *)imageView shouldPrepareForDragOperation:(id <NSDraggingInfo>)drop {
return YES;
}
- (BOOL)imageView:(MMAnimatingImageView *)imageView shouldPerformDragOperation:(id <NSDraggingInfo>)drop {
return YES;
}
- (void)imageView:(MMAnimatingImageView *)imageView didAcceptDroppedImages:(NSArray *)images {
CGFloat scale = imageView.scale;
[self.cursor setRepresentation:images.lastObject forScale:cursorScaleForScale(scale)];
}
@end
@implementation MCCursorTypeValueTransformer
+ (Class)transformedValueClass {
return [NSString class];
}
+ (BOOL)allowsReverseTransformation {
return YES;
}
- (id)transformedValue:(id)value {
return nameForCursorIdentifier(value);
}
- (id)reverseTransformedValue:(id)value {
return cursorIdentifierForName(value);
}
@end
@@ -0,0 +1,19 @@
//
// MCEditListController.h
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MCCursorLibrary.h"
@interface MCEditListController : NSViewController <NSTableViewDataSource, NSTableViewDelegate>
@property (strong) MCCursorLibrary *cursorLibrary;
@property (weak) id selectedObject;
@property (assign) IBOutlet NSTableView *tableView;
- (IBAction)addAction:(id)sender;
- (IBAction)removeAction:(id)sender;
@end
@@ -0,0 +1,150 @@
//
// MCEditListController.m
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCEditListController.h"
#import "NSOrderedSet+AZSortedInsert.h"
const char MCEditCursorsContext;
@interface MCEditListController ()
@property (nonatomic, strong) NSMutableOrderedSet *cursors;
+ (NSComparator)sortComparator;
@end
@implementation MCEditListController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[self addObserver:self forKeyPath:@"cursorLibrary.cursors" options:0 context:NULL];
}
return self;
}
- (id)initWithCoder:(NSCoder *)coder {
if ((self = [super initWithCoder:coder])) {
[self addObserver:self forKeyPath:@"cursorLibrary.cursors" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:(void*)&MCEditCursorsContext];
}
return self;
}
- (void)dealloc {
[self removeObserver:self forKeyPath:@"cursorLibrary.cursors" context:(void *)&MCEditCursorsContext];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == &MCEditCursorsContext) {
NSKeyValueChange kind = [change[NSKeyValueChangeKindKey] integerValue];
[self.tableView beginUpdates];
if (kind == NSKeyValueChangeSetting) {
id nextSet = change[NSKeyValueChangeNewKey];
if ([nextSet isKindOfClass:[NSNull class]]) {
self.cursors = [NSMutableOrderedSet orderedSet];
} else {
self.cursors = [NSMutableOrderedSet orderedSetWithSet:nextSet copyItems:NO];
[self.cursors sortUsingComparator:self.class.sortComparator];
}
[self.tableView reloadData];
[self tableViewSelectionDidChange:nil];
} else if (kind == NSKeyValueChangeInsertion) {
for (MCCursor *lib in change[NSKeyValueChangeNewKey]) {
NSUInteger index = [self.cursors indexForInsertingObject:lib sortedUsingComparator:self.class.sortComparator];
NSIndexSet *indices = [NSIndexSet indexSetWithIndex:index];
[self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indices forKey:@"capes"];
[self.cursors insertObject:lib atIndex:index];
[self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indices forKey:@"capes"];
[self.tableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:index + 1] withAnimation:NSTableViewAnimationSlideUp];
}
} else if (kind == NSKeyValueChangeRemoval) {
for (MCCursor *lib in change[NSKeyValueChangeOldKey]) {
NSUInteger index = [self.cursors indexOfObject:lib];
if (index != NSNotFound) {
NSIndexSet *indices = [NSIndexSet indexSetWithIndex:index];
[self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indices forKey:@"capes"];
[self.cursors removeObjectAtIndex:index];
[self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indices forKey:@"capes"];
[self.tableView removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:index + 1] withAnimation:NSTableViewAnimationSlideUp | NSTableViewAnimationEffectFade];
}
}
}
[self.tableView endUpdates];
}
}
+ (NSComparator)sortComparator {
static NSComparator sortComparator = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sortComparator = ^NSComparisonResult(id obj1, id obj2) {
return [[obj1 valueForKey:@"name"] localizedCaseInsensitiveCompare:[obj2 valueForKey:@"name"]];
};
});
return sortComparator;
}
- (IBAction)addAction:(id)sender {
[self.cursorLibrary addCursor:[[MCCursor alloc] init]];
}
- (IBAction)removeAction:(id)sender {
if (self.tableView.selectedRow != 0)
[self.cursorLibrary removeCursor:[[self.tableView viewAtColumn:0 row:self.tableView.selectedRow makeIfNecessary:NO] objectValue]];
}
#pragma mark - NSTableViewDelegate
- (void)tableViewSelectionDidChange:(NSNotification *)notification {
NSInteger selectedRow = [(NSTableView *)self.view selectedRow];
if (selectedRow == NSNotFound || selectedRow >= self.cursors.count + 1)
return;
if (selectedRow == 0)
self.selectedObject = self.cursorLibrary;
else
self.selectedObject = [self.cursors objectAtIndex:selectedRow - 1];
}
- (BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row {
return row == 0;
}
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row {
if (row == 0)
return 32.0;
return 22.0;
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSView *view;
if (row == 0)
view = [tableView makeViewWithIdentifier:@"MCCursorLibrary" owner:self];
else
view = [tableView makeViewWithIdentifier:@"MCCursor" owner:self];
return view;
}
#pragma mark - NSTableViewDataSource
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return self.cursors.count + 1;
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
if (row == 0)
return self.cursorLibrary;
return [self.cursors objectAtIndex: row - 1];
}
@end
@@ -0,0 +1,21 @@
//
// MCEditWindowController.h
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MCEditDetailController.h"
#import "MCEditListController.h"
#import "MCEditCapeController.h"
#import "MCCursorLibrary.h"
@interface MCEditWindowController : NSWindowController <NSWindowDelegate, NSSplitViewDelegate>
@property (assign) IBOutlet MCEditListController *editListController; // List of cursors in the library
@property (assign) IBOutlet MCEditDetailController *editDetailController; // Detail view of the selected cursor
@property (assign) IBOutlet MCEditCapeController *editCapeController; // Detail view of the entire library
@property (assign) IBOutlet NSView *detailView;
@property (assign) MCCursorLibrary *cursorLibrary;
@end
@@ -0,0 +1,175 @@
//
// MCEditWindowController.m
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCEditWindowController.h"
#import "MCLibraryController.h"
@interface MCEditWindowController ()
- (void)_setCurrentViewController:(NSViewController *)vc;
- (BOOL)promptSaveForLibrary:(MCCursorLibrary *)nextLibrary;
@end
@implementation MCEditWindowController
@dynamic cursorLibrary;
- (id)initWithWindow:(NSWindow *)window {
if ((self = [super initWithWindow:window])) {
// Initialization code here.
}
return self;
}
- (void)loadWindow {
[super loadWindow];
[self windowDidLoad];
}
+ (NSSet *)keyPathsForValuesAffectingCursorLibrary {
return [NSSet setWithObject:@"editListController.cursorLibrary"];
}
- (MCCursorLibrary *)cursorLibrary {
return self.editListController.cursorLibrary;
}
- (void)setCursorLibrary:(MCCursorLibrary *)cursorLibrary {
[self promptSaveForLibrary:cursorLibrary];
}
- (BOOL)promptSaveForLibrary:(MCCursorLibrary *)nextLibrary {
if (!self.window.isDocumentEdited) {
self.editListController.cursorLibrary = nextLibrary;
return NO;
}
NSBeginAlertSheet(@"Do you want to save your changes?", @"Save", @"Cancel", @"Discard Changes", self.window, self, NULL, @selector(sheetDidDismiss:returnCode:contextInfo:), (__bridge void *)nextLibrary, @"Your changes will be discarded if you don't save them.");
return YES;
}
- (void)windowDidLoad {
[super windowDidLoad];
[self.editListController addObserver:self forKeyPath:@"selectedObject" options:0 context:nil];
[self _setCurrentViewController:self.editCapeController];
[self.window bind:@"documentEdited" toObject:self withKeyPath:@"cursorLibrary.isDirty" options:nil];
}
- (void)dealloc {
[self.editListController removeObserver:self forKeyPath:@"selectedObject"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"selectedObject"]) {
[self _changeEditViewsForSelection];
}
}
- (BOOL)windowShouldClose:(NSWindow *)window {
return ![self promptSaveForLibrary:nil];
}
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
return self.cursorLibrary.undoManager;
}
- (void)sheetDidDismiss:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(MCCursorLibrary *)contextInfo {
if (returnCode == 0) { // cancel
// do nothing
} else if (returnCode == 1) { // save
[self.cursorLibrary save];
self.editListController.cursorLibrary = contextInfo;
if (!contextInfo)
[self.window close];
} else if (returnCode == -1) { // discard changes
[self.cursorLibrary revertToSaved];
self.editListController.cursorLibrary = contextInfo;
if (!contextInfo)
[self.window close];
}
}
#pragma mark - Menu Actions
- (IBAction)applyCape:(id)sender {
[self.cursorLibrary.library applyCape:self.cursorLibrary];
}
- (IBAction)removeCape:(id)sender {
[self.cursorLibrary.library removeCape:self.cursorLibrary];
}
- (IBAction)duplicateCape:(id)sender {
[self.cursorLibrary.library importCape:self.cursorLibrary.copy];
}
- (IBAction)checkCape:(id)sender {
}
- (IBAction)saveDocument:(id)sender {
[self.cursorLibrary save];
}
- (IBAction)revertDocumentToSaved:(id)sender {
[self.cursorLibrary revertToSaved];
}
#pragma mark - View Changing
- (void)_changeEditViewsForSelection {
BOOL capeEditor = [self.editListController.selectedObject isKindOfClass:[MCCursorLibrary class]];
if (capeEditor) {
[self _setCurrentViewController:self.editCapeController];
self.editCapeController.cursorLibrary = self.editListController.selectedObject;
} else {
[self _setCurrentViewController:self.editDetailController];
self.editDetailController.cursor = self.editListController.selectedObject;
}
}
- (void)_setCurrentViewController:(NSViewController *)vc {
if ([self.detailView.subviews containsObject:vc.view])
return;
[self.detailView setSubviews:@[]];
[self.detailView removeConstraints:self.detailView.constraints];
NSRect frame = self.detailView.bounds;
vc.view.frame = frame;
// Fill superview with subview
[vc.view setTranslatesAutoresizingMaskIntoConstraints:YES];
[vc.view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable | NSViewMinYMargin | NSViewMinXMargin];
[self.detailView addSubview:vc.view];
}
#pragma mark - NSSplitViewDelegate
- (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview {
return NO;
}
- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)dividerIndex {
if (dividerIndex == 0) {
return 120.0f;
}
return proposedMin;
}
- (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)dividerIndex {
if (dividerIndex == 0) {
return splitView.frame.size.width - 380.0;
}
return proposedMax;
}
@end
@@ -0,0 +1,34 @@
//
// MCLibraryController.h
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MCCursorLibrary.h"
@interface MCLibraryController : NSObject
@property (readonly, weak) MCCursorLibrary *appliedCape;
@property (nonatomic, readonly) NSUndoManager *undoManager;
@property (readonly, copy) NSURL *libraryURL;
- (instancetype)initWithURL:(NSURL *)url;
- (void)importCapeAtURL:(NSURL *)url;
- (void)importCape:(MCCursorLibrary *)cape;
- (void)addCape:(MCCursorLibrary *)cape;
- (void)removeCape:(MCCursorLibrary *)cape;
- (void)applyCape:(MCCursorLibrary *)cape;
- (void)restoreCape;
- (NSURL *)URLForCape:(MCCursorLibrary *)cape;
@end
@interface MCLibraryController (Capes)
@property (nonatomic, readonly) NSSet *capes;
@end
@@ -0,0 +1,162 @@
//
// MCLibraryController.m
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCLibraryController.h"
#import "NSOrderedSet+AZSortedInsert.h"
#import "apply.h"
#import "restore.h"
const char MCLibraryIdentifierContext;
@interface MCLibraryController ()
@property (nonatomic, readwrite, strong) NSUndoManager *undoManager;
@property (nonatomic, retain) NSMutableSet *capes;
@property (readwrite, copy) NSURL *libraryURL;
@property (readwrite, weak) MCCursorLibrary *appliedCape;
- (void)loadLibrary;
@end
@implementation MCLibraryController
- (NSURL *)URLForCape:(MCCursorLibrary *)cape {
return [NSURL fileURLWithPathComponents:@[ self.libraryURL.path, [cape.identifier stringByAppendingPathExtension:@"cape"] ]];
}
- (instancetype)initWithURL:(NSURL *)url {
if ((self = [self init])) {
self.libraryURL = url;
self.undoManager = [[NSUndoManager alloc] init];
[self loadLibrary];
}
return self;
}
- (void)loadLibrary {
[self.undoManager disableUndoRegistration];
self.capes = [NSMutableSet set];
NSString *capesPath = self.libraryURL.path;
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:capesPath error:NULL];
NSString *applied = [NSUserDefaults.standardUserDefaults stringForKey:MCPreferencesAppliedCursorKey];
for (NSString *filename in contents) {
NSURL *fileURL = [NSURL fileURLWithPathComponents:@[ capesPath, filename ]];
MCCursorLibrary *library = [MCCursorLibrary cursorLibraryWithContentsOfURL:fileURL];
if ([library.identifier isEqualToString:applied]) {
self.appliedCape = library;
}
[self addCape:library];
}
[self.undoManager enableUndoRegistration];
}
- (void)importCapeAtURL:(NSURL *)url {
MCCursorLibrary *lib = [MCCursorLibrary cursorLibraryWithContentsOfURL:url];
NSURL *destinationURL = [self URLForCape:lib];
NSError *error = nil;
[[NSFileManager defaultManager] copyItemAtURL:lib.fileURL toURL:destinationURL error:&error];
if (!error) {
lib.fileURL = destinationURL;
[self addCape:lib];
}
}
- (void)importCape:(MCCursorLibrary *)lib {
lib.fileURL = [self URLForCape:lib];
[lib writeToFile:lib.fileURL.path atomically:NO];
[self addCape:lib];
}
- (void)addCape:(MCCursorLibrary *)cape {
if ([self.capes containsObject:cape]) {
NSLog(@"Not adding %@ to the library because an object with that identifier already exists", cape.identifier);
return;
}
if (!cape) {
NSLog(@"Cannot add nil cape");
return;
}
NSSet *change = [NSSet setWithObject:cape];
[self willChangeValueForKey:@"capes" withSetMutation:NSKeyValueUnionSetMutation usingObjects:change];
[cape addObserver:self forKeyPath:@"identifier" options:0 context:(void *)&MCLibraryIdentifierContext];
cape.library = self;
[self.capes addObject:cape];
[[self.undoManager prepareWithInvocationTarget:self] removeCape:cape];
if (!self.undoManager.isUndoing) {
[self.undoManager setActionName:[@"Add " stringByAppendingString:cape.name]];
}
[self didChangeValueForKey:@"capes" withSetMutation:NSKeyValueUnionSetMutation usingObjects:change];
}
- (void)removeCape:(MCCursorLibrary *)cape {
NSSet *change = [NSSet setWithObject:cape];
[self willChangeValueForKey:@"capes" withSetMutation:NSKeyValueMinusSetMutation usingObjects:change];
if (cape == self.appliedCape)
[self restoreCape];
[cape removeObserver:self forKeyPath:@"identifier" context:(void *)&MCLibraryIdentifierContext];
if (cape.library == self)
cape.library = nil;
[self.capes removeObject:cape];
// Move the file to the trash
NSFileManager *manager = [NSFileManager defaultManager];
NSURL *destinationURL = [NSURL fileURLWithPath:[[@"~/.Trash" stringByExpandingTildeInPath] stringByAppendingPathComponent:cape.fileURL.lastPathComponent] isDirectory:NO];
[manager removeItemAtURL:destinationURL error:NULL];
[manager moveItemAtURL:cape.fileURL toURL:destinationURL error:NULL];
[[self.undoManager prepareWithInvocationTarget:self] importCapeAtURL:destinationURL];
if (!self.undoManager.isUndoing) {
[self.undoManager setActionName:[@"Remove " stringByAppendingString:cape.name]];
}
[self didChangeValueForKey:@"capes" withSetMutation:NSKeyValueMinusSetMutation usingObjects:change];
}
- (void)applyCape:(MCCursorLibrary *)cape {
if (applyCapeAtPath(cape.fileURL.path)) {
self.appliedCape = cape;
}
}
- (void)restoreCape {
resetAllCursors();
self.appliedCape = nil;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == &MCLibraryIdentifierContext) {
// change the file url to reflect the new identifier
MCCursorLibrary *cape = object;
NSURL *oldURL = cape.fileURL;
[cape setFileURL:[self URLForCape:cape]];
#warning TODO: Do something with the error
[[NSFileManager defaultManager] moveItemAtURL:oldURL toURL:cape.fileURL error:nil];
// [cape save];
}
}
@end
@@ -0,0 +1,30 @@
//
// MCLibraryViewController.h
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MCLibraryController.h"
@interface MCLibraryViewController : NSViewController <NSTableViewDelegate, NSTableViewDataSource>
@property (assign) IBOutlet NSMenu *contextMenu;
@property (assign) IBOutlet NSTableView *tableView;
@property (strong, readonly) MCLibraryController *libraryController;
- (MCCursorLibrary *)selectedCape;
- (MCCursorLibrary *)clickedCape;
- (void)editCape:(MCCursorLibrary *)library;
- (IBAction)applyAction:(NSMenuItem *)sender;
- (IBAction)editAction:(NSMenuItem *)sender;
- (IBAction)duplicateAction:(NSMenuItem *)sender;
- (IBAction)removeAction:(NSMenuItem *)sender;
@end
@interface MCLibraryController (Properties)
@property (readonly, strong) NSOrderedSet *capes;
@end
@@ -0,0 +1,205 @@
//
// MCLibraryViewController.m
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCLibraryViewController.h"
#import "MCCapeCellView.h"
#import "NSFileManager+DirectoryLocations.h"
#import "MCEditWindowController.h"
#import "NSOrderedSet+AZSortedInsert.h"
const char MCLibraryCapesContext;
const char MCLibraryNameContext;
@interface MCLibraryViewController ()
@property (strong) MCEditWindowController *editWindowController;
@property (readwrite, strong) NSMutableOrderedSet *capes;
@property (strong, readwrite) MCLibraryController *libraryController;
- (void)setupEnvironment;
- (void)doubleClick:(id)sender;
+ (NSString *)capesPath;
+ (NSComparator)sortComparator;
@end
@implementation MCLibraryViewController
+ (NSComparator)sortComparator {
static NSComparator sortComparator = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sortComparator = ^NSComparisonResult(id obj1, id obj2) {
NSComparisonResult result = [[obj1 valueForKey:@"name"] localizedCaseInsensitiveCompare:[obj2 valueForKey:@"name"]];
if (result == NSOrderedSame)
result = [[obj1 valueForKey:@"author"] localizedCaseInsensitiveCompare:[obj2 valueForKey:@"author"]];
return result;
};
});
return sortComparator;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
[self setupEnvironment];
}
return self;
}
- (id)initWithCoder:(NSCoder *)coder {
if ((self = [super initWithCoder:coder])) {
[self setupEnvironment];
}
return self;
}
- (void)dealloc {
[self.libraryController removeObserver:self forKeyPath:@"appliedCape"];
}
+ (NSString *)capesPath {
return [[NSFileManager defaultManager] findOrCreateDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appendPathComponent:@"Mousecape/capes" error:NULL];
}
- (void)awakeFromNib {
self.tableView.doubleAction = @selector(doubleClick:);
self.tableView.target = self;
}
- (void)setupEnvironment {
[self addObserver:self forKeyPath:@"libraryController.capes" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:(void *)&MCLibraryCapesContext];
self.libraryController = [[MCLibraryController alloc] initWithURL:[NSURL fileURLWithPath:self.class.capesPath]];
[self setRepresentedObject:self.libraryController];
[self.libraryController addObserver:self forKeyPath:NSStringFromSelector(@selector(appliedCape)) options:0 context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(appliedCape))]) {
for (NSUInteger x = 0; x < self.tableView.numberOfRows; x++) {
MCCapeCellView *cv = [self.tableView viewAtColumn:0 row:x makeIfNecessary:NO];
cv.appliedImageView.hidden = !(cv.objectValue == [self.libraryController appliedCape]);
}
} else if (context == &MCLibraryCapesContext) {
NSKeyValueChange kind = [change[NSKeyValueChangeKindKey] integerValue];
[self.tableView beginUpdates];
if (kind == NSKeyValueChangeInsertion || kind == NSKeyValueChangeSetting) {
if (kind == NSKeyValueChangeSetting) {
self.capes = [NSMutableOrderedSet orderedSet];
}
for (MCCursorLibrary *lib in change[NSKeyValueChangeNewKey]) {
NSUInteger index = [self.capes indexForInsertingObject:lib sortedUsingComparator:self.class.sortComparator];
NSIndexSet *indices = [NSIndexSet indexSetWithIndex:index];
[self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indices forKey:@"capes"];
[lib addObserver:self forKeyPath:@"name" options:0 context:(void *)&MCLibraryNameContext];
[self.capes insertObject:lib atIndex:index];
[self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indices forKey:@"capes"];
[self.tableView insertRowsAtIndexes:indices withAnimation:NSTableViewAnimationSlideUp];
}
} else if (kind == NSKeyValueChangeRemoval) {
for (MCCursorLibrary *lib in change[NSKeyValueChangeOldKey]) {
NSUInteger index = [self.capes indexOfObject:lib];
NSIndexSet *indices = [NSIndexSet indexSetWithIndex:index];
[self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indices forKey:@"capes"];
[lib removeObserver:self forKeyPath:@"name" context:(void *)&MCLibraryNameContext];
[self.capes removeObjectAtIndex:index];
[self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indices forKey:@"capes"];
[self.tableView removeRowsAtIndexes:indices withAnimation:NSTableViewAnimationSlideUp | NSTableViewAnimationEffectFade];
}
}
[self.tableView endUpdates];
} else if (context == &MCLibraryNameContext) {
// Reoder it
MCCursorLibrary *cape = object;
NSUInteger oldIndex = [self.capes indexOfObject:cape];
if (oldIndex != NSNotFound) {
[self.capes removeObjectAtIndex:oldIndex];
NSUInteger newIndex = [self.capes indexForInsertingObject:cape sortedUsingComparator:self.class.sortComparator];
[self.capes insertObject:cape atIndex:newIndex];
[self.tableView moveRowAtIndex:oldIndex toIndex:newIndex];
}
} else
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
- (void)doubleClick:(NSTableView *)sender {
NSUInteger row = sender.clickedRow;
MCCursorLibrary *library = [[sender viewAtColumn:0 row:row makeIfNecessary:NO] objectValue];
[self.libraryController applyCape:library];
}
- (MCCursorLibrary *)selectedCape {
return [[self.tableView viewAtColumn:0 row:self.tableView.selectedRow makeIfNecessary:NO] objectValue];
}
- (MCCursorLibrary *)clickedCape {
return [[self.tableView viewAtColumn:0 row:self.tableView.clickedRow makeIfNecessary:NO] objectValue];
}
- (void)editCape:(MCCursorLibrary *)library {
if (!library)
return;
if (!self.editWindowController) {
self.editWindowController = [[MCEditWindowController alloc] initWithWindowNibName:@"Edit"];
[self.editWindowController loadWindow];
}
self.editWindowController.cursorLibrary = library;
[self.editWindowController showWindow:self];
}
#pragma mark - Context Menu
- (IBAction)applyAction:(NSMenuItem *)sender {
[self.libraryController applyCape:self.clickedCape];
}
- (IBAction)editAction:(NSMenuItem *)sender {
[self editCape:self.clickedCape];
}
- (IBAction)duplicateAction:(NSMenuItem *)sender {
[self.libraryController importCape:self.clickedCape.copy];
}
- (IBAction)removeAction:(NSMenuItem *)sender {
[self.libraryController removeCape:self.clickedCape];
}
#pragma mark - NSTableViewDelegate
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return self.capes.count;
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
return self.capes[row];
}
#pragma mark - NSTableViewDelegate
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
MCCapeCellView *cellView = (MCCapeCellView *)[tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
cellView.appliedImageView.hidden = !([self.capes objectAtIndex:row] == self.libraryController.appliedCape);
return cellView;
}
//- (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row {
// return nil;
//}
@end
@@ -0,0 +1,18 @@
//
// MCLbraryWindowController.h
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MCLibraryViewController.h"
@interface MCLibraryWindowController : NSWindowController <NSWindowDelegate>
@property (assign) IBOutlet MCLibraryViewController *libraryViewController;
@property (assign) IBOutlet NSView *appliedAccessory;
@end
@interface MCAppliedCapeValueTransformer : NSValueTransformer
@end
@@ -0,0 +1,100 @@
//
// MCLbraryWindowController.m
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCLibraryWindowController.h"
@interface MCLibraryWindowController ()
- (void)composeAccessory;
@end
@implementation MCLibraryWindowController
- (id)initWithWindow:(NSWindow *)window {
if ((self = [super initWithWindow:window])) {
}
return self;
}
- (void)windowDidLoad {
[super windowDidLoad];
[self composeAccessory];
}
- (NSString *)windowNibName {
return @"Library";
}
- (void)composeAccessory {
NSView *themeFrame = [self.window.contentView superview];
NSView *accessory = self.appliedAccessory;
[accessory setTranslatesAutoresizingMaskIntoConstraints:NO];
NSRect c = themeFrame.frame;
NSRect aV = accessory.frame;
NSRect newFrame = NSMakeRect(
c.size.width - aV.size.width, // x position
c.size.height - aV.size.height, // y position
aV.size.width, // width
aV.size.height); // height
[accessory setFrame:newFrame];
[themeFrame addSubview:accessory];
[themeFrame addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|-(>=100)-[accessory(245)]-(0)-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(accessory)]];
[themeFrame addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-(0)-[accessory(20)]-(>=22)-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(accessory)]];
}
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
return self.libraryViewController.libraryController.undoManager;
}
#pragma mark - Menu Actions
- (IBAction)applyCape:(id)sender {
[self.libraryViewController.libraryController applyCape:self.libraryViewController.selectedCape];
}
- (IBAction)editCape:(id)sender {
[self.libraryViewController editCape:self.libraryViewController.selectedCape];
}
- (IBAction)removeCape:(id)sender {
[self.libraryViewController.libraryController removeCape:self.libraryViewController.selectedCape];
}
- (IBAction)duplicateCape:(id)sender {
[self.libraryViewController.libraryController importCape:self.libraryViewController.selectedCape.copy];
}
- (IBAction)checkCape:(id)sender {
}
@end
@implementation MCAppliedCapeValueTransformer
+ (Class)transformedValueClass {
return [NSString class];
}
- (id)transformedValue:(id)value {
return [NSLocalizedString(@"Applied Cape: ", @"Accessory label for applied cape") stringByAppendingString:value ? value : NSLocalizedString(@"None", @"Accessory label for when no cape is applied")];
}
@end
+48
View File
@@ -0,0 +1,48 @@
//
// MCCursor.h
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, MCCursorScale) {
MCCursorScaleNone = 000,
MCCursorScale100 = 100,
MCCursorScale200 = 200,
MCCursorScale500 = 500,
MCCursorScale1000 = 1000
};
extern MCCursorScale cursorScaleForScale(CGFloat scale);
@interface MCCursor : NSObject <NSCopying>
@property (nonatomic, copy) NSString *identifier;
@property (nonatomic, readonly) NSString *name;
@property (nonatomic, assign) CGFloat frameDuration;
@property (nonatomic, assign) NSUInteger frameCount;
@property (nonatomic, assign) NSSize size;
@property (nonatomic, assign) NSPoint hotSpot;
//@property (assign) NSUInteger repeatCount; // v2.01
// creating a cursor from a dictionary
+ (MCCursor *)cursorWithDictionary:(NSDictionary *)dict ofVersion:(CGFloat)version;
- (id)initWithCursorDictionary:(NSDictionary *)dict ofVersion:(CGFloat)version;
- (void)setRepresentation:(NSImageRep *)imageRep forScale:(MCCursorScale)scale;
- (void)removeRepresentationForScale:(MCCursorScale)scale;
- (NSImageRep *)representationForScale:(MCCursorScale)scale;
- (NSImageRep *)representationWithScale:(CGFloat)scale;
- (NSDictionary *)dictionaryRepresentation;
// Derived Properties
- (NSImage *)imageWithAllReps;
@end
@interface MCCursor (Properties)
@property (nonatomic, readonly, strong) NSDictionary *representations;
@end
+236
View File
@@ -0,0 +1,236 @@
//
// MCCursor.m
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCCursor.h"
MCCursorScale cursorScaleForScale(CGFloat scale) {
if (scale < 0.0)
return MCCursorScaleNone;
return (MCCursorScale)((NSInteger)scale * 100);
}
@interface MCCursor ()
@property (readwrite, strong) NSMutableDictionary *representations;
- (BOOL)_readFromDictionary:(NSDictionary *)dictionary ofVersion:(CGFloat)version;
@end
@implementation MCCursor
@dynamic name;
+ (MCCursor *)cursorWithDictionary:(NSDictionary *)dict ofVersion:(CGFloat)version {
return [[self alloc] initWithCursorDictionary:dict ofVersion:version];
}
- (id)init {
if ((self = [super init])) {
self.frameCount = 1;
self.frameDuration = 1.0;
self.size = NSZeroSize;
self.hotSpot = NSZeroPoint;
self.identifier = [UUID() stringByReplacingOccurrencesOfString:@"-" withString:@""];
self.representations = [NSMutableDictionary dictionary];
}
return self;
}
- (id)initWithCursorDictionary:(NSDictionary *)dict ofVersion:(CGFloat)version {
if ((self = [self init])) {
if (![self _readFromDictionary:dict ofVersion:version])
return nil;
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
MCCursor *cursor = [[MCCursor allocWithZone:zone] init];
cursor.frameCount = self.frameCount;
cursor.frameDuration = self.frameDuration;
cursor.size = self.size;
cursor.representations = self.representations.mutableCopy;
cursor.hotSpot = self.hotSpot;
cursor.identifier = self.identifier;
return cursor;
}
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@"imageWithAllReps"]) {
keyPaths = [keyPaths setByAddingObjectsFromArray:@[ @"representations" ]];
} else if ([key isEqualToString:@"name"]) {
keyPaths = [keyPaths setByAddingObjectsFromArray:@[ @"identifier" ]];
} else if ([key hasPrefix:@"cursorImage"]) {
keyPaths = [keyPaths setByAddingObjectsFromArray:@[ [key stringByReplacingCharactersInRange:NSMakeRange(6, 5) withString:@"Rep"] ]];
}
return keyPaths;
}
- (BOOL)_readFromDictionary:(NSDictionary *)dictionary ofVersion:(CGFloat)version {
if (!dictionary || !dictionary.count)
return NO;
NSNumber *frameCount = [dictionary objectForKey:MCCursorDictionaryFrameCountKey];
NSNumber *frameDuration = [dictionary objectForKey:MCCursorDictionaryFrameDuratiomKey];
// NSNumber *repeatCount = dictionary[MCCursorDictionaryRepeatCountKey];
NSNumber *hotSpotX = [dictionary objectForKey:MCCursorDictionaryHotSpotXKey];
NSNumber *hotSpotY = [dictionary objectForKey:MCCursorDictionaryHotSpotYKey];
NSNumber *pointsWide = [dictionary objectForKey:MCCursorDictionaryPointsWideKey];
NSNumber *pointsHigh = [dictionary objectForKey:MCCursorDictionaryPointsHighKey];
NSArray *reps = [dictionary objectForKey:MCCursorDictionaryRepresentationsKey];
// we only take version 2.0 documents.
if (version >= 2.0) {
if (frameCount && frameDuration && hotSpotX && hotSpotY && pointsWide && pointsHigh) {
self.frameCount = frameCount.unsignedIntegerValue;
self.frameDuration = frameDuration.doubleValue;
self.hotSpot = NSMakePoint(hotSpotX.doubleValue, hotSpotY.doubleValue);
self.size = NSMakeSize(pointsWide.doubleValue, pointsHigh.doubleValue);
// self.repeatCount = repeatCount.unsignedIntegerValue;
for (NSData *data in reps) {
// data in v2.0 documents are saved as PNGs
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithData:data];
rep.size = NSMakeSize(self.size.width, self.size.height * self.frameCount);
[self setRepresentation:rep forScale:cursorScaleForScale(rep.pixelsWide / self.size.width)];
}
return YES;
}
}
return NO;
}
- (NSDictionary *)dictionaryRepresentation {
NSMutableDictionary *drep = [NSMutableDictionary dictionary];
drep[MCCursorDictionaryFrameCountKey] = @(self.frameCount);
drep[MCCursorDictionaryFrameDuratiomKey] = @(self.frameDuration);
drep[MCCursorDictionaryHotSpotXKey] = @(self.hotSpot.x);
drep[MCCursorDictionaryHotSpotYKey] = @(self.hotSpot.y);
drep[MCCursorDictionaryPointsWideKey] = @(self.size.width);
drep[MCCursorDictionaryPointsHighKey] = @(self.size.height);
NSMutableArray *pngs = [NSMutableArray array];
for (NSString *key in self.representations) {
NSBitmapImageRep *rep = self.representations[key];
pngs[pngs.count] = [rep representationUsingType:NSPNGFileType properties:nil];
}
drep[MCCursorDictionaryRepresentationsKey] = pngs;
return drep;
}
- (id)valueForUndefinedKey:(NSString *)key {
// Special KVC for observers to be able to watch each scale
if ([key hasPrefix:@"cursorRep"] || [key hasPrefix:@"cursorImage"]) {
NSString *prefix = [key hasPrefix:@"cursorRep"] ? @"cursorRep" : @"cursorImage";
NSString *scaleString = [key substringFromIndex:prefix.length];
CGFloat scale = [scaleString doubleValue] / 100;
if ([key hasPrefix:@"cursorRep"])
return [self representationForScale:cursorScaleForScale(scale)];
else {
NSImageRep *rep = [self representationForScale:cursorScaleForScale(scale)];
if (rep) {
NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(rep.pixelsWide / scale, rep.pixelsHigh / scale)];
[image addRepresentation:rep];
return image;
}
return nil;
}
}
return [super valueForUndefinedKey:key];
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
// Special KVC for observers to be able to watch each scale
if ([key hasPrefix:@"cursorRep"] || [key hasPrefix:@"cursorImage"]) {
NSString *prefix = [key hasPrefix:@"cursorRep"] ? @"cursorRep" : @"cursorImage";
NSString *scaleString = [key substringFromIndex:prefix.length];
CGFloat scale = [scaleString doubleValue] / 100;
if ([key hasPrefix:@"cursorImage"]) {
value = [(NSImage *)value representations][0];
}
[self setRepresentation:value forScale:cursorScaleForScale(scale)];
return;
}
[super setValue:value forUndefinedKey:key];
}
- (void)setRepresentation:(NSImageRep *)imageRep forScale:(MCCursorScale)scale {
[self willChangeValueForKey:@"representations"];
NSString *key = [@"cursorRep" stringByAppendingFormat:@"%lu", scale];
[self willChangeValueForKey:key];
if (imageRep)
[self.representations setObject:imageRep forKey:@(scale)];
else
[self.representations removeObjectForKey:@(scale)];
[self didChangeValueForKey:key];
[self didChangeValueForKey:@"representations"];
}
- (void)removeRepresentationForScale:(MCCursorScale)scale {
[self setRepresentation:Nil forScale:scale];
}
- (NSImageRep *)representationForScale:(MCCursorScale)scale {
return self.representations[@(scale)];
}
- (NSImageRep *)representationWithScale:(CGFloat)scale {
return [self representationForScale:cursorScaleForScale(scale)];
}
- (NSImage *)imageWithAllReps {
NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(self.size.width, self.size.height * self.frameCount)];
image.matchesOnMultipleResolution = YES;
[image addRepresentations:self.representations.allValues];
return image;
}
- (NSString *)name {
return nameForCursorIdentifier(self.identifier);
}
- (BOOL)isEqualTo:(MCCursor *)object {
if (![object isKindOfClass:self.class]) {
return NO;
}
BOOL props = (object.frameCount == self.frameCount &&
object.frameDuration == self.frameDuration &&
NSEqualSizes(object.size, self.size) &&
NSEqualPoints(object.hotSpot, self.hotSpot) &&
[object.name isEqualToString:self.name] &&
[object.identifier isEqualToString:self.identifier]);
// props = (props && [self.representations isEqualToDictionary:object.representations]);
return props;
}
- (BOOL)isEqual:(id)object {
return [self isEqualTo:object];
}
@end
@@ -0,0 +1,51 @@
//
// MCCursorLibrary.h
// Mousecape
//
// Created by Alex Zielenski on 2/1/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MCCursor.h"
@class MCLibraryController;
@interface MCCursorLibrary : NSObject <NSCopying>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *author;
@property (nonatomic, copy) NSString *identifier;
@property (nonatomic, copy) NSNumber *version;
@property (nonatomic, copy) NSURL *fileURL;
@property (nonatomic, weak) MCLibraryController *library;
@property (nonatomic, readonly) NSUndoManager *undoManager;
@property (nonatomic, readonly) BOOL isDirty;
@property (nonatomic, assign, getter = isInCloud) BOOL inCloud;
@property (nonatomic, assign, getter = isHiDPI) BOOL hiDPI;
+ (MCCursorLibrary *)cursorLibraryWithContentsOfFile:(NSString *)path;
+ (MCCursorLibrary *)cursorLibraryWithContentsOfURL:(NSURL *)URL;
+ (MCCursorLibrary *)cursorLibraryWithDictionary:(NSDictionary *)dictionary;
+ (MCCursorLibrary *)cursorLibraryWithCursors:(NSSet *)cursors;
- (instancetype)initWithContentsOfFile:(NSString *)path;
- (instancetype)initWithContentsOfURL:(NSURL *)URL;
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
- (instancetype)initWithCursors:(NSSet *)cursors;
- (NSSet *)cursorsWithIdentifier:(NSString *)identifier;
- (void)addCursor:(MCCursor *)cursor;
- (void)removeCursor:(MCCursor *)cursor;
- (void)removeCursorsWithIdentifier:(NSString *)identifier;
- (NSDictionary *)dictionaryRepresentation;
- (BOOL)writeToFile:(NSString *)file atomically:(BOOL)atomically;
- (BOOL)save;
- (void)updateChangeCount:(NSDocumentChangeType)change;
- (void)revertToSaved;
@end
@interface MCCursorLibrary (Properties)
@property (nonatomic, readonly, strong) NSSet *cursors;
@end
@@ -0,0 +1,371 @@
//
// MCCursorLibrary.m
// Mousecape
//
// Created by Alex Zielenski on 2/1/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCCursorLibrary.h"
@interface MCCursorLibrary ()
@property (nonatomic, strong) NSUndoManager *undoManager;
@property (nonatomic, readwrite, strong) NSMutableSet *cursors;
@property (nonatomic, assign) NSUInteger changeCount;
- (BOOL)_readFromDictionary:(NSDictionary *)dictionary;
- (void)addCursorsFromDictionary:(NSDictionary *)cursorDicts ofVersion:(CGFloat)doubleVersion;
- (void)startObservingProperties;
- (void)stopObservingProperties;
- (void)startObservingCursor:(MCCursor *)cursor;
- (void)stopObservingCursor:(MCCursor *)cursor;
+ (NSArray *)cursorUndoProperties;
+ (NSArray *)undoProperties;
@end
@implementation MCCursorLibrary
@dynamic isDirty;
+ (NSArray *)undoProperties {
return @[ @"identifier", @"name", @"author", @"hiDPI", @"version", @"inCloud" ];
}
+ (NSArray *)cursorUndoProperties {
return @[ @"identifier", @"frameDuration", @"frameCount", @"size", @"hotSpot", @"cursorRep100", @"cursorRep200", @"cursorRep500", @"cursorRep1000" ];
}
+ (MCCursorLibrary *)cursorLibraryWithContentsOfFile:(NSString *)path {
return [[MCCursorLibrary alloc] initWithContentsOfFile:path];
}
+ (MCCursorLibrary *)cursorLibraryWithContentsOfURL:(NSURL *)URL {
return [[MCCursorLibrary alloc] initWithContentsOfURL:URL];
}
+ (MCCursorLibrary *)cursorLibraryWithDictionary:(NSDictionary *)dictionary {
return [[MCCursorLibrary alloc] initWithDictionary:dictionary];
}
+ (MCCursorLibrary *)cursorLibraryWithCursors:(NSSet *)cursors {
return [[MCCursorLibrary alloc] initWithCursors:cursors];
}
- (instancetype)initWithContentsOfFile:(NSString *)path {
return [self initWithContentsOfURL:[NSURL fileURLWithPath:path]];
}
- (instancetype)initWithContentsOfURL:(NSURL *)URL {
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:URL];
if ((self = [self initWithDictionary:dictionary]))
self.fileURL = URL;
return self;
}
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
if ((self = [self init])) {
if (![self _readFromDictionary:dictionary]) {
return nil;
}
}
return self;
}
- (instancetype)initWithCursors:(NSSet *)cursors {
if ((self = [self init])) {
self.cursors = cursors.mutableCopy;
}
return self;
}
- (instancetype)init {
if ((self = [super init])) {
self.undoManager = [[NSUndoManager alloc] init];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
__weak typeof(self) weakSelf = self;
[center addObserverForName:NSUndoManagerDidCloseUndoGroupNotification object:self.undoManager queue:nil usingBlock:^(NSNotification *note) {
[weakSelf updateChangeCount:NSChangeDone];
}];
[center addObserverForName:NSUndoManagerDidUndoChangeNotification object:self.undoManager queue:nil usingBlock:^(NSNotification *note) {
[weakSelf updateChangeCount:NSChangeUndone];
}];
[center addObserverForName:NSUndoManagerDidRedoChangeNotification object:self.undoManager queue:nil usingBlock:^(NSNotification *note) {
[weakSelf updateChangeCount:NSChangeRedone];
}];
self.name = @"Unnamed";
self.author = NSUserName();
self.hiDPI = NO;
self.inCloud = NO;
self.identifier = [NSString stringWithFormat:@"local.%@.Unnamed.%f", self.author, [NSDate timeIntervalSinceReferenceDate]];
self.version = @1.0;
self.cursors = [NSMutableSet set];
[self startObservingProperties];
}
return self;
}
- (instancetype)copyWithZone:(NSZone *)zone {
MCCursorLibrary *lib = [[MCCursorLibrary allocWithZone:zone] initWithCursors:self.cursors];
[lib.undoManager disableUndoRegistration];
lib.name = self.name;
lib.author = self.author;
lib.hiDPI = self.hiDPI;
lib.inCloud = self.inCloud;
lib.version = self.version;
lib.identifier = [self.identifier stringByAppendingFormat:@".%f", [NSDate timeIntervalSinceReferenceDate]];
[lib.undoManager enableUndoRegistration];
return lib;
}
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@"isDirty"]) {
keyPaths = [keyPaths setByAddingObject: @"changeCount"];
}
return keyPaths;
}
- (BOOL)_readFromDictionary:(NSDictionary *)dictionary {
if (!dictionary || !dictionary.count) {
NSLog(@"cannot make library from empty dicitonary");
return NO;
}
for (MCCursor *cursor in self.cursors) {
[self stopObservingCursor:cursor];
}
self.cursors = [NSMutableSet set];
[self.undoManager disableUndoRegistration];
NSNumber *minimumVersion = dictionary[MCCursorDictionaryMinimumVersionKey];
NSNumber *version = dictionary[MCCursorDictionaryVersionKey];
NSDictionary *cursorDicts = dictionary[MCCursorDictionaryCursorsKey];
NSNumber *cloud = dictionary[MCCursorDictionaryCloudKey];
NSString *author = dictionary[MCCursorDictionaryAuthorKey];
NSNumber *hiDPI = dictionary[MCCursorDictionaryHiDPIKey];
NSString *identifier = dictionary[MCCursorDictionaryIdentifierKey];
NSString *capeName = dictionary[MCCursorDictionaryCapeNameKey];
NSNumber *capeVersion = dictionary[MCCursorDictionaryCapeVersionKey];
self.name = capeName;
self.version = capeVersion;
self.author = author;
self.identifier = identifier;
self.hiDPI = hiDPI.boolValue;
self.inCloud = cloud.boolValue;
if (!self.identifier) {
[self.undoManager enableUndoRegistration];
NSLog(@"cannot make library from dictionary with no identifier");
return NO;
}
CGFloat doubleVersion = version.doubleValue;
if (minimumVersion.doubleValue > MCCursorParserVersion) {
[self.undoManager enableUndoRegistration];
return NO;
}
[self.cursors removeAllObjects];
[self addCursorsFromDictionary:cursorDicts ofVersion:doubleVersion];
[self.undoManager enableUndoRegistration];
return YES;
}
- (void)dealloc {
[self stopObservingProperties];
for (MCCursor *cursor in self.cursors) {
[self stopObservingCursor:cursor];
}
}
const char MCCursorLibraryPropertiesContext;
- (void)startObservingProperties {
for (NSString *key in self.class.undoProperties) {
[self addObserver:self forKeyPath:key options:NSKeyValueObservingOptionOld context:(void*)&MCCursorLibraryPropertiesContext];
}
}
- (void)stopObservingProperties {
for (NSString *key in self.class.undoProperties) {
[self removeObserver:self forKeyPath:key context:(void *)&MCCursorLibraryPropertiesContext];
}
}
const char MCCursorPropertiesContext;
- (void)startObservingCursor:(MCCursor *)cursor {
for (NSString *key in self.class.cursorUndoProperties) {
[cursor addObserver:self forKeyPath:key options:NSKeyValueObservingOptionOld context:(void *)&MCCursorPropertiesContext];
}
}
- (void)stopObservingCursor:(MCCursor *)cursor {
for (NSString *key in self.class.cursorUndoProperties) {
[cursor removeObserver:self forKeyPath:key context:(void *)&MCCursorPropertiesContext];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == &MCCursorLibraryPropertiesContext || context == &MCCursorPropertiesContext) {
NSString *decamelized = [keyPath stringByReplacingOccurrencesOfString:@"([a-z])([A-Z])"
withString:@"$1 $2"
options:NSRegularExpressionSearch
range:NSMakeRange(0, keyPath.length)];
id oldValue = change[NSKeyValueChangeOldKey];
if ([oldValue isKindOfClass:[NSNull class]])
oldValue = nil;
[[self.undoManager prepareWithInvocationTarget: object] setValue:oldValue forKeyPath:keyPath];
if (!self.undoManager.isUndoing) {
[self.undoManager setActionName:[[@"Change " stringByAppendingString:decamelized] capitalizedString]];
}
}
}
- (void)addCursorsFromDictionary:(NSDictionary *)cursorDicts ofVersion:(CGFloat)doubleVersion {
for (NSString *key in cursorDicts.allKeys) {
NSDictionary *cursorDictionary = [cursorDicts objectForKey:key];
MCCursor *cursor = [MCCursor cursorWithDictionary:cursorDictionary ofVersion:doubleVersion];
if (!cursor)
continue;
cursor.identifier = key;
[self addCursor: cursor];
}
}
- (NSSet *)cursorsWithIdentifier:(NSString *)identifier {
NSPredicate *filter = [NSPredicate predicateWithFormat:@"identififer == %@", identifier];
return [self.cursors filteredSetUsingPredicate:filter];
}
- (void)addCursor:(MCCursor *)cursor {
if ([self.cursors containsObject:cursor]) {
// Don't unnecessarily add a cursor/register observers with it because the
// observation info will leak when it gets dereferenced since we don't do it here
// since NSSet just silently skips items it already has
return;
}
NSSet *change = [NSSet setWithObject:cursor];
[[self.undoManager prepareWithInvocationTarget:self] removeCursor:cursor];
if (!self.undoManager.isUndoing) {
[self.undoManager setActionName:@"Add Cursor"];
}
[self willChangeValueForKey:@"cursors" withSetMutation:NSKeyValueUnionSetMutation usingObjects:change];
[self.cursors addObject:cursor];
[self startObservingCursor:cursor];
[self didChangeValueForKey:@"cursors" withSetMutation:NSKeyValueUnionSetMutation usingObjects:change];
}
- (void)removeCursor:(MCCursor *)cursor {
NSSet *change = [NSSet setWithObject:cursor];
[[self.undoManager prepareWithInvocationTarget:self] addCursor:cursor];
if (!self.undoManager.isUndoing) {
[self.undoManager setActionName:@"Remove Cursor"];
}
[self willChangeValueForKey:@"cursors" withSetMutation:NSKeyValueMinusSetMutation usingObjects:change];
[self.cursors removeObject:cursor];
[self stopObservingCursor:cursor];
[self didChangeValueForKey:@"cursors" withSetMutation:NSKeyValueMinusSetMutation usingObjects:change];
}
- (void)removeCursorsWithIdentifier:(NSString *)identifier {
for (MCCursor *cursor in [self cursorsWithIdentifier:identifier])
[self removeCursor: cursor];
}
- (NSDictionary *)dictionaryRepresentation {
NSMutableDictionary *drep = [NSMutableDictionary dictionary];
drep[MCCursorDictionaryMinimumVersionKey] = @(2.0);
drep[MCCursorDictionaryVersionKey] = @(2.0);
drep[MCCursorDictionaryCapeNameKey] = self.name;
drep[MCCursorDictionaryCapeVersionKey] = self.version;
drep[MCCursorDictionaryCloudKey] = @(self.inCloud);
drep[MCCursorDictionaryAuthorKey] = self.author;
drep[MCCursorDictionaryHiDPIKey] = @(self.isHiDPI);
drep[MCCursorDictionaryIdentifierKey] = self.identifier;
NSMutableDictionary *cursors = [NSMutableDictionary dictionary];
for (MCCursor *cursor in self.cursors) {
cursors[cursor.identifier] = [cursor dictionaryRepresentation];
}
drep[MCCursorDictionaryCursorsKey] = cursors;
return drep;
}
- (BOOL)writeToFile:(NSString *)file atomically:(BOOL)atomically {
return [self.dictionaryRepresentation writeToFile:file atomically:atomically];
}
- (BOOL)save {
[self updateChangeCount:NSChangeCleared];
[self.undoManager removeAllActions];
return [self writeToFile:self.fileURL.path atomically:NO];
}
- (void)updateChangeCount:(NSDocumentChangeType)change {
if (change == NSChangeDone || change == NSChangeRedone) {
self.changeCount = self.changeCount + 1;
} else if (change == NSChangeUndone && self.changeCount > 0) {
self.changeCount = self.changeCount - 1;
} else if (change == NSChangeCleared || change == NSChangeAutosaved) {
self.changeCount = 0;
}
}
- (void)revertToSaved {
NSUInteger changes = self.changeCount;
[self updateChangeCount:NSChangeCleared];
for (NSUInteger x = 0; x < changes; x++) {
[self.undoManager undo];
}
[self.undoManager removeAllActions];
}
- (BOOL)isDirty {
return (self.changeCount);
}
- (BOOL)isEqualTo:(MCCursorLibrary *)object {
if (![object isKindOfClass:self.class]) {
return NO;
}
return ([object.name isEqualToString:self.name] &&
[object.author isEqualToString:self.author] &&
[object.identifier isEqualToString:self.identifier] &&
[object.version isEqualToNumber:self.version] &&
object.inCloud == self.inCloud &&
object.isHiDPI == self.isHiDPI &&
[object.cursors isEqualToSet:self.cursors]);
}
- (BOOL)isEqual:(id)object {
return [self isEqualTo:object];
}
@end
+17
View File
@@ -0,0 +1,17 @@
//
// MCFormatters.h
// Mousecape
//
// Created by Alex Zielenski on 2/24/13.
// Copyright (c) 2013 Alex Zielenski. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface MCPointFormatter : NSFormatter
@end
@interface MCSizeFormatter : NSFormatter
@end
+73
View File
@@ -0,0 +1,73 @@
//
// MCFormatters.m
// Mousecape
//
// Created by Alex Zielenski on 2/24/13.
// Copyright (c) 2013 Alex Zielenski. All rights reserved.
//
#import "MCFormatters.h"
@implementation MCPointFormatter
- (NSString *)stringForObjectValue:(NSValue *)anObject {
if (![anObject isKindOfClass:[NSValue class]]) {
return nil;
}
return NSStringFromPoint(anObject.pointValue);
}
- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error {
*anObject = [NSValue valueWithPoint:NSPointFromString(string)];
return YES;
}
- (BOOL)isPartialStringValid:(NSString *)partialString newEditingString:(NSString **)newString errorDescription:(NSString **)error {
NSArray *components = [partialString componentsSeparatedByString:@","];
if (components.count == 1) {
return YES;
} else if (components.count == 2) {
NSString *perfect = NSStringFromPoint(NSPointFromString(partialString));
*newString = perfect;
return YES;
}
*error = [NSError errorWithDomain:@"com.alexzielenski.mcformatter.errordoman" code:0 userInfo:@{NSLocalizedDescriptionKey: NSLocalizedString(@"Invalid format. Must follow \"{0.0, 0.0}\"." , @"Invalid format error in edit window")}];
return NO;
}
@end
@implementation MCSizeFormatter
- (NSString *)stringForObjectValue:(NSValue *)anObject {
if (![anObject isKindOfClass:[NSValue class]]) {
return nil;
}
return NSStringFromSize(anObject.sizeValue);
}
- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error {
*anObject = [NSValue valueWithSize:NSSizeFromString(string)];
return YES;
}
- (BOOL)isPartialStringValid:(NSString *)partialString newEditingString:(NSString **)newString errorDescription:(NSString **)error {
NSArray *components = [partialString componentsSeparatedByString:@","];
if (components.count == 1) {
return YES;
} else if (components.count == 2) {
NSString *perfect = NSStringFromSize(NSSizeFromString(partialString));
*newString = perfect;
return YES;
}
*error = [NSError errorWithDomain:@"com.alexzielenski.mcformatter.errordoman" code:0 userInfo:@{NSLocalizedDescriptionKey: NSLocalizedString(@"Invalid format. Must follow \"{0.0, 0.0}\"." , @"Invalid format error in edit window")}];
return NO;
}
@end
@@ -0,0 +1,18 @@
//
// MCCapeCellView.h
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface MCCapeCellView : NSTableCellView
@property (assign) IBOutlet NSTextField *titleField;
@property (assign) IBOutlet NSTextField *subtitleField;
@property (assign) IBOutlet NSImageView *appliedImageView;
@end
@interface MCHDValueTransformer : NSValueTransformer
@end
@@ -0,0 +1,33 @@
//
// MCCapeCellView.m
// Mousecape
//
// Created by Alex Zielenski on 2/2/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import "MCCapeCellView.h"
@implementation MCCapeCellView
- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle {
[super setBackgroundStyle:backgroundStyle];
//
}
@end
@implementation MCHDValueTransformer
+ (Class)transformedValueClass {
return [NSString class];
}
- (NSString *)transformedValue:(NSNumber *)value {
BOOL isHiDPI = value.boolValue;
return isHiDPI ? [NSImage imageNamed:@"HDTemplate"] : [NSImage imageNamed:@"SDTemplate"];
}
@end
+14
View File
@@ -0,0 +1,14 @@
//
// MCSpriteLayer.h
// Mousecape
//
// Created by Alex Zielenski on 2/10/13.
// Copyright (c) 2013 Alex Zielenski. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
@interface MCSpriteLayer : CALayer
@property (assign) NSUInteger frameCount;
@property (assign) NSUInteger sampleIndex;
@end
+60
View File
@@ -0,0 +1,60 @@
//
// MCSpriteLayer.m
// Mousecape
//
// Created by Alex Zielenski on 2/10/13.
// Copyright (c) 2013 Alex Zielenski. All rights reserved.
//
#import "MCSpriteLayer.h"
@interface MCSpriteLayer ()
- (NSUInteger)currentSampleIndex;
@end
@implementation MCSpriteLayer
- (id)init {
if ((self = [super init])) {
self.sampleIndex = 1;
self.frameCount = 1;
self.anchorPoint = CGPointZero;
}
return self;
}
#pragma mark -
#pragma mark Frame by frame animation
+ (BOOL)needsDisplayForKey:(NSString *)key {
return [key isEqualToString:@"sampleIndex"] || [key isEqualToString:@"frameCount"];
}
+ (id < CAAction >)defaultActionForKey:(NSString *)aKey; {
return (id < CAAction >)[NSNull null];
}
- (NSUInteger)currentSampleIndex {
return ((MCSpriteLayer *)[self presentationLayer]).sampleIndex;
}
// Implement displayLayer: on the delegate to override how sample rectangles are calculated; remember to use currentSampleIndex, ignore sampleIndex == 0, and set the layer's bounds
- (void)display {
if ([self.delegate respondsToSelector:@selector(displayLayer:)]) {
[self.delegate displayLayer:self];
return;
}
NSUInteger currentSampleIndex = [self currentSampleIndex];
if (!currentSampleIndex) {
return;
}
CGSize sampleSize = NSMakeSize(1.0, 1.0 / (self.frameCount ? self.frameCount : 1.0));
self.contentsRect = CGRectMake(0, (currentSampleIndex - 1) * sampleSize.height, sampleSize.width, sampleSize.height);
}
@end
@@ -25,33 +25,14 @@
//!** This is a specialized view class for animating the cursors used in magic mouse. These animated cursors have a height that is their **//
//!** frame count multiplied by the normal image height so every time the timer fires, it moves the y offset displayed by the image. **//
//!****************************************************************************************************************************************//
@interface MMAnimatingImageView : NSView {
// Image to animate
NSBitmapImageRep *_image;
// Time in seconds of each frame
CGFloat _frameDuration;
// Amount of frames
NSInteger _frameCount;
@private
// Timer fires for every frame
NSTimer *frameTimer;
// Cursor size, not image size. Size the cursor gets displayed by
NSSize imageSize;
// Current rectangle to take out of the cursor image for display
NSRect currentImageFrame;
// Current frame we are on during animation
NSInteger currentFrame;
}
@property (nonatomic, retain) NSBitmapImageRep *image;
@property (nonatomic, assign) CGFloat frameDuration;
@property (nonatomic, assign) NSInteger frameCount;
@property (nonatomic, assign) IBOutlet id <MMAnimatingImageViewDelegate> delegate;
// Resets the timer and current frame for the animation. Should be used when new parameters are specified.
// The reason this isn't called automatically when each new parameter is set because that would waste resources.
- (void)resetAnimation;
// Don't call this. Registers the valid drag types. Probably should be a private categorybut we're all developers here...
- (void)registerTypes;
@interface MMAnimatingImageView : NSView
@property (strong) NSImage *image;
@property (strong) NSImage *placeholderImage;
@property (assign) CGFloat frameDuration;
@property (assign) NSInteger frameCount;
@property (assign) CGFloat scale; // set to 0.0 if you want to inherit window scale
@property (assign) NSPoint hotSpot;
@property (weak) IBOutlet id <MMAnimatingImageViewDelegate> delegate;
@property (assign) BOOL shouldAnimate;
@property (assign) BOOL shouldShowHotSpot;
@end
+222
View File
@@ -0,0 +1,222 @@
//
// MMAnimatingImageView.m
// Magic Mouse
//
// Created by Alex Zielenski on 2/25/12.
// Copyright (c) 2012 Alex Zielenski. All rights reserved.
//
#import "MMAnimatingImageView.h"
#import "MCSpriteLayer.h"
const char MCInvalidateContext;
@interface MMAnimatingImageView ()
@property (weak) MCSpriteLayer *spriteLayer;
@property (weak) CALayer *hotSpotLayer;
- (void)_initialize;
- (void)_invalidateFrame;
- (void)_invalidateAnimation;
- (void)registerTypes;
@end
@implementation MMAnimatingImageView
@dynamic shouldShowHotSpot;
- (id)init {
if ((self = [super init])) {
[self _initialize];
}
return self;
}
- (id)initWithCoder:(NSCoder *)coder {
if ((self = [super initWithCoder:coder])) {
[self _initialize];
}
return self;
}
- (id)initWithFrame:(NSRect)frame {
if ((self = [super initWithFrame:frame])) {
[self _initialize];
}
return self;
}
- (void)_initialize {
self.shouldAnimate = YES;
[self registerTypes];
self.layer = [[MCSpriteLayer alloc] init];
self.wantsLayer = YES;
self.layer.contentsGravity = kCAGravityCenter;
self.layer.bounds = self.bounds;
self.layer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable | kCALayerMinXMargin | kCALayerMinYMargin;
self.layer.delegate = self;
CALayer *hotSpotLayer = [CALayer layer];
hotSpotLayer.bounds = CGRectMake(0, 0, 3, 3);
hotSpotLayer.backgroundColor = [[NSColor redColor] CGColor];
hotSpotLayer.autoresizingMask = kCALayerNotSizable;
[self.layer addSublayer:hotSpotLayer];
self.hotSpotLayer = hotSpotLayer;
self.spriteLayer = (MCSpriteLayer *)self.layer;
self.frameCount = 1;
self.frameDuration = 1;
[self addObserver:self forKeyPath:@"image" options:0 context:(void *)&MCInvalidateContext];
[self addObserver:self forKeyPath:@"hotSpot" options:0 context:(void *)&MCInvalidateContext];
[self addObserver:self forKeyPath:@"placeholderImage" options:0 context:(void *)&MCInvalidateContext];
[self addObserver:self forKeyPath:@"frameCount" options:0 context:(void *)&MCInvalidateContext];
[self addObserver:self forKeyPath:@"frameDuration" options:0 context:(void *)&MCInvalidateContext];
[self addObserver:self forKeyPath:@"shouldAnimate" options:0 context:NULL];
}
- (void)dealloc {
[self removeObserver:self forKeyPath:@"image"];
[self removeObserver:self forKeyPath:@"hotSpot"];
[self removeObserver:self forKeyPath:@"placeholderImage"];
[self removeObserver:self forKeyPath:@"frameCount"];
[self removeObserver:self forKeyPath:@"frameDuration"];
[self removeObserver:self forKeyPath:@"shouldAnimate"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == &MCInvalidateContext) {
if ([keyPath isEqualToString:@"image"] || [keyPath isEqualToString:@"placeholderImage"]) {
self.spriteLayer.contents = !self.image ? self.placeholderImage : self.image;
}
[self _invalidateFrame];
[self _invalidateAnimation];
} else if ([keyPath isEqualToString:@"shouldAnimate"]) {
[self _invalidateAnimation];
}
}
- (BOOL)layer:(CALayer *)layer shouldInheritContentsScale:(CGFloat)newScale fromWindow:(NSWindow *)window {
return self.scale == 0.0 || !self.image;
}
// Tell OSX that our view can accept images to be dragged in
- (void)registerTypes {
[self registerForDraggedTypes:[NSArray arrayWithObjects:NSPasteboardTypeTIFF, NSPasteboardTypePNG, NSFilenamesPboardType, nil]];
}
- (void)viewDidMoveToWindow {
[self _invalidateFrame];
}
+ (NSSet *)keyPathsForValuesAffectingShouldShowHotSpot {
return [NSSet setWithObject:@"hotSpotLayer.hidden"];
}
- (BOOL)shouldShowHotSpot {
return !self.hotSpotLayer.isHidden;
}
- (void)setShouldShowHotSpot:(BOOL)shouldShowHotSpot {
self.hotSpotLayer.hidden = !shouldShowHotSpot;
}
#pragma mark - Invalidators
- (void)_invalidateFrame {
CGFloat scale = self.scale;
if (!self.scale || !self.image)
scale = self.window.backingScaleFactor;
self.layer.contentsScale = scale;
if (scale == 0.0)
scale = 1.0;
if (self.image) {
CGSize effectiveSize = CGSizeMake(self.image.size.width, self.image.size.height / self.frameCount);
CGRect effectiveRect = CGRectIntegral(CGRectMake(self.layer.frame.size.width / 2.0 - effectiveSize.width / 2.0, self.layer.frame.size.height / 2.0 + effectiveSize.height / 2.0, effectiveSize.width, effectiveSize.height));
self.hotSpotLayer.position = CGPointMake(CGRectGetMinX(effectiveRect) + self.hotSpot.x, CGRectGetMinY(effectiveRect) - self.hotSpot.y);
self.hotSpotLayer.opacity = 1.0;
} else {
self.hotSpotLayer.opacity = 0.0;
}
}
- (void)_invalidateAnimation {
[self.spriteLayer removeAllAnimations];
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"sampleIndex"];
BOOL none = (self.frameCount == 1 || !self.shouldAnimate);
NSUInteger frameCount = none || !self.image ? 0 : self.frameCount;
self.spriteLayer.frameCount = frameCount;
anim.fromValue = @(frameCount + 1);
anim.toValue = @(1);
anim.byValue = @(-1);
anim.duration = self.frameDuration * frameCount;
anim.repeatCount = none ? 0 : HUGE_VALF; // just keep repeating it
anim.autoreverses = NO; // do 1, 2, 3, 4, 5, 1, 2, 3, 4, 5
anim.removedOnCompletion = none;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[self.spriteLayer addAnimation:anim forKey:@"sampleIndex"]; // start
}
- (id <CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event {
return (id <CAAction>)[NSNull null];
}
#pragma mark - NSDragDestination
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
// Only thing we have to do here is confirm that the dragged file is an image. We use NSImage's +canInitWithPasteboard: and we also check to see there is only one item being dragged
if ([self.delegate conformsToProtocol:@protocol(MMAnimatingImageViewDelegate)] && // No point in accepting the drop if the delegate doesn't support it/exist
[NSImage canInitWithPasteboard:sender.draggingPasteboard] && // Only Accept Images
sender.draggingPasteboard.pasteboardItems.count == 1) { // Only accept one item
return [self.delegate imageView:self draggingEntered:sender];
}
return NSDragOperationNone;
}
// Give the delegate some more control
- (BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender {
if ([self.delegate conformsToProtocol:@protocol(MMAnimatingImageViewDelegate)]) {
return [self.delegate imageView:self shouldPerformDragOperation:sender];
}
return NO;
}
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
if ([self.delegate conformsToProtocol:@protocol(MMAnimatingImageViewDelegate)] && // Only do the operation if a delegate exists to actually set the image.
[self.delegate imageView:self shouldPerformDragOperation:sender]) { // Only do the operation if a delegate wants us to do the operation.
// Get the image from the pasteboard
NSImage *im = [[NSImage alloc] initWithPasteboard:sender.draggingPasteboard];
// Make an array of the valid drops (NSBitmapImageRep)
NSMutableArray *acceptedDrops = [NSMutableArray arrayWithCapacity:im.representations.count];
for (NSImageRep *rep in im.representations) {
if (![rep isKindOfClass:[NSBitmapImageRep class]]) // We don't want PDFs
continue;
[acceptedDrops addObject:rep];
}
if (acceptedDrops.count > 0) {
// We already confirmed that the delegate conforms to the protocol above. Now we can let the delegate
// decide what to do with the dropped images.
[self.delegate imageView:self didAcceptDroppedImages:acceptedDrops];
}
return YES;
}
return NO;
}
@end
@@ -3,17 +3,13 @@
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.alexzielenski.magicmouse-prefs</string>
<string>com.alexzielenski.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
@@ -21,16 +17,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>246</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2012 Alex Zielenski. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>Magic_Mouse</string>
<key>NSPrefPaneIconFile</key>
<string>cursor.png</string>
<key>NSPrefPaneIconLabel</key>
<string>Magic Mouse</string>
<key>NSPrincipalClass</key>
<string>MMPrefPane</string>
<string>1</string>
</dict>
</plist>
+69
View File
@@ -0,0 +1,69 @@
//
// MousecapeTests.m
// MousecapeTests
//
// Created by Alex Zielenski on 2/1/14.
// Copyright (c) 2014 Alex Zielenski. All rights reserved.
//
#import <XCTest/XCTest.h>
#import "MCCursorLibrary.h"
@interface MousecapeTests : XCTestCase
@property (strong) MCCursorLibrary *library;
@end
@implementation MousecapeTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
self.library = [MCCursorLibrary cursorLibraryWithContentsOfFile:[@(PROJECT_DIR) stringByAppendingPathComponent: @"com.maxrudberg.svanslosbluehazard.cape"]];
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testLibraryCreation {
XCTAssertTrue(self.library != nil, @"Library must not be nil");
XCTAssertEqualObjects(self.library.author, @"Max Rudberg", @"Author must be taken from cape");
XCTAssertEqualObjects(self.library.identifier, @"com.maxrudberg.svanslosbluehazard", @"Identifier must be taken from cape");
XCTAssertNotNil([self.library cursorWithIdentifier:@"com.apple.coregraphics.Arrow"], @"Must retrieve cursor correctly");
}
- (void)testCursorCreation {
MCCursor *cursor = [self.library cursorWithIdentifier:@"com.apple.coregraphics.Arrow"];
XCTAssertTrue(cursor.representations.count == 4, @"Must have correct cursor count");
XCTAssertTrue(cursor.frameCount == 1, @"Must have correct frame count");
XCTAssertTrue(cursor.frameDuration == 1, @"Must have current frame duration");
XCTAssertTrue(NSEqualSizes(cursor.size, NSMakeSize(20, 24)), @"Must have correct size");
NSImageRep *smallest = [cursor representationForScale:MCCursorScale100];
XCTAssertTrue(NSEqualSizes(NSMakeSize(smallest.pixelsWide, smallest.pixelsHigh), cursor.size), @"Size must be equal to 1x rep");
}
- (void)testCursorOperations {
MCCursor *cursor = [self.library cursorWithIdentifier:@"com.apple.coregraphics.Arrow"];
[self.library moveCursorAtIdentifier:@"com.apple.coregraphics.Arrow" toIdentifier:@"com.apple.cursor.2"];
XCTAssertEqualObjects(cursor.name, nameForCursorIdentifier(@"com.apple.cursor.2"), @"Name must be correctly set");
XCTAssertEqual(cursor, [self.library cursorWithIdentifier:@"com.apple.cursor.2"], @"Object must not be copied");
XCTAssertEqualObjects(cursor, cursor, @"isEqualTo: must work");
XCTAssertNil([self.library cursorWithIdentifier:@"com.apple.coregraphics.Arrow"], @"Old cursor spot must not be occupied");
MCCursor *replacement = [[MCCursor alloc] init];
[self.library setCursor:replacement forIdentifier:@"com.apple.cursor.2"];
XCTAssertEqualObjects(cursor.name, @"", @"Name of old cursor must be set to an empty string");
XCTAssertEqual(replacement, [self.library cursorWithIdentifier:@"com.apple.cursor.2"], @"Replacement cursor must be retrievable");
}
- (void)testSavingAndReading {
NSDictionary *dictionary = self.library.dictionaryRepresentation;
MCCursorLibrary *read = [MCCursorLibrary cursorLibraryWithDictionary:dictionary];
XCTAssertEqualObjects(self.library, read, @"Saving and reading must result in equal objects");
}
@end
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More