Compare commits

...
627 Commits
Author SHA1 Message Date
Ross Boucher 595c70ed56 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-18 14:28:33 -08:00
Alexander LjungbergandRoss Boucher 9faec8decd Fixed: calling setIsPaneSplitter: on a CPTableView would change the divider width but the subviews would not change size to match. 2009-11-18 14:22:58 -08:00
Tom Robinson 90dc1f6cf8 Reorder shell config file checks. 2009-11-18 01:34:01 -08:00
Francisco Ryan Tolmasky I ba01976151 Added target and action to radio groups.
Reviewed by me.
2009-11-17 19:52:20 -08:00
Francisco Ryan Tolmasky I 4d7f5a8a09 Fix for fixing state after turning setAllowsMixedState to NO.
Reviewed by me.
2009-11-17 19:17:58 -08:00
Ross Boucher 2d01fa6f94 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-17 17:04:12 -08:00
Ross Boucher 970f848b84 Make CPAlert slightly (but only slightly) more externally hackable 2009-11-17 17:03:42 -08:00
Tom Robinson 31feec0465 Flush stdin after writing file to ShrinkSafe process (fixes building in Rhino) 2009-11-17 17:02:07 -08:00
Francisco Ryan Tolmasky I 2466c14300 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-17 14:49:30 -08:00
Francisco Ryan Tolmasky I 49927fcfb7 Fix for building projects where source files are in nested subfolders.
Reviewed by me.
2009-11-17 14:46:54 -08:00
Ross Boucher f612683dfb Taking this out for now. 2009-11-17 10:26:58 -08:00
Ross Boucher 11e6ad2153 Adding a simple way to set a function for the target/action 2009-11-17 09:28:44 -08:00
Klaas Pieter AnnemaandRoss Boucher d041c69e0d Added a check if the window is loaded in CPWindowController 2009-11-17 09:19:05 -08:00
Randall LueckeandRoss Boucher b394052145 fixed tableview typo 2009-11-17 09:16:30 -08:00
Francisco Ryan Tolmasky I bce83e45b5 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-16 18:28:04 -08:00
Francisco Ryan Tolmasky I 77bd8d3a76 Add hide: and hideOthers support.
Reviewed by me.
2009-11-16 18:27:38 -08:00
Tom Robinson 118ece9f1c Implement "which" for bootstrap and switch to 280north repos. 2009-11-16 17:11:05 -08:00
Francisco Ryan Tolmasky I 971956a6ba Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-16 15:09:51 -08:00
Francisco Ryan Tolmasky I 48cd362015 Fix for using unicode characters with capp config.
Reviewed by me.
2009-11-16 15:09:22 -08:00
Tom Robinson b12b1bf662 Incorrect case in require("os") 2009-11-16 14:12:53 -08:00
Francisco Ryan Tolmasky I 6829d502d7 Better support for opening files.
Reviewed by me.
2009-11-16 11:47:06 -08:00
Francisco Ryan Tolmasky I aa8689a4f0 Fix for compiling with spaces in path name and misidentifying IE.
Reviewed by me.
2009-11-15 19:13:13 -08:00
Francisco Ryan Tolmasky I 44cbcc60fa Check for gcc.
Reviewed by me.
2009-11-15 15:07:58 -08:00
Francisco Ryan Tolmasky I d4edb28837 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-15 14:46:59 -08:00
Francisco Ryan Tolmasky I 3245f38788 nib2cib fix for pull down menus.
Reviewed by me.
2009-11-15 14:45:46 -08:00
Ross Boucher 392cca1b2a Look for uppercase charactrs OR shift keys for determining shift key mask status on menu items 2009-11-15 12:51:48 -08:00
Francisco Ryan Tolmasky I ad901ed4b0 Added convinience method to applicationtask for grabbing the built index file.
Reviewed by me.
2009-11-15 07:38:28 -08:00
Francisco Ryan Tolmasky I 8f1e56e398 Implemented manual validation for toolbar items and fixed a number of toolbar bugs.
Closes #43.
Closes #48.

Reviewed by me.
2009-11-15 00:35:52 -08:00
Francisco Ryan Tolmasky I b694437dba Fix for flash when closing windows.
Reviewed by me.
2009-11-14 19:58:40 -08:00
Francisco Ryan Tolmasky I 370efb35aa Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-14 19:57:59 -08:00
Francisco Ryan Tolmasky I dc93f39b58 Fix for infinite loop with inserting newlines and interpretKeyEvents:.
Reviewed by me.
2009-11-14 19:57:31 -08:00
Ross Boucher 629c8669c2 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-14 17:04:51 -08:00
Ross Boucher 558dbdc612 Some documentation. Eventually I will rewrite all of the key event stuff to work like Google Closure using this documentation 2009-11-14 17:04:18 -08:00
Ross Boucher 1944f51f97 Hack for desktop Capp key events 2009-11-14 17:04:02 -08:00
Francisco Ryan Tolmasky I 312a48a3fe Fix for borderless bridge windows showing and allowing the user to use resize indicator.
Reviewed by me.
2009-11-14 14:41:09 -08:00
Francisco Ryan Tolmasky I 5fc67ff7de Fix for CPScrollView not updating appropriately when using setShowsVerticalScroller: and setShowsHorizontalScroller:.
Reviewed by me.
2009-11-14 13:24:58 -08:00
Francisco Ryan Tolmasky I d584b4dccf Minor radio button change on init and info plist dependency.
Reviewed by me.
2009-11-14 10:57:19 -08:00
Francisco Ryan Tolmasky I 9d50b33268 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-14 07:25:37 -08:00
Francisco Ryan Tolmasky I 722166a9d2 Fix for default Jakefile for themes.
Reviewed by me.
2009-11-14 07:24:54 -08:00
Ross Boucher ec83a0f779 Add some support for setting save panel properties in desktop mode 2009-11-13 22:24:55 -08:00
Ross Boucher e20311c25a minor text field change 2009-11-13 22:24:45 -08:00
Francisco Ryan Tolmasky I c21fb3bb26 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-13 17:40:02 -08:00
Francisco Ryan Tolmasky I 9dfdde674f Fix for off by one error in HTML 5 Safari drag and drop, as well as error when building with Rhino Narwhal.
Reviewed by me.
2009-11-13 17:39:16 -08:00
tlrobinson f4b37fbf3b Add sudo to jake install. Add narwhal.local.conf. Remove tusk engine. 2009-11-13 13:58:23 -08:00
Francisco Ryan Tolmasky I 13c5736a0f Fix for capp gen sometimes failing.
Reviewed by me.
2009-11-13 10:10:26 -08:00
Ross Boucher 47de360719 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-13 08:43:38 -08:00
tlrobinson 19e3d93f1a Print warning and exit if a required package is missing. 2009-11-12 20:42:07 -08:00
Ross Boucher 2d5aef6157 Fix for **** type in DocumentController, and an Info.plist bug in bundle tasks. 2009-11-12 20:37:56 -08:00
Ross Boucher 29785e21cd Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-12 18:08:55 -08:00
Francisco Ryan Tolmasky I 95612b256f Fix for broken rm_rf reference in bundletask, as well as using Info.plist by default.
Reviewed by me.
2009-11-12 17:34:11 -08:00
Ross Boucher a3a03d702c Remove a few IE bugs. 2009-11-12 15:54:52 -08:00
Ross Boucher 742df0df82 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-12 11:24:47 -08:00
Ross Boucher aaac5e429d New textfield code that passes keyboard events through the standard mechanisms. Still broken in IE. 2009-11-12 11:24:23 -08:00
Francisco Ryan Tolmasky I c3ac3ddd3f A few fixes to drag and drop.
Reviewed by me.
2009-11-12 04:15:43 -08:00
Francisco Ryan Tolmasky I 61c0d33b4d Made shadows more robust with platform windows.
Reviewed by me.
2009-11-12 01:46:10 -08:00
Francisco Ryan Tolmasky I 67672ebb0c Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-12 01:28:53 -08:00
Francisco Ryan Tolmasky I 6132243968 Fix intersectsSet: in CPSet.
Reviewed by me.
2009-11-12 00:50:34 -08:00
Tom Robinson 88635ed440 bootstrap.sh changes: reorder shell config checks, add option to set JSC to default, misc cleanup. 2009-11-11 17:59:01 -08:00
Tom Robinson 3d42cba823 Fix capp gen -f . putting frameworks in / 2009-11-11 15:25:27 -08:00
Francisco Ryan Tolmasky I 51a58f650e Minor cleanup issues.
Reviewed by me.
2009-11-11 10:07:57 -08:00
Tom Robinson 6c79a31b38 Jake task for pushing built packages. Only to be used by maintainers, unless remote URLs are changed. 2009-11-11 05:02:12 -08:00
Francisco Ryan Tolmasky I 91ffb0ea0c Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-11 02:14:08 -08:00
Francisco Ryan Tolmasky I 77c74412dc Update shrinksafe for 1.5 support.
Reviewed by me.
2009-11-11 02:13:41 -08:00
Ross Boucher 008a320e6a Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-09 21:35:31 -08:00
Francisco Ryan Tolmasky I f3e90f87b1 Fixed a typo that caused non-IE configurations to stop spriting images.
Reviewed by me.
2009-11-09 14:35:28 +01:00
Francisco Ryan Tolmasky I 11b881273e Put MHTML contents into .sj.
Reviewed by me.
2009-11-09 13:57:00 +01:00
Ross Boucher 229debc2b7 Fixes a bug in testHasSuffix, adds test cases for hasSuffix and hasPrefix. 2009-11-09 13:11:04 +01:00
Francisco Ryan Tolmasky I 0c24a60bac Support setting sources per environment.
Reviewed by me.
2009-11-05 01:02:38 -08:00
Francisco Ryan Tolmasky I 2aa061a6af Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-05 00:05:02 -08:00
Francisco Ryan Tolmasky I 8f9d83495c Use interactive shrinksafe to improve buildtimes.
Reviewed by me.
2009-11-05 00:04:37 -08:00
Francisco Ryan Tolmasky I cb18896137 First pass at spriting in IE.
Reviewed by me.
2009-11-04 21:38:24 -08:00
Ross Boucher b13eee1fc9 Merge branch 'master' into jake 2009-11-04 14:24:10 -08:00
Ross Boucher 95c3401640 Fix some old calls to _bridgeMouseEvent: which were not updated 2009-11-04 14:23:30 -08:00
Francisco Ryan Tolmasky I 2f40cff3e2 Changed log message.
Reviewed by me.
2009-11-03 14:14:08 -08:00
Francisco Ryan Tolmasky I 848828222b Updated cappuccino dependency on objective-j. Also removed old install-tools script to remove confusion.
Reviewed by me.
2009-11-03 01:54:53 -08:00
Francisco Ryan Tolmasky I d3e6819fd7 Fix for cibs not being properly copied when built, also fixes Debug Objective-J not being placed in the objective-j package.
Reviewed by me.
2009-11-02 21:09:41 -08:00
Tom Robinson 55bbfc9205 Merge branch 'jake' of github.com:280north/cappuccino into jake 2009-11-02 19:39:09 -08:00
Tom Robinson b6e9625729 Update capp gen to use objj-frameworks data. 2009-11-02 19:38:48 -08:00
Francisco Ryan Tolmasky I fe91331dc4 Updated readme file to remove references to rake.
Reviewed by me.
2009-11-02 19:38:25 -08:00
Francisco Ryan Tolmasky I cf946c62a8 Merge branch 'master' of git@github.com:280north/cappuccino into jake 2009-11-02 19:22:29 -08:00
Francisco Ryan Tolmasky I 420ce1799a Added check to make sure user is using the right versions of jake and browserjs.
Reviewed by me.
2009-11-02 18:31:14 -08:00
Francisco Ryan Tolmasky I 72adaa51ee Skip all images, not just .gif.
Reviewed by me.
2009-11-02 17:36:13 -08:00
Francisco Ryan Tolmasky I 695f60aefc Replaced Rakefile with Jakefile for NibApplication template.
Reviewed by me.
2009-11-02 17:30:47 -08:00
Francisco Ryan Tolmasky I e00c2f3c05 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-02 17:24:50 -08:00
Francisco Ryan Tolmasky I 7ae0f1fec9 Updated Application and ThemeDescriptor templates to use jake instead of rake. Also made all objective-j jake definitions accessible through cappuccino/jake as well.
Reviewed by me.
2009-11-02 17:23:50 -08:00
Tom Robinson 6b3f05f517 Several fixes in "capp": handle empty config file, skip reading gifs, escape config keys in regex 2009-11-02 17:03:16 -08:00
Ross Boucher 93c90274b5 Updates for massaging a few key inputs. 2009-11-02 16:47:07 -08:00
Francisco Ryan Tolmasky I 2d1d30a663 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-02 16:01:02 -08:00
Francisco Ryan Tolmasky I baa1318298 Further cleanup.
Reviewed by me.
2009-11-02 15:59:42 -08:00
Tom Robinson 8fddc2370b Update test task. 2009-11-02 15:31:14 -08:00
Francisco Ryan Tolmasky I ea8245a6b3 Added an additional warning to the rake message.
Reviewed by me.
2009-11-02 15:20:23 -08:00
Francisco Ryan Tolmasky I d508459480 Added jake as a dependency for objective-j and cappuccino packages.
Reviewed by me.
2009-11-02 15:10:26 -08:00
Francisco Ryan Tolmasky I 6fc56226ba Removed jack as a dependency for packages.
Reviewed by me.
2009-11-02 15:04:00 -08:00
Francisco Ryan Tolmasky I c98107b6b8 Updated necessary tusk installs.
Reviewed by me.
2009-11-02 15:01:56 -08:00
Francisco Ryan Tolmasky I 17d68eeb97 Cleaned up a few unused Rakefiles and added warning to main Rakefile.
Reviewed by me.
2009-11-02 14:58:21 -08:00
Francisco Ryan Tolmasky I a457145312 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-02 14:50:51 -08:00
Francisco Ryan Tolmasky I 0c13138a20 Split up objective-j and cappuccino CommonJS packages, and added ability to include Objective-J frameworks in CommonJS packages.
Reviewed by me.
2009-11-02 14:49:58 -08:00
Tom Robinson e8b1ff8846 Another Array().join() trick off-by-one bug. 2009-11-02 00:37:40 -08:00
saikatandTom Robinson eeae653c94 Made secure text fields have the right number of characters when focus is taken away from them. Closes issue #318. 2009-11-02 00:35:53 -08:00
Tom Robinson 6d402bdc00 Install narwhal-jsc on OS X in bootstrap.sh. Add newline when appending PATH 2009-11-01 23:19:11 -08:00
Francisco Ryan Tolmasky I fddf3d70ff Fixed typo in bootstrap.sh prompt.
Reviewed by me.
2009-11-01 22:54:25 -08:00
Francisco Ryan Tolmasky I 87e39bc707 Added .bash_login to searched files in bootstrap.sh.
Reviewed by me.
2009-11-01 22:50:22 -08:00
Tom Robinson 7c4f01d81b bootstrap.sh script 2009-11-01 20:45:36 -08:00
Francisco Ryan Tolmasky I 96523aca07 Merge branch 'master' into jake 2009-11-01 15:11:51 -08:00
Francisco Ryan Tolmasky I 1ceeec8b5b Fixed typo in NSEvent.j.
Reviewed by me.
2009-11-01 15:05:22 -08:00
Francisco Ryan Tolmasky I cba546880b Added some missing import statements.
Reviewed by me.
2009-11-01 14:23:48 -08:00
Francisco Ryan Tolmasky I 2355cf4f6c Fixed performKeyEquivalent: order (execute on view hierarchy first, then menus).
Reviewed by me.
2009-11-01 13:05:49 -08:00
Ross Boucher 2c0e717b23 Merge branch 'master' of git@github.com:280north/cappuccino 2009-11-01 11:21:56 -08:00
Ross Boucher 8745843105 Change method name 2009-11-01 11:21:34 -08:00
Tom Robinson ef252a97c4 Merge branch 'master' of github.com:280north/cappuccino 2009-10-31 18:47:54 -07:00
Francisco Ryan Tolmasky I 14ad8f6d6d Cleaned up key equivalent handling and added support for key equivalents
to nib2cib.

Reviewed by me.
2009-10-31 18:32:58 -07:00
Ross BoucherandFrancisco Ryan Tolmasky I bcd8c72ae4 Add an unsaved state affordance to the close button on standard windows. 2009-10-31 18:22:27 -07:00
Francisco Ryan Tolmasky I 499d2d93d5 Added import just in case.
Reviewed by me.
2009-10-31 18:22:27 -07:00
Francisco Ryan Tolmasky I 84f131808d Removed some remaining cell "influences" in nib2cib'ed cib. There are references to NSCells in the object graph which should be removed, their children promoted to their parent's children.
Reviewed by me.
2009-10-31 18:22:27 -07:00
Ross Boucher 79fa65624d Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-31 09:52:52 -07:00
Ross Boucher 9ca96bc909 Add desktop support for recent file list 2009-10-31 09:52:26 -07:00
Francisco Ryan Tolmasky I 3dbddcf186 Added makeObjectsPerformSelector:withObjects:.
Reviewed by me.
2009-10-30 18:02:33 -07:00
Ross Boucher df8c648d70 Add an unsaved state affordance to the close button on standard windows. 2009-10-30 10:53:47 -07:00
Ross Boucher ee7c71a184 Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-29 22:22:51 -07:00
Ross Boucher de163e22d9 Add disabled states for all the existing controls. 2009-10-29 22:22:27 -07:00
Francisco Ryan Tolmasky I d9ef4342b6 Merge branch 'master' into jake 2009-10-29 21:35:15 -07:00
Francisco Ryan Tolmasky I e75ef74ea5 Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-29 21:32:13 -07:00
Ross Boucher 2e26db5bf5 Add mixed states to checkboxes. 2009-10-29 21:17:12 -07:00
Francisco Ryan Tolmasky I fe1c45980d Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-29 20:46:24 -07:00
Ross Boucher 0423546451 Update to the new close/warn stuff to correctly support multiple windows per document and multiple documents per window. 2009-10-29 16:33:56 -07:00
Francisco Ryan Tolmasky I 8da4ea0823 Added import just in case.
Reviewed by me.
2009-10-29 16:25:05 -07:00
Francisco Ryan Tolmasky I c48d9a01c6 Removed some remaining cell "influences" in nib2cib'ed cib. There are references to NSCells in the object graph which should be removed, their children promoted to their parent's children.
Reviewed by me.
2009-10-29 00:53:13 -07:00
Ross Boucher 4ca0044bbd Add isEqual: to CPDate 2009-10-28 23:38:58 -07:00
Ross Boucher 9f2ea190fc Make text field KVO compliant again. 2009-10-28 20:20:33 -07:00
Ross Boucher 4248348308 Updates to the way notifications work. New notifications for focus/blur. 2009-10-28 20:01:00 -07:00
Ross Boucher eaf701beca Support key paths instead of simple keys in sort descriptors. Match Cocoa's behavior here. 2009-10-28 16:24:41 -07:00
Francisco Ryan Tolmasky I a48a305cd8 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-10-28 00:59:27 -07:00
Francisco Ryan Tolmasky I cc334296bb Merge branch 'master' into jake
Conflicts:
	Objective-J/CommonJS/objective-j/lib-js/objective-j/compiler.js
2009-10-28 00:59:14 -07:00
Francisco Ryan Tolmasky I bb2726fb9a downloads, documentation, and deploy tasks.
Reviewed by me.
2009-10-28 00:55:51 -07:00
Ross Boucher 95b9ea336b Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-28 00:12:29 -07:00
Ross Boucher ba84e6d3e2 Support for sendsActionOnEndEditing in CPControl. Only works for textfields right now. 2009-10-28 00:12:03 -07:00
Ross Boucher 22c248454e Fix for the fact that bundles are not encodable in the last commits. 2009-10-28 00:11:42 -07:00
Tom Robinson 42611f3a84 Missing GET_FILE import. 2009-10-28 00:07:23 -07:00
Tom Robinson d7b778e8ac Improved capp gen frameworks installing 2009-10-27 23:39:41 -07:00
Francisco Ryan Tolmasky I 1be9d6816e Cleanup, and added deploy task.
Reviewed by me.
2009-10-27 22:23:37 -07:00
Justin MechamandRoss Boucher d263c74d5d Added support for archiving NSTitle and NSNibBundleIdentifier from the View Controller palette for NSViewControllers. 2009-10-27 20:49:35 -07:00
Justin MechamandRoss Boucher 25634a66cb Added support to nib2cib for specifying the "Nib Name" property of the View Controller palette to enable view controller initialization from cibs. 2009-10-27 20:49:18 -07:00
Justin MechamandRoss Boucher 228e801c91 Fixed the class name for archiving CPViewControllers (was CPCollectionView). 2009-10-27 20:49:03 -07:00
Francisco Ryan Tolmasky I abc715facb Added --force to tusk install.
Reviewed by me.
2009-10-27 19:02:33 -07:00
Ross Boucher a0a81be042 Add support for reviewing unsaved documents before application termination. 2009-10-27 18:44:09 -07:00
Francisco Ryan Tolmasky I 64948053df Merge branch 'master' into jake
Conflicts:
	Tools/capp/Generate.j
2009-10-27 18:41:19 -07:00
Ross Boucher 039de1b6e8 Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-27 17:40:01 -07:00
Tom Robinson b050559532 Improved capp gen. Don't blow away entire Frameworks directory with --force, just Objj/Foundation/AppKit. 2009-10-27 17:38:31 -07:00
Ross Boucher 064a062cd8 Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-27 17:37:38 -07:00
Ross Boucher b2d994bd66 Adds support for warning before closing documents that have unsaved changes.
Includes changes to the multiple documents per window controller stuff.
2009-10-27 17:36:46 -07:00
Francisco Ryan Tolmasky I 315e0eac0c Removed remaining references to full bridge in window template.
Reviewed by me.
2009-10-27 14:55:06 -07:00
Ross Boucher 06eac3e79b Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-26 23:20:29 -07:00
Ross Boucher 9e825ea62e Add close to CPDocument 2009-10-26 23:20:05 -07:00
Francisco Ryan Tolmasky I d8249b6035 Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-26 22:44:52 -07:00
Francisco Ryan Tolmasky I 7b14f41cd8 Added CGRectNull support to CGRectUnion.
Reviewed by me.
2009-10-26 22:43:51 -07:00
Ross Boucher 4bb4d6cd62 Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-26 22:19:23 -07:00
Ross Boucher 82404265fb Warn when closing an unsaved document. 2009-10-26 22:18:58 -07:00
Francisco Ryan Tolmasky I 9ee71e762c Added install call, stil won't work until parallel changes take place in tusk.
Reviewed by me.
2009-10-26 18:09:05 -07:00
Francisco Ryan Tolmasky I d52aa1575e Merge branch 'master' into jake 2009-10-26 18:08:46 -07:00
Tom Robinson 717c8520b4 Use MAX instead of Math.max 2009-10-26 16:53:13 -07:00
Tom Robinson 76edc4f914 Use Array(n).join(ch) trick for strings of identical chars 2009-10-26 16:47:09 -07:00
Francisco Ryan Tolmasky I 66b447de7b Stopped CPWindowController from setting self as next responder of CPDocument. Fixes issue with multi-document windows not sending saveDocument to focused document.
Reviewed by me.
2009-10-26 16:00:47 -07:00
Francisco Ryan Tolmasky I afaa816d5c More clean/clobber fixes.
Reviewed by me.
2009-10-26 03:28:36 -07:00
Francisco Ryan Tolmasky I 13e88c6295 Merge branch 'master' into jake 2009-10-26 02:12:07 -07:00
Francisco Ryan Tolmasky I b6cf4ad0a4 1. Added clean and clobber functionality to bundletask.
2. Prepared Foundation and Appkit for clean and clobber
3. Placed built-necessary requires in bundletask in the calling functions so that it can be included without being built for clean and clobber.
4. Made common.jake include unbuilt CommonJS files if built ones aren't present.

Reviewed by me.
2009-10-26 02:10:25 -07:00
Francisco Ryan Tolmasky I b457119925 Added shadow drawing styles.
Reviewed by me.
2009-10-25 23:11:00 -07:00
Randall LueckeandRoss Boucher b5cdcec004 fixed CPSearchField search and cancel buttons so they stay positioned correctly when resized. 2009-10-25 19:17:01 -07:00
Randall LueckeandRoss Boucher 86d5ea6c64 made sheet 10 percent transparent to match Cocoa sheets. 2009-10-25 19:10:15 -07:00
Randall LueckeandRoss Boucher 424611e7c7 fixed frameRectForContentRect:styleMask: so the styleMask argument is actually used and the method no longer outputs an error when called 2009-10-25 19:09:15 -07:00
Ross Boucher de920e959a Fix for updating table column header views after they are initially loaded. 2009-10-25 18:49:49 -07:00
Ross Boucher 9ab75eb662 Fixes a type which was causing columnWithIdentifier: in CPTableView to be broken. 2009-10-25 17:41:45 -07:00
Francisco Ryan Tolmasky I 4870ac86ef Merge branch 'master' into jake 2009-10-25 15:34:50 -07:00
Francisco Ryan Tolmasky I 24c6f0ec9f Fix for broken menu sizing.
Closes #308.

Reviewed by me.
2009-10-25 15:32:42 -07:00
Francisco Ryan Tolmasky I 250ceb69f4 Merge branch 'master' into jake 2009-10-25 11:03:20 -07:00
Francisco Ryan Tolmasky I 0561f69c86 Made cancelTracking send a close menu event so that it doesn't behave passively.
Reviewed by me.
2009-10-22 19:58:34 -07:00
Ross Boucher 341eddb9f9 Fixes a tab view bug with removing tabs.
Closes #274.

Kudos go to jtietema for tracking down the bug.
2009-10-22 10:20:14 -07:00
saikatandRoss Boucher ee8fef4e85 Fixes to autosizing behavior for CPMenu - closes issue #270 2009-10-22 10:08:56 -07:00
saikatandRoss Boucher e6d1753e74 Fixed issue with selectText in CPTextField. Closes issue #295 2009-10-22 10:07:06 -07:00
Seth BuntinandRoss Boucher 891d2a28c1 implement CPException tests 2009-10-22 10:05:58 -07:00
Francisco Ryan Tolmasky I 0af70c04a0 Fixed a bug where windows would not become visible again after closing their platform windows.
Reviewed by me.
2009-10-21 21:01:49 -07:00
Francisco Ryan Tolmasky I efaff96168 Consolidate with browser branch.
Reviewed by me.
2009-10-19 16:52:19 -07:00
Francisco Ryan Tolmasky I 6fc02623df Merge branch 'desktop' into jake
Conflicts:
	Objective-J/CommonJS/objective-j/lib-js/objective-j.js
2009-10-18 17:40:13 -07:00
Francisco Ryan Tolmasky I a27f104a63 Merge branch 'master' into desktop 2009-10-18 17:37:55 -07:00
Francisco Ryan Tolmasky I 9838bbf084 Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-18 17:36:31 -07:00
Francisco Ryan Tolmasky I 6076185da7 Added application activation.
Reviewed by me.
2009-10-18 17:35:53 -07:00
Francisco Ryan Tolmasky I 810f82cc60 Merge branch 'desktop' into jake
Conflicts:
	AppKit/CPSavePanel.j
2009-10-17 10:07:10 -07:00
Francisco Ryan Tolmasky I fce91c7ad3 Cleanuped up open/save panel.
Reviewed by me.
2009-10-17 10:00:50 -07:00
Francisco Ryan Tolmasky I e6ea4c267a Adjustments to save panel.
Reviewed by me.
2009-10-16 17:08:25 -07:00
Francisco Ryan Tolmasky I 95274f618c Merge branch 'desktop' into jake 2009-10-16 16:51:31 -07:00
Ross Boucher 385bec7400 Corrects a style issue. 2009-10-16 15:22:12 -07:00
Andreas FalkandRoss Boucher 41cb21cd0f Made CPCollectionView encode and decode the isSelectable property to the cib 2009-10-16 14:38:48 -07:00
Andreas FalkandRoss Boucher c7520593da Added getter for isSelectable and removed the getter for isSelected 2009-10-16 14:38:23 -07:00
Ross Boucher 666ac4acd1 Added test for 09858caaedfdc9211b7ee7355e104890b67d0d5e
Conflicts:

	Tests/AppKit/CPCollectionViewTest.j
2009-10-16 14:37:58 -07:00
Andreas FalkandRoss Boucher ea15b247d3 Made the item prototype test in the CPCollectionView test check for identity instead of equality 2009-10-16 14:34:49 -07:00
Ross Boucher ea252323d2 Cleaned up the test to better fit the xUnit standard
Conflicts:

	Tests/AppKit/CPCollectionViewTest.j
2009-10-16 14:34:35 -07:00
tlrobinson 42775cb152 Limit tests to those that end with *Test.j 2009-10-16 13:29:40 -07:00
tlrobinson f925585475 Fixed objj command line importing. 2009-10-16 13:29:22 -07:00
Francisco Ryan Tolmasky I aba7ea8bf1 Fixed Debug mode.
Reviewd by me.
2009-10-16 11:50:28 -07:00
Francisco Ryan Tolmasky I 29b0aa7cde Beginning to remove old files.
Reviewed by me.
2009-10-16 11:17:48 -07:00
Francisco Ryan Tolmasky I 375b490678 Removed dependencies on common.jake.
Reviewed by me.
2009-10-16 11:15:02 -07:00
Francisco Ryan Tolmasky I 27c2285600 Jakefile cleanup, beginnings of "install" task.
Reviewed by me.
2009-10-16 09:37:12 -07:00
Francisco Ryan Tolmasky I 1d1f664e07 Made starter_download and docs tasks jake compliant.
Reviewed by me.
2009-10-16 07:58:40 -07:00
Ross Boucher f2e95f7e63 Fix a broken import which caused all tests to fail. 2009-10-15 23:27:15 -07:00
Seth BuntinandRoss Boucher 3055522645 implement CPDictionary Tests 2009-10-15 20:53:21 -07:00
Francisco Ryan Tolmasky I 7347428e94 Merge branch 'master' into jake 2009-10-15 19:48:57 -07:00
Francisco Ryan Tolmasky I 4a8a205ae2 Merge branch 'master' into desktop 2009-10-15 19:48:43 -07:00
Francisco Ryan Tolmasky I 090bf3c46d More nib2cib CommonJS fixes.
Reviewed by me.
2009-10-15 19:47:06 -07:00
Tom Robinson 1691b6f07e Update externals (browserjs suppress warnings, narwhal file module fixes). 2009-10-15 19:35:52 -07:00
Francisco Ryan Tolmasky I 22578c3650 Merge branch 'master' into desktop 2009-10-15 19:05:55 -07:00
Francisco Ryan Tolmasky I 57c7757c2e Merge branch 'master' into jake 2009-10-15 19:05:43 -07:00
Francisco Ryan Tolmasky I 16deb3700d Fixed incompatibilities in nib2cib with CommonJS and JavaScriptCore.
Reviewed by me.
2009-10-15 19:03:59 -07:00
Ross Boucher f5d05a7c93 Change file encodings. 2009-10-15 16:59:19 -07:00
Francisco Ryan Tolmasky I 40b5332c83 Merge branch 'master' into jake 2009-10-15 13:29:21 -07:00
Francisco Ryan Tolmasky I 238da6b80f Narwhal fixes for capp gen.
Reviewed by me.
2009-10-15 13:27:27 -07:00
Ross Boucher 1c4f11c1d2 A few style fixes for the new CPDataTest 2009-10-15 11:00:30 -07:00
Seth BuntinandRoss Boucher e57e7cbbc5 remove unused import 2009-10-15 10:54:06 -07:00
Seth BuntinandRoss Boucher 97cfb5c1f9 clean up to follow style guidelines 2009-10-15 10:53:58 -07:00
Seth BuntinandRoss Boucher 9d7ba990a8 add dataWithPlistObject test CPDataTest 2009-10-15 10:53:52 -07:00
Seth BuntinandRoss Boucher cac6204a96 add tests for CPData.j 2009-10-15 10:53:42 -07:00
Francisco Ryan Tolmasky I b7f41c104c Merge branch 'master' into desktop 2009-10-14 14:05:50 -07:00
Francisco Ryan Tolmasky I 1123e848bf Removed debug logs.
Reviewed by me.
2009-10-14 09:16:30 -07:00
Francisco Ryan Tolmasky I e3fe4ff92f Only sprite images smaller than 32KB.
Reviewed by me.
2009-10-14 09:13:58 -07:00
Francisco Ryan Tolmasky I d6b338b160 Fix for dynamically loading objective-j loader mid-build.
Reviewed by me.
2009-10-13 16:42:05 -07:00
Francisco Ryan Tolmasky I ddada18069 Removed logs.
Reviewed by me.
2009-10-13 16:03:36 -07:00
Francisco Ryan Tolmasky I b43b097d40 Fix for building from scratch.
Reviewed by me.
2009-10-13 15:42:44 -07:00
Francisco Ryan Tolmasky I 2cc723752e Merge branch 'master' into jake
Conflicts:
	Objective-J/Runtime/constants.js
2009-10-13 13:45:41 -07:00
Francisco Ryan Tolmasky I 6b02a4105b Furhter cleanup.
Reviewed by me.
2009-10-13 13:41:45 -07:00
Francisco Ryan Tolmasky I 3098bfe6db Furhter cleanup.
Reviewed by me.
2009-10-13 13:40:28 -07:00
Tom Robinson 5e658354ab Fixes for objj on narwhal-jsc plus Externals update. 2009-10-13 13:31:46 -07:00
Francisco Ryan Tolmasky I 2f5e4d8335 Minor cleanup, much more needed.
Reviewed by me.
2009-10-13 12:34:33 -07:00
Francisco Ryan Tolmasky I a607d79c7d Further spriting work.
Reviewed by me.
2009-10-13 10:19:50 -07:00
Francisco Ryan Tolmasky I 81c71beaa7 Fix for decode errors.
Reviewed by me.
2009-10-11 11:15:09 -07:00
Francisco Ryan Tolmasky I 5bd30fc4e5 Merge branch 'master' into jake 2009-10-10 12:57:56 -04:00
Francisco Ryan Tolmasky I 46d452be5e Merge branch 'master' into desktop 2009-10-10 12:20:22 -04:00
Ross BoucherandFrancisco Ryan Tolmasky I 2338ca2fa2 Add support for minimization. 2009-10-10 12:20:02 -04:00
Ross Boucher 2900163644 Fixes bug in CPAnimation where certain ivars were not initialized correctly.
Closes #287.
2009-10-09 14:30:56 -07:00
Francisco Ryan Tolmasky I e90f0188c3 Merge branch 'master' into desktop 2009-10-09 11:16:51 -04:00
Francisco Ryan Tolmasky I 5fa457621b Merge branch 'master' into jake
Conflicts:
	Objective-J/Runtime/evaluate.js
2009-10-09 07:44:37 -04:00
Jake MacMullinandRoss Boucher e125139777 Fixed a bug where the CPAlert was being displayed with black text on a black background if the styleMask was set to 'CPHUDBackgroundWindowMask' and something else. #220 2009-10-09 00:06:44 -07:00
Nicholas SmallandRoss Boucher bc6f168afa Added some designated initializers to AppKit. 2009-10-09 00:03:52 -07:00
Ross Boucher fc85ae16a5 Fix for the keypress bug introduced in Safari 4.
Closes #280.
2009-10-08 23:10:58 -07:00
Ross Boucher d5f2654eae Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-08 21:50:45 -07:00
Ross Boucher 5e951c1e53 Fix for a break in key view loops from the previous text field change. 2009-10-08 21:50:03 -07:00
Tom Robinson 69cdc2ccd0 Check for "system", fixes press. 2009-10-08 21:41:35 -07:00
Tom Robinson 3474e8baf1 Merge branch 'master' of git@github.com:280north/cappuccino 2009-10-08 19:59:46 -07:00
Ross Boucher 6e7e3ef35e Updates to TextField.
Closes #219.
Closes #283.
Closes #232.
2009-10-08 19:28:45 -07:00
Ross Boucher 8a2cd8c5c6 Fix type in CPAnimation 2009-10-08 13:38:36 -07:00
Ross Boucher 306c1a962a Move tests. 2009-10-08 13:29:24 -07:00
Ross Boucher 8441e62f49 Merge branch 'sheets'
Conflicts:
	AppKit/CPControl.j
	AppKit/CPWindow/CPWindow.j
2009-10-08 13:25:20 -07:00
Ross Boucher 9b948dcac7 CPAnimation: cubic bezier curves - the real, working equation
Conflicts:

	AppKit/CPAnimation.j
2009-10-08 13:20:10 -07:00
Ross Boucher 1fb9c973fe More sheets. 2009-10-08 13:12:30 -07:00
cacaodevandRoss Boucher 048bcc1be7 Improved autoresizing mechanism for attached sheets 2009-10-08 12:58:45 -07:00
cacaodevandRoss Boucher 1d8cebd5be CPWindow : Added missing declarations for _isSheet and _parentView
sheet's subviews autoresizingMask is now correctly restored when the sheet is open or ended.
           Added CPWindow(WillBegin/DidEnd)SheetNotification globals

	   To do : support for maxSize and minSize
2009-10-08 12:58:37 -07:00
cacaodevandRoss Boucher 0e55a5d7c4 Added sample app. Corrected style (tabs) 2009-10-08 12:58:29 -07:00
cacaodevandRoss Boucher c6b934a035 Attached sheet implementation 2009-10-08 12:58:22 -07:00
cacaodevandRoss Boucher 5b531b2005 Improved autoresizing mechanism for attached sheets 2009-10-08 12:13:55 -07:00
cacaodevandRoss Boucher 570a2a56ff Added sample app. Corrected style (tabs) 2009-10-08 12:02:35 -07:00
cacaodevandRoss Boucher d79ed12b5c Attached sheet implementation 2009-10-08 12:02:26 -07:00
Francisco Ryan Tolmasky I 7864a9fa8e Updates to fix building.
Reviewed by me.
2009-10-08 14:59:10 -04:00
Francisco Ryan Tolmasky I 3aa7378699 Merge branch 'master' into desktop 2009-09-30 07:04:58 +01:00
Ross BoucherandFrancisco Ryan Tolmasky I 1d76ac1b91 Addes initial support for window shadow styles.
Reviewed by tolmasky.
2009-09-30 07:03:55 +01:00
Francisco Ryan Tolmasky I 99697926d9 Resource fixes, added index.html support.
Reviewed by me.
2009-09-29 15:44:46 -07:00
Francisco Ryan Tolmasky I 32d0c6ca17 Fix for non imported function in compiler.js.
Reviewed by me.
2009-09-28 05:12:20 -07:00
Francisco Ryan Tolmasky I 2dac122c30 Fix for loading platform dependent code.
Reviewed by me.
2009-09-28 04:27:03 -07:00
Francisco Ryan Tolmasky I e9092007ee Added support for new FileList.
Reviewed by me.
2009-09-27 21:13:50 -07:00
Francisco Ryan Tolmasky I b94c82f4aa Fix for double file inclusion.
Reviewed by me.
2009-09-27 15:31:24 -07:00
Francisco Ryan Tolmasky I 6a32314c0b Merge branch 'master' into desktop 2009-09-26 20:47:06 -07:00
Francisco Ryan Tolmasky I eff3170df1 Updated for jsc support.
Reviewed by me.
2009-09-26 20:05:41 -07:00
Tom Robinson 62d825d970 Merge branch 'master' of git@github.com:280north/cappuccino 2009-09-26 18:49:57 -07:00
Tom Robinson cb416e0277 Use system.engine to detect Rhino. 2009-09-26 18:49:35 -07:00
Francisco Ryan Tolmasky IandTom Robinson 5066a1d395 Fix for gcc args.
Reviewed by me.
2009-09-26 18:49:35 -07:00
Francisco Ryan Tolmasky IandTom Robinson df3658bc96 Update to support new narwhal.
Reviewed by me.
2009-09-26 18:49:35 -07:00
Francisco Ryan Tolmasky I 3ac8ac40bc Jakefile for press.
Reviewed by me.
2009-09-26 02:03:51 -07:00
Francisco Ryan Tolmasky I e5c5378ec0 A bit of work on top level tasks.
Reviewed by me.
2009-09-26 02:03:03 -07:00
Francisco Ryan Tolmasky I ef41abec97 Added loader.js
Reviewed by me.
2009-09-26 01:31:52 -07:00
Francisco Ryan Tolmasky I 72d4675ec4 More spriting stuff.
Reviewed by me.
2009-09-26 00:27:38 -07:00
Francisco Ryan Tolmasky I 1cd8acb92c blend working with jake build system.
Reviewed by me.
2009-09-25 23:37:38 -07:00
Francisco Ryan Tolmasky I 9856e6bfd7 nib2cib and capp building with jake.
Reviewed by me.
2009-09-25 21:52:41 -07:00
Francisco Ryan Tolmasky I be2ffe95c5 Added missing bin.
Reviewed by me.
2009-09-25 17:45:10 -07:00
Francisco Ryan Tolmasky I 3f2d6f24d2 Removed no longer used files.
Reviewed by me.
2009-09-25 03:33:40 -07:00
Francisco Ryan Tolmasky I 714cd402df Moved nib2cib and capp to jake.
Reviewed by me.
2009-09-25 03:28:38 -07:00
Francisco Ryan Tolmasky I ffd99e3ed7 Further jake work.
Reviewed by me.
2009-09-24 01:11:46 -07:00
Francisco Ryan Tolmasky I 64a8e4c5c0 More transition to jake.
Reviewed by me.
2009-09-23 18:46:11 -07:00
Francisco Ryan Tolmasky I bb0a1eadda Added more common routines to common.jake.
Reviewed by me.
2009-09-23 16:28:58 -07:00
Francisco Ryan Tolmasky I a8ab16002e More jakefiles and fixing incorrect commonjs package structure.
Reviewed by me.
2009-09-23 16:27:52 -07:00
Francisco Ryan Tolmasky I 9dc0c3ab6d First set of jake files.
Reviewed by me.
2009-09-23 03:49:08 -07:00
Francisco Ryan Tolmasky I 82df59e7dc Merge branch 'master' into desktop 2009-09-23 03:45:29 -07:00
Francisco Ryan Tolmasky I 47694c2d80 Fix for gcc args.
Reviewed by me.
2009-09-23 03:25:41 -07:00
Francisco Ryan Tolmasky I 4993d16738 Merge branch 'master' into desktop 2009-09-23 00:21:46 -07:00
Francisco Ryan Tolmasky I 43c0db44ea Update to support new narwhal.
Reviewed by me.
2009-09-23 00:20:30 -07:00
Francisco Ryan Tolmasky I ebbf3c4576 More desktop differences.
Reviewed by me.
2009-09-22 19:32:53 -07:00
Francisco Ryan Tolmasky I f109313d32 Reapply desktop differences.
Reviewed by me.
2009-09-22 19:32:23 -07:00
Tom Robinson e305d30c1b Update externals 2009-09-22 18:34:33 -07:00
Ross Boucher 317f1d356c Add copyright info to CPBox 2009-09-22 17:23:54 -07:00
Ross Boucher 25f3d99732 Add support for CPBox. 2009-09-22 17:23:02 -07:00
Tom Robinson b0443fe5e3 Fixed "animationShouldStart" selector missing a trailing colon. 2009-09-22 00:28:16 -07:00
Ross Boucher 3f5bb77230 Fix typo. 2009-09-21 18:51:21 -07:00
Francisco Ryan Tolmasky I 1cf292279c Improved scrolling for tablview and outlineview -- no longer sets non-integral scroll positions.
Reviewed by me.
2009-09-20 15:40:05 -07:00
Ross Boucher 2e350f6bc5 Fix an accidental global in platformwindow 2009-09-20 10:36:30 -07:00
Francisco Ryan Tolmasky I cfd91b7a61 Updated scrollers look.
Reviewed by me.
2009-09-20 02:47:52 -07:00
Tom Robinson 1a8062fbbc Added support for the "//@ sourceName" convention tell debuggers our file names.
http://pmuellr.blogspot.com/2009/06/debugger-friendly.html
2009-09-18 03:27:58 -07:00
Tom Robinson 32096ade9f Oops, OBJJ_HOME got left out of the Rhino scope thingy. Sorry, OBJJ_HOME. 2009-09-18 02:51:11 -07:00
Tom Robinson b7493586e2 Improve stack traces in objj on Rhino. 2009-09-18 02:21:31 -07:00
Francisco Ryan Tolmasky I a02cda6376 Fix for autoresizing breaking with bounds changes.
Reviewed by me.
2009-09-17 01:12:30 -07:00
Francisco Ryan Tolmasky I 2348a8ebd3 Brought cib support up to date with TableView changes.
Reviewed by me.
2009-09-17 00:38:19 -07:00
Michael PorterandFrancisco Ryan Tolmasky I 7728d8abfb Fix window maximise issue in Firefox 2009-09-16 15:23:42 -07:00
Francisco Ryan Tolmasky I b21b08f899 Improved drag and drop.
Reviewd by me.
2009-09-16 00:27:56 -07:00
Francisco Ryan Tolmasky I c752db905d Fix for updating sliders visually when min/max values change.
Reviewed by me.
2009-09-15 21:39:20 -07:00
Francisco Ryan Tolmasky I 7ca50e4d28 Fix for accessing view controllers for a document.
Reviewed by me.
2009-09-15 17:14:14 -07:00
Francisco Ryan Tolmasky I 1862eacc27 Change frame setting behavior to match immediacy of Cocoa/GNUStep.
Reviewed by me.
2009-09-15 14:51:07 -07:00
Francisco Ryan Tolmasky I 0497888edf Made CPCollectionViewItem a subclass of CPViewController and improved nib2cib support for CPCollectionView, CPCollectionViewItem, and CPViewController.
Reviewed by me.
2009-09-15 05:00:56 -07:00
Francisco Ryan Tolmasky I 25d76c9510 Further CPCollectionView nib2cib work.
Reviewed by me.
2009-09-15 03:20:47 -07:00
Francisco Ryan Tolmasky I 46dbce0dbb Fix for not being able to set headers on table view.
Closes #264.

Reviewed by me.
2009-09-15 02:30:18 -07:00
Francisco Ryan Tolmasky I 98ef1bfd05 Fix for Collection views having a gray background when nib2cibed.
Reviewed by me.
2009-09-15 02:22:05 -07:00
Francisco Ryan Tolmasky I 7205146e1b Fixed how children are loaded and reloaded in CPOutlineView and fixed a bug where CPWindowController would call windowControllerWillLoadCib: and windowControllerDidLoadCib: twice.
Reviewed by me.
2009-09-14 23:14:05 -07:00
Francisco Ryan Tolmasky I 02907a599d Minor outline view fix.
Reviewed by me.
2009-09-14 14:40:40 -07:00
Francisco Ryan Tolmasky I d6ac69029b Added sorting capabilities to CPTreeNode.
Reviewed by me.
2009-09-14 03:47:57 -07:00
Francisco Ryan Tolmasky I c8ed0f5436 Changed usages of string paths to CPURL objects.
Reviewed by me.
2009-09-14 01:01:05 -07:00
Francisco Ryan Tolmasky I 20d14d2f81 Added beginnings of tabbed documents support.
Reviewed by me.
2009-09-14 00:51:43 -07:00
Francisco Ryan Tolmasky I 668540d0ce Added CPViewController for managing views and CPWebDAVManager for interacting with web dav servers.
Reviewed by me.
2009-09-13 20:02:07 -07:00
Francisco Ryan Tolmasky I ee46ab23ba Improved arrow control in outline view, still could use considerable work.
Reviewed by me.
2009-09-13 01:10:11 -07:00
Francisco Ryan Tolmasky I dba418a93d Fix for:
- misindented items in outline view
- switched window controller to use synchronous cibs.
- typo in cibloading.

Reviewed by me.
2009-09-12 23:37:44 -07:00
Francisco Ryan Tolmasky I 186adee0f2 Merge branch 'master' of git@github.com:280north/cappuccino 2009-09-12 18:15:30 -07:00
Francisco Ryan Tolmasky I abd3abdfea Fixed only showing disclosure control for items that are expandable, and simplified the row to item mapping.
Reviewed by me.
2009-09-12 18:10:43 -07:00
Ross Boucher 7aa58fa98a Include default methods for nextState and setState 2009-09-12 20:48:44 -04:00
Francisco Ryan Tolmasky I a32368f89a Simply added constants to top of CPURL.j.
Reviewed by me.
2009-09-12 12:09:51 -07:00
Tom Robinson 4f1d9fe836 CPURL -description 2009-09-11 19:46:09 -07:00
Tom Robinson 98df1859af Inital CPURL 2009-09-11 19:46:09 -07:00
Francisco Ryan Tolmasky I 1bdea9ff45 Added selection delegate methods support to tableview and outlineview.
Reviewed by me.
2009-09-11 18:28:57 -07:00
Francisco Ryan Tolmasky I 17273ecbfa Added disclosure views to outline view.
Reviewed by me.
2009-09-11 10:24:16 -07:00
Francisco Ryan Tolmasky I fd62233960 Cleaned up outline view indentation code, and added parentForItem:.
Reviewed by me.
2009-09-10 17:02:47 -07:00
Francisco Ryan Tolmasky I 5b0876b7ed Merge branch 'master' of git@github.com:280north/cappuccino 2009-09-10 14:13:31 -07:00
Francisco Ryan Tolmasky I 96afa4b950 Added deferred loading for outline views (for remote data), and added CPTreeNode class.
Reviewed by me.
2009-09-10 14:12:34 -07:00
Ross Boucher 5e74290486 Fix typo in CPTextField. Closes 247. 2009-09-10 12:18:12 -04:00
Ross Boucher d00197b1f7 This forces a recalculation at the point where autorecalculation is turned off (only if it was dirty).
From what I can tell, this brings it into line with how Cocoa handles the situation.

Closes issue #250.
2009-09-10 12:05:55 -04:00
Ross Boucher 8b9f36043d Add a bit more context to the errors that we can. 2009-09-10 11:38:07 -04:00
Francisco Ryan Tolmasky I 041f8200df First pass at CPOutlineView.
Reviewed by me.
2009-09-09 17:48:59 -07:00
Francisco Ryan Tolmasky I b77eef0cd3 Fix for typo in method name.
Reviewed by me.
2009-09-08 02:44:55 -07:00
Tom Robinson 774e958d49 Properly "export" external git repos so we don't get .git directory. Update externals. 2009-09-07 18:53:59 -07:00
Tom Robinson f7c00df9a9 Sync bundle with TextMate repo 2009-09-07 18:53:59 -07:00
Francisco Ryan Tolmasky I 98e18340b7 Fix for tableview breaking when header view is removed.
Reviewed by me.
2009-09-07 18:22:34 -07:00
Francisco Ryan Tolmasky I 58e06142b9 Added support for external objects in cibs.
Reviewed by me.
2009-09-06 11:49:25 -07:00
Tom Robinson c895170597 Fix capp gen -f with no path. 2009-09-05 00:37:52 -07:00
Francisco Ryan Tolmasky I a619bc15c2 Fix for collection views unarchived from cibs crashing.
Reviewed by me.
2009-09-05 00:28:42 -07:00
Francisco Ryan Tolmasky I 369cacb3aa A bit of cleanup.
Reviewed by me.
2009-09-04 18:07:24 -07:00
Francisco Ryan Tolmasky I 78fe93be68 Imrpoved identifying main menus in cibs.
Reviewed by me.
2009-09-04 12:37:38 -07:00
Francisco Ryan Tolmasky I 1a7a07b51a Fix for draggedView:endedAt:operation: giving 0,0 locations.
Reviewed by me.
2009-09-04 03:54:40 -07:00
Francisco Ryan Tolmasky I 2996404ad4 Merge branch 'master' of git@github.com:280north/cappuccino 2009-09-03 02:32:03 -07:00
Francisco Ryan Tolmasky I 669dff7a9b nib2cib fix for new scrollers.
Reviewed by me.
2009-09-03 02:31:25 -07:00
Tom Robinson 3a7dee6cc2 Added template config file to "capp", and ability to specify an absolute path for a template. 2009-09-03 01:11:19 -07:00
Tom Robinson 7017000c81 Added dictionary methods to objj_dictionary.prototype 2009-09-03 01:11:19 -07:00
Tom Robinson 379eb05144 Various improvements to objj and objjc modules, added plist module. 2009-09-03 01:11:18 -07:00
Francisco Ryan Tolmasky I 8fc45cf345 Workaround for terminate: warning when using cibs.
Reviewed by me.
2009-09-02 23:37:51 -07:00
Francisco Ryan Tolmasky I dc85900780 Final resources for new scrollers.
Reviewed by me.
2009-09-02 03:56:58 -07:00
Francisco Ryan Tolmasky I 0a28127667 Merge branch 'new_Scroller' into master_scroller 2009-09-02 02:40:57 -07:00
Francisco Ryan Tolmasky I 879561f67b Replaced incorrect method names.
Reviewed by me.
2009-09-02 02:39:10 -07:00
Francisco Ryan Tolmasky I 7f9bc98929 Fix for CPSet count increasing even if the same object is added repeatedly.
Reviewed by me.
2009-09-01 17:20:00 -07:00
Francisco Ryan Tolmasky I 4c01bebd07 Minor fixes to segmented control.
Reviewed by me.
2009-09-01 12:54:32 -07:00
Francisco Ryan Tolmasky I 2fbe026215 Further drawing fixes.
Reviewed by me.
2009-08-31 14:39:00 -07:00
Francisco Ryan Tolmasky I efcc5d1054 Fixed a bug that could cause CPAccordionView to infinitely re-layout (due to autoresizing flags in child views), and added option to synchronously load cibs.
Reviewed by me.
2009-08-31 01:22:08 -07:00
Francisco Ryan Tolmasky I 2cf5b90183 Fixes for uncommon drawRect: bugs.
Reviewed by me.
2009-08-30 20:59:01 -07:00
Francisco Ryan Tolmasky I 75060a3385 Fix for accordion view occasionally incorrectly laying out.
Reviewed by me.
2009-08-29 00:20:39 -07:00
Francisco Ryan Tolmasky I b55ddcf4ce Merge branch 'master' of git@github.com:280north/cappuccino 2009-08-27 12:27:37 -07:00
Francisco Ryan Tolmasky I 744e78b7ad Added Accordion View. Also fixed a bug with changing table column withs in CPTableView not updating affected cells.
Reviewed by me.
2009-08-27 12:26:38 -07:00
Tom Robinson f360ab9475 Update objj and browserjs package.json, add Rake task for narwhal modules 2009-08-25 23:22:04 -07:00
Francisco Ryan Tolmasky I 58ac49e0b0 Fix for out of memory errors when building clean.
Reviewed by me.
2009-08-25 19:55:21 -07:00
Francisco Ryan Tolmasky I d1c0237bf3 Fix for recursive notification postings crashing. Also fixed sizing issues with tableview, including crashing when not in a superview.
Closes #238.

Reviewed by me.
2009-08-25 16:08:07 -07:00
Francisco Ryan Tolmasky I abc1c6f2db Merge branch 'master' of git@github.com:280north/cappuccino 2009-08-24 23:04:19 -07:00
Francisco Ryan Tolmasky I 14ba9c95eb Fix for incorrect calculation in rowsInRect when rect is out of bounds, or when there are 0 rows in CPTableView.
Reviewed by me.
2009-08-24 23:03:35 -07:00
Tom Robinson 0b03025924 Implemented rest of CPApplication openFile 2009-08-24 12:30:08 -07:00
Francisco Ryan Tolmasky I b369aa6aff Made CPCibConnector, CPCibOutletConnector, and CPCibControlConnector public classes.
Reviewed by me.
2009-08-24 00:21:15 -07:00
Francisco Ryan Tolmasky I f189ec6eb9 Change default log level from fatal to info.
Reviewed by me.
2009-08-22 16:32:11 -07:00
Francisco Ryan Tolmasky I 3b761ec55e Fixed a bug in the new CPIndexSet when adding indexes to the back of the set. Also added a test to handle this case. Also moved Table visual tests into Tests/ folder.
Reviewed by me.
2009-08-22 02:51:37 -07:00
Francisco Ryan Tolmasky I 1b4a5dc48b Merge branch 'master' of git@github.com:280north/cappuccino 2009-08-22 01:45:30 -07:00
Francisco Ryan Tolmasky I 356d2e9ea7 Merge branch 'tableview-merge' 2009-08-22 01:45:10 -07:00
Francisco Ryan Tolmasky I d3bebfd064 New scroller artwork.
Reviewed by me.
2009-08-22 01:43:29 -07:00
Francisco Ryan Tolmasky I da9221bf71 Fixed resources support being broken in nib2cib.
Reviewed by me.
2009-08-22 01:03:56 -07:00
Francisco Ryan Tolmasky I 8990f6c387 Minor fixes and added licenses to files.
Reviewed by me.
2009-08-21 23:32:34 -07:00
Francisco Ryan Tolmasky I cdaa363a82 Removed unecessary call in header view.
Reviewed by me.
2009-08-21 22:41:40 -07:00
Francisco Ryan Tolmasky I e910fee03f Fixed spacing issue.
Reviewed by me.
2009-08-21 20:03:26 -07:00
Francisco Ryan Tolmasky I 7528c452c4 Cleaned up row highlighting and added support for drawing column selection as well.
Reviewed by me.
2009-08-21 20:03:26 -07:00
Francisco Ryan Tolmasky I 824cd6d5f1 Removed unecessary functions.
Reviewed by me.
2009-08-21 20:03:26 -07:00
Francisco Ryan Tolmasky I 3f7db4ca12 Improved grid drawing code.
Reviewed by me.
2009-08-21 20:03:26 -07:00
Francisco Ryan Tolmasky I 2ee3b93e0d Made it so you can have arbitrary number of alternating row colors.
Reviewed by me.
2009-08-21 20:03:26 -07:00
Francisco Ryan Tolmasky I bd69683dc2 Fix for infinite loop when sizing last column to fit.
Reviewed by me.
2009-08-21 20:03:26 -07:00
Francisco Ryan Tolmasky I 1b8f263224 Fix for using tabledrawview.
Reviewed by me.
2009-08-21 20:03:26 -07:00
RandyandFrancisco Ryan Tolmasky I 58aef6ef74 tableview fixes 2009-08-21 20:03:26 -07:00
Francisco Ryan Tolmasky I 8a1c1b931f Fix for calling undefined function.
Reviewed by me.
2009-08-21 20:03:25 -07:00
Tom Robinson db77e826d4 Fixed syntax error reporting in objjc 2009-08-20 19:15:40 -07:00
Francisco Ryan Tolmasky IandTom Robinson 35fa76064c CPWindow centering 2009-08-20 19:15:31 -07:00
Francisco Ryan Tolmasky I d2df0919a5 Fix for calling undefined function.
Reviewed by me.
2009-08-20 01:07:47 -07:00
Francisco Ryan Tolmasky I b378a4d0fa Merge branch 'master' into tableview 2009-08-20 00:55:16 -07:00
Francisco Ryan Tolmasky I e174edd0dc Added file opening conviniences.
Reviewed by me.
2009-08-19 20:41:27 -07:00
Francisco Ryan Tolmasky I 3060c3f100 Add delegate method to prevent automatically opening a new document on launch in document based applications.
Reviewed by me.
2009-08-19 16:55:28 -07:00
Francisco Ryan Tolmasky I 14528d5a49 Fixed a bug where split view was setting NaN positions and sizes when position was set to 0.
Reviewed by me.
2009-08-17 23:47:33 -07:00
Francisco Ryan Tolmasky I 35c1221905 Fixed a bug with HTML 5 and platform windows.
Reviewed by me.
2009-08-17 14:10:22 -07:00
Francisco Ryan Tolmasky I 300f74bf4d Merge branch 'master' of git@github.com:280north/cappuccino
Conflicts:
	AppKit/CPDragServer.j
	AppKit/Platform/CPPlatform.j
2009-08-17 03:55:02 -07:00
Francisco Ryan Tolmasky I e8dd56bda7 Added HTML 5 drag and drop support for WebKit/Safari.
Reviewed by me.
2009-08-17 03:50:52 -07:00
Francisco Ryan Tolmasky I 0c9f247a82 Slight frame setting modification.
Reviewed by me.
2009-08-17 03:50:52 -07:00
Francisco Ryan Tolmasky I 51e6f92fee Fix for regression with menus showing up too low in menubar.
Reviewed by me.
2009-08-17 03:50:51 -07:00
Francisco Ryan Tolmasky I d1d0d72e32 Slight change from macro to runtime option.
Reviewed by me.
2009-08-17 03:50:51 -07:00
Tom RobinsonandFrancisco Ryan Tolmasky I aef723e160 Update Jack again. 2009-08-17 03:50:51 -07:00
Francisco Ryan Tolmasky I ab8add681e A number of fixes and improvements to the platform window subsystem.
Reviewed by me.
2009-08-17 03:50:51 -07:00
Francisco Ryan Tolmasky I 07da83715b Slight frame setting modification.
Reviewed by me.
2009-08-12 20:42:20 -07:00
Francisco Ryan Tolmasky I 7db40a6b0d Fix for regression with menus showing up too low in menubar.
Reviewed by me.
2009-08-12 17:46:44 -07:00
Francisco Ryan Tolmasky I 55a8084b39 Slight change from macro to runtime option.
Reviewed by me.
2009-08-12 17:34:13 -07:00
Tom Robinson 475cd6a21f Update Jack again. 2009-08-11 15:41:52 -07:00
Tom Robinson 4c3a43989b Merge branch 'master' of git@github.com:280north/cappuccino 2009-08-11 11:46:31 -07:00
Tom Robinson 0d7ba4e872 Update Jack to latest 2009-08-11 11:46:15 -07:00
Francisco Ryan Tolmasky I a40714e14a Merge branch 'master' of git@github.com:280north/cappuccino 2009-08-11 01:18:03 -07:00
Francisco Ryan Tolmasky I c850c0cf45 A number of fixes and improvements to the platform window subsystem.
Reviewed by me.
2009-08-11 01:13:33 -07:00
Francisco Ryan Tolmasky I ddc9334af3 Merge branch 'master' into tableview
Conflicts:
	AppKit/CPTableColumn.j
	AppKit/CPTableView.j
2009-08-10 15:09:10 -07:00
Tom Robinson 654b0493bb Update Narwhal to get readline package, modify objj.js to use readline(). 2009-08-09 20:11:19 -07:00
Tom Robinson 64cbf98140 Update Narwhal to latest 2009-08-09 15:19:21 -07:00
Tom Robinson 5fc8cd697e Merge branch 'master' of git@github.com:280north/cappuccino 2009-08-09 15:16:12 -07:00
Tom Robinson 2423faa8c6 Major improvments to Objective-J Narwhal support.
* Added objj_eval, objj_import_sync, objj_preprocess_sync, etc
* Refactored REPL.
* Added Objective-J plugin for load system, using new Narwhal plugin system.
* Refactored objj and objjc into single module.
2009-08-09 14:40:02 -07:00
Tom Robinson 172c7330ab Make objj a self contained narwhal package. Invert install so narwhal contains objj not vice versa.
Conflicts:

	Tools/Rake/lib/objective-j/bundletask.rb
2009-08-09 14:39:36 -07:00
lowell vizonandFrancisco Ryan Tolmasky I 1a5bf1c8eb CPBezierPath documentation completed.
Signed-off-by: Francisco Ryan Tolmasky I <francisco@280north.com>
2009-08-08 03:50:52 +08:00
lowell vizonandFrancisco Ryan Tolmasky I 377f331b47 Documentation Edits: Replaced <code> and <pre> tags with \c; this allows monospaced text to be displayed with formatted text without needing a new line. See AppKit/CPView after generating documentation for examples. Also added - and + signs to the above changes when referring to either an -instanceMethod or a +classMethod. --lowell@cocoastep
Signed-off-by: Francisco Ryan Tolmasky I <francisco@280north.com>
2009-08-08 03:50:50 +08:00
Francisco Ryan Tolmasky I 3e85bf0e8b Merge branch 'master' of git@github.com:280north/cappuccino 2009-08-07 10:50:54 -07:00
Francisco Ryan Tolmasky I 3f496f1a10 Fixed CPEvent returning a direct reference to its location (as opposed to a copy), and CPPlatformWindow doing geometry gymnastics instead of the well defined conversion methods on CPWindow.
Reviewed by me.
2009-08-03 01:47:33 -07:00
Sergio FelixandFrancisco Ryan Tolmasky I b52da00d46 Fixed a bug in CPTimer 2009-08-01 20:35:31 -07:00
Francisco Ryan Tolmasky I 69fa064509 Merge branch 'master' of git@github.com:280north/cappuccino 2009-07-29 20:28:42 -07:00
Tom Robinson 0c349a8d7f Add option to enable type checking in index-debug.html. 2009-07-29 20:23:40 -07:00
Tom Robinson 3b8664e6ff Disable typechecking by default 2009-07-29 19:23:32 -07:00
Tom Robinson 2bb6da5132 Undoing this so Ross stops complaining. 2009-07-29 19:21:17 -07:00
Francisco Ryan Tolmasky I 0876653ae3 Only include debug.js in DEBUG mode for Objective-J.
Reviewed by me.
2009-07-29 19:06:06 -07:00
Tom Robinson 4876c7142f Merge branch 'typecheck' 2009-07-29 19:02:16 -07:00
Tom Robinson 856373adec Added status code checks to abort Rake early. 2009-07-29 18:57:18 -07:00
Francisco Ryan Tolmasky I fbf559043e Fixed accidentally committed #if 0.
Reviewed by me.
2009-07-28 21:10:16 -07:00
Ross Boucher bbda6e6e77 Added the images for CPSearchField. Closes #205. 2009-07-27 23:28:10 -07:00
Ross Boucher 4cd7d35499 Merge branch 'master' of git@github.com:280north/cappuccino 2009-07-27 23:15:33 -07:00
Francisco Ryan Tolmasky I a8393eaa8a Merge branch 'master' of git@github.com:280north/cappuccino 2009-07-27 22:43:31 -07:00
Francisco Ryan Tolmasky I 6a9804939e More removal of "bridge".
Reviewed by me.
2009-07-27 22:43:01 -07:00
Ross Boucher b50067e39e Add a trim function to CPString. 2009-07-27 22:41:47 -07:00
Ross Boucher 028be939f9 Merge branch 'master' of git@github.com:280north/cappuccino 2009-07-27 18:47:29 -07:00
Ross Boucher b5e84342ac Fix for documentation error. Closes #208. 2009-07-27 18:43:46 -07:00
Francisco Ryan Tolmasky I 5bc92b686b Slight fix to new CPWindowController mechanics.
Reviewed by me.
2009-07-27 18:42:04 -07:00
Francisco Ryan Tolmasky I e8f1763615 Merge branch 'master' of git@github.com:280north/cappuccino 2009-07-27 18:22:53 -07:00
Francisco Ryan Tolmasky I 41dc660140 Added support for document cibs.
Reviewed by me.
2009-07-27 18:19:34 -07:00
Ross Boucher a05ecd2759 Add disabled state for check boxes 2009-07-27 17:03:34 -07:00
Ross Boucher f51222dff6 Add disabled states to CPRadioButton 2009-07-27 16:57:16 -07:00
Ross Boucher 598411c072 remove opacity from disabled buttons -- otherwise its unusable on dark backgrounds 2009-07-27 16:51:05 -07:00
Ross Boucher 241cc2ac06 Add highlighted states to radio buttons. 2009-07-27 16:38:30 -07:00
Ross Boucher 38e2ca3589 Add pushed states to checkboxes. 2009-07-27 16:20:12 -07:00
Ross Boucher 5ccc638baf Add resources for CPButton disabled state. Closes #152. 2009-07-27 15:55:53 -07:00
Ross Boucher 9e6ba1ea06 Merge branch 'master' of git@github.com:280north/cappuccino 2009-07-27 13:18:08 -07:00
Ross Boucher c0400d6362 Fix a bug where press was clobbering CPApplication arguments.
Also changed line endings to Mac/Unix from Windows.
2009-07-27 13:16:31 -07:00
Francisco Ryan Tolmasky I e9fee72744 Merge branch 'master' of git@github.com:280north/cappuccino
Conflicts:
	Foundation/CPKeyValueObserving.j
2009-07-27 12:10:51 -07:00
Francisco Ryan Tolmasky I 59bec06e6e Removed CPDOMWindowBridge file.
Reviewed by me.
2009-07-27 12:06:07 -07:00
Ross BoucherandFrancisco Ryan Tolmasky I 64b81cfcdb Remove several CPDictionaries in favor of Objects, about a 15% performance gain. 2009-07-27 12:06:07 -07:00
Ross BoucherandFrancisco Ryan Tolmasky I 865a2b513f Slight performance improvement and memory improvement by moving the storage of KVO proxy objects. 2009-07-27 12:06:07 -07:00
Francisco Ryan Tolmasky I 2e37945b4f Removed remaining references to CPDOMWindowBridge.
Reviewed by me.
2009-07-27 12:06:07 -07:00
Francisco Ryan Tolmasky I 92594a7ef9 Removed references from CPWindow and CPPlatformWindow to CPDOMWindowBridge.
Reviewed by me.
2009-07-27 12:06:07 -07:00
Francisco Ryan Tolmasky I a34e23fa1c Removed CPDOMWindowBridge dependency in CPTextField.
Reviewed by me.
2009-07-27 12:06:07 -07:00
Francisco Ryan Tolmasky I fa5352ad40 Fix for drag and drop with platform windows.
Reviewed by me.
2009-07-27 12:06:07 -07:00
Francisco Ryan Tolmasky I 4d179b1db7 Remove global references to first window.
Reviewed by me.
2009-07-27 12:06:07 -07:00
Francisco Ryan Tolmasky I d2b1df88e8 FIx for drag and drop without CPDOMWindowBridge.
Reviewed by me.
2009-07-27 12:06:07 -07:00
Francisco Ryan Tolmasky I 756885fd53 Remove debugger command in CPPopUpButton that breaks Release builds.
Reviewed by me.
2009-07-27 12:06:06 -07:00
Ross Boucher 0ef4e9bca5 store dependent keys on the class object itself, rather than in a global map. 2009-07-26 23:56:18 -07:00
Ross Boucher 4370604165 Remove several CPDictionaries in favor of Objects, about a 15% performance gain. 2009-07-26 23:40:52 -07:00
Ross Boucher 5ce96b45bb Slight performance improvement and memory improvement by moving the storage of KVO proxy objects. 2009-07-26 22:46:22 -07:00
Francisco Ryan Tolmasky I 4f4a488762 Remove debugger command in CPPopUpButton that breaks Release builds.
Reviewed by me.
2009-07-26 15:28:41 -07:00
Francisco Ryan Tolmasky I d53207efd5 Furhter platform window support.
Reviewed by me.
2009-07-26 12:52:24 -07:00
Francisco Ryan Tolmasky I ba81b1356d Merge branch 'master' of git@github.com:280north/cappuccino 2009-07-26 02:06:06 -07:00
Francisco Ryan Tolmasky I ae7fbad2b9 Fix for dom layer.
Reviewed by me.
2009-07-26 01:34:16 -07:00
Francisco Ryan Tolmasky I e69d770583 Further deprecation of CPDOMWindowBridge.
Reviewed by me.
2009-07-25 17:10:48 -07:00
Francisco Ryan Tolmasky I 8382bb1ae8 Beginnings of Platform reorg.
Reviewed by me.
2009-07-25 16:47:30 -07:00
Geoffrey GrosenbachandRoss Boucher 82cfc5f994 Created initial test for CPSegmentedControl 2009-07-24 23:00:18 -07:00
Ross Boucher 16be11325f Merge branch 'master' of git@github.com:280north/cappuccino 2009-07-24 22:50:01 -07:00
Ross Boucher 5829c8b682 Fix an issue where removing all items from a CPPopUpButton caused an exception. 2009-07-24 22:49:18 -07:00
cacaodevandFrancisco Ryan Tolmasky I 57ee7bcfce Fixed bug reported by Paul Tomlin http://groups.google.com/group/objectivej/browse_thread/thread/e4bc41026a8f100f/6b14f3b74189df18
Signed-off-by: Francisco Ryan Tolmasky I <francisco@280north.com>
2009-07-25 02:48:58 +08:00
Francisco Ryan Tolmasky I 4824f22e3c Fix for super not working for class methods.
Closes #227.

Reviewed by me.
2009-07-24 11:22:32 -07:00
Tom Robinson 88be473da4 Fixed bug in type check logic, added ability to print stack traces on type check errors 2009-07-23 14:14:34 -07:00
Tom Robinson 3ff945663f Refactored objj_msgSend debug hooks 2009-07-23 13:24:33 -07:00
Francisco Ryan Tolmasky I 9f989297df Merge branch 'master' into tableview 2009-07-22 23:57:30 -07:00
Francisco Ryan Tolmasky I 12d03a5128 Fix for custom objects.
Reviewed by me.
2009-07-22 19:34:44 -07:00
Francisco Ryan Tolmasky I 369e02fb37 Merge branch 'master' into tableview
Conflicts:
	AppKit/CPView.j
2009-07-22 16:14:18 -07:00
Francisco Ryan Tolmasky I 48f0aa0b78 Fix for menuDidClose: sometimes not being sent, and other times being sent after the menu item action (it should be sent before).
Reviewed by me.
2009-07-22 10:43:59 -07:00
Francisco Ryan Tolmasky I 3e8cb8f9c6 Fixed an issue with CPTextField not allowing select all from API, and also made editing field editor take on the alignment properties of the host textfield.
Reviewed by me.
2009-07-20 20:41:15 -07:00
Francisco Ryan Tolmasky I 4865d6b20f Fixed an issue with dependent keys in KVO only working for composed properties, and also made the "frame" key on views dependent on a view's frame origin and frame size.
Reviewed by me.
2009-07-20 20:37:19 -07:00
tlrobinson 745e24d2f5 Rename objj_msgSendTypeCheck to objj_msgSend_TypeCheck to match others 2009-07-20 18:42:54 -07:00
tlrobinson d7b679dc78 * Move type checking to debug.js.
* Use JSON.stringify for serializing types array.
* Print Objective-J objects' names instead of descriptions to prevent inf recursion.
2009-07-20 18:39:37 -07:00
tlrobinson 9b99457871 Preliminary typechecking version of objj_msgSend, and preprocessor support. 2009-07-20 18:16:17 -07:00
Francisco Ryan Tolmasky I 6592328553 Merge branch 'master' into tableview 2009-07-17 12:18:49 -07:00
Marc NijdamandFrancisco Ryan Tolmasky I 9c226ae574 Ensuring all instance variables initialized to same values as initWithFrame: on coder init
Signed-off-by: Francisco Ryan Tolmasky I <francisco@280north.com>
2009-07-18 03:03:14 +08:00
Marc NijdamandFrancisco Ryan Tolmasky I 215619e6e2 Initial nib2cib work on collectionview
Signed-off-by: Francisco Ryan Tolmasky I <francisco@280north.com>
2009-07-18 03:03:12 +08:00
Francisco Ryan Tolmasky I eee6fe0e67 Merge branch 'master' into tableview 2009-07-17 11:47:12 -07:00
Marc NijdamandRoss Boucher 8e3ac66a2d Added '_' as allowed characted in implementation, protocol and interface names 2009-07-13 17:21:43 -07:00
Marc NijdamandRoss Boucher cc90f2e5f0 Added run in browser/refresh browser commands for project level view of run application 2009-07-13 17:21:24 -07:00
Marc NijdamandRoss Boucher 0356c6e622 Reordered a bit and added separator 2009-07-13 17:20:20 -07:00
Francisco Ryan Tolmasky I 308bbb2f8c Updated tableview nib.
Reviewed by me.
2009-07-11 21:01:07 -07:00
Francisco Ryan Tolmasky I d0599aef8f More java call removal from nib2cib.
Reviewed by me.
2009-07-11 20:31:12 -07:00
Francisco Ryan Tolmasky I afba1909bb Improved TableView nib support as well as including several nib2cib improvements.
Reviewed by me.
2009-07-11 18:12:20 -07:00
Francisco Ryan Tolmasky I 3761fb8037 Removed some commented code.
Reviewed by me.
2009-07-09 10:55:38 -07:00
Francisco Ryan Tolmasky I adc2344454 Merge branch 'master' into tableview 2009-07-08 11:55:40 -07:00
Francisco Ryan Tolmasky I a5a43de26e Fix for objectAtIndex: throwing out of range exceptions.
Closes #105.

Reviewed by me.
2009-07-08 11:52:47 -07:00
Francisco Ryan Tolmasky I c281d01974 Updated cib for test project.
Reviewed by me.
2009-07-08 11:17:31 -07:00
Francisco Ryan Tolmasky I 8660c72015 Fix for scrollers and nib2cib, as well as resizing.
Closes #217.
Closes #218.

Reviewed by me.
2009-07-08 11:15:15 -07:00
Francisco Ryan Tolmasky I cb81eeed15 Fix for selection in tableview.
Reviewed by me.
2009-07-07 18:42:44 -07:00
Francisco Ryan Tolmasky I 6ad5ec4d66 Merge branch 'master' into tableview 2009-07-07 11:34:27 -07:00
Francisco Ryan Tolmasky I b2f35b61d3 Fix for making scrolling smoother.
Reviewed by me.
2009-07-07 11:33:58 -07:00
Francisco Ryan Tolmasky I ddbc1e0e94 Changes to tableview nib.
Reviewed by me.
2009-07-07 11:33:19 -07:00
Francisco Ryan Tolmasky I 4086d37dac Slight fixes for resizing tableviews.
Reviewed by me.
2009-07-07 10:26:03 -07:00
Francisco Ryan Tolmasky I b9208c2f59 Fixed bug in Scroll View where disabled scrollable scroller would appear. Also added tests for CPScrollView.
Reviewed by me.
2009-07-06 22:43:43 -07:00
Francisco Ryan Tolmasky I 92bce1a663 Merge branch 'master' into tableview 2009-07-06 14:41:14 -07:00
Francisco Ryan Tolmasky I a5b468bbeb Fix for adding support for NSMutableString and NSMutableDictionary in nib2cib. Also, added support for inline strings.
Reviewed by me.
2009-07-06 14:39:33 -07:00
Francisco Ryan Tolmasky I 761e32a847 Fix for updating window background color to match crushed png.
Reviewed by me.
2009-07-05 21:04:08 -07:00
Marc NijdamandRoss Boucher 1f356053db Expanding zip file to full bundle and adding Objective-C symbol lists 2009-07-05 15:47:02 -07:00
Geoffrey GrosenbachandRoss Boucher 9d64526f26 Emacs mode for editing Objective-J files. 2009-07-05 15:46:06 -07:00
Francisco Ryan Tolmasky I 3c087f01b4 Merge branch 'master' into tableview 2009-07-05 08:36:45 -07:00
Francisco Ryan Tolmasky I 0ef7f53250 Fix for throwing a proper exception when class isn't defined in an archive.
Reviewed by me.
2009-07-05 08:35:44 -07:00
Francisco Ryan Tolmasky I 528ef4394a Beginnings of nib2cib support for new tableview.
Reviewed by me.
2009-07-05 07:59:54 -07:00
Francisco Ryan Tolmasky I b12017cd51 Slight fix for comparing old tableview to new tableview.
Reviewed by me.
2009-07-04 10:43:59 -07:00
Francisco Ryan Tolmasky I 714fc9d5bb Added beginnings of drawing selection.
Reviewed by me.
2009-07-04 10:22:20 -07:00
Francisco Ryan Tolmasky I d131127717 Merge branch 'master' into tableview 2009-07-04 06:52:13 -07:00
Francisco Ryan Tolmasky I b8046c479f Fix for creating outlets and actions that don't exist in interface builder.
Reviewed by me.
2009-07-04 06:49:55 -07:00
Klaas Pieter AnnemaandFrancisco Ryan Tolmasky I af062da99d Fix for selection being lost when changing the number of segments.
Reviewed by tolmasky.

Signed-off-by: Francisco Ryan Tolmasky I <francisco@280north.com>
2009-06-30 20:59:49 +08:00
Francisco Ryan Tolmasky I 21da2c6f56 Merge branch 'master' into tableview 2009-06-29 05:36:20 -07:00
Francisco Ryan Tolmasky I 7cc6e6af0a Fix for having multiple copies of objective-j gem in the system.
Reviewed by me.
2009-06-29 05:35:44 -07:00
Francisco Ryan Tolmasky I ab2cb38362 Fixed incorrect variable in CPIndexSet.
Reviewed by me.
2009-06-27 23:43:49 -07:00
Ross Boucher 8c171e5a40 Add corner views to the table view stuff 2009-06-25 14:42:30 -07:00
Ross Boucher ac6c03f2c7 Fix for incorrectly sized header views 2009-06-24 22:52:42 -07:00
Ross Boucher e97b78477b Merge branch 'tableview' of git@github.com:280north/cappuccino into tableview
Conflicts:
	AppKit/NEWCPTableView.j
	TableTest/AppController.j
2009-06-24 15:16:55 -07:00
Ross Boucher 849dda0725 Add support for header views in table view and scroll view 2009-06-24 15:12:26 -07:00
Francisco Ryan Tolmasky I b8755c113f Merge branch 'master' into tableview 2009-06-24 14:45:29 -07:00
Francisco Ryan Tolmasky I d57e7050db Added CPWindowList and CPWindowObjectList functions for grabbing the currently visible windows.
Reviewed by me.
2009-06-24 14:41:37 -07:00
Francisco Ryan Tolmasky I dd4db720ef Added selection methods.
Reviewed by me.
2009-06-23 21:26:41 -07:00
Francisco Ryan Tolmasky I 202d59475b Slight movement of debug code.
Reviewed by me.
2009-06-23 20:46:17 -07:00
Francisco Ryan Tolmasky I 1fecae3dc0 Further improvements to tableview, and reimplemented getIndexes: for CPIndexSet to match the new architecture.
Reviewed by me.
2009-06-23 10:51:16 -07:00
Francisco Ryan Tolmasky I 998f52c4a4 Merge commit 'origin/tableview' into tableview
Conflicts:
	Tests/Foundation/CPIndexSetTest.j
2009-06-21 23:08:32 -07:00
Francisco Ryan Tolmasky I bd07054a1b Fix for removeIndex in CPIndexSet and added tests for CPIndexSet.
Reviewed by me.
2009-06-21 20:25:29 -07:00
Ross Boucher adde315e2d Fix a bug in [CPArray indexOfObject:sortedByDesciptors:], add a matching test. 2009-06-21 16:16:45 -07:00
Ross Boucher c97bb6cbdd CPIndexSet test 2009-06-21 15:20:24 -07:00
Francisco Ryan Tolmasky I f4171f9afa Made all initializers call designated initializers and fixed numerous spacing issues.
Reviewed by me.
2009-06-21 13:59:58 -07:00
Francisco Ryan Tolmasky I d165761740 Began work on rewriting CPIndexSet.
Reviewed by me.
2009-06-21 03:50:06 -07:00
Francisco Ryan Tolmasky I ca1ea3721f Merge branch 'master' into tableview 2009-06-20 17:13:17 -07:00
Saikat ChakrabartiandFrancisco Ryan Tolmasky I 7d158de356 Fix for incorrect chain received mouseEntered events.
Closes #199.

Reviewed by me.
2009-06-20 17:12:03 -07:00
Francisco Ryan Tolmasky I 71a99deada Further work on loading system and fixed faulty test.
Reviewed by me.
2009-06-20 17:06:24 -07:00
Nabil ElisaandRoss Boucher c7f81691bf Added more colors to satisfy issue #182 2009-06-20 14:32:57 -07:00
Francisco Ryan Tolmasky I 05cdc2bab3 Changed file type to UTF-8.
Reviewed by me.
2009-06-20 01:56:38 -07:00
Francisco Ryan Tolmasky I 8beb71aa76 Work on appropriately sizing table view.
Reviewed by me.
2009-06-19 03:37:14 -07:00
Francisco Ryan Tolmasky I 201fda96a5 Getting something on the screen.
Reviewed by me.
2009-06-18 16:56:49 -07:00
Francisco Ryan Tolmasky I 4e94fa51fe Further fleshed out methods.
Reviewed by me.
2009-06-18 01:28:33 -07:00
Francisco Ryan Tolmasky I f920202bec Merge branch 'master' into tableview 2009-06-17 23:45:23 -07:00
tlrobinson 19f1657824 Disable encoding/decoding of plusses in URIs 2009-06-17 01:43:39 -07:00
Francisco Ryan Tolmasky I 5d1db76be2 Merge branch 'master' of git@github.com:280north/cappuccino 2009-06-16 17:22:33 -07:00
Francisco Ryan Tolmasky I c6795fdfcf Merge branch 'master' into tableview 2009-06-16 17:22:13 -07:00
Francisco Ryan Tolmasky I 35a9305347 Add setters/getters to cib custom objects/view/windows.
Reviewed by me.
2009-06-16 17:21:52 -07:00
tlrobinson e36ab855e8 Missing import for CibLoading in CPApplication 2009-06-15 18:20:12 -07:00
Francisco Ryan Tolmasky I d516037286 Merge branch 'master' into tableview 2009-06-15 12:43:07 -07:00
Francisco Ryan Tolmasky I b4abc5a99d Further key handling fixes.
Reviewed by me.
2009-06-15 12:33:16 -07:00
Francisco Ryan Tolmasky I 9bb9db760e Added removeObjectsInArray: convinience method to CPMutableSet.
Reviewed by me.
2009-06-13 21:45:46 -07:00
Francisco Ryan Tolmasky I 831ea11a6b Merge branch 'master' into tableview 2009-06-13 18:28:23 -07:00
Francisco Ryan Tolmasky I bfcb94a844 Various key input fixes.
Reviewed by me.
2009-06-13 18:27:31 -07:00
Francisco Ryan Tolmasky I 1e3b79de17 Fix for superview's not remaining mouseEntered when mouse moves over subviews.
Closes #126.

Reviewed by me.
2009-06-13 14:50:38 -07:00
Francisco Ryan Tolmasky I fe21fc82c4 Updating version strings to 0.7.1.
Reviewed by me.
2009-06-12 13:50:26 -07:00
Francisco Ryan Tolmasky I cb9d81aa7f Fix for capitalization issue with circular slider images.
Reviewed by me.
2009-06-11 14:05:12 -07:00
Francisco Ryan Tolmasky I 8f1a02cb0f Merge branch 'master' into tableview 2009-06-10 13:17:37 -07:00
Francisco Ryan Tolmasky I 1f0e4b0eca Fix for window returning a direct reference to its frame instead of a copy.
Reviewed by me.
2009-06-10 13:17:09 -07:00
Francisco Ryan Tolmasky I e0f53b89ca Merge branch 'master' into tableview 2009-06-10 11:50:07 -07:00
Francisco Ryan Tolmasky I 8b25240d04 Cleaned up CPControl ephemeral views code and got rid of some dead code in cib logic.
Reviewed by me.
2009-06-10 11:49:16 -07:00
Francisco Ryan Tolmasky I 7e88b1abfd Minor stylistic changes.
Reviewed by me.
2009-06-09 17:54:18 -07:00
Francisco Ryan Tolmasky I e38dfc4335 Merge branch 'master' into tableview 2009-06-09 16:45:59 -07:00
Francisco Ryan Tolmasky I 90fe0d64f5 Fix for dragged types not working on decoded views.
Reviewed by me.
2009-06-09 16:45:27 -07:00
Francisco Ryan Tolmasky I eab4f4bf78 Made CPImageView accept image drag and drop.
Reviewed by me.
2009-06-09 15:36:53 -07:00
Francisco Ryan Tolmasky I ece999662d Beginnings of new versions of these classes.
Reviewed by me.
2009-06-08 10:27:25 -07:00
Francisco Ryan Tolmasky I 8c049c3de4 Merge branch 'master' into tableview 2009-06-07 16:08:00 -07:00
Francisco Ryan Tolmasky I 6cab77e005 More hash->UID name changes.
Reviewed by andrew.
2009-06-07 16:07:08 -07:00
Francisco Ryan Tolmasky I c74642b641 Replacing several instances of -hash with the new -UID method. Partial fix for http://github.com/280north/cappuccino/issues#issue/10 .
Reviewed by andrew.
2009-06-07 15:47:21 -07:00
tlrobinson e7e804cae3 TableTest 2009-06-07 14:58:24 -07:00
aburkhalter 7ca3473b64 failing test for issue #112, fix for said issue of _doubleAction ReferenceError 2009-06-06 17:51:32 -07:00
aburkhalterandtlrobinson 927b94244a Added test coverage for CPSearchField instantiation, recentSearch getter/setter, added DOM protection to class init 2009-06-06 16:49:46 -07:00
tlrobinson a5c467fba5 Add CPSearchField.j to AppKit.j imports 2009-06-06 16:12:02 -07:00
cacaodevandtlrobinson fc74bba68c CPSearchField contributed by cacaodev 2009-06-06 15:27:25 -07:00
Tom Robinson 656c94a8cd Merge branch 'master' of git@github.com:280north/cappuccino 2009-06-05 23:45:41 -07:00
Tom Robinson 896eaf7937 Update Externals to latest. Remove first arg in objj, objjc, and cplutil to match changes to Narwhal. 2009-06-05 23:40:31 -07:00
Francisco Ryan Tolmasky I 886b4ef118 Fix for image views in toolbar items not displaying their images.
Reviewed by me.
2009-06-05 20:01:30 -07:00
Francisco Ryan Tolmasky I c42fb68d8a Made class swapping more robust.
Reviewed by me.
2009-06-05 17:31:35 -07:00
Francisco Ryan Tolmasky I 3f27fca518 Added support for custom classes on non-customviews in nib2cib.
Reviewed by me.
2009-06-04 02:38:06 -07:00
Francisco Ryan Tolmasky I c7823a92f8 Fix for -description in CPArray containing null or undefined values.
Reviewed by me.
2009-06-02 21:14:22 -07:00
Francisco Ryan Tolmasky I c61c892732 Merge branch 'master' of git@github.com:280north/cappuccino 2009-06-02 21:13:47 -07:00
Tom Robinson b0470ca2d7 Update to use JSON.{parse,stringify} 2009-06-02 15:07:07 -07:00
Tom Robinson 7c305c45fc Merge branch 'master' of git@github.com:280north/cappuccino 2009-06-02 15:04:09 -07:00
Tom Robinson cfda93d1e3 Update JSON support to json2.js, added in Objective-J. Deprecate CPJSObjectCreateJSON and CPJSObjectCreateWithJSON. 2009-06-02 15:02:25 -07:00
Francisco Ryan Tolmasky I b4c7af498b Spacing fix.
Reviewed by me.
2009-06-01 17:38:19 -07:00
Francisco Ryan Tolmasky I 6ddb7851f6 Added generation code in a comment for future use if necessary.
Reviewed by me.
2009-06-01 17:17:45 -07:00
Ross Boucher 7f60bdec4f Update the documentation of methods define with the BRIDGE macro 2009-06-01 10:01:44 -07:00
Ross Boucher 8971c320bd Don't capture errors during DOM events in DEBUG mode, to make it easier to debug IE 2009-05-31 19:17:56 -07:00
Ross Boucher a710dc974f Fix for VML paths 2009-05-31 19:17:36 -07:00
cacaodevandRoss Boucher e1b63b848f Set disabled CPMenuItem's text color to lightGrayColor instead of darkGrayColor 2009-05-31 15:12:13 -07:00
Francisco Ryan Tolmasky I 5409face8c Fix for providing too many image slices breaking CPView.
Reviewed by me.
2009-05-31 13:44:58 -07:00
Ross Boucher c9e40cbfba Fix for a change in CGContextAddEllipseInRect that was breaking existing core graphics code 2009-05-31 13:06:50 -07:00
Ross Boucher 35947697f2 Fix for KAPPA missing in CGPath. Looks like it was auto-merged out. 2009-05-31 12:12:51 -07:00
Ross Boucher 3e1f09bb7a Merge branch 'master' of git@github.com:280north/cappuccino 2009-05-31 11:26:32 -07:00
Martin HäckerandRoss Boucher 82ef2356a5 fixes as per the review from Ross Boucher 2009-05-31 11:26:00 -07:00
Nicholas SmallandFrancisco Ryan Tolmasky I 33f96dacd1 Fix for undefined key handling.
Reviewed by me.
2009-05-31 01:34:03 -07:00
Francisco Ryan Tolmasky I cc24cd9a73 Fix for nib2cib's separator menu items not showing up.
Reviewed by me.
2009-05-31 01:32:56 -07:00
Francisco Ryan Tolmasky I 0fff3bade6 Support for new CPEvent mechanism.
Reviewed by me.
2009-05-30 23:18:48 -07:00
Francisco Ryan Tolmasky I b1c410d42c Merge branch 'master' of git@github.com:280north/cappuccino 2009-05-30 23:16:57 -07:00
Francisco Ryan Tolmasky I f4b4d38165 Coat tailed CPEvents on native DOM events if they exist, saving the creation of many objects.
Reviewed by me.
2009-05-30 23:16:18 -07:00
Ross Boucher f46aa870a7 adding briefs and unifying class header structure
Conflicts:

	Foundation/CPArray.j
	Foundation/CPAttributedString.j
	Foundation/CPBundle.j
	Foundation/CPCountedSet.j
	Foundation/CPIndexSet.j
	Foundation/CPJSONPConnection.j
2009-05-30 13:49:10 -07:00
Ross Boucher 7d4c2840eb All Foundation classes briefed
Conflicts:

	Foundation/CPSet.j
	Foundation/CPTimer.j
	Foundation/CPURLConnection.j
2009-05-30 13:46:42 -07:00
Ross Boucher 8fb0abd3d6 Added briefs to all Foundation and made some cleanups to docs
Conflicts:

	Foundation/CPArray.j
	Foundation/CPBundle.j
	Foundation/CPCountedSet.j
	Foundation/CPIndexSet.j
	Foundation/CPTimer.j
	Foundation/CPURLConnection.j
2009-05-30 13:45:26 -07:00
Ross Boucher f6bd4ddd96 Added a new group Cocoa Compatability for the empty compatability
classes like CPMutableArray

Conflicts:

	Foundation/CPAttributedString.j
	Foundation/CPSet.j
2009-05-30 13:42:57 -07:00
Ross Boucher 5f5efffe9d A few updates in preparation of the new media panel 2009-05-30 13:41:48 -07:00
Ross Boucher 48f31743dd Update to docs of replaceCharactersInRange in CPAttributedString.
Conflicts:

	Foundation/CPAttributedString.j
2009-05-30 13:41:18 -07:00
Tom Robinson 1224ca9493 Rename plutil back to cputil. Oops. 2009-05-29 18:28:06 -07:00
Tom Robinson 45ec895df0 Fixed incorrect variables in regexp-rhino-patch 2009-05-29 17:12:12 -07:00
Tom Robinson 318d0456af Merge branch 'master' of git@github.com:280north/cappuccino 2009-05-29 16:58:00 -07:00
Tom Robinson 5446e1f98f Bring back the Rhino regex patch to use native Java regex. 2009-05-29 16:57:28 -07:00
Francisco Ryan Tolmasky I d4b9c4c5e1 Merge branch 'master' of git@github.com:280north/cappuccino 2009-05-27 01:35:26 -07:00
Francisco Ryan Tolmasky I 5cb9f5f7c2 Fix for Unicode chars being mangled when building.
Closes #146.

Reviewed by me.
2009-05-27 01:34:56 -07:00
cacaodevandRoss Boucher a7bd5e1bf0 Allow rake to process files located subfolders of Foundation/ 2009-05-26 23:59:59 -07:00
Francisco Ryan Tolmasky I bf21fbd000 Slight color modification to theme showcase.
Reviewed by me.
2009-05-26 00:30:58 -07:00
Ross Boucher 377107d63a Fix for stringByReplacingOccurrencesOfString: not working with strings that have regex control characters in them. 2009-05-25 16:12:27 -07:00
Francisco Ryan Tolmasky I 25d20df5f3 Merge branch 'master' of git@github.com:280north/cappuccino 2009-05-25 15:29:41 -07:00
Francisco Ryan Tolmasky I cfdb6b0df2 Further work on theme showcase.
Reviewed by me.
2009-05-25 15:29:17 -07:00
tlrobinson 9955346958 When loading modules escape "+" in case they're converted to spaces later.
Updated to latest Narwhal and Jack
2009-05-25 15:22:07 -07:00
Francisco Ryan Tolmasky I a71822cee8 Added Demos, Aristo, and WebSite to .gitignore so they can be checked out together and eventually built together.
Reviewed by me.
2009-05-24 16:09:02 -07:00
Francisco Ryan Tolmasky I 3523a9ff12 Organized BlendKit classes into their own files and added licensing info.
Reviewed by me.
2009-05-24 15:00:14 -07:00
Francisco Ryan Tolmasky I 1f64cb6393 Merge branch 'master' of git@github.com:280north/cappuccino 2009-05-24 14:20:44 -07:00
Francisco Ryan Tolmasky I 0235076fb6 Fix for typos in CPButton.j.
Closes #139.

Reviewed by me.
2009-05-24 14:20:18 -07:00
Ross Boucher c56e552d6e Merge branch 'master' of git@github.com:280north/cappuccino 2009-05-24 13:43:44 -07:00
Ross Boucher 5a3f1c81a0 Add open panel beginnings 2009-05-24 13:43:23 -07:00
Ross Boucher d3938f3031 Merge branch 'master' of git@github.com:280north/cappuccino 2009-05-23 17:28:55 -07:00
Ross Boucher cfa21b0c96 Add a randomColor method. Useful for debugging. 2009-05-23 17:28:21 -07:00
444 changed files with 27746 additions and 9910 deletions
+3
View File
@@ -1,3 +1,6 @@
.DS_Store
Frameworks
Build
Demos
./Aristo
WebSite
+8
View File
@@ -25,12 +25,17 @@
@import "CPAnimation.j"
@import "CPApplication.j"
@import "CPBezierPath.j"
@import "CPBox.j"
@import "CPButton.j"
@import "CPButtonBar.j"
@import "CPCheckBox.j"
@import "CPCib.j"
@import "CPCibConnector.j"
@import "CPCibControlConnector.j"
@import "CPCibLoading.j"
@import "CPCibOutletConnector.j"
@import "CPClipView.j"
@import "CPCollectionViewItem.j"
@import "CPCollectionView.j"
@import "CPColor.j"
@import "CPColorPanel.j"
@@ -50,12 +55,14 @@
@import "CPImageView.j"
@import "CPMenu.j"
@import "CPMenuItem.j"
@import "CPOpenPanel.j"
@import "CPPanel.j"
@import "CPPasteboard.j"
@import "CPPopUpButton.j"
@import "CPProgressIndicator.j"
@import "CPRadio.j"
@import "CPResponder.j"
@import "CPSearchField.j"
@import "CPScrollView.j"
@import "CPScroller.j"
@import "CPSecureTextField.j"
@@ -70,6 +77,7 @@
@import "CPToolbar.j"
@import "CPToolbarItem.j"
@import "CPView.j"
@import "CPViewController.j"
@import "CPWebView.j"
@import "CPWindow.j"
@import "CPWindowController.j"
+361
View File
@@ -0,0 +1,361 @@
/*
* CPAccordionView.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPArray.j>
@import <Foundation/CPObject.j>
@import <Foundation/CPKeyValueObserving.j>
@import <Foundation/CPIndexSet.j>
@import <Foundation/CPString.j>
@import <AppKit/CPView.j>
#import "CoreGraphics/CGGeometry.h"
@implementation CPAccordionViewItem : CPObject
{
CPString _identifier @accessors(property=identifier);
CPView _view @accessors(property=view);
CPString _label @accessors(property=label);
}
- (id)init
{
return [self initWithIdentifier:@""];
}
- (id)initWithIdentifier:(CPString)anIdentifier
{
self = [super init];
if (self)
[self setIdentifier:anIdentifier];
return self;
}
@end
@implementation CPAccordionView : CPView
{
CPInteger _dirtyItemIndex;
CPView _itemHeaderPrototype;
CPMutableArray _items;
CPMutableArray _itemViews;
CPIndexSet _expandedItemIndexes;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_items = [];
_itemViews = [];
_expandedItemIndexes = [CPIndexSet indexSet];
[self setItemHeaderPrototype:[[CPButton alloc] initWithFrame:_CGRectMake(0.0, 0.0, 100.0, 24.0)]];
}
return self;
}
- (void)setItemHeaderPrototype:(CPView)aView
{
_itemHeaderPrototype = aView;
}
- (CPView)itemHeaderPrototype
{
return _itemHeaderPrototype;
}
- (CPArray)items
{
return _items;
}
- (void)addItem:(CPAccordionItem)anItem
{
[self insertItem:anItem atIndex:_items.length];
}
- (void)insertItem:(CPAccordionItem)anItem atIndex:(CPInteger)anIndex
{
// FIXME: SHIFT ITEMS RIGHT
[_expandedItemIndexes addIndex:anIndex];
var itemView = [[_CPAccordionItemView alloc] initWithAccordionView:self];
[itemView setIndex:anIndex];
[itemView setLabel:[anItem label]];
[itemView setContentView:[anItem view]];
[self addSubview:itemView];
[_items insertObject:anItem atIndex:anIndex];
[_itemViews insertObject:itemView atIndex:anIndex];
[self _invalidateItemsStartingAtIndex:anIndex];
[self setNeedsLayout];
}
- (void)removeItem:(CPAccordionItem)anItem
{
[self removeItemAtIndex:[_items indexOfObjectIdenticalTo:anItem]];
}
- (void)removeItemAtIndex:(CPInteger)anIndex
{
// SHIFT ITEMS LEFT
[_expandedItemIndexes removeIndex:anIndex];
[_itemViews[anIndex] removeFromSuperview];
[_items removeObjectAtIndex:anIndex];
[_itemViews removeObjectAtIndex:anIndex];
[self _invalidateItemsStartingAtIndex:anIndex];
[self setNeedsLayout];
}
- (void)removeAllItems
{
var count = _items.length;
while (count--)
[self removeItemAtIndex:count];
}
- (void)expandItemAtIndex:(CPInteger)anIndex
{
if (![_itemViews[anIndex] isCollapsed])
return;
[_expandedItemIndexes addIndex:anIndex];
[_itemViews[anIndex] setCollapsed:NO];
[self _invalidateItemsStartingAtIndex:anIndex];
}
- (void)collapseItemAtIndex:(CPInteger)anIndex
{
if ([_itemViews[anIndex] isCollapsed])
return;
[_expandedItemIndexes removeIndex:anIndex];
[_itemViews[anIndex] setCollapsed:YES];
[self _invalidateItemsStartingAtIndex:anIndex];
}
- (void)toggleItemAtIndex:(CPInteger)anIndex
{
var itemView = _itemViews[anIndex];
if ([itemView isCollapsed])
[self expandItemAtIndex:anIndex];
else
[self collapseItemAtIndex:anIndex];
}
- (CPIndexSet)expandedItemIndexes
{
return _expandedItemIndexes;
}
- (CPIndexSet)collapsedItemIndexes
{
var indexSet = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, _items.length)];
[indexSet removeIndexes:_expandedIndexes];
return indexSet;
}
- (void)_invalidateItemsStartingAtIndex:(CPInteger)anIndex
{
if (_dirtyItemIndex === CPNotFound)
_dirtyItemIndex = anIndex;
_dirtyItemIndex = MIN(_dirtyItemIndex, anIndex);
[self setNeedsLayout];
}
- (void)setFrameSize:(CGSize)aSize
{
var width = _CGRectGetWidth([self frame]);
[super setFrameSize:aSize];
if (width !== _CGRectGetWidth([self frame]))
[self _invalidateItemsStartingAtIndex:0];
}
- (void)layoutSubviews
{
if (_items.length <= 0)
return [self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), 0.0)];
if (_dirtyItemIndex === CPNotFound)
return;
_dirtyItemIndex = MIN(_dirtyItemIndex, _items.length - 1);
var index = _dirtyItemIndex,
count = _itemViews.length,
width = _CGRectGetWidth([self bounds]),
y = index > 0 ? CGRectGetMaxY([_itemViews[index - 1] frame]) : 0.0;
// Do this now (instead of after looping), so that if we are made dirty again in the middle we don't blow this value away.
_dirtyItemIndex = CPNotFound;
for (; index < count; ++index)
{
var itemView = _itemViews[index];
[itemView setFrameY:y width:width];
y = CGRectGetMaxY([itemView frame]);
}
[self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), y)];
}
@end
@implementation _CPAccordionItemView : CPView
{
CPAccordionView _accordionView;
BOOL _isCollapsed @accessors(getter=isCollapsed, setter=setCollapsed:);
CPInteger _index @accessors(property=index);
CPView _headerView;
CPView _contentView;
}
- (id)initWithAccordionView:(CPAccordionView)anAccordionView
{
self = [super initWithFrame:_CGRectMakeZero()];
if (self)
{
_accordionView = anAccordionView;
_isCollapsed = NO;
var bounds = [self bounds];
_headerView = [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:[_accordionView itemHeaderPrototype]]];
if ([_headerView respondsToSelector:@selector(setTarget:)] && [_headerView respondsToSelector:@selector(setAction:)])
{
[_headerView setTarget:self];
[_headerView setAction:@selector(toggle:)];
}
[self addSubview:_headerView];
}
return self;
}
- (void)toggle:(id)aSender
{
[_accordionView toggleItemAtIndex:[self index]];
}
- (void)setLabel:(CPString)aLabel
{
if ([_headerView respondsToSelector:@selector(setTitle:)])
[_headerView setTitle:aLabel];
else if ([_headerView respondsToSelector:@selector(setLabel:)])
[_headerView setLabel:aLabel];
else if ([_headerView respondsToSelector:@selector(setStringValue:)])
[_headerView setStringValue:aLabel];
}
- (void)setContentView:(CPView)aView
{
if (_contentView === aView)
return;
[_contentView removeObserver:self forKeyPath:@"frame"];
[_contentView removeFromSuperview];
_contentView = aView;
[_contentView addObserver:self forKeyPath:@"frame" options:0 context:NULL];
[self addSubview:_contentView];
[_accordionView _invalidateItemsStartingAtIndex:[self index]];
}
- (void)setFrameY:(float)aY width:(float)aWidth
{
var headerHeight = _CGRectGetHeight([_headerView frame]);
// Size to fit or something?
[_headerView setFrameSize:_CGSizeMake(aWidth, headerHeight)];
[_contentView setFrameOrigin:_CGPointMake(0.0, headerHeight)];
if ([self isCollapsed])
[self setFrame:_CGRectMake(0.0, aY, aWidth, headerHeight)];
else
{
var contentHeight = _CGRectGetHeight([_contentView frame]);
[_contentView setFrameSize:_CGSizeMake(aWidth, contentHeight)];
[self setFrame:_CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)];
}
}
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
{
}
- (void)observeValueForKeyPath:(CPString)aKeyPath
ofObject:(id)anObject
change:(CPDictionary)aChange
context:(id)aContext
{
if (aKeyPath === "frame" && !CGRectEqualToRect([aChange objectForKey:CPKeyValueChangeOldKey], [aChange objectForKey:CPKeyValueChangeNewKey]))
[_accordionView _invalidateItemsStartingAtIndex:[self index]];
/*
else if (aKeyPath === "itemHeaderPrototype")
{
}
*/
}
@end
+36 -29
View File
@@ -62,12 +62,12 @@ var CPAlertWarningImage,
CPAlert is an alert panel that can be displayed modally to present the
user with a message and one or more options.
It can be used to display an information message (<pre>CPInformationalAlertStyle</pre>),
a warning message (<pre>CPWarningAlertStyle</pre> - which is the default), or a critical
alert (<pre>CPCriticalAlertStyle</pre>). In each case the user can be presented with one
or more options by adding buttons using the <pre>addButtonWithTitle:</pre> method.
It can be used to display an information message \c CPInformationalAlertStyle,
a warning message \c CPWarningAlertStyle (the default), or a critical
alert \c CPCriticalAlertStyle. In each case the user can be presented with one
or more options by adding buttons using the \c -addButtonWithTitle: method.
The panel is displayed modally by calling <pre>runModal</pre> and once the user has
The panel is displayed modally by calling \c -runModal and once the user has
dismissed the panel, a message will be sent to the panel's delegate (if set), informing
it which button was clicked (see delegate methods).
@@ -112,25 +112,16 @@ var CPAlertWarningImage,
}
/*!
Initializes a <pre>CPAlert</pre> panel with the default alert style (<pre>CPWarningAlertStyle</pre>).
Initializes a \c CPAlert panel with the default alert style \c CPWarningAlertStyle.
*/
- (id)init
{
self = [super init];
if (self)
if (self = [super init])
{
_buttonCount = 0;
_buttons = [CPArray array];
_alertStyle = CPWarningAlertStyle;
_messageLabel = [[CPTextField alloc] initWithFrame:CGRectMake(57.0, 10.0, 220.0, 80.0)];
[_messageLabel setFont:[CPFont systemFontOfSize:12.0]];
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
[_messageLabel setAlignment:CPJustifiedTextAlignment];
_alertImageView = [[CPImageView alloc] initWithFrame:CGRectMake(15.0, 12.0, 32.0, 32.0)];
[self setWindowStyle:nil];
}
@@ -145,23 +136,36 @@ var CPAlertWarningImage,
{
_windowStyle = styleMask;
_alertPanel = [[CPPanel alloc] initWithContentRect:CGRectMake(0.0, 0.0, 300.0, 130.0) styleMask:styleMask ? styleMask | CPTitledWindowMask : CPTitledWindowMask];
_alertPanel = [[CPPanel alloc] initWithContentRect:CGRectMake(0.0, 0.0, 400.0, 110.0) styleMask:styleMask ? styleMask | CPTitledWindowMask : CPTitledWindowMask];
[_alertPanel setFloatingPanel:YES];
[_alertPanel center];
[_messageLabel setTextColor:(styleMask == CPHUDBackgroundWindowMask) ? [CPColor whiteColor] : [CPColor blackColor]];
[_messageLabel setTextColor:(styleMask & CPHUDBackgroundWindowMask) ? [CPColor whiteColor] : [CPColor blackColor]];
var count = [_buttons count];
for(var i=0; i < count; i++)
{
var button = _buttons[i];
[button setFrameSize:CGSizeMake([button frame].size.width, (styleMask == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
[button setBezelStyle:(styleMask == CPHUDBackgroundWindowMask) ? CPHUDBezelStyle : CPRoundedBezelStyle];
[button setBezelStyle:(styleMask & CPHUDBackgroundWindowMask) ? CPHUDBezelStyle : CPRoundedBezelStyle];
[[_alertPanel contentView] addSubview:button];
}
if (!_messageLabel)
{
var bounds = [[_alertPanel contentView] bounds];
_messageLabel = [[CPTextField alloc] initWithFrame:CGRectMake(57.0, 10.0, CGRectGetWidth(bounds) - 73.0, 62.0)];
[_messageLabel setFont:[CPFont boldSystemFontOfSize:13.0]];
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
[_messageLabel setAlignment:CPJustifiedTextAlignment];
[_messageLabel setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
_alertImageView = [[CPImageView alloc] initWithFrame:CGRectMake(15.0, 12.0, 32.0, 32.0)];
}
[[_alertPanel contentView] addSubview:_messageLabel];
[[_alertPanel contentView] addSubview:_alertImageView];
}
@@ -244,14 +248,15 @@ var CPAlertWarningImage,
/*!
Adds a button with a given title to the receiver.
Buttons will be added starting from the right hand side of the <pre>CPAlert</pre> panel.
Buttons will be added starting from the right hand side of the \c CPAlert panel.
The first button will have the index 0, the second button 1 and so on.
You really shouldn't need more than 3 buttons.
*/
- (void)addButtonWithTitle:(CPString)title
{
var button = [[CPButton alloc] initWithFrame:CGRectMake(200.0 - (_buttonCount * 90.0), 98.0, 80.0, (_windowStyle == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
var bounds = [[_alertPanel contentView] bounds],
button = [[CPButton alloc] initWithFrame:CGRectMake(CGRectGetWidth(bounds) - ((_buttonCount + 1) * 90.0), CGRectGetHeight(bounds) - 34.0, 80.0, (_windowStyle == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
[button setTitle:title];
[button setTarget:self];
@@ -259,6 +264,8 @@ var CPAlertWarningImage,
[button setAction:@selector(_notifyDelegate:)];
[button setBezelStyle:(_windowStyle == CPHUDBackgroundWindowMask) ? CPHUDBezelStyle : CPRoundRectBezelStyle];
[button setAutoresizingMask:CPViewMinXMargin|CPViewMinYMargin];
[[_alertPanel contentView] addSubview:button];
if (_buttonCount == 0)
@@ -269,7 +276,7 @@ var CPAlertWarningImage,
}
/*!
Displays the <pre>CPAlert</pre> panel as a modal dialog. The user will not be
Displays the \c CPAlert panel as a modal dialog. The user will not be
able to interact with any other controls until s/he has dismissed the alert
by clicking on one of the buttons.
*/
@@ -298,11 +305,11 @@ var CPAlertWarningImage,
/* @ignore */
- (void)_notifyDelegate:(id)button
{
if (_delegate && [_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:[button tag]];
[CPApp abortModal];
[_alertPanel close];
if (_delegate && [_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:[button tag]];
}
@end
+51 -16
View File
@@ -57,10 +57,10 @@ ACTUAL_FRAME_RATE = 0;
@par Delegate Methods
@delegate -(BOOL)animationShouldStart:(CPAnimation)animation;
Called at the beginning of <code>startAnimation</code>.
Called at the beginning of \c -startAnimation.
@param animation the animation that will start
@return <code>YES</code> allows the animation to start.
<code>NO</code> stops the animation.
@return \c YES allows the animation to start.
\c NO stops the animation.
@delegate -(void)animationDidEnd:(CPAnimation)animation;
Called when an animation has completed.
@@ -72,7 +72,7 @@ ACTUAL_FRAME_RATE = 0;
@delegate - (float)animation:(CPAnimation)animation valueForProgress:(float)progress;
The value from this method will be returned when CPAnimation's
<code>currentValue</code> method is called.
\c currentValue method is called.
@param animation the animation to obtain the curve value for
@param progress the current animation progress
@return the curve value
@@ -106,8 +106,9 @@ ACTUAL_FRAME_RATE = 0;
{
_progress = 0.0;
_duration = MAX(0.0, aDuration);
_animationCurve = anAnimationCurve;
_frameRate = 60.0;
[self setAnimationCurve:anAnimationCurve];
}
return self;
@@ -120,7 +121,7 @@ ACTUAL_FRAME_RATE = 0;
*/
- (void)setAnimationCurve:(CPAnimationCurve)anAnimationCurve
{
switch (_animationCurve)
switch (anAnimationCurve)
{
case CPAnimationEaseInOut: timingFunctionName = kCAMediaTimingFunctionEaseInEaseOut;
break;
@@ -154,7 +155,7 @@ ACTUAL_FRAME_RATE = 0;
/*!
Sets the animation's length.
@param aDuration the new animation length
@throws CPInvalidArgumentException if <code>aDuration</code> is negative
@throws CPInvalidArgumentException if \c aDuration is negative
*/
- (void)setDuration:(CPTimeInterval)aDuration
{
@@ -175,7 +176,7 @@ ACTUAL_FRAME_RATE = 0;
/*!
Sets the animation frame rate. This is not a guaranteed frame rate. 0 means to go as fast as possible.
@param frameRate the new desired frame rate
@throws CPInvalidArgumentException if <code>frameRate</code> is negative
@throws CPInvalidArgumentException if \c frameRate is negative
*/
- (void)setFrameRate:(float)frameRate
{
@@ -211,14 +212,14 @@ ACTUAL_FRAME_RATE = 0;
}
/*!
Starts the animation. The method calls <code>animationShouldStart:</code>
Starts the animation. The method calls \c -animationShouldStart:
on the delegate (if it implements it) to see if the animation
should begin.
*/
- (void)startAnimation
{
// If we're already animating, or our delegate stops us, animate.
if (_timer || _delegate && [_delegate respondsToSelector:@selector(animationShouldStart)] && ![_delegate animationShouldStart:self])
if (_timer || _delegate && [_delegate respondsToSelector:@selector(animationShouldStart:)] && ![_delegate animationShouldStart:self])
return;
if (_progress === 1.0)
@@ -270,7 +271,7 @@ ACTUAL_FRAME_RATE = 0;
}
/*!
Returns <code>YES</code> if the animation
Returns \c YES if the animation
is running.
*/
- (BOOL)isAnimating
@@ -300,13 +301,47 @@ ACTUAL_FRAME_RATE = 0;
*/
- (float)currentValue
{
var t = [self currentProgress];
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
return [_delegate animation:self valueForProgress:_progress];
return [_delegate animation:self valueForProgress:t];
if (_animationCurve == CPAnimationLinear)
return _progress;
alert("IMPLEMENT ANIMATION CURVES!!!");
var c1 = [],
c2 = [];
[_timingFunction getControlPointAtIndex:1 values:c1];
[_timingFunction getControlPointAtIndex:2 values:c2];
return CubicBezierAtTime(t,c1[0],c1[1],c2[0],c2[1],_duration);
}
@end
// currently used function to determine time
// 1:1 conversion to js from webkit source files
// UnitBezier.h, WebCore_animation_AnimationBase.cpp
var CubicBezierAtTime = function CubicBezierAtTime(t,p1x,p1y,p2x,p2y,duration)
{
var ax=0,bx=0,cx=0,ay=0,by=0,cy=0;
// `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
function sampleCurveX(t) {return ((ax*t+bx)*t+cx)*t;};
function sampleCurveY(t) {return ((ay*t+by)*t+cy)*t;};
function sampleCurveDerivativeX(t) {return (3.0*ax*t+2.0*bx)*t+cx;};
// The epsilon value to pass given that the animation is going to run over |duration| seconds. The longer the animation, the more precision is needed in the timing function result to avoid ugly discontinuities.
function solveEpsilon(duration) {return 1.0/(200.0*duration);};
function solve(x,epsilon) {return sampleCurveY(solveCurveX(x,epsilon));};
// Given an x value, find a parametric value it came from.
function solveCurveX(x,epsilon) {var t0,t1,t2,x2,d2,i;
function fabs(n) {if(n>=0) {return n;}else {return 0-n;}};
// First try a few iterations of Newton's method -- normally very fast.
for(t2=x, i=0; i<8; i++) {x2=sampleCurveX(t2)-x; if(fabs(x2)<epsilon) {return t2;} d2=sampleCurveDerivativeX(t2); if(fabs(d2)<1e-6) {break;} t2=t2-x2/d2;}
// Fall back to the bisection method for reliability.
t0=0.0; t1=1.0; t2=x; if(t2<t0) {return t0;} if(t2>t1) {return t1;}
while(t0<t1) {x2=sampleCurveX(t2); if(fabs(x2-x)<epsilon) {return t2;} if(x>x2) {t0=t2;}else {t1=t2;} t2=(t1-t0)*.5+t0;}
return t2; // Failure.
};
// Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
cx=3.0*p1x; bx=3.0*(p2x-p1x)-cx; ax=1.0-cx-bx; cy=3.0*p1y; by=3.0*(p2y-p1y)-cy; ay=1.0-cy-by;
// Convert from input time to parametric value in curve, then from that to output time.
return solve(t, solveEpsilon(duration));
};
+182 -39
View File
@@ -28,6 +28,9 @@
@import "CPResponder.j"
@import "CPDocumentController.j"
@import "CPThemeBlend.j"
@import "CPCibLoading.j"
@import "CPPlatform.j"
var CPMainCibFile = @"CPMainCibFile",
CPMainCibFileHumanFriendly = @"Main cib file base name";
@@ -36,6 +39,11 @@ CPApp = nil;
CPApplicationWillFinishLaunchingNotification = @"CPApplicationWillFinishLaunchingNotification";
CPApplicationDidFinishLaunchingNotification = @"CPApplicationDidFinishLaunchingNotification";
CPApplicationWillTerminateNotification = @"CPApplicationWillTerminateNotification";
CPTerminateNow = YES;
CPTerminateCancel = NO;
CPTerminateLater = -1; // not currently supported
CPRunStoppedResponse = -1000;
CPRunAbortedResponse = -1001;
@@ -48,7 +56,7 @@ CPRunContinuesResponse = -1002;
CPApplication is THE way to start up the Cappucino framework for your application to use.
Every GUI application has exactly one instance of CPApplication (or of a custom subclass of
CPApplication). Your program's main() function can create that instance by calling the
<code>CPApplicationMain</code> function. A simple example looks like this:
\c CPApplicationMain function. A simple example looks like this:
<pre>
function main(args, namedArgs)
@@ -83,6 +91,7 @@ CPRunContinuesResponse = -1002;
//
id _delegate;
BOOL _finishedLaunching;
CPDictionary _namedArgs;
CPArray _args;
@@ -104,7 +113,7 @@ CPRunContinuesResponse = -1002;
/*!
Initializes the Document based application with basic menu functions.
Functions are <code>New, Open, Undo, Redo, Save, Cut, Copy, Paste</code>.
Functions are \c New, \c Open, \c Undo, \c Redo, \c Save, \c Cut, \c Copy, \c Paste.
@return the initialized application
*/
- (id)init
@@ -234,10 +243,10 @@ CPRunContinuesResponse = -1002;
}
/*!
This method is called by <code>run</code> before the event loop begins.
This method is called by \c -run before the event loop begins.
When it successfully completes, it posts the notification
CPApplicationDidFinishLaunchingNotification. If you override
<code>finishLaunching</code>, the subclass method should invoke the superclass method.
\c -finishLaunching, the subclass method should invoke the superclass method.
*/
- (void)finishLaunching
{
@@ -265,19 +274,72 @@ CPRunContinuesResponse = -1002;
[defaultCenter
postNotificationName:CPApplicationWillFinishLaunchingNotification
object:self];
if (_documentController)
var needsUntitled = !!_documentController,
URLStrings = window.cpOpeningURLStrings && window.cpOpeningURLStrings(),
index = 0,
count = [URLStrings count];
for (; index < count; ++index)
needsUntitled = ![self _openURL:[CPURL URLWithString:URLStrings[index]]] || needsUntitled;
if (needsUntitled && [_delegate respondsToSelector:@selector(applicationShouldOpenUntitledFile:)])
needsUntitled = [_delegate applicationShouldOpenUntitledFile:self];
if (needsUntitled)
[_documentController newDocument:self];
[_documentController _updateRecentDocumentsMenu];
[defaultCenter
postNotificationName:CPApplicationDidFinishLaunchingNotification
object:self];
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
_finishedLaunching = YES;
}
- (void)terminate:(id)aSender
{
[[CPDocumentController sharedDocumentController] closeAllDocumentsWithDelegate:self
didCloseAllSelector:@selector(_documentController:didCloseAll:context:)
contextInfo:nil];
}
- (void)_documentController:(NSDocumentController *)docController didCloseAll:(BOOL)didCloseAll context:(Object)info
{
// callback method for terminate:
if (didCloseAll)
{
if ([_delegate respondsToSelector:@selector(applicationShouldTerminate:)])
[self replyToApplicationShouldTerminate:[_delegate applicationShouldTerminate:self]];
else
[self replyToApplicationShouldTerminate:YES];
}
}
- (void)replyToApplicationShouldTerminate:(BOOL)terminate
{
if (terminate == CPTerminateNow)
{
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillTerminateNotification object:self];
[CPPlatform terminateApplication];
}
}
- (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps
{
[CPPlatform activateIgnoringOtherApps:shouldIgnoreOtherApps];
}
- (void)hideOtherApplications:(id)aSender
{
[CPPlatform hideOtherApplications:self];
}
/*!
Calls <code>finishLaunching</code> method which results in starting
Calls \c -finishLaunching method which results in starting
the main event loop.
*/
- (void)run
@@ -287,7 +349,7 @@ CPRunContinuesResponse = -1002;
// Managing the Event Loop
/*!
Starts a modal event loop for <code>aWindow</code>
Starts a modal event loop for \c aWindow
@param aWindow the window to start the event loop for
*/
- (void)runModalForWindow:(CPWindow)aWindow
@@ -296,8 +358,8 @@ CPRunContinuesResponse = -1002;
}
/*!
Stops the event loop started by <code>runModalForWindow:</code> and
sets the code that <code>runModalForWindow:</code> will return.
Stops the event loop started by \c -runModalForWindow: and
sets the code that \c -runModalForWindow: will return.
@param aCode the return code for the modal event
*/
- (void)stopModalWithCode:(int)aCode
@@ -338,7 +400,7 @@ CPRunContinuesResponse = -1002;
}
/*!
Aborts the event loop started by <code>runModalForWindow:</code>
Aborts the event loop started by \c -runModalForWindow:
*/
- (void)abortModal
{
@@ -346,7 +408,7 @@ CPRunContinuesResponse = -1002;
}
/*!
Sets up a modal session with <code>theWindow</code>.
Sets up a modal session with \c theWindow.
@param aWindow the window to set up the modal session for
*/
- (CPModalSession)beginModalSessionForWindow:(CPWindow)aWindow
@@ -375,7 +437,7 @@ CPRunContinuesResponse = -1002;
/*!
Returns the window for the current modal session. If there is no
modal session, it returns <code>nil</code>.
modal session, it returns \c nil.
*/
- (CPWindow)modalWindow
{
@@ -388,10 +450,8 @@ CPRunContinuesResponse = -1002;
/* @ignore */
- (BOOL)_handleKeyEquivalent:(CPEvent)anEvent
{
if ([_mainMenu performKeyEquivalent:anEvent])
return YES;
return NO;
return [[self keyWindow] performKeyEquivalent:anEvent] ||
[_mainMenu performKeyEquivalent:anEvent];
}
/*!
@@ -400,12 +460,14 @@ CPRunContinuesResponse = -1002;
*/
- (void)sendEvent:(CPEvent)anEvent
{
_currentEvent = anEvent;
// Check if this is a candidate for key equivalent...
if ([anEvent type] == CPKeyDown &&
[anEvent modifierFlags] & (CPCommandKeyMask | CPControlKeyMask) &&
[[anEvent characters] length] > 0 &&
[self _handleKeyEquivalent:anEvent])
if ([anEvent _couldBeKeyEquivalent] && [self _handleKeyEquivalent:anEvent])
{
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
return;
}
if (_eventListeners.length)
{
@@ -443,7 +505,7 @@ CPRunContinuesResponse = -1002;
}
/*!
Returns the CPWindow object corresponding to <code>aWindowNumber</code>.
Returns the CPWindow object corresponding to \c aWindowNumber.
*/
- (CPWindow)windowWithWindowNumber:(int)aWindowNumber
{
@@ -458,6 +520,11 @@ CPRunContinuesResponse = -1002;
return _windows;
}
- (void)hide:(id)aSender
{
[CPPlatform hide:self];
}
// Accessing the Main Menu
/*!
Returns the application's main menu
@@ -473,7 +540,18 @@ CPRunContinuesResponse = -1002;
*/
- (void)setMainMenu:(CPMenu)aMenu
{
_mainMenu = aMenu;
if ([aMenu _menuName] === "CPMainMenu")
{
if (_mainMenu === aMenu)
return;
_mainMenu = aMenu;
if ([CPPlatform supportsNativeMainMenu])
window.cpSetMainMenu(_mainMenu);
}
else
[aMenu _setMenuName:@"CPMainMenu"];
}
- (void)orderFrontColorPanel:(id)aSender
@@ -499,7 +577,7 @@ CPRunContinuesResponse = -1002;
@param anAction the action to perform.
@param anObject the argument for the action
method
@return <code>YES</code> if the action was performed
@return \c YES if the action was performed
*/
- (BOOL)tryToPerform:(SEL)anAction with:(id)anObject
{
@@ -524,7 +602,7 @@ CPRunContinuesResponse = -1002;
@param anAction the action to send
@param aTarget the target for the action
@param aSender the action sender
@return <code>YES</code>
@return \c YES
*/
- (BOOL)sendAction:(SEL)anAction to:(id)aTarget from:(id)aSender
{
@@ -540,12 +618,12 @@ CPRunContinuesResponse = -1002;
/*!
Finds a target for the specified action. If the
action is <code>nil</code>, returns <code>nil</code>.
If the target is not <code>nil</code>, <code>aTarget</code> is
returned. Otherwise, it calls <code>targetForAction:</code>
action is \c nil, returns \c nil.
If the target is not \c nil, \c aTarget is
returned. Otherwise, it calls \c -targetForAction:
to search for a target.
@param anAction the action to find a target for
@param aTarget if not <code>nil</code>, this will be returned
@param aTarget if not \c nil, this will be returned
@aSender not used
@return a target for the action
*/
@@ -573,7 +651,7 @@ CPRunContinuesResponse = -1002;
</ol>
@param aWindow the window to search for a target
@param anAction the action to find a responder to
@return the object that responds to the action, or <code>nil</code>
@return the object that responds to the action, or \c nil
if no matching target was found
@ignore
*/
@@ -625,7 +703,7 @@ CPRunContinuesResponse = -1002;
<li>the document controller</li>
</ol>
@param anAction the action to handle
@return a target that can respond, or <code>nil</code>
@return a target that can respond, or \c nil
if no match could be found
*/
- (id)targetForAction:(SEL)anAction
@@ -667,6 +745,11 @@ CPRunContinuesResponse = -1002;
_eventListeners.push(_CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }));
}
- (CPEvent)currentEvent
{
return _currentEvent;
}
// Managing Sheets
/*!
@@ -679,9 +762,40 @@ CPRunContinuesResponse = -1002;
*/
- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
{
var styleMask = [aSheet styleMask];
if (!(styleMask & CPDocModalWindowMask))
{
[CPException raise:CPInternalInconsistencyException reason:@"Currently only CPDocModalWindowMask style mask is supported for attached sheets"];
return;
}
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
}
- (void)endSheet:(CPWindow)sheet returnCode:(int)returnCode
{
var count = [_windows count];
while (--count >= 0)
{
var aWindow = [_windows objectAtIndex:count];
var context = aWindow._sheetContext;
if (context != nil && context["sheet"] === sheet)
{
context["returnCode"] = returnCode;
[aWindow _detachSheetWindow];
return;
}
}
}
- (void)endSheet:(CPWindow)sheet
{
[self endSheet:sheet returnCode:0];
}
- (CPArray)arguments
{
if(_fullArgsString != window.location.hash)
@@ -730,6 +844,26 @@ CPRunContinuesResponse = -1002;
return _namedArgs;
}
- (BOOL)_openURL:(CPURL)aURL
{
if (_delegate && [_delegate respondsToSelector:@selector(application:openFile:)])
{
CPLog.warn("application:openFile: is deprecated, use application:openURL: instead.");
return [_delegate application:self openFile:[aURL absoluteString]];
}
if (_delegate && [_delegate respondsToSelector:@selector(application:openURL:)])
return [_delegate application:self openURL:aURL];
return !![_documentController openDocumentWithContentsOfURL:aURL display:YES error:NULL];
}
- (void)_didResignActive
{
if (self._activeMenu)
[self._activeMenu cancelTracking];
}
@end
var _CPModalSessionMake = function(aWindow, aStopCode)
@@ -755,7 +889,7 @@ var _CPRunModalLoop = function(anEvent)
/*!
Starts the GUI and Cappuccino frameworks. This function should be
called from the <code>main()</code> function of your program.
called from the \c main() function of your program.
@class CPApplication
@return void
*/
@@ -771,14 +905,18 @@ function CPApplicationMain(args, namedArgs)
[principalClass sharedApplication];
//FIXME?
if (!args && !namedArgs)
if (!args)
{
var args = [CPApp arguments],
searchParams = window.location.search.substring(1).split("&");
namedArgs = [CPDictionary dictionary];
var args = [CPApp arguments];
if([args containsObject:"debug"])
CPLogRegister(CPLogPopup);
}
if (!namedArgs)
{
var searchParams = window.location.search.substring(1).split("&");
namedArgs = [CPDictionary dictionary];
for(var i=0; i<searchParams.length; i++)
{
@@ -804,7 +942,7 @@ var _CPAppBootstrapperActions = nil;
+ (void)actions
{
return [@selector(loadDefaultTheme), @selector(loadMainCibFile)];
return [@selector(bootstrapPlatform), @selector(loadDefaultTheme), @selector(loadMainCibFile)];
}
+ (void)performActions
@@ -823,6 +961,11 @@ var _CPAppBootstrapperActions = nil;
[CPApp run];
}
+ (BOOL)bootstrapPlatform
{
return [CPPlatform bootstrap];
}
+ (BOOL)loadDefaultTheme
{
var blend = [[CPThemeBlend alloc] initWithContentsOfURL:[[CPBundle bundleForClass:[CPApplication class]] pathForResource:@"Aristo.blend"]];
+86 -9
View File
@@ -50,52 +50,76 @@ var DefaultLineWidth = 1.0;
float _lineWidth;
}
/*!
Create a new CPBezierPath object.
*/
+ (CPBezierPath)bezierPath
{
return [[[self class] alloc] init];
return [[self alloc] init];
}
/*!
Create a new CPBezierPath object initialized with an oval path drawn within a rectangular path.
*/
+ (CPBezierPath)bezierPathWithOvalInRect:(CGRect)rect
{
var path = [[self class] bezierPath];
var path = [self bezierPath];
[path appendBezierPathWithOvalInRect:rect];
return path;
}
/*!
Create a new CPBezierPath object initialized with a rectangular path.
*/
+ (CPBezierPath)bezierPathWithRect:(CGRect)rect
{
var path = [[self class] bezierPath];
var path = [self bezierPath];
[path appendBezierPathWithRect:rect];
return path;
}
/*!
Get default line width.
*/
+ (float)defaultLineWidth
{
return DefaultLineWidth;
}
/*!
Set default line width.
*/
+ (void)setDefaultLineWidth:(float)width
{
DefaultLineWidth = width;
}
+ (void)fillRect:(CGRect)rect
/*!
Fill rectangular path with current fill color.
*/
+ (void)fillRect:(CGRect)aRect
{
[[[self class] bezierPathWithRect:rect] fill];
[[self bezierPathWithRect:aRect] fill];
}
+ (void)strokeRect:(CGRect)rect
/*!
Using the current stroke color and default drawing attributes, strokes a counterclockwise path beginning at the rectangle's origin.
*/
+ (void)strokeRect:(CGRect)aRect
{
[[[self class] bezierPathWithRect:rect] stroke];
[[self bezierPathWithRect:aRect] stroke];
}
/*!
Using the current stroke color and default drawing attributes, strokes a line between two points.
*/
+ (void)strokeLineFromPoint:(CGPoint)point1 toPoint:(CGPoint)point2
{
var path = [[self class] bezierPath];
var path = [self bezierPath];
[path moveToPoint:point1];
[path lineToPoint:point2];
@@ -103,6 +127,9 @@ var DefaultLineWidth = 1.0;
[path stroke];
}
/*!
Create a new CPBezierPath object using the default line width.
*/
- (id)init
{
if (self = [super init])
@@ -114,26 +141,41 @@ var DefaultLineWidth = 1.0;
return self;
}
/*!
Moves the current point to another location.
*/
- (void)moveToPoint:(CGPoint)point
{
CGPathMoveToPoint(_path, nil, point.x, point.y);
}
/*!
Append a straight line to the path.
*/
- (void)lineToPoint:(CGPoint)point
{
CGPathAddLineToPoint(_path, nil, point.x, point.y);
}
/*!
Add a cubic Bezier curve to the path.
*/
- (void)curveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
{
CGPathAddCurveToPoint(_path, nil, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y);
}
/*!
Create a line segment between the first and last points in the subpath, closing it.
*/
- (void)closePath
{
CGPathCloseSubpath(_path);
}
/*!
Draw a line along the path with the current stroke color and default drawing attributes.
*/
- (void)stroke
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
@@ -145,6 +187,9 @@ var DefaultLineWidth = 1.0;
CGContextStrokePath(ctx);
}
/*!
Fill the path with the current fill color.
*/
- (void)fill
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
@@ -156,56 +201,88 @@ var DefaultLineWidth = 1.0;
CGContextFillPath(ctx);
}
/*!
Get the line width.
*/
- (float)lineWidth
{
return _lineWidth;
}
/*!
Set the line width.
*/
- (void)setLineWidth:(float)lineWidth
{
_lineWidth = lineWidth;
}
/*!
Get the total number of elements.
*/
- (unsigned)elementCount
{
return _path.count;
}
/*!
Check if receiver is empty, returns appropriate Boolean value.
*/
- (BOOL)isEmpty
{
return CGPathIsEmpty(_path);
}
/*!
Get the current point.
*/
- (CGPoint)currentPoint
{
return CGPathGetCurrentPoint(_path);
}
/*!
Append a series of line segments.
*/
- (void)appendBezierPathWithPoints:(CPArray)points count:(unsigned)count
{
CGPathAddLines(_path, nil, points, count);
}
/*!
Append a rectangular path.
*/
- (void)appendBezierPathWithRect:(CGRect)rect
{
CGPathAddRect(_path, nil, rect);
}
/*!
Append an oval path; oval is drawn within the rectangular path.
*/
- (void)appendBezierPathWithOvalInRect:(CGRect)rect
{
CGPathAddPath(_path, nil, CGPathWithEllipseInRect(rect));
}
/*!
Append a rounded rectangular path.
*/
- (void)appendBezierPathWithRoundedRect:(CGRect)rect xRadius:(float)xRadius yRadius:(float)yRadius
{
CGPathAddPath(_path, nil, CGPathWithRoundedRectangleInRect(rect, xRadius, yRadius, YES, YES, YES, YES));
}
/*!
Append the contents of a CPBezierPath object.
*/
- (void)appendBezierPath:(NSBezierPath *)other
{
CGPathAddPath(_path, nil, other._path);
}
/*!
Remove all path elements; clears path.
*/
- (void)removeAllPoints
{
_path = CGPathCreateMutable();
+244
View File
@@ -0,0 +1,244 @@
/*
* CPBox.j
* AppKit
*
* Created by Ross Boucher.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPView.j"
// CPBorderType
CPNoBorder = 0;
CPLineBorder = 1;
CPBezelBorder = 2;
CPGrooveBorder = 3;
@implementation CPBox : CPView
{
CPBorderType _borderType;
CPColor _borderColor;
CPColor _fillColor;
float _cornerRadius;
float _borderWidth;
CPSize _contentMargin;
CPView _contentView;
}
+ (id)boxEnclosingView:(CPView)aView
{
var box = [[self alloc] initWithFrame:CGRectMakeZero()],
enclosingView = [aView superview];
[box setFrameFromContentFrame:[aView frame]];
[enclosingView replaceSubview:aView with:box];
[box setContentView:aView];
return box;
}
- (id)initWithFrame:(CPRect)frameRect
{
self = [super initWithFrame:frameRect];
if (self)
{
_fillColor = [CPColor clearColor];
_borderColor = [CPColor blackColor];
_borderWidth = 1.0;
_contentMargin = CGSizeMake(0.0, 0.0);
_contentView = [[CPView alloc] initWithFrame:[self bounds]];
[self addSubview:_contentView];
}
return self;
}
// Configuring Boxes
- (CPRect)borderRect
{
return [self bounds];
}
- (CPBorderType)borderType
{
return _borderType;
}
- (void)setBorderType:(CPBorderType)value
{
_borderType = value;
[self setNeedsDisplay:YES];
}
- (CPColor)borderColor
{
return _borderColor;
}
- (void)setBorderColor:(CPColor)color
{
if ([color isEqual:_borderColor])
return;
_borderColor = color;
[self setNeedsDisplay:YES];
}
- (float)borderWidth
{
return _borderWidth;
}
- (void)setBorderWidth:(float)width
{
if (width === _borderWidth)
return;
_borderWidth = width;
[self setNeedsDisplay:YES];
}
- (float)cornerRadius
{
return _cornerRadius;
}
- (void)setCornerRadius:(float)radius
{
if (radius === _cornerRadius)
return;
_cornerRadius = radius;
[self setNeedsDisplay:YES];
}
- (CPColor)fillColor
{
return _fillColor;
}
- (void)setFillColor:(CPColor)color
{
if ([color isEqual:_fillColor])
return;
_fillColor = color;
[self setNeedsDisplay:YES];
}
- (CPView)contentView
{
return _contentView;
}
- (void)setContentView:(CPView)aView
{
if (aView === _contentView)
return;
[aView setFrame:CGRectInset([self bounds], _contentMargin.width + _borderWidth, _contentMargin.height + _borderWidth)];
[self replaceSubview:_contentView with:aView];
_contentView = aView;
}
- (CPSize)contentViewMargins
{
return _contentMargin;
}
- (void)setContentViewMargins:(CPSize)size
{
if(size.width < 0 || size.height < 0)
[CPException raise:CPGenericException reason:@"Margins must be positive"];
_contentMargin = CGSizeMakeCopy(size);
[self setNeedsDisplay:YES];
}
- (void)setFrameFromContentFrame:(CPRect)aRect
{
[self setFrame:CGRectInset(aRect, -(_contentMargin.width + _borderWidth), -(_contentMargin.height + _borderWidth))];
[self setNeedsDisplay:YES];
}
- (void)sizeToFit
{
var contentFrame = [_contentView frame];
[self setFrameSize:CGSizeMake(contentFrame.size.width + _contentMargin.width * 2,
contentFrame.size.height + _contentMargin.height * 2)];
[_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height)];
}
- (void)drawRect:(CPRect)rect
{
var bounds = [self bounds],
aContext = [[CPGraphicsContext currentContext] graphicsPort],
border2 = _borderWidth/2,
strokeRect = CGRectMake(bounds.origin.x + border2,
bounds.origin.y + border2,
bounds.size.width - _borderWidth,
bounds.size.height - _borderWidth),
fillRect = CGRectMake(bounds.origin.x + border2,
bounds.origin.y + border2,
bounds.size.width - _borderWidth,
bounds.size.height - _borderWidth);
CGContextSetFillColor(aContext, [self fillColor]);
CGContextSetStrokeColor(aContext, [self borderColor]);
CGContextSetLineWidth(aContext, _borderWidth);
switch(_borderType)
{
case CPLineBorder: CGContextFillRoundedRectangleInRect(aContext, fillRect, _cornerRadius, YES, YES, YES, YES);
CGContextStrokeRoundedRectangleInRect(aContext, strokeRect, _cornerRadius, YES, YES, YES, YES);
break;
case CPBezelBorder: CGContextFillRoundedRectangleInRect(aContext, fillRect, _cornerRadius, YES, YES, YES, YES);
CGContextSetStrokeColor(aContext, [CPColor colorWithWhite:190.0/255.0 alpha:1.0]);
CGContextBeginPath(aContext);
CGContextMoveToPoint(aContext, strokeRect.origin.x, strokeRect.origin.y);
CGContextAddLineToPoint(aContext, CGRectGetMinX(strokeRect), CGRectGetMaxY(strokeRect)),
CGContextAddLineToPoint(aContext, CGRectGetMaxX(strokeRect), CGRectGetMaxY(strokeRect)),
CGContextAddLineToPoint(aContext, CGRectGetMaxX(strokeRect), CGRectGetMinY(strokeRect)),
CGContextStrokePath(aContext);
CGContextSetStrokeColor(aContext, [CPColor colorWithWhite:142.0/255.0 alpha:1.0]);
CGContextBeginPath(aContext);
CGContextMoveToPoint(aContext, bounds.origin.x, strokeRect.origin.y);
CGContextAddLineToPoint(aContext, CGRectGetMaxX(bounds), CGRectGetMinY(strokeRect));
CGContextStrokePath(aContext);
break;
default: break;
}
}
@end
+8 -8
View File
@@ -172,7 +172,7 @@ CPButtonStateMixed = CPThemeState("mixed");
// Setting the state
/*!
Returns <code>YES</code> if the button has a 'mixed' state in addition to on and off.
Returns \c YES if the button has a 'mixed' state in addition to on and off.
*/
- (BOOL)allowsMixedState
{
@@ -192,8 +192,8 @@ CPButtonStateMixed = CPThemeState("mixed");
_allowsMixedState = aFlag;
if (!_allowsMixedState)
[self unsetThemeState:CPButtonStateMixed];
if (!_allowsMixedState && [self state] === CPMixedState)
[self setState:CPOnState];
}
- (void)setObjectValue:(id)anObjectValue
@@ -248,9 +248,9 @@ CPButtonStateMixed = CPThemeState("mixed");
}
/*!
Sets the button's state to <code>aState</code>.
Sets the button's state to \c aState.
@param aState Possible states are any of the CPButton globals:
<code>CPOffState, CPOnState, CPMixedState</code>
\c CPOffState, \c CPOnState, \c CPMixedState
*/
- (void)setState:(CPInteger)aState
{
@@ -368,7 +368,7 @@ CPButtonStateMixed = CPThemeState("mixed");
- (void)setButtonType:(CPButtonType)aButtonType
{
switch (buttonType)
switch (aButtonType)
{
case CPMomentaryLightButton: [self setHighlightsBy:CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
@@ -390,7 +390,7 @@ CPButtonStateMixed = CPThemeState("mixed");
[self setShowsStateBy:CPChangeBackgroundCellMask];
break;
case CPToggleButton: [self setHighlightsBy:CPPushInCellMask | NSContentsCellMask];
case CPToggleButton: [self setHighlightsBy:CPPushInCellMask | CPContentsCellMask];
[self setShowsStateBy:CPContentsCellMask];
break;
@@ -602,7 +602,7 @@ var CPButtonImageKey = @"CPButtonImageKey",
@implementation CPButton (CPCoding)
/*!
Initializes the button by unarchiving data from <code>aCoder</code>.
Initializes the button by unarchiving data from \c aCoder.
@param aCoder the coder containing the archived CPButton.
*/
- (id)initWithCoder:(CPCoder)aCoder
+4 -4
View File
@@ -38,8 +38,8 @@
}
/*!
Sets the document view to be <code>aView</code>.
@param aView the new document view. It's frame origin will be changed to <code>(0,0)</code> after calling this method.
Sets the document view to be \c aView.
@param aView the new document view. It's frame origin will be changed to \c (0,0) after calling this method.
*/
- (void)setDocumentView:(CPView)aView
{
@@ -95,7 +95,7 @@
}
/*!
Returns a new point that may be adjusted from <code>aPoint</code>
Returns a new point that may be adjusted from \c aPoint
to make sure it lies within the document view.
@param aPoint
@return the adjusted point
@@ -128,7 +128,7 @@
/*!
Scrolls the clip view to the specified point. The method
sets its bounds origin to <code>aPoint</code>.
sets its bounds origin to \c aPoint.
*/
- (void)scrollToPoint:(CGPoint)aPoint
{
+107 -178
View File
@@ -26,7 +26,8 @@
@import <Foundation/CPKeyedArchiver.j>
@import <Foundation/CPKeyedUnarchiver.j>
@import <AppKit/CPView.j>
@import "CPView.j"
@import "CPCollectionViewItem.j"
/*!
@@ -61,6 +62,7 @@
@param indices the indices to obtain drag types
@return an array of drag types (CPString)
*/
@implementation CPCollectionView : CPView
{
CPArray _content;
@@ -76,7 +78,9 @@
CGSize _minItemSize;
CGSize _maxItemSize;
CPArray _backgroundColors;
float _tileWidth;
BOOL _isSelectable;
@@ -93,6 +97,8 @@
unsigned _numberOfColumns;
id _delegate;
CPEvent _mouseDownEvent;
}
- (id)initWithFrame:(CGRect)aFrame
@@ -109,7 +115,9 @@
_itemSize = CGSizeMakeZero();
_minItemSize = CGSizeMakeZero();
_maxItemSize = CGSizeMakeZero();
[self setBackgroundColors:nil];
_verticalMargin = 5.0;
_tileWidth = -1.0;
@@ -122,15 +130,16 @@
}
/*!
Sets the item prototype to <code>anItem</code>
Sets the item prototype to \c anItem
@param anItem the new item prototype
*/
- (void)setItemPrototype:(CPCollectionViewItem)anItem
{
_itemData = [CPKeyedArchiver archivedDataWithRootObject:anItem];
_itemForDragging = anItem//[CPKeyedUnarchiver unarchiveObjectWithData:_itemData];
_cachedItems = [];
_itemData = nil;
_itemForDragging = nil;
_itemPrototype = anItem;
[self reloadContent];
}
@@ -143,17 +152,24 @@
}
/*!
Returns a collection view item for <code>anObject</code>.
Returns a collection view item for \c anObject.
@param anObject the object to be represented.
*/
- (CPCollectionViewItem)newItemForRepresentedObject:(id)anObject
{
var item = nil;
if (_cachedItems.length)
item = _cachedItems.pop();
else
{
if (!_itemData)
if (_itemPrototype)
_itemData = [CPKeyedArchiver archivedDataWithRootObject:_itemPrototype];
item = [CPKeyedUnarchiver unarchiveObjectWithData:_itemData];
}
[item setRepresentedObject:anObject];
[[item view] setFrameSize:_itemSize];
@@ -163,7 +179,7 @@
// Working with the Responder Chain
/*!
Returns <code>YES</code> by default.
Returns \c YES by default.
*/
- (BOOL)acceptsFirstResponder
{
@@ -175,13 +191,13 @@
*/
- (BOOL)isFirstResponder
{
return [[self window] firstResponder] == self;
return [[self window] firstResponder] === self;
}
// Setting the Content
/*!
Sets the content of the collection view to the content in <code>anArray</code>.
This array can be of any type, and each element will be passed to the <code>setRepresentedObject:</code> method.
Sets the content of the collection view to the content in \c anArray.
This array can be of any type, and each element will be passed to the \c -setRepresentedObject: method.
It's the responsibility of your custom collection view item to interpret the object.
@param anArray the content array
*/
@@ -214,7 +230,7 @@
// Setting the Selection Mode
/*!
Sets whether the user is allowed to select items
@param isSelectable <code>YES</code> allows the user to select items.
@param isSelectable \c YES allows the user to select items.
*/
- (void)setSelectable:(BOOL)isSelectable
{
@@ -233,17 +249,17 @@
}
/*!
Returns <code>YES</code> if the collection view is
selected, and <code>NO</code> otherwise.
Returns \c YES if the collection view is
selectable, and \c NO otherwise.
*/
- (BOOL)isSelected
- (BOOL)isSelectable
{
return _isSelected;
return _isSelectable;
}
/*!
Sets whether the user may have no items selected. If YES, mouse clicks not on any item will empty the current selection. The first item will also start off as selected.
@param shouldAllowMultipleSelection <code>YES</code> allows the user to select multiple items
@param shouldAllowMultipleSelection \c YES allows the user to select multiple items
*/
- (void)setAllowsEmptySelection:(BOOL)shouldAllowEmptySelection
{
@@ -251,7 +267,7 @@
}
/*!
Returns <code>YES</code> if the user can select no items, <code>NO</code> otherwise.
Returns \c YES if the user can select no items, \c NO otherwise.
*/
- (BOOL)allowsEmptySelection
{
@@ -260,7 +276,7 @@
/*!
Sets whether the user can select multiple items.
@param shouldAllowMultipleSelection <code>YES</code> allows the user to select multiple items
@param shouldAllowMultipleSelection \c YES allows the user to select multiple items
*/
- (void)setAllowsMultipleSelection:(BOOL)shouldAllowMultipleSelection
{
@@ -268,7 +284,7 @@
}
/*!
Returns <code>YES</code> if the user can select multiple items, <code>NO</code> otherwise.
Returns \c YES if the user can select multiple items, \c NO otherwise.
*/
- (BOOL)allowsMultipleSelection
{
@@ -322,13 +338,13 @@
_items = [];
if (!_itemData || !_content)
if (!_itemPrototype || !_content)
return;
var index = 0;
count = _content.length;
for (; index < count; ++index)
{
_items.push([self newItemForRepresentedObject:_content[index]]);
@@ -520,6 +536,30 @@
return _maxItemSize;
}
- (void)setBackgroundColors:(CPArray)backgroundColors
{
if (_backgroundColors === backgroundColors)
return;
_backgroundColors = backgroundColors;
if (!_backgroundColors)
_backgroundColors = [CPColor whiteColor];
if ([_backgroundColors count] === 1)
[self setBackgroundColor:_backgroundColors[0]];
else
[self setBackgroundColor:nil];
[self setNeedsDisplay:YES];
}
- (CPArray)backgroundColors
{
return _backgroundColors;
}
- (void)mouseUp:(CPEvent)anEvent
{
if ([_selectionIndexes count] && [anEvent clickCount] == 2 && [_delegate respondsToSelector:@selector(collectionView:didDoubleClickOnItemAtIndex:)])
@@ -528,13 +568,16 @@
- (void)mouseDown:(CPEvent)anEvent
{
_mouseDownEvent = anEvent;
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
row = FLOOR(location.y / (_itemSize.height + _verticalMargin)),
column = FLOOR(location.x / (_itemSize.width + _horizontalMargin)),
index = row * _numberOfColumns + column;
if (index >= 0 && index < _items.length)
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
else if (_allowsEmptySelection)
[self setSelectionIndexes:[CPIndexSet indexSet]];
}
@@ -543,30 +586,32 @@
{
if (![_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)])
return;
// If we don't have any selected items, we've clicked away, and thus the drag is meaningless.
if (![_selectionIndexes count])
return;
// Set up the pasteboard
var dragTypes = [_delegate collectionView:self dragTypesForItemsAtIndexes:_selectionIndexes];
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self];
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
[_itemForDragging setRepresentedObject:_content[[_selectionIndexes firstIndex]]];
if (!_itemForDragging)
_itemForDragging = [self newItemForRepresentedObject:_content[[_selectionIndexes firstIndex]]];
else
[_itemForDragging setRepresentedObject:_content[[_selectionIndexes firstIndex]]];
var view = [_itemForDragging view];
var view = [_itemForDragging view],
frame = [view frame];
[view setFrameSize:_itemSize];
[view setAlphaValue:0.7];
[self dragView:view
at:[[_items[[_selectionIndexes firstIndex]] view] frame].origin
offset:CGPointMakeZero()
event:anEvent
offset:CGSizeMakeZero()
event:_mouseDownEvent
pasteboard:nil
source:self
slideBack:YES];
@@ -627,98 +672,11 @@
@end
/*!
Represents an object inside a CPCollectionView.
*/
@implementation CPCollectionViewItem : CPObject
{
id _representedObject;
CPView _view;
BOOL _isSelected;
}
// Setting the Represented Object
/*!
Sets the object to be represented by this item.
@param anObject the object to be represented
*/
- (void)setRepresentedObject:(id)anObject
{
if (_representedObject == anObject)
return;
_representedObject = anObject;
// FIXME: This should be set up by bindings
[_view setRepresentedObject:anObject];
}
/*!
Returns the object represented by this view item
*/
- (id)representedObject
{
return _representedObject;
}
// Modifying the View
/*!
Sets the view that is used represent this object.
@param aView the view used to represent this object
*/
- (void)setView:(CPView)aView
{
_view = aView;
}
/*!
Returns the view that represents this object.
*/
- (CPView)view
{
return _view;
}
// Modifying the Selection
/*!
Sets whether this view item should be selected.
@param shouldBeSelected <code>YES</code> makes the item selected. <code>NO</code> deselects it.
*/
- (void)setSelected:(BOOL)shouldBeSelected
{
if (_isSelected == shouldBeSelected)
return;
_isSelected = shouldBeSelected;
// FIXME: This should be set up by bindings
[_view setSelected:_isSelected];
}
/*!
Returns <code>YES</code> if the item is currently selected. <code>NO</code> if the item is not selected.
*/
- (BOOL)isSelected
{
return _isSelected;
}
// Parent Collection View
/*!
Returns the collection view of which this item is a part.
*/
- (CPCollectionView)collectionView
{
return [_view superview];
}
@end
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey";
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
CPCollectionViewSelectableKey = @"CPCollectionViewSelectableKey",
CPCollectionViewBackgroundColorsKey = @"CPCollectionViewBackgroundColorsKey";
@implementation CPCollectionView (CPCoding)
@@ -735,13 +693,21 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
_cachedItems = [];
_itemSize = CGSizeMakeZero();
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey];
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey];
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey] || CGSizeMakeZero();
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey] || CGSizeMakeZero();
_verticalMargin = [aCoder decodeFloatForKey:CPCollectionViewVerticalMarginKey];
_isSelectable = [aCoder decodeBoolForKey:CPCollectionViewSelectableKey];
_verticalMargin = [aCoder decodeSizeForKey:CPCollectionViewVerticalMarginKey];
[self setBackgroundColors:[aCoder decodeObjectForKey:CPCollectionViewBackgroundColorsKey]];
_tileWidth = -1.0;
_selectionIndexes = [CPIndexSet indexSet];
_allowsEmptySelection = YES;
}
return self;
@@ -751,54 +717,17 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
{
[super encodeWithCoder:aCoder];
[aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey];
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
if (!CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
[aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey];
if (!CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
[aCoder encodeBool:_isSelectable forKey:CPCollectionViewSelectableKey];
[aCoder encodeFloat:_verticalMargin forKey:CPCollectionViewVerticalMarginKey];
[aCoder encodeSize:_verticalMargin forKey:CPCollectionViewVerticalMarginKey];
[aCoder encodeObject:_backgroundColors forKey:CPCollectionViewBackgroundColorsKey];
}
@end
var CPCollectionViewItemViewKey = @"CPCollectionViewItemViewKey";
@implementation CPCollectionViewItem (CPCoding)
/*
FIXME Not yet implemented
*/
- (id)copy
{
}
@end
var CPCollectionViewItemViewKey = @"CPCollectionViewItemViewKey";
@implementation CPCollectionViewItem (CPCoding)
/*!
Initializes the view item by unarchiving data from a coder.
@param aCoder the coder from which the data will be unarchived
@return the initialized collection view item
*/
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
_view = [aCoder decodeObjectForKey:CPCollectionViewItemViewKey];
return self;
}
/*!
Archives the colletion view item to the provided coder.
@param aCoder the coder to which the view item should be archived
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_view forKey:CPCollectionViewItemViewKey];
}
@end
+85
View File
@@ -0,0 +1,85 @@
/*
* CPCollectionViewItem.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPViewController.j"
/*!
Represents an object inside a CPCollectionView.
*/
@implementation CPCollectionViewItem : CPViewController
{
BOOL _isSelected;
}
// Setting the Represented Object
/*!
Sets the object to be represented by this item.
@param anObject the object to be represented
*/
- (void)setRepresentedObject:(id)anObject
{
[super setRepresentedObject:anObject];
var view = [self view];
if ([view respondsToSelector:@selector(setRepresentedObject:)])
[view setRepresentedObject:[self representedObject]];
}
// Modifying the Selection
/*!
Sets whether this view item should be selected.
@param shouldBeSelected \c YES makes the item selected. \c NO deselects it.
*/
- (void)setSelected:(BOOL)shouldBeSelected
{
shouldBeSelected = !!shouldBeSelected;
if (_isSelected === shouldBeSelected)
return;
_isSelected = shouldBeSelected;
var view = [self view];
if ([view respondsToSelector:@selector(setSelected:)])
[view setSelected:[self isSelected]];
}
/*!
Returns \c YES if the item is currently selected. \c NO if the item is not selected.
*/
- (BOOL)isSelected
{
return _isSelected;
}
// Parent Collection View
/*!
Returns the collection view of which this item is a part.
*/
- (CPCollectionView)collectionView
{
return [_view superview];
}
@end
+85 -6
View File
@@ -46,6 +46,11 @@ var cachedBlackColor,
cachedLightGrayColor,
cachedDarkGrayColor,
cachedWhiteColor,
cachedBrownColor,
cachedCyanColor,
cachedMagentaColor,
cachedOrangeColor,
cachedPurpleColor,
cachedShadowColor,
cachedClearColor;
@@ -53,13 +58,13 @@ var cachedBlackColor,
@ingroup appkit
@code CPColor
<code>CPColor</code> can be used to represent color
\c CPColor can be used to represent color
in an RGB or HSB model with an optional transparency value.</p>
<p>It also provides some class helper methods that
returns instances of commonly used colors.</p>
<p>The class does not have a <code>set:</code> method
<p>The class does not have a \c -set: method
like NextStep based frameworks to change the color of
the current context. To change the color of the current
context, use CGContextSetFillColor().
@@ -112,7 +117,7 @@ var cachedBlackColor,
/*!
Creates a new color object with <code>white</code> for the RGB components.
Creates a new color object with \c white for the RGB components.
For the alpha component, a value of 1.0 is opaque, and 0.0 means completely transparent.
@param white a float between 0.0 and 1.0
@@ -128,7 +133,7 @@ var cachedBlackColor,
/*!
@deprecated in favor of colorWithWhite:apha:
Creates a new color object with <code>white</code> for the RGB components.
Creates a new color object with \c white for the RGB components.
For the alpha component, a value of 1.0 is opaque, and 0.0 means completely transparent.
@param white a float between 0.0 and 1.0
@@ -291,6 +296,61 @@ var cachedBlackColor,
return cachedYellowColor;
}
/*!
Returns a brown color object (RGBA=[0.6, 0.4, 0.2, 1.0])
*/
+ (CPColor)brownColor
{
if (!cachedBrownColor)
cachedBrownColor = [[CPColor alloc] _initWithRGBA:[0.6, 0.4, 0.2, 1.0]];
return cachedBrownColor;
}
/*!
Returns a cyan color object (RGBA=[0.0, 1.0, 1.0, 1.0])
*/
+ (CPColor)cyanColor
{
if (!cachedCyanColor)
cachedCyanColor = [[CPColor alloc] _initWithRGBA:[0.0, 1.0, 1.0, 1.0]];
return cachedCyanColor;
}
/*!
Returns a magenta color object (RGBA=[1.0, 0.0, 1.0, 1.0])
*/
+ (CPColor)magentaColor
{
if (!cachedMagentaColor)
cachedMagentaColor = [[CPColor alloc] _initWithRGBA:[1.0, 0.0, 1.0, 1.0]];
return cachedMagentaColor;
}
/*!
Returns a orange color object (RGBA=[1.0, 0.5, 0.0, 1.0])
*/
+ (CPColor)orangeColor
{
if (!cachedOrangeColor)
cachedOrangeColor = [[CPColor alloc] _initWithRGBA:[1.0, 0.5, 0.0, 1.0]];
return cachedOrangeColor;
}
/*!
Returns a purple color object (RGBA=[0.5, 0.0, 0.5, 1.0])
*/
+ (CPColor)purpleColor
{
if (!cachedPurpleColor)
cachedPurpleColor = [[CPColor alloc] _initWithRGBA:[0.5, 0.0, 0.5, 1.0]];
return cachedPurpleColor;
}
/*!
Returns a shadow looking color (RGBA=[0.0, 0.0, 0.0, 0.33])
*/
@@ -315,8 +375,18 @@ var cachedBlackColor,
return cachedClearColor;
}
+ (CPColor)alternateSelectedControlColor
{
return [[CPColor alloc] _initWithRGBA:[0.22, 0.46, 0.84, 1.0]];
}
+ (CPColor)secondarySelectedControlColor
{
return [[CPColor alloc] _initWithRGBA:[0.83, 0.83, 0.83, 1.0]];
}
/*!
Creates a color using a tile pattern with <code>anImage</code>
Creates a color using a tile pattern with \c anImage
@param the image to tile
@return a tiled image color object
*/
@@ -623,6 +693,15 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
@end
@implementation CPColor (Debugging)
+ (CPColor)randomColor
{
return [CPColor colorWithRed:RAND() green:RAND() blue:RAND() alpha:1.0];
}
@end
var CPColorComponentsKey = @"CPColorComponentsKey",
CPColorPatternImageKey = @"CPColorPatternImageKey";
@@ -657,7 +736,7 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
var hexCharacters = "0123456789ABCDEF";
/*!
Used for the CPColor <code>colorWithHexString:</code> implementation
Used for the CPColor \c +colorWithHexString: implementation
@ignore
@class CPColor
@return an array of rgb components
+4 -4
View File
@@ -58,7 +58,7 @@ CPColorPickerViewHeight = 370;
CPColorPanel provides a reusable panel that can be used
displayed on screen to prompt the user for a color selection. To
obtain the panel, call the <code>sharedColorPanel</code> method.
obtain the panel, call the \c +sharedColorPanel method.
*/
@implementation CPColorPanel : CPPanel
{
@@ -111,7 +111,7 @@ CPColorPickerViewHeight = 370;
}
/*
To obtain the color panel, use <code>sharedColorPanel</code>.
To obtain the color panel, use \c +sharedColorPanel.
@ignore
*/
- (id)init
@@ -137,7 +137,7 @@ CPColorPickerViewHeight = 370;
}
/*!
Sets the color of the panel, and updates the picker. Also posts a <code>CPColorPanelDidChangeNotification</code>.
Sets the color of the panel, and updates the picker. Also posts a \c CPColorPanelDidChangeNotification.
*/
- (void)setColor:(CPColor)aColor
{
@@ -491,7 +491,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
var future = new Date();
future.setYear(2019);
[_swatchCookie setValue: CPJSObjectCreateJSON(result) expires:future domain: nil];
[_swatchCookie setValue: JSON.stringify(result) expires:future domain: nil];
}
- (void)setColorPanel:(CPColorPanel)panel
+2 -2
View File
@@ -27,7 +27,7 @@
@ingroup appkit
@class CPColorPicker
CPColorPicker is an abstract superclass for all color picker subclasses. If you want a particular color picker, use CPColorPanel's <code>setPickerMode:</code> method. The simplest way to implement your own color picker is to create a subclass of CPColorPicker.
CPColorPicker is an abstract superclass for all color picker subclasses. If you want a particular color picker, use CPColorPanel's \c +setPickerMode: method. The simplest way to implement your own color picker is to create a subclass of CPColorPicker.
*/
@implementation CPColorPicker : CPObject
{
@@ -60,7 +60,7 @@
/*
FIXME Not implemented.
@return <code>nil</code>
@return \c nil
@ignore
*/
- (CPImage)provideNewButtonImage
+5 -5
View File
@@ -35,7 +35,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
CPColorWell is a CPControl for selecting and displaying a single color value. An example of a CPColorWell object (or simply color well) is found in CPColorPanel, which uses a color well to display the current color selection.</p>
<p>An application can have one or more active CPColorWells. You can activate multiple CPColorWells by invoking the <code>activate:</code> method with <code>NO</code> as its argument. When a mouse-down event occurs on an CPColorWell's border, it becomes the only active color well. When a color well becomes active, it brings up the color panel also.
<p>An application can have one or more active CPColorWells. You can activate multiple CPColorWells by invoking the \c -activate: method with \c NO as its argument. When a mouse-down event occurs on an CPColorWell's border, it becomes the only active color well. When a color well becomes active, it brings up the color panel also.
*/
@implementation CPColorWell : CPControl
{
@@ -127,7 +127,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
}
/*!
Changes the color of the well to that of <code>aSender</code>.
Changes the color of the well to that of \c aSender.
@param aSender the object from which to retrieve the color
*/
- (void)takeColorFrom:(id)aSender
@@ -138,7 +138,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
// Activating and Deactivating Color Wells
/*!
Activates the color well, displays the color panel, and makes the panel's current color the same as its own.
If exclusive is <code>YES</code>, deactivates any other CPColorWells. <code>NO</code>, keeps them active.
If exclusive is \c YES, deactivates any other CPColorWells. \c NO, keeps them active.
@param shouldBeExclusive whether other color wells should be deactivated.
*/
- (void)activate:(BOOL)shouldBeExclusive
@@ -179,7 +179,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
}
/*!
Returns <code>YES</code> if the color well is active.
Returns \c YES if the color well is active.
*/
- (BOOL)isActive
{
@@ -262,7 +262,7 @@ var CPColorWellColorKey = "CPColorWellColorKey",
@implementation CPColorWell (CPCoding)
/*!
Initializes the color well by unarchiving data from <code>aCoder</code>.
Initializes the color well by unarchiving data from \c aCoder.
@param aCoder the coder containing the archived CPColorWell.
*/
- (id)initWithCoder:(CPCoder)aCoder
+30 -14
View File
@@ -21,6 +21,7 @@
*/
@import "CPEvent.j"
@import "CPPlatform.j"
// Browser Engines
CPUnknownBrowserEngine = 0;
@@ -35,17 +36,18 @@ CPCSSRGBAFeature = 1 << 5;
CPHTMLCanvasFeature = 1 << 6;
CPHTMLContentEditableFeature = 1 << 7;
CPHTMLDragAndDropFeature = 1 << 8;
CPJavascriptInnerTextFeature = 1 << 8;
CPJavascriptTextContentFeature = 1 << 9;
CPJavascriptClipboardEventsFeature = 1 << 10;
CPJavascriptClipboardAccessFeature = 1 << 11;
CPJavaScriptCanvasDrawFeature = 1 << 12;
CPJavaScriptCanvasTransformFeature = 1 << 13;
CPJavascriptInnerTextFeature = 1 << 9;
CPJavascriptTextContentFeature = 1 << 10;
CPJavascriptClipboardEventsFeature = 1 << 11;
CPJavascriptClipboardAccessFeature = 1 << 12;
CPJavaScriptCanvasDrawFeature = 1 << 13;
CPJavaScriptCanvasTransformFeature = 1 << 14;
CPVMLFeature = 1 << 14;
CPVMLFeature = 1 << 15;
CPJavascriptRemedialKeySupport = 1 << 15;
CPJavascriptRemedialKeySupport = 1 << 16;
CPJavaScriptShadowFeature = 1 << 20;
CPJavaScriptNegativeMouseWheelValues = 1 << 22;
@@ -54,7 +56,9 @@ CPJavaScriptMouseWheelValues_8_15 = 1 << 23
CPOpacityRequiresFilterFeature = 1 << 24;
//Internet explorer does not allow dynamically changing the type of an input element
CPInputTypeCanBeChangedFeature = 1 << 25;
CPInputTypeCanBeChangedFeature = 1 << 25;
CPHTML5DragAndDropSourceYOffBy1 = 1 << 26;
@@ -100,16 +104,28 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
// Features we can only be sure of with WebKit (no known independent tests)
PLATFORM_FEATURES |= CPCSSRGBAFeature;
PLATFORM_FEATURES |= CPHTMLContentEditableFeature;
PLATFORM_FEATURES |= CPHTMLDragAndDropFeature;
PLATFORM_FEATURES |= CPJavascriptClipboardEventsFeature;
PLATFORM_FEATURES |= CPJavascriptClipboardAccessFeature;
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
var versionStart = USER_AGENT.indexOf("AppleWebKit/") + "AppleWebKit/".length,
versionEnd = USER_AGENT.indexOf(" ", versionStart),
version = parseFloat(USER_AGENT.substring(versionStart, versionEnd), 10);
versionString = USER_AGENT.substring(versionStart, versionEnd),
versionDivision = versionString.indexOf('.'),
majorVersion = parseInt(versionString.substring(0, versionDivision)),
minorVersion = parseInt(versionString.substr(versionDivision + 1));
if(USER_AGENT.indexOf("Plainview") == -1 && version >= 525.14 || USER_AGENT.indexOf("Chrome") != -1)
if((USER_AGENT.indexOf("Safari") !== CPNotFound && (majorVersion > 525 || (majorVersion === 525 && minorVersion > 14))) || USER_AGENT.indexOf("Chrome") !== CPNotFound)
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
// FIXME this is a terrible hack to get around this bug:
// https://bugs.webkit.org/show_bug.cgi?id=21548
if (![CPPlatform isBrowser])
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
if (majorVersion < 532 || (majorVersion === 532 && minorVersion < 6))
PLATFORM_FEATURES |= CPHTML5DragAndDropSourceYOffBy1;
}
// KHTML
@@ -173,7 +189,7 @@ function CPBrowserIsEngine(anEngine)
if (USER_AGENT.indexOf("Mac") != -1)
{
CPPlatformActionKeyMask = CPCommandKeyMask;
CPUndoKeyEquivalent = @"Z";
CPRedoKeyEquivalent = @"Z";
@@ -183,10 +199,10 @@ if (USER_AGENT.indexOf("Mac") != -1)
else
{
CPPlatformActionKeyMask = CPControlKeyMask;
CPUndoKeyEquivalent = @"Z";
CPRedoKeyEquivalent = @"Y";
CPUndoKeyEquivalentModifierMask = CPControlKeyMask;
CPRedoKeyEquivalentModifierMask = CPControlKeyMask;
}
+14 -69
View File
@@ -94,15 +94,13 @@ var CPControlBlackColor = [CPColor blackColor];
id _target;
SEL _action;
int _sendActionOn;
BOOL _sendsActionOnEndEditing @accessors(property=sendsActionOnEndEditing);
// Mouse Tracking Support
BOOL _continuousTracking;
BOOL _trackingWasWithinFrame;
unsigned _trackingMouseDownFlags;
CGPoint _previousTrackingLocation;
JSObject _ephemeralSubviewsForNames;
CPSet _ephereralSubviews;
CPString _toolTip;
}
@@ -181,7 +179,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Causes <code>anAction</code> to be sent to <code>anObject</code>.
Causes \c anAction to be sent to \c anObject.
@param anAction the action to send
@param anObject the object to which the action will be sent
*/
@@ -296,6 +294,15 @@ var CPControlBlackColor = [CPColor blackColor];
_previousTrackingLocation = currentLocation;
}
- (void)setState:(int)state
{
}
- (int)nextState
{
return 0;
}
- (void)performClick:(id)sender
{
[self highlight:YES];
@@ -505,10 +512,12 @@ var CPControlBlackColor = [CPColor blackColor];
}
#define BRIDGE(UPPERCASE, LOWERCASE, ATTRIBUTENAME) \
/*! Sets the value for ATTRIBUTENAME */\
- (void)set##UPPERCASE:(id)aValue\
{\
[self setValue:aValue forThemeAttribute:ATTRIBUTENAME];\
}\
/*! Returns the current value for ATTRIBUTENAME */\
- (id)LOWERCASE\
{\
return [self valueForThemeAttribute:ATTRIBUTENAME];\
@@ -555,54 +564,6 @@ BRIDGE(ImageScaling, imageScaling, "image-scaling")
return [self hasThemeState:CPThemeStateHighlighted];
}
- (CPView)createEphemeralSubviewNamed:(CPString)aViewName
{
return nil;
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
{
return _CGRectMakeZero();
}
- (CPView)layoutEphemeralSubviewNamed:(CPString)aViewName
positioned:(CPWindowOrderingMode)anOrderingMode
relativeToEphemeralSubviewNamed:(CPString)relativeToViewName
{
if (!_ephemeralSubviewsForNames)
{
_ephemeralSubviewsForNames = {};
_ephemeralSubviews = [CPSet set];
}
var frame = [self rectForEphemeralSubviewNamed:aViewName];
if (frame && !_CGRectIsEmpty(frame))
{
if (!_ephemeralSubviewsForNames[aViewName])
{
_ephemeralSubviewsForNames[aViewName] = [self createEphemeralSubviewNamed:aViewName];
[_ephemeralSubviews addObject:_ephemeralSubviewsForNames[aViewName]];
if (_ephemeralSubviewsForNames[aViewName])
[self addSubview:_ephemeralSubviewsForNames[aViewName] positioned:anOrderingMode relativeTo:_ephemeralSubviewsForNames[relativeToViewName]];
}
if (_ephemeralSubviewsForNames[aViewName])
[_ephemeralSubviewsForNames[aViewName] setFrame:frame];
}
else if (_ephemeralSubviewsForNames[aViewName])
{
[_ephemeralSubviewsForNames[aViewName] removeFromSuperview];
[_ephemeralSubviews removeObject:_ephemeralSubviewsForNames[aViewName]];
delete _ephemeralSubviewsForNames[aViewName];
}
return _ephemeralSubviewsForNames[aViewName];
}
@end
var CPControlValueKey = "CPControlValueKey",
@@ -645,24 +606,8 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
var count = [_subviews count],
ephemeral
subviews = nil;
if (count > 0 && [_ephemeralSubviews count] > 0)
{
subviews = [_subviews.slice(0) copy];
while (count--)
if ([_ephemeralSubviews containsObject:_subviews[count]])
_subviews.splice(count, 1);
}
[super encodeWithCoder:aCoder];
if (subviews)
_subviews = subviews;
if (_value !== nil)
[aCoder encodeObject:_value forKey:CPControlValueKey];
+1 -1
View File
@@ -38,7 +38,7 @@
}
/*!
Initializes a cookie with a given name <code>aName</code>.
Initializes a cookie with a given name \c aName.
@param the name for the cookie
*/
- (id)initWithName:(CPString)aName
+248 -52
View File
@@ -24,6 +24,8 @@
@import <Foundation/CPArray.j>
@import "CPResponder.j"
@import "CPSavePanel.j"
@import "CPViewController.j"
@import "CPWindowController.j"
@@ -90,19 +92,25 @@ var CPDocumentUntitledCount = 0;
CPDocuments should be used to represent this.
*/
@implementation CPDocument : CPResponder
{
CPURL _fileURL;
CPString _fileType;
CPArray _windowControllers;
unsigned _untitledDocumentIndex;
{
CPWindow _window; // For outlet purposes.
CPView _view; // For outlet purposes
CPDictionary _viewControllersForWindowControllers;
BOOL _hasUndoManager;
CPUndoManager _undoManager;
int _changeCount;
CPURLConnection _readConnection;
CPURLRequest _writeRequest;
CPURL _fileURL;
CPString _fileType;
CPArray _windowControllers;
unsigned _untitledDocumentIndex;
BOOL _hasUndoManager;
CPUndoManager _undoManager;
int _changeCount;
CPURLConnection _readConnection;
CPURLRequest _writeRequest;
CPAlert _canCloseAlert;
}
/*!
@@ -116,10 +124,11 @@ var CPDocumentUntitledCount = 0;
if (self)
{
_windowControllers = [];
_viewControllersForWindowControllers = [CPDictionary dictionary];
_hasUndoManager = YES;
_changeCount = 0;
[self setNextResponder:CPApp];
}
@@ -159,10 +168,10 @@ var CPDocumentUntitledCount = 0;
if (self)
{
[self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
[self setFileURL:anAbsoluteURL];
[self setFileType:aType];
[self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
}
return self;
@@ -174,8 +183,8 @@ var CPDocumentUntitledCount = 0;
@param absoluteContentsURL the location of the document's contents
@param aType the type of the contents
@param aDelegate this object will receive a callback after the document's contents are loaded
@param aDidReadSelector the message selector that will be sent to <code>aDelegate</code>
@param aContextInfo passed as the argument to the message sent to the <code>aDelegate</code>
@param aDidReadSelector the message selector that will be sent to \c aDelegate
@param aContextInfo passed as the argument to the message sent to the \c aDelegate
@return the initialized document
*/
- (id)initForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo
@@ -184,10 +193,10 @@ var CPDocumentUntitledCount = 0;
if (self)
{
[self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
[self setFileURL:anAbsoluteURL];
[self setFileType:aType];
[self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
}
return self;
@@ -222,15 +231,69 @@ var CPDocumentUntitledCount = 0;
reason:"readFromData:ofType: must be overridden by the document subclass."];
}
- (void)viewControllerWillLoadCib:(CPViewController)aViewController
{
}
- (void)viewControllerDidLoadCib:(CPViewController)aViewController
{
}
- (CPWindowController)firstEligibleExistingWindowController
{
return nil;
}
// Creating and managing window controllers
/*!
Creates the window controller for this document.
*/
- (void)makeWindowControllers
{
var controller = [[CPWindowController alloc] initWithWindowCibName:nil];
[self addWindowController:controller];
[self makeViewAndWindowControllers];
}
- (void)makeViewAndWindowControllers
{
var viewCibName = [self viewCibName],
viewController = nil,
windowController = nil;
// Create our view controller if we have a cib for it.
if ([viewCibName length])
viewController = [[CPViewController alloc] initWithCibName:viewCibName bundle:nil owner:self];
// If we have a view controller, check if we have a free window for it.
if (viewController)
windowController = [self firstEligibleExistingWindowController];
// If not, create one.
if (!windowController)
{
var windowCibName = [self windowCibName];
// From a cib if we have one.
if ([windowCibName length])
windowController = [[CPWindowController alloc] initWithWindowCibName:windowCibName owner:self];
// If not you get a standard window capable of displaying multiple documents and view
else if (viewController)
{
var view = [viewController view],
theWindow = [[CPWindow alloc] initWithContentRect:[view frame] styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
windowController = [[CPWindowController alloc] initWithWindow:theWindow];
}
}
if (windowController && viewController)
[windowController setSupportsMultipleDocuments:YES];
if (windowController)
[self addWindowController:windowController];
if (viewController)
[self addViewController:viewController forWindowController:windowController];
}
/*!
@@ -249,12 +312,52 @@ var CPDocumentUntitledCount = 0;
- (void)addWindowController:(CPWindowController)aWindowController
{
[_windowControllers addObject:aWindowController];
if ([aWindowController document] != self)
{
[aWindowController setNextResponder:self];
if ([aWindowController document] !== self)
[aWindowController setDocument:self];
}
}
/*!
Remove a controller to the document's list of controllers. This should
be called after closing the controller's window.
@param aWindowController the controller to remove
*/
- (void)removeWindowController:(CPWindowController)aWindowController
{
if (aWindowController)
[_windowControllers removeObject:aWindowController];
if ([aWindowController document] === self)
[aWindowController setDocument:nil];
}
- (CPView)view
{
return _view;
}
- (CPArray)viewControllers
{
return [_viewControllersForWindowControllers allValues];
}
- (void)addViewController:(CPViewController)aViewController forWindowController:(CPWindowController)aWindowController
{
// FIXME: exception if we don't own the window controller?
[_viewControllersForWindowControllers setObject:aViewController forKey:[aWindowController UID]];
if ([aWindowController document] === self)
[aWindowController setViewController:aViewController];
}
- (void)removeViewController:(CPViewController)aViewController
{
[_viewControllersForWindowControllers removeObject:aViewController];
}
- (CPViewController)viewControllerForWindowController:(CPWindowController)aWindowController
{
return [_viewControllersForWindowControllers objectForKey:[aWindowController UID]];
}
// Managing Document Windows
@@ -263,6 +366,7 @@ var CPDocumentUntitledCount = 0;
*/
- (void)showWindows
{
[_windowControllers makeObjectsPerformSelector:@selector(setDocument:) withObject:self];
[_windowControllers makeObjectsPerformSelector:@selector(showWindow:) withObject:self];
}
@@ -283,6 +387,11 @@ var CPDocumentUntitledCount = 0;
return @"Untitled " + _untitledDocumentIndex;
}
- (CPString)viewCibName
{
return nil;
}
/*!
Returns the document's Cib name
*/
@@ -292,18 +401,18 @@ var CPDocumentUntitledCount = 0;
}
/*!
Called after <code>aWindowController<code> loads the document's Nib file.
Called after \c aWindowController loads the document's Nib file.
@param aWindowController the controller that loaded the Nib file
*/
- (void)windowControllerDidLoadNib:(CPWindowController)aWindowController
- (void)windowControllerDidLoadCib:(CPWindowController)aWindowController
{
}
/*!
Called before <code>aWindowController</code> will load the document's Nib file.
Called before \c aWindowController will load the document's Nib file.
@param aWindowController the controller that will load the Nib file
*/
- (void)windowControllerWillLoadNib:(CPWindowController)aWindowController
- (void)windowControllerWillLoadCib:(CPWindowController)aWindowController
{
}
@@ -322,7 +431,7 @@ var CPDocumentUntitledCount = 0;
// FIXME: Oh man is this every looking for trouble, we need to handle login at the Cappuccino level, with HTTP Errors.
_readConnection = [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:anAbsoluteURL] delegate:self];
_readConnection.session = _CPReadSessionMake(aType, aDelegate, aDidReadSelector, aContextInfo);
}
@@ -340,7 +449,7 @@ var CPDocumentUntitledCount = 0;
*/
- (void)setFileURL:(CPURL)aFileURL
{
if (_fileURL == aFileURL)
if (_fileURL === aFileURL)
return;
_fileURL = aFileURL;
@@ -365,17 +474,22 @@ var CPDocumentUntitledCount = 0;
_writeRequest = [CPURLRequest requestWithURL:anAbsoluteURL];
[_writeRequest setHTTPMethod:@"POST"];
// FIXME: THIS IS WRONG! We need a way to decide
if ([CPPlatform isBrowser])
[_writeRequest setHTTPMethod:@"POST"];
else
[_writeRequest setHTTPMethod:@"PUT"];
[_writeRequest setHTTPBody:[data string]];
[_writeRequest setValue:@"close" forHTTPHeaderField:@"Connection"];
if (aSaveOperation == CPSaveOperation)
[_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
if (aSaveOperation != CPSaveToOperation)
[self updateChangeCount:CPChangeCleared];
// FIXME: Oh man is this every looking for trouble, we need to handle login at the Cappuccino level, with HTTP Errors.
var connection = [CPURLConnection connectionWithRequest:_writeRequest delegate:self];
@@ -432,6 +546,7 @@ var CPDocumentUntitledCount = 0;
_writeRequest = nil;
objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo);
[self _sendDocumentSavedNotification:NO];
}
}
}
@@ -460,6 +575,7 @@ var CPDocumentUntitledCount = 0;
_writeRequest = nil;
objj_msgSend(session.delegate, session.didSaveSelector, self, YES, session.contextInfo);
[self _sendDocumentSavedNotification:YES];
}
}
@@ -487,6 +603,7 @@ var CPDocumentUntitledCount = 0;
alert("There was an error saving the document.");
objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo);
[self _sendDocumentSavedNotification:NO];
}
}
@@ -502,7 +619,7 @@ var CPDocumentUntitledCount = 0;
// Managing Document Status
/*!
Returns <code>YES</code> if there are any unsaved changes.
Returns \c YES if there are any unsaved changes.
*/
- (BOOL)isDocumentEdited
{
@@ -548,7 +665,7 @@ var CPDocumentUntitledCount = 0;
// Working with Undo Manager
/*!
Returns <code>YES</code> if the document has a
Returns \c YES if the document has a
CPUndoManager.
*/
- (BOOL)hasUndoManager
@@ -558,7 +675,7 @@ var CPDocumentUntitledCount = 0;
/*!
Sets whether the document should have a CPUndoManager.
@param aFlag <code>YES</code> makes the document have an undo manager
@param aFlag \c YES makes the document have an undo manager
*/
- (void)setHasUndoManager:(BOOL)aFlag
{
@@ -642,7 +759,7 @@ var CPDocumentUntitledCount = 0;
/*!
Returns the document's undo manager. If the document
should have one, but the manager is <code>nil</code>, it
should have one, but the manager is \c nil, it
will be created and then returned.
@return the document's undo manager
*/
@@ -666,11 +783,16 @@ var CPDocumentUntitledCount = 0;
// Handling User Actions
/*!
Saves the document. If the document does not
have a file path to save to (<code>fileURL</code>)
then <code>saveDocumentAs:</code> will be called.
have a file path to save to (\c fileURL)
then \c -saveDocumentAs: will be called.
@param aSender the object requesting the save
*/
- (void)saveDocument:(id)aSender
{
[self saveDocumentWithDelegate:nil didSaveSelector:nil contextInfo:nil];
}
- (void)saveDocumentWithDelegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(Object)contextInfo
{
if (_fileURL)
{
@@ -678,10 +800,10 @@ var CPDocumentUntitledCount = 0;
postNotificationName:CPDocumentWillSaveNotification
object:self];
[self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:self didSaveSelector:@selector(document:didSave:contextInfo:) contextInfo:NULL];
[self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
}
else
[self saveDocumentAs:self];
[self _saveDocumentAsWithDelegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
}
/*!
@@ -690,22 +812,30 @@ var CPDocumentUntitledCount = 0;
*/
- (void)saveDocumentAs:(id)aSender
{
_documentName = window.prompt("Document Name:");
[self _saveDocumentAsWithDelegate:nil didSaveSelector:nil contextInfo:nil];
}
if (!_documentName)
- (void)_saveDocumentAsWithDelegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(Object)contextInfo
{
var savePanel = [CPSavePanel savePanel],
response = [savePanel runModal];
if (!response)
return;
var saveURL = [savePanel URL];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPDocumentWillSaveNotification
object:self];
[self saveToURL:[self proposedFileURL] ofType:[self fileType] forSaveOperation:CPSaveAsOperation delegate:self didSaveSelector:@selector(document:didSave:contextInfo:) contextInfo:NULL];
[self saveToURL:saveURL ofType:[self fileType] forSaveOperation:CPSaveAsOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
}
/*
@ignore
*/
- (void)document:(id)aDocument didSave:(BOOL)didSave contextInfo:(id)aContextInfo
- (void)_sendDocumentSavedNotification:(BOOL)didSave
{
if (didSave)
[[CPNotificationCenter defaultCenter]
@@ -719,6 +849,72 @@ var CPDocumentUntitledCount = 0;
@end
@implementation CPDocument (ClosingDocuments)
- (void)close
{
[_windowControllers makeObjectsPerformSelector:@selector(removeDocumentAndCloseIfNecessary:) withObject:self];
[[CPDocumentController sharedDocumentController] removeDocument:self];
}
- (void)shouldCloseWindowController:(CPWindowController)controller delegate:(id)delegate shouldCloseSelector:(SEL)selector contextInfo:(Object)info
{
if ([controller shouldCloseDocument] || ([_windowControllers count] < 2 && [_windowControllers indexOfObject:controller] !== CPNotFound))
[self canCloseDocumentWithDelegate:self shouldCloseSelector:@selector(_document:shouldClose:context:) contextInfo:{delegate:delegate, selector:selector, context:info}];
else if ([delegate respondsToSelector:selector])
objj_msgSend(delegate, selector, self, YES, info);
}
- (void)_document:(CPDocument)aDocument shouldClose:(BOOL)shouldClose context:(Object)context
{
if (aDocument === self && shouldClose)
[self close];
objj_msgSend(context.delegate, context.selector, aDocument, shouldClose, context.context);
}
- (void)canCloseDocumentWithDelegate:(id)aDelegate shouldCloseSelector:(SEL)aSelector contextInfo:(Object)context
{
if (![self isDocumentEdited])
return [aDelegate respondsToSelector:aSelector] && objj_msgSend(aDelegate, aSelector, self, YES, context);
_canCloseAlert = [[CPAlert alloc] init];
[_canCloseAlert setDelegate:self];
[_canCloseAlert setAlertStyle:CPWarningAlertStyle];
[_canCloseAlert setTitle:@"Unsaved Document"];
[_canCloseAlert setMessageText:sprintf(@"Do you want to save the changes you've made to the document \"%@\"?",
[self displayName] || [self fileName])];
[_canCloseAlert addButtonWithTitle:@"Save"];
[_canCloseAlert addButtonWithTitle:@"Cancel"];
[_canCloseAlert addButtonWithTitle:@"Don't Save"];
_canCloseAlert._context = {delegate:aDelegate, selector:aSelector, context:context};
[_canCloseAlert runModal];
}
- (void)alertDidEnd:(CPAlert)alert returnCode:(int)returnCode
{
if (alert !== _canCloseAlert)
return;
var delegate = alert._context.delegate,
selector = alert._context.selector,
context = alert._context.context;
if (returnCode === 0)
[self saveDocumentWithDelegate:delegate didSaveSelector:selector contextInfo:context];
else
objj_msgSend(delegate, selector, self, returnCode === 2, context);
_canCloseAlert = nil;
}
@end
var _CPReadSessionMake = function(aType, aDelegate, aDidReadSelector, aContextInfo)
{
return { fileType:aType, delegate:aDelegate, didReadSelector:aDidReadSelector, contextInfo:aContextInfo };
+163 -16
View File
@@ -24,6 +24,7 @@
@import <Foundation/CPBundle.j>
@import "CPDocument.j"
@import "CPOpenPanel.j";
var CPSharedDocumentController = nil;
@@ -78,7 +79,7 @@ var CPSharedDocumentController = nil;
method searches documents already open. It does not
open the document at the URL if it is not already open.
@param aURL the url of the document
@return the document, or <code>nil</code> if such a document is not open
@return the document, or \c nil if such a document is not open
*/
- (CPDocument)documentForURL:(CPURL)aURL
{
@@ -113,7 +114,7 @@ var CPSharedDocumentController = nil;
[theDocument makeWindowControllers];
[theDocument showWindows];
}
return theDocument;
}
@@ -138,16 +139,21 @@ var CPSharedDocumentController = nil;
- (CPDocument)openDocumentWithContentsOfURL:(CPURL)anAbsoluteURL display:(BOOL)shouldDisplay error:(CPError)anError
{
var result = [self documentForURL:anAbsoluteURL];
if (!result)
{
var type = [self typeForContentsOfURL:anAbsoluteURL error:anError];
result = [self makeDocumentWithContentsOfURL:anAbsoluteURL ofType:type delegate:self didReadSelector:@selector(document:didRead:contextInfo:) contextInfo:[CPDictionary dictionaryWithObject:shouldDisplay forKey:@"shouldDisplay"]];
[self addDocument:result];
if (result)
[self noteNewRecentDocument:result];
}
else if (shouldDisplay)
[result showWindows];
return result;
}
@@ -157,7 +163,7 @@ var CPSharedDocumentController = nil;
@param anAbsoluteURL the document URL
@param absoluteContentsURL the location of the document's contents
@param anError not used
@return the loaded document or <code>nil</code> if there was an error
@return the loaded document or \c nil if there was an error
*/
- (CPDocument)reopenDocumentForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL error:(CPError)anError
{
@@ -187,7 +193,7 @@ var CPSharedDocumentController = nil;
@param aDelegate receives a callback after the load has completed
@param aSelector the selector to invoke for the callback
@param aContextInfo an object passed as an argument for the callback
@return a new document or <code>nil</code> if there was an error
@return a new document or \c nil if there was an error
*/
- (CPDocument)makeDocumentForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aSelector contextInfo:(id)aContextInfo
{
@@ -203,7 +209,6 @@ var CPSharedDocumentController = nil;
if (!didRead)
return;
[self addDocument:aDocument];
[aDocument makeWindowControllers];
if ([aContextInfo objectForKey:@"shouldDisplay"])
@@ -219,6 +224,20 @@ var CPSharedDocumentController = nil;
[self openUntitledDocumentOfType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] display:YES];
}
-(void)openDocument:(id)aSender
{
var openPanel = [CPOpenPanel openPanel];
[openPanel runModal];
var URLs = [openPanel URLs],
index = 0,
count = [URLs count];
for (; index < count; ++index)
[self openDocumentWithContentsOfURL:[CPURL URLWithString:URLs[index]] display:YES error:nil];
}
// Managing Documents
/*!
@@ -231,7 +250,7 @@ var CPSharedDocumentController = nil;
}
/*!
Adds <code>aDocument</code> under the control of the receiver.
Adds \c aDocument under the control of the receiver.
@param aDocument the document to add
*/
- (void)addDocument:(CPDocument)aDocument
@@ -240,7 +259,7 @@ var CPSharedDocumentController = nil;
}
/*!
Removes <code>aDocument</code> from the control of the receiver.
Removes \c aDocument from the control of the receiver.
@param aDocument the document to remove
*/
- (void)removeDocument:(CPDocument)aDocument
@@ -258,7 +277,8 @@ var CPSharedDocumentController = nil;
var index = 0,
count = _documentTypes.length,
extension = [[anAbsoluteURL pathExtension] lowercaseString];
extension = [[anAbsoluteURL pathExtension] lowercaseString],
starType = nil;
for (; index < count; ++index)
{
@@ -268,12 +288,17 @@ var CPSharedDocumentController = nil;
extensionCount = extensions.length;
for (; extensionIndex < extensionCount; ++extensionIndex)
if ([extensions[extensionIndex] lowercaseString] == extension)
{
var thisExtension = [extensions[extensionIndex] lowercaseString];
if (thisExtension === extension)
return [documentType objectForKey:@"CPBundleTypeName"];
if (thisExtension === "****")
starType = [documentType objectForKey:@"CPBundleTypeName"];
}
}
// FIXME?
return [self defaultType];//nil;
return starType || [self defaultType];
}
// Managing Document Types
@@ -296,9 +321,9 @@ var CPSharedDocumentController = nil;
}
/*!
Returns the CPDocument subclass associated with <code>aType</code>.
Returns the CPDocument subclass associated with \c aType.
@param aType the type of document
@return a Cappuccino Class object, or <code>nil</code> if no match was found
@return a Cappuccino Class object, or \c nil if no match was found
*/
- (Class)documentClassForType:(CPString)aType
{
@@ -308,3 +333,125 @@ var CPSharedDocumentController = nil;
}
@end
@implementation CPDocumentController (Closing)
- (void)closeAllDocumentsWithDelegate:(id)aDelegate didCloseAllSelector:(SEL)didCloseSelector contextInfo:(Object)info
{
var context = {
delegate: aDelegate,
selector: didCloseSelector,
context: info
};
[self _closeDocumentsStartingWith:nil shouldClose:YES context:context];
}
// Recursive callback method. Start it by passing in a document of nil.
- (void)_closeDocumentsStartingWith:(CPDocument)aDocument shouldClose:(BOOL)shouldClose context:(Object)context
{
if (shouldClose)
{
[aDocument close];
if ([[self documents] count] > 0)
{
[[[self documents] lastObject] canCloseDocumentWithDelegate:self
shouldCloseSelector:@selector(_closeDocumentsStartingWith:shouldClose:context:)
contextInfo:context];
return;
}
}
if ([context.delegate respondsToSelector:context.selector])
objj_msgSend(context.delegate, context.selector, self, [[self documents] count] === 0, context.context);
}
@end
@implementation CPDocumentController (Recents)
- (CPArray)recentDocumentURLs
{
// FIXME move this to CP land
if (typeof window["cpRecentDocumentURLs"] === 'function')
return window.cpRecentDocumentURLs();
return [];
}
- (void)clearRecentDocuments:(id)sender
{
if (typeof window["cpClearRecentDocuments"] === 'function')
window.cpClearRecentDocuments();
[self _updateRecentDocumentsMenu];
}
- (void)noteNewRecentDocument:(CPDocument)aDocument
{
[self noteNewRecentDocumentURL:[[aDocument fileURL] absoluteString]];
}
- (void)noteNewRecentDocumentURL:(CPString)aURL
{
if (typeof window["cpNoteNewRecentDocumentPath"] === 'function')
window.cpNoteNewRecentDocumentPath(aURL);
[self _updateRecentDocumentsMenu];
}
- (void)_removeAllRecentDocumentsFromMenu:(CPMenu)aMenu
{
var items = [aMenu itemArray],
count = [items count];
while (count--)
{
var item = items[count];
if ([item action] === @selector(_openRecentDocument:))
[aMenu removeItemAtIndex:count];
}
}
- (void)_updateRecentDocumentsMenu
{
var menu = [[CPApp mainMenu] _menuWithName:@"_CPRecentDocumentsMenu"],
recentDocuments = [self recentDocumentURLs],
menuItems = [menu itemArray],
documentCount = [recentDocuments count],
menuItemCount = [menuItems count];
[self _removeAllRecentDocumentsFromMenu:menu];
if (menuItemCount)
{
if (!documentCount)
{
if ([menuItems[0] isSeparatorItem])
[menu removeItemAtIndex:0];
}
else
{
if (![menuItems[0] isSeparatorItem])
[menu insertItem:[CPMenuItem separatorItem] atIndex:0];
}
}
while (documentCount--)
{
var path = recentDocuments[documentCount],
item = [[CPMenuItem alloc] initWithTitle:[path lastPathComponent] action:@selector(_openRecentDocument:) keyEquivalent:nil];
[item setTag:path];
[menu insertItem:item atIndex:0];
}
}
- (void)_openRecentDocument:(id)sender
{
[self openDocumentWithContentsOfURL:[sender tag] display:YES error:nil];
}
@end
+251 -156
View File
@@ -26,73 +26,28 @@
@import <AppKit/CPImageView.j>
#import "CoreGraphics/CGGeometry.h"
#import "Platform/Platform.h"
CPDragOperationNone = 0,
CPDragOperationCopy = 1 << 1,
CPDragOperationLink = 1 << 1,
CPDragOperationGeneric = 1 << 2,
CPDragOperationPrivate = 1 << 3,
CPDragOperationMove = 1 << 4,
CPDragOperationDelete = 1 << 5,
CPDragOperationEvery = -1;
#define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window])
var CPSharedDragServer = nil;
var CPDragServerView = nil,
CPDragServerSource = nil,
CPDragServerWindow = nil,
CPDragServerOffset = nil,
CPDragServerLocation = nil,
CPDragServerPasteboard = nil,
CPDragServerDestination = nil,
CPDragServerDraggingInfo = nil,
CPDragServerPreviousEvent = nil,
CPDragServerAutoscrollInterval = nil;
var CPDragServerIsDraggingImage = NO,
CPDragServerShouldSendDraggedViewMovedTo = NO,
CPDragServerShouldSendDraggedImageMovedTo = NO,
CPDragServerShouldSendDraggedViewEndedAtOperation = NO,
CPDragServerShouldSendDraggedImageEndedAtOperation = NO;
var CPDragServerPreviousEvent = nil,
CPDragServerAutoscrollInterval = nil;
/*
var CPDragServerAutoscroll = function()
{
[CPDragServerSource autoscroll:CPDragServerPreviousEvent];
}
var CPDragServerStartDragging = function(anEvent)
{
CPDragServerUpdateDragging(anEvent);
}
var CPDragServerUpdateDragging = function(anEvent)
{
// If this is a mouse up, then complete the drag.
if([anEvent type] == CPLeftMouseUp)
{
if (CPDragServerAutoscrollInterval !== nil)
clearInterval(CPDragServerAutoscrollInterval);
CPDragServerAutoscrollInterval = nil;
CPDragServerLocation = [DRAGGING_WINDOW(CPDragServerDestination) convertBridgeToBase:[[anEvent window] convertBaseToBridge:[anEvent locationInWindow]]];
[CPDragServerView removeFromSuperview];
[CPSharedDragServer._dragWindow orderOut:nil];
if (CPDragServerDestination &&
(![CPDragServerDestination respondsToSelector:@selector(prepareForDragOperation:)] || [CPDragServerDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
(![CPDragServerDestination respondsToSelector:@selector(performDragOperation:)] || [CPDragServerDestination performDragOperation:CPDragServerDraggingInfo]) &&
[CPDragServerDestination respondsToSelector:@selector(concludeDragOperation:)])
[CPDragServerDestination concludeDragOperation:CPDragServerDraggingInfo];
if (CPDragServerShouldSendDraggedImageEndedAtOperation)
[CPDragServerSource draggedImage:[CPDragServerView image] endedAt:CPDragServerLocation operation:NO];
else if (CPDragServerShouldSendDraggedViewEndedAtOperation)
[CPDragServerSource draggedView:CPDragServerView endedAt:CPDragServerLocation operation:NO];
CPDragServerIsDraggingImage = NO;
CPDragServerDestination = nil;
return;
}
if (CPDragServerAutoscrollInterval === nil)
{
if ([CPDragServerSource respondsToSelector:@selector(autoscroll:)])
@@ -101,43 +56,16 @@ var CPDragServerUpdateDragging = function(anEvent)
CPDragServerPreviousEvent = anEvent;
// If we're not a mouse up, then we're going to want to grab the next event.
[CPApp setCallback:CPDragServerUpdateDragging
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask
untilDate:nil inMode:0 dequeue:NO];
if (CPDragServerAutoscrollInterval !== nil)
clearInterval(CPDragServerAutoscrollInterval);
var location = [anEvent locationInWindow],
operation =
bridgeLocation = [[anEvent window] convertBaseToBridge:location];
CPDragServerAutoscrollInterval = nil;
*/
// We have to convert base to bridge since the drag event comes from the source window, not the drag window.
var draggingDestination = [[CPDOMWindowBridge sharedDOMWindowBridge] _dragHitTest:bridgeLocation pasteboard:CPDragServerPasteboard];
CPDragServerLocation = [DRAGGING_WINDOW(draggingDestination) convertBridgeToBase:bridgeLocation];
if(draggingDestination != CPDragServerDestination)
{
if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingExited:)])
[CPDragServerDestination draggingExited:CPDragServerDraggingInfo];
CPDragServerDestination = draggingDestination;
if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingEntered:)])
[CPDragServerDestination draggingEntered:CPDragServerDraggingInfo];
}
else if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingUpdated:)])
[CPDragServerDestination draggingUpdated:CPDragServerDraggingInfo];
location.x -= CPDragServerOffset.x;
location.y -= CPDragServerOffset.y;
[CPDragServerView setFrameOrigin:location];
if (CPDragServerShouldSendDraggedImageMovedTo)
[CPDragServerSource draggedImage:[CPDragServerView image] movedTo:location];
else if (CPDragServerShouldSendDraggedViewMovedTo)
[CPDragServerSource draggedView:CPDragServerView movedTo:location];
}
var CPSharedDragServer = nil;
var CPDragServerSource = nil;
var CPDragServerDraggingInfo = nil;
/*
CPDraggingInfo is a container of information about a specific dragging session.
@@ -147,24 +75,36 @@ var CPDragServerUpdateDragging = function(anEvent)
{
}
- (CPPasteboard)draggingPasteboard
{
if ([CPPlatform supportsDragAndDrop])
return [_CPDOMDataTransferPasteboard DOMDataTransferPasteboard];
return [[CPDragServer sharedDragServer] draggingPasteboard];
}
- (id)draggingSource
{
return CPDragServerSource;
return [[CPDragServer sharedDragServer] draggingSource];
}
/*
- (unsigned)draggingSourceOperationMask
*/
- (CPPoint)draggingLocation
{
return CPDragServerLocation;
return [[CPDragServer sharedDragServer] draggingLocation];
}
- (CPPasteboard)draggingPasteboard
- (CPWindow)draggingDestinationWindow
{
return CPDragServerPasteboard;
return DRAGGING_WINDOW([[CPDragServer sharedDragServer] draggingDestination]);
}
- (CPImage)draggedImage
{
return [CPDragServerView image];
return [[self draggedView] image];
}
- (CGPoint)draggedImageLocation
@@ -172,22 +112,44 @@ var CPDragServerUpdateDragging = function(anEvent)
return [self draggedViewLocation];
}
- (CGPoint)draggedViewLocation
{
return [DRAGGING_WINDOW(CPDragServerDestination) convertBridgeToBase:[CPDragServerView frame].origin];
}
- (CPView)draggedView
{
return CPDragServerView;
return [[CPDragServer sharedDragServer] draggedView];
}
- (CGPoint)draggedViewLocation
{
var dragServer = [CPDragServer sharedDragServer];
return [DRAGGING_WINDOW([dragServer draggingDestination]) convertPlatformWindowToBase:[[dragServer draggedView] frame].origin];
}
@end
var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
CPDraggingSource_draggedImage_endAt_operation_ = 1 << 1,
CPDraggingSource_draggedView_movedTo_ = 1 << 2,
CPDraggingSource_draggedView_endedAt_operation_ = 1 << 3;
@implementation CPDragServer : CPObject
{
CPWindow _dragWindow;
CPImageView _imageView;
BOOL _isDragging @accessors(readonly, getter=isDragging);
CPWindow _draggedWindow @accessors(readonly, getter=draggedWindow);
CPView _draggedView @accessors(readonly, getter=draggedView);
CPImageView _imageView;
BOOL _isDraggingImage;
CGSize _draggingOffset @accessors(readonly, getter=draggingOffset);
CPPasteboard _draggingPasteboard @accessors(readonly, getter=draggingPasteboard);
id _draggingSource @accessors(readonly, getter=draggingSource);
unsigned _implementedDraggingSourceMethods;
CGPoint _draggingLocation;
id _draggingDestination;
}
/*
@@ -196,9 +158,9 @@ var CPDragServerUpdateDragging = function(anEvent)
*/
+ (void)initialize
{
if (self != [CPDragServer class])
if (self !== [CPDragServer class])
return;
CPDragServerDraggingInfo = [[CPDraggingInfo alloc] init];
}
@@ -206,7 +168,7 @@ var CPDragServerUpdateDragging = function(anEvent)
{
if (!CPSharedDragServer)
CPSharedDragServer = [[CPDragServer alloc] init];
return CPSharedDragServer;
}
@@ -216,16 +178,104 @@ var CPDragServerUpdateDragging = function(anEvent)
- (id)init
{
self = [super init];
if (self)
{
_dragWindow = [[CPWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:CPBorderlessWindowMask];
[_dragWindow setLevel:CPDraggingWindowLevel];
_draggedWindow = [[CPWindow alloc] initWithContentRect:_CGRectMakeZero() styleMask:CPBorderlessWindowMask];
[_draggedWindow setLevel:CPDraggingWindowLevel];
}
return self;
}
- (CGPoint)draggingLocation
{
return _draggingLocation
}
- (void)draggingStartedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation
{
if (_isDraggingImage)
{
if ([_draggingSource respondsToSelector:@selector(draggedImage:beganAt:)])
[_draggingSource draggedImage:[_draggedView image] beganAt:aLocation];
}
else
{
if ([_draggingSource respondsToSelector:@selector(draggedView:beganAt:)])
[_draggingSource draggedView:_draggedView beganAt:aLocation];
}
if (![CPPlatform supportsDragAndDrop])
[_draggedWindow orderFront:self];
}
- (void)draggingSourceUpdatedWithGlobalLocation:(CGPoint)aGlobalLocation
{
if (![CPPlatform supportsDragAndDrop])
[_draggedWindow setFrameOrigin:_CGPointMake(aGlobalLocation.x - _draggingOffset.width, aGlobalLocation.y - _draggingOffset.height)];
if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_movedTo_)
[_draggingSource draggedImage:[_draggedView image] movedTo:aGlobalLocation];
else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_movedTo_)
[_draggingSource draggedView:_draggedView movedTo:aGlobalLocation];
}
- (CPDragOperation)draggingUpdatedInPlatformWindow:(CPPlatformWindow)aPlatformWindow location:(CGPoint)aLocation
{
var dragOperation = CPDragOperationCopy;
// We have to convert base to bridge since the drag event comes from the source window, not the drag window.
var draggingDestination = [aPlatformWindow _dragHitTest:aLocation pasteboard:[CPDragServerDraggingInfo draggingPasteboard]];
if (draggingDestination)
_draggingLocation = [DRAGGING_WINDOW(draggingDestination) convertPlatformWindowToBase:aLocation];
if(draggingDestination !== _draggingDestination)
{
if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingExited:)])
[_draggingDestination draggingExited:CPDragServerDraggingInfo];
_draggingDestination = draggingDestination;
if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingEntered:)])
dragOperation = [_draggingDestination draggingEntered:CPDragServerDraggingInfo];
}
else if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingUpdated:)])
dragOperation = [_draggingDestination draggingUpdated:CPDragServerDraggingInfo];
if (!_draggingDestination)
dragOperation = CPDragOperationNone;
return dragOperation;
}
- (void)draggingEndedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation operation:(CPDragOperation)anOperation
{
[_draggedView removeFromSuperview];
if (![CPPlatform supportsDragAndDrop])
[_draggedWindow orderOut:self];
if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_endAt_operation_)
[_draggingSource draggedImage:[_draggedView image] endedAt:aLocation operation:anOperation];
else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_endedAt_operation_)
[_draggingSource draggedView:_draggedView endedAt:aLocation operation:anOperation];
_isDragging = NO;
}
- (void)performDragOperationInPlatformWindow:(CPPlatformWindow)aPlatformWindow
{
if (_draggingDestination &&
(![_draggingDestination respondsToSelector:@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
(![_draggingDestination respondsToSelector:@selector(performDragOperation:)] || [_draggingDestination performDragOperation:CPDragServerDraggingInfo]) &&
[_draggingDestination respondsToSelector:@selector(concludeDragOperation:)])
[_draggingDestination concludeDragOperation:CPDragServerDraggingInfo];
}
/*!
Initiates a drag session.
@param aView the view being dragged
@@ -235,50 +285,70 @@ var CPDragServerUpdateDragging = function(anEvent)
@param anEvent
@param aPasteboard the pasteboard that contains the drag data
@param aSourceObject the object where the drag started
@param slideBack if <code>YES</code>, <code>aView</code> slides back to
@param slideBack if \c YES, \c aView slides back to
its origin on a failed drop
*/
- (void)dragView:(CPView)aView fromWindow:(CPWindow)aWindow at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
- (void)dragView:(CPView)aView fromWindow:(CPWindow)aWindow at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)mouseDownEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
{
var eventLocation = [anEvent locationInWindow];
CPDragServerView = aView;
CPDragServerSource = aSourceObject;
CPDragServerWindow = aWindow;
CPDragServerOffset = CPPointMake(eventLocation.x - viewLocation.x, eventLocation.y - viewLocation.y);
CPDragServerPasteboard = [CPPasteboard pasteboardWithName:CPDragPboard];//aPasteboard;
_isDragging = YES;
[_dragWindow setFrameSize:CGSizeMakeCopy([[CPDOMWindowBridge sharedDOMWindowBridge] frame].size)];
[_dragWindow orderFront:self];
_draggedView = aView;
_draggingPasteboard = aPasteboard || [CPPasteboard pasteboardWithName:CPDragPboard];
_draggingSource = aSourceObject;
_draggingDestination = nil;
[aView setFrameOrigin:viewLocation];
[[_dragWindow contentView] addSubview:aView];
// The offset is based on the distance from where we want the view to be initially from where the mouse is initially
// Hence the use of mouseDownEvent's location and view's location in global coordinates.
var mouseDownWindow = [mouseDownEvent window],
mouseDownEventLocation = [mouseDownEvent locationInWindow];
if (CPDragServerIsDraggingImage)
if (mouseDownEventLocation)
{
if ([CPDragServerSource respondsToSelector:@selector(draggedImage:beganAt:)])
[CPDragServerSource draggedImage:[aView image] beganAt:viewLocation];
CPDragServerShouldSendDraggedImageMovedTo = [CPDragServerSource respondsToSelector:@selector(draggedImage:movedTo:)];
CPDragServerShouldSendDraggedImageEndedAtOperation = [CPDragServerSource respondsToSelector:@selector(draggedImage:endAt:operation:)];
CPDragServerShouldSendDraggedViewMovedTo = NO;
CPDragServerShouldSendDraggedViewEndedAtOperation = NO;
if (mouseDownWindow)
mouseDownEventLocation = [mouseDownWindow convertBaseToGlobal:mouseDownEventLocation];
_draggingOffset = _CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y);
}
else
_draggingOffset = _CGSizeMakerZero();
if ([CPPlatform isBrowser])
[_draggedWindow setPlatformWindow:[aWindow platformWindow]];
[aView setFrameOrigin:_CGPointMakeZero()];
var mouseLocation = [CPEvent mouseLocation];
// Place it where the mouse pointer is.
[_draggedWindow setFrameOrigin:_CGPointMake(mouseLocation.x - _draggingOffset.width, mouseLocation.y - _draggingOffset.height)];
[_draggedWindow setFrameSize:[aView frame].size];
[[_draggedWindow contentView] addSubview:aView];
_implementedDraggingSourceMethods = 0;
if (_draggedView === _imageView)
{
if ([_draggingSource respondsToSelector:@selector(draggedImage:movedTo:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_movedTo_;
if ([_draggingSource respondsToSelector:@selector(draggedImage:endAt:operation:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_endAt_operation_;
}
else
{
if ([CPDragServerSource respondsToSelector:@selector(draggedView:beganAt:)])
[CPDragServerSource draggedView:aView beganAt:viewLocation];
CPDragServerShouldSendDraggedViewMovedTo = [CPDragServerSource respondsToSelector:@selector(draggedView:movedTo:)];
CPDragServerShouldSendDraggedViewEndedAtOperation = [CPDragServerSource respondsToSelector:@selector(draggedView:endedAt:operation:)];
if ([_draggingSource respondsToSelector:@selector(draggedView:movedTo:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedView_movedTo_;
CPDragServerShouldSendDraggedImageMovedTo = NO;
CPDragServerShouldSendDraggedImageEndedAtOperation = NO;
if ([_draggingSource respondsToSelector:@selector(draggedView:endedAt:operation:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedView_endedAt_operation_;
}
CPDragServerStartDragging(anEvent);
if (![CPPlatform supportsDragAndDrop])
{
[self draggingStartedInPlatformWindow:[aWindow platformWindow] globalLocation:mouseLocation];
[self trackDragging:mouseDownEvent];
}
}
/*!
@@ -290,22 +360,47 @@ var CPDragServerUpdateDragging = function(anEvent)
@param anEvent
@param aPasteboard the pasteboard where the drag data is located
@param aSourceObject the object where the drag started
@param slideBack if <code>YES</code>, <code>aView</code> slides back to
@param slideBack if \c YES, \c aView slides back to
its origin on a failed drop
*/
- (void)dragImage:(CPImage)anImage fromWindow:(CPWindow)aWindow at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
{
CPDragServerIsDraggingImage = YES;
_isDraggingImage = YES;
var imageSize = [anImage size];
if (!_imageView)
_imageView = [[CPImageView alloc] initWithFrame:CPRectMakeZero()];
_imageView = [[CPImageView alloc] initWithFrame:_CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)];
[_imageView setImage:anImage];
[_imageView setFrameSize:CGSizeMakeCopy([anImage size])];
[self dragView:_imageView fromWindow:aWindow at:imageLocation offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
}
- (void)trackDragging:(CPEvent)anEvent
{
var type = [anEvent type],
platformWindow = [_draggedWindow platformWindow],
platformWindowLocation = [[anEvent window] convertBaseToPlatformWindow:[anEvent locationInWindow]];
if (type === CPLeftMouseUp)
{
[self performDragOperationInPlatformWindow:platformWindow];
[self draggingEndedInPlatformWindow:platformWindow globalLocation:platformWindowLocation operation:CPDragOperationNone];
// Stop tracking events.
return;
}
[self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation];
[self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation];
// If we're not a mouse up, then we're going to want to grab the next event.
[CPApp setTarget:self selector:@selector(trackDragging:)
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask
untilDate:nil inMode:0 dequeue:NO];
}
@end
@implementation CPWindow (CPDraggingAdditions)
@@ -318,23 +413,23 @@ var CPDragServerUpdateDragging = function(anEvent)
return nil;
// We don't need to do this because the only place this gets called
// -_dragHitTest: in CPDOMWindowBridge does this already. Perhaps to
// -_dragHitTest: in CPPlatformWindow does this already. Perhaps to
// be safe?
// if (![self containsPoint:aPoint])
// return nil;
var adjustedPoint = _CGPointMake(aPoint.x - _CGRectGetMinX(_frame), aPoint.y - _CGRectGetMinY(_frame)),
var adjustedPoint = [self convertPlatformWindowToBase:aPoint],
hitView = [_windowView hitTest:adjustedPoint];
while (hitView && ![aPasteboard availableTypeFromArray:[hitView registeredDraggedTypes]])
hitView = [hitView superview];
if (hitView)
return hitView;
if ([aPasteboard availableTypeFromArray:[self registeredDraggedTypes]])
return self;
return nil;
}
+56 -96
View File
@@ -25,110 +25,26 @@
#include "CoreGraphics/CGGeometry.h"
/*
@global
@group CPEventType
*/
CPLeftMouseDown = 1;
/*
@global
@group CPEventType
*/
CPLeftMouseUp = 2;
/*
@global
@group CPEventType
*/
CPRightMouseDown = 3;
/*
@global
@group CPEventType
*/
CPRightMouseUp = 4;
/*
@global
@group CPEventType
*/
CPMouseMoved = 5;
/*
@global
@group CPEventType
*/
CPLeftMouseDragged = 6;
/*
@global
@group CPEventType
*/
CPRightMouseDragged = 7;
/*
@global
@group CPEventType
*/
CPMouseEntered = 8;
/*
@global
@group CPEventType
*/
CPMouseExited = 9;
/*
@global
@group CPEventType
*/
CPKeyDown = 10;
/*
@global
@group CPEventType
*/
CPKeyUp = 11;
/*
@global
@group CPEventType
*/
CPFlagsChanged = 12;
/*
@global
@group CPEventType
*/
CPAppKitDefined = 13;
/*
@global
@group CPEventType
*/
CPSystemDefined = 14;
/*
@global
@group CPEventType
*/
CPApplicationDefined = 15;
/*
@global
@group CPEventType
*/
CPPeriodic = 16;
/*
@global
@group CPEventType
*/
CPCursorUpdate = 17;
/*
@global
@group CPEventType
*/
CPScrollWheel = 22;
/*
@global
@group CPEventType
*/
CPOtherMouseDown = 25;
/*
@global
@group CPEventType
*/
CPOtherMouseUp = 26;
/*
@global
@group CPEventType
*/
CPOtherMouseDragged = 27;
// iPhone Event Types
@@ -206,6 +122,7 @@ var _CPEventPeriodicEventPeriod = 0,
unsigned _clickCount;
float _pressure;
CPWindow _window;
Number _windowNumber;
CPString _characters;
CPString _charactersIgnoringModifiers
BOOL _isARepeat;
@@ -220,16 +137,16 @@ var _CPEventPeriodicEventPeriod = 0,
/*!
Creates a new keyboard event.
@param anEventType the event type. Must be one of CPKeyDown, CPKeyUp or CPFlagsChanged
@param aPoint the location of the cursor in the window specified by <code>aWindowNumber</code>
@param aPoint the location of the cursor in the window specified by \c aWindowNumber
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
@param aTimestamp the time the event occurred
@param aWindowNumber the number of the CPWindow where the event occurred
@param aGraphicsContext the graphics context where the event occurred
@param characters the characters associated with the event
@param unmodCharacters the string of keys pressed without the presence of any modifiers other than Shift
@param repeatKey <code>YES</code> if this is caused by the system repeat as opposed to the user pressing the key again
@param repeatKey \c YES if this is caused by the system repeat as opposed to the user pressing the key again
@param code a number associated with the keyboard key of this event
@throws CPInternalInconsistencyException if <code>anEventType</code> is not a CPKeyDown,
@throws CPInternalInconsistencyException if \c anEventType is not a CPKeyDown,
CPKeyUp or CPFlagsChanged
@return the keyboard event
*/
@@ -245,7 +162,7 @@ var _CPEventPeriodicEventPeriod = 0,
/*!
Creates a new mouse event
@param anEventType the event type
@param aPoint the location of the cursor in the window specified by <code>aWindowNumber</code>
@param aPoint the location of the cursor in the window specified by \c aWindowNumber
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
@param aTimestamp the time the event occurred
@param aWindowNumber the number of the CPWindow where the event occurred
@@ -267,7 +184,7 @@ var _CPEventPeriodicEventPeriod = 0,
/*!
Creates a new custom event
@param anEventType the event type. Must be one of CPAppKitDefined, CPSystemDefined, CPApplicationDefined or CPPeriodic
@param aLocation the location of the cursor in the window specified by <code>aWindowNumber</code>
@param aLocation the location of the cursor in the window specified by \c aWindowNumber
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
@param aTimestamp the time the event occurred
@param aWindowNumber the number of the CPWindow where the event occurred
@@ -327,7 +244,7 @@ var _CPEventPeriodicEventPeriod = 0,
_charactersIgnoringModifiers = unmodCharacters;
_isARepeat = isARepeat;
_keyCode = code;
_window = [CPApp windowWithWindowNumber:aWindowNumber];
_windowNumber = aWindowNumber;
}
return self;
@@ -357,15 +274,15 @@ var _CPEventPeriodicEventPeriod = 0,
/*!
Returns the location of the mouse (for mouse events).
If this is not a mouse event, it returns <code>nil</code>.
If <code>window</code> returns <code>nil</code>, then
If this is not a mouse event, it returns \c nil.
If \c window returns \c nil, then
the mouse coordinates will be based on the screen coordinates.
Otherwise, the coordinates are relative to the window's coordinates.
@return the location of the mouse, or <code>nil</code> for non-mouse events.
@return the location of the mouse, or \c nil for non-mouse events.
*/
- (CGPoint)locationInWindow
{
return _location;
return _CGPointMakeCopy(_location);
}
/*!
@@ -397,6 +314,9 @@ var _CPEventPeriodicEventPeriod = 0,
*/
- (CPWindow)window
{
if (!_window)
_window = [CPApp windowWithWindowNumber:_windowNumber];
return _window;
}
@@ -444,7 +364,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns <code>YES</code> if the keyboard event was caused by the key being held down.
Returns \c YES if the keyboard event was caused by the key being held down.
@throws CPInternalInconsistencyException if this method is called on a non-key event
*/
- (BOOL)isARepeat
@@ -461,6 +381,18 @@ var _CPEventPeriodicEventPeriod = 0,
return _keyCode;
}
+ (CGPoint)mouseLocation
{
// FIXME: this is incorrect, we shouldn't depend on the current event.
var event = [CPApp currentEvent],
eventWindow = [event window];
if (eventWindow)
return [eventWindow convertBaseToGlobal:[event locationInWindow]];
return [event locationInWindow];
}
- (float)pressure
{
return _pressure;
@@ -499,8 +431,16 @@ var _CPEventPeriodicEventPeriod = 0,
return _deltaZ;
}
- (BOOL)_couldBeKeyEquivalent
{
// FIXME: More cases? Space?
return _type === CPKeyDown &&
_modifierFlags & (CPCommandKeyMask | CPControlKeyMask) &&
[_characters length] > 0;
}
/*!
Generates periodic events every <code>aPeriod</code> seconds.
Generates periodic events every \c aPeriod seconds.
@param aDelay the number of seconds before the first event
@param aPeriod the length of time in seconds between successive events
*/
@@ -532,3 +472,23 @@ function _CPEventFirePeriodEvent()
[CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:_CGPointMakeZero() modifierFlags:0 timestamp:0 windowNumber:0 context:nil subtype:0 data1:0 data2:0]];
}
var CPEventClass = [CPEvent class];
function _CPEventFromNativeMouseEvent(aNativeEvent, anEventType, aPoint, modifierFlags, aTimestamp, aWindowNumber, aGraphicsContext, anEventNumber, aClickCount, aPressure)
{
aNativeEvent.isa = CPEventClass;
aNativeEvent._type = anEventType;
aNativeEvent._location = aPoint;
aNativeEvent._modifierFlags = modifierFlags;
aNativeEvent._timestamp = aTimestamp;
aNativeEvent._windowNumber = aWindowNumber;
aNativeEvent._window = nil;
aNativeEvent._context = aGraphicsContext;
aNativeEvent._eventNumber = anEventNumber;
aNativeEvent._clickCount = aClickCount;
aNativeEvent._pressure = aPressure;
return aNativeEvent;
}
+1 -1
View File
@@ -34,7 +34,7 @@
}
/*!
Creates a new Flash movie with the swf at <code>aFileName</code>.
Creates a new Flash movie with the swf at \c aFileName.
@param aFilename the swf to load
@return the initialized CPFlashMovie
*/
+4 -4
View File
@@ -20,10 +20,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPDOMWindowBridge.j"
@import "CPFlashMovie.j"
@import "CPView.j"
/*!
@ingroup appkit
*/
@@ -96,17 +96,17 @@
- (void)mouseDragged:(CPEvent)anEvent
{
[[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES];
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
- (void)mouseDown:(CPEvent)anEvent
{
[[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES];
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
- (void)mouseUp:(CPEvent)anEvent
{
[[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES];
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
@end
+28 -28
View File
@@ -62,11 +62,11 @@ function CPPointMake(x, y)
}
/*!
Makes a CGRect with an origin and size equal to <code>aRect</code> less the <code>dX/dY</code> insets specified.
Makes a CGRect with an origin and size equal to \c aRect less the \c dX/dY insets specified.
@param dX the size of the inset in the x-axis
@param dY the size of the inset in the y-axis
@group CGRect
@return CGRect a rectangle like <code>aRect</code> with an inset
@return CGRect a rectangle like \c aRect with an inset
*/
function CPRectInset(aRect, dX, dY)
{
@@ -132,7 +132,7 @@ function CPRectMake(x, y, width, height)
}
/*!
Creates a new rectangle with its origin offset by <code>dX</code> and <code>dY</code>.
Creates a new rectangle with its origin offset by \c dX and \c dY.
@group CGRect
@param aRect the rectangle to copy the origin and size from
@param dX the amount added to the x-size of the new rectangle
@@ -171,7 +171,7 @@ function CPRectStandardize(aRect)
}
/*!
Returns the smallest rectangle that can contain the two argument <code>CGRect</code>s.
Returns the smallest rectangle that can contain the two argument \c CGRects.
@group CGRect
@param lhsRect the first CGRect to use for the union calculation
@param rhsRect the second CGRect to use for the union calculation
@@ -211,12 +211,12 @@ function CPSizeMake(width, height)
}
/*!
Returns <code>YES</code> if the CGRect, <code>aRect</code>, contains
the CGPoint, <code>aPoint</code>.
Returns \c YES if the CGRect, \c aRect, contains
the CGPoint, \c aPoint.
@param aRect the rectangle to test with
@param aPoint the point to test with
@group CGRect
@return BOOL <code>YES</code> if the rectangle contains the point, <code>NO</code> otherwise.
@return BOOL \c YES if the rectangle contains the point, \c NO otherwise.
*/
function CPRectContainsPoint(aRect, aPoint)
{
@@ -227,12 +227,12 @@ function CPRectContainsPoint(aRect, aPoint)
}
/*!
Returns a <code>BOOL</code> indicating whether CGRect <code>possibleOuter</code>
contains CGRect <code>possibleInner</code>.
Returns a \c BOOL indicating whether CGRect \c possibleOuter
contains CGRect \c possibleInner.
@group CGRect
@param possibleOuter the CGRect to test if <code>possibleInner</code> is inside of
@param possibleInner the CGRect to test if it fits inside <code>possibleOuter</code>.
@return BOOL <code>YES</code> if <code>possibleInner</code> fits inside <code>possibleOuter</code>.
@param possibleOuter the CGRect to test if \c possibleInner is inside of
@param possibleInner the CGRect to test if it fits inside \c possibleOuter.
@return BOOL \c YES if \c possibleInner fits inside \c possibleOuter.
*/
function CPRectContainsRect(lhsRect, rhsRect)
{
@@ -241,11 +241,11 @@ function CPRectContainsRect(lhsRect, rhsRect)
/*!
Tests whether the two CGPoints are equal to each other by comparing their
<code>x</code> and <code>y</code> members.
\c x and \c y members.
@group @CGPoint
@param lhsPoint the first CGPoint to check
@param rhsPoint the second CGPoint to check
@return BOOL <code>YES</code> if the two points have the same x's, and the same y's.
@return BOOL \c YES if the two points have the same x's, and the same y's.
*/
function CPPointEqualToPoint(lhsPoint, rhsPoint)
{
@@ -257,7 +257,7 @@ function CPPointEqualToPoint(lhsPoint, rhsPoint)
@group CGRect
@param lhsRect the first CGRect to compare
@param rhsRect the second CGRect to compare
@return BOOL <code>YES</code> if the two rectangles have the same origin and size. <code>NO</code>, otherwise.
@return BOOL \c YES if the two rectangles have the same origin and size. \c NO, otherwise.
*/
function CPRectEqualToRect(lhsRect, rhsRect)
{
@@ -346,11 +346,11 @@ function CPRectGetWidth(aRect)
}
/*!
Returns <code>YES</code> if the two rectangles intersect
Returns \c YES if the two rectangles intersect
@group CGRect
@param lhsRect the first CGRect
@param rhsRect the second CGRect
@return BOOL <code>YES</code> if the two rectangles have any common spaces, and <code>NO</code>, otherwise.
@return BOOL \c YES if the two rectangles have any common spaces, and \c NO, otherwise.
*/
function CPRectIntersectsRect(lhsRect, rhsRect)
{
@@ -358,11 +358,11 @@ function CPRectIntersectsRect(lhsRect, rhsRect)
}
/*!
Returns <code>YES</code> if the CGRect has no area.
Returns \c YES if the CGRect has no area.
The test is performed by checking if the width and height are both zero.
@group CGRect
@param aRect the CGRect to test
@return BOOL <code>YES</code> if the CGRect has no area, and <code>NO</code>, otherwise.
@return BOOL \c YES if the CGRect has no area, and \c NO, otherwise.
*/
function CPRectIsEmpty(aRect)
{
@@ -370,10 +370,10 @@ function CPRectIsEmpty(aRect)
}
/*!
Returns <code>YES</code> if the CGRect has no area.
Returns \c YES if the CGRect has no area.
The test is performed by checking if the width and height are both zero.
@group CGRect
@return BOOL <code>YES</code> if the CGRect has no area, and <code>NO</code>, otherwise.
@return BOOL \c YES if the CGRect has no area, and \c NO, otherwise.
*/
function CPRectIsNull(aRect)
{
@@ -381,11 +381,11 @@ function CPRectIsNull(aRect)
}
/*!
Returns <code>YES</code> if the two CGSizes are identical.
Returns \c YES if the two CGSizes are identical.
@group CGSize
@param lhsSize the first CGSize to compare
@param rhsSize the second CGSize to compare
@return BOOL <code>YES</code> if the two sizes are identical. <code>NO</code>, otherwise.
@return BOOL \c YES if the two sizes are identical. \c NO, otherwise.
*/
function CPSizeEqualToSize(lhsSize, rhsSize)
{
@@ -454,7 +454,7 @@ function CPSizeFromString(aString)
/*!
Returns a CGRect created from a string.
@group CGRect
@param aString a string in the form generated by <code>CPStringFromRect</code>
@param aString a string in the form generated by \c CPStringFromRect
@return CGRect the rectangle created from the string
*/
function CPRectFromString(aString)
@@ -477,7 +477,7 @@ function CPPointFromEvent(anEvent)
/*!
Returns a zero sized CGSize.
@group CGSize
@return CGSize a size object with zeros for <code>width</code> and <code>height</code>
@return CGSize a size object with zeros for \c width and \c height
*/
function CPSizeMakeZero()
{
@@ -485,7 +485,7 @@ function CPSizeMakeZero()
}
/*!
Returns a rectangle at origin <code>(0,0)</code> and size of <code>(0,0)</code>.
Returns a rectangle at origin \c (0,0) and size of \c (0,0).
@group CGRect
@return CGRect a zeroed out CGRect
*/
@@ -495,9 +495,9 @@ function CPRectMakeZero()
}
/*!
Returns a point located at <code>(0, 0)</code>.
Returns a point located at \c (0, 0).
@group CGPoint
@return CGPoint a point located at <code>(0, 0)</code>
@return CGPoint a point located at \c (0, 0)
*/
function CPPointMakeZero()
{
+12 -16
View File
@@ -49,15 +49,6 @@ function CPImageInBundle(aFilename, aSize, aBundle)
return [[CPImage alloc] initWithContentsOfFile:[aBundle pathForResource:aFilename]];
}
@implementation CPBundle (CPImageAdditions)
- (CPString)pathForResource:(CPString)aFilename
{
return [self resourcePath] + '/' + aFilename;
}
@end
/*!
@ingroup appkit
@class CPImage
@@ -90,15 +81,20 @@ function CPImageInBundle(aFilename, aSize, aBundle)
Image _image;
}
- (id)init
{
return [self initByReferencingFile:@"" size:CGSizeMake(-1, -1)];
}
/*!
Initializes the image, by associating it with a filename. The image
denoted in <code>aFilename</code> is not actually loaded. It will
denoted in \c aFilename is not actually loaded. It will
be loaded once needed.
@param aFilename the file containing the image
@param aSize the image's size
@return the initialized image
*/
- (CPImage)initByReferencingFile:(CPString)aFilename size:(CGSize)aSize
- (id)initByReferencingFile:(CPString)aFilename size:(CGSize)aSize
{
self = [super init];
@@ -118,7 +114,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
@param aSize the size of the image
@return the initialized image.
*/
- (CPImage)initWithContentsOfFile:(CPString)aFilename size:(CGSize)aSize
- (id)initWithContentsOfFile:(CPString)aFilename size:(CGSize)aSize
{
self = [self initByReferencingFile:aFilename size:aSize];
@@ -134,9 +130,9 @@ function CPImageInBundle(aFilename, aSize, aBundle)
@param aFilename the file name of the image
@return the initialized image
*/
- (CPImage)initWithContentsOfFile:(CPString)aFilename
- (id)initWithContentsOfFile:(CPString)aFilename
{
self = [self initByReferencingFile:aFilename size: CGSizeMake(-1, -1)];
self = [self initByReferencingFile:aFilename size:CGSizeMake(-1, -1)];
if (self)
[self load];
@@ -187,9 +183,9 @@ function CPImageInBundle(aFilename, aSize, aBundle)
}
/*!
Returns <code>YES</code> if the image data has already been loaded.
Returns the load status, which will be CPImageLoadStatusCompleted if the image data has already been loaded.
*/
- (BOOL)loadStatus
- (unsigned)loadStatus
{
return _loadStatus;
}
+60 -5
View File
@@ -70,7 +70,9 @@ var LEFT_SHADOW_INSET = 3.0,
BOOL _hasShadow;
CPView _shadowView;
BOOL _isEditable;
CGRect _imageRect;
}
@@ -85,7 +87,13 @@ var LEFT_SHADOW_INSET = 3.0,
_DOMImageElement.style.position = "absolute";
_DOMImageElement.style.left = "0px";
_DOMImageElement.style.top = "0px";
if ([CPPlatform supportsDragAndDrop])
{
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement);
_DOMImageElement.style.visibility = "hidden";
@@ -159,8 +167,8 @@ var LEFT_SHADOW_INSET = 3.0,
}
/*!
Returns <code>YES</code> if the image view draws with
a drop shadow. The default is <code>NO</code>.
Returns \c YES if the image view draws with
a drop shadow. The default is \c NO.
*/
- (BOOL)hasShadow
{
@@ -339,11 +347,47 @@ var LEFT_SHADOW_INSET = 3.0,
[[self nextResponder] mouseDown:anEvent];
}
- (void)setEditable:(BOOL)shouldBeEditable
{
if (_isEditable === shouldBeEditable)
return;
_isEditable = shouldBeEditable;
if (_isEditable)
[self registerForDraggedTypes:[CPImagesPboardType]];
else
{
var draggedTypes = [self registeredDraggedTypes];
[self unregisterDraggedTypes];
[draggedTypes removeObjectIdenticalTo:CPImagesPboardType];
[self registerForDraggedTypes:draggedTypes];
}
}
- (BOOL)isEditable
{
return _isEditable;
}
- (void)performDragOperation:(CPDraggingInfo)aSender
{
var images = [CPKeyedUnarchiver unarchiveObjectWithData:[[aSender draggingPasteboard] dataForType:CPImagesPboardType]];
if ([images count])
[self setImage:images[0]];
}
@end
var CPImageViewImageKey = @"CPImageViewImageKey",
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey";
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
@implementation CPImageView (CPCoding)
@@ -360,6 +404,11 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
_DOMImageElement.style.left = "0px";
_DOMImageElement.style.top = "0px";
_DOMImageElement.style.visibility = "hidden";
if ([CPPlatform supportsDragAndDrop])
{
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
#endif
self = [super initWithCoder:aCoder];
@@ -372,6 +421,9 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey] || NO)
[self setEditable:YES];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -402,6 +454,9 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
_subviews = actualSubviews;
[aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
if (_isEditable)
[aCoder encodeBool:_isEditable forKey:CPImageViewIsEditableKey];
}
@end
+204 -127
View File
@@ -30,6 +30,7 @@
@import "CPMenuItem.j"
@import "CPPanel.j"
#include "CoreGraphics/CGGeometry.h"
#include "Platform/Platform.h"
@@ -60,6 +61,7 @@ var _CPMenuBarVisible = NO,
CPMenu _supermenu;
CPString _title;
CPString _name;
CPMutableArray _items;
CPMenu _attachedMenu;
@@ -91,7 +93,10 @@ var _CPMenuBarVisible = NO,
return;
_CPMenuBarVisible = menuBarShouldBeVisible;
if ([CPPlatform supportsNativeMainMenu])
return;
if (menuBarShouldBeVisible)
{
if (!_CPMenuBarSharedWindow)
@@ -119,7 +124,7 @@ var _CPMenuBarVisible = NO,
// FIXME: There must be a better way to do this.
#if PLATFORM(DOM)
[[CPDOMWindowBridge sharedDOMWindowBridge] _bridgeResizeEvent:nil];
[[CPPlatformWindow primaryPlatformWindow] resizeEvent:nil];
#endif
}
@@ -267,13 +272,13 @@ var _CPMenuBarVisible = NO,
- (void)insertItem:(CPMenuItem)aMenuItem atIndex:(unsigned)anIndex
{
var menu = [aMenuItem menu];
if (menu)
if (menu != self)
if (menu !== self)
[CPException raise:CPInternalInconsistencyException reason:@"Attempted to insert item into menu that was already in another menu."];
else
return;
[aMenuItem setMenu:self];
[_items insertObject:aMenuItem atIndex:anIndex];
@@ -369,9 +374,9 @@ var _CPMenuBarVisible = NO,
/*!
Returns the menu item with the specified tag
@param the tag of the desired menu item
@return the menu item or <code>nil</code> if a match was not found
@return the menu item or \c nil if a match was not found
*/
- (CPMenuItem)menuWithTag:(int)aTag
- (CPMenuItem)itemWithTag:(int)aTag
{
var index = [self indexOfItemWithTag:aTag];
@@ -384,9 +389,9 @@ var _CPMenuBarVisible = NO,
/*!
Returns the menu item with the specified title.
@param aTitle the title of the menu item
@return the menu item or <code>nil</code> if a match was not found
@return the menu item or \c nil if a match was not found
*/
- (CPMenuItem)menuWithTitle:(CPString)aTitle
- (CPMenuItem)itemWithTitle:(CPString)aTitle
{
var index = [self indexOfItemWithTitle:aTitle];
@@ -551,7 +556,7 @@ var _CPMenuBarVisible = NO,
}
/*!
Returns the attaced menu, or <code>nil</code> if there isn't one.
Returns the attaced menu, or \c nil if there isn't one.
*/
- (CPMenu)attachedMenu
{
@@ -559,7 +564,7 @@ var _CPMenuBarVisible = NO,
}
/*!
Returns <code>YES</code> if the menu is attached to another menu.
Returns \c YES if the menu is attached to another menu.
*/
- (BOOL)isAttached
{
@@ -575,7 +580,7 @@ var _CPMenuBarVisible = NO,
}
/*!
Returns the super menu or <code>nil</code> if there is none.
Returns the super menu or \c nil if there is none.
*/
- (CPMenu)supermenu
{
@@ -592,8 +597,8 @@ var _CPMenuBarVisible = NO,
}
/*!
If there are two instances of this menu visible, return <code>NO</code>.
Otherwise, return <code>YES</code> if we are a detached menu and visible.
If there are two instances of this menu visible, return \c NO.
Otherwise, return \c YES if we are a detached menu and visible.
*/
- (BOOL)isTornOff
{
@@ -603,7 +608,7 @@ var _CPMenuBarVisible = NO,
// Enabling and Disabling Menu Items
/*!
Sets whether the menu automatically enables menu items.
@param aFlag <code>YES</code> sets the menu to automatically enable items.
@param aFlag \c YES sets the menu to automatically enable items.
*/
- (void)setAutoenablesItems:(BOOL)aFlag
{
@@ -611,7 +616,7 @@ var _CPMenuBarVisible = NO,
}
/*!
Returns <code>YES</code> if the menu auto enables items.
Returns \c YES if the menu auto enables items.
*/
- (BOOL)autoenablesItems
{
@@ -672,7 +677,7 @@ var _CPMenuBarVisible = NO,
[menuWindow setDelegate:self];
[menuWindow setBackgroundStyle:isForMenuBar ? _CPMenuWindowMenuBarBackgroundStyle : _CPMenuWindowPopUpBackgroundStyle];
[menuWindow setFrameOrigin:[[anEvent window] convertBaseToBridge:[anEvent locationInWindow]]];
[menuWindow setFrameOrigin:[[anEvent window] convertBaseToGlobal:[anEvent locationInWindow]]];
[menuWindow orderFront:self];
[menuWindow beginTrackingWithEvent:anEvent sessionDelegate:self didEndSelector:@selector(_menuWindowDidFinishTracking:highlightedItem:)];
@@ -686,17 +691,12 @@ var _CPMenuBarVisible = NO,
if([aMenuItem isEnabled])
[CPApp sendAction:[aMenuItem action] to:[aMenuItem target] from:aMenuItem];
var delegate = [menu delegate];
if ([delegate respondsToSelector:@selector(menuDidClose:)])
[delegate menuDidClose:menu];
}
// Managing Display of State Column
/*!
Sets whether to show the state column
@param shouldShowStateColumn <code>YES</code> shows the state column
@param shouldShowStateColumn \c YES shows the state column
*/
- (void)setShowsStateColumn:(BOOL)shouldShowStateColumn
{
@@ -704,7 +704,7 @@ var _CPMenuBarVisible = NO,
}
/*!
Returns <code>YES</code> if the menu shows the state column
Returns \c YES if the menu shows the state column
*/
- (BOOL)showsStateColumn
{
@@ -714,7 +714,7 @@ var _CPMenuBarVisible = NO,
// Handling Highlighting
/*!
Returns the currently highlighted menu item.
@return the highlighted menu item or <code>nil</code> if no item is currently highlighted
@return the highlighted menu item or \c nil if no item is currently highlighted
*/
- (CPMenuItem)highlightedItem
{
@@ -739,7 +739,21 @@ var _CPMenuBarVisible = NO,
*/
- (void)cancelTracking
{
[_menuWindow cancelTracking];
[[CPRunLoop currentRunLoop] performSelector:@selector(_fireCancelTrackingEvent) target:self argument:nil order:0 modes:[CPDefaultRunLoopMode]];
}
- (void)_fireCancelTrackingEvent
{
[CPApp sendEvent:[CPEvent
otherEventWithType:CPAppKitDefined
location:_CGPointMakeZero()
modifierFlags:0
timestamp:0
windowNumber:0
context:0
subtype:0
data1:0
data2:0]];
}
/* @ignore */
@@ -750,9 +764,9 @@ var _CPMenuBarVisible = NO,
/*!
Initiates the action of the menu item that
has a keyboard shortcut equivalent to <code>anEvent</code>
has a keyboard shortcut equivalent to \c anEvent
@param anEvent the keyboard event
@return <code>YES</code> if it was handled.
@return \c YES if it was handled.
*/
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
{
@@ -767,8 +781,8 @@ var _CPMenuBarVisible = NO,
for(; index < count; ++index)
{
var item = _items[index],
modifierMask = [item keyEquivalentModifierMask];
modifierMask = [item keyEquivalentModifierMask] | ([item keyEquivalent] === [[item keyEquivalent] uppercaseString] ? CPShiftKeyMask : 0);
if ((modifierFlags & (CPShiftKeyMask | CPAlternateKeyMask | CPCommandKeyMask | CPControlKeyMask)) == modifierMask &&
[characters caseInsensitiveCompare:[item keyEquivalent]] == CPOrderedSame)
{
@@ -826,10 +840,52 @@ var _CPMenuBarVisible = NO,
[[_items[_highlightedIndex] _menuItemView] highlight:YES];
}
- (void)_setMenuName:(CPString)aName
{
if (_name === aName)
return;
_name = aName;
if (_name === @"CPMainMenu")
[CPApp setMainMenu:self];
}
- (CPString)_menuName
{
return _name;
}
- (void)awakeFromCib
{
if (_name === @"_CPMainMenu")
{
[self _setMenuName:@"CPMainMenu"];
[CPMenu setMenuBarVisible:YES];
}
}
- (void)_menuWithName:(CPString)aName
{
if (aName === _name)
return self;
for (var i = 0, count = [_items count]; i < count; i++)
{
var menu = [[_items[i] submenu] _menuWithName:aName];
if (menu)
return menu;
}
return nil;
}
@end
var CPMenuTitleKey = @"CPMenuTitleKey",
CPMenuNameKey = @"CPMenuNameKey",
CPMenuItemsKey = @"CPMenuItemsKey",
CPMenuShowsStateColumnKey = @"CPMenuShowsStateColumnKey";
@@ -849,6 +905,8 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
_title = [aCoder decodeObjectForKey:CPMenuTitleKey];
_items = [aCoder decodeObjectForKey:CPMenuItemsKey];
[self _setMenuName:[aCoder decodeObjectForKey:CPMenuNameKey]];
_showsStateColumn = ![aCoder containsValueForKey:CPMenuShowsStateColumnKey] || [aCoder decodeBoolForKey:CPMenuShowsStateColumnKey];
}
@@ -862,6 +920,10 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_title forKey:CPMenuTitleKey];
if (_name)
[aCoder encodeObject:_name forKey:CPMenuNameKey];
[aCoder encodeObject:_items forKey:CPMenuItemsKey];
if (!_showsStateColumn)
@@ -897,7 +959,7 @@ var STICKY_TIME_INTERVAL = 500,
*/
@implementation _CPMenuWindow : CPWindow
{
_CPMenuView _menuView;
_CPMenuView _menuView;
CPClipView _menuClipView;
CPView _lastMouseOverMenuView;
@@ -909,7 +971,7 @@ var STICKY_TIME_INTERVAL = 500,
CPTimeInterval _startTime;
int _scrollingState;
CGPoint _lastScreenLocation;
CGPoint _lastGlobalLocation;
BOOL _isShowingTopScrollIndicator;
BOOL _isShowingBottomScrollIndicator;
@@ -926,10 +988,10 @@ var STICKY_TIME_INTERVAL = 500,
menuWindow = _CPMenuWindowPool.pop();
else
menuWindow = [[_CPMenuWindow alloc] init];
[menuWindow setFont:aFont];
[menuWindow setMenu:aMenu];
return menuWindow;
}
@@ -960,6 +1022,7 @@ var STICKY_TIME_INTERVAL = 500,
{
[self setLevel:CPPopUpMenuWindowLevel];
[self setHasShadow:YES];
[self setShadowStyle:CPMenuWindowShadowStyle];
[self setAcceptsMouseMovedEvents:YES];
_unconstrainedFrame = CGRectMakeZero();
@@ -986,6 +1049,8 @@ var STICKY_TIME_INTERVAL = 500,
[_moreBelowView setFrameSize:[_CPMenuWindowMoreBelowImage size]];
[contentView addSubview:_moreBelowView];
[self setShadowStyle:CPWindowShadowStyleMenu];
}
return self;
@@ -1001,7 +1066,7 @@ var STICKY_TIME_INTERVAL = 500,
[_menuView setFont:aFont];
}
- (void)setBackgroundStyle:(_CPMenuWindowBackgroundStyle)aBackgroundStyle
+ (CPColor)backgroundColorForBackgroundStyle:(_CPMenuWindowBackgroundStyle)aBackgroundStyle
{
var color = _CPMenuWindowBackgroundColors[aBackgroundStyle];
@@ -1043,8 +1108,13 @@ var STICKY_TIME_INTERVAL = 500,
_CPMenuWindowBackgroundColors[aBackgroundStyle] = color;
}
[self setBackgroundColor:color];
return color;
}
- (void)setBackgroundStyle:(_CPMenuWindowBackgroundStyle)aBackgroundStyle
{
[self setBackgroundColor:[[self class] backgroundColorForBackgroundStyle:aBackgroundStyle]];
}
- (void)setMenu:(CPMenu)aMenu
@@ -1081,35 +1151,42 @@ var STICKY_TIME_INTERVAL = 500,
- (void)constrainToScreen
{
// FIXME: There are integral window issues with platform windows.
// FIXME: This gets called far too often.
_unconstrainedFrame = CGRectMakeCopy([self frame]);
var screenBounds = CGRectInset([[CPDOMWindowBridge sharedDOMWindowBridge] contentBounds], 5.0, 5.0),
constrainedFrame = CGRectIntersection(_unconstrainedFrame, screenBounds),
menuViewOrigin = [self convertBaseToBridge:CGPointMake(LEFT_MARGIN, TOP_MARGIN)];
var isBrowser = [CPPlatform isBrowser],
visibleFrame = CGRectInset(isBrowser ? [[self platformWindow] contentBounds] : [[self screen] visibleFrame], 5.0, 5.0),
constrainedFrame = CGRectIntersection(_unconstrainedFrame, visibleFrame);
// We don't want to simply intersect the visible frame and the unconstrained frame.
// We should be allowing as much of the width to fit as possible (pushing back and forward).
constrainedFrame.origin.x = CGRectGetMinX(_unconstrainedFrame);
constrainedFrame.size.width = CGRectGetWidth(_unconstrainedFrame);
if (CGRectGetWidth(constrainedFrame) > CGRectGetWidth(screenBounds))
constrainedFrame.size.width = CGRectGetWidth(screenBounds);
if (CGRectGetMaxX(constrainedFrame) > CGRectGetMaxX(screenBounds))
constrainedFrame.origin.x -= CGRectGetMaxX(constrainedFrame) - CGRectGetMaxX(screenBounds);
if (CGRectGetMinX(constrainedFrame) < CGRectGetMinX(screenBounds))
constrainedFrame.origin.x = CGRectGetMinX(screenBounds);
if (CGRectGetWidth(constrainedFrame) > CGRectGetWidth(visibleFrame))
constrainedFrame.size.width = CGRectGetWidth(visibleFrame);
if (CGRectGetMaxX(constrainedFrame) > CGRectGetMaxX(visibleFrame))
constrainedFrame.origin.x -= CGRectGetMaxX(constrainedFrame) - CGRectGetMaxX(visibleFrame);
if (CGRectGetMinX(constrainedFrame) < CGRectGetMinX(visibleFrame))
constrainedFrame.origin.x = CGRectGetMinX(visibleFrame);
// This needs to happen before changing the frame.
var menuViewOrigin = [self convertBaseToGlobal:CGPointMake(LEFT_MARGIN, TOP_MARGIN)];
[super setFrame:constrainedFrame];
var topMargin = TOP_MARGIN,
var moreAbove = menuViewOrigin.y < CGRectGetMinY(constrainedFrame) + TOP_MARGIN,
moreBelow = menuViewOrigin.y + CGRectGetHeight([_menuView frame]) > CGRectGetMaxY(constrainedFrame) - BOTTOM_MARGIN,
topMargin = TOP_MARGIN,
bottomMargin = BOTTOM_MARGIN,
contentView = [self contentView],
bounds = [contentView bounds];
var moreAbove = menuViewOrigin.y < CGRectGetMinY(constrainedFrame) + TOP_MARGIN,
moreBelow = menuViewOrigin.y + CGRectGetHeight([_menuView frame]) > CGRectGetMaxY(constrainedFrame) - BOTTOM_MARGIN;
if (moreAbove)
{
topMargin += SCROLL_INDICATOR_HEIGHT;
@@ -1118,9 +1195,9 @@ var STICKY_TIME_INTERVAL = 500,
[_moreAboveView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(frame)) / 2.0, (TOP_MARGIN + SCROLL_INDICATOR_HEIGHT - CGRectGetHeight(frame)) / 2.0)];
}
[_moreAboveView setHidden:!moreAbove];
if (moreBelow)
{
bottomMargin += SCROLL_INDICATOR_HEIGHT;
@@ -1129,22 +1206,19 @@ var STICKY_TIME_INTERVAL = 500,
}
[_moreBelowView setHidden:!moreBelow];
var clipFrame = CGRectMake(LEFT_MARGIN, topMargin, CGRectGetWidth(constrainedFrame) - LEFT_MARGIN - RIGHT_MARGIN, CGRectGetHeight(constrainedFrame) - topMargin - bottomMargin)
[_menuClipView setFrame:clipFrame];
[_menuView setFrameSize:CGSizeMake(CGRectGetWidth(clipFrame), CGRectGetHeight([_menuView frame]))];
[_menuView scrollPoint:CGPointMake(0.0, [self convertBaseToBridge:clipFrame.origin].y - menuViewOrigin.y)];
}
- (void)cancelTracking
{
_trackingCanceled = YES;
[_menuView scrollPoint:CGPointMake(0.0, [self convertBaseToGlobal:clipFrame.origin].y - menuViewOrigin.y)];
}
- (void)beginTrackingWithEvent:(CPEvent)anEvent sessionDelegate:(id)aSessionDelegate didEndSelector:(SEL)aDidEndSelector
{
CPApp._activeMenu = [_menuView menu];
_startTime = [anEvent timestamp];//new Date();
_scrollingState = _CPMenuWindowScrollingStateNone;
_trackingCanceled = NO;
@@ -1158,12 +1232,46 @@ var STICKY_TIME_INTERVAL = 500,
- (void)trackEvent:(CPEvent)anEvent
{
var type = [anEvent type],
theWindow = [anEvent window],
screenLocation = theWindow ? [theWindow convertBaseToBridge:[anEvent locationInWindow]] : [anEvent locationInWindow];
if (type == CPPeriodic)
menu = [_menuView menu];
// Close Menu Event.
if (type === CPAppKitDefined)
{
var constrainedBounds = CGRectInset([[CPDOMWindowBridge sharedDOMWindowBridge] contentBounds], 5.0, 5.0);
// Stop all periodic events at this point.
[CPEvent stopPeriodicEvents];
var highlightedItem = [[_menuView menu] highlightedItem];
[menu _highlightItemAtIndex:CPNotFound];
[self orderOut:self];
var delegate = [menu delegate];
if ([delegate respondsToSelector:@selector(menuDidClose:)])
[delegate menuDidClose:menu];
if (_sessionDelegate && _didEndSelector)
objj_msgSend(_sessionDelegate, _didEndSelector, self, highlightedItem);
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidEndTrackingNotification
object:menu];
// Clear these now so its faster next time around.
[_menuView setMenu:nil];
CPApp._activeMenu = nil;
return;
}
var theWindow = [anEvent window],
globalLocation = theWindow ? [theWindow convertBaseToGlobal:[anEvent locationInWindow]] : [anEvent locationInWindow];
if (type === CPPeriodic)
{
var constrainedBounds = CGRectInset([CPPlatform isBrowser] ? [[self platformWindow] contentBounds] : [[self screen] visibleFrame], 5.0, 5.0);
if (_scrollingState == _CPMenuWindowScrollingStateUp)
{
@@ -1177,13 +1285,12 @@ var STICKY_TIME_INTERVAL = 500,
[self setFrame:_unconstrainedFrame];
[self constrainToScreen];
screenLocation = _lastScreenLocation;
globalLocation = _lastGlobalLocation;
}
_lastScreenLocation = screenLocation;
_lastGlobalLocation = globalLocation;
var menu = [_menuView menu],
menuLocation = [self convertBridgeToBase:screenLocation],
var menuLocation = [self convertGlobalToBase:globalLocation],
activeItemIndex = [_menuView itemIndexAtPoint:[_menuView convertPoint:menuLocation fromView:nil]],
mouseOverMenuView = [[menu itemAtIndex:activeItemIndex] view];
@@ -1214,7 +1321,7 @@ var STICKY_TIME_INTERVAL = 500,
_lastMouseOverMenuView = nil;
}
[menu _highlightItemAtIndex:[_menuView itemIndexAtPoint:[_menuView convertPoint:[self convertBridgeToBase:screenLocation] fromView:nil]]];
[menu _highlightItemAtIndex:[_menuView itemIndexAtPoint:[_menuView convertPoint:[self convertGlobalToBase:globalLocation] fromView:nil]]];
if (type == CPMouseMoved || type == CPLeftMouseDragged || type == CPLeftMouseDown)
{
@@ -1224,11 +1331,11 @@ var STICKY_TIME_INTERVAL = 500,
_scrollingState = _CPMenuWindowScrollingStateNone;
// If we're at or above of the top scroll indicator...
if (screenLocation.y < CGRectGetMinY(frame) + TOP_MARGIN + SCROLL_INDICATOR_HEIGHT)
if (globalLocation.y < CGRectGetMinY(frame) + TOP_MARGIN + SCROLL_INDICATOR_HEIGHT)
_scrollingState = _CPMenuWindowScrollingStateUp;
// If we're at or below the bottom scroll indicator...
else if (screenLocation.y > CGRectGetMaxY(frame) - BOTTOM_MARGIN - SCROLL_INDICATOR_HEIGHT)
else if (globalLocation.y > CGRectGetMaxY(frame) - BOTTOM_MARGIN - SCROLL_INDICATOR_HEIGHT)
_scrollingState = _CPMenuWindowScrollingStateDown;
if (_scrollingState != oldScrollingState)
@@ -1239,47 +1346,11 @@ var STICKY_TIME_INTERVAL = 500,
else if (oldScrollingState == _CPMenuWindowScrollingStateNone)
[CPEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.04];
}
else if (type == CPLeftMouseUp && ([anEvent timestamp] - _startTime > STICKY_TIME_INTERVAL))
{
// Stop these if they're still goin'.
if (_scrollingState != _CPMenuWindowScrollingStateNone)
[CPEvent stopPeriodicEvents];
[self cancelTracking];
}
[menu cancelTracking];
}
if (_trackingCanceled)
{
// Stop all periodic events at this point.
[CPEvent stopPeriodicEvents];
var highlightedItem = [[_menuView menu] highlightedItem];
[menu _highlightItemAtIndex:CPNotFound];
// Clear these now so its faster next time around.
[_menuView setMenu:nil];
[self orderOut:self];
if (_sessionDelegate && _didEndSelector)
objj_msgSend(_sessionDelegate, _didEndSelector, self, highlightedItem);
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidEndTrackingNotification
object:menu];
var delegate = [menu delegate];
if ([delegate respondsToSelector:@selector(menuDidClose:)])
[delegate menuDidClose:menu];
return;
}
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPAppKitDefinedMask untilDate:nil inMode:nil dequeue:YES];
}
@end
@@ -1452,10 +1523,13 @@ var _CPMenuBarWindowBackgroundColor = nil,
- (id)init
{
var bridgeWidth = CGRectGetWidth([[CPDOMWindowBridge sharedDOMWindowBridge] contentBounds]);
self = [super initWithContentRect:CGRectMake(0.0, 0.0, bridgeWidth, MENUBAR_HEIGHT) styleMask:CPBorderlessWindowMask];
// This only shows up in browser land, so don't bother calculating metrics in desktop.
var contentRect = [[CPPlatformWindow primaryPlatformWindow] contentBounds];
contentRect.size.height = MENUBAR_HEIGHT;
self = [super initWithContentRect:contentRect styleMask:CPBorderlessWindowMask];
if (self)
{
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/39-dont-allow-windows-to-go-above-menubar
@@ -1735,7 +1809,7 @@ var _CPMenuBarWindowBackgroundColor = nil,
return frame;
}
- (CPView)menuItemAtPoint:(CGPoint)aPoint
- (CPMenuItem)menuItemAtPoint:(CGPoint)aPoint
{
var items = [_menu itemArray],
count = items.length;
@@ -1927,11 +2001,14 @@ var _CPMenuBarWindowBackgroundColor = nil,
}
}
- (void)setFrameSize:(CGSize)aSize
- (void)setFrame:(CGRect)aRect display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
{
[super setFrameSize:aSize];
[self tile];
var size = [self frame].size;
[super setFrame:aRect display:shouldDisplay animate:shouldAnimate];
if (!_CGSizeEqualToSize(size, aRect.size))
[self tile];
}
@end
+56 -49
View File
@@ -38,6 +38,8 @@
*/
@implementation CPMenuItem : CPObject
{
BOOL _isSeparator;
CPString _title;
//CPAttributedString _attributedTitle;
@@ -76,6 +78,11 @@
_CPMenuItemView _menuItemView;
}
- (id)init
{
return [self initWithTitle:@"" action:nil keyEquivalent:nil];
}
/*!
Initializes the menu item with a title, action, and keyboard equivalent.
@param aTitle the menu item's title
@@ -89,6 +96,8 @@
if (self)
{
_isSeparator = NO;
_title = aTitle;
_action = anAction;
@@ -109,7 +118,7 @@
// Enabling a Menu Item
/*!
Sets whether the menu item is enabled or not
@param isEnabled <code>YES</code> enables the item. <code>NO</code> disables it.
@param isEnabled \c YES enables the item. \c NO disables it.
*/
- (void)setEnabled:(BOOL)isEnabled
{
@@ -124,7 +133,7 @@
}
/*!
Returns <code>YES</code> if the item is enabled.
Returns \c YES if the item is enabled.
*/
- (BOOL)isEnabled
{
@@ -134,7 +143,7 @@
// Managing Hidden Status
/*!
Sets whether the item should be hidden. A hidden item can not be triggered by keyboard shortcuts.
@param isHidden <code>YES</code> hides the item. <code>NO</code> reveals it.
@param isHidden \c YES hides the item. \c NO reveals it.
*/
- (void)setHidden:(BOOL)isHidden
{
@@ -147,7 +156,7 @@
}
/*!
Returns <code>YES</code> if the item is hidden.
Returns \c YES if the item is hidden.
*/
- (BOOL)isHidden
{
@@ -155,7 +164,7 @@
}
/*!
Returns <code>YES</code> if the item is hidden or if one of it's supermenus is hidden.
Returns \c YES if the item is hidden or if one of it's supermenus is hidden.
*/
- (BOOL)isHiddenOrHasHiddenAncestor
{
@@ -457,7 +466,7 @@ CPOffState
}
/*!
Returns the submenu of the item. <code>nil</code> if there is no submenu.
Returns the submenu of the item. \c nil if there is no submenu.
*/
- (CPMenu)submenu
{
@@ -465,7 +474,7 @@ CPOffState
}
/*!
Returns <code>YES</code> if the menu item has a submenu.
Returns \c YES if the menu item has a submenu.
*/
- (BOOL)hasSubmenu
{
@@ -479,15 +488,19 @@ CPOffState
*/
+ (CPMenuItem)separatorItem
{
return [[_CPMenuItemSeparator alloc] init];
var separatorItem = [[self alloc] initWithTitle:@"" action:nil keyEquivalent:nil];
separatorItem._isSeparator = YES;
return separatorItem;
}
/*!
Returns <code>YES</code> if the menu item is a separator.
Returns \c YES if the menu item is a separator.
*/
- (BOOL)isSeparatorItem
{
return NO;
return _isSeparator;
}
// Managing the Owning Menu
@@ -605,7 +618,7 @@ CPControlKeyMask
/*!
Sets whether this item is an alternate for the previous menu item.
@param isAlternate <code>YES</code> denotes that this menu item is an alternate
@param isAlternate \c YES denotes that this menu item is an alternate
*/
- (void)setAlternate:(BOOL)isAlternate
{
@@ -613,7 +626,7 @@ CPControlKeyMask
}
/*!
Returns <code>YES</code> if the menu item is an alternate for the previous item.
Returns \c YES if the menu item is an alternate for the previous item.
*/
- (BOOL)isAlternate
{
@@ -709,7 +722,7 @@ CPControlKeyMask
// Getting Highlighted Status
/*!
Returns <code>YES</code> if the menu item is highlighted.
Returns \c YES if the menu item is highlighted.
*/
- (BOOL)isHighlighted
{
@@ -731,46 +744,29 @@ CPControlKeyMask
@end
/* @ignore */
@implementation _CPMenuItemSeparator : CPMenuItem
{
}
var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
- (id)init
{
self = [super initWithTitle:@"" action:nil keyEquivalent:nil];
if (self)
[self setEnabled:NO];
return self;
}
CPMenuItemTitleKey = @"CPMenuItemTitleKey",
CPMenuItemTargetKey = @"CPMenuItemTargetKey",
CPMenuItemActionKey = @"CPMenuItemActionKey",
- (BOOL)isSeparatorItem
{
return YES;
}
CPMenuItemIsEnabledKey = @"CPMenuItemIsEnabledKey",
CPMenuItemIsHiddenKey = @"CPMenuItemIsHiddenKey",
@end
CPMenuItemTagKey = @"CPMenuItemTagKey",
CPMenuItemStateKey = @"CPMenuItemStateKey",
var CPMenuItemTitleKey = @"CPMenuItemTitleKey",
CPMenuItemTargetKey = @"CPMenuItemTargetKey",
CPMenuItemActionKey = @"CPMenuItemActionKey",
CPMenuItemImageKey = @"CPMenuItemImageKey",
CPMenuItemAlternateImageKey = @"CPMenuItemAlternateImageKey",
CPMenuItemIsEnabledKey = @"CPMenuItemIsEnabledKey",
CPMenuItemIsHiddenKey = @"CPMenuItemIsHiddenKey",
CPMenuItemSubmenuKey = @"CPMenuItemSubmenuKey",
CPMenuItemMenuKey = @"CPMenuItemMenuKey",
CPMenuItemTagKey = @"CPMenuItemTagKey",
CPMenuItemStateKey = @"CPMenuItemStateKey",
CPMenuItemKeyEquivalentKey = @"CPMenuItemKeyEquivalentKey",
CPMenuItemKeyEquivalentModifierMaskKey = @"CPMenuItemKeyEquivalentModifierMaskKey",
CPMenuItemImageKey = @"CPMenuItemImageKey",
CPMenuItemAlternateImageKey = @"CPMenuItemAlternateImageKey",
CPMenuItemSubmenuKey = @"CPMenuItemSubmenuKey",
CPMenuItemMenuKey = @"CPMenuItemMenuKey",
CPMenuItemRepresentedObjectKey = @"CPMenuItemRepresentedObjectKey",
CPMenuItemViewKey = @"CPMenuItemViewKey";
CPMenuItemRepresentedObjectKey = @"CPMenuItemRepresentedObjectKey",
CPMenuItemViewKey = @"CPMenuItemViewKey";
#define DEFAULT_VALUE(aKey, aDefaultValue) [aCoder containsValueForKey:(aKey)] ? [aCoder decodeObjectForKey:(aKey)] : (aDefaultValue)
#define ENCODE_IFNOT(aKey, aValue, aDefaultValue) if ((aValue) !== (aDefaultValue)) [aCoder encodeObject:(aValue) forKey:(aKey)];
@@ -787,6 +783,8 @@ var CPMenuItemTitleKey = @"CPMenuItemTitleKey",
if (self)
{
_isSeparator = [aCoder containsValueForKey:CPMenuItemIsSeparatorKey] && [aCoder decodeBoolForKey:CPMenuItemIsSeparatorKey];
_title = [aCoder decodeObjectForKey:CPMenuItemTitleKey];
// _font;
@@ -809,8 +807,8 @@ var CPMenuItemTitleKey = @"CPMenuItemTitleKey",
_submenu = DEFAULT_VALUE(CPMenuItemSubmenuKey, nil);
_menu = DEFAULT_VALUE(CPMenuItemMenuKey, nil);
// CPString _keyEquivalent;
// unsigned _keyEquivalentModifierMask;
_keyEquivalent = [aCoder decodeObjectForKey:CPMenuItemKeyEquivalentKey] || @"";
_keyEquivalentModifierMask = [aCoder decodeObjectForKey:CPMenuItemKeyEquivalentModifierMaskKey] || 0;
// int _mnemonicLocation;
@@ -832,6 +830,9 @@ var CPMenuItemTitleKey = @"CPMenuItemTitleKey",
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
if (_isSeparator)
[aCoder encodeBool:_isSeparator forKey:CPMenuItemIsSeparatorKey];
[aCoder encodeObject:_title forKey:CPMenuItemTitleKey];
[aCoder encodeObject:_target forKey:CPMenuItemTargetKey];
@@ -849,6 +850,12 @@ var CPMenuItemTitleKey = @"CPMenuItemTitleKey",
ENCODE_IFNOT(CPMenuItemSubmenuKey, _submenu, nil);
ENCODE_IFNOT(CPMenuItemMenuKey, _menu, nil);
if (_keyEquivalent && _keyEquivalent.length)
[aCoder encodeObject:_keyEquivalent forKey:CPMenuItemKeyEquivalentKey];
if (_keyEquivalentModifierMask)
[aCoder encodeObject:_keyEquivalentModifierMask forKey:CPMenuItemKeyEquivalentModifierMaskKey];
ENCODE_IFNOT(CPMenuItemRepresentedObjectKey, _representedObject, nil);
ENCODE_IFNOT(CPMenuItemViewKey, _view, nil);
}
@@ -1195,7 +1202,7 @@ var _CPMenuItemSelectionColor = nil,
- (CPColor)textColor
{
return [_menuItem isEnabled] ? (_textColor ? _textColor : [CPColor colorWithCalibratedRed:70.0 / 255.0 green:69.0 / 255.0 blue:69.0 / 255.0 alpha:1.0]) : [CPColor darkGrayColor];
return [_menuItem isEnabled] ? (_textColor ? _textColor : [CPColor colorWithCalibratedRed:70.0 / 255.0 green:69.0 / 255.0 blue:69.0 / 255.0 alpha:1.0]) : [CPColor lightGrayColor];
}
- (void)setTextShadowColor:(CPColor)aColor
+46
View File
@@ -0,0 +1,46 @@
@import <AppKit/CPPanel.j>
@implementation CPOpenPanel : CPPanel
{
BOOL _canChooseFiles @accessors(property=canChooseFiles);
BOOL _canChooseDirectories @accessors(property=canChooseDirectories);
BOOL _allowsMultipleSelection @accessors(property=allowsMultipleSelection);
CPURL _directoryURL @accessors(property=directoryURL);
CPArray _URLs;
}
+ (id)openPanel
{
return [[CPOpenPanel alloc] init];
}
- (CPInteger)runModal
{
if (typeof window["cpOpenPanel"] === "function")
{
// FIXME: Is this correct???
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
var options = { directoryURL: [self directoryURL],
canChooseFiles: [self canChooseFiles],
canChooseDirectories: [self canChooseDirectories],
allowsMultipleSelection: [self allowsMultipleSelection] };
var result = window.cpOpenPanel(options);
_URLs = result.URLs;
return result.button;
}
throw "-runModal is unimplemented.";
}
- (CPArray)URLs
{
return _URLs;
}
@end
+798 -57
View File
@@ -3,7 +3,7 @@
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,93 +20,834 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPTableColumn.j"
@import "CPTableView.j"
/*!
@ignore
This class is a subclass of CPTableView which provides the user with a way to display
tree structured data in an outline format. It is particularly useful for displaying hierarchical data
such as a class inheritance tree or any other set of relationships.
*/
#include "CoreGraphics/CGGeometry.h"
CPOutlineViewColumnDidMoveNotification = @"CPOutlineViewColumnDidMoveNotification";
CPOutlineViewColumnDidResizeNotification = @"CPOutlineViewColumnDidResizeNotification";
CPOutlineViewItemDidCollapseNotification = @"CPOutlineViewItemDidCollapseNotification";
CPOutlineViewItemDidExpandNotification = @"CPOutlineViewItemDidExpandNotification";
CPOutlineViewItemWillCollapseNotification = @"CPOutlineViewItemWillCollapseNotification";
CPOutlineViewItemWillExpandNotification = @"CPOutlineViewItemWillExpandNotification";
CPOutlineViewSelectionDidChangeNotification = @"CPOutlineViewSelectionDidChangeNotification";
CPOutlineViewSelectionIsChangingNotification = @"CPOutlineViewSelectionIsChangingNotification";
var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ = 1 << 1,
CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_ = 1 << 2,
CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_ = 1 << 3,
CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_ = 1 << 4,
CPOutlineViewDataSource_outlineView_validateDrop_proposedRow_proposedDropOperation_ = 1 << 5,
CPOutlineViewDataSource_outlineView_namesOfPromisedFilesDroppedAtDestination_forDraggedItems_ = 1 << 6,
CPOutlineViewDataSource_outlineView_itemForPersistentObject_ = 1 << 7,
CPOutlineViewDataSource_outlineView_persistentObjectForItem_ = 1 << 8,
CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_ = 1 << 9,
CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 10;
@implementation CPOutlineView : CPTableView
{
id _outlineDataSource;
CPArray _itemsByRow;
id _outlineViewDataSource;
id _outlineViewDelegate;
CPTableColumn _outlineTableColumn;
float _indentationPerLevel;
BOOL _indentationMarkerFollowsDataView;
CPInteger _implementedOutlineViewDataSourceMethods;
Object _rootItemInfo;
CPMutableArray _itemsForRows;
Object _itemInfosForItems;
CPControl _disclosureControlPrototype;
CPArray _disclosureControlsForRows;
CPData _disclosureControlData;
CPArray _disclosureControlQueue;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
[super setDataSource:self];
_itemsByRow = [[CPArray alloc] init];
// The root item has weight "0", thus represents the weight solely of its descendants.
_rootItemInfo = { isExpanded:YES, isExpandable:NO, level:-1, row:-1, children:[], weight:0 };
_itemsForRows = [];
_itemInfosForItems = { };
_disclosureControlsForRows = [];
[self setIndentationPerLevel:16.0];
[self setIndentationMarkerFollowsDataView:YES];
[super setDataSource:[[_CPOutlineViewTableViewDataSource alloc] initWithOutlineView:self]];
[self setDisclosureControlPrototype:[[CPDisclosureButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)]];
}
return self;
}
/*!
@ignore
Sets the outline's data source. The data source must implement the following methods:
<pre>
- (id)outlineView:(CPOutlineView)outlineView child:(int)index ofItem:(id)item
- (BOOL)outlineView:(CPOutlineView)outlineView isItemExpandable:(id)item
- (int)outlineView:(CPOutlineView)outlineView numberOfChildrenOfItem:(id)item
- (id)outlineView:(CPOutlineView)outlineView objectValueForTableColumn:(CPTableColumn)tableColumn byItem:(id)item
</pre>
@param aDataSource the outline's data source
@throws CPInternalInconsistencyException if the data source does not implement all the required methods
*/
- (void)setDataSource:(id)aDataSource
{
if (![aDataSource respondsToSelector:@selector(outlineView:child:ofItem)])
[CPException raise:CPInternalInconsistencyException reason:"Data source must implement 'outlineView:child:ofItem'"];
if (![aDataSource respondsToSelector:@selector(outlineView:isItemExpandable)])
[CPException raise:CPInternalInconsistencyException reason:"Data source must implement 'outlineView:isItemExpandable'"];
if (![aDataSource respondsToSelector:@selector(outlineView:numberOfChildrenOfItem)])
[CPException raise:CPInternalInconsistencyException reason:"Data source must implement 'outlineView:numberOfChildrenOfItem'"];
if (![aDataSource respondsToSelector:@selector(outlineView:objectValueForTableColumn:byItem)])
[CPException raise:CPInternalInconsistencyException reason:"Data source must implement 'outlineView:objectValueForTableColumn:byItem'"];
if (_outlineViewDataSource === aDataSource)
return;
_outlineDataSource = aDataSource;
if (![aDataSource respondsToSelector:@selector(outlineView:child:ofItem:)])
[CPException raise:CPInternalInconsistencyException reason:"Data source must implement 'outlineView:child:ofItem:'"];
if (![aDataSource respondsToSelector:@selector(outlineView:isItemExpandable:)])
[CPException raise:CPInternalInconsistencyException reason:"Data source must implement 'outlineView:isItemExpandable:'"];
if (![aDataSource respondsToSelector:@selector(outlineView:numberOfChildrenOfItem:)])
[CPException raise:CPInternalInconsistencyException reason:"Data source must implement 'outlineView:numberOfChildrenOfItem:'"];
if (![aDataSource respondsToSelector:@selector(outlineView:objectValueForTableColumn:byItem:)])
[CPException raise:CPInternalInconsistencyException reason:"Data source must implement 'outlineView:objectValueForTableColumn:byItem:'"];
_outlineViewDataSource = aDataSource;
_implementedOutlineViewDataSourceMethods = 0;
if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:setObjectValue:forTableColumn:byItem:)])
_implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_;
if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:shouldDeferDisplayingChildrenOfItem:)])
_implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_;
if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:acceptDrop:item:childIndex:)])
_implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_;
if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:validateDrop:proposedItem:proposedChildIndex:)])
_implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_;
if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:validateDrop:proposedRow:proposedDropOperation:)])
_implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_validateDrop_proposedRow_proposedDropOperation_;
if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:namesOfPromisedFilesDroppedAtDestination:forDraggedItems:)])
_implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_namesOfPromisedFilesDroppedAtDestination_forDraggedItems_;
if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:itemForPersistentObject:)])
_implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_itemForPersistentObject_;
if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:persistentObjectForItem:)])
_implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_persistentObjectForItem_;
if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:writeItems:toPasteboard:)])
_implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_;
if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:sortDescriptorsDidChange:)])
_implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_;
[self reloadData];
}
/* @ignore */
- (id)dataSource
{
return _outlineViewDataSource;
}
- (BOOL)isExpandable:(id)anItem
{
if (!anItem)
return YES;
var itemInfo = _itemInfosForItems[[anItem UID]];
if (!itemInfo)
return NO;
return itemInfo.isExpandable;
}
- (void)isItemExpanded:(id)anItem
{
if (!anItem)
return YES;
var itemInfo = _itemInfosForItems[[anItem UID]];
if (!itemInfo)
return NO;
return itemInfo.isExpanded;
}
- (void)expandItem:(id)anItem
{
if (!anItem)
return;
var itemInfo = _itemInfosForItems[[anItem UID]];
if (!itemInfo)
return;
if (itemInfo.isExpanded)
return;
itemInfo.isExpanded = YES;
[self reloadItem:anItem reloadChildren:YES];
}
- (void)collapseItem:(id)anItem
{
if (!anItem)
return;
var itemInfo = _itemInfosForItems[[anItem UID]];
if (!itemInfo)
return;
if (!itemInfo.isExpanded)
return;
itemInfo.isExpanded = NO;
[self reloadItem:anItem reloadChildren:YES];
}
- (void)reloadItem:(id)anItem
{
[self reloadItem:anItem reloadChildren:NO];
}
- (void)reloadItem:(id)anItem reloadChildren:(BOOL)shouldReloadChildren
{
if (!!shouldReloadChildren || !anItem)
_loadItemInfoForItem(self, anItem);
else
_reloadItem(self, anItem);
[super reloadData];
}
- (id)itemAtRow:(CPInteger)aRow
{
return _itemsForRows[aRow] || nil;
}
- (CPInteger)rowForItem:(id)aItem
{
if (!anItem)
return _rootItemInfo.row;
var itemInfo = _itemInfosForItems[[anItem UID]];
if (!itemInfo)
return CPNotFound;
return itemInfo.row;
}
- (void)setOutlineTableColumn:(CPTableColumn)aTableColumn
{
if (_outlineTableColumn === aTableColumn)
return;
_outlineTableColumn = aTableColumn;
// FIXME: efficiency.
[self reloadData];
}
- (CPTableColumn)outlineTableColumn
{
return _outlineTableColumn;
}
- (CPInteger)levelForItem:(id)anItem
{
if (!anItem)
return _rootItemInfo.level;
var itemInfo = _itemInfosForItems[[anItem UID]];
if (!itemInfo)
return CPNotFound;
return itemInfo.level;
}
- (CPInteger)levelForRow:(CPInteger)aRow
{
return [self levelForItem:[self itemAtRow:aRow]];
}
- (void)setIndentationPerLevel:(float)anIndentationWidth
{
if (_indentationPerLevel === anIndentationWidth)
return;
_indentationPerLevel = anIndentationWidth;
// FIXME: efficiency!!!!
[self reloadData];
}
- (float)indentationPerLevel
{
return _indentationPerLevel;
}
- (void)setIndentationMarkerFollowsDataView:(BOOL)indentationMarkerShouldFollowDataView
{
if (_indentationMarkerFollowsDataView === indentationMarkerShouldFollowDataView)
return;
_indentationMarkerFollowsDataView = indentationMarkerShouldFollowDataView;
// !!!!
[self reloadData];
}
- (BOOL)indentationMarkerFollowsDataView
{
return _indentationMarkerFollowsDataView;
}
- (id)parentForItem:(id)anItem
{
if (!anItem)
return nil;
var itemInfo = _itemInfosForItems[[anItem UID]];
if (!itemInfo)
return nil;
return itemInfo.parent;
}
- (CGRect)frameOfOutlineDataViewAtColumn:(CPInteger)aColumn row:(CPInteger)aRow
{
var frame = [super frameOfDataViewAtColumn:aColumn row:aRow],
indentationWidth = ([self levelForRow:aRow] + 1) * [self indentationPerLevel];
frame.origin.x += indentationWidth;
frame.size.width -= indentationWidth;
return frame;
}
- (void)setDelegate:(id)aDelegate
{
if (_outlineViewDelegate === aDelegate)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_outlineViewDelegate)
{
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewColumnDidMoveNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidResize:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewColumnDidResizeNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewSelectionDidChange:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewSelectionDidChangeNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewSelectionIsChanging:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewSelectionIsChangingNotification
object:self];
}
_outlineViewDelegate = aDelegate;/*
_implementedDelegateMethods = 0;
if ([_outlineViewDelegate respondsToSelector:@selector(selectionShouldChangeInTableView:)])
_implementedDelegateMethods |= CPTableViewDelegate_selectionShouldChangeInTableView_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:dataViewForTableColumn:row:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_dataViewForTableColumn_row_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:didClickTableColumn:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_didClickTableColumn_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:didDragTableColumn:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_didDragTableColumn_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:heightOfRow:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_heightOfRow_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:isGroupRow:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_isGroupRow_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:mouseDownInHeaderOfTableColumn:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_mouseDownInHeaderOfTableColumn_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:nextTypeSelectMatchFromRow:toRow:forString:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_nextTypeSelectMatchFromRow_toRow_forString_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:selectionIndexesForProposedSelection:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_selectionIndexesForProposedSelection_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldEditTableColumn:row:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldEditTableColumn_row_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldSelectRow:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldSelectRow_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldSelectTableColumn:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldSelectTableColumn_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldShowViewExpansionForTableColumn:row:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldShowViewExpansionForTableColumn_row_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldTrackView:forTableColumn:row:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldTrackView_forTableColumn_row_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldTypeSelectForEvent:withCurrentSearchString:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldTypeSelectForEvent_withCurrentSearchString_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:toolTipForView:rect:tableColumn:row:mouseLocation:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_toolTipForView_rect_tableColumn_row_mouseLocation_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:typeSelectStringForTableColumn:row:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_typeSelectStringForTableColumn_row_;
if ([_outlineViewDelegate respondsToSelector:@selector(tableView:willDisplayView:forTableColumn:row:)])
_implementedDelegateMethods |= CPTableViewDelegate_tableView_willDisplayView_forTableColumn_row_;
*/
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)])
[defaultCenter
addObserver:_outlineViewDelegate
selector:@selector(outlineViewColumnDidMove:)
name:CPOutlineViewColumnDidMoveNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidResize:)])
[defaultCenter
addObserver:_outlineViewDelegate
selector:@selector(outlineViewColumnDidMove:)
name:CPOutlineViewColumnDidResizeNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewSelectionDidChange:)])
[defaultCenter
addObserver:_outlineViewDelegate
selector:@selector(outlineViewSelectionDidChange:)
name:CPOutlineViewSelectionDidChangeNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewSelectionIsChanging:)])
[defaultCenter
addObserver:_outlineViewDelegate
selector:@selector(outlineViewSelectionIsChanging:)
name:CPOutlineViewSelectionIsChangingNotification
object:self];
}
- (id)delegate
{
return _outlineViewDelegate;
}
- (void)setDisclosureControlPrototype:(CPControl)aControl
{
_disclosureControlPrototype = aControl;
_disclosureControlData = nil;
_disclosureControlQueue = [];
// fIXME: reall?
[self reloadData];
}
- (void)reloadData
{
_numberOfVisibleItems = [_outlineDataSource outlineView:self numberOfChildrenOfItem:nil];
_numberOfRows = _numberOfVisibleItems;
var i = 0;
for (; i < _numberOfVisibleItems; ++i)
_itemsByRow[i] = [_outlineDataSource outlineView:self child:i ofItem:nil];
[self loadTableCellsInRect:[self bounds]];
[self reloadItem:nil reloadChildren:YES];
}
- (CGRect)frameOfDataViewAtColumn:(CPInteger)aColumn row:(CPInteger)aRow
{
var tableColumn = [self tableColumns][aColumn];
if (tableColumn === _outlineTableColumn)
return [self frameOfOutlineDataViewAtColumn:aColumn row:aRow];
return [super frameOfDataViewAtColumn:aColumn row:aRow];
}
- (void)_loadDataViewsInRows:(CPIndexSet)rows columns:(CPIndexSet)columns
{
[super _loadDataViewsInRows:rows columns:columns];
var outlineColumn = [[self tableColumns] indexOfObjectIdenticalTo:[self outlineTableColumn]];
if (![columns containsIndex:outlineColumn])
return;
var rowArray = [];
[rows getIndexes:rowArray maxCount:-1 inIndexRange:nil];
var rowIndex = 0,
rowsCount = rowArray.length;
for (; rowIndex < rowsCount; ++rowIndex)
{
var row = rowArray[rowIndex],
item = _itemsForRows[row],
isExpandable = [self isExpandable:item];
if (!isExpandable)
continue;
var control = [self _dequeueDisclosureControl],
frame = [control frame],
dataViewFrame = [self frameOfDataViewAtColumn:outlineColumn row:row];
frame.origin.x = _indentationMarkerFollowsDataView ? _CGRectGetMinX(dataViewFrame) - _CGRectGetWidth(frame) : 0.0;
frame.origin.y = _CGRectGetMinY(dataViewFrame);
frame.size.height = _CGRectGetHeight(dataViewFrame);
// FIXME: center instead?
//frame.origin.y = _CGRectGetMidY(dataViewFrame) - _CGRectGetHeight(frame) / 2.0;
_disclosureControlsForRows[row] = control;
[control setState:[self isItemExpanded:item] ? CPOnState : CPOffState];
[control setFrame:frame];
[self addSubview:control];
}
}
- (void)_unloadDataViewsInRows:(CPIndexSet)rows columns:(CPIndexSet)columns
{
[super _unloadDataViewsInRows:rows columns:columns];
var outlineColumn = [[self tableColumns] indexOfObjectIdenticalTo:[self outlineTableColumn]];
if (![columns containsIndex:outlineColumn])
return;
var rowArray = [];
[rows getIndexes:rowArray maxCount:-1 inIndexRange:nil];
var rowIndex = 0,
rowsCount = rowArray.length;
for (; rowIndex < rowsCount; ++rowIndex)
{
var row = rowArray[rowIndex],
control = _disclosureControlsForRows[row];
if (!control)
continue;
[control removeFromSuperview];
[self _enqueueDisclosureControl:control];
_disclosureControlsForRows[row] = nil;
}
}
- (void)_toggleFromDisclosureControl:(CPControl)aControl
{
var controlFrame = [aControl frame],
item = [self itemAtRow:[self rowAtPoint:_CGPointMake(_CGRectGetMinX(controlFrame), _CGRectGetMidY(controlFrame))]];
if ([self isItemExpanded:item])
[self collapseItem:item];
else
[self expandItem:item];
}
- (void)_enqueueDisclosureControl:(CPControl)aControl
{
_disclosureControlQueue.push(aControl);
}
- (CPControl)_dequeueDisclosureControl
{
if (_disclosureControlQueue.length)
return _disclosureControlQueue.pop();
if (!_disclosureControlData)
if (!_disclosureControlPrototype)
return nil;
else
_disclosureControlData = [CPKeyedArchiver archivedDataWithRootObject:_disclosureControlPrototype];
var disclosureControl = [CPKeyedUnarchiver unarchiveObjectWithData:_disclosureControlData];
[disclosureControl setTarget:self];
[disclosureControl setAction:@selector(_toggleFromDisclosureControl:)];
return disclosureControl;
}
- (void)_noteSelectionIsChanging
{
[[CPNotificationCenter defaultCenter]
postNotificationName:CPOutlineViewSelectionIsChangingNotification
object:self
userInfo:nil];
}
- (void)_noteSelectionDidChange
{
[[CPNotificationCenter defaultCenter]
postNotificationName:CPOutlineViewSelectionDidChangeNotification
object:self
userInfo:nil];
}
@end
/* @ignore */
@implementation CPOutlineView (CPTableDataSource)
/*
FIXME
*/
/* @ignore */
- (void)numberOfRowsInTableView:(CPTableView)aTableView
var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem)
{
return _numberOfVisibleItems;
if (!anItem)
return;
// Get the existing info if it exists.
var itemInfosForItems = anOutlineView._itemInfosForItems,
dataSource = anOutlineView._outlineViewDataSource,
itemUID = [anItem UID],
itemInfo = itemInfosForItems[itemUID];
// If we're not in the tree, then just bail.
if (!itemInfo)
return [];
// See if the item itself can be swapped out.
var parent = itemInfo.parent,
parentItemInfo = parent ? itemInfosForItems[[parent UID]] : anOutlineView._rootItemInfo,
parentChildren = parentItemInfo.children,
index = [parentChildren indexOfObjectIdenticalTo:anItem],
newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent];
if (anItem !== newItem)
{
itemInfosForItems[[anItem UID]] = nil;
itemInfosForItems[[newItem UID]] = itemInfo;
parentChildren[index] = newItem;
anOutlineView._itemsForRows[itemInfo.row] = newItem;
}
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem];
itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded;
}
/* @ignore */
- (void)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aTableColumn row:(int)aRowIndex
var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate)
{
return [_outlineDataSource outlineView:self objectValueForTableColumn:aTableColumn byItem:_itemsByRow[aRowIndex]];
var itemInfosForItems = anOutlineView._itemInfosForItems,
dataSource = anOutlineView._outlineViewDataSource;
if (!anItem)
var itemInfo = anOutlineView._rootItemInfo;
else
{
// Get the existing info if it exists.
var itemUID = [anItem UID],
itemInfo = itemInfosForItems[itemUID];
// If we're not in the tree, then just bail.
if (!itemInfo)
return [];
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem];
// If we were previously expanded, but now no longer expandable, "de-expand".
// NOTE: we are *not* collapsing, thus no notification is posted.
if (!itemInfo.isExpandable && itemInfo.isExpanded)
{
itemInfo.isExpanded = NO;
itemInfo.children = [];
}
}
// The root item does not count as a descendant.
var weight = itemInfo.weight,
descendants = anItem ? [anItem] : [];
if (itemInfo.isExpanded && (!(anOutlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) ||
![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem]))
{
var index = 0,
count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem],
level = itemInfo.level + 1;
itemInfo.children = [];
for (; index < count; ++index)
{
var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem],
childItemInfo = itemInfosForItems[[childItem UID]];
if (!childItemInfo)
{
childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 };
itemInfosForItems[[childItem UID]] = childItemInfo;
}
itemInfo.children[index] = childItem;
var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES);
childItemInfo.parent = anItem;
childItemInfo.level = level;
descendants = descendants.concat(childDescendants);
}
}
itemInfo.weight = descendants.length;
if (!isIntermediate)
{
// row = -1 is the root item, so just go to row 0 since it is ignored.
var index = MAX(itemInfo.row, 0),
itemsForRows = anOutlineView._itemsForRows;
descendants.unshift(index, weight);
itemsForRows.splice.apply(itemsForRows, descendants);
var count = itemsForRows.length;
for (; index < count; ++index)
itemInfosForItems[[itemsForRows[index] UID]].row = index;
var deltaWeight = itemInfo.weight - weight;
if (deltaWeight !== 0)
{
var parent = itemInfo.parent;
while (parent)
{
var parentItemInfo = itemInfosForItems[[parent UID]];
parentItemInfo.weight += deltaWeight;
parent = parentItemInfo.parent;
}
if (anItem)
anOutlineView._rootItemInfo.weight += deltaWeight;
}
}
return descendants;
}
@end
@implementation _CPOutlineViewTableViewDataSource : CPObject
{
CPObject _outlineView;
}
- (id)initWithOutlineView:(CPOutlineView)anOutlineView
{
self = [super init];
if (self)
_outlineView = anOutlineView;
return self;
}
- (CPInteger)numberOfRowsInTableView:(CPTableView)anOutlineView
{
return _outlineView._itemsForRows.length;
}
- (id)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRow
{
return [_outlineView._outlineViewDataSource outlineView:_outlineView objectValueForTableColumn:aTableColumn byItem:_outlineView._itemsForRows[aRow]];
}
@end
@implementation _CPOutlineViewTableViewDelegate : CPObject
{
CPOutlineView _outlineView;
}
- (id)initWithOutlineView:(CPOutlineView)anOutlineView
{
self = [super init];
if (self)
_outlineView = anOutlineView;
return self;
}
@end
@implementation CPDisclosureButton : CPButton
{
float _angle;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
[self setBordered:NO];
return self;
}
- (void)setState:(CPState)aState
{
[super setState:aState];
if ([self state] === CPOnState)
_angle = 0.0;
else
_angle = -PI_2;
}
- (void)drawRect:(CGRect)aRect
{
var bounds = [self bounds],
context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextBeginPath(context);
CGContextTranslateCTM(context, _CGRectGetWidth(bounds) / 2.0, _CGRectGetHeight(bounds) / 2.0);
CGContextRotateCTM(context, _angle);
CGContextTranslateCTM(context, -_CGRectGetWidth(bounds) / 2.0, -_CGRectGetHeight(bounds) / 2.0);
// Center, but crisp.
CGContextTranslateCTM(context, FLOOR((_CGRectGetWidth(bounds) - 9.0) / 2.0), FLOOR((_CGRectGetHeight(bounds) - 8.0) / 2.0));
CGContextMoveToPoint(context, 0.0, 0.0);
CGContextAddLineToPoint(context, 9.0, 0.0);
CGContextAddLineToPoint(context, 4.5, 8.0);
CGContextAddLineToPoint(context, 0.0, 0.0);
CGContextClosePath(context);
CGContextSetFillColor(context, ([self themeState] & CPThemeState("highlighted")) ? [CPColor blackColor] : [CPColor grayColor]);
CGContextFillPath(context);
}
@end
+13 -6
View File
@@ -46,6 +46,13 @@ CPCancelButton = 0;
<li>A panel can be made to work even when there's an attention panel on-screen. This permits actions within the panel to affect the attention panel.</li>
</ul>
*/
/*
@global
@class CPWindow
*/
CPDocModalWindowMask = 1 << 6;
@implementation CPPanel : CPWindow
{
BOOL _becomesKeyOnlyIfNeeded;
@@ -53,7 +60,7 @@ CPCancelButton = 0;
}
/*!
Returns <code>YES</code> if the receiver is a floating panel (like a palette).
Returns \c YES if the receiver is a floating panel (like a palette).
*/
- (BOOL)isFloatingPanel
{
@@ -61,8 +68,8 @@ CPCancelButton = 0;
}
/*!
Sets the receiver to be a floating panel. <code>YES</code>
makes the window a floating panel. <code>NO</code> makes it a normal window.
Sets the receiver to be a floating panel. \c YES
makes the window a floating panel. \c NO makes it a normal window.
@param isFloatingPanel specifies whether to make it floating
*/
- (void)setFloatingPanel:(BOOL)isFloatingPanel
@@ -71,8 +78,8 @@ CPCancelButton = 0;
}
/*!
Returns <code>YES</code> if the window only becomes key
if needed. <code>NO</code> means it behaves just like other windows.
Returns \c YES if the window only becomes key
if needed. \c NO means it behaves just like other windows.
*/
- (BOOL)becomesKeyOnlyIfNeeded
{
@@ -81,7 +88,7 @@ CPCancelButton = 0;
/*!
Sets whether the the window becomes key only if needed.
@param shouldBecomeKeyOnlyIfNeeded <code>YES</code> makes the window become key only if needed
@param shouldBecomeKeyOnlyIfNeeded \c YES makes the window become key only if needed
*/
- (void)setBecomesKeyOnlyIfNeeded:(BOOL)shouldBecomeKeyOnlyIfNeeded
{
+82 -8
View File
@@ -25,6 +25,8 @@
@import <Foundation/CPDictionary.j>
@import <Foundation/CPPropertyListSerialization.j>
#include "Platform/Platform.h"
CPGeneralPboard = @"CPGeneralPboard";
CPFontPboard = @"CPFontPboard";
@@ -38,8 +40,13 @@ CPFontPboardType = @"CPFontPboardType";
CPHTMLPboardType = @"CPHTMLPboardType";
CPStringPboardType = @"CPStringPboardType";
CPURLPboardType = @"CPURLPboardType";
CPImagesPboardType = @"CPImagesPboardType";
CPVideosPboardType = @"CPVideosPboardType";
// Deprecated
CPImagePboardType = @"CPImagePboardType";
var CPPasteboards = nil;
/*!
@@ -168,7 +175,7 @@ var CPPasteboards = nil;
Sets the pasteboard data for the specified type
@param aData the data
@param aType the data type being set
@return <code>YES</code> if the data was successfully written to the pasteboard
@return \c YES if the data was successfully written to the pasteboard
*/
- (BOOL)setData:(CPData)aData forType:(CPString)aType
{
@@ -181,7 +188,7 @@ var CPPasteboards = nil;
Writes the specified property list as data for the specified type
@param aPropertyList the property list to write
@param aType the data type
@return <code>YES</code> if the property list was successfully written to the pasteboard
@return \c YES if the property list was successfully written to the pasteboard
*/
- (BOOL)setPropertyList:(id)aPropertyList forType:(CPString)aType
{
@@ -192,7 +199,7 @@ var CPPasteboards = nil;
Sets the specified string as data for the specified type
@param aString the string to write
@param aType the data type
@return <code>YES</code> if the string was successfully written to the pasteboard
@return \c YES if the string was successfully written to the pasteboard
*/
- (void)setString:(CPString)aString forType:(CPString)aType
{
@@ -204,11 +211,11 @@ var CPPasteboards = nil;
Checks the pasteboard's types for a match with the types listen in the specified array. The array should
be ordered by the requestor's most preferred data type first.
@param anArray an array of requested types ordered by preference
@return the highest match with the pasteboard's supported types or <code>nil</code> if no match was found
@return the highest match with the pasteboard's supported types or \c nil if no match was found
*/
- (CPString)availableTypeFromArray:(CPArray)anArray
{
return [_types firstObjectCommonWithArray:anArray];
return [[self types] firstObjectCommonWithArray:anArray];
}
/*!
@@ -231,7 +238,7 @@ var CPPasteboards = nil;
/*!
Returns the pasteboard data for the specified data type
@param aType the requested data type
@return the requested data or <code>nil</code> if the data doesn't exist
@return the requested data or \c nil if the data doesn't exist
*/
- (CPData)dataForType:(CPString)aType
{
@@ -257,7 +264,7 @@ var CPPasteboards = nil;
/*!
Returns the property list for the specified data type
@param aType the requested data type
@return the property list or <code>nil</code> if the list was not found
@return the property list or \c nil if the list was not found
*/
- (id)propertyListForType:(CPString)aType
{
@@ -272,7 +279,7 @@ var CPPasteboards = nil;
/*!
Returns the string for the specified data type
@param aType the requested data type
@return the string or <code>nil</code> if the string was not found
@return the string or \c nil if the string was not found
*/
- (CPString)stringForType:(CPString)aType
{
@@ -299,3 +306,70 @@ var CPPasteboards = nil;
}
@end
#if PLATFORM(DOM)
var DOMDataTransferPasteboard = nil;
@implementation _CPDOMDataTransferPasteboard : CPPasteboard
{
DataTransfer _dataTransfer;
}
+ (_CPDOMDataTransferPasteboard)DOMDataTransferPasteboard
{
if (!DOMDataTransferPasteboard)
DOMDataTransferPasteboard = [[_CPDOMDataTransferPasteboard alloc] init];
return DOMDataTransferPasteboard;
}
- (void)_setDataTransfer:(DataTransfer)aDataTransfer
{
_dataTransfer = aDataTransfer;
}
- (void)_setPasteboard:(CPPasteboard)aPasteboard
{
_dataTransfer.clearData();
var types = [aPasteboard types],
count = types.length;
while (count--)
{
var type = types[count];
if (type === CPStringPboardType)
_dataTransfer.setData(type, [aPasteboard stringForType:type]);
else
_dataTransfer.setData(type, [[aPasteboard dataForType:type] string]);
}
}
- (CPArray)types
{
return Array.prototype.slice.apply(_dataTransfer.types);
}
- (CPData)dataForType:(CPString)aType
{
var dataString = _dataTransfer.getData(aType);
if (aType === CPStringPboardType)
return [CPData dataFromPropertyList:dataString format:kCFPropertyList280NorthFormat_v1_0 errorDescription:0];
return [CPData dataWithString:dataString];
}
- (id)propertyListForType:(CPString)aType
{
if (aType === CPStringPboardType)
return _dataTransfer.getData(aType);
return [CPPropertyListSerialization propertyListFromData:[self dataForType:aType] format:CPPropertyListUnknownFormat errorDescription:nil];
}
@end
#endif
+20 -18
View File
@@ -54,7 +54,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
Initializes the pop-up button to the specified size.
@param aFrame the size for the button
@param shouldPullDown <code>YES</code> makes this a pull-down menu, <code>NO</code> makes it a pop-up menu.
@param shouldPullDown \c YES makes this a pull-down menu, \c NO makes it a pop-up menu.
@return the initialized pop-up button
*/
- (id)initWithFrame:(CGRect)aFrame pullsDown:(BOOL)shouldPullDown
@@ -87,8 +87,8 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
Specifies whether the object is a pull-down or a pop-up menu.
@param shouldPullDown <code>YES</code> makes the pop-up button
a pull-down menu. <code>NO</code> makes it a pop-up menu.
@param shouldPullDown \c YES makes the pop-up button
a pull-down menu. \c NO makes it a pop-up menu.
*/
- (void)setPullsDown:(BOOL)shouldPullDown
{
@@ -111,7 +111,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
}
/*!
Returns <code>YES</code> if the button is a pull-down menu. <code>NO</code> if the button is a pop-up menu.
Returns \c YES if the button is a pull-down menu. \c NO if the button is a pop-up menu.
*/
- (BOOL)pullsDown
{
@@ -200,18 +200,18 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
// Getting the User's Selection
/*!
Returns the selected item or <code>nil</code> if no item is selected.
Returns the selected item or \c nil if no item is selected.
*/
- (CPMenuItem)selectedItem
{
if (_selectedIndex < 0)
if (_selectedIndex < 0 || _selectedIndex > [self numberOfItems] - 1)
return nil;
return [_menu itemAtIndex:_selectedIndex];
}
/*!
Returns the title of the selected item or <code>nil</code> if no item is selected.
Returns the title of the selected item or \c nil if no item is selected.
*/
- (CPString)titleOfSelectedItem
{
@@ -372,7 +372,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
}
/*!
Returns the item at the specified index or <code>nil</code> if the item does not exist.
Returns the item at the specified index or \c nil if the item does not exist.
@param anIndex the index of the item to obtain
*/
- (CPMenuItem)itemAtIndex:(unsigned)anIndex
@@ -381,7 +381,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
}
/*!
Returns the title of the item at the specified index or <code>nil</code> if no item exists.
Returns the title of the item at the specified index or \c nil if no item exists.
@param anIndex the index of the item
*/
- (CPString)itemTitleAtIndex:(unsigned)anIndex
@@ -628,13 +628,15 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
var numberOfItems = [self numberOfItems];
if (numberOfItems <= _selectedIndex)
if (numberOfItems <= _selectedIndex && numberOfItems > 0)
[self selectItemAtIndex:numberOfItems - 1];
else
[self synchronizeTitleAndSelectedItem];
}
- (void)mouseDown:(CPEvent)anEvent
{
if (![self isEnabled])
if (![self isEnabled] || ![self numberOfItems])
return;
[self highlight:YES];
@@ -648,7 +650,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
// Pull Down Menus show up directly below their buttons.
if ([self pullsDown])
var menuOrigin = [theWindow convertBaseToBridge:[self convertPoint:CGPointMake(0.0, CGRectGetMaxY([self bounds])) toView:nil]];
var menuOrigin = [theWindow convertBaseToGlobal:[self convertPoint:CGPointMake(0.0, CGRectGetMaxY([self bounds])) toView:nil]];
// Pop Up Menus attempt to show up "on top" of the selected item.
else
@@ -659,21 +661,21 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
// 2. Move LEFT by whatever indentation we have (offsetWidths, aka, window margin, item margin, etc).
// 3. MOVE UP by the difference in sizes of the content and menu item, this will only work if the content is vertically centered.
var contentRect = [self convertRect:[self contentRectForBounds:[self bounds]] toView:nil],
menuOrigin = [theWindow convertBaseToBridge:contentRect.origin],
menuOrigin = [theWindow convertBaseToGlobal:contentRect.origin],
menuItemRect = [menuWindow rectForItemAtIndex:_selectedIndex];
menuOrigin.x -= CGRectGetMinX(menuItemRect) + [menuWindow overlapOffsetWidth] + [[[menu itemAtIndex:_selectedIndex] _menuItemView] overlapOffsetWidth];
menuOrigin.y -= CGRectGetMinY(menuItemRect) + (CGRectGetHeight(menuItemRect) - CGRectGetHeight(contentRect)) / 2.0;
}
[menuWindow setFrameOrigin:menuOrigin];
var menuMaxX = CGRectGetMaxX([menuWindow frame]),
buttonMaxX = [theWindow convertBaseToBridge:CGPointMake(CGRectGetMaxX([self convertRect:[self bounds] toView:nil]), 0.0)].x;
buttonMaxX = [theWindow convertBaseToGlobal:CGPointMake(CGRectGetMaxX([self convertRect:[self bounds] toView:nil]), 0.0)].x;
if (menuMaxX < buttonMaxX)
[menuWindow setMinWidth:CGRectGetWidth([menuWindow frame]) + buttonMaxX - menuMaxX - ([self pullsDown] ? 0.0 : VISIBLE_MARGIN)];
[menuWindow orderFront:self];
[menuWindow beginTrackingWithEvent:anEvent sessionDelegate:self didEndSelector:@selector(menuWindowDidFinishTracking:highlightedItem:)];
}
+7 -7
View File
@@ -205,7 +205,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
/*!
Always returns <code>NO</code>. Cappuccino does not have multiple threads.
Always returns \c NO. Cappuccino does not have multiple threads.
*/
- (BOOL)usesThreadedAnimation
{
@@ -329,7 +329,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
/*!
Specifies whether this progress indicator should be indeterminate or display progress based on it's max and min.
@param isDeterminate <code>YES</code> makes the indicator indeterminate
@param isDeterminate \c YES makes the indicator indeterminate
*/
- (void)setIndeterminate:(BOOL)isIndeterminate
{
@@ -342,7 +342,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
/*!
Returns <code>YES</code> if the progress bar is indeterminate.
Returns \c YES if the progress bar is indeterminate.
*/
- (BOOL)isIndeterminate
{
@@ -377,9 +377,9 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
/*!
Sets whether the indicator should be displayed when it isn't animating. By default this is <code>YES</code> if the style
is CPProgressIndicatorBarStyle, and <code>NO</code> if it's CPProgressIndicatorSpinningStyle.
@param isDisplayedWhenStopped <code>YES</code> means the indicator will be displayed when it's not animating.
Sets whether the indicator should be displayed when it isn't animating. By default this is \c YES if the style
is CPProgressIndicatorBarStyle, and \c NO if it's CPProgressIndicatorSpinningStyle.
@param isDisplayedWhenStopped \c YES means the indicator will be displayed when it's not animating.
*/
- (void)setDisplayedWhenStopped:(BOOL)isDisplayedWhenStopped
{
@@ -394,7 +394,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
/*!
Returns <code>YES</code> if the progress bar is displayed when not animating.
Returns \c YES if the progress bar is displayed when not animating.
*/
- (BOOL)isDisplayedWhenStopped
{
+7 -2
View File
@@ -98,7 +98,7 @@
if (self)
{
[self setRadioGroup:aRadioGroup || [CPRadioGroup new]];
[self setRadioGroup:aRadioGroup];
[self setHighlightsBy:CPContentsCellMask];
[self setShowsStateBy:CPContentsCellMask];
@@ -115,7 +115,7 @@
- (id)initWithFrame:(CGRect)aFrame
{
return [self initWithFrame:aFrame radioGroup:nil];
return [self initWithFrame:aFrame radioGroup:[CPRadioGroup new]];
}
- (CPInteger)nextState
@@ -175,6 +175,9 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
{
CPSet _radios;
CPRadio _selectedRadio;
id _target @accessors(property=target);
SEL _action @accessors(property=action);
}
- (id)init
@@ -213,6 +216,8 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
[_selectedRadio setState:CPOffState];
_selectedRadio = aRadio;
[CPApp sendAction:_action to:_target from:self];
}
- (CPRadio)selectedRadio
+25 -31
View File
@@ -46,7 +46,7 @@ CPDownArrowKeyCode = 40;
// Changing the first responder
/*!
Returns <code>YES</code> if the receiver is able to become the first responder. <code>NO</code> otherwise.
Returns \c YES if the receiver is able to become the first responder. \c NO otherwise.
*/
- (BOOL)acceptsFirstResponder
{
@@ -55,8 +55,8 @@ CPDownArrowKeyCode = 40;
/*!
Notifies the receiver that it will become the first responder. The receiver can reject first
responder if it returns <code>NO</code>. The default implementation always returns <code>YES</code>.
@return <code>YES</code> if the receiver accepts first responder status.
responder if it returns \c NO. The default implementation always returns \c YES.
@return \c YES if the receiver accepts first responder status.
*/
- (BOOL)becomeFirstResponder
{
@@ -65,7 +65,7 @@ CPDownArrowKeyCode = 40;
/*!
Notifies the receiver that it has been asked to give up first responder status.
@return <code>YES</code> if the receiver is willing to give up first responder status.
@return \c YES if the receiver is willing to give up first responder status.
*/
- (BOOL)resignFirstResponder
{
@@ -96,36 +96,38 @@ CPDownArrowKeyCode = 40;
*/
- (void)interpretKeyEvents:(CPArray)events
{
var event,
index = 0;
while(event = events[index++])
var index = 0,
count = [events count];
for (; index < count; ++index)
{
var event = events[index];
switch([event keyCode])
{
case CPLeftArrowKeyCode: [self moveBackward:self];
case CPLeftArrowKeyCode: [self doCommandBySelector:@selector(moveLeft:)];
break;
case CPRightArrowKeyCode: [self moveForward:self];
case CPRightArrowKeyCode: [self doCommandBySelector:@selector(moveRight:)];
break;
case CPUpArrowKeyCode: [self moveUp:self];
case CPUpArrowKeyCode: [self doCommandBySelector:@selector(moveUp:)];
break;
case CPDownArrowKeyCode: [self moveDown:self];
case CPDownArrowKeyCode: [self doCommandBySelector:@selector(moveDown:)];
break;
case CPDeleteKeyCode: [self deleteBackward:self];
case CPDeleteKeyCode: [self doCommandBySelector:@selector(deleteBackward:)];
break;
case CPReturnKeyCode:
case 3: [self insertLineBreak:self];
case 3: [self doCommandBySelector:@selector(insertLineBreak:)];
break;
case CPEscapeKeyCode: [self cancel:self];
case CPEscapeKeyCode: [self doCommandBySelector:@selector(cancel:)];
break;
case CPTabKeyCode: var shift = [event modifierFlags] & CPShiftKeyMask;
if (!shift)
[self insertTab:self];
[self doCommandBySelector:@selector(insertTab:)];
else
[self insertBackTab:self];
[self doCommandBySelector:@selector(insertBackTab:)];
break;
@@ -214,9 +216,9 @@ CPDownArrowKeyCode = 40;
/*
FIXME This description is bad.
Based on <code>anEvent</code>, the receiver should simulate the event.
Based on \c anEvent, the receiver should simulate the event.
@param anEvent the event to simulate
@return <code>YES</code> if the event receiver simulated the event
@return \c YES if the event receiver simulated the event
*/
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
{
@@ -224,14 +226,6 @@ CPDownArrowKeyCode = 40;
}
// Action Methods
/*!
Deletes one character backward, or the selection if anything is selected.
@param aSender the object requesting this
*/
- (void)deleteBackward:(id)aSender
{
}
/*!
Insert a line break at the caret position or selection.
@param aSender the object requesting this
@@ -247,7 +241,7 @@ CPDownArrowKeyCode = 40;
*/
- (void)insertNewline:(id)aSender
{
[self insertNewline:aSender];
[[self nextResponder] insertNewline:aSender];
}
- (void)cancel:(id)sender
@@ -273,12 +267,12 @@ CPDownArrowKeyCode = 40;
// Dispatch methods
/*!
The receiver will attempt to perform the command,
if it responds to it. If not, the <code>nextResponder</code> will be called to do it.
if it responds to it. If not, the \c -nextResponder will be called to do it.
@param aSelector the command to attempt
*/
- (void)doCommandBySelector:(SEL)aSelector
{
if([self respondsToSelector:aSelector])
if ([self respondsToSelector:aSelector])
[self performSelector:aSelector];
else
[_nextResponder doCommandBySelector:aSelector];
@@ -288,7 +282,7 @@ CPDownArrowKeyCode = 40;
The receiver will attempt to perform the command, or pass it on to the next responder if it doesn't respond to it.
@param aSelector the command to perform
@param anObject the argument to the method
@return <code>YES</code> if the receiver was able to perform the command, or a responder down the chain was
@return \c YES if the receiver was able to perform the command, or a responder down the chain was
able to perform the command.
*/
- (BOOL)tryToPerform:(SEL)aSelector with:(id)anObject
+67
View File
@@ -0,0 +1,67 @@
@import <AppKit/CPPanel.j>
@implementation CPSavePanel : CPPanel
{
CPURL _URL;
BOOL _isExtensionHidden @accessors(getter=isExtensionHidden, setter=setExtensionHidden:);
BOOL _canSelectHiddenExtension @accessors(property=canSelectHiddenExtension);
BOOL _allowsOtherFileTypes @accessors(property=allowsOtherFileTypes);
BOOL _canCreateDirectories @accessors(property=canCreateDirectories);
CPArray _allowedFileTypes @accessors(property=allowedFileTypes);
}
+ (id)savePanel
{
return [[CPSavePanel alloc] init];
}
- (id)init
{
if (self = [super init])
{
_canCreateDirectories = YES;
}
return self;
}
- (CPInteger)runModal
{
// FIXME: Is this correct???
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
if (typeof window["cpSavePanel"] === "function")
{
var resultObject = window.cpSavePanel({
isExtensionHidden: _isExtensionHidden,
canSelectHiddenExtension: _canSelectHiddenExtension,
allowsOtherFileTypes: _allowsOtherFileTypes,
canCreateDirectories: _canCreateDirectories,
allowedFileTypes: _allowedFileTypes
}),
result = resultObject.button;
_URL = result ? [CPURL URLWithString:resultObject.URL] : nil;
}
else
{
// FIXME: This is not the best way to do this.
var documentName = window.prompt("Document Name:"),
result = documentName !== null;
_URL = result ? [[self class] proposedFileURLWithDocumentName:documentName] : nil;
}
return result;
}
- (CPURL)URL
{
return _URL;
}
@end
+16
View File
@@ -0,0 +1,16 @@
@import <Foundation/CPObject.j>
#import "CoreGraphics/CGGeometry.h"
@implementation CPScreen : CPObject
{
}
- (CGRect)visibleFrame
{
return _CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight);
}
@end
+184 -99
View File
@@ -38,7 +38,9 @@
@implementation CPScrollView : CPView
{
CPClipView _contentView;
CPClipView _headerClipView;
CPView _cornerView;
BOOL _hasVerticalScroller;
BOOL _hasHorizontalScroller;
BOOL _autohidesScrollers;
@@ -57,23 +59,27 @@
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_verticalLineScroll = 10.0;
_verticalPageScroll = 10.0;
_horizontalLineScroll = 10.0;
_horizontalPageScroll = 10.0;
_contentView = [[CPClipView alloc] initWithFrame:[self bounds]];
[self addSubview:_contentView];
_headerClipView = [[CPClipView alloc] init];
[self addSubview:_headerClipView];
[self setHasVerticalScroller:YES];
[self setHasHorizontalScroller:YES];
}
return self;
}
@@ -100,24 +106,24 @@
*/
- (void)setContentView:(CPClipView)aContentView
{
if (!aContentView)
if (_contentView !== aContentView || !aContentView)
return;
var documentView = [aContentView documentView];
if (documentView)
[documentView removeFromSuperview];
[_contentView removeFromSuperview];
var size = [self contentSize];
_contentView = aContentView;
[_contentView setFrame:CGRectMake(0.0, 0.0, size.width, size.height)];
[_contentView setDocumentView:documentView];
[self addSubview:_contentView];
// This will size the content view appropriately, so no need to size it in this method.
[self reflectScrolledClipView:_contentView];
}
/*!
@@ -134,8 +140,11 @@
*/
- (void)setDocumentView:(CPView)aView
{
[_contentView setDocumentView:aView];
[self reflectScrolledClipView:_contentView];
[_contentView setDocumentView:aView];
// FIXME: This should be observed.
[self _updateCornerAndHeaderView];
[self reflectScrolledClipView:_contentView];
}
/*!
@@ -166,72 +175,98 @@
// [_verticalScroller setEnabled:NO];
// [_horizontalScroller setEnabled:NO];
}
[_contentView setFrame:[self bounds]];
[_headerClipView setFrame:_CGRectMakeZero()];
--_recursionCount;
return;
}
var documentFrame = [documentView frame],
contentViewFrame = [self bounds],
scrollPoint = [_contentView bounds].origin,
difference = _CGSizeMake(CPRectGetWidth(documentFrame) - CPRectGetWidth(contentViewFrame), CPRectGetHeight(documentFrame) - CPRectGetHeight(contentViewFrame)),
shouldShowVerticalScroller = (!_autohidesScrollers || difference.height > 0.0) && _hasVerticalScroller,
shouldShowHorizontalScroller = (!_autohidesScrollers || difference.width > 0.0) && _hasHorizontalScroller,
wasShowingVerticalScroller = ![_verticalScroller isHidden],
wasShowingHorizontalScroller = ![_horizontalScroller isHidden],
verticalScrollerWidth = _CGRectGetWidth([_verticalScroller frame]);
horizontalScrollerHeight = _CGRectGetHeight([_horizontalScroller frame]);
var documentFrame = [documentView frame], // the size of the whole document
contentFrame = [self bounds], // assume it takes up the entire size of the scrollview (no scrollers)
headerClipViewFrame = [self _headerClipViewFrame],
headerClipViewHeight = _CGRectGetHeight(headerClipViewFrame);
if (_autohidesScrollers)
{
// Check to see if either affected the other!
if (shouldShowVerticalScroller)
shouldShowHorizontalScroller = (!_autohidesScrollers || difference.width > -verticalScrollerWidth) && _hasHorizontalScroller;
contentFrame.origin.y += headerClipViewHeight;
contentFrame.size.height -= headerClipViewHeight;
if (shouldShowHorizontalScroller)
shouldShowVerticalScroller = (!_autohidesScrollers || difference.height > -horizontalScrollerHeight) && _hasVerticalScroller;
}
[_verticalScroller setHidden:!shouldShowVerticalScroller];
[_verticalScroller setEnabled:difference.height > 0.0];
[_horizontalScroller setHidden:!shouldShowHorizontalScroller];
[_horizontalScroller setEnabled:difference.width > 0.0];
var difference = _CGSizeMake(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentFrame), _CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentFrame)),
verticalScrollerWidth = _CGRectGetWidth([_verticalScroller frame]),
horizontalScrollerHeight = _CGRectGetHeight([_horizontalScroller frame]),
hasVerticalScroll = difference.height > 0.0,
hasHorizontalScroll = difference.width > 0.0,
shouldShowVerticalScroller = _hasVerticalScroller && (!_autohidesScrollers || hasVerticalScroll),
shouldShowHorizontalScroller = _hasHorizontalScroller && (!_autohidesScrollers || hasHorizontalScroll);
// Now we have to account for the shown scrollers affecting the deltas.
if (shouldShowVerticalScroller)
{
var verticalScrollerHeight = CPRectGetHeight(contentViewFrame);
if (shouldShowHorizontalScroller)
verticalScrollerHeight -= horizontalScrollerHeight;
difference.width += verticalScrollerWidth;
contentViewFrame.size.width -= verticalScrollerWidth;
[_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height
knobProportion:CPRectGetHeight(contentViewFrame) / CPRectGetHeight(documentFrame)];
[_verticalScroller setFrame:CPRectMake(CPRectGetMaxX(contentViewFrame), 0.0, verticalScrollerWidth, verticalScrollerHeight)];
hasHorizontalScroll = difference.width > 0.0;
shouldShowHorizontalScroller = _hasHorizontalScroller && (!_autohidesScrollers || hasHorizontalScroll);
}
else if (wasShowingVerticalScroller)
[_verticalScroller setFloatValue:0.0 knobProportion:1.0];
if (shouldShowHorizontalScroller)
{
difference.height += horizontalScrollerHeight;
contentViewFrame.size.height -= horizontalScrollerHeight;
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width
knobProportion:CPRectGetWidth(contentViewFrame) / CPRectGetWidth(documentFrame)];
[_horizontalScroller setFrame:CPRectMake(0.0, CPRectGetMaxY(contentViewFrame), CPRectGetWidth(contentViewFrame), horizontalScrollerHeight)];
hasVerticalScroll = difference.height > 0.0;
shouldShowVerticalScroller = _hasVerticalScroller && (!_autohidesScrollers || hasVerticalScroll);
}
// We now definitively know which scrollers are shown or not, as well as whether they are showing scroll values.
[_verticalScroller setHidden:!shouldShowVerticalScroller];
[_verticalScroller setEnabled:hasVerticalScroll];
[_horizontalScroller setHidden:!shouldShowHorizontalScroller];
[_horizontalScroller setEnabled:hasHorizontalScroll];
// We can thus appropriately account for them changing the content size.
if (shouldShowVerticalScroller)
contentFrame.size.width -= verticalScrollerWidth;
if (shouldShowHorizontalScroller)
contentFrame.size.height -= horizontalScrollerHeight;
var scrollPoint = [_contentView bounds].origin,
wasShowingVerticalScroller = ![_verticalScroller isHidden],
wasShowingHorizontalScroller = ![_horizontalScroller isHidden];
if (shouldShowVerticalScroller)
{
var verticalScrollerY = MAX(_CGRectGetHeight([self _cornerViewFrame]), headerClipViewHeight),
verticalScrollerHeight = _CGRectGetHeight([self bounds]) - verticalScrollerY;
if (shouldShowHorizontalScroller)
verticalScrollerHeight -= horizontalScrollerHeight;
[_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height];
[_verticalScroller setKnobProportion:_CGRectGetHeight(contentFrame) / _CGRectGetHeight(documentFrame)];
[_verticalScroller setFrame:_CGRectMake(_CGRectGetMaxX(contentFrame), verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)];
}
else if (wasShowingVerticalScroller)
{
[_verticalScroller setFloatValue:0.0];
[_verticalScroller setKnobProportion:1.0];
}
if (shouldShowHorizontalScroller)
{
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
[_horizontalScroller setKnobProportion:_CGRectGetWidth(contentFrame) / _CGRectGetWidth(documentFrame)];
[_horizontalScroller setFrame:_CGRectMake(0.0, _CGRectGetMaxY(contentFrame), _CGRectGetWidth(contentFrame), horizontalScrollerHeight)];
}
else if (wasShowingHorizontalScroller)
[_horizontalScroller setFloatValue:0.0 knobProportion:1.0];
[_contentView setFrame:contentViewFrame];
{
[_horizontalScroller setFloatValue:0.0];
[_horizontalScroller setKnobProportion:1.0];
}
[_contentView setFrame:contentFrame];
[_headerClipView setFrame:headerClipViewFrame];
[_cornerView setFrame:[self _cornerViewFrame]];
--_recursionCount;
}
@@ -269,7 +304,7 @@
/*!
Specifies whether the scroll view can have a horizontal scroller.
@param hasHorizontalScroller <code>YES</code> lets the scroll view
@param hasHorizontalScroller \c YES lets the scroll view
allocate a horizontal scroller if necessary.
*/
- (void)setHasHorizontalScroller:(BOOL)shouldHaveHorizontalScroller
@@ -278,20 +313,15 @@
return;
_hasHorizontalScroller = shouldHaveHorizontalScroller;
if (_hasHorizontalScroller && !_horizontalScroller)
[self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, CPRectGetWidth([self bounds]), [CPScroller scrollerWidth])]];
[self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, _CGRectGetWidth([self bounds]), [CPScroller scrollerWidth])]];
else if (!_hasHorizontalScroller && _horizontalScroller)
{
[_horizontalScroller setHidden:YES];
[self reflectScrolledClipView:_contentView];
}
[self reflectScrolledClipView:_contentView];
}
/*!
Returns <code>YES</code> if the scroll view can have a horizontal scroller.
Returns \c YES if the scroll view can have a horizontal scroller.
*/
- (BOOL)hasHorizontalScroller
{
@@ -332,7 +362,7 @@
/*!
Specifies whether the scroll view has can have
a vertical scroller. It allocates it if necessary.
@param hasVerticalScroller <code>YES</code> allows
@param hasVerticalScroller \c YES allows
the scroll view to display a vertical scroller
*/
- (void)setHasVerticalScroller:(BOOL)shouldHaveVerticalScroller
@@ -343,18 +373,13 @@
_hasVerticalScroller = shouldHaveVerticalScroller;
if (_hasVerticalScroller && !_verticalScroller)
[self setVerticalScroller:[[CPScroller alloc] initWithFrame:CPRectMake(0.0, 0.0, [CPScroller scrollerWidth], CPRectGetHeight([self bounds]))]];
[self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidth], _CGRectGetHeight([self bounds]))]];
else if (!_hasVerticalScroller && _verticalScroller)
{
[_verticalScroller setHidden:YES];
[self reflectScrolledClipView:_contentView];
}
[self reflectScrolledClipView:_contentView];
}
/*!
Returns <code>YES</code> if the scroll view can have a vertical scroller.
Returns \c YES if the scroll view can have a vertical scroller.
*/
- (BOOL)hasVerticalScroller
{
@@ -363,7 +388,7 @@
/*!
Sets whether the scroll view hides its scoll bars when not needed.
@param autohidesScrollers <code>YES</code> causes the scroll bars
@param autohidesScrollers \c YES causes the scroll bars
to be hidden when not needed.
*/
- (void)setAutohidesScrollers:(BOOL)autohidesScrollers
@@ -377,20 +402,76 @@
}
/*!
Returns <code>YES</code> if the scroll view hides its scroll
Returns \c YES if the scroll view hides its scroll
bars when not necessary.
*/
- (BOOL)autohidesScrollers
{
return _autohidesScrollers;
}
/*
- (void)setFrameSize:(CPRect)aSize
- (void)_updateCornerAndHeaderView
{
[super setFrameSize:aSize];
var documentView = [self documentView],
currentHeaderView = [self _headerView],
documentHeaderView = [documentView respondsToSelector:@selector(headerView)] ? [documentView headerView] : nil;
if (currentHeaderView !== documentHeaderView)
{
[currentHeaderView removeFromSuperview];
[_headerClipView setDocumentView:documentHeaderView];
}
var documentCornerView = [documentView respondsToSelector:@selector(cornerView)] ? [documentView cornerView] : nil;
if (_cornerView !== documentCornerView)
{
[_cornerView removeFromSuperview];
_cornerView = documentCornerView;
if (_cornerView)
[self addSubview:_cornerView];
}
[self reflectScrolledClipView:_contentView];
}*/
}
- (CPView)_headerView
{
var headerClipViewSubviews = [_headerClipView subviews];
return [headerClipViewSubviews count] ? headerClipViewSubviews[0] : nil;
}
- (CGRect)_cornerViewFrame
{
if (!_cornerView)
return _CGRectMakeZero();
var bounds = [self bounds],
frame = [_cornerView frame];
frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame);
frame.origin.y = 0;
return frame;
}
- (CGRect)_headerClipViewFrame
{
var headerView = [self _headerView];
if (!headerView)
return _CGRectMakeZero();
var frame = [self bounds];
frame.size.height = _CGRectGetHeight([headerView frame]);
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
return frame;
}
/* @ignore */
- (void)_verticalScrollerDidScroll:(CPScroller)aScroller
@@ -415,7 +496,8 @@
case CPScrollerKnobSlot:
case CPScrollerKnob:
default: contentBounds.origin.y = value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds));
// We want integral bounds!
default: contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)));
}
[_contentView scrollToPoint:contentBounds.origin];
@@ -444,10 +526,12 @@
case CPScrollerKnobSlot:
case CPScrollerKnob:
default: contentBounds.origin.x = value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds));
// We want integral bounds!
default: contentBounds.origin.x = ROUND(value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds)));
}
[_contentView scrollToPoint:contentBounds.origin];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)];
}
/*!
@@ -580,20 +664,20 @@
*/
- (void)scrollWheel:(CPEvent)anEvent
{
var value = [_verticalScroller floatValue],
documentFrame = [[self documentView] frame],
var documentFrame = [[self documentView] frame],
contentBounds = [_contentView bounds];
contentBounds.origin.x += [anEvent deltaX] * _horizontalLineScroll;
contentBounds.origin.y += [anEvent deltaY] * _verticalLineScroll;
// We want integral bounds!
contentBounds.origin.x = ROUND(contentBounds.origin.x + [anEvent deltaX] * _horizontalLineScroll);
contentBounds.origin.y = ROUND(contentBounds.origin.y + [anEvent deltaY] * _verticalLineScroll);
[_contentView scrollToPoint:contentBounds.origin];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)];
}
- (void)keyDown:(CPEvent)anEvent
{
var keyCode = [anEvent keyCode],
value = [_verticalScroller floatValue],
documentFrame = [[self documentView] frame],
contentBounds = [_contentView bounds];
@@ -627,6 +711,7 @@
}
[_contentView scrollToPoint:contentBounds.origin];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin, 0)];
}
@end
+34 -33
View File
@@ -64,9 +64,9 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
BOOL _isVertical @accessors(readonly, getter=isVertical);
float _knobProportion;
CPScrollerPart _hitPart;
CPScrollerPart _trackingPart;
float _trackingFloatValue;
CGPoint _trackingStartPoint;
@@ -104,11 +104,12 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
_controlSize = CPRegularControlSize;
_partRects = [];
[self setFloatValue:0.0 knobProportion:1.0];
[self setFloatValue:0.0];
[self setKnobProportion:1.0];
_hitPart = CPScrollerNoPart;
[self _recalculateIsVertical];
[self _calculateIsVertical];
}
return self;
@@ -120,7 +121,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
*/
+ (float)scrollerWidth
{
return 17.0;//[self scrollerWidthForControlSize:CPRegularControlSize];
return 15.0;//[self scrollerWidthForControlSize:CPRegularControlSize];
}
/*!
@@ -129,7 +130,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
*/
+ (float)scrollerWidthForControlSize:(CPControlSize)aControlSize
{
return 17.0;//_CPScrollerWidths[aControlSize];
return 15.0;//_CPScrollerWidths[aControlSize];
}
/*!
@@ -155,28 +156,17 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
return _controlSize;
}
// Setting the Knob Position
/*!
Sets the scroller's knob position (ranges from 0.0 to 1.0).
@param aValue the knob position (ranges from 0.0 to 1.0)
*/
- (void)setFloatValue:(float)aValue
- (void)setObjectValue:(id)aValue
{
[super setFloatValue:MIN(1.0, MAX(0.0, aValue))];
[self setNeedsLayout];
[super setObjectValue:MIN(1.0, MAX(0.0, +aValue))];
}
/*!
Sets the position and proportion of the knob.
@param aValue the knob position (ranges from 0.0 to 1.0)
@param aProportion the knob's proportion (ranges from 0.0 to 1.0)
*/
- (void)setFloatValue:(float)aValue knobProportion:(float)aProportion
- (void)setKnobProportion:(float)aProportion
{
_knobProportion = MIN(1.0, MAX(0.0001, aProportion));
[self setFloatValue:aValue];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
/*!
@@ -208,7 +198,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
}
/*!
Returns the part of the scroller that would be hit by <code>aPoint</code>.
Returns the part of the scroller that would be hit by \c aPoint.
@param aPoint the simulated point hit
@return the part of the scroller that intersects the point
*/
@@ -533,15 +523,15 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
}
- (void)_recalculateIsVertical
- (void)_calculateIsVertical
{
// Recalculate isVertical.
var bounds = [self bounds],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
_isVertical = width < height ? 1 : (width > height ? 0 : -1);
if (_isVertical === 1)
[self setThemeState:CPThemeStateVertical];
else if (_isVertical === 0)
@@ -552,8 +542,6 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
{
[super setFrameSize:aSize];
[self _recalculateIsVertical];
[self checkSpaceForParts];
[self setNeedsLayout];
}
@@ -590,18 +578,16 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize",
_controlSize = CPRegularControlSize;
if ([aCoder containsValueForKey:CPScrollerControlSizeKey])
_controlSize = [aCoder decodeIntForKey:CPScrollerControlSizeKey];
_knobProportion = 1.0;
if ([aCoder containsValueForKey:CPScrollerKnobProportionKey])
_knobProportion = [aCoder decodeFloatForKey:CPScrollerKnobProportionKey];
_partRects = [];
_hitPart = CPScrollerNoPart;
[self _recalculateIsVertical];
// [self checkSpaceForParts];
// [self setNeedsLayout];
[self _calculateIsVertical];
}
return self;
@@ -616,3 +602,18 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize",
}
@end
@implementation CPScroller (Deprecated)
/*!
Sets the position and proportion of the knob.
@param aValue the knob position (ranges from 0.0 to 1.0)
@param aProportion the knob's proportion (ranges from 0.0 to 1.0)
*/
- (void)setFloatValue:(float)aValue knobProportion:(float)aProportion
{
[self setFloatValue:aValue];
[self setKnobProportion:aProportion];
}
@end
+706
View File
@@ -0,0 +1,706 @@
/*
* CPSearchField.j
* AppKit
*
* Created by cacaodev.
* Copyright 2009.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPTextField.j"
#include "Platform/Platform.h"
/*!
@global
@group Menu tags
*/
CPSearchFieldRecentsTitleMenuItemTag = 1000;
/*!
@global
@group Menu tags
*/
CPSearchFieldRecentsMenuItemTag = 1001;
/*!
@global
@group Menu tags
*/
CPSearchFieldClearRecentsMenuItemTag = 1002;
/*!
@global
@group Menu tags
*/
CPSearchFieldNoRecentsMenuItemTag = 1003;
var CPSearchFieldSearchImage = nil,
CPSearchFieldFindImage = nil,
CPSearchFieldCancelImage = nil,
CPSearchFieldCancelPressedImage = nil;
/*!
@ingroup appkit
@class CPSearchField
The CPSearchField class defines the programmatic interface for text fields that are optimized for text-based searches. A CPSearchField object directly inherits from the CPTextField class. The search field implemented by these classes presents a standard user interface for searches, including a search button, a cancel button, and a pop-up icon menu for listing recent search strings and custom search categories.
When the user types and then pauses, the text field's action message is sent to its target. You can query the text field's string value for the current text to search for. Do not rely on the sender of the action to be an CPMenu object because the menu may change. If you need to change the menu, modify the search menu template and call the setSearchMenuTemplate: method to update.
*/
@implementation CPSearchField : CPTextField
{
CPButton _searchButton;
CPButton _cancelButton;
CPMenu _searchMenuTemplate;
CPMenu _searchMenu;
CPString _recentsAutosaveName;
CPArray _recentSearches;
int _maximumRecents;
BOOL _sendsWholeSearchString;
BOOL _sendsSearchStringImmediately;
CPTimer _partialStringTimer;
}
+ (void)initialize
{
if (self != [CPSearchField class])
return;
var bundle = [CPBundle bundleForClass:self];
CPSearchFieldSearchImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldSearch.png"]];
CPSearchFieldFindImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldFind.png"]];
CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"]];
CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"]];
}
- (id)initWithFrame:(CPRect)frame
{
self = [super initWithFrame:frame];
if (self != nil)
{
_recentSearches = [CPArray array];
_maximumRecents = 10;
_sendsWholeSearchString = NO;
_sendsSearchStringImmediately = NO;
[self setBezeled:YES];
[self setBezelStyle:CPTextFieldRoundedBezel];
[self setBordered:YES];
[self setEditable:YES];
[self setDelegate:self];
_cancelButton = [[CPButton alloc] initWithFrame:CPMakeRect(frame.size.width - 27,(frame.size.height-22)/2,22,22)];
[self resetCancelButton];
[_cancelButton setHidden:YES];
[_cancelButton setAutoresizingMask:CPViewMinXMargin];
[self addSubview:_cancelButton];
_searchButton = [[CPButton alloc] initWithFrame:CPMakeRect(5,(frame.size.height-25)/2,25,25)];
[_searchButton setBezelStyle:CPRegularSquareBezelStyle];
[_searchButton setAutoresizingMask:CPViewMaxXMargin]
[_searchButton setBordered:NO];
[_searchButton setImageScaling:CPScaleToFit];
#if PLATFORM(DOM)
_cancelButton._DOMElement.style.cursor = "default";
_searchButton._DOMElement.style.cursor = "default";
#endif
[self setSearchMenuTemplate:[self _searchMenuTemplate]];
[self addSubview:_searchButton];
}
return self;
}
- (id)copy
{
var copy = [super copy];
[copy setCancelButton:[_cancelButton copy]];
[copy setSearchButton:[_searchButton copy]];
[copy setrecentsAutosaveName:[_recentsAutosaveName copy]];
[copy setSendsWholeSearchString:[_sendsWholeSearchString copy]];
[copy setSendsSearchStringImmediately:[_sendsSearchStringImmediately copy]];
[copy setMaximumRecents:_maximumRecents];
[copy setSearchMenutemplate:[_searchMenuTemplate copy]];
return copy;
}
// Managing Buttons
/*!
Sets the button used to display the search-button image
@param button The search button.
*/
- (void)setSearchButton:(CPButton)button
{
_searchButton = button;
}
/*!
Returns the button used to display the search-button image.
@return The search button.
*/
- (CPButton)searchButton
{
return _searchButton;
}
/*!
Resets the search button to its default attributes.
This method resets the target, action, regular image, and pressed image. By default, when users click the search button or press the Return key, the action defined for the receiver is sent to its designated target. This method gives you a way to customize the search button for specific situations and then reset the button defaults without having to undo changes individually.
*/
- (void)resetSearchButton
{
var searchButtonImage,
action,
target,
button = [self searchButton];
if (_searchMenuTemplate == nil)
{
searchButtonImage = CPSearchFieldSearchImage;
action = [self action];
target = [self target];
}
else
{
searchButtonImage = CPSearchFieldFindImage;
action = @selector(_showMenu:);
target = self;
}
[button setImage:searchButtonImage];
[button setTarget:target];
[button setAction:action];
}
/*!
Sets the button object used to display the cancel-button image.
@param button The cancel button.
*/
- (void)setCancelButton:(CPButton)button
{
_cancelButton = button;
}
/*!
Returns the button object used to display the cancel-button image.
@return The cancel button.
*/
- (CPButton)cancelButton
{
return _cancelButton;
}
/*!
Resets the cancel button to its default attributes.
This method resets the target, action, regular image, and pressed image. By default, when users click the cancel button, the delete: action message is sent up the responder chain. This method gives you a way to customize the cancel button for specific situations and then reset the button defaults without having to undo changes individually.
*/
- (void)resetCancelButton
{
var button = [self cancelButton];
[button setBezelStyle:CPRegularSquareBezelStyle];
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImage:CPSearchFieldCancelImage];
[button setAlternateImage:CPSearchFieldCancelPressedImage];
[button setTarget:self];
[button setAction:@selector(_searchFieldCancel:)];
}
// Custom Layout
/*!
Modifies the bounding rectangle for the search-text field.
@param rect The current bounding rectangle for the search text field.
@return The updated bounding rectangle to use for the search text field. The default value is the value passed into the rect parameter.
Subclasses can override this method to return a new bounding rectangle for the text-field object. You might use this method to provide a custom layout for the search field control.
*/
- (CPRect)searchTextRectForBounds:(CPRect)rect
{
var leftOffset = 0, width = rect.size.width;
if (_searchButton)
{
var searchRect = [_searchButton frame];
leftOffset = searchRect.origin.x + searchRect.size.width;
}
if (_cancelButton)
{
var cancelRect = [_cancelButton frame];
width = cancelRect.origin.x - leftOffset;
}
return CPMakeRect(leftOffset,rect.origin.y,width,rect.size.height);
}
/*!
Modifies the bounding rectangle for the search button.
@param rect The current bounding rectangle for the search button.
Subclasses can override this method to return a new bounding rectangle for the search button. You might use this method to provide a custom layout for the search field control.
*/
- (CPRect)searchButtonRectForBounds:(CPRect)rect // fix
{
return [_searchButton frame];
}
/*!
Modifies the bounding rectangle for the cancel button.
@param rect The updated bounding rectangle to use for the cancel button. The default value is the value passed into the rect parameter.
Subclasses can override this method to return a new bounding rectangle for the cancel button. You might use this method to provide a custom layout for the search field control.
*/
- (CPRect)cancelButtonRectForBounds:(CPRect)rect
{
return [_cancelButton frame];
}
// Managing Menu Templates
/*!
Returns the menu template object used to dynamically construct the search pop-up icon menu.
@return The current menu template.
*/
- (CPMenu)searchMenuTemplate
{
return _searchMenuTemplate;
}
/*!
Sets the menu template object used to dynamically construct the receiver's pop-up icon menu.
@param menu The menu template to use.
The receiver looks for the tag constants described in ŇMenu tagsÓ to determine how to populate the menu with items related to recent searches. See ŇConfiguring a Search MenuÓ for a sample of how you might set up the search menu template.
*/
- (void)setSearchMenuTemplate:(CPMenu)menu
{
_searchMenuTemplate = menu;
[self resetSearchButton];
[self _updateSearchMenu];
}
// Managing Search Modes
/*!
Returns a Boolean value indicating whether the receiver sends the search action message when the user clicks the search button (or presses return) or after each keystroke.
@return \c YES if the action message is sent all at once when the user clicks the search button or presses return; otherwise, NO if the search string is sent after each keystroke. The default value is NO.
*/
- (BOOL)sendsWholeSearchString
{
return _sendsWholeSearchString;
}
/*!
Sets whether the receiver sends the search action message when the user clicks the search button (or presses return) or after each keystroke.
@param flag \c YES to send the action message all at once when the user clicks the search button or presses return; otherwise, NO to send the search string after each keystroke.
*/
- (void)setSendsWholeSearchString:(BOOL)flag
{
_sendsWholeSearchString = flag;
}
/*!
Returns a Boolean value indicating whether the receiver sends its action immediately upon being notified of changes to the search field text or after a brief pause.
@return \c YES if the text field sends its action immediately upon notification of any changes to the search field; otherwise, NO.
*/
- (BOOL)sendsSearchStringImmediately
{
return _sendsSearchStringImmediately;
}
/*!
Sets whether the text field sends its action message to the target immediately upon notification of any changes to the search field text or after a brief pause.
@param flag \c YES to send the text field's action immediately upon notification of any changes to the search field; otherwise, NO if you want the text field to pause briefly before sending its action message. Pausing gives the user the opportunity to type more text into the search field before initiating the search.
*/
- (void)setSendsSearchStringImmediately:(BOOL)flag
{
_sendsSearchStringImmediately = flag;
}
// Managing Recent Search Strings
/*!
Returns the maximum number of recent search strings to display in the custom search menu.
@return The maximum number of search strings that can appear in the menu. This value is between 0 and 254.
*/
- (int)maximumRecents
{
return _maximumRecents;
}
/*!
Sets the maximum number of search strings that can appear in the search menu.
@param maxRecents The maximum number of search strings that can appear in the menu. This value can be between 0 and 254. Specifying a value less than 0 sets the value to the default, which is 10. Specifying a value greater than 254 sets the maximum to 254.
*/
- (void)setMaximumRecents:(int)max
{
if (max > 254)
max = 254;
else if (max < 0)
max = 10;
_maximumRecents = max;
}
/*!
Returns the list of recent search strings for the control.
@return An array of \c CPString objects, each of which contains a search string either displayed in the search menu or from a recent autosave archive. If there have been no recent searches and no prior searches saved under an autosave name, this array may be empty.
*/
- (CPArray)recentSearches
{
return _recentSearches;
}
/*!
Sets the list of recent search strings to list in the pop-up icon menu of the receiver.
@param searches An array of CPString objects containing the search strings.
You might use this method to set the recent list of searches from an archived copy.
*/
- (void)setRecentSearches:(CPArray)searches
{
var max = MIN([self maximumRecents],[searches count]);
var searches = [searches subarrayWithRange:CPMakeRange(0,max)];
_recentSearches = searches;
[self _autosaveRecentSearchList];
}
/*!
Returns the key under which the prior list of recent search strings has been archived.
@return The autosave name, which is used as a key in the standard user defaults to save the recent searches. The default value is nil, which causes searches not to be autosaved.
*/
- (CPString)recentsAutosaveName
{
return _recentsAutosaveName;
}
/*!
Sets the autosave name under which the receiver automatically archives the list of recent search strings.
@param name The autosave name, which is used as a key in the standard user defaults to save the recent searches. If you specify nil or an empty string for this parameter, no autosave name is set and searches are not autosaved.
*/
- (void)setRecentsAutosaveName:(CPString)name
{
_recentsAutosaveName = name;
if(name != nil)
[self _registerForAutosaveNotification];
else
[self _deregisterForAutosaveNotification];
}
// Private methods and subclassing
- (CPRect)contentRectForBounds:(CPRect)bounds
{
var superbounds = [super contentRectForBounds:bounds];
return [self searchTextRectForBounds:superbounds];
}
+ (double)_keyboardDelayForPartialSearchString:(CPString)string
{
return (6 - MIN([string length],4))/10;
}
- (CPMenu)menu
{
return _searchMenu;
}
- (BOOL)isOpaque
{
return [super isOpaque] && [_cancelButton isOpaque] && [_searchButton isOpaque];
}
- (void)_updateCancelButtonVisibility
{
[_cancelButton setHidden:([[self stringValue] length] == 0)];
}
- (void)controlTextDidChange:(CPNotification)aNotification
{
if(!_sendsWholeSearchString)
{
if(_sendsSearchStringImmediately)
[self _sendPartialString];
else
{
[_partialStringTimer invalidate];
var timeInterval = [CPSearchField _keyboardDelayForPartialSearchString:[self stringValue]];
_partialStringTimer = [CPTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(_sendPartialString) userInfo:nil repeats:NO];
}
}
[self _updateCancelButtonVisibility];
}
- (void)sendAction:(SEL)anAction to:(id)anObject
{
[super sendAction:anAction to:anObject];
[_partialStringTimer invalidate];
var current_value = [self objectValue];
if(current_value != nil && current_value != "" && ![_recentSearches containsObject:current_value])
{
[self _addStringToRecentSearches:current_value];
[self _updateSearchMenu];
}
[self _updateCancelButtonVisibility];
}
- (void)_addStringToRecentSearches:(CPString)string
{
var newSearches = [CPMutableArray arrayWithArray:_recentSearches];
[newSearches addObject:string];
[self setRecentSearches:newSearches];
}
- (BOOL)trackMouse:(CPEvent)event
{
var rect;
var point;
var location = [event locationInWindow];
point = [self convertPoint:location fromView:nil];
rect = [self searchButtonRectForBounds:[self frame]];
if (CPRectContainsPoint(rect,point))
{
return [[self searchButton] trackMouse:event];
}
rect = [self cancelButtonRectForBounds:[self frame]];
if (CPRectContainsPoint(rect,point))
{
return [[self cancelButton] trackMouse:event];
}
return [super trackMouse:event];
}
- (CPMenu)_searchMenuTemplate
{
var template, item;
template = [[CPMenu alloc] init];
item = [[CPMenuItem alloc] initWithTitle:@"Recent searches" action:NULL keyEquivalent:@""];
[item setTag:CPSearchFieldRecentsTitleMenuItemTag];
[item setEnabled:NO];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"Recent search item" action:@selector(_searchFieldSearch:) keyEquivalent:@""];
[item setTag:CPSearchFieldRecentsMenuItemTag];
[item setTarget:self];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"Clear recent searches" action:@selector(_searchFieldClearRecents:) keyEquivalent:@""];
[item setTag:CPSearchFieldClearRecentsMenuItemTag];
[item setTarget:self];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"No recent searches" action:NULL keyEquivalent:@""];
[item setTag:CPSearchFieldNoRecentsMenuItemTag];
[item setEnabled:NO];
[template addItem:item];
return template;
}
- (void)_updateSearchMenu
{
if(_searchMenuTemplate == nil)
return;
var i, menu = [[CPMenu alloc] init];
var countOfRecents = [_recentSearches count];
for (i = 0; i < [_searchMenuTemplate numberOfItems]; i++)
{
var item = [_searchMenuTemplate itemAtIndex:i];
var tag = [item tag];
if(tag == CPSearchFieldClearRecentsMenuItemTag && countOfRecents != 0)
{
var separator = [CPMenuItem separatorItem];
[menu addItem:separator];
}
if (!(tag == CPSearchFieldRecentsTitleMenuItemTag && countOfRecents == 0) &&
!(tag == CPSearchFieldClearRecentsMenuItemTag && countOfRecents == 0) &&
!(tag == CPSearchFieldNoRecentsMenuItemTag && countOfRecents != 0) &&
!(tag == CPSearchFieldRecentsMenuItemTag))
{
var templateItem = [[CPMenuItem alloc] initWithTitle:[item title] action:[item action] keyEquivalent:[item keyEquivalent]];
[templateItem setTarget:[item target]];
[templateItem setEnabled:[item isEnabled]];
[templateItem setTag:[item tag]];
[menu addItem:templateItem];
}
else if (tag == CPSearchFieldRecentsMenuItemTag)
{
var j;
for (j = 0; j < countOfRecents; j++)
{
var rencentItem = [[CPMenuItem alloc] initWithTitle:[_recentSearches objectAtIndex:j] action:[item action] keyEquivalent:[item keyEquivalent]];
[rencentItem setTarget:[item target]];
[menu addItem:rencentItem];
}
}
}
_searchMenu = menu;
}
- (void)_showMenu:(id)sender
{
if(_searchMenu == nil || ![self isEnabled])
return;
[super selectText:nil];
var origin = CPMakePoint([self frame].origin.x, [self frame].origin.y + [self frame].size.height);
var anEvent = [CPEvent keyEventWithType:CPRightMouseDown location:origin modifierFlags:0 timestamp:[CPDate date] windowNumber:1 context:[[CPGraphicsContext currentContext] graphicsPort] characters:"" charactersIgnoringModifiers:"" isARepeat:NO keyCode:0];
[CPMenu popUpContextMenu:_searchMenu withEvent:anEvent forView:sender];
}
- (void)_sendPartialString
{
[[self target] performSelector:[self action] withObject:self];
}
- (void)_searchFieldCancel:(id)sender
{
[self setObjectValue:nil];
[self _sendPartialString];
[self _updateCancelButtonVisibility];
[sender setHidden:YES];
}
- (void)_searchFieldSearch:(id)sender
{
[self setObjectValue:[sender title]];
[self _sendPartialString];
[self _updateCancelButtonVisibility];
}
- (void)_searchFieldClearRecents:(id)sender
{
[self setRecentSearches:[CPArray array]];
[self _updateSearchMenu];
}
- (void)_registerForAutosaveNotification
{
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_updateAutosavedRecents:) name:@"CPAutosavedRecentsChangedNotification" object:nil];
}
- (void)_deregisterForAutosaveNotification
{
[[CPNotificationCenter defaultCenter] removeObserver:self name:@"CPAutosavedRecentsChangedNotification" object:nil];
}
- (void)_updateAutosavedRecents:(id)notification
{
var name = [notification object];
var list = [self recentSearches];
[[CPUserDefaults standardUserDefaults] setObject:list forKey:name];
}
- (void)_autosaveRecentSearchList
{
if(_recentsAutosaveName != nil)
[[CPNotificationCenter defaultCenter] postNotificationName:@"CPAutosavedRecentsChangedNotification" object:_recentsAutosaveName];
}
- (void)_loadRecentSearchList
{
var list,
name = [self recentsAutosaveName];
list = [[CPUserDefaults standardUserDefaults] objectForKey:name];
_recentSearches = list;
}
/*
- (BOOL)trackMouse:(CPEvent)theEvent inRect:(CPRect)cellFrame ofView:(CPView)aTextView untilMouseUp:(BOOL)flag
{
}
- (BOOL)_trimRecentSearchList
{
}
- (void)_trackButton:(CPButton)button forEvent:(CPEvent)event inRect:(CPRect)rect ofView:(id)view
{
}
- (id)_selectOrEdit:(CPRect)rect inView:(id)view target:(id)target editor:(id)editor event:(id)event start:(int)start end:(int)end
{
}
- (void)resetCursorRect:(CPRect)rect inView:(id)view
{
}
*/
@end
var CPSearchButtonKey = @"CPSearchButtonKey",
CPCancelButtonKey = @"CPCancelButtonKey",
CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey",
CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey",
CPMaximumRecentsKey = @"CPMaximumRecentsKey",
CPSearchMenuTemplateKey = @"CPSearchMenuTemplateKey";
@implementation CPSearchField (CPCoding)
- (void)encodeWithCoder:(CPCoder)coder
{
[super encodeWithCoder:coder];
[coder encodeObject:_searchButton forKey:CPSearchButtonKey];
[coder encodeObject:_cancelButton forKey:CPCancelButtonKey];
[coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey];
[coder encodeBool:_sendsWholeSearchString forKey:CPSendsWholeSearchStringKey];
[coder encodeBool:_sendsSearchStringImmediately forKey:CPSendsSearchStringImmediatelyKey];
[coder encodeInt:_maximumRecents forKey:CPMaximumRecentsKey];
[coder encodeObject:_searchMenuTemplate forKey:CPSearchMenuTemplateKey];
}
- (id)initWithCoder:(CPCoder)coder
{
self = [super initWithCoder:coder];
_searchButton = [coder decodeObjectForKey:CPSearchButtonKey];
_cancelButton = [coder decodeObjectForKey:CPCancelButtonKey];
_recentsAutosaveName = [coder decodeObjectForKey:CPRecentsAutosaveNameKey];
_sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey];
_sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey];
_maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey];
[self setSearchMenuTemplate:[coder decodeObjectForKey:CPSearchMenuTemplateKey]];
[self resetCancelButton];
[self setDelegate:self];
return self;
}
@end
+43 -25
View File
@@ -119,13 +119,13 @@ CPSegmentSwitchTrackingMomentary = 2;
}
else if (aCount < _segments.length)
{
for (var index = aCount; index < _segments.length; ++index)
_segments[index] = nil;
_segments.length = aCount;
_themeStates.length = aCount;
}
if (_selectedSegment < _segments.length)
if (_selectedSegment >= _segments.length)
_selectedSegment = -1;
[self tileWithChangedSegment:0];
}
@@ -141,7 +141,7 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Selects a segment.
@param aSegment the segment to select
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setSelectedSegment:(unsigned)aSegment
{
@@ -225,7 +225,7 @@ CPSegmentSwitchTrackingMomentary = 2;
Sets the width of the specified segment.
@param aWidth the new width for the segment
@param aSegment the segment to set the width for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setWidth:(float)aWidth forSegment:(unsigned)aSegment
{
@@ -237,7 +237,7 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Returns the width for the specified segment.
@param aSegment the segment to get the width for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (float)widthForSegment:(unsigned)aSegment
{
@@ -248,7 +248,7 @@ CPSegmentSwitchTrackingMomentary = 2;
Sets the image for the specified segment.
@param anImage the image for the segment
@param aSegment the segment to set the image on
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setImage:(CPImage)anImage forSegment:(unsigned)aSegment
{
@@ -262,7 +262,7 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Returns the image for the specified segment
@param aSegment the segment to obtain the image for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (CPImage)imageForSegment:(unsigned)aSegment
{
@@ -273,7 +273,7 @@ CPSegmentSwitchTrackingMomentary = 2;
Sets the label for the specified segment
@param aLabel the label for the segment
@param aSegment the segment to label
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setLabel:(CPString)aLabel forSegment:(unsigned)aSegment
{
@@ -287,7 +287,7 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Returns the label for the specified segment
@param the segment to obtain the label for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (CPString)labelForSegment:(unsigned)aSegment
{
@@ -298,7 +298,7 @@ CPSegmentSwitchTrackingMomentary = 2;
Sets the menu for the specified segment
@param aMenu the menu to set
@param aSegment the segment to set the menu on
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setMenu:(CPMenu)aMenu forSegment:(unsigned)aSegment
{
@@ -308,7 +308,7 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Returns the menu for the specified segment.
@param aSegment the segment to obtain the menu for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (CPMenu)menuForSegment:(unsigned)aSegment
{
@@ -318,9 +318,9 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Sets the selection for the specified segment. If only one segment
can be selected at a time, any other segment will be deselected.
@param isSelected <code>YES</code> selects the segment. <code>NO</code> deselects it.
@param isSelected \c YES selects the segment. \c NO deselects it.
@param aSegment the segment to set the selection for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setSelected:(BOOL)isSelected forSegment:(unsigned)aSegment
{
@@ -358,9 +358,9 @@ CPSegmentSwitchTrackingMomentary = 2;
}
/*!
Returns <code>YES</code> if the specified segment is selected.
Returns \c YES if the specified segment is selected.
@param aSegment the segment to check for selection
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (BOOL)isSelectedForSegment:(unsigned)aSegment
{
@@ -369,9 +369,9 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Enables/diables the specified segment.
@param isEnabled <code>YES</code> enables the segment
@param isEnabled \c YES enables the segment
@param aSegment the segment to enable/disble
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setEnabled:(BOOL)isEnabled forSegment:(unsigned)aSegment
{
@@ -382,9 +382,9 @@ CPSegmentSwitchTrackingMomentary = 2;
}
/*!
Returns <code>YES</code> if the specified segment is enabled.
Returns \c YES if the specified segment is enabled.
@param aSegment the segment to check
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (BOOL)isEnabledForSegment:(unsigned)aSegment
{
@@ -414,7 +414,7 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Draws the specified segment bezel
@param aSegment the segment to draw the bezel for
@param shouldHighlight <code>YES</code> highlights the bezel
@param shouldHighlight \c YES highlights the bezel
*/
- (void)drawSegmentBezel:(int)aSegment highlight:(BOOL)shouldHighlight
{
@@ -439,6 +439,16 @@ CPSegmentSwitchTrackingMomentary = 2;
return [self _leftOffsetForSegment:segment - 1] + [self widthForSegment:segment - 1] + thickness;
}
- (unsigned)_indexOfLastSegment
{
var lastSegmentIndex = [_segments count] - 1;
if (lastSegmentIndex < 0)
lastSegmentIndex = 0;
return lastSegmentIndex;
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
{
var height = [self currentValueForThemeAttribute:@"default-height"],
@@ -452,7 +462,12 @@ CPSegmentSwitchTrackingMomentary = 2;
}
else if (aName === "right-segment-bezel")
{
return CGRectMake(CGRectGetMaxX(bounds) - contentInset.right - bezelInset.right, bezelInset.top, contentInset.right, height);
var lastSegmentLeftOffset = [self _leftOffsetForSegment:[self _indexOfLastSegment]];
return CPRectMake(lastSegmentLeftOffset + [self widthForSegment:[self _indexOfLastSegment]] - contentInset.right,
bezelInset.top,
contentInset.right,
height);
}
else if (aName.substring(0, "segment-bezel".length) == "segment-bezel")
{
@@ -499,6 +514,9 @@ CPSegmentSwitchTrackingMomentary = 2;
- (void)layoutSubviews
{
if (_segments.length <= 0)
return;
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
inState:_themeStates[0]];
@@ -582,7 +600,7 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Draws the specified segment
@param aSegment the segment to draw
@param shouldHighlight <code>YES</code> highlights the bezel
@param shouldHighlight \c YES highlights the bezel
*/
- (void)drawSegment:(int)aSegment highlight:(BOOL)shouldHighlight
{
+8
View File
@@ -83,6 +83,10 @@ CPCircularSlider = 1;
if (doubleValue < _minValue)
[self setDoubleValue:_minValue];
// The relative position may have (did) change.
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
- (float)minValue
@@ -101,6 +105,10 @@ CPCircularSlider = 1;
if (doubleValue > _maxValue)
[self setDoubleValue:_maxValue];
// The relative position may have (did) change.
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
- (float)maxValue
+15 -8
View File
@@ -151,6 +151,9 @@ var CPSplitViewHorizontalImage = nil,
_DOMDividerElements = [];
#endif
// The divider changes size when pane splitter mode is toggled, so the
// subviews need to change size too.
_needsResizeSubviews = YES;
[self setNeedsDisplay:YES];
}
@@ -210,7 +213,7 @@ var CPSplitViewHorizontalImage = nil,
_DOMDividerElements[_drawingDivider].style.cursor = "move";
_DOMDividerElements[_drawingDivider].style.position = "absolute";
_DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat";
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
if (_isPaneSplitter)
@@ -224,7 +227,7 @@ var CPSplitViewHorizontalImage = nil,
_DOMDividerElements[_drawingDivider].style.backgroundImage = "url('"+_dividerImagePath+"')";
}
}
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect));
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect));
#endif
@@ -303,7 +306,7 @@ var CPSplitViewHorizontalImage = nil,
- (void)trackDivider:(CPEvent)anEvent
{
var type = [anEvent type];
if (type == CPLeftMouseUp)
{
if (_currentDivider != CPNotFound)
@@ -359,6 +362,9 @@ var CPSplitViewHorizontalImage = nil,
}
}
}
if (_currentDivider === CPNotFound)
return;
}
else if (type == CPLeftMouseDragged && _currentDivider != CPNotFound)
@@ -423,7 +429,7 @@ var CPSplitViewHorizontalImage = nil,
frameA = [viewA frame],
viewB = _subviews[dividerIndex + 1],
frameB = [viewB frame];
var realPosition = MAX(MIN(position, actualMax), actualMin);
if (position < proposedMin + (actualMin - proposedMin) / 2)
@@ -488,8 +494,9 @@ var CPSplitViewHorizontalImage = nil,
totalSizableSpace = 0;
var nonSizableSpace = totalSizableSpace ? bounds.size[_sizeComponent] - totalSizableSpace : 0,
ratio = (bounds.size[_sizeComponent] - totalDividers*dividerThickness - nonSizableSpace) / (oldSize[_sizeComponent]- totalDividers*dividerThickness - nonSizableSpace),
remainingFlexibleSpace = bounds.size[_sizeComponent] - oldSize[_sizeComponent];
remainingFlexibleSpace = bounds.size[_sizeComponent] - oldSize[_sizeComponent],
oldDimension = (oldSize[_sizeComponent]- totalDividers*dividerThickness - nonSizableSpace),
ratio = oldDimension <= 0 ? 0 : (bounds.size[_sizeComponent] - totalDividers*dividerThickness - nonSizableSpace) / oldDimension;
for (index = 0; index < count; ++index)
{
@@ -510,7 +517,7 @@ var CPSplitViewHorizontalImage = nil,
viewFrame.size[_sizeComponent] = [view frame].size[_sizeComponent];
else
alert("SHOULD NEVER GET HERE");
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
[view setFrame:viewFrame];
@@ -559,7 +566,7 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
@implementation CPSplitView (CPCoding)
/*
Initializes the split view by unarchiving data from <code>aCoder</code>.
Initializes the split view by unarchiving data from \c aCoder.
@param aCoder the coder containing the archived CPSplitView.
*/
- (id)initWithCoder:(CPCoder)aCoder
+2 -74
View File
@@ -22,13 +22,9 @@
@import <Foundation/CPString.j>
#include "CoreGraphics/CGGeometry.h"
#include "Platform/Platform.h"
@import "CPPlatformString.j"
var CPStringReferenceElement = nil,
CPStringDefaultFont = nil;
@implementation CPString (CPStringDrawing)
/*!
@@ -46,75 +42,7 @@ var CPStringReferenceElement = nil,
- (CGSize)sizeWithFont:(CPFont)aFont inWidth:(float)aWidth
{
#if PLATFORM(DOM)
if (!CPStringReferenceElement)
{
CPStringReferenceElement = document.createElement("span");
var style = CPStringReferenceElement.style;
style.position = "absolute";
style.whiteSpace = "pre";
style.visibility = "visible";
style.padding = "0px";
style.margin = "0px";
style.left = "-100000px";
style.top = "-100000px";
style.zIndex = "10000";
style.background = "red";
document.getElementsByTagName("body")[0].appendChild(CPStringReferenceElement);
}
if (!aFont)
{
if (!CPStringDefaultFont)
CPStringDefaultFont = [CPFont systemFontOfSize:12.0];
aFont = CPStringDefaultFont;
}
var style = CPStringReferenceElement.style;
if (aWidth === NULL)
{
style.width = "";
style.whiteSpace = "pre";
}
else
{
style.width = ROUND(aWidth) + "px";
if (document.attachEvent)
style.wordWrap = "break-word";
else
{
style.whiteSpace = "-o-pre-wrap";
style.whiteSpace = "-pre-wrap";
style.whiteSpace = "-moz-pre-wrap";
style.whiteSpace = "pre-wrap";
}
}
style.font = [aFont cssString];
if (CPFeatureIsCompatible(CPJavascriptInnerTextFeature))
CPStringReferenceElement.innerText = self;
else if (CPFeatureIsCompatible(CPJavascriptTextContentFeature))
CPStringReferenceElement.textContent = self;
return _CGSizeMake(CPStringReferenceElement.clientWidth, CPStringReferenceElement.clientHeight);
#endif
return _CGSizeMakeZero();
}
+ (void)_resetSize
{
CPStringReferenceElement = nil;
return [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth];
}
@end
+5 -4
View File
@@ -260,9 +260,11 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)removeTabViewItem:(CPTabViewItem)aTabViewItem
{
var index = [self indexOfTabViewItem:aTabViewItem];
[_tabViewItems removeObjectIdenticalTo:aTabViewItem];
[_labelsView tabView:self didRemoveTabViewItem:aTabViewItem];
[_labelsView tabView:self didRemoveTabViewItemAtIndex:index];
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
@@ -648,10 +650,9 @@ var _CPTabLabelsViewBackgroundColor = nil,
[self layoutSubviews];
}
- (void)tabView:(CPTabView)aTabView didRemoveTabViewItem:(CPTabViewItem)aTabViewItem
- (void)tabView:(CPTabView)aTabView didRemoveTabViewItemAtIndex:(unsigned)index
{
var index = [aTabView indexOfTabViewItem:aTabViewItem],
label = _tabLabels[index];
var label = _tabLabels[index];
[_tabLabels removeObjectAtIndex:index];
+5
View File
@@ -60,6 +60,11 @@ CPPressedTab = 2;
CPView _auxiliaryView;
}
- (id)init
{
return [self initWithIdentifier:@""];
}
/*!
Initializes the tab view item with the specified identifier.
@return the initialized CPTabViewItem
+282 -318
View File
@@ -3,7 +3,7 @@
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,12 +20,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/Foundation.j>
@import <Foundation/CPDictionary.j>
@import <Foundation/CPObject.j>
@import <Foundation/CPSortDescriptor.j>
@import <Foundation/CPString.j>
@import "CPTableHeaderView.j"
/*
@ignore
*/
/*
@global
@@ -43,389 +44,310 @@ CPTableColumnAutoresizingMask = 1;
*/
CPTableColumnUserResizingMask = 2;
#define PurgableInfoMake(aView, aRow) { view:(aView), row:(aRow) }
#define PurgableInfoView(anInfo) ((anInfo).view)
#define PurgableInfoRow(anInfo) ((anInfo).row)
/*!
@ingroup appkit
@class CPTableColumn
An CPTableColumn object mainly keeps information about the width of the column, its minimum and maximum width; whether the column can be edited or resized; and the cells used to draw the column header and the data in the column. You can change all these attributes of the column by calling the appropriate methods. Please note that the table column does not hold nor has access to the data to be displayed in the column; this data is maintained in the table view's data source.</p>
<p>Each CPTableColumn object is identified by a CPString, called the column identifier. The reason is that, after a column has been added to a table view, the user might move the columns around, so there is a need to identify the columns regardless of its position in the table.
@ignore
*/
@implementation CPTableColumn : CPObject
{
CPString _identifier;
CPView _headerView;
CPTableView _tableView;
float _width;
float _minWidth;
float _maxWidth;
unsigned _resizingMask;
CPTableView _tableView;
CPView _headerView;
CPView _dataView;
Object _dataViewData;
CPView _dataView; // default data view for this column
float _width;
float _minWidth;
float _maxWidth;
Object _dataViewData; // cache of data view archives (key=data view hash, value=data view archive)
Object _dataViewForView; // mapping from view instances back to their data view prototype (key=view instance hash, value=data view)
Object _purgableInfosForDataView; // (key=data view hash, value=)
id _identifier;
BOOL _isEditable;
CPSortDescriptor _sortDescriptorPrototype;
BOOL _isHidden;
CPString _headerToolTip;
}
/*!
Initializes the table column with the specified identifier.
@param anIdentifier the identifier
@return the initialized table column
*/
- (id)initWithIdentifier:(CPString)anIdentifier
- (id)init
{
return [self initWithIdentifier:@""];
}
- (id)initWithIdentifier:(id)anIdentifier
{
self = [super init];
if (self)
{
[self _init];
_identifier = anIdentifier;
_width = 40.0;
_minWidth = 8.0;
_maxWidth = 1000.0;
var dataView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()];
[dataView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateHighlighted];
[self setDataView:dataView];
_headerView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()];
[_headerView setBackgroundColor:[CPColor greenColor]];
_dataViewData = { };
_width = 100.0;
_minWidth = 10.0;
_maxWidth = 1000000.0;
[self setIdentifier:anIdentifier];
[self setHeaderView:[CPTextField new]];
[self setDataView:[CPTextField new]];
}
return self;
}
- (void)_init
{
_dataViewData = {};
_dataViewForView = {};
_purgableInfosForDataView = {};
}
/*!
Sets the table column's identifier
@param anIdentifier the new identifier
*/
- (void)setIdentifier:(CPString)anIdentifier
{
_identifier = anIdentifier;
}
/*!
Returns the table column's identifier
*/
- (CPString)identifier
{
return _identifier;
}
// Setting the CPTableView
/*!
Sets the table's view. This is called automatically by Cappuccino.
@param aTableView the new table view
*/
- (void)setTableView:(CPTableView)aTableView
{
_tableView = aTableView;
}
/*!
Returns the column's table view.
*/
- (CPTableView)tableView
{
return _tableView;
}
// Controlling size
/*!
Sets the column's width.
@param aWidth the new column width
*/
- (void)setWidth:(float)aWidth
{
_width = aWidth;
aWidth = +aWidth;
if (_width === aWidth)
return;
var newWidth = MIN(MAX(aWidth, [self minWidth]), [self maxWidth]);
if (_width === newWidth)
return;
var oldWidth = _width;
_width = newWidth;
var tableView = [self tableView];
if (tableView)
{
var index = [[tableView tableColumns] indexOfObjectIdenticalTo:self];
// FIXME: THIS IS HORRIBLE. Don't just reload everything when a table column changes, just relayout the changed widths.
tableView._reloadAllRows = YES;
tableView._dirtyTableColumnRangeIndex = tableView._dirtyTableColumnRangeIndex < 0 ? index : MIN(index, tableView._dirtyTableColumnRangeIndex);
[tableView tile];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPTableViewColumnDidResizeNotification
object:tableView
userInfo:[CPDictionary dictionaryWithObjects:[self, oldWidth] forKeys:[@"CPTableColumn", "CPOldWidth"]]];
}
}
/*!
Returns the column's width
*/
- (float)width
{
return _width;
}
/*!
Sets column's minimum width.
@param aWidth the new minimum column width
*/
- (void)setMinWidth:(float)aWidth
- (void)setMinWidth:(float)aMinWidth
{
if (_width < (_minWidth = aWidth))
[self setWidth:_minWidth];
aMinWidth = +aMinWidth;
if (_minWidth === aMinWidth)
return;
_minWidth = aMinWidth;
var width = [self width],
newWidth = MAX(width, [self minWidth]);
if (width !== newWidth)
[self setWidth:newWidth];
}
/*!
The column's minimum width
*/
- (float)minWidth
{
return _minWidth;
}
/*!
Sets the column's maximum width.
@param aWidth the new maximum width
*/
- (void)setMaxWidth:(float)aWidth
- (void)setMaxWidth:(float)aMaxWidth
{
if (_width > (_maxmimumWidth = aWidth))
[self setWidth:_maxWidth];
aMaxWidth = +aMaxWidth;
if (_maxWidth === aMaxWidth)
return;
_maxWidth = aMaxWidth;
var width = [self width],
newWidth = MAX(width, [self maxWidth]);
if (width !== newWidth)
[self setWidth:newWidth];
}
/*!
Sets the resizing mask. The mask is one of:
<pre>
CPTableColumnNoResizing;
CPTableColumnAutoresizingMask;
CPTableColumnUserResizingMask;
</pre>
@param aMask the new resizing mask
*/
- (void)setResizingMask:(unsigned)aMask
- (float)maxWidth
{
_resizingMask = aMask;
return _maxWidth;
}
/*!
Returns the column's resizing mask. One of:
<pre>
CPTableColumnNoResizing;
CPTableColumnAutoresizingMask;
CPTableColumnUserResizingMask;
</pre>
*/
- (unsigned)resizingMask
- (void)setResizingMask:(unsigned)aResizingMask
{
_resizingMask = aResizingMask;
}
- (float)resizingMask
{
return _resizingMask;
}
/*!
Resizes the column according to the min, max and set width.
*/
- (void)sizeToFit
{
var width = CPRectGetWidth([_headerView frame]);
if (width < _minWidth)
var width = _CGRectGetWidth([_headerView frame]);
if (width < [self minWidth])
[self setMinWidth:width];
else if (width > _maxWidth)
else if (width > [self maxWidth])
[self setMaxWidth:width]
if (_width != width)
if (_width !== width)
[self setWidth:width];
}
/*!
Sets whether the column in this data is editable.
@param aFlag <code>YES</code> means the column data is editable
*/
- (void)setEditable:(BOOL)aFlag
//Setting Component Cells
- (void)setHeaderView:(CPView)aView
{
_isEditable = aFlag;
if (!aView)
[CPException raise:CPInvalidArgumentException reason:@"Attempt to set nil header view on " + [self description]];
_headerView = aView;
var tableHeaderView = [_tableView headerView];
[tableHeaderView setNeedsLayout];
[tableHeaderView setNeedsDisplay:YES];
}
/*!
Returns <code>YES</code> if the column data is editable.
- (CPView)headerView
{
return _headerView;
}
- (void)setDataView:(CPView)aView
{
if (_dataView === aView)
return;
if (_dataView)
_dataViewData[[_dataView UID]] = nil;
_dataView = aView;
_dataViewData[[aView UID]] = [CPKeyedArchiver archivedDataWithRootObject:aView];
}
- (CPView)dataView
{
return _dataView;
}
/*
Returns the CPView object used by the CPTableView to draw values for the receiver.
By default, this method just calls dataView. Subclassers can override if they need to
potentially use different cells for different rows. Subclasses should expect this method
to be invoked with row equal to -1 in cases where no actual row is involved but the table
view needs to get some generic cell info.
*/
- (id)dataViewForRow:(int)aRowIndex
{
return [self dataView];
}
- (id)_newDataViewForRow:(int)aRowIndex
{
var dataView = [self dataViewForRow:aRowIndex],
dataViewUID = [dataView UID];
var x = [self tableView]._cachedDataViews[dataViewUID];
if (x && x.length)
return x.pop();
// if we haven't cached an archive of the data view, do it now
if (!_dataViewData[dataViewUID])
_dataViewData[dataViewUID] = [CPKeyedArchiver archivedDataWithRootObject:dataView];
// unarchive the data view cache
var newDataView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[dataViewUID]];
newDataView.identifier = dataViewUID;
return newDataView;
}
//Setting the Identifier
/*
Sets the receiver identifier to anIdentifier.
*/
- (void)setIdentifier:(id)anIdentifier
{
_identifier = anIdentifier;
}
/*
Returns the object used by the data source to identify the attribute corresponding to the receiver.
*/
- (id)identifier
{
return _identifier;
}
//Controlling Editability
/*
Controls whether the user can edit cells in the receiver by double-clicking them.
*/
- (void)setEditable:(BOOL)shouldBeEditable
{
_isEditable = shouldBeEditable;
}
/*
Returns YES if the user can edit cells associated with the receiver by double-clicking the
column in the NSTableView, NO otherwise.
*/
- (BOOL)isEditable
{
return _isEditable;
}
//Setting the column header view
/*!
Sets the view that draws the column's header.
@param aHeaderView the view that will draws the column header
*/
- (void)setHeaderView:(CPView)aView
//Sorting
- (void)setSortDescriptorPrototype:(CPSortDescriptor)aSortDescriptor
{
_headerView = aView;
_sortDescriptorPrototype = aSortDescriptor;
}
/*!
Return the view that draws the column's header
*/
- (CPView)headerView
- (CPSortDescriptor)sortDescriptorPrototype
{
return _headerView;
return _sortDescriptorPrototype;
}
/*!
Sets the data cell that draws rows in this column.
*/
- (void)setDataCell:(CPView <CPCoding>)aView
//Setting Column Visibility
- (void)setHidden:(BOOL)shouldBeHidden
{
[self setDataView:aView];
_isHidden = shouldBeHidden;
}
- (BOOL)isHidden
{
return _isHidden;
}
//Setting Tool Tips
/*
Sets the data view that draws rows in this column.
Sets the tooltip string that is displayed when the cursor pauses over the
header cell of the receiver.
*/
- (void)setDataView:(CPView <CPCoding>)aView
- (void)setHeaderToolTip:(CPString)aToolTip
{
if (_dataView)
_dataViewData[[_dataView hash]] = nil;
_dataView = aView;
_dataViewData[[aView hash]] = [CPKeyedArchiver archivedDataWithRootObject:aView];
_headerToolTip = aToolTip;
}
/*!
Returns the data cell that draws rows in this column
*/
- (CPCell)dataCell
- (CPString)headerToolTip
{
return _dataView;
}
/*
Returns the data view that draws rows in this column
*/
- (CPView)dataView
{
return [self dataCell];
}
/*!
By default returns the value from <code>dataCell</code>. This can
be overridden by a subclass to return different cells for different
rows.
@param aRowIndex the index of the row to obtain the cell for
*/
- (CPCell)dataCellForRow:(int)aRowIndex
{
return [self dataView];
}
- (CPView)dataViewForRow:(int)aRowIndex
{
return [self dataCellForRow:aRowIndex];
}
/*
- (void)_markViewAsPurgable:(CPView)aView
{
var viewHash = [aView hash],
dataViewHash = [_dataViewForView[viewHash] hash];
if (!_purgableInfosForDataView[dataViewHash])
_purgableInfosForDataView[dataViewHash] = [CPDictionary dictionary];
[_purgableInfosForDataView[dataViewHash] setObject:aView forKey:viewHash];
}
*/
- (void)_markView:(CPView)aView inRow:(unsigned)aRow asPurgable:(BOOL)isPurgable
{
var viewHash = [aView hash],
dataViewHash = [_dataViewForView[viewHash] hash];
if (!_purgableInfosForDataView[dataViewHash])
{
if (!isPurgable)
return;
_purgableInfosForDataView[dataViewHash] = {};
}
if (!isPurgable) {
if (_purgableInfosForDataView[dataViewHash][viewHash])
CPLog.warn("removing unpurgable " + _purgableInfosForDataView[dataViewHash][viewHash]);
delete _purgableInfosForDataView[dataViewHash][viewHash];
}
else
_purgableInfosForDataView[dataViewHash][viewHash] = PurgableInfoMake(aView, aRow);
}
- (CPView)_newDataViewForRow:(int)aRowIndex avoidingRows:(CPRange)rows
{
var view = [self dataViewForRow:aRowIndex],
viewHash = [view hash],
purgableInfos = _purgableInfosForDataView[viewHash];
if (purgableInfos)
{
for (var key in purgableInfos)
{
var info = purgableInfos[key];
//if (!CPLocationInRange(PurgableInfoRow(info), rows))
//{
//CPLog.debug("yes, a purged view is usable, its called: " + PurgableInfoView(info));
delete purgableInfos[key];
return PurgableInfoView(info);
//}
//else
// CPLog.warn("avoiding");
}
}
// if we haven't cached an archive of the data view, do it now
if (!_dataViewData[viewHash])
_dataViewData[viewHash] = [CPKeyedArchiver archivedDataWithRootObject:view];
// unarchive the data view cache
var newView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[viewHash]];
// map the new view's hash to it's data view prototype
_dataViewForView[[newView hash]] = view;
CPLog.warn("creating cell: %s", newView);
return newView;
}
- (void)_purge
{
for (var viewHash in _purgableInfosForDataView)
{
var purgableInfos = _purgableInfosForDataView[viewHash];
for (var key in purgableInfos)
{
var view = PurgableInfoView(purgableInfos[key]);
if (!view)
CPLog.info("key="+key+" view=" + view + " purgableInfos[key]="+purgableInfos[key])
else if (view._superview) {
//CPLog.error("PURGING: (removing)" + view);
//[view removeFromSuperview];
[view setHidden:YES];
}
//else
// CPLog.warn("PURGING: (already removed)" + view);
//delete purgableInfos[key];
}
}
return _headerToolTip;
}
@end
var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
CPTableColumnHeaderViewKey = @"CPTableColumnHeaderViewKey",
CPTableColumnDataViewKey = @"CPTableColumnDataViewKey",
@@ -438,18 +360,26 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
- (id)initWithCoder:(CPCoder)aCoder
{
[self _init];
_identifier = [aCoder decodeObjectForKey:CPTableColumnIdentifierKey];
self = [super init];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
[self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
_width = [aCoder decodeFloatForKey:CPTableColumnWidthKey];
_minWidth = [aCoder decodeFloatForKey:CPTableColumnMinWidthKey];
_maxWidth = [aCoder decodeFloatForKey:CPTableColumnMaxWidthKey];
_resizingMask = [aCoder decodeBoolForKey:CPTableColumnResizingMaskKey];
if (self)
{
_dataViewData = { };
_width = [aCoder decodeFloatForKey:CPTableColumnWidthKey];
_minWidth = [aCoder decodeFloatForKey:CPTableColumnMinWidthKey];
_maxWidth = [aCoder decodeFloatForKey:CPTableColumnMaxWidthKey];
[self setIdentifier:[aCoder decodeObjectForKey:CPTableColumnIdentifierKey]];
// [self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
// [self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
[self setHeaderView:[CPTextField new]];
[self setDataView:[CPTextField new]];
// _resizingMask = [aCoder decodeBoolForKey:CPTableColumnResizingMaskKey];
}
return self;
}
@@ -457,15 +387,49 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_identifier forKey:CPTableColumnIdentifierKey];
[aCoder encodeObject:_headerView forKey:CPTableColumnHeaderViewKey];
[aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
[aCoder encodeObject:_width forKey:CPTableColumnWidthKey];
[aCoder encodeObject:_minWidth forKey:CPTableColumnMinWidthKey];
[aCoder encodeObject:_maxWidth forKey:CPTableColumnMaxWidthKey];
[aCoder encodeObject:_resizingMask forKey:CPTableColumnResizingMaskKey];
// [aCoder encodeObject:_headerView forKey:CPTableColumnHeaderViewKey];
// [aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
// [aCoder encodeObject:_resizingMask forKey:CPTableColumnResizingMaskKey];
}
@end
@implementation CPTableColumn (NSInCompatibility)
- (void)setHeaderCell:(CPView)aView
{
[CPException raise:CPUnsupportedMethodException
reason:@"setHeaderCell: is not supported. -setHeaderCell:aView instead."];
}
- (CPView)headerCell
{
[CPException raise:CPUnsupportedMethodException
reason:@"headCell is not supported. -headerView instead."];
}
- (void)setDataCell:(CPView)aView
{
[CPException raise:CPUnsupportedMethodException
reason:@"setDataCell: is not supported. Use -setHeaderCell:aView instead."];
}
- (CPView)dataCell
{
[CPException raise:CPUnsupportedMethodException
reason:@"dataCell is not supported. Use -dataCell instead."];
}
- (id)dataCellForRow:(int)row
{
[CPException raise:CPUnsupportedMethodException
reason:@"dataCellForRow: is not supported. Use -dataViewForRow:row instead."];
}
@end
+145
View File
@@ -0,0 +1,145 @@
/*
* CPTableHeaderView.j
* AppKit
*
* Created by Ross Boucher.
* Copyright 2009 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPTableColumn.j"
@import "CPTableView.j"
@import "CPView.j"
@implementation CPTableHeaderView : CPView
{
int _resizedColumn @accessors(readonly, property=resizedColumn);
int _draggedColumn @accessors(readonly, property=draggedColumn);
float _draggedDistance @accessors(readonly, property=draggedDistance);
CPTableView _tableView @accessors(property=tableView);
}
- (void)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_resizedColumn = CPNotFound;
_draggedColumn = CPNotFound;
_draggedDistance = 0.0;
}
return self;
}
- (int)columnAtPoint:(CGPoint)aPoint
{
if (!CGRectContainsPoint([self bounds], aPoint))
return CPNotFound;
// at this point, we can essentially ignore height, because all columns have equal heights
// and that height is equal to the height of our own bounds, which we know we are inside of
var index = 0,
count = [[_tableView tableColumns] count],
tableSpacing = [_tableView intercellSpacing],
tableColumns = [_tableView tableColumns],
leftOffset = 0,
pointX = aPoint.x;
for (; index < count; index++)
{
var width = [tableColumns[index] width] + tableSpacing.width;
if (pointX >= leftOffset && pointX < leftOffset + width)
return index;
leftOffset += width;
}
return CPNotFound;
}
- (CGRect)headerRectOfColumn:(int)aColumnIndex
{
var tableColumns = [_tableView tableColumns],
tableSpacing = [_tableView intercellSpacing],
bounds = [self bounds];
if (aColumnIndex < 0 || aColumnIndex > [tableColumns count])
[CPException raise:"invalid" reason:"tried to get headerRectOfColumn: on invalid column"];
bounds.size.width = [tableColumns[aColumnIndex] width] + tableSpacing.width;
while (--aColumnIndex >= 0)
bounds.origin.x += [tableColumns[aColumnIndex] width] + tableSpacing.width;
return bounds;
}
- (void)layoutSubviews
{
var tableColumns = [_tableView tableColumns],
count = [tableColumns count],
columnRect = [self bounds],
spacing = [_tableView intercellSpacing];
for (i = 0; i < count; ++i)
{
var column = [tableColumns objectAtIndex:i],
headerView = [column headerView];
columnRect.size.width = [column width] + spacing.width;
[headerView setFrame:columnRect];
columnRect.origin.x += [column width] + spacing.width;
[self addSubview:headerView];
}
}
- (void)drawRect:(CGRect)aRect
{
[[_tableView gridColor] setStroke];
var context = [[CPGraphicsContext currentContext] graphicsPort],
exposedColumnIndexes = exposedColumnIndexes = [_tableView columnIndexesInRect:aRect],
columnsArray = [];
[exposedColumnIndexes getIndexes:columnsArray maxCount:-1 inIndexRange:nil];
var columnArrayIndex = 0,
columnArrayCount = columnsArray.length;
for(; columnArrayIndex < columnArrayCount; ++columnArrayIndex)
{
// grab each column rect and add horizontal lines
var columnToStroke = [self headerRectOfColumn:columnArrayIndex];
CGContextBeginPath(context);
CGContextMoveToPoint(context, ROUND(columnToStroke.origin.x + columnToStroke.size.width) - 0.5, ROUND(columnToStroke.origin.y) - 0.5);
CGContextAddLineToPoint(context, ROUND(columnToStroke.origin.x + columnToStroke.size.width) - 0.5, ROUND(columnToStroke.origin.y + columnToStroke.size.height) - 0.5);
CGContextSetLineWidth(context, 1);
CGContextStrokePath(context);
}
}
@end
+1677 -1137
View File
File diff suppressed because it is too large Load Diff
+158 -131
View File
@@ -30,50 +30,18 @@
#include "Platform/DOM/CPDOMDisplayServer.h"
/*
@global
@group CPLineBreakMode
*/
CPLineBreakByWordWrapping = 0;
/*
@global
@group CPLineBreakMode
*/
CPLineBreakByCharWrapping = 1;
/*
@global
@group CPLineBreakMode
*/
CPLineBreakByClipping = 2;
/*
@global
@group CPLineBreakMode
*/
CPLineBreakByTruncatingHead = 3;
/*
@global
@group CPLineBreakMode
*/
CPLineBreakByTruncatingTail = 4;
/*
@global
@group CPLineBreakMode
*/
CPLineBreakByTruncatingMiddle = 5;
/*
A textfield bezel with a squared corners.
@global
@group CPTextFieldBezelStyle
*/
CPTextFieldSquareBezel = 0;
/*
A textfield bezel with rounded corners.
@global
@group CPTextFieldBezelStyle
*/
CPTextFieldRoundedBezel = 1;
CPTextFieldSquareBezel = 0; /*! A textfield bezel with a squared corners. */
CPTextFieldRoundedBezel = 1; /*! A textfield bezel with rounded corners. */
CPTextFieldDidFocusNotification = @"CPTextFieldDidFocusNotification";
CPTextFieldDidBlurNotification = @"CPTextFieldDidBlurNotification";
#if PLATFORM(DOM)
@@ -100,7 +68,7 @@ var CPSecureTextFieldCharacter = "\u2022";
@implementation CPString (CPTextFieldAdditions)
/*!
Returns the string (<code>self</code>).
Returns the string (\c self).
*/
- (CPString)string
{
@@ -118,6 +86,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
*/
@implementation CPTextField : CPControl
{
BOOL _isEditing;
BOOL _isEditable;
BOOL _isSelectable;
BOOL _isSecure;
@@ -239,80 +209,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return true;
}
CPTextFieldKeyDownFunction = function(anEvent)
{
CPTextFieldTextDidChangeValue = [CPTextFieldInputOwner stringValue];
CPTextFieldKeyPressFunction(anEvent);
return true;
}
CPTextFieldKeyPressFunction = function(aDOMEvent)
{
aDOMEvent = aDOMEvent || window.event;
if (aDOMEvent.keyCode == CPReturnKeyCode || aDOMEvent.keyCode == CPTabKeyCode)
{
if (aDOMEvent.preventDefault)
aDOMEvent.preventDefault();
if (aDOMEvent.stopPropagation)
aDOMEvent.stopPropagation();
aDOMEvent.cancelBubble = true;
var owner = CPTextFieldInputOwner;
if (aDOMEvent && aDOMEvent.keyCode == CPReturnKeyCode)
{
[owner sendAction:[owner action] to:[owner target]];
[[owner window] makeFirstResponder:nil];
}
else if (aDOMEvent && aDOMEvent.keyCode == CPTabKeyCode)
{
if (!aDOMEvent.shiftKey)
[[owner window] selectNextKeyView:owner];
else
[[owner window] selectPreviousKeyView:owner];
}
}
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
CPTextFieldKeyUpFunction = function()
{
[CPTextFieldInputOwner setStringValue:CPTextFieldDOMInputElement.value];
if ([CPTextFieldInputOwner stringValue] !== CPTextFieldTextDidChangeValue)
{
CPTextFieldTextDidChangeValue = [CPTextFieldInputOwner stringValue];
[CPTextFieldInputOwner textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:CPTextFieldInputOwner userInfo:nil]];
}
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
CPTextFieldHandleBlur = function(anEvent)
{
var owner = CPTextFieldInputOwner;
CPTextFieldInputOwner = nil;
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
if (document.attachEvent)
{
CPTextFieldDOMInputElement.attachEvent("on" + CPDOMEventKeyUp, CPTextFieldKeyUpFunction);
CPTextFieldDOMInputElement.attachEvent("on" + CPDOMEventKeyDown, CPTextFieldKeyDownFunction);
CPTextFieldDOMInputElement.attachEvent("on" + CPDOMEventKeyPress, CPTextFieldKeyPressFunction);
}
else
{
CPTextFieldDOMInputElement.addEventListener(CPDOMEventKeyUp, CPTextFieldKeyUpFunction, NO);
CPTextFieldDOMInputElement.addEventListener(CPDOMEventKeyDown, CPTextFieldKeyDownFunction, NO);
CPTextFieldDOMInputElement.addEventListener(CPDOMEventKeyPress, CPTextFieldKeyPressFunction, NO);
}
//FIXME make this not onblur
CPTextFieldDOMInputElement.onblur = CPTextFieldBlurFunction;
@@ -389,7 +292,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
/*!
Returns <code>YES</code> if the textfield is currently editable by the user.
Returns \c YES if the textfield is currently editable by the user.
*/
- (BOOL)isEditable
{
@@ -398,7 +301,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
/*!
Sets whether the field's text is selectable by the user.
@param aFlag <code>YES</code> makes the text selectable
@param aFlag \c YES makes the text selectable
*/
- (void)setSelectable:(BOOL)aFlag
{
@@ -406,7 +309,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
/*!
Returns <code>YES</code> if the field's text is selectable by the user.
Returns \c YES if the field's text is selectable by the user.
*/
- (BOOL)isSelectable
{
@@ -415,7 +318,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
/*!
Sets whether the field's text is secure.
@param aFlag <code>YES</code> makes the text secure
@param aFlag \c YES makes the text secure
*/
- (void)setSecure:(BOOL)aFlag
{
@@ -423,7 +326,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
/*!
Returns <code>YES</code> if the field's text is secure (password entry).
Returns \c YES if the field's text is secure (password entry).
*/
- (BOOL)isSecure
{
@@ -433,7 +336,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
// Setting the Bezel Style
/*!
Sets whether the textfield will have a bezeled border.
@param shouldBeBezeled <code>YES</code> means the textfield will draw a bezeled border
@param shouldBeBezeled \c YES means the textfield will draw a bezeled border
*/
- (void)setBezeled:(BOOL)shouldBeBezeled
{
@@ -444,7 +347,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
/*!
Returns <code>YES</code> if the textfield draws a bezeled border.
Returns \c YES if the textfield draws a bezeled border.
*/
- (BOOL)isBezeled
{
@@ -478,7 +381,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
/*!
Sets whether the textfield will have a border drawn.
@param shouldBeBordered <code>YES</code> makes the textfield draw a border
@param shouldBeBordered \c YES makes the textfield draw a border
*/
- (void)setBordered:(BOOL)shouldBeBordered
{
@@ -489,7 +392,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
/*!
Returns <code>YES</code> if the textfield has a border.
Returns \c YES if the textfield has a border.
*/
- (BOOL)isBordered
{
@@ -498,7 +401,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
/*!
Sets whether the textfield will have a background drawn.
@param shouldDrawBackground <code>YES</code> makes the textfield draw a background
@param shouldDrawBackground \c YES makes the textfield draw a background
*/
- (void)setDrawsBackground:(BOOL)shouldDrawBackground
{
@@ -512,7 +415,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
/*!
Returns <code>YES</code> if the textfield draws a background.
Returns \c YES if the textfield draws a background.
*/
- (BOOL)drawsBackground
{
@@ -551,8 +454,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
/* @ignore */
- (BOOL)becomeFirstResponder
{
#if PLATFORM(DOM)
if (CPTextFieldInputOwner && [CPTextFieldInputOwner window] !== [self window])
[[CPTextFieldInputOwner window] makeFirstResponder:nil];
#endif
[self setThemeState:CPThemeStateEditing];
@@ -560,6 +465,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[self setNeedsLayout];
_isEditing = NO;
#if PLATFORM(DOM)
var string = [self stringValue],
@@ -570,6 +477,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
element.style.font = [[self currentValueForThemeAttribute:@"font"] cssString];
element.style.zIndex = 1000;
switch ([self alignment])
{
case CPCenterTextAlignment: element.style.textAlign = "center";
break;
case CPRightTextAlignment: element.style.textAlign = "right";
break;
default: element.style.textAlign = "left";
}
var contentRect = [self contentRectForBounds:[self bounds]];
element.style.top = _CGRectGetMinY(contentRect) + "px";
@@ -581,14 +497,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
window.setTimeout(function()
{
element.focus();
element.focus();
CPTextFieldInputOwner = self;
}, 0.0);
//post CPControlTextDidBeginEditingNotification
[self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
[[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES];
element.value = [self stringValue];
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
CPTextFieldInputIsActive = YES;
@@ -601,6 +516,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
document.body.onselectstart = function () {};
}
[self textDidFocus:[CPNotification notificationWithName:CPTextFieldDidFocusNotification object:self userInfo:nil]];
#endif
return YES;
@@ -647,7 +563,16 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
#endif
//post CPControlTextDidEndEditingNotification
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
if (_isEditing)
{
_isEditing = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
if ([self sendsActionOnEndEditing])
[self sendAction:[self action] to:[self target]];
}
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
return YES;
}
@@ -661,6 +586,86 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return [[self nextResponder] mouseDown:anEvent];
}
- (void)mouseUp:(CPEvent)anEvent
{
if (![self isEditable] || ![self isEnabled])
[[self nextResponder] mouseUp:anEvent];
}
- (void)mouseDragged:(CPEvent)anEvent
{
if (![self isEditable] || ![self isEnabled])
[[self nextResponder] mouseDragged:anEvent];
}
- (void)keyUp:(CPEvent)anEvent
{
var oldValue = [self stringValue];
[self _setStringValue:[self _inputElement].value];
if (oldValue !== [self stringValue])
{
if (!_isEditing)
{
_isEditing = YES;
[self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
}
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
}
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
- (void)keyDown:(CPEvent)anEvent
{
if ([anEvent keyCode] === CPReturnKeyCode)
{
if (_isEditing)
{
_isEditing = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
}
[self sendAction:[self action] to:[self target]];
[self selectText:nil];
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
}
else if ([anEvent keyCode] === CPTabKeyCode)
{
if ([anEvent modifierFlags] & CPShiftKeyMask)
[[self window] selectPreviousKeyView:self];
else
[[self window] selectNextKeyView:self];
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
}
else
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
- (void)textDidBlur:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotification:note];
}
- (void)textDidFocus:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotification:note];
}
/*!
Returns the string the text field.
*/
@@ -672,10 +677,23 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
/*
@ignore
*/
- (void)_setStringValue:(id)aValue
{
[self willChangeValueForKey:@"objectValue"];
[super setObjectValue:String(aValue)];
[self _updatePlaceholderState];
[self didChangeValueForKey:@"objectValue"];
}
- (void)setObjectValue:(id)aValue
{
[super setObjectValue:aValue];
#if PLATFORM(DOM)
if (CPTextFieldInputOwner === self)
[self _inputElement].value = aValue;
#endif
[self _updatePlaceholderState];
}
@@ -683,7 +701,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{
var string = [self stringValue];
if ((!string || [string length] === 0) && ![self hasThemeState:CPThemeStateEditing])
if ((!string || string.length === 0) && ![self hasThemeState:CPThemeStateEditing])
[self setThemeState:CPTextFieldStatePlaceholder];
else
[self unsetThemeState:CPTextFieldStatePlaceholder];
@@ -763,8 +781,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
#if PLATFORM(DOM)
var element = [self _inputElement];
if (element.parentNode == _DOMElement && ([self isEditable] || [self isSelectable]))
element.select();
if (element.parentNode === _DOMElement && ([self isEditable] || [self isSelectable]))
window.setTimeout(function() { element.select(); }, 0);
#endif
}
@@ -780,6 +798,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[defaultCenter removeObserver:_delegate name:CPControlTextDidBeginEditingNotification object:self];
[defaultCenter removeObserver:_delegate name:CPControlTextDidChangeNotification object:self];
[defaultCenter removeObserver:_delegate name:CPControlTextDidEndEditingNotification object:self];
[defaultCenter removeObserver:_delegate name:CPTextFieldDidFocusNotification object:self];
[defaultCenter removeObserver:_delegate name:CPTextFieldDidBlurNotification object:self];
}
_delegate = aDelegate;
@@ -806,6 +826,19 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
name:CPControlTextDidEndEditingNotification
object:self];
if ([_delegate respondsToSelector:@selector(controlTextDidFocus:)])
[defaultCenter
addObserver:_delegate
selector:@selector(controlTextDidFocus:)
name:CPTextFieldDidFocusNotification
object:self];
if ([_delegate respondsToSelector:@selector(controlTextDidBlur:)])
[defaultCenter
addObserver:_delegate
selector:@selector(controlTextDidBlur:)
name:CPTextFieldDidBlurNotification
object:self];
}
- (id)delegate
@@ -924,13 +957,7 @@ var secureStringForString = function(aString)
if (!aString)
return "";
var secureString = "",
length = aString.length;
while (length--)
secureString += CPSecureTextFieldCharacter;
return secureString;
return Array(aString.length+1).join(CPSecureTextFieldCharacter);
}
+32 -1
View File
@@ -531,7 +531,7 @@ function CPThemeAttributeEncode(aCoder, aThemeAttribute)
function CPThemeAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme, aClass)
{
var key = "$a" + anAttributeName;
var key = "$a" + anAttributeName;
if (![aCoder containsValueForKey:key])
var attribute = [[_CPThemeAttribute alloc] initWithName:anAttributeName defaultValue:aDefaultValue];
@@ -555,3 +555,34 @@ function CPThemeAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme,
return attribute;
}
/* TO AUTO CREATE THESE:
function bit_count(bits)
{
var count = 0;
while (bits)
{
++count;
bits &= (bits - 1);
}
return count ;
}
zeros = "000000000";
function pad(string, digits)
{
return zeros.substr(0, digits - string.length) + string;
}
var str = ""
str += '[';
for (i = 0;i < Math.pow(2,6);++i)
{
str += bit_count(i) + " /*" + pad(i.toString(2),6) + "*" + "/, ";
}
print(str+']');
*/
+10 -16
View File
@@ -58,27 +58,21 @@
- (void)bundleDidFinishLoading:(CPBundle)aBundle
{
var paths = [_bundle objectForInfoDictionaryKey:@"CPBundleReplacedFiles"],
index = 0,
count = paths.length,
bundlePath = [_bundle bundlePath];
var themes = [_bundle objectForInfoDictionaryKey:@"CPKeyedThemes"],
count = themes.length;
while (count--)
{
var path = paths[count];
if ([path pathExtension] === "keyedtheme")
{
var unarchiver = [[_CPThemeKeyedUnarchiver alloc]
initForReadingWithData:[CPData dataWithString:objj_files[bundlePath + '/' + path].contents]
bundle:_bundle];
var path = [aBundle pathForResource:themes[count]],
unarchiver = [[_CPThemeKeyedUnarchiver alloc]
initForReadingWithData:[CPData dataWithString:objj_files[path].contents]
bundle:_bundle];
[unarchiver decodeObjectForKey:@"root"];
[unarchiver decodeObjectForKey:@"root"];
[unarchiver finishDecoding];
}
[unarchiver finishDecoding];
}
[_loadDelegate blendDidFinishLoading:self];
}
+392 -203
View File
@@ -28,6 +28,8 @@
@import "CPPopUpButton.j"
@import "CPToolbarItem.j"
#include "CoreGraphics/CGGeometry.h"
/*
@global
@@ -76,9 +78,9 @@ var CPToolbarConfigurationsByIdentifier = nil;
Called to obtain a toolbar item. Required.
@param toolbar the toolbar the item belongs to
@param itemIdentifier the identifier of the toolbar item
@param flag <code>YES</code> means the item will be placed in the toolbar. <code>NO</code> means the item will be displayed for
@param flag \c YES means the item will be placed in the toolbar. \c NO means the item will be displayed for
some other purpose (non-functional)
@return the toolbar item or <code>nil</code> if no such item belongs in the toolbar
@return the toolbar item or \c nil if no such item belongs in the toolbar
*/
@implementation CPToolbar : CPObject
{
@@ -128,6 +130,11 @@ var CPToolbarConfigurationsByIdentifier = nil;
[toolbarsSharingIdentifier addObject:toolbar];
}
- (id)init
{
return [self initWithIdentifier:@""];
}
/*!
Initializes the toolbar with the specified identifier.
@param anIdentifier the identifier for the toolbar
@@ -176,7 +183,7 @@ var CPToolbarConfigurationsByIdentifier = nil;
}
/*!
Returns <code>YES</code> if the toolbar is currently visible
Returns \c YES if the toolbar is currently visible
*/
- (BOOL)isVisible
{
@@ -185,7 +192,7 @@ var CPToolbarConfigurationsByIdentifier = nil;
/*!
Sets whether the toolbar should be visible.
@param aFlag <code>YES</code> makes the toolbar visible
@param aFlag \c YES makes the toolbar visible
*/
- (void)setVisible:(BOOL)aFlag
{
@@ -304,13 +311,22 @@ var CPToolbarConfigurationsByIdentifier = nil;
}
/*!
Returns the toolbar items sorted by their <code>visibilityPriority</code>(ies).
Returns the toolbar items sorted by their \c visibilityPriority(ies).
*/
- (CPArray)itemsSortedByVisibilityPriority
{
return _itemsSortedByVisibilityPriority;
}
- (void)validateVisibleToolbarItems
{
var toolbarItems = [self visibleItems],
count = [toolbarItems count];
while (count--)
[toolbarItems[count] validate];
}
/* @ignore */
- (id)_itemForItemIdentifier:(CPString)identifier willBeInsertedIntoToolbar:(BOOL)toolbar
{
@@ -369,7 +385,7 @@ var CPToolbarIdentifierKey = "CPToolbarIdentifierKey",
@implementation CPToolbar (CPCoding)
/*
Initializes the toolbar by unarchiving data from <code>aCoder</code>.
Initializes the toolbar by unarchiving data from \c aCoder.
@param aCoder the coder containing the archived CPToolbar.
*/
- (id)initWithCoder:(CPCoder)aCoder
@@ -443,15 +459,18 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
CPIndexSet _visibleFlexibleWidthIndexes;
CPDictionary _itemInfos;
CPArray _visibleItems;
JSObject _viewsForToolbarItems;
CPArray _visibleItems @accessors(readonly, property=visibleItems);
CPArray _invisibleItems;
CPPopUpButton _additionalItemsButton;
CPColor _labelColor;
CPColor _labelShadowColor;
float _minWidth;
BOOL _FIXME_isHUD;
}
+ (void)initialize
@@ -499,108 +518,110 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
return _toolbar;
}
- (void)setLabelColor:(CPColor)aColor
- (void)FIXME_setIsHUD:(BOOL)shouldBeHUD
{
if (_labelColor === aColor)
if (_FIXME_isHUD === shouldBeHUD)
return;
_labelColor = aColor;
var items = [_toolbar items],
count = [items count];
while (count--)
[[self labelForItem:items[count]] setTextColor:_labelColor];
}
- (void)setLabelShadowColor:(CPColor)aColor
{
if (_labelShadowColor === aColor)
return;
_labelShadowColor = aColor;
_FIXME_isHUD = shouldBeHUD;
var items = [_toolbar items],
count = [items count];
while (count--)
[[self labelForItem:items[count]] setTextShadowColor:_labelShadowColor];
[[self viewForItem:items[count]] FIXME_setIsHUD:shouldBeHUD];
}
// This *should* be roughly O(3N) = O(N)
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
{
[self layoutSubviews];
[self tile];
}
- (void)layoutSubviews
- (_CPToolbarItemView)viewForItem:(CPToolbarItem)anItem
{
return _viewsForToolbarItems[[anItem UID]] || nil;
}
- (void)tile
{
// We begin by recalculating the visible items.
var items = [_toolbar items],
width = CGRectGetWidth([self bounds]),
itemsWidth = CGRectGetWidth([self bounds]),
minWidth = _minWidth,
flexibleItemIndexes = [CPIndexSet indexSet],
// FIXME: This should be a CPSet.
invisibleItemsSortedByPriority = [];
_visibleItems = items;
// We only have hidden items if our actual width is smaller than our
// minimum width for hiding items.
if (width < minWidth)
if (itemsWidth < minWidth)
{
width -= TOOLBAR_EXTRA_ITEMS_WIDTH;
itemsWidth -= TOOLBAR_EXTRA_ITEMS_WIDTH;
_visibleItems = [_visibleItems copy];
var itemsSortedByVisibilityPriority = [_toolbar itemsSortedByVisibilityPriority],
count = itemsSortedByVisibilityPriority.length;
// While our items take up too much space...
while (minWidth > width)
// Remove items until we fit:
// The assumption here is that there are more visible items than there are
// invisible items, if not it would be faster to add items until we *no
// longer fit*.
while (minWidth > itemsWidth && count)
{
var item = itemsSortedByVisibilityPriority[count--];
minWidth -= [self minWidthForItem:item] + TOOLBAR_ITEM_MARGIN;
var item = itemsSortedByVisibilityPriority[--count],
view = [self viewForItem:item];
minWidth -= [view minSize].width + TOOLBAR_ITEM_MARGIN;
[_visibleItems removeObjectIdenticalTo:item];
[invisibleItemsSortedByPriority addObject:item];
[[self viewForItem:item] setHidden:YES];
[[self labelForItem:item] setHidden:YES];
[view setHidden:YES];
[view FIXME_setIsHUD:_FIXME_isHUD];
}
}
// FIXME: minHeight?
var count = [items count],
height = 0.0;
while (count--)
{
var view = [self viewForItem:items[count]],
minSize = [view minSize];
if (height < minSize.height)
height = minSize.height;
}
// Determine all the items that have flexible width.
// Also determine the height of the toolbar.
// NOTE: height is height without top margin, and bottom margin/label.
var index = _visibleItems.length,
height = 0.0;
var count = _visibleItems.length
flexibleItemIndexes = [CPIndexSet indexSet];
while (index--)
while (count--)
{
var item = _visibleItems[index],
minSize = [item minSize],
view = [self viewForItem:item];
if (minSize.width != [item maxSize].width)
[flexibleItemIndexes addIndex:index];
// If the item doesn't have flexible width, then make sure it's set to the static width (min==max)
// This handles the case where the user did setView: with a view of a different size than minSize/maxSize
else
[view setFrameSize:CGSizeMake([item minSize].width, CGRectGetHeight([view frame]))];
var item = _visibleItems[count],
view = [self viewForItem:item],
minSize = [view minSize];
// FIXME: minHeight?
if (minSize.width !== [view maxSize].width)
[flexibleItemIndexes addIndex:count];
// FIXME: Is this still necessary? (probably not since we iterate them all below).
// If the item doesn't have flexible width, then make sure it's set to the
// static width (min==max). This handles the case where the user did setView:
// with a view of a different size than minSize/maxSize
else
[view setFrameSize:CGSizeMake(minSize.width, height)];
[view setHidden:NO];
[[self labelForItem:item] setHidden:NO];
if (height < minSize.height)
height = minSize.height;
}
var remainingSpace = width - minWidth,
var remainingSpace = itemsWidth - minWidth,
proportionate = 0.0;
// Continue to distribute space proportionately while we have it,
@@ -613,70 +634,44 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
// Reset the remaining space to 0
remainingSpace = 0.0;
var index = CPNotFound;
while ((index = [flexibleItemIndexes indexGreaterThanIndex:index]) != CPNotFound)
while ((index = [flexibleItemIndexes indexGreaterThanIndex:index]) !== CPNotFound)
{
var item = _visibleItems[index];
var item = _visibleItems[index],
view = [self viewForItem:item],
viewFrame = [view frame],
// FIXME: Should this be minWidthForItem: ?
proposedWidth = [item minSize].width + proportionate,
constrainedWidth = MIN(proposedWidth, [item maxSize].width);
proposedWidth = [view minSize].width + proportionate,
constrainedWidth = MIN(proposedWidth, [view maxSize].width);
if (constrainedWidth < proposedWidth)
{
[flexibleItemIndexes removeIndex:index];
remainingSpace += proposedWidth - constrainedWidth;
}
[view setFrameSize:CGSizeMake(constrainedWidth, CGRectGetHeight(viewFrame))];
[view setFrameSize:CGSizeMake(constrainedWidth, height)];
}
}
// Now that all the visible items are the correct width, position them accordingly.
var count = _visibleItems.length,
x = TOOLBAR_ITEM_MARGIN,
fullHeightItems = [];
// Now that all the visible items are the correct width, give them their final frames.
var index = 0,
count = _visibleItems.length,
x = TOOLBAR_ITEM_MARGIN;
for (index = 0; index < count; ++index)
for (; index < count; ++index)
{
var item = _visibleItems[index],
view = [self viewForItem:item],
viewFrame = [view frame],
viewWidth = CGRectGetWidth(viewFrame),
label = [self labelForItem:item],
labelFrame = [label frame],
labelWidth = CGRectGetWidth(labelFrame),
itemWidth = MAX([self minWidthForItem:item], viewWidth),
viewHeight = CGRectGetHeight(viewFrame);
var view = [self viewForItem:_visibleItems[index]],
viewWidth = CGRectGetWidth([view frame]);
// itemWidth != viewWidth. itemWidth is MAX(size of view, size of label). If the label is larger,
// *center* the view, don't resize it.
[view setFrame:CGRectMake(x + (itemWidth - viewWidth) / 2.0, TOOLBAR_TOP_MARGIN + (height - viewHeight) / 2.0, viewWidth, viewHeight)];
[label setFrameOrigin:CGPointMake(x + (itemWidth - labelWidth) / 2.0, TOOLBAR_TOP_MARGIN + height + 2.0)];
[view setFrame:CGRectMake(x, 0.0, viewWidth, height)];
x += itemWidth + TOOLBAR_ITEM_MARGIN;
if ([item itemIdentifier] == CPToolbarSeparatorItemIdentifier)
fullHeightItems.push(item);
}
for (index = 0, count = fullHeightItems.length; index < count; ++index)
{
var view = [self viewForItem:fullHeightItems[index]],
viewHeight = 53.0;
// FIXME: Variable Height
[view setFrame:CGRectMake(CGRectGetMinX([view frame]), (59.0 - viewHeight) / 2.0, CGRectGetWidth([view frame]), viewHeight)];
x += viewWidth + TOOLBAR_ITEM_MARGIN;
}
var needsAdditionalItemsButton = NO;
if ([invisibleItemsSortedByPriority count])
{
var index = 0,
@@ -687,27 +682,55 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
for (; index < count; ++index)
{
var item = items[index];
if ([invisibleItemsSortedByPriority indexOfObjectIdenticalTo:item] != CPNotFound)
if ([invisibleItemsSortedByPriority indexOfObjectIdenticalTo:item] !== CPNotFound)
{
[_invisibleItems addObject:item];
var identifier = [item itemIdentifier];
if (identifier !== CPToolbarSpaceItemIdentifier &&
identifier !== CPToolbarFlexibleSpaceItemIdentifier &&
identifier !== CPToolbarSeparatorItemIdentifier)
needsAdditionalItemsButton = YES;
}
}
[_additionalItemsButton setFrameOrigin:CGPointMake(width + 5.0, (CGRectGetHeight([self bounds]) - CGRectGetHeight([_additionalItemsButton frame])) / 2.0)];
}
if (needsAdditionalItemsButton)
{
[_additionalItemsButton setFrameOrigin:CGPointMake(itemsWidth + 5.0, (CGRectGetHeight([self bounds]) - CGRectGetHeight([_additionalItemsButton frame])) / 2.0)];
[self addSubview:_additionalItemsButton];
[_additionalItemsButton removeAllItems];
var index = 0,
count = [_invisibleItems count];
[_additionalItemsButton addItemWithTitle:@"Additional Items"];
[[_additionalItemsButton itemArray][0] setImage:_CPToolbarViewExtraItemsImage];
var index = 0,
count = [_invisibleItems count],
hasNonSeparatorItem = NO;
for (; index < count; ++index)
{
var item = _invisibleItems[index];
var item = _invisibleItems[index],
identifier = [item itemIdentifier];
if (identifier === CPToolbarSpaceItemIdentifier ||
identifier === CPToolbarFlexibleSpaceItemIdentifier)
continue;
if (identifier === CPToolbarSeparatorItemIdentifier)
{
if (hasNonSeparatorItem)
[_additionalItemsButton addItem:[CPMenuItem separatorItem]];
continue;
}
hasNonSeparatorItem = YES;
[_additionalItemsButton addItemWithTitle:[item label]];
var menuItem = [_additionalItemsButton itemArray][index + 1];
@@ -723,36 +746,6 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
}
- (CPView)viewForItem:(CPToolbarItem)anItem
{
var info = [_itemInfos objectForKey:[anItem hash]];
if (!info)
return nil;
return info.view;
}
- (CPTextField)labelForItem:(CPToolbarItem)anItem
{
var info = [_itemInfos objectForKey:[anItem hash]];
if (!info)
return nil;
return info.label;
}
- (float)minWidthForItem:(CPToolbarItem)anItem
{
var info = [_itemInfos objectForKey:[anItem hash]];
if (!info)
return 0;
return info.minWidth;
}
- (void)reloadToolbarItems
{
// Get rid of all our current subviews.
@@ -767,63 +760,22 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
index = 0;
count = items.length;
_itemInfos = [CPDictionary dictionary];
_minWidth = TOOLBAR_ITEM_MARGIN;
_viewsForToolbarItems = { };
for (; index < count; ++index)
{
var item = items[index],
view = [item view];
// If this item doesn't have a custom view, create a standard one.
if (!view)
{
view = [[CPButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 32.0, 32.0)];
[view setBordered:NO];
[view setImage:[item image]];
[view setAlternateImage:[item alternateImage]];
[view setTarget:[item target]];
[view setAction:[item action]];
[view setTag:[item tag]];
[view setImagePosition:CPImageOnly];
}
view = [[_CPToolbarItemView alloc] initWithToolbarItem:item toolbar:self];
_viewsForToolbarItems[[item UID]] = view;
[self addSubview:view];
// Create a lable for this item.
var label = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[label setStringValue:[item label]];
[label setFont:[CPFont systemFontOfSize:11.0]];
[label setTextColor:_labelColor];
[label setTextShadowColor:_labelShadowColor];
[label setTextShadowOffset:CGSizeMake(0, 1)];
[label sizeToFit];
[label setTarget:[item target]];
[label setAction:[item action]];
[self addSubview:label];
var minSize = [item minSize],
minWidth = MAX(minSize.width, CGRectGetWidth([label frame]));
[_itemInfos setObject:_CPToolbarItemInfoMake(index, view, label, minWidth) forKey:[item hash]];
_minWidth += minWidth + TOOLBAR_ITEM_MARGIN;
// If the minSize is different than the maxSize, then this item has flexible width.
//if (minSize.width != [item maxSize].width)
// [_flexibleWidthIndexes addIndex:index];
_minWidth += [view minSize].width + TOOLBAR_ITEM_MARGIN;
}
[self layoutSubviews];
[self tile];
}
@end
@@ -842,3 +794,240 @@ var _CPToolbarItemVisibilityPriorityCompare = function(lhs, rhs)
return CPOrderedDescending;
}
var TOP_MARGIN = 5.0,
LABEL_MARGIN = 2.0;
@implementation _CPToolbarItemView : CPControl
{
CGSize _minSize @accessors(readonly, property=minSize);
CGSize _maxSize @accessors(readonly, property=maxSize);
CGSize _labelSize;
CPToolbarItem _toolbarItem;
CPToolbar _toolbar;
CPImageView _imageView;
CPView _view;
CPTextField _labelField;
BOOL _FIXME_isHUD;
}
- (id)initWithToolbarItem:(CPToolbarItem)aToolbarItem toolbar:(CPToolbar)aToolbar
{
self = [super init];
if (self)
{
_toolbarItem = aToolbarItem;
_labelField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_labelField setFont:[CPFont systemFontOfSize:11.0]];
[_labelField setTextColor:[self FIXME_labelColor]];
[_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
[_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_labelField setAutoresizingMask:CPViewWidthSizable | CPViewMinXMargin];
[self addSubview:_labelField];
[self updateFromItem];
_toolbar = aToolbar;
[_toolbarItem addObserver:self forKeyPath:"enabled" options:0 context:NULL];
}
return self;
}
- (void)FIXME_setIsHUD:(BOOL)shouldBeHUD
{
_FIXME_isHUD = shouldBeHUD;
[_labelField setTextColor:[self FIXME_labelColor]];
[_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
}
- (void)updateFromItem
{
var identifier = [_toolbarItem itemIdentifier];
if (identifier === CPToolbarSpaceItemIdentifier ||
identifier === CPToolbarFlexibleSpaceItemIdentifier ||
identifier === CPToolbarSeparatorItemIdentifier)
{
[_view removeFromSuperview];
[_imageView removeFromSuperview];
_minSize = [_toolbarItem minSize];
_maxSize = [_toolbarItem maxSize];
if (identifier === CPToolbarSeparatorItemIdentifier)
{
_view = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 2.0, 32.0)];
// FIXME: Get rid of this old API!!!
sizes = {};
sizes[@"CPToolbarItemSeparator"] = [CGSizeMake(2.0, 26.0), CGSizeMake(2.0, 1.0), CGSizeMake(2.0, 26.0)];
[_view setBackgroundColor:_CPControlThreePartImagePattern(YES, sizes, @"CPToolbarItem", @"Separator")];
[self addSubview:_view];
}
return;
}
[self setTarget:[_toolbarItem target]];
[self setAction:[_toolbarItem action]];
var view = [_toolbarItem view] || nil;
if (view !== _view)
{
if (!view)
[_view removeFromSuperview];
else
{
[self addSubview:view];
[_imageView removeFromSuperview];
}
_view = view;
}
if (!_view)
{
if (!_imageView)
{
_imageView = [[CPImageView alloc] initWithFrame:[self bounds]];
[_imageView setImageScaling:CPScaleNone];
[self addSubview:_imageView];
}
[_imageView setImage:[_toolbarItem image]];
}
var minSize = [_toolbarItem minSize],
maxSize = [_toolbarItem maxSize];
[_labelField setStringValue:[_toolbarItem label]];
[_labelField sizeToFit]; // FIXME
_labelSize = [_labelField frame].size;
_minSize = CGSizeMake(MAX(_labelSize.width, minSize.width), _labelSize.height + minSize.height + LABEL_MARGIN + TOP_MARGIN);
_maxSize = CGSizeMake(MAX(_labelSize.width, minSize.width), 100000000.0);
[_toolbar tile];
}
- (void)layoutSubviews
{
var identifier = [_toolbarItem itemIdentifier];
if (identifier === CPToolbarSpaceItemIdentifier ||
identifier === CPToolbarFlexibleSpaceItemIdentifier)
return;
var bounds = [self bounds],
width = _CGRectGetWidth(bounds);
if (identifier === CPToolbarSeparatorItemIdentifier)
return [_view setFrame:CGRectMake(ROUND((width - 2.0) / 2.0), 0.0, 2.0, _CGRectGetHeight(bounds))];
var view = _view || _imageView,
itemMaxSize = [_toolbarItem maxSize],
height = _CGRectGetHeight(bounds) - _labelSize.height - LABEL_MARGIN - TOP_MARGIN,
viewWidth = MIN(itemMaxSize.width, width),
viewHeight = MIN(itemMaxSize.height, height);
[view setFrame:CGRectMake( ROUND((width - viewWidth) / 2.0),
TOP_MARGIN + ROUND((height - viewHeight) / 2.0),
viewWidth,
viewHeight)];
[_labelField setFrameOrigin:CGPointMake(ROUND((width - _labelSize.width) / 2.0), TOP_MARGIN + height + LABEL_MARGIN)];
}
- (void)mouseDown:(CPEvent)anEvent
{
if ([_toolbarItem view])
return;
[super mouseDown:anEvent];
}
- (void)setEnabled:(BOOL)shouldBeEnabled
{
[super setEnabled:shouldBeEnabled];
if (shouldBeEnabled)
{
[_imageView setAlphaValue:1.0];
[_labelField setAlphaValue:1.0];
}
else
{
[_imageView setAlphaValue:0.5];
[_labelField setAlphaValue:0.5];
}
}
- (CPColor)FIXME_labelColor
{
if (_FIXME_isHUD)
return [CPColor whiteColor];
return [CPColor blackColor];
}
- (CPColor)FIXME_labelShadowColor
{
if (_FIXME_isHUD)
return [self isHighlighted] ? [CPColor colorWithWhite:1.0 alpha:0.5] : [CPColor clearColor];
return [self isHighlighted] ? [CPColor colorWithWhite:0.0 alpha:0.3] : [CPColor colorWithWhite:1.0 alpha:0.75];
}
- (void)setHighlighted:(BOOL)shouldBeHighlighted
{
[super setHighlighted:shouldBeHighlighted];
if (shouldBeHighlighted)
{
var alternateImage = [_toolbarItem alternateImage];
if (alternateImage)
[_imageView setImage:alternateImage];
[_labelField setTextShadowOffset:CGSizeMakeZero()];
}
else
{
var image = [_toolbarItem image];
if (image)
[_imageView setImage:image];
[_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
}
[_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath
ofObject:(id)anObject
change:(CPDictionary)aChange
context:(id)aContext
{
// FIXME: Not clear if -synchronizeWindowTitleWithDocumentName is the best way to go.
if (aKeyPath === "enabled")
[self setEnabled:[anObject isEnabled]];
}
@end
+65 -46
View File
@@ -65,9 +65,9 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
@implementation CPToolbarItem : CPObject
{
CPString _itemIdentifier;
CPToolbar _toolbar;
CPString _label;
CPString _paletteLabel;
CPString _toolTip;
@@ -77,13 +77,20 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
BOOL _isEnabled;
CPImage _image;
CPImage _alternateImage;
CPView _view;
CGSize _minSize;
CGSize _maxSize;
int _visibilityPriority;
BOOL _autovalidates;
}
- (id)init
{
return [self initWithItemIdentifier:@""];
}
// Creating a Toolbar Item
@@ -223,7 +230,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
}
/*!
Sets the target of the action that is triggered when the user clicks this item. <code>nil</code> will cause
Sets the target of the action that is triggered when the user clicks this item. \c nil will cause
the action to be passed on to the first responder.
@param aTarget the new target
*/
@@ -261,7 +268,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
}
/*!
Returns <code>YES</code> if the item is enabled.
Returns \c YES if the item is enabled.
*/
- (BOOL)isEnabled
{
@@ -273,7 +280,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
/*!
Sets whether the item is enabled.
@param aFlag <code>YES</code> enables the item
@param aFlag \c YES enables the item
*/
- (void)setEnabled:(BOOL)shouldBeEnabled
{
@@ -444,6 +451,48 @@ CPToolbarItemVisibilityPriorityUser
_visibilityPriority = aVisibilityPriority;
}
- (void)validate
{
// View items do not do any target-action analysis.
if (_view)
{
if ([target respondsToSelector:@selector(validateToolbarItem:)])
[self setEnabled:[target validateToolbarItem:self]];
return;
}
var action = [self action];
if (!action)
return [self setEnabled:NO];
var target = [self target];
if (target && ![target respondsToSelector:action])
return [self setEnabled:NO];
target = [CPApp targetForAction:action to:target from:self];
if (!target)
return [self setEnabled:NO];
if ([target respondsToSelector:@selector(validateToolbarItem:)])
[self setEnabled:[target validateToolbarItem:self]];
else
[self setEnabled:YES];
}
- (BOOL)autovalidates
{
return _autovalidates;
}
- (void)setAutovalidates:(BOOL)shouldAutovalidate
{
_autovalidates = !!shouldAutovalidate;
}
@end
@implementation CPToolbarItem (CPCopying)
@@ -458,15 +507,16 @@ CPToolbarItemVisibilityPriorityUser
[copy setLabel:_label];
[copy setPaletteLabel:_paletteLabel];
[copy setToolTip:[self toolTip]];
[copy setTag:[self tag]];
[copy setTarget:[self target]];
[copy setAction:[self action]];
[copy setEnabled:[self isEnabled]];
[copy setImage:_image];
[copy setAlternateImage:_alternateImage];
[copy setImage:[self image]];
[copy setAlternateImage:[self alternateImage]];
[copy setMinSize:_minSize];
[copy setMaxSize:_maxSize];
@@ -479,33 +529,8 @@ CPToolbarItemVisibilityPriorityUser
// Standard toolbar identifiers
var _CPToolbarSeparatorItemView = nil,
_CPToolbarSpaceItemView = nil;
@implementation CPToolbarItem (Standard)
+ (CPView)_separatorItemView
{
if (!_CPToolbarSeparatorItemView)
{
_CPToolbarSeparatorItemView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 2.0, 32.0)];
sizes = {};
sizes[@"CPToolbarItemSeparator"] = [CGSizeMake(2.0, 26.0), CGSizeMake(2.0, 1.0), CGSizeMake(2.0, 26.0)];
[_CPToolbarSeparatorItemView setBackgroundColor:_CPControlThreePartImagePattern(YES, sizes, @"CPToolbarItem", @"Separator")];
}
return _CPToolbarSeparatorItemView;
}
+ (CPView)_spaceItemView
{
if (!_CPToolbarSpaceItemView)
_CPToolbarSpaceItemView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
return _CPToolbarSpaceItemView;
}
/* @ignore */
+ (CPToolbarItem)_standardItemWithItemIdentifier:(CPString)anItemIdentifier
{
@@ -513,23 +538,17 @@ var _CPToolbarSeparatorItemView = nil,
switch (anItemIdentifier)
{
case CPToolbarSeparatorItemIdentifier: [item setView:[self _separatorItemView]];
[item setMinSize:CGSizeMake(2.0, 0.0)];
case CPToolbarSeparatorItemIdentifier: [item setMinSize:CGSizeMake(2.0, 0.0)];
[item setMaxSize:CGSizeMake(2.0, 100000.0)];
return item;
case CPToolbarSpaceItemIdentifier: [item setView:[self _spaceItemView]];
[item setMinSize:CGSizeMake(32.0, 32.0)];
case CPToolbarSpaceItemIdentifier: [item setMinSize:CGSizeMake(32.0, 32.0)];
[item setMaxSize:CGSizeMake(32.0, 32.0)];
return item;
case CPToolbarFlexibleSpaceItemIdentifier: [item setView:[self _spaceItemView]];
[item setMinSize:CGSizeMake(32.0, 32.0)];
case CPToolbarFlexibleSpaceItemIdentifier: [item setMinSize:CGSizeMake(32.0, 32.0)];
[item setMaxSize:CGSizeMake(10000.0, 32.0)];
return item;
+82
View File
@@ -0,0 +1,82 @@
@import <Foundation/CPObject.j>
@implementation CPTreeNode : CPObject
{
id _representedObject @accessors(readonly, property=representedObject);
CPTreeNode _parentNode @accessors(readonly, property=parentNode);
CPMutableArray _childNodes @accessors(readonly, property=childNodes);
}
+ (id)treeNodeWithRepresentedObject:(id)anObject
{
return [[self alloc] initWithRepresentedObject:anObject];
}
- (id)initWithRepresentedObject:(id)anObject
{
self = [super init];
if (self)
{
_representedObject = anObject;
_childNodes = [];
}
return self;
}
- (BOOL)isLeaf
{
return [_childNodes count] <= 0;
}
- (CPMutableArray)mutableChildNodes
{
return [self mutableArrayValueForKey:@"childNodes"];
}
- (void)insertObject:(id)anObject inChildNodesAtIndex:(CPInteger)anIndex
{
anObject._parentNode = self;
[_childNodes addObject:anObject];
}
- (void)removeObjectFromChildNodesAtIndex:(CPInteger)anIndex
{
[_childNodes objectAtIndex:anIndex]._parentNode = nil;
[_childNodes removeObjectAtIndex:anIndex];
}
- (void)replaceObjectFromChildNodesAtIndex:(CPInteger)anIndex withObject:(id)anObject
{
var oldObject = [_childNodes objectAtIndex:anIndex];
oldObject._parentNode = nil;
[_childNodes replaceObjectAtIndex:anIndex withObject:anObject];
}
- (id)objectInChildNodesAtIndex:(CPInteger)anIndex
{
return _childNodes[anIndex];
}
- (void)sortWithSortDescriptors:(CPArray)sortDescriptors recursively:(BOOL)shouldSortRecursively
{
[_childNodes sortUsingDescriptors:sortDescriptors];
if (!shouldSortRecursively)
return;
var count = [_childNodes count];
while (count--)
[_childNodes[count] sortWithSortDescriptors:sortDescriptors recursively:YES];
}
@end
+205 -114
View File
@@ -27,11 +27,11 @@
@import "CGGeometry.j"
@import "CPColor.j"
@import "CPDOMDisplayServer.j"
@import "CPGeometry.j"
@import "CPGraphicsContext.j"
@import "CPResponder.j"
@import "CPTheme.j"
@import "_CPDisplayServer.j"
#include "Platform/Platform.h"
@@ -94,12 +94,13 @@ var DOMElementPrototype = nil,
BackgroundTrivialColor = 0,
BackgroundVerticalThreePartImage = 1,
BackgroundHorizontalThreePartImage = 2,
BackgroundNinePartImage = 3,
CustomDrawRectViews = {},
CustomLayoutSubviewsViews = {};
BackgroundNinePartImage = 3;
#endif
var CPViewFlags = { },
CPViewHasCustomDrawRect = 1 << 0,
CPViewHasCustomLayoutSubviews = 1 << 1;
/*!
@ingroup appkit
@class CPView
@@ -113,7 +114,7 @@ var DOMElementPrototype = nil,
headed by the window's content view. Every other view in a window is a descendant
of this view.</p>
<p>Subclasses can override <code>-drawRect:</code> in order to implement their
<p>Subclasses can override \c -drawRect: in order to implement their
appearance. Other methods of CPView and CPResponder can
also be overridden to handle user generated events.
*/
@@ -143,8 +144,6 @@ var DOMElementPrototype = nil,
BOOL _postsBoundsChangedNotifications;
BOOL _inhibitFrameAndBoundsChangedNotifications;
CPString _displayHash;
#if PLATFORM(DOM)
DOMElement _DOMElement;
DOMElement _DOMContentsElement;
@@ -180,9 +179,14 @@ var DOMElementPrototype = nil,
JSObject _themeAttributes;
unsigned _themeState;
JSObject _ephemeralSubviewsForNames;
CPSet _ephereralSubviews;
// Key View Support
CPView _nextKeyView;
CPView _previousKeyView;
unsigned _viewClassFlags;
}
/*
@@ -208,6 +212,32 @@ var DOMElementPrototype = nil,
CachedNotificationCenter = [CPNotificationCenter defaultCenter];
}
- (void)setupViewFlags
{
var theClass = [self class],
classUID = [theClass UID];
if (CPViewFlags[classUID] === undefined)
{
var flags = 0;
if ([theClass instanceMethodForSelector:@selector(drawRect:)] !== [CPView instanceMethodForSelector:@selector(drawRect:)])
flags |= CPViewHasCustomDrawRect;
if ([theClass instanceMethodForSelector:@selector(layoutSubviews)] !== [CPView instanceMethodForSelector:@selector(layoutSubviews)])
flags |= CPViewHasCustomLayoutSubviews;
CPViewFlags[classUID] = flags;
}
_viewClassFlags = CPViewFlags[classUID];
}
+ (CPSet)keyPathsForValuesAffectingFrame
{
return [CPSet setWithObjects:@"frameOrigin", @"frameSize"];
}
- (id)init
{
return [self initWithFrame:CGRectMakeZero()];
@@ -242,11 +272,9 @@ var DOMElementPrototype = nil,
_isHidden = NO;
_hitTests = YES;
_displayHash = [self hash];
#if PLATFORM(DOM)
_DOMElement = DOMElementPrototype.cloneNode(false);
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(aFrame), _CGRectGetMinY(aFrame));
CPDOMDisplayServerSetStyleSize(_DOMElement, width, height);
@@ -257,6 +285,8 @@ var DOMElementPrototype = nil,
_theme = [CPTheme defaultTheme];
_themeState = CPThemeStateNormal;
[self setupViewFlags];
[self _loadThemeAttributes];
}
@@ -299,10 +329,10 @@ var DOMElementPrototype = nil,
}
/*!
Makes <code>aSubview</code> a subview of the receiver. It is positioned relative to <code>anotherView</code>
Makes \c aSubview a subview of the receiver. It is positioned relative to \c anotherView
@param aSubview the view to add as a subview
@param anOrderingMode specifies <code>aSubview</code>'s ordering relative to <code>anotherView</code>
@param anotherView <code>aSubview</code> will be positioned relative to this argument
@param anOrderingMode specifies \c aSubview's ordering relative to \c anotherView
@param anotherView \c aSubview will be positioned relative to this argument
*/
- (void)addSubview:(CPView)aSubview positioned:(CPWindowOrderingMode)anOrderingMode relativeTo:(CPView)anotherView
{
@@ -390,7 +420,7 @@ var DOMElementPrototype = nil,
}
/*!
Called when the receiver has added <code>aSubview</code> to it's child views.
Called when the receiver has added \c aSubview to it's child views.
@param aSubview the view that was added
*/
- (void)didAddSubview:(CPView)aSubview
@@ -474,7 +504,7 @@ var DOMElementPrototype = nil,
}
/*!
Returns <code>YES</code> if the receiver is, or is a descendant of, <code>aView</code>.
Returns \c YES if the receiver is, or is a descendant of, \c aView.
@param aView the view to test for ancestry
*/
- (BOOL)isDescendantOf:(CPView)aView
@@ -532,7 +562,7 @@ var DOMElementPrototype = nil,
/*!
Returns the menu item containing the receiver or one of its ancestor views.
@return a menu item, or <code>nil</code> if the view or one of its ancestors wasn't found
@return a menu item, or \c nil if the view or one of its ancestors wasn't found
*/
- (CPMenuItem)enclosingMenuItem
{
@@ -585,7 +615,7 @@ var DOMElementPrototype = nil,
/*!
Returns whether the view is flipped.
@return <code>YES</code> if the view is flipped. <code>NO</code>, otherwise.
@return \c YES if the view is flipped. \c NO, otherwise.
*/
- (BOOL)isFlipped
{
@@ -624,6 +654,16 @@ var DOMElementPrototype = nil,
return _CGRectMakeCopy(_frame);
}
- (CGPoint)frameOrigin
{
return _CGPointMakeCopy(_frame.origin);
}
- (CGSize)frameSize
{
return _CGSizeMakeCopy(_frame.size);
}
/*!
Moves the center of the receiver's frame to the provided point. The point is defined in the superview's coordinate system.
The method posts a CPViewFrameDidChangeNotification to the default notification center if the receiver
@@ -666,12 +706,14 @@ var DOMElementPrototype = nil,
[CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
#if PLATFORM(DOM)
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, _superview ? _superview._boundsTransform : NULL, origin.x, origin.y);
var transform = _superview ? _superview._boundsTransform : NULL;
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, transform, origin.x, origin.y);
#endif
}
/*!
Sets the receiver's frame size. If <code>aSize</code> is the same as the frame's current dimensions, this
Sets the receiver's frame size. If \c aSize is the same as the frame's current dimensions, this
method simply returns. The method posts a CPViewFrameDidChangeNotification to the
default notification center if the receiver is configured to do so.
@param aSize the new size for the frame
@@ -888,7 +930,7 @@ var DOMElementPrototype = nil,
}
/*!
Initiates <code>superviewSizeChanged:</code> messages to subviews.
Initiates \c -superviewSizeChanged: messages to subviews.
@param aSize the size for the subviews
*/
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
@@ -901,9 +943,9 @@ var DOMElementPrototype = nil,
/*!
Specifies whether the receiver view should automatically resize its
subviews when its <code>setFrameSize:</code> method receives a change.
@param aFlag If <code>YES</code>, then subviews will automatically be resized
when this view is resized. <code>NO</code> means the views will not
subviews when its \c -setFrameSize: method receives a change.
@param aFlag If \c YES, then subviews will automatically be resized
when this view is resized. \c NO means the views will not
be resized automatically.
*/
- (void)setAutoresizesSubviews:(BOOL)aFlag
@@ -913,7 +955,7 @@ var DOMElementPrototype = nil,
/*!
Reports whether the receiver automatically resizes its subviews when its frame size changes.
@return <code>YES</code> means it resizes its subviews on a frame size change.
@return \c YES means it resizes its subviews on a frame size change.
*/
- (BOOL)autoresizesSubviews
{
@@ -956,7 +998,7 @@ var DOMElementPrototype = nil,
{
_fullScreenModeState = _CPViewFullScreenModeStateMake(self);
var fullScreenWindow = [[CPWindow alloc] initWithContentRect:[[CPDOMWindowBridge sharedDOMWindowBridge] contentBounds] styleMask:CPBorderlessWindowMask];
var fullScreenWindow = [[CPWindow alloc] initWithContentRect:[[CPPlatformWindow primaryPlatformWindow] contentBounds] styleMask:CPBorderlessWindowMask];
[fullScreenWindow setLevel:CPScreenSaverWindowLevel];
[fullScreenWindow setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
@@ -1005,7 +1047,7 @@ var DOMElementPrototype = nil,
}
/*!
Returns <code>YES</code> if the receiver is currently in full screen mode.
Returns \c YES if the receiver is currently in full screen mode.
*/
- (BOOL)isInFullScreenMode
{
@@ -1014,7 +1056,7 @@ var DOMElementPrototype = nil,
/*!
Sets whether the receiver should be hidden.
@param aFlag <code>YES</code> makes the receiver hidden.
@param aFlag \c YES makes the receiver hidden.
*/
- (void)setHidden:(BOOL)aFlag
{
@@ -1050,7 +1092,7 @@ var DOMElementPrototype = nil,
}
/*!
Returns <code>YES</code> if the receiver is hidden.
Returns \c YES if the receiver is hidden.
*/
- (BOOL)isHidden
{
@@ -1094,8 +1136,8 @@ var DOMElementPrototype = nil,
}
/*!
Returns <code>YES</code> if the receiver is hidden, or one
of it's ancestor views is hidden. <code>NO</code>, otherwise.
Returns \c YES if the receiver is hidden, or one
of it's ancestor views is hidden. \c NO, otherwise.
*/
- (BOOL)isHiddenOrHasHiddenAncestor
{
@@ -1108,9 +1150,9 @@ var DOMElementPrototype = nil,
}
/*!
Returns whether the receiver should be sent a <code>mouseDown:</code> message for <code>anEvent</code>.<br/>
Returns <code>YES</code> by default.
@return <code>YES</code>, if the view object accepts first mouse-down event. <code>NO</code>, otherwise.
Returns whether the receiver should be sent a \c -mouseDown: message for \c anEvent.<br/>
Returns \c YES by default.
@return \c YES, if the view object accepts first mouse-down event. \c NO, otherwise.
*/
//FIXME: should be NO by default?
- (BOOL)acceptsFirstMouse:(CPEvent)anEvent
@@ -1120,7 +1162,7 @@ var DOMElementPrototype = nil,
/*!
Returns whether or not the view responds to hit tests.
@return <code>YES</code> if this view listens to hitTest messages, <code>NO</code> otherwise.
@return \c YES if this view listens to \c -hitTest messages, \c NO otherwise.
*/
- (BOOL)hitTests
{
@@ -1129,7 +1171,7 @@ var DOMElementPrototype = nil,
/*!
Set whether or not the view should respond to hit tests.
@param shouldHitTest should be <code>YES</code> if this view should respond to hit tests, <code>NO</code> otherwise.
@param shouldHitTest should be \c YES if this view should respond to hit tests, \c NO otherwise.
*/
- (void)setHitTests:(BOOL)shouldHitTest
{
@@ -1161,8 +1203,8 @@ var DOMElementPrototype = nil,
}
/*!
Returns <code>YES</code> if mouse events aren't needed by the receiver and can be sent to the superview. The
default implementation returns <code>NO</code> if the view is opaque.
Returns \c YES if mouse events aren't needed by the receiver and can be sent to the superview. The
default implementation returns \c NO if the view is opaque.
*/
- (BOOL)mouseDownCanMoveWindow
{
@@ -1208,7 +1250,7 @@ var DOMElementPrototype = nil,
amount = 0 - _DOMImageParts.length;
}
if (amount > 0)
while (amount--)
{
@@ -1236,16 +1278,16 @@ var DOMElementPrototype = nil,
else
{
var slices = [patternImage imageSlices],
count = slices.length,
count = MIN(_DOMImageParts.length, slices.length),
frameSize = _frame.size;
while (count--)
{
var image = slices[count],
size = _DOMImageSizes[count] = image ? [image size] : _CGSizeMakeZero();
CPDOMDisplayServerSetStyleSize(_DOMImageParts[count], size.width, size.height);
_DOMImageParts[count].style.background = image ? "url(\"" + [image filename] + "\")" : "";
}
@@ -1300,7 +1342,7 @@ var DOMElementPrototype = nil,
// Converting Coordinates
/*!
Converts <code>aPoint</code> from the coordinate space of <code>aView</code> to the coordinate space of the receiver.
Converts \c aPoint from the coordinate space of \c aView to the coordinate space of the receiver.
@param aPoint the point to convert
@param aView the view space to convert from
@return the converted point
@@ -1311,7 +1353,7 @@ var DOMElementPrototype = nil,
}
/*!
Converts <code>aPoint</code> from the receiver's coordinate space to the coordinate space of <code>aView</code>.
Converts \c aPoint from the receiver's coordinate space to the coordinate space of \c aView.
@param aPoint the point to convert
@param aView the coordinate space to which the point will be converted
@return the converted point
@@ -1322,7 +1364,7 @@ var DOMElementPrototype = nil,
}
/*!
Convert's <code>aSize</code> from <code>aView</code>'s coordinate space to the receiver's coordinate space.
Convert's \c aSize from \c aView's coordinate space to the receiver's coordinate space.
@param aSize the size to convert
@param aView the coordinate space to convert from
@return the converted size
@@ -1333,7 +1375,7 @@ var DOMElementPrototype = nil,
}
/*!
Convert's <code>aSize</code> from the receiver's coordinate space to <code>aView</code>'s coordinate space.
Convert's \c aSize from the receiver's coordinate space to \c aView's coordinate space.
@param aSize the size to convert
@param the coordinate space to which the size will be converted
@return the converted size
@@ -1344,7 +1386,7 @@ var DOMElementPrototype = nil,
}
/*!
Converts <code>aRect</code> from <code>aView</code>'s coordinate space to the receiver's space.
Converts \c aRect from \c aView's coordinate space to the receiver's space.
@param aRect the rectangle to convert
@param aView the coordinate space from which to convert
@return the converted rectangle
@@ -1355,7 +1397,7 @@ var DOMElementPrototype = nil,
}
/*!
Converts <code>aRect</code> from the receiver's coordinate space to <code>aView</code>'s coordinate space.
Converts \c aRect from the receiver's coordinate space to \c aView's coordinate space.
@param aRect the rectangle to convert
@param aView the coordinate space to which the rectangle will be converted
@return the converted rectangle
@@ -1367,14 +1409,14 @@ var DOMElementPrototype = nil,
/*!
Sets whether the receiver posts a CPViewFrameDidChangeNotification notification
to the default notification center when its frame is changed. The default is <code>NO</code>.
to the default notification center when its frame is changed. The default is \c NO.
Methods that could cause a frame change notification are:
<pre>
setFrame:
setFrameSize:
setFrameOrigin:
</pre>
@param shouldPostFrameChangedNotifications <code>YES</code> makes the receiver post
@param shouldPostFrameChangedNotifications \c YES makes the receiver post
notifications on frame changes (size or origin)
*/
- (void)setPostsFrameChangedNotifications:(BOOL)shouldPostFrameChangedNotifications
@@ -1391,7 +1433,7 @@ setFrameOrigin:
}
/*!
Returns <code>YES</code> if the receiver posts a CPViewFrameDidChangeNotification if its frame is changed.
Returns \c YES if the receiver posts a CPViewFrameDidChangeNotification if its frame is changed.
*/
- (BOOL)postsFrameChangedNotifications
{
@@ -1400,14 +1442,14 @@ setFrameOrigin:
/*!
Sets whether the receiver posts a CPViewBoundsDidChangeNotification notification
to the default notification center when its bounds is changed. The default is <code>NO</code>.
to the default notification center when its bounds is changed. The default is \c NO.
Methods that could cause a bounds change notification are:
<pre>
setBounds:
setBoundsSize:
setBoundsOrigin:
</pre>
@param shouldPostBoundsChangedNotifications <code>YES</code> makes the receiver post
@param shouldPostBoundsChangedNotifications \c YES makes the receiver post
notifications on bounds changes
*/
- (void)setPostsBoundsChangedNotifications:(BOOL)shouldPostBoundsChangedNotifications
@@ -1424,7 +1466,7 @@ setBoundsOrigin:
}
/*!
Returns <code>YES</code> if the receiver posts a
Returns \c YES if the receiver posts a
CPViewBoundsDidChangeNotification when its
bounds is changed.
*/
@@ -1436,9 +1478,9 @@ setBoundsOrigin:
/*!
Initiates a drag operation from the receiver to another view that accepts dragged data.
@param anImage the image to be dragged
@param aLocation the lower-left corner coordinate of <code>anImage</code>
@param mouseOffset the distance from the <code>mouseDown:</code> location and the current location
@param anEvent the <code>mouseDown:</code> that triggered the drag
@param aLocation the lower-left corner coordinate of \c anImage
@param mouseOffset the distance from the \c -mouseDown: location and the current location
@param anEvent the \c -mouseDown: that triggered the drag
@param aPastebaord the pasteboard that holds the drag data
@param aSourceObject the drag operation controller
@param slideBack Whether the image should 'slide back' if the drag is rejected
@@ -1451,9 +1493,9 @@ setBoundsOrigin:
/*!
Initiates a drag operation from the receiver to another view that accepts dragged data.
@param aView the view to be dragged
@param aLocation the top-left corner coordinate of <code>aView</code>
@param mouseOffset the distance from the <code>mouseDown:</code> location and the current location
@param anEvent the <code>mouseDown:</code> that triggered the drag
@param aLocation the top-left corner coordinate of \c aView
@param mouseOffset the distance from the \c -mouseDown: location and the current location
@param anEvent the \c -mouseDown: that triggered the drag
@param aPastebaord the pasteboard that holds the drag data
@param aSourceObject the drag operation controller
@param slideBack Whether the view should 'slide back' if the drag is rejected
@@ -1469,7 +1511,7 @@ setBoundsOrigin:
*/
- (void)registerForDraggedTypes:(CPArray)pasteboardTypes
{
if (!pasteboardTypes)
if (!pasteboardTypes || ![pasteboardTypes count])
return;
var theWindow = [self window];
@@ -1505,7 +1547,7 @@ setBoundsOrigin:
}
/*!
Draws the receiver into <code>aRect</code>. This method should be overridden by subclasses.
Draws the receiver into \c aRect. This method should be overridden by subclasses.
@param aRect the area that should be drawn into
*/
- (void)drawRect:(CPRect)aRect
@@ -1522,43 +1564,26 @@ setBoundsOrigin:
{
if (aFlag)
[self setNeedsDisplayInRect:[self bounds]];
#if PLATFORM(DOM)
else
CPDOMDisplayServerRemoveView(self);
#endif
}
/*!
Marks the area denoted by <code>aRect</code> as dirty, and initiates a redraw on it.
Marks the area denoted by \c aRect as dirty, and initiates a redraw on it.
@param aRect the area that needs to be redrawn
*/
- (void)setNeedsDisplayInRect:(CPRect)aRect
{
#if PLATFORM(DOM)
var hash = [[self class] hash],
hasCustomDrawRect = CustomDrawRectViews[hash];
if (!hasCustomDrawRect && typeof hasCustomDrawRect === "undefined")
{
hasCustomDrawRect = [self methodForSelector:@selector(drawRect:)] != [CPView instanceMethodForSelector:@selector(drawRect:)];
CustomDrawRectViews[hash] = hasCustomDrawRect;
}
if (!hasCustomDrawRect)
if (!(_viewClassFlags & CPViewHasCustomDrawRect))
return;
#endif
if (_CGRectIsEmpty(aRect))
return;
if (_dirtyRect && !_CGRectIsEmpty(_dirtyRect))
_dirtyRect = CGRectUnion(aRect, _dirtyRect);
else
_dirtyRect = _CGRectMakeCopy(aRect);
#if PLATFORM(DOM)
CPDOMDisplayServerAddView(self);
#endif
_CPDisplayServerAddDisplayObject(self);
}
- (BOOL)needsDisplay
@@ -1576,7 +1601,7 @@ setBoundsOrigin:
}
/*!
Draws the entire area of the receiver as defined by its <code>bounds</code>.
Draws the entire area of the receiver as defined by its \c -bounds.
*/
- (void)display
{
@@ -1590,7 +1615,7 @@ setBoundsOrigin:
}
/*!
Draws the receiver into the area defined by <code>aRect</code>.
Draws the receiver into the area defined by \c aRect.
@param aRect the area to be drawn
*/
- (void)displayRect:(CPRect)aRect
@@ -1663,26 +1688,12 @@ setBoundsOrigin:
- (void)setNeedsLayout
{
_needsLayout = YES;
#if PLATFORM(DOM)
var hash = [[self class] hash],
hasCustomLayoutSubviews = CustomLayoutSubviewsViews[hash];
if (hasCustomLayoutSubviews === undefined)
{
hasCustomLayoutSubviews = [self methodForSelector:@selector(layoutSubviews)] != [CPView instanceMethodForSelector:@selector(layoutSubviews)];
CustomLayoutSubviewsViews[hash] = hasCustomLayoutSubviews;
}
if (!hasCustomLayoutSubviews)
if (!(_viewClassFlags & CPViewHasCustomLayoutSubviews))
return;
if (_needsLayout)
{
CPDOMDisplayServerAddView(self);
}
#endif
_needsLayout = YES;
_CPDisplayServerAddLayoutObject(self);
}
- (void)layoutIfNeeded
@@ -1700,7 +1711,7 @@ setBoundsOrigin:
}
/*!
Returns whether the receiver is completely opaque. By default, returns <code>NO</code>.
Returns whether the receiver is completely opaque. By default, returns \c NO.
*/
- (BOOL)isOpaque
{
@@ -1732,7 +1743,7 @@ setBoundsOrigin:
}
/*!
Changes the receiver's frame origin to a 'constrained' <code>aPoint</code>.
Changes the receiver's frame origin to a 'constrained' \c aPoint.
@param aPoint the proposed frame origin
*/
- (void)scrollPoint:(CGPoint)aPoint
@@ -1746,9 +1757,9 @@ setBoundsOrigin:
}
/*!
Scrolls the nearest ancestor CPClipView a minimum amount so <code>aRect</code> can become visible.
Scrolls the nearest ancestor CPClipView a minimum amount so \c aRect can become visible.
@param aRect the area to become visible
@return <codeYES</code> if any scrolling occurred, <code>NO</code> otherwise.
@return <codeYES if any scrolling occurred, \c NO otherwise.
*/
- (BOOL)scrollRectToVisible:(CGRect)aRect
{
@@ -1850,6 +1861,19 @@ setBoundsOrigin:
@implementation CPView (KeyView)
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
{
var subviews = [self subviews],
count = [subviews count];
// Is reverse iteration correct here? It matches the other (correct) code like hit testing.
while (count--)
if ([subviews[count] performKeyEquivalent:anEvent])
return YES;
return NO;
}
- (BOOL)canBecomeKeyView
{
return [self acceptsFirstResponder] && ![self isHiddenOrHasHiddenAncestor];
@@ -1942,7 +1966,7 @@ setBoundsOrigin:
/*!
Sets whether the receiver wants a core animation layer.
@param <code>YES</code> means the receiver wants a layer.
@param \c YES means the receiver wants a layer.
*/
- (void)setWantsLayer:(BOOL)aFlag
{
@@ -1950,8 +1974,8 @@ setBoundsOrigin:
}
/*!
Returns <code>YES</code> if the receiver uses a CALayer
@returns <code>YES</code> if the receiver uses a CALayer
Returns \c YES if the receiver uses a CALayer
@returns \c YES if the receiver uses a CALayer
*/
- (BOOL)wantsLayer
{
@@ -2184,6 +2208,54 @@ setBoundsOrigin:
return [_themeAttributes[aName] valueForState:_themeState];
}
- (CPView)createEphemeralSubviewNamed:(CPString)aViewName
{
return nil;
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
{
return _CGRectMakeZero();
}
- (CPView)layoutEphemeralSubviewNamed:(CPString)aViewName
positioned:(CPWindowOrderingMode)anOrderingMode
relativeToEphemeralSubviewNamed:(CPString)relativeToViewName
{
if (!_ephemeralSubviewsForNames)
{
_ephemeralSubviewsForNames = {};
_ephemeralSubviews = [CPSet set];
}
var frame = [self rectForEphemeralSubviewNamed:aViewName];
if (frame && !_CGRectIsEmpty(frame))
{
if (!_ephemeralSubviewsForNames[aViewName])
{
_ephemeralSubviewsForNames[aViewName] = [self createEphemeralSubviewNamed:aViewName];
[_ephemeralSubviews addObject:_ephemeralSubviewsForNames[aViewName]];
if (_ephemeralSubviewsForNames[aViewName])
[self addSubview:_ephemeralSubviewsForNames[aViewName] positioned:anOrderingMode relativeTo:_ephemeralSubviewsForNames[relativeToViewName]];
}
if (_ephemeralSubviewsForNames[aViewName])
[_ephemeralSubviewsForNames[aViewName] setFrame:frame];
}
else if (_ephemeralSubviewsForNames[aViewName])
{
[_ephemeralSubviewsForNames[aViewName] removeFromSuperview];
[_ephemeralSubviews removeObject:_ephemeralSubviewsForNames[aViewName]];
delete _ephemeralSubviewsForNames[aViewName];
}
return _ephemeralSubviewsForNames[aViewName];
}
@end
var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
@@ -2234,6 +2306,10 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
_subviews = [aCoder decodeObjectForKey:CPViewSubviewsKey] || [];
_superview = [aCoder decodeObjectForKey:CPViewSuperviewKey];
// FIXME: Should we encode/decode this?
_registeredDraggedTypes = [CPSet set];
_registeredDraggedTypesArray = [];
_autoresizingMask = [aCoder decodeIntForKey:CPViewAutoresizingMaskKey] || CPViewNotSizable;
_autoresizesSubviews = ![aCoder containsValueForKey:CPViewAutoresizesSubviewsKey] || [aCoder decodeBoolForKey:CPViewAutoresizesSubviewsKey];
@@ -2256,7 +2332,6 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
//_subviews[index]._superview = self;
}
#endif
_displayHash = [self hash];
if ([aCoder containsValueForKey:CPViewIsHiddenKey])
[self setHidden:[aCoder decodeBoolForKey:CPViewIsHiddenKey]];
@@ -2270,6 +2345,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
[self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]];
[self setupViewFlags];
_theme = [CPTheme defaultTheme];
_themeState = CPThemeState([aCoder decodeIntForKey:CPViewThemeStateKey]);
_themeAttributes = {};
@@ -2287,6 +2364,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
}
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
return self;
@@ -2310,8 +2388,20 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
if (_window !== nil)
[aCoder encodeConditionalObject:_window forKey:CPViewWindowKey];
if (_subviews.length > 0)
[aCoder encodeObject:_subviews forKey:CPViewSubviewsKey];
var count = [_subviews count],
encodedSubviews = _subviews;
if (count > 0 && [_ephemeralSubviews count] > 0)
{
encodedSubviews = [encodedSubviews copy];
while (count--)
if ([_ephemeralSubviews containsObject:encodedSubviews[count]])
encodedSubviews.splice(count, 1);
}
if (encodedSubviews.length > 0)
[aCoder encodeObject:encodedSubviews forKey:CPViewSubviewsKey];
// This will come out nil on the other side with decodeObjectForKey:
if (_superview !== nil)
@@ -2372,6 +2462,7 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView)
{
var view = fromView;
// FIXME: This doesn't handle the case when the outside views are equal.
// If we have a fromView, "climb up" the view tree until
// we hit the root node or we hit the toLayer.
while (view && view != toView)
+213
View File
@@ -0,0 +1,213 @@
/*
* CPViewController.j
* AppKit
*
* Created by Nicholas Small and Francisco Tolmasky.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CPResponder.j>
/*! @class CPViewController
The CPViewController class provides the fundamental view-management controller for Cappuccino applications.
The basic view controller class supports the presentation of an associated view in addition to basic support
for managing modal views and, in the future, animations. Subclasses such as CPNavigationController and
CPTabBarController provide additional behavior for managing complex hierarchies of view controllers and views.
You use each instance of CPViewController to manage a single view (and hierarchy). For a simple view controller,
this entails managing the view hierarchy responsible for presenting your application content.
A typical view hierarchy consists of a root viewŃa reference to which is available in the view property of this classŃ
and one or more subviews presenting the actual content. In the case of navigation and tab bar controllers, the view
controller manages not only the high-level view hierarchy (which provides the navigation controls) but also one
or more additional view controllers that handle the presentation of the application content.
Unlike UIViewController in Cocoa Touch, a CPViewController does not represent an entire screen of content. You
will add your root view to an existing view or window's content view. You can manage many view controllers
on screen at once. CPViewController is also the preferred way of working with Cibs.
Subclasses can override -loadView to create their custom view hierarchy, or specify a cib name to be loaded automatically.
It has methods that are called when a view appears or disappears.
This class is also a good place for delegate & datasource methods, and other controller stuff.
*/
@implementation CPViewController : CPResponder
{
CPView _view;
id _representedObject @accessors(property=representedObject);
CPString _title @accessors(property=title);
CPString _cibName @accessors(property=cibName, readonly);
CPBundle _cibBundle @accessors(property=cibBundle, readonly);
CPDictionary _cibExternalNameTable @accessors(property=cibExternalNameTable, readonly);
}
/*!
Convenience initializer calls -initWithCibName:bundle: with nil for both parameters.
*/
- (id)init
{
return [self initWithCibName:nil bundle:nil];
}
- (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil
{
return [self initWithCibName:aCibNameOrNil bundle:aCibBundleOrNil externalNameTable:nil];
}
- (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil owner:(id)anOwner
{
return [self initWithCibName:aCibNameOrNil bundle:aCibBundleOrNil externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]];
}
/*!
The designated initializer. If you subclass CPViewController, you must call the super implementation of this method, even if you aren't using a Cib.
In the specified Cib, the File's Owner proxy should have its class set to your view controller subclass, with the view outlet connected to the main view.
If you pass in a nil Cib name, then you must either call -setView: before -view is invoked, or override -loadView to set up your views.
@param cibNameOrNil The path to the cib to load for the root view or nil to programmatically create views.
@param cibBundleOrNil The bundle that the cib is located in or nil for the main bundle.
*/
- (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil externalNameTable:(CPDictionary)anExternalNameTable
{
self = [super init];
if (self)
{
// Don't load the cib until someone actually requests the view. The user may just be intending to use setView:.
_cibName = aCibNameOrNil;
_cibBundle = aCibBundleOrNil || [CPBundle mainBundle];
_cibExternalNameTable = anExternalNameTable || [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
}
return self;
}
/*!
Programmatically creates the view that the controller manages.
You should never call this method directly. The view controller calls this method when the view property is requested but is nil.
If you create your views manually, you must override this method and use it to create your view and assign it to the view property.
The default implementation for programmatic views is to create a plain view. You can invoke super to utilize this view.
If you use Interface Builder to create your views and initialize the view controllerŃthat is, you initialize the view using the
initWithCibName:bundle: methodŃthen you must not override this method. The consequences risk shattering the space-time continuum.
Note: The cib loading system is currently asynchronous.
*/
- (void)loadView
{
if (_view)
return;
// if (_cibName)
// [CPException raise: reason:];
var cib = [[CPCib alloc] initWithContentsOfURL:[_cibBundle pathForResource:_cibName + @".cib"]];
[cib instantiateCibWithExternalNameTable:_cibExternalNameTable];
}
/*!
Returns the view that the controller manages.
If this property is nil, the controller sends loadView to itself to create the view that it manages.
Subclasses should override the loadView method to create any custom views. The default value is nil.
Note: An error will not be thrown if after -loadView, the view property is still nil. -view will simply return nil, but will continue to call -loadView on subsequent calls.
*/
- (CPView)view
{
if (!_view)
{
var cibOwner = [_cibExternalNameTable objectForKey:CPCibOwner];
if ([cibOwner respondsToSelector:@selector(viewControllerWillLoadCib:)])
[cibOwner viewControllerWillLoadCib:self];
[self loadView];
if (_view === nil && [cibOwner isKindOfClass:[CPDocument class]])
[self setView:[cibOwner valueForKey:@"view"]];
if ([cibOwner respondsToSelector:@selector(viewControllerDidLoadCib:)])
[cibOwner viewControllerDidLoadCib:self];
}
return _view;
}
/*!
Manually sets the view that the controller manages.
Setting to nil will cause -loadView to be called on all subsequent calls of -view.
@param aView The view this controller should represent.
*/
- (void)setView:(CPView)aView
{
_view = aView;
}
@end
var CPViewControllerViewKey = @"CPViewControllerViewKey",
CPViewControllerTitleKey = @"CPViewControllerTitleKey",
CPViewControllerCibNameKey = @"CPViewControllerCibNameKey",
CPViewControllerBundleKey = @"CPViewControllerBundleKey";
@implementation CPViewController (CPCoding)
/*!
Initializes the view controller by unarchiving data from a coder.
@param aCoder the coder from which the data will be unarchived
@return the initialized view controller
*/
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_view = [aCoder decodeObjectForKey:CPViewControllerViewKey];
_title = [aCoder decodeObjectForKey:CPViewControllerTitleKey];
_cibName = [aCoder decodeObjectForKey:CPViewControllerCibNameKey];
var bundlePath = [aCoder decodeObjectForKey:CPViewControllerBundleKey];
_cibBundle = bundlePath ? [CPBundle bundleWithPath:bundlePath] : [CPBundle mainBundle];
_cibExternalNameTable = [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
}
return self;
}
/*!
Archives the view controller to the provided coder.
@param aCoder the coder to which the view controller should be archived
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_view forKey:CPViewControllerViewKey];
[aCoder encodeObject:_title forKey:CPViewControllerTitleKey];
[aCoder encodeObject:_cibName forKey:CPViewControllerCibNameKey];
[aCoder encodeObject:[_cibBundle bundlePath] forKey:CPViewControllerBundleKey];
}
@end
+710 -312
View File
File diff suppressed because it is too large Load Diff
@@ -38,6 +38,11 @@ var _CPToolbarViewBackgroundColor = nil;
return _CPToolbarViewBackgroundColor;
}
- (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator
{
// We don't ever want to show the resize indicator.
}
- (void)tile
{
[super tile];
+50
View File
@@ -0,0 +1,50 @@
@import "_CPWindowView.j"
var _CPStandardWindowViewBodyBackgroundColor = nil;
@implementation _CPDocModalWindowView : _CPWindowView
{
CPView _bodyView;
}
+ (CPColor)bodyBackgroundColor
{
if (!_CPStandardWindowViewBodyBackgroundColor)
_CPStandardWindowViewBodyBackgroundColor = [CPColor colorWithWhite:0.96 alpha:0.9];
return _CPStandardWindowViewBodyBackgroundColor;
}
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
{
self = [super initWithFrame:aFrame styleMask:aStyleMask];
if (self)
{
var theClass = [self class],
bounds = [self bounds];
_bodyView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), CGRectGetHeight(bounds))];
[_bodyView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_bodyView setBackgroundColor:[theClass bodyBackgroundColor]];
[_bodyView setHitTests:NO];
[self addSubview:_bodyView];
}
return self;
}
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
return aFrameRect;
}
- (CGRect)frameRectForContentRect:(CGRect)aContentRect
{
return aContentRect;
}
@end
+75 -17
View File
@@ -56,7 +56,7 @@ var _CPTexturedWindowHeadGradientColor = nil,
+ (CPColor)solidColor
{
if (!_CPTexturedWindowHeadSolidColor)
_CPTexturedWindowHeadSolidColor = [CPColor colorWithCalibratedRed:182.0 / 255.0 green:182.0 / 255.0 blue:182.0 / 255.0 alpha:1.0];
_CPTexturedWindowHeadSolidColor = [CPColor colorWithCalibratedRed:195.0 / 255.0 green:195.0 / 255.0 blue:195.0 / 255.0 alpha:1.0];
return _CPTexturedWindowHeadSolidColor;
}
@@ -94,11 +94,15 @@ var _CPTexturedWindowHeadGradientColor = nil,
@end
var _CPStandardWindowViewBodyBackgroundColor = nil,
_CPStandardWindowViewDividerBackgroundColor = nil,
_CPStandardWindowViewTitleBackgroundColor = nil,
_CPStandardWindowViewCloseButtonImage = nil,
_CPStandardWindowViewCloseButtonHighlightedImage = nil;
var _CPStandardWindowViewBodyBackgroundColor = nil,
_CPStandardWindowViewDividerBackgroundColor = nil,
_CPStandardWindowViewTitleBackgroundColor = nil,
_CPStandardWindowViewCloseButtonImage = nil,
_CPStandardWindowViewCloseButtonHighlightedImage = nil,
_CPStandardWindowViewCloseButtonUnsavedImage = nil,
_CPStandardWindowViewCloseButtonUnsavedHighlightedImage = nil,
_CPStandardWindowViewMinimizeButtonImage = nil,
_CPStandardWindowViewMinimizeButtonHighlightedImage = nil;
var STANDARD_GRADIENT_HEIGHT = 41.0;
STANDARD_TITLEBAR_HEIGHT = 25.0;
@@ -112,6 +116,9 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
CPTextField _titleField;
CPButton _closeButton;
CPButton _minimizeButton;
BOOL _isDocumentEdited;
}
+ (CPColor)bodyBackgroundColor
@@ -230,7 +237,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
[_bodyView setHitTests:NO];
[self addSubview:_bodyView];
[self setResizeIndicatorOffset:CGSizeMake(2.0, 2.0)];
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
@@ -256,24 +263,44 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
if (!_CPStandardWindowViewCloseButtonImage)
{
var bundle = [CPBundle bundleForClass:[CPWindow class]];
_CPStandardWindowViewCloseButtonImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardCloseButton.png"] size:CGSizeMake(16.0, 16.0)];
_CPStandardWindowViewCloseButtonHighlightedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardCloseButtonHighlighted.png"] size:CGSizeMake(16.0, 16.0)];
_CPStandardWindowViewCloseButtonUnsavedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardCloseButtonUnsaved.png"] size:CGSizeMake(16.0, 16.0)];
_CPStandardWindowViewCloseButtonUnsavedHighlightedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardCloseButtonUnsavedHighlighted.png"] size:CGSizeMake(16.0, 16.0)];
}
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 7.0, 16.0, 16.0)];
[_closeButton setBordered:NO];
[_closeButton setImage:_CPStandardWindowViewCloseButtonImage];
[_closeButton setAlternateImage:_CPStandardWindowViewCloseButtonHighlightedImage];
[self _updateCloseButton];
[self addSubview:_closeButton];
}
if (_styleMask & CPMiniaturizableWindowMask && ![CPPlatform isBrowser])
{
if (!_CPStandardWindowViewMinimizeButtonImage)
{
var bundle = [CPBundle bundleForClass:[CPWindow class]];
_CPStandardWindowViewMinimizeButtonImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardMinimizeButton.png"] size:CGSizeMake(16.0, 16.0)];
_CPStandardWindowViewMinimizeButtonHighlightedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardMinimizeButtonHighlighted.png"] size:CGSizeMake(16.0, 16.0)];
}
_minimizeButton = [[CPButton alloc] initWithFrame:CGRectMake(27.0, 7.0, 16.0, 16.0)];
[_minimizeButton setBordered:NO];
[_minimizeButton setImage:_CPStandardWindowViewMinimizeButtonImage];
[_minimizeButton setAlternateImage:_CPStandardWindowViewMinimizeButtonHighlightedImage];
[self addSubview:_minimizeButton];
}
[self tile];
}
return self;
}
@@ -281,6 +308,9 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
{
[_closeButton setTarget:[self window]];
[_closeButton setAction:@selector(performClose:)];
[_minimizeButton setTarget:[self window]];
[_minimizeButton setAction:@selector(performMiniaturize:)];
}
- (CGSize)toolbarOffset
@@ -303,7 +333,14 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
[_bodyView setFrame:CGRectMake(0.0, dividerMaxY, width, CGRectGetHeight(bounds) - dividerMaxY)];
[_titleField setFrame:CGRectMake(10.0, 3.0, width - 20.0, CGRectGetHeight([_titleField frame]))];
var leftOffset = 8;
if (_closeButton)
leftOffset += 19.0;
if (_minimizeButton)
leftOffset += 19.0;
[_titleField setFrame:CGRectMake(leftOffset, 5.0, width - leftOffset*2.0, CGRectGetHeight([_titleField frame]))];
[[theWindow contentView] setFrameOrigin:CGPointMake(0.0, CGRectGetMaxY([_dividerView frame]))];
}
@@ -334,6 +371,27 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
}
}
*/
- (void)_updateCloseButton
{
if (_isDocumentEdited)
{
[_closeButton setImage:_CPStandardWindowViewCloseButtonUnsavedImage];
[_closeButton setAlternateImage:_CPStandardWindowViewCloseButtonUnsavedHighlightedImage];
}
else
{
[_closeButton setImage:_CPStandardWindowViewCloseButtonImage];
[_closeButton setAlternateImage:_CPStandardWindowViewCloseButtonHighlightedImage];
}
}
- (void)setDocumentEdited:(BOOL)isEdited
{
_isDocumentEdited = isEdited;
[self _updateCloseButton];
}
- (void)setTitle:(CPString)aTitle
{
[_titleField setStringValue:aTitle];
+29 -17
View File
@@ -81,13 +81,15 @@ var _CPWindowViewResizeIndicatorImage = nil;
_styleMask = aStyleMask;
_resizeIndicatorOffset = CGSizeMake(0.0, 0.0);
_toolbarOffset = CGSizeMake(0.0, 0.0);
[self setShowsResizeIndicator:!(_styleMask & CPBorderlessBridgeWindowMask) && (_styleMask & CPResizableWindowMask)];
}
return self;
}
- (void)setDocumentEdited:(BOOL)isEdited
{
}
- (void)setTitle:(CPString)aTitle
{
}
@@ -100,7 +102,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
- (void)mouseDown:(CPEvent)anEvent
{
var theWindow = [self window];
if ((_styleMask & CPResizableWindowMask) && _resizeIndicator)
{
// FIXME: This should be better
@@ -135,17 +137,28 @@ var _CPWindowViewResizeIndicatorImage = nil;
}
else if (type === CPLeftMouseDragged)
[theWindow setFrameSize:CGSizeMake(CGRectGetWidth(_resizeFrame) + location.x - CGRectGetMinX(_resizeFrame), CGRectGetHeight(_resizeFrame) + location.y - CGRectGetMinY(_resizeFrame))];
{
var newSize = CGSizeMake(CGRectGetWidth(_resizeFrame) + location.x - CGRectGetMinX(_resizeFrame), CGRectGetHeight(_resizeFrame) + location.y - CGRectGetMinY(_resizeFrame));
if (theWindow._isSheet && theWindow._parentView && (theWindow._frame.size.width !== newSize.width))
[theWindow._parentView _setAttachedSheetFrameOrigin];
[theWindow setFrameSize:newSize];
}
[CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (CGPoint)_pointWithinScreenFrame:(CGPoint)aPoint
{
// FIXME: this is WRONG, all of this is WRONG
if (![CPPlatform isBrowser])
return aPoint;
var visibleFrame = _cachedScreenFrame;
if (!visibleFrame)
visibleFrame = [[CPDOMWindowBridge sharedDOMWindowBridge] visibleFrame];
visibleFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
var restrictedPoint = CGPointMake(0, 0);
@@ -158,22 +171,24 @@ var _CPWindowViewResizeIndicatorImage = nil;
- (void)trackMoveWithEvent:(CPEvent)anEvent
{
var type = [anEvent type];
if (type === CPLeftMouseUp)
{
_cachedScreenFrame = nil;
return;
}
else if (type === CPLeftMouseDown)
{
_mouseDraggedPoint = [[self window] convertBaseToBridge:[anEvent locationInWindow]];
_cachedScreenFrame = [[CPDOMWindowBridge sharedDOMWindowBridge] visibleFrame];
_mouseDraggedPoint = [[self window] convertBaseToGlobal:[anEvent locationInWindow]];
_cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
}
else if (type === CPLeftMouseDragged)
{
var theWindow = [self window],
frame = [theWindow frame],
location = [theWindow convertBaseToBridge:[anEvent locationInWindow]],
location = [theWindow convertBaseToGlobal:[anEvent locationInWindow]],
origin = [self _pointWithinScreenFrame:CGPointMake(_CGRectGetMinX(frame) + (location.x - _mouseDraggedPoint.x),
_CGRectGetMinY(frame) + (location.y - _mouseDraggedPoint.y))];
@@ -196,13 +211,13 @@ var _CPWindowViewResizeIndicatorImage = nil;
[_resizeIndicator setImage:_CPWindowViewResizeIndicatorImage];
[_resizeIndicator setAutoresizingMask:CPViewMinXMargin | CPViewMinYMargin];
[self addSubview:_resizeIndicator];
}
else
{
[_resizeIndicator removeFromSuperview];
_resizeIndicator = nil;
}
}
@@ -305,11 +320,8 @@ var _CPWindowViewResizeIndicatorImage = nil;
if (toolbarView)
{
[toolbarView removeFromSuperview];
[toolbarView setLabelColor:[self toolbarLabelColor]];
if ([self respondsToSelector:@selector(toolbarLabelShadowColor)])
[toolbarView setLabelShadowColor:[self toolbarLabelShadowColor]];
[toolbarView FIXME_setIsHUD:_styleMask & CPHUDBackgroundWindowMask];
[self addSubview:toolbarView];
}
@@ -322,7 +334,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
{
var contentRect = [self convertRect:[[theWindow contentView] frame] toView:nil];
contentRect.origin = [theWindow convertBaseToBridge:contentRect.origin];
contentRect.origin = [theWindow convertBaseToGlobal:contentRect.origin];
[self setAutoresizesSubviews:NO];
[theWindow setFrame:[theWindow frameRectForContentRect:contentRect]];
+227 -40
View File
@@ -41,10 +41,24 @@
*/
@implementation CPWindowController : CPResponder
{
id _owner;
CPWindow _window;
CPDocument _document;
CPString _windowCibName;
CPWindow _window;
CPArray _documents;
CPDocument _document;
BOOL _shouldCloseDocument;
BOOL _supportsMultipleDocuments;
id _cibOwner;
CPString _windowCibName;
CPString _windowCibPath;
CPViewController _viewController;
CPView _viewControllerContainerView;
}
- (id)init
{
return [self initWithWindow:nil];
}
/*!
@@ -55,14 +69,17 @@
- (id)initWithWindow:(CPWindow)aWindow
{
self = [super init];
if (self)
{
[self setWindow:aWindow];
[self setShouldCloseDocument:NO];
[self setNextResponder:CPApp];
_documents = [];
}
return self;
}
@@ -84,16 +101,27 @@
*/
- (id)initWithWindowCibName:(CPString)aWindowCibName owner:(id)anOwner
{
self = [super init];
self = [self initWithWindow:nil];
if (self)
{
_owner = anOwner;
_cibOwner = anOwner;
_windowCibName = aWindowCibName;
[self setNextResponder:CPApp];
}
return self;
}
- (id)initWithWindowCibPath:(CPString)aWindowCibPath owner:(id)anOwner
{
self = [self initWithWindow:nil];
if (self)
{
_cibOwner = anOwner;
_windowCibPath = aWindowCibPath;
}
return self;
}
@@ -102,34 +130,33 @@
*/
- (void)loadWindow
{
[self windowWillLoad];
//FIXME: ACTUALLY LOAD WINDOW!!!
[self setWindow:CPApp._keyWindow = [[CPWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:CPBorderlessBridgeWindowMask|CPTitledWindowMask|CPClosableWindowMask|CPResizableWindowMask]];
[self windowDidLoad];
if (_window)
return;
[[CPBundle bundleForClass:[_cibOwner class]] loadCibFile:[self windowCibPath] externalNameTable:[CPDictionary dictionaryWithObject:_cibOwner forKey:CPCibOwner]];
}
/*!
Shows the window.
@param aSender the object requesting the show
*/
- (CFAction)showWindow:(id)aSender
- (@action)showWindow:(id)aSender
{
var theWindow = [self window];
if ([theWindow respondsToSelector:@selector(becomesKeyOnlyIfNeeded)] && [theWindow becomesKeyOnlyIfNeeded])
if ([theWindow respondsToSelector:@selector(becomesKeyOnlyIfNeeded)] && [theWindow becomesKeyOnlyIfNeeded])
[theWindow orderFront:aSender];
else
[theWindow makeKeyAndOrderFront:aSender];
}
/*!
Returns <code>YES</code> if the window has been loaded. Specifically,
Returns \c YES if the window has been loaded. Specifically,
if loadWindow has been called.
*/
- (BOOL)isWindowLoaded
{
return _window;
return _window !== nil;
}
/*!
@@ -138,7 +165,28 @@
- (CPWindow)window
{
if (!_window)
[self loadWindow];
{
[self windowWillLoad];
[_document windowControllerWillLoadCib:self];
[self loadWindow];
if (_window === nil && [_cibOwner isKindOfClass:[CPDocument class]])
[self setWindow:[_cibOwner valueForKey:@"window"]];
if (!_window)
{
var reason = [CPString stringWithFormat:@"Window for %@ could not be loaded from Cib or no window specified. \
Override loadWindow to load the window manually.", self];
[CPException raise:CPInternalInconsistencyException reason:reason];
}
[self windowDidLoad];
[_document windowControllerDidLoadCib:self];
[self synchronizeWindowTitleWithDocumentName];
}
return _window;
}
@@ -149,8 +197,10 @@
*/
- (void)setWindow:(CPWindow)aWindow
{
[_window setWindowController:nil];
_window = aWindow;
[_window setWindowController:self];
[_window setNextResponder:self];
}
@@ -160,9 +210,6 @@
*/
- (void)windowDidLoad
{
[_document windowControllerDidLoadNib:self];
[self synchronizeWindowTitleWithDocumentName];
}
/*!
@@ -170,7 +217,6 @@
*/
- (void)windowWillLoad
{
[_document windowControllerWillLoadNib:self];
}
/*!
@@ -179,17 +225,20 @@
*/
- (void)setDocument:(CPDocument)aDocument
{
if (_document == aDocument)
if (_document === aDocument)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_document)
{
if (![self supportsMultipleDocuments])
[self removeDocument:_document];
[defaultCenter removeObserver:self
name:CPDocumentWillSaveNotification
object:_document];
[defaultCenter removeObserver:self
name:CPDocumentDidSaveNotification
object:_document];
@@ -198,16 +247,18 @@
name:CPDocumentDidFailToSaveNotification
object:_document];
}
_document = aDocument;
if (_document)
{
[self addDocument:_document];
[defaultCenter addObserver:self
selector:@selector(_documentWillSave:)
name:CPDocumentWillSaveNotification
object:_document];
[defaultCenter addObserver:self
selector:@selector(_documentDidSave:)
name:CPDocumentDidSaveNotification
@@ -217,13 +268,113 @@
selector:@selector(_documentDidFailToSave:)
name:CPDocumentDidFailToSaveNotification
object:_document];
[self setDocumentEdited:[_document isDocumentEdited]];
}
}
var viewController = [_document viewControllerForWindowController:self];
if (viewController)
[self setViewController:viewController];
[self synchronizeWindowTitleWithDocumentName];
}
- (void)setSupportsMultipleDocuments:(BOOL)shouldSupportMultipleDocuments
{
_supportsMultipleDocuments = shouldSupportMultipleDocuments;
}
- (BOOL)supportsMultipleDocuments
{
return _supportsMultipleDocuments;
}
- (void)addDocument:(CPDocument)aDocument
{
if (aDocument && ![_documents containsObject:aDocument])
[_documents addObject:aDocument];
}
- (void)removeDocument:(CPDocument)aDocument
{
var index = [_documents indexOfObjectIdenticalTo:aDocument];
if (index === CPNotFound)
return;
[_documents removeObjectAtIndex:index];
if (_document === aDocument && [_documents count])
[self setDocument:[_documents objectAtIndex:MIN(index, [_documents count] - 1)]];
}
- (void)removeDocumentAndCloseIfNecessary:(CPDocument)aDocument
{
[self removeDocument:aDocument];
if (![_documents count])
[self close];
}
- (CPArray)documents
{
return _documents;
}
- (void)setViewController:(CPViewController)aViewController
{
var containerView = [self viewControllerContainerView] || [[self window] contentView],
view = [_viewController view],
frame = view ? [view frame] : [containerView bounds];
[view removeFromSuperview];
_viewController = aViewController;
view = [_viewController view];
if (view)
{
[view setFrame:frame];
[containerView addSubview:view];
}
}
- (void)setViewControllerContainerView:(CPView)aView
{
_viewControllerContainerView = aView;
}
- (void)viewControllerContainerView
{
return _viewControllerContainerView;
}
- (void)setViewController:(CPViewController)aViewController
{
var containerView = [self viewControllerContainerView] || [[self window] contentView],
view = [_viewController view],
frame = view ? [view frame] : [containerView bounds];
[view removeFromSuperview];
_viewController = aViewController;
view = [_viewController view];
if (view)
{
[view setFrame:frame];
[containerView addSubview:view];
}
}
- (CPViewController)viewController
{
return _viewController;
}
/* @ignore */
- (void)_documentWillSave:(CPNotification)aNotification
{
@@ -252,13 +403,49 @@
/*!
Sets whether the document has unsaved changes. The window can use this as a hint to
@param isEdited <code>YES</code> means the document has unsaved changes.
@param isEdited \c YES means the document has unsaved changes.
*/
- (void)setDocumentEdited:(BOOL)isEdited
{
[[self window] setDocumentEdited:isEdited];
}
- (void)close
{
[[self window] close];
}
- (void)setShouldCloseDocument:(BOOL)shouldCloseDocument
{
_shouldCloseDocument = shouldCloseDocument;
}
- (BOOL)shouldCloseDocument
{
return _shouldCloseDocument;
}
- (id)owner
{
return _cibOwner;
}
- (CPString)windowCibName
{
if (_windowCibName)
return _windowCibName;
return [[_windowCibPath lastPathComponent] stringByDeletingPathExtension];
}
- (CPString)windowCibPath
{
if (_windowCibPath)
return _windowCibPath;
return [[CPBundle bundleForClass:[_cibOwner class]] pathForResource:_windowCibName + @".cib"];
}
// Setting and Getting Window Attributes
/*!
@@ -268,7 +455,7 @@
{
if (!_document || !_window)
return;
// [_window setRepresentedFilename:];
[_window setTitle:[self windowTitleForDocumentDisplayName:[_document displayName]]];
}
+21 -10
View File
@@ -24,17 +24,20 @@
@import <Foundation/CPURLConnection.j>
@import <Foundation/CPURLRequest.j>
@import "_CPCibClassSwapper.j"
@import "_CPCibCustomObject.j"
@import "_CPCibCustomResource.j"
@import "_CPCibCustomView.j"
@import "_CPCibKeyedUnarchiver.j"
@import "_CPCibObjectData.j"
@import "_CPCibProxyObject.j"
@import "_CPCibWindowTemplate.j"
CPCibOwner = @"CPCibOwner",
CPCibTopLevelObjects = @"CPCibTopLevelObjects",
CPCibReplacementClasses = @"CPCibReplacementClasses";
CPCibReplacementClasses = @"CPCibReplacementClasses",
CPCibExternalObjects = @"CPCibExternalObjects";
var CPCibObjectDataKey = @"CPCibObjectDataKey";
@@ -80,11 +83,25 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
return self;
}
- (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle loadDelegate:(id)aLoadDelegate
- (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle
{
if (![aName hasSuffix:@".cib"])
aName = [aName stringByAppendingString:@".cib"];
// If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later.
self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName]];
if (self)
_bundle = aBundle;
return self;
}
- (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle loadDelegate:(id)aLoadDelegate
{
if (![aName hasSuffix:@".cib"])
aName = [aName stringByAppendingString:@".cib"];
// If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later.
self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName] loadDelegate:aLoadDelegate];
@@ -124,6 +141,8 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
[unarchiver setClass:[replacementClasses objectForKey:key] forClassName:key];
}
[unarchiver setExternalObjectsForProxyIdentifiers:[anExternalNameTable objectForKey:CPCibExternalObjects]];
var objectData = [unarchiver decodeObjectForKey:CPCibObjectDataKey];
if (!objectData || ![objectData isKindOfClass:[_CPCibObjectData class]])
@@ -135,14 +154,6 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
[objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects];
[objectData awakeWithOwner:owner topLevelObjects:topLevelObjects];
var menu;
if ((menu = [objectData mainMenu]) != nil)
{
[CPApp setMainMenu:menu];
[CPMenu setMenuBarVisible:YES];
}
// Display Visible Windows.
[objectData displayVisibleWindows];
+88
View File
@@ -0,0 +1,88 @@
/*
* CPCibConnector.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPKeyValueCoding.j>
var _CPCibConnectorSourceKey = @"_CPCibConnectorSourceKey",
_CPCibConnectorDestinationKey = @"_CPCibConnectorDestinationKey",
_CPCibConnectorLabelKey = @"_CPCibConnectorLabelKey";
@implementation CPCibConnector : CPObject
{
id _source @accessors(property=source);
id _destination @accessors(property=destination);
CPString _label @accessors(property=label);
}
- (void)replaceObject:(id)anObject withObject:(id)anotherObject
{
if (_source === anObject)
_source = anotherObject;
if (_destination === anObject)
_destination = anotherObject;
}
- (void)replaceObjects:(Object)replacementObjects
{
var replacement = replacementObjects[[_source UID]];
if (replacement !== undefined)
_source = replacement;
replacement = replacementObjects[[_destination UID]];
if (replacement !== undefined)
_destination = replacement;
}
@end
@implementation CPCibConnector (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_source = [aCoder decodeObjectForKey:_CPCibConnectorSourceKey];
_destination = [aCoder decodeObjectForKey:_CPCibConnectorDestinationKey];
_label = [aCoder decodeObjectForKey:_CPCibConnectorLabelKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_source forKey:_CPCibConnectorSourceKey];
[aCoder encodeObject:_destination forKey:_CPCibConnectorDestinationKey];
[aCoder encodeObject:_label forKey:_CPCibConnectorLabelKey];
}
@end
// For backwards compatibility.
@implementation _CPCibConnector : CPCibConnector { } @end
+76
View File
@@ -0,0 +1,76 @@
/*
* CPCibControlConnector.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPCibConnector.j"
@implementation CPCibControlConnector : CPCibConnector
{
}
- (void)establishConnection
{
var selectorName = _label,
selectorNameLength = [selectorName length];
if (selectorNameLength && selectorName[selectorNameLength - 1] !== ':')
selectorName += ':';
var selector = CPSelectorFromString(selectorName);
// Not having a selector is a fatal error.
if (!selector)
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] selector " + selectorName + @" does not exist."];
// If the destination doesn't respond to this selector, warn but don't die.
if (_destination && ![_destination respondsToSelector:selector])
{
CPLog.warn(@"Could not connect the action " + selector + @" to target of class " + [_destination className]);
return;
}
// Not being able to set the action is a fatal error.
if ([_source respondsToSelector:@selector(setAction:)])
objj_msgSend(_source, @selector(setAction:), selector);
else
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] " + [_source description] + " does not respond to setAction:"];
// Not being able to set the target is a fatal error.
if ([_source respondsToSelector:@selector(setTarget:)])
objj_msgSend(_source, @selector(setTarget:), _destination);
else
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] " + [_source description] + " does not respond to setTarget:"];
}
@end
@implementation _CPCibControlConnector : CPCibControlConnector { } @end
+30 -5
View File
@@ -39,16 +39,41 @@ var LoadInfoForCib = {};
@implementation CPBundle (CPCibLoading)
+ (void)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable
{
[[[CPCib alloc] initWithContentsOfURL:anAbsolutePath] instantiateCibWithExternalNameTable:aNameTable];
}
+ (void)loadCibNamed:(CPString)aName owner:(id)anOwner
{
if (![aName hasSuffix:@".cib"])
aName = [aName stringByAppendingString:@".cib"];
// Path is based solely on anOwner:
var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle],
path = [bundle pathForResource:aName];
[self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]];
}
- (void)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable
{
[[[CPCib alloc] initWithContentsOfURL:aFileName] instantiateCibWithExternalNameTable:aNameTable];
}
+ (void)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable loadDelegate:aDelegate
{
var cib = [[CPCib alloc] initWithContentsOfURL:anAbsolutePath loadDelegate:self];
LoadInfoForCib[[cib hash]] = { loadDelegate:aDelegate, externalNameTable:aNameTable };
LoadInfoForCib[[cib UID]] = { loadDelegate:aDelegate, externalNameTable:aNameTable };
}
+ (void)loadCibNamed:(CPString)aName owner:(id)anOwner loadDelegate:(id)aDelegate
{
// Path is based solely on anOwner:
if (![aName hasSuffix:@".cib"])
aName = [aName stringByAppendingString:@".cib"];
// Path is based solely on anOwner:
var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle],
path = [bundle pathForResource:aName];
@@ -59,14 +84,14 @@ var LoadInfoForCib = {};
{
var cib = [[CPCib alloc] initWithCibNamed:aFileName bundle:self loadDelegate:[self class]];
LoadInfoForCib[[cib hash]] = { loadDelegate:aDelegate, externalNameTable:aNameTable };
LoadInfoForCib[[cib UID]] = { loadDelegate:aDelegate, externalNameTable:aNameTable };
}
+ (void)cibDidFinishLoading:(CPCib)aCib
{
var loadInfo = LoadInfoForCib[[aCib hash]];
var loadInfo = LoadInfoForCib[[aCib UID]];
delete LoadInfoForCib[[aCib hash]];
delete LoadInfoForCib[[aCib UID]];
[aCib instantiateCibWithExternalNameTable:loadInfo.externalNameTable];
+48
View File
@@ -0,0 +1,48 @@
/*
* CPCibOutletConnector.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPCibConnector.j"
@implementation CPCibOutletConnector : CPCibConnector
{
}
- (void)establishConnection
{
try
{
[_source setValue:_destination forKey:_label];
}
catch (anException)
{
if ([anException name] === CPUndefinedKeyException)
CPLog.warn(@"Could not connect the outlet " + _label + @" of target of class " + [_source className]);
else
throw anException;
}
}
@end
@implementation _CPCibOutletConnector : CPCibOutletConnector { } @end
+76
View File
@@ -0,0 +1,76 @@
/*
* _CPCibClassSwapper.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
var _CPCibClassSwapperClassNameKey = @"_CPCibClassSwapperClassNameKey",
_CPCibClassSwapperOriginalClassNameKey = @"_CPCibClassSwapperOriginalClassNameKey";
@implementation _CPCibClassSwapper : CPObject
{
}
+ (void)allocObjectWithCoder:(CPCoder)aCoder className:(CPString)aClassName
{
// FIXME: Also check class classForClassName:
var theClass = [aCoder classForClassName:aClassName];
if (!theClass)
{
theClass = objj_lookUpClass(aClassName);
if (!theClass)
return nil;
}
return [theClass alloc];
}
+ (id)allocWithCoder:(CPCoder)aCoder
{
if ([aCoder respondsToSelector:@selector(usesOriginalClasses)] && [aCoder usesOriginalClasses])
{
var theClassName = [aCoder decodeObjectForKey:_CPCibClassSwapperOriginalClassNameKey],
object = [self allocObjectWithCoder:aCoder className:theClassName];
}
else
{
var theClassName = [aCoder decodeObjectForKey:_CPCibClassSwapperClassNameKey],
object = [self allocObjectWithCoder:aCoder className:theClassName];
if (!object)
{
CPLog.error("Unable to find class " + theClassName + " in cib file.");
object = [self allocObjectWithCoder:aCoder className:[aCoder decodeObjectForKey:_CPCibClassSwapperOriginalClassNameKey]];
}
}
if (!object)
[CPException raise:CPInvalidArgumentException reason:@"Unable to find class " + theClassName + " in cib file."];
return object;
}
@end
-103
View File
@@ -1,103 +0,0 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPKeyValueCoding.j>
var _CPCibConnectorSourceKey = @"_CPCibConnectorSourceKey",
_CPCibConnectorDestinationKey = @"_CPCibConnectorDestinationKey",
_CPCibConnectorLabelKey = @"_CPCibConnectorLabelKey";
@implementation _CPCibConnector : CPObject
{
id _source;
id _destination;
CPString _label;
}
- (void)replaceObjects:(JSObject)replacementObjects
{
var replacement = replacementObjects[[_source hash]];
if (replacement !== undefined)
_source = replacement;
replacement = replacementObjects[[_destination hash]];
if (replacement !== undefined)
_destination = replacement;
}
@end
@implementation _CPCibConnector (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_source = [aCoder decodeObjectForKey:_CPCibConnectorSourceKey];
_destination = [aCoder decodeObjectForKey:_CPCibConnectorDestinationKey];
_label = [aCoder decodeObjectForKey:_CPCibConnectorLabelKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_source forKey:_CPCibConnectorSourceKey];
[aCoder encodeObject:_destination forKey:_CPCibConnectorDestinationKey];
[aCoder encodeObject:_label forKey:_CPCibConnectorLabelKey];
}
@end
@implementation _CPCibControlConnector : _CPCibConnector
{
}
- (void)establishConnection
{
var selectorName = _label;
if (![selectorName hasSuffix:@":"])
selectorName += ':';
var selector = CPSelectorFromString(selectorName);
if (!selector)
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] selector " + selectorName + @" does not exist."];
if ([_source respondsToSelector:@selector(setAction:)])
objj_msgSend(_source, @selector(setAction:), selector);
else
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] " + [_source description] + " does not respond to setAction:"];
if ([_source respondsToSelector:@selector(setTarget:)])
objj_msgSend(_source, @selector(setTarget:), _destination);
else
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] " + [_source description] + " does not respond to setTarget:"];
}
@end
@implementation _CPCibOutletConnector : _CPCibConnector
{
}
- (void)establishConnection
{
[_source setValue:_destination forKey:_label];
}
@end
+17 -1
View File
@@ -14,6 +14,11 @@ var _CPCibCustomObjectClassName = @"_CPCibCustomObjectClassName";
return _className;
}
- (void)setCustomClassName:(CPString)aClassName
{
_className = aClassName;
}
- (CPString)description
{
return [super description] + " (" + [self customClassName] + ')';
@@ -42,10 +47,21 @@ var _CPCibCustomObjectClassName = @"_CPCibCustomObjectClassName";
{
var theClass = CPClassFromString(_className);
#if DEBUG
// Hey this is us!
if (theClass === [self class])
{
_className = @"CPObject";
return self;
}
if (!theClass)
{
#if DEBUG
CPLog("Unknown class \"" + _className + "\" in cib file");
#endif
theClass = [CPObject class];
}
if (theClass === [CPApplication class])
return [CPApplication sharedApplication];
+13 -15
View File
@@ -35,6 +35,11 @@
return _className;
}
- (void)setCustomClassName:(CPString)aClassName
{
_className = aClassName;
}
@end
var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
@@ -47,33 +52,26 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
if (self)
_className = [aCoder decodeObjectForKey:_CPCibCustomViewClassNameKey];
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_className forKey:_CPCibCustomViewClassNameKey];
}
- (void)drawRect:(CGRect)aRect
- (CPString)customClassName
{
var bounds = [self bounds],
context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetLineWidth(context, 1.0);
CGContextSetStrokeColor(context, [CPColor colorWithCalibratedRed:169.0 / 255.0 green:173.0 / 255.0 blue:178.0 / 255.0 alpha:1.0]);
CGContextStrokeRect(context, CGRectInset(CGRectIntegral(bounds), 0.5, 0.5));
CGContextSetFillColor(context, [CPColor colorWithCalibratedRed:224.0 / 255.0 green:236.0 / 255.0 blue:250.0 / 255.0 alpha:1.0]);
CGContextFillRect(context, CGRectInset(bounds, 2.0, 2.0));
return _className;
}
- (id)_cibInstantiate
{
var theClass = CPClassFromString(_className);
// If we don't have this class, just use CPView.
// FIXME: Should we instead throw an exception?
if (!theClass)
@@ -83,7 +81,7 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
#endif
theClass = [CPView class];
}
// Hey this is us!
if (theClass === [self class])
{
@@ -110,7 +108,7 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
[view setAutoresizingMask:[self autoresizingMask]];
[view setAutoresizesSubviews:[self autoresizesSubviews]];
[view setHitTests:[self hitTests]];
[view setHidden:[self isHidden]];
[view setAlphaValue:[self alphaValue]];
@@ -119,7 +117,7 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
[view setBackgroundColor:[self backgroundColor]];
}
return view;
}
+13 -2
View File
@@ -4,8 +4,9 @@
@implementation _CPCibKeyedUnarchiver : CPKeyedUnarchiver
{
CPBundle _bundle;
BOOL _awakenCustomResources;
CPBundle _bundle;
BOOL _awakenCustomResources;
CPDictionary _externalObjectsForProxyIdentifiers;
}
- (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle awakenCustomResources:(BOOL)shouldAwakenCustomResources
@@ -33,6 +34,16 @@
return _awakenCustomResources;
}
- (void)setExternalObjectsForProxyIdentifiers:(CPDictionary)externalObjectsForProxyIdentifiers
{
_externalObjectsForProxyIdentifiers = externalObjectsForProxyIdentifiers;
}
- (id)externalObjectForProxyIdentifier:(CPString)anIdentifier
{
return [_externalObjectsForProxyIdentifiers objectForKey:anIdentifier];
}
- (void)replaceObjectAtUID:(int)aUID withObject:(id)anObject
{
_objects[aUID] = anObject;
+7 -20
View File
@@ -25,7 +25,9 @@
@import <Foundation/CPString.j>
@import "CPCib.j"
@import "_CPCibConnector.j"
@import "CPCibConnector.j"
@import "CPCibControlConnector.j"
@import "CPCibOutletConnector.j"
@implementation _CPCibObjectData : CPObject
@@ -98,28 +100,13 @@
return self;
}
- (CPMenu)mainMenu
{
var index = [_namesValues indexOfObjectIdenticalTo:"MainMenu"];
if (index === CPNotFound)
{
index = [_namesValues indexOfObjectIdenticalTo:"Main Menu"];
if (index === CPNotFound)
return nil;
}
return _namesKeys[index];
}
- (void)displayVisibleWindows
{
var object = nil,
objectEnumerator = [_visibleWindows objectEnumerator];
while (object = [objectEnumerator nextObject])
[_replacementObjects[[object hash]] makeKeyAndOrderFront:self];
[_replacementObjects[[object UID]] makeKeyAndOrderFront:self];
}
@end
@@ -242,7 +229,7 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
if (instantiatedObject !== object)
{
_replacementObjects[[object hash]] = instantiatedObject;
_replacementObjects[[object UID]] = instantiatedObject;
if ([instantiatedObject isKindOfClass:[CPView class]])
{
@@ -266,7 +253,7 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
- (void)establishConnectionsWithOwner:(id)anOwner topLevelObjects:(CPMutableArray)topLevelObjects
{
_replacementObjects[[_fileOwner hash]] = anOwner;
_replacementObjects[[_fileOwner UID]] = anOwner;
var index = 0,
count = _connections.length;
@@ -287,7 +274,7 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
while (count--)
{
var object = _objectsKeys[count],
instantiatedObject = _replacementObjects[[object hash]];
instantiatedObject = _replacementObjects[[object UID]];
if (instantiatedObject)
object = instantiatedObject;
+33
View File
@@ -0,0 +1,33 @@
@import <Foundation/CPObject.j>
@implementation _CPCibProxyObject : CPObject
{
CPString _identifier;
}
@end
var _CPCibProxyObjectIdentifierKey = @"CPIdentifier";
@implementation _CPCibProxyObject (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
_identifier = [aCoder decodeObjectForKey:_CPCibProxyObjectIdentifierKey];
if ([aCoder respondsToSelector:@selector(externalObjectForProxyIdentifier:)])
return [aCoder externalObjectForProxyIdentifier:_identifier];
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_identifier forKey:_CPCibProxyObjectIdentifierKey];
}
@end
+51 -13
View File
@@ -2,18 +2,19 @@
@import <Foundation/CPObject.j>
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
_CPCibWindowTemplateViewClassKey = @"_CPCibWindowTemplateViewClassKey",
_CPCibWindowTemplateWindowClassKey = @"_CPCibWindowTemplateWindowClassKey",
_CPCibWindowTemplateViewClassKey = @"_CPCibWindowTemplateViewClassKey",
_CPCibWindowTemplateWindowClassKey = @"_CPCibWindowTemplateWindowClassKey",
_CPCibWindowTemplateWindowRectKey = @"_CPCibWindowTemplateWindowRectKey",
_CPCibWindowTemplateWindowStyleMaskKey = @"_CPCibWindowTempatStyleMaskKey",
_CPCibWindowTemplateWindowTitleKey = @"_CPCibWindowTemplateWindowTitleKey",
_CPCibWindowTemplateWindowViewKey = @"_CPCibWindowTemplateWindowViewKey",
_CPCibWindowTemplateWindowRectKey = @"_CPCibWindowTemplateWindowRectKey",
_CPCibWindowTemplateWindowStyleMaskKey = @"_CPCibWindowTempatStyleMaskKey",
_CPCibWindowTemplateWindowTitleKey = @"_CPCibWindowTemplateWindowTitleKey",
_CPCibWindowTemplateWindowViewKey = @"_CPCibWindowTemplateWindowViewKey",
_CPCibWindowTemplateWindowIsFullBridgeKey = @"_CPCibWindowTemplateWindowIsFullBridgeKey";
_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop = @"_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop";
_CPCibWindowTemplateWindowIsFullPlatformWindowKey = @"_CPCibWindowTemplateWindowIsFullPlatformWindowKey";
@implementation _CPCibWindowTemplate : CPObject
{
@@ -30,7 +31,27 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeK
CPString _windowTitle;
CPView _windowView;
BOOL _windowIsFullBridge;
BOOL _windowAutorecalculatesKeyViewLoop;
BOOL _windowIsFullPlatformWindow;
}
- (id)init
{
self = [super init];
if (self)
{
_windowClass = @"CPWindow";
_windowRect = CGRectMake(0.0, 0.0, 400.0, 200.0);
_windowStyleMask = CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask;
_windowTitle = @"Window";
_windowView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 400.0, 200.0)];
_windowIsFullPlatformWindow = NO;
}
return self;
}
- (id)initWithCoder:(CPCoder)aCoder
@@ -53,7 +74,8 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeK
_windowTitle = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowTitleKey];
_windowView = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowViewKey];
_windowIsFullBridge = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowIsFullBridgeKey];
_windowAutorecalculatesKeyViewLoop = !![aCoder decodeObjectForKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
_windowIsFullPlatformWindow = !![aCoder decodeObjectForKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
}
return self;
@@ -75,7 +97,22 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeK
[aCoder encodeObject:_windowTitle forKey:_CPCibWindowTemplateWindowTitleKey];
[aCoder encodeObject:_windowView forKey:_CPCibWindowTemplateWindowViewKey];
[aCoder encodeObject:_windowIsFullBridge forKey:_CPCibWindowTemplateWindowIsFullBridgeKey];
if (_windowAutorecalculatesKeyViewLoop)
[aCoder encodeObject:_windowAutorecalculatesKeyViewLoop forKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
if (_windowIsFullPlatformWindow)
[aCoder encodeObject:_windowIsFullPlatformWindow forKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
}
- (CPString)customClassName
{
return _windowClass;
}
- (void)setCustomClassName:(CPString)aClassName
{
_windowClass = aClassName;
}
- (CPString)windowClass
@@ -114,7 +151,8 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeK
[theWindow setToolbar:_viewClass];
}
[theWindow setFullBridge:_windowIsFullBridge];
[theWindow setAutorecalculatesKeyViewLoop:_windowAutorecalculatesKeyViewLoop];
[theWindow setFullBridge:_windowIsFullPlatformWindow];
return theWindow;
}
+8 -8
View File
@@ -54,8 +54,8 @@
}
/*!
Returns <code>YES</code>
@return <code>YES</code>
Returns \c YES
@return \c YES
*/
- (void)shouldArchiveValueForKey:(CPString)aKey
{
@@ -63,8 +63,8 @@
}
/*!
Returns <code>nil</code>
@return <code>nil</code>
Returns \c nil
@return \c nil
*/
+ (id)defaultValueForKey:(CPString)aKey
{
@@ -73,7 +73,7 @@
/*!
Specifies whether this animation should be removed after it has completed.
@param <code>YES</code> means the animation should be removed
@param \c YES means the animation should be removed
*/
- (void)setRemovedOnCompletion:(BOOL)isRemovedOnCompletion
{
@@ -81,7 +81,7 @@
}
/*!
Returns <code>YES</code> if the animation is removed after completion
Returns \c YES if the animation is removed after completion
*/
- (BOOL)removedOnCompletion
{
@@ -89,7 +89,7 @@
}
/*!
Returns <code>YES</code> if the animation is removed after completion
Returns \c YES if the animation is removed after completion
*/
- (BOOL)isRemovedOnCompletion
{
@@ -97,7 +97,7 @@
}
/*!
Returns the animation's timing function. If <code>nil</code>, then it has a linear pacing.
Returns the animation's timing function. If \c nil, then it has a linear pacing.
*/
- (CAMediaTimingFunction)timingFunction
{
+18 -18
View File
@@ -56,12 +56,12 @@ var CALayerRegisteredRunLoopUpdates = nil;
@delegate -(void)drawLayer:(CALayer)layer inContext:(CGContextRef)ctx;
If the delegate implements this method, the CALayer will
call this in place of its <code>drawInContext:</code>.
call this in place of its \c -drawInContext:.
@param layer the layer to draw for
@param ctx the context to draw on
@delegate -(void)displayLayer:(CALayer)layer;
The delegate can override the layer's <code>display</code> method
The delegate can override the layer's \c -display method
by implementing this method.
*/
@implementation CALayer : CPObject
@@ -419,7 +419,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
// Providing Layer Content
/*!
Returns the CGImage contents of this layer.
The default contents are <code>nil</code>.
The default contents are \c nil.
*/
- (CGImage)contents
{
@@ -547,7 +547,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
// Style Attributes
/*!
Returns the opacity of the layer. The value is between
<code>0.0</code> (transparent) and <code>1.0</code> (opaque).
\c 0.0 (transparent) and \c 1.0 (opaque).
*/
- (float)opacity
{
@@ -556,7 +556,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
/*!
Sets the opacity for the layer.
@param anOpacity the new opacity (between <code>0.0</code> (transparent) and <code>1.0</code> (opaque)).
@param anOpacity the new opacity (between \c 0.0 (transparent) and \c 1.0 (opaque)).
*/
- (void)setOpacity:(float)anOpacity
{
@@ -571,7 +571,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
/*!
Sets whether the layer is hidden.
@param isHidden <code>YES</code> means the layer will be hidden. <code>NO</code> means the layer will be visible.
@param isHidden \c YES means the layer will be hidden. \c NO means the layer will be visible.
*/
- (void)setHidden:(BOOL)isHidden
{
@@ -580,7 +580,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
}
/*!
Returns <code>YES</code> if the layer is hidden.
Returns \c YES if the layer is hidden.
*/
- (BOOL)hidden
{
@@ -588,7 +588,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
}
/*!
Returns <code>YES</code> if the layer is hidden.
Returns \c YES if the layer is hidden.
*/
- (BOOL)isHidden
{
@@ -597,7 +597,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
/*!
Sets whether content that goes lies outside the bounds is hidden or visible.
@param masksToBounds <code>YES</code> hides the excess content. <code>NO</code> makes it visible.
@param masksToBounds \c YES hides the excess content. \c NO makes it visible.
*/
- (void)setMasksToBounds:(BOOL)masksToBounds
{
@@ -724,7 +724,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
Inserts a layer below another layer.
@param aLayer the layer to insert
@param aSublayer the layer to insert below
@throws CALayerNotFoundException if <code>aSublayer</code> is not in the array of sublayers
@throws CALayerNotFoundException if \c aSublayer is not in the array of sublayers
*/
- (void)insertSublayer:(CALayer)aLayer below:(CALayer)aSublayer
{
@@ -737,7 +737,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
Inserts a layer above another layer.
@param aLayer the layer to insert
@param aSublayer the layer to insert above
@throws CALayerNotFoundException if <code>aSublayer</code> is not in the array of sublayers
@throws CALayerNotFoundException if \c aSublayer is not in the array of sublayers
*/
- (void)insertSublayer:(CALayer)aLayer above:(CALayer)aSublayer
{
@@ -779,9 +779,9 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
+ (void)runLoopUpdateLayers
{if (window.oops) {alert(window.latest); objj_debug_print_backtrace();}
window.loop = true;
for (hash in CALayerRegisteredRunLoopUpdates)
for (UID in CALayerRegisteredRunLoopUpdates)
{
var layer = CALayerRegisteredRunLoopUpdates[hash],
var layer = CALayerRegisteredRunLoopUpdates[UID],
mask = layer._runLoopUpdateMask;
if (mask & CALayerDOMUpdateMask)
@@ -813,7 +813,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
}
_runLoopUpdateMask |= anUpdateMask;
CALayerRegisteredRunLoopUpdates[[self hash]] = self;
CALayerRegisteredRunLoopUpdates[[self UID]] = self;
}
/*
@@ -834,7 +834,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
/*!
Sets whether the layer needs to be redrawn when its bounds are changed.
@param needsDisplayOnBoundsChange <code>YES</code> means the display is redraw on a bounds change.
@param needsDisplayOnBoundsChange \c YES means the display is redraw on a bounds change.
*/
- (void)setNeedsDisplayOnBoundsChange:(BOOL)needsDisplayOnBoundsChange
{
@@ -842,7 +842,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
}
/*!
Returns <code>YES</code> if the display should be redrawn on a bounds change.
Returns \c YES if the display should be redrawn on a bounds change.
*/
- (BOOL)needsDisplayOnBoundsChange
{
@@ -906,7 +906,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
// Hit Testing
/*!
Returns <code>YES</code> if the layer contains the point.
Returns \c YES if the layer contains the point.
@param aPoint the point to test
*/
- (BOOL)containsPoint:(CGPoint)aPoint
@@ -917,7 +917,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
/*!
Returns the farthest descendant of this layer that contains the specified point.
@param aPoint the point to test
@return the containing layer or <code>nil</code> if there was no hit.
@return the containing layer or \c nil if there was no hit.
*/
- (CALayer)hitTest:(CGPoint)aPoint
{
+15 -15
View File
@@ -101,8 +101,8 @@ function CGColorCreateCopy(aColor)
/*!
Creates a gray color object.
@param gray the value to use for the color intensities (<code>0.0-1.0</code>)
@param alpha the gray's alpha value (<code>0.0-1.0</code>)
@param gray the value to use for the color intensities (\c 0.\c 0-\c 1.\c 0).
@param alpha the gray's alpha value (\c 0.\c 0-\c 1.\c 0).
@return CGColor the new gray color object
@group CGColor
*/
@@ -113,10 +113,10 @@ function CGColorCreateGenericGray(gray, alpha)
/*!
Creates an RGB color.
@param red the red component (<code>0.0-1.0</code>)
@param green the green component (<code>0.0-1.0</code>)
@param blue the blue component (<code>0.0-1.0</code>)
@param alpha the alpha component (<code>0.0-1.0</code>)
@param red the red component (\c 0.\c 0-\c 1.\c 0)..
@param green the green component (\c 0.\c 0-\c 1.\c 0).
@param blue the blue component (\c 0.\c 0-\c 1.\c 0).
@param alpha the alpha component (\c 0.\c 0-\c 1.\c 0).
@return CGColor the RGB based color
@group CGColor
*/
@@ -127,11 +127,11 @@ function CGColorCreateGenericRGB(red, green, blue, alpha)
/*!
Creates a CMYK color.
@param cyan the cyan component (<code>0.0-1.0</code>)
@param magenta the magenta component (<code>0.0-1.0</code>)
@param yellow the yellow component (<code>0.0-1.0</code>)
@param black the black component (<code>0.0-1.0</code>)
@param alpha the alpha component (<code>0.0-1.0</code>)
@param cyan the cyan component (\c 0.\c 0-\c 1.\c 0).
@param magenta the magenta component (\c 0.\c 0-\c 1.\c 0).
@param yellow the yellow component (\c 0.\c 0-\c 1.\c 0).
@param black the black component (\c 0.\c 0-\c 1.\c 0).
@param alpha the alpha component (\c 0.\c 0-\c 1.\c 0).
@return CGColor the CMYK based color
@group CGColor
*/
@@ -143,7 +143,7 @@ function CGColorCreateGenericCMYK(cyan, magenta, yellow, black, alpha)
/*!
Creates a copy of the color with a specified alpha.
@param aColor the color object to copy
@param anAlpha the new alpha component for the copy (<code>0.0-1.0</code>)
@param anAlpha the new alpha component for the copy (\c 0.\c 0-\c 1.\c 0).
@return CGColor the new copy
@group CGColor
*/
@@ -184,8 +184,8 @@ function CGColorCreateWithPattern(aColorSpace, aPattern, components)
Determines if two colors are the same.
@param lhs the first CGColor
@param rhs the second CGColor
@return <code>YES</code> if the two colors are equal.
<code>NO</code> otherwise.
@return \c YES if the two colors are equal.
\c NO otherwise.
*/
function CGColorEqualToColor(lhs, rhs)
{
@@ -218,7 +218,7 @@ function CGColorEqualToColor(lhs, rhs)
/*!
Returns the color's alpha component.
@param aColor the color
@return float the alpha component (<code>0.0-1.0</code>)
@return float the alpha component (\c 0.\c 0-\c 1.\c 0).
@group CGColor
*/
function CGColorGetAlpha(aColor)
+15 -9
View File
@@ -548,7 +548,9 @@ var KAPPA = 4.0 * ((SQRT2 - 1.0) / 3.0);
*/
function CGContextAddEllipseInRect(aContext, aRect)
{
CGContextBeginPath(aContext);
CGContextAddPath(aContext, CGPathWithEllipseInRect(aRect));
CGContextClosePath(aContext);
}
/*!
@@ -650,15 +652,17 @@ function CGContextSetStrokeColor(aContext, aColor)
@param aContext the CGContext to draw into
@param aRect the base rectangle
@param aRadius the distance from the rectange corner to the rounded corner
@param ne set it to <code>YES</code> for a rounded northeast corner
@param se set it to <code>YES</code> for a rounded southeast corner
@param sw set it to <code>YES</code> for a rounded southwest corner
@param nw set it to <code>YES</code> for a rounded northwest corner
@param ne set it to \c YES for a rounded northeast corner
@param se set it to \c YES for a rounded southeast corner
@param sw set it to \c YES for a rounded southwest corner
@param nw set it to \c YES for a rounded northwest corner
@return void
*/
function CGContextFillRoundedRectangleInRect(aContext, aRect, aRadius, ne, se, sw, nw)
{
CGContextAddPath(aContext, CGPathWithRoundedRectangleInRect(aRect, aRadius, aRadius, ne, se, sw, nw));
CGContextBeginPath(aContext);
CGContextAddPath(aContext, CGPathWithRoundedRectangleInRect(aRect, aRadius, aRadius, ne, se, sw, nw));
CGContextClosePath(aContext);
CGContextFillPath(aContext);
}
@@ -667,15 +671,17 @@ function CGContextFillRoundedRectangleInRect(aContext, aRect, aRadius, ne, se, s
@param aContext the CGContext to draw into
@param aRect the base rectangle
@param aRadius the distance from the rectange corner to the rounded corner
@param ne set it to <code>YES</code> for a rounded northeast corner
@param se set it to <code>YES</code> for a rounded southeast corner
@param sw set it to <code>YES</code> for a rounded southwest corner
@param nw set it to <code>YES</code> for a rounded northwest corner
@param ne set it to \c YES for a rounded northeast corner
@param se set it to \c YES for a rounded southeast corner
@param sw set it to \c YES for a rounded southwest corner
@param nw set it to \c YES for a rounded northwest corner
@return void
*/
function CGContextStrokeRoundedRectangleInRect(aContext, aRect, aRadius, ne, se, sw, nw)
{
CGContextBeginPath(aContext);
CGContextAddPath(aContext, CGPathWithRoundedRectangleInRect(aRect, aRadius, aRadius, ne, se, sw, nw));
CGContextClosePath(aContext);
CGContextStrokePath(aContext);
}
-1
View File
@@ -312,7 +312,6 @@ function CGContextDrawLinearGradient(aContext, aGradient, aStartPoint, anEndPoin
}
aContext.gState.gradient = vml.join("");
console.log(vml.join(""));
// if (aContext.buffer != nil)
// aContext.buffer += vml.join("");
+21 -16
View File
@@ -70,18 +70,20 @@ _function(CGInsetMakeZero())
_function(CGInsetMakeCopy(anInset))
_function(CGInsetIsEmpty(anInset))
CGRectNull = _CGRectMake(Infinity, Infinity, 0.0, 0.0);
/*!
@addtogroup appkit
@{
*/
/*!
Returns a <code>BOOL</code> indicating whether CGRect <code>lhsRect</code>
contains CGRect <code>rhsRect</code>.
Returns a \c BOOL indicating whether CGRect \c lhsRect
contains CGRect \c rhsRect.
@group CGRect
@param lhsRect the CGRect to test if <code>rhsRect</code> is inside of
@param rhsRect the CGRect to test if it fits inside <code>lhsRect</code>.
@return BOOL <code>YES</code> if <code>rhsRect</code> fits inside <code>lhsRect</code>.
@param lhsRect the CGRect to test if \c rhsRect is inside of
@param rhsRect the CGRect to test if it fits inside \c lhsRect.
@return BOOL \c YES if \c rhsRect fits inside \c lhsRect.
*/
function CGRectContainsRect(lhsRect, rhsRect)
{
@@ -91,11 +93,11 @@ function CGRectContainsRect(lhsRect, rhsRect)
}
/*!
Returns <code>YES</code> if the two rectangles intersect
Returns \c YES if the two rectangles intersect
@group CGRect
@param lhsRect the first CGRect
@param rhsRect the second CGRect
@return BOOL <code>YES</code> if the two rectangles have any common spaces, and <code>NO</code>, otherwise.
@return BOOL \c YES if the two rectangles have any common spaces, and \c NO, otherwise.
*/
function CGRectIntersectsRect(lhsRect, rhsRect)
{
@@ -155,31 +157,34 @@ function CGRectStandardize(aRect)
{
var width = _CGRectGetWidth(aRect),
height = _CGRectGetHeight(aRect),
standardized = aRect;
standardized = _CGRectMakeCopy(aRect);
if (width < 0.0)
{
if (standardized == aRect)
standardized = _CGRectMakeCopy(aRect);
standardized.origin.x += width;
standardized.size.width = -width;
}
if (height < 0.0)
{
if (standardized == aRect)
standardized = _CGRectMakeCopy(aRect);
standardized.origin.y += height;
standardized.size.height = -height;
}
return standardized;
}
function CGRectUnion(lhsRect, rhsRect)
{
var lhsRectIsNull = !lhsRect || lhsRect === CGRectNull,
rhsRectIsNull = !rhsRect || rhsRect === CGRectNull;
if (lhsRectIsNull)
return rhsRectIsNull ? CGRectNull : rhsRect;
if (rhsRectIsNull)
return lhsRectIsNull ? CGRectNull : lhsRect;
var minX = MIN(_CGRectGetMinX(lhsRect), _CGRectGetMinX(rhsRect)),
minY = MIN(_CGRectGetMinY(lhsRect), _CGRectGetMinY(rhsRect)),
maxX = MAX(_CGRectGetMaxX(lhsRect), _CGRectGetMaxX(rhsRect)),
+37 -20
View File
@@ -87,20 +87,20 @@ function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle,
var center = _CGPointMake(x, y),
end = _CGPointMake(COS(anEndAngle), SIN(anEndAngle)),
start = _CGPointMake(COS(aStartAngle), SIN(aStartAngle));
end = _CGPointApplyAffineTransform(end, aTransform);
start = _CGPointApplyAffineTransform(start, aTransform);
center = _CGPointApplyAffineTransform(center, aTransform);
x = center.x;
y = center.y;
var oldEndAngle = anEndAngle,
oldStartAngle = aStartAngle;
anEndAngle = ATAN2(end.y - aTransform.ty, end.x - aTransform.tx);
aStartAngle = ATAN2(start.y - aTransform.ty, start.x - aTransform.tx);
// Angles that equal "modulo" 2 pi return as equal after transforming them,
// so we have to make sure to make them different again if they were different
// to start out with. It's the difference between no circle and a full circle.
@@ -109,7 +109,7 @@ function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle,
anEndAngle = anEndAngle - PI2;
else
aStartAngle = aStartAngle - PI2;
aRadius = _CGSizeMake(aRadius, 0);
aRadius = _CGSizeApplyAffineTransform(aRadius, aTransform);
aRadius = SQRT(aRadius.width * aRadius.width + aRadius.height * aRadius.height);
@@ -169,23 +169,38 @@ function CGPathAddLineToPoint(aPath, aTransform, x, y)
function CGPathAddPath(aPath, aTransform, anotherPath)
{
var i = 0,
count = anotherPath.count;
for (; i < count; ++i)
for (var i = 0, count = anotherPath.count; i < count; ++i)
{
var element = anotherPath.elements[i];
aPath.elements[aPath.count] = { type:element.type, x:element.x, y:element.y,
cpx:element.cpx, cpy:element.cpy,
radius:element.radius, startAngle:element.startAngle, endAngle:element.endAngle,
cp1x:element.cp1x, cp1y:element.cp1y, cp2x:element.cp2x, cp2y:element.cp2y,
points: element.points ? element.points.slice() : nil};
aPath.count++
switch (element.type)
{
case kCGPathElementAddLineToPoint: CGPathAddLineToPoint(aPath, aTransform, element.x, element.y);
break;
case kCGPathElementAddCurveToPoint: CGPathAddCurveToPoint(aPath, aTransform,
element.cp1x, element.cp1y,
element.cp2x, element.cp2y,
element.x, element.y);
break;
case kCGPathElementAddArc: CGPathAddArc(aPath, aTransform, element.x, element.y,
element.radius, element.startAngle,
element.endAngle, element.isClockwise);
break;
case kCGPathElementAddQuadCurveToPoint: CGPathAddQuadCurveToPoint(aPath, aTransform,
element.cpx, element.cpy,
element.x, element.y);
break;
case kCGPathElementMoveToPoint: CGPathMoveToPoint(aPath, aTransform, element.x, element.y);
break;
case kCGPathElementCloseSubpath: CGPathCloseSubpath(aPath);
break;
}
}
aPath.current = anotherPath.current;
}
function CGPathAddQuadCurveToPoint(aPath, aTransform, cpx, cpy, x, y)
@@ -250,6 +265,8 @@ function CGPathMoveToPoint(aPath, aTransform, x, y)
aPath.elements[aPath.count++] = { type:kCGPathElementMoveToPoint, x:point.x, y:point.y };
}
var KAPPA = 4.0 * ((SQRT2 - 1.0) / 3.0);
function CGPathWithEllipseInRect(aRect)
{
var path = CGPathCreateMutable();
-4
View File
@@ -4,10 +4,6 @@
<dict>
<key>CPBundleIdentifier</key>
<string>com.280n.AppKit</string>
<key>Default Themes Path</key>
<string>Default.cptheme</string>
<key>Default Theme Name</key>
<string>Default</string>
<key>CPBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CPBundleName</key>
+50
View File
@@ -0,0 +1,50 @@
require("../common.jake");
$BUILD_PATH = FILE.join($BUILD_DIR, $CONFIGURATION, 'AppKit');
AppKitFiles = new FileList("**/*.j").exclude('CoreGraphics/CGContextCanvas.j', 'CoreGraphics/CGContextVML.j', 'Themes/**/*', 'Tools/**/*');
appKitTask = framework ("AppKit", function(appKitTask)
{
appKitTask.setBuildIntermediatesPath(FILE.join($BUILD_DIR, "AppKit.build", $CONFIGURATION))
appKitTask.setBuildPath($BUILD_CONFIGURATION_DIR);
appKitTask.setAuthor("280 North, Inc.");
appKitTask.setEmail("feedback @nospam@ 280north.com");
appKitTask.setSummary("AppKit classes for Cappuccino");
appKitTask.setIdentifier("com.280n.AppKit");
appKitTask.setVersion("0.7.9");
appKitTask.setLicense(BundleTask.License.LGPL_v2_1);
appKitTask.setSources(AppKitFiles);
appKitTask.setResources(new FileList("Resources/**/*"));
appKitTask.setFlattensSources(true);
appKitTask.setInfoPlistPath("Info.plist");
if ($CONFIGURATION === "Release")
appKitTask.setCompilerFlags("-O");
else
appKitTask.setCompilerFlags("-DDEBUG -g");
});
$BUILD_CJS_CAPPUCCINO_APPKIT = FILE.join($BUILD_CJS_CAPPUCCINO_FRAMEWORKS, "AppKit");
filedir ($BUILD_CJS_CAPPUCCINO_APPKIT, ["AppKit"], function()
{
cp_r(appKitTask.buildProductPath(), $BUILD_CJS_CAPPUCCINO_APPKIT);
});
subtasks (["Themes"], ["clean", "clobber"]);
task ("Theme", [$BUILD_CJS_CAPPUCCINO_APPKIT], function()
{
subjake(["Themes"], "build");
cp_r(FILE.join($BUILD_DIR, $CONFIGURATION, 'Aristo.blend'), FILE.join($BUILD_PATH, 'Resources', 'Aristo.blend'));
cp_r(FILE.join($BUILD_DIR, $CONFIGURATION, 'Aristo.blend'), FILE.join($BUILD_CJS_CAPPUCCINO_APPKIT, "Resources", "Aristo.blend"));
});
task ("build", ["AppKit", $BUILD_CJS_CAPPUCCINO_APPKIT, "Theme"]);
CLOBBER.include($BUILD_CJS_CAPPUCCINO_APPKIT);
+72
View File
@@ -0,0 +1,72 @@
@import <Foundation/CPObject.j>
#include "Platform.h"
@implementation CPPlatform : CPObject
{
}
+ (void)bootstrap
{
#if PLATFORM(DOM)
var body = document.getElementsByTagName("body")[0];
body.innerHTML = ""; // Get rid of anything that might be lingering in the body element.
body.style.overflow = "hidden";
if (document.documentElement)
document.documentElement.style.overflow = "hidden";
#endif
[CPPlatformString bootstrap];
[CPPlatformWindow setPrimaryPlatformWindow:[[CPPlatformWindow alloc] _init]];
}
+ (BOOL)isBrowser
{
return typeof window.cpIsDesktop === "undefined";
}
+ (BOOL)supportsDragAndDrop
{
return CPFeatureIsCompatible(CPHTMLDragAndDropFeature);
}
+ (BOOL)supportsNativeMainMenu
{
return (typeof window["cpSetMainMenu"] === "function");
}
+ (void)terminateApplication
{
if (typeof window["cpTerminate"] === "function")
window.cpTerminate();
}
+ (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps
{
#if PLATFORM(DOM)
if (typeof window["cpActivateIgnoringOtherApps"] === "function")
window.cpActivateIgnoringOtherApps(!!shouldIgnoreOtherApps);
#endif
}
+ (void)hideOtherApplications:(id)aSender
{
#if PLATFORM(DOM)
if (typeof window["cpHideOtherApplications"] === "function")
window.cpHideOtherApplications();
#endif
}
+ (void)hide:(id)aSender
{
#if PLATFORM(DOM)
if (typeof window["cpHide"] === "function")
window.cpHide();
#endif
}
@end
+104
View File
@@ -0,0 +1,104 @@
@import <Foundation/CPObject.j>
#include "../CoreGraphics/CGGeometry.h"
#include "Platform.h"
#if PLATFORM(DOM)
var DOMIFrameElement = nil,
DOMSpanElement = nil,
DefaultFont = nil;
#endif
@implementation CPPlatformString : CPObject
{
}
+ (void)bootstrap
{
#if PLATFORM(DOM)
DOMIFrameElement = document.createElement("iframe");
DOMIFrameElement.name = name = "iframe_" + FLOOR(RAND() * 10000);
DOMIFrameElement.style.position = "absolute";
DOMIFrameElement.style.left = "-100px";
DOMIFrameElement.style.top = "-100px";
DOMIFrameElement.style.width = "1px";
DOMIFrameElement.style.height = "1px";
DOMIFrameElement.style.borderWidth = "0px";
DOMIFrameElement.style.background = "blue";
DOMIFrameElement.style.overflow = "hidden";
DOMIFrameElement.style.zIndex = 100000000000;
document.getElementsByTagName("body")[0].appendChild(DOMIFrameElement);
var DOMIFrameDocument = (DOMIFrameElement.contentDocument || DOMIFrameElement.contentWindow.document);
DOMIFrameDocument.write("<html><head></head><body></body></html>");
DOMIFrameDocument.close();
DOMSpanElement = DOMIFrameDocument.createElement("span");
DOMSpanElement.style.position = "absolute";
DOMSpanElement.style.whiteSpace = "pre";
DOMSpanElement.style.visibility = "visible";
DOMSpanElement.style.padding = "0px";
DOMSpanElement.style.margin = "0px";
DOMSpanElement.style.background = "red";
DOMIFrameDocument.getElementsByTagName("body")[0].appendChild(DOMSpanElement);
#endif
}
+ (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth
{
#if PLATFORM(DOM)
if (!aFont)
{
if (!DefaultFont)
DefaultFont = [CPFont systemFontOfSize:12.0];
aFont = DefaultFont;
}
var style = DOMSpanElement.style;
if (aWidth === NULL)
{
style.width = "";
style.whiteSpace = "pre";
}
else
{
style.width = ROUND(aWidth) + "px";
if (document.attachEvent)
style.wordWrap = "break-word";
else
{
style.whiteSpace = "-o-pre-wrap";
style.whiteSpace = "-pre-wrap";
style.whiteSpace = "-moz-pre-wrap";
style.whiteSpace = "pre-wrap";
}
}
style.font = [aFont cssString];
if (CPFeatureIsCompatible(CPJavascriptInnerTextFeature))
DOMSpanElement.innerText = aString;
else if (CPFeatureIsCompatible(CPJavascriptTextContentFeature))
DOMSpanElement.textContent = aString;
return _CGSizeMake(DOMSpanElement.clientWidth, DOMSpanElement.clientHeight);
#else
return _CGSizeMakeZero();
#endif
}
@end
+207
View File
@@ -0,0 +1,207 @@
@import <Foundation/CPObject.j>
#import "Platform.h"
#import "../CoreGraphics/CGGeometry.h"
var PrimaryPlatformWindow = NULL;
@implementation CPPlatformWindow : CPObject
{
CGRect _contentRect;
CPInteger _level;
BOOL _hasShadow;
unsigned _shadowStyle;
#if PLATFORM(DOM)
DOMWindow _DOMWindow;
DOMElement _DOMBodyElement;
DOMElement _DOMFocusElement;
CPArray _windowLevels;
CPDictionary _windowLayers;
BOOL _mouseIsDown;
CPWindow _mouseDownWindow;
CPTimeInterval _lastMouseUp;
CPTimeInterval _lastMouseDown;
Object _charCodes;
unsigned _keyCode;
BOOL _DOMEventMode;
// Native Pasteboard Support
DOMElement _DOMPasteboardElement;
CPEvent _pasteboardKeyDownEvent;
CPString _overriddenEventType;
#endif
}
+ (CPPlatformWindow)primaryPlatformWindow
{
return PrimaryPlatformWindow;
}
+ (void)setPrimaryPlatformWindow:(CPPlatformWindow)aPlatformWindow
{
PrimaryPlatformWindow = aPlatformWindow;
}
- (id)initWithContentRect:(CGRect)aRect
{
self = [super init];
if (self)
{
_contentRect = _CGRectMakeCopy(aRect);
#if PLATFORM(DOM)
_windowLevels = [];
_windowLayers = [CPDictionary dictionary];
_charCodes = {};
#endif
}
return self;
}
- (id)init
{
return [self initWithContentRect:_CGRectMake(0.0, 0.0, 400.0, 500.0)];
}
- (CGRect)contentRect
{
return _CGRectMakeCopy(_contentRect);
}
- (CGRect)contentBounds
{
var contentBounds = [self contentRect];
contentBounds.origin = _CGPointMakeZero();
return contentBounds;
}
- (CGRect)visibleFrame
{
var frame = [self contentBounds];
frame.origin = CGPointMakeZero();
if ([CPMenu menuBarVisible])
{
var menuBarHeight = [[CPApp mainMenu] menuBarHeight];
frame.origin.y += menuBarHeight;
frame.size.height -= menuBarHeight;
}
return frame;
}
- (void)usableContentFrame
{
return [self visibleFrame];
}
- (void)setContentRect:(CGRect)aRect
{
if (!aRect || _CGRectEqualToRect(_contentRect, aRect))
return;
_contentRect = _CGRectMakeCopy(aRect);
[self updateNativeContentRect];
}
- (void)updateFromNativeContentRect
{
[self setContentRect:[self nativeContentRect]];
}
- (CGPoint)convertBaseToScreen:(CGPoint)aPoint
{
var contentRect = [self contentRect];
return _CGPointMake(aPoint.x + _CGRectGetMinX(contentRect), aPoint.y + _CGRectGetMinY(contentRect));
}
- (CGPoint)convertScreenToBase:(CGPoint)aPoint
{
var contentRect = [self contentRect];
return _CGPointMake(aPoint.x - _CGRectGetMinX(contentRect), aPoint.y - _CGRectGetMinY(contentRect));
}
- (BOOL)isVisible
{
#if PLATFORM(DOM)
return _DOMWindow !== NULL;
#else
return NO;
#endif
}
- (void)deminiaturize:(id)sender
{
#if PLATFORM(DOM)
if (_DOMWindow && typeof _DOMWindow["cpDeminiaturize"] === "function")
_DOMWindow.cpDeminiaturize();
#endif
}
- (void)miniaturize:(id)sender
{
#if PLATFORM(DOM)
if (_DOMWindow && typeof _DOMWindow["cpMiniaturize"] === "function")
_DOMWindow.cpMiniaturize();
#endif
}
- (void)setLevel:(CPInteger)aLevel
{
_level = aLevel;
#if PLATFORM(DOM)
if (_DOMWindow && _DOMWindow.cpSetLevel)
_DOMWindow.cpSetLevel(aLevel);
#endif
}
- (void)setHasShadow:(BOOL)shouldHaveShadow
{
_hasShadow = shouldHaveShadow;
#if PLATFORM(DOM)
if (_DOMWindow && _DOMWindow.cpSetHasShadow)
_DOMWindow.cpSetHasShadow(shouldHaveShadow);
#endif
}
- (void)setShadowStyle:(int)aStyle
{
_shadowStyle = aStyle;
#if PLATFORM(DOM)
if (_DOMWindow && _DOMWindow.cpSetShadowStyle)
_shadowStyle.cpSetShadowStyle(aStyle);
#endif
}
- (BOOL)supportsFullPlatformWindows
{
return [CPPlatform isBrowser];
}
@end
#if PLATFORM(BROWSER)
@import "CPPlatformWindow+DOM.j"
#endif
+109 -22
View File
@@ -20,6 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define DOM_OPTIMIZATION 0
#define SetStyleOrigin 0
#define SetStyleLeftTop 0
#define SetStyleRightTop 1
@@ -45,7 +47,49 @@
CPDOMDisplayServerInstructions[__index + 2] = aTransform;\
CPDOMDisplayServerInstructions[__index + 3] = x;\
CPDOMDisplayServerInstructions[__index + 4] = y;
#if !DOM_OPTIMIZATION
#define CPDOMDisplayServerSetStyleLeftTop(aDOMElement, aTransform, aLeft, aTop) \
if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aLeft, aTop), aTransform); \
else var ____p = _CGPointMake(aLeft, aTop); \
aDOMElement.style.left = ROUND(____p.x) + "px";\
aDOMElement.style.top = ROUND(____p.y) + "px";
#define CPDOMDisplayServerSetStyleRightTop(aDOMElement, aTransform, aRight, aTop) \
if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aRight, aTop), aTransform); \
else var ____p = _CGPointMake(aRight, aTop); \
aDOMElement.style.right = ROUND(____p.x) + "px";\
aDOMElement.style.top = ROUND(____p.y) + "px";
#define CPDOMDisplayServerSetStyleLeftBottom(aDOMElement, aTransform, aLeft, aBottom) \
if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aLeft, aBottom), aTransform); \
else var ____p = _CGPointMake(aLeft, aBottom); \
aDOMElement.style.left = ROUND(____p.x) + "px";\
aDOMElement.style.bottom = ROUND(____p.y) + "px";
#define CPDOMDisplayServerSetStyleRightBottom(aDOMElement, aTransform, aRight, aBottom) \
if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aRight, aBottom), aTransform); \
else var ____p = _CGPointMake(aRight, aBottom); \
aDOMElement.style.right = ROUND(____p.x) + "px";\
aDOMElement.style.bottom = ROUND(____p.y) + "px";
#define CPDOMDisplayServerSetStyleSize(aDOMElement, aWidth, aHeight) \
aDOMElement.style.width = MAX(0.0, ROUND(aWidth)) + "px";\
aDOMElement.style.height = MAX(0.0, ROUND(aHeight)) + "px";
#define CPDOMDisplayServerSetSize(aDOMElement, aWidth, aHeight) \
aDOMElement.width = MAX(0.0, ROUND(aWidth));\
aDOMElement.height = MAX(0.0, ROUND(aHeight));
#define CPDOMDisplayServerAppendChild(aParentElement, aChildElement) aParentElement.appendChild(aChildElement)
#define CPDOMDisplayServerInsertBefore(aParentElement, aChildElement, aBeforeElement) aParentElement.insertBefore(aChildElement, aBeforeElement)
#define CPDOMDisplayServerRemoveChild(aParentElement, aChildElement) aParentElement.removeChild(aChildElement)
#define PREPARE_DOM_OPTIMIZATION()
#define EXECUTE_DOM_INSTRUCTIONS()
#else
#define CPDOMDisplayServerSetStyleLeftTop(aDOMElement, aTransform, aLeft, aTop) CPDOMDisplayServerSetStyleOrigin(SetStyleLeftTop, aDOMElement, aTransform, aLeft, aTop)
#define CPDOMDisplayServerSetStyleRightTop(aDOMElement, aTransform, aRight, aTop) CPDOMDisplayServerSetStyleOrigin(SetStyleRightTop, aDOMElement, aTransform, aRight, aTop)
@@ -99,27 +143,70 @@
CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = RemoveChild;\
CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aParentElement;\
CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aChildElement;
//#dfeine CPDOMDisplayServerCustomAction()
#define CPDOMDisplayServerAddView(aView)\
#define PREPARE_DOM_OPTIMIZATION()\
CPDOMDisplayServerInstructions = [];\
CPDOMDisplayServerInstructionCount = 0;
#define EXECUTE_DOM_INSTRUCTIONS()\
var index = 0;\
while (index < CPDOMDisplayServerInstructionCount)\
{\
var ___hash = [aView hash];\
if (typeof (CPDOMDisplayServerViewsContext[___hash]) == "undefined")\
{\
CPDOMDisplayServerViews[CPDOMDisplayServerViewsCount++] = aView;\
CPDOMDisplayServerViewsContext[___hash] = aView;\
var instruction = CPDOMDisplayServerInstructions[index++];\
try{\
switch (instruction)\
{\
case SetStyleLeftTop:\
case SetStyleRightTop:\
case SetStyleLeftBottom:\
case SetStyleRightBottom: var element = CPDOMDisplayServerInstructions[index],\
style = element.style,\
x = (instruction == SetStyleLeftTop || instruction == SetStyleLeftBottom) ? "left" : "right",\
y = (instruction == SetStyleLeftTop || instruction == SetStyleRightTop) ? "top" : "bottom";\
CPDOMDisplayServerInstructions[index++] = nil;\
var transform = CPDOMDisplayServerInstructions[index++];\
if (transform)\
{\
var point = _CGPointMake(CPDOMDisplayServerInstructions[index++], CPDOMDisplayServerInstructions[index++]),\
transformed = _CGPointApplyAffineTransform(point, transform);\
style[x] = ROUND(transformed.x) + "px";\
style[y] = ROUND(transformed.y) + "px";\
}\
else\
{\
style[x] = ROUND(CPDOMDisplayServerInstructions[index++]) + "px";\
style[y] = ROUND(CPDOMDisplayServerInstructions[index++]) + "px";\
}\
element.CPDOMDisplayContext[SetStyleOrigin] = -1;\
break;\
case SetStyleSize: var element = CPDOMDisplayServerInstructions[index],\
style = element.style;\
CPDOMDisplayServerInstructions[index++] = nil;\
element.CPDOMDisplayContext[SetStyleSize] = -1;\
style.width = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])) + "px";\
style.height = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])) + "px";\
break;\
case SetSize: var element = CPDOMDisplayServerInstructions[index];\
CPDOMDisplayServerInstructions[index++] = nil;\
element.CPDOMDisplayContext[SetSize] = -1;\
element.width = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++]));\
element.height = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++]));\
break;\
case AppendChild: CPDOMDisplayServerInstructions[index].appendChild(CPDOMDisplayServerInstructions[index + 1]);\
CPDOMDisplayServerInstructions[index++] = nil;\
CPDOMDisplayServerInstructions[index++] = nil;\
break;\
case InsertBefore: CPDOMDisplayServerInstructions[index].insertBefore(CPDOMDisplayServerInstructions[index + 1], CPDOMDisplayServerInstructions[index + 2]);\
CPDOMDisplayServerInstructions[index++] = nil;\
CPDOMDisplayServerInstructions[index++] = nil;\
CPDOMDisplayServerInstructions[index++] = nil;\
break;\
case RemoveChild: CPDOMDisplayServerInstructions[index].removeChild(CPDOMDisplayServerInstructions[index + 1]);\
CPDOMDisplayServerInstructions[index++] = nil;\
CPDOMDisplayServerInstructions[index++] = nil;\
break;\
}\
}\
catch(e) { CPLog("e " + e + " " + instruction); }\
}\
}\
#define CPDOMDisplayServerRemoveView(aView)\
{\
var index = CPDOMDisplayServerViewsContext[[aView hash]];\
if (typeof index != "undefined") \
{\
CPDOMDisplayServerViewsContext[[aView hash]];\
CPDOMDisplayServerViews[index] = NULL;\
}\
}\
CPDOMDisplayServerInstructionCount = 0;
#endif
-165
View File
@@ -1,165 +0,0 @@
/*
* CPDOMDisplayServer.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPRunLoop.j>
#include "../../CoreGraphics/CGAffineTransform.h"
#include "CPDOMDisplayServer.h"
var CPDOMDisplayRunLoop = nil;
CPDOMDisplayServerInstructions = [];
CPDOMDisplayServerInstructionCount = 0;
CPDOMDisplayServerViews = [];
CPDOMDisplayServerViewsCount = 0;
CPDOMDisplayServerViewsContext = {};
@implementation CPDOMDisplayServer : CPObject
{
}
+ (void)start
{
CPDOMDisplayRunLoop = [CPRunLoop currentRunLoop];
[CPDOMDisplayRunLoop performSelector:@selector(run) target:CPDOMDisplayServer argument:nil order:0 modes:[CPDefaultRunLoopMode]];
}
+ (void)run
{
while (CPDOMDisplayServerInstructionCount || CPDOMDisplayServerViewsCount)
{
var index = 0;
while (index < CPDOMDisplayServerInstructionCount)
{
var instruction = CPDOMDisplayServerInstructions[index++];
try{
switch (instruction)
{
case SetStyleLeftTop:
case SetStyleRightTop:
case SetStyleLeftBottom:
case SetStyleRightBottom: var element = CPDOMDisplayServerInstructions[index],
style = element.style,
x = (instruction == SetStyleLeftTop || instruction == SetStyleLeftBottom) ? "left" : "right",
y = (instruction == SetStyleLeftTop || instruction == SetStyleRightTop) ? "top" : "bottom";
CPDOMDisplayServerInstructions[index++] = nil;
var transform = CPDOMDisplayServerInstructions[index++];
if (transform)
{
var point = _CGPointMake(CPDOMDisplayServerInstructions[index++], CPDOMDisplayServerInstructions[index++]),
transformed = _CGPointApplyAffineTransform(point, transform);
style[x] = ROUND(transformed.x) + "px";
style[y] = ROUND(transformed.y) + "px";
}
else
{
style[x] = ROUND(CPDOMDisplayServerInstructions[index++]) + "px";
style[y] = ROUND(CPDOMDisplayServerInstructions[index++]) + "px";
}
element.CPDOMDisplayContext[SetStyleOrigin] = -1;
break;
case SetStyleSize: var element = CPDOMDisplayServerInstructions[index],
style = element.style;
CPDOMDisplayServerInstructions[index++] = nil;
element.CPDOMDisplayContext[SetStyleSize] = -1;
style.width = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])) + "px";
style.height = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])) + "px";
break;
case SetSize: var element = CPDOMDisplayServerInstructions[index];
CPDOMDisplayServerInstructions[index++] = nil;
element.CPDOMDisplayContext[SetSize] = -1;
element.width = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++]));
element.height = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++]));
break;
case AppendChild: CPDOMDisplayServerInstructions[index].appendChild(CPDOMDisplayServerInstructions[index + 1]);
CPDOMDisplayServerInstructions[index++] = nil;
CPDOMDisplayServerInstructions[index++] = nil;
break;
case InsertBefore: CPDOMDisplayServerInstructions[index].insertBefore(CPDOMDisplayServerInstructions[index + 1], CPDOMDisplayServerInstructions[index + 2]);
CPDOMDisplayServerInstructions[index++] = nil;
CPDOMDisplayServerInstructions[index++] = nil;
CPDOMDisplayServerInstructions[index++] = nil;
break;
case RemoveChild: CPDOMDisplayServerInstructions[index].removeChild(CPDOMDisplayServerInstructions[index + 1]);
CPDOMDisplayServerInstructions[index++] = nil;
CPDOMDisplayServerInstructions[index++] = nil;
break;
}}catch(e) { CPLog("here?" + instruction) }
}
CPDOMDisplayServerInstructionCount = 0;
var views = CPDOMDisplayServerViews,
index = 0,
count = CPDOMDisplayServerViewsCount;
// We don't reset CPDOMDisplayServerViewsContext because it can serve for displays that are coming...
CPDOMDisplayServerViews = [];
CPDOMDisplayServerViewsCount = 0;
for (; index < count; ++index)
{
var view = views[index];
delete CPDOMDisplayServerViewsContext[[view hash]];
[view layoutIfNeeded];
[view displayIfNeeded];
}
}
[CPDOMDisplayRunLoop performSelector:@selector(run) target:CPDOMDisplayServer argument:nil order:0 modes:[CPDefaultRunLoopMode]];
}
@end
[CPDOMDisplayServer start];
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -68,7 +68,7 @@
count = _windows.length - 1;
CPDOMDisplayServerRemoveChild(_DOMElement, aWindow._DOMElement);
[_windows removeObjectAtIndex:aWindow._index];
for (; index < count; ++index)
@@ -107,15 +107,16 @@
_windows[zIndex]._index = zIndex;
_windows[zIndex]._DOMElement.style.zIndex = zIndex;
}
// If the window is not already a resident of this layer, add it.
if (!isVisible)
if (aWindow._DOMElement.parentNode !== _DOMElement)
{
CPDOMDisplayServerAppendChild(_DOMElement, aWindow._DOMElement);
aWindow._isVisible = YES;
if ([aWindow isFullBridge])
[aWindow setFrame:[aWindow._bridge visibleFrame]];
[aWindow setFrame:[aWindow._platformWindow usableContentFrame]];
}
}
File diff suppressed because it is too large Load Diff
-78
View File
@@ -1,78 +0,0 @@
#!/usr/bin/env ruby
require 'rake'
require '../common'
require 'objective-j'
require 'objective-j/bundletask'
$BUILD_PATH = File.join($BUILD_DIR, $CONFIGURATION, 'AppKit')
$ENVIRONMENT_PRODUCT = File.join($ENVIRONMENT_FRAMEWORKS_DIR, 'AppKit')
$THEME_PRODUCT = File.join($BUILD_PATH, 'Resources', 'Aristo.blend')
$ENVIRONMENT_THEME_PRODUCT = File.join($ENVIRONMENT_PRODUCT, 'Resources', 'Aristo.blend')
AppKitFiles = FileList['**/*.j'].exclude('CoreGraphics/CGContextCanvas.j', 'CoreGraphics/CGContextVML.j', 'Themes/**', 'Tools/**')
ObjectiveJ::BundleTask.new(:AppKit) do |t|
t.name = 'AppKit'
t.identifier = 'com.280n.AppKit'
t.version = '0.7.0'
t.author = '280 North, Inc.'
t.email = 'feedback @nospam@ 280north.com'
t.summary = 'AppKit classes for Cappuccino'
t.sources = AppKitFiles
t.resources = FileList['Resources/*']
t.license = ObjectiveJ::License::LGPL_v2_1
t.build_path = $BUILD_PATH
t.flag = '-DDEBUG -g' if $CONFIGURATION == 'Debug'
t.flag = '-O' if $CONFIGURATION == 'Release'
t.platforms = [ObjectiveJ::Platform::Browser, ObjectiveJ::Platform::Rhino]
t.type = ObjectiveJ::Bundle::Type::Framework
end
# It would be nice to just have ENVIRONMENT_PRODUCT depend on THEME_PRODUCT,
# but this would be a circular dependency because THEME_PRODUCT needs
# ENVIRONMENT_PRODUCT up-to-date since it runs an objj application that uses
# AppKit.
file_d $ENVIRONMENT_PRODUCT => [:AppKit] do
cp_r(File.join($BUILD_PATH, '.'), $ENVIRONMENT_PRODUCT)
end
file_d $ENVIRONMENT_THEME_PRODUCT => $THEME_PRODUCT do
cp_r(File.join($THEME_PRODUCT, '.'), $ENVIRONMENT_THEME_PRODUCT)
end
ThemeFiles = FileList['Themes/Aristo/*']
file_d $THEME_PRODUCT => ThemeFiles << $ENVIRONMENT_PRODUCT do
File.popen("blend -d Themes/Aristo/ThemeDescriptors.j -o #{$THEME_PRODUCT} -R Themes/Aristo/Resources") do |blend|
blend.sync = true
while str = blend.gets
puts str
end
end
end
task :build => [:build_subprojects, :AppKit, $ENVIRONMENT_PRODUCT, $THEME_PRODUCT, $ENVIRONMENT_THEME_PRODUCT]
task :clean => :clean_suprojects
task :clobber => :clobber_subprojects
subprojects = %w{Tools}
task :build_subprojects do
subrake(subprojects, :build)
end
task :clean_suprojects do
subrake(subprojects, :clean)
end
task :clobber_subprojects do
subrake(subprojects, :clobber)
end
CLOBBER.include($ENVIRONMENT_PRODUCT)
Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

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