Compare commits

...
599 Commits
Author SHA1 Message Date
Ross Boucher 16a70c5c8e Update to the starter package readme. 2011-02-22 14:09:09 -08:00
Randall Luecke b78eddd878 Clearer explaination of setPullsDown: of CPPopupButton 2011-02-04 19:01:12 -05:00
Randall Luecke 203942d123 Documentation of CPApplication. 2011-01-30 16:56:56 -05:00
Klaas Pieter Annema 5957e71967 enable nib2cib image support for CPMenuItem 2011-01-28 14:50:42 +01:00
Randall Luecke fdf47eb84e Fix for tableview reloadData call inside setObjectValue: causing additional editing to being. 2011-01-27 14:37:26 -05:00
Paul Baumgart 6963b37f61 Add --clone-http option to bootstrap 2011-01-26 21:09:10 -08:00
Ayal SpitzandPaul Baumgart 379c5294c2 Added a 'clone_http' flag to enable clonging of a git repo via http 2011-01-26 20:57:42 -08:00
Francisco Ryan Tolmasky I fb27f86126 Merge branch 'paulbaumgart-bootstrap-fixes' 2011-01-26 08:03:24 -08:00
Klaas Pieter Annema 133dd39485 don't blur input element more than once 2011-01-26 11:03:09 +01:00
Paul Baumgart d50cbb02e6 Allow users to respond 'yes' to the narwhal install location bootstrap prompt to just use the default location. 2011-01-25 17:39:24 -08:00
Randall Luecke 30695e4110 Document delete key delegate in tableview. 2011-01-25 11:03:12 -05:00
Jürgen Kartnaller 3e79d8324d Fix check for allowsReverseTransformation in reverseTransformedValue 2011-01-25 08:46:40 +01:00
Randall Luecke 71de04787d Fix backspace issue with textfield. Closes #1107. Thanks to Jukart for the patch. 2011-01-24 18:25:18 -05:00
Randall Luecke 81332fa57e Proper theme states for the tableview edit change I made yesterday. 2011-01-24 15:35:10 -05:00
Randall Luecke 191a02a89b Update documentation version number to 0.9. 2011-01-24 14:28:07 -05:00
Ross Boucher f4ae6c450b Update the README a bit. 2011-01-24 10:19:52 -08:00
Alexander Ljungberg f2c53c9f52 Documentation tweaks. 2011-01-24 14:00:15 -03:00
Alexander Ljungberg 090fcab8c6 More globals fixing. 2011-01-24 13:43:55 -03:00
Alexander Ljungberg d3836c2a52 Global fixes. 2011-01-24 13:22:07 -03:00
Alexander Ljungberg ea8c29356d More typo and formatting fixes. 2011-01-24 13:17:48 -03:00
Stephen Ierodiaconou 6a942630e4 Fixing spelling mistakes 2011-01-24 11:05:48 +02:00
Randall Luecke 2aa806e52a Docs for CPControl. 2011-01-24 01:18:40 -05:00
Randall Luecke 04f1b61534 Fixes to tableview inline editing. 2011-01-24 00:56:39 -05:00
Randall Luecke b6119a763e Docs for CPWebView. 2011-01-23 19:05:02 -05:00
Randall Luecke 0876fd6db9 Docs of CPViewAnimation. 2011-01-23 18:10:26 -05:00
Randall Luecke 3d106c0716 Merge branch 'master' of git://github.com/280north/cappuccino 2011-01-23 17:53:20 -05:00
Randall Luecke c390b19d4b Much needed documentation of CPSplitView and some docs for CPWindow. 2011-01-23 17:50:39 -05:00
Francisco Ryan Tolmasky I 6a735ecda9 Merge branch 'master' of github.com:280north/cappuccino 2011-01-23 08:44:01 -08:00
Francisco Ryan Tolmasky I aada884cff A few import fixes.
Reviewed by me.
2011-01-23 08:43:46 -08:00
Paul Baumgart b62789bb18 Check for one of curl or wget. 2011-01-21 17:35:33 -08:00
Paul Baumgart eafec339f1 Minor update to bootstrap to have it check to make sure java is installed. 2011-01-21 16:49:32 -08:00
Alexander Ljungberg ef326dbbb4 Fix an accidental global, whitespace. 2011-01-20 22:33:42 -03:00
Alexander Ljungberg 4bbbcb15f1 Array controller documentation. 2011-01-20 22:27:09 -03:00
Alexander Ljungberg 92cb69b623 Merge branch 'CPArrayControllerFixes' of https://github.com/cacaodev/cappuccino into cacaodev-CPArrayControllerFixes 2011-01-20 22:14:17 -03:00
Alexander Ljungberg 18ea086ffc Removed unused Aristo files. 2011-01-20 22:13:01 -03:00
Alexander Ljungberg 40b04b7956 Merge branch 'master' of github.com:280north/cappuccino into cacaodev-CPTableColumnValueBinder
Conflicts:
	AppKit/CPTableColumn.j
2011-01-20 21:56:30 -03:00
Francisco Ryan Tolmasky I 38dc125fc2 Fix CPSubclassableDictionaryTest.
Reviewed by me.
2011-01-20 09:50:32 -08:00
Francisco Ryan Tolmasky I 378df68995 Merge branch 'master' of github.com:280north/cappuccino 2011-01-20 09:17:29 -08:00
Francisco Ryan Tolmasky I ec330a1090 Fix for pop up not reflecting changes in individual menu items.
Reviewed by me.
2011-01-20 09:07:04 -08:00
Randall Luecke f07543045a Doc fixes and more docs in the tableview. 2011-01-20 03:07:01 -05:00
Paul Baumgart 4458884048 Fallback to wget if curl isn't installed. 2011-01-19 20:28:49 -08:00
Paul Baumgart 7245fb99a6 Check to make sure SSL is working in tusk and advise on how to fix it otherwise. 2011-01-19 20:27:16 -08:00
Paul BaumgartandPaul Baumgart 5d27661354 Update check_build_environment in bootstrap
Newer versions of OpenJDK can handle running Narwhal.
It seems the problem is fixed in versions of OpenJDK 6 >= b18.
This commit checks for a sufficiently recent version of
OpenJDK and only prints an error/exits if the OpenJDK
version is older than 6b18.
2011-01-19 20:26:28 -08:00
Francisco Ryan Tolmasky I b33b2df778 Merge branch 'master' of github.com:280north/cappuccino 2011-01-19 19:30:46 -08:00
Francisco Ryan Tolmasky I d2f27408a5 Additional fix for archived CPPopUpButtons, and backwards compatibility support for old archives/cibs.
Reviewed by me.
2011-01-19 19:29:39 -08:00
cacaodev 235b323658 Add CPTableColumnValueBinder. This binder subclass just reloads the table column when a table column's value binding is updated because of a change in the bound-to object.
TableBindings test.
2011-01-19 19:56:46 +01:00
cacaodev 54c3cc0187 CPArrayController & nib2cib: added _automaticallyRearrangeObjects flag (not used currently).
_sortDescriptors initial value is an emty array (like in cocoa), not nil;
Added shared _init with default values, added missing accessors.
2011-01-19 19:26:21 +01:00
cacaodev 59cc590b51 CPArrayController -setContent: fixed a bug where objects where not rearranged if clearsFilterPredicateOnInsertion == YES and filterPredicate == nil. 2011-01-19 19:26:01 +01:00
Randall Luecke 66a87c472b Remove old resources from the old CPTabView. 2011-01-19 11:15:31 -05:00
Francisco Ryan Tolmasky I 688aed72cb Fix for CPPopUpButton's encoded prior to CPResponder/menu change.
Reviewed by me.
2011-01-18 23:09:43 -08:00
Francisco Ryan Tolmasky I 6310733881 Fix for menu bar color being reset (+ [CPMenu initialize] didn't check the class).
Reviewed by me.
2011-01-18 13:59:57 -08:00
Francisco Ryan Tolmasky I 3fe505b8e5 Merge branch 'master' of github.com:280north/cappuccino 2011-01-18 13:26:14 -08:00
Francisco Ryan Tolmasky I 00915083d4 Quick fix for initWithCapacity: not working on CPMutableArray.
Reviewed by me.
2011-01-18 13:25:43 -08:00
Klaas Pieter Annema 4e1ecbef72 Merge branch 'CPTextField-InterpretKeyEvents' of https://github.com/luuse/cappuccino into luuse-CPTextField-InterpretKeyEvents
Conflicts:
	AppKit/CPSearchField.j
	AppKit/CPTextField.j
2011-01-18 10:07:16 +01:00
Klaas Pieter Annema e4f6214005 Merge branch 'imports' of https://github.com/stevegeek/cappuccino into stevegeek-imports 2011-01-18 09:52:40 +01:00
Klaas Pieter Annema ed98a44116 detect sort descriptors when table column is added 2011-01-18 09:29:29 +01:00
Klaas Pieter Annema 50d36e76ac reverse set sort descriptors in CPTableView 2011-01-18 09:29:28 +01:00
Randall Luecke 818bf475f2 New gradient color to match aristo better. 2011-01-17 23:30:29 -05:00
Randall Luecke 47afb96c4c Drawing fixes for the tableview gradient. 2011-01-17 23:30:04 -05:00
Randall Luecke 467dc3c2d5 OutlineView docs. 2011-01-17 20:13:54 -05:00
Randall Luecke 7e3079add6 Magic enable to outlineview variable item height 2011-01-17 20:07:15 -05:00
Francisco Ryan Tolmasky I 9796f5d5d7 Fix CPPopUpButton menu support.
- Added enumerateObjectsUsingBlock: to CPArray
- Fixed a remaining case of [] being used instead of objectAtIndex: in CPMutableArray.
- Added KVO support for menu items array in menus.
- Changed CPPopUpButton to use KVO to sync up with menu instead of notifications.
- Removed extra menu encoding in CPPopUpButton.
- Removed extra mainMenu object from CPApplication.
- Use setters in CPResponder instead of direct ivar access in initWithCoder:.

Closes #298.
Closes $1059.

Reviewed by me.
2011-01-17 01:31:15 -08:00
Stephen Ierodiaconou 37323b811c Merge branch 'master' of git://github.com/280north/cappuccino into imports
Conflicts:
	Foundation/CPDecimalNumber.j
	Foundation/CPPredicate/CPComparisonPredicate.j
	Foundation/CPPredicate/CPCompoundPredicate.j
	Foundation/CPPredicate/CPExpression.j
	Foundation/CPPredicate/CPExpression_aggregate.j
	Foundation/CPPredicate/CPExpression_constant.j
	Foundation/CPPredicate/CPExpression_function.j
	Foundation/CPPredicate/CPExpression_keypath.j
	Foundation/CPPredicate/CPExpression_self.j
	Foundation/CPPredicate/CPExpression_set.j
	Foundation/CPPredicate/CPExpression_subquery.j
	Foundation/CPPredicate/CPExpression_variable.j
	Foundation/CPPredicate/CPPredicate.j
2011-01-16 10:03:42 +02:00
Randall Luecke 8720a952b0 Fix for scrollview flashing while uniformly resizing columns. Closes #1075 2011-01-16 00:23:14 -05:00
Randall Luecke bf4724d401 Fix for textfield jumping when textfield wasn't the right size or the vertical alignment was something other than center. 2011-01-15 23:15:55 -05:00
Randall Luecke c73e2e1a91 Fix for nib2cib'd textfields jumping when editing 2011-01-15 21:45:37 -05:00
Randall Luecke 630cd121a6 Typo in docs 2011-01-15 20:40:24 -05:00
Randall Luecke 5d88ffbe66 Merge branch 'decimal' of https://github.com/stevegeek/cappuccino into stevegeek-decimal 2011-01-15 20:32:24 -05:00
Randall Luecke bd5aa1c959 Merge branch 'CPPredicate' of https://github.com/cacaodev/cappuccino into cacaodev-CPPredicate 2011-01-15 18:50:12 -05:00
Stephen Ierodiaconou c65bfd22a2 Use native javascript array for mantissa for big performance increase 2011-01-16 01:47:14 +02:00
Randall Luecke e656e0561b removeTableColumn: on the outlineview shouldn't allow removal of outlineTableColumn per cocoa. 2011-01-15 18:31:41 -05:00
Randall Luecke ddbba22533 Only set the outlineview column if it's the first column added. 2011-01-15 18:10:28 -05:00
Randall Luecke 91b5596034 Merge branch 'cacaodev-CPOutlineView' 2011-01-15 17:59:13 -05:00
Stephen Ierodiaconou e0185a0eff Documentation for CPDecimalNumber 2011-01-15 21:58:47 +02:00
Stephen Ierodiaconou 2fe8845842 CPDecimalString returns NaN for a NaN and Fix Compare of NaNs and Cocoa compatable handling of overflow/underflows when no exception 2011-01-15 19:29:55 +02:00
Stephen Ierodiaconou c02128a1fd Instantiate default number handler lazily and fix CPDecimalNumberHandler initialisers and CPDecimalNumberHandler docs 2011-01-15 18:50:47 +02:00
Stephen Ierodiaconou 27ad98e160 Initialiser fixes and docs
Fix tests for new initialisers
2011-01-15 16:40:11 +02:00
Stephen Ierodiaconou fc746db70f Cocoa compatible constructors for CPDecimals 2011-01-15 16:12:06 +02:00
Stephen Ierodiaconou 6a6256bdb4 CPCoding support for CPDecimalNumber and test 2011-01-15 14:15:31 +02:00
Stephen Ierodiaconou 5a0cfc1595 Make default number hanler file global only and Improvements and optimisations for CPDecimalNumber 2011-01-15 11:49:20 +02:00
Stephen Ierodiaconou 32107ab650 Improvements to CPDecimalNumberHandler including docs and archiving/unarchiving and associated test. 2011-01-15 09:38:31 +02:00
Stephen Ierodiaconou 494f615aaa Merge branch 'master' into imports
Conflicts:
	Foundation/CPScanner.j
2011-01-15 09:11:46 +02:00
Francisco Ryan Tolmasky I 5c2ebd546c Don't include a delegate class entry in Info.plist for nib application templates.
Reviewed by me.
2011-01-14 15:42:23 -08:00
cacaodev 72b8ed2faf CPOutlineView: If nil, set outlineTableColumn when the first column is added.
nib2cib: handle indentationPerLevel when the key is not in the xib.
CPoutlineViewCibTest
2011-01-15 00:39:38 +01:00
Alexander Ljungberg 6b8c85df7c Additional testing for outline view archiving. 2011-01-14 19:59:25 -03:00
Alexander Ljungberg cce4e3ded8 Fixed: manual CPBrowser test's click handler threw an exception. 2011-01-14 14:46:37 -03:00
Alexander Ljungberg 0240c648aa Encode delegate when archiving CPBrowser. 2011-01-14 14:36:57 -03:00
Alexander Ljungberg 6019ff9107 Fixed: archiving 'undefined' would cause an exception. 2011-01-14 14:25:11 -03:00
Alexander Ljungberg c4ee83e4c1 Basic CPBrowser CPCoding support. 2011-01-14 13:34:18 -03:00
Alexander Ljungberg 61b0cbb1af Test CPBrowser data loading. 2011-01-14 12:42:38 -03:00
Alexander Ljungberg af30e96b7b Cleanup. 2011-01-14 12:16:51 -03:00
Alexander Ljungberg b7bdec189a Fixed: when an outline view node was expanded, selections below it would not stick to their items if the newly expanded node also had previously expanded children. 2011-01-14 12:10:52 -03:00
Alexander Ljungberg 2a27a87ae6 Fixed: CPOutlineView could not be archived with CPCoding. Closes #1093.
This fixes the exception "[_CPOutlineViewTableViewDataSource encodeWithCoder:] unrecognized selector sent to instance".
2011-01-13 22:18:05 -03:00
Alexander Ljungberg 31ac84f683 Fix non ASCII codes in documentation. 2011-01-13 20:59:28 -03:00
Alexander Ljungberg c41defe864 Merge branch 'master' of github.com:280north/cappuccino 2011-01-13 20:56:58 -03:00
Alexander Ljungberg 6bc109f7fc Optimised: outline view expandItem:expandChildren:YES sent repeated selection change notifications. 2011-01-13 20:51:43 -03:00
Alexander Ljungberg 2d603df83c Fixed: outline view's collapseItem sent up selection notifications in triplicate, each of them at the wrong time. 2011-01-13 20:03:06 -03:00
Alexander Ljungberg dcf440396d Fixed: the outline view was temporarily inconsistent to outside observers while expanding a node.
In particular, a selection did change notification was sent before the rows the selection referred to had had a chance to be loaded.
2011-01-13 18:57:36 -03:00
Randall Luecke 1dc10440b7 Documentaion of CPObjectController. 2011-01-13 00:57:07 -05:00
Randall Luecke 0ef2557ec3 Documentation of CPArrayController. 2011-01-13 00:30:50 -05:00
Randall Luecke 05e69c85c7 More documentation of the tableview, outlineview, and table columns. Wrapped formatted documenation in <pre> tags and added sample code for using custom dataviews 2011-01-12 23:40:28 -05:00
cacaodev 9c6476615d Allow parsing of functions with multiple arguments like multiply:by:(5,2) or FUNCTION('method:arg:', arg1, arg2)
Added a missing CPDate.j import in CPExpression_function that was causing an 'unknown variable CPDate' error in deploy builds.
Added documentation for +expressionForSubquery:...
Added licence headers with credits.
2011-01-12 18:43:09 +01:00
Randall Luecke b393d0597f If selectedRow no longer exists when numberOfRows change reset it to CPNotFound. Closes #1089. 2011-01-12 11:49:36 -05:00
Francisco Ryan Tolmasky I f69e2e8d8f Merge branch 'master' of github.com:280north/cappuccino 2011-01-12 08:41:26 -08:00
Francisco Ryan Tolmasky I 5fd470acea Fix for adding a js object to a CPArray and associated tests.
Reviewed by me.
2011-01-12 08:41:02 -08:00
Alexander Ljungberg 28e660c295 Merge branch 'master' of github.com:280north/cappuccino 2011-01-12 11:02:33 -03:00
Alexander Ljungberg 9a76b4451f Cleanup. 2011-01-12 10:54:47 -03:00
Alexander Ljungberg b50f955cfd Standardise source file header. 2011-01-12 10:52:35 -03:00
Francisco Ryan Tolmasky I 0aa2e2b298 0.9.0 RC 1.
Reviewed by me.
2011-01-11 16:12:30 -08:00
Francisco Ryan Tolmasky I 1f5ad49591 CPMutableArray fixes and tests.
Reviewed by me.
2011-01-11 15:27:35 -08:00
Francisco Ryan Tolmasky I 3e45c7895c More tests and bug fixes for CPArray family.
Reviewed by me.
2011-01-11 12:08:00 -08:00
Francisco Ryan Tolmasky I 29301f440e Fixed a few bugs in CPArray and added many new tests for CPArray.
Reviewed by me.
2011-01-11 10:12:26 -08:00
Francisco Ryan Tolmasky I 2f86c0d9d2 Slight initWithArray:shouldCopyItems: fix.
Reviewed by me.
2011-01-10 09:21:46 -08:00
Klaas Pieter Annema e7dbd5a5cc add test for CPButton setObjectValue: behavior 2011-01-10 09:32:18 +01:00
Francisco Ryan Tolmasky I 62c00bb7f5 Fix for press removing all files.
Reviewed by me.
2011-01-10 00:19:34 -08:00
Aparajita Fishman 12f0d2a867 Fixes to content-inset bugs introduced by b80c48886a 2011-01-09 19:04:12 -05:00
Francisco Ryan Tolmasky I 5af66b60e1 Better -copy implementations for KVC arrays and sets.
Reviewed by me.
2011-01-09 03:46:29 -08:00
Francisco Ryan Tolmasky I 028a4fe5b2 Merge branch 'CPKeyValueCodingArray-copy' of https://github.com/cacaodev/cappuccino into cacaodev-CPKeyValueCodingArray-copy 2011-01-09 03:29:51 -08:00
Francisco Ryan Tolmasky I fa6e711c2f Merge branch 'master' of github.com:280north/cappuccino 2011-01-09 03:27:46 -08:00
Francisco Ryan Tolmasky I c620c7bf39 Fix for %% being broken in sprintf (minor bugfix for press message showing undefined, larger press bugs remain).
Reviewed by me.
2011-01-09 03:25:59 -08:00
Derek Hammer f3066594fe Tests for Pull Request 1085 2011-01-08 22:12:20 -06:00
Francisco Ryan Tolmasky I 4db1e28677 Merge branch 'trunk' of https://github.com/meelash/cappuccino into meelash-trunk 2011-01-08 15:27:34 -08:00
meelash d6cbc52790 Fix for issue #302 CPTabViewItem _tabView is not set. Closes #302 2011-01-08 15:15:13 -05:00
Alexander Ljungberg 0943065498 Merge branch 'master' of github.com:280north/cappuccino into eventualbuddha-CPTokenField-sendAction-fix
Conflicts:
	AppKit/CPTokenField.j
2011-01-07 18:53:44 -03:00
Alexander Ljungberg 42cc3f309f Manual test for token field action sending. 2011-01-07 18:52:18 -03:00
Alexander Ljungberg 6d7dc24775 Merge branch 'CPTokenField-sendAction-fix' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-CPTokenField-sendAction-fix 2011-01-07 18:14:17 -03:00
Klaas Pieter Annema 8faa17ad33 reset allow mixed state when bound 2011-01-07 15:20:12 +01:00
Klaas Pieter Annema 3d5232b308 give objects a chance to change their binder class
- make every object calling getBinding:forObject: aware of this change
- implement _CPCheckBoxValueBinder to handle binding to the value of a checkbox Closes: #1083
- re-implement CPTextField's behavior for controller markers using the new binder class
- disabled some tests that are not compliant with Cocoa
2011-01-07 14:14:19 +01:00
Klaas Pieter Annema c2bab5b369 fix [CPButton setObjectValue:CPOnState] 2011-01-07 14:14:19 +01:00
Klaas Pieter Annema eee1dcef13 restore the original placeholder when unbinding 2011-01-07 14:14:19 +01:00
Randall Luecke 8254543da7 Fix for scrollColumnToVisisble also scrolling in the Y direction. Also fixed headerview not being scrolled. Closes #1081 2011-01-06 15:22:18 -06:00
Randall Luecke 2028efabc3 Fix for scrollRowToVisible changing the X value instead of just the Y. Closes #1082 2011-01-06 15:08:35 -06:00
Randall Luecke 011c033478 Merge branch 'master' of git://github.com/280north/cappuccino 2011-01-06 14:51:16 -06:00
Randall Luecke 477e9f85be Fix for variable row heights when initial setup of the tableview had zero rows 2011-01-06 14:50:40 -06:00
Ilya Kulakov 0d5ae63013 The isSubsetOfSet looking for objects inside itself instead of provided set 2011-01-07 02:03:11 +06:00
Francisco Ryan Tolmasky I aa60a7b975 Use stubbed out Array methods instead of relying on them existing on the object.
Reviewed by me.
2011-01-06 10:28:24 -08:00
Francisco Ryan Tolmasky I c071569f3c Fix for @import loop when pressing.
Reviewed by me.
2011-01-05 18:24:42 -08:00
Alexander Ljungberg 1d717ffe99 Merge branch 'flllow-outlineview-selection' 2011-01-05 21:30:34 -03:00
Alexander Ljungberg c53fff058b Preserve selection when expanding items in an outline view. 2011-01-05 21:25:57 -03:00
Alexander Ljungberg c836bd48e0 Preserve selection when collapsing items in an outline view.
This fixes the error where if a row was selected below a certain item and that item was collapsed, the row selection would remain fixed in place even while the item it was highlighting moved upwards.
2011-01-05 21:09:19 -03:00
Alexander Ljungberg ec675a5662 Deselect outline view items when their ancestor is collapsed. 2011-01-05 20:41:26 -03:00
Alexander Ljungberg 02e72493ef Unit test outline view data loading and item collapse. 2011-01-05 20:40:30 -03:00
Alexander Ljungberg dd2ad410b8 Cleanup. 2011-01-05 17:45:51 -03:00
cacaodev 92fb183c22 CPKeyValueCodingArray/Set -copy. Fetch all objects through accessors, that's what cocoa does. 2011-01-05 19:21:13 +01:00
Klaas Pieter Annema 46eca09d69 determine sorted column in setSortDescriptors:
Closes #1079
2011-01-05 12:48:19 +01:00
Klaas Pieter Annema f7bc2b6d06 add a description to CPSortDescriptor 2011-01-05 12:47:36 +01:00
Klaas Pieter Annema c87cb4bacd properly fix CPThemeStateNormal behavior
- revert the previous fix
- explicitly check for CPThemeStateNormal in hasThemeState:
- update the test case
2011-01-05 12:30:14 +01:00
Klaas Pieter Annema b6ea6530b7 hasThemeState: always returned no for normal state 2011-01-05 10:44:50 +01:00
Randall Luecke af4e69afc9 Fix for variable row heights with no rows on startup 2011-01-05 01:46:12 -06:00
Randall Luecke a292936d55 Extra bracket. 2011-01-04 23:01:44 -06:00
Randall Luecke a000687a42 Fix for CPArray and _CPJavaScriptArray -copy 2011-01-04 22:59:33 -06:00
Alexander Ljungberg 03aaa89a61 Merge branch 'master' of github.com:280north/cappuccino 2011-01-04 17:02:11 -03:00
Alexander Ljungberg be71d957e1 Fixed: indexOfObject:inSortedRange: searched 1 index too far when a range was applied. 2011-01-04 17:00:48 -03:00
Francisco Ryan Tolmasky I 651970899d Merge branch 'primalmotion-fix-cptabview' 2011-01-04 11:26:01 -08:00
Antoine Mercadal ae67b00c4d remove the change in tabViewItemAtIndex: 2011-01-04 20:06:53 +01:00
Alexander Ljungberg 51848b6cce Merge branch 'master' of github.com:280north/cappuccino 2011-01-04 16:06:25 -03:00
Alexander Ljungberg 8e0b3a5df3 Test indexOfObject:inSortedRange: with out of range insertion point. 2011-01-04 15:38:54 -03:00
Randall Luecke 692c43a3cc Snap columns when we size the last column to fit. 2011-01-04 12:36:57 -06:00
Antoine Mercadal 29430df66d fix small bugs in CPTabView 2011-01-04 19:36:05 +01:00
Alexander Ljungberg 9954a75cdd Fixed array test arrayByReversingArray. More indexOfObject:inSortedRange:... tests. 2011-01-04 15:30:02 -03:00
Alexander Ljungberg 6ee7964fa6 Cleanup. 2011-01-04 13:42:00 -03:00
Ilya KulakovandAlexander Ljungberg db6608571a Refs #1071. indexOfObject:inSortedRange:options:usingComparator is incorrectly implemented.
Add more tests to cover more features of the indexOfObject:inSortedRange:options:usingComparator method
2011-01-04 13:37:06 -03:00
Randall Luecke 76d5051833 Remove unused variable 2011-01-03 20:25:56 -06:00
cacaodevandRandall Luecke 9cdcbb1988 OutlineView should decode a new instance of tableview delegate 2011-01-03 20:24:01 -06:00
Randall Luecke 33882942e4 Documentation of the outlineview and some API fixes. 2011-01-03 20:17:12 -06:00
Randall Luecke 6c2c690504 Remove log 2011-01-03 16:23:43 -06:00
Randall Luecke c78f232e4a Fix for ouline column disclosure button staying in place while resizing 2011-01-03 16:22:28 -06:00
Randall Luecke 5f39046a52 Document setBorderType: for CPScrollView 2011-01-03 15:53:00 -06:00
Randall Luecke fff2be49fc Fix for outline column dragging leaving disclosure indicator in place. 2011-01-03 15:36:19 -06:00
Alexander Ljungberg 95a2b46ae1 Merge branch 'master' of github.com:280north/cappuccino 2011-01-03 16:37:47 -03:00
Alexander Ljungberg 754324d253 Table view documentation fix. 2011-01-03 16:36:26 -03:00
Francisco Ryan Tolmasky I b350b89376 Added some more KVO tests.
Reviewed by me.
2011-01-02 13:16:43 -08:00
Alexander Ljungberg 4445f752f3 Avoid usage of [event keyCode].
Key codes have platform and browser specific behaviours.
2011-01-02 13:15:38 -03:00
Alexander Ljungberg 9e92947b2c Cleanup, fix accidental global in the average operator. 2011-01-02 11:42:40 -03:00
Alexander Ljungberg 92d44b12bd Fixed: a recent change disabled first and last column resizing modes. 2010-12-31 20:56:24 -03:00
Alexander Ljungberg 36c673c660 Whitespace cleanup. 2010-12-31 15:25:39 -03:00
Alexander Ljungberg db509cb72f Merge branch 'master' of github.com:280north/cappuccino 2010-12-31 15:24:09 -03:00
Alexander Ljungberg c0af2af7e7 Merge branch 'master' of https://github.com/Kentzo/cappuccino into Kentzo-master 2010-12-31 15:12:35 -03:00
Alexander Ljungberg 35b2b5263c Test table view inline cell editing in general, and the next fix in particular. 2010-12-31 14:59:24 -03:00
Alexander Ljungberg fa3df44535 Fixed: the text field selectText: message worked significantly differently in unit tests than in the browser.
The message normally makes the text field the first responder, but this did not happen outside of the DOM platform.

Also documented the first responder side effect.
2010-12-31 14:49:03 -03:00
Alexander Ljungberg 08dd7d6951 ASCII fix, cleanup. 2010-12-31 14:18:56 -03:00
Alexander Ljungberg d7316918a3 Refactor test data source in table view test. 2010-12-31 12:56:56 -03:00
Ilya Kulakov 044fc3af69 Refs issue #1607. Make CPTableView the first responder after user is done editing dataview. 2010-12-31 12:07:42 +06:00
Francisco Ryan Tolmasky I d1eb20e7b3 Merge branch 'master' of https://github.com/snaury/cappuccino into snaury-master 2010-12-30 21:49:50 -08:00
Alexander Ljungberg c27edb2475 Various documentation fixes. 2010-12-30 00:06:06 -03:00
Alexander Ljungberg 58d4030133 Brief documentation about using bindings to provide data for a table view. 2010-12-29 23:40:30 -03:00
Alexander Ljungberg e8b1063647 Whitespace cleanup. 2010-12-29 23:17:18 -03:00
Alexander Ljungberg 3caa703ced Bring back testing of HUD style CPAlerts.
This part of the test was temporarily disabled recently due to changes which broke HUD style CPAlerts.
2010-12-29 23:15:22 -03:00
Alexander Ljungberg f7e016a98c Merge branch 'cpalert-fixes' of https://github.com/primalmotion/cappuccino into primalmotion-cpalert-fixes 2010-12-29 23:11:10 -03:00
Randall Luecke 156e9b8e54 Merge branch 'master' of git://github.com/280north/cappuccino 2010-12-29 19:45:36 -06:00
Randall Luecke 7aa00a961a Attached sheets should have a shadow. 2010-12-29 19:45:09 -06:00
Alexey Borzenkov 4678efff72 Fix #1063 [CPDate description] returns incorrect timezone + tests 2010-12-28 23:42:06 +03:00
Klaas Pieter Annema f3b4e7f752 fixes for inline table editing
- make sure the data view is reset to it's no editable state when a textfield is dismissed without editing
- remove a comment (selectText: works now)
2010-12-27 19:48:21 +01:00
Francisco Ryan Tolmasky I e39fa44cdb Fix for typo in new KVC code.
Reviewed by me.
2010-12-27 10:40:27 -08:00
Francisco Ryan Tolmasky I 3fb4d1e4c1 Merge branch 'master' of github.com:280north/cappuccino 2010-12-27 10:38:41 -08:00
Francisco Ryan Tolmasky I 06b8636817 Removed remaining references to isKeyObserved.
Reviewed by me.
2010-12-27 10:38:10 -08:00
Randall Luecke 4b653ee367 in sizeLastColumnToFit make sure we respect min/max widths 2010-12-27 12:05:38 -06:00
Klaas Pieter Annema d2cdd46466 fix a typo in CPTableView 2010-12-27 13:52:50 +01:00
David K. HessandFrancisco Ryan Tolmasky I 2d46fb885d Fix for -nextValidKeyView infinitely looping when no next valid key view.
Closes #1049.

Reviewed by me.
2010-12-27 03:17:52 -08:00
Francisco Ryan Tolmasky I b3e0c4a5d5 Added a FIXME.
Reviewed by me.
2010-12-27 03:05:20 -08:00
Francisco Ryan Tolmasky I ab6609282d Some reorganization.
Reviewed by me.
2010-12-27 03:02:00 -08:00
Francisco Ryan Tolmasky I 6ff21692f1 Fix for incorrectly installing KVO if all the mutation methods aren't implemented.
Reviewed by me.
2010-12-27 02:18:52 -08:00
Randall Luecke f64cc4c655 Bounds errors on rectOfColumn 2010-12-27 01:25:32 -06:00
Randall Luecke e31af96ef9 Made the selection behavior more correct 2010-12-27 00:59:46 -06:00
Randall Luecke a431b34c43 Merge branch 'master' of git://github.com/280north/cappuccino 2010-12-26 17:40:15 -06:00
Randall Luecke 562bb8a878 setIntercellSpacing doesn't update dateviews. Closes #827 2010-12-26 17:39:10 -06:00
Francisco Ryan Tolmasky I 719dbf02d4 Merge branch 'master' of github.com:280north/cappuccino 2010-12-26 15:38:01 -08:00
Francisco Ryan Tolmasky I e2327fcf94 Fix for remaining delegate reference instead of _delegate in CPTabView.
Closes #1061.

Reviewed by me.
2010-12-26 15:36:06 -08:00
Randall Luecke 5a0c8f4a8b Legacy tableviews cibs dont decode properly. Closes #850 2010-12-26 17:31:54 -06:00
Francisco Ryan Tolmasky I 031a380c25 Merge branch 'master' of github.com:280north/cappuccino 2010-12-26 15:27:10 -08:00
Francisco Ryan Tolmasky I 23c4e584d4 Automatically re-validate toolbar items in multi-document windows, and restore removeObjectsInArray: to CPMutableSet.
Reviewed by me.
2010-12-26 15:26:04 -08:00
Randall Luecke 452febd73e Test for uniform column resizing 2010-12-26 17:17:27 -06:00
Randall Luecke 645741aa23 Merge branch 'master' of git://github.com/280north/cappuccino 2010-12-26 16:14:34 -06:00
Randall Luecke 97b141b653 Fixes for uniform column resizing 2010-12-26 13:44:31 -06:00
Francisco Ryan Tolmasky I 67ac778d4c Sight improvement to applyChange: in KVO.
Reviewed by me.
2010-12-26 00:31:14 -08:00
Stephen Ierodiaconou 76b5682234 Missing imports in CPSet+KVO 2010-12-26 10:29:46 +02:00
Francisco Ryan Tolmasky I e45ed19dc7 Fix remaining failing tests and add indexOfObject:inSortedRange:options:usingComparator:, and removed non-standard methods:
- indexOfObject:sortedBySelector:
- indexOfObject:sortedByFunction:
- indexOfObject:sortedByDescriptors:
- indexOfObject:sortedByFunction:context:

Reviewed by me.
2010-12-25 21:10:32 -08:00
Francisco Ryan Tolmasky I f79c2346a5 More test fixes.
Reviewed by me.
2010-12-25 17:05:31 -08:00
Francisco Ryan Tolmasky I e964c60830 Fix a few failing tests, and a bad import.
Reviewed by me.
2010-12-25 16:58:09 -08:00
Francisco Ryan Tolmasky I f8ffb4abbd Small fix and whitespace fix.
Reviewed by me.
2010-12-25 16:38:56 -08:00
Francisco Ryan Tolmasky I 37931f08b5 First pass at CPArray class cluster.
Reviewed by me.
2010-12-25 16:07:30 -08:00
Stephen Ierodiaconou 4aa4f1a62a Some more missing imports 2010-12-26 01:47:26 +02:00
Stephen Ierodiaconou 7ae14e9eb5 CPCharacterSet lint and fixes 2010-12-26 01:34:43 +02:00
Stephen Ierodiaconou bfe03a8874 CPJSONPConnection Missing imports and self check 2010-12-26 01:34:43 +02:00
Stephen Ierodiaconou 66b6b44f86 CPPredicate lint, import fixes, and some bug fixes 2010-12-26 01:34:43 +02:00
Stephen Ierodiaconou b70018bd80 Import fixes and lint 2010-12-26 01:34:37 +02:00
Francisco Ryan Tolmasky I 9b75e37e1f A number of set and array fixes and added tests for unordered accessor pattern in key value coding.
Reviewed by me.
2010-12-25 02:18:02 -08:00
Francisco Ryan Tolmasky I 232f1d008d Added better implementation of valueForKey for indexed accessor pattern and tests for it.
Reviewed by me.
2010-12-25 01:47:18 -08:00
Francisco Ryan Tolmasky I 3947bd65f2 Reimplementation of CPSet as a class-cluster, and better set support for valueForKey:
1. CPSet and CPMutableSet are now abstract super classes that create appropriate concrete subclasses behind the scenes.
2. CPSet subclassers need only implement -count, -member:, and -objectEnumerator.
3. CPMutableSet subclassers need only implement -count, -member:, -objectEnumerator:, -addObject:, and removeObject:.
4. Added more CPSet tests.
5. Added _CPKeyValueCodingSet which subclasses CPSet for set returns in valueForKey:.

Reviewed by me.
2010-12-25 01:01:19 -08:00
Francisco Ryan Tolmasky I 1d39299a7d Fix for missing imports and incorrect variable.
Reviewed by me.
2010-12-24 23:36:53 -08:00
Francisco Ryan Tolmasky I da1389b0b4 Forgot one last typo.
Reviewed by me.
2010-12-24 16:46:17 -08:00
Francisco Ryan Tolmasky I 818c7dac3d Fix for set accessor methods.
Reveiwed by me.
2010-12-24 16:29:40 -08:00
Francisco Ryan Tolmasky I 15b05304cc Cleanup setValue:forKey:.
Reviewed by me.
2010-12-24 13:20:13 -08:00
Francisco Ryan Tolmasky I e33c7f6be4 Initial support for valueForKey: supporting sets and arrays.
Reviewed by me.
2010-12-24 12:42:28 -08:00
Francisco Ryan Tolmasky I d23bf7b927 Some KVC cleanup:
1. Added class_getInstanceVariable to runtime.
2. Changed KVC to rely on class-defined variables vs prototypal ones.
3. Modified KVO code to use public APIs.

Reviewed by me.
2010-12-23 23:46:23 -08:00
Klaas Pieter Annema de1ebe6319 add test case for previous fix 2010-12-22 10:49:02 +01:00
cncolder 3e9e0802f6 Show null placeholder when the value is CPNull. 2010-12-22 15:15:05 +08:00
Randall Luecke b8f9263d18 Fixed some 3am typos in the documentation 2010-12-21 16:55:00 -05:00
Randall Luecke 946cd381a0 Compelete documentation of the tableview and tablecolumns (which the exception of bindins) 2010-12-21 02:29:14 -05:00
Francisco Ryan Tolmasky I 0a49d09878 Merge branch 'new-aristo-theme' of https://github.com/primalmotion/cappuccino into primalmotion-new-aristo-theme 2010-12-20 14:07:12 -08:00
Antoine Mercadal f936277a4d make CPTokenField's token pixel perfect 2010-12-20 21:34:25 +01:00
Antoine Mercadal ac16c5663b fix the frame size of the pulldown button 2010-12-20 21:25:40 +01:00
Francisco Ryan Tolmasky I 83058b01d3 Remove AppKit imports from Foundation.
Bugs filed to deal with associated technologies: #1051 and #1052

Reviewed by me.
2010-12-20 11:14:55 -08:00
Francisco Ryan Tolmasky I 3c8619db5d Merge branch 'fixes' of https://github.com/stevegeek/cappuccino into stevegeek-fixes
Conflicts:
	Foundation/CPValueTransformer.j
2010-12-20 11:13:54 -08:00
Randall Luecke 14226ef69c Merge branch 'master' of git://github.com/280north/cappuccino 2010-12-19 20:19:02 -05:00
Randall Luecke 910691ad4b Capp Lint of tableview 2010-12-19 20:18:36 -05:00
Alexander Ljungberg 115d29b6f8 Fixed: if data source was nil, the table view needlessly warned about no content binding in numberOfRowsInTableView.
A table with a nil data source and no content binding is simply an empty table, or more likely, a table not fully configured yet.
2010-12-19 22:54:29 +01:00
Francisco Ryan Tolmasky I 05ef7c83a8 Merge branch 'CPTokenField-missing-import' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-CPTokenField-missing-import 2010-12-19 12:43:43 -08:00
Francisco Ryan Tolmasky I 2311fb9a6d Merge branch 'master' of github.com:280north/cappuccino 2010-12-19 12:37:46 -08:00
Francisco Ryan Tolmasky I c1b8ec8da1 Some minor style changes and perf improvements.
Reviewed by me.
2010-12-19 12:34:57 -08:00
Randall Luecke a1efd1d024 Merge branch 'master' of git://github.com/280north/cappuccino 2010-12-19 15:33:26 -05:00
Randall Luecke 088b6eac35 Last row of the tableview didn't draw 2010-12-19 15:32:52 -05:00
Francisco Ryan Tolmasky I ea1068c465 Merge branch 'nib2cib-binding-transformer' of https://github.com/cncolder/cappuccino into cncolder-nib2cib-binding-transformer 2010-12-19 12:21:03 -08:00
Brian Donovan 978545af94 Import required CPTableView. 2010-12-19 11:46:13 -08:00
Randall Luecke 86c10e687b Row offset regression fix, removed console.log 2010-12-19 02:06:25 -05:00
Randall Luecke 24ab9f9fdf Merge branch 'master' of git://github.com/280north/cappuccino 2010-12-18 22:32:24 -05:00
Randall Luecke 5d69bbc4ca Fixed several bugs and regressions in the tableview. 2010-12-18 22:31:49 -05:00
Johannes FahrenkrugandFrancisco Ryan Tolmasky I 3c3b7ff61c Addition of applications tests and CPCollectionView selection fix.
Reviewed by me.
2010-12-18 10:34:32 -08:00
cncolder 5a6e266c8d nib2cib binding with buildin transformers support. 2010-12-18 15:02:25 +08:00
Brian Donovan 6f724e34f5 Fix apostrophe typo. 2010-12-17 17:14:58 -08:00
Antoine Mercadal 7cec421419 revert test 2010-12-17 12:55:49 +01:00
Antoine Mercadal 967f541659 change inset for CPTokenField 2010-12-17 12:52:23 +01:00
Antoine Mercadal 6e78d903e0 make only border translucent in disabled state 2010-12-17 12:52:22 +01:00
Antoine Mercadal 03a243fd20 Make CPPopUpButton art pixel perfect 2010-12-17 12:52:22 +01:00
Antoine Mercadal 0b8d3744bb update MainMenu bar art 2010-12-17 12:52:22 +01:00
Antoine Mercadal a0bb3b31a3 adding the art for disabled CPTextField 2010-12-17 12:52:22 +01:00
Antoine Mercadal 1f79402a0a use alpha-ized art.. 2010-12-17 12:52:22 +01:00
Antoine Mercadal f7db4058a8 fix another inset issue 2010-12-17 12:52:22 +01:00
Antoine Mercadal 4d9854695a fix a offset in inset 2010-12-17 12:52:22 +01:00
Antoine Mercadal e90133ebd0 uses the new CPPPopUpButton Aristo art 2010-12-17 12:52:22 +01:00
Antoine Mercadal d4818b5a71 uses the new CPTextField Aristo art 2010-12-17 12:52:21 +01:00
Ross Boucher 68a15c5c7c Be more lenient in documents about strings versus URLs.
Fix a typo in CPTextField.
2010-12-16 17:22:32 -08:00
Francisco Ryan Tolmasky I 42db55fabd Apply Chrome Frame fix across the board.
Reviewed by me.
2010-12-16 14:49:15 -08:00
Francisco Ryan Tolmasky I e6c1dfc51e Merge branch 'google-chrome-frame-support' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-google-chrome-frame-support 2010-12-16 14:24:26 -08:00
Stephen Ierodiaconou 4f3146dc7b Remove unnecessary defines of MIN/MAX/ABS 2010-12-16 20:20:58 +02:00
Francisco Ryan Tolmasky I 4372edb7c4 Fix for remaining reference to objj_standardize_path.
Closes #1040.

Reviewed by me.
2010-12-16 09:51:44 -08:00
Stephen Ierodiaconou d105388d82 Move CPOrderedX to CPObjRuntime only instead of duplicated in CPSortDescriptor 2010-12-16 19:16:38 +02:00
Stephen Ierodiaconou fd812f25a5 Imports additions
Import fixes and clean up

Missing import

Missing imports

Missing import

Remove uncessary comments
2010-12-16 19:16:33 +02:00
Stephen Ierodiaconou 9f5904eaf2 Alphabetical order 2010-12-16 17:34:02 +02:00
Stephen Ierodiaconou d246b19750 Some linting and deprecation error and ivar '_' addition 2010-12-16 17:18:11 +02:00
cncolder 128a3ac4d9 Commit ab083a3b change CPTabView variable names to underscore style. This patch fix nib2cib NSTabView. 2010-12-16 14:19:46 +08:00
Ross Boucher abd908949a Merge branch 'master' of github.com:280north/cappuccino 2010-12-15 15:53:23 -08:00
Ross Boucher ab083a3baf Clean up several flaws in CPTabView:
- should not force empty space above and below, but only where the tabs are
- box should fill frame when no tabs are present
- ivars should be prefixed with underscore
- not sure about the current background color code, may revisit
2010-12-15 15:48:42 -08:00
Alexander Ljungberg 45ee3aa0a3 Merge branch 'master' of github.com:280north/cappuccino 2010-12-15 23:32:16 +01:00
Alexander Ljungberg d587016cc3 Fixed: CPSegmentedControl did not take divider width into account when auto sizing. This resolves the incorrect tab sizes in CPTabView.
If a segmented control was initialised with a zero width and then expanded with setSegmentCount, it would not allocate space for any needed dividers. The more tabs were added the more the segmented control would be undersized. The fix is to automatically adjust the width when dividers are added or removed.
2010-12-15 23:26:31 +01:00
Alexander Ljungberg 8edee4e755 Fix accidental globals, cleanup. 2010-12-15 16:02:50 +01:00
Klaas Pieter Annema 8aeaa6681a implement menuForEvent in CPTableView 2010-12-15 15:30:10 +01:00
Klaas Pieter Annema 8a0a68248c don't check valid row range in dragging code 2010-12-15 15:30:10 +01:00
Alexander Ljungberg 251ba407be Implement CPURL isEqualToURL:. 2010-12-15 11:08:28 +01:00
Alexander Ljungberg bd28d688aa Merge branch 'CPScrollView-home-end-fix' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-CPScrollView-home-end-fix 2010-12-15 01:06:32 +01:00
Alexander Ljungberg 6ab679a725 Optimise _processKeyboardUIKey by only declaring the keys of interest once. 2010-12-15 01:06:02 +01:00
Brian Donovan 6b7d636b0d Follow tolmasky's suggestions.
- Fixes a bug in moveByOffset where we called CGPointMake with a CGPoint.
- Remove _moveToPoint: and just inline it where it was used.
2010-12-14 16:00:20 -08:00
Alexander Ljungberg f72749fbd6 Allow home and end function keys as unqualified key equivalents. Manual test for home and end function keys. 2010-12-15 00:26:42 +01:00
Alexander Ljungberg 9a032a57d0 Merge branch 'CPScrollView-home-end-fix' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-CPScrollView-home-end-fix 2010-12-15 00:12:30 +01:00
Alexander Ljungberg 244ff0d846 Finished unit test based on Cocoa example With And Without Bindings 02. 2010-12-14 23:57:51 +01:00
Alexander Ljungberg c65726fb12 Fixed: CPURL isEqual threw an exception if the argument was not a CPURL. 2010-12-14 23:49:24 +01:00
Alexander Ljungberg 8ef7f07195 Fixed: CPArrayController's addObject and CPArray's insertObject:inArraySortedByDescriptors:.
CPArray insertObject:inArraySortedByDescriptors: now quickly inserts objects at the end of the array if no sort descriptors are specified.

CPArrayController initialises its sort descriptors to an empty array.

Fixed: array controller's addObject added objects to the arranged objects array in a different order than in the content array if no sort descriptor was set.
2010-12-14 23:33:14 +01:00
Alexander Ljungberg 2af2fc31a1 Fixed: archived table views could end up with a nil sort descriptor instead of an empty array. 2010-12-14 21:36:04 +01:00
Brian Donovan 9bf0edb5df Implement CPScrollView scrollToBeginningOfDocument: and scrollToEndOfDocument:.
Also ensures that the home/end DOM keys were properly mapped to their Cocoa equivalents, so that home/end will trigger scrollToBeginningOfDocument:/scrollToEndOfDocument:.
2010-12-14 12:12:25 -08:00
Alexander Ljungberg 53f4baa9ac Fixed: CPArrayController add: and insert: would fail if automaticallyPreparesContent was NO.
This was caused by an unimplemented method in the original adapted from Cocotron CPObjectController.
2010-12-14 20:44:22 +01:00
Alexander Ljungberg 63cc9c4b36 Fixed: nib2cib did not properly transfer the 'isEditable' property for object and array controllers. 2010-12-14 20:28:57 +01:00
Alexander Ljungberg 8b60ef1156 Added nib2cib support for several array controller properties.
The properties in question are declaredKeys, automaticallyPreparesContent and objectClass, from the base object controller class.
2010-12-14 20:28:40 +01:00
Brian Donovan 751a80afb7 Google Chrome Frame doesn't work with duplicate X-UA-Compatible header.
There should only be one X-UA-Compatible header and it should have the chrome=1 part at the end, per http://www.chromium.org/developers/how-tos/chrome-frame-getting-started.

"You may recognize the X-UA-Compatible flag as the same mechanism introduced with IE 8 for controlling the rendering engine that IE uses for a particular page. In cases where GCF is not installed, the values can be combined to control IE's rendering behavior:"

    <meta http-equiv="X-UA-Compatible" content="IE=8,chrome=1">
2010-12-14 10:37:15 -08:00
Alexander Ljungberg f2b2852b76 Allow array controllers as table sources in cibs.
When an array controller is loaded from a cib, the data source may be connected before the bindings are. Hence, we can't check for required data source methods at the time because we do not know if we are using bindings yet. The new behaviour is to only warn when the methods are actually required, which matches Cocoa.
2010-12-14 17:35:34 +01:00
Alexander Ljungberg f36d8224a6 Unit test based on Cocoa example With And Without Bindings 01.
This test exercises loading of an array controller with bindings to a table and a content array, plus various editing actions.
2010-12-14 15:05:30 +01:00
Alexander Ljungberg c5c2a80af9 More unit tests on 01_WithoutBindings. 2010-12-14 13:40:44 +01:00
Alexander Ljungberg b9dfd2a795 Merge branch 'master' of github.com:280north/cappuccino 2010-12-14 12:36:53 +01:00
Alexander Ljungberg b381fe6c27 Cleanup. 2010-12-14 12:36:37 +01:00
Klaas Pieter Annema 003dcface0 make selectedTag accessor public again
This reverts commit cfee75b6e9.
2010-12-13 22:16:06 +01:00
Alexander Ljungberg 0e05f1a8b7 Merge branch 'master' of github.com:280north/cappuccino 2010-12-13 13:39:41 +01:00
Klaas Pieter Annema 5a340804fe remove failing reverse set selected tag test 2010-12-13 10:55:10 +01:00
Klaas Pieter Annema 65f6c35c88 add manual test for CPPopUpButton 2010-12-13 10:44:25 +01:00
Klaas Pieter Annema cfee75b6e9 rename CPPopUpButton selectedTag to _selectedTag 2010-12-13 10:38:23 +01:00
Klaas Pieter Annema 0463af26b3 Merge branch 'CPPopUpButton-selectedTag-binding' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-CPPopUpButton-selectedTag-binding 2010-12-13 10:11:46 +01:00
Francisco Ryan Tolmasky I ced3c2d778 Missing @end in NSMutableDictionary.
Reviewed by me.
2010-12-11 21:51:27 -08:00
Francisco Ryan Tolmasky I 7e4e6932a0 Merge branch 'cpbutton-rounded-hud-support' of https://github.com/primalmotion/cappuccino into primalmotion-cpbutton-rounded-hud-support 2010-12-11 11:47:15 -08:00
Blair DuncanandFrancisco Ryan Tolmasky I 13940c97e7 Manual test for issue 842.
Reviewed by me.
2010-12-11 11:41:15 -08:00
Francisco Ryan Tolmasky I 91d28cbbdd Fix for FireFox plists breaking with text over 4096 bytes.
Closes #842.

Reviewed by me.
2010-12-11 11:29:49 -08:00
Antoine Mercadal adc2d2b513 support for HUD rounded button 2010-12-11 14:34:03 +01:00
Randall Luecke c80116e90d Removed leftover from versioning fixes 2010-12-11 01:01:56 -05:00
Francisco Ryan Tolmasky I f667c39ade Further versioning fix.
Reviewed by me.
2010-12-10 09:04:13 -08:00
Randall Luecke ce0ddb2e1f Test for previous commit 2010-12-10 10:29:59 -05:00
Randall Luecke 3a716c08f8 CPObject -version should be static and zero by default. 2010-12-10 10:01:33 -05:00
Francisco Ryan Tolmasky I d69f46f7ee More capp_linting.
Reviewed by me.
2010-12-09 13:45:29 -08:00
Ross Boucher 3cda75986b Merge branch 'master' of github.com:280north/cappuccino 2010-12-09 13:08:52 -08:00
Francisco Ryan Tolmasky I ffea2de826 Style fixes.
Reviewed by me.
2010-12-09 13:00:52 -08:00
Ross Boucher ac6ccc3257 Merge branch 'master' of https://github.com/dasto/cappuccino into dasto-master
Conflicts:
	Tests/Foundation/CPKeyValueCodingTest.j
2010-12-09 12:59:11 -08:00
Daniel Stolzenberg 29ed8f3116 fixed issues with "CPKeyValueObservingOptionPrior" and "CPKeyValueObservingOptionOld" on dependent keys caused by improper wrapped observation messages 2010-12-09 14:56:55 +01:00
Ross Boucher 3f2dd34ee5 We should be using UID not hash 2010-12-08 16:43:45 -08:00
Ross Boucher df7c8bf508 Remove unwanted global. 2010-12-08 16:11:25 -08:00
Ross Boucher 1e2fdc3e1b Remove tabs; Update some of the toll free bridging code. 2010-12-08 15:44:28 -08:00
Ross Boucher 901f3fe63b Merge branch 'nib2cib-bindings-options' of https://github.com/cacaodev/cappuccino into cacaodev-nib2cib-bindings-options 2010-12-08 14:11:23 -08:00
Ross Boucher a767d2199d Merge branch 'tollfreefix' of https://github.com/hammerdr/cappuccino into hammerdr-tollfreefix 2010-12-08 13:35:22 -08:00
Ross Boucher ceb4432b49 Add a round button to the aristo showcase 2010-12-08 13:32:04 -08:00
Ross Boucher b80c48886a Merge branch 'cpbutton-rounded-bezel-style-support' of https://github.com/primalmotion/cappuccino into primalmotion-cpbutton-rounded-bezel-style-support
Conflicts:
	AppKit/Themes/Aristo/ThemeDescriptors.j
2010-12-08 13:23:14 -08:00
Brian Donovan 55121d501b Call will/didChange manually since this isn't a setter. 2010-12-08 07:38:10 -08:00
Brian Donovan 2c0c8b59a2 Fix documentation typo. 2010-12-07 11:44:48 -08:00
Brian Donovan 788419d64c NSPopUpButton has no public -setSelectedTag, so make it private. 2010-12-07 07:23:50 -08:00
Brian Donovan 735a38d134 NSPopUpButton has no CPValueBinding, use @"selectedIndex". 2010-12-07 07:23:30 -08:00
Francisco Ryan Tolmasky I 8d80903cf2 Merge branch 'CPFontManager-fix' of https://github.com/aparajita/cappuccino into aparajita-CPFontManager-fix 2010-12-06 11:46:52 -08:00
Aparajita Fishman 432c98f5f7 Fix variable name 2010-12-06 14:05:18 -05:00
Klaas Pieter Annema f7495155af Merge branch 'issue702' of https://github.com/stevegeek/cappuccino into stevegeek-issue702 2010-12-06 09:47:08 +01:00
Francisco Ryan Tolmasky I c2ee9a9a5e Fix for rows not showing up in tablviews that were not directly in scrollviews.
Reviewed by Randy.
2010-12-04 18:52:46 -08:00
Francisco Ryan Tolmasky I 71bbd85ba4 Fix for ctrl not being interpreted as command in Linux.
Reviewed by me.
2010-12-04 11:12:28 -08:00
Francisco Ryan Tolmasky I 3776a7bee1 Fix for invisible toolbar items sending their associated menu item as the sender for their actions.
Reviewed by me.
2010-12-04 10:43:34 -08:00
Francisco Ryan Tolmasky I fb51a0f892 Merge branch 'CPMenu-menuWillOpen-fix' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-CPMenu-menuWillOpen-fix 2010-12-04 09:46:22 -08:00
Francisco Ryan Tolmasky I 2d74d9fa92 Slight style fix.
Reviewed by me.
2010-12-04 09:43:35 -08:00
Francisco Ryan Tolmasky I 2014f47046 Merge branch 'master' of github.com:280north/cappuccino 2010-12-04 09:42:56 -08:00
Brian Donovan 79c2edca2d Allow binding to CPPopUpButton's selectedTag. 2010-12-03 16:12:22 -08:00
Klaas Pieter Annema 175f1a9acd add support for windows in CPViewAnimation 2010-12-03 15:08:53 +01:00
Mike Fellows 18e943a65b Expand the KeyEquivalent manual test to include tests for the keys allowed without Cmd/Ctrl modifier. Also include an additional check that each button's callback is being called. 2010-12-03 02:06:04 -08:00
Francisco Ryan Tolmasky I 20f36eaa9a Added platform windows manual test.
Reviewed by me.
2010-12-02 18:41:00 -08:00
Francisco Ryan Tolmasky I 6cbff694ab Fix for CPTextField not found in tests.
Reviewed by me.
2010-12-02 17:20:35 -08:00
Randall Luecke 54e106bb14 Merge branch 'master' of git://github.com/280north/cappuccino
Conflicts:
	AppKit/CPTableView.j
2010-12-02 19:51:40 -05:00
Randall Luecke 3d1992440b Fix drag and drop bug 2010-12-02 19:50:55 -05:00
Francisco Ryan Tolmasky I 1cbaea0e3d Further capp_linting - removing accidental global.
Reviewed by me.
2010-12-02 12:11:57 -08:00
Francisco Ryan Tolmasky I 400bdb5103 Further capp_linting.
Reviewed by me.
2010-12-02 11:44:42 -08:00
Francisco Tolmasky dd560fb78c capp_lint CPAnimation.j.
Reviewed by me.
2010-12-02 10:38:51 -08:00
Ross Boucher e71cbfbde2 Need to re-examine this.
Revert "Make @accessors generating code with static type. Not id only. This is useful when check ivar infomation from class_copyMethodList(YourClass)."

This reverts commit c713a3fb25.
2010-12-02 10:06:10 -08:00
Klaas Pieter Annema eb6c103396 Merge branch 'fixes' of https://github.com/MCF/cappuccino into MCF-fixes 2010-12-02 10:58:14 +01:00
Klaas Pieter Annema 45c585e5c2 fix CPViewAnimation invalid dictionary key strings 2010-12-02 10:54:27 +01:00
Francisco Ryan Tolmasky I 0ab92c77bd More capp_linting.
Reviewed by me.
2010-12-01 22:57:57 -08:00
Francisco Ryan Tolmasky I 2d1fd1b3a5 Merge branch 'master' of github.com:280north/cappuccino 2010-12-01 20:40:55 -08:00
Derek Hammer d4d831b9ac Fixing a bug caused by the function inline. 2010-12-01 20:12:12 -08:00
cncolderandRoss Boucher c713a3fb25 Make @accessors generating code with static type. Not id only. This is useful when check ivar infomation from class_copyMethodList(YourClass). 2010-12-01 19:16:12 -08:00
Francisco Ryan Tolmasky I ff60125183 Some capp_linting.
Reviewed by me.
2010-12-01 11:04:17 -08:00
Klaas Pieter Annema 94d28a2593 Merge branch 'cacaodev-CPSearchField' 2010-12-01 10:35:51 +01:00
cacaodevandKlaas Pieter Annema 43f8b50ef7 revert _searchMenuTemplate -> searchMenuTemplate 2010-12-01 10:35:25 +01:00
cacaodevandKlaas Pieter Annema 7c098753cf CPSearchField:
- Fix recentAutosaveName decoding (setter was needed)
- Fix a bug where 2 search fields in the same app would receive the same recentSearches update when recentAutosaveName set.
- Update recentAutosaveName to use the new CPUserDefaults class instead of CPCookie.
- searchMenuTemplate nib2cib decoding. searchMenutemplate is just an outlet, it's automatically connected.
- Removed CPSearchFieldSeparatorItemTag
- Updated Test app with a nib2cibed search field. Ability to set some options for the regular search field.
- Style and white space.
2010-12-01 10:35:25 +01:00
Stephen Ierodiaconou b46d283dc4 Closes 702: CPBezierPath stroke calls CGContextClosePath 2010-12-01 09:45:46 +02:00
Mike Fellows f9639eb695 Add the space key as an allowable key equivalent 2010-11-30 23:09:02 -08:00
Brian Donovan 9fc0006316 Fix copy-paste error in calling the menuDidOpen: delegate method. 2010-11-30 17:58:26 -08:00
Klaas Pieter Annema a51672cc82 use charAt in CPDecimal, IE doesn't support [] 2010-11-30 16:05:32 +01:00
Klaas Pieter Annema 32decc31db CGContext should close path after fill or stroke 2010-11-29 12:47:38 +01:00
Klaas Pieter Annema 14d9aac98b add the test project used for the bindings fix 2010-11-29 09:49:58 +01:00
Randall Luecke 327962bc01 Fix for intercellSpacing reference and fix for the outlineview... 2010-11-28 13:32:30 -05:00
Randall Luecke 4197bbe73c Fixed some intercell spacing issues 2010-11-27 17:04:10 -05:00
Randall Luecke e3ef20eec3 Fixed up the variable row height test. 2010-11-27 16:48:08 -05:00
Randall Luecke 8ddb80fca2 Rewrote background color drawing code. 2010-11-27 16:45:59 -05:00
Randall Luecke b8eb72f823 Fixes for drag and drop with variable row heights. 2010-11-27 13:19:51 -05:00
Randall Luecke 9003177bb7 Added more variable row height tabletests 2010-11-27 04:04:21 -05:00
Randall Luecke 591142ba84 Some clean up 2010-11-27 03:57:02 -05:00
Randall Luecke 7b4f7f75b0 Made variable rows actually work... 2010-11-27 02:47:15 -05:00
Randall Luecke 31b2cb35f7 Fix syntax errors causing the build to break 2010-11-27 01:09:24 -05:00
Randall Luecke 20eb2a9fb0 instance variable initialized twice from merge 2010-11-27 00:16:27 -05:00
Randall Luecke 37d9bff77f Merge branch 'master' into tableview-variable
Conflicts:
	AppKit/CPTableView.j
2010-11-26 17:44:37 -05:00
Alexander Ljungberg f3f0bf3524 Unit test based on Cocoa example With And Without Bindings 01. 2010-11-26 17:12:46 -03:00
Alexander Ljungberg b9ca57a921 Merge branch 'master' of github.com:280north/cappuccino 2010-11-26 15:57:48 -03:00
Alexander Ljungberg 04546e39a5 Missing semicolon, indentation. 2010-11-26 15:57:04 -03:00
Alexander Ljungberg e6cf98f743 Fixed: [tableview selectedRow] returned nil right after awakening from a cib.
The correct response is CPNotFound.
2010-11-26 15:53:14 -03:00
Alexander Ljungberg a528a503d3 Typo fix. 2010-11-26 13:37:58 -03:00
Klaas Pieter Annema 8345788e59 disable value caching in CPControllerSelectionProxy
More information here http://groups.google.com/group/objectivej-dev/browse_thread/thread/c100f16095073332.
2010-11-24 14:27:59 +01:00
Klaas Pieter Annema 21c2b8f74a trigger notification for correct key path in _CPObservationProxy
Previously _CPObservationProxy would only trigger notifications for the key path it was created with. For example a notification for department would be forwarded to the controller and observer as a notification on department.name because that was the key path the observation proxy was created for.
2010-11-24 14:21:19 +01:00
Brian Donovan 69c004093d CPTokenField did not send its action on end edit.
Also fixes that the CPNotification sent out was CPControlTextDidBeginEditingNotification, not CPControlTextDidEndEditingNotification.
2010-11-23 10:47:59 -08:00
cacaodev 5bec411bdc Fix for nib2cibing bindings options. 2010-11-23 19:38:03 +01:00
Klaas Pieter Annema 34339fbcd9 several bindings / KVC fixes
- setValue:forKeyPath will now get call setValue:forKeyPath again on the value of the first part of the key path
- override valueForKeyPath: and valueForKey: in CPObjectController's CPControllerSelectionProxy to return controller markers when appropriate
- override setValue:forKeyPath: and setValue:forKey: in CPObjectController's CPControllerSelectionProxy to bypass possible controller markers

This commit also removes previous hacks for compound paths and adds test cases for the errors. All this is related to issue #967.
2010-11-23 14:18:22 +01:00
Klaas Pieter Annema b49dc87a86 Merge branch 'fix-967' 2010-11-23 12:16:57 +01:00
Klaas Pieter Annema 535d6c9dc5 make setValue:forKey: handle controller markers 2010-11-23 12:15:53 +01:00
Klaas Pieter Annema 221fad6c3e improve _setCurrentValueIsPlaceholder logic 2010-11-23 12:03:00 +01:00
Klaas Pieter Annema aeb3873f3c fix valueForKeyPath: attempting to call valueForKey: on controller markers 2010-11-23 11:56:46 +01:00
Randall Luecke 4f6c83cb3a Fix for setFont: not working in the table header because of the new theme stuff. 2010-11-23 01:20:38 -05:00
Randall Luecke 2ba5cffe44 More variable row height stuff. 2010-11-23 01:15:47 -05:00
Klaas Pieter Annema 1e85a054ac better fix for long key paths
The previous fix for issue #967 would only work if there was only one object observing a compound key path like selection.customer.name.
2010-11-22 19:13:20 +01:00
Klaas Pieter Annema ca60e50128 small bindings fix in CPObjectController
CPObjectController would attempt to remove observations from the new selection in stead of the old selection. This would throw an error when binding to longer compound key paths like selection.customer.name

Fixes #967
2010-11-22 18:10:34 +01:00
Klaas Pieter Annema 70c13a7588 style cleanup in CPObjectController 2010-11-22 18:10:28 +01:00
Alexander Ljungberg 6653bab492 Cleanup. 2010-11-19 13:08:55 -03:00
Alexander Ljungberg 741c235f08 Fix strange cib loading path caused by non-bundliness of Tests/AppKit. 2010-11-19 13:04:59 -03:00
Alexander Ljungberg 70bc3557b4 Simplify. 2010-11-19 00:38:34 -03:00
Alexander Ljungberg 7509e5c99b Bindings test case based on Cocoa example Simple Bindings Adoption 03.
In this test the bindings and controller are entirely configured in IB. Note: the path to the cib file is a little strange.
2010-11-19 00:23:27 -03:00
Alexander Ljungberg 5a2c401e05 Cleanup. 2010-11-19 00:07:37 -03:00
Alexander Ljungberg 75427973f0 More bindings nib2cib fixes. 2010-11-19 00:06:55 -03:00
Ross Boucher 63d5c442a3 Bug fixes. 2010-11-18 16:52:41 -08:00
Ross Boucher 45f74386b8 Add bindings support to nib2cib 2010-11-18 15:52:54 -08:00
Daniel Brajkovic 6093530175 Added some documentation to CPButton.j 2010-11-18 13:18:01 -06:00
Daniel Brajkovic 6bd064f289 Fixed errors in the incompatibility CPException reasons. For example -setHeaderView instead of setHeaderCell. 2010-11-18 12:33:17 -06:00
Alexander Ljungberg 31d57b0c37 Optimise table view selection notification.
Before the table view would send a CPTableViewSelectionDidChangeNotification whenever the number of rows in the table decreased, regardless of if any selected rows actually became deselected. This could be a needless performance drain in the common case where other program components update and reload on selection changes in a table or outline view.
2010-11-18 15:00:46 -03:00
Alexander Ljungberg 22a185b52e Fixed CPTableViewTest which was both broken and unfinished. 2010-11-18 14:09:18 -03:00
Alexander Ljungberg 0067bd0d16 Browser test for CPSound. 2010-11-18 11:54:05 -03:00
Alexander Ljungberg 6521202e68 Add CPSound to AppKit. 2010-11-18 11:53:37 -03:00
Alexander Ljungberg 67e87c7367 Add missing semicolons, clean up. 2010-11-18 11:23:13 -03:00
Alexander Ljungberg a4eeb91290 Merge branch 'CPSound' of https://github.com/primalmotion/cappuccino into primalmotion-CPSound 2010-11-18 11:13:13 -03:00
Antoine Mercadal c0b1322c77 remove stupid test 2010-11-18 12:14:19 +01:00
Antoine Mercadal 3c18282510 add support for theme state rounded 2010-11-18 12:07:44 +01:00
Randall Luecke 55674e31ea Initial work on variable row heights. No drawing support at all yet. 2010-11-18 01:22:51 -05:00
Alexander Ljungberg 39a69b6850 Bindings test case based on Cocoa example Simple Bindings Adoption 02. 2010-11-18 00:06:46 -03:00
Alexander Ljungberg 2b8a5d6176 Clean up and simplify. 2010-11-17 23:54:48 -03:00
Alexander Ljungberg eb692e672e Bindings test case based on Cocoa example Simple Bindings Adoption 01. 2010-11-17 23:51:33 -03:00
Alexander Ljungberg 381a6a999b Fixed a bad var statement in CPDecimal. Cleanup. 2010-11-17 21:58:58 -03:00
Alexander Ljungberg e276a830d3 Test token field represented object autocomplete. 2010-11-17 21:43:24 -03:00
Alexander Ljungberg e4ee9284b4 Merge branch 'cptokenfield-fixes' of https://github.com/miLibris/cappuccino into miLibris-cptokenfield-fixes 2010-11-17 21:08:43 -03:00
Alexander Ljungberg 9e441f69b8 Merge branch 'CPCollectionView-setContent-fix' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-CPCollectionView-setContent-fix 2010-11-17 20:45:45 -03:00
Alexander Ljungberg 0d2b13dd75 Merge branch 'CPArrayController-removeObject-fix' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-CPArrayController-removeObject-fix 2010-11-17 20:12:44 -03:00
Alexander Ljungberg 2df07344c8 Merge branch 'button-inset' of https://github.com/aparajita/cappuccino into aparajita-button-inset 2010-11-17 19:59:43 -03:00
Alexander Ljungberg 38ad5a8e2c Regenerated nib with latest text field height fix. 2010-11-17 19:58:20 -03:00
Francisco Ryan Tolmasky I bd15d2f331 Fix for [CPUndoManager removeAllActions] not clearing the current groupings as well.
Closes #1002.

Reviewed by me.
2010-11-17 12:21:09 -08:00
Klaas Pieter Annema 80ec35fd0a Merge branch 'hover-states' 2010-11-17 10:11:11 +01:00
Francisco Ryan Tolmasky I fb8d834036 Improved key view loop algorithm.
Reviewed by me.
2010-11-16 19:33:08 -08:00
Francisco Ryan Tolmasky I 4191153d0b Fix for key views not being properly auto-calculated.
Closes #965.

Reviewed by me.
2010-11-16 15:24:09 -08:00
Aparajita FishmanandRandall Luecke ace66b2b2f Sizing code had been added to CPTextField initWithCoder that required resizing in NSTextField NS_initWithCoder to be removed. However, the sizing code was removed, so this code has to be re-inserted. 2010-11-16 10:29:19 -05:00
Klaas Pieter Annema c8afcde4e5 implement NSTableColumn data cell text color support 2010-11-16 11:56:00 +01:00
Andreas Falk a302fdfb8f CPTextField should not bother with handling tab to go to the next key
view, CPWindow does that for us.
2010-11-15 19:44:02 +01:00
Luc Vauvillier 8b9a0edeba Fix CPTokenField autocompletion to deal with represented objects 2010-11-15 15:51:21 +01:00
Klaas Pieter Annema 923770d95a style cleanup 2010-11-15 14:27:43 +01:00
Klaas Pieter Annema 011b8d250a remove second implementation of _processKeyboardUIKey: 2010-11-15 14:25:47 +01:00
Luc Vauvillier 0f8aa1e644 Support object representation in CPTokenField
Add some tests
2010-11-15 13:14:53 +01:00
Francisco Ryan Tolmasky I 9179a31a93 Style fixes.
Reviewed by me.
2010-11-13 12:41:31 -08:00
Francisco Ryan Tolmasky I c9d32b4163 Merge branch 'CPTreeNode-descendantNodeAtIndexPath' of https://github.com/luuse/cappuccino into luuse-CPTreeNode-descendantNodeAtIndexPath 2010-11-13 10:26:07 -08:00
Andreas 57c691c2e2 Make CPBundle post a notification on successfull load 2010-11-13 15:38:14 +01:00
Andreas bb9e1a830d Add cancelOperation action to clear text when pressing ESC 2010-11-13 15:21:37 +01:00
Andreas 9b7f8ec31e Add -insertTabIgnoringFieldEditor: and -insertNewlineIgnoringFieldEditor: 2010-11-13 15:16:25 +01:00
Andreas 17b40fcb9d Adapt CPTextField to use interpretKeyEvents and actions instead of directly reading from keyDown 2010-11-13 15:14:09 +01:00
Andreas Falk 8a75c9078e Fix display names in CFBundle 2010-11-13 13:36:24 +01:00
Andreas Falk fbcf84e63f Fix some broken things after cherry-pick 2010-11-13 13:03:01 +01:00
Andreas ea5ab5e921 Add CPIndexPath implementation and tests 2010-11-13 12:22:06 +01:00
Andreas 3a8773baec Add -descendantNodeAtIndexPath: and tests to CPTreeNode 2010-11-13 12:06:43 +01:00
Francisco Ryan Tolmasky I ab4dd1ac6d Got rid of nonsensical tasks in ThemeDescriptor Jakefile.
Reviewed by me.
2010-11-12 15:47:25 -08:00
Brian Donovan 6f38b2aa0d -[CPCollectionView setContent:] did not always call reloadContent:.
This would break key-value binding setups where a CPCollectionView's content property was hooked up to a CPArrayController's content or arrangedObjects property since the CPArrayController maintains the same object and calls setValue:forKey: with the same object the CPCollectionView already has. Therefore we cannot skip calling reloadContent even when the incoming content array is the same one we got before, because most likely the contents have changed out from under us.
2010-11-11 21:39:07 -08:00
Brian Donovan 929ec28436 CPArrayController did not allow removing objects without a selection.
CPArrayController was erroneously using canRemove to determine whether explicit removal could take place, when in fact the documentation for [NSObjectController canRemove] (NSArrayController does not override canRemove) states that it returns "YES if an object can be removed from the receiver using remove:, otherwise NO", implying that it should only be used to check whether there is a selected element that can be removed (for example, to bind the enabled state of a toolbar button to a CPArrayController's canRemove property). It should not be used to decide whether a specific object can be removed or not.
2010-11-11 17:45:18 -08:00
Alexander Ljungberg 04a19543a5 Fix CPTabView decoding to work better with nib2cib. 2010-11-11 20:21:24 -03:00
Alexander Ljungberg 5d505f5271 Merge branch 'CPString-copy' of https://github.com/cacaodev/cappuccino into cacaodev-CPString-copy 2010-11-11 16:57:49 -03:00
Antoine Mercadal 60ff3ca0a1 Support for HUD style
use [alert setTheme:[CPTheme defaultHUDTheme]] or [alert setTheme:[CPTheme defaultTheme]] to switch theme.
Add deprecated procies setWindowStyle: and windowStyles;
2010-11-11 18:24:17 +01:00
Alexander Ljungberg e4f5d9b32f Fixed some comments referencing NS* classes. 2010-11-11 13:42:25 -03:00
Antoine Mercadal 6b42ef3cb1 fix: CPAlert fails to runModal if ran sheetModal before 2010-11-11 17:38:39 +01:00
Alexander Ljungberg 345b9d9297 Fix some comments. 2010-11-11 13:38:16 -03:00
Alexander Ljungberg 4bad3c2823 Merge branch 'CPPredicate' of https://github.com/cacaodev/cappuccino into cacaodev-CPPredicate 2010-11-11 12:59:04 -03:00
Alexander Ljungberg 38033d9dcb Fixed the CPAlert manual test which did not work after the recent changes. 2010-11-11 12:46:25 -03:00
Nicholas Small 5c961d4f16 Restore CPAlert -setTitle: functionality. 2010-11-10 17:43:21 -05:00
Nicholas Small c21cdc2916 Cleanup CPAlert. 2010-11-10 17:39:56 -05:00
Nicholas Small 1a797b10c3 Merge branch 'CPAlert-Cocoa-Compliance' of https://github.com/primalmotion/cappuccino into primalmotion-CPAlert-Cocoa-Compliance 2010-11-10 13:46:50 -05:00
Antoine Mercadal 3bfa427134 Add setTitle: and title, deprecated proxies for setMessageText: and messageText
Add some missing Cocoa accessors
Fix acessors for messageText and informativeText that returned CPTextField instead of CPString
2010-11-10 11:02:27 +01:00
Antoine Mercadal 9a8c4bd431 move CPAlertLabelOffset to a theme attribute 2010-11-10 10:25:23 +01:00
Antoine Mercadal dc72b55361 remove the title of the panel. Cocoa doesn't display any title 2010-11-09 18:33:39 +01:00
Antoine Mercadal ee4ef882dd add X and Y offet theme properties for supression button 2010-11-09 18:27:26 +01:00
Antoine Mercadal 23c2f4bb8c remove the movable thing and remove the bezel-color them attribute 2010-11-09 18:08:13 +01:00
Antoine Mercadal bd01955f39 support for setShowsSupressionButton 2010-11-09 18:02:24 +01:00
Antoine Mercadal 3f1e1e57d8 update help button art 2010-11-09 18:02:06 +01:00
Antoine Mercadal ee343c7533 make window not movable by dragging background if sheet + capp_lint/sorting/cleaning/commenting 2010-11-09 17:01:11 +01:00
Antoine Mercadal 961071e3fa refactor a method 2010-11-09 16:55:33 +01:00
Antoine Mercadal 0219341ee8 add support for setShowHelp: 2010-11-09 16:41:41 +01:00
Aparajita Fishman 5df3c7838d Increased content inset a bit to match Cocoa, whitespace cleanup. 2010-11-09 09:27:11 -05:00
Antoine Mercadal bf63147ca3 Cleaning CPAlert, add accessoryView 2010-11-09 15:21:25 +01:00
Klaas Pieter Annema b7d7b99a82 Merge branch 'CPDecimalNumber' 2010-11-09 10:38:58 +01:00
Brian DonovanandKlaas Pieter Annema 5a0129018a Fix spelling of "separator". 2010-11-09 10:33:49 +01:00
Klaas Pieter Annema e48a437c88 fix failing CPUserDefaults test 2010-11-09 10:28:36 +01:00
Antoine Mercadal 187c32d231 fix CPStepper test cases 2010-11-09 00:46:47 +01:00
Antoine Mercadal c680e31817 add test case for CPStepper 2010-11-09 00:37:27 +01:00
Antoine Mercadal cc177eeb2b add artwork 2010-11-09 00:37:14 +01:00
Antoine Mercadal 918db24c63 add CPStepper to Aristo 2010-11-09 00:36:56 +01:00
Antoine Mercadal 7e005f4559 use setNeedsLayout to layout subviews 2010-11-09 00:36:28 +01:00
Antoine Mercadal 5d49c1346a implement CPStepper 2010-11-08 23:20:05 +01:00
Antoine Mercadal f6147850b9 use document.createElement('audio') instead of new Audio(). work better 2010-11-08 22:16:21 +01:00
Nicholas Small 731e50da32 Clean up value accessors in CPUserDefaults. 2010-11-08 12:35:23 -05:00
Nicholas Small 5078c3e9cf Merge branch 'fix-cpuserdefaults-protocol' of https://github.com/primalmotion/cappuccino into primalmotion-cpuserdefaults-fixes 2010-11-08 11:52:43 -05:00
Klaas Pieter Annema de0a09899a Merge branch 'sizeToFit-fix' of https://github.com/aparajita/cappuccino into aparajita-sizeToFit-fix 2010-11-08 10:08:50 +01:00
Klaas Pieter Annema 4041ef8746 Merge branch 'CPView-ephemeral-subview' of https://github.com/aparajita/cappuccino into aparajita-CPView-ephemeral-subview 2010-11-08 09:59:52 +01:00
cacaodev 3b35219beb Fix [[string copy] isEqual:[string copy]] == NO 2010-11-07 21:43:02 +01:00
cacaodev ca289e081e CPPredicate parsing support:
"($)path.($)variable"
 "SUBQUERY(collection, $x,$x = 2)"
 "sum:(arg1, ...)"
 "FUNCTION(target, selector, arg1, ...)
 "object[expression]"
 "set UNION|INTERSECT|MINUS otherset"
Fixed a bug where CPExpression_set was evaluating to an expression instead of a set.
Replaced parsing exceptions with a generic function indicating where it failed.
2010-11-07 17:56:22 +01:00
Aparajita Fishman 5cd00d71c7 Fixed sizeToFit drawing when there is no image, setNeedsDisplay is no longer needed after sizeToFit. 2010-11-06 17:12:09 -04:00
Antoine Mercadal ea924fbb26 some small glitch fix 2010-11-06 18:59:02 +01:00
Antoine Mercadal da23a89910 update header 2010-11-06 18:38:52 +01:00
Antoine Mercadal e4b47090ba added CPSound, an HTML5 wrapper for NSSound 2010-11-06 18:37:17 +01:00
Antoine Mercadal 386ded05fd remove useless _searchListNeedsReload 2010-11-06 10:19:21 +01:00
Alexander Ljungberg e3b6cbcee9 Merge branch 'CPArrayControllerFixes' of https://github.com/dasto/cappuccino into dasto-CPArrayControllerFixes 2010-11-05 15:48:10 -03:00
Alexander Ljungberg fd7651e895 Merge branch 'base-conversion' of https://github.com/aparajita/cappuccino into aparajita-base-conversion 2010-11-05 15:29:12 -03:00
Alexander Ljungberg 8ca2f53828 Merge branch 'CPPredicate' of https://github.com/cacaodev/cappuccino into cacaodev-CPPredicate 2010-11-05 14:52:37 -03:00
Alexander Ljungberg fc385935ef Test nib2cib for CPTabView. 2010-11-05 13:52:59 -03:00
Alexander Ljungberg ed1c5714a3 Closes #971. Fixed: nib2cib did not work with the new CPTabView. 2010-11-05 13:51:51 -03:00
Alexander Ljungberg dfe03458d0 Fixed: decoding a CPTabView would result in "TypeError: Result of expression 'aRect' [null] is not an object" due to incomplete initialisation. 2010-11-05 13:30:57 -03:00
Antoine Mercadal c55cd03db1 more robust tests for CPUserDefaults 2010-11-05 17:28:40 +01:00
Antoine Mercadal 6a2b347b21 authorize string in setURL:forKey: 2010-11-05 17:28:18 +01:00
Antoine Mercadal b96abb5fd4 fix typo 2010-11-05 17:01:24 +01:00
Alexander Ljungberg 4974a47c94 Merge branch 'master' of github.com:280north/cappuccino 2010-11-05 12:03:25 -03:00
Alexander Ljungberg 7e229652f1 Merge branch 'fix-cptabview-height-resizing' of https://github.com/primalmotion/cappuccino into primalmotion-fix-cptabview-height-resizing 2010-11-05 11:56:19 -03:00
Alexander Ljungberg 81f2959417 Visually test tab view resizing. 2010-11-05 11:52:11 -03:00
Daniel Stolzenberg 9d46c688ed fixed support for "contentSet" in CPArrayController.j, where sets were not converted to arrays 2010-11-05 15:02:31 +01:00
Antoine Mercadal 60a8ddd306 be less restrictive on setInteger, setFloat and setDouble 2010-11-05 14:42:22 +01:00
Klaas Pieter Annema 4817a87499 fix CPBox drawing the separator style between pixels 2010-11-05 13:05:43 +01:00
Antoine Mercadal 91ce1c3f6c add stringArrayForKey: 2010-11-05 11:52:43 +01:00
Antoine Mercadal 0c9cba4e71 add test cases for CPUserDefaults 2010-11-05 11:47:23 +01:00
Antoine Mercadal c833de2e0a set _searchListNeedsReload to YES after setting defaults 2010-11-05 11:37:46 +01:00
Antoine Mercadal 6824e42c69 fix some small bugs 2010-11-05 11:32:18 +01:00
Antoine Mercadal 67a41534bd make CPUserDefault more Cocoa compliant 2010-11-05 11:08:27 +01:00
Klaas Pieter Annema 3d0d522f76 implement coding support for autosaveName in CPTableView 2010-11-05 11:02:37 +01:00
Klaas Pieter Annema accd29804c implement table column order and width autosaving 2010-11-05 11:02:26 +01:00
Klaas Pieter Annema 0c62609e76 made CPTableView aware of a resize in CPTableColumn 2010-11-05 11:02:05 +01:00
Aparajita Fishman 6148654604 Added convertTo/FromBase methods for completeness (and convenience). 2010-11-04 23:01:28 -04:00
Nicholas Small 40c1957484 Update documentation in CPUserDefaults. 2010-11-04 16:06:53 -04:00
Nicholas Small 6f754d9810 Added CPUserDefaults.j 2010-11-04 15:53:53 -04:00
Antoine Mercadal 9a4c9e4306 add test for CPTabView height resizing 2010-11-04 10:41:24 +01:00
Randall Luecke c52b40657a Removed frame resizing in the textfield's initWithCoder: 2010-11-03 22:54:09 -04:00
Ross Boucher b85e9d83b8 Fix for the fix for extensionless IB resource names. 2010-11-03 11:18:37 -07:00
Daniel Stolzenberg db2c88f2e5 Merge branch 'master' of git://github.com/280north/cappuccino 2010-11-02 13:49:52 +01:00
Antoine Mercadal b9095b2176 box is now resized using CPViewHeightSizable 2010-11-02 13:02:24 +01:00
Daniel Stolzenberg ec9fac6629 Merge branch 'master' of git://github.com/280north/cappuccino 2010-11-01 10:13:59 +01:00
Daniel Stolzenberg b2dac594dc fixed 4 spaces for tab formatting issues in CPKeyValueCodingTest.j 2010-11-01 09:47:19 +01:00
Daniel Stolzenberg 28029030b6 fixed 4 spaces for tab formatting issues 2010-11-01 09:38:19 +01:00
cacaodev 4b1fbf1eff Implemented subquery expressions.
Added missing getters in CPExpression.
Added a type: argument to FunctionExpression initializer used by  subclasses to init super with their own type.
Fixed evaluation with bindings dictionary in CPExpression_variable. Allow values in bindings to be a constant or an expression (per cocoa).

Tests: added tests for subqueryExpressions, for variableExpression evaluation where the value in the bindings dictionary can be either a constant or another expression.
Parsing a simple variable expression works (e.g. '$x = 12'), parsing a variable in a combined path (e.g.
'$x.path = 12' won't yet.
2010-10-29 18:58:29 +02:00
Daniel Stolzenberg 24fbecb2e6 Merge branch 'master' of git://github.com/280north/cappuccino 2010-10-28 09:20:52 +02:00
Daniel Stolzenberg 4a142b5c02 implemented missing features of KVO for unordered to-many relationships in CPKeyValueCoding.j 2010-10-27 19:08:34 +02:00
Daniel Stolzenberg dfba974572 enabled subclasses of CPSet to use CPObjects "addObserver:/removeObserver:" methods without throwing exception 2010-10-27 12:35:50 +02:00
Daniel Stolzenberg c1fd31fa23 removed unnecessary @import "CPArray+KVO.j" statement in CPKeyValueCoding.j 2010-10-27 12:13:47 +02:00
Daniel Stolzenberg fd3e10f793 added some comments to original behaviour of Cocoa in CPKeyValueCoding.j 2010-10-27 12:07:50 +02:00
Daniel Stolzenberg 6a7358920b implemented CPKeyValueCodingTests for CPNull-nil-conversion and CPDictionary KVC-compliance 2010-10-27 10:43:31 +02:00
Daniel Stolzenberg c0aa180e83 improved Cocoa compatibility, enhanced usage of accessor pattern in "removeAllObjects" in CPSet+KVO.j 2010-10-27 10:41:48 +02:00
Daniel Stolzenberg 82cf7df7e9 implemented missing "setValue:forKey:" test for CPKeyValueCoding.j 2010-10-26 18:10:31 +02:00
Daniel Stolzenberg 4c58c602ff implemented Tests for CPKeyValueCoding "valueForKey:" 2010-10-26 17:09:12 +02:00
Daniel Stolzenberg 14e4b71d20 removed unnecessary ".isa" statements in CPKeyValueCoding.j 2010-10-26 17:07:13 +02:00
Daniel Stolzenberg 6483ea233c imported new implementation for unordered to-many relationships in CPKeyValueObserving.j/CPSet+KVO.j 2010-10-26 14:23:24 +02:00
Daniel Stolzenberg 895ed4f6ff implemented missing replacement methods for accessor patterns in CPKeyValueObserving.j 2010-10-26 14:20:54 +02:00
Daniel Stolzenberg 5ff7e66981 implemented "will/didChangeValueForKey:withSetMutation:usingObjects:" in _CPKVOModelSubclass in CPKeyValueObserving.j 2010-10-26 14:17:39 +02:00
Daniel Stolzenberg a2ff814796 added missing accessor patterns in "_replaceSetterForKey:" in CPKeyValueObserving.j 2010-10-26 14:13:21 +02:00
Daniel Stolzenberg c1e42a2f3e refactored duplicated method copying implementation 2010-10-26 14:11:47 +02:00
Daniel Stolzenberg 9e1c07b195 added "CPKeyValueSetMutationKind" definitions to CPKeyValueObserving.j 2010-10-26 14:08:56 +02:00
Daniel Stolzenberg c71c732fc0 added "will/didChangeValueForKey:withSetMutation:usingObjects:" stubs to CPObject in CPKeyValueObserving.j 2010-10-26 14:06:56 +02:00
Daniel Stolzenberg b3e0ec60df fixed bug in "_modifierForKey()" where self was used in a plain JS-function 2010-10-26 13:57:57 +02:00
Daniel Stolzenberg 513cc2cac7 removed unnecessary if-statement (because it never gets executed) 2010-10-26 13:04:25 +02:00
Daniel Stolzenberg b0feeb3d31 improved cocoa compatibility by _CPKVCArray-proxy inheriting from CPMutableArray, fixed wrong mutable accessors patterns in "CPArray+KVO.j" 2010-10-26 12:53:21 +02:00
Daniel Stolzenberg 9c7b3475d8 fixed bug in "mutableArrayValueForKeyPath:" in CPArray+KVO.j which was not calling itself recursively 2010-10-26 12:50:33 +02:00
Daniel Stolzenberg 99e4a4fb4f implemented missing "setValuesForKeysWithDictionary:" method in "CPKeyValueCoding.j" 2010-10-26 12:48:32 +02:00
Daniel Stolzenberg 7b7b46a61e unified implementations of "_accessorForKey", "_modifierForKey" and "_ivarForKey" in CPKeyValueCoding.j 2010-10-26 12:39:47 +02:00
Daniel Stolzenberg ed4a264108 removed duplicated (and buggy) implementations of "valueForKey:" and "setValue:forKey:" in CPArray.j 2010-10-26 12:24:20 +02:00
Derek Hammer ae5d56471f Inlining function, fixing a style issue. 2010-10-14 19:31:04 -05:00
Aparajita Fishman bafb23ae44 Allow ephemeral subviews to be created when the parent view has an empty frame, de-lint 2010-10-09 08:14:00 -04:00
Klaas Pieter Annema c481d55976 fix hovered state being removed when the mouse leaves a subview of a control 2010-09-17 13:21:54 +02:00
Klaas Pieter Annema 7aa7d61984 Implement hover states.
- Set CPWindow _acceptsMouseMovedEvents default to YES
- Add CPThemeStateHovered to CPTheme
- Add hovered logic to CPControl is hovered
2010-09-17 12:06:01 +02:00
Derek Hammer fc545ed995 Adding support for CPURL 2010-09-06 14:18:53 -05:00
Derek Hammer f85ab24993 Finishing the rest to make them inherit properties of superclasses. 2010-09-06 14:02:52 -05:00
Derek Hammer 4e1766485f Updating CPDictionary and CPString to both actually subclass.. not just create a new object without inherited properties. 2010-09-06 13:46:27 -05:00
Derek Hammer 8e5471d0fe Updating CPData and CPDate to be subclassable. Only non-subclassable toll free bridged object is CPURL at this point. 2010-09-06 13:45:46 -05:00
Derek Hammer a09878dcb4 Adding self checks in toll free bridged objects so that they are subclassable. 2010-09-06 12:07:50 -05:00
Klaas Pieter Annema b3f2ba035e add CPDecimal and CPDecimalNumber to Foundation.j 2010-08-25 15:07:04 +02:00
Klaas Pieter Annema 10a620017d Merge remote branch 'stevegeek/CPDecimalNumber' into CPDecimalNumber 2010-08-25 15:06:47 +02:00
Stephen Ierodiaconou c10b06e29b Merge branch 'master' of git://github.com/280north/cappuccino into CPDecimalNumber 2010-06-13 00:03:13 +03:00
Stephen Ierodiaconou 411a634242 Merge branch 'CPDecimalNumber' of http://github.com/klaaspieter/cappuccino into CPDecimalNumber 2010-05-23 10:35:44 +03:00
Stephen Ierodiaconou 4ab421f183 Merge branch 'master' of git://github.com/280north/cappuccino into CPDecimalNumber 2010-05-23 10:26:17 +03:00
Klaas Pieter Annema 8e3e15080b made CPDecimalCreateWithString work with empty string 2010-05-06 14:13:29 +02:00
Klaas Pieter Annema fd625c96d6 made CPDecimalNumber a subclass of CPNumber 2010-05-05 12:14:55 +02:00
Klaas Pieter Annema 4f721fc1e2 added description to CPDecimalNumber 2010-05-05 12:13:47 +02:00
Klaas Pieter Annema 373210e610 fixed several global declarations of i in for loops 2010-05-05 12:13:24 +02:00
Stephen Ierodiaconou 0ddb17862c Merge branch 'master' of git://github.com/280north/cappuccino into CPDecimalNumber 2009-11-28 17:02:43 +00:00
Stephen Ierodiaconou aae415c1ee Merge branch 'master' of git://github.com/280north/cappuccino into CPDecimalNumber 2009-10-18 21:05:19 +01:00
Stephen Ierodiaconou c79b2456f5 Some style changes to CPDecimal 2009-10-16 12:35:59 +01:00
Stephen Ierodiaconou 5104d323bb Merge branch 'master' of git://github.com/280north/cappuccino 2009-10-14 14:30:13 +01:00
Stephen Ierodiaconou 80c4be6e5f Merge branch 'master' of git://github.com/280north/cappuccino 2009-10-11 19:34:13 +01:00
Stephen Ierodiaconou 970859311d Merge branch 'master' of git://github.com/280north/cappuccino 2009-10-09 15:21:43 +01:00
Stephen Ierodiaconou 449581e7c4 Merge branch 'master' of git://github.com/280north/cappuccino 2009-10-08 21:39:23 +01:00
Stephen Ierodiaconou 02a8fc7f72 Merge branch 'master' of git://github.com/280north/cappuccino 2009-10-08 21:32:59 +01:00
stevegeek 7bbeee8234 Merge branch 'master' of git://github.com/280north/cappuccino 2009-10-02 14:22:33 +01:00
stevegeek 00532fe7ac First CPDecimal and CPDecimalNumber commits (and tests).
These implementations are mostly complete but require optimisation.
2009-09-28 13:59:18 +01:00
stevegeek 073a934b2b Merge branch 'master' of git://github.com/280north/cappuccino 2009-09-28 11:55:10 +01:00
stevegeek ea7631de9e Merge branch 'master' of git://github.com/280north/cappuccino 2009-09-23 23:20:19 +01:00
stevegeek 81e15c91f4 Merge branch 'master' of git://github.com/280north/cappuccino 2009-09-21 09:30:21 +01:00
Stephen Ierodiaconou b8afbb66a7 Merge branch 'master' of git://github.com/280north/cappuccino 2009-09-20 10:35:33 +01:00
stephen 9e9eba695f Merge branch 'master' of git://github.com/280north/cappuccino
Conflicts:

	Foundation/CPArray.j
	Foundation/CPAttributedString.j
	Foundation/CPCountedSet.j
	Foundation/CPIndexSet.j
	Foundation/CPJSONPConnection.j
	Foundation/CPSet.j
	Foundation/CPTimer.j
2009-05-31 12:09:43 +01:00
Stephen Ierodiaconou c6e3cad944 Update to docs of replaceCharactersInRange in CPAttributedString. 2009-05-28 01:51:19 +01:00
Stephen Ierodiaconou 3af0e3249a Added a new group Cocoa Compatability for the empty compatability
classes like CPMutableArray
2009-05-28 01:34:40 +01:00
Stephen Ierodiaconou 510a836b90 Added briefs to all Foundation and made some cleanups to docs 2009-05-28 01:24:48 +01:00
Stephen Ierodiaconou 25f415045a All Foundation classes briefed 2009-05-28 01:14:27 +01:00
Stephen Ierodiaconou 0af9c18ef2 adding briefs and unifying class header structure 2009-05-28 00:15:57 +01:00
556 changed files with 52722 additions and 7519 deletions
+5 -2
View File
@@ -24,6 +24,7 @@
@import "CPAlert.j"
@import "CPAnimation.j"
@import "CPApplication.j"
@import "CPArrayController.j"
@import "CPBezierPath.j"
@import "CPBox.j"
@import "CPBrowser.j"
@@ -31,6 +32,7 @@
@import "CPButtonBar.j"
@import "CPCheckBox.j"
@import "CPCib.j"
@import "CPCibBindingConnector.j"
@import "CPCibConnector.j"
@import "CPCibControlConnector.j"
@import "CPCibLoading.j"
@@ -74,15 +76,17 @@
@import "CPSegmentedControl.j"
@import "CPShadow.j"
@import "CPSlider.j"
@import "CPSound.j"
@import "CPSplitView.j"
@import "CPStepper.j"
@import "CPTableColumn.j"
@import "CPTableView.j"
@import "CPTabView.j"
@import "CPText.j"
@import "CPTextField.j"
@import "CPTokenField.j"
@import "CPToolbar.j"
@import "CPToolbarItem.j"
@import "CPTokenField.j"
@import "CPTreeNode.j"
@import "CPView.j"
@import "CPViewAnimation.j"
@@ -90,4 +94,3 @@
@import "CPWebView.j"
@import "CPWindow.j"
@import "CPWindowController.j"
@import "CPArrayController.j"
+1 -1
View File
@@ -69,7 +69,7 @@
@class CPAccordionView
<p>CPAccordionView provides a container for CPAccordionViewItem objects and manages layout state
for all sublayout items.</p>
for all sub-layout items.</p>
<strong>Example</strong><br />
<pre>
+600 -364
View File
@@ -6,7 +6,9 @@
* Copyright 2008, Jake MacMullin.
*
* 11/10/2008 Ross Boucher
* - Make it conform to style guidelines, general cleanup and ehancements
* - Make it conform to style guidelines, general cleanup and enhancements
* 11/10/2010 Antoine Mercadal
* - Enhancements, better compliance with Cocoa API
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -75,22 +77,587 @@ CPCriticalAlertStyle = 2;
*/
@implementation CPAlert : CPView
{
CPPanel _alertPanel;
BOOL _showHelp @accessors(property=showsHelp);
BOOL _showSuppressionButton @accessors(property=showsSuppressionButton);
CPTextField _messageLabel;
CPTextField _informativeLabel;
CPImageView _alertImageView;
CPAlertStyle _alertStyle @accessors(property=alertStyle);
CPString _title @accessors(property=title);
CPView _accessoryView @accessors(property=accessoryView);
CPImage _icon @accessors(property=icon);
CPAlertStyle _alertStyle;
CPString _windowTitle;
int _windowStyle;
CPArray _buttons;
CPArray _buttons @accessors(property=buttons,readonly);
CPCheckBox _suppressionButton @accessors(property=suppressionButton,readonly);
id _delegate;
SEL _didEndSelector;
id _delegate @accessors(property=delegate);
id _modalDelegate;
SEL _didEndSelector;
CPWindow _window @accessors(property=window,readonly);
int _defaultWindowStyle;
CPImageView _alertImageView;
CPTextField _informativeLabel;
CPTextField _messageLabel;
CPButton _alertHelpButton;
BOOL _needsLayout;
}
#pragma mark Creating Alerts
/*!
Returns a CPAlert object with the provided info
@param aMessage the main body text of the alert
@param defaultButton the title of the default button
@param alternateButton if not nil, the title of a second button
@param otherButton if not nil, the title of the third button
@param informativeText if not nil the informative text of the alert
@return fully initialized CPAlert
*/
+ (CPAlert)alertWithMessageText:(CPString)aMessage defaultButton:(CPString)defaultButtonTitle alternateButton:(CPString)alternateButtonTitle otherButton:(CPString)otherButtonTitle informativeTextWithFormat:(CPString)informativeText
{
var alert = [[CPAlert alloc] init];
[alert setMessageText:aMessage];
[alert addButtonWithTitle:defaultButtonTitle];
if (alternateButtonTitle)
[alert addButtonWithTitle:alternateButtonTitle];
if (otherButtonTitle)
[alert addButtonWithTitle:otherButtonTitle];
if (informativeText)
[alert setInformativeText:informativeText];
return alert;
}
/*!
Return an CPAlert with type error
@param anErrorMessage the message of the alert
@return fully initialized CPAlert
*/
+ (CPAlert)alertWithError:(CPString)anErrorMessage
{
var alert = [[CPAlert alloc] init];
[alert setMessageText:anErrorMessage];
[alert setAlertStyle:CPCriticalAlertStyle];
return alert;
}
/*!
Initializes a \c CPAlert panel with the default alert style \c CPWarningAlertStyle.
*/
- (id)init
{
self = [super init];
if (self)
{
_buttons = [];
_alertStyle = CPWarningAlertStyle;
_showHelp = NO;
_needsLayout = YES;
_defaultWindowStyle = CPTitledWindowMask;
_messageLabel = [CPTextField labelWithTitle:@"Alert"];
_alertImageView = [[CPImageView alloc] init];
_informativeLabel = [[CPTextField alloc] init];
_suppressionButton = [CPCheckBox checkBoxWithTitle:@"Do not show this message again"];
_alertHelpButton = [[CPButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 16.0, 16.0)];
[_alertHelpButton setTarget:self];
[_alertHelpButton setAction:@selector(_showHelp:)];
}
return self;
}
#pragma mark Accessors
/*!
set the theme to use
@param the theme to use
*/
- (void)setTheme:(CPTheme)aTheme
{
if (aTheme === [self theme])
return;
if (aTheme === [CPTheme defaultHudTheme])
_defaultWindowStyle = CPTitledWindowMask | CPHUDBackgroundWindowMask;
else
_defaultWindowStyle = CPTitledWindowMask;
_window = nil; // will be regenerated at next layout
_needsLayout = YES;
[super setTheme:aTheme];
}
/*! @deprecated
*/
- (void)setWindowStyle:(int)aStyle
{
CPLog.warn("DEPRECATED: setWindowStyle: is deprecated. use setTheme: instead");
[self setTheme:(aStyle === CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]];
}
/*! @deprecated
*/
- (int)windowStyle
{
CPLog.warn("DEPRECATED: windowStyle: is deprecated. use theme instead");
return _defaultWindowStyle;
}
/*!
set the text of the alert's message
@param aText CPString containing the text
*/
- (void)setMessageText:(CPString)aText
{
[_messageLabel setStringValue:aText];
_needsLayout = YES;
}
/*!
return the content of the message text
@return CPString containing the message text
*/
- (CPString)messageText
{
return [_messageLabel stringValue];
}
/*!
set the text of the alert's informative text
@param aText CPString containing the informative text
*/
- (void)setInformativeText:(CPString)aText
{
[_informativeLabel setStringValue:aText];
_needsLayout = YES;
}
/*!
return the content of the message text
@return CPString containing the message text
*/
- (CPString)informativeText
{
return [_informativeLabel stringValue];
}
/*!
Sets the title of the alert window.
This API is not present in Cocoa.
@param aTitle CPString containing the window title
*/
- (void)setTitle:(CPString)aTitle
{
_title = aTitle;
[_window setTitle:aTitle];
}
/*!
set the accessory view
@param aView the accessory view
*/
- (void)setAccessoryView:(CPView)aView
{
_accessoryView = aView;
_needsLayout = YES;
}
/*!
set if alert shows the suppression button
@param shouldShowSuppressionButton YES or NO
*/
- (void)setShowsSuppressionButton:(BOOL)shouldShowSuppressionButton
{
_showSuppressionButton = shouldShowSuppressionButton;
_needsLayout = YES;
}
#pragma mark Accessing Buttons
/*!
Adds a button with a given title to the receiver.
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.
The first button will automatically be given a key equivalent of Return,
and any button titled "Cancel" will be given a key equivalent of Escape.
You really shouldn't need more than 3 buttons.
@param title the title of the button
*/
- (void)addButtonWithTitle:(CPString)aTitle
{
var bounds = [[_window contentView] bounds],
count = [_buttons count],
button = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
[button setTitle:aTitle];
[button setTag:count];
[button setTarget:self];
[button setAction:@selector(_takeReturnCodeFrom:)];
[[_window contentView] addSubview:button];
if (count == 0)
[button setKeyEquivalent:CPCarriageReturnCharacter];
else if ([aTitle lowercaseString] === @"cancel")
[button setKeyEquivalent:CPEscapeFunctionKey];
[_buttons insertObject:button atIndex:0];
}
#pragma mark Layout
/*!
@ignore
*/
- (void)_layoutMessageView
{
var inset = [self currentValueForThemeAttribute:@"content-inset"],
sizeWithFontCorrection = 6.0,
messageLabelWidth,
messageLabelTextSize;
[_messageLabel setTextColor:[self currentValueForThemeAttribute:@"message-text-color"]];
[_messageLabel setFont:[self currentValueForThemeAttribute:@"message-text-font"]];
[_messageLabel setTextShadowColor:[self currentValueForThemeAttribute:@"message-text-shadow-color"]];
[_messageLabel setTextShadowOffset:[self currentValueForThemeAttribute:@"message-text-shadow-offset"]];
[_messageLabel setAlignment:[self currentValueForThemeAttribute:@"message-text-alignment"]];
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
messageLabelWidth = CGRectGetWidth([[_window contentView] frame]) - inset.left - inset.right;
messageLabelTextSize = [[_messageLabel stringValue] sizeWithFont:[_messageLabel font] inWidth:messageLabelWidth];
[_messageLabel setFrame:CGRectMake(inset.left, inset.top, messageLabelTextSize.width, messageLabelTextSize.height + sizeWithFontCorrection)];
}
/*!
@ignore
*/
- (void)_layoutInformativeView
{
var inset = [self currentValueForThemeAttribute:@"content-inset"],
defaultElementsMargin = [self currentValueForThemeAttribute:@"default-elements-margin"],
sizeWithFontCorrection = 6.0,
informativeLabelWidth,
informativeLabelOriginY,
informativeLabelTextSize;
[_informativeLabel setTextColor:[self currentValueForThemeAttribute:@"informative-text-color"]];
[_informativeLabel setFont:[self currentValueForThemeAttribute:@"informative-text-font"]];
[_informativeLabel setTextShadowColor:[self currentValueForThemeAttribute:@"informative-text-shadow-color"]];
[_informativeLabel setTextShadowOffset:[self currentValueForThemeAttribute:@"informative-text-shadow-offset"]];
[_informativeLabel setAlignment:[self currentValueForThemeAttribute:@"informative-text-alignment"]];
[_informativeLabel setLineBreakMode:CPLineBreakByWordWrapping];
informativeLabelWidth = CGRectGetWidth([[_window contentView] frame]) - inset.left - inset.right,
informativeLabelOriginY = [_messageLabel frameOrigin].y + [_messageLabel frameSize].height + defaultElementsMargin,
informativeLabelTextSize = [[_informativeLabel stringValue] sizeWithFont:[_informativeLabel font] inWidth:informativeLabelWidth];
[_informativeLabel setFrame:CGRectMake(inset.left, informativeLabelOriginY, informativeLabelTextSize.width, informativeLabelTextSize.height + sizeWithFontCorrection)];
}
/*!
@ignore
*/
- (void)_layoutAccessoryView
{
if (!_accessoryView)
return;
var inset = [self currentValueForThemeAttribute:@"content-inset"],
defaultElementsMargin = [self currentValueForThemeAttribute:@"default-elements-margin"],
accessoryViewWidth = CGRectGetWidth([[_window contentView] frame]) - inset.left - inset.right,
accessoryViewOriginY = CGRectGetMaxY([_informativeLabel frame]) + defaultElementsMargin;
[_accessoryView setFrameOrigin:CGPointMake(inset.left, accessoryViewOriginY)];
[[_window contentView] addSubview:_accessoryView];
}
/*!
@ignore
*/
- (void)_layoutSuppressionButton
{
if (!_showSuppressionButton)
return;
var inset = [self currentValueForThemeAttribute:@"content-inset"],
suppressionViewXOffset = [self currentValueForThemeAttribute:@"suppression-button-x-offset"],
suppressionViewYOffset = [self currentValueForThemeAttribute:@"suppression-button-y-offset"],
defaultElementsMargin = [self currentValueForThemeAttribute:@"default-elements-margin"],
suppressionButtonViewOriginY = CGRectGetMaxY([(_accessoryView || _informativeLabel) frame]) + defaultElementsMargin + suppressionViewYOffset;
[_suppressionButton setTextColor:[self currentValueForThemeAttribute:@"suppression-button-text-color"]];
[_suppressionButton setFont:[self currentValueForThemeAttribute:@"suppression-button-text-font"]];
[_suppressionButton setTextShadowColor:[self currentValueForThemeAttribute:@"suppression-button-text-shadow-color"]];
[_suppressionButton setTextShadowOffset:[self currentValueForThemeAttribute:@"suppression-button-text-shadow-offset"]];
[_suppressionButton sizeToFit];
[_suppressionButton setFrameOrigin:CGPointMake(inset.left + suppressionViewXOffset, suppressionButtonViewOriginY)];
[[_window contentView] addSubview:_suppressionButton];
}
/*!
@ignore
*/
- (CGSize)_layoutButtonsFromView:(CPView)lastView
{
var inset = [self currentValueForThemeAttribute:@"content-inset"],
minimumSize = [self currentValueForThemeAttribute:@"size"],
buttonOffset = [self currentValueForThemeAttribute:@"button-offset"],
helpLeftOffset = [self currentValueForThemeAttribute:@"help-image-left-offset"],
aRepresentativeButton = [_buttons objectAtIndex:0],
defaultElementsMargin = [self currentValueForThemeAttribute:@"default-elements-margin"],
panelSize = [[_window contentView] frame].size,
buttonsOriginY,
offsetX;
[aRepresentativeButton setTheme:[self theme]];
[aRepresentativeButton sizeToFit];
panelSize.height = CGRectGetMaxY([lastView frame]) + defaultElementsMargin + [aRepresentativeButton frameSize].height;
if (panelSize.height < minimumSize.height)
panelSize.height = minimumSize.height;
buttonsOriginY = panelSize.height - [aRepresentativeButton frameSize].height + buttonOffset;
offsetX = panelSize.width - inset.right;
for (var i = [_buttons count] - 1; i >= 0 ; i--)
{
var button = _buttons[i];
[button setTheme:[self theme]];
[button sizeToFit];
var buttonFrame = [button frame],
width = MAX(80.0, CGRectGetWidth(buttonFrame)),
height = CGRectGetHeight(buttonFrame);
offsetX -= width;
[button setFrame:CGRectMake(offsetX, buttonsOriginY, width, height)];
offsetX -= 10;
}
if (_showHelp)
{
var helpImage = [self currentValueForThemeAttribute:@"help-image"],
helpImagePressed = [self currentValueForThemeAttribute:@"help-image-pressed"],
helpImageSize = helpImage ? [helpImage size] : CGSizeMakeZero(),
helpFrame = CGRectMake(helpLeftOffset, buttonsOriginY, helpImageSize.width, helpImageSize.height);
[_alertHelpButton setImage:helpImage];
[_alertHelpButton setAlternateImage:helpImagePressed];
[_alertHelpButton setBordered:NO];
[_alertHelpButton setFrame:helpFrame];
}
panelSize.height += [aRepresentativeButton frameSize].height + inset.bottom + buttonOffset;
return panelSize;
}
/*!
@ignore
*/
- (void)layout
{
if (!_needsLayout)
return;
if (!_window)
[self _createWindowWithStyle:nil];
var iconOffset = [self currentValueForThemeAttribute:@"image-offset"],
theImage = _icon,
finalSize;
if (!theImage)
switch (_alertStyle)
{
case CPWarningAlertStyle:
theImage = [self currentValueForThemeAttribute:@"warning-image"];
break;
case CPInformationalAlertStyle:
theImage = [self currentValueForThemeAttribute:@"information-image"];
break;
case CPCriticalAlertStyle:
theImage = [self currentValueForThemeAttribute:@"error-image"];
break;
}
[_alertImageView setImage:theImage];
var imageSize = theImage ? [theImage size] : CGSizeMakeZero();
[_alertImageView setFrame:CGRectMake(iconOffset.x, iconOffset.y, imageSize.width, imageSize.height)];
[self _layoutMessageView];
[self _layoutInformativeView];
[self _layoutAccessoryView];
[self _layoutSuppressionButton];
var lastView = _informativeLabel;
if (_showSuppressionButton)
lastView = _suppressionButton;
else if (_accessoryView)
lastView = _accessoryView
finalSize = [self _layoutButtonsFromView:lastView];
if ([_window styleMask] & CPDocModalWindowMask)
finalSize.height -= 26; // adjust the absence of title bar
[_window setFrameSize:finalSize];
[_window center];
_needsLayout = NO;
}
#pragma mark Displaying Alerts
/*!
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.
*/
- (void)runModal
{
if (!([_window styleMask] & _defaultWindowStyle))
{
_needsLayout = YES;
[self _createWindowWithStyle:_defaultWindowStyle];
}
[self layout];
[CPApp runModalForWindow:_window];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
@param window The parent window for the sheet.
@param modalDelegate The delegate for the modal-dialog session.
@param alertDidEndSelector Message the alert sends to modalDelegate after the sheet is dismissed.
@param contextInfo Contextual data passed to modalDelegate in didEndSelector message.
*/
- (void)beginSheetModalForWindow:(CPWindow)aWindow modalDelegate:(id)modalDelegate didEndSelector:(SEL)alertDidEndSelector contextInfo:(id)contextInfo
{
if (!([_window styleMask] & CPDocModalWindowMask))
{
_needsLayout = YES;
[self _createWindowWithStyle:CPDocModalWindowMask];
}
[self layout];
_modalDelegate = modalDelegate;
_didEndSelector = alertDidEndSelector;
[CPApp beginSheet:_window modalForWindow:aWindow modalDelegate:self didEndSelector:@selector(_alertDidEnd:returnCode:contextInfo:) contextInfo:contextInfo];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
@param window The parent window for the sheet.
*/
- (void)beginSheetModalForWindow:(CPWindow)aWindow
{
[self beginSheetModalForWindow:aWindow modalDelegate:nil didEndSelector:nil contextInfo:nil];
}
#pragma mark Private
/*!
@ignore
*/
- (void)_createWindowWithStyle:(int)forceStyle
{
var frame = CGRectMakeZero();
frame.size = [self currentValueForThemeAttribute:@"size"];
_window = [[CPWindow alloc] initWithContentRect:frame styleMask:forceStyle || _defaultWindowStyle];
if (_title)
[_window setTitle:_title];
var contentView = [_window contentView],
count = [_buttons count];
if (count)
while (count--)
[contentView addSubview:_buttons[count]];
else
[self addButtonWithTitle:@"OK"];
[contentView addSubview:_messageLabel];
[contentView addSubview:_alertImageView];
[contentView addSubview:_informativeLabel];
if (_showHelp)
[contentView addSubview:_alertHelpButton];
}
/*!
@ignore
*/
- (@action)_showHelp:(id)aSender
{
if ([_delegate respondsToSelector:@selector(alertShowHelp:)])
[_delegate alertShowHelp:self];
}
/*
@ignore
*/
- (@action)_takeReturnCodeFrom:(id)aSender
{
if ([_window isSheet])
[CPApp endSheet:_window returnCode:[aSender tag]];
else
{
[CPApp abortModal];
[_window close];
[self _alertDidEnd:_window returnCode:[aSender tag] contextInfo:nil];
}
}
/*!
@ignore
*/
- (void)_alertDidEnd:(CPWindow)aWindow returnCode:(int)returnCode contextInfo:(id)contextInfo
{
if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:returnCode];
if (_didEndSelector)
objj_msgSend(_modalDelegate, _didEndSelector, self, returnCode, contextInfo);
_modalDelegate = nil;
_didEndSelector = nil;
}
#pragma mark Theme Attributes
+ (CPString)defaultThemeClass
{
return @"alert";
@@ -104,7 +671,17 @@ CPCriticalAlertStyle = 2;
CGPointMake(15, 12),
[CPNull null],
[CPNull null],
[CPNull null]
[CPNull null],
[CPNull null],
[CPNull null],
[CPNull null],
0.0,
0.0,
3.0,
[CPColor blackColor],
[CPFont systemFontOfSize:12.0],
[CPNull null],
0.0
]
forKeys:[@"size", @"content-inset", @"informative-offset", @"button-offset",
@"message-text-alignment", @"message-text-color", @"message-text-font", @"message-text-shadow-color", @"message-text-shadow-offset",
@@ -112,359 +689,18 @@ CPCriticalAlertStyle = 2;
@"image-offset",
@"information-image",
@"warning-image",
@"error-image"
@"error-image",
@"help-image",
@"help-image-left-offset",
@"help-image-pressed",
@"suppression-button-y-offset",
@"suppression-button-x-offset",
@"default-elements-margin",
@"suppression-button-text-color",
@"suppression-button-text-font",
@"suppression-button-text-shadow-color",
@"suppression-button-text-shadow-offset"
]];
}
/*!
Initializes a \c CPAlert panel with the default alert style \c CPWarningAlertStyle.
*/
- (id)init
{
if (self = [super init])
{
_buttons = [CPArray array];
_alertStyle = CPWarningAlertStyle;
_alertPanel = nil;
_windowStyle = nil;
_didEndSelector = nil;
_messageLabel = [CPTextField labelWithTitle:@"Alert"];
_alertImageView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
_informativeLabel = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
}
return self;
}
/*!
Sets the window appearance. If CPHUDBackgroundWindowMask is set, the default HUD theme
will be activated.
@param styleMask - Either CPHUDBackgroundWindowMask or nil for standard.
*/
- (void)setWindowStyle:(int)styleMask
{
_windowStyle = styleMask;
[self setTheme:(_windowStyle & CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]];
// We'll need to recreate the panel to get the new window style.
_alertPanel = nil;
}
- (void)_createPanel
{
var frame = CGRectMakeZero();
frame.size = [self currentValueForThemeAttribute:@"size"];
_alertPanel = [[CPPanel alloc] initWithContentRect:frame styleMask:_windowStyle ? _windowStyle | CPTitledWindowMask : CPTitledWindowMask];
var contentView = [_alertPanel contentView],
count = [_buttons count];
if (count)
{
while (count--)
[contentView addSubview:_buttons[count]];
}
else
[self addButtonWithTitle:@"OK"];
[contentView addSubview:_messageLabel];
[contentView addSubview:_alertImageView];
[contentView addSubview:_informativeLabel];
}
/*!
Sets the window's title. If this is not defined, a default title based on your warning level will be used.
@param aTitle the title to use in place of the default. Set to nil to use default.
*/
- (void)setTitle:(CPString)aTitle
{
_windowTitle = aTitle;
}
/*!
Gets the window's title.
*/
- (CPString)title
{
return _windowTitle;
}
/*!
Gets the window's style.
*/
- (int)windowStyle
{
return _windowStyle;
}
/*!
Sets the receivers delegate.
@param delegate - Delegate for the alert. nil removes the delegate.
*/
- (void)setDelegate:(id)delegate
{
_delegate = delegate;
}
/*!
Gets the receiver's delegate.
*/
- (void)delegate
{
return _delegate;
}
/*!
Sets the alert style of the receiver.
@param style - Alert style for the alert.
*/
- (void)setAlertStyle:(CPAlertStyle)style
{
_alertStyle = style;
}
/*!
Gets the alert style.
*/
- (CPAlertStyle)alertStyle
{
return _alertStyle;
}
/*!
Sets the receivers message text, or title, to a given text.
@param messageText - Message text for the alert.
*/
- (void)setMessageText:(CPString)messageText
{
[_messageLabel setStringValue:messageText];
}
/*!
Returns the receiver's message text body.
*/
- (CPString)messageText
{
return [_messageLabel stringValue];
}
/*!
Sets the receiver's informative text, shown below the message text.
@param informativeText - The informative text.
*/
- (void)setInformativeText:(CPString)informativeText
{
[_informativeLabel setStringValue:informativeText];
}
/*!
Returns the receiver's informative text.
*/
- (CPString)informativeText
{
return [_informativeLabel stringValue];
}
/*!
Adds a button with a given title to the receiver.
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.
The first button will automatically be given a key equivalent of Return,
and any button titled "Cancel" will be given a key equivalent of Escape.
You really shouldn't need more than 3 buttons.
*/
- (void)addButtonWithTitle:(CPString)title
{
var bounds = [[_alertPanel contentView] bounds],
button = [[CPButton alloc] initWithFrame:CGRectMakeZero()],
_buttonCount = [_buttons count];
[button setTitle:title];
[button setTarget:self];
[button setTag:_buttonCount];
[button setAction:@selector(_dismissAlert:)];
[[_alertPanel contentView] addSubview:button];
if (_buttonCount == 0)
[button setKeyEquivalent:CPCarriageReturnCharacter];
else if ([title lowercaseString] === "cancel")
[button setKeyEquivalent:CPEscapeFunctionKey];
else
[button setKeyEquivalent:nil];
[_buttons insertObject:button atIndex:0];
}
- (void)layoutPanel
{
if (!_alertPanel)
[self _createPanel];
var inset = [self currentValueForThemeAttribute:@"content-inset"],
iconOffset = [self currentValueForThemeAttribute:@"image-offset"],
theTitle,
theImage;
switch (_alertStyle)
{
case CPWarningAlertStyle: theImage = [self currentValueForThemeAttribute:@"warning-image"];
theTitle = @"Warning";
break;
case CPInformationalAlertStyle: theImage = [self currentValueForThemeAttribute:@"information-image"];
theTitle = @"Information";
break;
case CPCriticalAlertStyle: theImage = [self currentValueForThemeAttribute:@"error-image"];
theTitle = @"Error";
break;
}
[_alertImageView setImage:theImage];
var imageSize = theImage ? [theImage size] : CGSizeMakeZero();
[_alertImageView setFrame:CGRectMake(iconOffset.x, iconOffset.y, imageSize.width, imageSize.height)];
[_alertPanel setTitle:_windowTitle ? _windowTitle : theTitle];
[_alertPanel setFloatingPanel:YES];
[_alertPanel center];
[_messageLabel setTextColor:[self currentValueForThemeAttribute:@"message-text-color"]];
[_messageLabel setFont:[self currentValueForThemeAttribute:@"message-text-font"]];
[_messageLabel setTextShadowColor:[self currentValueForThemeAttribute:@"message-text-shadow-color"]];
[_messageLabel setTextShadowOffset:[self currentValueForThemeAttribute:@"message-text-shadow-offset"]];
[_messageLabel setAlignment:[self currentValueForThemeAttribute:@"message-text-alignment"]];
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
[_informativeLabel setTextColor:[self currentValueForThemeAttribute:@"informative-text-color"]];
[_informativeLabel setFont:[self currentValueForThemeAttribute:@"informative-text-font"]];
[_informativeLabel setTextShadowColor:[self currentValueForThemeAttribute:@"informative-text-shadow-color"]];
[_informativeLabel setTextShadowOffset:[self currentValueForThemeAttribute:@"informative-text-shadow-offset"]];
[_informativeLabel setLineBreakMode:CPLineBreakByWordWrapping];
// FIXME sizeWithFontCorrection shouldn't be needed.
var bounds = [[_alertPanel contentView] bounds],
offsetX = CGRectGetWidth(bounds) - inset.right,
informativeOffset = [self currentValueForThemeAttribute:@"informative-offset"],
buttonOffset = [self currentValueForThemeAttribute:@"button-offset"],
textWidth = offsetX - inset.left,
messageSize = [([_messageLabel stringValue] || " ") sizeWithFont:[_messageLabel font] inWidth:textWidth],
informationString = [_informativeLabel stringValue],
informativeSize = [(informationString || " ") sizeWithFont:[_informativeLabel font] inWidth:textWidth],
sizeWithFontCorrection = 6.0;
[_messageLabel setFrame:CGRectMake(inset.left, inset.top, textWidth, messageSize.height + sizeWithFontCorrection)];
[_informativeLabel setFrame:CGRectMake(inset.left, CGRectGetMaxY([_messageLabel frame]) + informativeOffset, textWidth, informativeSize.height + sizeWithFontCorrection)];
// Don't let an empty informative label partially cover the buttons.
[_informativeLabel setHidden:!informationString];
var aRepresentativeButton = _buttons[0],
buttonY = MAX(CGRectGetMaxY([_alertImageView frame]), CGRectGetMaxY(informationString ? [_informativeLabel frame] : [_messageLabel frame])) + buttonOffset; // the lower of the bottom of the text and the bottom of the icon.
[aRepresentativeButton setTheme:[self theme]];
[aRepresentativeButton sizeToFit];
// Make the window just tall enough to fit everything. Bit of a hack really.
var minimumSize = [self currentValueForThemeAttribute:@"size"],
desiredHeight = MAX(minimumSize.height, buttonY + CGRectGetHeight([aRepresentativeButton bounds]) + inset.bottom),
deltaY = desiredHeight - CGRectGetHeight(bounds),
frameSize = CGSizeMakeCopy([_alertPanel frame].size);
frameSize.height += deltaY;
[_alertPanel setFrameSize:frameSize];
var count = [_buttons count];
while (count--)
{
var button = _buttons[count];
[button setTheme:[self theme]];
[button sizeToFit];
var buttonBounds = [button bounds],
width = MAX(80.0, CGRectGetWidth(buttonBounds)),
height = CGRectGetHeight(buttonBounds);
offsetX -= width;
[button setFrame:CGRectMake(offsetX, buttonY, width, height)];
offsetX -= 10;
}
}
/*!
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.
*/
- (void)runModal
{
[self layoutPanel];
[CPApp runModalForWindow:_alertPanel];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
@param window The parent window for the sheet.
@param modalDelegate The delegate for the modal-dialog session.
@param alertDidEndSelector Message the alert sends to modalDelegate after the sheet is dismissed.
@param contextInfo Contextual data passed to modalDelegate in didEndSelector message.
*/
- (void)beginSheetModalForWindow:(CPWindow)window modalDelegate:(id)modalDelegate didEndSelector:(SEL)alertDidEndSelector contextInfo:(void)contextInfo
{
if (!(_windowStyle & CPDocModalWindowMask))
[self setWindowStyle:CPDocModalWindowMask];
[self layoutPanel];
_didEndSelector = alertDidEndSelector;
_modalDelegate = modalDelegate;
[CPApp beginSheet:_alertPanel modalForWindow:window modalDelegate:self didEndSelector:@selector(_alertDidEnd:returnCode:contextInfo:) contextInfo:contextInfo];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
@param window The parent window for the sheet.
*/
- (void)beginSheetModalForWindow:(CPWindow)window
{
if (!(_windowStyle & CPDocModalWindowMask))
[self setWindowStyle:CPDocModalWindowMask];
[self layoutPanel];
[CPApp beginSheet:_alertPanel modalForWindow:window modalDelegate:self didEndSelector:@selector(_alertDidEnd:returnCode:contextInfo:) contextInfo:nil];
}
- (void)_alertDidEnd:(CPWindow)aSheet returnCode:(CPInteger)returnCode contextInfo:(id)contextInfo
{
if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:returnCode];
if (_didEndSelector)
objj_msgSend(_modalDelegate, _didEndSelector, self, returnCode, contextInfo);
_didEndSelector = nil;
_modalDelegate = nil;
}
/* @ignore */
- (void)_dismissAlert:(CPButton)button
{
if ([_alertPanel isSheet])
[CPApp endSheet:_alertPanel returnCode:[button tag]];
else
{
[CPApp abortModal];
[_alertPanel close];
[self _alertDidEnd:nil returnCode:[button tag] contextInfo:nil];
}
}
@end
+91 -14
View File
@@ -21,6 +21,7 @@
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPTimer.j>
@import "CAMediaTimingFunction.j"
@@ -312,7 +313,7 @@ ACTUAL_FRAME_RATE = 0;
[_timingFunction getControlPointAtIndex:1 values:c1];
[_timingFunction getControlPointAtIndex:2 values:c2];
return CubicBezierAtTime(t,c1[0],c1[1],c2[0],c2[1],_duration);
return CubicBezierAtTime(t, c1[0], c1[1], c2[0], c2[1], _duration);
}
@end
@@ -320,28 +321,104 @@ ACTUAL_FRAME_RATE = 0;
// 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 CubicBezierAtTime = function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration)
{
var ax=0,bx=0,cx=0,ay=0,by=0,cy=0;
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;};
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));};
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;}};
function solveCurveX(x, epsilon)
{
var t0,
t1,
t2 = x,
x2,
d2,
i = 0;
// 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;}
for (; i < 8; i++)
{
x2 = sampleCurveX(t2) - x;
if (ABS(x2) < epsilon)
return t2;
d2 = sampleCurveDerivativeX(t2);
if (ABS(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;}
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 (ABS(x2 - x) < epsilon)
return t2;
if (x > x2)
t0 = t2;
else
t1 = t2;
t2 = (t1 - t0) * 0.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;
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));
};
+146 -9
View File
@@ -57,7 +57,7 @@ CPRunContinuesResponse = -1002;
@ingroup appkit
@class CPApplication
CPApplication is THE way to start up the Cappucino framework for your application to use.
CPApplication is THE way to start up the Cappuccino 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
\c CPApplicationMain function. A simple example looks like this:
@@ -90,7 +90,6 @@ CPRunContinuesResponse = -1002;
CPWindow _previousKeyWindow;
CPWindow _previousMainWindow;
CPMenu _mainMenu;
CPDocumentController _documentController;
CPModalSession _currentSession;
@@ -293,11 +292,21 @@ CPRunContinuesResponse = -1002;
}
}
/*!
Sets the applications icon image. This image is used in the default "About" window.
By default this value is pulled from the CPApplicationIcon key in your info.plist file.
@param anImage - The image to set.
*/
- (void)setApplicationIconImage:(CPImage)anImage
{
_applicationIconImage = anImage;
}
/*!
Returns the application icon image. By default this is pulled from the CPApplicationIcon key of info.plist.
@return CPImage - Your application icon image.
*/
- (CPImage)applicationIconImage
{
if (_applicationIconImage)
@@ -310,11 +319,38 @@ CPRunContinuesResponse = -1002;
return _applicationIconImage;
}
/*!
Opens the standard about panel with no options.
*/
- (void)orderFrontStandardAboutPanel:(id)sender
{
[self orderFrontStandardAboutPanelWithOptions:nil];
}
/*!
Opens the standard about panel. This method takes a single argument \c options.
Options is a dictionary that can contain any of the following keys:
<pre>
ApplicationName - The name of your application.
ApplicationIcon - Application icon image.
Version - The full version of your application
ApplicationVersion - The shorter version number of your application.
Copyright - Human readable copyright information.
</pre>
If you choose not the include any of the above keys, they will default
to the following respective keys in your info.plist file.
<pre>
CPBundleName
CPApplicationIcon (through a call to -applicationIconImage, see documentation for that method for more details)
CPBundleVersion
CPBundleShortVersionString
CPHumanReadableCopyright
</pre>
@param options - A dictionary with the aboe listed keys. You can pass nil to default to your plist values.
*/
- (void)orderFrontStandardAboutPanelWithOptions:(CPDictionary)options
{
if (!_aboutPanel)
@@ -530,7 +566,7 @@ CPRunContinuesResponse = -1002;
- (BOOL)_handleKeyEquivalent:(CPEvent)anEvent
{
return [[self keyWindow] performKeyEquivalent:anEvent] ||
[_mainMenu performKeyEquivalent:anEvent];
[[self mainMenu] performKeyEquivalent:anEvent];
}
/*!
@@ -574,6 +610,10 @@ CPRunContinuesResponse = -1002;
[[anEvent window] sendEvent:anEvent];
}
/*!
If the delegate responds to the given selector it will call the method on the delegate,
otherwise the method will be passed to CPResponder.
*/
- (void)doCommandBySelector:(SEL)aSelector
{
if ([_delegate respondsToSelector:aSelector])
@@ -637,7 +677,7 @@ CPRunContinuesResponse = -1002;
*/
- (CPMenu)mainMenu
{
return _mainMenu;
return [self menu];
}
/*!
@@ -645,21 +685,30 @@ CPRunContinuesResponse = -1002;
@param aMenu the menu to set for the application
*/
- (void)setMainMenu:(CPMenu)aMenu
{
[self setMenu:aMenu];
}
- (void)setMenu:(CPMenu)aMenu
{
if ([aMenu _menuName] === "CPMainMenu")
{
if (_mainMenu === aMenu)
if ([self menu] === aMenu)
return;
_mainMenu = aMenu;
[super setMenu:aMenu];
if ([CPPlatform supportsNativeMainMenu])
window.cpSetMainMenu(_mainMenu);
window.cpSetMainMenu([self menu]);
}
else
[aMenu _setMenuName:@"CPMainMenu"];
}
/*!
Opens the shared color panel.
@param aSender
*/
- (void)orderFrontColorPanel:(id)aSender
{
[[CPColorPanel sharedColorPanel] orderFront:self];
@@ -828,16 +877,38 @@ CPRunContinuesResponse = -1002;
return nil;
}
/*!
Fires a callback function when an event matching a given mask occurs.
@param aCallback - A js function to be fired.
@prarm aMask - An event mask for the next event.
@param anExpiration - The date for which this callback expires (not implemented).
@param inMode (not implemented).
@param shouldDequeue (not implemented).
*/
- (void)setCallback:(Function)aCallback forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
{
_eventListeners.push(_CPEventListenerMake(aMask, aCallback));
}
- (CPEvent)setTarget:(id)aTarget selector:(SEL)aSelector forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
/*!
Assigns a target and action for the next event matching a given event mask.
The callback method called will be passed the CPEvent when it fires.
@param aTarget - The target object for the callback.
@param aSelector - The selector which should be called on the target object.
@param aMask - The mask for a given event which should trigger the callback.
@param anExpiration - The date for which the callback expires (not implemented).
@param aMode (not implemented).
@param shouldDequeue (not implemented).
*/
- (void)setTarget:(id)aTarget selector:(SEL)aSelector forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
{
_eventListeners.push(_CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }));
}
/*!
Returns the last event recieved by your application.
*/
- (CPEvent)currentEvent
{
return _currentEvent;
@@ -867,6 +938,19 @@ CPRunContinuesResponse = -1002;
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
}
/*!
Ends a sheet modal.
The following are predefined return codes:
<pre>
CPRunStoppedResponse
CPRunAbortedResponse
CPRunContinuesResponse
</pre>
@param sheet - The window object (sheet) to dismiss.
@param returnCode - The return code to send to the delegate. You can use one of the return codes above or a custom value that you define.
*/
- (void)endSheet:(CPWindow)sheet returnCode:(int)returnCode
{
var count = [_windows count];
@@ -885,11 +969,31 @@ CPRunContinuesResponse = -1002;
}
}
/*!
Ends a sheet and sends the return code "0".
@param sheet - The CPWindow object (sheet) that should be dismissed.
*/
- (void)endSheet:(CPWindow)sheet
{
// FIX ME: this is wrong: by Cocoa this should be: CPRunStoppedResponse.
[self endSheet:sheet returnCode:0];
}
/*!
Returns and array of slash seperated arugments to your application.
These values are pulled from your window location hash.
For exampled if your application loaded:
<pre>
index.html#280north/cappuccino/issues
</pre>
The follow array would be returned:
<pre>
["280north", "cappuccino", "issues"]
</pre>
@return CPArray - The array of arguments.
*/
- (CPArray)arguments
{
if (_fullArgsString !== window.location.hash)
@@ -898,6 +1002,22 @@ CPRunContinuesResponse = -1002;
return _args;
}
/*!
Sets the arguments of your application.
That is, set the slash seperated values of an array as the window location hash.
For example if you pass an array:
<pre>
["280north", "cappuccino", "issues"]
</pre>
The new window location would be
<pre>
index.html#280north/cappuccino/issues
</pre>
@param args - An array of arguments.
*/
- (void)setArguments:(CPArray)args
{
if (!args || args.length == 0)
@@ -908,7 +1028,7 @@ CPRunContinuesResponse = -1002;
return;
}
if ([args class] != CPArray)
if (![args isKindOfClass:CPArray])
args = [CPArray arrayWithObject:args];
_args = args;
@@ -939,6 +1059,23 @@ CPRunContinuesResponse = -1002;
_args = [];
}
/*!
Returns a dictionary of the window location named arguments.
For example if your location was:
<pre>
index.html?owner=280north&repo=cappuccino&type=issues
</pre>
a CPDictionary with the keys:
<pre>
owner, repo, type
</pre>
and respective values:
<pre>
280north, cappuccino, issues
</pre>
Will be returned.
*/
- (CPDictionary)namedArguments
{
return _namedArgs;
+322 -31
View File
@@ -1,5 +1,3 @@
/*
* CPArrayController.j
* AppKit
@@ -29,7 +27,14 @@
@import "CPObjectController.j"
@import "CPKeyValueBinding.j"
/*!
@class CPArrayController
CPArrayController is a bindings compatible class that manages an array.
CPArrayController also provides selection management and sorting capabilities.
*/
@implementation CPArrayController : CPObjectController
{
BOOL _avoidsEmptySelection;
@@ -39,10 +44,12 @@
BOOL _selectsInsertedObjects;
BOOL _alwaysUsesMultipleValuesMarker;
id _selectionIndexes;
id _sortDescriptors;
id _filterPredicate;
id _arrangedObjects;
BOOL _automaticallyRearrangesObjects; // FIXME: Not in use
CPIndexSet _selectionIndexes;
CPArray _sortDescriptors;
CPPredicate _filterPredicate;
CPArray _arrangedObjects;
}
+ (void)initialize
@@ -102,53 +109,168 @@
return [CPSet setWithObjects:"selectionIndexes"];
}
- (id)init
{
self = [super init];
if (self)
{
_selectionIndexes = [CPIndexSet indexSet];
_preservesSelection = YES;
_selectsInsertedObjects = YES;
_avoidsEmptySelection = YES;
_clearsFilterPredicateOnInsertion = YES;
_alwaysUsesMultipleValuesMarker = NO;
_automaticallyRearrangesObjects = NO;
_filterRestrictsInsertion = YES; // FIXME: Not in use
[self _init];
}
return self;
}
- (void)_init
{
_sortDescriptors = [CPArray array];
_filterPredicate = nil;
_selectionIndexes = [CPIndexSet indexSet];
_arrangedObjects = nil;
}
- (void)prepareContent
{
[self _setContentArray:[[self newObject]]];
}
/*!
Returns YES if the selection should try to be preserved when the content changes, otherwise NO.
@return BOOL YES if the selection is preserved, otherwise NO.
*/
- (BOOL)preservesSelection
{
return _preservesSelection;
}
/*!
Sets whether the selection is kept when the content changes.
@param BOOL aFlag - YES if the selection should be kept, otherwise NO.
*/
- (void)setPreservesSelection:(BOOL)value
{
_preservesSelection = value;
}
/*!
@return BOOL - Returns YES if new objects are automatically selected, otherwise NO.
*/
- (BOOL)selectsInsertedObjects
{
return _selectsInsertedObjects;
}
/*!
Sets whether the controller will automatically select objects as they are inserted.
@return BOOL - YES if new objects are selected, otherwise NO.
*/
- (void)setSelectsInsertedObjects:(BOOL)value
{
_selectsInsertedObjects = value;
}
/*!
@return BOOL - YES if the controller should try to avoid an empty selection otherwise NO.
*/
- (BOOL)avoidsEmptySelection
{
return _avoidsEmptySelection;
}
/*!
Sets whether the controller should try to avoid an empty selection.
@param BOOL aFlag - YES if the receiver should attempt to avoid an empty selection, otherwise NO.
*/
- (void)setAvoidsEmptySelection:(BOOL)value
{
_avoidsEmptySelection = value;
}
/*!
Whether the receiver will clear its filter predicate when a new object is inserted.
@return BOOL YES if the receiver clears filter predicates on insert
*/
- (BOOL)clearsFilterPredicateOnInsertion
{
return _clearsFilterPredicateOnInsertion;
}
/*!
Sets whether the receiver should clear its filter predicate when a new object is inserted.
@param BOOL YES if the receiver should clear filter predicates on insert
*/
- (void)setClearsFilterPredicateOnInsertion:(BOOL)aFlag
{
_clearsFilterPredicateOnInsertion = aFlag;
}
/*!
Whether the receiver will always return the multiple values marker when multiple
items are selected, even if the items have the same value.
@return BOOL YES if the receiver always uses the multiple values marker
*/
- (BOOL)alwaysUsesMultipleValuesMarker
{
return _alwaysUsesMultipleValuesMarker;
}
/*!
Sets whether the receiver should always return the multiple values marker when multiple
items are selected, even if the items have the same value.
@param BOOL aFlag YES if the receiver should always use the multiple values marker
*/
- (void)setAlwaysUsesMultipleValuesMarker:(BOOL)aFlag
{
_alwaysUsesMultipleValuesMarker = aFlag;
}
/*!
Whether the receiver will rearrange its contents automatically whenever the sort
descriptors or filter predicates are changed.
NOTE: not yet implemented. Cappuccino always act as if this value was YES.
@return BOOL YES if the receiver will automatically rearrange its content on new sort
descriptors or filter predicates
*/
- (BOOL)automaticallyRearrangesObjects
{
return _automaticallyRearrangesObjects;
}
/*!
Sets whether the receiver should rearrange its contents automatically whenever the sort
descriptors or filter predicates are changed.
NOTE: not yet implemented. Cappuccino always act as if this value was YES.
@param BOOL YES if the receiver should automatically rearrange its content on new sort
descriptors or filter predicates
*/
- (void)setAutomaticallyRearrangesObjects:(BOOL)aFlag
{
_automaticallyRearrangesObjects = aFlag;
}
/*!
Sets the controller's content object.
@param id value - the content object of the controller.
*/
- (void)setContent:(id)value
{
if (value === nil)
@@ -184,7 +306,7 @@
// We need to be in control of when notifications fire.
_contentObject = value;
if (_clearsFilterPredicateOnInsertion)
if (_clearsFilterPredicateOnInsertion && _filterPredicate != nil)
[self __setFilterPredicate:nil]; // Causes a _rearrangeObjects.
else
[self _rearrangeObjects];
@@ -198,32 +320,53 @@
[self didChangeValueForKey:@"filterPredicate"];
}
/*!
@ignore
*/
- (void)_setContentArray:(id)anArray
{
[self setContent:anArray];
}
/*!
@ignore
*/
- (void)_setContentSet:(id)aSet
{
[self setContent:aSet];
[self setContent:[aSet allObjects]];
}
/*!
Returns the content array of the controller.
@return id the content array of the receiver
*/
- (id)contentArray
{
return [self content];
}
/*!
Returns the content of the receiver as a CPSet.
@return id - the content of the controller as a set.
*/
- (id)contentSet
{
return [self content];
return [CPSet setWithArray:[self content]];
}
/*!
Sorts and filters a given array and returns it.
@param CPArray anArray - an array of objects.
@return CPArray - the array of sorted objects.
*/
- (CPArray)arrangeObjects:(CPArray)objects
{
var filterPredicate = [self filterPredicate],
sortDescriptors = [self sortDescriptors];
if (filterPredicate && sortDescriptors)
if (filterPredicate && [sortDescriptors count] > 0)
{
var sortedObjects = [objects filteredArrayUsingPredicate:filterPredicate];
[sortedObjects sortUsingDescriptors:sortDescriptors];
@@ -231,12 +374,15 @@
}
else if (filterPredicate)
return [objects filteredArrayUsingPredicate:filterPredicate];
else if (sortDescriptors)
else if ([sortDescriptors count] > 0)
return [objects sortedArrayUsingDescriptors:sortDescriptors];
return [objects copy];
}
/*!
Triggers the filtering of the objects in the controller.
*/
- (void)rearrangeObjects
{
[self willChangeValueForKey:@"arrangedObjects"];
@@ -270,24 +416,40 @@
[self __setSelectionIndexes:oldSelectionIndexes];
}
/*!
@ignore
*/
- (void)__setArrangedObjects:(id)value
{
if (_arrangedObjects === value)
return;
_arrangedObjects = [[_CPObservableArray alloc] initWithArray:value];
_arrangedObjects = [[_CPObservableArray alloc] initWithArray:value];
}
/*!
Returns an array of the controller's objects sorted and filtered.
@return - array of objects
*/
- (id)arrangedObjects
{
return _arrangedObjects;
}
/*!
Returns the receiver's array of sort descriptors.
@return CPArray an array of sort descriptors
*/
- (CPArray)sortDescriptors
{
return _sortDescriptors;
}
/*!
Sets the sort descriptors for the controller.
@param CPArray descriptors - the new sort descriptors.
*/
- (void)setSortDescriptors:(CPArray)value
{
if (_sortDescriptors === value)
@@ -299,11 +461,23 @@
[self _rearrangeObjects];
}
/*!
Returns the predicate used by the controller to filter the contents of the receiver.
If no predicate is set nil is returned.
@return CPPredicate the predicate used by the controller
*/
- (CPPredicate)filterPredicate
{
return _filterPredicate;
}
/*!
Sets the predicate for the controller to filter the content.
Passing nil will remove an existing prediate.
@param CPPrediate aPredicate - the new predicate.
*/
- (void)setFilterPredicate:(CPPredicate)value
{
[self __setFilterPredicate:value];
@@ -324,28 +498,52 @@
[self _rearrangeObjects];
}
/*!
Returns a BOOL indicating whether the receiver always returns the multiple values marker when multiple objects are selected.
@return BOOL YES is the controller always uses multiple value markers, otherwise NO.
*/
- (BOOL)alwaysUsesMultipleValuesMarker
{
return _alwaysUsesMultipleValuesMarker;
}
//Selection
/*!
Returns the index of the first object in the controller's selection.
@return unsigned - Index of the first selected object.
*/
- (unsigned)selectionIndex
{
return [_selectionIndexes firstIndex];
}
/*!
Sets the selected index
@param unsigned anIndex - the new index to select
@return BOOL - Returns YES if the selection was changed, otherwise NO.
*/
- (BOOL)setSelectionIndex:(unsigned)index
{
return [self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
/*!
Returns an index set of the selected indexes.
@return CPIndexSet - The selected indexes.
*/
- (CPIndexSet)selectionIndexes
{
return _selectionIndexes;
}
/*!
Sets the selection indexes of the controller.
@param CPIndexSet indexes - the indexes to select
@return BOOL - Returns YES if the selection changed, otherwise NO.
*/
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
{
[self _selectionWillChange]
@@ -393,11 +591,16 @@
// Push back the new selection to the model for selectionIndexes if we have one.
// There won't be an infinite loop because of the equality check above.
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
var binderClass = [[self class] _binderClassForBinding:@"selectionIndexes"];
[[binderClass getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
return YES;
}
/*!
Returns an array of the selected objects.
@return CPArray - the selected objects.
*/
- (CPArray)selectedObjects
{
var objects = [[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]];
@@ -405,6 +608,12 @@
return [_CPObservableArray arrayWithArray:(objects || [])];
}
/*!
Sets the selected objects of the controller.
@param CPArray anArray - the objects to select
@return BOOL - Returns YES if the selection was changed, otherwise NO.
*/
- (BOOL)setSelectedObjects:(CPArray)objects
{
[self willChangeValueForKey:@"selectionIndexes"];
@@ -439,12 +648,20 @@
}
//Moving selection
/*!
Returns YES if the previous object, relative to the current selection, in the controller's content array can be selected.
@return BOOL - YES if the object can be selected, otherwise NO.
*/
- (BOOL)canSelectPrevious
{
return [[self selectionIndexes] firstIndex] > 0
}
/*!
Selects the previous object, relative to the current selection, in the controllers arranged content.
@param id sender - the sender of the message.
*/
- (void)selectPrevious:(id)sender
{
var index = [[self selectionIndexes] firstIndex] - 1;
@@ -453,11 +670,20 @@
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
/*!
Returns YES if the next object, relative to the current selection, in the controller's content array can be selected.
@return BOOL - YES if the object can be selected, otherwise NO.
*/
- (BOOL)canSelectNext
{
return [[self selectionIndexes] firstIndex] < [[self arrangedObjects] count] - 1;
}
/*!
Selects the next object, relative to the current selection, in the controllers arranged content.
@param id sender - the sender of the message.
*/
- (void)selectNext:(id)sender
{
var index = [[self selectionIndexes] firstIndex] + 1;
@@ -468,6 +694,11 @@
//Add/Remove
/*!
Adds object to the receiver's content collection and the arranged objects array.
@param id anObject - the object to add the controller.
*/
- (void)addObject:(id)object
{
if (![self canAdd])
@@ -501,6 +732,12 @@
[self didChangeValueForKey:@"filterPredicate"];
}
/*!
Adds an object at a given index to the receiver's collection.
@param id anObject - The object to add to the collection.
@param int anIndex - The index to insert the object at.
*/
- (void)insertObject:(id)anObject atArrangedObjectIndex:(int)anIndex
{
if (![self canAdd])
@@ -532,11 +769,13 @@
[self didChangeValueForKey:@"filterPredicate"];
}
/*!
Removes a given object from the receiver's collection.
@param id anObject - The object to remove from the collection.
*/
- (void)removeObject:(id)object
{
if (![self canRemove])
return;
[self willChangeValueForKey:@"content"];
[_contentObject removeObject:object];
@@ -553,6 +792,11 @@
[self didChangeValueForKey:@"content"];
}
/*!
Creates and adds a new object to the receiver's content and arranged objects.
@param id sender - The sender of the message.
*/
- (void)add:(id)sender
{
if (![self canAdd])
@@ -561,6 +805,10 @@
[self insert:sender];
}
/*!
Creates a new object and inserts it into the receiver's content array.
@param id sender - The sender of the message.
*/
- (void)insert:(id)sender
{
if (![self canInsert])
@@ -571,17 +819,29 @@
[self addObject:newObject];
}
/*!
Removes the controller's selected objects from the controller's collection.
@param id sender - The sender of the message.
*/
- (void)remove:(id)sender
{
[self removeObjects:[[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]]];
}
/*!
Removes the objects at the specified indexes in the controller's arranged objects from the content array.
@param CPIndexSet indexes - indexes of the objects to remove.
*/
- (void)removeObjectsAtArrangedObjectIndexes:(CPIndexSet)indexes
{
[self _removeObjects:[[self arrangedObjects] objectsAtIndexes:indexes]];
}
/*!
Adds an array of objects to the controller's collection.
@param CPArray anArray - The array of objects to add to the collection.
*/
- (void)addObjects:(CPArray)objects
{
if (![self canAdd])
@@ -596,14 +856,18 @@
[self setContent:contentArray];
}
/*!
Removes an array of objects from the collection.
@param CPArray anArray - The array of objects to remove
*/
- (void)removeObjects:(CPArray)objects
{
if (![self canRemove])
return;
[self _removeObjects:objects];
}
/*!
@ignore
*/
- (void)_removeObjects:(CPArray)objects
{
[self willChangeValueForKey:@"content"];
@@ -635,6 +899,10 @@
[self didChangeValueForKey:@"content"];
}
/*!
Returns a BOOL indicating whether an object can be inserted into the controller's collection.
@return BOOL - YES if an object can be inserted, otherwise NO.
*/
- (BOOL)canInsert
{
return [self isEditable];
@@ -642,30 +910,53 @@
@end
var CPArrayControllerAvoidsEmptySelection = @"CPArrayControllerAvoidsEmptySelection",
CPArrayControllerClearsFilterPredicateOnInsertion = @"CPArrayControllerClearsFilterPredicateOnInsertion",
CPArrayControllerFilterRestrictsInsertion = @"CPArrayControllerFilterRestrictsInsertion",
CPArrayControllerPreservesSelection = @"CPArrayControllerPreservesSelection",
CPArrayControllerSelectsInsertedObjects = @"CPArrayControllerSelectsInsertedObjects",
CPArrayControllerAlwaysUsesMultipleValuesMarker = @"CPArrayControllerAlwaysUsesMultipleValuesMarker",
CPArrayControllerAutomaticallyRearrangesObjects = @"CPArrayControllerAutomaticallyRearrangesObjects";
@implementation CPArrayController (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:coder];
self = [super initWithCoder:aCoder];
if (self)
{
_avoidsEmptySelection = [coder decodeBoolForKey:@"CPArrayControllerAvoidsEmptySelection"];
_clearsFilterPredicateOnInsertion = [coder decodeBoolForKey:@"CPClearsFilterPredicateOnInsertion"];
_filterRestrictsInsertion = [coder decodeBoolForKey:@"CPArrayControllerFilterRestrictsInsertion"];
_preservesSelection = [coder decodeBoolForKey:@"CPArrayControllerPreservesSelection"];
_selectsInsertedObjects = [coder decodeBoolForKey:@"CPArrayControllerSelectsInsertedObjects"];
_alwaysUsesMultipleValuesMarker = [coder decodeBoolForKey:@"CPArrayControllerAlwaysUsesMultipleValuesMarker"];
_avoidsEmptySelection = [aCoder decodeBoolForKey:CPArrayControllerAvoidsEmptySelection];
_clearsFilterPredicateOnInsertion = [aCoder decodeBoolForKey:CPArrayControllerClearsFilterPredicateOnInsertion];
_filterRestrictsInsertion = [aCoder decodeBoolForKey:CPArrayControllerFilterRestrictsInsertion];
_preservesSelection = [aCoder decodeBoolForKey:CPArrayControllerPreservesSelection];
_selectsInsertedObjects = [aCoder decodeBoolForKey:CPArrayControllerSelectsInsertedObjects];
_alwaysUsesMultipleValuesMarker = [aCoder decodeBoolForKey:CPArrayControllerAlwaysUsesMultipleValuesMarker];
_automaticallyRearrangesObjects = [aCoder decodeBoolForKey:CPArrayControllerAutomaticallyRearrangesObjects];
_sortDescriptors = [CPArray array];
if ([self automaticallyPreparesContent])
if (![self content] && [self automaticallyPreparesContent])
[self prepareContent];
else
else if (![self content])
[self _setContentArray:[]];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeBool:_avoidsEmptySelection forKey:CPArrayControllerAvoidsEmptySelection];
[aCoder encodeBool:_clearsFilterPredicateOnInsertion forKey:CPArrayControllerClearsFilterPredicateOnInsertion];
[aCoder encodeBool:_filterRestrictsInsertion forKey:CPArrayControllerFilterRestrictsInsertion];
[aCoder encodeBool:_preservesSelection forKey:CPArrayControllerPreservesSelection];
[aCoder encodeBool:_selectsInsertedObjects forKey:CPArrayControllerSelectsInsertedObjects];
[aCoder encodeBool:_alwaysUsesMultipleValuesMarker forKey:CPArrayControllerAlwaysUsesMultipleValuesMarker];
[aCoder encodeBool:_automaticallyRearrangesObjects forKey:CPArrayControllerAutomaticallyRearrangesObjects];
}
- (void)awakeFromCib
{
[self _selectionWillChange];
+2 -2
View File
@@ -38,7 +38,7 @@ var DefaultLineWidth = 1.0;
@class CPBezierPath
A CPBezierPath allows you to create paths for drawing to the screen using a simpler API than CoreGraphics.
Paths can form any shape, including regular polgyons like squares and triangles; circles, arcs; or complex
Paths can form any shape, including regular polygons like squares and triangles; circles, arcs; or complex
line segments.
A path can be stroked and filled using the relevant method. The currently active fill and stroke color will
@@ -184,7 +184,6 @@ var DefaultLineWidth = 1.0;
CGContextBeginPath(ctx);
CGContextAddPath(ctx, _path);
CGContextSetLineWidth(ctx, [self lineWidth]);
CGContextClosePath(ctx);
CGContextStrokePath(ctx);
}
@@ -281,6 +280,7 @@ var DefaultLineWidth = 1.0;
{
CGPathAddPath(_path, nil, other._path);
}
/*!
Remove all path elements; clears path.
*/
+8 -8
View File
@@ -25,7 +25,7 @@
// CPBoxType
CPBoxPrimary = 0;
CPBoxSecondary = 1;
CPBoxSeperator = 2;
CPBoxSeparator = 2;
CPBoxOldStyle = 3;
CPBoxCustom = 4;
@@ -234,9 +234,9 @@ CPGrooveBorder = 3;
switch (_boxType)
{
case CPBoxSeperator:
// NSBox does not include a horitontal flag for the seperator type. We have to determine
// the type of seperator to draw by the width and height of the frame.
case CPBoxSeparator:
// NSBox does not include a horizontal flag for the separator type. We have to determine
// the type of separator to draw by the width and height of the frame.
if (CGRectGetWidth(bounds) === 5.0)
return [self _drawVerticalSeperatorInRect:bounds];
else if (CGRectGetHeight(bounds) === 5.0)
@@ -265,8 +265,8 @@ CPGrooveBorder = 3;
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, CGRectGetWidth(aRect), CGRectGetMinY(aRect));
CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMinY(aRect) + 0.5);
CGContextAddLineToPoint(context, CGRectGetWidth(aRect), CGRectGetMinY(aRect) + 0.5);
CGContextStrokePath(context);
}
@@ -277,8 +277,8 @@ CPGrooveBorder = 3;
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, CGRectGetMinX(aRect), CGRectGetHeight(aRect));
CGContextMoveToPoint(context, CGRectGetMinX(aRect) + 0.5, CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, CGRectGetMinX(aRect) + 0.5, CGRectGetHeight(aRect));
CGContextStrokePath(context);
}
+83 -31
View File
@@ -83,42 +83,47 @@
{
if (self = [super initWithFrame:aFrame])
{
_rowHeight = 23.0;
_defaultColumnWidth = 140.0;
_minColumnWidth = 80.0;
_imageWidth = 23.0;
_leafWidth = 13.0;
_columnWidths = [];
_pathSeparator = "/";
_tableViews = [];
_tableDelegates = [];
_allowsMultipleSelection = YES;
_allowsEmptySelection = YES;
_tableViewClass = [_CPBrowserTableView class];
_prototypeView = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_prototypeView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_prototypeView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateSelectedDataView];
[_prototypeView setLineBreakMode:CPLineBreakByTruncatingTail];
_horizontalScrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
[_horizontalScrollView setHasVerticalScroller:NO];
[_horizontalScrollView setAutohidesScrollers:YES];
[_horizontalScrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_contentView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 0, CGRectGetHeight([self bounds]))];
[_contentView setAutoresizingMask:CPViewHeightSizable];
[_horizontalScrollView setDocumentView:_contentView];
[self addSubview:_horizontalScrollView];
[self _init];
}
return self;
}
- (void)_init
{
_rowHeight = 23.0;
_defaultColumnWidth = 140.0;
_minColumnWidth = 80.0;
_imageWidth = 23.0;
_leafWidth = 13.0;
_columnWidths = [];
_pathSeparator = "/";
_tableViews = [];
_tableDelegates = [];
_allowsMultipleSelection = YES;
_allowsEmptySelection = YES;
_tableViewClass = [_CPBrowserTableView class];
_prototypeView = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_prototypeView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_prototypeView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateSelectedDataView];
[_prototypeView setLineBreakMode:CPLineBreakByTruncatingTail];
_horizontalScrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
[_horizontalScrollView setHasVerticalScroller:NO];
[_horizontalScrollView setAutohidesScrollers:YES];
[_horizontalScrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_contentView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 0, CGRectGetHeight([self bounds]))];
[_contentView setAutoresizingMask:CPViewHeightSizable];
[_horizontalScrollView setDocumentView:_contentView];
[self addSubview:_horizontalScrollView];
}
- (void)setPrototypeView:(CPView)aPrototypeView
{
_prototypeView = [CPKeyedUnarchiver unarchiveObjectWithData:
@@ -650,6 +655,53 @@
@end
@implementation CPBrowser (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
[self _init];
_allowsEmptySelection = [aCoder decodeBoolForKey:@"CPBrowserAllowsEmptySelectionKey"];
_allowsMultipleSelection = [aCoder decodeBoolForKey:@"CPBrowserAllowsMultipleSelectionKey"];
_prototypeView = [aCoder decodeObjectForKey:@"CPBrowserPrototypeViewKey"];
_rowHeight = [aCoder decodeFloatForKey:@"CPBrowserRowHeightKey"];
_imageWidth = [aCoder decodeFloatForKey:@"CPBrowserImageWidthKey"];
_minColumnWidth = [aCoder decodeFloatForKey:@"CPBrowserMinColumnWidthKey"];
_columnWidths = [aCoder decodeObjectForKey:@"CPBrowserColumnWidthsKey"];
[self setDelegate:[aCoder decodeObjectForKey:@"CPBrowserDelegateKey"]];
[self setAutohidesScroller:[aCoder decodeBoolForKey:@"CPBrowserAutohidesScrollerKey"]];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
// Don't encode the subviews, they're transient and will be recreated from data.
var actualSubviews = _subviews;
_subviews = [];
[super encodeWithCoder:aCoder];
_subviews = actualSubviews;
[aCoder encodeBool:[self autohidesScroller] forKey:@"CPBrowserAutohidesScrollerKey"];
[aCoder encodeBool:_allowsEmptySelection forKey:@"CPBrowserAllowsEmptySelectionKey"];
[aCoder encodeBool:_allowsMultipleSelection forKey:@"CPBrowserAllowsMultipleSelectionKey"];
[aCoder encodeObject:_delegate forKey:@"CPBrowserDelegateKey"];
[aCoder encodeObject:_prototypeView forKey:@"CPBrowserPrototypeViewKey"];
[aCoder encodeFloat:_rowHeight forKey:@"CPBrowserRowHeightKey"];
[aCoder encodeFloat:_imageWidth forKey:@"CPBrowserImageWidthKey"];
[aCoder encodeFloat:_minColumnWidth forKey:@"CPBrowserMinColumnWidthKey"];
[aCoder encodeObject:_columnWidths forKey:@"CPBrowserColumnWidthsKey"];
}
@end
var _CPBrowserResizeControlBackgroundImage = nil;
@implementation _CPBrowserResizeControl : CPView
+62 -4
View File
@@ -70,7 +70,13 @@ CPPushInCellMask = CPPushInButtonMask;
CPChangeGrayCellMask = CPGrayButtonMask;
CPChangeBackgroundCellMask = CPBackgroundButtonMask;
CPButtonStateMixed = CPThemeState("mixed");
CPButtonStateMixed = CPThemeState("mixed");
CPButtonStateBezelStyleRounded = CPThemeState("rounded");
// add all future correspondance between bezel styles and theme state here.
var CPButtonBezelStyleStateMap = [CPDictionary dictionaryWithObjects:[CPButtonStateBezelStyleRounded, nil]
forKeys:[CPRoundedBezelStyle, CPRoundRectBezelStyle]];
CPButtonDefaultHeight = 24.0;
CPButtonImageOffset = 3.0;
@@ -129,6 +135,11 @@ CPButtonImageOffset = 3.0;
forKeys:[@"image", @"image-offset", @"bezel-inset", @"content-inset", @"bezel-color"]];
}
/*!
Initializes and returns a newly allocated CPButton object with a specified frame rectangle.
@param aFrame The frame rectangle for the created button object.
@return An initialized CPView object or nil if the object couldn't be created.
*/
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
@@ -146,7 +157,7 @@ CPButtonImageOffset = 3.0;
_keyEquivalent = @"";
_keyEquivalentModifierMask = 0;
// [self setBezelStyle:CPRoundRectBezelStyle];
[self setBezelStyle:CPRoundRectBezelStyle];
[self setBordered:YES];
}
@@ -155,7 +166,8 @@ CPButtonImageOffset = 3.0;
// Setting the state
/*!
Returns \c YES if the button has a 'mixed' state in addition to on and off.
Returns a Boolean value indicating whether the button allows a mixed state.
@return \c YES if the button has a 'mixed' state in addition to on and off.
*/
- (BOOL)allowsMixedState
{
@@ -179,6 +191,10 @@ CPButtonImageOffset = 3.0;
[self setState:CPOnState];
}
/*!
Sets the value of the button using an Objective-J object.
@param anObjectValue The value of the button interpreted as an Objective-J object.
*/
- (void)setObjectValue:(id)anObjectValue
{
if (!anObjectValue || anObjectValue === @"" || ([anObjectValue intValue] === 0))
@@ -187,7 +203,7 @@ CPButtonImageOffset = 3.0;
else if (![anObjectValue isKindOfClass:[CPNumber class]])
anObjectValue = CPOnState;
else if (anObjectValue > CPOnState)
else if (anObjectValue >= CPOnState)
anObjectValue = CPOnState
else if (anObjectValue < CPOffState)
@@ -213,6 +229,13 @@ CPButtonImageOffset = 3.0;
}
}
/*!
Returns the button's next state.
@return The button's state. A button can have two or three states.
If it has two, this value is either \c CPOffState (the normal or unpressed state)
or \c CPOnState (the alternate or pressed state).
If it has three, this value can be \c CPOnState (the feature is in effect everywhere), \c CPOffState (the feature is in effect nowhere), or \c CPMixedState (the feature is in effect somewhere).
*/
- (CPInteger)nextState
{
if ([self allowsMixedState])
@@ -225,8 +248,16 @@ CPButtonImageOffset = 3.0;
return 1 - [self state];
}
/*!
Sets the button's next state to \c aState.
@param aState Possible states are any of the CPButton globals:
\c CPOffState, \c CPOnState, \c CPMixedState
*/
- (void)setNextState
{
if ([self infoForBinding:CPValueBinding])
[self setAllowsMixedState:NO];
[self setState:[self nextState]];
}
@@ -248,6 +279,11 @@ CPButtonImageOffset = 3.0;
return [self intValue];
}
/*!
Sets the title displayed by the button when in its normal state.
@param aTitle The string to set as the button's title. This title is always shown on buttons
that dont use their alternate contents when highlighting or displaying their alternate state.
*/
- (void)setTitle:(CPString)aTitle
{
if (_title === aTitle)
@@ -259,6 +295,11 @@ CPButtonImageOffset = 3.0;
[self setNeedsDisplay:YES];
}
/*!
Returns the title displayed on the button when its in its normal state.
@return The title displayed on the receiver when its in its normal state
or the empty string if the button doesnt display a title.
*/
- (CPString)title
{
return _title;
@@ -493,6 +534,9 @@ CPButtonImageOffset = 3.0;
size.height = MIN(size.height, maxSize.height);
[self setFrameSize:size];
if (contentView)
[self layoutSubviews];
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
@@ -643,10 +687,24 @@ CPButtonImageOffset = 3.0;
- (void)setBezelStyle:(unsigned)aBezelStyle
{
if (aBezelStyle === _bezelStyle)
return;
var currentState = [CPButtonBezelStyleStateMap objectForKey:_bezelStyle],
newState = [CPButtonBezelStyleStateMap objectForKey:aBezelStyle];
if (currentState)
[self unsetThemeState:currentState];
if (newState)
[self setThemeState:newState];
_bezelStyle = aBezelStyle;
}
- (unsigned)bezelStyle
{
return _bezelStyle;
}
@end
+58
View File
@@ -44,6 +44,14 @@ CPCheckBoxImageOffset = 4.0;
return @"check-box";
}
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding === CPValueBinding)
return [_CPCheckBoxValueBinder class];
return [super _binderClassForBinding:theBinding];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
@@ -87,3 +95,53 @@ CPCheckBoxImageOffset = 4.0;
}
@end
@implementation _CPCheckBoxValueBinder : CPBinder
{
}
- (void)setValueFor:(CPString)theBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
if (isPlaceholder)
{
switch (newValue)
{
case CPMultipleValuesMarker:
newValue = CPMixedState;
break;
case CPNoSelectionMarker:
newValue = CPOffState;
break;
case CPNotApplicableMarker:
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
[CPException raise:CPGenericException reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
newValue = CPOffState;
break;
}
if (newValue === CPMixedState)
{
[_source setAllowsMixedState:YES];
}
else
{
// Cocoa will always set allowsMixedState to NO
// This behavior will be fine for Cappuccino as well if we (like Cocoa)
// default the CPConditionallySetsEnabledBindingOption to YES
[_source setAllowsMixedState:NO];
}
}
[_source setState:newValue];
}
@end
+4 -3
View File
@@ -203,8 +203,8 @@
*/
- (void)setContent:(CPArray)anArray
{
if (_content == anArray)
return;
// reset the _selectionIndexes
[self setSelectionIndexes:[CPIndexSet indexSet]];
_content = anArray;
@@ -312,7 +312,8 @@
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
[_items[index] setSelected:YES];
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
var binderClass = [[self class] _binderClassForBinding:@"selectionIndexes"];
[[binderClass getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
[_delegate collectionViewDidChangeSelection:self];
+1 -1
View File
@@ -125,7 +125,7 @@ var cachedBlackColor,
}
/*!
@deprecated in favor of colorWithWhite:apha:
@deprecated in favor of colorWithWhite:alpha:
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.
+1 -1
View File
@@ -534,7 +534,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if(point.x > [self bounds].size.width - 1 || point.x < 1)
if (point.x > [self bounds].size.width - 1 || point.x < 1)
return NO;
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPArray arrayWithObject:CPColorDragType] owner:self];
+1 -1
View File
@@ -57,7 +57,7 @@ CPJavascriptRemedialKeySupport = 1 << 16;
CPJavaScriptShadowFeature = 1 << 20;
CPJavaScriptNegativeMouseWheelValues = 1 << 22;
CPJavaScriptMouseWheelValues_8_15 = 1 << 23
CPJavaScriptMouseWheelValues_8_15 = 1 << 23;
CPOpacityRequiresFilterFeature = 1 << 24;
+207 -39
View File
@@ -43,21 +43,21 @@ CPLineBreakByTruncatingHead = 3;
CPLineBreakByTruncatingTail = 4;
CPLineBreakByTruncatingMiddle = 5;
CPTopVerticalTextAlignment = 1,
CPCenterVerticalTextAlignment = 2,
CPTopVerticalTextAlignment = 1;
CPCenterVerticalTextAlignment = 2;
CPBottomVerticalTextAlignment = 3;
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
CPImageRight = 3;
CPImageBelow = 4;
CPImageAbove = 5;
CPImageOverlaps = 6;
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
CPImageRight = 3;
CPImageBelow = 4;
CPImageAbove = 5;
CPImageOverlaps = 6;
CPOnState = 1;
CPOffState = 0;
@@ -72,7 +72,7 @@ CPControlTextDidBeginEditingNotification = "CPControlTextDidBeginEditingNotif
CPControlTextDidChangeNotification = "CPControlTextDidChangeNotification";
CPControlTextDidEndEditingNotification = "CPControlTextDidEndEditingNotification";
var CPControlBlackColor = [CPColor blackColor];
var CPControlBlackColor = [CPColor blackColor];
/*!
@ingroup appkit
@@ -141,18 +141,20 @@ var CPControlBlackColor = [CPColor blackColor];
}
}
- (void)_reverseSetBinding
+ (Class)_binderClassForBinding:(CPString)theBinding
{
var theBinding = [CPKeyValueBinding getBinding:CPValueBinding forObject:self];
[theBinding reverseSetValueFor:@"objectValue"];
if (theBinding === CPValueBinding)
return [_CPValueBinder class];
return [super _binderClassForBinding:theBinding];
}
- (void)_replacementKeyPathForBinding:(CPString)aBinding
- (void)_reverseSetBinding
{
if (aBinding === @"value")
return @"objectValue";
var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
theBinding = [binderClass getBinding:CPValueBinding forObject:self];
return [super _replacementKeyPathForBinding:aBinding];
[theBinding reverseSetValueFor:@"objectValue"];
}
- (id)initWithFrame:(CGRect)aFrame
@@ -169,7 +171,8 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Sets the receiver's target action
Sets the receiver's target action.
@param anAction Sets the action message that gets sent to the target.
*/
- (void)setAction:(SEL)anAction
@@ -178,7 +181,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's target action
Returns the receiver's target action.
*/
- (SEL)action
{
@@ -187,6 +190,7 @@ var CPControlBlackColor = [CPColor blackColor];
/*!
Sets the receiver's target. The target receives action messages from the receiver.
@param aTarget the object that will receive the message specified by action
*/
- (void)setTarget:(id)aTarget
@@ -204,6 +208,7 @@ var CPControlBlackColor = [CPColor blackColor];
/*!
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
*/
@@ -224,6 +229,7 @@ var CPControlBlackColor = [CPColor blackColor];
/*!
Sets the tooltip for the receiver.
@param aToolTip the tooltip
*/
/*
@@ -260,7 +266,7 @@ var CPControlBlackColor = [CPColor blackColor];
/*!
Sets whether the cell can continuously send its action messages.
*/
*/
- (void)setContinuous:(BOOL)flag
{
// Some subclasses should redefine this with CPLeftMouseDraggedMask
@@ -270,6 +276,9 @@ var CPControlBlackColor = [CPColor blackColor];
_sendActionOn &= ~CPPeriodicMask;
}
/*!
Returns YES if the receiver tracks the mouse outside the frame, otherwise NO.
*/
- (BOOL)tracksMouseOutsideOfFrame
{
return NO;
@@ -286,9 +295,14 @@ var CPControlBlackColor = [CPColor blackColor];
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:YES];
_trackingMouseDownFlags = 0;
if (isWithinFrame)
[self setThemeState:CPThemeStateHovered];
}
else
{
[self unsetThemeState:CPThemeStateHovered];
if (type === CPLeftMouseDown)
{
_trackingMouseDownFlags = [anEvent modifierFlags];
@@ -327,6 +341,11 @@ var CPControlBlackColor = [CPColor blackColor];
return 0;
}
/*!
Perform a click on the receiver.
@param sender - The sender object
*/
- (void)performClick:(id)sender
{
if (![self isEnabled])
@@ -349,11 +368,18 @@ var CPControlBlackColor = [CPColor blackColor];
}
}
/*!
@ignore
Fired when the button timer finished, usually after the user hits enter.
*/
- (void)unhighlightButtonTimerDidFinish:(id)sender
{
[self highlight:NO];
}
/*!
Returns the mask of modifier keys held down when the user clicked.
*/
- (unsigned)mouseDownFlags
{
return _trackingMouseDownFlags;
@@ -384,8 +410,27 @@ var CPControlBlackColor = [CPColor blackColor];
[self trackMouse:anEvent];
}
- (void)mouseEntered:(CPEvent)anEvent
{
if (![self isEnabled])
return;
[self setThemeState:CPThemeStateHovered];
}
- (void)mouseExited:(CPEvent)anEvent
{
var currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
isWithinFrame = [self tracksMouseOutsideOfFrame] || CGRectContainsPoint([self bounds], currentLocation);
// Make sure we're not still in the frame because Cappuccino will sent mouseExited events
// for all of the (ephemeral) subviews of a view as well.
if (!isWithinFrame)
[self unsetThemeState:CPThemeStateHovered];
}
/*!
Returns the receiver's object value
Returns the receiver's object value.
*/
- (id)objectValue
{
@@ -393,7 +438,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's object value
Sets the receiver's object value.
*/
- (void)setObjectValue:(id)anObject
{
@@ -404,7 +449,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's float value
Returns the receiver's float value.
*/
- (float)floatValue
{
@@ -413,7 +458,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Sets the receiver's float value
Sets the receiver's float value.
*/
- (void)setFloatValue:(float)aValue
{
@@ -421,7 +466,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's double value
Returns the receiver's double value.
*/
- (double)doubleValue
{
@@ -430,7 +475,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's double value
Sets the receiver's double value.
*/
- (void)setDoubleValue:(double)anObject
{
@@ -438,7 +483,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's int value
Returns the receiver's int value.
*/
- (int)intValue
{
@@ -447,7 +492,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's int value
Sets the receiver's int value.
*/
- (void)setIntValue:(int)anObject
{
@@ -455,7 +500,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's int value
Returns the receiver's int value.
*/
- (int)integerValue
{
@@ -464,7 +509,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's int value
Sets the receiver's int value.
*/
- (void)setIntegerValue:(int)anObject
{
@@ -472,7 +517,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's string value
Returns the receiver's string value.
*/
- (CPString)stringValue
{
@@ -480,7 +525,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's string value
Sets the receiver's string value.
*/
- (void)setStringValue:(CPString)anObject
{
@@ -556,96 +601,199 @@ var CPControlBlackColor = [CPColor blackColor];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
}
/*!
Sets the text alignment of the control.
<pre>
CPLeftTextAlignment
CPCenterTextAlignment
CPRightTextAlignment
CPJustifiedTextAlignment
CPNaturalTextAlignment
</pre>
*/
- (void)setAlignment:(CPTextAlignment)alignment
{
[self setValue:alignment forThemeAttribute:@"alignment"];
}
/*!
Returns the text alignment of the control.
*/
- (CPTextAlignment)alignment
{
return [self valueForThemeAttribute:@"alignment"];
}
/*!
Set the vertical text alignment of the control.
<pre>
CPTopVerticalTextAlignment
CPCenterVerticalTextAlignment
CPBottomVerticalTextAlignment
</pre>
*/
- (void)setVerticalAlignment:(CPTextVerticalAlignment)alignment
{
[self setValue:alignment forThemeAttribute:@"vertical-alignment"];
}
/*!
Returns the vertical text alignment of the receiver.
*/
- (CPTextVerticalAlignment)verticalAlignment
{
return [self valueForThemeAttribute:@"vertical-alignment"];
}
/*!
Sets the line break mode of the receiver.
<pre>
CPLineBreakByWordWrapping
CPLineBreakByCharWrapping
CPLineBreakByClipping
CPLineBreakByTruncatingHead
CPLineBreakByTruncatingTail
CPLineBreakByTruncatingMiddle
</pre>
*/
- (void)setLineBreakMode:(CPLineBreakMode)mode
{
[self setValue:mode forThemeAttribute:@"line-break-mode"];
}
/*!
Returns the line break mode of the control.
*/
- (CPLineBreakMode)lineBreakMode
{
return [self valueForThemeAttribute:@"line-break-mode"];
}
/*!
Sets the text color of the receiver.
@param aColor - A CPColor object.
*/
- (void)setTextColor:(CPColor)aColor
{
[self setValue:aColor forThemeAttribute:@"text-color"];
}
/*!
Returns the text color of the receiver.
*/
- (CPColor)textColor
{
return [self valueForThemeAttribute:@"text-color"];
}
/*!
Sets the shadow color of the text for the receiver.
*/
- (void)setTextShadowColor:(CPColor)aColor
{
[self setValue:aColor forThemeAttribute:@"text-shadow-color"];
}
/*!
Returns the shadow color of the text for the control.
*/
- (CPColor)textShadowColor
{
return [self valueForThemeAttribute:@"text-shadow-color"];
}
- (void)setTextShadowOffset:(float)offset
/*!
Sets the shadow offset for the text.
@param offset - a CGSize with the x and y offsets.
*/
- (void)setTextShadowOffset:(CGSize)offset
{
[self setValue:offset forThemeAttribute:@"text-shadow-offset"];
}
- (float)textShadowOffset
/*!
Returns the text shadow offset of the receiver.
*/
- (CGSize)textShadowOffset
{
return [self valueForThemeAttribute:@"text-shadow-offset"];
}
/*!
Sets the font of the control.
*/
- (void)setFont:(CPFont)aFont
{
[self setValue:aFont forThemeAttribute:@"font"];
}
/*!
Returns the font of the control.
*/
- (CPFont)font
{
return [self valueForThemeAttribute:@"font"];
}
/*!
Sets the image position of the control.
<pre>
CPNoImage
CPImageOnly
CPImageLeft
CPImageRight
CPImageBelow
CPImageAbove
CPImageOverlaps
</pre>
*/
- (void)setImagePosition:(CPCellImagePosition)position
{
[self setValue:position forThemeAttribute:@"image-position"];
}
/*!
Returns the image position of the receiver.
*/
- (CPCellImagePosition)imagePosition
{
return [self valueForThemeAttribute:@"image-position"];
}
/*!
Sets the image scaling of the control.
<pre>
CPScaleProportionally
CPScaleToFit
CPScaleNone
</pre>
*/
- (void)setImageScaling:(CPImageScaling)scaling
{
[self setValue:scaling forThemeAttribute:@"image-scaling"];
}
/*!
Returns the image scaling of the control.
*/
- (CPImageScaling)imageScaling
{
return [self valueForThemeAttribute:@"image-scaling"];
}
/*!
Sets the enabled status of the control.
Controls that are not enabled can not be used by the user and obtain the CPThemeStateDisabled theme state.
@param BOOL - YES if the control should be enabled, otherwise NO.
*/
- (void)setEnabled:(BOOL)isEnabled
{
if (isEnabled)
@@ -654,16 +802,29 @@ var CPControlBlackColor = [CPColor blackColor];
[self setThemeState:CPThemeStateDisabled];
}
/*!
Returns YES if the receiver is enabled, otherwise NO.
*/
- (BOOL)isEnabled
{
return ![self hasThemeState:CPThemeStateDisabled];
}
/*!
Highlights the receiver.
@param BOOL - YES if the receiver should be highlighted, otherwise NO.
*/
- (void)highlight:(BOOL)shouldHighlight
{
[self setHighlighted:shouldHighlight];
}
/*!
Highlights the receiver.
@param BOOL - YES if the receiver should be highlighted, otherwise NO.
*/
- (void)setHighlighted:(BOOL)isHighlighted
{
if (isHighlighted)
@@ -672,6 +833,9 @@ var CPControlBlackColor = [CPColor blackColor];
[self unsetThemeState:CPThemeStateHighlighted];
}
/*!
Returns YES if the control is highlighted, otherwise NO.
*/
- (BOOL)isHighlighted
{
return [self hasThemeState:CPThemeStateHighlighted];
@@ -695,6 +859,7 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
/*
Initializes the control by unarchiving it from a coder.
@param aCoder the coder from which to unarchive the control
@return the initialized control
*/
@@ -718,6 +883,7 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
/*
Archives the control to the provided coder.
@param aCoder the coder to which the control will be archived.
*/
- (void)encodeWithCoder:(CPCoder)aCoder
@@ -727,8 +893,10 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
if (_sendsActionOnEndEditing)
[aCoder encodeBool:_sendsActionOnEndEditing forKey:CPControlSendsActionOnEndEditingKey];
if (_value !== nil)
[aCoder encodeObject:_value forKey:CPControlValueKey];
var objectValue = [self objectValue];
if (objectValue !== nil)
[aCoder encodeObject:objectValue forKey:CPControlValueKey];
if (_target !== nil)
[aCoder encodeConditionalObject:_target forKey:CPControlTargetKey];
+2 -2
View File
@@ -88,7 +88,7 @@ var CPDocumentUntitledCount = 0;
@class CPDocument
CPDocument is used to represent a document/file in a Cappuccino application.
In a document-based application, generally multiple documents are open simutaneously
In a document-based application, generally multiple documents are open simultaneously
(multiple text documents, slide presentations, spreadsheets, etc.), and multiple
CPDocuments should be used to represent this.
*/
@@ -208,7 +208,7 @@ var CPDocumentUntitledCount = 0;
throws an exception.
@param aType the format of the data
@param anError not used
@throws CPUnsupportedMethodException if this method hasn't been overriden by the subclass
@throws CPUnsupportedMethodException if this method hasn't been overridden by the subclass
@return the document data
*/
- (CPData)dataOfType:(CPString)aType error:({CPError})anError
+6 -5
View File
@@ -24,7 +24,7 @@
@import <Foundation/CPBundle.j>
@import "CPDocument.j"
@import "CPOpenPanel.j";
@import "CPOpenPanel.j"
var CPSharedDocumentController = nil;
@@ -177,7 +177,7 @@ var CPSharedDocumentController = nil;
@param aType the document type
@param aDelegate the delegate to notify
@param aSelector the selector to notify with
@param aContextInfo the context infomration passed to the delegate
@param aContextInfo the context information passed to the delegate
*/
- (CPDocument)makeDocumentWithContentsOfURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aSelector contextInfo:(id)aContextInfo
{
@@ -390,13 +390,14 @@ var CPSharedDocumentController = nil;
- (void)noteNewRecentDocument:(CPDocument)aDocument
{
[self noteNewRecentDocumentURL:[[aDocument fileURL] absoluteString]];
[self noteNewRecentDocumentURL:[aDocument fileURL]];
}
- (void)noteNewRecentDocumentURL:(CPString)aURL
- (void)noteNewRecentDocumentURL:(CPURL)aURL
{
var urlAsString = [aURL isKindOfClass:CPString] ? aURL : [aURL absoluteString];
if (typeof window["cpNoteNewRecentDocumentPath"] === 'function')
window.cpNoteNewRecentDocumentPath(aURL);
window.cpNoteNewRecentDocumentPath(urlAsString);
[self _updateRecentDocumentsMenu];
}
+12 -12
View File
@@ -28,13 +28,13 @@
@import "CPWindow.j"
CPDragOperationNone = 0,
CPDragOperationCopy = 1 << 1,
CPDragOperationLink = 1 << 1,
CPDragOperationGeneric = 1 << 2,
CPDragOperationPrivate = 1 << 3,
CPDragOperationMove = 1 << 4,
CPDragOperationDelete = 1 << 5,
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])
@@ -220,14 +220,14 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
[_draggingUpdateTimer invalidate];
_draggingUpdateTimer = nil;
var dragOperation = CPDragOperationCopy;
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]];
draggingDestination = [aPlatformWindow _dragHitTest:aLocation pasteboard:[CPDragServerDraggingInfo draggingPasteboard]];
if (draggingDestination)
_draggingLocation = [DRAGGING_WINDOW(draggingDestination) convertPlatformWindowToBase:aLocation];
if(draggingDestination !== _draggingDestination)
if (draggingDestination !== _draggingDestination)
{
if ([_draggingDestination respondsToSelector:@selector(draggingExited:)])
[_draggingDestination draggingExited:CPDragServerDraggingInfo];
@@ -456,8 +456,8 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
}
else if (type === CPKeyDown)
{
var keyCode = [anEvent keyCode];
if (keyCode === CPEscapeKeyCode)
var characters = [anEvent characters];
if (characters === CPEscapeFunctionKey)
{
_dragOperation = CPDragOperationNone;
[self draggingEndedInPlatformWindow:platformWindow globalLocation:CGPointMakeZero() operation:_dragOperation];
+45 -32
View File
@@ -158,23 +158,24 @@ CPFindFunctionKey = "\uF745";
CPHelpFunctionKey = "\uF746";
CPModeSwitchFunctionKey = "\uF747";
CPEscapeFunctionKey = "\u001B";
CPSpaceFunctionKey = "\u0020";
CPDOMEventDoubleClick = "dblclick",
CPDOMEventMouseDown = "mousedown",
CPDOMEventMouseUp = "mouseup",
CPDOMEventMouseMoved = "mousemove",
CPDOMEventMouseDragged = "mousedrag",
CPDOMEventKeyUp = "keyup",
CPDOMEventKeyDown = "keydown",
CPDOMEventKeyPress = "keypress";
CPDOMEventCopy = "copy";
CPDOMEventPaste = "paste";
CPDOMEventScrollWheel = "mousewheel";
CPDOMEventTouchStart = "touchstart";
CPDOMEventTouchMove = "touchmove";
CPDOMEventTouchEnd = "touchend";
CPDOMEventTouchCancel = "touchcancel";
CPDOMEventDoubleClick = "dblclick";
CPDOMEventMouseDown = "mousedown";
CPDOMEventMouseUp = "mouseup";
CPDOMEventMouseMoved = "mousemove";
CPDOMEventMouseDragged = "mousedrag";
CPDOMEventKeyUp = "keyup";
CPDOMEventKeyDown = "keydown";
CPDOMEventKeyPress = "keypress";
CPDOMEventCopy = "copy";
CPDOMEventPaste = "paste";
CPDOMEventScrollWheel = "mousewheel";
CPDOMEventTouchStart = "touchstart";
CPDOMEventTouchMove = "touchmove";
CPDOMEventTouchEnd = "touchend";
CPDOMEventTouchCancel = "touchcancel";
var _CPEventPeriodicEventPeriod = 0,
_CPEventPeriodicEventTimer = nil,
@@ -210,6 +211,7 @@ 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 \c aWindowNumber
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
@@ -234,7 +236,8 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Creates a new mouse event
Creates a new mouse event.
@param anEventType the event type
@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
@@ -256,7 +259,8 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Creates a new custom event
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 \c aWindowNumber
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
@@ -348,10 +352,10 @@ var _CPEventPeriodicEventPeriod = 0,
/*!
Returns the location of the mouse (for mouse events).
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.
If the receiver 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 \c nil for non-mouse events.
*/
- (CGPoint)locationInWindow
@@ -371,7 +375,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns event information as a bit mask
Returns event information as a bit mask.
*/
- (unsigned)modifierFlags
{
@@ -379,7 +383,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns the time the event occurred
Returns the time the event occurred.
*/
- (CPTimeInterval)timestamp
{
@@ -395,7 +399,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns the event's associated window
Returns the event's associated window.
*/
- (CPWindow)window
{
@@ -426,7 +430,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns the number of clicks that caused this event. (mouse only)
Returns the number of clicks that caused this event (mouse only).
*/
- (int)clickCount
{
@@ -434,7 +438,8 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns the characters associated with this event (keyboard only)
Returns the characters associated with this event (keyboard only).
@throws CPInternalInconsistencyException if this method is called on a non-key event
*/
- (CPString)characters
@@ -444,6 +449,7 @@ var _CPEventPeriodicEventPeriod = 0,
/*!
Returns the character ignoring any modifiers (except shift).
@throws CPInternalInconsistencyException if this method is called on a non-key event
*/
- (CPString)charactersIgnoringModifiers
@@ -453,6 +459,7 @@ var _CPEventPeriodicEventPeriod = 0,
/*!
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
@@ -462,6 +469,7 @@ var _CPEventPeriodicEventPeriod = 0,
/*!
Returns the key's key code.
@throws CPInternalInconsistencyException if this method is called on a non-key event
*/
- (unsigned short)keyCode
@@ -494,7 +502,7 @@ var _CPEventPeriodicEventPeriod = 0,
return _DOMEvent;
}
// Getting Scroll Wheel Event Infomration
// Getting Scroll Wheel Event Information
/*!
Returns the change in the x-axis for a mouse event.
*/
@@ -527,7 +535,8 @@ var _CPEventPeriodicEventPeriod = 0,
if (_CPEventUpperCaseRegex.test(aKeyEquivalent))
aKeyEquivalentModifierMask |= CPShiftKeyMask;
if (CPBrowserIsOperatingSystem(CPWindowsOperatingSystem) && (aKeyEquivalentModifierMask & CPCommandKeyMask))
// Windows and Linux don't have command keys, so just switch it to ctrl.
if (!CPBrowserIsOperatingSystem(CPMacOperatingSystem) && (aKeyEquivalentModifierMask & CPCommandKeyMask))
{
aKeyEquivalentModifierMask |= CPControlKeyMask;
aKeyEquivalentModifierMask &= ~CPCommandKeyMask;
@@ -556,9 +565,9 @@ var _CPEventPeriodicEventPeriod = 0,
if (_modifierFlags & (CPCommandKeyMask | CPControlKeyMask))
return YES;
for(var i=0; i<characterCount; i++)
for (var i = 0; i < characterCount; i++)
{
switch(_characters.charAt(i))
switch (_characters.charAt(i))
{
case CPBackspaceCharacter:
case CPDeleteCharacter:
@@ -566,6 +575,7 @@ var _CPEventPeriodicEventPeriod = 0,
case CPTabCharacter:
case CPCarriageReturnCharacter:
case CPNewlineCharacter:
case CPSpaceFunctionKey:
case CPEscapeFunctionKey:
case CPPageUpFunctionKey:
case CPPageDownFunctionKey:
@@ -573,15 +583,18 @@ var _CPEventPeriodicEventPeriod = 0,
case CPUpArrowFunctionKey:
case CPRightArrowFunctionKey:
case CPDownArrowFunctionKey:
case CPEndFunctionKey:
case CPHomeFunctionKey:
return YES;
}
}
// FIXME: More cases? Space?
// FIXME: More cases?
return NO;
}
/*!
Gene rates periodic events every \c aPeriod 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
*/
@@ -594,7 +607,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Stops the periodic events from being generated
Stops the periodic events from being generated.
*/
+ (void)stopPeriodicEvents
{
+3 -3
View File
@@ -23,7 +23,7 @@
@import <Foundation/CPObject.j>
/*!
/*!
@ingroup appkit
@class CPFlashMovie
@@ -52,10 +52,10 @@
- (id)initWithFile:(CPString)aFilename
{
self = [super init];
if (self)
_filename = aFilename;
return self;
}
+21 -21
View File
@@ -32,10 +32,10 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
@implementation CPFlashView : CPView
{
CPFlashMovie _flashMovie;
CPDictionary _params;
CPDictionary _paramElements;
#if PLATFORM(DOM)
#if PLATFORM(DOM)
DOMElement _DOMParamElement;
DOMElement _DOMObjectElement;
DOMElement _DOMInnerObjectElement;
@@ -45,7 +45,7 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
#if PLATFORM(DOM)
@@ -58,24 +58,24 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
_DOMObjectElement.style.left = @"0px";
_DOMObjectElement.type = @"application/x-shockwave-flash";
_DOMObjectElement.setAttribute(@"classid", IEFlashCLSID);
_DOMParamElement = document.createElement(@"param");
_DOMParamElement.name = @"movie";
_DOMInnerObjectElement = document.createElement(@"object");
_DOMInnerObjectElement.width = @"100%";
_DOMInnerObjectElement.height = @"100%";
_DOMObjectElement.appendChild(_DOMParamElement);
_DOMObjectElement.appendChild(_DOMInnerObjectElement);
_DOMElement.appendChild(_DOMObjectElement);
}
else
[self _rebuildIEObjects];
#endif
}
return self;
}
@@ -83,7 +83,7 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
{
if (_flashMovie == aFlashMovie)
return;
_flashMovie = aFlashMovie;
#if PLATFORM(DOM)
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
@@ -105,14 +105,14 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
{
var varString = @"",
enumerator = [aDictionary keyEnumerator];
var key;
while (key = [enumerator nextObject])
varString = [varString stringByAppendingFormat:@"&%@=%@", key, [aDictionary objectForKey:key]];
if (!_params)
_params = [CPDictionary dictionary];
[_params setObject:varString forKey:@"flashvars"];
[self setParameters:_params];
}
@@ -129,7 +129,7 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
{
var elements = [_paramElements allValues],
count = [elements count];
for (var i = 0; i < count; i++)
_DOMObjectElement.removeChild([elements objectAtIndex:i]);
}
@@ -139,18 +139,18 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
_paramElements = [CPDictionary dictionary];
var enumerator = [_params keyEnumerator],
key;
while (key = [enumerator nextObject] && _DOMObjectElement)
{
var param = document.createElement(@"param");
param.name = key;
param.value = [_params objectForKey:key];
_DOMObjectElement.appendChild(param);
[_paramElements setObject:param forKey:key];
}
}
@@ -170,17 +170,17 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
_DOMElement.innerHTML = @"";
if (![_flashMovie filename])
return;
var paramString = [CPString stringWithFormat:@"<param name='movie' value='%@' />", [_flashMovie filename]],
paramEnumerator = [_params keyEnumerator],
key;
while (key = [paramEnumerator nextObject])
paramString = [paramString stringByAppendingFormat:@"<param name='%@' value='%@' />", key, [_params objectForKey:key]];
_DOMObjectElement = document.createElement(@"object");
_DOMElement.appendChild(_DOMObjectElement);
_DOMObjectElement.outerHTML = [CPString stringWithFormat:@"<object classid=%@ width=%@ height=%@>%@</object>", IEFlashCLSID, CGRectGetWidth([self bounds]), CGRectGetHeight([self bounds]), paramString];
}
#endif
+38 -32
View File
@@ -45,7 +45,7 @@ var CPSharedFontManager = nil,
{
if (!CPSharedFontManager)
CPSharedFontManager = [[CPFontManagerFactory alloc] init];
return CPSharedFontManager;
}
@@ -65,7 +65,7 @@ var CPSharedFontManager = nil,
- (CPArray)availableFonts
{
if (!_availableFonts)
{
{
_CPFontDetectSpan = document.createElement("span");
_CPFontDetectSpan.fontSize = "24px";
_CPFontDetectSpan.appendChild(document.createTextNode("mmmmmmmmmml"));
@@ -74,13 +74,14 @@ var CPSharedFontManager = nil,
div.style.top = "-1000px";
div.appendChild(_CPFontDetectSpan);
document.getElementsByTagName("body")[0].appendChild(div);
_CPFontDetectReferenceFonts = _CPFontDetectPickTwoDifferentFonts(["monospace", "serif", "sans-serif", "cursive"]);
_CPFontDetectReferenceFonts = _CPFontDetectPickTwoDifferentFonts(["monospace", "serif", "sans-serif", "cursive"]);
_availableFonts = [];
for (var i = 0; i < _CPFontDetectAllFonts.length; i++) {
for (var i = 0; i < _CPFontDetectAllFonts.length; i++)
{
var available = _CPFontDetectFontAvailable(_CPFontDetectAllFonts[i]);
if (available)
if (available)
_availableFonts.push(_CPFontDetectAllFonts[i]);
}
}
@@ -101,8 +102,8 @@ var CPSharedFontManager = nil,
var _CPFontDetectSpan,
_CPFontDetectReferenceFonts,
_CPFontDetectAllFonts = [
/* "04b_21","A Charming Font","Abadi MT Condensed","Abadi MT Condensed Extra Bold","Abadi MT Condensed Light","Academy Engraved LET","Agency FB","Alba","Alba Matter","Alba Super","Algerian",*/
"American Typewriter",
/* "04b_21","A Charming Font","Abadi MT Condensed","Abadi MT Condensed Extra Bold","Abadi MT Condensed Light","Academy Engraved LET","Agency FB","Alba","Alba Matter","Alba Super","Algerian",*/
"American Typewriter",
/* "Andale Mono","Andale Mono IPA","Andy", */
"Apple Chancery","Arial","Arial Black","Arial Narrow","Arial Rounded MT Bold","Arial Unicode MS",
/* "Avant Garde","Avantgarde","Baby Kruffy","Base 02","Baskerville","Baskerville Old Face","Bauhaus 93","Beesknees ITC","Bell MT","Berlin Sans FB","Berlin Sans FB Demi","Bernard MT Condensed","Bickley Script",*/
@@ -122,8 +123,8 @@ var _CPFontDetectSpan,
/* "GlooGun","Gloucester MT Extra Condensed","Goudy Old Style","Goudy Stout","Haettenschweiler","Harlow Solid Italic","Harrington",*/
"Helvetica","Helvetica Narrow","Helvetica Neue","Herculanum","High Tower Text","Highlight LET","Hoefler Text","Impact","Imprint MT Shadow",
/* "Informal Roman","Jenkins v2.0","John Handy LET","Jokerman","Jokerman LET","Jokewood","Juice ITC","Kabel Ult BT","Kartika","Kino MT","Kristen ITC","Kunstler Script","La Bamba LET", */
"Lucida","Lucida Bright","Lucida Calligraphy","Lucida Console","Lucida Fax","Lucida Grande","Lucida Handwriting","Lucida Sans","Lucida Sans Typewriter","Lucida Sans Unicode",
/* "Luxi Mono","Luxi Sans","Luxi Serif","MARKETPRO","MS Reference Sans Serif","MS Reference Serif","Magneto","Maiandra GD", */
"Lucida","Lucida Bright","Lucida Calligraphy","Lucida Console","Lucida Fax","Lucida Grande","Lucida Handwriting","Lucida Sans","Lucida Sans Typewriter","Lucida Sans Unicode",
/* "Luxi Mono","Luxi Sans","Luxi Serif","MARKETPRO","MS Reference Sans Serif","MS Reference Serif","Magneto","Maiandra GD", */
"Marker Felt",
/* "Matisse ITC","Matura MT Script Capitals","Mead Bold","Mekanik LET","Mercurius Script MT Bold", */
"Microsoft Sans Serif","Milano LET","Minion Web","MisterEarl BT","Mistral","Monaco","Monotype Corsiva","Monotype.com","New Century Schoolbook","New York","News Gothic MT",
@@ -136,39 +137,44 @@ var _CPFontDetectSpan,
"Zapfino"];
// Compare against the reference fonts. Return true if it produces a different size than at least one of them.
var _CPFontDetectFontAvailable = function(font) {
for (var i = 0; i < _CPFontDetectReferenceFonts.length; i++)
if (_CPFontDetectCompareFonts(_CPFontDetectReferenceFonts[i], font))
return true;
return false;
var _CPFontDetectFontAvailable = function(font)
{
for (var i = 0; i < _CPFontDetectReferenceFonts.length; i++)
if (_CPFontDetectCompareFonts(_CPFontDetectReferenceFonts[i], font))
return true;
return false;
}
var _CPFontDetectCache = {};
// Compares two given fonts. Returns true if they produce different sizes (i.e. fontA didn't fallback to fontB)
var _CPFontDetectCompareFonts = function(fontA, fontB) {
var _CPFontDetectCompareFonts = function(fontA, fontB)
{
var a;
if (_CPFontDetectCache[fontA]) {
if (_CPFontDetectCache[fontA])
a = _CPFontDetectCache[fontA];
} else {
_CPFontDetectSpan.style.fontFamily = '"' + fontA + '"';
else
{
_CPFontDetectSpan.style.fontFamily = '"' + fontA + '"';
_CPFontDetectCache[fontA] = a = { w: _CPFontDetectSpan.offsetWidth, h: _CPFontDetectSpan.offsetHeight };
}
_CPFontDetectSpan.style.fontFamily= '"' + fontB + '", "' + fontA + '"';
var bWidth = _CPFontDetectSpan.offsetWidth;
var bHeight = _CPFontDetectSpan.offsetHeight;
return (a.w != bWidth || a.h != bHeight);
_CPFontDetectSpan.style.fontFamily = '"' + fontB + '", "' + fontA + '"';
var bWidth = _CPFontDetectSpan.offsetWidth,
bHeight = _CPFontDetectSpan.offsetHeight;
return (a.w != bWidth || a.h != bHeight);
}
// Test the candidate fonts pairwise until we find two that are different. Otherwise return the first.
var _CPFontDetectPickTwoDifferentFonts = function(candidates) {
for (var i = 0; i < candidates.length; i++)
for (var j = 0; j < i; j++)
if (_CPFontDetectCompareFonts(candidates[i], candidates[j]))
return [candidates[i], candidates[j]];
return [candidates[0]];
var _CPFontDetectPickTwoDifferentFonts = function(candidates)
{
for (var i = 0; i < candidates.length; i++)
for (var j = 0; j < i; j++)
if (_CPFontDetectCompareFonts(candidates[i], candidates[j]))
return [candidates[i], candidates[j]];
return [candidates[0]];
}
[CPFontManager setFontManagerFactory:[CPFontManager class]];
+1 -1
View File
@@ -71,7 +71,7 @@ function CPPointMake(x, y)
function CPRectInset(aRect, dX, dY)
{
return CPRectMake( aRect.origin.x + dX, aRect.origin.y + dY,
aRect.size.width - 2 * dX, aRect.size.height - 2*dY);
aRect.size.width - 2 * dX, aRect.size.height - 2 * dY);
}
/*!
+3 -3
View File
@@ -25,7 +25,7 @@
@import "CGContext.j"
var CPGraphicsContextCurrent = nil;
var CPGraphicsContextCurrent = nil;
/*!
@ingroup appkit
@@ -71,10 +71,10 @@ var CPGraphicsContextCurrent = nil;
- (id)initWithGraphicsPort:(CPContext)aGraphicsPort
{
self = [super init];
if (self)
_graphicsPort = aGraphicsPort;
return self;
}
+2 -2
View File
@@ -65,7 +65,7 @@ function CPAppKitImage(aFilename, aSize)
return CPImageInBundle(aFilename, aSize, [CPBundle bundleForClass:[CPView class]]);
}
/*!
/*!
@ingroup appkit
@class CPImage
@@ -73,7 +73,7 @@ function CPAppKitImage(aFilename, aSize)
all image types supported by the browser.
@par Delegate Methods
@delegate -(void)imageDidLoad:(CPImage)image;
Called when the specified image has finished loading.
@param image the image that loaded
+45 -44
View File
@@ -43,7 +43,7 @@ CPImageAlignRight = 8;
var CPImageViewShadowBackgroundColor = nil,
CPImageViewEmptyPlaceholderImage = nil;
var LEFT_SHADOW_INSET = 3.0,
RIGHT_SHADOW_INSET = 3.0,
TOP_SHADOW_INSET = 3.0,
@@ -51,7 +51,7 @@ var LEFT_SHADOW_INSET = 3.0,
VERTICAL_SHADOW_INSET = TOP_SHADOW_INSET + BOTTOM_SHADOW_INSET,
HORIZONTAL_SHADOW_INSET = LEFT_SHADOW_INSET + RIGHT_SHADOW_INSET;
/*!
/*!
@ingroup appkit
@class CPImageView
@@ -60,7 +60,7 @@ var LEFT_SHADOW_INSET = 3.0,
@implementation CPImageView : CPControl
{
DOMElement _DOMImageElement;
BOOL _hasShadow;
CPView _shadowView;
@@ -73,14 +73,14 @@ var LEFT_SHADOW_INSET = 3.0,
+ (void)initialize
{
var bundle = [CPBundle bundleForClass:[CPView class]];
CPImageViewEmptyPlaceholderImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"empty.png"]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
#if PLATFORM(DOM)
@@ -96,11 +96,11 @@ var LEFT_SHADOW_INSET = 3.0,
}
CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement);
_DOMImageElement.style.visibility = "hidden";
#endif
}
return self;
}
@@ -121,29 +121,29 @@ var LEFT_SHADOW_INSET = 3.0,
- (void)setObjectValue:(CPImage)anImage
{
var oldImage = [self objectValue];
if (oldImage === anImage)
return;
[super setObjectValue:anImage];
var defaultCenter = [CPNotificationCenter defaultCenter];
if (oldImage)
[defaultCenter removeObserver:self name:CPImageDidLoadNotification object:oldImage];
var newImage = [self objectValue];
#if PLATFORM(DOM)
_DOMImageElement.src = newImage ? [newImage filename] : [CPImageViewEmptyPlaceholderImage filename];
#endif
var size = [newImage size];
if (size && size.width === -1 && size.height === -1)
{
[defaultCenter addObserver:self selector:@selector(imageDidLoad:) name:CPImageDidLoadNotification object:newImage];
#if PLATFORM(DOM)
_DOMImageElement.width = 0;
_DOMImageElement.height = 0;
@@ -162,7 +162,7 @@ var LEFT_SHADOW_INSET = 3.0,
- (void)imageDidLoad:(CPNotification)aNotification
{
[self hideOrDisplayContents];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -184,25 +184,25 @@ var LEFT_SHADOW_INSET = 3.0,
{
if (_hasShadow == shouldHaveShadow)
return;
_hasShadow = shouldHaveShadow;
if (_hasShadow)
{
_shadowView = [[CPShadowView alloc] initWithFrame:[self bounds]];
[self addSubview:_shadowView];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
else
{
[_shadowView removeFromSuperview];
_shadowView = nil;
}
[self hideOrDisplayContents];
}
@@ -215,12 +215,12 @@ var LEFT_SHADOW_INSET = 3.0,
{
if (_imageAlignment == anImageAlignment)
return;
_imageAlignment = anImageAlignment;
if (![self image])
return;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -238,14 +238,14 @@ var LEFT_SHADOW_INSET = 3.0,
- (void)setImageScaling:(CPImageScaling)anImageScaling
{
[super setImageScaling:anImageScaling];
#if PLATFORM(DOM)
if ([self currentValueForThemeAttribute:@"image-scaling"] === CPScaleToFit)
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, 0.0, 0.0);
}
#endif
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -314,7 +314,7 @@ var LEFT_SHADOW_INSET = 3.0,
else
{
var size = [image size];
if (size.width == -1 && size.height == -1)
return;
@@ -331,7 +331,7 @@ var LEFT_SHADOW_INSET = 3.0,
{
var imageRatio = size.width / size.height,
viewRatio = width / height;
if (viewRatio > imageRatio)
width = height * imageRatio;
else
@@ -348,7 +348,7 @@ var LEFT_SHADOW_INSET = 3.0,
width = size.width;
height = size.height;
}
if (imageScaling == CPScaleNone)
{
#if PLATFORM(DOM)
@@ -357,8 +357,9 @@ var LEFT_SHADOW_INSET = 3.0,
#endif
}
var x, y;
var x,
y;
switch (_imageAlignment)
{
case CPImageAlignLeft:
@@ -366,7 +367,7 @@ var LEFT_SHADOW_INSET = 3.0,
case CPImageAlignBottomLeft:
x = 0.0;
break;
case CPImageAlignRight:
case CPImageAlignTopRight:
case CPImageAlignBottomRight:
@@ -377,7 +378,7 @@ var LEFT_SHADOW_INSET = 3.0,
x = (boundsWidth - width) / 2.0;
break;
}
switch (_imageAlignment)
{
case CPImageAlignTop:
@@ -385,7 +386,7 @@ var LEFT_SHADOW_INSET = 3.0,
case CPImageAlignTopRight:
y = 0.0;
break;
case CPImageAlignBottom:
case CPImageAlignBottomLeft:
case CPImageAlignBottomRight:
@@ -395,7 +396,7 @@ var LEFT_SHADOW_INSET = 3.0,
default:
y = (boundsHeight - height) / 2.0;
break;
}
}
#if PLATFORM(DOM)
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, x, y);
@@ -403,7 +404,7 @@ var LEFT_SHADOW_INSET = 3.0,
}
_imageRect = _CGRectMake(x, y, width, height);
if (_hasShadow)
[_shadowView setFrame:_CGRectMake(x - LEFT_SHADOW_INSET, y - TOP_SHADOW_INSET, width + insetWidth, height + insetHeight)];
}
@@ -450,7 +451,7 @@ var LEFT_SHADOW_INSET = 3.0,
[self setImage:images[0]];
[self sendAction:[self action] to:[self target]];
}
return YES;
}
@@ -485,7 +486,7 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
#endif
self = [super initWithCoder:aCoder];
if (self)
{
#if PLATFORM(DOM)
@@ -494,14 +495,14 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
[self setImageAlignment:[aCoder decodeIntForKey:CPImageViewImageAlignmentKey]];
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey] || NO)
[self setEditable:YES];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
return self;
}
@@ -512,21 +513,21 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
// We do this in order to avoid encoding the _shadowView, which
// We do this in order to avoid encoding the _shadowView, which
// should just automatically be created programmatically as needed.
if (_shadowView)
{
var actualSubviews = _subviews;
_subviews = [_subviews copy];
[_subviews removeObjectIdenticalTo:_shadowView];
}
[super encodeWithCoder:aCoder];
if (_shadowView)
_subviews = actualSubviews;
[aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
[aCoder encodeInt:_imageAlignment forKey:CPImageViewImageAlignmentKey];
+79 -77
View File
@@ -35,7 +35,7 @@ var exposedBindingsMap = [CPDictionary new],
var CPBindingOperationAnd = 0,
CPBindingOperationOr = 1;
@implementation CPKeyValueBinding : CPObject
@implementation CPBinder : CPObject
{
CPDictionary _info;
id _source;
@@ -43,12 +43,12 @@ var CPBindingOperationAnd = 0,
+ (void)exposeBinding:(CPString)aBinding forClass:(Class)aClass
{
var bindings = [exposedBindingsMap objectForKey:[aClass hash]];
var bindings = [exposedBindingsMap objectForKey:[aClass UID]];
if (!bindings)
{
bindings = [];
[exposedBindingsMap setObject:bindings forKey:[aClass hash]];
[exposedBindingsMap setObject:bindings forKey:[aClass UID]];
}
bindings.push(aBinding);
@@ -56,12 +56,12 @@ var CPBindingOperationAnd = 0,
+ (CPArray)exposedBindingsForClass:(Class)aClass
{
return [[exposedBindingsMap objectForKey:[aClass hash]] copy];
return [[exposedBindingsMap objectForKey:[aClass UID]] copy];
}
+ (CPKeyValueBinding)getBinding:(CPString)aBinding forObject:(id)anObject
+ (CPBinder)getBinding:(CPString)aBinding forObject:(id)anObject
{
return [[bindingsMap objectForKey:[anObject hash]] objectForKey:aBinding];
return [[bindingsMap objectForKey:[anObject UID]] objectForKey:aBinding];
}
+ (CPDictionary)infoForBinding:(CPString)aBinding forObject:(id)anObject
@@ -76,12 +76,12 @@ var CPBindingOperationAnd = 0,
+ (CPDictionary)allBindingsForObject:(id)anObject
{
return [bindingsMap objectForKey:[anObject hash]];
return [bindingsMap objectForKey:[anObject UID]];
}
+ (void)unbind:(CPString)aBinding forObject:(id)anObject
{
var bindings = [bindingsMap objectForKey:[anObject hash]];
var bindings = [bindingsMap objectForKey:[anObject UID]];
if (!bindings)
return;
@@ -101,7 +101,7 @@ var CPBindingOperationAnd = 0,
+ (void)unbindAllForObject:(id)anObject
{
var bindings = [bindingsMap objectForKey:[anObject hash]];
var bindings = [bindingsMap objectForKey:[anObject UID]];
if (!bindings)
return;
@@ -111,7 +111,7 @@ var CPBindingOperationAnd = 0,
while (count--)
[anObject unbind:[bindings objectForKey:allKeys[count]]];
[bindingsMap removeObjectForKey:[anObject hash]];
[bindingsMap removeObjectForKey:[anObject UID]];
}
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
@@ -128,11 +128,11 @@ var CPBindingOperationAnd = 0,
[aDestination addObserver:self forKeyPath:aKeyPath options:CPKeyValueObservingOptionNew context:aBinding];
var bindings = [bindingsMap objectForKey:[_source hash]];
var bindings = [bindingsMap objectForKey:[_source UID]];
if (!bindings)
{
bindings = [CPDictionary new];
[bindingsMap setObject:bindings forKey:[_source hash]];
[bindingsMap setObject:bindings forKey:[_source UID]];
}
[bindings setObject:self forKey:aName];
@@ -147,39 +147,10 @@ var CPBindingOperationAnd = 0,
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
if (isPlaceholder)
{
switch (newValue)
{
case CPMultipleValuesMarker:
newValue = [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || @"Multiple Values";
break;
case CPNoSelectionMarker:
newValue = [options objectForKey:CPNoSelectionPlaceholderBindingOption] || @"No Selection";
break;
case CPNotApplicableMarker:
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
[CPException raise:CPGenericException reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
newValue = [options objectForKey:CPNotApplicablePlaceholderBindingOption] || @"Not Applicable";
break;
}
}
else
{
// Only transform the value if the current value is not a placeholder
newValue = [self transformValue:newValue withOptions:options];
}
newValue = [destination valueForKeyPath:keyPath];
newValue = [self transformValue:newValue withOptions:options];
[_source setValue:newValue forKey:aBinding];
if ([_source respondsToSelector:@selector(_setCurrentValueIsPlaceholder:)])
[_source _setCurrentValueIsPlaceholder:isPlaceholder];
}
- (void)reverseSetValueFor:(CPString)aBinding
@@ -231,7 +202,7 @@ var CPBindingOperationAnd = 0,
aValue = [valueTransformer transformedValue:aValue];
if (aValue === undefined || aValue === nil)
if (aValue === undefined || aValue === nil || aValue === [CPNull null])
aValue = [options objectForKey:CPNullPlaceholderBindingOption] || nil;
return aValue;
@@ -259,7 +230,13 @@ var CPBindingOperationAnd = 0,
+ (void)exposeBinding:(CPString)aBinding
{
[CPKeyValueBinding exposeBinding:aBinding forClass:[self class]];
[CPBinder exposeBinding:aBinding forClass:[self class]];
}
+ (Class)_binderClassForBinding:(CPString)theBinding
{
return [CPBinder class];
}
- (CPArray)exposedBindings
@@ -269,7 +246,7 @@ var CPBindingOperationAnd = 0,
while (theClass)
{
var temp = [CPKeyValueBinding exposedBindingsForClass:theClass];
var temp = [CPBinder exposedBindingsForClass:theClass];
if (temp)
[exposedBindings addObjectsFromArray:temp];
@@ -293,18 +270,21 @@ var CPBindingOperationAnd = 0,
//if (![[self exposedBindings] containsObject:aBinding])
// CPLog.warn("No binding exposed on "+self+" for "+aBinding);
var binderClass = [[self class] _binderClassForBinding:aBinding];
[self unbind:aBinding];
[[CPKeyValueBinding alloc] initWithBinding:[self _replacementKeyPathForBinding:aBinding] name:aBinding to:anObject keyPath:aKeyPath options:options from:self];
[[binderClass alloc] initWithBinding:[self _replacementKeyPathForBinding:aBinding] name:aBinding to:anObject keyPath:aKeyPath options:options from:self];
}
- (CPDictionary)infoForBinding:(CPString)aBinding
{
return [CPKeyValueBinding infoForBinding:aBinding forObject:self];
return [CPBinder infoForBinding:aBinding forObject:self];
}
- (void)unbind:(CPString)aBinding
{
[CPKeyValueBinding unbind:aBinding forObject:self];
var binderClass = [[self class] _binderClassForBinding:aBinding];
[binderClass unbind:aBinding forObject:self];
}
- (id)_replacementKeyPathForBinding:(CPString)binding
@@ -314,13 +294,35 @@ var CPBindingOperationAnd = 0,
@end
@implementation _CPKeyValueOrBinding : CPKeyValueBinding
/*!
@ignore
Provides stub implementations that simply call super for the "objectValue" binding
This class should not be necessary but assures backwards compliance with our old way of doing bindings
Every class with a value binding should implement a subclass to handle it's specific value binding logic
*/
@implementation _CPValueBinder : CPBinder
{
}
- (void)setValueFor:(CPString)theBinding
{
[super setValueFor:@"objectValue"];
}
- (void)reverseSetValueFor:(CPString)theBinding
{
[super reverseSetValueFor:@"objectValue"];
}
@end
@implementation _CPKeyValueOrBinding : CPBinder
{
}
- (void)setValueFor:(CPString)aBinding
{
var bindings = [bindingsMap valueForKey:[_source hash]];
var bindings = [bindingsMap valueForKey:[_source UID]];
if (!bindings)
return;
@@ -335,13 +337,13 @@ var CPBindingOperationAnd = 0,
@end
@implementation _CPKeyValueAndBinding : CPKeyValueBinding
@implementation _CPKeyValueAndBinding : CPBinder
{
}
- (void)setValueFor:(CPString)aBinding
{
var bindings = [bindingsMap objectForKey:[_source hash]];
var bindings = [bindingsMap objectForKey:[_source UID]];
if (!bindings)
return;
@@ -441,30 +443,30 @@ CPToolTipBinding = @"CPToolTipBinding";
CPValueBinding = @"value";
//Binding options constants
CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelectionBindingOption";
CPAllowsNullArgumentBindingOption = @"CPAllowsNullArgumentBindingOption";
CPConditionallySetsEditableBindingOption = @"CPConditionallySetsEditableBindingOption";
CPConditionallySetsEnabledBindingOption = @"CPConditionallySetsEnabledBindingOption";
CPConditionallySetsHiddenBindingOption = @"CPConditionallySetsHiddenBindingOption";
CPContinuouslyUpdatesValueBindingOption = @"CPContinuouslyUpdatesValueBindingOption";
CPCreatesSortDescriptorBindingOption = @"CPCreatesSortDescriptorBindingOption";
CPDeletesObjectsOnRemoveBindingsOption = @"CPDeletesObjectsOnRemoveBindingsOption";
CPDisplayNameBindingOption = @"CPDisplayNameBindingOption";
CPDisplayPatternBindingOption = @"CPDisplayPatternBindingOption";
CPHandlesContentAsCompoundValueBindingOption = @"CPHandlesContentAsCompoundValueBindingOption";
CPInsertsNullPlaceholderBindingOption = @"CPInsertsNullPlaceholderBindingOption";
CPInvokesSeparatelyWithArrayObjectsBindingOption = @"CPInvokesSeparatelyWithArrayObjectsBindingOption";
CPMultipleValuesPlaceholderBindingOption = @"CPMultipleValuesPlaceholderBindingOption";
CPNoSelectionPlaceholderBindingOption = @"CPNoSelectionPlaceholderBindingOption";
CPNotApplicablePlaceholderBindingOption = @"CPNotApplicablePlaceholderBindingOption";
CPNullPlaceholderBindingOption = @"CPNullPlaceholderBindingOption";
CPPredicateFormatBindingOption = @"CPPredicateFormatBindingOption";
CPRaisesForNotApplicableKeysBindingOption = @"CPRaisesForNotApplicableKeysBindingOption";
CPSelectorNameBindingOption = @"CPSelectorNameBindingOption";
CPSelectsAllWhenSettingContentBindingOption = @"CPSelectsAllWhenSettingContentBindingOption";
CPValidatesImmediatelyBindingOption = @"CPValidatesImmediatelyBindingOption";
CPValueTransformerNameBindingOption = @"CPValueTransformerNameBindingOption";
CPValueTransformerBindingOption = @"CPValueTransformerBindingOption";
CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelection";
CPAllowsNullArgumentBindingOption = @"CPAllowsNullArgument";
CPConditionallySetsEditableBindingOption = @"CPConditionallySetsEditable";
CPConditionallySetsEnabledBindingOption = @"CPConditionallySetsEnabled";
CPConditionallySetsHiddenBindingOption = @"CPConditionallySetsHidden";
CPContinuouslyUpdatesValueBindingOption = @"CPContinuouslyUpdatesValue";
CPCreatesSortDescriptorBindingOption = @"CPCreatesSortDescriptor";
CPDeletesObjectsOnRemoveBindingsOption = @"CPDeletesObjectsOnRemove";
CPDisplayNameBindingOption = @"CPDisplayName";
CPDisplayPatternBindingOption = @"CPDisplayPattern";
CPHandlesContentAsCompoundValueBindingOption = @"CPHandlesContentAsCompoundValue";
CPInsertsNullPlaceholderBindingOption = @"CPInsertsNullPlaceholder";
CPInvokesSeparatelyWithArrayObjectsBindingOption = @"CPInvokesSeparatelyWithArrayObjects";
CPMultipleValuesPlaceholderBindingOption = @"CPMultipleValuesPlaceholder";
CPNoSelectionPlaceholderBindingOption = @"CPNoSelectionPlaceholder";
CPNotApplicablePlaceholderBindingOption = @"CPNotApplicablePlaceholder";
CPNullPlaceholderBindingOption = @"CPNullPlaceholder";
CPPredicateFormatBindingOption = @"CPPredicateFormat";
CPRaisesForNotApplicableKeysBindingOption = @"CPRaisesForNotApplicableKeys";
CPSelectorNameBindingOption = @"CPSelectorName";
CPSelectsAllWhenSettingContentBindingOption = @"CPSelectsAllWhenSettingContent";
CPValidatesImmediatelyBindingOption = @"CPValidatesImmediately";
CPValueTransformerNameBindingOption = @"CPValueTransformerName";
CPValueTransformerBindingOption = @"CPValueTransformer";
CPIsControllerMarker = function(/*id*/anObject)
{
+65 -29
View File
@@ -52,7 +52,7 @@ var _CPMenuBarVisible = NO,
@class CPMenu
Menus provide the user with a list of actions and/or submenus. Submenus themselves are full fledged menus
and so a heirarchical structure appears.
and so a hierarchical structure appears.
*/
@implementation CPMenu : CPObject
{
@@ -80,6 +80,9 @@ var _CPMenuBarVisible = NO,
+ (void)initialize
{
if (self !== CPMenu)
return;
[[self class] setMenuBarAttributes:[CPDictionary dictionary]];
}
@@ -274,22 +277,7 @@ var _CPMenuBarVisible = NO,
*/
- (void)insertItem:(CPMenuItem)aMenuItem atIndex:(unsigned)anIndex
{
var menu = [aMenuItem menu];
if (menu)
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];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidAddItemNotification
object:self
userInfo:[CPDictionary dictionaryWithObject:anIndex forKey:@"CPMenuItemIndex"]];
[self insertObject:aMenuItem inItemsAtIndex:anIndex];
}
/*!
@@ -346,16 +334,7 @@ var _CPMenuBarVisible = NO,
*/
- (void)removeItemAtIndex:(unsigned)anIndex
{
if (anIndex < 0 || anIndex >= _items.length)
return;
[_items[anIndex] setMenu:nil];
[_items removeObjectAtIndex:anIndex];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidRemoveItemNotification
object:self
userInfo:[CPDictionary dictionaryWithObject:anIndex forKey:@"CPMenuItemIndex"]];
[self removeObjectFromItemsAtIndex:anIndex];
}
/*!
@@ -364,9 +343,11 @@ var _CPMenuBarVisible = NO,
*/
- (void)itemChanged:(CPMenuItem)aMenuItem
{
if ([aMenuItem menu] != self)
if ([aMenuItem menu] !== self)
return;
[aMenuItem setValue:[aMenuItem valueForKey:@"changeCount"] + 1 forKey:@"changeCount"];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidChangeItemNotification
object:self
@@ -692,7 +673,7 @@ var _CPMenuBarVisible = NO,
var delegate = [self delegate];
if ([delegate respondsToSelector:@selector(menuWillOpen:)])
[delegate menuWillOpen:aMenu];
[delegate menuWillOpen:self];
// Convert location to global coordinates if not already in them.
if (aView)
@@ -1035,6 +1016,61 @@ var _CPMenuBarVisible = NO,
@end
@implementation CPMenu (CPKeyValueCoding)
- (CPUInteger)countOfItems
{
return [_items count];
}
- (CPMenuItem)objectInItemsAtIndex:(CPUInteger)anIndex
{
return [_items objectAtIndex:anIndex];
}
- (CPArray)itemsAtIndexes:(CPIndexSet)indexes
{
return [_items objectsAtIndexes:indexes];
}
@end
@implementation CPMenu (CPKeyValueObserving)
- (void)insertObject:(CPMenuItem)aMenuItem inItemsAtIndex:(CPUInteger)anIndex
{
var menu = [aMenuItem menu];
if (menu)
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];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidAddItemNotification
object:self
userInfo:[CPDictionary dictionaryWithObject:anIndex forKey:@"CPMenuItemIndex"]];
}
- (void)removeObjectFromItemsAtIndex:(CPUInteger)anIndex
{
if (anIndex < 0 || anIndex >= [_items count])
return;
[[_items objectAtIndex:anIndex] setMenu:nil];
[_items removeObjectAtIndex:anIndex];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidRemoveItemNotification
object:self
userInfo:[CPDictionary dictionaryWithObject:anIndex forKey:@"CPMenuItemIndex"]];
}
@end
var CPMenuTitleKey = @"CPMenuTitleKey",
CPMenuNameKey = @"CPMenuNameKey",
+13 -8
View File
@@ -77,6 +77,8 @@
id _representedObject;
CPView _view;
int _changeCount;
_CPMenuItemView _menuItemView;
}
@@ -98,12 +100,14 @@
if (self)
{
_changeCount = 0;
_isSeparator = NO;
_title = aTitle;
_action = anAction;
_isEnabled = YES;
_isHidden = NO;
_tag = 0;
_state = CPOffState;
@@ -445,7 +449,7 @@ CPOffState
return _mixedStateImage;
}
// Managing Subemenus
// Managing Submenus
/*!
Sets the submenu for this item
@param aMenu the submenu
@@ -459,7 +463,7 @@ CPOffState
if (supermenu)
[CPException raise:CPInvalidArgumentException
reason: @"Can't add submenu \"" + [aMenu title] + "\" to item \"" + [self title] + "\", because it is already submenu of \"" + [[aMenu supermenu] title] + "\""];
reason: @"Can't add submenu \"" + [aMenu title] + "\" to item \"" + [self title] + "\", because it is already submenu of \"" + [[aMenu supermenu] title] + "\""];
_submenu = aMenu;
@@ -592,7 +596,7 @@ CPControlKeyMask
return @"";
var string = _keyEquivalent.toUpperCase(),
needsShift = _keyEquivalentModifierMask & CPShiftKeyMask ||
needsShift = _keyEquivalentModifierMask & CPShiftKeyMask ||
(string === _keyEquivalent && _keyEquivalent.toLowerCase() !== _keyEquivalent.toUpperCase());
if (CPBrowserIsOperatingSystem(CPMacOperatingSystem))
@@ -644,7 +648,7 @@ CPControlKeyMask
}
/*!
Sets the title of the menu item and the mnemonic character. The mnemonic chracter should be preceded by an '&'.
Sets the title of the menu item and the mnemonic character. The mnemonic character should be preceded by an '&'.
@param aTitle the title string with a denoted mnemonic
*/
- (void)setTitleWithMnemonicLocation:(CPString)aTitle
@@ -791,12 +795,12 @@ CPControlKeyMask
- (id)copy
{
var item = [[CPMenuItem alloc] init];
// No point in going through accessors and doing lots of unnecessary state checking/updating
item._isSeparator = _isSeparator;
[item setTitle:_title];
[item setFont:_font];
[item setFont:_font];
[item setTarget:_target];
[item setAction:_action];
[item setEnabled:_isEnabled];
@@ -815,7 +819,7 @@ CPControlKeyMask
[item setIndentationLevel:_indentationLevel];
[item setToolTip:_toolTip];
[item setRepresentedObject:_representedObject];
return item;
}
@@ -890,6 +894,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
if (self)
{
_changeCount = 0;
_isSeparator = [aCoder containsValueForKey:CPMenuItemIsSeparatorKey] && [aCoder decodeBoolForKey:CPMenuItemIsSeparatorKey];
_title = [aCoder decodeObjectForKey:CPMenuItemTitleKey];
-1
View File
@@ -34,7 +34,6 @@ var _CPMenuItemSelectionColor = nil,
BOOL _isDirty;
BOOL _showsStateColumn;
CPImageView _stateView;
_CPImageAndTextView _imageAndTextView;
CPView _submenuView;
}
+197 -64
View File
@@ -4,13 +4,23 @@
@import "CPController.j"
/*!
@class
CPObjectController is a bindings-compatible controller class.
Properties of the content object of an object of this class can be bound to user interface elements to change and access their values.
The content of an CPObjectController instance is an CPMutableDictionary object by default.
This allows a single CPObjectController instance to be used to manage several properties accessed by key value paths.
The default content object class can be changed by calling setObjectClass:, which a subclass must override.
*/
@implementation CPObjectController : CPController
{
id _contentObject;
id _selection;
Class _objectClass;
CPString _objectClassName;
BOOL _isEditable;
BOOL _automaticallyPreparesContent;
@@ -52,11 +62,20 @@
return [CPSet setWithObjects:"editable", "selection"];
}
/*!
@ignore
*/
- (id)init
{
return [self initWithContent:nil];
}
/*!
Inits and returns a CPObjectController object with the given content.
@param id aContent - The object the controller will use.
@return id the CPObjectConroller instance.
*/
- (id)initWithContent:(id)aContent
{
if (self = [super init])
@@ -71,11 +90,19 @@
return self;
}
/*!
Returns the controller's content object.
@return id - The content object of the controller.
*/
- (id)content
{
return _contentObject;
}
/*!
Sets the content object for the controller.
@param id aContent - The new content object for the controller.
*/
- (void)setContent:(id)aContent
{
[self willChangeValueForKey:@"contentObject"];
@@ -87,109 +114,193 @@
[self _selectionDidChange];
}
/*!
@ignore
*/
- (void)_setContentObject:(id)aContent
{
[self setContent:aContent];
}
/*!
@ignore
*/
- (id)_contentObject
{
return [self content];
}
/*!
Sets whether the controller automatically creates and inserts new content objects automatically when loading from a cib file.
If you pass YES and the controller uses prepareContent to create the content object.
The default is NO.
@param BOOL shouldAutomaticallyPrepareContent - YES if the content should be prepared, otherwise NO.
*/
- (void)setAutomaticallyPreparesContent:(BOOL)shouldAutomaticallyPrepareContent
{
_automaticallyPreparesContent = shouldAutomaticallyPrepareContent;
}
/*!
Returns if the controller prepares the content automatically.
@return BOOL - YES if the content is prepared, otherwise NO.
*/
- (BOOL)automaticallyPreparesContent
{
return _automaticallyPreparesContent;
}
/*!
Overridden by a subclass that require control over the creation of new objects.
*/
- (void)prepareContent
{
[self setContent:[self newObject]];
}
/*!
Sets the object class when creating new objects.
@param Class - the class of new objects that will be created.
*/
- (void)setObjectClass:(Class)aClass
{
_objectClass = aClass;
}
/*!
Returns the class of what new objects will be when they are created.
@return Class - The class of new objects.
*/
- (Class)objectClass
{
return _objectClass;
}
- (id)newObject
/*!
@ignore
*/
- (id)_defaultNewObject
{
return [[[self objectClass] alloc] init];
}
/*!
Creates and returns a new object of the appropriate class.
@return id - The object created.
*/
- (id)newObject
{
return [self _defaultNewObject];
}
/*!
Sets the controller's content object.
@param id anObject - The object to set for the controller.
*/
- (void)addObject:(id)anObject
{
[self setContent:anObject];
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
var binderClass = [[self class] _binderClassForBinding:@"contentObject"];
[[binderClass getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
}
/*!
Removes a given object from the controller.
@param id anObject - The object to remove from the receiver.
*/
- (void)removeObject:(id)anObject
{
if ([self content] === anObject)
[self setContent:nil];
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
var binderClass = [[self class] _binderClassForBinding:@"contentObject"];
[[binderClass getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
}
/*!
Creates and adds a sets the object as the controller's content.
@param id aSender - The sender of the message.
*/
- (void)add:(id)aSender
{
// FIXME: This should happen on the next run loop?
[self addObject:[self newObject]];
}
/*!
@return BOOL - YES if you can added to the controller using add:
*/
- (BOOL)canAdd
{
return [self isEditable];
}
/*!
Removes the content object from the controller.
@param id aSender - The sender of the message.
*/
- (void)remove:(id)aSender
{
// FIXME: This should happen on the next run loop?
[self removeObject:[self content]];
}
/*!
@return BOOL - Returns YES if you can remove the controller's content using remove:
*/
- (BOOL)canRemove
{
return [self isEditable] && [[self selectedObjects] count];
}
/*!
Sets whether the controller allows for the editing of the content.
@param BOOL shouldBeEditable - YES if the content should be editable, otherwise NO.
*/
- (void)setEditable:(BOOL)shouldBeEditable
{
_isEditable = shouldBeEditable;
}
/*!
@return BOOL - Returns YES if the content of the controller is editable, otherwise NO.
*/
- (BOOL)isEditable
{
return _isEditable;
}
/*!
@return CPArray - Returns an array of all objects to be affected by editing.
*/
- (CPArray)selectedObjects
{
return [[_CPObservableArray alloc] initWithObjects:[_contentObject] count:1];
return [[_CPObservableArray alloc] initWithArray:[_contentObject]];
}
/*!
Returns a proxy object representing the controller's selection.
*/
- (id)selection
{
return _selection;
}
/*!
@ignore
*/
- (void)_selectionWillChange
{
[_selection controllerWillChange];
[self willChangeValueForKey:@"selection"];
}
/*!
@ignore
*/
- (void)_selectionDidChange
{
if (_selection === undefined || _selection === nil)
@@ -199,6 +310,9 @@
[self didChangeValueForKey:@"selection"];
}
/*!
@return id - Returns the keys which are being observed.
*/
- (id)observedKeys
{
return _observedKeys;
@@ -218,7 +332,8 @@
@end
var CPObjectControllerObjectClassNameKey = @"CPObjectControllerObjectClassNameKey",
var CPObjectControllerContentKey = @"CPObjectControllerContentKey",
CPObjectControllerObjectClassNameKey = @"CPObjectControllerObjectClassNameKey",
CPObjectControllerIsEditableKey = @"CPObjectControllerIsEditableKey",
CPObjectControllerAutomaticallyPreparesContentKey = @"CPObjectControllerAutomaticallyPreparesContentKey";
@@ -233,11 +348,10 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
var objectClassName = [aCoder decodeObjectForKey:CPObjectControllerObjectClassNameKey],
objectClass = CPClassFromString(objectClassName);
// FIXME: Error if objectClass === nil
[self setObjectClass:objectClass];
[self setObjectClass:objectClass || [CPMutableDictionary class]];
[self setEditable:[aCoder decodeBoolForKey:CPObjectControllerIsEditableKey]];
[self setAutomaticallyPreparesContent:[aCoder decodeBoolForKey:CPObjectControllerAutomaticallyPreparesContentKey] || NO];
[self setContent:[aCoder decodeObjectForKey:CPObjectControllerContentKey]];
_observedKeys = [[CPCountedSet alloc] init];
}
@@ -247,11 +361,15 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:CPStringFromClass(objectClass) forKey:CPObjectControllerObjectClassNameKey];
[aCoder encodeObject:[self isEditable] forKey:CPObjectControllerIsEditableKey];
[aCoder encodeObject:[self content] forKey:CPObjectControllerContentKey];
if (![self automaticallyPreparesContent])
[aCoder encodeBOOL:YES forKey:CPObjectControllerAutomaticallyPreparesContentKey];
if (_objectClass)
[aCoder encodeObject:CPStringFromClass(_objectClass) forKey:CPObjectControllerObjectClassNameKey];
else if (_objectClassName)
[aCoder encodeObject:_objectClassName forKey:CPObjectControllerObjectClassNameKey];
[aCoder encodeBool:[self isEditable] forKey:CPObjectControllerIsEditableKey];
[aCoder encodeBool:[self automaticallyPreparesContent] forKey:CPObjectControllerAutomaticallyPreparesContentKey];
}
@end
@@ -270,7 +388,7 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
- (id)initWithKeyPath:(id)aKeyPath observer:(id)anObserver object:(id)anObject
{
if (self=[super init])
if (self = [super init])
{
_keyPath = aKeyPath;
_observer = anObserver;
@@ -319,9 +437,9 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
{
if (_notifyObject)
[_object observeValueForKeyPath:_keyPath ofObject:_object change:change context:context];
[_object observeValueForKeyPath:aKeyPath ofObject:_object change:change context:context];
[_observer observeValueForKeyPath:_keyPath ofObject:_object change:change context:context];
[_observer observeValueForKeyPath:aKeyPath ofObject:_object change:change context:context];
}
- (CPString)description
@@ -331,7 +449,8 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
@end
@implementation _CPObservableArray : CPMutableArray
// FIXME: This should subclass CPMutableArray not _CPJavaScriptArray
@implementation _CPObservableArray : _CPJavaScriptArray
{
CPArray _observationProxies;
}
@@ -357,25 +476,15 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
- (id)initWithArray:(CPArray)anArray
{
if (self = [super initWithArray:anArray])
{
_observationProxies = [];
}
self = [super initWithArray:anArray];
self.isa = [_CPObservableArray class];
self._observationProxies = [];
return self;
}
- (id)initWithObjects:(CPArray)objects count:(unsigned)count
{
if (self = [super initWithObjects:objects count:count])
{
_observationProxies = [];
}
return self;
}
-(void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
- (void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
if (aKeyPath.indexOf("@") === 0)
{
@@ -387,7 +496,7 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
[_observationProxies addObject:proxy];
var dotIndex = aKeyPath.indexOf("."),
remaining = aKeyPath.substring(dotIndex+1),
remaining = aKeyPath.substring(dotIndex + 1),
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self addObserver:proxy toObjectsAtIndexes:indexes forKeyPath:remaining options:options context:context];
@@ -409,7 +518,7 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
proxy = [_observationProxies objectAtIndex:index];
var dotIndex = aKeyPath.indexOf("."),
remaining = aKeyPath.substring(dotIndex+1),
remaining = aKeyPath.substring(dotIndex + 1),
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self removeObserver:proxy fromObjectsAtIndexes:indexes forKeyPath:remaining];
@@ -423,7 +532,7 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
- (void)insertObject:(id)anObject atIndex:(unsigned)anIndex
{
for (var i=0, count=[_observationProxies count]; i<count; i++)
for (var i = 0, count = [_observationProxies count]; i < count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
@@ -443,7 +552,7 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
- (void)removeObjectAtIndex:(unsigned)anIndex
{
for (var i=0, count=[_observationProxies count]; i<count; i++)
for (var i = 0, count = [_observationProxies count]; i < count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
@@ -480,7 +589,7 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
{
var currentObject = [self objectAtIndex:anIndex];
for (var i=0, count=[_observationProxies count]; i<count; i++)
for (var i = 0, count = [_observationProxies count]; i < count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
@@ -503,11 +612,13 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
@implementation CPControllerSelectionProxy : CPObject
{
id _controller;
id _keys;
id _controller;
id _keys;
CPDictionary _cachedValues;
CPArray _observationProxies;
CPDictionary _cachedValues;
CPArray _observationProxies;
Object _observedObjectsByKeyPath;
}
- (id)initWithController:(id)aController
@@ -517,46 +628,65 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
_cachedValues = [CPDictionary dictionary];
_observationProxies = [CPArray array];
_controller = aController;
_observedObjectsByKeyPath = {};
}
return self;
}
- (id)valueForKey:(CPString)aKey
- (id)_controllerMarkerForValues:(CPArray)theValues
{
var value = [_cachedValues objectForKey:aKey];
if (value !== undefined && value !== nil)
return value;
var allValues = [[_controller selectedObjects] valueForKeyPath:aKey],
count = [allValues count];
var count = [theValues count];
if (!count)
value = CPNoSelectionMarker;
else if (count === 1)
value = [allValues objectAtIndex:0];
value = [theValues objectAtIndex:0];
else
{
if ([_controller alwaysUsesMultipleValuesMarker])
value = CPMultipleValuesMarker;
else
{
value = [allValues objectAtIndex:0];
value = [theValues objectAtIndex:0];
for (var i=0, count=[allValues count]; i<count && value!=CPMultipleValuesMarker; i++)
for (var i = 0, count= [theValues count]; i < count && value != CPMultipleValuesMarker; i++)
{
if (![value isEqual:[allValues objectAtIndex:i]])
if (![value isEqual:[theValues objectAtIndex:i]])
value = CPMultipleValuesMarker;
}
}
}
[_cachedValues setValue:value forKey:aKey];
return value;
}
- (id)valueForKeyPath:(CPString)theKeyPath
{
var values = [[_controller selectedObjects] valueForKeyPath:theKeyPath];
value = [self _controllerMarkerForValues:values];
[_cachedValues setObject:value forKey:theKeyPath];
return value;
}
- (id)valueForKey:(CPString)theKeyPath
{
return [self valueForKeyPath:theKeyPath];
}
- (void)setValue:(id)theValue forKeyPath:(CPString)theKeyPath
{
[[_controller selectedObjects] setValue:theValue forKeyPath:theKeyPath];
[_cachedValues removeObjectForKey:theKeyPath];
}
- (void)setValue:(id)theValue forKey:(CPString)theKeyPath
{
[self setValue:theKeyPath forKeyPath:theKeyPath];
}
- (unsigned)count
{
return [_cachedValues count];
@@ -567,32 +697,27 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
return [_cachedValues keyEnumerator];
}
- (void)setValue:(id)aValue forKey:(CPString)aKey
{
[[_controller selectedObjects] setValue:aValue forKey:aKey];
}
-(void)controllerWillChange
- (void)controllerWillChange
{
_keys = [_cachedValues allKeys];
if (!_keys)
return;
for (var i=0, count=_keys.length; i<count; i++)
for (var i = 0, count = _keys.length; i < count; i++)
[self willChangeValueForKey:_keys[i]];
[_cachedValues removeAllObjects];
}
-(void)controllerDidChange
- (void)controllerDidChange
{
[_cachedValues removeAllObjects];
if (!_keys)
return;
for (var i=0, count=_keys.length; i<count; i++)
for (var i = 0, count = _keys.length; i < count; i++)
[self didChangeValueForKey:_keys[i]];
_keys = nil;
@@ -610,7 +735,11 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
[proxy setNotifyObject:YES];
[_observationProxies addObject:proxy];
[[_controller selectedObjects] addObserver:proxy forKeyPath:aKeyPath options:options context:context];
// We keep are reference to the observed objects
// because the removeObserver: will be called after the selection changes
var observedObjects = [_controller selectedObjects];
_observedObjectsByKeyPath[aKeyPath] = observedObjects;
[observedObjects addObserver:proxy forKeyPath:aKeyPath options:options context:context];
}
- (void)removeObserver:(id)anObject forKeyPath:(CPString)aKeyPath
@@ -618,8 +747,12 @@ var CPObjectControllerObjectClassNameKey = @"CPObjectControllerOb
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self],
index = [_observationProxies indexOfObject:proxy];
[[_controller selectedObjects] removeObserver:[_observationProxies objectAtIndex:index] forKeyPath:aKeyPath];
var observedObjects = _observedObjectsByKeyPath[aKeyPath];
[observedObjects removeObserver:[_observationProxies objectAtIndex:index] forKeyPath:aKeyPath];
[_observationProxies removeObjectAtIndex:index];
_observedObjects = nil;
}
@end
+624 -40
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -26,7 +26,7 @@
CPOKButton = 1;
CPCancelButton = 0;
/*!
/*!
@ingroup appkit
@class CPPanel
@@ -51,7 +51,7 @@ CPCancelButton = 0;
@global
@class CPWindow
*/
CPDocModalWindowMask = 1 << 6;
CPDocModalWindowMask = 1 << 6;
@implementation CPPanel : CPWindow
{
+24 -24
View File
@@ -50,18 +50,18 @@ CPImagePboardType = @"CPImagePboardType";
var CPPasteboards = nil,
supportsNativePasteboard = NO;
/*!
/*!
@ingroup appkit
@class CPPasteboard
CPPasteBoard is the object responsible for cut/copy/paste and drag&drop operations.
CPPasteBoard is the object responsible for cut/copy/paste and drag&drop operations.
*/
@implementation CPPasteboard : CPObject
{
CPArray _types;
CPDictionary _owners;
CPDictionary _provided;
unsigned _changeCount;
CPString _stateUID;
@@ -77,7 +77,7 @@ var CPPasteboards = nil,
return;
[self setVersion:1.0];
CPPasteboards = [CPDictionary dictionary];
if (typeof window.cpPasteboardWithName !== "undefined")
@@ -103,10 +103,10 @@ var CPPasteboards = nil,
if (pasteboard)
return pasteboard;
pasteboard = [[CPPasteboard alloc] _initWithName:aName];
[CPPasteboards setObject:pasteboard forKey:aName];
return pasteboard;
}
@@ -114,15 +114,15 @@ var CPPasteboards = nil,
- (id)_initWithName:(CPString)aName
{
self = [super init];
if (self)
{
_name = aName;
_types = [];
_owners = [CPDictionary dictionary];
_provided = [CPDictionary dictionary];
_changeCount = 0;
if (supportsNativePasteboard)
@@ -131,7 +131,7 @@ var CPPasteboards = nil,
[self _synchronizePasteboard];
}
}
return self;
}
@@ -145,17 +145,17 @@ var CPPasteboards = nil,
{
var i = 0,
count = types.length;
for (; i < count; ++i)
{
var type = types[i];
if(![_owners objectForKey:type])
if (![_owners objectForKey:type])
{
[_types addObject:type];
[_provided removeObjectForKey:type];
}
[_owners setObject:anOwner forKey:type];
}
@@ -191,7 +191,7 @@ var CPPasteboards = nil,
_provided = [CPDictionary dictionary];
var count = _types.length;
while (count--)
[_owners setObject:anOwner forKey:_types[count]];
@@ -283,18 +283,18 @@ var CPPasteboards = nil,
- (CPData)dataForType:(CPString)aType
{
var data = [_provided objectForKey:aType];
if (data)
return data;
var owner = [_owners objectForKey:aType];
if (owner)
{
[owner pasteboard:self provideDataForType:aType];
[owner pasteboard:self provideDataForType:aType];
return [_provided objectForKey:aType];
}
if (aType === CPStringPboardType)
return [self dataForType:UTF8PboardType];
@@ -339,10 +339,10 @@ var CPPasteboards = nil,
- (id)propertyListForType:(CPString)aType
{
var data = [self dataForType:aType];
if (data)
return [CPPropertyListSerialization propertyListFromData:data format:CPPropertyList280NorthFormat_v1_0];
return nil;
}
@@ -360,9 +360,9 @@ var CPPasteboards = nil,
- (CPString)_generateStateUID
{
var bits = 32;
_stateUID = @"";
while (bits--)
_stateUID += FLOOR(RAND() * 16.0).toString(16).toUpperCase();
+244 -191
View File
@@ -26,7 +26,7 @@
@import "CPMenuItem.j"
var VISIBLE_MARGIN = 7.0;
var VISIBLE_MARGIN = 7.0;
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
@@ -38,10 +38,8 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
@implementation CPPopUpButton : CPButton
{
int _selectedIndex;
CPUInteger _selectedIndex;
CPRectEdge _preferredEdge;
CPMenu _menu;
}
+ (CPString)defaultThemeClass
@@ -49,6 +47,21 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
return "popup-button";
}
+ (CPSet)keyPathsForValuesAffectingSelectedIndex
{
return [CPSet setWithObject:@"objectValue"];
}
+ (CPSet)keyPathsForValuesAffectingSelectedTag
{
return [CPSet setWithObject:@"objectValue"];
}
+ (CPSet)keyPathsForValuesAffectingSelectedItem
{
return [CPSet setWithObject:@"objectValue"];
}
/*!
Initializes the pop-up button to the specified size.
@param aFrame the size for the button
@@ -61,7 +74,8 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if (self)
{
_selectedIndex = CPNotFound;
[self selectItemAtIndex:CPNotFound];
_preferredEdge = CPMaxYEdge;
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
@@ -71,6 +85,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
[self setMenu:[[CPMenu alloc] initWithTitle:@""]];
[self setPullsDown:shouldPullDown];
var options = CPKeyValueObservingOptionNew |
CPKeyValueObservingOptionOld;/* |
CPKeyValueObservingOptionInitial;
*/
[self addObserver:self forKeyPath:@"menu.items" options:options context:nil];
[self addObserver:self forKeyPath:@"_firstItem.changeCount" options:options context:nil];
[self addObserver:self forKeyPath:@"selectedItem.changeCount" options:options context:nil];
}
return self;
@@ -85,6 +107,9 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
Specifies whether the object is a pull-down or a pop-up menu.
If the button pulls down the menu items represent actions, not states.
So the text in the button will NOT change when the user selects something different.
@param shouldPullDown \c YES makes the pop-up button
a pull-down menu. \c NO makes it a pop-up menu.
*/
@@ -98,7 +123,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if (!changed)
return;
var items = [_menu itemArray];
var items = [[self menu] itemArray];
if ([items count] <= 0)
return;
@@ -123,21 +148,21 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (void)addItem:(CPMenuItem)anItem
{
[_menu addItem:anItem];
[[self menu] addItem:anItem];
}
/*!
Adds a new menu item with the specified title.
@param the new menu item's tite
@param the new menu item's title
*/
- (void)addItemWithTitle:(CPString)aTitle
{
[_menu addItemWithTitle:aTitle action:NULL keyEquivalent:nil];
[[self menu] addItemWithTitle:aTitle action:NULL keyEquivalent:nil];
}
/*!
Adds multiple new menu items with the titles specified in the provided array.
@param titles an arry of names for the new items
@param titles an array of names for the new items
*/
- (void)addItemsWithTitles:(CPArray)titles
{
@@ -150,7 +175,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
Inserts a new item with the specified title and index location.
@param aTitle the new itme's title
@param aTitle the new item's title
@param anIndex the item's index in the menu
*/
- (void)insertItemWithTitle:(CPString)aTitle atIndex:(int)anIndex
@@ -162,7 +187,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if ([items[count] title] == aTitle)
[self removeItemAtIndex:count];
[_menu insertItemWithTitle:aTitle action:NULL keyEquivalent:nil atIndex:anIndex];
[[self menu] insertItemWithTitle:aTitle action:NULL keyEquivalent:nil atIndex:anIndex];
}
/*!
@@ -170,10 +195,11 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (void)removeAllItems
{
var count = [_menu numberOfItems];
var menu = [self menu],
count = [menu numberOfItems];
while (count--)
[_menu removeItemAtIndex:0];
[menu removeItemAtIndex:0];
}
/*!
@@ -192,7 +218,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (void)removeItemAtIndex:(int)anIndex
{
[_menu removeItemAtIndex:anIndex];
[[self menu] removeItemAtIndex:anIndex];
[self synchronizeTitleAndSelectedItem];
}
@@ -202,10 +228,12 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPMenuItem)selectedItem
{
if (_selectedIndex < 0 || _selectedIndex > [self numberOfItems] - 1)
var indexOfSelectedItem = [self indexOfSelectedItem];
if (indexOfSelectedItem < 0 || indexOfSelectedItem > [self numberOfItems] - 1)
return nil;
return [_menu itemAtIndex:_selectedIndex];
return [[self menu] itemAtIndex:indexOfSelectedItem];
}
/*!
@@ -224,13 +252,20 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
return _selectedIndex;
}
// For us, CPNumber is toll-free bridged to Number, so just return the selected index.
/*!
Returns the selected item's index. If no item is selected, it returns CPNotFound.
@ignore
*/
- (id)objectValue
- (int)selectedTag
{
return _selectedIndex;
return [[self selectedItem] tag];
}
/*!
@ignore
*/
- (void)_setSelectedTag:(int)aTag
{
[self selectItemWithTag:aTag];
}
// Setting the Current Selection
@@ -247,22 +282,50 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
Selects the item at the specified index
@param anIndex the index of the item to select
*/
- (void)selectItemAtIndex:(int)anIndex
- (void)selectItemAtIndex:(CPUInteger)anIndex
{
if (_selectedIndex == anIndex)
[self setObjectValue:anIndex];
}
- (void)setSelectedIndex:(CPUInteger)anIndex
{
[self setObjectValue:anIndex];
}
- (CPUInteger)selectedIndex
{
return [self objectValue];
}
/*!
Selects the item at the specified index
@param anIndex the index of the item to select
*/
- (void)setObjectValue:(int)anIndex
{
var indexOfSelectedItem = [self objectValue];
anIndex = parseInt(+anIndex, 10);
if (indexOfSelectedItem === anIndex)
return;
if (_selectedIndex >= 0 && ![self pullsDown])
if (indexOfSelectedItem >= 0 && ![self pullsDown])
[[self selectedItem] setState:CPOffState];
_selectedIndex = anIndex;
if (_selectedIndex >= 0 && ![self pullsDown])
if (indexOfSelectedItem >= 0 && ![self pullsDown])
[[self selectedItem] setState:CPOnState];
[self synchronizeTitleAndSelectedItem];
}
- (id)objectValue
{
return _selectedIndex;
}
/*!
Selects the menu item with the specified tag
@param the tag of the item to select
@@ -281,84 +344,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
[self selectItemAtIndex:[self indexOfItemWithTitle:aTitle]];
}
/*!
Sets the object for the selected item. If no item is selected, then this method has no effect.
@param the object set for the selected item
*/
- (void)setObjectValue:(id)aValue
{
[self selectItemAtIndex:[aValue intValue]];
}
// Getting Menu Items
/*!
Returns the button's menu of items.
*/
- (CPMenu)menu
{
return _menu;
}
/*!
Sets the menu for the button
*/
- (void)setMenu:(CPMenu)aMenu
{
if (_menu === aMenu)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_menu)
{
[defaultCenter
removeObserver:self
name:CPMenuDidAddItemNotification
object:_menu];
[defaultCenter
removeObserver:self
name:CPMenuDidChangeItemNotification
object:_menu];
[defaultCenter
removeObserver:self
name:CPMenuDidRemoveItemNotification
object:_menu];
}
_menu = aMenu;
if (_menu)
{
[defaultCenter
addObserver:self
selector:@selector(menuDidAddItem:)
name:CPMenuDidAddItemNotification
object:_menu];
[defaultCenter
addObserver:self
selector:@selector(menuDidChangeItem:)
name:CPMenuDidChangeItemNotification
object:_menu];
[defaultCenter
addObserver:self
selector:@selector(menuDidRemoveItem:)
name:CPMenuDidRemoveItemNotification
object:_menu];
}
[self synchronizeTitleAndSelectedItem];
}
/*!
Returns a count of the number of items in the button's menu.
*/
- (int)numberOfItems
{
return [_menu numberOfItems];
return [[self menu] numberOfItems];
}
/*!
@@ -366,7 +359,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPArray)itemArray
{
return [_menu itemArray];
return [[self menu] itemArray];
}
/*!
@@ -375,7 +368,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPMenuItem)itemAtIndex:(unsigned)anIndex
{
return [_menu itemAtIndex:anIndex];
return [[self menu] itemAtIndex:anIndex];
}
/*!
@@ -384,7 +377,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPString)itemTitleAtIndex:(unsigned)anIndex
{
return [[_menu itemAtIndex:anIndex] title];
return [[[self menu] itemAtIndex:anIndex] title];
}
/*!
@@ -409,7 +402,9 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPMenuItem)itemWithTitle:(CPString)aTitle
{
return [_menu itemAtIndex:[_menu indexOfItemWithTitle:aTitle]];
var menu = [self menu];
return [menu itemAtIndex:[menu indexOfItemWithTitle:aTitle]];
}
/*!
@@ -417,7 +412,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPMenuItem)lastItem
{
return [[_menu itemArray] lastObject];
return [[[self menu] itemArray] lastObject];
}
// Getting the Indices of Menu Items
@@ -427,7 +422,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (int)indexOfItem:(CPMenuItem)aMenuItem
{
return [_menu indexOfItem:aMenuItem];
return [[self menu] indexOfItem:aMenuItem];
}
/*!
@@ -436,16 +431,16 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (int)indexOfItemWithTag:(int)aTag
{
return [_menu indexOfItemWithTag:aTag];
return [[self menu] indexOfItemWithTag:aTag];
}
/*!
Returns the index of the item with the specified title or CPNotFound.
@param aTitle the item's titel
@param aTitle the item's title
*/
- (int)indexOfItemWithTitle:(CPString)aTitle
{
return [_menu indexOfItemWithTitle:aTitle];
return [[self menu] indexOfItemWithTitle:aTitle];
}
/*!
@@ -456,7 +451,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (int)indexOfItemWithRepresentedObject:(id)anObject
{
return [_menu indexOfItemWithRepresentedObject:anObject];
return [[self menu] indexOfItemWithRepresentedObject:anObject];
}
/*!
@@ -468,7 +463,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (int)indexOfItemWithTarget:(id)aTarget action:(SEL)anAction
{
return [_menu indexOfItemWithTarget:aTarget action:anAction];
return [[self menu] indexOfItemWithTarget:aTarget action:anAction];
}
// Setting the Cell Edge to Pop out in Restricted Situations
@@ -483,7 +478,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
}
/*!
Sets the preffered edge of the button to display the
Sets the preferred edge of the button to display the
pop-up when there is a limited amount of screen space.
By default, the pop-up should draw on top of the button.
*/
@@ -504,7 +499,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if ([self pullsDown])
{
var items = [_menu itemArray];
var items = [[self menu] itemArray];
if ([items count] <= 0)
[self addItemWithTitle:aTitle];
@@ -552,7 +547,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if ([self pullsDown])
{
var items = [_menu itemArray];
var items = [[self menu] itemArray];
if ([items count] > 0)
item = items[0];
@@ -564,73 +559,117 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
[super setTitle:[item title]];
}
//
/*!
Called when the menu has a new item added to it.
@param aNotification information about the event
*/
- (void)menuDidAddItem:(CPNotification)aNotification
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)aContext
{
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"];
var pullsDown = [self pullsDown];
if (_selectedIndex < 0)
[self selectItemAtIndex:0];
else if (index == _selectedIndex)
if (!pullsDown && aKeyPath === @"selectedItem.changeCount" ||
pullsDown && (aKeyPath === @"_firstItem" || aKeyPath === @"_firstItem.changeCount"))
[self synchronizeTitleAndSelectedItem];
else if (index < _selectedIndex)
++_selectedIndex;
if (index == 0 && [self pullsDown])
// FIXME: This is due to a bug in KVO, we should never get it for "menu".
if (aKeyPath === @"menu")
{
var items = [_menu itemArray];
aKeyPath = @"menu.items";
[items[0] setHidden:YES];
if (items.length > 0)
[items[1] setHidden:NO];
[changes setObject:CPKeyValueChangeSetting forKey:CPKeyValueChangeKindKey];
[changes setObject:[[self menu] itemArray] forKey:CPKeyValueChangeNewKey];
}
var item = [_menu itemArray][index],
action = [item action];
if (!action || (action === @selector(_popUpItemAction:)))
if (aKeyPath === @"menu.items")
{
[item setTarget:self];
[item setAction:@selector(_popUpItemAction:)];
var changeKind = [changes objectForKey:CPKeyValueChangeKindKey],
indexOfSelectedItem = [self indexOfSelectedItem];
if (changeKind === CPKeyValueChangeRemoval)
{
var index = CPNotFound,
indexes = [changes objectForKey:CPKeyValueChangeIndexesKey];
if ([indexes containsIndex:0] && [self pullsDown])
[self _firstItemDidChange];
// See whether the index has changed, despite the actual item not changing.
while ((index = [indexes indexGreaterThanIndex:index]) !== CPNotFound &&
index <= indexOfSelectedItem)
--indexOfSelectedItem;
[self selectItemAtIndex:indexOfSelectedItem];
}
else if (changeKind === CPKeyValueChangeReplacement)
{
var indexes = [changes objectForKey:CPKeyValueChangeIndexesKey];
if (pullsDown && [indexes containsIndex:0] ||
!pullsDown && [indexes containsIndex:indexOfSelectedItem])
[self synchronizeTitleAndSelectedItem];
}
else
{
// No matter what, we want to prepare the new items.
var newItems = [changes objectForKey:CPKeyValueChangeNewKey];
[newItems enumerateObjectsUsingBlock:function(aMenuItem)
{
var action = [aMenuItem action];
if (!action)
[aMenuItem setAction:action = @selector(_popUpItemAction:)];
if (action === @selector(_popUpItemAction:))
[aMenuItem setTarget:self];
}];
if (changeKind === CPKeyValueChangeSetting)
{
[self _firstItemDidChange];
[self selectItemAtIndex:CPNotFound];
[self selectItemAtIndex:MIN([newItems count] - 1, indexOfSelectedItem)];
}
else //if (changeKind === CPKeyValueChangeInsertion)
{
var indexes = [changes objectForKey:CPKeyValueChangeIndexesKey];
if ([self pullsDown] && [indexes containsIndex:0])
{
[self _firstItemDidChange];
if ([self numberOfItems] > 1)
{
var index = CPNotFound,
originalIndex = 0;
while ((index = [indexes indexGreaterThanIndex:index]) !== CPNotFound &&
index <= originalIndex)
++originalIndex;
[[self itemAtIndex:originalIndex] setHidden:NO];
}
}
if (indexOfSelectedItem < 0)
[self selectItemAtIndex:0];
else
{
var index = CPNotFound;
// See whether the index has changed, despite the actual item not changing.
while ((index = [indexes indexGreaterThanIndex:index]) !== CPNotFound &&
index <= indexOfSelectedItem)
++indexOfSelectedItem;
[self selectItemAtIndex:indexOfSelectedItem];
}
}
}
}
}
/*!
Called when a menu item has changed.
@param aNotification information about the event
*/
- (void)menuDidChangeItem:(CPNotification)aNotification
{
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"];
if ([self pullsDown] && index != 0)
return;
if (![self pullsDown] && index != _selectedIndex)
return;
[self synchronizeTitleAndSelectedItem];
}
/*!
Called when an item was removed from the menu.
@param aNotification information about the event
*/
- (void)menuDidRemoveItem:(CPNotification)aNotification
{
var numberOfItems = [self numberOfItems];
if (numberOfItems <= _selectedIndex && numberOfItems > 0)
[self selectItemAtIndex:numberOfItems - 1];
else
[self synchronizeTitleAndSelectedItem];
// [super observeValueForKeyPath:aKeyPath ofObject:anObject change:changes context:aContext];
}
- (void)mouseDown:(CPEvent)anEvent
@@ -702,7 +741,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
- (void)rightMouseDown:(CPEvent)anEvent
{
// Disable standard CPView behaviour which incorrectly displays the menu as a 'context menu'.
// Disable standard CPView behavior which incorrectly displays the menu as a 'context menu'.
}
- (void)_popUpItemAction:(id)aSender
@@ -710,6 +749,22 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
[self sendAction:[self action] to:[self target]];
}
- (void)_firstItemDidChange
{
[self willChangeValueForKey:@"_firstItem"];
[self didChangeValueForKey:@"_firstItem"];
[[self _firstItem] setHidden:YES];
}
- (CPMenuItem)_firstItem
{
if ([self numberOfItems] <= 0)
return nil;
return [[self menu] itemAtIndex:0];
}
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
{
var count = objects.length,
@@ -719,19 +774,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
[self setEnabled:YES];
while (count-- > 1)
{
if (value !== [objects[count] valueForKeyPath:aKeyPath])
{
[[self selectedItem] setState:CPOffState];
}
}
}
@end
var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
CPPopUpButtonSelectedIndexKey = @"CPPopUpButtonSelectedIndexKey",
CPPopUpButtonPullsDownKey = @"CPPopUpButtonPullsDownKey";
var DEPRECATED_CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
DEPRECATED_CPPopUpButtonSelectedIndexKey = @"CPPopUpButtonSelectedIndexKey";
@implementation CPPopUpButton (CPCoding)
/*!
@@ -747,27 +797,30 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
if (self)
{
// Nothing is currently selected
_selectedIndex = -1;
// FIXME: (or not?) _title is nulled in - [CPButton initWithCoder:],
// so we need to do this again.
[self synchronizeTitleAndSelectedItem];
[self setMenu:[aCoder decodeObjectForKey:CPPopUpButtonMenuKey]];
[self selectItemAtIndex:[aCoder decodeObjectForKey:CPPopUpButtonSelectedIndexKey]];
// FIXME: Remove deprecation leniency for 1.0
if ([aCoder containsValueForKey:DEPRECATED_CPPopUpButtonMenuKey])
{
CPLog.warn(self + " was encoded with an older version of Cappuccino. Please nib2cib the original nib again or open and re-save in Atlas.");
[self setMenu:[aCoder decodeObjectForKey:DEPRECATED_CPPopUpButtonMenuKey]];
[self setObjectValue:[aCoder decodeObjectForKey:DEPRECATED_CPPopUpButtonSelectedIndexKey]];
}
var options = CPKeyValueObservingOptionNew |
CPKeyValueObservingOptionOld;/* |
CPKeyValueObservingOptionInitial;
*/
[self addObserver:self forKeyPath:@"menu.items" options:options context:nil];
[self addObserver:self forKeyPath:@"_firstItem.changeCount" options:options context:nil];
[self addObserver:self forKeyPath:@"selectedItem.changeCount" options:options context:nil];
}
return self;
}
/*!
Encodes the data of the pop-up button into a coder
@param aCoder the coder to which the data
will be written
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_menu forKey:CPPopUpButtonMenuKey];
[aCoder encodeInt:_selectedIndex forKey:CPPopUpButtonSelectedIndexKey];
}
@end
+42 -43
View File
@@ -47,7 +47,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
CPProgressIndicatorStyleIdentifiers = nil,
CPProgressIndicatorStyleSizes = nil;
/*!
/*!
@ingroup appkit
@class CPProgressIndicator
@@ -59,19 +59,19 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
double _minValue;
double _maxValue;
double _doubleValue;
CPControlSize _controlSize;
BOOL _isIndeterminate;
CPProgressIndicatorStyle _style;
BOOL _isAnimating;
BOOL _isDisplayedWhenStoppedSet;
BOOL _isDisplayedWhenStopped;
CPView _barView;
}
@@ -82,11 +82,11 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (self != [CPProgressIndicator class])
return;
var bundle = [CPBundle bundleForClass:self];
CPProgressIndicatorSpinningStyleColors = [];
CPProgressIndicatorSpinningStyleColors[CPMiniControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]];
CPProgressIndicatorSpinningStyleColors[CPSmallControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:
@@ -95,10 +95,10 @@ var CPProgressIndicatorSpinningStyleColors = nil,
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]];
CPProgressIndicatorBezelBorderViewPool = [];
var start = CPProgressIndicatorBarStyle,
end = CPProgressIndicatorHUDBarStyle;
for (; start <= end; ++start)
{
CPProgressIndicatorBezelBorderViewPool[start] = [];
@@ -106,21 +106,21 @@ var CPProgressIndicatorSpinningStyleColors = nil,
CPProgressIndicatorBezelBorderViewPool[start][CPSmallControlSize] = [];
CPProgressIndicatorBezelBorderViewPool[start][CPRegularControlSize] = [];
}
CPProgressIndicatorClassName = [self className];
CPProgressIndicatorStyleIdentifiers = [];
CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle] = @"Bar";
CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorSpinningStyle] = @"Spinny";
CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle] = @"HUDBar";
var regularIdentifier = _CPControlIdentifierForControlSize(CPRegularControlSize),
smallIdentifier = _CPControlIdentifierForControlSize(CPSmallControlSize),
miniIdentifier = _CPControlIdentifierForControlSize(CPMiniControlSize);
CPProgressIndicatorStyleSizes = [];
// Bar Sttyle
// Bar Style
var prefixes = [
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
@@ -128,7 +128,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle]
];
for (var i = 0, count = prefixes.length; i<count; i++)
for (var i = 0, count = prefixes.length; i < count; i++)
{
var prefix = prefixes[i];
CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(3.0, 16.0), _CGSizeMake(1.0, 16.0), _CGSizeMake(3.0, 16.0)];
@@ -140,23 +140,23 @@ var CPProgressIndicatorSpinningStyleColors = nil,
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_minValue = 0.0;
_maxValue = 100.0;
_doubleValue = 0.0;
_style = CPProgressIndicatorBarStyle;
_isDisplayedWhenStoppedSet = NO;
_controlSize = CPRegularControlSize;
[self updateBackgroundColor];
[self drawBar];
}
return self;
}
@@ -174,7 +174,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
- (void)startAnimation:(id)aSender
{
_isAnimating = YES;
[self _hideOrDisplay];
}
@@ -213,7 +213,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
- (void)setDoubleValue:(double)aValue
{
_doubleValue = MIN(MAX(aValue, _minValue), _maxValue);
[self drawBar];
}
@@ -268,7 +268,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_controlSize == aControlSize)
return;
_controlSize = aControlSize;
[self updateBackgroundColor];
@@ -290,7 +290,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
/*
Not yet impemented.
Not yet implemented.
*/
- (CPControlTint)controlTint
{
@@ -320,7 +320,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_isIndeterminate == isIndeterminate)
return;
_isIndeterminate = isIndeterminate;
[self updateBackgroundColor];
@@ -342,9 +342,9 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_style == aStyle)
return;
_style = aStyle;
[self updateBackgroundColor];
}
@@ -357,8 +357,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
[self setFrameSize:[[CPProgressIndicatorSpinningStyleColors[_controlSize] patternImage] size]];
else
[self setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), CPProgressIndicatorStyleSizes[
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle] +
_CPControlIdentifierForControlSize(_controlSize)][0].height)];
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle] + _CPControlIdentifierForControlSize(_controlSize)][0].height)];
}
/*!
@@ -370,11 +369,11 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_isDisplayedWhenStoppedSet && _isDisplayedWhenStopped == isDisplayedWhenStopped)
return;
_isDisplayedWhenStoppedSet = YES;
_isDisplayedWhenStopped = isDisplayedWhenStopped;
[self _hideOrDisplay];
}
@@ -385,10 +384,10 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_isDisplayedWhenStoppedSet)
return _isDisplayedWhenStopped;
if (_style == CPProgressIndicatorBarStyle || _style == CPProgressIndicatorHUDBarStyle)
return YES;
return NO;
}
@@ -401,7 +400,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
- (void)setFrameSize:(CGSize)aSize
{
[super setFrameSize:aSize];
[self drawBar];
}
@@ -410,13 +409,13 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_style == CPProgressIndicatorSpinningStyle)
return;
if (!_barView)
{
_barView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 16.0)];
_barView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 16.0)];
[self addSubview:_barView];
}
[_barView setBackgroundColor:_CPControlThreePartImagePattern(
NO,
CPProgressIndicatorStyleSizes,
@@ -442,9 +441,9 @@ var CPProgressIndicatorSpinningStyleColors = nil,
if (_style == CPProgressIndicatorSpinningStyle)
{
[_barView removeFromSuperview];
_barView = nil;
[self setBackgroundColor:CPProgressIndicatorSpinningStyleColors[_controlSize]];
}
else
@@ -456,7 +455,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
@"BezelBorder",
CPProgressIndicatorStyleIdentifiers[_style],
_CPControlIdentifierForControlSize(_controlSize))];
[self drawBar];
}
}
+2 -2
View File
@@ -358,8 +358,8 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
if (self)
{
_nextResponder = [aCoder decodeObjectForKey:CPResponderNextResponderKey];
_menu = [aCoder decodeObjectForKey:CPResponderMenuKey];
[self setNextResponder:[aCoder decodeObjectForKey:CPResponderNextResponderKey]];
[self setMenu:[aCoder decodeObjectForKey:CPResponderMenuKey]];
}
return self;
+24 -3
View File
@@ -354,6 +354,11 @@
/*!
Sets the type of border to be drawn around the view.
Valid types are:
CPNoBorder
CPLineBorder
CPBezelBorder
CPGrooveBorder
*/
- (void)setBorderType:(CPBorderType)borderType
{
@@ -501,7 +506,7 @@
}
/*!
Sets whether the scroll view hides its scoll bars when not needed.
Sets whether the scroll view hides its scroll bars when not needed.
@param autohidesScrollers \c YES causes the scroll bars
to be hidden when not needed.
*/
@@ -791,7 +796,7 @@
/*!
Sets the vertical page scroll amount.
@param aPageScroll the new vertcal page scroll amount
@param aPageScroll the new vertical page scroll amount
*/
- (void)setVerticalPageScroll:(float)aPageScroll
{
@@ -974,6 +979,22 @@
[self moveByOffset:CGSizeMake(0.0, _CGRectGetHeight(contentBounds) - _verticalPageScroll)];
}
- (void)scrollToBeginningOfDocument:(id)sender
{
[_contentView scrollToPoint:_CGPointMakeZero()];
[_headerClipView scrollToPoint:_CGPointMakeZero()];
}
- (void)scrollToEndOfDocument:(id)sender
{
var contentBounds = [_contentView bounds],
documentFrame = [[self documentView] frame],
scrollPoint = _CGPointMake(0.0, _CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds));
[_contentView scrollToPoint:scrollPoint];
[_headerClipView scrollToPoint:_CGPointMakeZero()];
}
- (void)moveLeft:(id)sender
{
[self moveByOffset:CGSizeMake(-_horizontalLineScroll, 0.0)];
@@ -1003,7 +1024,7 @@
contentBounds.origin.y += aSize.height;
[_contentView scrollToPoint:contentBounds.origin];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin, 0)];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0)];
}
@end
+113 -138
View File
@@ -23,12 +23,10 @@
@import "CPButton.j"
@import "CPTextField.j"
CPSearchFieldRecentsTitleMenuItemTag = 1000;
CPSearchFieldRecentsMenuItemTag = 1001;
CPSearchFieldClearRecentsMenuItemTag = 1002;
CPSearchFieldNoRecentsMenuItemTag = 1003;
CPSearchFieldSeparatorMenuItemTag = 1004;
var CPSearchFieldSearchImage = nil,
CPSearchFieldFindImage = nil,
@@ -39,15 +37,16 @@ var SEARCH_BUTTON_DEFAULT_WIDTH = 25.0,
CANCEL_BUTTON_DEFAULT_WIDTH = 22.0,
BUTTON_DEFAULT_HEIGHT = 22.0;
var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotification";
var RECENT_SEARCH_PREFIX = @" ";
/*!
/*!
@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.
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
{
@@ -58,7 +57,7 @@ var RECENT_SEARCH_PREFIX = @" ";
CPString _recentsAutosaveName;
CPArray _recentSearches;
int _maximumRecents;
BOOL _sendsWholeSearchString;
BOOL _sendsSearchStringImmediately;
@@ -96,9 +95,9 @@ var RECENT_SEARCH_PREFIX = @" ";
#if PLATFORM(DOM)
_cancelButton._DOMElement.style.cursor = "default";
_searchButton._DOMElement.style.cursor = "default";
#endif
#endif
}
return self;
}
@@ -112,17 +111,17 @@ var RECENT_SEARCH_PREFIX = @" ";
[self setEditable:YES];
[self setDelegate:self];
[self setContinuous:YES];
var bounds = [self bounds],
cancelButton = [[CPButton alloc] initWithFrame:[self cancelButtonRectForBounds:bounds]],
searchButton = [[CPButton alloc] initWithFrame:[self searchButtonRectForBounds:bounds]];
[self setCancelButton:cancelButton];
[self resetCancelButton];
[self setSearchButton:searchButton];
[self resetSearchButton];
_canResignFirstResponder = YES;
}
@@ -132,12 +131,12 @@ var RECENT_SEARCH_PREFIX = @" ";
@param button The search button.
*/
- (void)setSearchButton:(CPButton)button
{
{
if (button != _searchButton)
{
[_searchButton removeFromSuperview];
_searchButton = button;
[_searchButton setFrame:[self searchButtonRectForBounds:[self bounds]]];
[_searchButton setAutoresizingMask:CPViewMaxXMargin];
[self addSubview:_searchButton];
@@ -161,7 +160,7 @@ var RECENT_SEARCH_PREFIX = @" ";
{
var button = [self searchButton],
searchButtonImage = (_searchMenuTemplate === nil) ? CPSearchFieldSearchImage : CPSearchFieldFindImage;
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImage:searchButtonImage];
@@ -178,11 +177,11 @@ var RECENT_SEARCH_PREFIX = @" ";
{
[_cancelButton removeFromSuperview];
_cancelButton = button;
[_cancelButton setFrame:[self cancelButtonRectForBounds:[self bounds]]];
[_cancelButton setAutoresizingMask:CPViewMinXMargin];
[_cancelButton setTarget:self];
[_cancelButton setAction:@selector(_searchFieldCancel:)];
[_cancelButton setAction:@selector(cancelOperation:)];
[self _updateCancelButtonVisibility];
[self addSubview:_cancelButton];
}
@@ -210,7 +209,7 @@ var RECENT_SEARCH_PREFIX = @" ";
[button setAlternateImage:CPSearchFieldCancelPressedImage];
[button setAutoresizingMask:CPViewMinXMargin];
[button setTarget:self];
[button setAction:@selector(_searchFieldCancel:)];
[button setAction:@selector(cancelOperation:)];
}
// Custom Layout
@@ -222,22 +221,22 @@ var RECENT_SEARCH_PREFIX = @" ";
*/
- (CGRect)searchTextRectForBounds:(CGRect)rect
{
var leftOffset = 0,
var leftOffset = 0,
width = _CGRectGetWidth(rect),
bounds = [self bounds];
if (_searchButton)
{
var searchBounds = [self searchButtonRectForBounds:bounds];
leftOffset = _CGRectGetMaxX(searchBounds) + 2;
}
if (_cancelButton)
{
var cancelRect = [self cancelButtonRectForBounds:bounds];
width = _CGRectGetMinX(cancelRect) - leftOffset;
}
return _CGRectMake(leftOffset, _CGRectGetMinY(rect), width, _CGRectGetHeight(rect));
}
@@ -257,7 +256,7 @@ var RECENT_SEARCH_PREFIX = @" ";
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.
*/
- (CGRect)cancelButtonRectForBounds:(CGRect)rect
{
{
return _CGRectMake(_CGRectGetWidth(rect) - CANCEL_BUTTON_DEFAULT_WIDTH - 5, (_CGRectGetHeight(rect) - CANCEL_BUTTON_DEFAULT_WIDTH) / 2, BUTTON_DEFAULT_HEIGHT, BUTTON_DEFAULT_HEIGHT);
}
@@ -279,7 +278,7 @@ var RECENT_SEARCH_PREFIX = @" ";
- (void)setSearchMenuTemplate:(CPMenu)aMenu
{
_searchMenuTemplate = aMenu;
[self resetSearchButton];
[self _loadRecentSearchList];
[self _updateSearchMenu];
@@ -291,8 +290,8 @@ var RECENT_SEARCH_PREFIX = @" ";
@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;
{
return _sendsWholeSearchString;
}
/*!
@@ -309,8 +308,8 @@ var RECENT_SEARCH_PREFIX = @" ";
@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;
{
return _sendsSearchStringImmediately;
}
/*!
@@ -328,7 +327,7 @@ var RECENT_SEARCH_PREFIX = @" ";
@return The maximum number of search strings that can appear in the menu. This value is between 0 and 254.
*/
- (int)maximumRecents
{
{
return _maximumRecents;
}
@@ -342,13 +341,13 @@ var RECENT_SEARCH_PREFIX = @" ";
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.
@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
{
@@ -364,8 +363,8 @@ var RECENT_SEARCH_PREFIX = @" ";
{
var max = MIN([self maximumRecents], [searches count]),
searches = [searches subarrayWithRange:CPMakeRange(0, max)];
_recentSearches = searches;
_recentSearches = searches;
[self _autosaveRecentSearchList];
}
@@ -375,7 +374,7 @@ var RECENT_SEARCH_PREFIX = @" ";
*/
- (CPString)recentsAutosaveName
{
return _recentsAutosaveName;
return _recentsAutosaveName;
}
/*!
@@ -386,9 +385,9 @@ var RECENT_SEARCH_PREFIX = @" ";
{
if (_recentsAutosaveName != nil)
[self _deregisterForAutosaveNotification];
_recentsAutosaveName = name;
if (_recentsAutosaveName != nil)
[self _registerForAutosaveNotification];
}
@@ -397,13 +396,13 @@ var RECENT_SEARCH_PREFIX = @" ";
- (CGRect)contentRectForBounds:(CGRect)bounds
{
var superbounds = [super contentRectForBounds:bounds];
var superbounds = [super contentRectForBounds:bounds];
return [self searchTextRectForBounds:superbounds];
}
+ (double)_keyboardDelayForPartialSearchString:(CPString)string
{
return (6 - MIN([string length],4))/10;
return (6 - MIN([string length], 4)) / 10;
}
- (CPMenu)menu
@@ -431,15 +430,15 @@ var RECENT_SEARCH_PREFIX = @" ";
{
[_partialStringTimer invalidate];
var timeInterval = [CPSearchField _keyboardDelayForPartialSearchString:[self stringValue]];
_partialStringTimer = [CPTimer scheduledTimerWithTimeInterval:timeInterval
target:self
selector:@selector(_sendPartialString)
userInfo:nil
repeats:NO];
_partialStringTimer = [CPTimer scheduledTimerWithTimeInterval:timeInterval
target:self
selector:@selector(_sendPartialString)
userInfo:nil
repeats:NO];
}
}
[self _updateCancelButtonVisibility];
}
@@ -462,7 +461,7 @@ var RECENT_SEARCH_PREFIX = @" ";
{
if (string === nil || string === @"" || [_recentSearches containsObject:string])
return;
var searches = [CPMutableArray arrayWithArray:_recentSearches];
[searches addObject:string];
[self setRecentSearches:searches];
@@ -471,7 +470,7 @@ var RECENT_SEARCH_PREFIX = @" ";
- (CPView)hitTest:(CGPoint)aPoint
{
// Make sure a hit anywhere within the search field returns the search field itself
// Make sure a hit anywhere within the search field returns the search field itself
if (_CGRectContainsPoint([self frame], aPoint))
return self;
else
@@ -493,8 +492,8 @@ var RECENT_SEARCH_PREFIX = @" ";
if (_searchMenuTemplate == nil)
[self _sendAction:self];
else
[self _showMenu];
}
[self _showMenu];
}
else if (_CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point))
[_cancelButton mouseDown:anEvent];
else
@@ -504,69 +503,69 @@ var RECENT_SEARCH_PREFIX = @" ";
/*!
Provides the common case items for a recent searches menu. If there are not recent searches,
displays a single disabled item:
No Recent Searches
If there are 1 more recent searches, it displays:
Recent Searches
recent search 1
recent search 2
etc.
---------------------
Clear Recent Searches
If you wish to add items before or after the template, you can. If you put items
before, a separator will automatically be placed before the default template item.
If you add items after the default template, it is your responsibility to add a separator.
To add a custom item:
item = [[CPMenuItem alloc] initWithTitle:@"google"
action:@selector(google:)
item = [[CPMenuItem alloc] initWithTitle:@"google"
action:@selector(google:)
keyEquivalent:@""];
[item setTag:700];
[item setTarget:self];
[template addItem:item];
Be sure that your custom items do not use tags in the range 1000-1004 inclusive.
Be sure that your custom items do not use tags in the range 1000-1003 inclusive.
If you wish to maintain state in custom menu items that you add, you will need to maintain
the item state yourself, then in the action method of the custom items, modify the items
in the search menu template and send [searchField setSearchMenuTemplate:template] to update the menu.
*/
- (CPMenu)defaultSearchMenuTemplate
{
var template = [[CPMenu alloc] init],
var template = [[CPMenu alloc] init],
item;
item = [[CPMenuItem alloc] initWithTitle:@"Recent Searches"
action:nil
item = [[CPMenuItem alloc] initWithTitle:@"Recent Searches"
action:nil
keyEquivalent:@""];
[item setTag:CPSearchFieldRecentsTitleMenuItemTag];
[item setEnabled:NO];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"Recent search item"
action:@selector(_searchFieldSearch:)
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:)
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:nil
item = [[CPMenuItem alloc] initWithTitle:@"No Recent Searches"
action:nil
keyEquivalent:@""];
[item setTag:CPSearchFieldNoRecentsMenuItemTag];
[item setEnabled:NO];
[template addItem:item];
return template;
}
@@ -574,72 +573,66 @@ var RECENT_SEARCH_PREFIX = @" ";
{
if (_searchMenuTemplate === nil)
return;
var menu = [[CPMenu alloc] init],
countOfRecents = [_recentSearches count],
numberOfItems = [_searchMenuTemplate numberOfItems];
for (var i = 0; i < numberOfItems; i++)
{
var item = [[_searchMenuTemplate itemAtIndex:i] copy];
switch ([item tag])
{
case CPSearchFieldRecentsTitleMenuItemTag:
if (countOfRecents === 0)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
break;
case CPSearchFieldRecentsMenuItemTag:
{
var itemAction = @selector(_searchFieldSearch:);
for (var recentIndex = 0; recentIndex < countOfRecents; ++recentIndex)
{
// RECENT_SEARCH_PREFIX is a hack until CPMenuItem -setIndentationLevel works
var recentItem = [[CPMenuItem alloc] initWithTitle:RECENT_SEARCH_PREFIX + [_recentSearches objectAtIndex:recentIndex]
action:itemAction
var recentItem = [[CPMenuItem alloc] initWithTitle:RECENT_SEARCH_PREFIX + [_recentSearches objectAtIndex:recentIndex]
action:itemAction
keyEquivalent:[item keyEquivalent]];
[item setTarget:self];
[menu addItem:recentItem];
}
continue;
}
case CPSearchFieldClearRecentsMenuItemTag:
if (countOfRecents === 0)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
[item setAction:@selector(_searchFieldClearRecents:)];
[item setTarget:self];
break;
case CPSearchFieldNoRecentsMenuItemTag:
if (countOfRecents !== 0)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
break;
case CPSearchFieldSeparatorMenuItemTag:
item = [CPMenuItem separatorItem];
[item setEnabled:NO];
[menu addItem:item];
continue;
}
}
[item setEnabled:([item isEnabled] && [item action] != nil && [item target] != nil)];
[menu addItem:item];
}
[menu setDelegate:self];
_searchMenu = menu;
@@ -660,7 +653,7 @@ var RECENT_SEARCH_PREFIX = @" ";
- (void)menuDidClose:(CPMenu)menu
{
_canResignFirstResponder = YES;
[self becomeFirstResponder];
}
@@ -668,12 +661,12 @@ var RECENT_SEARCH_PREFIX = @" ";
{
if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled])
return;
var aFrame = [[self superview] convertRect:[self frame] toView:nil],
location = CPMakePoint(aFrame.origin.x + 10, aFrame.origin.y + aFrame.size.height - 4);
var anEvent = [CPEvent mouseEventWithType:CPRightMouseDown location:location modifierFlags:0 timestamp:[[CPApp currentEvent] timestamp] windowNumber:[[self window] windowNumber] context:nil eventNumber:1 clickCount:1 pressure:0];
[self selectAll:nil];
[CPMenu popUpContextMenu:_searchMenu withEvent:anEvent forView:self];
}
@@ -684,8 +677,8 @@ var RECENT_SEARCH_PREFIX = @" ";
[_partialStringTimer invalidate];
}
- (void)_searchFieldCancel:(id)sender
{
- (void)cancelOperation:(id)sender
{
[self setObjectValue:@""];
[self _sendPartialString];
[self _updateCancelButtonVisibility];
@@ -694,14 +687,14 @@ var RECENT_SEARCH_PREFIX = @" ";
- (void)_searchFieldSearch:(id)sender
{
var searchString = [[sender title] substringFromIndex:[RECENT_SEARCH_PREFIX length]];
if ([sender tag] != CPSearchFieldRecentsMenuItemTag)
[self _addStringToRecentSearches:searchString];
[self setObjectValue:searchString];
[self _sendPartialString];
[self selectAll:nil];
[self _updateCancelButtonVisibility];
}
@@ -715,54 +708,36 @@ var RECENT_SEARCH_PREFIX = @" ";
- (void)_registerForAutosaveNotification
{
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_updateAutosavedRecents:) name:@"CPAutosavedRecentsChangedNotification" object:nil];
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_updateAutosavedRecents:) name:CPAutosavedRecentsChangedNotification object:_recentsAutosaveName];
}
- (void)_deregisterForAutosaveNotification
{
[[CPNotificationCenter defaultCenter] removeObserver:self name:@"CPAutosavedRecentsChangedNotification" object:nil];
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPAutosavedRecentsChangedNotification object:_recentsAutosaveName];
}
- (void)_autosaveRecentSearchList
{
if (_recentsAutosaveName != nil)
[[CPNotificationCenter defaultCenter] postNotificationName:@"CPAutosavedRecentsChangedNotification" object:_recentsAutosaveName];
{
if (_recentsAutosaveName != nil)
[[CPNotificationCenter defaultCenter] postNotificationName:CPAutosavedRecentsChangedNotification object:_recentsAutosaveName];
}
- (void)_updateAutosavedRecents:(id)notification
{
var list = [self recentSearches],
name = [notification object],
bundle_name = [[[CPBundle mainBundle] infoDictionary] objectForKey:"CPBundleName"],
cookie_name = [bundle_name lowercaseString] + "." + [notification object],
cookie = [[CPCookie alloc] initWithName:cookie_name],
cookie_value = [list componentsJoinedByString:@","];
[cookie setValue:cookie_value
expires:[[CPDate alloc] initWithTimeIntervalSinceNow:3600*24*365]
domain:(window.location.href.hostname)];
var name = [notification object];
[[CPUserDefaults standardUserDefaults] setObject:_recentSearches forKey:name];
}
- (void)_loadRecentSearchList
{
var list,
name = [self recentsAutosaveName];
var name = [self recentsAutosaveName];
if (name === nil)
return;
var bundle_name = [[[CPBundle mainBundle] infoDictionary] objectForKey:"CPBundleName"],
cookie_name = [bundle_name lowercaseString] + "." + name,
var list = [[CPUserDefaults standardUserDefaults] objectForKey:name];
cookie = [[CPCookie alloc] initWithName:cookie_name];
if (cookie != nil)
{
var cookie_value = [cookie value];
list = (cookie_value != @"") ? [cookie_value componentsSeparatedByString:@","] : [CPArray array];
if (list !== nil)
_recentSearches = list;
}
}
@end
@@ -780,7 +755,7 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
[_searchButton removeFromSuperview];
[_cancelButton removeFromSuperview];
[super encodeWithCoder:coder];
[super encodeWithCoder:coder];
if (_searchButton)
[self addSubview:_searchButton];
@@ -793,7 +768,7 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
if (_recentsAutosaveName)
[coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey];
if (_searchMenuTemplate)
[coder encodeObject:_searchMenuTemplate forKey:CPSearchMenuTemplateKey];
}
@@ -802,16 +777,16 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
{
if (self = [super initWithCoder:coder])
{
_recentsAutosaveName = [coder decodeObjectForKey:CPRecentsAutosaveNameKey];
[self setRecentsAutosaveName:[coder decodeObjectForKey:CPRecentsAutosaveNameKey]];
_sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey];
_sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey];
_maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey];
var template = [coder decodeObjectForKey:CPSearchMenuTemplateKey];
if (template)
[self setSearchMenuTemplate:template];
[self _init];
}
+14 -4
View File
@@ -94,7 +94,9 @@ CPSegmentSwitchTrackingMomentary = 2;
if (_segments.length == aCount)
return;
var height = CGRectGetHeight([self bounds]);
var height = CGRectGetHeight([self bounds]),
dividersBefore = MAX(0, _segments.length - 1),
dividersAfter = MAX(0, aCount - 1);
if (_segments.length < aCount)
{
@@ -113,6 +115,14 @@ CPSegmentSwitchTrackingMomentary = 2;
if (_selectedSegment >= _segments.length)
_selectedSegment = -1;
// Make space for/remove space used by dividers.
var thickness = [self currentValueForThemeAttribute:@"divider-thickness"],
delta = thickness * (dividersAfter - dividersBefore),
frame = [self frame];
if (delta)
[self setFrameSize:CGSizeMake(frame.size.width + delta, frame.size.height)];
[self tileWithChangedSegment:0];
}
@@ -351,9 +361,9 @@ CPSegmentSwitchTrackingMomentary = 2;
}
/*!
Enables/diables the specified segment.
Enables/disables the specified segment.
@param isEnabled \c YES enables the segment
@param aSegment the segment to enable/disble
@param aSegment the segment to enable/disable
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setEnabled:(BOOL)isEnabled forSegment:(unsigned)aSegment
@@ -607,7 +617,7 @@ CPSegmentSwitchTrackingMomentary = 2;
segmentWidth = [segment width],
themeState = _themeStates[aSegment] | (_themeState & CPThemeStateDisabled),
contentInset = [self valueForThemeAttribute:@"content-inset" inState:themeState],
font = [self valueForThemeAttribute:@"font" inState:themeState];
font = [self font];
if (!segmentWidth)
{
+6 -6
View File
@@ -23,8 +23,8 @@
@import <Foundation/CPObject.j>
/*!
@deprecated
/*!
@deprecated
@class CPShadow
Instances of this class contain the attributes of a drop shadow used in Cappuccino.
@@ -34,7 +34,7 @@
CPSize _offset;
float _blurRadius;
CPColor _color;
CPString _cssString;
}
@@ -54,16 +54,16 @@
- (id)_initWithOffset:(CPSize)anOffset blurRadius:(float)aBlurRadius color:(CPColor)aColor
{
self = [super init];
if (self)
{
_offset = anOffset;
_blurRadius = aBlurRadius;
_color = aColor;
_cssString = [_color cssString] + " " + Math.round(anOffset.width) + @"px " + Math.round(anOffset.height) + @"px " + Math.round(_blurRadius) + @"px";
}
return self;
}
+1 -1
View File
@@ -384,7 +384,7 @@ CPCircularSlider = 1;
/*!
@ignore
shoudl we have _continuous?
should we have _continuous?
*/
- (void)setContinuous:(BOOL)flag
{
+55 -48
View File
@@ -28,16 +28,16 @@
@ignore
*/
@implementation CPSliderColorPicker : CPColorPicker
{
{
CPView _contentView;
CPSlider _redSlider;
CPSlider _greenSlider;
CPSlider _blueSlider;
CPSlider _hueSlider;
CPSlider _saturationSlider;
CPSlider _brightnessSlider;
CPTextField _rgbLabel;
CPTextField _hsbLabel;
CPTextField _redLabel;
@@ -58,27 +58,27 @@
CPTextField _brightnessValue;
}
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
{
return [super initWithPickerMask:mask colorPanel: owningColorPanel];
}
-(id)initView
- (id)initView
{
aFrame = CPRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
aFrame = CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
_contentView = [[CPView alloc] initWithFrame:aFrame];
[_contentView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
_rgbLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 10, 100, 20)];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_rgbLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 10, 100, 20)];
[_rgbLabel setStringValue: "Red, Green, Blue"];
[_rgbLabel setTextColor:[CPColor blackColor]];
_redLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 35, 15, 20)];
_redLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 35, 15, 20)];
[_redLabel setStringValue: "R"];
[_redLabel setTextColor:[CPColor blackColor]];
_redSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 35, aFrame.size.width - 70, 20)];
_redSlider = [[CPSlider alloc] initWithFrame: CGRectMake(15, 35, aFrame.size.width - 70, 20)];
[_redSlider setMaxValue: 1.0];
[_redSlider setMinValue: 0.0];
[_redSlider setTarget: self];
@@ -93,11 +93,11 @@
[_redValue setDelegate: self];
[_contentView addSubview: _redValue];
_greenLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 58, 15, 20)];
_greenLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 58, 15, 20)];
[_greenLabel setStringValue: "G"];
[_greenLabel setTextColor:[CPColor blackColor]];
_greenSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 58, aFrame.size.width - 70, 20)];
_greenSlider = [[CPSlider alloc] initWithFrame: CGRectMake(15, 58, aFrame.size.width - 70, 20)];
[_greenSlider setMaxValue: 1.0];
[_greenSlider setMinValue: 0.0];
[_greenSlider setTarget: self];
@@ -112,11 +112,11 @@
[_greenValue setDelegate: self];
[_contentView addSubview: _greenValue];
_blueLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 81, 15, 20)];
_blueLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 81, 15, 20)];
[_blueLabel setStringValue: "B"];
[_blueLabel setTextColor:[CPColor blackColor]];
_blueSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 81, aFrame.size.width - 70, 20)];
_blueSlider = [[CPSlider alloc] initWithFrame: CGRectMake(15, 81, aFrame.size.width - 70, 20)];
[_blueSlider setMaxValue: 1.0];
[_blueSlider setMinValue: 0.0];
[_blueSlider setTarget: self];
@@ -131,15 +131,15 @@
[_blueValue setDelegate: self];
[_contentView addSubview: _blueValue];
_hsbLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 120, 190, 20)];
_hsbLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 120, 190, 20)];
[_hsbLabel setStringValue: "Hue, Saturation, Brightness"];
[_hsbLabel setTextColor:[CPColor blackColor]];
_hueLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 145, 15, 20)];
_hueLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 145, 15, 20)];
[_hueLabel setStringValue: "H"];
[_hueLabel setTextColor:[CPColor blackColor]];
_hueSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 145, aFrame.size.width - 70, 20)];
_hueSlider = [[CPSlider alloc] initWithFrame: CGRectMake(15, 145, aFrame.size.width - 70, 20)];
[_hueSlider setMaxValue: 359.0];
[_hueSlider setMinValue: 0.0];
[_hueSlider setTarget: self];
@@ -154,11 +154,11 @@
[_hueValue setDelegate: self];
[_contentView addSubview: _hueValue];
_saturationLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 168, 15, 20)];
_saturationLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 168, 15, 20)];
[_saturationLabel setStringValue: "S"];
[_saturationLabel setTextColor:[CPColor blackColor]];
_saturationSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 168, aFrame.size.width - 70, 20)];
_saturationSlider = [[CPSlider alloc] initWithFrame: CGRectMake(15, 168, aFrame.size.width - 70, 20)];
[_saturationSlider setMaxValue: 100.0];
[_saturationSlider setMinValue: 0.0];
[_saturationSlider setTarget: self];
@@ -173,11 +173,11 @@
[_saturationValue setDelegate: self];
[_contentView addSubview: _saturationValue];
_brightnessLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 191, 15, 20)];
_brightnessLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 191, 15, 20)];
[_brightnessLabel setStringValue: "B"];
[_brightnessLabel setTextColor:[CPColor blackColor]];
_brightnessSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 191, aFrame.size.width - 70, 20)];
_brightnessSlider = [[CPSlider alloc] initWithFrame: CGRectMake(15, 191, aFrame.size.width - 70, 20)];
[_brightnessSlider setMaxValue: 100.0];
[_brightnessSlider setMinValue: 0.0];
[_brightnessSlider setTarget: self];
@@ -192,7 +192,7 @@
[_brightnessValue setDelegate: self];
[_contentView addSubview: _brightnessValue];
_hexLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 230, 30, 20)];
_hexLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 230, 30, 20)];
[_hexLabel setStringValue: "Hex"];
[_hexLabel setTextColor:[CPColor blackColor]];
@@ -210,7 +210,7 @@
[_contentView addSubview: _redSlider];
[_contentView addSubview: _greenSlider];
[_contentView addSubview: _blueSlider];
[_contentView addSubview: _hsbLabel];
[_contentView addSubview: _hueLabel];
[_contentView addSubview: _saturationLabel];
@@ -218,35 +218,35 @@
[_contentView addSubview: _hueSlider];
[_contentView addSubview: _saturationSlider];
[_contentView addSubview: _brightnessSlider];
[_contentView addSubview: _hexLabel];
}
- (CPView)provideNewView:(BOOL)initialRequest
- (CPView)provideNewView:(BOOL)initialRequest
{
if (initialRequest)
if (initialRequest)
[self initView];
return _contentView;
}
- (int)currentMode
- (int)currentMode
{
return CPSliderColorPickerMode;
}
- (BOOL)supportsMode:(int)mode
- (BOOL)supportsMode:(int)mode
{
return (mode == CPSliderColorPickerMode) ? YES : NO;
}
-(void)sliderChanged:(id)sender
- (void)sliderChanged:(id)sender
{
var newColor,
colorPanel = [self colorPanel],
alpha = [colorPanel opacity];
switch(sender)
switch (sender)
{
case _hueSlider:
case _saturationSlider:
@@ -254,27 +254,27 @@
saturation: [_saturationSlider floatValue]
brightness: [_brightnessSlider floatValue]
alpha: alpha];
[self updateRGBSliders: newColor];
break;
case _redSlider:
case _greenSlider:
case _blueSlider: newColor = [CPColor colorWithCalibratedRed: [_redSlider floatValue]
green: [_greenSlider floatValue]
blue: [_blueSlider floatValue]
alpha: alpha];
[self updateHSBSliders: newColor];
break;
}
[self updateLabels];
[self updateHex: newColor];
[colorPanel setColor: newColor];
}
-(void)setColor:(CPColor)aColor
- (void)setColor:(CPColor)aColor
{
[self updateRGBSliders: aColor];
[self updateHSBSliders: aColor];
@@ -282,10 +282,10 @@
[self updateLabels];
}
-(void)updateHSBSliders:(CPColor)aColor
- (void)updateHSBSliders:(CPColor)aColor
{
var hsb = [aColor hsbComponents];
[_hueSlider setFloatValue:hsb[0]];
[_saturationSlider setFloatValue:hsb[1]];
[_brightnessSlider setFloatValue:hsb[2]];
@@ -310,7 +310,7 @@
[_hueValue setStringValue: ROUND([_hueSlider floatValue])];
[_saturationValue setStringValue: ROUND([_saturationSlider floatValue])];
[_brightnessValue setStringValue: ROUND([_brightnessSlider floatValue])];
[_redValue setStringValue: ROUND([_redSlider floatValue] * 255)];
[_greenValue setStringValue: ROUND([_greenSlider floatValue] * 255)];
[_blueValue setStringValue: ROUND([_blueSlider floatValue] * 255)];
@@ -330,14 +330,21 @@
{
var field = [aNotification object],
value = [[field stringValue] stringByTrimmingWhitespace];
if (field === _hexValue) {
if (field === _hexValue)
{
var newColor = [CPColor colorWithHexString: value];
if (newColor) {
if (newColor)
{
[self setColor: newColor];
[[self colorPanel] setColor: newColor];
}
} else {
switch(field) {
}
else
{
switch (field)
{
case _redValue: [_redSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _redSlider];
break;
+268
View File
@@ -0,0 +1,268 @@
/*
* CPSound.j
* AppKit
*
* Created by Antoine Mercadal
* Copyright 2010, Antoine Mercadal
*
* 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>
CPSoundLoadStateEmpty = 0;
CPSoundLoadStateLoading = 1;
CPSoundLoadStateCanBePlayed = 2;
CPSoundPlayBackStatePlay = 0;
CPSoundPlayBackStateStop = 1;
CPSoundPlayBackStatePause = 2;
/*!
CPSound provides a way to load and play sounds. In the browser it relies on the
HTML5 audio tag being available.
CPSound delegate:
- sound:didFinishPlaying: called when sound has finished to played
*/
@implementation CPSound : CPObject
{
CPString _name @accessors(property=name);
id _delegate @accessors(property=delegate);
HTMLAudioElement _audioTag;
int _loadStatus;
int _playBackStatus;
}
#pragma mark -
#pragma mark Initialization
- (id)init
{
if (self = [super init])
{
_loadStatus = CPSoundLoadStateEmpty;
_loops = NO;
_audioTag = document.createElement("audio");
_audioTag.preload = YES;
_audioTag.addEventListener("canplay", function()
{
[self _soundDidload];
});
_audioTag.addEventListener("ended", function()
{
[self _soundDidEnd];
});
}
return self;
}
/*!
Initialize with the sound contents of the URL represented by aFile.
@param aFile CPString the path of the sound
@param byRef ignored (Cocoa compatibility)
*/
- (id)initWithContentsOfFile:(CPString)aFile byReference:(BOOL)byRef
{
if (self = [self init])
{
_loadStatus = CPSoundLoadStateLoading;
_audioTag.src = aFile;
}
return self;
}
/*!
Initialize with the sound contents of the file located at aURL.
@param aURL CPURL containing the URL of the sound
@param byRef ignored (Cocoa compatibility)
*/
- (id)initWithContentsOfURL:(CPURL)aURL byReference:(BOOL)byRef
{
return [self initWithContentsOfFile:[aURL absoluteString] byReference:NO];
}
/*!
Initialize with the sound contents of someData.
@param someData CPData containing the sound
@param byRef ignored (Cocoa compatibility)
*/
- (id)initWithData:(CPData)someData
{
if (self = [self init])
{
_loadStatus = CPSoundLoadStateLoading;
_audioTag.src = [someData rawString];
}
return self;
}
#pragma mark -
#pragma mark Events listener
/*! @ignore
*/
- (void)_soundDidload
{
_loadStatus = CPSoundLoadStateCanBePlayed;
}
/*! @ignore
*/
- (void)_soundDidEnd
{
if (![self loops])
[self stop];
}
#pragma mark -
#pragma mark Media controls
/*!
Play the sound.
*/
- (void)play
{
if ((_loadStatus !== CPSoundLoadStateCanBePlayed)
|| (_playBackStatus === CPSoundPlayBackStatePlay))
return;
_audioTag.play();
_playBackStatus = CPSoundPlayBackStatePlay;
}
/*!
Stop the sound.
*/
- (void)stop
{
if ((_loadStatus !== CPSoundLoadStateCanBePlayed)
|| (_playBackStatus === CPSoundPlayBackStateStop))
return;
_audioTag.pause();
_audioTag.currentTime = 0.0;
_playBackStatus = CPSoundPlayBackStateStop;
if (_delegate && [_delegate respondsToSelector:@selector(sound:didFinishPlaying:)])
[_delegate sound:self didFinishPlaying:YES];
}
/*!
Pause the sound.
*/
- (void)pause
{
if ((_loadStatus !== CPSoundLoadStateCanBePlayed)
|| (_playBackStatus === CPSoundPlayBackStatePause))
return;
_audioTag.pause();
_playBackStatus = CPSoundPlayBackStatePause;
}
/*!
Resume playback of a paused sound.
*/
- (void)resume
{
if ((_loadStatus !== CPSoundLoadStateCanBePlayed)
|| (_playBackStatus !== CPSoundPlayBackStatePause))
return;
_audioTag.play();
_playBackStatus = CPSoundPlayBackStatePlay;
}
/*!
Return YES if the sound is in loop mode.
@return BOOL YES if in loop mode, NO otherwise
*/
- (BOOL)loops
{
return _audioTag.loop;
}
/*!
Specifies whether the sound should repeat.
@param BOOL YES for loop mode, NO otherwise
*/
- (void)setLoops:(BOOL)shouldLoop
{
_audioTag.loop = shouldLoop;
}
/*!
Returns the volume of the receiver.
@return double from 0.0 to 1.0
*/
- (double)volume
{
return _audioTag.volume;
}
/*!
Set the volume the sound should be played at.
@param double a volume value between 0.0 and 1.0
*/
- (void)setVolume:(double)aVolume
{
if (aVolume > 1.0)
aVolume = 1.0;
else if (aVolume < 0.0)
aVolume = 0.0;
_audioTag.volume = aVolume;
}
#pragma mark -
#pragma mark Accessors
/*!
Returns the duration in seconds of the sound.
@return double the duration
*/
- (double)duration
{
return _audioTag.duration;
}
/*!
Returns if the sound is playing or not.
@return BOOL YES if the sound is playing, NO otherwise
*/
- (BOOL)isPlaying
{
return (_playBackStatus === CPSoundPlayBackStatePlay);
}
@end
+126 -13
View File
@@ -33,6 +33,14 @@ var CPSplitViewHorizontalImage = nil,
/*!
@ingroup appkit
@class CPSplitView
CPSplitView is a view that allows you to stack several subviews vertically or horizontally. The user is given divider to resize the subviews.
The divider indices are zero-based. So the divider on the top (or left for vertical dividers) will be index 0.
CPSplitView can be supplied a delegate to provide control over the resizing of the splitview and subviews. Those methods are documented in setDelegate:
CPSplitView will add dividers for each subview you add. So just like adding subviews to a CPView you should call addSubview: to add new resizable subviews in your splitview.
*/
@implementation CPSplitView : CPView
@@ -96,16 +104,28 @@ var CPSplitViewHorizontalImage = nil,
return self;
}
/*!
Returns the thickness of the divider.
@return float - the thickness of the divider.
*/
- (float)dividerThickness
{
return [self currentValueForThemeAttribute:[self isPaneSplitter] ? @"pane-divider-thickness" : @"divider-thickness"];
}
/*!
Returns YES if the dividers are vertical, otherwise NO.
@return YES if vertical, otherwise NO.
*/
- (BOOL)isVertical
{
return _isVertical;
}
/*!
Sets if the splitview dividers are vertical.
@param shouldBeVertical - YES if the splitview dividers should be vertical, otherwise NO.
*/
- (void)setVertical:(BOOL)shouldBeVertical
{
if (![self _setVertical:shouldBeVertical])
@@ -147,11 +167,21 @@ var CPSplitViewHorizontalImage = nil,
return changed;
}
/*!
Use to find if the divider is a larger pane splitter.
@return BOOL - YES if the dividers are the larger pane splitters. Otherwise NO.
*/
- (BOOL)isPaneSplitter
{
return _isPaneSplitter;
}
/*!
Used to set if the split view dividers should be the larger pane splitter.
@param shouldBePaneSplitter - YES if the dividers should be the thicker pane splitter, otherwise NO.
*/
- (void)setIsPaneSplitter:(BOOL)shouldBePaneSplitter
{
if (_isPaneSplitter == shouldBePaneSplitter)
@@ -173,11 +203,22 @@ var CPSplitViewHorizontalImage = nil,
_needsResizeSubviews = YES;
}
/*!
Returns YES if the supplied subview is collapsed, otherwise NO.
@param aSubview - the subview you are interested in.
@return BOOL - YES if the subview is collapsed, otherwise NO.
*/
- (BOOL)isSubviewCollapsed:(CPView)subview
{
return [subview frame].size[_sizeComponent] < 1 ? YES : NO;
}
/*!
Returns the CGRect of the divider at a given index.
@param int - The index of a divider.
@return CGRect - The rect of a divider.
*/
- (CGRect)rectOfDividerAtIndex:(int)aDivider
{
var frame = [_subviews[aDivider] frame],
@@ -191,6 +232,12 @@ var CPSplitViewHorizontalImage = nil,
return rect;
}
/*!
Returns the rect of the divider which the user is able to drag to resize.
@param int - The index of the divider.
@return CGRect - The rect the user can drag.
*/
- (CGRect)effectiveRectOfDividerAtIndex:(int)aDivider
{
var realRect = [self rectOfDividerAtIndex:aDivider],
@@ -212,7 +259,10 @@ var CPSplitViewHorizontalImage = nil,
[self drawDividerInRect:[self rectOfDividerAtIndex:count]];
}
}
/*!
Draws the divider at a given rect.
@param aRect - the rect of the divider to draw.
*/
- (void)drawDividerInRect:(CGRect)aRect
{
#if PLATFORM(DOM)
@@ -485,6 +535,11 @@ var CPSplitViewHorizontalImage = nil,
[[CPCursor arrowCursor] set];
}
/*!
Returns the maximum possible position of a divider at a given index.
@param the index of the divider.
@return float - the max possible position.
*/
- (float)maxPossiblePositionOfDividerAtIndex:(int)dividerIndex
{
var frame = [_subviews[dividerIndex + 1] frame];
@@ -495,6 +550,11 @@ var CPSplitViewHorizontalImage = nil,
return [self frame].size[_sizeComponent] - [self dividerThickness];
}
/*!
Returns the minimum possible position of a divider at a given index.
@param the index of the divider.
@return float - the min possible position.
*/
- (float)minPossiblePositionOfDividerAtIndex:(int)dividerIndex
{
if (dividerIndex > 0)
@@ -535,6 +595,11 @@ var CPSplitViewHorizontalImage = nil,
return realPosition;
}
/*!
Sets the position of a divider at a given index.
@param position - The float value of the position to place the divider.
@param dividerIndex - The index of the divider to position.
*/
- (void)setPosition:(float)position ofDividerAtIndex:(int)dividerIndex
{
[self _adjustSubviewsWithCalculatedSize];
@@ -621,17 +686,20 @@ var CPSplitViewHorizontalImage = nil,
viewFrame = CGRectMakeCopy(bounds),
isSizable = isVertical ? [view autoresizingMask] & CPViewWidthSizable : [view autoresizingMask] & CPViewHeightSizable;
if (index + 1 == count)
viewFrame.size[_sizeComponent] = bounds.size[_sizeComponent] - viewFrame.origin[_originComponent];
else if (totalSizableSpace && isSizable && lastSizableIndex === index)
viewFrame.size[_sizeComponent] = MAX(0, ROUND([view frame].size[_sizeComponent] + remainingFlexibleSpace))
else if (isSizable || !totalSizableSpace)
{
viewFrame.size[_sizeComponent] = MAX(0, ROUND(ratio * [view frame].size[_sizeComponent]));
remainingFlexibleSpace -= (viewFrame.size[_sizeComponent] - [view frame].size[_sizeComponent]);
}
else if (totalSizableSpace && !isSizable)
viewFrame.size[_sizeComponent] = [view frame].size[_sizeComponent];
if (index + 1 === count)
viewFrame.size[_sizeComponent] = bounds.size[_sizeComponent] - viewFrame.origin[_originComponent];
else if (totalSizableSpace && isSizable && lastSizableIndex === index)
viewFrame.size[_sizeComponent] = MAX(0, ROUND([view frame].size[_sizeComponent] + remainingFlexibleSpace))
else if (isSizable || !totalSizableSpace)
{
viewFrame.size[_sizeComponent] = MAX(0, ROUND(ratio * [view frame].size[_sizeComponent]));
remainingFlexibleSpace -= (viewFrame.size[_sizeComponent] - [view frame].size[_sizeComponent]);
}
else if (totalSizableSpace && !isSizable)
viewFrame.size[_sizeComponent] = [view frame].size[_sizeComponent];
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
@@ -641,6 +709,48 @@ var CPSplitViewHorizontalImage = nil,
[self _postNotificationDidResize];
}
/*!
Sets the delegate of the receiver.
Possible delegate methods to implement are listed below.
<pre>
- (void)splitViewDidResizeSubviews:(CPSplitView)aSplitView;
Notifies the delegate when the subviews have resized.
- (void)splitViewWillResizeSubviews:(CPSplitView)aSplitView;
Notifies the delegate when the subviews will be resized.
- (CGRect)splitView:(CPSplitView)aSplitView effectiveRect:(CGRect)aRect forDrawnRect:(CGRect)aDrawnRect ofDividerAtIndex:(int)aDividerIndex;
Lets the delegate specify a different rect for which the user can drag the splitView divider.
- (CGRect)splitView:(CPSplitView)aSplitView additionalEffectiveRectOfDividerAtIndex:(int)indexOfDivider;
Lets the delegate specify an additional rect for which the user can drag the splitview divider.
- (BOOL)splitView:(CPSplitView)aSplitView canCollapseSubview:(CPView)aSubview;
Notifies the delegate that the splitview is about to be collapsed. This usually happens when the user
Double clicks on the divider. Return YES if the subview can be collapsed, otherwise NO.
- (BOOL)splitView:(CPSplitView)aSplitView shouldCollapseSubview:(CPView)aSubview;
Notifies the delegate that the splitview is about to be collapsed. This usually happens when the user
Double clicks on the divider. Return YES if the subview should be collapsed, otherwise NO.
- (float)splitView:(CPSplitView)aSpiltView constrainSplitPosition:(float)proposedPosition ofSubviewAt:(int)subviewIndex;
Allows the delegate to constrain the subview beings resized. This method is called continuously as the user resizes the divider.
For example if the subview needs to have a width which is a multiple of a certain number you could return that multiple with this method.
- (float)splitView:(CPSplitView)aSplitView constrainMinCoordinate:(float)proposedMin ofSubviewAt:(int)subviewIndex;
Allows the delegate to constrain the minimum position of a subview.
- (float)splitView:(CPSplitView)aSplitView constrainMaxCoordinate:(float)proposedMax ofSubviewAt:(int)subviewIndex;
Allows the delegate to constrain the maximum position of a subview.
- (void)splitView:(CPSplitView)aSplitView resizeSubviewsWithOldSize:(CGSize)oldSize;
Allows the splitview to specify a custom resizing behavior. This is called when the splitview is resized.
The sum of the views and the sum of the dividers should be equal to the size of the splitview.
</pre>
@param delegate - The delegate of the splitview.
*/
- (void)setDelegate:(id)delegate
{
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
@@ -673,6 +783,9 @@ var CPSplitViewHorizontalImage = nil,
This method will automatically configure the hasResizeControl and resizeControlIsLeftAligned
parameters of the button bar, and will override any currently set values.
@param CPButtonBar - The supplied button bar.
@param unsigned int - The divider index the button bar will be assigned to.
*/
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex
{
@@ -738,7 +851,7 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
_buttonBars = [aCoder decodeObjectForKey:CPSplitViewButtonBarsKey] || [];
_delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];
[self setDelegate:[aCoder decodeObjectForKey:CPSplitViewDelegateKey]];
_isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey];
[self _setVertical:[aCoder decodeBoolForKey:CPSplitViewIsVerticalKey]];
+344
View File
@@ -0,0 +1,344 @@
/*
* CPStepper.j
* AppKit
*
* Created by Antoine Mercadal
* Copyright 2009, Antoine Mercadal
*
* 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/CPControl.j>
@import <AppKit/CPButton.j>
@import <AppKit/CPTextField.j>
var CPStepperButtonsSize = CPSizeMake(19, 13);
/*! CPStepper is an implementation of Cocoa NSStepper.
This control display a two part button that can be used to increase or decrease a value with a given interval.
*/
@implementation CPStepper: CPControl
{
BOOL _valueWraps @accessors(property=valueWraps);
int _increment @accessors(property=increment);
int _maxValue @accessors(property=maxValue);
int _minValue @accessors(property=minValue);
_CPContinuousButton _buttonDown;
_CPContinuousButton _buttonUp;
}
#pragma mark -
#pragma mark Initialization
/*! Initializes a CPStepper with given values
@param aValue the initial value of the CPStepper
@param minValue the minimal acceptable value of the stepper
@param maxValue the maximal acceptable value of the stepper
@return Initialized CPStepper
*/
+ (CPStepper)stepperWithInitialValue:(float)aValue minValue:(float)aMinValue maxValue:(float)aMaxValue
{
var stepper = [[CPStepper alloc] initWithFrame:CPRectMake(0, 0, 19, 25)];
[stepper setDoubleValue:aValue];
[stepper setMinValue:aMinValue];
[stepper setMaxValue:aMaxValue];
return stepper;
}
/*! Initializes a CPStepper with default values:
- minValue = 0.0
- maxValue = 59.0
- value = 0.0
@return Initialized CPStepper
*/
+ (CPStepper)stepper
{
return [CPStepper stepperWithInitialValue:0.0 minValue:0.0 maxValue:59.0];
}
/*! Initializes the CPStepper
@param aFrame the frame of the control
@return initialized CPStepper
*/
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
_maxValue = 59.0;
_minValue = 0.0;
_increment = 1.0;
_valueWraps = YES;
[self setDoubleValue:0.0];
_buttonUp = [[_CPContinuousButton alloc] initWithFrame:CPRectMake(aFrame.size.width - CPStepperButtonsSize.width, 0, CPStepperButtonsSize.width, CPStepperButtonsSize.height)];
[_buttonUp setContinuous:YES];
[_buttonUp setTarget:self];
[_buttonUp setAction:@selector(_buttonDidClick:)];
[_buttonUp setAutoresizingMask:CPViewNotSizable];
[self addSubview:_buttonUp];
_buttonDown = [[_CPContinuousButton alloc] initWithFrame:CPRectMake(aFrame.size.width - CPStepperButtonsSize.width, CPStepperButtonsSize.height, CPStepperButtonsSize.width, CPStepperButtonsSize.height - 1)];
[_buttonDown setContinuous:YES];
[_buttonDown setTarget:self];
[_buttonDown setAction:@selector(_buttonDidClick:)];
[_buttonDown setAutoresizingMask:CPViewNotSizable];
[self addSubview:_buttonDown];
[self setNeedsLayout];
}
return self;
}
#pragma mark -
#pragma mark Superclass overrides
/*! set if the CPStepper is enabled or not
@param shouldEnabled BOOL that define if stepper is enabled or not.
*/
- (void)setEnabled:(BOOL)shouldEnabled
{
[super setEnabled:shouldEnabled];
[_buttonUp setEnabled:shouldEnabled];
[_buttonDown setEnabled:shouldEnabled];
}
/*! set the frame of the CPStepper and check if width is not smaller than theme min-size
@param aFrame the frame
*/
- (void)setFrame:(CGRect)aFrame
{
if (aFrame.size.width >= CGRectGetWidth(aFrame))
[super setFrame:aFrame];
}
/*! @ignore
*/
- (void)layoutSubviews
{
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered | CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateDisabled];
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered | CPThemeStateHighlighted] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateHighlighted];
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:CPThemeStateBordered] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:CPThemeStateBordered | CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateDisabled];
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:CPThemeStateBordered | CPThemeStateHighlighted] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateHighlighted];
}
/*! set if CPStepper should autorepeat
@param shouldAutoRepeat if YES, the first mouse down does one increment (decrement) and, after each delay of 0.5 seconds
*/
- (void)setAutorepeat:(BOOL)shouldAutoRepeat
{
[_buttonUp setContinuous:shouldAutoRepeat];
[_buttonDown setContinuous:shouldAutoRepeat];
}
/*! set the current value of the stepper
@param aValue a float containing the value
*/
- (void)setDoubleValue:(float)aValue
{
if (aValue > _maxValue)
[super setDoubleValue:_valueWraps ? _minValue : _maxValue];
else if (aValue < _minValue)
[super setDoubleValue:_valueWraps ? _maxValue : _minValue];
else
[super setDoubleValue:aValue];
}
#pragma mark -
#pragma mark Actions
/*! @ignore
*/
- (IBAction)_buttonDidClick:(id)aSender
{
if (![self isEnabled])
return;
if (aSender == _buttonUp)
[self setDoubleValue:([self doubleValue] + _increment)];
else
[self setDoubleValue:([self doubleValue] - _increment)];
if (_target && _action && [_target respondsToSelector:_action])
[self sendAction:_action to:_target];
}
/*! @perform a programatic click on up button
@param aSender sender of the action
*/
- (IBAction)performClickUp:(id)aSender
{
[_buttonUp performClick:aSender];
}
/*! @perform a programatic click on down button
@param aSender sender of the action
*/
- (IBAction)performClickDown:(id)aSender
{
[_buttonDown performClick:aSender];
}
#pragma mark -
#pragma mark Theming
+ (CPString)defaultThemeClass
{
return @"stepper";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPNull null]]
forKeys:[@"bezel-color-up-button", @"bezel-color-down-button"]];
}
@end
@implementation CPStepper (CPCodingCompliance)
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_maxValue = [aCoder decodeObjectForKey:@"_maxValue"];
_minValue = [aCoder decodeObjectForKey:@"_minValue"];
_increment = [aCoder decodeObjectForKey:@"_increment"];
_buttonUp = [aCoder decodeObjectForKey:@"_buttonUp"];
_buttonDown = [aCoder decodeObjectForKey:@"_buttonDown"];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_maxValue forKey:@"_maxValue"];
[aCoder encodeObject:_minValue forKey:@"_minValue"];
[aCoder encodeObject:_increment forKey:@"_increment"];
[aCoder encodeObject:_buttonUp forKey:@"_buttonUp"];
[aCoder encodeObject:_buttonDown forKey:@"_buttonDown"];
}
@end
/*! This is a subclass of CPButton that allows to send continuous action.
This may should be include in CPButton..
*/
@implementation _CPContinuousButton : CPButton
{
CPTimer _continuousDelayTimer;
CPTimer _continuousTimer;
float _periodicDelay;
float _periodicInterval;
}
- (void)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
_periodicInterval = 0.05;
_periodicDelay = 0.5;
}
return self;
}
- (void)setPeriodicDelay:(float)aDelay interval:(float)anInterval
{
_periodicDelay = aDelay;
_periodicInterval = anInterval;
}
- (void)mouseDown:(CPEvent)anEvent
{
if ([self isContinuous])
{
_continuousDelayTimer = [CPTimer scheduledTimerWithTimeInterval:_periodicDelay callback: function()
{
if (!_continuousTimer)
_continuousTimer = [CPTimer scheduledTimerWithTimeInterval:_periodicInterval target:self selector:@selector(onContinousEvent:) userInfo:anEvent repeats:YES];
}
repeats:NO];
}
[super mouseDown:anEvent];
}
- (void)onContinousEvent:(CPTimer)aTimer
{
if (_target && _action && [_target respondsToSelector:_action])
[_target performSelector:_action withObject:self];
}
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
{
[self invalidateTimers];
[super stopTracking:lastPoint at:aPoint mouseIsUp:mouseIsUp];
}
- (void)invalidateTimers
{
if (_continuousTimer)
{
[_continuousTimer invalidate];
_continuousTimer = nil;
}
if (_continuousDelayTimer)
{
[_continuousDelayTimer invalidate];
_continuousDelayTimer = nil;
}
}
@end
@implementation _CPContinuousButton (CPCodingCompliance)
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_periodicDelay = [aCoder decodeObjectForKey:@"_periodicDelay"];
_periodicInterval = [aCoder decodeObjectForKey:@"_periodicInterval"];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[self invalidateTimers];
[aCoder encodeObject:_periodicDelay forKey:@"_periodicDelay"];
[aCoder encodeObject:_periodicInterval forKey:@"_periodicInterval"];
}
@end
+137 -131
View File
@@ -3,83 +3,66 @@
@import "CPTabViewItem.j"
@import "CPView.j"
/*
Places tabs on top with a bezeled border.
@global
@group CPTabViewType
*/
CPTopTabsBezelBorder = 0;
//CPLeftTabsBezelBorder = 1;
//CPLeftTabsBezelBorder = 1;
CPBottomTabsBezelBorder = 2;
//CPRightTabsBezelBorder = 3;
/*
Displays no tabs and has a bezeled border.
@global
@group CPTabViewType
*/
CPNoTabsBezelBorder = 4;
/*
Has no tabs and displays a line border.
@global
@group CPTabViewType
*/
CPNoTabsLineBorder = 5;
/*
Displays no tabs and no border.
@global
@group CPTabViewType
*/
CPNoTabsNoBorder = 6;
//CPRightTabsBezelBorder = 3;
CPNoTabsBezelBorder = 4; //Displays no tabs and has a bezeled border.
CPNoTabsLineBorder = 5; //Has no tabs and displays a line border.
CPNoTabsNoBorder = 6; //Displays no tabs and no border.
var CPTabViewDidSelectTabViewItemSelector = 1,
CPTabViewShouldSelectTabViewItemSelector = 2,
CPTabViewWillSelectTabViewItemSelector = 4,
CPTabViewDidChangeNumberOfTabViewItemsSelector = 8;
var HEIGHT_OF_SEGMENTED_CONTROL = 24;
@implementation CPTabView : CPView
{
CPArray items;
CPArray _items;
CPSegmentedControl tabs;
CPBox box;
CPSegmentedControl _tabs;
CPBox _box;
CPNumber selectedIndex;
CPNumber _selectedIndex;
CPTabViewType type;
CPTabViewType _type;
id delegate;
unsigned delegateSelectors;
id _delegate;
unsigned _delegateSelectors;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
if (self = [super initWithFrame:aFrame])
{
items = [CPArray array];
tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, HEIGHT_OF_SEGMENTED_CONTROL)];
[tabs setHitTests:NO];
box = [[CPBox alloc] initWithFrame:CGRectMake(0, HEIGHT_OF_SEGMENTED_CONTROL / 2, CGRectGetWidth(aFrame),
CGRectGetHeight(aFrame) - HEIGHT_OF_SEGMENTED_CONTROL)];
selectedIndex = CPNotFound;
_items = [CPArray array];
_selectedIndex = CPNotFound;
[self _init];
[self setTabViewType:CPTopTabsBezelBorder];
[self setBackgroundColor:[CPColor colorWithCalibratedWhite:0.95 alpha:1.0]];
[self addSubview:box];
[self addSubview:tabs];
[box setAutoresizingMask:CPViewWidthSizable];
[tabs setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin];
}
return self;
}
- (void)_init
{
_tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[_tabs setHitTests:NO];
var height = [_tabs valueForThemeAttribute:@"default-height"];
[_tabs setFrameSize:CGSizeMake(0, height)];
_box = [[CPBox alloc] initWithFrame:[self bounds]];
[self setBackgroundColor:[CPColor colorWithCalibratedWhite:0.95 alpha:1.0]];
[_box setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_tabs setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin];
[self addSubview:_box];
[self addSubview:_tabs];
}
// Adding and Removing Tabs
/*!
Adds a CPTabViewItem to the tab view.
@@ -87,7 +70,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)addTabViewItem:(CPTabViewItem)aTabViewItem
{
[self insertTabViewItem:aTabViewItem atIndex:[items count]];
[self insertTabViewItem:aTabViewItem atIndex:[_items count]];
}
/*!
@@ -98,13 +81,15 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)insertTabViewItem:(CPTabViewItem)aTabViewItem atIndex:(unsigned)anIndex
{
[items insertObject:aTabViewItem atIndex:anIndex];
[_items insertObject:aTabViewItem atIndex:anIndex];
[self _updateItems];
[self _repositionTabs];
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[delegate tabViewDidChangeNumberOfTabViewItems:self];
[aTabViewItem _setTabView:self];
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
}
/*!
@@ -113,19 +98,23 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)removeTabViewItem:(CPTabViewItem)aTabViewItem
{
for (var i = 0; i < [items count]; i++)
var count = [_items count];
for (var i = 0; i < count; i++)
{
if ([items objectAtIndex:i] === aTabViewItem)
if ([_items objectAtIndex:i] === aTabViewItem)
{
[items removeObjectAtIndex:i];
[_items removeObjectAtIndex:i];
break;
}
}
[self _updateItems];
[self _repositionTabs];
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[delegate tabViewDidChangeNumberOfTabViewItems:self];
[aTabViewItem _setTabView:nil];
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
}
// Accessing Tabs
@@ -135,7 +124,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (int)indexOfTabViewItem:(CPTabViewItem)aTabViewItem
{
return [items indexOfObjectIdenticalTo:aTabViewItem];
return [_items indexOfObjectIdenticalTo:aTabViewItem];
}
/*!
@@ -144,8 +133,8 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (int)indexOfTabViewItemWithIdentifier:(CPString)anIdentifier
{
for (var index = [items count]; index >= 0; index--)
if ([[items[index] identifier] isEqual:anIdentifier])
for (var index = [_items count]; index >= 0; index--)
if ([[_items[index] identifier] isEqual:anIdentifier])
return index;
return CPNotFound;
@@ -156,7 +145,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (unsigned)numberOfTabViewItems
{
return [items count];
return [_items count];
}
/*!
@@ -164,7 +153,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (CPTabViewItem)tabViewItemAtIndex:(unsigned)anIndex
{
return [items objectAtIndex:anIndex];
return [_items objectAtIndex:anIndex];
}
/*!
@@ -172,7 +161,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (CPArray)tabViewItems
{
return [items copy]; // Copy?
return [_items copy]; // Copy?
}
// Selecting a Tab
@@ -182,7 +171,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectFirstTabViewItem:(id)aSender
{
if ([items count] === 0)
if ([_items count] === 0)
return; // throw?
[self selectTabViewItemAtIndex:0];
@@ -194,10 +183,10 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectLastTabViewItem:(id)aSender
{
if ([items count] === 0)
if ([_items count] === 0)
return; // throw?
[self selectTabViewItemAtIndex:[items count] - 1];
[self selectTabViewItemAtIndex:[_items count] - 1];
}
/*!
@@ -206,12 +195,12 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectNextTabViewItem:(id)aSender
{
if (selectedIndex === CPNotFound)
if (_selectedIndex === CPNotFound)
return;
var nextIndex = selectedIndex + 1;
var nextIndex = _selectedIndex + 1;
if (nextIndex === [items count])
if (nextIndex === [_items count])
// does nothing. According to spec at (http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/ApplicationKit/Classes/NSTabView_Class/Reference/Reference.html#//apple_ref/occ/instm/NSTabView/selectNextTabViewItem:)
return;
@@ -224,10 +213,10 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectPreviousTabViewItem:(id)aSender
{
if (selectedIndex === CPNotFound)
if (_selectedIndex === CPNotFound)
return;
var previousIndex = selectedIndex - 1;
var previousIndex = _selectedIndex - 1;
if (previousIndex < 0)
return; // does nothing. See above.
@@ -250,24 +239,24 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectTabViewItemAtIndex:(unsigned)anIndex
{
var aTabViewItem = [items objectAtIndex:anIndex];
var aTabViewItem = [_items objectAtIndex:anIndex];
if (anIndex === selectedIndex)
if (anIndex === _selectedIndex)
return;
var aTabViewItem = [self tabViewItemAtIndex:anIndex];
if ((delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![delegate tabView:self shouldSelectTabViewItem:aTabViewItem])
if ((_delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![_delegate tabView:self shouldSelectTabViewItem:aTabViewItem])
return;
if (delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
[delegate tabView:self willSelectTabViewItem:aTabViewItem];
if (_delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
[_delegate tabView:self willSelectTabViewItem:aTabViewItem];
[tabs selectSegmentWithTag:anIndex];
[_tabs selectSegmentWithTag:anIndex];
[self _setSelectedIndex:anIndex];
if (delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
[delegate tabView:self didSelectTabViewItem:aTabViewItem];
if (_delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
[_delegate tabView:self didSelectTabViewItem:aTabViewItem];
}
/*!
@@ -275,7 +264,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (CPTabViewItem)selectedTabViewItem
{
return [items objectAtIndex:selectedIndex];
return [_items objectAtIndex:_selectedIndex];
}
//
@@ -285,31 +274,40 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)setTabViewType:(CPTabViewType)aTabViewType
{
if (type === aTabViewType)
if (_type === aTabViewType)
return;
if ((type === CPTopTabsBezelBorder || type === CPBottomTabsBezelBorder)
&& (aTabViewType !== CPTopTabsBezelBorder && aTabViewType !== CPBottomTabsBezelBorder))
[tabs removeFromSuperview];
_type = aTabViewType;
if ((type === CPNoTabsBezelBorder || type === CPNoTabsLineBorder || type === CPNoTabsNoBorder)
&& (aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsNoBorder))
[self addSubview:tabs];
if (_type !== CPTopTabsBezelBorder && _type !== CPBottomTabsBezelBorder)
{
[_box setFrame:[self bounds]];
[_tabs removeFromSuperview];
}
else
{
var aFrame = [self frame],
segmentedHeight = CGRectGetHeight([_tabs frame]),
origin = _type === CPTopTabsBezelBorder ? segmentedHeight / 2 : 0;
type = aTabViewType;
[_box setFrame:CGRectMake(0, origin, CGRectGetWidth(aFrame),
CGRectGetHeight(aFrame) - segmentedHeight / 2)];
switch (type)
[self addSubview:_tabs];
}
switch (_type)
{
case CPTopTabsBezelBorder:
case CPBottomTabsBezelBorder:
case CPNoTabsBezelBorder:
[box setBorderType:CPBezelBorder];
[_box setBorderType:CPBezelBorder];
break;
case CPNoTabsLineBorder:
[box setBorderType:CPLineBorder];
[_box setBorderType:CPLineBorder];
break;
case CPNoTabsNoBorder:
[box setBorderType:CPNoBorder];
[_box setBorderType:CPNoBorder];
break;
}
}
@@ -319,7 +317,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (CPTabViewType)tabViewType
{
return type;
return _type;
}
/*!
@@ -327,7 +325,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (id)delegate
{
return delegate;
return _delegate;
}
/*!
@@ -336,71 +334,77 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)setDelegate:(id)aDelegate
{
if (delegate == aDelegate)
if (_delegate == aDelegate)
return;
delegate = aDelegate;
_delegate = aDelegate;
delegateSelectors = 0;
_delegateSelectors = 0;
if ([delegate respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)])
delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector;
if ([_delegate respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)])
_delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)])
delegateSelectors |= CPTabViewWillSelectTabViewItemSelector;
if ([_delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)])
_delegateSelectors |= CPTabViewWillSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)])
delegateSelectors |= CPTabViewDidSelectTabViewItemSelector;
if ([_delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)])
_delegateSelectors |= CPTabViewDidSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)])
delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector;
if ([_delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)])
_delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector;
}
- (void)setBackgroundColor:(CPColor)aColor
{
[box setBackgroundColor:aColor];
[_box setBackgroundColor:aColor];
}
- (CPColor)backgroundColor
{
return [_box backgroundColor];
}
- (void)mouseDown:(CPEvent)anEvent
{
var segmentIndex = [tabs testSegment:[tabs convertPoint:[anEvent locationInWindow] fromView:nil]];
var segmentIndex = [_tabs testSegment:[_tabs convertPoint:[anEvent locationInWindow] fromView:nil]];
if (segmentIndex != CPNotFound)
{
[self selectTabViewItemAtIndex:segmentIndex];
[tabs trackSegment:anEvent];
[_tabs trackSegment:anEvent];
}
}
- (void)_repositionTabs
{
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
verticalCenterOfTabs = CGRectGetHeight([tabs bounds]) / 2;
verticalCenterOfTabs = CGRectGetHeight([_tabs bounds]) / 2;
if (type === CPBottomTabsBezelBorder)
[tabs setCenter:CGPointMake(horizontalCenterOfSelf, CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
if (_type === CPBottomTabsBezelBorder)
[_tabs setCenter:CGPointMake(horizontalCenterOfSelf, CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
else
[tabs setCenter:CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
[_tabs setCenter:CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
}
- (void)_setSelectedIndex:(CPNumber)index
{
selectedIndex = index;
_selectedIndex = index;
[box setContentView:[[items objectAtIndex:selectedIndex] view]];
[_box setContentView:[[_items objectAtIndex:_selectedIndex] view]];
}
- (void)_updateItems
{
[tabs setSegmentCount:[items count]];
var count = [_items count];
[_tabs setSegmentCount:count];
for (var i = 0; i < [items count]; i++)
for (var i = 0; i < count; i++)
{
[tabs setLabel:[[items objectAtIndex:i] label] forSegment:i];
[tabs setTag:i forSegment:i];
[_tabs setLabel:[[_items objectAtIndex:i] label] forSegment:i];
[_tabs setTag:i forSegment:i];
}
if (selectedIndex === CPNotFound)
if (_selectedIndex === CPNotFound)
{
[self selectFirstTabViewItem:self];
}
@@ -419,18 +423,20 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
{
if (self = [super initWithCoder:aCoder])
{
type = [aCoder decodeIntForKey:CPTabViewTypeKey];
items = [];
[self _init];
var encodedItems = [aCoder decodeObjectForKey:CPTabViewItemsKey];
for (var i = 0; encodedItems && i < encodedItems.length; i++)
[self insertTabViewItem:encodedItems[i] atIndex:i];
_items = [aCoder decodeObjectForKey:CPTabViewItemsKey];
[self _updateItems];
[self _repositionTabs];
var selected = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
if (selected)
[self selectTabViewItem:selected];
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
[self setTabViewType:[aCoder decodeIntForKey:CPTabViewTypeKey]];
}
return self;
@@ -440,12 +446,12 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:items forKey:CPTabViewItemsKey];;
[aCoder encodeObject:_items forKey:CPTabViewItemsKey];
[aCoder encodeObject:[self selectedTabViewItem] forKey:CPTabViewSelectedItemKey];
[aCoder encodeInt:type forKey:CPTabViewTypeKey];
[aCoder encodeInt:_type forKey:CPTabViewTypeKey];
[aCoder encodeConditionalObject:delegate forKey:CPTabViewDelegateKey];
[aCoder encodeConditionalObject:_delegate forKey:CPTabViewDelegateKey];
}
@end
+12 -12
View File
@@ -44,7 +44,7 @@ CPBackgroundTab = 1;
*/
CPPressedTab = 2;
/*!
/*!
@ingroup appkit
@class CPTabViewItem
@@ -55,10 +55,10 @@ CPPressedTab = 2;
{
id _identifier;
CPString _label;
CPView _view;
CPView _auxiliaryView;
CPTabView _tabView;
}
@@ -74,10 +74,10 @@ CPPressedTab = 2;
- (id)initWithIdentifier:(id)anIdentifier
{
self = [super init];
if (self)
_identifier = anIdentifier;
return self;
}
@@ -145,8 +145,8 @@ CPPressedTab = 2;
// Assigning an Auxiliary View
/*!
Sets the tab's auxillary view.
@param anAuxillaryView the new auxillary view
Sets the tab's auxiliary view.
@param anAuxiliaryView the new auxiliary view
*/
- (void)setAuxiliaryView:(CPView)anAuxiliaryView
{
@@ -154,7 +154,7 @@ CPPressedTab = 2;
}
/*!
Returns the tab's auxillary view
Returns the tab's auxiliary view
*/
- (CPView)auxiliaryView
{
@@ -191,16 +191,16 @@ var CPTabViewItemIdentifierKey = "CPTabViewItemIdentifierKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_identifier = [aCoder decodeObjectForKey:CPTabViewItemIdentifierKey];
_label = [aCoder decodeObjectForKey:CPTabViewItemLabelKey];
_view = [aCoder decodeObjectForKey:CPTabViewItemViewKey];
_auxiliaryView = [aCoder decodeObjectForKey:CPTabViewItemAuxViewKey];
}
return self;
}
@@ -208,7 +208,7 @@ var CPTabViewItemIdentifierKey = "CPTabViewItemIdentifierKey",
{
[aCoder encodeObject:_identifier forKey:CPTabViewItemIdentifierKey];
[aCoder encodeObject:_label forKey:CPTabViewItemLabelKey];
[aCoder encodeObject:_view forKey:CPTabViewItemViewKey];
[aCoder encodeObject:_auxiliaryView forKey:CPTabViewItemAuxViewKey];
}
+236 -26
View File
@@ -33,6 +33,17 @@ CPTableColumnNoResizing = 0;
CPTableColumnAutoresizingMask = 1 << 0;
CPTableColumnUserResizingMask = 1 << 1;
/*!
@class CPTableColumn
A CPTableColumn contains a dataview to display for its column of the CPTableView.
A CPTableColumn determines its own size constrains and resizing behavior.
The default dataview is a CPTextField but you can set it to any view you'd like. See -setDataView: for documentation including theme states.
To customize the text of the column header you can simply call setStringValue: on the headerview of a table column.
For example: [[myTableColumn headerView] setStringValue:"My Title"];
*/
@implementation CPTableColumn : CPObject
{
CPTableView _tableView;
@@ -54,11 +65,18 @@ CPTableColumnUserResizingMask = 1 << 1;
BOOL _disableResizingPosting @accessors(property=disableResizingPosting);
}
/*!
@ignore
*/
- (id)init
{
return [self initWithIdentifier:@""];
}
/*!
Initializes a newly created CPTableColumn with a given identifier.
*/
- (id)initWithIdentifier:(id)anIdentifier
{
self = [super init];
@@ -84,17 +102,50 @@ CPTableColumnUserResizingMask = 1 << 1;
return self;
}
/*!
Set the columns's parent tableview
*/
- (void)setTableView:(CPTableView)aTableView
{
_tableView = aTableView;
}
/*!
Return the column's parent tableview
*/
- (CPTableView)tableView
{
return _tableView;
}
/*!
@ignore
this method tries to resize a column called via the tableview via autoresizing
it returns the delta from the actual resize and the proposed resize
for example if the column should have been resized 50px but the maxWidth was hit only
after 25px then the return value would be 25px;
if no edge has been hit zero will be returned
*/
- (int)_tryToResizeToWidth:(int)width
{
var min = [self minWidth],
max = [self maxWidth],
newWidth = MIN(MAX(width, min), max);
[self setWidth:newWidth];
return newWidth - width;
}
/*!
Set the width of the column
Default value is: 100
If the value is greater than the maxWidth the maxWidth will be reset with the supplied width here
If the value is less than the minWidth the minWidth will be reset with the supplied width.
*/
- (void)setWidth:(float)aWidth
{
aWidth = +aWidth;
@@ -135,11 +186,18 @@ CPTableColumnUserResizingMask = 1 << 1;
}
}
/*!
Returns the column's width
*/
- (float)width
{
return _width;
}
/*!
Sets the minimum width of the column.
Default value is 10.
*/
- (void)setMinWidth:(float)aMinWidth
{
aMinWidth = +aMinWidth;
@@ -156,11 +214,18 @@ CPTableColumnUserResizingMask = 1 << 1;
[self setWidth:newWidth];
}
/*!
Returns the minimum width of the column.
*/
- (float)minWidth
{
return _minWidth;
}
/*!
Sets the maximum width of the table column.
Default value is: 1000000
*/
- (void)setMaxWidth:(float)aMaxWidth
{
aMaxWidth = +aMaxWidth;
@@ -177,21 +242,42 @@ CPTableColumnUserResizingMask = 1 << 1;
[self setWidth:newWidth];
}
/*!
Returns the maximum width of the column
*/
- (float)maxWidth
{
return _maxWidth;
}
/*!
<pre>
Set the resizing mask of the column.
By default the column can be resized automatically with the tableview and manually by the user
Possible masking values are:
CPTableColumnNoResizing
CPTableColumnAutoresizingMask
CPTableColumnUserResizingMask
</pre>
*/
- (void)setResizingMask:(unsigned)aResizingMask
{
_resizingMask = aResizingMask;
}
/*!
Returns the resizing mask of the column
*/
- (unsigned)resizingMask
{
return _resizingMask;
}
/*!
Sizes the column to fix the column header text.
*/
- (void)sizeToFit
{
var width = _CGRectGetWidth([_headerView frame]);
@@ -205,7 +291,16 @@ CPTableColumnUserResizingMask = 1 << 1;
[self setWidth:width];
}
//Setting Component Cells
/*!
Sets the header view for the column.
The headerview handles the display of sort indicators, text, etc.
If you do not want a headerview for you table you should call setHeaderView: on your CPTableView instance.
Passing nil here will throw an exception.
In order to customize the text of the column header see - (CPView)headerView;
*/
- (void)setHeaderView:(CPView)aView
{
if (!aView)
@@ -219,17 +314,31 @@ CPTableColumnUserResizingMask = 1 << 1;
[tableHeaderView setNeedsDisplay:YES];
}
/*!
Returns the headerview for the column.
In order to change the text of the headerview for a column you should call setStringValue: on the headerview.
For example: [[myTableColumn headerView] setStringValue:"My Column"];
*/
- (CPView)headerView
{
return _headerView;
}
/*!
This method set's the "prototype" view which will be used to create all table cells in this column.
<pre>
This method sets the "prototype" view which will be used to create all table cells in this column.
It creates a snapshot of aView, using keyed archiving, which is then copied over and over for each
individual cell that is shown. As a result, changes made after calling this method won't be reflected.
When you set a dataview and it is added to the tableview the theme state will be set to CPThemeStateTableDataView
When the dataview becomes selected the theme state will be set to CPThemeStateSelectedDataView.
If the dataview shows up in a group row of the tableview the theme state will be set to CPThemeStateGroupRow.
You should overide setThemeState: and unsetThemeState: to handle these theme state changes in your dataview.
Example:
[tableColumn setDataView:someView]; // snapshot taken
@@ -239,6 +348,38 @@ CPTableColumnUserResizingMask = 1 << 1;
[someView setSomething:x];
[tableColumn setDataView:someView];
REMEMBER: you should implement CPKeyedArchiving otherwise you might see unexpected results.
This is done by adding the following methods to your class:
- (id)initWithCoder(CPCoder)aCoder;
- (void)encodeWithCoder:(CPCoder)aCoder;
Example:
Say you have two instance variables in your object that need to be set up each time an object is create.
We will call these instance variables "image" and "text".
Your CPCoding methods will look like the following:
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
image = [aCoder decodeObjectForKey:"MyDataViewImage"];
text = [aCoder decodeObjectForKey:"MyDataViewText"];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:image forKey:"MyDataViewImage"];
[aCoder encodeObject:text forKey:"MyDataViewText"];
}
</pre>
*/
- (void)setDataView:(CPView)aView
{
@@ -260,7 +401,7 @@ CPTableColumnUserResizingMask = 1 << 1;
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
potentially use different "cells" or dataViews 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.
*/
@@ -269,6 +410,9 @@ CPTableColumnUserResizingMask = 1 << 1;
return [self dataView];
}
/*!
@ignore
*/
- (id)_newDataViewForRow:(int)aRowIndex
{
var dataView = [self dataViewForRow:aRowIndex],
@@ -294,7 +438,7 @@ CPTableColumnUserResizingMask = 1 << 1;
//Setting the Identifier
/*
/*!
Sets the receiver identifier to anIdentifier.
*/
- (void)setIdentifier:(id)anIdentifier
@@ -302,7 +446,7 @@ CPTableColumnUserResizingMask = 1 << 1;
_identifier = anIdentifier;
}
/*
/*!
Returns the object used by the data source to identify the attribute corresponding to the receiver.
*/
- (id)identifier
@@ -312,7 +456,7 @@ CPTableColumnUserResizingMask = 1 << 1;
//Controlling Editability
/*
/*!
Controls whether the user can edit cells in the receiver by double-clicking them.
*/
- (void)setEditable:(BOOL)shouldBeEditable
@@ -320,7 +464,7 @@ CPTableColumnUserResizingMask = 1 << 1;
_isEditable = shouldBeEditable;
}
/*
/*!
Returns YES if the user can edit cells associated with the receiver by double-clicking the
column in the NSTableView, NO otherwise.
*/
@@ -329,19 +473,26 @@ CPTableColumnUserResizingMask = 1 << 1;
return _isEditable;
}
//Sorting
/*!
Sets the sort descriptor prototype for the column.
*/
- (void)setSortDescriptorPrototype:(CPSortDescriptor)aSortDescriptor
{
_sortDescriptorPrototype = aSortDescriptor;
}
/*!
Returns the sort descriptor prototype for the column.
*/
- (CPSortDescriptor)sortDescriptorPrototype
{
return _sortDescriptorPrototype;
}
//Setting Column Visibility
/*!
If NO the tablecolumn will no longer be visible in the tableview
If YES the tablecolumn will be visible in the tableview.
*/
- (void)setHidden:(BOOL)shouldBeHidden
{
shouldBeHidden = !!shouldBeHidden
@@ -354,6 +505,9 @@ CPTableColumnUserResizingMask = 1 << 1;
[[self tableView] _tableColumnVisibilityDidChange:self];
}
/*!
Returns the visibility status of the column.
*/
- (BOOL)isHidden
{
return _isHidden;
@@ -361,7 +515,7 @@ CPTableColumnUserResizingMask = 1 << 1;
//Setting Tool Tips
/*
/*!
Sets the tooltip string that is displayed when the cursor pauses over the
header cell of the receiver.
*/
@@ -370,13 +524,21 @@ CPTableColumnUserResizingMask = 1 << 1;
_headerToolTip = aToolTip;
}
/*!
Returns the tooltip for the column header
*/
- (CPString)headerToolTip
{
return _headerToolTip;
}
/*!
@ignore
*/
- (void)_postDidResizeNotificationWithOldWidth:(float)oldWidth
{
[[self tableView] _didResizeTableColumn:self];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPTableViewColumnDidResizeNotification
object:[self tableView]
@@ -385,8 +547,40 @@ CPTableColumnUserResizingMask = 1 << 1;
@end
@implementation CPTableColumnValueBinder : CPBinder
{
}
- (void)setValueFor:(CPString)aBinding
{
var tableView = [_source tableView],
column = [[tableView tableColumns] indexOfObjectIdenticalTo:_source],
rowIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [tableView numberOfRows])],
columnIndexes = [CPIndexSet indexSetWithIndex:column];
[tableView reloadDataForRowIndexes:rowIndexes columnIndexes:columnIndexes];
}
@end
@implementation CPTableColumn (Bindings)
+ (id)_binderClassForBinding:(CPString)aBinding
{
if (aBinding == CPValueBinding)
return [CPTableColumnValueBinder class];
return [super _binderClassForBinding:aBinding];
}
/*!
Binds the receiver to an object.
@param CPString aBinding - The binding you wish to make. Typically CPValueBinding.
@param id anObject - The object to bind the receiver to.
@param CPString aKeyPath - The key path you wish to bind the receiver to.
@param CPDictionary options - A dictionary of options for the binding. This parameter is optional, pass nil if you do not wish to use it.
*/
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
{
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
@@ -395,9 +589,12 @@ CPTableColumnUserResizingMask = 1 << 1;
[[self tableView] _establishBindingsIfUnbound:anObject];
}
/*!
@ignore
*/
- (void)prepareDataView:(CPView)aDataView forRow:(unsigned)aRow
{
var bindingsDictionary = [CPKeyValueBinding allBindingsForObject:self],
var bindingsDictionary = [CPBinder allBindingsForObject:self],
keys = [bindingsDictionary allKeys];
for (var i = 0, count = [keys count]; i < count; i++)
@@ -437,9 +634,7 @@ CPTableColumnUserResizingMask = 1 << 1;
}
value = [binding transformValue:value withOptions:[bindingInfo objectForKey:CPOptionsKey]];
// console.log(bindingName+" : "+keyPath+" : "+aRow+" : "+[[destination valueForKeyPath:keyPath] objectAtIndex:aRow]);
[aDataView setValue:value forKey:bindingPath];
[aDataView setValue:value forKey:@"objectValue"];
}
}
@@ -448,11 +643,6 @@ CPTableColumnUserResizingMask = 1 << 1;
// return nil;
//}
- (void)setValue:(CPArray)content
{
[[self tableView] reloadData];
}
@end
var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
@@ -468,6 +658,9 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
@implementation CPTableColumn (CPCoding)
/*!
@ignore
*/
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
@@ -495,6 +688,9 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
return self;
}
/*!
@ignore
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_identifier forKey:CPTableColumnIdentifierKey];
@@ -516,31 +712,45 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
@end
@implementation CPTableColumn (NSInCompatibility)
/*!
@ignore
*/
- (void)setHeaderCell:(CPView)aView
{
[CPException raise:CPUnsupportedMethodException
reason:@"setHeaderCell: is not supported. -setHeaderCell:aView instead."];
reason:@"setHeaderCell: is not supported. Use -setHeaderView:aView instead."];
}
/*!
@ignore
*/
- (CPView)headerCell
{
[CPException raise:CPUnsupportedMethodException
reason:@"headCell is not supported. -headerView instead."];
reason:@"headCell is not supported. Use -headerView instead."];
}
/*!
@ignore
*/
- (void)setDataCell:(CPView)aView
{
[CPException raise:CPUnsupportedMethodException
reason:@"setDataCell: is not supported. Use -setHeaderCell:aView instead."];
reason:@"setDataCell: is not supported. Use -setDataView:aView instead."];
}
/*!
@ignore
*/
- (CPView)dataCell
{
[CPException raise:CPUnsupportedMethodException
reason:@"dataCell is not supported. Use -dataCell instead."];
reason:@"dataCell is not supported. Use -dataView instead."];
}
/*!
@ignore
*/
- (id)dataCellForRow:(int)row
{
[CPException raise:CPUnsupportedMethodException
+22 -14
View File
@@ -56,7 +56,7 @@
{
_textField = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
[_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
[_textField setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_textField setLineBreakMode:CPLineBreakByTruncatingTail];
[_textField setAlignment:CPLeftTextAlignment];
@@ -102,20 +102,20 @@
- (void)setFont:(CPFont)aFont
{
[_textField setFont:aFont];
[self setValue:aFont forThemeAttribute:"text-font"];
}
- (void)_setIndicatorImage:(CPImage)anImage
{
if (anImage)
{
[_textField setImage:anImage];
[_textField setImagePosition:CPImageRight];
}
else
{
[_textField setImagePosition:CPNoImage];
}
if (anImage)
{
[_textField setImage:anImage];
[_textField setImagePosition:CPImageRight];
}
else
{
[_textField setImagePosition:CPNoImage];
}
}
@end
@@ -604,7 +604,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[headerView setFrame:frame];
if([headerView superview] != self)
if ([headerView superview] != self)
[self addSubview:headerView];
}
@@ -634,7 +634,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
columnMaxX;
CGContextBeginPath(context);
for(; columnArrayIndex < columnArrayCount; columnArrayIndex++)
for (; columnArrayIndex < columnArrayCount; columnArrayIndex++)
{
// grab each column rect and add vertical lines
var columnIndex = columnsArray[columnArrayIndex],
@@ -669,7 +669,15 @@ var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey",
{
[self _init];
_tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
_drawsColumnLines = [aCoder decodeBoolForKey:CPTableHeaderViewDrawsColumnLines];
// FIX ME: Take this out before 1.0
if ([aCoder containsValueForKey:CPTableHeaderViewDrawsColumnLines])
_drawsColumnLines = [aCoder decodeBoolForKey:CPTableHeaderViewDrawsColumnLines];
else
{
_drawsColumnLines = YES;
CPLog.warn("The tableview header being decoded is using an old cib. Please run Nib2Cib.");
}
}
return self;
+1407 -435
View File
File diff suppressed because it is too large Load Diff
+182 -67
View File
@@ -84,7 +84,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
CPColor _textFieldBackgroundColor;
id _placeholderString;
id _originalPlaceholderString;
BOOL _currentValueIsPlaceholder;
id _delegate;
@@ -160,6 +159,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return "textfield";
}
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding === CPValueBinding)
return [_CPTextFieldValueBinder class];
return [super _binderClassForBinding:theBinding];
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMake(2.0, 2.0, 2.0, 2.0), [CPNull null]]
@@ -479,11 +486,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
#if PLATFORM(DOM)
var string = [self stringValue],
element = [self _inputElement];
element = [self _inputElement],
font = [self currentValueForThemeAttribute:@"font"];
// generate the font metric
[font _getMetrics];
element.value = string;
element.style.color = [[self currentValueForThemeAttribute:@"text-color"] cssString];
element.style.font = [[self currentValueForThemeAttribute:@"font"] cssString];
element.style.font = [font cssString];
element.style.zIndex = 1000;
switch ([self alignment])
@@ -495,12 +506,32 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
default: element.style.textAlign = "left";
}
var contentRect = [self contentRectForBounds:[self bounds]];
var contentRect = [self contentRectForBounds:[self bounds]],
verticalAlign = [self currentValueForThemeAttribute:"vertical-alignment"];
element.style.top = _CGRectGetMinY(contentRect) + "px";
switch (verticalAlign)
{
case CPTopVerticalTextAlignment:
var topPoint = (_CGRectGetMinY(contentRect) + 1) + "px"; // for the same reason we have a -1 for the left, we also have a + 1 here
break;
case CPCenterVerticalTextAlignment:
var topPoint = (_CGRectGetMidY(contentRect) - (font._lineHeight / 2) + 1) + "px";
break;
case CPBottomVerticalTextAlignment:
var topPoint = (_CGRectGetMaxY(contentRect) - font._lineHeight) + "px";
break;
default:
var topPoint = (_CGRectGetMinY(contentRect) + 1) + "px";
break;
}
element.style.top = topPoint;
element.style.left = (_CGRectGetMinX(contentRect) - 1) + "px"; // why -1?
element.style.width = _CGRectGetWidth(contentRect) + "px";
element.style.height = _CGRectGetHeight(contentRect) + "px";
element.style.height = font._lineHeight + "px"; // private ivar for the line height of the DOM text at this particular size
_DOMElement.appendChild(element);
@@ -554,7 +585,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[self _setStringValue:element.value];
CPTextFieldInputResigning = YES;
element.blur();
if (CPTextFieldInputIsActive)
element.blur();
if (!CPTextFieldInputDidBlur)
CPTextFieldBlurFunction();
@@ -672,25 +705,87 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)keyDown:(CPEvent)anEvent
{
if ([anEvent keyCode] === CPReturnKeyCode)
{
if (_isEditing)
{
_isEditing = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
}
if ([anEvent _couldBeKeyEquivalent] && [self performKeyEquivalent:anEvent])
return;
[self sendAction:[self action] to:[self target]];
[self selectText:nil];
// CPTextField uses an HTML input element to take the input so we need to
// propagate the dom event so the element is updated. This has to be done
// before interpretKeyEvents: though so individual commands have a chance
// to override this (escape to clear the text in a search field for example).
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
}
else
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
[self interpretKeyEvents:[anEvent]];
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
/*!
Invoke the action specified by aSelector on the current responder.
This is implemented by CPResponder and by default it passes any unrecognized
actions on to the next responder but text fields apparently aren't supposed
to do that according to this documentation by Apple:
http://developer.apple.com/mac/library/documentation/cocoa/reference/NSTextInputClient_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/NSTextInputClient/doCommandBySelector:
*/
- (void)doCommandBySelector:(SEL)aSelector
{
if ([self respondsToSelector:aSelector])
[self performSelector:aSelector];
}
- (void)insertNewline:(id)sender
{
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];
}
- (void)insertNewlineIgnoringFieldEditor:(id)sender
{
var oldValue = [self stringValue];
[self _inputElement].value += CPNewlineCharacter;
[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]];
}
}
- (void)insertTabIgnoringFieldEditor:(id)sender
{
var oldValue = [self stringValue];
[self _inputElement].value += CPTabCharacter;
[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]];
}
}
- (void)textDidBlur:(CPNotification)note
{
// this looks to prevent false propagation of notifications for other objects
@@ -728,6 +823,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
/*
@ignore
Sets the internal string value without updating the value in the input element
*/
- (void)_setStringValue:(id)aValue
{
@@ -787,34 +883,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return _placeholderString;
}
- (void)_setCurrentValueIsPlaceholder:(BOOL)isPlaceholder
{
// The initial _currentValueIsPlaceholder is null so convert it to NO for comparison purposes.
if (!!_currentValueIsPlaceholder === isPlaceholder)
return;
if (isPlaceholder)
{
// Save the original placeholder value so we can restore it later
// Only do this if the placeholder is not already overridden because the bindings logic might call this method
// several times and we don't want the bindings placeholder to ever become the original placeholder
if (!_currentValueIsPlaceholder)
_originalPlaceholderString = [self placeholderString];
// Set the current string value as the current placeholder and clear the string value
[self setPlaceholderString:[self stringValue]];
[self setStringValue:@""];
}
else
{
// Restore the original placeholder, the actual textfield value is already correct
// because it was set using setValue:forKey:
[self setPlaceholderString:_originalPlaceholderString];
}
_currentValueIsPlaceholder = isPlaceholder;
}
/*!
For non-bezeled text fields (typically a label), sizeToFit has two behaviors, depending
on the line break mode of the receiver.
@@ -885,21 +953,28 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
/*!
Select all the text in the CPTextField.
Make the receiver the first responder and select all the text in the field.
*/
- (void)selectText:(id)sender
{
#if PLATFORM(DOM)
var element = [self _inputElement];
// FIXME Should this really make the text field the first responder?
if (([self isEditable] || [self isSelectable]))
{
#if PLATFORM(DOM)
var element = [self _inputElement];
if ([[self window] firstResponder] === self)
window.setTimeout(function() { element.select(); }, 0);
else if ([self window] !== nil && [[self window] makeFirstResponder:self])
window.setTimeout(function() {[self selectText:sender];}, 0);
}
#else
// Even if we can't actually select the text we need to preserve the first
// responder side effect.
if ([self window] !== nil && [[self window] firstResponder] !== self)
[[self window] makeFirstResponder:self];
#endif
}
}
- (void)copy:(id)sender
@@ -981,7 +1056,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
// fall through to the return
}
return CGMakeRange(0, 0);
return CPMakeRange(0, 0);
}
- (void)setSelectedRange:(CPRange)aRange
@@ -1026,8 +1101,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)deleteBackward:(id)sender
{
var selectedRange = [self selectedRange],
stringValue = [self stringValue],
var selectedRange = [self selectedRange];
if (selectedRange.length < 2)
return;
selectedRange.location += 1;
selectedRange.length -= 1;
var stringValue = [self stringValue],
newValue = [stringValue stringByReplacingCharactersInRange:selectedRange withString:""];
[self setStringValue:newValue];
@@ -1262,18 +1344,6 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
[self setAlignment:[aCoder decodeIntForKey:CPTextFieldAlignmentKey]];
[self setPlaceholderString:[aCoder decodeObjectForKey:CPTextFieldPlaceholderStringKey]];
// Make sure the frame is big enough
var minSize = [self _minimumFrameSize];
minSize.width = MAX(CGRectGetWidth([self frame]), minSize.width);
minSize.height = MAX(CGRectGetHeight([self frame]), minSize.height);
// Only size multiline bezeled textfields if it's to small to fit the content
if ([self isBezeled])
if ([self lineBreakMode] === CPLineBreakByCharWrapping || [self lineBreakMode] == CPLineBreakByWordWrapping)
minSize.height = MAX(CGRectGetHeight([self frame]), minSize.height);
[self setFrameSize:minSize];
}
return self;
@@ -1302,3 +1372,48 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
@end
@implementation _CPTextFieldValueBinder : CPBinder
{
}
- (void)setValueFor:(CPString)theBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
if (isPlaceholder)
{
switch (newValue)
{
case CPMultipleValuesMarker:
newValue = [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || @"Multiple Values";
break;
case CPNoSelectionMarker:
newValue = [options objectForKey:CPNoSelectionPlaceholderBindingOption] || @"No Selection";
break;
case CPNotApplicableMarker:
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
[CPException raise:CPGenericException
reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
newValue = [options objectForKey:CPNotApplicablePlaceholderBindingOption] || @"Not Applicable";
break;
}
[_source setPlaceholderString:newValue];
[_source setObjectValue:nil];
}
else
{
newValue = [self transformValue:newValue withOptions:options];
[_source setObjectValue:newValue];
}
}
@end
+1
View File
@@ -405,6 +405,7 @@ function CPThemeStateName(aState)
CPThemeStateNames[0] = "normal";
CPThemeStateNormal = CPThemeStates["normal"] = 0;
CPThemeStateDisabled = CPThemeState("disabled");
CPThemeStateHovered = CPThemeState("hovered");
CPThemeStateHighlighted = CPThemeState("highlighted");
CPThemeStateSelected = CPThemeState("selected");
CPThemeStateTableDataView = CPThemeState("tableDataView");
+60 -16
View File
@@ -27,6 +27,7 @@
@import "CPButton.j"
@import "CPScrollView.j"
@import "CPTextField.j"
@import "CPTableView.j"
@import "CPWindow.j"
@import "_CPMenuWindow.j"
@@ -79,6 +80,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
CPEvent _mouseDownEvent;
BOOL _preventResign;
BOOL _shouldNotifyTarget;
}
+ (CPCharacterSet)defaultTokenizingCharacterSet
@@ -177,7 +179,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
token = [self _inputElement].value;
// Make sure the user typed an actual token to prevent the previous token from being emptied
// If the input area is empty, we want to fallback to the normal behaviour, resigning first responder or select the next or previous key view
// If the input area is empty, we want to fallback to the normal behavior, resigning first responder or select the next or previous key view
if (!token || token === @"")
{
if (DOMEvent && DOMEvent.keyCode === CPTabKeyCode)
@@ -196,7 +198,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
var objectValue = [self objectValue];
// Remove the uncompleted token and add the token string.
// Explicitely remove the last object because the array contains strings and removeObject uses isEqual to compare objects
// Explicitly remove the last object because the array contains strings and removeObject uses isEqual to compare objects
if (shouldRemoveLastObject)
[objectValue removeObjectAtIndex:_selectedRange.location];
@@ -208,10 +210,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
[self _inputElement].value = @"";
[self setNeedsLayout];
var theBinding = [CPKeyValueBinding getBinding:CPValueBinding forObject:self];
if (theBinding)
[theBinding reverseSetValueFor:@"objectValue"];
[self _controlTextDidChange];
}
- (void)_autocomplete
@@ -265,12 +264,15 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
- (void)_controlTextDidChange
{
var theBinding = [CPKeyValueBinding getBinding:CPValueBinding forObject:self];
var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
theBinding = [binderClass getBinding:CPValueBinding forObject:self];
if (theBinding)
[theBinding reverseSetValueFor:@"objectValue"];
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
_shouldNotifyTarget = YES;
}
- (void)_removeSelectedTokens:(id)sender
@@ -401,7 +403,14 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
[self setNeedsLayout];
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
if (_shouldNotifyTarget)
{
_shouldNotifyTarget = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
if ([self sendsActionOnEndEditing])
[self sendAction:[self action] to:[self target]];
}
return YES;
}
@@ -446,7 +455,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
- (CPArray)_tokens
{
// We return super here because objectValue uses this method
// If we called self we would loop infinitly
// If we called self we would loop infinitely
return [super objectValue];
}
@@ -465,7 +474,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
if ([token isKindOfClass:[CPString class]])
continue;
[objectValue addObject:[token stringValue]];
[objectValue addObject:[token representedObject]];
}
#if PLATFORM(DOM)
@@ -501,13 +510,14 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
for (var i = 0, count = [aValue count]; i < count; i++)
{
// Do we have this token among the old ones?
var tokenValue = aValue[i],
var tokenObject = aValue[i],
tokenValue = [self tokenField:self displayStringForRepresentedObject:tokenObject],
newToken = nil;
for (var j = 0, oldCount = [oldTokens count]; j < oldCount; j++)
{
var oldToken = oldTokens[j];
if ([oldToken stringValue] == tokenValue)
if ([oldToken representedObject] == tokenObject)
{
// Yep. Reuse it.
[oldTokens removeObjectAtIndex:j];
@@ -520,6 +530,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
{
newToken = [[_CPTokenFieldToken alloc] init];
[newToken setTokenField:self];
[newToken setRepresentedObject:tokenObject];
[newToken setStringValue:tokenValue];
[contentView addSubview:newToken];
}
@@ -552,6 +563,12 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
[self setNeedsDisplay:YES];
}
- (void)sendAction:(SEL)anAction to:(id)anObject
{
_shouldNotifyTarget = NO;
[super sendAction:anAction to:anObject];
}
// Incredible hack to disable supers implementation
// so it cannot change our object value and break the tokenfield
- (void)_setStringValue:(id)aValue
@@ -616,7 +633,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
CPTokenFieldTextDidChangeValue = [CPTokenFieldInputOwner stringValue];
// Update the selectedIndex if necesary
// Update the selectedIndex if necessary
var index = [[CPTokenFieldInputOwner autocompleteView] selectedRow];
if (aDOMEvent.keyCode === CPUpArrowKeyCode)
@@ -648,7 +665,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
aDOMEvent.stopPropagation();
aDOMEvent.cancelBubble = true;
// Only resign first responder if we weren't autocompleting
// Only resign first responder if we weren't auto-completing
if (![CPTokenFieldInputOwner hasThemeState:CPThemeStateAutoCompleting])
{
if (aDOMEvent && aDOMEvent.keyCode === CPReturnKeyCode)
@@ -1074,7 +1091,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
- (void)tableView:(CPTableView)tableView objectValueForTableColumn:(CPTableColumn)tableColumn row:(int)row
{
return [_cachedCompletions objectAtIndex:row];
return [self tokenField:self displayStringForRepresentedObject:[_cachedCompletions objectAtIndex:row]];
}
- (void)tableViewSelectionDidChange:(CPNotification)notification
@@ -1111,6 +1128,23 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
return [];
}
// // Allows the delegate to provide a string to be displayed as a proxy for the given represented object.
// // If you return nil or do not implement this method, then representedObject is displayed as the string.
- (CPString)tokenField:(CPTokenField)tokenField displayStringForRepresentedObject:(id)representedObject
{
if ([[self delegate] respondsToSelector:@selector(tokenField:displayStringForRepresentedObject:)])
{
var stringForRepresentedObject = [[self delegate] tokenField:tokenField displayStringForRepresentedObject:representedObject];
if (stringForRepresentedObject !== nil)
{
return stringForRepresentedObject;
}
}
return representedObject;
}
//
// // return an array of represented objects you want to add.
// // If you want to reject the add, return an empty array.
@@ -1119,7 +1153,6 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
//
// // If you return nil or don't implement these delegate methods, we will assume
// // editing string = display string = represented object
// - (NSString *)tokenField:(NSTokenField *)tokenField displayStringForRepresentedObject:(id)representedObject;
// - (NSString *)tokenField:(NSTokenField *)tokenField editingStringForRepresentedObject:(id)representedObject;
// - (id)tokenField:(NSTokenField *)tokenField representedObjectForEditingString: (NSString *)editingString;
//
@@ -1143,6 +1176,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
{
_CPTokenFieldTokenCloseButton _deleteButton;
CPTokenField _tokenField;
id _representedObject;
}
+ (CPString)defaultThemeClass
@@ -1175,6 +1209,16 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
_tokenField = tokenField;
}
- (id)representedObject
{
return _representedObject;
}
- (void)setRepresentedObject:(id)representedObject
{
_representedObject = representedObject;
}
- (CGSize)_minimumFrameSize
{
var size = CGSizeMakeZero(),
+19 -6
View File
@@ -50,8 +50,8 @@ CPToolbarDisplayModeIconOnly = 2;
*/
CPToolbarDisplayModeLabelOnly = 3;
var CPToolbarsByIdentifier = nil;
var CPToolbarConfigurationsByIdentifier = nil;
var CPToolbarsByIdentifier = nil,
CPToolbarConfigurationsByIdentifier = nil;
/*!
@ingroup appkit
@@ -464,7 +464,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
// Because we don't know if a delegate will be set later (it is optional
// as of OS X 10.5), we need to call -_reloadToolbarItems here.
// In order to load any toolbar items that may have been configured in the
// Cib. Unfortunatelly this means that if there is a delegate
// Cib. Unfortunately this means that if there is a delegate
// specified, it will be read later and the resulting call to -setDelegate:
// will cause -_reloadToolbarItems] to run again :-(
// FIXME: Can we make this better?
@@ -667,7 +667,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
// Determine all the items that have flexible width.
// Also determine the height of the toolbar.
var count = _visibleItems.length
var count = _visibleItems.length,
flexibleItemIndexes = [CPIndexSet indexSet];
while (count--)
@@ -799,10 +799,11 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
hasNonSeparatorItem = YES;
var menuItem = [[CPMenuItem alloc] initWithTitle:[item label] action:[item action] keyEquivalent:nil];
var menuItem = [[CPMenuItem alloc] initWithTitle:[item label] action:@selector(didSelectMenuItem:) keyEquivalent:nil];
[menuItem setRepresentedObject:item];
[menuItem setImage:[item image]];
[menuItem setTarget:[item target]];
[menuItem setTarget:self];
[menuItem setEnabled:[item isEnabled]];
[_additionalItemsButton addItem:menuItem];
@@ -812,6 +813,18 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
[_additionalItemsButton removeFromSuperview];
}
/*
Used privately.
@ignore
*/
- (void)didSelectMenuItem:(id)aSender
{
var toolbarItem = [aSender representedObject];
[CPApp sendAction:[toolbarItem action] to:[toolbarItem target] from:toolbarItem];
}
- (void)reloadToolbarItems
{
// Get rid of all our current subviews.
+36 -36
View File
@@ -40,7 +40,7 @@ CPToolbarShowFontsItemIdentifier = @"CPToolbarShowFontsItem";
CPToolbarCustomizeToolbarItemIdentifier = @"CPToolbarCustomizeToolbarItem";
CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
/*!
/*!
@ingroup appkit
@class CPToolbarItem
@@ -49,9 +49,9 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
@implementation CPToolbarItem : CPObject
{
CPString _itemIdentifier;
CPToolbar _toolbar;
CPString _label;
CPString _paletteLabel;
CPString _toolTip;
@@ -61,12 +61,12 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
BOOL _isEnabled;
CPImage _image;
CPImage _alternateImage;
CPView _view;
CGSize _minSize;
CGSize _maxSize;
CGSize _maxSize;
int _visibilityPriority;
BOOL _autovalidates;
@@ -86,21 +86,21 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
- (id)initWithItemIdentifier:(CPString)anItemIdentifier
{
self = [super init];
if (self)
{
_itemIdentifier = anItemIdentifier;
_tag = 0;
_isEnabled = YES;
_minSize = CGSizeMakeZero();
_maxSize = CGSizeMakeZero();
_visibilityPriority = CPToolbarItemVisibilityPriorityStandard;
_autovalidates = YES;
}
return self;
}
@@ -170,7 +170,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if ([_view respondsToSelector:@selector(toolTip)])
return [_view toolTip];
return _toolTip;
}
@@ -182,7 +182,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if ([_view respondsToSelector:@selector(setToolTip:)])
[_view setToolTip:aToolTip];
_toolTip = aToolTip;
}
@@ -193,7 +193,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if ([_view respondsToSelector:@selector(tag)])
return [_view tag];
return _tag;
}
@@ -205,7 +205,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if ([_view respondsToSelector:@selector(setTag:)])
[_view setTag:aTag];
_tag = aTag;
}
@@ -216,12 +216,12 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if (_view)
return [_view respondsToSelector:@selector(target)] ? [_view target] : nil;
return _target;
}
/*!
Sets the target of the action that is triggered when the user clicks this item. \c nil 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
*/
@@ -229,7 +229,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if (!_view)
_target = aTarget;
else if ([_view respondsToSelector:@selector(setTarget:)])
[_view setTarget:aTarget];
}
@@ -241,7 +241,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if (_view)
return [_view respondsToSelector:@selector(action)] ? [_view action] : nil;
return _action;
}
@@ -265,7 +265,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if ([_view respondsToSelector:@selector(isEnabled)])
return [_view isEnabled];
return _isEnabled;
}
@@ -277,7 +277,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if ([_view respondsToSelector:@selector(setEnabled:)])
[_view setEnabled:shouldBeEnabled];
_isEnabled = shouldBeEnabled;
}
@@ -288,7 +288,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if ([_view respondsToSelector:@selector(image)])
return [_view image];
return _image;
}
@@ -302,11 +302,11 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
[_view setImage:anImage];
_image = anImage;
if (!_image)
return;
if (_minSize.width === 0 && _minSize.height === 0 &&
if (_minSize.width === 0 && _minSize.height === 0 &&
_maxSize.width === 0 && _maxSize.height === 0)
{
var imageSize = [_image size];
@@ -327,7 +327,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if ([_view respondsToSelector:@selector(setAlternateImage:)])
[_view setAlternateImage:anImage];
_alternateImage = anImage;
}
@@ -338,7 +338,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if ([_view respondsToSelector:@selector(alternateIamge)])
return [_view alternateImage];
return _alternateImage;
}
@@ -358,7 +358,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
{
if (_view == aView)
return;
_view = aView;
if (_view)
@@ -366,7 +366,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
// Tags get forwarded.
if (_tag !== 0 && [_view respondsToSelector:@selector(setTag:)])
[_view setTag:_tag];
_target = nil;
_action = nil;
}
@@ -386,11 +386,11 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
*/
- (void)setMinSize:(CGSize)aMinSize
{
if(!aMinSize.height || !aMinSize.width)
if (!aMinSize.height || !aMinSize.width)
return;
_minSize = CGSizeMakeCopy(aMinSize);
// Try to provide some sanity: Make maxSize >= minSize
_maxSize = CGSizeMake(MAX(_minSize.width, _maxSize.width), MAX(_minSize.height, _maxSize.height));
}
@@ -409,11 +409,11 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
*/
- (void)setMaxSize:(CGSize)aMaxSize
{
if(!aMaxSize.height || !aMaxSize.width)
if (!aMaxSize.height || !aMaxSize.width)
return;
_maxSize = CGSizeMakeCopy(aMaxSize);
// Try to provide some sanity: Make minSize <= maxSize
_minSize = CGSizeMake(MIN(_minSize.width, _maxSize.width), MIN(_minSize.height, _maxSize.height));
}
@@ -623,7 +623,7 @@ var CPToolbarItemItemIdentifierKey = @"CPToolbarItemItemIdentifierKey",
case CPToolbarCustomizeToolbarItemIdentifier: return nil;
case CPToolbarPrintItemIdentifier: return nil;
}
return nil;
}
+14 -1
View File
@@ -1,11 +1,12 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPIndexPath.j>
@implementation CPTreeNode : CPObject
{
id _representedObject @accessors(readonly, property=representedObject);
CPTreeNode _parentNode @accessors(readonly, property=parentNode);
CPMutableArray _childNodes;
}
@@ -87,6 +88,18 @@
[_childNodes[count] sortWithSortDescriptors:sortDescriptors recursively:YES];
}
- (CPTreeNode)descendantNodeAtIndexPath:(CPIndexPath)indexPath
{
var index = 0,
count = [indexPath length],
node = self;
for (; index < count; ++index)
node = [node objectInChildNodesAtIndex:[indexPath indexAtPosition:index]];
return node;
}
@end
var CPTreeNodeRepresentedObjectKey = @"CPTreeNodeRepresentedObjectKey",
+57 -6
View File
@@ -705,7 +705,7 @@ var CPViewFlags = { },
Sets the frame size of the receiver to the dimensions and origin of the provided rectangle in the coordinate system
of the superview. The method also posts an CPViewFrameDidChangeNotification to the notification
center if the receiver is configured to do so. If the frame is the same as the current frame, the method simply
returns (and no notificaion is posted).
returns (and no notification is posted).
@param aFrame the rectangle specifying the new origin and size of the receiver
*/
- (void)setFrame:(CGRect)aFrame
@@ -1566,6 +1566,16 @@ var CPViewFlags = { },
return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(aView, self));
}
/*!
Converts the point from the base coordinate system to the receivers coordinate system.
@param aPoint A point specifying a location in the base coordinate system
@return The point converted to the receivers base coordinate system
*/
- (CGPoint)convertPointFromBase:(CGPoint)aPoint
{
return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(nil, self));
}
/*!
Converts \c aPoint from the receiver's coordinate space to the coordinate space of \c aView.
@param aPoint the point to convert
@@ -1577,6 +1587,16 @@ var CPViewFlags = { },
return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(self, aView));
}
/*!
Converts the point from the receivers coordinate system to the base coordinate system.
@param aPoint A point specifying a location in the coordinate system of the receiver
@return The point converted to the base coordinate system
*/
- (CGPoint)convertPointToBase:(CGPoint)aPoint
{
return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(self, nil));
}
/*!
Convert's \c aSize from \c aView's coordinate space to the receiver's coordinate space.
@param aSize the size to convert
@@ -1610,6 +1630,16 @@ var CPViewFlags = { },
return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(aView, self));
}
/*!
Converts the rectangle from the base coordinate system to the receivers coordinate system.
@param aRect A rectangle specifying a location in the base coordinate system
@return The rectangle converted to the receivers base coordinate system
*/
- (CGRect)convertRectFromBase:(CGRect)aRect
{
return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(nil, self));
}
/*!
Converts \c aRect from the receiver's coordinate space to \c aView's coordinate space.
@param aRect the rectangle to convert
@@ -1621,6 +1651,16 @@ var CPViewFlags = { },
return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(self, aView));
}
/*!
Converts the rectangle from the receivers coordinate system to the base coordinate system.
@param aRect A rectangle specifying a location in the coordinate system of the receiver
@return The rectangle converted to the base coordinate system
*/
- (CGRect)convertRectToBase:(CGRect)aRect
{
return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(self, nil));
}
/*!
Sets whether the receiver posts a CPViewFrameDidChangeNotification notification
to the default notification center when its frame is changed. The default is \c NO.
@@ -1695,7 +1735,7 @@ setBoundsOrigin:
@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 aPasteboard 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
*/
@@ -1710,7 +1750,7 @@ setBoundsOrigin:
@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 aPasteboard 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
*/
@@ -2060,7 +2100,7 @@ setBoundsOrigin:
/*!
Scrolls the clip view to a specified point
@param the clip view to scoll
@param the clip view to scroll
@param the point to scroll to
*/
- (void)scrollClipView:(CPClipView)aClipView toPoint:(CGPoint)aPoint
@@ -2105,11 +2145,18 @@ setBoundsOrigin:
- (CPView)nextValidKeyView
{
var result = [self nextKeyView];
var result = [self nextKeyView],
firstResult = result;
while (result && ![result canBecomeKeyView])
{
result = [result nextKeyView];
// Cycled.
if (result === firstResult)
return nil;
}
return result;
}
@@ -2213,6 +2260,10 @@ setBoundsOrigin:
- (BOOL)hasThemeState:(CPThemeState)aState
{
// Because CPThemeStateNormal is defined as 0 we need to check for it explicitly here
if (aState === CPThemeStateNormal && _themeState === CPThemeStateNormal)
return YES;
return !!(_themeState & ((typeof aState === "string") ? CPThemeState(aState) : aState));
}
@@ -2469,7 +2520,7 @@ setBoundsOrigin:
var frame = [self rectForEphemeralSubviewNamed:aViewName];
if (frame && !_CGRectIsEmpty(frame))
if (frame)
{
if (!_ephemeralSubviewsForNames[aViewName])
{
+57 -9
View File
@@ -23,19 +23,49 @@
@import "CPAnimation.j"
CPViewAnimationTargetKey = @"CPViewAnimationTarget";
CPViewAnimationStartFrameKey = @"CPViewAnimationStartFrame";
CPViewAnimationEndFrameKey = @"CPViewAnimationEndFrame";
CPViewAnimationEffectKey = @"CPViewAnimationEffect";
CPViewAnimationTargetKey = @"CPViewAnimationTargetKey";
CPViewAnimationStartFrameKey = @"CPViewAnimationStartFrameKey";
CPViewAnimationEndFrameKey = @"CPViewAnimationEndFrameKey";
CPViewAnimationEffectKey = @"CPViewAnimationEffectKey";
CPViewAnimationFadeInEffect = @"CPViewAnimationFadeIn";
CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
CPViewAnimationFadeInEffect = @"CPViewAnimationFadeInEffect";
CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
/*!
@class CPViewAnimation
CPViewAnimation is a subclass of CPAnimation that makes it easy to do
basic animations on views.
*/
@implementation CPViewAnimation : CPAnimation
{
CPArray _viewAnimations;
}
/*!
Designated initializer.
This method takes an array of CPDictionaries. Each dictionary should
contain values for the following keys:
<pre>
CPViewAnimationTargetKey - (Required) The view to animate.
CPViewAnimationStartFrameKey - (Optional) The start frame of the target.
CPViewAnimationEndFrameKey - (Optional) The end frame of the target.
CPViewAnimationEffectKey - (Optional) a fade effect to use for the animation.
</pre>
For example:
<pre>
var animation = [CPDictionary dictionaryWithObjects:[myViewToAnimate, aStartFrame, anEndFrame, CPViewAnimationFadeInEffect]
forKeys:[CPViewAnimationTargetKey, CPViewAnimationStartFrameKey, CPViewAnimationEndFrameKey, CPViewAnimationEffectKey]];
</pre>
If you pass nil instead of an array of dictionaries you should later call setViewAnimations:.
@param viewAnimations - An array of CPDictionaries for each animation.
*/
- (id)initWithViewAnimations:(CPArray)viewAnimations
{
if (self = [super initWithDuration:0.5 animationCurve:CPAnimationLinear])
@@ -61,7 +91,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
if (effect === CPViewAnimationFadeInEffect)
{
[view setAlphaValue:0.0];
[view setHidden:NO];
[self _targetView:view setHidden:NO];
}
else if (effect === CPViewAnimationFadeOutEffect)
[view setAlphaValue:1.0];
@@ -104,7 +134,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
[view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * progress];
if (progress === 1.0)
[view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
[self _targetView:view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
}
}
@@ -125,12 +155,25 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
else if (effect === CPViewAnimationFadeOutEffect)
[view setAlphaValue:0.0];
[view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
[self _targetView:view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
}
[super stopAnimation];
}
- (void)_targetView:(id)theView setHidden:(BOOL)isHidden
{
if ([theView isKindOfClass:[CPWindow class]])
{
if (isHidden)
[theView orderOut:self];
else
[theView orderFront:self];
}
else
[theView setHidden:isHidden];
}
- (id)_targetView:(CPDictionary)dictionary
{
var targetView = [dictionary valueForKey:CPViewAnimationTargetKey];
@@ -168,6 +211,11 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
return _viewAnimations;
}
/*!
Takes an array of CPDictionaries as documented in initWithViewAnimations:.
@param viewAnimations - An array of dictionaries describing the animation.
*/
- (void)setViewAnimations:(CPArray)viewAnimations
{
if (viewAnimations != _viewAnimations)
+4 -4
View File
@@ -163,7 +163,7 @@ var CPViewControllerCachedCibs;
if (_view === nil && [cibOwner isKindOfClass:[CPDocument class]])
[self setView:[cibOwner valueForKey:@"view"]];
if (!_view)
if (!_view)
{
var reason = [CPString stringWithFormat:@"View for %@ could not be loaded from Cib or no view specified. Override loadView to load the view manually.", self];
@@ -182,13 +182,13 @@ var CPViewControllerCachedCibs;
/*!
This method is called after the view controller has loaded its associated views into memory.
This method is called regardless of whether the views were stored in a nib file or created programmatically in the loadView method.
This method is called after the view controller has loaded its associated views into memory.
This method is called regardless of whether the views were stored in a nib file or created programmatically in the loadView method.
This method is most commonly used to perform additional initialization steps on views that are loaded from cib files.
*/
- (void)viewDidLoad
{
}
+186 -33
View File
@@ -43,6 +43,16 @@ CPWebViewScrollNative = 2;
/*!
@ingroup appkit
@class CPWebView
CPWebView is a class which allows you to display arbitrary HTML or embed a
webpage inside your application.
It's important to note that the same origin policy applies to this view.
That is, if the web page being displayed is not located in the same origin
(protocol, domain, and port) as the application, you will have limited
control over the view and no access to its contents.
*/
@implementation CPWebView : CPView
@@ -107,7 +117,7 @@ CPWebViewScrollNative = 2;
_ignoreLoadEnd = YES;
_iframe = document.createElement("iframe");
_iframe.name = "iframe_" + Math.floor(Math.random()*10000);
_iframe.name = "iframe_" + FLOOR(RAND() * 10000);
_iframe.style.width = "100%";
_iframe.style.height = "100%";
_iframe.style.borderWidth = "0px";
@@ -116,47 +126,46 @@ CPWebViewScrollNative = 2;
[self setDrawsBackground:YES];
_loadCallback = function() {
// HACK: this block handles the case where we don't know about loads initiated by the user clicking a link
if (!_ignoreLoadStart)
{
// post the start load notification
[self _startedLoading];
// HACK: this block handles the case where we don't know about loads initiated by the user clicking a link
if (!_ignoreLoadStart)
{
// post the start load notification
[self _startedLoading];
if (_mainFrameURL)
[_backwardStack addObject:_mainFrameURL];
if (_mainFrameURL)
[_backwardStack addObject:_mainFrameURL];
// FIXME: this doesn't actually get the right URL for different domains. Not possible due to browser security restrictions.
// FIXME: this doesn't actually get the right URL for different domains. Not possible due to browser security restrictions.
_mainFrameURL = _iframe.src;
_mainFrameURL = _iframe.src;
// clear the forward
[_forwardStack removeAllObjects];
}
else
[_forwardStack removeAllObjects];
}
else
_ignoreLoadStart = NO;
if (!_ignoreLoadEnd)
{
if (!_ignoreLoadEnd)
{
[self _finishedLoading];
}
else
_ignoreLoadEnd = NO;
}
else
_ignoreLoadEnd = NO;
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
if (_iframe.addEventListener)
_iframe.addEventListener("load", _loadCallback, false);
else if (_iframe.attachEvent)
_iframe.attachEvent("onload", _loadCallback);
}
if (_iframe.addEventListener)
_iframe.addEventListener("load", _loadCallback, false);
else if (_iframe.attachEvent)
_iframe.attachEvent("onload", _loadCallback);
_frameView = [[CPView alloc] initWithFrame:[self bounds]];
[_frameView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
[_frameView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_scrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
[_scrollView setAutohidesScrollers:YES];
[_scrollView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
[_scrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_scrollView setDocumentView:_frameView];
_frameView._DOMElement.appendChild(_iframe);
@@ -237,6 +246,10 @@ CPWebViewScrollNative = 2;
}
}
/*!
Sets the scroll mode of the receiver. Valid options are
CPWebViewScrollAppKit and CPWebViewScrollNative.
*/
- (void)setScrollMode:(int)aScrollMode
{
if (_scrollMode == aScrollMode)
@@ -278,11 +291,22 @@ CPWebViewScrollNative = 2;
parent.appendChild(_iframe);
}
/*!
Loads a string of HTML into the webview.
@param CPString - The string to load.
*/
- (void)loadHTMLString:(CPString)aString
{
[self loadHTMLString:aString baseURL:nil];
}
/*!
Loads a string of HTML into the webview.
@param CPString - The string to load.
@param CPURL - The base url of the string. (not implemented)
*/
- (void)loadHTMLString:(CPString)aString baseURL:(CPURL)URL
{
// FIXME: do something with baseURL?
@@ -366,11 +390,21 @@ CPWebViewScrollNative = 2;
[_frameLoadDelegate webView:self didFinishLoadForFrame:nil]; // FIXME: give this a frame somehow?
}
/*!
Returns the URL of the main frame.
@return CPString - The URL of the main frame.
*/
- (CPString)mainFrameURL
{
return _mainFrameURL;
}
/*!
Sets the URL of the main frame.
@param CPString - the url to set.
*/
- (void)setMainFrameURL:(CPString)URLString
{
if (_mainFrameURL)
@@ -381,6 +415,11 @@ CPWebViewScrollNative = 2;
[self _loadMainFrameURL];
}
/*!
Tells the webview to navigate to the previous page.
@return BOOL - YES if the receiver was able to go back, otherwise NO.
*/
- (BOOL)goBack
{
if (_backwardStack.length > 0)
@@ -397,6 +436,11 @@ CPWebViewScrollNative = 2;
return NO;
}
/*!
Tells the receiver to go forward in page history.
@return - YES if the receiver was able to go forward, otherwise NO.
*/
- (BOOL)goForward
{
if (_forwardStack.length > 0)
@@ -413,11 +457,23 @@ CPWebViewScrollNative = 2;
return NO;
}
/*!
Checks to see if the webview has a history stack you can navigate back
through.
@return BOOL - YES if the receiver can navigate backward through history, otherwise NO.
*/
- (BOOL)canGoBack
{
return (_backwardStack.length > 0);
}
/*!
Checks to see if the webview has a history stack you can navigate forward
through.
@return BOOL - YES if the receiver can navigate forward through history, otherwise NO.
*/
- (BOOL)canGoForward
{
return (_forwardStack.length > 0);
@@ -429,16 +485,30 @@ CPWebViewScrollNative = 2;
return { back: _backwardStack, forward: _forwardStack };
}
/*!
Closes the webview by unloading the webpage. The webview will no longer
respond to load requests or delegate methods once this is called.
*/
- (void)close
{
_iframe.parentNode.removeChild(_iframe);
}
/*!
Returns the window object of the webview.
@return DOMWindow - The window object.
*/
- (DOMWindow)DOMWindow
{
return (_iframe.contentDocument && _iframe.contentDocument.defaultView) || _iframe.contentWindow;
}
/*!
Returns the root Object of the webview as a CPWebScriptObject.
@return CPWebScriptObject - the Object of the webview.
*/
- (CPWebScriptObject)windowScriptObject
{
var win = [self DOMWindow];
@@ -452,17 +522,37 @@ CPWebViewScrollNative = 2;
return _wso;
}
/*!
Evaluates a javascript string in the webview and returns the result of
that evaluation as a string.
@param script - A string of javascript.
@return CPString - The result of the evaluation.
*/
- (CPString)stringByEvaluatingJavaScriptFromString:(CPString)script
{
var result = [self objectByEvaluatingJavaScriptFromString:script];
return result ? String(result) : nil;
}
/*!
Evaluates a string of javascript in the webview and returns the result.
@param script - A string of javascript.
@return JSObject - A JSObject resulting from the evaluation.
*/
- (JSObject)objectByEvaluatingJavaScriptFromString:(CPString)script
{
return [[self windowScriptObject] evaluateWebScript:script];
}
/*!
Gets the computed style for an element.
@param DOMElement - An Element.
@param pseudoElement - A pseudoElement.
@return DOMCSSStyleDeclaration - The computed style for an element.
*/
- (DOMCSSStyleDeclaration)computedStyleForElement:(DOMElement)element pseudoElement:(CPString)pseudoElement
{
var win = [[self windowScriptObject] window];
@@ -475,47 +565,85 @@ CPWebViewScrollNative = 2;
}
/*!
@return BOOL - YES if the webview draws its own background, otherwise NO.
*/
- (BOOL)drawsBackground
{
return _iframe.style.backgroundColor != "";
}
/*!
Sets whether the webview draws its own background.
@param BOOL - YES if the webview should draw its background, otherwise NO.
*/
- (void)setDrawsBackground:(BOOL)drawsBackround
{
_iframe.style.backgroundColor = drawsBackround ? "white" : "";
}
// IBActions
- (IBAction)takeStringURLFrom:(id)sender
/*!
Used with the target/action mechanism to automatically set the webviews
mainFrameURL to the senders stringValue.
@param sender - the sender of the action. Should respond to -stringValue.
*/
- (@action)takeStringURLFrom:(id)sender
{
[self setMainFrameURL:[sender stringValue]];
}
- (IBAction)goBack:(id)sender
/*!
Same as -goBack but takes a sender as a param.
@param sender - the sender of the action.
*/
- (@action)goBack:(id)sender
{
[self goBack];
}
- (IBAction)goForward:(id)sender
/*!
Same as -goForward but takes a sender as a param.
@param sender - the sender of the action.
*/
- (@action)goForward:(id)sender
{
[self goForward];
}
- (IBAction)stopLoading:(id)sender
/*!
Stops loading the webview. (not yet implemented)
@param sender - the sender of the action.
*/
- (@action)stopLoading:(id)sender
{
// FIXME: what to do?
}
- (IBAction)reload:(id)sender
/*!
Reloads the webview.
@param sender - the sender of the action.
*/
- (@action)reload:(id)sender
{
[self _loadMainFrameURL];
}
- (IBAction)print:(id)sender
/*!
Tells the webview to print. If the webview is unable to print due to
browser restrictions the user is alerted to print from the file menu.
@param sender - the sender of the receiver.
*/
- (@action)print:(id)sender
{
try
{
@@ -575,12 +703,19 @@ CPWebViewScrollNative = 2;
@end
/*!
@class CPWebScriptObject
A CPWebScriptObject is an Objective-J wrapper around a scripting object.
*/
@implementation CPWebScriptObject : CPObject
{
Window _window;
}
/*!
Initializes the scripting object with the scripting Window object.
*/
- (id)initWithWindow:(Window)aWindow
{
if (self = [super init])
@@ -590,6 +725,12 @@ CPWebViewScrollNative = 2;
return self;
}
/*!
Call a method with arguments on the receiver.
@param methodName - The method that should be called.
@param args - An array of arguments to pass to the method call.
*/
- (id)callWebScriptMethod:(CPString)methodName withArguments:(CPArray)args
{
// Would using "with" be better here?
@@ -603,15 +744,25 @@ CPWebViewScrollNative = 2;
return undefined;
}
/*!
Evaluates a string of javascript and returns the result.
@param script - The script to run.
@return - The result of the evaluation, which may be 'undefined'.
*/
- (id)evaluateWebScript:(CPString)script
{
try {
return _window.eval(script);
} catch (e) {
// FIX ME: if we fail inside here, shouldn't we return an exception?
}
return undefined;
}
/*!
Returns the receivers Window object.
*/
- (Window)window
{
return _window;
@@ -624,6 +775,7 @@ CPWebViewScrollNative = 2;
/*!
Initializes the web view from the data in a coder.
@param aCoder the coder from which to read the data
@return the initialized web view
*/
@@ -651,6 +803,7 @@ CPWebViewScrollNative = 2;
/*!
Writes out the web view's instance information to a coder.
@param aCoder the coder to which to write the data
*/
- (void)encodeWithCoder:(CPCoder)aCoder
+174 -93
View File
@@ -197,6 +197,21 @@ var CPWindowSaveImage = nil,
var CPWindowResizeTime = 0.2;
/*
Keys for which action messages will be sent by default when unhandled, e.g. complete:.
*/
var CPWindowActionMessageKeys = [
CPLeftArrowFunctionKey,
CPRightArrowFunctionKey,
CPUpArrowFunctionKey,
CPDownArrowFunctionKey,
CPPageUpFunctionKey,
CPPageDownFunctionKey,
CPHomeFunctionKey,
CPEndFunctionKey,
CPEscapeFunctionKey
];
/*!
@ingroup appkit
@class CPWindow
@@ -388,6 +403,7 @@ CPTexturedBackgroundWindowMask
_registeredDraggedTypes = [CPSet set];
_registeredDraggedTypesArray = [];
_isSheet = NO;
_acceptsMouseMovedEvents = YES;
// Set up our window number.
_windowNumber = [CPApp._windows count];
@@ -523,6 +539,12 @@ CPTexturedBackgroundWindowMask
}
}
/*!
Sets the receiver as a full platform window. If you pass YES the CPWindow instance will fill the entire browser content area,
otherwise the CPWindow will be a window inside of your browser window which the user can drag around, and resize (if you allow).
@param BOOL - YES if the window should fill the browser window, otherwise NO.
*/
- (void)setFullPlatformWindow:(BOOL)shouldBeFullPlatformWindow
{
if (![_platformWindow supportsFullPlatformWindows])
@@ -563,6 +585,9 @@ CPTexturedBackgroundWindowMask
}
}
/*!
@return BOOL - YES if the CPWindow fills the browser window, otherwise NO.
*/
- (BOOL)isFullPlatformWindow
{
return _isFullPlatformWindow;
@@ -578,6 +603,18 @@ CPTexturedBackgroundWindowMask
/*!
Returns the frame rectangle used by a window.
Style masks include:
<pre>
CPBorderlessWindowMask
CPTitledWindowMask
CPClosableWindowMask
CPMiniaturizableWindowMask (NOTE: only available in NativeHost)
CPResizableWindowMask
CPTexturedBackgroundWindowMask
CPBorderlessBridgeWindowMask
CPHUDBackgroundWindowMask
</pre>
@param aContentRect the content rectangle of the window
@param aStyleMask the style mask of the window
@return the matching window's frame rectangle
@@ -619,7 +656,7 @@ CPTexturedBackgroundWindowMask
the resize operation, and redraw itself if necessary.
@param aFrame the new size and location for the window
@param shouldDisplay whether the window should redraw its views
@param shouldAnimate whether the window resize should be animated
@param shouldAnimate whether the window resize should be animated.
*/
- (void)_setClippedFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
{
@@ -628,6 +665,13 @@ CPTexturedBackgroundWindowMask
[self setFrame:aFrame display:shouldDisplay animate:shouldAnimate];
}
/*!
Sets the frame of the window.
@param aFrame - A CGRect of the new frame for the receiver.
@param shouldDisplay - YES if the window should call setNeedsDisplay otherwise NO.
@param shouldAnimate - YES if the window should animate to it's new size and position, otherwise NO.
*/
- (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
{
aFrame = _CGRectMakeCopy(aFrame);
@@ -705,6 +749,11 @@ CPTexturedBackgroundWindowMask
}
}
/*!
Sets the window's frame rect.
@param aFrame - The new CGRect of the window.
@param shouldDisplay - YES if the window should call setNeedsDisplay: otherwise NO.
*/
- (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay
{
[self _setClippedFrame:aFrame display:shouldDisplay animate:NO];
@@ -712,6 +761,7 @@ CPTexturedBackgroundWindowMask
/*!
Sets the window's frame rectangle
@param aFrame - The CGRect of the windows new frame
*/
- (void)setFrame:(CGRect)aFrame
{
@@ -937,7 +987,7 @@ CPTexturedBackgroundWindowMask
/*!
Sets the window's minimum size. If the provided
size is the same as the current minimum size, the method simply returns.
@aSize the new minimum size for the window
@param aSize the new minimum size for the window
*/
- (void)setMinSize:(CGSize)aSize
{
@@ -1095,6 +1145,17 @@ CPTexturedBackgroundWindowMask
[self _updateShadow];
}
/*!
Sets the shadow style of the receiver.
Values are:
<pre>
CPWindowShadowStyleStandard
CPWindowShadowStyleMenu
CPWindowShadowStylePanel
</pre>
@param aStyle - The new shadow style of the receiver.
*/
- (void)setShadowStyle:(unsigned)aStyle
{
_shadowStyle = aStyle;
@@ -1223,10 +1284,10 @@ CPTexturedBackgroundWindowMask
if (_firstResponder === aResponder)
return YES;
if(![_firstResponder resignFirstResponder])
if (![_firstResponder resignFirstResponder])
return NO;
if(!aResponder || ![aResponder acceptsFirstResponder] || ![aResponder becomeFirstResponder])
if (!aResponder || ![aResponder acceptsFirstResponder] || ![aResponder becomeFirstResponder])
{
_firstResponder = self;
@@ -1615,7 +1676,7 @@ CPTexturedBackgroundWindowMask
@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 aPasteboard 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
*/
@@ -1652,7 +1713,7 @@ CPTexturedBackgroundWindowMask
@param aLocation the lower-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 aPasteboard 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
*/
@@ -1803,7 +1864,7 @@ CPTexturedBackgroundWindowMask
}
/*!
Restores a mimized window to it's original size.
Restores a minimized window to it's original size.
*/
- (void)deminiaturize:(id)sender
{
@@ -2155,7 +2216,7 @@ CPTexturedBackgroundWindowMask
aSheet._isSheet = YES;
aSheet._parentView = self;
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width)/2),
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2),
originy = frame.origin.y + [[self contentView] frame].origin.y,
startFrame = CGRectMake(originx, originy, sheetFrame.size.width, 0),
endFrame = CGRectMake(originx, originy, sheetFrame.size.width, sheetFrame.size.height);
@@ -2314,7 +2375,7 @@ CPTexturedBackgroundWindowMask
// Apple's documentation is inconsistent with their behavior here. According to the docs
// an event going of the responder chain is passed to the input system as a last resort.
// However, the only methods I could get Cocoa to call automatically are
// However, the only methods I could get Cocoa to call automatically are
// moveUp: moveDown: moveLeft: moveRight: pageUp: pageDown: and complete:
[self _processKeyboardUIKey:anEvent];
}
@@ -2323,59 +2384,15 @@ CPTexturedBackgroundWindowMask
@ignore
Interprets the key event for action messages and sends the action message down the responder chain
Cocoa only sends moveDown:, moveUp:, moveLeft:, moveRight:, pageUp:, pageDown: and complete: messages.
We deviate from this by sending (the default) scrollPageUp: scrollPageDown: for pageUp and pageDown keys.
@param anEvent the event to handle.
We deviate from this by sending (the default) scrollPageUp:, scrollPageDown:, scrollToBeginningOfDocument: and scrollToEndOfDocument: for pageUp, pageDown, home and end keys.
@param anEvent the event to handle.
@return YES if the key event was handled, NO if no responder handled the key event
*/
- (BOOL)_processKeyboardUIKey:(CPEvent)anEvent
{
var character = [anEvent charactersIgnoringModifiers],
uiKeys = [CPLeftArrowFunctionKey, CPRightArrowFunctionKey, CPUpArrowFunctionKey, CPDownArrowFunctionKey, CPPageUpFunctionKey, CPPageDownFunctionKey, CPEscapeFunctionKey];
var character = [anEvent charactersIgnoringModifiers];
if (![uiKeys containsObject:character])
return NO;
var selectors = [CPKeyBinding selectorsForKey:character modifierFlags:0];
if ([selectors count] <= 0)
return NO;
if (character !== CPEscapeFunctionKey)
{
var selector = [selectors objectAtIndex:0];
return [[self firstResponder] tryToPerform:selector with:self];
}
else
{
// Cocoa sends complete: for the escape key (in stead of the default cancelOperation:)
// This is also the only action that is not sent directly to the first responder, but through doCommandBySelector.
// The difference is that doCommandBySelector: will also send the action to the window and application delegates.
[[self firstResponder] doCommandBySelector:@selector(complete:)];
}
}
/*
@ignore
Interprets the key event for action messages and sends the action message down the responder chain
Cocoa only sends moveDown:, moveUp:, moveLeft:, moveRight:, pageUp:, pageDown: and complete: messages.
We deviate from this by sending (the default) scrollPageUp: scrollPageDown: for pageUp and pageDown keys.
@param anEvent the event to handle.
@return YES if the key event was handled, NO if no responder handled the key event
*/
- (BOOL)_processKeyboardUIKey:(CPEvent)anEvent
{
var character = [anEvent charactersIgnoringModifiers],
uiKeys = [
CPLeftArrowFunctionKey,
CPRightArrowFunctionKey,
CPUpArrowFunctionKey,
CPDownArrowFunctionKey,
CPPageUpFunctionKey,
CPPageDownFunctionKey,
CPEscapeFunctionKey
];
if (![uiKeys containsObject:character])
if (![CPWindowActionMessageKeys containsObject:character])
return NO;
var selectors = [CPKeyBinding selectorsForKey:character modifierFlags:0];
@@ -2405,45 +2422,31 @@ CPTexturedBackgroundWindowMask
- (BOOL)_hasKeyViewLoop
{
var subviews = [];
var views = allViews(self),
index = [views count];
[self _appendSubviewsOf:_contentView toArray:subviews];
for (var i = 0, count = [subviews count]; i<count; i++)
{
if (subviews[i]._nextKeyView)
while (index--)
if ([views[index] nextKeyView])
return YES;
}
return NO;
}
- (void)recalculateKeyViewLoop
{
var subviews = [];
var views = allViews(self);
[self _appendSubviewsOf:_contentView toArray:subviews];
[views sortUsingFunction:keyViewComparator context:nil];
var keyViewOrder = [subviews sortedArrayUsingFunction:keyViewComparator context:_contentView],
count = [keyViewOrder count];
var index = 0,
count = [views count];
for (var i=0; i<count; i++)
[keyViewOrder[i] setNextKeyView:keyViewOrder[(i+1)%count]];
for (; index < count; ++index)
[views[index] setNextKeyView:views[(index + 1) % count]];
_keyViewLoopIsDirty = NO;
}
- (void)_appendSubviewsOf:(CPView)aView toArray:(CPArray)anArray
{
var subviews = [aView subviews],
count = [subviews count];
while (count--)
[self _appendSubviewsOf:subviews[count] toArray:anArray];
[anArray addObject:aView];
}
- (void)setAutorecalculatesKeyViewLoop:(BOOL)shouldRecalculate
{
if (_autorecalculatesKeyViewLoop === shouldRecalculate)
@@ -2490,16 +2493,31 @@ CPTexturedBackgroundWindowMask
[self makeFirstResponder:[aView previousValidKeyView]];
}
/*!
Sets the default button for the window.
Note: this method is deprecated use setDefaultButton: instead.
@param aButton - The button that should become default.
*/
- (void)setDefaultButtonCell:(CPButton)aButton
{
[self setDefaultButton:aButton];
}
/*!
Returns the default button of the receiver.
NOTE: This method is deprecated. Use defaultButton instead.
*/
- (CPButton)defaultButtonCell
{
return [self defaultButton];
}
/*!
Sets the default button for the window.
This is equivalent to setting the the key equivalent of the button to "return".
Additionally this will turn your button blue (with the Aristo theme).
@param aButton - The button that should become default.
*/
- (void)setDefaultButton:(CPButton)aButton
{
if (_defaultButton === aButton)
@@ -2514,26 +2532,43 @@ CPTexturedBackgroundWindowMask
[_defaultButton setKeyEquivalent:CPCarriageReturnCharacter];
}
/*!
Returns the default button of the receiver.
*/
- (CPButton)defaultButton
{
return _defaultButton;
}
/*!
Sets the default button key equivalent to "return".
*/
- (void)enableKeyEquivalentForDefaultButton
{
_defaultButtonEnabled = YES;
}
/*!
Sets the default button key equivalent to "return".
NOTE: this method is deprecated. Use enableKeyEquivalentForDefaultButton instead.
*/
- (void)enableKeyEquivalentForDefaultButtonCell
{
[self enableKeyEquivalentForDefaultButton];
}
/*!
Removes the key equivalent for the default button.
*/
- (void)disableKeyEquivalentForDefaultButton
{
_defaultButtonEnabled = NO;
}
/*!
Removes the key equivalent for the default button.
Note: this method is deprecated. Use disableKeyEquivalentForDefaultButton instead.
*/
- (void)disableKeyEquivalentForDefaultButtonCell
{
[self disableKeyEquivalentForDefaultButton];
@@ -2541,19 +2576,46 @@ CPTexturedBackgroundWindowMask
@end
var keyViewComparator = function(a, b, context)
var allViews = function(aWindow)
{
var viewBounds = [a convertRect:[a bounds] toView:nil],
otherBounds = [b convertRect:[b bounds] toView:nil];
var views = [[aWindow contentView] subviews],
index = 0;
if (CGRectGetMinY(viewBounds) < CGRectGetMinY(otherBounds))
return -1;
else if (CGRectGetMinY(viewBounds) == CGRectGetMinY(otherBounds) && CGRectGetMinX(viewBounds) < CGRectGetMinX(otherBounds))
return -1;
else if (CGRectGetMinX(viewBounds) == CGRectGetMinX(otherBounds) && CGRectGetMinX(viewBounds) == CGRectGetMinX(otherBounds))
return 0;
else
return 1;
for (; index < views.length; ++index)
views = views.concat([views[index] subviews]);
return views;
}
var keyViewComparator = function(lhs, rhs, context)
{
var lhsBounds = [lhs convertRect:[lhs bounds] toView:nil],
rhsBounds = [rhs convertRect:[rhs bounds] toView:nil],
lhsY = _CGRectGetMinY(lhsBounds),
rhsY = _CGRectGetMinY(rhsBounds),
lhsX = _CGRectGetMinX(lhsBounds),
rhsX = _CGRectGetMinX(rhsBounds),
intersectsVertically = MIN(_CGRectGetMaxY(lhsBounds), _CGRectGetMaxY(rhsBounds)) - MAX(lhsY, rhsY);
// If two views are "on the same line" (intersect vertically), then rely on the x comparison.
if (intersectsVertically > 0)
{
if (lhsX < rhsX)
return CPOrderedAscending;
if (lhsX === rhsX)
return CPOrderedSame;
return CPOrderedDescending;
}
if (lhsY < rhsY)
return CPOrderedAscending;
if (lhsY === rhsY)
return CPOrderedSame;
return CPOrderedDescending;
}
@implementation CPWindow (MenuBar)
@@ -2618,16 +2680,25 @@ var keyViewComparator = function(a, b, context)
return _autoresizingMask;
}
/*!
Converts aPoint from the window coordinate system to the global coordinate system.
*/
- (CGPoint)convertBaseToGlobal:(CGPoint)aPoint
{
return [CPPlatform isBrowser] ? [self convertBaseToPlatformWindow:aPoint] : [self convertBaseToScreen:aPoint];
}
/*!
Converts aPoint from the global coordinate system to the window coordinate system.
*/
- (CGPoint)convertGlobalToBase:(CGPoint)aPoint
{
return [CPPlatform isBrowser] ? [self convertPlatformWindowToBase:aPoint] : [self convertScreenToBase:aPoint];
}
/*!
Converts aPoint from the window coordinate system to the coordinate system of the parent platform window.
*/
- (CGPoint)convertBaseToPlatformWindow:(CGPoint)aPoint
{
if ([self _sharesChromeWithPlatformWindow])
@@ -2638,6 +2709,9 @@ var keyViewComparator = function(a, b, context)
return _CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y);
}
/*!
Converts aPoint from the parent platform window coordinate system to the windows coordinate system.
*/
- (CGPoint)convertPlatformWindowToBase:(CGPoint)aPoint
{
if ([self _sharesChromeWithPlatformWindow])
@@ -2727,12 +2801,19 @@ var keyViewComparator = function(a, b, context)
@end
@implementation CPWindow (Deprecated)
/*!
Sets the CPWindow to fill the whole browser window.
NOTE: this method has been deprecated in favor of setFullPlatformWindow:
*/
- (void)setFullBridge:(BOOL)shouldBeFullBridge
{
[self setFullPlatformWindow:shouldBeFullBridge];
}
/*!
Returns YES if the window fills the full browser window, otherwise NO.
NOTE: this method has been deprecated in favor of isFullPlatformWindow.
*/
- (BOOL)isFullBridge
{
return [self isFullPlatformWindow];
+8 -1
View File
@@ -6,6 +6,7 @@ var _CPStandardWindowViewBodyBackgroundColor = nil;
@implementation _CPDocModalWindowView : _CPWindowView
{
CPView _bodyView;
CPView _shadowView;
}
+ (CPColor)bodyBackgroundColor
@@ -25,13 +26,19 @@ var _CPStandardWindowViewBodyBackgroundColor = nil;
var theClass = [self class],
bounds = [self bounds];
_bodyView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), CGRectGetHeight(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];
var bundle = [CPBundle bundleForClass:[CPWindow class]];
_shadowView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, _CGRectGetWidth(bounds), 8)];
[_shadowView setAutoresizingMask:CPViewWidthSizable];
[_shadowView setBackgroundColor:[CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowAttachedSheetShadow.png"] size:CGSizeMake(9,8)]]];
[self addSubview:_shadowView];
}
return self;
+34 -32
View File
@@ -19,9 +19,11 @@
* 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"
var _CPHUDWindowViewBackgroundColor = nil,
CPHUDCloseButtonImage = nil;
var HUD_TITLEBAR_HEIGHT = 26.0;
@@ -29,7 +31,7 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
@implementation _CPHUDWindowView : _CPWindowView
{
CPView _toolbarView;
CPTextField _titleField;
CPButton _closeButton;
}
@@ -38,19 +40,19 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
{
if (self != [_CPHUDWindowView class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPHUDWindowViewBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground0.png"] size:CPSizeMake(7.0, 37.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground1.png"] size:CPSizeMake(1.0, 37.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground2.png"] size:CPSizeMake(7.0, 37.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground3.png"] size:CPSizeMake(7.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground4.png"] size:CPSizeMake(2.0, 2.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground5.png"] size:CPSizeMake(7.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground6.png"] size:CPSizeMake(7.0, 3.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground7.png"] size:CPSizeMake(1.0, 3.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground8.png"] size:CPSizeMake(7.0, 3.0)]
@@ -64,7 +66,7 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
{
var contentRect = CGRectMakeCopy(aFrameRect),
titleBarHeight = HUD_TITLEBAR_HEIGHT;
contentRect.origin.y += titleBarHeight;
contentRect.size.height -= titleBarHeight;
@@ -75,92 +77,92 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
{
var frameRect = CGRectMakeCopy(aContentRect),
titleBarHeight = HUD_TITLEBAR_HEIGHT;
frameRect.origin.y -= titleBarHeight;
frameRect.size.height += titleBarHeight;
return frameRect;
}
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
var contentRect = [[self class] contentRectForFrameRect:aFrameRect];
if ([[[self window] toolbar] isVisible])
{
toolbarHeight = CGRectGetHeight([[self toolbarView] frame]);
contentRect.origin.y += toolbarHeight;
contentRect.size.height -= toolbarHeight;
}
return contentRect;
}
- (CGRect)frameRectForContentRect:(CGRect)aContentRect
{
var frameRect = [[self class] frameRectForContentRect:aContentRect];
if ([[[self window] toolbar] isVisible])
{
toolbarHeight = CGRectGetHeight([[self toolbarView] frame]);
frameRect.origin.y -= toolbarHeight;
frameRect.size.height += toolbarHeight;
}
return frameRect;
}
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
{
self = [super initWithFrame:aFrame styleMask:aStyleMask];
if (self)
{
var bounds = [self bounds];
[self setBackgroundColor:_CPHUDWindowViewBackgroundColor];
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_titleField setHitTests:NO];
[_titleField setFont:[CPFont systemFontOfSize:11.0]];
[_titleField setTextColor:[CPColor whiteColor]];
[_titleField setTextShadowColor:[CPColor blackColor]];
[_titleField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_titleField setAutoresizingMask:CPViewWidthSizable];
// FIXME: Make this to CPLineBreakByTruncatingMiddle once it's implemented.
[_titleField setLineBreakMode:CPLineBreakByTruncatingTail];
[_titleField setAlignment:CPCenterTextAlignment];
[_titleField setStringValue:@"Untitled"];
[_titleField sizeToFit];
[_titleField setAutoresizingMask:CPViewWidthSizable];
[_titleField setStringValue:@""];
[_titleField setFrame:CGRectMake(20.0, 3.0, CGRectGetWidth([self bounds]) - 40.0, CGRectGetHeight([_titleField frame]))];
[self addSubview:_titleField];
if (_styleMask & CPClosableWindowMask)
{
var closeSize = [_CPHUDWindowViewCloseImage size];
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 5.0, closeSize.width, closeSize.height)];
[_closeButton setBordered:NO];
[_closeButton setImage:_CPHUDWindowViewCloseImage];
[_closeButton setAlternateImage:_CPHUDWindowViewCloseActiveImage];
[self addSubview:_closeButton];
}
[self setResizeIndicatorOffset:CGSizeMake(5.0, 5.0)];
}
return self;
}
+42 -41
View File
@@ -20,6 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPTextField.j"
@import "_CPWindowView.j"
@@ -40,7 +41,7 @@ var _CPTexturedWindowHeadGradientColor = nil,
if (!_CPTexturedWindowHeadGradientColor)
{
var bundle = [CPBundle bundleForClass:[_CPWindowView class]];
_CPTexturedWindowHeadGradientColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardTop0.png"] size:CGSizeMake(6.0, 41.0)],
@@ -50,7 +51,7 @@ var _CPTexturedWindowHeadGradientColor = nil,
isVertical:NO
]];
}
return _CPTexturedWindowHeadGradientColor;
}
@@ -58,37 +59,37 @@ var _CPTexturedWindowHeadGradientColor = nil,
{
if (!_CPTexturedWindowHeadSolidColor)
_CPTexturedWindowHeadSolidColor = [CPColor colorWithCalibratedRed:195.0 / 255.0 green:195.0 / 255.0 blue:195.0 / 255.0 alpha:1.0];
return _CPTexturedWindowHeadSolidColor;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
var theClass = [self class],
bounds = [self bounds];
_gradientView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), GRADIENT_HEIGHT)];
[_gradientView setBackgroundColor:[theClass gradientColor]];
[self addSubview:_gradientView];
_solidView = [[CPView alloc] initWithFrame:CGRectMake(0.0, GRADIENT_HEIGHT, CGRectGetWidth(bounds), CGRectGetHeight(bounds) - GRADIENT_HEIGHT)];
[_solidView setBackgroundColor:[theClass solidColor]];
[self addSubview:_solidView];
}
return self;
}
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
{
var bounds = [self bounds];
[_gradientView setFrameSize:CGSizeMake(CGRectGetWidth(bounds), GRADIENT_HEIGHT)];
[_solidView setFrameSize:CGSizeMake(CGRectGetWidth(bounds), CGRectGetHeight(bounds) - GRADIENT_HEIGHT)];
}
@@ -114,7 +115,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
CPView _dividerView;
CPView _bodyView;
CPView _toolbarView;
CPTextField _titleField;
CPButton _closeButton;
CPButton _minimizeButton;
@@ -126,15 +127,15 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
{
if (!_CPStandardWindowViewBodyBackgroundColor)
_CPStandardWindowViewBodyBackgroundColor = [CPColor colorWithWhite:0.96 alpha:1.0];
return _CPStandardWindowViewBodyBackgroundColor;
return _CPStandardWindowViewBodyBackgroundColor;
}
+ (CPColor)dividerBackgroundColor
{
if (!_CPStandardWindowViewDividerBackgroundColor)
_CPStandardWindowViewDividerBackgroundColor = [CPColor colorWithCalibratedRed:125.0 / 255.0 green:125.0 / 255.0 blue:125.0 / 255.0 alpha:1.0];
return _CPStandardWindowViewDividerBackgroundColor;
}
@@ -142,7 +143,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
{
if (!_CPStandardWindowViewTitleBackgroundColor)
_CPStandardWindowViewTitleBackgroundColor = [CPColor colorWithCalibratedRed:44.0 / 255.0 green:44.0 / 255.0 blue:44.0 / 255.0 alpha:1.0];
return _CPStandardWindowViewTitleBackgroundColor;
}
@@ -150,7 +151,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
{
var contentRect = CGRectMakeCopy(aFrameRect),
titleBarHeight = [self titleBarHeight] + 1.0;
contentRect.origin.y += titleBarHeight;
contentRect.size.height -= titleBarHeight;
@@ -161,10 +162,10 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
{
var frameRect = CGRectMakeCopy(aContentRect),
titleBarHeight = [self titleBarHeight] + 1.0;
frameRect.origin.y -= titleBarHeight;
frameRect.size.height += titleBarHeight;
return frameRect;
}
@@ -177,15 +178,15 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
{
var contentRect = [[self class] contentRectForFrameRect:aFrameRect],
theToolbar = [[self window] toolbar];
if ([theToolbar isVisible])
{
toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]);
contentRect.origin.y += toolbarHeight;
contentRect.size.height -= toolbarHeight;
}
return contentRect;
}
@@ -193,72 +194,72 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
{
var frameRect = [[self class] frameRectForContentRect:aContentRect],
theToolbar = [[self window] toolbar];
if ([theToolbar isVisible])
{
toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]);
frameRect.origin.y -= toolbarHeight;
frameRect.size.height += toolbarHeight;
}
return frameRect;
}
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
{
self = [super initWithFrame:aFrame styleMask:aStyleMask];
if (self)
{
var theClass = [self class],
bounds = [self bounds];
_headView = [[_CPTexturedWindowHeadView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), [[self class] titleBarHeight])];
[_headView setAutoresizingMask:CPViewWidthSizable];;
[_headView setHitTests:NO];
[self addSubview:_headView];
_dividerView = [[CPView alloc] initWithFrame:CGRectMake(0.0, CGRectGetMaxY([_headView frame]), CGRectGetWidth(bounds), 1.0)];
[_dividerView setAutoresizingMask:CPViewWidthSizable];
[_dividerView setBackgroundColor:[theClass dividerBackgroundColor]];
[_dividerView setHitTests:NO];
[self addSubview:_dividerView];
var y = CGRectGetMaxY([_dividerView frame]);
_bodyView = [[CPView alloc] initWithFrame:CGRectMake(0.0, y, CGRectGetWidth(bounds), CGRectGetHeight(bounds) - y)];
[_bodyView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_bodyView setBackgroundColor:[theClass bodyBackgroundColor]];
[_bodyView setHitTests:NO];
[self addSubview:_bodyView];
[self setResizeIndicatorOffset:CGSizeMake(2.0, 2.0)];
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_titleField setFont:[CPFont boldSystemFontOfSize:12.0]];
[_titleField setAutoresizingMask:CPViewWidthSizable];
// FIXME: Make this to CPLineBreakByTruncatingMiddle once it's implemented.
[_titleField setLineBreakMode:CPLineBreakByTruncatingTail];
[_titleField setAlignment:CPCenterTextAlignment];
[_titleField setTextShadowColor:[CPColor whiteColor]];
[_titleField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_titleField setStringValue:@"Untitled"];
[_titleField sizeToFit];
[_titleField setAutoresizingMask:CPViewWidthSizable];
[_titleField setStringValue:@""];
[self addSubview:_titleField];
if (_styleMask & CPClosableWindowMask)
{
if (!_CPStandardWindowViewCloseButtonImage)
+37 -38
View File
@@ -29,15 +29,14 @@ var _CPWindowViewResizeIndicatorImage = nil;
@implementation _CPWindowView : CPView
{
unsigned _styleMask;
CPImageView _resizeIndicator;
CGSize _resizeIndicatorOffset;
CPView _toolbarView;
CGSize _toolbarOffset;
// BOOL _isAnimatingToolbar;
CGRect _resizeFrame;
CGPoint _mouseDraggedPoint;
@@ -48,7 +47,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
{
if (self != [_CPWindowView class])
return;
_CPWindowViewResizeIndicatorImage = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPWindow class]] pathForResource:@"_CPWindowView/_CPWindowViewResizeIndicator.png"] size:CGSizeMake(12.0, 12.0)];
}
@@ -75,14 +74,14 @@ var _CPWindowViewResizeIndicatorImage = nil;
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
{
self = [super initWithFrame:aFrame];
if (self)
{
_styleMask = aStyleMask;
_resizeIndicatorOffset = CGSizeMakeZero();
_toolbarOffset = CGSizeMakeZero();
}
return self;
}
@@ -107,14 +106,14 @@ var _CPWindowViewResizeIndicatorImage = nil;
{
// FIXME: This should be better
var frame = [_resizeIndicator frame];
if (CGRectContainsPoint(frame, [self convertPoint:[anEvent locationInWindow] fromView:nil]))
return [self trackResizeWithEvent:anEvent];
}
if ([theWindow isMovableByWindowBackground])
[self trackMoveWithEvent:anEvent];
else
[super mouseDown:anEvent];
}
@@ -123,29 +122,29 @@ var _CPWindowViewResizeIndicatorImage = nil;
{
var location = [anEvent locationInWindow],
type = [anEvent type];
if (type === CPLeftMouseUp)
return;
var theWindow = [self window];
if (type === CPLeftMouseDown)
{
var frame = [theWindow frame];
_resizeFrame = CGRectMake(location.x, location.y, CGRectGetWidth(frame), CGRectGetHeight(frame));
}
else if (type === CPLeftMouseDragged)
{
var newSize = 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];
[theWindow._parentView _setAttachedSheetFrameOrigin];
[theWindow setFrameSize:newSize];
}
[CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
@@ -161,10 +160,10 @@ var _CPWindowViewResizeIndicatorImage = nil;
visibleFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
var minPointY = 0;
if([CPMenu menuBarVisible])
minPointY = [[CPApp mainMenu] menuBarHeight];
var restrictedPoint = CGPointMake(0, 0);
restrictedPoint.x = MIN(MAX(aPoint.x, -_frame.size.width + 4.0), CGRectGetMaxX(visibleFrame) - 4.0);
@@ -194,14 +193,14 @@ var _CPWindowViewResizeIndicatorImage = nil;
var theWindow = [self window],
frame = [theWindow frame],
location = [theWindow convertBaseToGlobal:[anEvent locationInWindow]],
origin = [self _pointWithinScreenFrame:CGPointMake(_CGRectGetMinX(frame) + (location.x - _mouseDraggedPoint.x),
origin = [self _pointWithinScreenFrame:CGPointMake(_CGRectGetMinX(frame) + (location.x - _mouseDraggedPoint.x),
_CGRectGetMinY(frame) + (location.y - _mouseDraggedPoint.y))];
[theWindow setFrameOrigin:origin];
_mouseDraggedPoint = [self _pointWithinScreenFrame:location];
}
[CPApp setTarget:self selector:@selector(trackMoveWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
@@ -211,9 +210,9 @@ var _CPWindowViewResizeIndicatorImage = nil;
{
var size = [_CPWindowViewResizeIndicatorImage size],
boundsSize = [self frame].size;
_resizeIndicator = [[CPImageView alloc] initWithFrame:CGRectMake(boundsSize.width - size.width - _resizeIndicatorOffset.width, boundsSize.height - size.height - _resizeIndicatorOffset.height, size.width, size.height)];
[_resizeIndicator setImage:_CPWindowViewResizeIndicatorImage];
[_resizeIndicator setAutoresizingMask:CPViewMinXMargin | CPViewMinYMargin];
@@ -236,15 +235,15 @@ var _CPWindowViewResizeIndicatorImage = nil;
{
if (CGSizeEqualToSize(_resizeIndicatorOffset, anOffset))
return;
_resizeIndicatorOffset = anOffset;
if (!_resizeIndicator)
return;
var size = [_resizeIndicator frame].size,
boundsSize = [self frame].size;
[_resizeIndicator setFrameOrigin:CGPointMake(boundsSize.width - size.width - anOffset.width, boundsSize.height - size.height - anOffset.height)];
}
@@ -280,7 +279,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
{
if (!_toolbarView || [_toolbarView isHidden])
return [self toolbarOffset].height;
return CGRectGetMaxY([_toolbarView frame]);
}
@@ -294,20 +293,20 @@ var _CPWindowViewResizeIndicatorImage = nil;
var theWindow = [self window],
bounds = [self bounds],
width = CGRectGetWidth(bounds);
if ([[theWindow toolbar] isVisible])
{
var toolbarView = [self toolbarView],
toolbarOffset = [self toolbarOffset];
[toolbarView setFrame:CGRectMake(toolbarOffset.width, toolbarOffset.height, width, CGRectGetHeight([toolbarView frame]))];
}
if ([self showsResizeIndicator])
{
var size = [_resizeIndicator frame].size,
boundsSize = [self bounds].size;
[_resizeIndicator setFrameOrigin:CGPointMake(boundsSize.width - size.width - _resizeIndicatorOffset.width, boundsSize.height - size.height - _resizeIndicatorOffset.height)];
}
}
@@ -317,11 +316,11 @@ var _CPWindowViewResizeIndicatorImage = nil;
var theWindow = [self window],
toolbar = [theWindow toolbar],
toolbarView = [toolbar _toolbarView];
if (_toolbarView !== toolbarView)
{
[_toolbarView removeFromSuperview];
if (toolbarView)
{
[toolbarView removeFromSuperview];
@@ -329,7 +328,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
[self addSubview:toolbarView];
}
_toolbarView = toolbarView;
}
+11 -7
View File
@@ -28,7 +28,7 @@
@import "CPDocument.j"
/*!
/*!
@ingroup appkit
@class CPWindowController
@@ -62,7 +62,7 @@
/*!
Initializes the controller with a window.
@param aWindow the window to control
@return the initialzed window controller
@return the initialized window controller
*/
- (id)initWithWindow:(CPWindow)aWindow
{
@@ -82,7 +82,7 @@
}
/*!
Initializes the controller with a Capppuccino Interface Builder name.
Initializes the controller with a Cappuccino Interface Builder name.
@param aWindowCibName the cib name of the window to control
@return the initialized window controller
*/
@@ -171,8 +171,8 @@
if (_window === nil && [_cibOwner isKindOfClass:[CPDocument class]])
[self setWindow:[_cibOwner valueForKey:@"window"]];
if (!_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];
@@ -232,7 +232,7 @@
{
if (![self supportsMultipleDocuments])
[self removeDocument:_document];
[defaultCenter removeObserver:self
name:CPDocumentWillSaveNotification
object:_document];
@@ -276,6 +276,10 @@
[self setViewController:viewController];
[self synchronizeWindowTitleWithDocumentName];
// Change of document means toolbar items may no longer make sense.
// FIXME: DOCUMENT ARCHITECTURE Should we setToolbar: as well?
[[[self window] toolbar] validateVisibleItems];
}
- (void)setSupportsMultipleDocuments:(BOOL)shouldSupportMultipleDocuments
@@ -381,7 +385,7 @@
}
/*!
Sets whether the document has unsaved changes. The window can use this as a hint to
Sets whether the document has unsaved changes. The window can use this as a hint to
@param isEdited \c YES means the document has unsaved changes.
*/
- (void)setDocumentEdited:(BOOL)isEdited
+62
View File
@@ -0,0 +1,62 @@
/*
* CPCibBindingConnector.j
* AppKit
*
* Created by Ross Boucher.
* Copyright 2010, 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"
var CPCibBindingConnectorBindingKey = @"CPCibBindingConnectorBindingKey",
CPCibBindingConnectorKeyPathKey = @"CPCibBindingConnectorKeyPathKey",
CPCibBindingConnectorOptionsKey = @"CPCibBindingConnectorOptionsKey";
@implementation CPCibBindingConnector : CPCibConnector
{
id _binding;
id _keyPath;
id _options;
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_binding = [aCoder decodeObjectForKey:CPCibBindingConnectorBindingKey];
_keyPath = [aCoder decodeObjectForKey:CPCibBindingConnectorKeyPathKey];
_options = [aCoder decodeObjectForKey:CPCibBindingConnectorOptionsKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_binding forKey:CPCibBindingConnectorBindingKey];
[aCoder encodeObject:_keyPath forKey:CPCibBindingConnectorKeyPathKey];
[aCoder encodeObject:_options forKey:CPCibBindingConnectorOptionsKey];
}
- (void)establishConnection
{
[_source bind:_binding toObject:_destination withKeyPath:_keyPath options:_options];
}
@end
+2 -2
View File
@@ -34,7 +34,7 @@ var _CPCibCustomObjectClassName = @"_CPCibCustomObjectClassName";
if (self)
_className = [aCoder decodeObjectForKey:_CPCibCustomObjectClassName];
return self;
}
@@ -65,7 +65,7 @@ var _CPCibCustomObjectClassName = @"_CPCibCustomObjectClassName";
if (theClass === [CPApplication class])
return [CPApplication sharedApplication];
return [[theClass alloc] init];
}
+5 -5
View File
@@ -84,7 +84,7 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
{
#if DEBUG
CPLog("Unknown class \"" + _className + "\" in cib file, using CPView instead.");
#endif
#endif
theClass = [CPView class];
}
@@ -97,16 +97,16 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
}
var view = [[theClass alloc] initWithFrame:[self frame]];
if (view)
{
[view setBounds:[self bounds]];
// Since the object replacement logic hasn't had a chance to kick in yet, we need to do it manually:
var subviews = [self subviews],
index = 0,
count = subviews.length;
for (; index < count; ++index)
[view addSubview:subviews[index]];
@@ -116,7 +116,7 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
[view setHitTests:[self hitTests]];
[view setHidden:[self isHidden]];
[view setAlphaValue:[self alphaValue]];
[_superview replaceSubview:self with:view];
[view setBackgroundColor:[self backgroundColor]];
+3 -3
View File
@@ -12,15 +12,15 @@
- (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle awakenCustomResources:(BOOL)shouldAwakenCustomResources
{
self = [super initForReadingWithData:data];
if (self)
{
_bundle = aBundle;
_awakenCustomResources = shouldAwakenCustomResources;
[self setDelegate:self];
}
return self;
}
+22 -21
View File
@@ -28,36 +28,37 @@
@import "CPCibConnector.j"
@import "CPCibControlConnector.j"
@import "CPCibOutletConnector.j"
@import "CPCibBindingConnector.j"
@implementation _CPCibObjectData : CPObject
{
CPArray _namesKeys;
CPArray _namesValues;
CPArray _accessibilityConnectors;
CPArray _accessibilityOidsKeys;
CPArray _accessibilityOidsValues;
CPArray _classesKeys;
CPArray _classesValues;
CPArray _connections;
id _fontManager;
CPString _framework;
int _nextOid;
CPArray _objectsKeys;
CPArray _objectsValues;
CPArray _oidKeys;
CPArray _oidValues;
_CPCibCustomObject _fileOwner;
CPSet _visibleWindows;
JSObject _replacementObjects;
@@ -113,28 +114,28 @@
var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey",
_CPCibObjectDataNamesValuesKey = @"_CPCibObjectDataNamesValuesKey",
_CPCibObjectDataAccessibilityConnectorsKey = @"_CPCibObjectDataAccessibilityConnectors",
_CPCibObjectDataAccessibilityOidsKeysKey = @"_CPCibObjectDataAccessibilityOidsKeys",
_CPCibObjectDataAccessibilityOidsValuesKey = @"_CPCibObjectDataAccessibilityOidsValues",
_CPCibObjectDataClassesKeysKey = @"_CPCibObjectDataClassesKeysKey",
_CPCibObjectDataClassesValuesKey = @"_CPCibObjectDataClassesValuesKey",
_CPCibObjectDataConnectionsKey = @"_CPCibObjectDataConnectionsKey",
_CPCibObjectDataFontManagerKey = @"_CPCibObjectDataFontManagerKey",
_CPCibObjectDataFrameworkKey = @"_CPCibObjectDataFrameworkKey",
_CPCibObjectDataNextOidKey = @"_CPCibObjectDataNextOidKey",
_CPCibObjectDataObjectsKeysKey = @"_CPCibObjectDataObjectsKeysKey",
_CPCibObjectDataObjectsValuesKey = @"_CPCibObjectDataObjectsValuesKey",
_CPCibObjectDataOidKeysKey = @"_CPCibObjectDataOidKeysKey",
_CPCibObjectDataOidValuesKey = @"_CPCibObjectDataOidValuesKey",
_CPCibObjectDataFileOwnerKey = @"_CPCibObjectDataFileOwnerKey",
_CPCibObjectDataVisibleWindowsKey = @"_CPCibObjectDataVisibleWindowsKey";
@@ -194,17 +195,17 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
[aCoder encodeObject:_connections forKey:_CPCibObjectDataConnectionsKey];
//id _fontManager;
[aCoder encodeObject:_framework forKey:_CPCibObjectDataFrameworkKey];
[aCoder encodeInt:_nextOid forKey:_CPCibObjectDataNextOidKey];
[aCoder encodeObject:_objectsKeys forKey:_CPCibObjectDataObjectsKeysKey];
[aCoder encodeObject:_objectsValues forKey:_CPCibObjectDataObjectsValuesKey];
[aCoder encodeObject:_oidKeys forKey:_CPCibObjectDataOidKeysKey];
[aCoder encodeObject:_oidValues forKey:_CPCibObjectDataOidValuesKey];
[aCoder encodeObject:_fileOwner forKey:_CPCibObjectDataFileOwnerKey];
// CPCustomObject _fileOwner;
+24 -24
View File
@@ -5,19 +5,19 @@
@import "CPWindow.j"
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
_CPCibWindowTemplateViewClassKey = @"_CPCibWindowTemplateViewClassKey",
_CPCibWindowTemplateWindowClassKey = @"_CPCibWindowTemplateWindowClassKey",
_CPCibWindowTemplateWindowRectKey = @"_CPCibWindowTemplateWindowRectKey",
_CPCibWindowTemplateWindowStyleMaskKey = @"_CPCibWindowTempatStyleMaskKey",
_CPCibWindowTemplateWindowTitleKey = @"_CPCibWindowTemplateWindowTitleKey",
_CPCibWindowTemplateWindowViewKey = @"_CPCibWindowTemplateWindowViewKey",
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop = @"_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop";
_CPCibWindowTemplateWindowIsFullPlatformWindowKey = @"_CPCibWindowTemplateWindowIsFullPlatformWindowKey";
_CPCibWindowTemplateViewClassKey = @"_CPCibWindowTemplateViewClassKey",
_CPCibWindowTemplateWindowClassKey = @"_CPCibWindowTemplateWindowClassKey",
_CPCibWindowTemplateWindowRectKey = @"_CPCibWindowTemplateWindowRectKey",
_CPCibWindowTemplateWindowStyleMaskKey = @"_CPCibWindowTempatStyleMaskKey",
_CPCibWindowTemplateWindowTitleKey = @"_CPCibWindowTemplateWindowTitleKey",
_CPCibWindowTemplateWindowViewKey = @"_CPCibWindowTemplateWindowViewKey",
_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop = @"_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop",
_CPCibWindowTemplateWindowIsFullPlatformWindowKey = @"_CPCibWindowTemplateWindowIsFullPlatformWindowKey";
@implementation _CPCibWindowTemplate : CPObject
{
@@ -60,27 +60,27 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinS
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
if ([aCoder containsValueForKey:_CPCibWindowTemplateMinSizeKey])
_minSize = [aCoder decodeSizeForKey:_CPCibWindowTemplateMinSizeKey];
if ([aCoder containsValueForKey:_CPCibWindowTemplateMaxSizeKey])
_maxSize = [aCoder decodeSizeForKey:_CPCibWindowTemplateMaxSizeKey];
_viewClass = [aCoder decodeObjectForKey:_CPCibWindowTemplateViewClassKey];
_windowClass = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowClassKey];
_windowRect = [aCoder decodeRectForKey:_CPCibWindowTemplateWindowRectKey];
_windowStyleMask = [aCoder decodeIntForKey:_CPCibWindowTemplateWindowStyleMaskKey];
_windowTitle = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowTitleKey];
_windowView = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowViewKey];
_windowAutorecalculatesKeyViewLoop = !![aCoder decodeObjectForKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
_windowIsFullPlatformWindow = !![aCoder decodeObjectForKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
}
return self;
}
@@ -90,13 +90,13 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinS
[aCoder encodeSize:_minSize forKey:_CPCibWindowTemplateMinSizeKey];
if (_maxSize)
[aCoder encodeSize:_maxSize forKey:_CPCibWindowTemplateMaxSizeKey];
[aCoder encodeObject:_viewClass forKey:_CPCibWindowTemplateViewClassKey];
[aCoder encodeObject:_windowClass forKey:_CPCibWindowTemplateWindowClassKey];
[aCoder encodeRect:_windowRect forKey:_CPCibWindowTemplateWindowRectKey];
[aCoder encodeInt:_windowStyleMask forKey:_CPCibWindowTemplateWindowStyleMaskKey];
[aCoder encodeObject:_windowTitle forKey:_CPCibWindowTemplateWindowTitleKey];
[aCoder encodeObject:_windowView forKey:_CPCibWindowTemplateWindowViewKey];
@@ -126,13 +126,13 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinS
- (id)_cibInstantiate
{
var windowClass = CPClassFromString([self windowClass]);
/* if (!windowClass)
[NSException raise:NSInvalidArgumentException format:@"Unable to locate NSWindow class %@, using NSWindow",_windowClass];
class=[NSWindow class];*/
var theWindow = [[windowClass alloc] initWithContentRect:_windowRect styleMask:_windowStyleMask];
if (_minSize)
[theWindow setMinSize:_minSize];
if (_maxSize)
@@ -147,7 +147,7 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinS
[theWindow setContentView:_windowView];
[_windowView setAutoresizesSubviews:YES];
if ([_viewClass isKindOfClass:[CPToolbar class]])
{
[theWindow setToolbar:_viewClass];
+148 -148
View File
@@ -64,54 +64,54 @@ var CALayerRegisteredRunLoopUpdates = nil;
@implementation CALayer : CPObject
{
// Modifying the Layer Geometry
CGRect _frame;
CGRect _bounds;
CGPoint _position;
unsigned _zPosition;
CGPoint _anchorPoint;
CGAffineTransform _affineTransform;
CGAffineTransform _sublayerTransform;
CGAffineTransform _sublayerTransformForSublayers;
CGRect _backingStoreFrame;
CGRect _standardBackingStoreFrame;
BOOL _hasSublayerTransform;
BOOL _hasCustomBackingStoreFrame;
// Style Attributes
float _opacity;
BOOL _isHidden;
CPColor _backgroundColor;
// Managing Layer Hierarchy
CALayer _superlayer;
CPMutableArray _sublayers;
// Updating Layer Display
unsigned _runLoopUpdateMask;
BOOL _needsDisplayOnBoundsChange;
// Modifying the Delegate
id _delegate;
BOOL _delegateRespondsToDisplayLayerSelector;
BOOL _delegateRespondsToDrawLayerInContextSelector;
// DOM Implementation
DOMElement _DOMElement;
DOMElement _DOMContentsElement;
id _contents;
CGContext _context;
CPView _owningView;
CGAffineTransform _transformToLayer;
CGAffineTransform _transformFromLayer;
}
@@ -130,14 +130,14 @@ var CALayerRegisteredRunLoopUpdates = nil;
- (id)init
{
self = [super init];
if (self)
{
_frame = CGRectMakeZero();
_backingStoreFrame = CGRectMakeZero();
_standardBackingStoreFrame = CGRectMakeZero();
_bounds = CGRectMakeZero();
_position = CGPointMakeZero();
_zPosition = 0.0;
@@ -147,15 +147,15 @@ var CALayerRegisteredRunLoopUpdates = nil;
_transformToLayer = CGAffineTransformMakeIdentity(); // FIXME? does it matter?
_transformFromLayer = CGAffineTransformMakeIdentity();
_opacity = 1.0;
_isHidden = NO;
_masksToBounds = NO;
_sublayers = [];
_DOMElement = document.createElement("div");
_DOMElement.style.overflow = "visible";
_DOMElement.style.position = "absolute";
_DOMElement.style.visibility = "visible";
@@ -165,7 +165,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
_DOMElement.style.width = "0px";
_DOMElement.style.height = "0px";
}
return self;
}
@@ -182,20 +182,20 @@ var CALayerRegisteredRunLoopUpdates = nil;
var oldOrigin = _bounds.origin;
_bounds = _CGRectMakeCopy(aBounds);
if (_hasSublayerTransform)
_CALayerUpdateSublayerTransformForSublayers(self);
// _hasSublayerTransform == true will handle this for us.
/*else if (!CGPointEqualToPoint(_bounds.origin, oldOrigin))
{
var index = _sublayers.length;
// FIXME: This should climb the layer tree down.
while (index--)
_CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryPositionMask);
}*/
_CALayerRecalculateGeometry(self, CALayerGeometryBoundsMask);
}
@@ -215,9 +215,9 @@ var CALayerRegisteredRunLoopUpdates = nil;
{
if (CGPointEqualToPoint(_position, aPosition))
return;
_position = _CGPointMakeCopy(aPosition);
_CALayerRecalculateGeometry(self, CALayerGeometryPositionMask);
}
@@ -237,9 +237,9 @@ var CALayerRegisteredRunLoopUpdates = nil;
{
if (_zPosition == aZPosition)
return;
_zPosition = aZPosition;
[self registerRunLoopUpdateWithMask:CALayerZPositionUpdateMask];
}
@@ -252,18 +252,18 @@ var CALayerRegisteredRunLoopUpdates = nil;
anAnchorPoint = _CGPointMakeCopy(anAnchorPoint);
anAnchorPoint.x = MIN(1.0, MAX(0.0, anAnchorPoint.x));
anAnchorPoint.y = MIN(1.0, MAX(0.0, anAnchorPoint.y));
if (CGPointEqualToPoint(_anchorPoint, anAnchorPoint))
return;
_anchorPoint = anAnchorPoint;
if (_hasSublayerTransform)
_CALayerUpdateSublayerTransformForSublayers(self);
if (_owningView)
_position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y);
_CALayerRecalculateGeometry(self, CALayerGeometryAnchorPointMask);
}
@@ -283,9 +283,9 @@ var CALayerRegisteredRunLoopUpdates = nil;
{
if (CGAffineTransformEqualToTransform(_affineTransform, anAffineTransform))
return;
_affineTransform = _CGAffineTransformMakeCopy(anAffineTransform);
_CALayerRecalculateGeometry(self, CALayerGeometryAffineTransformMask);
}
@@ -307,16 +307,16 @@ var CALayerRegisteredRunLoopUpdates = nil;
return;
var hadSublayerTransform = _hasSublayerTransform;
_sublayerTransform = _CGAffineTransformMakeCopy(anAffineTransform);
_hasSublayerTransform = !_CGAffineTransformIsIdentity(_sublayerTransform);
if (_hasSublayerTransform)
{
_CALayerUpdateSublayerTransformForSublayers(self);
var index = _sublayers.length;
// FIXME: This should climb the layer tree down.
while (index--)
_CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryParentSublayerTransformMask);
@@ -353,23 +353,23 @@ var CALayerRegisteredRunLoopUpdates = nil;
/*!
Returns the layer's frame.
The frame defines the bounding box of the layer: the smallest
possible rectangle that could fit this layer after transform
The frame defines the bounding box of the layer: the smallest
possible rectangle that could fit this layer after transform
properties are applied in superlayer coordinates.
*/
- (CGRect)frame
{
if (!_frame)
_frame = [self convertRect:_bounds toLayer:_superlayer];
return _frame;
}
/*!
The Backing Store Frame specifies the frame of the actual backing
store used to contain this layer. Naturally, by default it is the
same as the frame, however, users can specify their own custom
Backing Store Frame in order to speed up certain operations, such as
store used to contain this layer. Naturally, by default it is the
same as the frame, however, users can specify their own custom
Backing Store Frame in order to speed up certain operations, such as
live transformation.
@return the backing store frame
*/
@@ -385,7 +385,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
- (void)setBackingStoreFrame:(CGRect)aFrame
{
_hasCustomBackingStoreFrame = (aFrame != nil);
if (aFrame == nil)
aFrame = CGRectMakeCopy(_standardBackingStoreFrame);
else
@@ -393,23 +393,23 @@ var CALayerRegisteredRunLoopUpdates = nil;
if (_superlayer)
{
aFrame = [_superlayer convertRect:aFrame toLayer:nil];
var bounds = [_superlayer bounds],
frame = [_superlayer convertRect:bounds toLayer:nil];
aFrame.origin.x -= _CGRectGetMinX(frame);
aFrame.origin.y -= _CGRectGetMinY(frame);
}
else
aFrame = CGRectMakeCopy(aFrame);
}
if (!CGPointEqualToPoint(_backingStoreFrame.origin, aFrame.origin))
[self registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask];
if (!CGSizeEqualToSize(_backingStoreFrame.size, aFrame.size))
[self registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask];
_backingStoreFrame = aFrame;
}
@@ -431,9 +431,9 @@ var CALayerRegisteredRunLoopUpdates = nil;
{
if (_contents == contents)
return;
_contents = contents;
[self composite];
}
@@ -445,26 +445,26 @@ var CALayerRegisteredRunLoopUpdates = nil;
{
if (USE_BUFFER && !_contents || !_context)
return;
CGContextClearRect(_context, _CGRectMake(0.0, 0.0, _CGRectGetWidth(_backingStoreFrame), _CGRectGetHeight(_backingStoreFrame)));
// Recomposite
var transform = _transformFromLayer;
if (_superlayer)
{
var superlayerTransform = _CALayerGetTransform(_superlayer, nil),
superlayerOrigin = CGPointApplyAffineTransform(_superlayer._bounds.origin, superlayerTransform);
transform = CGAffineTransformConcat(transform, superlayerTransform);
transform.tx -= superlayerOrigin.x;
transform.ty -= superlayerOrigin.y;
}
transform.tx -= _CGRectGetMinX(_backingStoreFrame);
transform.ty -= _CGRectGetMinY(_backingStoreFrame);
CGContextSaveGState(_context);
CGContextConcatCTM(_context, transform);//_transformFromView);
if (USE_BUFFER)
@@ -485,18 +485,18 @@ var CALayerRegisteredRunLoopUpdates = nil;
if (!_context)
{
_context = CGBitmapGraphicsContextCreate();
_DOMContentsElement = _context.DOMElement;
_DOMContentsElement.style.zIndex = -100;
_DOMContentsElement.style.overflow = "hidden";
_DOMContentsElement.style.position = "absolute";
_DOMContentsElement.style.visibility = "visible";
_DOMContentsElement.width = ROUND(_CGRectGetWidth(_backingStoreFrame));
_DOMContentsElement.height = ROUND(_CGRectGetHeight(_backingStoreFrame));
_DOMContentsElement.style.top = "0px";
_DOMContentsElement.style.left = "0px";
_DOMContentsElement.style.width = ROUND(_CGRectGetWidth(_backingStoreFrame)) + "px";
@@ -504,23 +504,23 @@ var CALayerRegisteredRunLoopUpdates = nil;
_DOMElement.appendChild(_DOMContentsElement);
}
if (USE_BUFFER)
{
if (_delegateRespondsToDisplayLayerSelector)
return [_delegate displayInLayer:self];
if (_CGRectGetWidth(_backingStoreFrame) == 0.0 || _CGRectGetHeight(_backingStoreFrame) == 0.0)
return;
if (!_contents)
_contents = CABackingStoreCreate();
CABackingStoreSetSize(_contents, _bounds.size);
[self drawInContext:CABackingStoreGetContext(_contents)];
}
[self composite];
}
@@ -535,7 +535,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
CGContextSetFillColor(aContext, _backgroundColor);
CGContextFillRect(aContext, _bounds);
}
if (_delegateRespondsToDrawLayerInContextSelector)
[_delegate drawLayer:self inContext:aContext];
}
@@ -559,9 +559,9 @@ var CALayerRegisteredRunLoopUpdates = nil;
{
if (_opacity == anOpacity)
return;
_opacity = anOpacity;
_DOMElement.style.opacity = anOpacity;
_DOMElement.style.filter = "alpha(opacity=" + anOpacity * 100 + ")";
}
@@ -600,7 +600,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
{
if (_masksToBounds == masksToBounds)
return;
_masksToBounds = masksToBounds;
_DOMElement.style.overflow = _masksToBounds ? "hidden" : "visible";
}
@@ -612,7 +612,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
- (void)setBackgroundColor:(CPColor)aColor
{
_backgroundColor = aColor;
[self setNeedsDisplay];
}
@@ -665,10 +665,10 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
{
if (_owningView)
[_owningView setLayer:nil];
if (!_superlayer)
return;
_superlayer._DOMElement.removeChild(_DOMElement);
[_superlayer._sublayers removeObject:self];
@@ -684,24 +684,24 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
{
if (!aLayer)
return;
var superlayer = [aLayer superlayer];
if (superlayer == self)
{
var index = [_sublayers indexOfObjectIdenticalTo:aLayer];
if (index == anIndex)
return;
[_sublayers removeObjectAtIndex:index];
if (index < anIndex)
--anIndex;
}
else if (superlayer != nil)
[aLayer removeFromSuperlayer];
ADJUST_CONTENTS_ZINDEX(aLayer);
[_sublayers insertObject:aLayer atIndex:anIndex];
@@ -710,9 +710,9 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
_DOMElement.appendChild(DOM(aLayer));
else
_DOMElement.insertBefore(DOM(aLayer), _sublayers[anIndex + 1]._DOMElement);
aLayer._superlayer = self;
if (self != superlayer)
_CALayerRecalculateGeometry(aLayer, 0xFFFFFFF);
}
@@ -726,7 +726,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
- (void)insertSublayer:(CALayer)aLayer below:(CALayer)aSublayer
{
var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : 0;
[self insertSublayer:aLayer atIndex:index == CPNotFound ? _sublayers.length : index];
}
@@ -754,16 +754,16 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
{
if (aSublayer == aLayer)
return;
// FIXME: EXCEPTION
if (aSublayer._superlayer != self)
{
alert("EXCEPTION");
return;
}
ADJUST_CONTENTS_ZINDEX(aLayer);
[_sublayers replaceObjectAtIndex:[_sublayers indexOfObjectIdenticalTo:aSublayer] withObject:aLayer];
_DOMElement.replaceChild(DOM(aSublayer), DOM(aLayer));
}
@@ -782,13 +782,13 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
if (mask & CALayerDOMUpdateMask)
_CALayerUpdateDOM(layer, mask);
if (mask & CALayerDisplayUpdateMask)
[layer display];
else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask)
[layer composite];
layer._runLoopUpdateMask = 0;
}
window.loop= false;
@@ -803,11 +803,11 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
if (CALayerRegisteredRunLoopUpdates == nil)
{
CALayerRegisteredRunLoopUpdates = {};
[[CPRunLoop currentRunLoop] performSelector:@selector(runLoopUpdateLayers)
target:CALayer argument:nil order:0 modes:[CPDefaultRunLoopMode]];
}
_runLoopUpdateMask |= anUpdateMask;
CALayerRegisteredRunLoopUpdates[[self UID]] = self;
}
@@ -846,7 +846,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
}
/*!
Marks the specified rectange as needing to be redrawn.
Marks the specified rectangle as needing to be redrawn.
@param aRect the area that needs to be redrawn.
*/
- (void)setNeedsDisplayInRect:(CGRect)aRect
@@ -890,8 +890,8 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
}
/*!
Converts the rectangle from the receier's coordinate system to the specified layer's coordinate system.
@param aRect the rectange to convert
Converts the rectangle from the receiver's coordinate system to the specified layer's coordinate system.
@param aRect the rectangle to convert
@param aLayer the layer coordinate system to convert to
@return the converted rectangle
*/
@@ -919,21 +919,21 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
{
if (_isHidden)
return nil;
var point = CGPointApplyAffineTransform(aPoint, _transformToLayer);
//alert(point.x + " " + point.y);
if (!_CGRectContainsPoint(_bounds, point))
return nil;
var layer = nil,
index = _sublayers.length;
// FIXME: this should take into account zPosition.
while (index--)
if (layer = [_sublayers[index] hitTest:point])
return layer;
return self;
}
@@ -946,12 +946,12 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
{
if (_delegate == aDelegate)
return;
_delegate = aDelegate;
_delegateRespondsToDisplayLayerSelector = [_delegate respondsToSelector:@selector(displayLayer:)];
_delegateRespondsToDrawLayerInContextSelector = [_delegate respondsToSelector:@selector(drawLayer:inContext:)];
if (_delegateRespondsToDisplayLayerSelector || _delegateRespondsToDrawLayerInContextSelector)
[self setNeedsDisplay];
}
@@ -968,15 +968,15 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
- (void)_setOwningView:(CPView)anOwningView
{
_owningView = anOwningView;
if (_owningView)
{
_owningView = anOwningView;
_bounds.size = CGSizeMakeCopy([_owningView bounds].size);
_position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y);
}
_CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask);
}
@@ -985,7 +985,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
{
_bounds.size = CGSizeMakeCopy([_owningView bounds].size);
_position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y);
_CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask);
}
@@ -993,20 +993,20 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
- (void)_update
{
window.loop = true;
var mask = _runLoopUpdateMask;
if (mask & CALayerDOMUpdateMask)
_CALayerUpdateDOM(self, mask);
if (mask & CALayerDisplayUpdateMask)
[self display];
else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask)
[self composite];
_runLoopUpdateMask = 0;
window.loop = false;
}
@@ -1018,7 +1018,7 @@ function _CALayerUpdateSublayerTransformForSublayers(aLayer)
anchorPoint = aLayer._anchorPoint,
translateX = _CGRectGetWidth(bounds) * anchorPoint.x,
translateY = _CGRectGetHeight(bounds) * anchorPoint.y;
aLayer._sublayerTransformForSublayers = CGAffineTransformConcat(
CGAffineTransformMakeTranslation(-translateX, -translateY),
CGAffineTransformConcat(aLayer._sublayerTransform,
@@ -1028,27 +1028,27 @@ function _CALayerUpdateSublayerTransformForSublayers(aLayer)
function _CALayerUpdateDOM(aLayer, aMask)
{
var DOMElementStyle = aLayer._DOMElement.style;
if (aMask & CALayerZPositionUpdateMask)
DOMElementStyle.zIndex = aLayer._zPosition;
var frame = aLayer._backingStoreFrame;
if (aMask & CALayerFrameOriginUpdateMask)
{
DOMElementStyle.top = ROUND(_CGRectGetMinY(frame)) + "px";
DOMElementStyle.left = ROUND(_CGRectGetMinX(frame)) + "px";
}
if (aMask & CALayerFrameSizeUpdateMask)
{
var width = MAX(0.0, ROUND(_CGRectGetWidth(frame))),
height = MAX(0.0, ROUND(_CGRectGetHeight(frame))),
DOMContentsElement = aLayer._DOMContentsElement;
DOMElementStyle.width = width + "px";
DOMElementStyle.height = height + "px";
if (DOMContentsElement)
{
DOMContentsElement.width = width;
@@ -1070,7 +1070,7 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
affineTransform = aLayer._affineTransform,
backingStoreFrameSize = _CGSizeMakeCopy(aLayer._backingStoreFrame),
hasCustomBackingStoreFrame = aLayer._hasCustomBackingStoreFrame;
// Go to anchor, transform, go back to bounds.
aLayer._transformFromLayer = CGAffineTransformConcat(
CGAffineTransformMakeTranslation(-width * anchorPoint.x - _CGRectGetMinX(aLayer._bounds), -height * anchorPoint.y - _CGRectGetMinY(aLayer._bounds)),
@@ -1082,68 +1082,68 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
// aLayer._transformFromLayer = CGAffineTransformConcat(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers);
_CGAffineTransformConcatTo(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers, aLayer._transformFromLayer);
}
aLayer._transformToLayer = CGAffineTransformInvert(aLayer._transformFromLayer);
//aLayer._transformFromLayer.tx = ROUND(aLayer._transformFromLayer.tx);
//aLayer._transformFromLayer.ty = ROUND(aLayer._transformFromLayer.ty);
aLayer._frame = nil;
aLayer._standardBackingStoreFrame = [aLayer convertRect:bounds toLayer:nil];
if (superlayer)
{
var bounds = [superlayer bounds],
frame = [superlayer convertRect:bounds toLayer:nil];
aLayer._standardBackingStoreFrame.origin.x -= _CGRectGetMinX(frame);
aLayer._standardBackingStoreFrame.origin.y -= _CGRectGetMinY(frame);
}
// We used to use CGRectIntegral here, but what we actually want, is the largest integral
// rect that would ever contain this box, since for any width/height, there are 2 (4)
// rect that would ever contain this box, since for any width/height, there are 2 (4)
// possible integral rects for it depending on it's position. It's OK that this is sometimes
// bigger than the "optimal" bounding integral rect since that doesn't change drawing.
var origin = aLayer._standardBackingStoreFrame.origin,
size = aLayer._standardBackingStoreFrame.size;
origin.x = FLOOR(origin.x);
origin.y = FLOOR(origin.y);
size.width = CEIL(size.width) + 1.0;
size.height = CEIL(size.height) + 1.0;
// FIXME: This avoids the central issue that a position change is sometimes a display and sometimes
// a div move, and sometimes both.
// Only use this frame if we don't currently have a custom backing store frame.
if (!hasCustomBackingStoreFrame)
{
var backingStoreFrame = CGRectMakeCopy(aLayer._standardBackingStoreFrame);
// These values get rounded in the DOM, so don't both updating them if they're
// These values get rounded in the DOM, so don't both updating them if they're
// not going to be different after rounding.
if (ROUND(_CGRectGetMinX(backingStoreFrame)) != ROUND(_CGRectGetMinX(aLayer._backingStoreFrame)) ||
ROUND(_CGRectGetMinY(backingStoreFrame)) != ROUND(_CGRectGetMinY(aLayer._backingStoreFrame)))
[aLayer registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask];
// Any change in size due to a geometry change is purely due to rounding error.
if ((_CGRectGetWidth(backingStoreFrame) != ROUND(_CGRectGetWidth(aLayer._backingStoreFrame)) ||
_CGRectGetHeight(backingStoreFrame) != ROUND(_CGRectGetHeight(aLayer._backingStoreFrame))))
[aLayer registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask];
aLayer._backingStoreFrame = backingStoreFrame;
}
if (aGeometryChange & CALayerGeometryBoundsMask && aLayer._needsDisplayOnBoundsChange)
[aLayer setNeedsDisplay];
// We need to recomposite if we have a custom backing store frame, OR
// We need to recompose if we have a custom backing store frame, OR
// If the change is not solely composed of position and anchor points changes.
// Anchor point and position changes simply move the object, requiring
// Anchor point and position changes simply move the object, requiring
// no re-rendering.
else if (hasCustomBackingStoreFrame || (aGeometryChange & ~(CALayerGeometryPositionMask | CALayerGeometryAnchorPointMask)))
[aLayer setNeedsComposite];
var sublayers = aLayer._sublayers,
index = 0,
count = sublayers.length;
@@ -1155,45 +1155,45 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
function _CALayerGetTransform(fromLayer, toLayer)
{
var transform = CGAffineTransformMakeIdentity();
if (fromLayer)
{
var layer = fromLayer;
// If we have a fromLayer, "climb up" the layer tree until
// If we have a fromLayer, "climb up" the layer tree until
// we hit the root node or we hit the toLayer.
while (layer && layer != toLayer)
{
var transformFromLayer = layer._transformFromLayer;
//transform = CGAffineTransformConcat(transform, layer._transformFromLayer);
_CGAffineTransformConcatTo(transform, transformFromLayer, transform);
layer = layer._superlayer;
}
// If we hit toLayer, then we're done.
if (layer == toLayer)
return transform;
}
var layers = [],
layer = toLayer;
while (layer)
{
layers.push(layer);
layer = layer._superlayer;
}
var index = layers.length;
while (index--)
{
var transformToLayer = layers[index]._transformToLayer;
_CGAffineTransformConcatTo(transform, transformToLayer, transform);
}
return transform;
}
+23 -23
View File
@@ -31,7 +31,7 @@ function CFHashCode(aCFObject)
{
if (!aCFObject.hash)
aCFObject.hash = ++CFTypeGlobalCount;
return aCFObject;
}
@@ -47,7 +47,7 @@ function CGColorGetConstantColor(aColorName)
}
/*!
This function is for source compatability.
This function is for source compatibility.
*/
function CGColorRetain(aColor)
{
@@ -55,7 +55,7 @@ function CGColorRetain(aColor)
}
/*!
This function is for source compatability.
This function is for source compatibility.
*/
function CGColorRelease()
{
@@ -74,14 +74,14 @@ function CGColorCreate(aColorSpace, components)
return NULL;
var components = components.slice();
CGColorSpaceStandardizeComponents(aColorSpace, components);
var UID = CFHashCode(aColorSpace) + components.join("");
if (_CGColorMap[UID])
return _CGColorMap[UID];
return _CGColorMap[UID] = { colorspace:aColorSpace, pattern:NULL, components:components };
}
@@ -150,9 +150,9 @@ function CGColorCreateGenericCMYK(cyan, magenta, yellow, black, alpha)
function CGColorCreateCopyWithAlpha(aColor, anAlpha)
{
var components = aColor.components;
if (!aColor || anAlpha == components[components.length - 1])
return aColor;
return aColor;
if (aColor.pattern)
var copy = CGColorCreateWithPattern(aColor.colorspace, aColor.pattern, components);
@@ -160,7 +160,7 @@ function CGColorCreateCopyWithAlpha(aColor, anAlpha)
var copy = CGColorCreate(aColor.colorspace, components);
copy.components[components.length - 1] = anAlpha;
return copy;
}
@@ -191,7 +191,7 @@ function CGColorEqualToColor(lhs, rhs)
{
if (lhs == rhs)
return true;
if (!lhs || !rhs)
return false;
@@ -201,17 +201,17 @@ function CGColorEqualToColor(lhs, rhs)
if (lhsComponentCount != rhsComponents.length)
return false;
while (lhsComponentCount--)
while (lhsComponentCount--)
if (lhsComponents[lhsComponentCount] != rhsComponents[lhsComponentCount])
return false;
if (lhs.pattern != rhs.pattern)
return false;
if (CGColorSpaceEqualToColorSpace(lhs.colorspace, rhs.colorspace))
return false;
return true;
}
@@ -224,7 +224,7 @@ function CGColorEqualToColor(lhs, rhs)
function CGColorGetAlpha(aColor)
{
var components = aColor.components;
return components[components.length - 1];
}
@@ -273,13 +273,13 @@ function CGColorGetPattern(aColor)
}
/* var components = aColor.components;
case : _CGCSSForColor[CFGetHash(aColor)] = "rgba(" + ROUND(components[0] * 255.0) + ',' + ROUND(components[0] * 255.0) + ',' ROUND(components[0] * 255.0) + ',' + ROUND(components[0] * 255.0);
_cssString = (hasAlpha ? "rgba(" : "rgb(") +
parseInt(_components[0] * 255.0) + ", " +
parseInt(_components[1] * 255.0) + ", " +
parseInt(_components[2] * 255.0) +
(hasAlpha ? (", " + _components[3]) : "") + ")";
_cssString = (hasAlpha ? "rgba(" : "rgb(") +
parseInt(_components[0] * 255.0) + ", " +
parseInt(_components[1] * 255.0) + ", " +
parseInt(_components[2] * 255.0) +
(hasAlpha ? (", " + _components[3]) : "") + ")";
function CFStringFromColor()
{
+34 -32
View File
@@ -27,7 +27,7 @@
kCGLineCapButt = 0;
kCGLineCapRound = 1;
kCGLineCapRound = 1;
kCGLineCapSquare = 2;
kCGLineJoinMiter = 0;
@@ -79,7 +79,7 @@ kCGBlendModePlusLighter = 27;
*/
/*!
This function is just here for source compatability.
This function is just here for source compatibility.
It does nothing.
@group CGContext
*/
@@ -88,7 +88,7 @@ function CGContextRelease()
}
/*!
This function is just here for source compatability.
This function is just here for source compatibility.
It does nothing.
@param aContext a CGContext
@return CGContext the context
@@ -114,8 +114,8 @@ if (!CPFeatureIsCompatible(CPHTMLCanvasFeature))
*/
function CGGStateCreate()
{
return { alpha:1.0, strokeStyle:"#000", fillStyle:"#ccc", lineWidth:1.0, lineJoin:kCGLineJoinMiter, lineCap:kCGLineCapButt, miterLimit:10.0, globalAlpha:1.0,
blendMode:kCGBlendModeNormal,
return { alpha:1.0, strokeStyle:"#000", fillStyle:"#ccc", lineWidth:1.0, lineJoin:kCGLineJoinMiter, lineCap:kCGLineCapButt, miterLimit:10.0, globalAlpha:1.0,
blendMode:kCGBlendModeNormal,
shadowOffset:_CGSizeMakeZero(), shadowBlur:0.0, shadowColor:NULL, CTM:_CGAffineTransformMakeIdentity() };
}
@@ -126,9 +126,9 @@ function CGGStateCreate()
*/
function CGGStateCreateCopy(aGState)
{
return { alpha:aGState.alpha, strokeStyle:aGState.strokeStyle, fillStyle:aGState.fillStyle, lineWidth:aGState.lineWidth,
lineJoin:aGState.lineJoin, lineCap:aGState.lineCap, miterLimit:aGState.miterLimit, globalAlpha:aGState.globalAlpha,
blendMode:aGState.blendMode,
return { alpha:aGState.alpha, strokeStyle:aGState.strokeStyle, fillStyle:aGState.fillStyle, lineWidth:aGState.lineWidth,
lineJoin:aGState.lineJoin, lineCap:aGState.lineCap, miterLimit:aGState.miterLimit, globalAlpha:aGState.globalAlpha,
blendMode:aGState.blendMode,
shadowOffset:aGState.shadowOffset, shadowBlur:aGState.shadowBlur, shadowColor:aGState.shadowColor, CTM:_CGAffineTransformMakeCopy(aGState.CTM) };
}
@@ -256,10 +256,10 @@ function CGContextAddPath(aContext, aPath)
{
if (!aContext || CGPathIsEmpty(aPath))
return;
if (!aContext.path)
aContext.path = CGPathCreateMutable();
CGPathAddPath(aContext.path, aContext.gState.CTM, aPath);
}
@@ -332,7 +332,7 @@ function CGContextMoveToPoint(aContext, x, y)
{
if (!aContext.path)
aContext.path = CGPathCreateMutable();
CGPathMoveToPoint(aContext.path, aContext.gState.CTM, x, y);
}
@@ -358,11 +358,11 @@ function CGContextFillRects(aContext, rects, count)
{
if (arguments[2] === undefined)
var count = rects.length;
CGContextBeginPath(aContext);
CGContextAddRects(aContext, rects, count);
CGContextClosePath(aContext);
CGContextDrawPath(aContext, kCGPathFill);
}
@@ -373,11 +373,11 @@ function CGContextFillRects(aContext, rects, count)
@return void
*/
function CGContextStrokeRect(aContext, aRect)
{
{
CGContextBeginPath(aContext);
CGContextAddRect(aContext, aRect);
CGContextClosePath(aContext);
CGContextDrawPath(aContext, kCGPathStroke);
}
@@ -391,10 +391,10 @@ function CGContextStrokeRect(aContext, aRect)
function CGContextStrokeRectWithWidth(aContext, aRect, aWidth)
{
CGContextSaveGState(aContext);
CGContextSetLineWidth(aContext, aWidth);
CGContextStrokeRect(aContext, aRect);
CGContextRestoreGState(aContext);
}
@@ -407,7 +407,7 @@ function CGContextStrokeRectWithWidth(aContext, aRect, aWidth)
function CGContextConcatCTM(aContext, aTransform)
{
var CTM = aContext.gState.CTM;
_CGAffineTransformConcatTo(CTM, aTransform, CTM);
}
@@ -431,7 +431,7 @@ function CGContextGetCTM(aContext)
function CGContextRotateCTM(aContext, anAngle)
{
var gState = aContext.gState;
gState.CTM = CGAffineTransformRotate(gState.CTM, anAngle);
}
@@ -445,7 +445,7 @@ function CGContextRotateCTM(aContext, anAngle)
function CGContextScaleCTM(aContext, sx, sy)
{
var gState = aContext.gState;
gState.CTM = _CGAffineTransformScale(gState.CTM, sx, sy);
}
@@ -459,14 +459,14 @@ function CGContextScaleCTM(aContext, sx, sy)
function CGContextTranslateCTM(aContext, tx, ty)
{
var gState = aContext.gState;
gState.CTM = _CGAffineTransformTranslate(gState.CTM, tx, ty);
}
/*!
Sets the current offset, and blur for shadows in core graphics drawing operations
@param aContext the CGContext of the shadow
@param aSize a CGSize indicating the offset of the shaodw
@param aSize a CGSize indicating the offset of the shadow
@param aBlur a float indicating the blur radius
@return void
*/
@@ -474,7 +474,7 @@ function CGContextTranslateCTM(aContext, tx, ty)
function CGContextSetShadow(aContext, aSize, aBlur)
{
var gState = aContext.gState;
gState.shadowOffset = _CGSizeMakeCopy(aSize);
gState.shadowBlur = aBlur;
gState.shadowColor = [CPColor shadowColor];
@@ -483,7 +483,7 @@ function CGContextSetShadow(aContext, aSize, aBlur)
/*!
Sets the current offset, blur, and color for shadows in core graphics drawing operations
@param aContext the CGContext of the shadow
@param aSize a CGSize indicating the offset of the shaodw
@param aSize a CGSize indicating the offset of the shadow
@param aBlur a float indicating the blur radius
@param aColor a CPColor object indicating the color of the shadow
@return void
@@ -491,7 +491,7 @@ function CGContextSetShadow(aContext, aSize, aBlur)
function CGContextSetShadowWithColor(aContext, aSize, aBlur, aColor)
{
var gState = aContext.gState;
gState.shadowOffset = _CGSizeMakeCopy(aSize);
gState.shadowBlur = aBlur;
gState.shadowColor = aColor;
@@ -535,6 +535,7 @@ function CGContextEOFillPath(aContext)
function CGContextFillPath(aContext)
{
CGContextDrawPath(aContext, kCGPathFill);
CGContextClosePath(aContext);
}
var KAPPA = 4.0 * ((SQRT2 - 1.0) / 3.0);
@@ -588,6 +589,7 @@ function CGContextStrokeEllipseInRect(aContext, aRect)
function CGContextStrokePath(aContext)
{
CGContextDrawPath(aContext, kCGPathStroke);
CGContextClosePath(aContext);
}
/*!
@@ -603,10 +605,10 @@ function CGContextStrokePath(aContext)
function CGContextStrokeLineSegments(aContext, points, count)
{
var i = 0;
if (arguments["count"] == NULL)
var count = points.length;
CGContextBeginPath(aContext);
for (; i < count; i += 2)
@@ -614,7 +616,7 @@ function CGContextStrokeLineSegments(aContext, points, count)
CGContextMoveToPoint(aContext, points[i].x, points[i].y);
CGContextAddLineToPoint(aContext, points[i + 1].x, points[i + 1].y);
}
CGContextStrokePath(aContext);
}
@@ -650,7 +652,7 @@ function CGContextSetStrokeColor(aContext, aColor)
Fills a rounded rectangle.
@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 aRadius the distance from the rectangle corner to the rounded 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
@@ -669,7 +671,7 @@ function CGContextFillRoundedRectangleInRect(aContext, aRect, aRadius, ne, se, s
Strokes a rounded rectangle.
@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 aRadius the distance from the rectangle corner to the rounded 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
@@ -679,12 +681,12 @@ function CGContextFillRoundedRectangleInRect(aContext, aRect, aRadius, ne, se, s
function CGContextStrokeRoundedRectangleInRect(aContext, aRect, aRadius, ne, se, sw, nw)
{
CGContextBeginPath(aContext);
CGContextAddPath(aContext, CGPathWithRoundedRectangleInRect(aRect, aRadius, aRadius, ne, se, sw, nw));
CGContextAddPath(aContext, CGPathWithRoundedRectangleInRect(aRect, aRadius, aRadius, ne, se, sw, nw));
CGContextClosePath(aContext);
CGContextStrokePath(aContext);
}
/*!
/*!
@}
*/
-2
View File
@@ -255,8 +255,6 @@ function CGContextDrawPath(aContext, aMode)
vml.push("</cg_vml_:shape>");
aContext.path = NULL;
if (aContext.buffer != nil)
aContext.buffer += vml.join("");
else
+44 -43
View File
@@ -267,21 +267,21 @@ var KAPPA = 4.0 * ((SQRT2 - 1.0) / 3.0);
function CGPathWithEllipseInRect(aRect)
{
var path = CGPathCreateMutable();
if (_CGRectGetWidth(aRect) == _CGRectGetHeight(aRect))
if (_CGRectGetWidth(aRect) == _CGRectGetHeight(aRect))
CGPathAddArc(path, nil, _CGRectGetMidX(aRect), _CGRectGetMidY(aRect), _CGRectGetWidth(aRect) / 2.0, 0.0, 2 * PI, YES);
else
{
var axis = _CGSizeMake(_CGRectGetWidth(aRect) / 2.0, _CGRectGetHeight(aRect) / 2.0),
center = _CGPointMake(_CGRectGetMinX(aRect) + axis.width, _CGRectGetMinY(aRect) + axis.height);
else
{
var axis = _CGSizeMake(_CGRectGetWidth(aRect) / 2.0, _CGRectGetHeight(aRect) / 2.0),
center = _CGPointMake(_CGRectGetMinX(aRect) + axis.width, _CGRectGetMinY(aRect) + axis.height);
CGPathMoveToPoint(path, nil, center.x, center.y - axis.height);
CGPathAddCurveToPoint(path, nil, center.x + (KAPPA * axis.width), center.y - axis.height, center.x + axis.width, center.y - (KAPPA * axis.height), center.x + axis.width, center.y);
CGPathAddCurveToPoint(path, nil, center.x + axis.width, center.y + (KAPPA * axis.height), center.x + (KAPPA * axis.width), center.y + axis.height, center.x, center.y + axis.height);
CGPathAddCurveToPoint(path, nil, center.x - (KAPPA * axis.width), center.y + axis.height, center.x - axis.width, center.y + (KAPPA * axis.height), center.x - axis.width, center.y);
CGPathAddCurveToPoint(path, nil, center.x - axis.width, center.y - (KAPPA * axis.height), center.x - (KAPPA * axis.width), center.y - axis.height, center.x, center.y - axis.height);
}
CGPathAddCurveToPoint(path, nil, center.x + (KAPPA * axis.width), center.y - axis.height, center.x + axis.width, center.y - (KAPPA * axis.height), center.x + axis.width, center.y);
CGPathAddCurveToPoint(path, nil, center.x + axis.width, center.y + (KAPPA * axis.height), center.x + (KAPPA * axis.width), center.y + axis.height, center.x, center.y + axis.height);
CGPathAddCurveToPoint(path, nil, center.x - (KAPPA * axis.width), center.y + axis.height, center.x - axis.width, center.y + (KAPPA * axis.height), center.x - axis.width, center.y);
CGPathAddCurveToPoint(path, nil, center.x - axis.width, center.y - (KAPPA * axis.height), center.x - (KAPPA * axis.width), center.y - axis.height, center.x, center.y - axis.height);
}
CGPathCloseSubpath(path);
@@ -297,37 +297,38 @@ function CGPathWithRoundedRectangleInRect(aRect, xRadius, yRadius/*not currently
yMax = _CGRectGetMaxY(aRect);
CGPathMoveToPoint(path, nil, xMin + xRadius, yMin);
if (ne)
{
CGPathAddLineToPoint(path, nil, xMax - xRadius, yMin);
CGPathAddCurveToPoint(path, nil, xMax - xRadius, yMin, xMax, yMin, xMax, yMin + xRadius);
}
else
CGPathAddLineToPoint(path, nil, xMax, yMin);
if (se)
{
CGPathAddLineToPoint(path, nil, xMax, yMax - xRadius);
CGPathAddCurveToPoint(path, nil, xMax, yMax - xRadius, xMax, yMax, xMax - xRadius, yMax);
}
else
CGPathAddLineToPoint(path, nil, xMax, yMax);
if (sw)
{
CGPathAddLineToPoint(path, nil, xMin + xRadius, yMax);
CGPathAddCurveToPoint(path, nil, xMin + xRadius, yMax, xMin, yMax, xMin, yMax - xRadius);
}
else
CGPathAddLineToPoint(path, nil, xMin, yMax);
if (nw)
{
CGPathAddLineToPoint(path, nil, xMin, yMin + xRadius);
CGPathAddCurveToPoint(path, nil, xMin, yMin + xRadius, xMin, yMin, xMin + xRadius, yMin);
} else
CGPathAddLineToPoint(path, nil, xMin, yMin);
if (ne)
{
CGPathAddLineToPoint(path, nil, xMax - xRadius, yMin);
CGPathAddCurveToPoint(path, nil, xMax - xRadius, yMin, xMax, yMin, xMax, yMin + xRadius);
}
else
CGPathAddLineToPoint(path, nil, xMax, yMin);
if (se)
{
CGPathAddLineToPoint(path, nil, xMax, yMax - xRadius);
CGPathAddCurveToPoint(path, nil, xMax, yMax - xRadius, xMax, yMax, xMax - xRadius, yMax);
}
else
CGPathAddLineToPoint(path, nil, xMax, yMax);
if (sw)
{
CGPathAddLineToPoint(path, nil, xMin + xRadius, yMax);
CGPathAddCurveToPoint(path, nil, xMin + xRadius, yMax, xMin, yMax, xMin, yMax - xRadius);
}
else
CGPathAddLineToPoint(path, nil, xMin, yMax);
if (nw)
{
CGPathAddLineToPoint(path, nil, xMin, yMin + xRadius);
CGPathAddCurveToPoint(path, nil, xMin, yMin + xRadius, xMin, yMin, xMin + xRadius, yMin);
}
else
CGPathAddLineToPoint(path, nil, xMin, yMin);
CGPathCloseSubpath(path);
@@ -168,6 +168,8 @@ KeyCodesToUnicodeMap[CPKeyCodes.LEFT] = CPLeftArrowFunctionKey
KeyCodesToUnicodeMap[CPKeyCodes.UP] = CPUpArrowFunctionKey;
KeyCodesToUnicodeMap[CPKeyCodes.RIGHT] = CPRightArrowFunctionKey;
KeyCodesToUnicodeMap[CPKeyCodes.DOWN] = CPDownArrowFunctionKey;
KeyCodesToUnicodeMap[CPKeyCodes.HOME] = CPHomeFunctionKey;
KeyCodesToUnicodeMap[CPKeyCodes.END] = CPEndFunctionKey;
KeyCodesToUnicodeMap[CPKeyCodes.SEMICOLON] = ";";
KeyCodesToUnicodeMap[CPKeyCodes.DASH] = "-";
KeyCodesToUnicodeMap[CPKeyCodes.EQUALS] = "=";
Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

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