Compare commits

..
3068 Commits
Author SHA1 Message Date
Randall Luecke a80147bafd Merge branch 'master' into coretext 2011-06-25 22:03:51 -07:00
Randall Luecke fc81483371 Fix typeo in CPToolbar.j CPToolbarItems to not respect maxSize. Closes #1305. 2011-06-25 00:45:07 -07:00
Klaas Pieter Annema e552b022ba Merge branch 'pull-request-1302' 2011-06-24 12:21:02 +02:00
Antoine Mercadal 6c34bec51e do not return 0 if any conversion fail (return 2 instead) 2011-06-19 19:32:42 +02:00
Randall Luecke f170e4812d Documented CoreText. 2011-06-19 01:00:22 -07:00
Randall Luecke 070728aea9 Typo 2011-06-18 23:57:31 -07:00
Randall Luecke 5e3ae58d42 Added view drawing methods to CPAttributedString 2011-06-18 23:54:56 -07:00
Randall Luecke b4e4bdb924 Added string drawing methods for CPString. 2011-06-18 23:44:32 -07:00
Randall Luecke 0f097e0ff4 Added support for center alginment of in CTFrameDraw. 2011-06-18 22:59:28 -07:00
Randall Luecke e38845f993 Default to left alignment for frameDraw. 2011-06-18 22:54:03 -07:00
Randall Luecke f4f4dd8025 Default the text position point to (0,0) if it's undefined. 2011-06-18 21:53:50 -07:00
Randall Luecke c942259c90 Import CPAttributedString in Foundation.j now that we can actually use it! :D 2011-06-18 18:59:01 -07:00
Nicholas Small a4fb0920f6 Forgot key file of CoreText. 2011-06-16 11:49:05 -04:00
Ross Boucher cbabb544ab bootstrap should have a +x bit. 2011-06-15 12:54:11 -07:00
Nicholas Small 4d47b5abf5 CoreText.
Still needs a lot of work; there are bugs,
performance issues, and missing features.
2011-06-13 01:30:50 -07:00
Alexander Ljungberg aac09d8208 Clicking on a non-editable level indicator in a table row now selects that row. 2011-06-06 00:44:15 -04:00
Alexander Ljungberg a127fc9ec3 'Enabled' support for nib2cib of NSLevelIndicator. 2011-06-06 00:35:41 -04:00
Alexander Ljungberg 551aa300ea Merge branch 'master' of github.com:280north/cappuccino 2011-06-06 00:11:23 -04:00
Alexander Ljungberg 485e59b5eb More handlesContentAsCompoundValue, although fairly guess-work based. More research needed in the future. 2011-06-06 00:11:04 -04:00
Alexander Ljungberg fdfcbf1da2 CPArrayController handlesContentAsCompoundValue support for contentArray binding. 2011-06-05 19:39:28 -04:00
Alexander Ljungberg 0f5eee0258 nib2cib compatible CPNumberFormatter skeleton. 2011-06-05 19:27:21 -04:00
Alexander Ljungberg 870492eb96 Fix selection behaviour in previous commit. 2011-06-05 19:19:14 -04:00
Alexander Ljungberg b50005049e Fixed: array controller remove: would not only remove selected rows, but any other rows isEqual: to the selected rows. 2011-06-05 18:57:36 -04:00
Alexander Ljungberg 0e890e19ea Fixed: during CPUserDefault change notifications, objectForKey: could return the value from prior to the change. 2011-06-05 17:32:56 -04:00
Alexander Ljungberg 59aabc150c Crude but functional infinite recursion checker, optional at compile time. 2011-06-04 01:23:24 -04:00
Alexander Ljungberg b159815349 Suppress binding updates support. 2011-06-04 00:57:57 -04:00
Tom Robinson fa0a4d3b56 Fix tests for CI. 2011-06-03 21:15:25 -07:00
Alexander Ljungberg bfe5afaddd Whitespace cleanup. 2011-06-03 00:05:30 -04:00
Alexander Ljungberg 64e907156c Minor array controller optimisation: don't send a filterPredicate change notification if clearsFilterPredicateOnInsertion is YES but filterPredicate is already nil when insertObject:atArrangedObjectIndex: is called. 2011-06-03 00:00:39 -04:00
Alexander Ljungberg 5d01ca428c Optimise CPArrayController insertObject:atArrangedObjectIndex: by not attempting to arrange the content array. The given index is only meant for the arrangedObjects. 2011-06-02 23:41:03 -04:00
Alexander Ljungberg 0a9c9741e8 CPArray mutableCopy. 2011-06-02 15:09:54 -04:00
Alexander Ljungberg 2a3b9e13c3 Merge branch 'master' of github.com:280north/cappuccino 2011-06-02 12:35:23 -04:00
Alexander Ljungberg 4e07c9f9ee Decode but mostly ignore NSImages in nib2cib. Fixed: radio groups in IB come with an NSImage and so would not nib2cib anymore after the recent addition of template image support in NSButton. 2011-06-02 12:33:43 -04:00
Klaas Pieter Annema 9f2804c700 Merge branch '0.9.1b' 2011-06-01 12:10:10 +02:00
Klaas Pieter Annema 16183cca09 fix nib2cibbed controls enabled state 2011-06-01 12:09:49 +02:00
Klaas Pieter Annema 0af3b2f97c Merge branch 'master' of github.com:280north/cappuccino 2011-05-31 14:38:38 +02:00
Klaas Pieter Annema 065227a467 Merge branch '0.9.1b' 2011-05-31 14:38:18 +02:00
Klaas Pieter Annema 753257a650 Always tile the collectionview
A collectionview should always tile because it needs to adjusts it's size to properly work with an enclosing scrollview
2011-05-31 14:37:29 +02:00
Francisco Ryan Tolmasky I 671666e842 Fix selector typo.
Reviewed by me.
2011-05-31 01:27:41 -07:00
Francisco Ryan Tolmasky I b9ba1bbe93 Merge branch 'master' of github.com:280north/cappuccino 2011-05-31 00:46:23 -07:00
Francisco Ryan Tolmasky I 33e4fea0ec Fix forwarding in Objective-J (and many infinite recursions, such as when there is no superclass):
1. Fix infinite recursion when no superclass and method isn't implemented. Closes #469.
2. Fix infinite recursion when coercing an object without description implemented into a string. Closes #1289.
3. Add -forwardingTargetForSelector: support.

Reviewed by @tolmasky.
2011-05-31 00:44:16 -07:00
Randall Luecke 2887d4224c Remove empty setThemeState method in CPTableView 2011-05-30 23:08:41 -07:00
Randall Luecke 7a52805587 Support for setContinuous in CPLevelIndicator 2011-05-30 22:16:38 -07:00
Alexander Ljungberg 56d0ebe420 Typo fix. 2011-05-30 22:48:12 -04:00
Alexander Ljungberg b4b54e5744 Partial button image support in nib2cib covering NSAddTemplate and NSRemoveTemplate (standard plus and minus buttons). 2011-05-30 22:16:42 -04:00
Alexander Ljungberg 8a9d997b44 Manual test for CPUserDefaultsController and nib2cib of it. 2011-05-30 21:34:20 -04:00
Alexander Ljungberg e1f55fce3a nib2cib support for CPUserDefaultsController. 2011-05-30 21:15:43 -04:00
Alexander Ljungberg 6f6ce40c06 CPUserDefaultsController. 2011-05-30 21:03:44 -04:00
Alexander Ljungberg e32b302c59 Fixed: don't return nil from CPController initWithCoder:. 2011-05-30 20:45:35 -04:00
Alexander Ljungberg 302e753ebc Table nib2cib test with taller table rows and a level indicator cell. The latter is very useful when comparing cell spacing between Cappuccino and Cocoa. 2011-05-30 18:05:49 -04:00
Alexander Ljungberg 1c007461bd Draw table view gridlines precisely inside the right side of cells so that grid line positioning and spacing matches Cocoa.
Checked against Cocoa with 0, 1, 2 and 3 px intercell spacing.
2011-05-30 17:46:46 -04:00
Alexander Ljungberg 3d1638c780 Fixed: remove unused var block. 2011-05-30 16:56:24 -04:00
Alexander Ljungberg c5965c41d5 Fixed: don't repeat level indicator graphics downwards when the indicator is made taller than its natural size. Instead centre the indicator vertically.
This is not strictly like Cocoa - Cocoa places it on top vertically. But vertical centring makes more sense in e.g. tables with a large row height so it seems to make sense to deviate slightly here.
2011-05-30 16:21:50 -04:00
Alexander Ljungberg 7cc6fa348c Less flashy level indicator colours. 2011-05-30 12:56:35 -04:00
Alexander Ljungberg 1e6bca2214 Test level indicator with many segments. 2011-05-30 12:44:00 -04:00
Alexander Ljungberg d199bd86e6 More square level indicator segments which look better when each segment is very small. Colour and shadowing tweaks. Removed most of control border for a cleaner look. 2011-05-30 12:42:19 -04:00
Alexander Ljungberg 6338b01cb4 Fix accidental global. 2011-05-30 11:56:52 -04:00
Alexander Ljungberg 7714bcc34c Merge pull request #1288 from primalmotion/cappuccino
---

This patch avoids to have this kind of problem when too much segments are present:

<http://gyazo.com/36da2019514c429dd6edc2318fc101fc>

And do this:

<http://gyazo.com/65e23eb978dc493be96633c612e538ca.png>

+ fix typo ("self" not "sef")
2011-05-30 11:55:21 -04:00
Antoine Mercadal e6f029c1fa use all remaining space for last segment 2011-05-30 17:17:42 +02:00
Antoine Mercadal fe606e4757 fix typo + wrong sizing behaviour with too much segment 2011-05-30 17:06:39 +02:00
Alexander Ljungberg a6ee37e030 Support level indicators as table cells through nib2cib. 2011-05-30 00:56:28 -04:00
Alexander Ljungberg 71364c9b1a Fixed: very large numbers written to 280north1 plist files would be read back as very small numbers.
This affected nib2cib and cib files in particular.
2011-05-30 00:51:35 -04:00
Alexander Ljungberg a34155da61 Whitespace cleanup. 2011-05-30 00:43:07 -04:00
Alexander Ljungberg 2b8fa11b84 Optimise level indicator archiving (don't record static background colour). 2011-05-30 00:03:12 -04:00
Alexander Ljungberg 8fdcbac2bd Fix CPTableColumn width, minWidth and maxWidth encoding. 2011-05-29 23:18:30 -04:00
Alexander Ljungberg 4316192b8d Support NSButtonCell (e.g. checkboxes) in table columns through nib2cib. 2011-05-29 21:24:41 -04:00
Alexander Ljungberg 19090de380 Relayout level indicator as needed. 2011-05-29 16:47:36 -04:00
Alexander Ljungberg 85c5094c8b Manual test for level indicator. 2011-05-29 16:17:40 -04:00
Alexander Ljungberg ed8811e66b Click and drag edit support for level indicators. 2011-05-29 16:04:27 -04:00
Alexander Ljungberg b2e13919e0 Support for editing level indicators. 2011-05-29 15:41:53 -04:00
Alexander Ljungberg b4dabb6c35 Fix level indicator property names. 2011-05-29 15:26:21 -04:00
Alexander Ljungberg e9d0be1b6a Level indicator drawing. 2011-05-29 15:17:28 -04:00
Alexander Ljungberg 3f2607c2d0 CPLevelIndicator nib2cib support. 2011-05-28 18:44:32 -04:00
Alexander Ljungberg ceaea9c5b0 Remove leftover reference code. 2011-05-28 18:44:16 -04:00
Alexander Ljungberg 5419272e48 Fixed: don't import NSSlider.j in NSSlider.j. 2011-05-28 18:08:17 -04:00
Alexander Ljungberg 888fc89f86 Foundation for CPLevelIndicator. 2011-05-28 17:53:39 -04:00
Alexander Ljungberg 66c644641c Merge branch 'master' of github.com:280north/cappuccino 2011-05-28 02:08:22 -04:00
Alexander Ljungberg 669c6d4ac0 Merge branch '0.9.1b' 2011-05-28 02:08:03 -04:00
Alexander Ljungberg 8ed06169d1 Merge branch '0.9.1b' of github.com:280north/cappuccino into 0.9.1b 2011-05-28 02:07:33 -04:00
Alexander Ljungberg cf04fcc9d0 Verify correctness of observation notifications on arrangedObjects when the addObjects: message is sent. 2011-05-28 02:06:27 -04:00
Alexander Ljungberg 2e5081b137 Optimise array controller addObject: by eliminating entirely pointless rearrange when added objects did not pass the filter. Also avoided double rearrange if clearsFilterPredicateOnInsertion.
CPArrayControllerPerformance.j execution time on "testAddObject_, sorted, filtered" down from ~420ms to ~60ms on my machine.
2011-05-28 02:02:24 -04:00
Alexander Ljungberg a1a06c3f75 Performance test array controller addObject: when clearing the filter predicate. 2011-05-28 01:47:25 -04:00
Alexander Ljungberg e4950bd831 Fixed: duplicate observer notification for array controller addObject: (on arrangedObjects). 2011-05-28 01:26:28 -04:00
Alexander Ljungberg 607f681780 Typo fix. 2011-05-26 23:59:49 -04:00
Alexander Ljungberg 6eb4bf6656 Add temporary @ref and @deref analogs. 2011-05-26 23:59:08 -04:00
Klaas Pieter Annema 9b3926cada Merge branch '0.9.1b' 2011-05-24 12:30:07 +02:00
Klaas Pieter Annema 815e64356d implement _minimumFrameSize in CPButton 2011-05-24 12:29:23 +02:00
Klaas Pieter Annema 249a63af95 don't use remove method for removeMany selector 2011-05-24 12:28:25 +02:00
Klaas Pieter Annema 8520247605 Merge pull request #1247 from primalmotion/bundletask-option-preventsnib2cib
add setPreventsNib2Cib to bundletask.js
2011-05-23 22:45:42 -07:00
Alexander Ljungberg 686bce00d9 Merge branch '0.9.1b' 2011-05-23 13:49:09 -04:00
Alexander Ljungberg 8ae94c2745 Put CPBox in the right documentation module and add some basic documentation. 2011-05-23 13:46:09 -04:00
Klaas Pieter Annema 8feb5b5cee Merge branch 'right-command-key-fix' of https://github.com/aparajita/cappuccino into aparajita-right-command-key-fix 2011-05-23 11:14:12 +02:00
cacaodevandKlaas Pieter Annema 2b52f7d8da - Fixed a bug where the right control was incorrectly recreated with a default value when switching operators.
- As per cocoa, the predicate is recomputed when you send the right control action, not when you change text.  Update-as-you-type can be turned ON by subclassing -_sendsActionOnIncompleteTextChange method. Default is NO.
- Rewrote _reconfigureSubviews method, should be faster.
2011-05-23 10:59:44 +02:00
cacaodevandKlaas Pieter Annema ea660e3dd4 CPPredicateEditorRowtemplate:
Fixed a bug  when menu item titles and their corresponding keypath expressions where different and templates created in IB.
Fixed a bug appearing in Xcode4 IB when titles and keypath where identical.
2011-05-23 10:59:43 +02:00
cacaodevandKlaas Pieter Annema ca1a1b43f1 CPRuleEditor & CPPredicateEditor & CPPredicateEditorRowtemplate implementations with theming, nib2cib support.
Tests: CPRuleEditorCibTest, CPPredicateEditorCibTest, SmartFoldersDemo: a real world usage of CPPredicateEditor.
Documentation for these 3 new classes.
2011-05-23 10:59:43 +02:00
Ross Boucher 6c6ac4bd2e Merge pull request #1276 from hammerdr/Documentation
Elaborate what setItemPrototype expects and does in CPCollectionView.
2011-05-22 17:17:04 -07:00
Aparajita Fishman 59e5689d1a On WebKit (at least on Mac), right Command key code is 93, not 91. This was not being interpreted correctly. 2011-05-22 17:07:49 -07:00
Derek Hammer 7194a6961a Forgot a forward slash to end the pre tag. 2011-05-22 17:58:25 -05:00
Derek Hammer e404217e8b Elaborate what setItemPrototype expects and does in CPCollectionView. 2011-05-22 17:55:17 -05:00
Randy Luecke f419629ce4 Merge pull request #1260 from aparajita/cpmenu-remove-all
Added CPMenu -removeAll
2011-05-21 18:21:15 -07:00
Randy Luecke 35f958f1a7 Merge pull request #1273 from aparajita/cornerview-fix
CPTableView does not remove corner view if header view is removed
2011-05-21 18:20:43 -07:00
Alexander Ljungberg 64f9309994 Merge pull request #1268 from primalmotion/cappuccino
---

This patch makes nib2cib dealing with NSButtons much more better by setting particular offsets
according to the the kind of button.

Here is a screenshot of what I have done in IB :
<http://img839.imageshack.us/img839/4379/19894787.png>

This is the rendering of nib2cib without this patch:
<http://img263.imageshack.us/img263/1708/without.png>

This is the rendering of nib2cib with this patch:
<http://img263.imageshack.us/img263/1097/with.png>
2011-05-19 21:54:12 -04:00
Alexander Ljungberg 1c201d7dba Refs #1270. Fix a typo. 2011-05-19 21:50:30 -04:00
Alexander Ljungberg e1cd4d0f6e Merge pull request #1270 from aparajita/cappuccino
---

- Worked around a major bug in doxygen. It turns out that doxygen would not generate documentation for the first method -- or sometimes all methods (e.g. CPPredicate) -- if the ivar block for a class was missing or empty. This is solved now by inserting a dummy __doxygen__ ivar block.
- Missed a text substitution
- Darkened up the method header a bit to make it easier for the eye to anchor on.
- Changed to centered, fixed-width layout, it results in shorter line lengths which reads more easily.
- Moved support files to separate support directory.
- Removed blank lines at end of multi-parameter method prototypes.
- Fixed font declaration so fonts are correct in FireFox.
- Added spacing between parameter descriptions in method prototype.
- Fixed formatting of class description for CPPredicate.
- Added a missing @endverbatim to CPExpression.j.
2011-05-19 21:44:49 -04:00
Alexander Ljungberg 8fcbf3ce0c Merge branch '0.9.1' 2011-05-19 21:39:18 -04:00
Antoine MercadalandAlexander Ljungberg 915867e296 update the CPToolTip manual test 2011-05-19 21:33:36 -04:00
Antoine MercadalandAlexander Ljungberg ac24b9ee68 Fix Firefox problem. close #1271
This patch fix the blink problem with FF, by changing the positionning of tooltips, which by the way reflects more the Cocoa behaviour.
2011-05-19 21:33:25 -04:00
Aparajita Fishman aa7345935d Oops, accessor methods weren't being synthesized, removed some cruft 2011-05-19 17:10:50 -07:00
Aparajita Fishman 3937e66e06 Major fix to documentation generation:
- It turns out doxygen would not generate documentation for the first method in a file (or sometimes any methods at all) if there was no ivar block or an empty ivar block. Now a dummy __doxygen__ ivar is inserted in empty blocks to force correct behavior.

- Added a missing @endverbatim to CPExpression.j.

- Tweaked class documentation for CPPredicate.j.
2011-05-19 16:47:11 -07:00
Aparajita Fishman 634fa7b850 Stupid Uber Glory bundle duplicated the file a few times when stripping whitespace. 2011-05-18 17:33:30 -07:00
Aparajita Fishman f132ec5a50 Fixed formatting of lists and code in class description. The code did not change, I don't know why git says it did. 2011-05-18 16:55:43 -07:00
Aparajita Fishman 896f91215e Whitespace cleanup 2011-05-18 16:54:21 -07:00
Alexander Ljungberg b3d3f742f1 Merge pull request #1272 from primalmotion/cappuccino
---

This patch fix the blink problem with FF, by changing the positionning of tooltips, which by the way reflects more the Cocoa behaviour.
2011-05-18 14:50:53 -04:00
Antoine Mercadal bf516b5fc5 update the CPToolTip manual test 2011-05-18 19:33:01 +02:00
Aparajita Fishman 4ab69ebb68 If there is no header view, there should be no corner view. This is what Cocoa does. Also for correctness -enclosingScrollView should be used to get the table's scrollview. Test app included. 2011-05-18 10:30:43 -07:00
Antoine Mercadal 5a7c38d6eb Fix Firefox problem. close #1271
This patch fix the blink problem with FF, by changing the positionning of tooltips, which by the way reflects more the Cocoa behaviour.
2011-05-18 19:30:16 +02:00
Aparajita Fishman 6d962bc51a More documentation enhancements...
- Changed to centered, fixed-width layout, it results in shorter line lengths which reads more easily.
- Moved support files to separate support directory.
- Removed blank lines at end of multi-parameter method prototypes.
2011-05-18 07:50:27 -07:00
Antoine Mercadal e8a38e0bc0 add small visual test project 2011-05-18 08:51:05 +02:00
Aparajita Fishman 800e32edad Missed a text substitution, darkened up the method header a bit 2011-05-17 21:14:01 -07:00
Antoine Mercadal 4acb757aec adjust CPTextField positioning. Offsets changed since the usage of the new Aristo Art 2011-05-17 23:02:25 +02:00
Antoine Mercadal 9708985901 Make CPPopUpButton positionning pixel perfect 2011-05-17 22:16:26 +02:00
Ross Boucher 27a1c5e9a4 Merge pull request #1269 from aparajita/CPScrollView-doc-tweak
CPScrollView documentation tweak
2011-05-17 12:40:24 -07:00
Aparajita Fishman d7ef31c4f5 Documentation tweak 2011-05-17 10:54:52 -07:00
Antoine Mercadal fde18bba2e Correct button positionning.
This patch makes nib2cib dealing with NSButtons much more better by setting particular offsets
according the the kind of button.
2011-05-17 19:30:42 +02:00
Alexander Ljungberg f7a2a2e6fd Merge branch '0.9.1'
Conflicts:
	Tools/nib2cib/NSFont.j
2011-05-17 01:18:56 -04:00
Alexander Ljungberg fb07e2ae06 Refs #1266. Simple manual/visual test for font conversion. 2011-05-17 01:17:38 -04:00
Alexander Ljungberg f414ed2e8d Refs #1266. Still convert default font size in nib2cib even if the default font is bold.
(E.g. Lucida Grande 13 Bold should become Arial 12 Bold, not Arial 13 Bold.)
2011-05-17 01:16:03 -04:00
Alexander Ljungberg 86f3cc1831 Refs #1266. Minor optimisation. 2011-05-17 00:45:36 -04:00
Antoine MercadalandAlexander Ljungberg e77c706c38 nib2cib now takes care of bold and italic
This allows to set bold and italic in IB even if the size of the font is the default one
2011-05-17 00:45:28 -04:00
Alexander Ljungberg 8bdb0f6215 Replace extremely outdated and defunct NibApp manual test with a new one based on current templates, preserving and fixing the good parts of NibApp. 2011-05-17 00:40:41 -04:00
Alexander Ljungberg ec5c0e361d Refs #1266. Minor optimisation. 2011-05-17 00:38:39 -04:00
Alexander Ljungberg 533dbbfc69 Merge branch 'master' of github.com:280north/cappuccino 2011-05-17 00:12:08 -04:00
Alexander Ljungberg 0e04f7cae3 Merge pull request #1266 from primalmotion/cappuccino
---

This allows to set bold and italic in IB even if the size of the font is the default one
2011-05-17 00:11:57 -04:00
Antoine Mercadal e4c708efde nib2cib now takes care of bold and italic
This allows to set bold and italic in IB even if the size of the font is the default one
2011-05-17 00:28:33 +02:00
Francisco Ryan Tolmasky I 28bd18fab6 Merge pull request #1265 from aparajita/NSColorWell-enabled
NSColorWell was not setting its enabled state
2011-05-16 12:28:29 -07:00
Aparajita Fishman c9faea8753 NSColorWell was not setting its enabled state 2011-05-16 11:16:22 -07:00
Alexander Ljungberg 24c5b5f6c9 Merge branch '0.9.1' 2011-05-15 19:48:32 -04:00
Alexander Ljungberg 868201b492 Merge pull request #1033 from jlujan/cappuccino
---

The expression in the while loop in setParameters results in the wrong value being assigned to "key" which results in malformed param tags that look like the following:

    <param name=​"[object HTMLObjectElement]" >

Also, _params is not checked before assignment in setParameters which will overwrite flashvars if setFlashVars was called before setParameters.

Addresses issues #1031 and #1032
2011-05-15 19:47:43 -04:00
Alexander Ljungberg 8db94c0849 Merge branch '0.9.1' 2011-05-15 19:37:10 -04:00
Alexander Ljungberg f8984ced97 Refs #903. Comment out failing tests until Obj-J 2 fixes them. 2011-05-15 19:36:04 -04:00
Alexander Ljungberg 7539b5b06d Merge pull request #903 from paulbaumgart/cappuccino
---

Some OJTestCases for the Preprocessor to help make sure it still works as expected when it gets revamped to remove with() from method code generation.

Note that this adds a test case which the current Preprocessor fails: http://github.com/paulbaumgart/cappuccino/commit/8cc61cccfd78debe96eba96a7b332938e6d5377e#L1R81
2011-05-15 19:25:10 -04:00
Alexander Ljungberg 4ae47ed7c4 Merge branch 'master' of github.com:280north/cappuccino 2011-05-15 19:06:26 -04:00
Alexander Ljungberg 23cc507b12 Refs #1264. Make tooltip delay a constant and reduce it to 1.0 second to match Cocoa a little more closely.
Perhaps we should implement something like [[CPToolTipManager sharedToolTipManager] setInitialToolTipDelay:X] for completeness.
2011-05-15 19:01:26 -04:00
Alexander Ljungberg e9cfc806b6 Refs #1264. Size to fit small tooltips to remove empty whitespace on right side. 2011-05-15 18:58:01 -04:00
Alexander Ljungberg 5994c48d5f Refs #1264. Fix accidental global, cleanup. 2011-05-15 18:36:21 -04:00
Alexander Ljungberg bba0de3306 Merge pull request #1264 from primalmotion/cappuccino
---

These commits make the tooltips looking like cocoa ones.

 - More simple implementation (only one file added _CPToolTips.j)
 - Removal of CPAttachedWindow and CPAttachedWindowView
 - Placement is based on mouse position (just like cocoa)
 - It will try to find the best placement in case of a lake of space

Here is a screenshot : http://twitpic.com/4x401t
2011-05-15 18:29:51 -04:00
Francisco Ryan Tolmasky I 55937daa20 Merge pull request #1263 from aparajita/CPMenuManager-cleanup
_CPMenuManager style cleanup
2011-05-15 13:37:08 -07:00
Antoine Mercadal fe53f2503b let a fancy padding in case of placement forcing due to a lack of space 2011-05-15 22:36:33 +02:00
Antoine Mercadal 9058857403 style 2011-05-15 22:17:11 +02:00
Antoine Mercadal c7517d81c7 remove useless variables 2011-05-15 22:17:11 +02:00
Antoine Mercadal b8f46565ef make CPToolTip a framework private class 2011-05-15 22:17:11 +02:00
Antoine Mercadal 10940ace13 improve CPToolTips. Make them more cocoa like. Remove usage of CPAttachedWindow 2011-05-15 22:15:37 +02:00
Antoine Mercadal c57842d125 move Tooltips to CPView 2011-05-15 22:14:44 +02:00
Aparajita Fishman bb3ed30b4e Style cleanup 2011-05-15 12:15:00 -07:00
Alexander Ljungberg 1b1bd039c9 Merge branch '0.9.1' 2011-05-14 13:32:22 -04:00
Alexander Ljungberg 3fe907f007 Merge remote branch 'aparajita/better-docs' into 0.9.1 2011-05-14 13:28:19 -04:00
Alexander Ljungberg c784a2a1ca Merge branch '0.9.1' 2011-05-14 13:14:04 -04:00
Alexander Ljungberg d4d01d9686 Refs #1261. Clean up README.html tmp build file when jake docs is done. 2011-05-14 13:10:49 -04:00
Alexander Ljungberg 7ca8d0fb01 Whitespace cleanup. 2011-05-14 13:05:07 -04:00
Aparajita Fishman b985081184 Tweak the class list page 2011-05-12 23:16:50 -04:00
Aparajita Fishman 02f61fa413 Lightened up box around method prototype 2011-05-12 16:56:28 -04:00
Alexander Ljungberg 1a8808a4fd Merge pull request #1261 from aparajita/cappuccino
---

- Added generic facility for pre- and post-processor scripts to be run.
- Added support utility script for inclusion by processors.
- Totally overhauled css to make the pages more readable (I hope).
- Fixed some doc errors in CPTableView.
- Dont generate XML.
- Added colorize() and colorPrint() functions to common.jake.
- Added docs-no-frame task for generating docs without a sidebar frame.
2011-05-12 15:02:57 -04:00
Aparajita Fishman be5bbdcb32 Another overhaul of doc generation.
- Added generic facility for pre- and post-processor scripts to be run.
- Added support utility script for inclusion by processors.
- Totally overhauled css to make the pages more readable (I hope).
- Fixed some doc errors in CPTableView.
- Don't generate XML.
- Added colorize() and colorPrint() functions to common.jake.
- Added docs-no-frame task for generating docs without a sidebar frame.
2011-05-12 14:41:54 -04:00
Aparajita Fishman 1e9798eead Whitespace cleanup 2011-05-11 23:59:43 -04:00
Aparajita Fishman 3242e35250 Added CPMenu -removeAll method, removed unused internal _itemIsHighlighted method, test app 2011-05-11 23:59:33 -04:00
Alexander Ljungberg 864c4495c3 Merge branch '0.9.1' 2011-05-11 21:39:58 -04:00
Alexander Ljungberg 1c0f679f50 Refs #1245. Fixed: setToolTip: belongs in CPView, not CPControl. 2011-05-11 21:36:49 -04:00
Alexander Ljungberg 71763d041b Merge branch '0.9.1' 2011-05-11 21:04:47 -04:00
Alexander Ljungberg 345d48e224 Refs #1245. Make CPToolTip and CPAttachedWindow internal since they're not part of the Cocoa API. Refactored some code from CPControl to CPToolTip. 2011-05-11 20:35:13 -04:00
Alexander Ljungberg bb97c107c9 Refs #1245. Minor clean up. 2011-05-11 20:02:08 -04:00
Alexander Ljungberg 37cad2f59a Merge pull request #1245 from primalmotion/cappuccino
---

This is a basic merge of the TNKits tooltip system in Cappuccino.
2011-05-11 19:30:41 -04:00
Alexander Ljungberg 4ccbd592b2 Merge branch '0.9.1' 2011-05-11 19:28:34 -04:00
Alexander Ljungberg 8f5fe55dea Manual test for continuous buttons. 2011-05-11 19:28:01 -04:00
Alexander Ljungberg a51a051cee Fixed: if a button was unarchived it would have no continuous push delay and a 0 interval. 2011-05-11 19:15:44 -04:00
Alexander Ljungberg abd32f5abc Renamed CPButtonImageTest to CPButtonTest to reuse it for non image related tests.
Having fewer but slightly wider manual tests reduces the number of individual apps which need testing when changes are made.
2011-05-11 19:03:21 -04:00
Alexander Ljungberg d869350a56 Merge branch 'master' of github.com:280north/cappuccino 2011-05-11 18:54:50 -04:00
Alexander Ljungberg a3cd47b57c Merge pull request #1100 from MCF/cappuccino
---

Move the functionality from CPSteppers _CPContinuousButton object into CPButton.  Now any button can be made continuous instead of just the buttons for CPStepper.
2011-05-11 18:40:07 -04:00
Francisco Ryan Tolmasky I 019acb76a3 Very minor style change.
Reviewed by me.
2011-05-10 21:34:34 -07:00
Francisco Ryan Tolmasky I 4509df3c2a Merge pull request #1259 from masonmark/fix-test-for-leopard-sdk
Fix build-time test for presence of Mac OS X 10.5 SDK
2011-05-10 21:33:25 -07:00
Mason Mark 7059dd63b7 Use code style similar to other code in file 2011-05-11 13:26:18 +09:00
Mason Mark 402c82801b Extra newline typo 2011-05-11 13:23:09 +09:00
Mason Mark b84d721887 Fix build-time test for presence of Mac OS X 10.5 SDK
Some jake build tasks test whether the 10.5 SDK is present, and if so, they build using it. However, the path to the SDK is not necessarily consistent across installations, so testing for path existence is not the best way to check whether the SDK is present. Doing it that way caused build failures on machines with both Xcode 3 and Xcode 4 installed. In this fix, we now ask xcodebuild what SDKs are present, and only fall back on the path existence test if the local copy of xcodebuild does not support listing SDKs (as is the case for old versions of xcodebuild).
2011-05-11 13:15:12 +09:00
Randy Luecke 48ccbb8883 Merge pull request #1258 from aparajita/performKeyEquivalent-docs
Correct -performKeyEquivalent docs.
2011-05-10 16:23:38 -07:00
Aparajita Fishman 23a5b83ea6 Corrected and added -performKeyEquivalent docs. 2011-05-10 19:20:37 -04:00
Alexander Ljungberg 5a2e5a7de3 Fixed CPColor isEqual: for pattern images. 2011-05-09 21:38:32 -04:00
Alexander Ljungberg 3db05c94ab Closes #682. Fix CPColor isEqual:. 2011-05-09 20:59:38 -04:00
Alexander Ljungberg 1ba69aee91 Refs #1254. Updated unit test to account for, and verify that CPSet addObject:nil/undefined throws an exception. 2011-05-09 20:03:09 -04:00
Aparajita Fishman ea958160dc Although it is not directly documented, CPMutableSet -addObject should raise with nil or undefined. 2011-05-09 15:49:44 -04:00
Alexander Ljungberg 3d614b38c1 Merge branch '0.9.1' 2011-05-09 14:54:54 -04:00
Alexander Ljungberg d51921d4f3 Closes #664. Fixed: web view sizing bug when loading contents prior to adding the view to the display tree. 2011-05-09 14:54:30 -04:00
Alexander Ljungberg eb8d9775aa [CPView _isVisible] convenience method. 2011-05-09 14:54:24 -04:00
Alexander Ljungberg d5a0469333 Closes #664. Fixed: web view sizing bug when loading contents prior to adding the view to the display tree. 2011-05-09 14:38:17 -04:00
Alexander Ljungberg d5f281320f [CPView _isVisible] convenience method. 2011-05-09 14:37:54 -04:00
Alexander Ljungberg 1e49072763 Merge branch '0.9.1' 2011-05-09 01:37:29 -04:00
Alexander Ljungberg d6c7fecf64 Closes #684. Cleaned up, added attribution and instructions for the CPWebView2 manual test. 2011-05-09 01:36:23 -04:00
Alexander Ljungberg 1392714896 Manual test which tests the effectiveness of both of the previous fixes.
The test also includes a URL based web view to show it works before and after the fixes.
2011-05-09 01:24:33 -04:00
Alexander Ljungberg 2563cb5dc1 Refs #684. Handle content reflows and associated scroll updates when unhiding a CPWebViewScrollAppKit webview. 2011-05-09 01:13:57 -04:00
Alexander Ljungberg c42295f0c7 Refs #684. Fixed: sizing problem when revealing hidden CPWebView. 2011-05-09 00:59:45 -04:00
Alexander Ljungberg cc9bcabf38 Remove apparently unused CPWebView ivar _scrollSize and code.
_scrollSize was never set anywhere in Cappuccino, yet it only had an effect if set.
2011-05-09 00:46:25 -04:00
Alexander Ljungberg 6d98583fa6 Merge branch '0.9.1' 2011-05-09 00:34:22 -04:00
Alexander Ljungberg 6f869cebc1 Closes #688. Unit test verifying that the CPColor hexString weakness described in issue 688 has been resolved. 2011-05-09 00:29:43 -04:00
Francisco Ryan Tolmasky I 5c10615c9f Fix for could not load theme errors in nib2cib. CFBundle was using Image to determine if the platform in question supported image spriting. On Rhino, the Image object doesn't exist, throwing an exception and causing everything to break from that point forward.
Reviewed by me.
2011-05-06 12:40:09 -07:00
Klaas Pieter Annema 1a842b2a6f add manual test case for previous commit 2011-05-05 13:21:50 +02:00
Klaas Pieter Annema 9842640474 add more CPMenuItem keyEquivalent mappings 2011-05-05 13:15:38 +02:00
Ross Boucher 1b1bd4f972 Merge pull request #1249 from aparajita/shared-image-fix.
Ensure multiple _CPImageAndTextViews sharing the same image are notified
2011-05-04 11:10:58 -07:00
Klaas Pieter Annema d8a09722c6 Merge branch '0.9.1' 2011-05-04 19:08:42 +02:00
Klaas Pieter Annema 21a50b990f fix 2 bugs in CPIndexPath
1. we didn't return a copy of the indexes
2. indexPathByRemovingLastIndex didn't remove the last index
2011-05-04 19:07:06 +02:00
Aparajita Fishman 739c844b10 Make sure multiple _CPImageAndTextViews sharing the same image are all notified when it is loaded. 2011-05-04 12:16:43 -04:00
Randall Luecke cd05d30f86 Fix for setting a new platform window on a visisble window throwing a DOM exception. 2011-05-01 21:01:13 -04:00
Antoine Mercadal 3012cc7c92 add setPreventsNib2Cib to bundletask.js
This allows to be able to have the XIB/NIB and CIB version in the resource
directory and to prevent to run nib2cib by just copying the CIB version.
This is very usefull in the caseof using a Linux build machine for your application
2011-04-30 11:40:47 +02:00
Klaas Pieter Annema a9fe07f854 Merge branch '0.9.1' 2011-04-29 12:02:14 +02:00
Klaas Pieter Annema 0f88207d7b fix out of bounds error in itemWithTitle: 2011-04-29 12:01:51 +02:00
Klaas Pieter Annema 81ffed3b9b Merge branch '0.9.1' 2011-04-28 14:01:24 +02:00
Klaas Pieter Annema ead6e4a592 implement CPDictionary's keysSortedByValueUsingSelector 2011-04-28 14:01:04 +02:00
Alexander Ljungberg 288c3e9c70 Merge branch 'master' of github.com:280north/cappuccino 2011-04-27 13:20:51 -04:00
Alexander Ljungberg 5a580f4983 Merge branch '0.9.1' 2011-04-27 13:20:39 -04:00
Alexander Ljungberg 9cf664fe7b Merge branch '0.9.1' of github.com:280north/cappuccino into 0.9.1 2011-04-27 13:16:49 -04:00
Alexander Ljungberg 10ec8b528c Correct return type for [CPURL staticResourceData]. 2011-04-27 13:14:44 -04:00
Antoine Mercadal 3ddf6031fb Support for tooltips on CPControls 2011-04-26 14:46:30 +02:00
Klaas Pieter Annema 0ee304058d consolidate both CPKeyValueObservingTests into one 2011-04-26 11:34:47 +02:00
Klaas Pieter Annema 03e7d81ffa fail more gracefully when attempting to remove the same observer twice
Before this commit we would fail gracefully for single keys. For key paths an application would crash because we would try to get the forwarder property of an undefined object. This commit makes sure we don't attempt any removal and logs a warning (just like Cocoa) about the attempt to remove an unregistered observer.
2011-04-26 11:34:40 +02:00
Klaas Pieter Annema afb2352a7c consolidate both CPKeyValueObservingTests into one 2011-04-26 11:20:47 +02:00
Klaas Pieter Annema cde179786c fail more gracefully when attempting to remove the same observer twice
Before this commit we would fail gracefully for single keys. For key paths an application would crash because we would try to get the forwarder property of an undefined object. This commit makes sure we don't attempt any removal and logs a warning (just like Cocoa) about the attempt to remove an unregistered observer.
2011-04-26 11:19:51 +02:00
Randall Luecke 1b3792a1cc Exclude build directory in xcodecapp. 2011-04-25 17:13:43 -04:00
Randy Luecke 3d8b836184 Merged pull request #1243 from gorenje/more_unit_tests_2.
Fix shadowOffset not being copied when creating a copy of the GState
2011-04-25 10:17:35 -07:00
Randy Luecke 08d33f3c1f Merged pull request #1242 from gorenje/unit_tests_cgcolor.
Some more unit tests for coregraphics - cgcolor and cgcolorspace
2011-04-25 10:16:54 -07:00
Randy Luecke 7d1b873beb Merged pull request #1241 from gorenje/remove_two_color_assumption.
remove an assumption of two colors in the gradient creation stuff
2011-04-25 10:09:33 -07:00
Gerrit Riessen 6c12442870 Fixed copy the shadowOffset, similar to the copying of the affine transform 2011-04-25 14:13:16 +02:00
Gerrit Riessen 6a4d8a24be unit test for CGContext 2011-04-25 14:13:04 +02:00
Gerrit Riessen d147e9cbaa unit test for CGAffineTransform 2011-04-25 14:12:52 +02:00
Randall Luecke 7480f02c22 Merge branch '0.9.1' 2011-04-24 22:29:07 -04:00
Randall Luecke 26afe7c0d8 Fix return type on sortUsingDescriptors in CPMutableArray. 2011-04-24 22:28:41 -04:00
Gerrit Riessen c537541825 added test for color equal to color 2011-04-23 20:56:23 +02:00
Gerrit Riessen e248433ec0 fixed an issue where setting the alpha after creating the color causes all colors referencing that color in the cache to have their alpha value changed 2011-04-23 20:50:42 +02:00
Gerrit Riessen 63e63ce7a1 fix the color creation when using shortcut functions 2011-04-23 17:22:02 +02:00
Gerrit Riessen 6e6011c5ea testing rgb colorspace 2011-04-23 15:50:32 +02:00
Gerrit Riessen 4ce8dcef12 testing cgcolorspace 2011-04-23 15:25:11 +02:00
Gerrit Riessen 7ee414d0b8 remove an assumption of two colors in the gradient creation stuff 2011-04-23 14:10:23 +02:00
Randall Luecke 2c8972514f Merge branch '0.9.1' 2011-04-22 12:59:25 -04:00
Randall Luecke 05b0abacd4 When dragging horizontally we need to update the location of the header view too 2011-04-22 12:59:16 -04:00
Randall Luecke 5315095182 When dragging horizontally we need to update the location of the header view too 2011-04-22 12:53:49 -04:00
Alexander Ljungberg 321c11ec9f Merge branch '0.9.1' 2011-04-21 20:02:22 -04:00
Alexander Ljungberg ca53e56c19 Merge branch '0.9.1' of github.com:280north/cappuccino into 0.9.1 2011-04-21 20:01:53 -04:00
Alexander Ljungberg dcf1d324a5 Additional test for the previous bug. 2011-04-21 19:03:10 -04:00
Alexander Ljungberg 27211db0cc Fixed: JS objects 'randomly' failed to unarchive.
The problem was that if the same JS object was decoded twice as part of a more complex object, the first decoded version was cached in its unwrapped state and not properly unwrapped the second time. This caused very hard to debug theming errors where e.g. a CPTextField's custom inset would decode fine, but a subclass of a CPTextField otherwise exactly the same would fail to decode the inset.
2011-04-21 18:59:30 -04:00
Klaas Pieter Annema 2743fe4c0d Merge branch 'master' of github.com:280north/cappuccino 2011-04-20 21:01:24 +02:00
Klaas Pieter Annema dc5d8f5fd3 never disable menu items with submenus 2011-04-20 21:00:52 +02:00
Randall Luecke be96e3037d Merge branch '0.9.1' 2011-04-20 12:25:41 -04:00
Gerrit RiessenandRandall Luecke b249a1db13 test demostrating limitations of CGGradientCreateWithColorComponents 2011-04-20 12:25:24 -04:00
Randall Luecke f001b7f2d3 Merge branch '0.9.1' 2011-04-20 12:24:32 -04:00
Randall Luecke 561d22168a Stop references function arguments with arguments["name"] in CG. 2011-04-20 12:19:29 -04:00
Klaas Pieter Annema da2c360446 Merge branch '0.9.1' of github.com:280north/cappuccino into 0.9.1 2011-04-20 16:22:28 +02:00
Klaas Pieter Annema 8027ebbe02 Merge branch '0.9.1' 2011-04-20 16:21:59 +02:00
Klaas Pieter Annema 71d8582f94 make unhandled keyboard events travel past the window 2011-04-20 16:21:28 +02:00
Klaas Pieter Annema f8674b6d87 add collectionView:menuForItemAtIndex delegate 2011-04-20 14:40:47 +02:00
Klaas Pieter Annema a086e2fa71 Merge branch '0.9.1' 2011-04-20 11:24:28 +02:00
Klaas Pieter Annema 592328f604 Merge branch 'menu-validation' into 0.9.1 2011-04-20 11:24:17 +02:00
Klaas Pieter Annema 089372be4b Merge branch '0.9.1' 2011-04-20 11:23:58 +02:00
Klaas Pieter Annema ba3a2a9f89 add unit test for CPMenu user interface validation 2011-04-20 11:20:07 +02:00
Klaas Pieter Annema 8e3c26c313 implement CPMenu user interface validation 2011-04-20 10:38:22 +02:00
Klaas Pieter Annema dc264231c8 open menu bar menus directly 2011-04-20 08:58:30 +02:00
Randall Luecke 86e3717222 Fixes for splitview documentation 2011-04-19 01:46:41 -04:00
Alexander Ljungberg c4fb9ccc17 Merge branch '0.9.1' 2011-04-18 20:28:25 -04:00
Alexander Ljungberg 041f2ecf4d Merge branch '0.9.1' of github.com:280north/cappuccino into 0.9.1 2011-04-18 20:16:36 -04:00
Alexander Ljungberg 1db9b6a9d8 Merge branch 'CPTableView-setDropRow_dropOperation-fix' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-CPTableView-setDropRow_dropOperation-fix 2011-04-18 20:13:59 -04:00
Klaas Pieter Annema 3b6bd5a292 take min and max size from item prototype 2011-04-18 10:36:56 +02:00
Francisco Ryan Tolmasky IandKlaas Pieter Annema 51d8fd512a Don't traverse subprojects (folders with Jakefiles).
Reviewed by me.
2011-04-18 10:36:56 +02:00
Francisco Ryan Tolmasky IandKlaas Pieter Annema a578d4881d Don't make IBOutlet a pointer.
Reviewed by me.
2011-04-18 10:36:56 +02:00
Francisco Ryan Tolmasky IandKlaas Pieter Annema 2fb58d3ae1 Always convert to pointers, not just with NS classes.
Reviewed by me.
2011-04-18 10:36:56 +02:00
Francisco Ryan Tolmasky IandKlaas Pieter Annema 35bbb1a3d5 Handle source files being deleted.
Reviewed by me.
2011-04-18 10:36:56 +02:00
Francisco Ryan Tolmasky IandKlaas Pieter Annema d5355df61c Fix superclasses in class generation.
Reviewed by me.
2011-04-18 10:36:56 +02:00
Francisco Ryan Tolmasky IandKlaas Pieter Annema 222223b847 Minor fix.
Reviewed by me.
2011-04-18 10:36:55 +02:00
Francisco Ryan Tolmasky IandKlaas Pieter Annema 9e03df7416 First pass at Xcode 4 support.
Reviewed by me.
2011-04-18 10:36:55 +02:00
Francisco Ryan Tolmasky IandKlaas Pieter Annema 26d124d54b Store type info for ivars when proper flags are set.
Reviewed by me.
2011-04-18 10:36:55 +02:00
Aparajita FishmanandKlaas Pieter Annema 635a0d965c If $CAPP_BUILD is not set or entity is not found in it, look in the narwhal cappuccino package. 2011-04-18 10:36:55 +02:00
Francisco Ryan Tolmasky IandKlaas Pieter Annema c891418849 Change NibApplication template's slider to be continuous since it makes for a better first experience.
Reviewed by me.
2011-04-18 10:36:55 +02:00
Klaas Pieter Annema 39459c9a44 take min and max size from item prototype 2011-04-18 10:34:45 +02:00
Francisco Ryan Tolmasky I 8661625dac Don't traverse subprojects (folders with Jakefiles).
Reviewed by me.
2011-04-15 09:16:25 -07:00
Klaas Pieter Annema 38db22db06 fix a decoding bug with CPBox and it's contentView 2011-04-15 16:01:03 +02:00
Klaas Pieter Annema 722ffeda88 add CPIndexPath to Foundation.j 2011-04-15 16:01:03 +02:00
Klaas Pieter Annema ca74f32e3b fix a decoding bug with CPBox and it's contentView 2011-04-15 16:00:18 +02:00
Klaas Pieter Annema a837b26ac3 add CPIndexPath to Foundation.j 2011-04-15 15:59:59 +02:00
Francisco Ryan Tolmasky I 3b9ed4c1b5 Don't make IBOutlet a pointer.
Reviewed by me.
2011-04-14 14:52:36 -07:00
Francisco Ryan Tolmasky I 77b5f0475d Always convert to pointers, not just with NS classes.
Reviewed by me.
2011-04-14 14:47:14 -07:00
Francisco Ryan Tolmasky I 1c5d311ec2 Handle source files being deleted.
Reviewed by me.
2011-04-14 14:35:29 -07:00
Francisco Ryan Tolmasky I 7d3768e13d Fix superclasses in class generation.
Reviewed by me.
2011-04-14 13:57:24 -07:00
Francisco Ryan Tolmasky I e6acc7a7d8 Minor fix.
Reviewed by me.
2011-04-14 10:27:24 -07:00
Francisco Ryan Tolmasky I 7099acde2f First pass at Xcode 4 support.
Reviewed by me.
2011-04-14 09:49:34 -07:00
Francisco Ryan Tolmasky I 96e3c4db68 Store type info for ivars when proper flags are set.
Reviewed by me.
2011-04-14 09:49:33 -07:00
Alexander Ljungberg 3b35703c2b Merge branch 'master' of github.com:280north/cappuccino 2011-04-14 11:58:05 -04:00
Alexander Ljungberg 1a0b69c10b Merge branch '0.9.1' of github.com:280north/cappuccino into 0.9.1 2011-04-14 11:54:40 -04:00
Alexander Ljungberg 5564b75ed0 Merge branch 'CPArrayController-arrangedObjects-fix-redux' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-CPArrayController-arrangedObjects-fix-redux 2011-04-14 11:52:58 -04:00
Brian Donovan 27cf82e1d3 Use our internal setter while initializing to make sure arrangedObjects is properly observable.
This fixes both the case I reported earlier (#1174) and a new issue I found where attempting to bind to a CPArrayController's arrangedObjects before calling -setContent: would throw this exception:

Uncaught CPInvalidArgumentException: Unsupported method on CPArray

The reason for this exception is that the old implementation set _arrangedObjects to an instance of _CPJavaScriptArray, whereas the new one will set it to a _CPObservableArray.
2011-04-13 21:18:33 -07:00
Aparajita Fishman 025e761929 If $CAPP_BUILD is not set or entity is not found in it, look in the narwhal cappuccino package. 2011-04-13 18:02:08 -04:00
Klaas Pieter Annema 1a99ac7681 Merge branch 'master' of github.com:280north/cappuccino 2011-04-13 17:34:40 +02:00
Francisco Ryan Tolmasky IandKlaas Pieter Annema 1ecbe997df Change NibApplication template's slider to be continuous since it makes for a better first experience.
Reviewed by me.
2011-04-13 17:33:52 +02:00
Klaas Pieter Annema 1d28b120dc fix CPOutlineView providing the dragged items in reverse order 2011-04-13 17:31:29 +02:00
Klaas Pieter Annema 97289d9070 add CPCoding support to CPIndexPath 2011-04-13 17:31:14 +02:00
Klaas Pieter Annema a303b3c04f Merge branch '0.9.1' 2011-04-13 08:27:53 +02:00
Klaas Pieter Annema c317274a26 Merge branch 'purem-master' into 0.9.1 2011-04-13 08:27:45 +02:00
Klaas Pieter Annema 547e57c014 Merge branch 'master' of https://github.com/purem/cappuccino into purem-master 2011-04-13 08:27:23 +02:00
Klaas Pieter Annema 5a1a7f2c86 Merge branch 'purem-master' 2011-04-13 08:24:56 +02:00
Klaas Pieter Annema fb866699e5 Merge branch 'master' of https://github.com/purem/cappuccino into purem-master 2011-04-13 08:24:47 +02:00
Francisco Ryan Tolmasky I cf487ba4de Change NibApplication template's slider to be continuous since it makes for a better first experience.
Reviewed by me.
2011-04-12 09:49:14 -07:00
Brian Donovan f79203f5d5 Fix feedback view when retargeting the drop row & operation.
CPTableView was inappropriately preserving the retargeted drop row & operation as the drag operation continued, causing the data source call to - tableView:validateDrop:proposedRow:proposedDropOperation: to echo any row and operation set by the first call to -setDropRow:dropOperation:, making it impossible for the data source to determine new values for -setDropRow:dropOperation:, making the feedback view stay in the same place it was initially drawn.
2011-04-11 15:00:20 -07:00
purem d7fe42387c Edited bootstrap to find zsh's configuration file ~/.zshrc by default 2011-04-11 11:16:10 -07:00
Alexander Ljungberg ff7f469f9f Fixed: CPColor colorWithCSSString did not properly handle the alpha component of the CSS rbga() syntax. Fixes #687. 2011-04-10 22:16:28 -04:00
Alexander Ljungberg e44ffdc7f4 CPString subtringWithRange: and rangeOfString:options:range now throws CPRangeException for out of bounds ranges. 2011-04-10 21:20:22 -04:00
Alexander Ljungberg 91ef6bf925 Fixed: CPString rangeOfString:options:range returned locations relative to the passed-in range instead of the full string. 2011-04-10 21:05:43 -04:00
Alexander Ljungberg a33dd51d8e Fixed: searching a string for @"" with CPString rangeOfString returned results other than CPNotFound. 2011-04-10 20:38:51 -04:00
Alexander Ljungberg 2166fc1d51 Fixed: CPString rangeOfString: anchored backwards search did not work. 2011-04-10 20:19:04 -04:00
Alexander Ljungberg b29e722132 Fixed: CPString rangeOfString: backwards search did not work. Fixes #1065. 2011-04-10 20:12:33 -04:00
Alexander Ljungberg 06122bba19 Test CPString rangeOfString: in CPCaseInsensitiveSearch | CPBackwardsSearch mode. 2011-04-10 20:10:08 -04:00
Alexander Ljungberg b40f920ec6 Fixed: don't crash on the first mouse move event after merge #1211. Fixes #1221. 2011-04-10 18:33:57 -04:00
Alexander Ljungberg e327c39776 Code formatting. 2011-04-10 17:26:22 -04:00
Alexander Ljungberg c7a1717ebe Added CPDate test which catches mishandling of timezones in initWithString.
(Unfortunately the test is rather crude and only works when your current timezone offset is not 0 (UTC).)
2011-04-10 17:24:18 -04:00
Randall Luecke b9533386b4 Merge branch 'natemartinsf-master' into 0.9.1 2011-04-08 09:32:14 -04:00
Mike FellowsandRandall Luecke 69d27364d5 Trivial fix, add missing spinner.gif from manual scroll view test 2011-04-08 09:30:56 -04:00
Aparajita FishmanandRandall Luecke e3abd4e407 Fixed timezone calculation in initWithString. 2011-04-08 09:29:45 -04:00
Mike FellowsandRandall Luecke 2f501ad736 Add a manual test for drag and drop in a CPTableView 2011-04-08 09:28:30 -04:00
Randall Luecke ae5359f953 Merge branch '0.9.1' of git://github.com/280north/cappuccino into 0.9.1 2011-04-08 09:26:55 -04:00
Mike FellowsandRandall Luecke 4a57f6a1c4 Better inset bounds to improve autoscrolling while dragging in a scrollview. 2011-04-08 09:26:04 -04:00
Nathaniel Martin 9b1eac1923 deltaX and deltaY now set on mousemoved, based on last mouse event 2011-04-07 22:00:09 -07:00
Nathaniel Martin 875dbaa78f Fix for issue 1210 2011-04-06 23:16:13 -07:00
Klaas Pieter Annema 6b64291690 Merge branch 'aparajita-nib2cib-man' 2011-04-06 11:55:17 +02:00
Aparajita Fishman 52ce4c1ebf Properly documented the -F option, some formatting tweaks 2011-04-06 05:15:52 -04:00
Aparajita Fishman a7161e3ca7 Changed comparison in initial check to <=, a cib with an equal mtime could not have been converted from an IB file, it would have a later mtime. 2011-04-06 04:40:05 -04:00
Aparajita Fishman 73746e00b0 Fixes and enhancements...
- If an IB file is deleted, the corresponding cib is no longer deleted.
- In watch mode, the first time through no conversion is done if an IB file has a corresponding cib file with a later mtime.
- In watch mode, an add does not convert if there is a corresponding cib file with a later mtime.
- When catching exceptions, deal correctly with both CPException and strings.
2011-04-06 04:34:56 -04:00
Klaas Pieter Annema 327d796653 implement outlineViewDeleteKeyPressed 2011-04-06 08:14:29 +02:00
Aparajita Fishman af6d38fd16 Fixes and enhancements
- When a xib/nib is deleted, the corresponding cib is deleted.
- Fixed the calculation of the output path when given a relative path.
- Works with .nib files now.
- Works with -R option now. NSCustomResource was assuming an image path would always be relative to cwd().
- The Resources directory is always inferred from the input path, so the -R option is usually unnecessary.
- Added --default-theme option.
- Multiple extra themes can be specified with the --theme option.
- Verbose mode displays the inferred application and resources paths, and the source theme used when doing font substitutions.
- Added a man page.
- Themes are read using StaticResource instead of parsing the file myself.
- Error message tweaks.
2011-04-05 16:57:16 -04:00
Klaas Pieter Annema ab105e7273 Merge branch 'capp-man' of https://github.com/aparajita/cappuccino into aparajita-capp-man 2011-04-05 13:53:02 +02:00
Alexander Ljungberg 6115acea05 Merge branch '0.9.1' 2011-04-04 23:58:13 -04:00
Alexander Ljungberg 0d8bd95c86 Fixed: systems without xcodebuild would fail jake clean and jake clobber. 2011-04-04 23:56:30 -04:00
Klaas Pieter Annema 40bfb55b64 don't resolve nib2cib output path 2011-04-04 14:23:36 +02:00
Alexander Ljungberg f0bba44e45 Completed CPTabView documentation. 2011-04-03 17:56:31 -04:00
Alexander Ljungberg 7107adfe16 Minor doc formatting. 2011-04-03 17:45:53 -04:00
Alexander Ljungberg 501c15775e Use bsdtar explicitly for 'jake docs' in case the user has GNU tar installed through e.g. fink.
This enables the -s parameter to work.
2011-04-03 16:58:39 -04:00
Alexander Ljungberg f29dcc9c6b Document CPScreen. 2011-04-03 16:12:27 -04:00
Alexander Ljungberg 370960418f Better formatting, clickable links and basic code styling for the Doxygen docs front page. This look will resemble that of the GitHub front page.
The README file was converted to Markdown which is nice to read in the terminal and automatically formatted by GitHub. For Doxygen, the markdown is first converted to HTML.
2011-04-03 14:34:20 -04:00
Aparajita Fishman c9fb862ee2 Tweak 2011-04-03 07:56:16 -04:00
Antoine Mercadal 6e1acf1f06 fix wrong AGPL header in CPUserDefaultTest.j 2011-04-03 11:41:56 +02:00
Alexander Ljungberg 2952070698 Whitespace, comment tweak. 2011-04-03 00:56:28 -04:00
Alexander Ljungberg dbb10f69f6 Merge branch 'aparajita-fonts' into 0.9.1 2011-04-02 23:32:59 -04:00
Alexander Ljungberg 9fc10260fb Merge branch 'fonts' of https://github.com/aparajita/cappuccino into aparajita-fonts 2011-04-02 22:26:21 -04:00
Alexander Ljungberg 2fbd54521d Fix up and restore all functionality to ArrayController manual test. 2011-04-02 20:08:36 -04:00
Alexander Ljungberg ae3780c0cf Recreated and cleaned up ArrayController1 since MainMenu.xib was missing. 2011-04-02 19:43:51 -04:00
Alexander Ljungberg ccf9225773 Minor KVO optimisation. 2011-04-02 18:10:13 -04:00
Alexander Ljungberg 8aaa5fe07f Test array controller KVC binding correctness.
This change splits the insertObjectAtArrangedObjectIndex:, addObject:, and removeObject: tests into two versions: one for a regular AC setContent: setup and one for when the AC is bound to an array-like destination implementing KVC.
2011-04-02 18:09:16 -04:00
Alexander Ljungberg fa1a10730e Fixed: an array controller with a bound contentArray would sometimes fail when add:, remove: and similar methods were called.
In particular the AC would fail when a _CPKeyValueCodingArray proxy was required (the destination implements insertObject:in<key>AtIndex etc.). The previous commit by cacaodev is the larger part of this fix as it enables use of mutableArrayValueForKeyPath properly. This commit merely fixes an error exposed by the previous commit where e.g. add: would apparently add two objects rather than one. This was caused by the AC observing and reacting to its own change even that it already had an optimised path to update arrangedObjects.
2011-04-02 18:03:21 -04:00
cacaodevandAlexander Ljungberg e91bc3eeef Adds a binder subclass for CPArrayController's contentArray binding. This binder allows destination.keypath who are kvc compliant, still works if they're not (through _CPKVCArray). Fixes addObject: error when contentArray is bound to a kvc array, a bug visible in ArrayController1 manual test. 2011-04-01 21:29:37 -04:00
Alexander Ljungberg 76400ecca9 Make table column internal bindings support methods private. 2011-03-31 20:48:51 -04:00
Alexander Ljungberg 9a0cf2b37d Manual test for bindings based table view editing. 2011-03-31 20:35:11 -04:00
Alexander Ljungberg dae36cda56 Bindings support for inline table view cell editing. 2011-03-31 20:26:56 -04:00
Aparajita Fishman e07ff706ab Fixed stupid bug in figuring out what directory to watch 2011-03-31 20:10:18 -04:00
Aparajita Fishman 7ec31a7c53 If no directory is passed to --watch, default to Resources 2011-03-31 19:51:22 -04:00
Aparajita Fishman b4221aebcb fontinfo binary is built directly in $CAPP_BUILD, and intermediate build products are put there also. 2011-03-31 16:43:58 -04:00
Aparajita Fishman fdcd56e0ae Added a man page for capp, global function for copying a man page 2011-03-31 14:52:38 -04:00
Alexander Ljungberg 2532c760ea Closes #1202. Test that CPEvent deltaX, deltaY and deltaZ do work. Also initialise deltas to 0 instead of nil. 2011-03-31 11:11:57 -04:00
Aparajita Fishman 0f68fa0141 Added ability to pass a string and get its width, removed some unnecessary releases 2011-03-30 00:28:45 -04:00
Aparajita Fishman 26fba1fdd9 Remove bogus line, not sure how it got there 2011-03-29 17:44:34 -04:00
Aparajita Fishman 16bacae7e3 More cool stuff...
- The holy grail! I took Klaas' great autonib2cib and rolled it into nib2cib.
- Removed check for stream in CPLogColorize, it isn't necessary and reduces its general-purpose usage.
2011-03-29 16:06:19 -04:00
Aparajita Fishman d00a8b9d18 Use a parser action to show version and quit 2011-03-29 12:54:54 -04:00
Alexander Ljungberg 094b798765 Fixed: when table view grid lines were active they did not draw on top of selection highlights like in Cocoa. 2011-03-29 00:45:25 -04:00
Alexander Ljungberg 89974796b1 Fixed: table view's rectOfColumn: method returned a rect reduced by the intercell spacing. It should return the rect of the entire column. Fixed: when a column was selected the column selection colour would not cover the whole column. Fixed: in recent builds, table view header divider lines did not line up with body divider lines.
Ultimately, intercell spacing is only applied, as the name implies, inside of cells. It is not applied in the header, nor at the column or row level. Only data views inside of cells are offset.
2011-03-29 00:33:32 -04:00
Aparajita Fishman 90c19b1856 Added explicit size for completeness of sample, fixed font substitution if theme has no font, used LucidaGrande-Bold 13 to do better code coverage. 2011-03-28 23:55:31 -04:00
Aparajita Fishman 044a605e47 Added font methods so that nib2cib can do font substitution 2011-03-28 23:51:45 -04:00
Aparajita Fishman 7d62b6e1eb Made the defaults global constants 2011-03-28 23:50:56 -04:00
Aparajita Fishman 93f36a2326 Added missing license, added a lot more support for radio button attributes, included fix for issue #1190 2011-03-28 22:44:03 -04:00
Aparajita Fishman 0218246678 Added key equivalents to radio buttons, more attributes to test new radio button support 2011-03-28 22:42:46 -04:00
Aparajita Fishman 79fde3fbeb Factored out font substitution code, added special case for radio buttons 2011-03-28 22:38:26 -04:00
Alexander Ljungberg 539ea2e589 Merge branch '0.9.1' of github.com:280north/cappuccino into 0.9.1 2011-03-28 22:14:32 -04:00
Alexander Ljungberg 4f6d939634 Minor table view cleanup. 2011-03-28 22:14:11 -04:00
Alexander Ljungberg d68d84cfdf Merge branch '0.9.1' of github.com:280north/cappuccino into 0.9.1 2011-03-28 21:24:45 -04:00
Alexander Ljungberg 1ef7fc45f5 Added a note to the CPContinuouslyUpdates test clarifying the purpose of the sliders. 2011-03-28 21:23:53 -04:00
Alexander Ljungberg 430a74735b Fixed: CPSliders always became continuous when archived/unarchived through CPCoding. 2011-03-28 21:18:47 -04:00
Randall Luecke de08addfa1 Fix for grid lines not being drawn in the headers of table columns which were not originally exposed. 2011-03-28 21:10:59 -04:00
Alexander Ljungberg 26003365bc Fixed: CPSlider isContinuous disagreed with setContinuous. 2011-03-28 21:06:07 -04:00
Alexander Ljungberg 11ab9a77ad Minor performance improvement to CPContinuouslyUpdatesValueBindingOption. 2011-03-28 20:12:32 -04:00
Aparajita Fishman 52f3f81265 Changed window title 2011-03-28 18:59:03 -04:00
Aparajita Fishman 2599f820c7 Merge branch 'font-fun' into fonts
Conflicts:
	Tools/nib2cib/NSButton.j
2011-03-28 18:51:10 -04:00
Aparajita Fishman 8fed2c7a9a Factored code into functions, fixed input and output path computation 2011-03-28 18:45:03 -04:00
Alexander Ljungberg f9f03c8b54 Manual test for CPContinuouslyUpdatesValueBindingOption and CPNullPlaceholderBindingOption. 2011-03-28 18:23:17 -04:00
Alexander Ljungberg 110d75b1e5 Text field support for CPContinuouslyUpdatesValueBindingOption. 2011-03-28 18:20:19 -04:00
Alexander Ljungberg 79ec12e2a2 Added support for the CPNullPlaceholderBindingOption for bound text fields. 2011-03-28 18:02:52 -04:00
Aparajita Fishman 5133a7dc91 Fix NSButton so it will merge with master 2011-03-28 16:28:28 -04:00
Klaas Pieter Annema 425401c049 Merge branch 'keyview' of https://github.com/aparajita/cappuccino into aparajita-keyview 2011-03-28 20:12:45 +02:00
Klaas Pieter Annema 38f896d018 fix CPURL equality check 2011-03-28 18:56:25 +02:00
Alexander Ljungberg 7b3ae56031 CPObjectController automaticallyPreparesContent support. 2011-03-28 11:06:12 -04:00
Klaas Pieter Annema 4418b2403f add test case for firstObject 2011-03-28 15:23:03 +02:00
Klaas Pieter Annema 42c60913c6 add firstObject method to CPArray 2011-03-28 13:14:25 +02:00
Alexander Ljungberg 65ce93ce42 Merge branch '0.9.1' of github.com:280north/cappuccino into 0.9.1 2011-03-27 18:18:30 -04:00
Alexander Ljungberg 651882b3c8 Merge branch 'aparajita-keyEquivalent' into 0.9.1 2011-03-27 18:18:07 -04:00
Aparajita Fishman ac7ff24dd7 These got left out in f1f78d6c6a 2011-03-27 15:22:13 -04:00
Aparajita Fishman b54ea6e8ac Ignore Xcode project user data, added fontinfo package 2011-03-25 23:38:49 -04:00
Randall Luecke cf6d7f2d85 Rev version number to 0.9.1 2011-03-25 23:36:07 -04:00
Alexander Ljungberg 65043c5d78 Added some missing LGPL headers. 2011-03-25 22:52:57 -04:00
Aparajita Fishman 30484e04b9 Moved some useful functions to common.jake and made some private functions global so they can be reused by our Jakefiles 2011-03-25 18:51:37 -04:00
Aparajita Fishman 4decc6d9c7 Use a relative path in the symlink 2011-03-25 18:47:41 -04:00
Aparajita Fishman 1a5b8f5210 Fixed install-symlinks to actually work, added sudo-install-symlinks 2011-03-25 18:47:24 -04:00
Aparajita Fishman 93119233cd Prevent self-reference in _next/_previousKeyView 2011-03-25 14:45:19 -04:00
Alexander Ljungberg 2f56f899cf Merge branch 'master' of https://github.com/eventualbuddha/cappuccino into eventualbuddha-master 2011-03-25 12:53:42 -04:00
Brian Donovan b69c25bc2a Fix documentation typo. 2011-03-25 08:50:06 -07:00
Alexander Ljungberg bdcf84ec15 Merge branch '0.9.1' of github.com:280north/cappuccino into 0.9.1 2011-03-25 00:43:36 -04:00
Aparajita FishmanandRandall Luecke f1f78d6c6a Fixed the infamous "wandering checkbox" bug 2011-03-24 23:39:25 -04:00
Randall Luecke 83e4e7ecce Merge branch 'jake-install-symlinks' of https://github.com/aparajita/cappuccino into aparajita-jake-install-symlinks 2011-03-24 23:38:45 -04:00
Alexander Ljungberg e6eb14e819 Fixed: in Firefox, certain web views would not send the first webView:didFinishLoadForFrame: delegate message nor detect the need for AppKit scrollbars. 2011-03-24 23:33:44 -04:00
Alexander Ljungberg 380a860ba9 Fixed: loading an empty string into a web view would make it entirely white regardless of the background colour specified. 2011-03-24 21:20:55 -04:00
Alexander Ljungberg 5cbbafdf72 Support for web views with transparent or coloured backgrounds. 2011-03-24 21:13:41 -04:00
Klaas Pieter Annema 863c4639cf implement outline view menu delegate method 2011-03-24 14:56:23 +01:00
Alexander Ljungberg 79e977b2d9 CPWebView isLoading method. 2011-03-24 01:03:02 -04:00
Alexander Ljungberg 93fe320e22 Minor fixes and cleanup. 2011-03-24 00:56:35 -04:00
Alexander Ljungberg 0337744c05 Web view accessor method to check which scrollbar style is currently in use. Also documented CPWebViewScrollNone. 2011-03-24 00:43:23 -04:00
Alexander Ljungberg 43f4ecc1b4 More consistent CPCompatibility constant naming. 2011-03-23 23:54:56 -04:00
Alexander Ljungberg 310d49c74c Merge branch 'master' of github.com:280north/cappuccino 2011-03-24 00:35:26 -04:00
Alexander Ljungberg 3bd2c2d266 Fixed: web view loadHTMLString:"" now works again. Incidentally it only used to work by accident. 2011-03-24 00:33:54 -04:00
Alexander Ljungberg b9d2927368 Fixed: web views with CPWebViewScrollAuto would reload after determining which scrollbars to use. The new solution makes a best effort attempt to determine this ahead of loading, avoiding reloads.
The problem in particular is that we can't change from AppKit to Native scrollbars or vice versa once an iframe has been loaded. Until we find a way to do so, this less flexible solution will have to do. Note that if the loaded URL passes the SOP, but the content contains links to URLs which do not pass the SOP which can be brought up in the web view, CPWebViewScrollAuto will not work correctly and CPWebViewScrollNative should be used instead.
2011-03-24 00:14:06 -04:00
Randall Luecke 8737b1207f Fix for corner view not drawing the line above the left edge of the scrollview. closes #864 2011-03-23 23:02:10 -04:00
Aparajita FishmanandRandall Luecke 7b6713aa90 Better error checking, error messages, and help. 2011-03-23 21:47:02 -04:00
Aparajita FishmanandRandall Luecke ea25d22628 Cocoa docs state that if unarchiver:didDecodeObject: returns nil, the original object should be used, no replacement should be done. 2011-03-23 21:45:53 -04:00
Randall Luecke d54db1d52b Merge branch 'CPScanner' of https://github.com/cacaodev/cappuccino into cacaodev-CPScanner
Conflicts:
	Foundation/CPScanner.j
2011-03-23 21:43:43 -04:00
Randall Luecke 9746e3d554 More fixes for the splitview. 2011-03-23 13:26:38 -04:00
Aparajita Fishman 6afc5faab0 Moved some useful functions to common.jake and made some private functions global so they can be reused by our Jakefiles 2011-03-23 12:18:11 -04:00
Aparajita Fishman 2899389561 Use a relative path in the symlink 2011-03-23 11:17:01 -04:00
Aparajita Fishman a1e9322d69 Fixed install-symlinks to actually work, added sudo-install-symlinks 2011-03-23 10:54:47 -04:00
Alexander Ljungberg da0558f09c Fixed: avoid momentarily showing native scrollbars while loading URL based content of a CPWebViewScrollAuto CPWebView. 2011-03-22 19:00:54 -04:00
Alexander Ljungberg 8879ef99c6 Fixed: [CPWebView reload] did nothing if the content was an HTML string. 2011-03-22 18:37:45 -04:00
Alexander Ljungberg 09d515e6cc Reload buttons for CPWebViewTest. 2011-03-22 18:37:34 -04:00
Randall Luecke 014354432a Merge branch 'master' of git://github.com/280north/cappuccino 2011-03-22 13:44:48 -04:00
Randall Luecke d9b327db83 Fix for splitview not repositioning subviews or removing divider when a subview is removed. 2011-03-22 13:43:42 -04:00
Gerrit RiessenandFrancisco Ryan Tolmasky I da0b0d6c84 Fix for root layer transform inadvertantly changing when redisplayed.
Reviewed by tolmasky.
2011-03-22 12:34:23 -03:00
Randall Luecke 3f271463e5 Better CPWindowController docs. 2011-03-22 02:29:45 -04:00
Randall Luecke 459240bb88 Fix for scroller error when horizontal scroller is too small. 2011-03-19 22:51:45 -04:00
Randall Luecke e8210f7dde Proper fix for mem leakage. 2011-03-17 03:03:51 -04:00
Randall Luecke 32fc629c33 Prevent memory leak my only adding the observer when the searchfield is added to a superview, that way we can also remove the observer later. 2011-03-17 01:31:25 -04:00
cacaodevandRandall Luecke d5b2ccbc30 CPSearchField: register for textDidChange notifications instead of hijacking the delegate. Post the notification in -canCelOperation: (triggered by escape key OR cancel button). Fixes issue #1160 2011-03-17 01:18:25 -04:00
Aparajita FishmanandRandall Luecke a3e70a56c5 Added support for sendsActionOnEndEditing flag in nibs 2011-03-17 01:16:43 -04:00
Brian Donovan abce41d6fd Make sure -[CPArrayController arrangedObjects] always has a non-nil value. 2011-03-15 19:53:14 -07:00
Randall Luecke e1d45fd385 Merge branch 'master' of git://github.com/280north/cappuccino 2011-03-15 18:03:24 -04:00
Randall Luecke a3e6105a11 Fix for errors with variable row height edge cases. 2011-03-15 18:02:26 -04:00
Klaas Pieter Annema f022386502 Merge branch 'doc-optimize' of https://github.com/aparajita/cappuccino into aparajita-doc-optimize 2011-03-15 10:18:06 +01:00
Aparajita Fishman e18b21ec1b Fixed output path check 2011-03-13 10:15:26 -04:00
Aparajita Fishman 42c71172f2 Better path checking and error messages, fixed issue #1154 2011-03-13 10:08:17 -04:00
Aparajita Fishman dc801a11c8 Instead of blindly, recursively copying the AppKit and Foundation directories, more intelligently copy only the *.j files we want. 2011-03-12 23:34:53 -05:00
Randall Luecke 24fbf27880 Headerview and corner view fixes 2011-03-12 01:24:15 -05:00
Aparajita Fishman b0af42e236 Removed extra blank line 2011-03-11 12:39:54 -05:00
Aparajita Fishman 32fd03b4a0 Explicitly test for null cibFont for clarity 2011-03-11 12:15:58 -05:00
Aparajita Fishman 6b72651a05 Error message tweaks 2011-03-11 12:00:58 -05:00
Aparajita Fishman d6117b832f Comment tweaks 2011-03-11 09:46:42 -05:00
Aparajita Fishman 3a79e82ce8 Removed check for fontinfo, it will be part of the cappuccino package 2011-03-11 09:04:11 -05:00
Aparajita Fishman 522d4dcb2b Removed layout constants 2011-03-11 08:39:41 -05:00
Aparajita Fishman 11f92353c8 Removed layoutMode references 2011-03-11 08:37:23 -05:00
Aparajita Fishman 3b60714bf0 Documented how to configure the system font face. 2011-03-10 19:54:38 -05:00
Aparajita Fishman 239b6ed79d Fixed CPFontTest, removed unused RegExp from CPFont 2011-03-10 19:19:32 -05:00
Aparajita Fishman a20b0a7dca Removed google fonts, added test of dynamically set font with fallback 2011-03-10 18:53:57 -05:00
Randall Luecke e9dba10903 Move coder unarchiving logic to nib2cib. 2011-03-10 18:37:44 -05:00
Aparajita Fishman fd43a08fa3 Merge remote branch 'refs/remotes/280north/master' into font-fun 2011-03-10 18:18:18 -05:00
Aparajita Fishman 627566465e Moved legacy font substitution to nib2cib to avoid any side effects, linted NSTableColumn, NSTableColumn now uses cibFontForNibFont, finished test app 2011-03-10 18:13:35 -05:00
Randall Luecke b087757a72 Pump runloop for async callbacks. 2011-03-10 17:39:39 -05:00
Randall Luecke d926ad6221 Merge branch 'fix-cpsound-firefox' of https://github.com/primalmotion/cappuccino into primalmotion-fix-cpsound-firefox 2011-03-10 17:11:19 -05:00
Aparajita FishmanandRandall Luecke 90e6c21c95 Be sure the build directory exists in case 'jake docs' is done before any other jake commands 2011-03-10 17:05:40 -05:00
Randall Luecke ad4d408f3e Merge branch 'pattern-fill' of https://github.com/aparajita/cappuccino into aparajita-pattern-fill 2011-03-10 17:04:26 -05:00
Aparajita FishmanandRandall Luecke 9a2d079bee lint the template files, update setFullBridge (deprecated) to setFullPlatformWindow 2011-03-10 17:03:38 -05:00
Aparajita FishmanandRandall Luecke f254122346 Added CPView -hasThemeAttribute and tests 2011-03-10 17:02:30 -05:00
Aparajita Fishman 10bfeaf8f7 Added comment for non-obvious code, fixed option name in nib2cib 2011-03-10 12:49:50 -05:00
Aparajita Fishman f93aa2c5bc Merge branch 'master' of https://github.com/280north/cappuccino into font-fun 2011-03-10 12:38:37 -05:00
Francisco Ryan Tolmasky I acf7ef3a96 Use 10.5 SDK for building NativeHost if available, otherwise use latest Mac OS X SDK.
Reviewed by me.
2011-03-10 12:33:35 -04:00
Aparajita Fishman a8d07961c0 -familyName should always return whatever family names the font was initialized with, in case there are fallbacks for different platforms 2011-03-10 11:28:48 -05:00
Aparajita Fishman 95cc88733c Fixed default system font substitution 2011-03-09 16:37:23 -05:00
Aparajita Fishman 120c06fcb2 Further CPFont work, don't print nib2cib version all the time. 2011-03-09 14:33:11 -05:00
Aparajita Fishman d303e6e96c Initial commit before testing. 2011-03-08 17:40:41 -05:00
Aparajita Fishman c4dce38484 Added support for pattern fills in CGContext, fixed bug in COORD macro in CGContextVML.j, test app 2011-03-08 03:11:08 -05:00
Ross Boucher 8eb8b7711d Binding to wrong event in IE. 2011-03-07 15:08:57 -08:00
Alexander Ljungberg f7fc669216 Fix missing 'self' in previous commit. 2011-03-06 11:51:20 -03:00
Alexander Ljungberg 7d6b7fd676 CPCoding fix, remove a log statement. 2011-03-05 22:56:49 -03:00
Alexander Ljungberg 2387cee799 Fixed: web view AppKit scrollbars often did not reflect the true content size of the view.
The reason for this is that the size changes as the page progressively loads, and this continues after the 'load' event fired. For now, we use a simple timer to poll the size a few times after loading. These polls are very bad for performance and battery life so we terminate them quickly, meaning that the underlying problem where the contents of the web view can get out of sync with its scrollbars fundamentally remains - this fix merely alleviates the problem.
2011-03-05 22:50:20 -03:00
Alexander Ljungberg e214d49ea9 Change SOP error to a warning. Warn about problematic testing setup in CPWebViewTest. 2011-03-05 19:52:39 -03:00
Alexander Ljungberg 6f8d2190f5 Closes #1136. Fixed: for the most part, web view's setScrollMode: message did nothing. New: automatic or explicit scroll mode selection in web views.
By default the automatic mode will try to use Cappuccino scrollbars whenever possible, and otherwise fall back on Native scrollbars. Explicit settings are also allowed. The explicit AppKit setting will degrade to Native with a warning if impossible due to implement due to SOP.
2011-03-05 19:45:39 -03:00
Alexander Ljungberg 9ca1865179 Test the various web view scroll modes about to be implemented. 2011-03-05 18:00:17 -03:00
Randall Luecke a7c5ca740a Typo in doc changes 2011-03-05 00:20:28 -05:00
Randall Luecke 590b3705eb Style changes for table column documentation. 2011-03-04 23:15:24 -05:00
Klaas Pieter Annema a9f23fe082 open submenus after a short delay 2011-03-04 10:21:26 +01:00
Klaas Pieter Annema 3c77d43e03 implement mousewheel support for CPMenu 2011-03-04 10:21:26 +01:00
Klaas Pieter Annema 7fb78fe157 lint _CPMenuWindow 2011-03-04 10:21:26 +01:00
Klaas Pieter Annema 566fdf6400 lint _CPMenuManager.j 2011-03-04 10:21:25 +01:00
Klaas Pieter Annema 1dc53ed149 lint CPPlatformWindow+DOM.j 2011-03-04 10:20:55 +01:00
Klaas Pieter Annema b57b705b1d place the scroll element above menus 2011-03-04 10:20:54 +01:00
Blair DuncanandKlaas Pieter Annema 7d7c037682 add support for Home and End key and modified logic for pageUp and pageDown 2011-03-04 10:20:54 +01:00
Blair DuncanandKlaas Pieter Annema bf72a7f92d added support for escape key to cancel menus, removed unused var 2011-03-04 10:20:54 +01:00
Blair DuncanandKlaas Pieter Annema df9387fc78 remove unneccessary scrolling calls and periodic events when not needed 2011-03-04 10:20:54 +01:00
Blair DuncanandKlaas Pieter Annema 9296df89df fixed some spacing and added a delay in the reset time for longer lists 2011-03-04 10:19:35 +01:00
Blair DuncanandKlaas Pieter Annema d4d65ed4d7 Add support for keyboard navigation in menus 2011-03-04 10:19:35 +01:00
Klaas Pieter Annema 163550c3d5 determine NSControl enabled state from NSCellFlags 2011-03-04 08:56:25 +01:00
Klaas Pieter Annema a11f12ab09 fix unarchiving tableviews with no header view 2011-03-04 08:51:21 +01:00
Klaas Pieter Annema 8e14d6cebc unarchive corner and headerviews correctly 2011-03-04 08:15:54 +01:00
Randall Luecke 90d50bb593 Sizing fixes for the textfields of the color panel. 2011-03-02 22:51:03 -05:00
cacaodevandRoss Boucher b715fb6182 Enable representedObject decoding in NSMenuItem.j 2011-03-02 13:32:56 -08:00
Ross Boucher 31dbd208f4 We don't need to copy the string since strings are immutable in javascript. 2011-03-02 13:26:49 -08:00
Tobias M. BölzandRoss Boucher 49707af1ba Fixed binding name constants 2011-03-02 13:17:44 -08:00
Ross Boucher b77668dd5a Fix spacing in CPBrowser. 2011-03-02 12:36:44 -08:00
Alexander Ljungberg 50e5fa2c8e Fix accidental globals. 2011-03-01 00:02:35 -03:00
Alexander Ljungberg dedf3cd90f More AppKit coding standards. 2011-02-28 23:55:29 -03:00
Alexander Ljungberg 651d6a7ed8 Linting AppKit. 2011-02-28 23:48:34 -03:00
meelash 383dcd5ee6 Corrected mistake in CPSplitView delegate documentation 2011-02-28 20:19:00 -05:00
Francisco Ryan Tolmasky I 1589d501cc Slight typo.
Reviewed by me.
2011-02-27 10:01:16 -08:00
Randall Luecke 060563b748 Documentation style fixes for CPOutlineView. Now setDelegate: actually shows up. 2011-02-26 15:13:34 -05:00
Randall Luecke b8b74f1e35 Revert "Crazy cool selection behavior."
This reverts commit 2b498feb67.
2011-02-26 14:58:47 -05:00
Ross Boucher 6435372fd9 We weren't actually keeping track of replaced methods, and thus were replacing every time you call addObserver: 2011-02-25 17:59:54 -08:00
Klaas Pieter Annema 3ebb432d3f Merge branch 'traceback' of https://github.com/jukart/cappuccino 2011-02-25 23:57:29 +01:00
Klaas Pieter Annema f13362b224 fix sortDescriptorsDidChange: not called for outline view 2011-02-25 23:52:41 +01:00
Derek HammerandKlaas Pieter Annema 2b498feb67 Crazy cool selection behavior. 2011-02-25 23:52:41 +01:00
Randall Luecke 5c6fce4e8c Following the fix for the pane spiltter flag change in the CPSplitView, the theme file also needed to be updated. 2011-02-24 01:48:36 -05:00
Randall Luecke d000e67fc4 Merge branch 'master' of https://github.com/dbrajkovic/cappuccino into dbrajkovic-master 2011-02-24 01:28:14 -05:00
Randall Luecke c9bc6c3991 Fix for Xcode 4.0 pre-release causing cappuccino not to build because of NativeHost. This is just a work around for the time being so that Cappuccino still finishes building. 2011-02-24 01:25:11 -05:00
Randall Luecke 8c1a3a3bba Refactored the tableview docs a little. Now using real doxygen commands instead of using <pre> on everything. 2011-02-23 02:46:30 -05:00
Randall Luecke f723318601 Column resize fixes 2011-02-22 22:07:31 -05:00
Randall Luecke ebcbfc76b8 Merge branch 'fix-searchfield-glitch' of https://github.com/primalmotion/cappuccino into primalmotion-fix-searchfield-glitch 2011-02-22 21:11:53 -05:00
Randall Luecke eaa4efc805 Imageview support for tableview nib2cib 2011-02-22 21:08:30 -05:00
Randall Luecke e717fd82b9 Merge branch 'Selection' of https://github.com/hammerdr/cappuccino into tableview-selection
Conflicts:
	AppKit/CPTableView.j
2011-02-22 20:05:00 -05:00
Randall Luecke 46781cb6fd Merge branch 'mb-cpcursor-refactor' of https://github.com/saikat/cappuccino into saikat-mb-cpcursor-refactor 2011-02-22 19:58:31 -05:00
Randall Luecke 02eaded719 Merge branch 'UniformColumnSizing' of https://github.com/hammerdr/cappuccino into hammerdr-UniformColumnSizing 2011-02-22 19:54:14 -05:00
Randall Luecke 0748190ab7 Merge branch 'bootstrap-fixes' of https://github.com/paulbaumgart/cappuccino into paulbaumgart-bootstrap-fixes 2011-02-22 19:53:08 -05:00
Randall Luecke cccbb8eee4 Merge branch 'master' of https://github.com/purem/cappuccino into purem-master 2011-02-22 19:51:51 -05:00
Randall Luecke 902878756e Merge branch 'fix-progressindicator-not-cpcoding-compliant' of https://github.com/primalmotion/cappuccino into primalmotion-fix-progressindicator-not-cpcoding-compliant 2011-02-22 19:51:07 -05:00
Randall Luecke 033663f2cf fix for a couple methods not being generated for the docs. 2011-02-22 19:48:53 -05:00
Ross Boucher e4093ac3ae Merge branch '0.9' 2011-02-22 14:13:12 -08:00
Ross Boucher 16a70c5c8e Update to the starter package readme. 2011-02-22 14:09:09 -08:00
Jürgen Kartnaller b7f871e31b Merge branch 'master' into traceback 2011-02-21 14:38:49 +01:00
Klaas Pieter Annema cc5e8c3f34 fix textfield cut and paste notifications
Closes #555 #1001
2011-02-21 10:26:58 +01:00
Klaas Pieter Annema 85e80a62a3 remove old '_currentValueIsPlaceholder' code 2011-02-21 10:26:58 +01:00
Antoine Mercadal 60d1073d9a do not encode _barView 2011-02-16 17:39:06 +01:00
Antoine Mercadal b620de45a2 make CPProgressIndicator CPCodingCompliant 2011-02-16 17:34:26 +01:00
purem 536d012105 Fixed typo 2011-02-13 15:01:59 -08:00
Jürgen Kartnaller 2e24761a54 Merge branch 'master' into traceback 2011-02-09 10:30:12 +01:00
Daniel Brajkovic 956b640339 Fixes #1122. Nib2Cib was checking if NSSplitViewDividerStyle ==2 should be == 3 as NSSplitViewDividerStylePaneSplitter = 3.
In CPSplitView.j the divider thicknesses in the themeAttributes were swapped. Also swapped the statements in _setupDOMDivider if(_isPaneSplitter) statement.
2011-02-07 23:59:43 -06:00
Paul Baumgart bee1db8c7d Optionally add CAPP_BUILD to the shell config automatically. 2011-02-05 17:32:02 -08:00
Paul Baumgart 51deaf4552 Enquote more command output in bootstrap to prevent spaces in paths from breaking things. 2011-02-05 17:31:04 -08:00
Paul Baumgart 57e1431e1a Remove duplicate prompts from bootstrap. 2011-02-05 17:30:03 -08:00
Saikat Chakrabarti 975e11abfc CPCursor refactor according to discussion in http://groups.google.com/group/objectivej-dev/browse_thread/thread/eabe59dc7d71122b/ddc6f1b61e5f3c2a?lnk=gst&q=cpcursor#ddc6f1b61e5f3c2a and new test for CPCursor that is easier to go through. 2011-02-04 17:41:40 -08:00
Randall Luecke b78eddd878 Clearer explaination of setPullsDown: of CPPopupButton 2011-02-04 19:01:12 -05:00
Jürgen Kartnaller 09ebc0effd Merge branch 'master' into traceback 2011-02-03 09:04:48 +01:00
Jürgen Kartnaller 6a4e0bd43a log a traceback only once 2011-02-02 22:43:20 +01:00
Antoine Mercadal 8994f08cbf move the fix to themedRoundedTextField: 2011-02-02 18:27:31 +01:00
Antoine Mercadal 55b97a7eeb fix CPSearchField layout glitch 2011-02-02 12:02:46 +01:00
Randall Luecke 203942d123 Documentation of CPApplication. 2011-01-30 16:56:56 -05:00
Derek Hammer 436f6cb8ea Fixing uniform column resize spacing issue. 2011-01-30 13:01:44 -06:00
Derek Hammer 9c4fb2c18c Updating selection code based on feedback from Randy 2011-01-29 18:01:57 -06:00
Derek Hammer d27544f2bf Crazy cool selection behavior. 2011-01-28 12:59:01 -06:00
Klaas Pieter Annema 5957e71967 enable nib2cib image support for CPMenuItem 2011-01-28 14:50:42 +01:00
Derek Hammer 85f51d7a66 Extend selection in a meaningful way when using keys. 2011-01-27 21:50:36 -08: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
Antoine Mercadal 3a6f2c4d5b make CPSound handling error + More Cocoa compliant 2011-01-26 11:06:10 +01: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
Antoine Mercadal f39441e101 avoid error in FF 2011-01-25 21:24:36 +01: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
Mike Fellows a801860f90 Move the functionality from CPStepper's _CPContinuousButton object into CPButton so any CPButton can be made continuous 2011-01-19 12:02:43 -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
Jeremy Lujan 41d757e0c4 *Fix issue in setParameters due to expression in while condition in CPFlashView
*Protect against overwriting flashvars in _params when setParams is called after setFlashVars in CPFlashView
2010-12-14 21:38:52 -06: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
cacaodev 602a2c47c2 CPScanner fixes with tests. 2010-11-13 02:29:04 +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
Francisco Ryan Tolmasky I 2e9684e9a7 Fix for bottom corner view of CPScrollView being broken in CPCoding circumstances (normal coding, nib2cibing, Atlas, etc.).
Reviewed by me.
2010-11-03 10:37:51 -07:00
Klaas Pieter Annema a80a0d0a13 Complete the style fix started in previous commit 2010-11-03 14:13:55 +01:00
Francisco Ryan Tolmasky I 885eff1f9b Style fix.
Reviewed by me.
2010-11-03 01:34:54 -07:00
Francisco Ryan Tolmasky I 706e80362d Slight change to last commit, change == to ===.
Reviewed by me.
2010-11-03 01:25:08 -07:00
Brian DonovanandFrancisco Ryan Tolmasky I 7bf2297125 -[CPArrayController setContent:] would interpret nil as [nil].
When initializing a CPArrayController with a value that is not an array setContent: would make it an array by replacing value with [value]. This is consistent with how Cocoa does it, but it should first check to make sure that the content is not nil. If it is, the sensible thing to do (and what Cocoa does) is to replace it with an empty array.

This commit also includes a missing import to make CPArrayControllerTest run without error.
2010-11-03 01:24:38 -07:00
Francisco Ryan Tolmasky I 99c1d18d95 Fix for targets and actions not working in nib2cibed toolbars.
Reviewed by me.
2010-11-03 00:36:30 -07:00
Ross Boucher a45668e7cb Updates to make nib2cib work better with CPToolbar (and with image resources in IB in general). 2010-11-02 20:31:43 -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
Francisco Ryan Tolmasky I f46bbf83a8 Slight fix for correctness with --include.
Reviewed by me.
2010-11-01 11:26:59 -07:00
Francisco Ryan Tolmasky I 52f7844aee Made it so .h files are automatically included in AppKit (avoiding needing to manually include Platform.h, etc.).
Also changed a bunch of <AppKit/*> imports to "*" imports.

Reviewed by me.
2010-11-01 11:10:01 -07:00
Klaas Pieter Annema 64aeea0f08 Merge branch 'runtime-theming' 2010-11-01 14:04:22 +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
Alexander Ljungberg 06db60d7df Merge branch 'fix-cptabview-not-resizable' of http://github.com/primalmotion/cappuccino into primalmotion-fix-cptabview-not-resizable 2010-10-29 16:13:47 -03:00
Alexander Ljungberg eb39e2e81a Optimise token field redraws when adding or deleting tokens by recycling token fields. This eliminates the flicker of all previous tokens whenever a new token was added. 2010-10-29 14:40:46 -03:00
Alexander Ljungberg 0867ccdc73 Reduced token height by 1 pixel to put some more whitespace underneath it in a standard height token field. 2010-10-29 14:23:36 -03: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
Antoine Mercadal 8ead5f63da fix CPtabViewTest 2010-10-28 11:01:38 +02:00
Daniel Stolzenberg 24fbecb2e6 Merge branch 'master' of git://github.com/280north/cappuccino 2010-10-28 09:20:52 +02:00
Alexander Ljungberg a80732f13a Whitespace and style cleanup. 2010-10-27 20:44:55 -03:00
Alexander Ljungberg 923d7c63b5 Fixed an accidental global. 2010-10-27 20:24:05 -03:00
Alexander Ljungberg 7626af00e7 Apply Cappuccino code style. 2010-10-27 20:16:14 -03:00
Alexander Ljungberg 1d647fab10 Merge branch 'CPPredicate-parsing' of http://github.com/cacaodev/cappuccino into cacaodev-CPPredicate-parsing 2010-10-27 19:34:44 -03:00
Alexander Ljungberg c9fcbe0e93 Merge branch 'eventualbuddha-sprintf-format-parameter-indexes' 2010-10-27 19:26:51 -03:00
Alexander Ljungberg 6d9d443d0a Merge branch 'sprintf-format-parameter-indexes' of http://github.com/eventualbuddha/cappuccino into eventualbuddha-sprintf-format-parameter-indexes 2010-10-27 19:16:50 -03: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
cacaodev 2a95523577 CPPredicate & CPExpression changes:
Parsing: fixed typos in built-in function names, fixed support for [FIRST], [LAST], [INDEX]
	Fixed aggregates {exp1,exp2}
Fixed -expressionForFunction:selectorName:arguments:
built-in functions are now class methods
Cleaned a lot of code in built-in functions
EvaluatedObjectExpression is now a singleton
Merged inserset/minus/union Set into one file
Deleted unused expression subclasses : expression_operator and expression_assignement
Added CPCoding methods and changed key names to match Cocoa
Made KeyPathExpresion a subclass of FunctionExpression like in Cocoa
Tests
2010-10-27 00:57:31 +02:00
Klaas Pieter Annema 0fa149b74f encode and decode themeClass
This makes it possible to theme any themeClass without having to subclass a CPView and return something different from defaultThemeClass. Theme a custom theme class by assigning to a control within the theme descriptor ([control setThemeClass:"your-theme-class"]).
2010-10-26 20:41:56 +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
Klaas Pieter Annema c7fdad883a add deprecation warning for class that have themeClass implemented 2010-10-25 16:14:33 +02:00
Klaas Pieter Annema 6e9f82212b rename CPView +themeClass to +defaultThemeClass 2010-10-25 14:15:22 +02:00
Klaas Pieter Annema 22e2bdcd25 make theme class runtime configurable 2010-10-25 13:54:39 +02:00
Klaas Pieter Annema 85c9ca518f lint cleanup in CPView 2010-10-25 13:54:19 +02:00
Alexander Ljungberg 29a93b20f4 Merge branch 'flllow-tokenfield-improvements' 2010-10-23 20:53:34 -03:00
Alexander Ljungberg b95bdca2a3 Lint cleanup. 2010-10-23 20:47:11 -03:00
Alexander Ljungberg 6fd5f66a15 Support forward delete in token fields. 2010-10-23 20:42:01 -03:00
Alexander Ljungberg 9e235f7236 Fixed: clicking tokens in a token field could disable its keyboard handling due to the input field losing focus. 2010-10-23 20:21:02 -03:00
Alexander Ljungberg 90d12ef77e Place the cursor correctly when arrow keys are used with one or more tokens selected. Fixed: the layout would not update to remove the gap for the editor if between tokens when resigning first responders. 2010-10-23 19:31:08 -03:00
Alexander Ljungberg 0c2301766a Place the cursor after the last inserted token when editing. 2010-10-23 17:09:46 -03:00
Alexander Ljungberg 8a7b6054ef If the text editing part of the token field is the last in the line, make it take up the remaining field width so that it captures clicks there. 2010-10-23 16:58:02 -03:00
Alexander Ljungberg 7037151bfc Fixed: clicking a token would cause the token field to resign first responder status, only to reclaim it on mouse up.
This was caused by the framework's stop DOM event code blurring the field. Now simply refuse to resign first responder status between mouse down and mouse up. Note that this fixes the bug the previous commit did too, but that commit improves other scrolling behaviour so it gets to stay.
2010-10-23 16:00:45 -03:00
Alexander Ljungberg ba26b19567 Fixed: if the token field was scrolled up and a token was clicked, the scroll position would jump back down. 2010-10-23 15:41:41 -03:00
Alexander Ljungberg 6587014014 Improve token field scrolling behaviour and performance: only resize the document view frame when necessary to prevent the loss of scroll position and display jumps. Fixed: if a token on a new line was clicked, the view would scroll up to the first line. 2010-10-23 14:36:42 -03:00
Alexander Ljungberg 80b16ae9ab Bluer selected tokens in token field. 2010-10-23 14:07:46 -03:00
Alexander Ljungberg 07330a0ca8 Select tokens by clicking on them. Select multiple tokens by holding down shift. Also fixed a bug when deleting multiple tokens at a time. 2010-10-23 13:49:36 -03:00
cacaodev 3cfbca5a19 CPScanner: When the scanner did not accumulate any string, do not change (to nil) the object passed as a ref in ...intoSring:ref() methods. With tests. 2010-10-23 10:25:42 +02:00
cacaodev c735399ca5 CPPredicate: Fix for fail when parsing empty quotes. With Tests. 2010-10-23 09:26:12 +02:00
Alexander Ljungberg d68f4359ac Reduce token shifting when a token is selected. Ideally there shouldn't be any shifting at all, but placing a tiny editor at the right spot simplifies scroll handling. 2010-10-23 00:22:40 -03:00
Alexander Ljungberg d4cfa4b24f Minor optimisations and cleanup. 2010-10-23 00:00:00 -03:00
Alexander Ljungberg 2912acb4f5 Simplify: remove _selectedTokenIndexes since we now have _selectedRange. Hide the editor when tokens are selected. Preserve cursor position when tokens are deleted. 2010-10-22 23:45:48 -03:00
Alexander Ljungberg 85683d8f18 Navigate among tokens with the arrow keys. Insert and delete tokens relative to the cursor. 2010-10-22 20:43:40 -03:00
Brian Donovan 8ca2a1bf5b IE uses an empty string as the value of an empty capture group. 2010-10-22 14:41:31 -07:00
Brian Donovan 8427697a4b Fix accidental globals. 2010-10-22 14:15:22 -07:00
cacaodev 275f89a340 CPPredicate: parsing 'BETWEEN' or 'CONTAINS' keywords now generates predicates with their corresponding operators. Some code style.
CPComparisonPredicate: fixed typo in 'between' operator evaluation, simplified 'contains' and 'in'  evaluation.
Added tests in CPPredicateTest for theses fixes.
2010-10-22 22:13:57 +02:00
Klaas Pieter Annema 49c8a02b5f cleanup in CPSplitView and the Aristo ThemeDescriptors 2010-10-22 13:55:37 +02:00
Klaas Pieter Annema 1165e569d2 make splitview pane divider color theme-able 2010-10-22 13:54:39 +02:00
Alexander Ljungberg e66f22d094 Allow the editor to be placed anywhere based on a selection range. 2010-10-21 23:46:03 -03:00
Alexander Ljungberg d0b29fd38c Fix resizing and initial sizing of token fields. 2010-10-21 17:49:41 -03:00
Alexander Ljungberg 28378ff19b Minor performance tweaks. 2010-10-21 17:11:47 -03:00
Alexander Ljungberg b4f2f15698 Fixed: if a token field had many tokens and a long token name was entered, that token name had to be edited in the small amount of space left on the right hand side of the token field. Now the editor wraps to a new line as needed. 2010-10-21 17:04:09 -03:00
Alexander Ljungberg 2210c1f4c5 Implemented token field overflow support as in Cocoa: if more tokens than can fit are entered, they wrap to a new line. If the new line does not fit within the height of the token field, the previous line is scrolled out of view.
Note: this replaces the previous non Cocoa behaviour where the token field would grow height-wise with new tokens. This behaviour can still be useful, as seen in Apple Mail, but it will now require the user to subclass CPTokenField, override layoutSubview and set the frame size to the size of the scroll view's document view.
2010-10-21 15:56:17 -03:00
Brian Donovan 7be6352531 Add format parameter index support to sprintf.
This is primarily useful in cases when the format string can vary, but the argument order will not, as is often the case with format strings in Localized.strings files.

From http://perldoc.perl.org/functions/sprintf.html:

An explicit format parameter index, such as 2$. By default sprintf will format the next unused argument in the list, but this allows you to take the arguments out of order.

See also this Cocoa example: http://stackoverflow.com/questions/1063843/is-there-a-way-to-specify-argument-position-index-in-nsstring-stringwithformat
2010-10-21 09:54:51 -07:00
Randall Luecke f2391cb150 Merge branch 'master' of git://github.com/280north/cappuccino 2010-10-21 12:02:06 -04:00
Randall Luecke 09c02c5884 Typeo in group items in outlineview. 2010-10-21 12:01:34 -04:00
Klaas Pieter Annema 71d02abc28 add global to disable string size caching 2010-10-21 17:36:09 +02:00
Alexander LjungbergandKlaas Pieter Annema 367efe590e Fixed with the new string size optimisation: the cache value was returned by reference and something in the CPButton path for image and text buttons changed it causing text to become misaligned. A defensive copy avoids this problem. 2010-10-21 17:36:09 +02:00
Klaas Pieter Annema afcce49455 improve CPString sizeOfString performance by caching the calculated result 2010-10-21 17:36:09 +02:00
Alexander Ljungberg d63e4f8021 Remove some placeholder comments for methods which now exist. 2010-10-21 00:47:58 -03:00
Blair DuncanandRoss Boucher c9a4821d15 Fix for issue 951 - CPResponder flagsChanged does not fire when the key is up 2010-10-20 18:54:50 -07:00
Blair DuncanandRoss Boucher 696990f035 Fix for previous fix and modified the test file. 2010-10-20 18:48:29 -07:00
Blair DuncanandRoss Boucher ad0867ba7d Fix for issue 948 Custom Cursors not working 2010-10-20 18:48:24 -07:00
Antoine Mercadal 48ebd2e954 add tests for CPTabView 2010-10-20 00:05:03 +02:00
Antoine Mercadal 3d82203893 remove 'drunk' code and simply use resizing masks 2010-10-19 22:53:52 +02:00
Klaas Pieter Annema a3766a0f96 whitespace cleanup in NSTextField and NSSearchField 2010-10-19 15:12:53 +02:00
Klaas Pieter Annema 2eb27a6492 Don't adjust the origin and size of a text field during nib2cib
This interferes with Aparajita's auto-sizing of controls in initWithCoder:. Also it's better to calculate the size in initWithCoder: because the theme information is available.
2010-10-19 15:07:01 +02:00
Klaas Pieter Annema 991e213d02 give CPSearchField it's own theme class
Before this change it was not possible to theme CPSearchField separately from a CPTextField. Aristo still just uses the rounded theme style.
2010-10-19 14:21:00 +02:00
Joachim GarthandRoss Boucher 834480ff68 Fixed a bug in reverseTransformValue: that caused transformedValue: to be called instead of reverseTransformedValue: 2010-10-18 10:46:13 -07:00
cacaodevandRoss Boucher 678563a970 Accidental globals in CPNotificationCenter and Runtime.js 2010-10-18 10:15:40 -07:00
Randall Luecke 00e638f406 initWithCoder on CPTextField should respect the larger height value if it's set. 2010-10-18 01:30:25 -04:00
Alexander Ljungberg 6b37bae2c2 Fixed: removed the previous CPTimer DOM check - it doesn't work in Foundation. 2010-10-15 16:03:00 -03:00
Alexander Ljungberg a3a4aed0d2 Merge branch 'master' of github.com:280north/cappuccino 2010-10-15 15:00:40 -03:00
Alexander Ljungberg 8ec78f20d1 Implement _minimumFrameSize for CPTokenField tokens. Also honor min-size width - not used by Aristo but potentially useful for custom themes. 2010-10-15 12:40:09 -03:00
Alexander Ljungberg a821614939 Clean up code. 2010-10-15 12:36:57 -03:00
Randall Luecke e13d771560 Performance related fixes for tableview drawing. 2010-10-15 11:09:26 -04:00
Randall Luecke 49a0a3d86e Fix for parameter type change from a find/replace. 2010-10-15 02:10:29 -04:00
Randall Luecke 56bc94f98c Merge branch 'tableview-grouprows' 2010-10-15 01:52:57 -04:00
Randall Luecke f0b527b680 Selection fixes for group rows in the tableview. 2010-10-15 01:52:22 -04:00
Derek Hammer ae5d56471f Inlining function, fixing a style issue. 2010-10-14 19:31:04 -05:00
Tom Robinson 58494c5c2a Merge branch 'master' of github.com:280north/cappuccino into integration 2010-10-14 16:38:45 -07:00
Tom Robinson c72e136370 Require latest versions of all package to eliminate deprecation warnings. 2010-10-14 16:38:06 -07:00
Alexander Ljungberg b4c8da8f3d Fix CPTokenField imports. 2010-10-14 20:21:00 -03:00
Alexander Ljungberg 612e8c3f0b Add DOM checks to CPTimer's window.setTimeout bridge code. 2010-10-14 20:20:20 -03:00
Tom Robinson 9763cef196 Merge branch 'fix-deprecation-warnings' of http://github.com/paulbaumgart/cappuccino into paulbaumgart-fix-deprecation-warnings 2010-10-14 16:16:02 -07:00
Alexander Ljungberg ebd83b4941 Merge branch 'fix-cptokenfieldtoken-sizetofit' of http://github.com/primalmotion/cappuccino into primalmotion-fix-cptokenfieldtoken-sizetofit 2010-10-14 19:42:33 -03:00
Alexander Ljungberg 48d3ae61c5 Merge branch 'master' of github.com:280north/cappuccino 2010-10-14 19:38:11 -03:00
Alexander Ljungberg cfba019e3d CPCoding support for CPResponder menus. This allows context menus to be set for collection view items through the item prototype. 2010-10-14 19:36:48 -03:00
Brian DonovanandRoss Boucher 2037ab9a5e -[CPScrollView setContentView:] did not allow changing the content view. 2010-10-14 11:25:29 -07:00
Paul BaumgartandRoss Boucher 3287b02816 add script to automatically detect missing @imports and have it run from "jake test-only" 2010-10-13 18:48:46 -07:00
Paul BaumgartandRoss Boucher 12deb6859e Make CPCompatibility a little more CommonJS friendly. 2010-10-13 18:48:37 -07:00
Paul BaumgartandRoss Boucher 98393c66fc change a 'self' to a 'super' to fix infinite recursion 2010-10-13 18:41:59 -07:00
Ross Boucher 74bedf6dcd Add a missing import to the ArrayController test. 2010-10-13 18:39:46 -07:00
Brian DonovanandRoss Boucher b5d0054f94 -[CPIndexSet shiftIndexesStartingAtIndex:by:] did not properly adjust count.
When clipping a range (i.e. some or all of it went below the lower bound) as a result of
calling shiftIndexesStartingAtIndex:by: with a negative delta, the CPIndexSet did not adjust
the index count, which caused calls to -lastIndex to fail.

This caused -[CPArrayController removeObject:] to fail when the object removed was at index 0.
2010-10-13 18:20:20 -07:00
Antoine Mercadal 560c971aeb capp_lint 2010-10-13 13:41:35 +02:00
Antoine Mercadal 8fc465b63a fix: CPTabView not resizable
fix: delegate problem with uninitialized variable
2010-10-13 13:37:28 +02:00
Antoine Mercadal ca0c68c9bf fix: CPTokenFieldToken impacted by new CPTextField sizeToFit behaviour 2010-10-13 13:34:37 +02:00
Klaas Pieter Annema 6c663ddf32 nib2cib NSTableColumn dataCell's alignment property 2010-10-12 16:30:14 +02:00
Klaas Pieter Annema 7129094e26 always archive the table column it's dataView when it's set
Don't equality check so the data view is always re-archived when it's set. A dataView with a different font size should be re-archived, but will not be if we check for equality.
2010-10-12 13:47:15 +02:00
Klaas Pieter Annema 802d7d53b0 fix multiline bezeled textfields being sized when initialized from coder 2010-10-12 11:26:28 +02:00
Klaas Pieter Annema c4a074a92d Merge branch 'CPTextField-height-fix' of http://github.com/aparajita/cappuccino into aparajita-CPTextField-height-fix 2010-10-12 10:54:38 +02:00
Klaas Pieter Annema fe35823b46 implement NSFormatter nib2cib support 2010-10-11 12:35:45 +02:00
Alexander Ljungberg 8439dc1c0f CPKeyBinding description message. Decouple CPKeyBinding physical key string parsing from cache setup to make CPKeyBinding more reusable in user code. 2010-10-10 01:35:30 -03:00
Alexander Ljungberg db8e132ef2 Whitespace and style fixes. 2010-10-09 22:07:57 -04:00
Alexander Ljungberg 7e0c61bef0 Replace a non ASCII character. 2010-10-09 22:02:34 -04:00
Alexander Ljungberg 2c4bb019ba Add license and creator to _CPCornerView.j. 2010-10-09 22:01:21 -04:00
Alexander Ljungberg 0bd03b8d58 Closes #926. Don't display a menu when a CPPopUpButton is right clicked, especially not a broken one. 2010-10-09 21:54:19 -04:00
Alexander Ljungberg e62af384ea Merge branch 'fix-imports' of http://github.com/paulbaumgart/cappuccino into paulbaumgart-fix-imports 2010-10-09 21:32:58 -04:00
Klaas Pieter Annema e23c70b5c4 Merge remote branch 'aparajita/NSCell-layout' 2010-10-09 16:25:48 +02: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
Aparajita Fishman c8639cc8cd Fixed the attribution 2010-10-08 23:18:48 -04:00
Aparajita Fishman 87c9f9ef03 Added bezeled multi-line field with wrapping 2010-10-08 17:52:47 -04:00
Aparajita Fishman ab430b3574 Forgot to update sizeToFit documentation. 2010-10-08 10:18:38 -04:00
Aparajita Fishman b8ae14d3a8 Fixes and more tests:
- Fixed _minimumFrameSize to take into account bezel and line break mode.

- Added test to show how sizeToFit was broken for multi-line labels in the old code.

- Added test to verify that behavior is correct for single-line labels.
2010-10-08 10:17:12 -04:00
Randall Luecke ca0ed0ccb9 Merge branch 'master' of git://github.com/280north/cappuccino 2010-10-08 00:48:40 -04:00
Randall Luecke 99201dc3db Initial commit for group rows in the TableView. Drawing code still needs to be cleaned up a LOT... still buggy. i.e. after you select a group row, any rows after that which are selected then get selected with a gray highlight color. 2010-10-08 00:44:17 -04:00
Klaas Pieter Annema 5074938437 implement KVO dependent key path support 2010-10-07 21:17:28 +02:00
Aparajita Fishman 637b8bed33 wraps flag was not being calculated correctly, added flags for other layout modes 2010-10-07 10:27:05 -04:00
Klaas Pieter Annema fcd75d72e0 remove cancel: action from CPResponder 2010-10-07 12:10:42 +02:00
Klaas Pieter Annema 5b82417698 Merge branch 'CPKeyValueObservingOptionInitial-fix' of http://github.com/eventualbuddha/cappuccino into eventualbuddha-CPKeyValueObservingOptionInitial-fix 2010-10-07 10:37:50 +02:00
Paul Baumgart 45ebe2c905 Fix deprecation warnings 2010-10-06 23:04:46 -07:00
Ross Boucher ff2aa51a68 Fix accidental global in CPObject. 2010-10-06 19:41:45 -07:00
Aparajita Fishman b6491f7bb8 CPTextField -initWithCoder was not ensuring the frame size was high enough. The default label height in IB is 17px, which unmodified was cutting off the bottom pixel of labels in Cappuccino. 2010-10-06 08:43:21 -04:00
Klaas Pieter Annema e78200838f don't make a modally run window the main window 2010-10-06 09:04:54 +02:00
Paul Baumgart 01852d8075 Fix a bunch of missing @imports.
All classes (excluding the ones prefixed with underscores) in Foundation
and AppKit can now be loaded individually except CPOpenPanel and
CPSavePanel. These two classes have some sort of dependency cycle
that seems impossible to resolve without forward declarations (which
we don't have).
2010-10-05 15:54:25 -07:00
Brian Donovan 0ce115bc9c Ensure observeValueForKeyPath:ofObject:change:context is called consistently.
During the "normal" callback for new and old values, the ofObject:
parameter passed to the observer is the original receiver of the
addObserver:forKeyPath:options:context: call, but that isn't the case
with the call caused by the CPKeyValueObservingOptionInitial option.
This commit uses _targetObject, the receiver of the addObserver:...
call, rather than self, the _CPKVOProxy.
2010-10-05 07:45:43 -07:00
Brian Donovan b430e2ef65 Fix "differ" that was supposed to be "defer". 2010-10-04 15:02:41 -07:00
Klaas Pieter Annema a99e976610 Merge branch 'CPControl-bridge' of http://github.com/aparajita/cappuccino into aparajita-CPControl-bridge 2010-10-04 10:44:03 +02:00
Klaas Pieter Annema 9b4807de26 Merge branch 'CPButton-copy-bounds' of http://github.com/aparajita/cappuccino into aparajita-CPButton-copy-bounds 2010-10-04 10:39:32 +02:00
Alexander Ljungberg 56a0184258 Fixed a missing comma in the token field theme descriptor. 2010-10-03 15:39:17 -04:00
Alexander Ljungberg b64390077a Remove margin from token fields without bezel so that the tokens line up with text labels at the same X coordinate. 2010-10-03 15:31:48 -04:00
Alexander Ljungberg e7e9c24aaa Fix accidental globals in CPTokenField, convert tabs to spaces. 2010-10-03 00:35:57 -04:00
Alexander Ljungberg 9eba3c0cec Make theme work for token fields without bezeled:NO. Demo of auto suggest in test app. 2010-10-03 00:29:29 -04:00
Alexander Ljungberg 69b30df8e6 Fixed: with more than one token field, the separator character for all fields would be bound to that of the first field. 2010-10-03 00:23:05 -04:00
Alexander Ljungberg ca2aab1198 Visual CPTokenField test application. 2010-10-02 22:45:05 -04:00
Alexander Ljungberg 1b45f621a7 Created and implemented a first draft Aristo theme for CPTokenField. 2010-10-02 22:41:38 -04:00
Alexander Ljungberg 421a51f008 Made CPTokenField themeable separately from CPTextField since the placeholder insets must be handled differently. 2010-10-02 19:38:12 -04:00
Alexander Ljungberg cce21e7e87 Fixed: forgot to define a theme name for the CPTokenField close button. 2010-10-02 19:38:01 -04:00
Alexander Ljungberg f6236ca317 Fixed: CPTokenField setObjectValue:nil did not clear the token field. 2010-10-02 19:37:48 -04:00
Alexander Ljungberg 77e10c94e9 Fixed: if setValue was called to clear a token field, the placeholder message would not appear. 2010-10-02 19:37:37 -04:00
Alexander Ljungberg 38cc1943ee Reverse binding support for deleting tokens using the delete button. Fixed: if the last token was deleted using the close button without the token field being the first responder, the placeholder message would not appear. 2010-10-02 19:37:31 -04:00
Alexander Ljungberg 3b1047e97d Implemented tokenizingCharacterSet property for CPTokenField. This changes the default tag separator to "," and allows tags with spaces. The previous behaviour can be restored using [field setTokenizingCharacterSet:[CPCharacterSet characterSetWithCharactersInString:@" "]]. 2010-10-02 19:37:17 -04:00
Alexander Ljungberg 34c1a1ce10 Fixed: if a CPTokenField was a subview of a container not at the top at the window, such as is often the case with a toolbar, the autocomplete view of CPTokenField would appear offset downwards.
Also switched the background of the autocomplete view to a simple menu style for now since the other graphics were not available.
2010-10-02 19:37:08 -04:00
Alexander Ljungberg b0e3e38791 Reverse bindings support for when tokens are deleted through the close button. 2010-10-02 19:36:55 -04:00
Alexander Ljungberg 124a63736f Made CPTokenField themeable. Todo: the autocomplete drop-down is still hardcoded and Aristo style images are needed. 2010-10-02 19:36:24 -04:00
Alexander Ljungberg 656e0eb28e Whitespace cleanup in preparation for the next merge. 2010-10-02 19:19:51 -04:00
Alexander Ljungberg 688c46c793 Fixed some typos in the previous CPTokenField commit. 2010-10-02 15:36:35 -04:00
Alexander Ljungberg ee2228a83c Fixed: if [CPTokenField setObjectValue:X] was called while the token field was the first responder, the input value would be set to a string version of the object value due to CPTextField's setObjectValue method. 2010-10-02 15:36:29 -04:00
Klaas Pieter AnnemaandAlexander Ljungberg 9f4dd3c2b8 added various hacks to make the cptokenfield work with the new enstore admin 2010-10-02 15:36:24 -04:00
Klaas Pieter AnnemaandAlexander Ljungberg c80a28077a fixed some tokenfield issues 2010-10-02 15:36:19 -04:00
Klaas Pieter AnnemaandAlexander Ljungberg 47c631c58e added CPTokenField 2010-10-02 15:36:11 -04:00
Alexander Ljungberg ed4235d2f9 Fixed: setting any binding on a text field - even on an attribute like 'hidden' - would clear its placeholder string. 2010-10-02 14:42:06 -04:00
Alexander Ljungberg 16e9fce5b5 Unit test exposing a new bug: setting a binding on a text field causes it to lose its placeholder string. 2010-10-02 14:38:34 -04:00
Alexander Ljungberg 2e22a0d5e8 Merge branch 'master' of github.com:280north/cappuccino 2010-10-01 17:30:17 -04:00
Alexander Ljungberg 1ae31c9374 Style fixes. 2010-10-01 17:28:55 -04:00
Klaas Pieter Annema 973c43843d improve multiple selection login in CPCollectionView 2010-10-01 11:31:59 +02:00
Alexander Ljungberg 90709156c6 Merge branch '_CPImageAndTextView-tweaks' of http://github.com/aparajita/cappuccino 2010-09-30 23:52:27 -04:00
Alexander Ljungberg 0d15e59d0a CPSlider code cleanup. 2010-09-30 23:51:12 -04:00
Aparajita Fishman 60fcb24159 De-lint, whitespace cleanup, typos 2010-09-30 21:14:47 -04:00
Aparajita Fishman a175e71906 - Fixed type of _textSize.
- Changed NULL to nil.
2010-09-30 17:30:58 -04:00
Aparajita Fishman c3b5dc747a CPButton bezelRectForBounds and contentRectForBounds were modifying the bounds parameter in place without copying it. 2010-09-30 17:27:06 -04:00
Klaas Pieter Annema e527c7e19f fix another bug introduced in my last commit 2010-09-30 18:58:40 +02:00
Klaas Pieter Annema 790327fbe8 revert d18bba6b03, it had unexpected side effect 2010-09-30 18:44:00 +02:00
Klaas Pieter Annema d18bba6b03 make sure CPScrollView always sets up it's corner and header view when initializing from coder 2010-09-30 18:40:45 +02:00
Aparajita Fishman 0a752be53c Moved methods defined by BRIDGE into real method declarations so they will be included in doxygen docs, lint cleanup. 2010-09-30 08:37:36 -04:00
Klaas Pieter Annema b221cc1853 properly decode allows multiple selection in CPCollectionView 2010-09-30 13:54:34 +02:00
Klaas Pieter Annema 2935651578 only nib2cib bundle if bundle path is set in nib 2010-09-30 13:13:18 +02:00
Paul Baumgart ca2ae22f15 Fix non-ASCII characters in CPDictionary.j and CPFormatter.j 2010-09-29 18:21:10 -07:00
Paul Baumgart 2cc6c54fbf Start index for var-args needs to be 2, not 0. I only got lucky that it worked anyway. 2010-09-29 15:19:20 -07:00
Mike Fellows 1c597eb0df Fix regression in CPBox's setBorder 2010-09-29 00:05:15 -07:00
Alexander Ljungberg 28dd74444f Fixed a string of accidental globals in CPScroller. 2010-09-28 19:50:20 -04:00
Alexander Ljungberg 28cf834e0b Merge branch 'CGGradientCreateWithColorComponents-location-fix' of http://github.com/eventualbuddha/cappuccino 2010-09-28 19:29:46 -04:00
Alexander Ljungberg 4dc102a3cf Applied coding standards. 2010-09-28 19:00:59 -04:00
Brian Donovan 23a654d57a Allow null locations per Quartz 2D documentation.
See http://developer.apple.com/library/ios/#DOCUMENTATION/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_shadings/dq_shadings.html%23//apple_ref/doc/uid/TP30001066-CH207-TPXREF101
2010-09-28 08:22:09 -07:00
Klaas Pieter Annema ffcbf87858 add basic support for drawing separators to CPBox 2010-09-28 14:50:20 +02:00
Ross Boucher 32a0e950fe Allow comparators to return any value > 1 to indicate CPOrderedDescending. 2010-09-28 16:46:39 +05:30
Randall Luecke f21ec37531 Fix for NativeHost windows becoming inactive when then go to the background. 2010-09-28 00:18:02 -04:00
Paul BaumgartandRandall Luecke a8d02f43e2 minor CPTableView clean-ups-- fix missing semi-colon, missing parameter type, and missing space 2010-09-27 22:43:58 -04:00
Paul BaumgartandRandall Luecke 7e863e7e96 selectTabViewItemAtIndex does not look up the TabViewItem to send to the delegate, which causes a JS ReferenceError; this commit fixes that 2010-09-27 22:42:55 -04:00
Randall Luecke 588577bd96 try to use setLocalStorageDatabasePath or use _setLocalStorageDatabasePath if not
Conflicts:

	Tools/NativeHost/AppController.m
2010-09-27 22:38:32 -04:00
Randall Luecke ee64c5d832 Proper decoding of delegate and datasource for the tableview. 2010-09-27 17:56:48 -04:00
Antoine MercadalandRandall Luecke e55cbbdc0e Support for localstorage in NativeHost 2010-09-27 16:27:04 -04:00
Klaas Pieter Annema 65c48004ba properly handle key events manually in the tableview
Commit cf6dc3fa5e was wrong. This commit should fix that.
2010-09-27 15:56:00 +02:00
Klaas Pieter Annema 4211abd0b0 handle tab key as early as possible in CPWindow sendEvent: 2010-09-27 11:53:07 +02:00
Klaas Pieter Annema cf6dc3fa5e Manually handle key events in CPTableView 2010-09-27 11:50:23 +02:00
Klaas Pieter Annema fb3da5c5bd don't handle key events directly in CPScrollView
In stead CPScrollView will just pass the keyDown: event up the responder chain. If the event reaches the window, the window will send the correct action back to the first responder, if no responder before CPScrollView in the chain handles the event, CPScrollView will.
2010-09-27 11:50:23 +02:00
Klaas Pieter Annema e6bd921746 fix CPWindow to only sent certain not handled keys as actions
In Cocoa CPWindow will only send moveDown: (down arrow), moveUp: (up arrow), moveLeft: (left arrow), moveRight: (right arrow), pageUp: (page up), pageDown: (page down) and complete: (escape) down the responder chain. This commits makes us fully compatible with Cocoa except that we send scrollPageDown: and scrollPageUp: in stead of pageUp: and pageDown:.
2010-09-27 11:50:23 +02:00
Francisco Ryan Tolmasky I 40dcfbd72c Merge branch 'master' of github.com:280north/cappuccino 2010-09-27 06:49:18 +05:30
Francisco Ryan Tolmasky I 48d14840ee Fix file encoding for CPTableView.j.
Reviewed by me.
2010-09-26 15:40:36 +05:30
Paul Baumgart e62fd3cf40 Add a test case to test some reductions of regexes that current cause errors in the Preprocessor. 2010-09-24 16:46:31 -07:00
Paul Baumgart 8cc61cccfd add behavior tests for methods, ivars, and inheritance; currently, one of the ivar tests fails due to bug #498 2010-09-24 15:10:06 -07:00
Paul Baumgart 0802b80c35 Make local param shadowing detection print a warning instead of throwing a SyntaxError. This way it's easier to test that particular scenario, since this is actually a bug in the Preprocessor. 2010-09-24 15:03:22 -07:00
Paul Baumgart 8de508381a re-organize directory structure of preprocessor tests 2010-09-24 15:02:07 -07:00
Klaas Pieter Annema c9e0ab654f test observations during setSelectionIndexes 2010-09-23 10:59:00 +02:00
Klaas Pieter Annema d8c0d2da8e don't reverse set binding if textfield is showing a bindings placeholder 2010-09-23 10:35:42 +02:00
Klaas Pieter Annema e59f20668b don't set objectValue in resignFirstResponder if it didn't change
This change makes sure that the textfield doesn't sent change notifications if the value didn't actually changed when resigning first responder.
2010-09-23 10:35:41 +02:00
Klaas Pieter Annema 8fe67b73da implement _setCurrentValueIsPlaceholder in CPTextField
CPKeyValueBinding will sent _setCurrentValueIsPlaceholder: to indicate to an object that current value is a placeholder and should be displayed as such. This commit implements the method for CPTextField and adds a unit test to test the behavior.
2010-09-23 10:35:41 +02:00
Klaas Pieter Annema 2fba03dc75 fix style issues in CPTextField and CPKeyValueBindingTest 2010-09-23 10:35:41 +02:00
Klaas Pieter Annema 71f8d1db74 call selectionWill and didChange when setting selection indexes 2010-09-23 10:35:41 +02:00
Klaas Pieter Annema 098131e252 coding guideline improvements for CPArrayController 2010-09-23 10:35:41 +02:00
Klaas Pieter Annema afc5b72092 made setting binding placeholder values slightly less hacky 2010-09-23 10:35:41 +02:00
Klaas Pieter Annema 14f494a25d Properly set multiple value placeholders on textfields.
Previously CPKeyValueBinding would just set the binding marker placeholder values as the stringValue of the textfield. This commit fixes that and properly sets those values as the placeholder value.
2010-09-23 10:35:41 +02:00
Francisco Ryan Tolmasky I 8bc665f355 Merge branch 'master' of github.com:280north/cappuccino 2010-09-23 10:43:08 +05:30
Paul Baumgart 086fa29d78 Objective-J Preprocessor Tests: fix scoping bug that caused only the last file in FILENAMES to be tested. 2010-09-22 00:50:15 -07:00
Brian DonovanandRoss Boucher 6dd872f2d2 Fix CPScrollView -contentSize return type. 2010-09-21 21:43:28 +05:30
Mike FellowsandRandall Luecke 461bb65263 Set vertical slider disabled track-color to the proper background images, stop overwriting the horizontal slider disabled track-color background images with those meant for the vertical slider - fixes issue #737 2010-09-20 01:37:03 -04:00
Derek HammerandRandall Luecke 266bed7dc9 Use include instead of push to increase performance of jake. 2010-09-20 01:33:36 -04:00
Randall Luecke 9777e4c52f Added a missing import to the new CPTabView, and fixed the import for the test. 2010-09-20 01:28:57 -04:00
Derek HammerandRandall Luecke dd89a98242 Renaming class to CPTabView from CPTabView2. Also doing a little clean up for style. 2010-09-20 01:21:45 -04:00
Derek HammerandRandall Luecke 9b57d04181 Tabs to spaces 2010-09-20 01:20:58 -04:00
Derek HammerandRandall Luecke 8e74418a5c Replacing CPTabView with new one 2010-09-20 01:20:48 -04:00
Derek HammerandRandall Luecke 3350579675 Patch to fix error. :( 2010-09-20 01:20:40 -04:00
Derek HammerandRandall Luecke 46c14f3766 Adding the real skeleton
Copying previous constants

Removing unnecessary constants

Borrowing initialization from my old implementation.

Refactoring the initialization method and adding setBackgroundColor: override.

Removing +initialize (no theming support yet) and -viewDidMoveToWindow (not sure why this was there?)

Implement the bulk of the new CPTabView

Adding delegate selectors. Don't think this is complete, though. What about when a user clicks on a segmented tab control?!

Adding delegate

Think I may have fixed the delegate blocking for selected segment control items

Adding tests. Fixing a bug by reverting to old way. Delegates still broken.

Cleaning up the test.

Resolving delegate issues (thanks Saikat!).

Switching tab appearance based on type enum. Updating tests to slightly test this.

Conflicts:

	AppKit/CPTabView2.j
2010-09-20 01:20:31 -04:00
Randall Luecke 0aa65de6df Fix for CPCookie not working after DOM checks. 2010-09-19 23:26:52 -04:00
Francisco Ryan Tolmasky I 06bb1a96f3 Fix for objjc not compiling.
Reviewed by me.
2010-09-19 15:21:01 -07:00
Francisco Ryan Tolmasky I 70e4dd16df A few more parser tests and reorg of tests.
Reviewed by me.
2010-09-19 08:18:54 -07:00
Francisco Ryan Tolmasky I b66034ef38 First couple of Objective-J language spec tests.
Reviewed by me.
2010-09-18 23:50:06 -07:00
Francisco Ryan Tolmasky I d3c86aeefd Cleanup for previous undo patch and added a few test cases.
Reviewed by me.
2010-09-18 21:47:43 -07:00
Blair DuncanandFrancisco Ryan Tolmasky I 212feff636 CPUndoManager -added support for setActionName to enable the undo/redo menu to automatically update with the value passed as the action name. Test file included. 2010-09-18 20:30:43 -07:00
Alexander Ljungberg b1b0cea27e Merge remote branch 'hammerdr/clean_fix' 2010-09-17 21:25:05 -04:00
Alexander Ljungberg 5742608595 Recreated Aparajita Fishman's documentation related Jakefile change from 345343ef52. 2010-09-17 21:21:40 -04:00
Aparajita FishmanandAlexander Ljungberg f46f97f8b6 Implemented doxygen parsing of @accessors synthesized methods, moved @accessors declarations in .h files to a comment to prevent improper parsing. 2010-09-17 21:19:02 -04:00
Alexander Ljungberg 7692f80f64 Additional fixes of inadvertent globals. 2010-09-17 16:48:00 -04:00
Alexander Ljungberg bb811238f3 Fixed a number of inadvertent globals and improved code style. 2010-09-17 16:46:55 -04:00
Derek Hammer 68c657eb66 Adding the $CAPP_BUILD directory to the "jake clean" and "jake clobber" commands so that they act as expected. 2010-09-17 13:03:50 -05:00
Nicholas Small b5bae40a0c Fix the short circuit in CPCollectionView -setSelectionIndexes: 2010-09-17 12:23:36 -04:00
Michael VillarandNicholas Small f7c68736f0 Ctrl+click only sends right click on Mac. 2010-09-17 12:21:57 -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
Mike FellowsandKlaas Pieter Annema 7d855a9c09 Fix minor typos, some accidental globals, missing coma and missing semicolon 2010-09-17 11:03:32 +02:00
Nicholas Small d59d141302 Fix a bool that's supposed to be an int in CPUndoManager -groupingLevel. 2010-09-16 13:26:17 -04:00
Aparajita FishmanandKlaas Pieter Annema 0c4ce1e756 Additions to the theme API to open it up to developers and provide access to theme attributes defined in ThemeDescriptors.j:
- Current theme blend is available via CPApplication -themeBlend.

- List of themes is available via CPApplication -themes.

- CPThemeBlend adds the following methods:

themes
themeNames

- CPTheme adds a number of methods to access theme attributes:

classNames
attributesForClass:
attributeNamesForClass:
attributeWithName:forClass:  (was _attributeWithName:forClass:)
valueForAttributeWithName:forClass
valueForAttributeWithName:inState:forClass:

- _CPThemeAttribute -values was added to access the dictionary of attribute values.

- Theme browser application that demonstrates the API.

- In the course of making the test app, added the function CGInsetEqualToInset().
2010-09-16 10:28:06 +02:00
Alexander Ljungberg 9b8cadb91c Fixed some additional accidental globals. Very addictive this. 2010-09-15 17:41:58 -04:00
Alexander Ljungberg 9c9d6a7fdc Merge branch 'master' of github.com:280north/cappuccino 2010-09-15 17:25:54 -04:00
Alexander Ljungberg fb31267cc1 Fixed two accidental globals found while testing Aparajita Fishman's capp_check utility. 2010-09-15 17:23:48 -04:00
Alexander Ljungberg b194d407d3 Whitespace cleanup. 2010-09-15 17:19:45 -04:00
Klaas Pieter Annema 57813ea3fb change CPButton imageOffset theme property to image-offset 2010-09-15 12:34:16 +02:00
Alexander Ljungberg bce89ca75b Merge branch 'master' of github.com:280north/cappuccino 2010-09-14 15:39:23 -04:00
Alexander Ljungberg 7204e73c22 Minor code cleanup. 2010-09-14 15:38:45 -04:00
Alexander Ljungberg 541f5b8948 Test editable text field text selection in a modal window. 2010-09-14 15:38:45 -04:00
Alexander Ljungberg c5d471b31b Fixed: if a text field in a modal window was clicked, it would become deselected. This prevented text selection by dragging or by double click. The problem was that the DOM event guard was always enabled when a modal window was on screen and this prevented the normal mouse event pass through to the text field input element. 2010-09-14 15:38:45 -04:00
Klaas Pieter Annema ac26827f32 make CPTableHeaderView divider color theme-able 2010-09-14 14:47:10 +02:00
Klaas Pieter Annema 677cb4638f fix bug where CPViewController viewDidLoad is called to early
The bug was caused by connections (outlets) being defined in undefined order. Sometimes the view connection was decoded and connected before other connections, because setView: would automatically call viewDidLoad the first time a view was set viewDidLoad was called before the entire view was actually loaded.

ViewDidLoad is now only called from setView: if the _view === nil and no view is currently being loaded.
2010-09-14 12:58:47 +02:00
Klaas Pieter Annema 32348148b8 fixed typos in CPViewController documentation 2010-09-14 12:12:50 +02:00
Klaas Pieter Annema f79edc7bfb fix scroller being offset 1 pixel when headerview had the same height as corner view 2010-09-14 12:05:39 +02:00
Klaas Pieter Annema f7c7ee447d set proper autoresizing for ScrollviewTheming test color well 2010-09-14 12:05:39 +02:00
Tom Robinson 1220555936 Fix for CPProxy not returning the return value 2010-09-13 16:44:45 -07:00
Sami SamhuriandKlaas Pieter Annema 032639234e Use CPTextFields for RGB, HSB, and hex inputs in CPSliderColorPicker
The old DOM based fields only accepted a few characters. Backspace and
other expected functionality was broken. Switching to CPTextFields
makes them behave as expected.
2010-09-13 15:20:26 +02:00
Saikat ChakrabartiandRandall Luecke cdf9a8c2a7 Adding a DOM check for CPCookie 2010-09-13 01:30:46 -04:00
Aparajita FishmanandAlexander Ljungberg 6fbdf7b400 Support for NSBox in nib2cib and some fixes to CPDrawTiledRects/CPDrawColorTiledRects.
- The default box background color is now clear, that is what Cocoa does.

- Bezel drawing uses CPDrawTiledRects, obeys border width.

- CPDrawTiledRects/CPDrawColorTiledRects explicitly sets the line width and saves/restores the graphics state.

- Whitespace cleanup in CPBox.
2010-09-10 20:35:38 -04:00
Alexander Ljungberg 4983e97884 Use CPNotFound instead of -1 in CPTableView editedRow and editedColumn for clarity. 2010-09-10 20:27:22 -04:00
Alexander Ljungberg cc7d50f505 Fixed: CPTableView editedRow returned the edited column, not the edited row. 2010-09-10 20:26:01 -04:00
Alexander Ljungberg f2f737fcd3 Merge remote branch 'hammerdr/subclassable' 2010-09-10 20:18:30 -04:00
cacaodevandAlexander Ljungberg c47e6af6e4 nib2cib: Fix a bug where a view's tag of 0 in Interface Builder was decoded as -1 in capp. This is the default when instancing in code, not when unarchiving a Nib. Testing: in Tests/Manual/NibApp, just logging a textfield's tag 2010-09-10 20:03:28 -04:00
Alexander Ljungberg 5e6485b622 Merge remote branch 'samsonjs/rightclick' 2010-09-10 19:26:12 -04:00
Alexander Ljungberg bb2ec9098b Merge remote branch 'aparajita/CPLog-formatter' 2010-09-10 19:15:21 -04:00
Alexander Ljungberg 4e4cc65645 Style and whitespace cleanup. 2010-09-10 19:07:48 -04:00
Arkadiusz MłynarczykandAlexander Ljungberg ddfac8d717 - moved componentsSeparatedByCharactersInSet: into CPCharacterSetAdditions CPString category
- added tests for componentsSeparatedByCharactersInSet:
- ensured Cocoa compatibility of componentsSeparatedByCharactersInSet:
- added new test for CPString boolValue
- fixed CPString boolValue (" ++01" should return NO as in Cocoa, previously it returned YES)
2010-09-10 18:58:18 -04:00
Arkadiusz MłynarczykandAlexander Ljungberg 009683ddd4 - Exception raising in componentsSeparatedByCharactersInSet: when separator parameter is nil
- Added support for edge cases (string is empty or string doesn't contain characters from separator set).
2010-09-10 18:58:10 -04:00
Arkadiusz MłynarczykandAlexander Ljungberg 8eefb90944 - implemented componentsSeparatedByCharactersInSet: 2010-09-10 18:58:02 -04:00
Klaas Pieter Annema 6bc8a53618 Merge branch 'scrollview-theming' 2010-09-10 14:37:51 +02:00
Klaas Pieter Annema de73c05316 add colorwell to change bordercolor to Scrollview theming test 2010-09-10 14:28:09 +02:00
Klaas Pieter Annema fba8b85c90 theming changes to CPScrollView
- Add bottom corner view and make it's background color a theme property
- Make the border color themeable
2010-09-10 14:20:19 +02:00
Klaas Pieter Annema 20557190d9 make the scroller width themeable 2010-09-10 14:20:18 +02:00
Klaas Pieter Annema 4e4e7ae015 properly position the vertical scrollbar
The vertical scrollbar would be one pixel of if there was:

- no headerview (overlapping the border)
- a headerview, but no cornerview
2010-09-10 14:20:18 +02:00
Klaas Pieter Annema 36c3c94d3b add the ability to turn header view on and off in ScrollviewTheming test 2010-09-10 14:20:18 +02:00
Klaas Pieter Annema 64b733b1ea remove bottom corner view drawing in CPScrollView 2010-09-10 14:20:18 +02:00
Klaas Pieter Annema 67a023a992 set proper autoresizing mask for theming controls in ScrollviewTheming test app 2010-09-10 14:20:18 +02:00
Klaas Pieter Annema b6e7d4149d add scrollview theming test application 2010-09-10 14:20:18 +02:00
Klaas Pieter Annema bcacee2147 draw the bottom corner in CPScrollView 2010-09-10 14:20:17 +02:00
Klaas Pieter Annema b75dcd7ac4 made the scrollview line border color themeable 2010-09-10 14:20:17 +02:00
Klaas Pieter Annema e77d28f761 properly decode CPColorWell color as an object in stead of bool 2010-09-10 14:17:39 +02:00
Sami SamhuriandKlaas Pieter Annema bc9645aa4f Added a test for hex conversions in CPColor 2010-09-10 10:02:21 +02:00
Sami SamhuriandKlaas Pieter Annema d52cbb7077 Don't set placeholder text on hex text field 2010-09-10 10:02:14 +02:00
Sami SamhuriandKlaas Pieter Annema ba9df402b0 Use a CPTextField for hex input in CPSliderColorPicker
The old DOM based field only accepted a few characters, and not even hex
chars. Backspace and other expected functionality was broken. Switching
to a CPTextField makes it behave as expected.
2010-09-10 10:02:04 +02:00
Sami SamhuriandKlaas Pieter Annema c78b5e580a Reliably convert colors to hex strings
Converting a hex string to CPColor and back to a hex string now returns
the same initial hex string. (Fixed an off-by-one error)
2010-09-10 10:01:57 +02:00
Aparajita FishmanandKlaas Pieter Annema ce2c662872 Fixes to previous CPButton image positioning commit.
- Checkbox and radio selected states would not show in the images. It turns out that the image and alternate image cannot be encoded->decoded->set without messing up the theme, and unfortunately the theme blending task (during a jake build) would do so. So for now this means that we cannot encode non-theme images with a button class, which is unlikely to happen.

- Since we cannot access themes in the NS classes, I went ahead and started to make some constants in a few control classes so that the values can be changed in one place and affect the theme and nib2cib.
2010-09-10 09:56:26 +02:00
Klaas Pieter Annema 04b331ad55 decode CPTableColumn resizing mask as integer 2010-09-09 16:36:32 +02:00
Klaas Pieter Annema 35c026f92c Merge branch 'master' of github.com:280north/cappuccino 2010-09-08 22:14:34 +02:00
Aparajita FishmanandKlaas Pieter Annema 6680a1f2a7 Overhaul of CPButton and supporting classes to support image positioning the way Cocoa does 2010-09-08 22:13:39 +02:00
Klaas Pieter Annema 1ffbf7857f Overhaul of CPButton and supporting classes to support image positioning the way Cocoa does. 2010-09-08 22:10:20 +02:00
Klaas Pieter Annema e2741ba604 made press work with custom themes 2010-09-08 16:13:45 +02:00
Koen BokandKlaas Pieter Annema 5b7497093c Made flatten work with custom themes. 2010-09-08 16:12:22 +02:00
Klaas Pieter Annema b092ed8c2c only load Aristo from AppKit/Resources
Other themes are loaded from the main bundle's resource directory
2010-09-08 16:12:21 +02:00
Klaas Pieter Annema 2dd1a1b54d always return a boolean from CPKeyedUnarchiver decodeBoolForKey: 2010-09-08 13:28:40 +02:00
Klaas Pieter Annema 1952bc2b76 unhide the cornerview when a tableview is unarchived 2010-09-08 13:28:18 +02:00
Klaas Pieter Annema b6da0fdf06 start of CPSplitView theming 2010-09-07 10:23:21 +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
Derek Hammer 7f7571a2d1 Adding tests to verify the behavior of CPDictionary when subclassed. 2010-09-06 11:44:27 -05:00
Alexander Ljungberg e704d42adb Fixed: if CPArrayController setPreserveSelection was off and a selected item disappeared, an invalid selection state could occur. The error was caused by a slightly overeager early-out optimisation in __setSelectionIndexes. 2010-09-04 22:12:08 -04:00
Sami Samhuri 5ff9683cd7 Send the correct event when right-clicking in a focused text field 2010-09-03 10:18:26 -07:00
Aparajita Fishman 7d36daa5b7 Added documentation for CPLogColorize 2010-09-03 11:45:06 -04:00
Aparajita Fishman 46956dbe9e Added a README 2010-09-03 11:36:11 -04:00
Aparajita Fishman 586e18f1a7 Custom formatter support (and fixes) for CPLog.
- A formatter function can be passed to the CPLogRegister functions. If the given level already has a provider for the given level, the formatter will be replaced with the one passed to the register function.

- Added CPLogColorize function to make it easy for users to colorize messages.

- CPLogRegisterRange now checks for min <= max, and  now correctly starts iterating from min.

- Moved colorization of log level to _CPFormatLogMessage.

- Whitespace cleanup.
2010-09-03 11:20:28 -04:00
luddepandRandall Luecke c489909542 Added manual test for cpscrollview behavior 2010-09-03 11:09:08 -04:00
Randall Luecke ad679e7c34 Merge remote branch 'luddep/native-scrolling-2' 2010-09-02 23:29:44 -04:00
luddep 75f6db436b fix for clearing the hiding of the scroll element timeout not working. This improved performance. Also make the actual dom element smaller and the inner one bigger, since sometimes deltas need to be larger than 150px. 2010-09-02 22:25:09 +02:00
Alexander Ljungberg bdcef193b7 Minor CPArrayTest cleanup. 2010-08-31 23:45:35 -04:00
Derek HammerandAlexander Ljungberg d377790e9d Adding some tests to verify behavior. 2010-08-31 23:41:51 -04:00
Alexander Ljungberg 9a31297249 Put the logging setup into the natural code path. 2010-08-31 22:33:11 -04:00
Aparajita FishmanandAlexander Ljungberg b4f7df4786 Graphics primitives
- Implemented CGRectDivide/CPDivideRect.
- Implemented CPDrawTiledRects/CPDrawColorTiledRects.
- Removed CPDrawGrayBezel and CPDrawGroove, they were not being done in a Cocoa-compliant way, and the Cocoa way is not really useful right now.
- Moved border drawing code back to CPScrollView since CPDrawGrayBezel/CPDrawGroove are gone.
- Test app to do simple demo of the new functions.
- Removed trailing whitespace.
2010-08-31 22:26:54 -04:00
Alexander Ljungberg 18d7dcc226 Closes #849. Test application to verify the graphical rendering of menus. 2010-08-31 22:18:26 -04:00
Sami SamhuriandAlexander Ljungberg f7ef182d33 Add 3px padding to the right of menu bar icons 2010-08-31 22:15:46 -04:00
Aparajita FishmanandAlexander Ljungberg be36e17bd8 Make the names in +themeShowcaseExcludes case-insensitive 2010-08-31 22:09:29 -04:00
Aparajita FishmanandAlexander Ljungberg 6b940116be Added ability to set sample text 2010-08-31 22:02:50 -04:00
luddep da8ea72593 fix for scrolling not working in windows other than the default bridge one. 2010-08-31 14:22:46 +02:00
luddep 5effa853a3 use visibility instead of display to hide the scroll dom element. Using display made the div reset its scroll offset. 2010-08-31 14:09:49 +02:00
luddep 0780a68fba fix for not being able to interact with DOM elements in views such as CPTextField 2010-08-31 09:36:54 +02:00
luddep b61192a050 Initial lower level native scrolling attempt. Fixes scroll deltas globally, rather than in just CPScrollView. 2010-08-30 12:27:28 +02:00
Alexander Ljungberg 9bc9a49b8f Merge branch 'master' of github.com:280north/cappuccino 2010-08-29 17:46:47 -04:00
Alexander Ljungberg 547f1fb786 While not used anywhere, the preprocessor 'peak' method was most likely meant to be called 'peek'. Renamed it. Also some minor code styling and whitespace fixes. 2010-08-29 17:42:22 -04:00
Blair DuncanandRandall Luecke b27560c51e Fix for issue 841 where the edit cursor would not always flash 2010-08-27 19:46:55 -04:00
Aparajita FishmanandAlexander Ljungberg 8dd1d20a2d Made sure to remove the .doc directories first, fixed exec 2010-08-27 19:29:11 -04:00
Aparajita FishmanandAlexander Ljungberg ad5badb0d7 Remove @import statements from source files, doxygen doesn't parse them correctly. 2010-08-27 19:28:23 -04:00
Aparajita FishmanandAlexander Ljungberg 18696e6bc2 Ensure CPControl -performClick unhighlights the button if the action throws. 2010-08-27 15:58:35 -04:00
Aparajita FishmanandAlexander Ljungberg 4f2914a123 Implementation of CPFont -ascender, -descender and -defaultLineHeightForFont, supporting method +metricsOfFont in CPStringDrawing and CPPlatformString, and Font Metrics Explorer test app. 2010-08-27 14:32:03 -04:00
Alexander Ljungberg 431c6522a6 Test alerts with 1 or 0 buttons defined. 2010-08-27 14:07:31 -04:00
Aparajita FishmanandAlexander Ljungberg b823eb7fe0 Fixes for Cocoa compliance 2010-08-27 14:04:28 -04:00
Klaas Pieter Annema f8ceaf62b7 set font for tableCell during nib2cib 2010-08-27 15:50:59 +02:00
Klaas Pieter Annema 213fde04fe fix CPArray+KVO addObjects inserting objects at beginning of array one by one 2010-08-27 12:06:40 +02:00
Klaas Pieter Annema ddad10b615 fix CPPredicate predicateWithFormat: throwing exception (in WebKit)
I believe the exception was caused because WebKit thought arguments was the function.Arguments.
Issue was resolved by renaming the local arguments variable to args
2010-08-26 16:55:05 +02:00
Klaas Pieter Annema f4e7386a0a fix gridColor when decoding a CPTableView
Don't default to a gray color when there is no grid color in the cib.
The tableview theme will automatically set the correct grid color.
2010-08-26 16:29:46 +02:00
Alexander Ljungberg 9a42e12985 Moved TableCibTest into the table tests folder. 2010-08-25 16:15:27 -04:00
Klaas Pieter Annema 86ee790ea1 implement missing __setSelectionIndex: 2010-08-25 15:57:35 +02:00
Klaas Pieter Annema b21eab1bf1 Improved KVC mutable indexed accessors
Refactored everything away into insertObjects:atIndexes: so all the logic is in the same place
and made it so that the _insertManySEL is the preferred selector to use. If it doesn't exist it will fall back to the _insertSEL.
2010-08-25 15:50:24 +02: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
Klaas Pieter Annema c9752195ac several CPButton theming additions
- made image and alternate image a theme property
- made image margins theme-able
2010-08-25 13:26:44 +02:00
Klaas Pieter Annema 64000215a4 Call CPObjectController designated initializer from init and initialize _observedKeys instance variable 2010-08-25 13:15:19 +02:00
Alexander Ljungberg 65d957f9f5 Fixed: an ivar was not being properly initialized in CPAlert. 2010-08-24 14:00:12 -04:00
Alexander Ljungberg aef19c3b13 Merge branch 'master' of github.com:280north/cappuccino 2010-08-24 12:30:51 -04:00
Alexander Ljungberg 9968896bbd When running CPAlert as a sheet, automatically activate the CPDocModalWindowMask window style if needed. 2010-08-24 12:14:24 -04:00
Alexander Ljungberg 1a27ae39a3 Removed CPAlert long message test from last commit since this branch already has its own long message test. Also slight clean up. 2010-08-24 11:58:36 -04:00
cacaodevandAlexander Ljungberg ee4802e513 CPAlert: Attached alerts. Added a new method -beginSheetModalForWindow: that calls -alertDidEnd:returnCode: on ending. CPAlertTest update testing it.
Fixed a bug in CPWindow where the didEndSelector was reset too early. This bug was visible only when trying to chain sheet alerts.
         Fixed a local/instance variable conflict in AttachedSheet/AppController.j
2010-08-24 11:50:44 -04:00
Klaas Pieter Annema 60dd1863b3 Implement objectsAtIndexes on _CPObservableArray to return another _CPObservableArray instance 2010-08-24 11:41:52 +02:00
Klaas Pieter Annema 71408e7c3a made CPObjectController call it's designated initializer (init) 2010-08-24 11:41:51 +02:00
Klaas Pieter Annema 659543461b Merge branch 'upstream' 2010-08-24 11:13:26 +02:00
Alexander Ljungberg 50b7f02470 Merge branch 'master' of github.com:280north/cappuccino 2010-08-23 19:45:08 -04:00
Alexander Ljungberg febdf4092e New implementation of change notifications from CPArrayController.
It is crucial that we send notification only before and after complete changes. In the middle notifications might cause observers to see or react to inconsistent data (e.g. selection indexes pointing to rows no longer present). Added some unit tests - more might be needed in the future. Fixed: before and after values when observing array controller key paths during content changes or rearranges were wrong. Fixed: the array controller sent out multiple redundant change notifications.
2010-08-23 18:53:29 -04:00
Alexander Ljungberg a3d89c8d78 Ignore table view row selection of already selected rows. This avoids potential infinite recursion caused by the explicit bindings propagation. 2010-08-23 18:51:00 -04:00
Nicholas Small c9b02603bc Don't use the deprecated .path() method in CFBundle OBJJ_PROGRESS_CALLBACK. 2010-08-23 15:48:17 -04:00
Alexander Ljungberg b9086f134a Don't include table column header graphics in the showcase - they're not really widgets which make sense standing alone. 2010-08-22 23:03:51 -04:00
Alexander Ljungberg 447c33b806 Don't layout CPAlert in layoutSubviews since it's not a real view. This avoids the theme showcase error where the CPAlert windowing code was activated by the theme descriptor setup. 2010-08-22 23:01:52 -04:00
Aparajita FishmanandAlexander Ljungberg ae47ba78cd Use [self respondsToSelector] instead of class_respondsToSelector 2010-08-22 22:06:38 -04:00
Aparajita FishmanandAlexander Ljungberg 2f51358ea0 Added documentation for the excluded mechanism. 2010-08-22 22:06:31 -04:00
Aparajita FishmanandAlexander Ljungberg c91c513b60 Proposed method of excluding themed objects from the theme showcase.
- Also added class_respondsToSelector, it was a no-brainer.

- Cleaned up trailing whitespace in CPThemeBlend.j. Woo-hoo!
2010-08-22 22:06:22 -04:00
Aparajita FishmanandAlexander Ljungberg 189d90da91 Moved theWindow to an ivar so other methods can reference it. 2010-08-22 19:03:15 -04:00
Aparajita FishmanandAlexander Ljungberg 5e20a6d9ef Sending NS_initWithCoder at the right time 2010-08-22 19:03:02 -04:00
Aparajita FishmanandAlexander Ljungberg 05edec8a8b Removed CPButton -setDefaultButton, new version of CPButton after merging with latest master. 2010-08-22 18:53:52 -04:00
Aparajita FishmanandAlexander Ljungberg 75cc0be52a Test app for default button fixes 2010-08-22 18:48:43 -04:00
Alexander Ljungberg a9e59e1e87 Fixed: in the new theme definition the table header sort images were no longer images. This would cause an exception whenever a table header was clicked such that the sort arrows needed to display. 2010-08-22 17:47:52 -04:00
Alexander Ljungberg e766a2c945 Fixed: if a CPAlert message was 3 lines or more and there was no informative text, the upper half of the CPAlert buttons would not react to clicks as the blank informative label partially covered them. 2010-08-21 17:47:03 -04:00
Alexander Ljungberg fbd5a78cf0 Don't make space for CPAlert informative text if there is none. Consider the theme size a minimum size. 2010-08-20 12:41:20 -04:00
Alexander Ljungberg f39c1a2eb8 Try to help the build bot by not calling CPAlert setWindowStyle: in init. 2010-08-20 03:01:37 -04:00
Alexander Ljungberg 5335a611a0 Use Aristo icons for CPAlert. 2010-08-20 01:55:45 -04:00
Alexander Ljungberg c06068c931 Themable CPAlert which automatically grows height-wise to accommodate all text. Adjustable icons, margins, spacing and fonts. 2010-08-19 23:03:35 -04:00
Alexander Ljungberg 62f81f2601 Remove hardcoded Aristo theme from CPAlert. New CPTheme method to get the default HUD theme style, which defaults to the default theme + "-HUD". Clean up CPAlert slightly. 2010-08-19 19:11:52 -04:00
Alexander Ljungberg 077e548219 Manual test for CPAlert which cycles through all 6 possible alert types for visual verification. 2010-08-19 19:08:25 -04:00
Alexander Ljungberg d56bc733ad Remove some accidental globals. 2010-08-18 22:01:18 -04:00
Alexander Ljungberg 8fbd24c861 Moved file globals to the top of the file. Removed a misplaced var. Eliminated empty statements. 2010-08-18 21:32:51 -04:00
Alexander Ljungberg 98049aeb78 Whitespace cleanup. 2010-08-18 17:02:22 -04:00
Aparajita FishmanandAlexander Ljungberg c9718783af Made the new theming mechanism generic (see ecbbe57) 2010-08-18 16:45:45 -04:00
Aparajita FishmanandAlexander Ljungberg bfe01badc1 Radically simplified the whole theming mechanism. Theming can now be done declaratively with less typing, better readability, easier maintenance.
Also fixed some oversights in the existing themes: text was not dimmed in disabled state for segmented controls, text was not dimmed for default buttons in disabled state in HUD (IIRC).
2010-08-18 16:45:38 -04:00
Francisco Ryan Tolmasky I 111ac84a65 Removed unecessary whitespace.
Reviewed by me.
2010-08-17 11:23:50 -07:00
Randall Luecke d7540eea84 if the new proposed selection is empty the tableview should not deselect any rows. 2010-08-17 00:01:33 -05:00
Randall Luecke 88408fc0ea Missed a couple lines in tableview custom drawing because of a merge conflict. 2010-08-16 15:10:29 -05:00
Randall Luecke 6e796d7a22 Fix for endless loop with default buttons. 2010-08-16 15:05:46 -05:00
Randall Luecke f587713795 This was terrible, real fix soon...Revert "Fix for endless loop when changing platform windows."
This reverts commit 66fcba846b.
2010-08-16 14:55:44 -05:00
Randall Luecke 66fcba846b Fix for endless loop when changing platform windows. 2010-08-16 01:26:48 -05:00
Alexander Ljungberg bdf20b0267 Merge branch 'master' of github.com:280north/cappuccino 2010-08-13 20:24:00 -04:00
Alexander Ljungberg 0292203ec0 Test that CPValueTransformerBindingOption works with CPTableColumn bindings. When run the rightmost column should read "right" and "also right" in the two initial rows. 2010-08-13 20:19:45 -04:00
Alexander Ljungberg 112ad65882 Support value transformers in CPTableColumn when using bindings. 2010-08-13 20:19:35 -04:00
Tom Robinson 6bc0880a0d Fix Doxygen executable search logic 2010-08-13 16:48:49 -07:00
Aparajita FishmanandTom Robinson 90a63e1b14 Fixes/enhancements to jake docs:
- We now have class hierarchy information! Don't remove generated headers before doxygen runs so it can generate class hierarchies. Now the headers are cleaned up separately.

- Added inline collapsible class hierarchy diagrams within each class.

- Enabled the built-in search! It's awesome!

- Changed image format to gif, dot is generated invalid png on Mac OS X.

- Explicitly turned off generation of to do and bug list.

- Turned off most warnings, most of them are useless warnings arising from the fact that we are pretending Objective-J is Objective-C.

- Doxyfile format updated to 1.7.1.
2010-08-13 15:42:43 -07:00
Tom Robinson 6ce45d32da Add comparison test for native sorting. 2010-08-13 15:40:33 -07:00
Tom Robinson 4eaf560ee6 Fixes two bugs in compareObjectsUsingDescriptors causing test to fail: extra semi-colon after while() and uninitized "result" variable.
The former masked the latter when a single sort descriptor was used.
2010-08-13 15:34:28 -07:00
Alexander Ljungberg 4c0057e66a Undoing this change since it is no longer necessary due to an alternative solution implemented by Ross Boucher. Revert "Merge commit 'c17a3533ecae63d479b285b23ac3a490ebe8bd3c'"
This reverts commit 039f2ce449, reversing
changes made to 494f39dd86.
2010-08-13 14:39:27 -04:00
Alexander Ljungberg bcb22c7e46 Remove debug output from CPArrayControllerTest. 2010-08-13 14:28:25 -04:00
Alexander Ljungberg 0683b46239 Since issue #795 has not been decided on yet, make CPArrayControllerTest pass without those changes at this time. 2010-08-13 14:18:25 -04:00
Alexander Ljungberg 61ccc39f81 Merge remote branch 'klaaspieter/fix/794-cparraycontroller-preserveselection'
Conflicts:
	Tests/AppKit/CPArrayControllerTest.j
2010-08-13 14:06:35 -04:00
Alexander Ljungberg 533e1a1846 Merge remote branch 'klaaspieter/fix/786-cparraycontroller-removeobject' 2010-08-13 14:01:47 -04:00
Alexander Ljungberg 6afe22f351 Merge remote branch 'klaaspieter/fix/784-cparraycontroller-selection' 2010-08-13 14:00:27 -04:00
Alexander Ljungberg 039f2ce449 Merge commit 'c17a3533ecae63d479b285b23ac3a490ebe8bd3c' 2010-08-13 13:56:21 -04:00
Alexander Ljungberg 494f39dd86 Closes #752. Removed some debug code which snuck in with the merge of fix-752-CPValueTransformerNameBindingOption. 2010-08-12 23:37:53 -04:00
Alexander Ljungberg c851522536 Fixed: if the CPWebView iframe was destroyed before its HTML loader timer fired, an error would occur. 2010-08-12 23:36:25 -04:00
Alexander Ljungberg 9b37ba20a3 Merge remote branch 'klaaspieter/fix-752-CPValueTransformerNameBindingOption' 2010-08-12 22:59:42 -04:00
Alexander Ljungberg 6310bfe084 Merge branch 'master' of github.com:280north/cappuccino 2010-08-12 22:50:09 -04:00
Klaas Pieter AnnemaandAlexander Ljungberg 1a9670ae9c made sure CPViewController calls viewDidLoad if it's view property is set directly 2010-08-12 22:47:59 -04:00
Randall Luecke ee9da8e31e Only call drawRect: is the view is visible. 2010-08-12 16:03:24 -05:00
cacaodevandRandall Luecke 23e9fd927c CPBox: Made CPBezelType the default type instead of none.
Slighly grayed stroke color for bezel type & fillColor for all types to better match cocoa
       Fix contentView autoresizingMask
2010-08-12 15:16:20 -05:00
Randall Luecke 22c481ff27 Implemented allKeysForObject: in CPDictionary with tests. 2010-08-12 14:18:45 -05:00
Randall Luecke 14fb769582 Removed ambiguity in CPDictionary keys type. Closes #700 2010-08-12 13:29:17 -05:00
Randall Luecke da0af13142 Added basic suppport for CPOutlineView in the nib2cib tool
Conflicts:

	AppKit/CPOutlineView.j
2010-08-12 13:11:41 -05:00
Aparajita FishmanandRandall Luecke 44fb4a9b83 -setIntercellSpacing should update the header as well as the table, per Cocoa (and common sense) 2010-08-11 23:21:30 -05:00
Randall Luecke 1e6f6879ff Run CPArrayPerformanceTest with jake test. 2010-08-11 23:17:38 -05:00
Alexander Ljungberg ba33bb56d0 Moved the visual table test for borders into the TableTest folder. 2010-08-12 00:08:43 -04:00
Aparajita FishmanandAlexander Ljungberg ab5e2dd774 Fix for issue #816 (NSTableView/CPTableView do not read selection highlight style and column resizing style) 2010-08-12 00:06:52 -04:00
Aparajita FishmanandAlexander Ljungberg 0b1b1bbe0b Fix for issue #817 (Support for alignment and line break mode in NSTextField/CPTextField) 2010-08-11 23:53:34 -04:00
Alexander Ljungberg 1aebc8942d Merge branch 'master' of github.com:280north/cappuccino 2010-08-11 23:35:26 -04:00
Alexander Ljungberg 233df3bdab Fixed: the "fix for column reordering with hidden columns" sometimes caused the table view to try to remove nonexistent data views and crash. The fix is to consider a nonexistent data view already removed and just move on. 2010-08-11 23:33:21 -04:00
Randall Luecke dd9c085ae3 Fix for new sort being unstable with a huge thanks to Shon Frazier. Reviewed by Me and Alexander Ljungberg. 2010-08-11 22:33:14 -05:00
Alexander Ljungberg 1fed798120 Fixed: CPGraphics.j was not imported anywhere so the CPScrollView borders changes didn't work. Also minor code cleanup. 2010-08-11 23:07:05 -04:00
Aparajita FishmanandAlexander Ljungberg fcf9c0bc84 Full support for all NSScrollView border types, beginnings of a new tableview tester that shows dynamic changing of border type. 2010-08-11 22:49:37 -04:00
Aparajita FishmanandAlexander Ljungberg fd9a753170 Port of NSGraphics 2010-08-11 22:49:31 -04:00
Randall Luecke 2a5f4b98ed Merge branch 'master' of git://github.com/280north/cappuccino 2010-08-11 20:30:17 -05:00
David HessandRandall Luecke ad33d1648c Patch to CPSlider to invert its value in vertical mode so that max value is represented at the top of the track instead of the bottom. 2010-08-11 20:29:46 -05:00
Alexander Ljungberg 1f784f46c7 Merge branch 'master' of github.com:280north/cappuccino 2010-08-11 20:24:29 -04:00
Randall Luecke ed52b44f8b Removed redundent methods in the tableview. Closes #822 2010-08-11 19:07:13 -05:00
Randall Luecke 4b8cc3e6d1 Table column drag view should draw lines the same color as the parent tableview. 2010-08-11 18:39:16 -05:00
Alexander Ljungberg 6b8e10cb2e Whitespace cleanup of CPShadowView. 2010-08-11 19:20:10 -04:00
Aparajita FishmanandAlexander Ljungberg 952bb4bb7c added CPShadow shadowViewEnclosingView 2010-08-11 19:18:52 -04:00
Aparajita FishmanandRandall Luecke a0bcae2404 The Cocoa default is always to draw column lines, this wasn't being set in CPTableColumnView. 2010-08-11 18:16:48 -05:00
Randall Luecke 567f54c9f9 Fix global from error in previous mergre. 2010-08-11 17:32:50 -05:00
Aparajita FishmanandRandall Luecke 66f84ede6e Fix for issue #799 (NSFont replaces LucidaGrande-Bold 13 with the theme font) 2010-08-11 17:16:44 -05:00
Aparajita FishmanandRandall Luecke 5b1ca8a7f9 Fix for issue #807 (NSTextField sets text color unconditionally, which causes theme lookup failure later) 2010-08-11 17:07:51 -05:00
Aparajita FishmanandRandall Luecke 4fc894e430 Fix for issue #820 (horizontal grid drawn incorrectly with no rows) 2010-08-11 16:58:05 -05:00
cacaodevandRandall Luecke 15356b617b DrawRowTest that was announced in the previous commit 2010-08-11 16:32:26 -05:00
cacaodevandRandall Luecke c8f6e12586 CPTableView: Implement -drawRow:clipRect: . The method is called only when a tableview subclass implements it for performance reasons.
DrawRowTest demonstrating the feature.

Conflicts:

	AppKit/CPTableView.j
2010-08-11 16:32:01 -05:00
Randall Luecke 102cc92991 Merge branch 'master' of git://github.com/280north/cappuccino 2010-08-11 16:12:43 -05:00
Randall Luecke 1e490f1796 Fix for column reordering with hidden columns. Closes #637 2010-08-11 15:59:04 -05:00
Aparajita FishmanandAlexander Ljungberg 088a5c7166 Remove extra call to _init in -initWithCoder: 2010-08-11 12:23:47 -04:00
Randall Luecke 5837533678 Use a default TableView. 2010-08-10 20:58:04 -05:00
Randall Luecke 20ec557655 Initial reorganization of CPTableView testing. 2010-08-10 20:53:43 -05:00
cacaodevandRandall Luecke b7d1dfa75f CPArray sorting: improve performance by 40% (JSC) replacing native js sort() with the merge-sort algorithm.
Test with ojunit CPArrayPerformance.j
2010-08-10 18:16:03 -05:00
Randall Luecke 33e4a082d6 Some visual changes to column dragging to make it a bit more like cocoa. 2010-08-09 18:43:11 -05:00
Randall Luecke dd49ef51d5 Merge branch 'master' of git://github.com/280north/cappuccino 2010-08-09 17:37:49 -05:00
Randall Luecke 13b2a886f3 Changed CPRect and CPPoint functions to _CG 2010-08-09 17:36:33 -05:00
Alexander Ljungberg c1dfb315a9 Merge branch 'master' of github.com:280north/cappuccino 2010-08-09 18:31:51 -04:00
Randall Luecke 96958d26c7 Accidental globals. 2010-08-09 17:22:14 -05:00
Alexander Ljungberg 8d635c7a5a Moved ArrayController1 test into the Manual folder. 2010-08-09 18:21:16 -04:00
Aparajita FishmanandAlexander Ljungberg 627c300b4a Switched to using bit mask constants 2010-08-09 18:02:40 -04:00
Aparajita FishmanandAlexander Ljungberg 00812025c2 Fix for issue #818 (NSView does not read hidden flag) 2010-08-09 18:02:32 -04:00
Alexander Ljungberg 0b21b8bab1 Merge branch 'master' of github.com:280north/cappuccino 2010-08-09 17:54:30 -04:00
Alexander Ljungberg 271bb00147 Marginally faster filter and sort in CPArrayController's arrangeObjects (4% in the performance tester.) Reduced memory usage when both a filter and a sort order are applied. Cleanup of the tester and a filter only test run. 2010-08-09 17:31:36 -04:00
Randall Luecke b346d761d8 Fix bug so we can drag items below the last child index in the outlineView. 2010-08-09 14:13:04 -05:00
Randall Luecke 21614e15b2 Draw column header lines by default. 2010-08-09 14:05:58 -05:00
Alexander Ljungberg 998c2f19cf Performance tester for CPArrayController. 2010-08-09 14:21:22 -04:00
cacaodevandAlexander Ljungberg 750cd3c258 CPComparisonPredicate :
Fixed a bug where *lhs custom_selector: nil* was always returning false.
Test nil on left and/or right with some operators.
2010-08-05 16:18:18 -04:00
Alexander Ljungberg df358ccc42 Fix failing CPPredicate unit tests: comment out test for unimplemented expressionForSubquery, finish CPExpression_unionset and fix typo in CPExpression expressionForIntersectSet. 2010-08-04 21:27:01 -04:00
Alexander Ljungberg 1b5efdfc5b Fixed with CPPredicate tests: [CPArray arrayWithObjects] don't take a final nil anymore in Cappuccino. 2010-08-04 20:50:55 -04:00
Alexander Ljungberg 63dfb8a227 CPPredicate optimization: early out in failing AND expression. 2010-08-04 20:50:36 -04:00
Alexander Ljungberg a3c0590218 Fixed with CPPredicate: [CPArray arrayWithObjects:...] should no longer be terminated with a nil in Cappuccino. 2010-08-04 20:50:07 -04:00
cacaodevandAlexander Ljungberg c694c96a32 CPPredicate & co style cleaning 2010-08-04 20:45:06 -04:00
Alexander Ljungberg 30bc304a20 Whitespace and style fixes. 2010-08-04 20:23:35 -04:00
cacaodevandAlexander Ljungberg 974cf64e1d CPPredicate &al implementation. OJUnit test. 2010-08-04 19:53:44 -04:00
cacaodevandAlexander Ljungberg fce726a031 CPScanner implementation 2010-08-04 19:48:51 -04:00
cacaodevandAlexander Ljungberg 7187ba3074 CPCharacterSet implementation 2010-08-04 19:48:27 -04:00
cacaodevandAlexander Ljungberg bfbf8fb841 Support for diacritics aware strings comparison 2010-08-04 19:48:06 -04:00
Alexander Ljungberg 4ea0d4d043 CPNull is equal to CPNull. Unit test included. 2010-08-04 16:43:04 -04:00
Alexander Ljungberg 8c13204afa Save some memory and time in CPTableViewFirstColumnOnlyAutoresizingStyle mode. 2010-08-02 23:28:40 -04:00
Alexander Ljungberg e4c79d2101 Closes #809. End editing of a text field if it is disabled or made uneditable. Manual test included. 2010-08-02 23:13:06 -04:00
Randall Luecke 90a45dca29 some fixes to default buttons to make them more cocoa compliant... 2010-08-01 20:19:26 -05:00
Alexander Ljungberg bcff25b959 Merge branch 'master' of github.com:280north/cappuccino 2010-08-01 19:15:52 -04:00
Alexander Ljungberg dff6203fb3 Closes #806. Fixed: if a selected row was removed from a table view, the selection remained and would show up again if a new row was later added. 2010-08-01 19:10:22 -04:00
Alexander Ljungberg b4dd6b670b Switch to the standard macros in _resizeAllColumnUniformlyWithOldSize as originally intended by Randy Luecke. 2010-08-01 19:06:57 -04:00
Randall Luecke f028533c07 Removed gradient stuff that has been moved to the theme. 2010-08-01 17:50:19 -05:00
Alexander Ljungberg dac61a14cd Eliminated some accidental globals in uniform table column resizing. 2010-08-01 18:10:27 -04:00
Alexander Ljungberg 6884f93d76 Fixed: after the intercell spacing commit, table column auto resizing on the first or last column would result in a total column width wider than the scroll width of the table. This would appear as the rightmost column sticking out and the table showing a horizontal scrollbar. 2010-08-01 18:06:18 -04:00
Alexander Ljungberg 17cc77e816 Clean up code in table column resizing paths in preparation for fixing it. 2010-08-01 17:14:59 -04:00
Randall Luecke 7ac59dd142 Sheets should be assigned to the platform window of the window it is attached to. 2010-07-31 20:20:18 -05:00
Alexander Ljungberg c277ae7f68 Fixed: calling CPTabView setTabViewType:CPNoTabsNoBorder before the first insertTabViewItem would cause an error. Fixed: if a tab item was added in CPNoTabsNoBorder mode, and the mode was later switched to CPTopTabsBezelBorder, that previously added tab item would have no label/tab. The solution is to maintain _labelsView in either mode; since in CPNoTabsNoBorder mode _labelsView is not in the view hierarchy anyhow the performance impact should be minimal. 2010-07-30 21:03:00 -04:00
Alexander Ljungberg 7c78753865 Fixed with CPTabView: don't remove the content and auxiliary views if the new views are the same as the old ones. This prevents flickering and needless redraws when the currently selected tab is reselected. 2010-07-30 21:02:50 -04:00
Alexander Ljungberg 9fc07ac622 Implemented NSView viewDidHide and viewDidUnhide. 2010-07-30 20:52:26 -04:00
Aparajita FishmanandRoss Boucher 364a11491d Full support for intercell spacing (issue #797) 2010-07-30 16:14:53 -07:00
Aparajita FishmanandRoss Boucher 0a26288d88 Fix for issue #804 (doxygen fails to generate class references), also did a bit of formatting cleanup in CPColor.j 2010-07-30 15:48:06 -07:00
Aparajita FishmanandRoss Boucher dcfb916d30 Fix for issue #803 (jake docs doesn't use Doxygen.app on Mac OS X) 2010-07-30 15:47:56 -07:00
Alexander Ljungberg d1c7dab356 If a CPSplitView view is collapsed through means of double click and then later restored in the same manner, preserve the original position of the divider. If the view was collapsed through dragging, double clicking to expand still positions the divider in the center of its available space. 2010-07-29 23:23:00 -04:00
Alexander Ljungberg 0e5b5c844c Split view cursor improvements. If a split view divider is at its minimum position but a collapse is possible, show that a smaller size is possible through the cursor. If a split view has a collapsed view and the cursor moves over the divider, show a 'larger size is possible' cursor. 2010-07-29 23:22:45 -04:00
Aparajita FishmanandRoss Boucher 3eea14abe4 For the methods that don't have context: in their signature, the predicate will receive undefined in the context parameter instead of nil. 2010-07-29 14:08:04 -07:00
Ross Boucher a7ca917abf Better method of expressing this condition. 2010-07-29 11:26:13 -07:00
Aparajita FishmanandRoss Boucher 9ca80df67a Cleaned up the state indicator (it was a little uneven) and centered it more horizontally in the state column. 2010-07-29 11:24:06 -07:00
Aparajita FishmanandRoss Boucher 48a89fd828 frame parameter is not being used in _initWithFrame, might as well leave it out, fixed typo in comment 2010-07-29 09:56:55 -07:00
Aparajita FishmanandRoss Boucher 1002f80617 Another fix for issue #782, uses class variable for the empty image placeholder. 2010-07-28 16:27:56 -07:00
Aparajita FishmanandRoss Boucher fc51bead8e Another try at fixing issue #782 2010-07-28 16:27:56 -07:00
Francisco Ryan Tolmasky I cea663f4eb Fix for isEqual: not being implemented in CPIndexSet.
Closes #785.

Reviewed by rossco.
2010-07-28 16:17:54 -07:00
Aparajita FishmanandRoss Boucher 8ecac8d03c Fix and test case for issue #746 2010-07-28 16:12:02 -07:00
Ross Boucher f26d2f4ebf Merge remote branch 'klaaspieter/fix-751-cpwindow-center' 2010-07-28 16:03:48 -07:00
Aparajita FishmanandRoss Boucher cb7f60aba8 Added -indexOfObjectPassingTest: and related methods 2010-07-28 15:57:47 -07:00
Ross Boucher b4dbe422ff Revert to addObject if there are no sort descriptors in insert...sortedby.
Closes #764.
2010-07-28 15:48:25 -07:00
AndreasandRoss Boucher aea19c5cd0 Add modal stylemask in nib2cib 2010-07-28 15:33:45 -07:00
Aparajita FishmanandRoss Boucher edc5542ee6 Fix for issue #748 2010-07-28 15:24:37 -07:00
Aparajita FishmanandRoss Boucher eb99b7d7ca CPSearchField fixes/enhancements to commit 5b763928fe:
- Added more documentation for -defaultSearchTemplate.

- Capitalized the text of the menu items in the default template.

- Adding a separator before no recents menu item if there are items before it.

- Updated the test app to use the default template and then modify it.

- Updated the test app to maintain the state of the custom items.
2010-07-28 15:16:04 -07:00
Aparajita FishmanandRoss Boucher 006f709d37 Fixes to commit 69273259a5:
- No longer setting the search menu template to the default, but -defaultSearchMenuTemplate was made public.

- Action and target for clear recents item is always set to CPSearchField -_searchFieldClearRecents: since that is a built-in type.

- Action and target for recents item is always set to CPSearchField -_searchFieldSearch: since that is a built-in type.

- Template menu items are copied via CPMenuItem -copy (which is now implemented), so all state is maintained.
2010-07-28 15:15:47 -07:00
Ross Boucher f5322b39bc Fix a debug mode bug in IE. Closes #768. 2010-07-28 15:13:21 -07:00
Aparajita FishmanandRoss Boucher 8702b1421f Fix for issue #777, also fixed a declared type while I was at it 2010-07-28 15:09:02 -07:00
Nicholas Small 3070634aab Make -center on a bridge window into a no-op. 2010-07-28 18:06:08 -04:00
Nicholas Small b65041a780 Merge branch 'master' of github.com:280north/cappuccino 2010-07-28 18:05:23 -04:00
Aparajita FishmanandRoss Boucher 6426c8aee2 Fix for issue #778 2010-07-28 15:04:40 -07:00
Nicholas Small 16b6753f1d Merge branch 'master' of github.com:280north/cappuccino 2010-07-28 18:03:12 -04:00
Nicholas Small b96db40e3d Merge branch 'master' of github.com:280north/cappuccino 2010-07-28 17:56:45 -04:00
Ross Boucher 7caf5fe20a Must return from this method. 2010-07-28 14:54:07 -07:00
Aparajita FishmanandRoss Boucher 44a958d3f8 -hitTest was always returning self, which did not allow any other views to receive a mouse down 2010-07-28 14:53:13 -07:00
Aparajita FishmanandRoss Boucher 4c562048dc More fixes to CPSearchField (Cocoa compliance and bugs):
- Added the ability to specify a separator in the template by using the tag CPSearchFieldSeparatorMenuItemTag.
- _recentSearches was not being initialized by -initWithCoder, moved that code into -_init.
- -setSearchMenuTemplate was not being invoked. Since having a recents menu is the default behavior in Cocoa, it should probably be the default behavior in cappuccino. To turn it off, set _maximumRecents to >= 254.
- -searchTextRectForBounds was using the wrong rect for -searchButtonRectForBounds and -cancelButtonRectForBounds, resulting in a rect that was too narrow and did not fill the space.
- Tightened up the spacing between the magnifying glass and the text to exactly Cocoa distance.
- Overhauled -
updateSearchMenu to fix some logic bugs.
- Made sure the search field becomes first responder after closing the search menu.
- Cleared the search string when clearing recent searches, this is what Safari does.
- Removed redundant invoking of -setDelegate in -initWithCoder.
- -_init has to be called last in _initWithCoder.
2010-07-28 14:53:04 -07:00
Aparajita FishmanandRoss Boucher f3b92c7445 Fixes to cacaodev/searchfield/ffb8f99603d96b903b6bb39bc4dcb15ad09465be...
- Replaced CG functions with inline _CG functions
- _canResignFirstResponder was not being initialized to YES
- -resignFirstResponder has to call super if _canResignFirstResponder == YES
2010-07-28 14:51:57 -07:00
cacaodevandRoss Boucher 675e9829bd CPSearchField: Fixes (per cocoa)
- Do not override search button action, catch mouse events in mouseDown: instead.
- Do not resign first responder on searchfield when showing the context menu
- Give more space between search button and insertion point
- Do not add search string to recents searches when typing and sendsWholeString == NO, only on enter.
- Select all text when showing the menu or after selecting a recent search in the menu
- Support custom search/cancel buttons and custom layout
- Allow images in template menu items
- Updated Test App with custom buttons
2010-07-28 14:49:02 -07:00
Ross Boucher 4c0dbda558 Merge remote branch 'klaaspieter/fix/789-observeablearray-removeobjectatindex' 2010-07-28 14:22:14 -07:00
Ross Boucher e586273a3f Fix accidental global. 2010-07-28 14:13:12 -07:00
Ross Boucher d4a0f0cd21 Merge remote branch 'klaaspieter/fix/787-cptablecolumn-editability' 2010-07-28 14:12:49 -07:00
Klaas Pieter AnnemaandRoss Boucher 8cfba4c242 only offset a nib2cib'ed textfield if it has a bezel 2010-07-28 14:09:11 -07:00
Aparajita FishmanandRoss Boucher cce13b4b45 NSMenuItem is not reading the tag for some reason 2010-07-28 14:07:45 -07:00
Alexander LjungbergandRoss Boucher 05e435633f Fixed: if a custom CPTableView header view was used for a column, such as a CPImageView, sorting by that column would cause an exception as CPTableView tried to send _setIndicatorImage: to the view. The fix is to only send the message if the view supports it. 2010-07-28 13:57:49 -07:00
Mike FellowsandRoss Boucher 6ff3fa0e52 Fix for issue #769, allow ctrl/cmd keys and F1-F12 keys to propagate to the browser unless they are blacklisted 2010-07-28 13:52:01 -07:00
Aparajita FishmanandRoss Boucher c3c996f1f7 Don't substitute the font if the textfield is not editable (a label) 2010-07-28 13:50:52 -07:00
Klaas Pieter Annema ff98a9be5a fix preserve selection in removeObjects and added unit test 2010-07-28 15:02:48 +02:00
Klaas Pieter Annema 96cef81267 Merge branch 'master' of git://github.com/280north/cappuccino 2010-07-28 13:29:16 +02:00
Klaas Pieter Annema 75ceeffab8 remove commented code from CPArrayControllerTest 2010-07-28 13:28:53 +02:00
Klaas Pieter Annema 71fffb6b68 Merge branch 'master' of git://github.com/280north/cappuccino into cparraycontroller-removeobject 2010-07-27 09:47:28 +02:00
Klaas Pieter Annema e066228015 Merge branch 'cpindexset-isequal' into arraycontroller-fixes 2010-07-27 09:23:00 +02:00
Klaas Pieter Annema 48a5d55af7 fix CPArrayController selectPrevious: and selectNext:
Also added unit-tests for canSelectPrevious, canSelectNext, selectPrevious: and selectNext:
2010-07-27 09:10:41 +02:00
Klaas Pieter Annema b9c2becd3e implement CPIndexSet isEqual: 2010-07-27 09:09:59 +02:00
Klaas Pieter Annema 24f72c0b73 Merge branch 'master' of git://github.com/280north/cappuccino into arraycontroller-fixes 2010-07-27 08:47:14 +02:00
Klaas Pieter AnnemaandRoss Boucher 90e9b86497 match CPTableView's alternating row colors with Aristo's 2010-07-26 22:48:58 -07:00
Klaas Pieter AnnemaandRoss Boucher 560ea75a25 added CPArrayController to AppKit.j 2010-07-26 22:48:40 -07:00
Klaas Pieter AnnemaandRoss Boucher 78fd972312 only reverse set the binding on end editing 2010-07-26 22:48:40 -07:00
Klaas Pieter AnnemaandRoss Boucher d947c849c8 made _accessorForKey slightly faster by inlining it as a function 2010-07-26 22:48:40 -07:00
Klaas Pieter AnnemaandRoss Boucher 8ce63a244c store accessors in a javascript object not a CPDictionary, for slight performance improvement 2010-07-26 22:48:39 -07:00
Klaas Pieter AnnemaandRoss Boucher 0306c35b54 don't copy the selection indexes in setContent: 2010-07-26 22:48:39 -07:00
Klaas Pieter AnnemaandRoss Boucher ff8e5ae42e save _replacedKeys on the class in stead of the object instance
reviewed: Ross
2010-07-26 22:48:39 -07:00
Klaas Pieter Annema acf5e5b75f call super in _CPObservableArray removeObjectAtIndex:
The current implementation calls self, which causes an infinite loop
2010-07-26 18:44:50 +02:00
Klaas Pieter Annema 4f946f267e fix CPArrayController removeObject:
removeObject: only shifted the selection, it never actually removes the object
2010-07-26 18:44:00 +02:00
Klaas Pieter Annema abfe2b4be6 Merge branch 'master' of git://github.com/280north/cappuccino 2010-07-26 16:23:28 +02:00
Klaas Pieter Annema bb3c08ce0b add CPArrayController test 2010-07-26 14:04:26 +02:00
Klaas Pieter Annema 138888e620 implement CPArrayController insertObject:atArrangedObjectIndex: 2010-07-26 14:04:05 +02:00
Nicholas Small 4e1b429913 Merge branch 'master' of github.com:280north/cappuccino 2010-07-22 15:41:28 -04:00
Randall Luecke 51f780b5f5 Merge branch 'master' of github.com:280north/cappuccino 2010-07-22 00:21:51 -05:00
Randall Luecke cffbf86351 TableView theming 2010-07-22 00:21:02 -05:00
Ross Boucher 709a9b3c61 Merge remote branch 'klaaspieter/fix-758-cpdate-isequal' 2010-07-21 15:04:10 -07:00
Ross Boucher c35621b669 Merge remote branch 'klaaspieter/fix-756-cpstring-isequal' 2010-07-21 15:03:43 -07:00
Alexander LjungbergandRoss Boucher 4d1baac4db Fixed: first clearing a \r keqyEquivalent from one button and then setting it on another would result in an exception. 2010-07-21 14:57:52 -07:00
Alexander LjungbergandRoss Boucher 474623feb3 Added support for punctuation based key equivalents such as Cmd-' or Cmd-;. Fixed: [event characters] would contain Þ when Cmd-' was pressed and º for Cmd-; since the key codes for punctuation do not match the ASCII codes and String.fromCharCode does not work. Manual test included. 2010-07-21 14:52:05 -07:00
Klaas Pieter Annema c17a3533ec fix #764
Array controller inserts object in wrong arranged object position if there are no sort descriptors defined
2010-07-20 14:59:18 +02:00
Ross Boucher 85f3691432 Don't add a "Shift" if it's not required. 2010-07-19 16:27:44 -07:00
Klaas Pieter Annema 2ae8d25d18 don't use === for date equality checking
Apparently this will return false for equal dates, reverted the actual equality check to what was already in Cappuccino before my fix !(date < otherDate || date > otherDate)
2010-07-19 13:10:15 +02:00
Nicholas Small 780bdc4421 Generate accessors for _CPSegmentInfo. 2010-07-18 03:05:31 -04:00
Randall Luecke a2e6f8f964 Initial theming of TableView header. 2010-07-15 22:32:00 -05:00
Klaas Pieter Annema 564668587c fix CPDate isEqual: and isEqualToDate: 2010-07-15 14:42:48 +02:00
Klaas Pieter Annema 023cf46041 check for nil in CPString isEqual: 2010-07-15 14:39:24 +02:00
Klaas Pieter Annema 36bb41a945 implemented isEqual: on CPString 2010-07-15 12:49:52 +02:00
Randall Luecke 0cbdb3b2d1 Fix for redrawing issues in tableview. Closes #627 2010-07-12 21:14:48 -05:00
Randall Luecke 70f2d86b58 Fixes for adding and removing columns to the tableview after the tableview has already been displayed... There are still issues though. 2010-07-12 20:45:30 -05:00
Klaas Pieter Annema 914175de70 If CPValueTransformerNameBindingOption contains an existing class, allocate and use it in CPKeyValueBinding 2010-07-12 15:41:00 +02:00
Randall Luecke 7696b30067 Added tests for CPFormatter and Foundation import. 2010-07-11 16:57:17 -05:00
Klaas Pieter Annema 478b5eaba3 make sure CPWindow center never puts it's window origin at a negative coordinate 2010-07-09 12:46:54 +02:00
Klaas Pieter Annema 52f0c0f587 Merge branch 'master' of git://github.com/280north/cappuccino 2010-07-08 16:27:15 +02:00
Randall Luecke 2a4d3507b8 Implementation fix for CPFormatter to conform to documentation. 2010-07-07 19:49:16 -05:00
Randall Luecke 78a75924de selectedRowIndexes should return a copy, closes #605 2010-07-07 16:46:48 -05:00
Randall Luecke a34dfee752 CPFormatter implementation. 2010-07-06 22:43:30 -05:00
Randall Luecke 5ca9b4f370 Merge branch 'master' of git://github.com/280north/cappuccino 2010-07-06 22:43:15 -05:00
Randall Luecke 2a2b320be3 Added image support for overflow toolbaritems. Also disabled the menu items if the toolbar is disabled. 2010-07-06 22:37:58 -05:00
Nicholas Small 071ab7d555 Only use CPView -display* methods while in DOM. 2010-07-02 14:58:23 -04:00
Klaas Pieter Annema 9738bbfbe5 Merge branch 'master' of git://github.com/280north/cappuccino 2010-07-02 09:25:27 +02:00
Nicholas Small e385321f95 CPArrayController -selectedObjects returns a CPObservableArray. 2010-06-30 22:28:02 -04:00
Nicholas Small 21a9ae4c45 Make CPTableView work with selectionIndexes binding. 2010-06-30 12:03:03 -04:00
Nicholas Small 6a689dc3df Fix for asking the wrong object for -_replacementKeyPathForBinding: when creating a new binding. 2010-06-30 12:00:20 -04:00
Klaas Pieter Annema af0ca52739 made CPViewController equal cappuccino master 2010-06-30 11:50:53 +02:00
Klaas Pieter Annema 83ea50a836 don't send windowWillLoad and windowDidLoad if the window is not loaded from cib 2010-06-30 11:41:22 +02:00
Klaas Pieter Annema 2022eb5c12 Merge branch 'master' of git://github.com/280north/cappuccino 2010-06-30 11:19:23 +02:00
Klaas Pieter Annema 6b132c4d3b added check for nil in CPIndexSet isEqual 2010-06-30 11:15:38 +02:00
Nicholas Small f34775b038 CPAttributedString should not call its own -beginEditing or -endEditing. 2010-06-29 14:02:37 -04:00
Klaas Pieter Annema f73d8a55de implemented isEditable nib2cib support for CPTableColumn 2010-06-29 17:47:36 +02:00
Klaas Pieter Annema 3d39bf8720 Merge branch 'master' of git://github.com/280north/cappuccino 2010-06-29 11:27:33 +02:00
Randall Luecke 9a302328c6 Move the new close button a little to the right to confrom with the Aristo art. 2010-06-26 23:35:33 -05:00
Randall Luecke cdb1ac32fa Use the new Aristo HUD window art. 2010-06-26 23:22:24 -05:00
Alexander LjungbergandRandall Luecke 74af0dc93a Fixed: Shift + Arrow Keys in allowsMultipleSelection CPTableViews did not expand the selection anymore after the recent key binding updates. 2010-06-26 00:10:30 -05:00
Alexander LjungbergandRandall Luecke 2da1dc31fb Simplify CPCollectionView keyboard selection code, eliminate some redundancy. 2010-06-26 00:10:21 -05:00
Alexander LjungbergandRandall Luecke 6b55c81462 Fixed: Shift + Arrow Keys in allowsMultipleSelection CPCollectionViews did not expand the selection anymore after the recent key binding updates. 2010-06-26 00:10:12 -05:00
Alexander LjungbergandRandall Luecke 07630964c1 Reverse bindings support for CPCollectionView selectionIndexes. This enables binding a CPCollectionView's selectionIndexes to a CPArrayController. 2010-06-26 00:09:54 -05:00
AndreasandRoss Boucher a6b7d456f4 Add isLoaded to CFBundle and CPBundle 2010-06-23 20:11:05 -07:00
Ross Boucher 7c5a07f709 Fix the issue where CPSecureTextField would sometimes cause all other text fields to go crazy afterwards. 2010-06-23 19:58:43 -07:00
Ross Boucher 7e25166ce1 Revert the fixed frame size assumption for now. 2010-06-23 19:13:56 -07:00
Klaas Pieter Annema 10df31cbf9 made isEqual: work on CPIndexSet and updated unit tests 2010-06-22 07:47:30 +02:00
Randall Luecke 10c067e44f When dragging over a tableview row we should jump to the next row at the bottom 30% of the row, not 50%... otherwise it gets really really bad with large row heights. 2010-06-21 22:32:18 -05:00
Scott KyleandRoss Boucher f81e97726a Fixed setName: in CPImage to return BOOL as in Cocoa 2010-06-21 13:23:27 -07:00
nciagra 8f040d6ff1 Fixed a couple of Unix key bindings. 2010-06-21 13:53:17 -04:00
Alexander LjungbergandRoss Boucher 32fb13a9a9 Fixed: long titles in CPAlert buttons would be cut off. Fix is to use the standard 80 pixels width as a minimum width only. 2010-06-19 18:26:19 -07:00
Alexander LjungbergandRoss Boucher 4b86115d30 Set the alert default button using the CPCarriageReturnCharacter key equivalent to match the recent Cappuccino change for default buttons. 2010-06-19 15:42:29 -07:00
Alexander LjungbergandRoss Boucher 12a49d0ee1 CPAlert informative text support. 2010-06-19 15:41:15 -07:00
nciagra b37f5b4143 Fix CPResponderTest. 2010-06-18 14:18:29 -04:00
nciagra cbb9602f9e Better caching of key bindings. 2010-06-18 11:50:33 -04:00
nciagra 997a305d35 Added CPKeyBinding for a dynamic key binding system. 2010-06-18 10:40:15 -04:00
nciagra f09193ce07 Properly differentiate between special keys and normal keys in key handlers. 2010-06-17 00:17:52 -04:00
nciagra 96fc34c00e CPResponder -interpretKeyEvents: will only call -insertText: if the Command and Control keys are not being held. 2010-06-16 22:03:31 -04:00
nciagra bd06b8a867 Modifier keys will fire flagsChanged: instead of keyDown: and keyUp:, like Cocoa does. 2010-06-16 22:02:40 -04:00
Randall Luecke 7414d1407f Moved tracking of last selected row index to selectRowIndexes: in tableview. 2010-06-16 13:59:25 -05:00
Ross Boucher 19d5431f60 Revert "slightly delay triggering the action in CPControl performClick: to make sure the click is always visible"
This reverts commit eaf4fa240f.
2010-06-16 08:54:30 -07:00
Alexander LjungbergandRoss Boucher f2c01cbbbd In CPUndoManager, handle the edge cases if an object changes from being an Objective-J object to being just a JS object. Also handle the case where an Objective-J object could theoretically compare equal to nil - CPNull isEqual:. 2010-06-16 08:50:42 -07:00
Alexander LjungbergandRoss Boucher c807358216 Support non Objective-J objects in CPUndoManager's no-op check for auto undo. 2010-06-16 08:50:34 -07:00
Alexander LjungbergandRoss Boucher 685c3c9853 Don't add no-ops to the undo stack when using automatic undo manager mode. This is necessary when used together with bindings since controls issue reverse binding updates whenever editing ends, which would add a 'do nothing' undo entry on the stack in cases where nothing changed. 2010-06-16 08:50:27 -07:00
Alexander LjungbergandRoss Boucher db3514a2c1 Only allow a single window frame animation at a time; stop the previous animation before starting a new one. This allows e.g. a sheet animating open to 'turn around' and animate right back out. Fixed: if a sheet was closed before it finished animating open, for example by hitting a keyboard equivalent immediately, CPWindow would crash with "Uncaught TypeError: Cannot read property 'sheet' of null". 2010-06-16 08:46:54 -07:00
Aparajita FishmanandRoss Boucher 6a43c544eb Added support for reading max rows/columns from cib 2010-06-16 08:32:14 -07:00
Ross Boucher 1b174b86ca Buttons should also be re-centered after their height is changed in nib2cib. 2010-06-16 08:14:04 -07:00
Klaas Pieter Annema f40fc321fe Make the window perform it's defaults button's key equivalent after the default keyDown messages are handled 2010-06-16 14:17:58 +02:00
Klaas Pieter Annema eaf4fa240f slightly delay triggering the action in CPControl performClick: to make sure the click is always visible 2010-06-16 14:16:17 +02:00
Ross Boucher 17a8be1ae6 Return the actually last selected row in CPTableView.
Closes 716.
2010-06-15 19:20:48 -07:00
Aparajita FishmanandRoss Boucher 16be03b162 If first segment is enabled and mode is one-only, _selectedSegment is correctly set to 0 2010-06-15 19:11:31 -07:00
Ross Boucher 2f58517ce5 Request headers should be set after the request is re-opened. Closes #701. 2010-06-15 09:29:04 -07:00
Francisco Ryan Tolmasky I 9a3c2d5311 Fix for scrolling affecting background windows with NativeHost.
Reviewed by me.
2010-06-12 18:33:59 -07:00
Ross Boucher fed39694f6 Improve the handling of key window's losing their status. 2010-06-12 18:23:51 -07:00
Stephen Ierodiaconou c10b06e29b Merge branch 'master' of git://github.com/280north/cappuccino into CPDecimalNumber 2010-06-13 00:03:13 +03:00
Alexander LjungbergandRoss Boucher 5c5412db67 Make didChangeValueForKey work even if willChangeValueForKey was not called. 2010-06-11 14:08:07 -07:00
Alexander LjungbergandRoss Boucher 1c35bd22f8 Don't test keyCodes directly in CPResponder now that we have proper key equivalent characters. 2010-06-11 12:05:31 -07:00
Alexander LjungbergandRoss Boucher c28222e04d Test CPResponder's interpretKeyEvents in preparation for rewrite. 2010-06-11 12:05:23 -07:00
Alexander LjungbergandRoss Boucher 854481e395 Fixes #710. Treat \r and \n key equivalents as the same key (return). 2010-06-11 10:19:07 -07:00
Alexander LjungbergandRoss Boucher 44555ac724 UTF compatible CFData base64 string encoder and decoder. Use it for CPButton key equivalent archiving. Also ordered CPText.j constants by value and removed the empty CPText class definition as it caused errors with nib2cib. Fixed: the key equivalent for forward delete (CPDeleteFunctionKey, \uF728) was transformed to '(' (\u0028) when archived and unarchived. 2010-06-11 09:39:19 -07:00
Alexander LjungbergandRoss Boucher dcec14decd Fixed: delete (backspace) and forward delete were switched as compared to Cocoa. Fixed: delete could not be used as a key equivalent without a modifier. 2010-06-11 09:37:47 -07:00
Randall Luecke f62d81e79f Fix for nib2cib breaking with an emptry class implementation. 2010-06-10 22:37:52 -05:00
Derek HammerandRandall Luecke 9ff056f073 Making the DisclosureButton a little more subtle. Adding shadow to the disclosure buttons. 2010-06-10 18:21:51 -05:00
Ross Boucher 1edb0bcc4a Fix for null key equivalents. 2010-06-10 16:14:22 -07:00
Scott KyleandRandall Luecke 1899250a53 Semicolons are nice... 2010-06-10 16:42:28 -05:00
Scott KyleandRandall Luecke 443e23e348 Without the commas, these create global variables 2010-06-10 16:42:19 -05:00
Ross Boucher 1e6595fca7 Slight switch statement change so that nil/0 are treated equivalently. 2010-06-10 13:29:47 -07:00
Alexander LjungbergandRoss Boucher 5ed475eedd Slightly faster _couldBeKeyEquivalent (1% of runtime in 3000 calls). Performance test included. 2010-06-10 10:57:42 -07:00
Alexander LjungbergandRoss Boucher 17669fd09d Optimized _triggersKeyEquivalent for a 6.5% performance gain in the CPKeyEquivalentPerformance test. 2010-06-10 10:56:02 -07:00
Alexander LjungbergandRoss Boucher 51825db716 Fixed: [CPDate description] did not generate a correct date for users in timezones with a negative timezone offset. 2010-06-10 10:49:49 -07:00
Ross Boucher 421ae6b316 Make CPButton archive its key equivalents, and make nib2cib support the feature. 2010-06-10 10:41:15 -07:00
Aparajita FishmanandRoss Boucher 9ab446b790 Added image alignment support to CPImageView, CPWindowController always loads a cib from the main bundle for consistency with Cocoa, CPApplication modified to explicitly load the About panel cib from the Framework bundle 2010-06-09 14:24:00 -07:00
Ross Boucher c65e3d4e6d Move the bindings test to the manual folder. 2010-06-09 14:23:27 -07:00
Ross Boucher 10fad00c1e Merge remote branch 'aljungberg/keyequivalents-merge' 2010-06-09 13:42:57 -07:00
Tom Robinson 478f2d8134 Name Objective-J allocators to get correct WebKit heap snapshot reports. 2010-06-09 13:16:45 -07:00
Thomas InghamandRoss Boucher a49b01d396 Added missing asset. 2010-06-08 19:29:11 -07:00
Alexander Ljungberg c26ebe0bd2 Added support for menu key equivalents such as Escape or Cmd-Delete. Refactored code to recognize key equivalents for reuse between CPMenu and CPButton. Added unit tests for CPMenu key equivalents. 2010-06-07 19:09:15 -04:00
Alexander Ljungberg 381a44148e Special keys such as backspace and escape can now be used as key equivalents through checking for their unicode representations in [CPEvent characters]. This replaces the earlier raw key code approach. 2010-06-07 19:09:10 -04:00
Alexander Ljungberg c1f16de441 Defined function and special key constants. 2010-06-07 19:09:01 -04:00
Alexander Ljungberg 4a048657c5 If a button is named "Cancel" in a CPAlert window, give it the 'escape' key equivalent. 2010-06-07 19:08:50 -04:00
Alexander Ljungberg 44f5086600 Key equivalents for CPButton. 2010-06-07 19:08:44 -04:00
Klaas Pieter Annema ddddc3330d Merge branch 'master' of git://github.com/280north/cappuccino 2010-06-07 11:09:41 +02:00
Randall Luecke 39ba9b9a4f setSeletable now works in CPTextField. Closes #690 2010-06-06 16:26:51 -05:00
Alexander LjungbergandRandall Luecke bdb36f35cf Fixed: the actual delegate method definition somehow didn't make it into the change enabling outlineView:shouldEditTableColumn:item: for outline view inline editing. This commit predefines all CPOutlineView delegate methods. 2010-06-06 16:07:50 -05:00
Ross Boucher 0c9b4da473 Don't supress exceptions in the backtrace decorator, add an exception supressing decarator. 2010-06-06 12:57:45 -07:00
Stephen IerodiaconouandRoss Boucher 935f1084d6 Javascript Date object returns month between 0 and 11 2010-06-06 12:05:11 -07:00
Saikat ChakrabartiandRoss Boucher c8759babae Adding checks for existence of DOM when calling CPPlatformWindow+DOM-only methods
Conflicts:

	AppKit/CPWindow/CPWindow.j
2010-06-06 11:48:15 -07:00
Francisco Ryan Tolmasky I ab3d648244 Fix for browser:acceptDrop:atRow:column:dropOperation: not being called if browser:validateDrop:proposedRow:column:dropOperation: is implemented.
Reviewed by me.
2010-06-04 19:21:43 -07:00
Randall Luecke 57dc0460a3 Fixed theme state for CPBrowser. 2010-06-03 21:09:18 -05:00
Randall Luecke d5ee07fe1b CPControl should not be allowed to performClick: if it's disabled. 2010-06-02 20:43:09 -05:00
Klaas Pieter Annema 89e3618d85 Merge branch 'master' of git://github.com/280north/cappuccino 2010-06-02 15:37:11 +02:00
Randall Luecke 162381a73f Removed worthless variable in the collectionview. 2010-06-01 19:16:02 -05:00
Klaas Pieter Annema 08db857334 Merge branch 'master' of git://github.com/280north/cappuccino 2010-06-01 10:16:11 +02:00
Randall Luecke bb651d0c70 Added multiple selection support to the collectionview. 2010-06-01 01:53:26 -05:00
klaaspieterandRandall Luecke d9c094f644 call tableview doubleclick action even if target is nil (action will travel down the responder chain)
Conflicts:

	AppKit/CPTableView.j
2010-05-31 19:14:54 -05:00
Klaas Pieter Annema 32040bdd7e Merge branch 'tableview-doubleclick'
Conflicts:
	AppKit/CPTableView.j
2010-05-31 15:44:24 +02:00
Klaas Pieter Annema 43f0e43de7 call tableview doubleclick action even if target is nil (action will travel down the responder chain) 2010-05-31 15:41:52 +02:00
Klaas Pieter Annema 5122b15ffb Merge branch 'windowcontroller-loadwindowfix' 2010-05-31 13:48:23 +02:00
Klaas Pieter Annema 468d8e7c33 call windowWillLoad and windowDidLoad if the window is set directly from the initializer 2010-05-31 13:45:51 +02:00
Klaas Pieter Annema 93b1d1e591 Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-31 10:34:52 +02:00
Ross Boucher 1642149228 Missing #include had broken the slider color picker. 2010-05-28 12:45:15 -07:00
Ross Boucher 8fd564b034 Minor cleanup to the current test cases. 2010-05-28 10:54:45 -07:00
Ross Boucher 7c3f94dd87 Merge remote branch 'klaaspieter/bindings-fixes' into bindings
Conflicts:
	AppKit/CPControl.j
	Foundation/CPValueTransformer.j
2010-05-28 10:23:47 -07:00
Klaas Pieter Annema eacd408ce8 Fixed a typo in CPObjectController 2010-05-27 15:23:09 +02:00
Klaas Pieter Annema 084da71420 exposed more bindings on CPControl 2010-05-27 15:22:40 +02:00
Alexander Ljungberg 3fa47ee9ec Fixed: [_CPImageAndTextView setDimsImage] wasn't working right due to checking if a non existent variable equalled the current value. 2010-05-26 20:09:01 -04:00
Alexander Ljungberg e811895570 Fixed: CPObjectController keyPathsForValuesAffectingX typos. 2010-05-26 20:06:32 -04:00
Alexander Ljungberg 47e890b8e1 Fixed table row drag view when using bindings. 2010-05-26 20:02:12 -04:00
Alexander Ljungberg f2bb27dc32 Fixed: [CPArray isEqualToArray:nil] threw an exception instead of returning NO. 2010-05-26 19:54:20 -04:00
Alexander Ljungberg ef9d2d1775 Reverse update value binding when control editing stops, not only when the action fires. This causes tabbing out of a text field to update the binding source. Based on the description of the bindings option NSContinuouslyUpdatesValueBindingOption this is the right thing to do: if NSContinuouslyUpdatesValueBindingOption is on, update on every character; "otherwise the update is made only when the user interface item resigns as the responder." 2010-05-26 19:51:51 -04:00
Alexander Ljungberg be13a14330 Hack to make [textField bind:CPValueBinding ...] work. Without this, any observed change leads to a [textField setValue:X forKey:"value"] which in turn leads to a direct ivar access changing the value in textField._value. This means the text field has no idea the value changed and it doesn't update to show the new text. I'm not sure what the right solution should be here. It looks like _replacementKeyPathForBinding should play into this and change the end result to [textField setValue:X forKey:"objectValue"] which would work fine. But currently _replacementKeyPathForBinding applies to the observed key path, not the bound one. 2010-05-26 19:51:28 -04:00
Alexander Ljungberg 45a2bcb71a Fixed bindings problems where 'nil' would be transformed into @"". Also, CPIsNilTransformerName and its inverse couldn't work because any nil value was immediately returned without transformations being applied. Full complement of unit tests included, based on Cocoa empirical testing.
Fixed with CPKeyValueBinding: the CPValueTransformerNameBindingOption option would cause an exception due a missing import.
2010-05-26 19:50:35 -04:00
Alexander Ljungberg 48fb660e66 The problem with initialize in fb5950c82d0124bdebb6e03cb4509306ef4161c8 turned out to be caused by a Cappuccino bug with class methods and arguments named 'name'. Renaming the argument solved the problem so I reverted the initialize change. This fix also fixes valueTransformerForName. 2010-05-26 19:49:49 -04:00
Alexander Ljungberg 218919a8ba Fixed: exposed bindings on CPObject would not appear in CPObject subclasses. 2010-05-26 19:48:27 -04:00
Alexander Ljungberg 79ed04e403 Fixed: including CPValueTransformer.j causes an infinite loop due to the recent Objective-J (mis?) behavior that every class has to inherit from CPObject. Also, the transformer map failed to initialize properly with the existing setup code for reasons which were not immediately clear. Moving the initialization to a regular + initialize method eliminated the problem.
Fixed: CPKeyValueBinding.j would throw an exception if a named value transformer option was specified, due to CPValueTransformer.j not being imported.
2010-05-26 19:47:45 -04:00
Alexander Ljungberg 3c995fe17b Fixed: the array controller remove method mapped selection indexes to the content array instead of the arranged objects, leading to the wrong objects being removed as filters and sort descriptors were effectively ignored. 2010-05-26 19:45:13 -04:00
Alexander Ljungberg 5ff8ddf5f3 Fewer bindings debug log messages. 2010-05-26 19:44:14 -04:00
Alexander Ljungberg 8b2350fb22 Optimized table data loading when using bindings for the cell values. A special code path in the CPTableColumn's prepareDataView:forRow: method turns a O(n) operation into O(1) where n is the number of items in the model array. 2010-05-26 19:42:59 -04:00
Alexander Ljungberg 15be647c16 Fixed: the CPArrayController code to remove out of bounds selections failed to remove the last selected item if the new arrangedObjects array was empty. 2010-05-26 19:42:40 -04:00
Alexander Ljungberg 8a8af0e4a9 Fixed: CPArrayController could get out of bounds selections if a call to rearrangeObjects caused objects to disappear from the arranged set. 2010-05-26 19:41:34 -04:00
Alexander Ljungberg 4ff89eab04 Fixed: CPArrayController would throw out of bounds exceptions when its content array was shortened and items at the end were selected.
Extended avoid empty selection support so that when the last item is selected and deleted, the (previously) second to last item is selected instead. Works as expected with multiple selections.
2010-05-26 19:40:55 -04:00
Alexander Ljungberg ec032cb739 Performance fix: willChange and didChange for CPArrayController's selectionIndexes were sent doubly. 2010-05-26 19:40:24 -04:00
Alexander Ljungberg 2b287a85e5 CPArrayController now pushes new selections to the bound model for selectionIndexes. Using this, support for selectsInsertedObjects was added.
This commit also fixes a performance problem where calling setSelectionIndexes with a selection equal to the one already active caused a selection update.
2010-05-26 19:39:42 -04:00
Alexander Ljungberg 6ea2b4e0e2 Fixed: the CPArrayController addObject: optimization for fast index updates would never fire with a nil _filterPredicate, causing rearrangeObjects to be called needlessly. 2010-05-26 19:39:09 -04:00
Alexander Ljungberg f7e2e9c2ee Fixed: the _CPObservableArray init method used by CPArrayController did not properly initialize _observationProxies.
Fixed: _CPObservableArray's insertObject:atIndex: caused an infinite loop.
2010-05-26 19:37:28 -04:00
Alexander Ljungberg 5463e5ca55 Fixed: CPArray insertObject:inArraySortedByDescriptors: did not return the index into which the object was inserted. This would have broken CPArrayController's addObject code. 2010-05-26 19:36:26 -04:00
Alexander Ljungberg 396d4218f0 Fixed: CPArrayController keys ContentArray, ArrangedObjects, Selection, SelectionIndex, SelectedObjects, CanRemove and CanSelectNext could not be observed properly because their dependency declarations had a repeated typo. 2010-05-26 19:30:06 -04:00
Alexander Ljungberg e3a07845d4 Implemented CPTableView clickedRow for use in double-action. 2010-05-26 19:24:36 -04:00
Alexander Ljungberg 341a42bddd DataSource delegate method tableView:objectValueForTableColumn:row is optional if bindings are used to provide data for the table view. 2010-05-26 19:20:38 -04:00
Alexander Ljungberg 573444e640 Removed a bindings console.log statement incompatible with browsers without a debug console. 2010-05-26 19:14:03 -04:00
Alexander Ljungberg ed9c6d7959 Added reverse sort tests for CPArray insertObject:inArraySortedByDescriptors:. 2010-05-26 19:11:58 -04:00
Alexander Ljungberg ed2c65dd6f Merge branch 'master' of git://github.com/280north/cappuccino into bindings-merge
Conflicts:
	AppKit/CPTableView.j
	Foundation/CPArray+KVO.j
	Foundation/CPArray.j
2010-05-26 19:05:04 -04:00
cacaodevandRoss Boucher 0062caafdf CPObject -implementsSelector: 2010-05-26 10:06:49 -07:00
Stephen IerodiaconouandRoss Boucher b98f0b1427 Apply style rules to Foundation 2010-05-26 08:53:05 -07:00
Stephen IerodiaconouandRoss Boucher b6a3d2b283 Remove import of deprecated CPLog.j
Remove deprecated CPLog.j
2010-05-26 08:52:59 -07:00
Stephen IerodiaconouandRoss Boucher 0d848e3d93 Add test on self in init of CPAttributedString 2010-05-26 08:52:46 -07:00
Stephen IerodiaconouandRoss Boucher 065197980b CPCoder typo fixes 2010-05-26 08:51:58 -07:00
Thomas InghamandRoss Boucher 2a36488db7 Added new artwork and theme style for the button.
Matching fonts to segctl.
2010-05-26 08:51:36 -07:00
Klaas Pieter Annema 3cd44284c4 - added CPValueTransformer to Foundation.j
- made CPValueTransformer import Foundation objects directly
- gave the build in transformers CPValueTransformer as superclass
2010-05-26 16:46:44 +02:00
Klaas Pieter Annema bc0fa6a62e made removeObject on _CPKVCArray work properly 2010-05-26 16:45:55 +02:00
Klaas Pieter Annema 51c90223fc exposed enabled binding on CPControl and made sure CPControl's bindings are only exposed once 2010-05-26 16:44:55 +02:00
Klaas Pieter Annema df1b56becf Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-26 11:58:49 +02:00
Tom Robinson 5a77c19791 Silence tools output during tests (press, flatten, capp gen) 2010-05-25 16:24:29 -07:00
Tom Robinson eae3270385 Add bcomm hook to LoadTimeTest 2010-05-25 14:09:10 -07:00
Randall Luecke daee101005 Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-25 14:05:24 -05:00
Klaas Pieter AnnemaandRandall Luecke b32d503d65 implemented CPTableColumn isHidden nib2cib support 2010-05-25 14:03:14 -05:00
Klaas Pieter AnnemaandRandall Luecke ca7af88c59 - updated tablecolumn nib2cib to support new row selection theme state
- nib2cibed the MainMenu.xib in the tablecib example to update it's cib to the changes
2010-05-25 14:03:04 -05:00
Klaas Pieter AnnemaandRandall Luecke 6bd8e96ac0 fixed a bug where the table header would attempt to set content inset on a _CPImageAndTextView 2010-05-25 14:02:52 -05:00
Klaas Pieter AnnemaandRandall Luecke d06d69966b used content inset in stead of frame offset to properly place the table header text 2010-05-25 14:02:41 -05:00
Klaas Pieter AnnemaandRandall Luecke 004829ac9e table header view nib2cib updates 2010-05-25 14:02:30 -05:00
Randall Luecke 0009603098 removed the border from _CPCornerView (Aristo)
Conflicts:

	Tests/Manual/TableCibTest/Resources/MainMenu.cib
2010-05-25 14:01:42 -05:00
Klaas Pieter AnnemaandRandall Luecke 5479c77ae6 changed the table header view image height to 23.0 2010-05-25 14:00:46 -05:00
Klaas Pieter AnnemaandRandall Luecke 1f97616f3c override default IB tableview grid colors with aristo's 2010-05-25 14:00:34 -05:00
Klaas Pieter AnnemaandRandall Luecke e65fcdab42 - changed default dataview styling to aristo
- updated nib2cib support for CPTableColumn
2010-05-25 14:00:22 -05:00
Klaas Pieter AnnemaandRandall Luecke 428f5a656d changed default table view alternating row colors to aristo 2010-05-25 14:00:10 -05:00
Klaas Pieter AnnemaandRoss Boucher 0315ad38f9 - fixed CPKeyedUnarchiver decodeBytesForKey attempting to access nil (or undefined) data
- improved CPSearchField nib2cib support
2010-05-25 11:48:03 -07:00
Klaas Pieter AnnemaandRoss Boucher 6c1a6a2033 made _sendPartialString send it's action down the responder chain 2010-05-25 11:47:52 -07:00
Klaas Pieter AnnemaandRoss Boucher 2a630a7210 made CPDictionary call [super valueForKey:] on keys prefixed with @ 2010-05-25 11:40:45 -07:00
Klaas Pieter Annema 528203d8e5 made CPDictionary call [super valueForKey:] on keys prefixed with @ 2010-05-25 20:37:00 +02:00
Klaas Pieter Annema fd5a0cc468 Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-25 11:23:18 +02:00
Randall Luecke 359a29874b Return a copy instead of the array itself. 2010-05-24 22:44:14 -05:00
Randall Luecke f9da7f73b3 Added missing pathComponents method to CPURL. 2010-05-24 21:59:37 -05:00
Alexander LjungbergandFrancisco Ryan Tolmasky I 49ae82d96a Fixed: CPToolbar validateVisibleItems was called validateVisibleToolbarItems. 2010-05-24 15:53:12 -07:00
Francisco Ryan Tolmasky I fbd23fb2c3 Removed unecessary var.
Reviewed by me.
2010-05-24 15:45:54 -07:00
Paul BaumgartandFrancisco Ryan Tolmasky I 252b258159 fix CFDictionary.containsValue and CFDictionary.countOfValue and add tests to prove it 2010-05-24 15:45:21 -07:00
Alexander LjungbergandFrancisco Ryan Tolmasky I dfcef3ca2d Fixed: [CPPopUpButton itemTitles] didn't work. 2010-05-24 15:45:07 -07:00
Thomas InghamandRoss Boucher 3d4a33d373 Re-preflight on the image assets resulting in 24px tall images in each case. This is done by cutting the top edge close (well into the aliased edge on top.)
Added defs for the horizontal and vertical sliders.
2010-05-24 15:31:04 -07:00
Ross Boucher 28397e672e fix a misnamed variable.
closes #673.
2010-05-24 11:28:57 -07:00
Alexander LjungbergandRoss Boucher bbbf439028 Fixed: contentBounds not var'ed in _verticalScrollerDidScroll. Whitespace cleanup. 2010-05-24 11:21:23 -07:00
Alexander LjungbergandRoss Boucher 3c5dab1f34 Implemented CPCoding for CPButton imageDimsWhenDisabled. Fixed a problem where setImageDimsWhenDisabled:NO would not cause a redraw even if the image was previously dimmed. 2010-05-24 11:17:25 -07:00
Saikat ChakrabartiandRoss Boucher e8499e1751 Adding grab/grabbing cursors for Firefox. 2010-05-24 10:15:29 -07:00
Ross Boucher be26ab9201 CPDictionary is now KVO compliant. 2010-05-24 10:09:39 -07:00
Thomas InghamandRoss Boucher 7519b7ab63 Added hud style for circular slider knob thing. 2010-05-24 10:09:39 -07:00
Thomas InghamandRoss Boucher aaf5c7581c Moved the non-highlighted version of the knob down one more freaking pixel. 2010-05-24 10:09:39 -07:00
Thomas InghamandRoss Boucher ce4e8dc8b7 Moved knobs down a pixel. 2010-05-24 10:09:39 -07:00
Thomas InghamandRoss Boucher 5c2e6c8ed8 Matched up the knob images to those in the file and split them into HUD as well. 2010-05-24 10:09:39 -07:00
Thomas InghamandRoss Boucher 4020f9c6c2 Adding images for sliders. 2010-05-24 10:09:38 -07:00
Thomas InghamandRoss Boucher 16bf635aca Added images that I missed because git doesn't do recursive directories. 2010-05-24 10:09:38 -07:00
Thomas InghamandRoss Boucher 99bc5a018e Added segmented control graphics and theme method to support HUD style displays for CPSegmentedControl. 2010-05-24 10:09:38 -07: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 06a553ba85 Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-21 11:51:02 +02:00
klaaspieterandRandall Luecke 08b06b8632 implemented CPCoding support for CPSortDescriptor and made CPTableColumn decode it's _sortDescriptorPrototype
Conflicts:

	AppKit/CPTableColumn.j
	Tools/nib2cib/NSTableColumn.j
2010-05-20 22:51:01 -05:00
Randall Luecke 79e8b6e242 Added API for changing tableview selection color and source list gradient. 2010-05-20 19:43:01 -05:00
Klaas Pieter AnnemaandRandall Luecke 6a34329765 fixed a typo where CPThemeStateSelectedDataView was set on the header view of a table column 2010-05-20 13:42:50 -05:00
Klaas Pieter Annema f7dd6e4387 fixed a typo where CPThemeStateSelectedDataView was set on the header view of a table column 2010-05-20 18:52:43 +02:00
Klaas Pieter Annema 6a33acbb7c implemented CPCoding support for CPSortDescriptor and made CPTableColumn decode it's _sortDescriptorPrototype 2010-05-20 11:39:47 +02:00
Klaas Pieter Annema 97e4b69eaa Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-20 10:50:47 +02:00
Alan RogersandRandall Luecke e96678eebc Fix for gh issue #674: passing item in userInfo for the will/did expand/collapse notifications for the OutlineView. 2010-05-20 02:12:39 -05:00
Randall Luecke 1bc8536f0e Row indexes which no longer exist are removed from selectedRowIndexes. 2010-05-19 21:15:50 -05:00
Klaas Pieter Annema 76df9be4fb implemented CPTableColumn isHidden nib2cib support 2010-05-19 18:51:18 +02:00
Klaas Pieter Annema 322d8c67b3 Fixed NSTableColumn user resizable nib2cib 2010-05-19 18:31:21 +02:00
Randall Luecke d6ac30be75 CPTableView dataViews when selected now use the new CPThemeStateSelectedDataView state to avoid conflict with other CPControl theme states. 2010-05-19 01:55:01 -05:00
Randall Luecke a9f970459b Fix for undoManager thowing exception in -canUndo. 2010-05-19 01:33:13 -05:00
Randall Luecke 76443a5d7f Fire selectionIsChanging when selecting column. closes #437 2010-05-19 01:02:39 -05:00
Randall Luecke f0501f8494 Fixed regression from last commits where children would fail to expand. 2010-05-19 00:29:12 -05:00
Blair DuncanandRandall Luecke efb752f1f4 CPOutlineView, forgot to unregister notifications prior to adding them in the last commit. 2010-05-19 00:13:26 -05:00
Randall Luecke d252e94892 CPOutlineView item Expande/Collapse delegate method notifications
Conflicts:

	AppKit/CPOutlineView.j
2010-05-19 00:13:05 -05:00
Alexander LjungbergandRandall Luecke 0be23981f3 Fixed a nonsensical CPTableview highlight style check which only accidentally did the right thing. 2010-05-18 23:57:00 -05:00
cacaodevandRandall Luecke a4cadc5fb3 CPOutlineView: fix for _retargetedDropRow not set when retargeting an item which resulted in a wrong drop line position 2010-05-18 23:56:49 -05:00
Alexander LjungbergandRandall Luecke f902223597 Edit table cells programmatically (editColumn:row:withEvent:select:). Also implements editedColumn and editedRow. 2010-05-18 23:56:42 -05:00
Alexander LjungbergandRandall Luecke 9b926be557 Support CPOutlineView inline editing. 2010-05-18 23:56:34 -05:00
Klaas Pieter Annema db568af302 made sure CPViewController calls viewDidLoad if it's view property is set directly 2010-05-17 12:44:11 +02:00
Klaas Pieter Annema e7cf20a723 Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-17 11:19:14 +02:00
Randall Luecke 202243f711 fixed typo in CPViewAnimation. 2010-05-16 13:41:09 -05:00
Randall Luecke c5f51ae826 Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-16 13:26:45 -05:00
Randall Luecke 61b9c7a1ee Moved depreciated CPGeometry methods to CGGeomotry and fixed the filename in the header. 2010-05-16 13:19:28 -05:00
Saikat ChakrabartiandRoss Boucher 4520715b5b Making CPURLConnection authentication challenges happen before the delegate gets a response 2010-05-15 19:14:57 -07:00
Thomas InghamandRoss Boucher 6ef829e9ec Added documentation in the form of source code comments; verified using doxygen and the included recipe file. 2010-05-15 12:36:36 -07:00
Alexander LjungbergandRoss Boucher 791e65c88b Improved CPArray sortUsingDescriptors performance by about 3% by pulling the descriptor count out of the sort function. 2010-05-15 12:32:19 -07:00
Ross Boucher fddcde757f Add a more specific cache header.
Closes #649.
2010-05-15 12:22:29 -07:00
Paul BaumgartandRoss Boucher 66180f8de4 change @property to @accessors in pre-processor error messages 2010-05-15 12:19:35 -07:00
Paul BaumgartandRoss Boucher bc5a21d545 Change objj_exception_throw to manually throw an exception, because objj_exception_throw doesn't exist anymore. 2010-05-15 12:19:06 -07:00
Paul BaumgartandRoss Boucher fc8525e4d8 throw a regular Error() exception in Runtime.js because objj_exception doesn't exist anymore 2010-05-15 12:19:00 -07:00
Francisco Ryan Tolmasky I 8dd61155bf Merge branch 'master' of github.com:280north/cappuccino 2010-05-12 19:23:06 -07:00
Francisco Ryan Tolmasky I 5a89dfe8f4 Fix for identifying when we can use platform windows.
Reviewed by me.
2010-05-12 19:22:31 -07:00
Ross Boucher 80b70ec6b9 Can't sprited resources whos resulting dataURL is larger than 32k, not resources which themselves are over 32k. 2010-05-12 19:08:30 -07:00
Francisco Ryan Tolmasky I ac81ab458c Fix for same html appearing multiple times in CPWebView when using loadHTMLString: many times in succession.
Reviewed by me.
2010-05-12 18:41:14 -07:00
Ross Boucher 23b76874df A few IE fixes for web view. 2010-05-12 18:23:33 -07:00
Randall Luecke bc54fcf6c0 Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-12 19:46:34 -05:00
Randall Luecke e0a3a683a5 access ivars directly from within CPTableHeaderView class. 2010-05-12 19:44:07 -05:00
Randall Luecke c31786c4c1 Refactored autoresizing 2010-05-12 19:01:28 -05:00
Ross Boucher 13a5c7f215 indexOf is not a safe operation on arrays. 2010-05-12 16:51:28 -07:00
Klaas Pieter AnnemaandRoss Boucher ee2f361425 Reimplemented setImageDimsWhenDisabled: on CPButton to only dim the image instead of the entire button 2010-05-12 16:51:28 -07:00
Scott KyleandRoss Boucher 9eab2071dc In CPImageView, performDragOperation: should return a BOOL 2010-05-12 16:51:28 -07:00
Randall Luecke 61d7fe04e8 If we tell the tableview not to draw a selection then we shouldn't draw it... 2010-05-12 18:43:56 -05:00
Randall Luecke d3161422db Updated TableTest adding a checkbox as a dataview for a column. 2010-05-12 17:14:25 -05:00
Ross Boucher d1ae1bd41f Menu window's should open in the same platform window as the view they are attached to. 2010-05-12 10:36:48 -07:00
Francisco Ryan Tolmasky I 6384bed9cc Properly handle window.location= links as well.
Reviewed by me.
2010-05-12 09:45:58 -07:00
Francisco Ryan Tolmasky I be75e4948d Merge branch 'master' of github.com:280north/cappuccino 2010-05-12 08:54:15 -07:00
Francisco Ryan Tolmasky I 337f5d9e73 Correctly handle targeted links in NativeHost.
Reviewed by me.
2010-05-12 08:53:50 -07:00
Ross Boucher 4afa2bfada clean up style issues 2010-05-11 23:20:02 -07:00
Randall Luecke b94174f9e1 Updated TableTest to provide a test case for tables that do not sit at (0,0) of a window. 2010-05-11 19:43:01 -05:00
Randall Luecke bf71045381 Fixed bug where column reordering would be off if the table didn't sit at (0,0) on a window. 2010-05-11 19:39:51 -05:00
Francisco Ryan Tolmasky I 0ade0e1361 Merge branch 'master' of github.com:280north/cappuccino 2010-05-11 14:05:51 -07:00
Ross Boucher 0f02e0d8dd Revert "added enumerateWithBlock: to CPArray"
This reverts commit 39bb8e3418.
2010-05-11 12:40:37 -07:00
klaaspieterandRandall Luecke 7c786407a5 Merge remote branch 'klaaspieter/column-reordering'
Conflicts:
	AppKit/CPTableHeaderView.j
2010-05-11 01:18:56 -05:00
Klaas Pieter AnnemaandRandall Luecke 79ba8fecd5 made column reordering work with scrolled content 2010-05-11 00:25:54 -05:00
Klaas Pieter AnnemaandRandall Luecke 213c81ed4d made table column reordering work in non full-bridged apps 2010-05-11 00:25:47 -05:00
Klaas Pieter AnnemaandRandall Luecke d7432c376d fixed a bug where column reordering would break when the last column was hidden 2010-05-11 00:25:39 -05:00
Klaas Pieter AnnemaandRandall Luecke b8c7d6ea86 some cleanup 2010-05-11 00:25:30 -05:00
Randall Luecke 983f0a92b2 - fixed a out of bounds error when clicking in the table header outside of any column
- made the dragged table column appear gray
- gave the tablecolumn drag view a white background

Conflicts:

	AppKit/CPTableView.j
2010-05-11 00:25:19 -05:00
Klaas Pieter AnnemaandRandall Luecke 256cc902eb - switch columns when the dragged column is more than halfway over the previous/next column
- constrain the horizontal coordinates within the header view
2010-05-11 00:24:16 -05:00
Klaas Pieter AnnemaandRandall Luecke f7b766cc4a - made the _dragViewForTableColumn:event:offset: method private
- removed the multiple column support from _dragViewForTableColumn:event:offset: (Cocoa doesn't allow multiple column selection / dragging)
- made the dragview the size of the dragged column
2010-05-11 00:24:03 -05:00
Klaas Pieter AnnemaandRandall Luecke dca66f300d - gave the drag column a proper 'image' representation
- constrained the drags y coordinates
- made sure a drag is never out of bounds
2010-05-11 00:23:55 -05:00
Klaas Pieter AnnemaandRandall Luecke fd9dac8122 - refactored mouse interaction
- implemented basic column reordering
2010-05-11 00:23:40 -05:00
Klaas Pieter AnnemaandRandall Luecke 8b168e76af refactored CPTableHeaderView mouse interaction 2010-05-11 00:18:21 -05:00
Randall Luecke 5b518797d7 fixed CPTableView moveColumn:
Conflicts:

	AppKit/CPTableView.j
2010-05-11 00:18:05 -05:00
Randall Luecke e5275514dd OutlineView items auto expand when hovering over them. 2010-05-11 00:05:12 -05:00
cacaodevandRandall Luecke 0d35b38282 CPOutlineView: Fix a bug where newly expanded items would have a white disclosure control.
In CPTableView, add a method for data view selection. Use it in CPOutlineView for disclosure selection and do not subclass the entire -selectRows:... method.
               Darken disclosure control when pressed depending on the selected state.
2010-05-10 15:03:06 -05:00
Randall Luecke 837dcbf19d Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-10 15:02:19 -05:00
Ross BoucherandRandall Luecke e68d70cf1d Make mouse wheel events work in CPWebView in Firefox 3+ 2010-05-09 21:46:02 -05:00
Klaas Pieter Annema 1171e2c9af Merge branch 'master' of git://github.com/280north/cappuccino
Conflicts:
	Foundation/CPKeyValueObserving.j
2010-05-07 10:23:27 +02:00
Klaas Pieter Annema e5873caf04 fixed a typo in objectValueForTableColumn:row: 2010-05-07 09:38:23 +02:00
Ross Boucher 34ee33aea0 Merge commit '6f0ca9d94c217bc5e3c3' into bindings 2010-05-06 13:35:00 -07:00
Klaas Pieter AnnemaandRoss Boucher 2d93d12cad Made bindings branch jake buildable 2010-05-06 13:33:38 -07:00
Ross Boucher c43b80cb91 Make mouse wheel events work in CPWebView in Firefox 3+ 2010-05-06 12:41:01 -07:00
Ross Boucher 542e491bb4 whitespace cleanup. 2010-05-06 11:26:56 -07:00
Klaas Pieter AnnemaandRoss Boucher 9c9eb519df call willChange* and didChange* methods on the actual classes 2010-05-06 11:23:49 -07:00
Klaas Pieter Annema 0a96cb8eb3 call willChange* and didChange* methods on the actual classes 2010-05-06 17:36:11 +02:00
Klaas Pieter Annema 8e3e15080b made CPDecimalCreateWithString work with empty string 2010-05-06 14:13:29 +02:00
Ross Boucher 90975c96f9 Updates for scrolling behavior in webview. 2010-05-05 14:05:09 -07:00
Klaas Pieter Annema 2fd85ab78f made column reordering work with scrolled content 2010-05-05 14:08:06 +02:00
Klaas Pieter Annema a0cf7d5787 made table column reordering work in non full-bridged apps 2010-05-05 12:56:23 +02:00
Klaas Pieter Annema e7fc9d9912 fixed a bug where column reordering would break when the last column was hidden 2010-05-05 12:25:09 +02:00
Klaas Pieter Annema bdb0fb1310 some cleanup 2010-05-05 12:24:05 +02:00
Klaas Pieter Annema 006f7e0c15 - fixed a out of bounds error when clicking in the table header outside of any column
- made the dragged table column appear gray
- gave the tablecolumn drag view a white background
2010-05-05 12:23:55 +02:00
Klaas Pieter Annema 93afa11ef9 - switch columns when the dragged column is more than halfway over the previous/next column
- constrain the horizontal coordinates within the header view
2010-05-05 12:23:07 +02:00
Klaas Pieter Annema 040e7bc9ee - made the _dragViewForTableColumn:event:offset: method private
- removed the multiple column support from _dragViewForTableColumn:event:offset: (Cocoa doesn't allow multiple column selection / dragging)
- made the dragview the size of the dragged column
2010-05-05 12:23:00 +02:00
Klaas Pieter Annema 6bb8514253 - gave the drag column a proper 'image' representation
- constrained the drags y coordinates
- made sure a drag is never out of bounds
2010-05-05 12:22:53 +02:00
Klaas Pieter Annema 85283cff38 - refactored mouse interaction
- implemented basic column reordering
2010-05-05 12:22:42 +02:00
Klaas Pieter Annema ef68408fff refactored CPTableHeaderView mouse interaction 2010-05-05 12:22:36 +02:00
Klaas Pieter Annema 71104e4902 fixed CPTableView moveColumn: 2010-05-05 12:22:16 +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
Klaas Pieter Annema 65362e727a Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-05 12:03:51 +02:00
Ross Boucher 5044ce4236 Add a doctype when creating new platform windows. 2010-05-04 22:55:06 -07:00
Francisco Ryan Tolmasky I b4aca3410f Merge branch 'master' of github.com:280north/cappuccino 2010-05-04 22:08:08 -07:00
Ross Boucher b5971eae95 Missed this, it's no longer needed. 2010-05-04 19:09:06 -07:00
Tom Robinson 4b775796be Add a test for capp gen, press, and flatten. 2010-05-04 15:41:50 -07:00
Tom Robinson e97af776a0 Fix press/flatten due to changes to CFHTTPRequest. 2010-05-04 15:40:35 -07:00
Ross Boucher e83e5b7c29 Only send open if we aren't already open 2010-05-04 15:04:51 -07:00
Francisco Ryan Tolmasky I 179ef85f4e Final timer fix.
Reviewed by me.
2010-05-04 14:49:31 -07:00
Ross Boucher 5b4603b6a7 add missing ivar declaration to CPPlatformWindow 2010-05-04 13:53:56 -07:00
Francisco Ryan Tolmasky I fc2560eb32 Fix for native drag and drop breaking across different window starts.
Reviewed by me.
2010-05-04 10:28:51 -07:00
Francisco Ryan Tolmasky I 2c23c0ffa7 Disable new timer stuff for CommonJS.
Reviewed by me.
2010-05-04 10:09:16 -07:00
Klaas Pieter Annema fda974458e Merge branch 'master' of git://github.com/280north/cappuccino 2010-05-04 15:55:17 +02:00
Francisco Ryan Tolmasky I efe4d5f339 Merge branch 'master' of github.com:280north/cappuccino 2010-05-04 03:32:51 -07:00
Francisco Ryan Tolmasky I 032fe7cc0c Fix for timers not working if they are created outside of a run loop.
Reviewed by me.
2010-05-04 03:32:16 -07:00
Randall Luecke 50c519ec69 Fixed issue with CPWebView where document.body didn't exist when reloaded quickly. 2010-05-03 17:34:12 -04:00
Tom Robinson af566ec08a Fix LoadTimeTest, location.host includes the port. 2010-05-03 00:25:35 -07:00
Ross Boucher cb7879eecf Make CFHTTPRequests re-fireable. 2010-05-02 12:58:36 -07:00
Ross Boucher b1825334dd If the vertical status changes, or the pane splitter status changes, we need to update the image value. 2010-05-01 20:40:38 -07:00
Ross Boucher 09727909b3 Fix for menuless windows. Closes #640. 2010-05-01 14:47:43 -07:00
Ross Boucher f98d3bd44b Add global 403 handler for CFHTTPRequest, to make it easier to catch authentication challenges. 2010-05-01 11:57:32 -07:00
Ross Boucher 1545f7b60a Return the cib created in CibLoading.j methods. 2010-04-29 15:38:33 -07:00
Ross Boucher 2453e403ef Make nil a completely valid object in a CPArray.
Closes #630.
2010-04-29 12:04:44 -07:00
Klaas Pieter Annema 2bb16c3617 Merge branch 'master' of git://github.com/280north/cappuccino 2010-04-29 14:28:16 +02:00
Klaas Pieter Annema 4ef9202e92 made the tableview handle hiding and showing of columns properly 2010-04-29 14:22:46 +02:00
Tom Robinson 22668b6b43 Use 127.0.0.1 instead of localhost in case localhost != loopback. 2010-04-28 02:23:07 -07:00
Francisco Ryan Tolmasky I f9c786f3eb Merge branch 'master' of git@github.com:280north/cappuccino 2010-04-28 02:06:48 -07:00
Francisco Ryan Tolmasky I 0f2ee1966e Only create main menu in code if no cib is loaded.
Reviewed by me.
2010-04-28 02:06:01 -07:00
Tom Robinson 62e520a6a5 Some more NativeHost building enhancements. 2010-04-28 01:45:04 -07:00
Ross Boucher 2f9cf6bc9b Add action buttons to button bars. 2010-04-27 22:11:17 -07:00
Ross Boucher e03cfe8287 Missing printResults() in Jakefile for ThemeDescriptor template
Conflicts:

	Tools/capp/Resources/Templates/ThemeDescriptor/Jakefile
2010-04-27 13:16:17 -07:00
Tom Robinson 0d97dfacd6 give zero sized borderless bridge windows a default size if we're not in the browser so they show up in NativeHost. 2010-04-27 12:56:24 -07:00
Francisco Ryan Tolmasky I 6ac0191451 Show main menu in cibless apps.
Remaining: Make a main menu with quit for desktop version, without for web version.

Reviewed by me.
2010-04-27 11:33:00 -07:00
Ross Boucher f5b360f66c Move a lot of common initialization code into the _init method. 2010-04-27 10:49:50 -07:00
Ross Boucher 1d5c21fa72 If we decode a scroll view without a header clip view, create one. 2010-04-27 10:49:50 -07:00
Klaas Pieter Annema 015aca9165 Merge branch 'master' of git://github.com/280north/cappuccino 2010-04-27 10:36:12 +02:00
Francisco Ryan Tolmasky I d3e1c39e35 Merge branch 'master' of git@github.com:280north/cappuccino 2010-04-27 01:05:14 -07:00
Francisco Ryan Tolmasky I ae47509aa7 Add convinience methods for dealing with multiple objects and controls.
Reviewed by me.
2010-04-27 01:04:46 -07:00
Tom Robinson 5ff798306f Copy CFBundleIconFile in NativeHost building. 2010-04-26 23:19:05 -07:00
Ross Boucher c41ffc14c7 checkboxes and radio buttons shouldn't be bold. 2010-04-26 21:36:45 -07:00
Ross Boucher 1e7a3bef0d Fix a potential infinite loop in CPBrowser. 2010-04-26 12:56:52 -07:00
Nicholas Small 243f564396 Fix typo in new autoscroll stuff. 2010-04-26 11:11:42 -04:00
Tom Robinson dae1e44a8f Merge Cappuccino Info.plist into NativeHost's Info.plist. 2010-04-25 23:22:16 -07:00
Tom Robinson 67bcc29baf NativeHost. 2010-04-25 22:33:31 -07:00
Ross Boucher cdb089778c autoscroll when drag selecting. 2010-04-25 15:43:23 -07:00
Ross Boucher 5e43a02ffa Fix some faulty validation logic. 2010-04-25 15:43:22 -07:00
Ross Boucher 7395d13c3e Typo in CPJSONPConnection. 2010-04-25 15:43:22 -07:00
Tom Robinson f6000468db Missing printResults function in ThemeDescriptor Jakefile. 2010-04-25 14:58:27 -07:00
Stephen IerodiaconouandRoss Boucher 09e52d82bf Code style clean up, as per style guide 2010-04-24 15:06:12 -07:00
Ross Boucher 0e98f44a93 Fix for IE transparent backgrounds not being resized.
Closes #604.
2010-04-24 14:51:10 -07:00
Ross Boucher 6d595c1344 Collection view should tile itself to be the height of its superview if inside a clip view. 2010-04-24 11:10:58 -07:00
Ross Boucher 5f6f997095 Only attempt to scroll views, not windows. 2010-04-24 11:10:36 -07:00
Ross Boucher 6662fabcb8 Tests for the bug exposed in the previous cparray commit. 2010-04-23 16:43:22 -07:00
Stephen IerodiaconouandRoss Boucher 7577cf8645 Fix error in initWithArray:copyItems: 2010-04-23 16:42:55 -07:00
Ross Boucher 8340791824 Don't let color wells work if they are disabled.
Closes #626.
2010-04-23 16:34:47 -07:00
Ross Boucher 14f0d16fae Update scrollWheel: to propagate unused scroll deltas to parent scroll views. 2010-04-23 16:16:46 -07:00
cacaodevandRoss Boucher e1ad4a2fce CPTableView: remove custom scrolling now that it's handled in the CPDragServer + CPClipView 2010-04-23 14:31:25 -07:00
Ross Boucher f67580e2b2 Add support for automatically scrolling during drag and drop operations. 2010-04-23 14:00:47 -07:00
Ross Boucher 31f408478a Update to scrolling behavior. 2010-04-23 12:03:25 -07:00
Klaas Pieter Annema fd93b6e5f7 Merge branch 'master' of git://github.com/280north/cappuccino 2010-04-23 16:34:59 +02:00
Klaas Pieter Annema 39bb8e3418 added enumerateWithBlock: to CPArray 2010-04-23 16:34:40 +02:00
Randall Luecke ab6d5d6a90 Added connectionDidFinsihLoading delegate to CPJSONPConnection 2010-04-23 01:29:46 -04:00
Ross Boucher 6b3600d67b Slight update to button bar theme values. 2010-04-22 11:50:06 -07:00
Francisco Ryan Tolmasky I bf8ff44b84 Merge branch 'master' of git@github.com:280north/cappuccino 2010-04-21 22:56:21 -07:00
Francisco Ryan Tolmasky I 72a3888062 Add ObjectiveJ global to CommonJS so that references to it aren't broken in Cappuccino.
Reviewed by me.
2010-04-21 22:55:46 -07:00
Ross Boucher 4479233bea Return nil fonts if they are the aristo default, so that the theme default is used instead of the arist default (for custom themes). 2010-04-21 20:57:53 -07:00
Alexander LjungbergandRoss Boucher a7021e6b66 Fixed a parameter type typo. 2010-04-21 15:48:47 -07:00
Alexander LjungbergandRoss Boucher 0f5dd9d469 [CPSet description] with unit test. 2010-04-21 15:48:39 -07:00
Alexander LjungbergandRoss Boucher 388f008189 Fixed: CPCollectionView frameForItemsAtIndexes used the deprecated method rectForItemAtIndex causing warnings. 2010-04-21 15:47:48 -07:00
Alexander LjungbergandRoss Boucher 639a32ea7e CPWindow alpha value support. 2010-04-21 15:47:25 -07:00
Alexander LjungbergandRoss Boucher 5838f1aec8 Implemented CPCoding for CPNull. 2010-04-21 15:36:29 -07:00
Ross Boucher d2399b6157 Add support for not clipping to bounds in cpview. 2010-04-21 14:15:05 -07:00
Ross Boucher b1282b4362 Fix an infinite recursion bug in CPBrowser, and add support for looking up a column/row by location. 2010-04-21 12:58:31 -07:00
Francisco Ryan Tolmasky I bbd402fcff Partial fix for HTML5 drag and drop with collection views.
Reviewed by me.
2010-04-20 23:51:18 -07:00
Klaas Pieter Annema 6f0ca9d94c Merge branch 'master' into bindings
Conflicts:
	AppKit/CPTableView.j
	AppKit/_CPCornerView.j
	Foundation/CPArray.j
	Foundation/CPKeyValueCoding.j
	Foundation/CPKeyValueObserving.j
2010-04-15 10:57:46 +02:00
Tom Robinson a18fb1b686 Add manifest generation options to press and flatten, since manifests need to be updated after each is run. 2010-04-12 13:47:38 -07:00
Francisco Ryan Tolmasky I 6a72e1b6ff Merge branch 'master' of git@github.com:280north/cappuccino 2010-04-12 12:22:25 -07:00
Francisco Ryan Tolmasky I b3141f1a62 Add CPApplicationWillTerminateNotification.
Reviewed by me.
2010-04-12 12:21:45 -07:00
Randall Luecke aea8f1f0dc Added proper background color to the tableview. 2010-04-12 02:09:46 -04:00
Francisco Ryan Tolmasky I 8aecf880e5 Merge branch 'master' of git@github.com:280north/cappuccino 2010-04-09 22:22:55 -07:00
Francisco Ryan Tolmasky I 7d5ce51910 Upped the version number to 0.8.1.
Reviewed by me.
2010-04-09 22:22:35 -07:00
Ross Boucher cfc8ccafce Remove typo. 2010-04-09 14:56:54 -07:00
Kelly McDonaldandRoss Boucher e11dfc2875 CPDragServer was checking the selector on the delegate of draggedImage:endAt:operation: but calling draggedImage:endedAt:operation:. I changed so that it uses endedAt to better reflect what is done in cocoa 2010-04-09 14:56:43 -07:00
Ross Boucher b3ef31ad05 Fixed: [CPArray isEqualToArray:nil] threw an exception instead of returning NO.
Conflicts:

	Foundation/CPArray.j
	Tests/Foundation/CPArrayTest.j
2010-04-09 14:51:46 -07:00
Ross Boucher 70410d6311 Fix the buttonNumber method of CPEvent.
Closes #70.
2010-04-09 14:38:08 -07:00
Ross Boucher 4cc7dec35b Throw syntax error for # followed by anything other than pragma. 2010-04-09 14:34:02 -07:00
Ross Boucher 47ecd40c4f Made the pre-processor capable of recognizing and ignoring Xcode's '#pragma mark' mark-ups
Conflicts:

	Objective-J/Preprocessor.js
2010-04-09 14:26:29 -07:00
saikatandRoss Boucher 489f2bcfa0 Reverting 1c9763eaa8 - autoresizing the contentview breaks sizetofit 2010-04-09 14:18:20 -07:00
Ross Boucher 16590e0603 Closes #590.
Closes #594.
2010-04-09 14:17:11 -07:00
Paul BaumgartandRoss Boucher f50cda9abc change CPAccordionItem to CPAccordionViewItem in CPAccordionView
selector types. Closes gh-596.
2010-04-09 13:58:05 -07:00
Francisco Ryan Tolmasky I 7543968203 Merge branch 'master' of git@github.com:280north/cappuccino 2010-04-08 23:59:00 -07:00
Francisco Ryan Tolmasky I 54685b1f36 One additional fix for IE not loading in certain occasions.
Reviewed by me.
2010-04-08 23:58:47 -07:00
Francisco Ryan Tolmasky I abdc601d92 Fix for IE not loading bug.
Reviewed by me.
2010-04-08 23:58:31 -07:00
Tom Robinson 9f50f08065 Add automated HTML5 cache manifest generation. Disabled by default. 2010-04-07 22:46:23 -07:00
Tom Robinson aabb1fa6f2 Move CPCursor test out of Resources. 2010-04-07 16:03:42 -07:00
Tom Robinson 4b770714bd Update starter task to include version of bootstrap which installs Cappuccino packages. 2010-04-06 12:54:23 -07:00
Ross Boucher 8175dbca53 Updates to the Jakefile and capp gen. 2010-04-06 12:26:35 -07:00
Tom Robinson c91332afb4 Add the other MobileSafari meta/link tags. 2010-04-05 20:09:04 -07:00
Tom Robinson 08fb1b33b4 Add viewport tag to templates. Fixes drawing errors on MobileSafari. 2010-04-05 18:14:04 -07:00
Ross Boucher cd6b6afc65 Don't convert text fields to bold default system font. 2010-04-05 10:38:20 -07:00
Tom Robinson cd4a70ea78 Add hook to CPApplicationMain to notify parent frame (if app is in a child frame of same origin) 2010-04-04 18:39:47 -07:00
Tom Robinson eb24ba9835 Re-enable flatten compression by default. 2010-04-01 23:48:48 -07:00
Tom Robinson 468869821f Add charset attributes to all external script tags, including flatten. Fixes unicode bugs in flatten. 2010-04-01 23:41:08 -07:00
Tom Robinson 0c85dbf9b0 Add some charset options, and disable compressor by default. 2010-04-01 23:15:47 -07:00
Tom Robinson 2db47e413e Add comrpessor support to flatten. 2010-04-01 12:01:16 -07:00
Tom Robinson b8fddc98bf Fixes flatten, splitting mode. Also escape dollar signs before replacing. 2010-04-01 11:12:08 -07:00
Tom Robinson 467f798147 Fixes flatten, non-splitting mode. 2010-04-01 11:11:58 -07:00
Ross Boucher 374f3d13f1 Convert default IB fonts to default Cappuccino fonts 2010-03-31 21:31:09 -07:00
Tom Robinson b0a35a183f Only enable debug logger in browsers, not command line utilities. 2010-03-31 17:28:46 -07:00
Francisco Ryan Tolmasky I 74e349ed33 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-31 17:05:32 -07:00
Francisco Ryan Tolmasky I c57aa2ac5e Fix for menu bar being broken if displayed after a window is ordered front in IE.
Reviewed by me.
2010-03-31 17:04:35 -07:00
Ross Boucher acac29dcda Merge branch 'master' of github.com:280north/cappuccino 2010-03-31 16:37:16 -07:00
Paul BaumgartandTom Robinson 675969af6d Add some dependency checking to bootstrap.sh: make sure correct JVM is
being used and ensure other dependencies are installed and on the $PATH.
2010-03-31 15:00:09 -07:00
Tom Robinson ce32177e1d Use "CommonJS" task as the dependency for "test" task for now. 2010-03-31 13:53:09 -07:00
Randall Luecke e956d61a08 Fixed bug introduced by renaming of private class. 2010-03-31 16:41:13 -04:00
Alexander LjungbergandRoss Boucher 068cdb9817 CPNull valueForKey:X returns CPNull for any value of X, paralleling [nil valueForKey:X]. Verified against Cocoa through empirical testing. 2010-03-31 13:17:42 -07:00
Randall Luecke 0ec7d4cd9a Made drag feedback view in the tableview more correct, fixed encoding issues.
Conflicts:

	AppKit/CPTableView.j
2010-03-31 16:11:10 -04:00
Nicholas Small 6a8126337c Added right click responder methods and context menu support. 2010-03-31 15:56:18 -04:00
Ross Boucher 12db25a829 Fix for a potential error in IE when setting a width to a negative value. 2010-03-31 12:11:21 -07:00
Ross Boucher a347bfb8b1 Sprite images recursively. 2010-03-31 11:10:17 -07:00
Francisco Ryan Tolmasky I 9255af210c Fix for loading Cappuccino apps locally on Windows.
Reviewed by me.
2010-03-30 16:28:42 -07:00
Tom Robinson 0b3264a99d Enable default logger in debug frameworks. Add configurable options to index-debug.html. 2010-03-30 14:12:59 -07:00
Ross Boucher 2bf16da441 These menu key equivs were incorrect. 2010-03-30 11:10:36 -07:00
Ross Boucher 5c4d890100 Fix a nil variable error that caused problems in Firefox 2. 2010-03-30 10:52:48 -07:00
Francisco Ryan Tolmasky I 99282026fa One more fix for image spriting.
Reviewed by me.
2010-03-30 00:45:11 -07:00
Francisco Ryan Tolmasky I 8f4b2a7cfd Fail more gracefully when main cib is not found.
Reviewed by me.
2010-03-29 23:20:31 -07:00
Randall Luecke c78feda3d6 Fixed nib2cib bug with cornerview where resources were not loaded from the correct location. 2010-03-30 01:45:36 -04:00
Francisco Ryan Tolmasky I a279d62c88 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-28 11:40:38 -07:00
Francisco Ryan Tolmasky I 8d1f787179 Fix for a few minor regressions:
1. Split out flatten specific code to get file size back down.
2. Fix for non-native string URL not working with the URLCache (typeof x !=== "string")
3. Fix for slight IE performance regression.

Reviewed by me.
2010-03-28 11:39:36 -07:00
Ross Boucher 7ab41cf195 If there is no key window or no main window make the first opened window those things. 2010-03-28 09:03:33 -07:00
Ross Boucher df728b7a21 Support terminating method signatures with ;. Closes #416. 2010-03-28 08:51:35 -07:00
Francisco Ryan Tolmasky I cba26faf9b Fix for HelloWorld not flattening correctly.
Reviewed by me.
2010-03-27 19:31:16 -07:00
Francisco Ryan Tolmasky I c4c1cffc01 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-27 18:53:03 -07:00
Francisco Ryan Tolmasky I 321706e5c6 Fix for user code errors during load not being reported (Cappuccino failing silently).
Reviewed by me.
2010-03-27 18:52:19 -07:00
Ross Boucher 47bf4c0baa Finish split view cursor implementation.
Closes #494.
2010-03-27 15:47:10 -07:00
Alexander LjungbergandRoss Boucher fc628c1221 CPSplitView resize cursors now require [[self window] setAcceptsMouseMovedEvents:YES]; to be called manually pending a CPTrackingArea based implementation. 2010-03-27 15:47:10 -07:00
Ross Boucher eb6a03704a Proper resize cursors for CPSplitView. Also enables resize cursor for additionalEffectiveRectOfDividerAtIndex areas.
Conflicts:

	AppKit/CPSplitView.j
2010-03-27 15:47:10 -07:00
Francisco Ryan Tolmasky I 7b855e6c68 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-27 13:56:35 -07:00
Francisco Ryan Tolmasky I fe0818c612 Don't generate image files if there aren't any.
Reviewed by me.
2010-03-27 13:54:07 -07:00
Ross Boucher 74dabcae8a Update the CPDictionary test suite. 2010-03-27 13:52:44 -07:00
Emmanuel MaillardandRoss Boucher daf7870bab - add containsKey: method 2010-03-27 13:41:32 -07:00
Ross Boucher 64da7f8775 define out DOM code from _CPImageAndTextView.
Closes #562.
2010-03-27 13:37:13 -07:00
aburkhalterandRoss Boucher 6cfa11a94d Initial boilerplate and file for putting the untested (at least not directly) CPView.j under test. Initial test to confirm we can actually create the object and a test demonstrating issue #562. 2010-03-27 13:33:04 -07:00
Ross Boucher db3c6c1463 A few minor updates to the pathExtension patch. 2010-03-27 13:25:44 -07:00
Emmanuel MaillardandRoss Boucher 65a669a9a1 - correct pathExtension and stringByDeletingPathExtension 2010-03-27 13:23:55 -07:00
Emmanuel MaillardandRoss Boucher 33f56bb203 - implement stringByDeletingPathExtension 2010-03-27 13:23:32 -07:00
Emmanuel MaillardandRoss Boucher 1ff873e170 - add tests for pathExtension and stringByDeletingPathExtension 2010-03-27 13:22:36 -07:00
Ross Boucher b0e0156880 Fix support for initial first responder. 2010-03-27 13:08:47 -07:00
Ross Boucher 896f36dffb A better (but not perfect) way to handle the browser's first responder state. 2010-03-27 11:27:44 -07:00
Ross Boucher eae975652e Add default line break mode. 2010-03-26 16:59:02 -07:00
Ross Boucher e46d1a793c autoresize the cpbrowser test browser. 2010-03-26 16:41:33 -07:00
Ross Boucher 1c9763eaa8 CPBox should autoresize its content view. 2010-03-26 16:41:23 -07:00
Ross Boucher 686370ac0e Add convenience accessors for the browser's selected items. 2010-03-26 15:52:53 -07:00
Ross Boucher e4ca057e4c Fix import directives. 2010-03-26 14:27:46 -07:00
Ross Boucher ac5a0e3dfc Add CPBrowser manual test app. 2010-03-26 14:00:51 -07:00
Ross Boucher a580b522e3 Add initial CPBrowser implementation. 2010-03-26 14:00:30 -07:00
Ross Boucher af53c271c7 Fix a few naming convention violations.
Make dragView.... use the columns its passed, rather than computing from scratch.
2010-03-26 13:59:41 -07:00
Ross Boucher 4476dad395 Whitespace fix. 2010-03-26 10:36:08 -07:00
Emmanuel MaillardandRoss Boucher b7b2dd2915 - CGPathAddQuadCurveToPoint fix for an unknown variable when using a transformation matrix 2010-03-26 10:36:08 -07:00
Francisco Ryan Tolmasky I efb6a0f5c6 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-26 01:31:39 -07:00
Francisco Ryan Tolmasky I deba653661 Fix for unrecognized selector in CPURL's initWithCoder:.
Reviewed by me.
2010-03-26 01:30:50 -07:00
Ross Boucher eb831dc4ac Typo. Closes #572. 2010-03-25 10:40:37 -07:00
Scott KyleandRoss Boucher b0d355a71c Some somewhat minor style fixes 2010-03-24 19:46:38 -07:00
Ross Boucher af11b4e423 Fix for pattern images not being displayed correctly under the new background color system 2010-03-23 14:32:24 -07:00
Ross Boucher 0cf86318ce Make semi-transparent background colors work in browsers that don't support RGBA.
Closes #569.
2010-03-23 14:26:32 -07:00
Ross Boucher 4175b762c3 Disable new syntax check while we work out the build issue some people are having. 2010-03-23 13:29:55 -07:00
Ross Boucher 3ddcb5f118 Remove duplicate method declaration. 2010-03-23 13:29:43 -07:00
Ross Boucher d0ad865976 Add the with{} back in for Class methods, instead take the disallowed list from objj_class. 2010-03-23 11:21:59 -07:00
Ross Boucher 7013b34897 Add a few additional syntax checks.
Throw an error if a method uses a parameter name that is also an ivar name.
Stop using with{} block for class methods.
2010-03-23 11:21:59 -07:00
Ross Boucher bbbae36e6a Missing - on a method. 2010-03-23 11:21:59 -07:00
Francisco Ryan Tolmasky I 34c3a9530b Fixed a bug where CPKeyedUnarchiver would incorrectly unarchive 0 as null.
Reviewed by me.
2010-03-23 02:06:44 -07:00
Francisco Ryan Tolmasky I 78cb522874 Temporarily revert "Make semi-transparent background colors work in browsers that don't support RGBA."
This fix was making lots of resources not show up.

This reverts commit f8c13f1e30.
2010-03-23 01:22:59 -07:00
Francisco Ryan Tolmasky I e8a0d2acf6 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-23 00:04:59 -07:00
Ross Boucher f8c13f1e30 Make semi-transparent background colors work in browsers that don't support RGBA.
Closes #569.
2010-03-22 19:00:49 -07:00
Randall Luecke 4b272a76fd Merge branch 'master' of git://github.com/280north/cappuccino 2010-03-22 19:27:13 -04:00
Randall Luecke f73d96af08 Fixed black background of dragview in Opera and IE. 2010-03-22 19:24:32 -04:00
Scott KyleandRoss Boucher bb0835e2f3 CPImageView should send action on drop, as in Cocoa 2010-03-22 16:15:02 -07:00
Ross Boucher ef4c108b9e Date test wasn't accurately accounting for daylight savings time. 2010-03-22 15:08:29 -07:00
Ross Boucher 319b9ed00f Use === not ==. 2010-03-22 14:53:49 -07:00
Alan RogersandRoss Boucher 35b62ca53f Updated test and fix for gh issue #539 2010-03-22 14:53:07 -07:00
Alan RogersandRoss Boucher 4e1e6f3c0b Little fix for CPDictionary, we should not try and recursively convert null JSON objects. 2010-03-22 14:52:55 -07:00
Alan RogersandRoss Boucher c8f3445fa6 Adding a unit test to verify fix to +[CPDictionary dictionaryWithJSObject:(JSObject)object recursively:(BOOL)recursively] 2010-03-22 14:52:49 -07:00
Emmanuel MaillardandRoss Boucher 7aa1ae6bd4 - fix typo 2010-03-22 14:43:53 -07:00
Emmanuel MaillardandRoss Boucher 58179939bb - fix a typo in documentation 2010-03-22 14:43:31 -07:00
Scott KyleandRoss Boucher 5d3eae9022 deleteBackwards: => deleteBackward: 2010-03-22 14:30:48 -07:00
aburkhalterandRoss Boucher 05f8a10b3d Trivial syntax fixes. 2010-03-22 14:29:27 -07:00
Francisco Ryan Tolmasky I 6843df410a Fix for empty data URLs, MHTML, etc. files being created when no image resources exist, causing a useless xhr.
Reviewed by me.
2010-03-21 14:30:31 -07:00
Randall Luecke f324577014 Fixed default height in tableheader for Nib2Cib. 2010-03-21 02:54:14 -04:00
Tom Robinson df8357e1fc Add --split option to flatten. Asynchronously load multiple flattened files. 2010-03-20 23:38:40 -07:00
Tom Robinson 35d14939c4 Fix for flatten in Firefox (silly security restriction makes onreadystatechange not readable) 2010-03-20 22:32:11 -07:00
Francisco Ryan Tolmasky I f2c19ad403 Slight fix for collectionView:canDragItemsAtIndexes:withEvent: not passing the correct event.
Reviewed by me.
2010-03-20 20:58:08 -07:00
Francisco Ryan Tolmasky I ed9fee3038 Added collectionView:canDragItemAtIndexes:forEvent:.
Reviewed by me.
2010-03-20 20:56:37 -07:00
Francisco Ryan Tolmasky I 58e31b9cb4 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-19 12:25:39 -07:00
Francisco Ryan Tolmasky I 401ee3fd94 Added itemAtIndex: to CPCollectionView and updates API names.
Reviewed by me.
2010-03-19 12:24:07 -07:00
Randall Luecke 43b601af9b Fixed TableTest for IE. 2010-03-17 21:07:47 -04:00
Francisco Ryan Tolmasky I 5581dd71fa Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-17 01:17:50 -07:00
Tom Robinson d8fb849691 Refactor objj_eval to work in the browser. Move from CommonJS-specific code to Objective-J proper. 2010-03-16 23:57:37 -07:00
Tom Robinson 5f4281b851 Add default theme to flattened app, "-P" option for specifying other inlined files. 2010-03-16 22:38:30 -07:00
Tom Robinson 24ab176236 Make asyncLoader a configurable option on exports. 2010-03-16 22:38:30 -07:00
Tom Robinson 9c342ca19c Fix objj_eval (used in objj REPL, etc). 2010-03-16 22:38:30 -07:00
Randall Luecke 3ee3acc948 Fixed failed TableCibTest in Firefox. 2010-03-17 00:11:36 -04:00
Randall Luecke 9bdc5fa0fe Various nib2cib improvements on the tableview. 2010-03-16 22:49:38 -04:00
Randall Luecke d7a7d8e2ae Merge branch 'master' of git://github.com/280north/cappuccino 2010-03-16 22:47:40 -04:00
Ross Boucher 5a9682b1bd Remove two calls to a dead function. 2010-03-16 18:13:57 -07:00
Randall Luecke 3c97903ed0 Fixed Nib2Cib selection color for the tableview. 2010-03-16 19:34:04 -04:00
Ross Boucher c9cf21be80 Fix for sizeWithFont: in Internet Explorer. 2010-03-16 16:01:44 -07:00
Tom Robinson f0818d94e9 Typo in window.clearNativeInterval. 2010-03-16 15:44:45 -07:00
Francisco Ryan Tolmasky I 831555cf5a Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-15 02:33:36 -07:00
Randall Luecke e0483e316e Fixed bug with nib2cib tableviews loading incorrect resources. 2010-03-14 17:24:36 -04:00
Ross Boucher c1fe45cbcd Add a way to tell a CPSplitView about a button bar for a specific divider index,
which mitigates the need to use additional effective rect delegate method when
using a split view + button bar.
2010-03-14 12:32:52 -07:00
Ross Boucher ef7ad8ee8e A few minor bug fixes for key/main window handling. 2010-03-13 22:49:06 -08:00
Ross Boucher 0ed7d46926 Add encoding support for CPButtonBar. 2010-03-13 22:49:06 -08:00
Tom Robinson ac69879fba Update flatten to use new file/function caching system. 2010-03-13 21:42:51 -08:00
Tom Robinson 50e779ef5a Add CFHTTPRequest and FileExecutable hooks for inlining files and module functions (for flatten). Removed hook used by flatten. 2010-03-13 21:35:15 -08:00
Tom Robinson 0032af1468 Merge branch 'master' of github.com:280north/cappuccino 2010-03-13 19:05:10 -08:00
Ross Boucher cf1c369dc3 Rewrite of CPButtonBar. Now it will automatically layout the buttons, and the position
and visibility of the resize control is configurable.

Also has class methods for plusButton and minusButton. API subject to change.
2010-03-13 17:37:28 -08:00
Tom Robinson ece7996895 Cleanup flatten, use resourceAtURL instead of manually walking path. 2010-03-13 01:17:47 -08:00
Randall Luecke 3cdfc1192a Fixes flickering issues with CPTableView if you hold the command key and drag. Closes #544 2010-03-13 00:07:00 -05:00
Ross Boucher 8b8998a2b9 Don't encode the search/cancel buttons. They add bloat and complicate the process. 2010-03-12 19:46:05 -08:00
Tom Robinson 677cf9e1df Change FileRequest to always use CFHTTPRequest and make async/sync configurable. Preparation for "flatten" changes. 2010-03-12 19:40:27 -08:00
Ross Boucher a08d4c6a06 Whitespace error. 2010-03-12 18:55:44 -08:00
aburkhalterandRoss Boucher e1e344dad1 Missing semi-colon. 2010-03-12 18:54:05 -08:00
aburkhalterandRoss Boucher b9427f84ae Fixes testShiftIndexesStartingAtIndex. Upward shifting no longer throws. 2010-03-12 18:53:58 -08:00
Andrew BurkhalterandRoss Boucher dc9d79bc3d Adding failing test demonstrating that CPIndexSet throws with negative delta (e.g. shifting indexes at starting point upwards). Simple downward shift example included and working successfully.
Misc method reorganization with test suite so it's a bit more intuitive.
2010-03-12 18:50:35 -08:00
Ross Boucher 503ce5502e Fix nib2cib support for CPSearchField 2010-03-12 18:49:37 -08:00
Tom Robinson 0e4d476d76 Add guard div to protect against iframes consuming events during tracking. 2010-03-12 17:25:19 -08:00
Francisco Ryan Tolmasky I cc2d579bc9 Merge branch '0.8.0' of git@github.com:280north/cappuccino 2010-03-12 03:33:21 -08:00
Tom Robinson 94bf2a36cf Updated flatten to work with new loader changes. 2010-03-11 15:56:58 -08:00
Tom Robinson 63127bf9c3 Fix CFBundle path deprecation warning and absoluteString not found. 2010-03-11 14:35:06 -08:00
Ross Boucher 033765e866 temporary fix for whiteSpace style issue in IE. 2010-03-11 14:28:31 -08:00
Ross Boucher 1634e4562a Update the template files to more modern standards. 2010-03-11 14:28:22 -08:00
Ross Boucher ed66d78585 Update the template files to more modern standards. 2010-03-11 14:27:15 -08:00
Ross Boucher 39e1514620 temporary fix for whiteSpace style issue in IE. 2010-03-11 14:18:24 -08:00
Randall Luecke 10b7eb83f1 Fixed previous commit so it doesn't break buttons in the tableview. 2010-03-09 23:52:08 -05:00
Randall Luecke 672be3991d Merge branch '0.8.0' of git://github.com/280north/cappuccino into 0.8.0 2010-03-09 23:49:03 -05:00
Randall Luecke b350c2be91 Fixed previous commit so it doesn't break buttons in the tableview. 2010-03-09 19:19:25 -05:00
Tom Robinson 68ab5bd4e7 Typo in CI script. 2010-03-09 16:12:13 -08:00
Tom Robinson bd21153300 Typo in CI script. 2010-03-09 16:07:39 -08:00
Tom Robinson 9cca7ead17 Factor out nightly build portion of CI script so not all branches push builds 2010-03-09 15:35:53 -08:00
Tom Robinson 4b1bf1fe65 Factor out nightly build portion of CI script so not all branches push builds 2010-03-09 15:32:13 -08:00
Randall Luecke 6d353f378d Fixed bug where editable tableview would not honor setEditable:NO for columns unless resized. closes #426 2010-03-09 14:43:12 -05:00
Randall Luecke cc2bb8f496 Fixed bug where editable tableview would not honor setEditable:NO for columns unless resized. closes #426 2010-03-09 14:39:26 -05:00
cacaodevandRandall Luecke 20853e3ad7 CPTableView & al. : change CPThemeStateHighlighted to CPThemeStateSelected to avoid conflicts with CPControl -highlight: method. 2010-03-09 11:43:37 -05:00
appdenandRandall Luecke 67def34e29 Added semi-colons to global vars and removed accidental gloabl variable. 2010-03-09 03:22:02 -05:00
appdenandRandall Luecke 54549b61e1 Added semi-colons to global vars and removed accidental gloabl variable. 2010-03-09 03:20:00 -05:00
Tom Robinson 3e7c3e952b Merge branch '0.8.0' of github.com:280north/cappuccino into 0.8.0 2010-03-08 19:03:14 -08:00
Francisco Ryan Tolmasky I e6411d7d90 Fix for classes declared in subfolders reporting wrong bundle (fictional).
Reviewed by me.
2010-03-08 18:27:43 -08:00
Francisco Ryan Tolmasky I 9e7d0d3183 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-08 18:23:36 -08:00
Francisco Ryan Tolmasky I 3ae4b1cf19 Fix for classes declared in subfolders reporting wrong bundle (fictional).
Reviewed by me.
2010-03-08 18:22:53 -08:00
Ross Boucher 2841223c9d Create the args and namedArgs objects in Bootstrap.js, pass them along up to CPApplication. 2010-03-08 15:14:09 -08:00
Tom Robinson ba713b8b06 Use getCappuccinoVersion() in various Jakefiles instead of hardcoded versions. 2010-03-08 15:10:08 -08:00
Tom Robinson c53bff288a Add a central version.json file. Change package building to insert version, revision, and timestamp. Auto-push tags. 2010-03-08 15:10:08 -08:00
Ross Boucher d85e8798c2 Create the args and namedArgs objects in Bootstrap.js, pass them along up to CPApplication. 2010-03-08 15:00:52 -08:00
Randall Luecke 6dbb4eedb7 Merge branch 'master' of git://github.com/280north/cappuccino 2010-03-08 10:56:56 -05:00
Francisco Ryan Tolmasky I 33b4b94426 Fix for loading bundles generating multiple did load callbacks.
Reviewed by me.
2010-03-08 01:03:52 -08:00
Francisco Ryan Tolmasky I 3fc99095e2 Fix bug in keyed unarchiving.
Reviewed by me.
2010-03-07 23:48:23 -08:00
Randall Luecke 8410198c37 Merge branch 'master' of git://github.com/280north/cappuccino 2010-03-08 00:58:28 -05:00
Francisco Ryan Tolmasky I d1b325052d Fixed incorrect import.
Reviewed by me.
2010-03-07 21:56:29 -08:00
Randall Luecke 4c4b42833a Added -selectedColumn to the tableview. 2010-03-08 00:00:28 -05:00
Randall Luecke 519a9300e2 Merge branch 'master' of git://github.com/280north/cappuccino 2010-03-07 23:39:41 -05:00
Tom Robinson 91dda1f759 Remove warning from press. 2010-03-07 18:24:45 -08:00
Tom Robinson 65e12269d1 Fix flatten 2010-03-07 18:24:45 -08:00
Francisco Ryan Tolmasky I 9d2474b142 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-07 17:57:36 -08:00
Ross Boucher e804d44934 Slight error in my sprintf change. Fixed here. 2010-03-07 17:54:57 -08:00
Francisco Ryan Tolmasky I 961628d8d3 Fix for count global and also cleaned up display names in CFDictionary.
Reviewed by me.
2010-03-07 17:53:44 -08:00
Randall Luecke 7522751fd2 Merge branch 'master' of git://github.com/280north/cappuccino 2010-03-07 20:50:29 -05:00
Ross Boucher e3dc9fd96b Make sprintf no longer global, instead ObjectiveJ.sprintf. 2010-03-07 17:41:33 -08:00
Ross Boucher c3ac076d13 Remove base64 globals, move to CFData. Update tests. 2010-03-07 17:22:29 -08:00
Francisco Ryan Tolmasky I 1e02511022 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-07 17:20:56 -08:00
Francisco Ryan Tolmasky I 071a772208 Fix for drawRect: not working in IE 8 anymore. (Close chrome meta tag).
Reviewed by me.
2010-03-07 17:20:26 -08:00
Ross Boucher 78711163c5 Update the README to more accurately reflect the process. 2010-03-07 17:03:29 -08:00
Ross Boucher 3f005ff476 Add a "demos" task which downloads the demos repo and zips each demo as part of the deploy process. 2010-03-07 17:03:28 -08:00
Emmanuel MaillardandRoss Boucher ddd399631f - correct CPEmptyRange documentation 2010-03-07 17:03:28 -08:00
Francisco Ryan Tolmasky I c0ce830456 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-07 16:55:33 -08:00
Francisco Ryan Tolmasky I 481555f11f Further perfomance improvements.
Reviewed by me.
2010-03-07 16:54:43 -08:00
Tom Robinson 20327d8fb6 Move CPLog css file inline, remove redundant ANSI control sequence stuff, automatically use command line tool name in CPLog title. 2010-03-07 16:18:26 -08:00
Francisco Ryan Tolmasky I a377e15368 Added display names to Executables and FileExecutables.
Reviewed by me.
2010-03-07 15:51:49 -08:00
Francisco Ryan Tolmasky I 52ca9628fd Added display names to CFURL.
Reviewed by me.
2010-03-07 15:44:59 -08:00
Francisco Ryan Tolmasky I db1454c4fe Add display names to runtime methods.
Reviewed by me.
2010-03-07 15:36:32 -08:00
Francisco Ryan Tolmasky I 6845bd4598 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-07 14:34:12 -08:00
Francisco Ryan Tolmasky I f02286e3f5 Update press to support new fileExecutableSearcher style.
Reviewed by me.
2010-03-07 14:33:39 -08:00
Ross Boucher d473c251e6 Update undo/redo key equivalents to match the new menu code from a while ago. 2010-03-07 14:10:18 -08:00
Francisco Ryan Tolmasky I 64a401125d Further performance improvements and better debug values for CFDictionary and CFMutableDictionary.
Reviewed by me.
2010-03-07 12:49:37 -08:00
Francisco Ryan Tolmasky I 68ae1af13f Some performance improvements in CPKeyedUnarchiver.
Reviewed by me.
2010-03-07 12:24:59 -08:00
Randall Luecke f2165af48f Merge branch 'master' of git://github.com/280north/cappuccino 2010-03-07 10:30:17 -05:00
Francisco Ryan Tolmasky I 62b1dbbc74 Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-07 03:58:48 -08:00
Francisco Ryan Tolmasky I 0881d86998 A number of performance improvements in the loader.
Reviewed by me.
2010-03-07 03:58:21 -08:00
Tom Robinson aff4883222 Initial fixes for "flatten". Loads everything correct but AppKit does not start completely. 2010-03-07 02:16:01 -08:00
Tom Robinson fbed77fc64 Fix press yet again. 2010-03-07 00:53:08 -08:00
Francisco Ryan Tolmasky I 276e8b948d Removed remaining Rakefiles.
Reviewed by me.
2010-03-06 22:32:52 -08:00
Francisco Ryan Tolmasky I 2edcfbda35 Updated version strings in preparation for 0.8.0 Release Candidate.
Reviewed by me.
2010-03-06 22:30:51 -08:00
Tom Robinson 22cdd6e04d Cleanup nib2cib logging. 2010-03-06 21:21:08 -08:00
Tom Robinson 3518813145 Switch nib2cib to use more robust args parsing. 2010-03-06 21:21:08 -08:00
Tom Robinson a453412d5b Strip invalid characters from plist before attempting to parse (so far just ESC) 2010-03-06 21:21:08 -08:00
Ross Boucher 55b438e8c1 Use sudo to update jake packages if sudo-install was the task.
Closes #525.
2010-03-06 20:17:51 -08:00
Tom Robinson ce749302a5 Fix nib2cib .nib support. Also use array form of OS.popen to avoid path escaping issues. 2010-03-06 19:34:56 -08:00
Francisco Ryan Tolmasky I 3356175f3e Merge branch 'master' of git@github.com:280north/cappuccino 2010-03-06 16:54:31 -08:00
Francisco Ryan Tolmasky I 50ff20ba33 Further reduction of CFURL creation and caching of method values.
Reviewed by me.
2010-03-06 16:53:24 -08:00
Francisco Ryan Tolmasky I d3ba51104e Create much fewer CFURLs.
Reviewed by me.
2010-03-06 16:20:20 -08:00
Francisco Ryan Tolmasky I 981c184c20 A few performance improvements in Objective-J loading.
Reviewed by me.
2010-03-06 16:01:03 -08:00
Randall Luecke e3a65a1847 Added preparatory support for group items in CPOutlineView. 2010-03-06 18:46:49 -05:00
Ross Boucher 64eb440ea3 nib2cib will now launch a rhino process in order to get the size of images. 2010-03-06 15:39:46 -08:00
Ross Boucher 994383f73a Remove print statement. 2010-03-06 15:32:07 -08:00
Francisco Ryan Tolmasky I 89bd5f5b93 Fixed remaining failing CPURL tests and removed prints from CFURL tests.
Reviewed by me.
2010-03-06 12:10:57 -08:00
Francisco Ryan Tolmasky I ae25f489ad Add back in accidentally removed "baseURL".
Reviewed by me.
2010-03-06 11:40:24 -08:00
Francisco Ryan Tolmasky I 510eaabcfb Fix some MHTML generation stuff.
Reviewed by me.
2010-03-06 01:57:10 -08:00
Francisco Ryan Tolmasky I 875e177219 Added global versions of objj_importFile and objj_executeFile, as well as objj_import with a deprecation warning.
Reviewed by me.
2010-03-06 01:26:27 -08:00
Francisco Ryan Tolmasky I f8f62e1473 Merge branch 'master' into URL 2010-03-06 01:15:07 -08:00
Ross Boucher c1a70a3aa2 Closes #528.
Update CPScrollView to use more modern key command parsing.
2010-03-06 01:07:46 -08:00
Ross Boucher c514fd7a08 Fix an issue where window levels weren't kept in sync with dom window layers.
Closes #507.
2010-03-06 00:57:59 -08:00
Ross Boucher 3cefc86fbf Whitespace fix. 2010-03-06 00:55:39 -08:00
Ross Boucher 0c66606d1d Closes #517.
Adds missing delegate accessor.
2010-03-06 00:01:36 -08:00
Francisco Ryan Tolmasky I 05fc35a5b9 Merge branch 'master' of git@github.com:280north/cappuccino into URL 2010-03-05 23:59:05 -08:00
Tom Robinson 2425838ea6 Add install-symlinks Jake task. 2010-03-05 23:30:39 -08:00
Francisco Ryan Tolmasky I 20d117e129 Further movement to CFURL.
Reviewed by me.
2010-03-05 22:56:15 -08:00
Francisco Ryan Tolmasky I 8f08c33bcc Update CPBundle to better support CPURLs.
Reviewed by me.
2010-03-05 22:44:59 -08:00
Francisco Ryan Tolmasky I d7f0bf6a24 Support root level apps.
Reviewed by me.
2010-03-05 22:34:04 -08:00
Francisco Ryan Tolmasky I 5afe6fea3c Better support for exotic main file locations.
Reviewed by me.
2010-03-05 21:54:22 -08:00
Francisco Ryan Tolmasky I 9441739839 Fixed incorrect method call.
Reviewed by me.
2010-03-05 21:23:25 -08:00
Francisco Ryan Tolmasky I 8727d96a06 Merge branch 'master' into URL 2010-03-05 21:14:07 -08:00
Francisco Ryan Tolmasky I b2ffe7e509 Further cleaning and bringing CPURL up to speed with CFURL.
Reviewed by me.
2010-03-05 21:11:53 -08:00
Randall Luecke 119c950b53 Merge branch 'master' of git://github.com/280north/cappuccino 2010-03-05 23:39:31 -05:00
Ross Boucher 29a0de3636 Fix document title's not being synced properly. 2010-03-05 20:09:23 -08:00
Francisco Ryan Tolmasky I aa3e3c7e71 Better support for MHTML URLs.
Reviewed by me.
2010-03-05 16:34:27 -08:00
Francisco Ryan Tolmasky I eb00953c60 Merge branch 'master' into URL 2010-03-05 16:06:42 -08:00
Francisco Ryan Tolmasky I c4b255ae46 Performance improvements to CFURL internals.
Reviewed by me.
2010-03-05 16:06:05 -08:00
Ross Boucher d3547dd892 Merge branch 'master' into keywindows 2010-03-05 14:45:56 -08:00
Ross Boucher 7d1c7b2907 Add missing accessor to CPImageView, and fix nib2cib support for image scaling.
Closes #523.
2010-03-05 13:46:41 -08:00
Randall Luecke d0999fa5d5 Additional fixes for drag and drop in the TableView after OutlineView merge. 2010-03-05 16:20:24 -05:00
Ross Boucher c478afee0f Add a missing import to CPTheme.
Closes #527.
2010-03-05 12:38:59 -08:00
Paul BaumgartandRoss Boucher ab196e75c1 Fix missing throw in Preprocessor to report an error on unmatched brackets. Closes gh-524 2010-03-05 12:34:57 -08:00
saikatandRoss Boucher 50b5c21fcf Fixes calling selectText in the text field's delegate's controlTextDidFocus: method. 2010-03-05 11:06:00 -08:00
saikatandRoss Boucher 47bc7e812d Fix for issue #511 - disabling a menu item in the menu item's action 2010-03-05 11:05:56 -08:00
saikatandRoss Boucher ad5f574fb7 Fix for issue #511 - disabling a menu item in the menu item's action 2010-03-05 10:49:42 -08:00
saikatandRoss Boucher 9537a62ab1 Fixes calling selectText in the text field's delegate's controlTextDidFocus: method. 2010-03-05 10:49:23 -08:00
Randall Luecke dc7bd3355d Fixed wrong import for outlineview test. 2010-03-05 03:59:37 -05:00
Randall Luecke d76d9bcfad Fixed bugs with drag and drop in tableview after outlineview drag and drop merge. 2010-03-05 03:37:19 -05:00
klaaspieterandRandall Luecke 440eed77cf Merge commit 'klaaspieter/outlineview' into outlineview
Conflicts:
	AppKit/CPDragServer.j
	AppKit/CPTableView.j
	Tests/Manual/TableTest/AppController.j
2010-03-05 02:40:47 -05:00
Francisco Ryan Tolmasky I b906fbea29 Merge branch 'master' into URL 2010-03-04 15:04:08 -08:00
Ross Boucher af148137d6 Merge branch 'master' into keywindows 2010-03-04 14:33:09 -08:00
Randall Luecke 64357fde0d Fixed bug where you could drag non-existant rows. Closes #520 and #521 2010-03-04 14:04:15 -05:00
Ross Boucher 7512a45cda Add #if PLATFORM(DOM) protection to several additional classes. 2010-03-03 21:20:00 -08:00
Ross Boucher e034abef82 Add a test for the initWithItems:copy: fix. 2010-03-03 20:38:56 -08:00
Scott KyleandRoss Boucher 0b5db9c4bd Fix CPArray initWithArray: copyItems: to actually work 2010-03-03 20:36:49 -08:00
Ross Boucher 3cd763aabb Add #if PLATFORM(DOM) in a missing place in CPView. 2010-03-03 19:42:16 -08:00
Ross Boucher 1a881fb501 Merge branch 'master' into keywindows 2010-03-03 14:43:43 -08:00
Ross Boucher 2f68804279 Revert "fix for scroller still being drawn below resize indicator on the first reflect of the clipview."
This reverts commit fa63551b42.
2010-03-03 14:43:25 -08:00
Ross Boucher 60d15e2983 Revert "fix for scrollviews being drawn below window resize indicator."
This reverts commit 18a0deb678.
2010-03-03 14:43:19 -08:00
Ross Boucher 628488f7aa Revert "fix for scroller still being drawn below resize indicator on the first reflect of the clipview."
This reverts commit fa63551b42.
2010-03-03 14:42:29 -08:00
Ross Boucher 149308bc89 Revert "fix for scrollviews being drawn below window resize indicator."
This reverts commit 18a0deb678.
2010-03-03 14:42:15 -08:00
Francisco Ryan Tolmasky I b4fa971007 Merge branch 'master' into URL 2010-03-03 11:40:08 -08:00
Tom Robinson b30f10ca46 Enquote NARWHALOPT package paths to fix building in directories with spaces.
Bump jake version to 0.1.5
2010-03-03 10:50:53 -08:00
Ross Boucher da725f6ffc Merge branch 'master' of github.com:280north/cappuccino into keywindows 2010-03-03 09:40:25 -08:00
Tom Robinson b0d62a8608 Add option to automatically upgrade packages for CI server, etc. 2010-03-03 09:08:02 -08:00
Tom Robinson 3da2d3718b Bump required Narwhal version to 0.2.2 2010-03-03 09:03:20 -08:00
Francisco Ryan Tolmasky I 4bd6aca0c0 Cache URLs for performance improvement.
Reviewed by me.
2010-03-03 02:36:40 -08:00
Francisco Ryan Tolmasky I e90c84ee81 Merge branch 'master' into URL 2010-03-03 01:43:40 -08:00
Francisco Ryan Tolmasky I 45b8f83cdd Revert "Revert "Revert "Enquote NARWHALOPT package paths to fix building in directories with spaces."""
This reverts commit cb939baca0.
2010-03-03 01:41:13 -08:00
Francisco Ryan Tolmasky I c8e0aa9cb4 Merge branch 'master' into URL 2010-03-03 01:36:15 -08:00
Francisco Ryan Tolmasky I 7a486db45f Update to reverted jake version.
Reviewed by me.
2010-03-03 01:35:02 -08:00
Francisco Ryan Tolmasky I 4634c6cf3b Merge branch 'master' into URL 2010-03-03 01:05:56 -08:00
Francisco Ryan Tolmasky I eb57d14673 Further migration from file paths to CFURLs.
Reviewed by me.
2010-03-03 01:04:25 -08:00
Tom Robinson cb939baca0 Revert "Revert "Enquote NARWHALOPT package paths to fix building in directories with spaces.""
This reverts commit db8a277960.
2010-03-02 17:33:39 -08:00
Tom Robinson db8a277960 Revert "Enquote NARWHALOPT package paths to fix building in directories with spaces."
This reverts commit 783159ee44.
2010-03-02 16:38:24 -08:00
Ross Boucher 398d61097c Typo in miniaturize: 2010-03-02 15:27:40 -08:00
Ross Boucher 4a43e4fda6 Overhaul of the key/main window status, esp. with respect to assigning new values after a window
closes or after a window is minimized, and with app activation/deactivation.
2010-03-02 15:16:10 -08:00
Tom Robinson 783159ee44 Enquote NARWHALOPT package paths to fix building in directories with spaces. 2010-03-02 11:47:29 -08:00
luddepandRoss Boucher fa63551b42 fix for scroller still being drawn below resize indicator on the first reflect of the clipview. 2010-03-02 11:44:31 -08:00
luddepandRoss Boucher 18a0deb678 fix for scrollviews being drawn below window resize indicator. 2010-03-02 11:44:25 -08:00
cacaodevandRoss Boucher f7c46855b8 Added missing @imports in AppKit.j 2010-03-02 11:29:09 -08:00
Ross Boucher e67539c3b1 Merge branch 'master' of github.com:280north/cappuccino 2010-03-02 11:20:38 -08:00
Ross Boucher b8d06521b2 Fix a bogus Regex in json2.js. Closes #513. 2010-03-02 11:20:02 -08:00
Tom Robinson 3225d980c5 Bump required Jake version to 0.1.3 to fix build problems with Rhino. 2010-03-02 02:09:49 -08:00
Tom Robinson 9c3a579ff8 Exit with error from capp gen 2010-03-02 01:40:00 -08:00
Tom Robinson 92b5b34d17 Add --index option to flatten to specify an alternate index.html file. 2010-03-02 00:52:19 -08:00
Ross Boucher 47e8696b9f Missing string close. 2010-03-02 00:51:46 -08:00
Tom Robinson 7938384162 Fix "capp gen -l" 2010-03-01 18:31:00 -08:00
Ross Boucher 01aec1f78e If the mainWindow tries to become main again, just return early. 2010-03-01 18:07:38 -08:00
Nicholas Small 67f35c7b74 Update deprecated sendSynchronousRequest:returningResponse:error: to sendSynchronousRequest:returningResponse: 2010-03-01 17:03:00 -05:00
Ross Boucher d600df4585 Make doxygen recursive. 2010-03-01 12:14:27 -08:00
Francisco Ryan Tolmasky I f3a0710059 Merge branch 'master' into URL 2010-02-27 13:36:56 -08:00
Ross Boucher 203e0d150b Update table headers to return the cursor to normal if the window doesn't accept mousemoved events. 2010-02-27 12:22:52 -08:00
Ross Boucher efd699a044 Add -isEqual: and -description to CPFont. Add a unit test for -isEqual:
Closes #506.
Closes #505.
2010-02-27 12:00:44 -08:00
Ross Boucher dbe0ca0adc Expand macros in the documentation generation. 2010-02-27 10:31:05 -08:00
Francisco Ryan Tolmasky I 5316cabf30 Fix for capp config <key> <value> not working.
Reviewed by me.
2010-02-26 23:35:27 -08:00
cacaodevandRandall Luecke 9a16921a32 CPTableHeaderView: Avoid vertical lines disapearring when autoresizing the table.
Fix cursor updates disabled when table autoresizing is NoAutoresizing.
                   nil check table headerView before sending a message to itself or to a table column header view.

Conflicts:

	AppKit/CPTableHeaderView.j
2010-02-26 11:35:49 -05:00
Tom Robinson f5edf2a4c2 Cleanup press and flatten arguments. 2010-02-25 19:50:06 -08:00
Ross Boucher cfdcfdbc99 Update the default jakefiles with bug fixes and convenience tasks. 2010-02-25 16:34:47 -08:00
Tom Robinson ad99dca6ac Move tools to cappuccino package's "bin" directory 2010-02-25 15:32:24 -08:00
Francisco Ryan Tolmasky I fbcc81056b Merge branch 'master' into URL
Conflicts:
	Objective-J/FileExecutable.js
2010-02-25 13:59:00 -08:00
Francisco Ryan Tolmasky I 756877b94c Removed some unecessary uses of sprintf.
Reviewed by me.
2010-02-25 12:38:50 -08:00
Ross Boucher 68d30c8802 Replace the old support for window.update_progress with OBJJ_PROGRESS_CALLBACK.
Function gets passed float from 0 to 1, the total size, and the last loaded bundle path, in that order.
2010-02-25 11:39:08 -08:00
Tom Robinson 555b83a359 "flatten" now inlines functions 2010-02-25 00:57:21 -08:00
Tom Robinson ff43be6d7b Added LoadTimeTest app to test load times. 2010-02-25 00:57:21 -08:00
Tom Robinson 7defbce1dd Fix more incorrect type annotations 2010-02-24 22:45:34 -08:00
Ross Boucher ef5aead17d Disabled resize cursor support in CPTableViewHeader 2010-02-24 21:22:07 -08:00
Ross Boucher 585b70a6a9 Fix whitespace errors. 2010-02-24 20:10:08 -08:00
Scott KyleandRoss Boucher b24a78bdd5 CPTableView delegate method tableView:setObjectValue:forTableColumn:row: is now being called for cells with CPButton data views, as it should. Fixes bug #466 2010-02-24 20:06:24 -08:00
Ross Boucher f305621ade Merge branch 'master' of github.com:280north/cappuccino 2010-02-24 17:47:09 -08:00
Ross Boucher 24198a7890 Add a missing import, exposed by press. 2010-02-24 17:46:47 -08:00
Tom Robinson 2d477b38bc Fix bootstrap when run within another sea and check for writability of /usr/local, defaulting to $HOME/narwhal 2010-02-24 16:16:27 -08:00
Paul BaumgartandTom Robinson 48afc5639e re-factor shell_config_file to make bootstrap.sh self-contained 2010-02-24 15:47:22 -08:00
Francisco Ryan Tolmasky I 7b932fbf4a Merge branch 'master' into URL 2010-02-24 11:26:46 -08:00
Francisco Ryan Tolmasky I 39f3e7b292 Fix for menus not redrawing correctly after closing in non-Safari browsers.
Closes #495.

Reviewed by me.
2010-02-24 02:56:38 -08:00
Randall Luecke 49f3038737 Merge branch 'master' of git://github.com/280north/cappuccino 2010-02-24 02:27:32 -05:00
Randall Luecke f7a40a071b Added proper resize cursor support for CPSplitView and cleaned up some whitespace. 2010-02-24 02:24:36 -05:00
Tom Robinson 3a1ebcaf3f Allow interleaved arguments in "capp gen" (requires latest Narwhal) 2010-02-23 20:07:17 -08:00
Tom Robinson 3da1c4381c Setup automated builds. 2010-02-23 18:06:23 -08:00
Tom Robinson 9ff73e5e63 Make "capp" print usage if more than one file argument is given 2010-02-23 17:04:56 -08:00
Tom Robinson f3633c050b Add OBJJ_AUTO_BOOTSTRAP option to disable auto-bootstrapping. Fixes flatten race condition. 2010-02-23 15:41:52 -08:00
Francisco Ryan Tolmasky I 1ba828da18 Beginning transition from string paths to CFURLs.
Reviewed by me.
2010-02-23 15:11:10 -08:00
Ross Boucher 109725d613 Fix whitespace issues from the previous commit. 2010-02-23 11:34:58 -08:00
Klaas Pieter AnnemaandRoss Boucher 4bc8f01376 made sure the dragserver doesn't call prepareDrag if the last drag update returned CPDragOperationNone 2010-02-23 11:25:10 -08:00
Ross Boucher df20a6d6df Add a couple tests for bugs reported from Pivotal. They aren't ideal, though, because of the CPApp issue. 2010-02-23 11:07:53 -08:00
cacaodevandRoss Boucher e32963384e _CPKVCArray -indexOfObject: typo 2010-02-23 11:07:53 -08:00
Tom Robinson 03a9865ccb Remove warning from bootstrap.sh about narwhal-jsc failing on 10.5 2010-02-22 22:06:44 -08:00
Francisco Ryan Tolmasky I 7674b3aec6 Merge branch 'master' of git@github.com:280north/cappuccino 2010-02-22 18:50:00 -08:00
Francisco Ryan Tolmasky I 9c9a5bcd51 Fix for stream undefined.
Reviewed by me.
2010-02-22 18:48:13 -08:00
Tom Robinson 8948f7f43c Fix broken flatten bit due to loader changes. Refactor flatten into ObjectiveJFlattener which inherits from ObjectiveJRuntimeAnalyzer. 2010-02-22 18:41:19 -08:00
Tom Robinson ef4e86a124 Remove StaticResource.prototype.type() 2010-02-22 18:39:50 -08:00
Francisco Ryan Tolmasky I b9edc357f3 Fix for absolute paths working with <> includes.
Reviewed by me.
2010-02-22 14:50:25 -08:00
Francisco Ryan Tolmasky I 9353d0f95c Merge branch 'master' of git@github.com:280north/cappuccino 2010-02-22 14:30:46 -08:00
Francisco Ryan Tolmasky I 7defdd2a00 Fix for some files showing up as anonymous.
Reviewed by tlrobinson.
2010-02-22 14:27:30 -08:00
Tom Robinson 621e79fe33 Fixes press, objj-analysis-tools, etc broken due to changes to loader 2010-02-22 12:54:17 -08:00
Ross Boucher e759c5343b Add a missing import in CPButton, and a test to ensure you can create one on the command line. 2010-02-22 11:07:11 -08:00
Francisco Ryan Tolmasky I d879b25458 Re-enabled menu bar button support.
Closes #410.

Reviewed by me.
2010-02-22 02:12:11 -08:00
Francisco Ryan Tolmasky I ccffde6966 Merge branch 'master' of git@github.com:280north/cappuccino 2010-02-22 00:56:23 -08:00
Francisco Ryan Tolmasky I 1524f80418 Fix for toolbar item's sending their views as senders for actions (should be the item itself).
Closes #493.

Reviewed by me.
2010-02-22 00:49:35 -08:00
Tom Robinson bcbeb888f6 Various bootstrap.sh improvements (noprompt mode, etc) 2010-02-22 00:00:40 -08:00
Francisco Ryan Tolmasky I 7730aeb652 Merge branch 'master' of git@github.com:280north/cappuccino 2010-02-21 23:30:58 -08:00
Francisco Ryan Tolmasky I 272f938f2e Fix for CPData naming issues, added test cases, and fixed isEqual: for CPDictionary.
Reviewed by me.
2010-02-21 23:29:41 -08:00
Randall Luecke 5570a346c4 Imported CPOutlineView.j in AppKit. 2010-02-22 00:26:50 -05:00
Ross Boucher 2b90652a16 Add chrome frame tag for the benefit of those people who may have installed it. 2010-02-21 17:01:33 -08:00
Ross Boucher a58dd4678c Move NibApp to manual tests. 2010-02-21 17:01:33 -08:00
Randall Luecke 25f4574093 TableView now renders white background by default (like cocoa) thereby fixing a bug where Opera rendered the tableview with a black background if you did no specify alternating row colors. 2010-02-21 19:53:40 -05:00
Tom Robinson 733b9b731d Cleanup Jakefiles, enquote arguments, add built packages bin to PATH so ojtest runs / uses the correct Cappuccino, etc. 2010-02-21 15:42:56 -08:00
Francisco Ryan Tolmasky I 20637fc5e0 Added missing licenses and removed a bit of unused code.
Reviewed by me.
2010-02-21 13:52:51 -08:00
Francisco Ryan Tolmasky I c33e2ee51f Fixed a bug with objj_debug_typecheck incorrectly misidentifying empty string as not a CPString. Also fixed a number of type declarations after running with objj_msgSend_decorate(objj_typecheck_decorator); turned on.
Reviewed by me.
2010-02-21 13:37:20 -08:00
Francisco Ryan Tolmasky I 7ef59418dd Merge branch 'master' of git@github.com:280north/cappuccino 2010-02-21 13:10:55 -08:00
Francisco Ryan Tolmasky I 0805e58a94 Fix for objj_msgSend_reset errors when running debug.
Reviewed by me.
2010-02-21 13:10:31 -08:00
Ross Boucher 6ddeff2b21 Fix the remaining tests that were failing. 2010-02-21 13:02:52 -08:00
Francisco Ryan Tolmasky I 7433c38d92 Pulled @each out into a separate feature branch, so as to not conflict with the 0.8 work: http://github.com/280north/cappuccino/tree/@each .
Reviewed by me.
2010-02-21 12:31:13 -08:00
Tom Robinson 5f930ec840 Fix for press interpreting "." as "/" 2010-02-20 23:01:06 -08:00
Randall Luecke 0dd36b2275 Merge branch 'master' of git://github.com/280north/cappuccino 2010-02-20 17:46:09 -05:00
Randall Luecke 629428739d Fixed error when headerview was set to nil on the CPTableView. 2010-02-20 17:44:45 -05:00
Francisco Ryan Tolmasky I 7d7281480a Typo in last commit and forgot one change.
Reviewed by me.
2010-02-20 02:42:57 -08:00
Francisco Ryan Tolmasky I 666e2c0190 Updated press for changed names.
Reviewed by me.
2010-02-20 02:36:14 -08:00
Francisco Ryan Tolmasky I 3968d35cac Once again fix for Fix for accounting for non-Cappuccino libraries placing things on
Object.prototype and Don't recreate sprited resources every time, and fix a bug where two
bundle tasks in the same jakefile would conflict when creating sprited
resources.

Reviewed by me.
2010-02-20 02:24:54 -08:00
Francisco Ryan Tolmasky I 551677d6fd Removed no longer used file, and renamed HTTPRequest.js to CFHTTPRequest.js to match the class name change in the previous commit.
Reviewed by me.
2010-02-20 01:08:15 -08:00
Francisco Ryan Tolmasky I 85b029fad0 Merge branch 'master' of git@github.com:280north/cappuccino 2010-02-20 01:05:04 -08:00
Francisco Ryan Tolmasky I 841ed9ea89 Major cleanup of globals and exports. Removed many accidental globals and no more need for eval in the initialization process. Also fixes Theme Showcase.
Reviewed by me.
2010-02-20 01:04:17 -08:00
Randall Luecke 74fd7eb793 Merge branch 'master' of git://github.com/280north/cappuccino 2010-02-20 03:59:40 -05:00
BlairDuncanandRandall Luecke 26df9e861f Fix for cursor showing resize indicator when column isn't user resizable. 2010-02-20 03:58:38 -05:00
Tom Robinson 338860d05b Allow additional frameworks to be copied by capp gen. Use args parser. 2010-02-19 18:27:43 -08:00
Ross Boucher b7df6c1480 Fix support for MHTML. This uses feature detection to determine if DataURLs, and then if MHTML is supported, and falls back on the original unsprited images.
Closes #376.
2010-02-19 16:48:57 -08:00
Tom Robinson b2179f14ab Cleanup Jakefiles:
* require common.jake first
* require Objective-J/Cappuccino stuff only when needed (automatically requiring these caused too many problems)
* remove useless shebangs, cleanup whitespace
2010-02-19 16:09:39 -08:00
Paul BaumgartandRoss Boucher 99b43fed7f Add support for sudo-install on systems with sudo compiled w/ --with-secure-path 2010-02-19 13:01:11 -08:00
Paul BaumgartandRoss Boucher 25dfcd38a7 Fix case on require() parameter ("OS" -> "os") 2010-02-19 13:00:31 -08:00
Tom Robinson a6d2c42402 Only log errors in setupEnvironment. 2010-02-19 02:43:39 -08:00
Francisco Ryan Tolmasky I fd8271396d Fix for accounting for non-Cappuccino libraries placing things on Object.prototype.
Reviewed by me.
2010-02-19 02:08:34 -08:00
Francisco Ryan Tolmasky I 19ca6a342e Merge branch 'master' of git@github.com:280north/cappuccino 2010-02-19 00:43:18 -08:00
Francisco Ryan Tolmasky I 7819e174f1 Added setString: to CPData which sits on top of setSerializedPlistObject:.
Reviewed by me.
2010-02-19 00:42:23 -08:00
Randall Luecke 7cd6d026a2 Merge branch 'master' of git://github.com/280north/cappuccino 2010-02-19 03:24:59 -05:00
Randall Luecke c48d306195 Initial refactor/rewrite of auto resizing columns. 2010-02-19 03:23:29 -05:00
Francisco Ryan Tolmasky I 3a9845f784 Don't recreate sprited resources every time, and fix a bug where two bundle tasks in the same jakefile would conflict when creating sprited resources.
Reviewed by me.
2010-02-18 23:32:11 -08:00
Francisco Ryan Tolmasky I 94d3053232 Added CommonJS extensions to CFPropertyList.
Reviewed by me.
2010-02-18 15:28:30 -08:00
Francisco Ryan Tolmasky I b078169adf Fix for slight name change.
Reviewed by me.
2010-02-18 14:05:33 -08:00
Francisco Ryan Tolmasky I 38c4dd408c Fix for CPBundle loading all code. Fixes external frameworks with nib2cib.
Reviewed by me.
2010-02-18 13:55:30 -08:00
Francisco Ryan Tolmasky I 8beb9dfed0 Merge branch 'master' of git@github.com:280north/cappuccino 2010-02-18 11:18:17 -08:00
Francisco Ryan Tolmasky I eef9549e96 Fix for HelloWorld/ not working when HelloWorld/index.html does.
Closes #483.

Reviewed by me.
2010-02-18 11:17:21 -08:00
Randall Luecke 82ac98ddc7 Initial refactoring of init with a fix for gradients not being initialized correctly. Initial refactoring of uniform column auto resizing to prep for a rewrite. 2010-02-18 11:09:07 -05:00
cacaodevandRandall Luecke 3d52ffcbdc CPTableView: fix shiftKey+selection to match cocoa behavior. closes issue #433 2010-02-18 02:30:57 -05:00
Randall Luecke 3fad4635b0 Updated tabletest to include new source list selection styles, also cleaned up the tableview a bit, and made the default selection style of the outlineview use the source list gradient. 2010-02-18 02:21:40 -05:00
cacaodevandRandall Luecke b0b19328a8 CPTableView: CPTableViewSelectionHighlightStyleSourceList for canvas browsers. Removed references to selectionHighlightColor. 2010-02-18 01:27:06 -05:00
Francisco Ryan Tolmasky I 9fd79488f8 Merge branch 'master' of git@github.com:280north/cappuccino 2010-02-17 21:13:14 -08:00
Francisco Ryan Tolmasky I cebe31857a Fix for image loading problem.
Reviewed by me.
2010-02-17 21:12:14 -08:00
Ross Boucher 1961829414 Correct a use of global. to be GLOBAL_NAMESPACE. at least until we have a better solution. 2010-02-17 19:31:11 -08:00
Ross Boucher 3e5bdec033 Merge branch 'master' of github.com:280north/cappuccino 2010-02-17 19:22:02 -08:00
Ross Boucher 5789021a76 modify the copyright date 2010-02-17 19:20:44 -08:00
Tom Robinson 6bf0319c51 Add ojdepcheck tool to print out missing @imports 2010-02-17 18:09:55 -08:00
Tom Robinson 8f519caa77 Remove old shrinksafe jars 2010-02-17 18:02:32 -08:00
Ross Boucher a38be80a86 Revert "A better fix for the IE bug. Rather than introduce the secondary global and the eval, just refer to the actual global object (works in any javascript env)."
This reverts commit d40619aca0.
2010-02-17 17:37:46 -08:00
Ross Boucher 81b72fc571 Throw a syntax error if we don't recognize the @accessors syntax. 2010-02-17 17:27:37 -08:00
Ross Boucher 91681d7846 Move more constants to CPControl.j 2010-02-17 17:06:09 -08:00
Ross Boucher d40619aca0 A better fix for the IE bug. Rather than introduce the secondary global and the eval, just refer to the actual global object (works in any javascript env). 2010-02-17 16:55:07 -08:00
Ross Boucher 1328bc732f Move around some imports and constant declarations. 2010-02-17 16:29:57 -08:00
Ross Boucher 060f65b27e Use CPLog instead of console 2010-02-17 16:24:04 -08:00
Tom Robinson 364669f527 Remove formatting from capp usage message for now. 2010-02-17 16:15:10 -08:00
Ross Boucher f4042b9d4b Fix an error in IE6 with XMLHttpRequest being undefined 2010-02-17 16:09:58 -08:00
Ross Boucher c750b696d2 Merge branch 'master' of github.com:280north/cappuccino 2010-02-17 16:08:58 -08:00
Ross Boucher 02cdee6c75 Fix a missing import. 2010-02-17 16:08:11 -08:00
Tom Robinson c4a824b5db More bootstrap improvements: follow narwhal symlinks to actual installation 2010-02-17 15:18:07 -08:00
Tom Robinson 7f31c0632d flatten: build nodes relative to cwd 2010-02-17 14:57:33 -08:00
Francisco Tolmasky 96ee92695c Merge branch 'jake'
Conflicts:
	Tools/press/objj-analysis-tools.j
2010-02-17 13:50:18 -08:00
Francisco Ryan Tolmasky I 80b252a744 Merge branch 'loader' into jake 2010-02-17 13:40:22 -08:00
Francisco Ryan Tolmasky I 4f50f8b83f Fix for IE Bug that caused stack overflow at line 0 when loading Objective-J every time.
Reviewed by me.
2010-02-17 13:39:15 -08:00
Francisco Ryan Tolmasky I df895b9529 Treat extensionless files as Objective-J.
Reviewed by ross.
2010-02-16 19:31:31 -08:00
Tom Robinson f9e9e51352 A couple fixes in flatten 2010-02-16 18:21:36 -08:00
Ross Boucher 27e99344bd Make nib2cib quieter by default. Prints only fatal error messages.
Pass the -v flag to print warnings, and -vv or --verbose to print all messages.

Closes #475.
2010-02-16 16:59:44 -08:00
Ross Boucher 32572844fd Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-16 16:37:24 -08:00
Ross Boucher a77e67e578 Add support for keyboard navigation in CPCollectionView 2010-02-16 16:36:40 -08:00
Francisco Ryan Tolmasky I fb9cd1ef93 Don't Objective-J preprocess non-.j files.
Reviewed by me.
2010-02-16 16:23:03 -08:00
Ross Boucher 93722f6a7d Fix a bug where any @ added accessors to ivar declarations.
Closes #474.
2010-02-16 15:50:04 -08:00
Francisco Ryan Tolmasky I 76da7466ec Fix for CPDictionary CPFastEnumeration.
Reviewed by me.
2010-02-16 13:51:02 -08:00
Stephen IerodiaconouandRoss Boucher 6b3c95f09f Fix for issue #473. Call setEnabled from _CPToolbarItemView updateFromItem. 2010-02-16 10:43:48 -08:00
Francisco Ryan Tolmasky I 81110ddba7 Further performance improvements.
Reviewed by me.
2010-02-16 02:41:15 -08:00
Francisco Ryan Tolmasky I 64fd9f615c Additional performance improvements to CPFastEnumeration.
Reviewed by me.
2010-02-16 02:04:31 -08:00
Randall Luecke 213df88766 Merge branch 'loader' of git://github.com/280north/cappuccino into loader 2010-02-16 03:58:22 -05:00
Tom Robinson a26750d4f4 Fixed objj arguments parsing 2010-02-16 00:57:50 -08:00
Randall Luecke 72edd7376e temp fix for auto resizing when user manually resizes. Uniform resizing is still broken. 2010-02-16 03:56:17 -05:00
Randall Luecke 948e9ae139 Merge branch 'loader' of git://github.com/280north/cappuccino into loader 2010-02-16 03:43:22 -05:00
Francisco Ryan Tolmasky I ae357d1a2b Support for post and pre order CPFastEnumration for CPTreeNode. In order and level order remain.
Reviewed by me.
2010-02-16 00:41:20 -08:00
Randall Luecke 59756ff1b3 Made the hit test area for the column resizing a bit smaller. 2010-02-16 03:40:05 -05:00
Klaas Pieter Annema 2908e453e8 Merge branch 'jake' into outlineview 2010-02-16 09:39:49 +01:00
Klaas Pieter Annema 7b1ffc885f Merge branch 'jake' of git://github.com/280north/cappuccino into jake 2010-02-16 09:39:32 +01:00
Randall Luecke 95364b1d31 Tableview fixes including setMaxWidth reset on columns, added grid line to cornerview, cleaned up width validation in sizeLastColumnToFit, and cleaned up TableTest. 2010-02-16 03:00:49 -05:00
Ross Boucher f3257c0847 Add trunaction defaults to the table view cells 2010-02-15 23:05:23 -08:00
Ross Boucher eb0fc35c8f Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-15 23:05:10 -08:00
Ross Boucher 3dccd93093 Fix a typo. Closes #380. 2010-02-15 23:04:47 -08:00
Francisco Ryan Tolmasky I 8929199082 Add CPFastEnumeration support for CPEnumerator.
Reviewed by me.
2010-02-15 22:48:28 -08:00
Klaas Pieter Annema 20f6a57b3a - made the proposed drag row calculations more accurate when a tableview has non-default row height or inter-cell spacing
- fixed a bug in the dragged row at point calculation
2010-02-16 07:45:19 +01:00
Francisco Ryan Tolmasky I db949728dd Add CPFastEnumeration support to CPSet and CPNull.
Reviewed by me.
2010-02-15 22:44:52 -08:00
Francisco Ryan Tolmasky I 92d28e468e Autogenerate the index parameter for Fast Enumeration, and add Fast Enumeration support to CPIndexSet.
Reviewed by me.
2010-02-15 22:34:50 -08:00
Francisco Ryan Tolmasky I f95c3ca46a Adds fast enumeration to Cappuccino. Currently support for Arrays, dictionaries, single objects, and nil.
Closes #472.

Reviewed by me.
2010-02-15 21:46:50 -08:00
Ross Boucher 477b6bcdc5 Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-15 21:28:58 -08:00
Ross Boucher 3e40deba5f Fix a lot of style issues.
Change a 1px value.
Closes #444.
2010-02-15 21:27:27 -08:00
Tom Robinson 7d9bd25270 Disable bootstrap installing prebuilt packages 2010-02-15 21:26:49 -08:00
Tom Robinson c201990cb0 Switch compressor to use CommonJS packages for ShrinkSafe, etc. 2010-02-15 21:26:02 -08:00
Tom Robinson 289df53fb4 Disable bootstrap installing prebuilt packages 2010-02-15 21:26:02 -08:00
Ross Boucher 62788423a1 Add missing accessors. Closes #452. 2010-02-15 18:32:45 -08:00
Ross Boucher 8617990206 Add much better support for CPTableView to nib2cib. 2010-02-15 17:28:35 -08:00
cacaodevandRandall Luecke 2d8f2b328f Fixed a bug where column selection code was trying to highlight unexposed data views 2010-02-15 11:09:16 -05:00
Francisco Ryan Tolmasky I 833896e267 Renaming file to match class renaming.
Reviewed by me.
2010-02-14 19:17:56 -08:00
Francisco Ryan Tolmasky I f12b4520f6 Some renaming.
Reviewed by me.
2010-02-14 19:17:50 -08:00
Randall Luecke 2564003c85 Added new aristo resources for CPTableView sorting. 2010-02-14 21:37:03 -05:00
cacaodevandRandall Luecke c36b8f2257 CPTableView: -setHighlightedTableColumn: argument should be a CPTableColumn 2010-02-14 21:33:47 -05:00
cacaodevandRandall Luecke d413fbe0ed Fix for indentations not respected when resizing an outlineview column. Closes issue #470 2010-02-14 21:33:32 -05:00
Randall Luecke 4237000fc9 TableView:
Set a CPThemeStateHighlighted for both selecting and sorting.
Do not change sort descriptors when selecting with a modifier flag.

Conflicts:

	AppKit/CPTableView.j
2010-02-14 21:33:20 -05:00
cacaodevandRandall Luecke 5131aff352 Column sorting : Sort descriptors, sort indicator image, highlighted column.
Column resizing : Fixed bug where last column could not be resized.
                  Left arrow cursor when reaching maxWidth.
                  Moved table selection code to CPTableView.
                  Disable automatic resizing when user is resizing column
		  Partially fixed uniform resizing not prop. to columns width.
2010-02-14 21:32:07 -05:00
Francisco Ryan Tolmasky I f77f52802c Fix for new loader not working when app lives in the root directory of a website.
Reviewed by me.
2010-02-14 16:26:54 -08:00
Francisco Ryan Tolmasky I d52ab34421 Better Cib loading that doesn't make assumptions about the asynchronisity of the load.
Reviewed by me.
2010-02-14 12:23:47 -08:00
Francisco Ryan Tolmasky I 81e4c26b38 Fix for properly handling XMLHTTPRequests with files that don't exist when using file:// URL's in FireFox.
Reviewed by me.
2010-02-14 12:22:37 -08:00
Ross Boucher 1eed1901e9 Add some documentation to CPTableColum's setDataView: method.
Closes #315.
2010-02-13 22:33:36 -08:00
Ross Boucher a8b1c7bce1 Fix a number of segmented control bugs. Among other things, the disabled state is respected per segment.
Closes #386.

Also fixes the error where right side of segments would often not be visible.
Also fixes the error which caused the right and left bezel images to not show as disabled ever.
2010-02-13 20:40:32 -08:00
Alexander LjungbergandRoss Boucher ac3d035ce7 Fixed: CPTableView deselectRow: changed the column selection rather than the row selection. 2010-02-13 20:08:12 -08:00
Ross Boucher c8575cac05 Revert "Fix the collection view resizing behavior."
This reverts commit 9b01561127.
2010-02-13 20:04:18 -08:00
Francisco Ryan Tolmasky I 8d63c059c5 Fixed scope issues when running Cappuccino under CommonJS.
Reviewed by me.
2010-02-13 16:57:09 -08:00
Francisco Ryan Tolmasky I bc53288fca Fix for failing CPAttributedString test.
Reviewed by me.
2010-02-13 16:14:18 -08:00
Francisco Ryan Tolmasky I 474d4281f1 Actual fix for pasteboard exception for strings.
Reviewed by me.
2010-02-13 14:39:44 -08:00
Ross Boucher 73babcd7d6 Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-13 14:24:35 -08:00
Ross Boucher 5fe208d6a0 Update to the last scroller fix, slightly different approach. 2010-02-13 13:55:23 -08:00
Tom Robinson 94ca0ed71b Read as binary then decode to string to workaround narwhal-rhino bug of adding newlines on read() 2010-02-13 13:54:38 -08:00
Ross Boucher a323cfe08c Allow developers to choose to enable the HTML5 drag and drop support, even though its off by default. 2010-02-13 13:38:56 -08:00
Ross Boucher 29c3654928 Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-13 13:25:31 -08:00
Ross Boucher 27fefed0d8 Recaluclate the orientation of a scroller on frame change.
Closes #454.
2010-02-13 13:24:31 -08:00
Tom Robinson 235d974ce1 Beginning of "flatten" tool. 2010-02-13 13:13:47 -08:00
Tom Robinson cb1d3168e3 press cleanup, refactor setting environments and include paths into analyzer. 2010-02-13 13:13:47 -08:00
Tom Robinson 64dc25dfb6 Export rootNode. 2010-02-13 13:13:47 -08:00
Ross Boucher 9a7484e57d Fix Typo. Closes #463. 2010-02-13 12:06:52 -08:00
Ross Boucher b89ee3e4c1 Use longform RegEx creation in json2.js to fix a bug in Opera 9.2.
Closes #323.
2010-02-12 21:51:06 -08:00
Ross Boucher ec5645d380 Only change button heights if the button isn't bordered.
Closes #157.
2010-02-12 21:36:32 -08:00
Ross Boucher a0abf1e221 Fix a slight bug with default values in nib2cib segmented controls.
Closes #215.
2010-02-12 21:29:19 -08:00
Ross Boucher 0e558d54e5 Move CPControl constants to that file (from CPTextField).
Respect line break mode in NSControl nib2cib.

Closes #420.
2010-02-12 21:16:44 -08:00
Ross Boucher 004cc5fe5a Store a conversion table of views/objects we're replacing and restore connections to those replaced objects. (nib2cib) 2010-02-12 20:31:36 -08:00
Ross Boucher 0b22b1d022 Correctly convert NSButtons set as checkboxs and radiogroups to CPCheckBoxes and CPRadios.
Closes #365.
2010-02-12 20:05:34 -08:00
Ross Boucher 24ecf31bd3 Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-12 14:18:19 -08:00
Ross Boucher c37c80771c Fix broken tests with CPData. 2010-02-12 14:17:58 -08:00
Francisco Ryan Tolmasky I a017c0c4a8 Fix for failing CPDictionary tests.
Reviewed by me.
2010-02-12 14:09:40 -08:00
Francisco Ryan Tolmasky I 3a35ab449b Fixed failing KVO tests.
Reviewed by me.
2010-02-12 13:46:26 -08:00
Ross Boucher da84964a33 Fix two problems with KVC:
- valueForKeyPath: looped over individual components, which meant classes couldn't override valueForKeyPath: to do multi-part keys (needed for operators)
- CPArray's valueForKeyPath: implementation was incorrectly parsing the operator if it was a simple key
2010-02-12 12:53:15 -08:00
Klaas Pieter Annema 65051855ee fixed a bug where the tableview would draw a row to many 2010-02-12 13:02:55 +01:00
Ross Boucher 72c36789c6 Accidental global var.
Closes #462.
2010-02-11 09:35:36 -08:00
Klaas Pieter Annema bc07bd16bd implemented outlineView:willDisplayView:forTableColumn:row delegate method 2010-02-11 16:47:49 +01:00
Klaas Pieter Annema bf691fa552 removed incorrect implementation of imageDimsWhenDisabled 2010-02-11 12:47:27 +01:00
Ross Boucher 47ddfec1f9 Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-10 19:56:33 -08:00
Ross Boucher fb8ba655e1 Do not enforce min/max size in setFrame:display:animate: only do so in the other setFrame* variants.
Closes #284.
2010-02-10 19:55:40 -08:00
Tom Robinson d64f56817d Remove unused imports etc from press 2010-02-10 19:35:53 -08:00
Tom Robinson 9363708e49 Move push-package dir to .push-package and add to .gitignore 2010-02-10 19:19:00 -08:00
Ross Boucher 65a2e4d6b0 Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-10 18:33:03 -08:00
Randall LueckeandRoss Boucher 138d7bd9a2 Added _ in front of CG calls to last commit... 2010-02-10 18:19:13 -08:00
Randall LueckeandRoss Boucher 97fe09fbdd Added proper support for hiding scroller elements when CPScroller is resized too small to display all of them. 2010-02-10 18:19:07 -08:00
Tom Robinson 487412fa22 objj repl respects -I args. Closes gh-235 2010-02-10 18:17:41 -08:00
Klaas Pieter Annema ea47baa1fc implemented imageDimsWhenDisabled on CPButton 2010-02-10 16:19:51 +01:00
Klaas Pieter Annema 90cd519916 added viewDidLoad to CPViewController 2010-02-10 12:13:17 +01:00
Klaas Pieter Annema 669d18b218 added missing exception when a viewcontroller has no view after loadView 2010-02-10 11:46:40 +01:00
Tom Robinson fbcd2b3174 Merge branch 'loader' of git@github.com:280north/cappuccino into loader 2010-02-10 00:49:11 -08:00
Tom Robinson 99a839456d Remove --flatten and --nostrip command line flags from press. 2010-02-10 00:34:51 -08:00
Tom Robinson 0d9d60466d It's alive! press appears to be working completely (minus removed --flatten feature) 2010-02-10 00:31:00 -08:00
Francisco Ryan Tolmasky I 5a031efa7a Fixed issues with imports that had ".." in the paths.
Reviewed by me.
2010-02-10 00:03:46 -08:00
Tom Robinson 1f64fce47c First pass at fixing "press" output stage. 2010-02-09 17:25:11 -08:00
Tom Robinson 04529897dc Add setCode to Executable; use toMarkedString() in compiler; more robust function wrapper stripping in compressor 2010-02-09 14:55:50 -08:00
Tom Robinson 7837e1ad81 Fixed Executable's toMarkedString() 2010-02-09 14:49:54 -08:00
Francisco Ryan Tolmasky I c7c60b2b94 Added toMarkedString to Executable.
Reviewed by me.
2010-02-09 13:57:47 -08:00
Francisco Ryan Tolmasky I f9c2805379 Removed reference to MARKER_TEXT.
Reviewed by me.
2010-02-09 13:40:04 -08:00
Tom Robinson 035d772a4a Respect previously set OBJJ_MAIN_FILE 2010-02-09 11:46:25 -08:00
Alexander LjungbergandRoss Boucher f89c2e0ba9 Fixed: CPDates compared equal to nil and CPNull. 2010-02-09 10:59:59 -08:00
Philipe FatioandRoss Boucher 94ce055bc2 CPWindow's makeFirstResponder: return type was void, changed to BOOL 2010-02-09 10:49:04 -08:00
Klaas Pieter Annema 9b3d4d4453 Merge branch 'jake' into outlineview 2010-02-09 15:01:10 +01:00
Klaas Pieter Annema 329e4dc3c3 Merge branch 'jake' of git://github.com/280north/cappuccino into jake
Conflicts:
	AppKit/CPTableColumn.j
	AppKit/CPTableView.j
2010-02-09 14:57:37 +01:00
Klaas Pieter Annema d96e939eed made sure the dragserver doesn't call prepareDrag if the last drag update returned CPDragOperationNone 2010-02-09 14:43:02 +01:00
Klaas Pieter Annema c8437895dc fixed setDropItem:dropChildIndex behavior 2010-02-09 14:42:11 +01:00
Francisco Ryan Tolmasky I 95ba648dae Fix for keys being wrong in cplutil conversion, and making sure to use the right radix with parseInt when reading plists.
Reviewed by me.
2010-02-09 02:18:52 -08:00
Francisco Ryan Tolmasky I 9f847e5a24 Merge branch 'jake' into loader 2010-02-09 01:03:37 -08:00
Francisco Ryan Tolmasky I a4eec5fef8 Fix for UID returning different values every time for CPString.
Reviewed by me.
2010-02-09 01:02:49 -08:00
Tom Robinson e51bf3f0c1 More upgrading of press to new load system. Analysis is complete, need to build resulting files. 2010-02-08 23:47:29 -08:00
Tom Robinson b907ea59f4 Export a few more properties from Objective-J for use in "press" 2010-02-08 23:45:59 -08:00
Tom Robinson cebff75992 Change jakefile to throw exception if there's a syntax error, etc in one of the optionally required modules. 2010-02-08 23:44:44 -08:00
Alexander LjungbergandRandall Luecke a3f9b65501 Implemented [CPDate copy] with unit test. Also whitespace cleanup in CPDate. 2010-02-09 01:57:24 -05:00
Nicholas Small 1f7afe7a49 Merge branch 'jake' of github.com:280north/cappuccino into loader 2010-02-08 10:51:30 -05:00
Nicholas Small ceecaa0184 Fixed missing { in objj-analysis-tools.j 2010-02-08 10:50:44 -05:00
Klaas Pieter Annema 78b4bbb06e implement setDropItem:dropChildIndex on CPOutlineView 2010-02-08 16:49:07 +01:00
Klaas Pieter Annema 0375e7a881 - further improved outline view drag & drop for multiple parent situations 2010-02-08 14:44:21 +01:00
Klaas Pieter Annema ebc831663b Merge branch 'jake' into outlineview
Conflicts:
	AppKit/CPTableView.j
2010-02-08 11:34:16 +01:00
Klaas Pieter Annema 65ceb96e4f Merge branch 'jake' of git://github.com/280north/cappuccino into jake
Conflicts:
	AppKit/CPTableColumn.j
	AppKit/CPTableView.j
2010-02-08 11:33:33 +01:00
Klaas Pieter Annema 57ef2d2229 removed log statements 2010-02-08 11:14:50 +01:00
Klaas Pieter Annema 8759b175bd various fixes to outline view drag & drop 2010-02-08 11:14:03 +01:00
Tom Robinson 13f86b0cd4 Refactor objj-analysis-tools a bit. 2010-02-08 01:44:55 -08:00
Tom Robinson c0fad49375 Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-08 01:12:22 -08:00
Derek HammerandTom Robinson 579cc98e4f Adding the --symlink and --build flags. capp gen -l something is now just an alias for capp gen --symlink --build something. This allows for easy copying of built Frameworks for those hacking on Cappuccino 2010-02-08 01:04:22 -08:00
Randall Luecke 4a98417ee8 Added call to auto resizing after user manually resizes the columns. 2010-02-08 02:20:38 -05:00
Randall Luecke 4a5e90b5cb Fixed column resizing mask types. 2010-02-08 02:16:06 -05:00
cacaodevandRandall Luecke 36a85e935b TableView : Column resizing. Works with column resizingMasks.
TODO: Automatic table resizing should only resize columns marked with TableColumnAutoresizingMask.
TODO: When implemented, use CPTrackingArea instead of mouse moved events.
2010-02-08 01:19:10 -05:00
chandlerkentandRandall Luecke 9034203a4f Fixed a bug where CPTableView doesn't scroll to the top index when using the arrow keys. 2010-02-08 00:49:08 -05:00
Randall Luecke 24e8f8aa43 Restyled tableview to match new Aristo art. Added a bit of a padding to the dataviews and headerviews. 2010-02-07 23:55:40 -05:00
Ross Boucher 632251b16c Infinite recursion error. 2010-02-06 18:31:20 -08:00
Ross Boucher 2406cbe7ed Merge branch 'jake' into loader 2010-02-06 17:47:03 -08:00
Ross Boucher e6a0caa164 cplutil wasn't converting.
CFPropertyList couldn't output XML correctly.
2010-02-06 17:46:32 -08:00
Francisco Ryan Tolmasky I cd3e2fbbb8 Fix for cplutil.
Reviewed by me.
2010-02-06 17:14:37 -08:00
Randall Luecke 47bd6e5ce3 Further cleanup of code and logs in the tableview. 2010-02-06 17:53:40 -05:00
Randall Luecke f590c63e33 Cleaned up tableview logs. 2010-02-06 17:36:20 -05:00
Randall Luecke e8b74ece72 Fixed tableview begin drag/drop behavior to be more cocoa like. 2010-02-06 17:29:19 -05:00
Tom Robinson 3d45699bc7 Merge branch 'loader' of github.com:280north/cappuccino into loader
Conflicts:
	Objective-J/CPLog.js
2010-02-06 14:01:56 -08:00
Tom Robinson ae987f19dc Fixed CPLogRegisterRange and added dup checking and unregister function 2010-02-06 14:00:58 -08:00
Francisco Ryan Tolmasky I 09786cb8d2 Fix CPLog additions breaking build.
Reviewed by me.
2010-02-06 01:57:44 -08:00
Tom Robinson 17072f9ed4 Move CPLog to Objective-J 2010-02-05 22:27:13 -08:00
Tom Robinson 82d3d1abc5 Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-05 21:12:08 -08:00
Tom Robinson 2cc40a7961 Add sprintf.js to Objective-J 2010-02-05 21:11:47 -08:00
Francisco Ryan Tolmasky I c523e706e9 Better error reporting.
Reviewed by me.
2010-02-05 20:18:18 -08:00
Klaas Pieter Annema cdca8047b9 Merge branch 'jake' into outlineview
Conflicts:
	AppKit/CPTableView.j
2010-02-05 15:14:40 +01:00
Klaas Pieter Annema 09b8a3394e Merge branch 'jake' of git://github.com/280north/cappuccino into jake
Conflicts:
	AppKit/CPTableColumn.j
2010-02-05 12:15:34 +01:00
Klaas Pieter Annema ed1a7a4bc9 - removed variable row heights from CPTableView (can be found in variabletableview branch)
- fixed a bug where it was not possible to drag unselectable rows #445
2010-02-05 12:11:39 +01:00
Klaas Pieter Annema 0696fb405e improved CPTableView's drop row logic for the lowest possible row 2010-02-05 11:51:06 +01:00
Randall Luecke 265a410342 Changed the default text color for table column data views to match Aristo. 2010-02-04 21:27:06 -05:00
Nicholas Small cbd0d6e6a2 Better nib2cib and CPCoder support for CPTableView. 2010-02-04 15:25:16 -05:00
Nicholas Small 25e0a59d5b Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-04 14:14:36 -05:00
Nicholas Small ab34ee882e Add a few flags to NSTableView and CPCoder support for gridColor and gridStyleMask in CPTableView. 2010-02-04 14:14:31 -05:00
Ross Boucher 4f05657236 Merge branch 'jake' into loader
Conflicts:
	Objective-J/Preprocessor.js
2010-02-04 11:10:39 -08:00
Klaas Pieter Annema 7720200679 - improved the CPOutlineView drag & drop support in cases where more than 1 parent is possible
- improved the outline view test project
2010-02-04 16:56:48 +01:00
Klaas Pieter Annema 117ec9970c - reduced the number of rows on the tableview sample so it works with the variable row heights
- made CPTableView ask for the rect of the drop highlight so CPOutlineView can adjust this
- re factored some stuff in CPOutlineView's table delegate
2010-02-04 14:20:12 +01:00
Klaas Pieter Annema 766073f77a reverted some of my drop highlight changes 2010-02-04 13:09:10 +01:00
Klaas Pieter Annema 5f0a60f61c Merge branch 'jake' of git://github.com/280north/cappuccino into jake 2010-02-04 10:35:47 +01:00
Tom Robinson d608d34166 Fixed "phase 1" of press for new loader 2010-02-04 01:00:55 -08:00
Tom Robinson 8bc1c7445d export fileExecuterForPath (and use exports.fileExecuterForPath internally so it can be overridden for press, etc) 2010-02-03 23:50:16 -08:00
Tom Robinson 985b906c94 Merge branch 'loader' of git@github.com:280north/cappuccino into loader 2010-02-03 22:21:55 -08:00
Randall Luecke e8ac94f8da Improved logic for drawing highlighted grid lines. 2010-02-04 00:41:15 -05:00
Randall Luecke 9465dd6941 Merge branch 'jake' of git://github.com/280north/cappuccino into jake 2010-02-04 00:23:19 -05:00
Randall Luecke 28a00fff23 Fixed drawing bug where a the bottom grid line for the selected rows would be drawn white. 2010-02-04 00:19:59 -05:00
Francisco Ryan Tolmasky I c418481981 Don't require trashing Objective-J when changes are made for them to be picked up.
Reviewed by me.
2010-02-03 20:37:24 -08:00
Randall Luecke 2b87b9f3fc Styled the test for the tableview headers, also added more rows to tabletest for performance testing. 2010-02-03 22:34:13 -05:00
Ross Boucher 683eb993e8 Fix for a broken dirname method on File. 2010-02-03 16:17:12 -08:00
Ross Boucher e19d6a58c9 Merge branch 'loader' of github.com:280north/cappuccino into loader 2010-02-03 14:58:16 -08:00
Alexander LjungbergandRoss Boucher 2dccee05bc Fixed: CPWindow setFrame:display: failed with an "unrecognized selector" exception. 2010-02-03 14:58:01 -08:00
Francisco Ryan Tolmasky I ac2885afc6 Support base tag again.
Reviewed by me.
2010-02-03 14:31:02 -08:00
Nicholas Small 972909902e Added ApplicationTask#setFrameworks path. The default is local frameworks, you could also use ENV.CAPP_BUILD or pass capp to use the installed frameworks. 2010-02-03 11:43:48 -05:00
Klaas Pieter Annema b07f2ed186 improved the location of the drag feedback view 2010-02-03 15:25:28 +01:00
Klaas Pieter Annema ee6160e796 - fixed some issues with variable sized
- made CPOutlineView return the last index when dragging the row outside of it's bounds
2010-02-03 15:06:42 +01:00
Klaas Pieter Annema 5940e6913d Merge branch 'jake' of git://github.com/280north/cappuccino into jake 2010-02-03 10:16:45 +01:00
Klaas Pieter Annema c85e33c034 Fixed a bug where the CPTextField value was not updated properly when the update happened in the same 'runloop' iteration as becomeFirstResponder 2010-02-03 10:11:32 +01:00
Francisco Ryan Tolmasky I 21ef259e1f Fix for being too strict when accepting PLISTs and also fixes a regression with erroring when parsing code with shebangs(!).
Closes #69.

Reviewed by me.
2010-02-03 00:31:37 -08:00
Ross Boucher 2b66683167 Update the documentation config based on feedback from:
http://cappnotes.worldofkrauss.com/sectins/objective-j-categories/8-miscellaneous/14-api-documentation-fixes.html

If you have graphviz installed, graphs will now be generated.
Ruby and doxygen are prereqs for building the docs.
2010-02-02 18:35:42 -08:00
Ross Boucher 851a0e3d24 Fix a preprocess.js typo.
Closes #440.
2010-02-02 14:52:55 -08:00
Klaas Pieter Annema 8b32f561ec added selectedRow to CPTableView 2010-02-02 15:57:15 +01:00
Klaas Pieter Annema 1571b6daa2 fixed CPTableView's header view reliance on row height 2010-02-02 15:44:23 +01:00
Klaas Pieter Annema 2d69509d5e - implemented CPTableView heightOfRow: delegate method
- implemented CPOutlineView heightForItem: delegate method
- made CPTableView work correctly with variable sized rows
2010-02-02 14:15:22 +01:00
Klaas Pieter Annema 8edf05c000 made sure the outline view returns a dataview if it's delegate doesn't implement dataViewForTableColumn:item: or if that method returned nil 2010-02-02 11:37:57 +01:00
Klaas Pieter Annema 0e6cef0268 implement outlineview expandItem:expandChildren: 2010-02-02 11:23:24 +01:00
Klaas Pieter Annema 60e4d8e080 Merge remote branch 'cappuccino/jake' into jake
Conflicts:
	AppKit/CPOutlineView.j
	AppKit/CPTableView.j
2010-02-02 10:24:13 +01:00
Randall Luecke 6b58986ec3 Added better artwork for pressed header images for the tableview. 2010-02-02 01:56:53 -05:00
Randall Luecke e88ec01fca Fixed bug where the first click on the CPTableView wouldn't select a row if drag and drop was supported. 2010-02-01 23:26:24 -05:00
Francisco Ryan Tolmasky I 8284498722 Merge branch 'jake' into loader
Conflicts:
	AppKit/Platform/DOM/CPPlatformString.j
2010-02-01 20:19:20 -08:00
Tom Robinson e088280a5f Implement description and toString for class objects. 2010-02-01 17:38:13 -08:00
Klaas Pieter Annema 7f78c323e9 implemented outlineView:shouldSelectItem delegate method 2010-02-01 19:08:22 +01:00
Klaas Pieter Annema 77303c1aeb - implemented CPTableView's dataViewForTableColumn:row: delegate method
- implemented CPOutlineView's dataViewForTableColumn:item: delegate method
2010-02-01 19:00:48 +01:00
Randall Luecke cc74f941c6 Better "fix" for Safari breaking the outlineview... This bug still needs a reduction though. 2010-02-01 11:44:24 -05:00
Randall Luecke 775c1c1c8b Fixed the outline view again... 2010-02-01 11:11:51 -05:00
cacaodevandRandall Luecke 35a7456302 Fixes rows drawing when alternatingRowBackgroundColors > 2. TableTest showing 3 row colors 2010-02-01 10:59:23 -05:00
Klaas Pieter Annema 4006b35a5e fixed a bug where the outline view would send drag & drop datasource messages to it's datasource when they are not implemented 2010-02-01 12:39:22 +01:00
Tom Robinson b562280503 press cleanup 2010-02-01 02:33:41 -08:00
Klaas Pieter Annema e3a075a6a6 - implemented CPOutlineView drag & drop
- improved CPTableView drag & drop feedback
2010-02-01 11:22:57 +01:00
Klaas Pieter Annema 8c534c6d33 Merge branch 'outlineview' into jake 2010-02-01 11:17:15 +01:00
Klaas Pieter Annema 82be6c243c Merge branch 'jake' into enstore_jake
Conflicts:
	AppKit/CPTableView.j
2010-02-01 11:07:42 +01:00
Klaas Pieter Annema 5b8ee5dd1b Merge branch 'jake' of git://github.com/280north/cappuccino into jake
Conflicts:
	AppKit/CPTableView.j
2010-02-01 11:03:27 +01:00
Randall Luecke 050a132bd5 Initial documentation of CPTableView. 2010-02-01 03:40:09 -05:00
Randall Luecke 146bff6766 Initial documentation of CPTableView 2010-02-01 03:27:03 -05:00
Francisco Ryan Tolmasky I cd98bce331 Turned off logging by default, removed unecessary logs, and fixed bug where turning of logs broke the build.
Reviewed by me.
2010-01-31 23:59:58 -08:00
Randall Luecke a2d3723c7a Merge branch 'jake-table' into jake 2010-02-01 02:38:32 -05:00
Randall Luecke ecb88a87ad Added proper grid drawing for highlighted rows. Closing issues #369 Also fixing bug where top row would not draw its background when clipped 2010-02-01 02:33:04 -05:00
Ross Boucher 3f2813932a Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-31 23:07:11 -08:00
Ross Boucher c2223e3942 Closes #429. This should actually resolve the issue by simply removing the potential race condition entirely. 2010-01-31 23:06:23 -08:00
Randall Luecke 2dc0839d36 Fixed bug where CPButtonBar would not display anything until resized. Closes issue #151. 2010-02-01 00:58:30 -05:00
Tom Robinson 97ef1d1781 Added persistent history to objj repl. 2010-01-31 19:41:58 -08:00
Francisco Ryan Tolmasky I e64a9a7ab9 Fix for objj command line tool not working.
Reviewed by me.
2010-01-31 18:36:36 -08:00
Francisco Ryan Tolmasky I d4f3f83212 Fix for nib2cib not working with new loader.
Reviewed by me.
2010-01-31 17:28:51 -08:00
Randall Luecke 1488f3ed58 Merge branch 'jake' of git://github.com/280north/cappuccino into jake 2010-01-31 19:02:20 -05:00
Randall Luecke 26945bde42 Removed commented out code and fixed a bug where the pressed state was still set when you drag the mouse from outside the bounds of the header and let go. 2010-01-31 18:58:32 -05:00
Ross Boucher c911dd8aa6 Slight order change. This really should not matter. 2010-01-31 15:37:06 -08:00
Ross Boucher 1c81e0eee0 Closes #429. Doesn't necessarily address the root cause however.
The problem stems from a bug in Safari which is allowing callbacks
to interrupt running code (which should be impossible in JavaScript).
The change essentially makes it so that in the case where this happens,
which is rare, we'll end up accidentally creating an extra iframe.
This isn't ideal, but it also isn't harmful, versus the current
situation where code will simply break.
2010-01-31 15:13:07 -08:00
Ross Boucher 5366713790 Closes #429. Doesn't necessarily address the root cause however.
The problem stems from a bug in Safari which is allowing callbacks
to interrupt running code (which should be impossible in JavaScript).
The change essentially makes it so that in the case where this happens,
which is rare, we'll end up accidentally creating an extra iframe.
This isn't ideal, but it also isn't harmful, versus the current
situation where code will simply break.
2010-01-31 15:07:23 -08:00
Ross Boucher e9940d060a Merge branch 'loader' of git@github.com:280north/cappuccino into loader 2010-01-31 14:01:32 -08:00
Ross Boucher 605e905f3e Missing a local assignment of the task variable in one of our jake additions. Causes failures on non cappuccino builds. 2010-01-31 14:00:12 -08:00
cacaodevandRandall Luecke 11d30566bf CPTableHeaderView: change background in -layoutSubviews instead of -setThemeState: ; Added a CPThemeStatePressed used privately, makes things easier for custom headers 2010-01-31 16:31:25 -05:00
Francisco Ryan Tolmasky I 0942f9fac3 Replaced instances of non-compressable words.
Reviewed by me.
2010-01-31 13:14:51 -08:00
Francisco Ryan Tolmasky I 7b303b6529 Removed unused functions.
Reviewed by me.
2010-01-31 12:48:26 -08:00
Ross Boucher 6a9040989d Merge branch 'jake' into loader 2010-01-31 12:32:41 -08:00
Ross Boucher 840e9c7671 When removing an item from the collection view, we now unconditionally unhighlight it.
We also reapply highlights after reloading finishes.

Closes #248.
2010-01-31 12:29:38 -08:00
Randall Luecke 1d9e2f8169 Changed drawn gradients to aristo art. 2010-01-31 01:55:45 -05:00
Francisco Ryan Tolmasky I 8c9f302b67 Added debug stuff.
Reviewed by me.
2010-01-30 21:08:18 -08:00
Ross Boucher 44f23cd8ac Merge branch 'loader' of git@github.com:280north/cappuccino into loader 2010-01-30 19:24:47 -08:00
Ross Boucher c88f781509 Fix for Cib connections not being available in IE. 2010-01-30 19:23:45 -08:00
Francisco Ryan Tolmasky I 3dc578d585 Fix for using setTimeout instead of setNativeTimeout and assuming bundled directories are themselves not bundles.
Reviewed by me.
2010-01-30 19:11:12 -08:00
Francisco Ryan Tolmasky I 238d8ff0be Merge branch 'jake' into loader 2010-01-30 18:09:17 -08:00
Francisco Ryan Tolmasky I ca5dd0071c Various IE fixes.
Reviewed by me.
2010-01-30 18:08:19 -08:00
cacaodevandRandall Luecke 86fa759f9f CPTableHeaderView.j: Gradient headers for canvas capable browsers | Bg images for others. Column selection with pressed state.
AppController.j:	Modified left table in TestTable to test column selection.
CPTableView.j:          Added missing ivar; Fixed -deselectRow|Column:
2010-01-30 13:05:48 -05:00
Francisco Ryan Tolmasky I 0bcf8a6626 Trailing comma fix.
Reviewed by me.
2010-01-30 01:14:32 -08:00
Francisco Ryan Tolmasky I d735cd98e7 Fix for FireFox not working.
Reviewed by me.
2010-01-30 00:35:59 -08:00
Francisco Ryan Tolmasky I e25a550d3f Merge branch 'cheese' into loader 2010-01-29 22:33:32 -08:00
Francisco Ryan Tolmasky I 8a2206656d Fix for responseXML not working correctly from remote.
Reviewed by me.
2010-01-29 22:31:34 -08:00
Ross Boucher ac68d670a2 Slight error in the sizing for the previous progress bar commit 2010-01-29 22:11:43 -08:00
Ross Boucher e6539bbed5 MHTML cache testing 2010-01-29 22:11:18 -08:00
Ross Boucher 9db0694677 Remove unused images. 2010-01-29 21:45:03 -08:00
Francisco Ryan Tolmasky I a4d73330cc Data URLs.
Reviewed by me.
2010-01-29 21:43:23 -08:00
Francisco Ryan Tolmasky I ea6a983e9b Merge branch 'jake' of git@github.com:280north/cappuccino into loader 2010-01-29 17:53:36 -08:00
Francisco Ryan Tolmasky I 79cd8603a2 Removed now unecessary CommonJS files.
Reviewed by me.
2010-01-29 16:37:53 -08:00
Francisco Ryan Tolmasky I 02cb054b71 Removed unused plist file.
Reviewed by me.
2010-01-29 16:21:27 -08:00
Ross Boucher 007cfd589f Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-29 15:18:10 -08:00
Ross Boucher 90d24fd6bf Temporary update for progress indicators for 0.8 2010-01-29 15:17:21 -08:00
Francisco Ryan Tolmasky I 4b7310d0cb More consistent naming scheme.
Reviewed by me.
2010-01-29 15:16:22 -08:00
Francisco Ryan Tolmasky I 59660032e1 nib2cib fixes.
Reviewed by me.
2010-01-29 13:22:44 -08:00
Francisco Ryan Tolmasky I d9c47ec763 Updated environments and removed environment collections. Also creates separate files for different forms of spriting.
Reviewed by me.
2010-01-29 10:54:47 -08:00
Klaas Pieter Annema a18ea750a6 Fixed a bug where CPOutlineView would not call super's implementation of selectRowIndexes:byExtendingSelection: 2010-01-29 18:01:46 +01:00
Klaas Pieter AnnemaandRandall Luecke c423411639 made sure CPControl's trackMouse: doesn't eat mouse events when the tableview is in a drag session #431 2010-01-29 11:36:13 -05:00
Francisco Ryan Tolmasky I b5ad030e40 Further blend work.
Reviewed by me.
2010-01-29 08:04:00 -08:00
Klaas Pieter Annema bfdbe2a34a updated the collection view sample to actually move the dragged items 2010-01-29 16:46:56 +01:00
Klaas Pieter Annema ec5dcb47c9 - fixed a bug where the tableview would send the wrong concluded dropped row to it's datasource
- implemented CPCollectioView drop on behavior
2010-01-29 14:58:45 +01:00
Klaas Pieter Annema 436f1d1541 improved the way drop highlights are shown 2010-01-29 14:24:44 +01:00
Klaas Pieter Annema 05873a030f Merge branch 'jake' into enstore_jake 2010-01-29 12:19:59 +01:00
Klaas Pieter Annema 78083eea48 made sure CPControl's trackMouse: doesn't eat mouse events when the tableview is in a drag session #431 2010-01-29 12:14:08 +01:00
Klaas Pieter Annema 7715da02e7 Merge remote branch 'cappuccino/jake' into jake
Conflicts:
	AppKit/CPTableView.j
	AppKit/CPViewAnimation.j
2010-01-29 12:12:50 +01:00
Klaas Pieter Annema 6798a5777a added the cpoutlineview test app 2010-01-29 10:57:34 +01:00
Klaas Pieter Annema 2f3ad961e7 Merge remote branch 'cappuccino/jake' into enstore_jake
Conflicts:
	AppKit/CPTableView.j
2010-01-29 10:56:30 +01:00
Klaas Pieter Annema dba047187f improved the way a CPTableView renders the drag & drop highlight between rows 2010-01-29 10:47:49 +01:00
Ross Boucher 03e63f29dc Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-29 00:13:33 -08:00
Ross Boucher b4cd9c4c45 Remove HTML5 drag and drop support from browsers. 2010-01-29 00:12:51 -08:00
Randall Luecke b9b2649db9 Cleaned up merge and removed unnessisary selectionIsChanging notification. 2010-01-29 01:37:57 -05:00
Derek HammerandRandall Luecke df98483b06 Removing extraneous selection did change notifications 2010-01-29 01:28:09 -05:00
cacaodevandRandall Luecke 37fbeaad02 CPTableView -dragViewForRowsWithIndexes:
- Change the way dragViewOffset is computed to conform to cocoa
- Drag exposed rows only
2010-01-29 01:22:38 -05:00
Francisco Ryan Tolmasky I 794d8a754c Make blendtask work with new system.
Reviewed by me.
2010-01-28 16:24:18 -08:00
Ross Boucher b081debf88 Missing #include for the platform header.
Closes #412.
2010-01-28 15:49:03 -08:00
Nicholas Small 36c6c9bfa6 Merge branch 'jake' of github.com:280north/cappuccino into jake 2010-01-28 17:59:08 -05:00
Nicholas Small bda5ea1c59 Rewrote CPFlashView implementation to be fully cross-browser and standards compliant. 2010-01-28 17:58:50 -05:00
Nicholas Small 5ccf6eefc0 Changed CPFlashMovie -fileName to -filename. 2010-01-28 17:58:08 -05:00
Francisco Ryan Tolmasky I 06261559fc Improvements for CommonJS.
Reviewed by me.
2010-01-28 14:19:23 -08:00
Klaas Pieter Annema 477d2f9d82 fixed the disclosure triangle highlighting behavior 2010-01-28 20:10:14 +01:00
Klaas Pieter Annema 0cb66ddc6e set the default CPTableColumn dataview's center vertical-alignment (because it looks better) 2010-01-28 18:52:01 +01:00
Klaas Pieter Annema 99df7f6acb - further implemented CPOutlineView drag & drop support
- implemented a work around in CPPlatformWindow+DOM.j for the javascript drop event never being fired
2010-01-28 16:54:50 +01:00
Tom Robinson 0791fa0ad3 Eliminate a couple accidental globals. 2010-01-28 00:18:40 -08:00
Tom Robinson 9811327672 press whitespace cleanup 2010-01-27 22:37:26 -08:00
Tom Robinson 60f2eaadf5 Modify press to inspect cibs for dependent classes. 2010-01-27 22:36:28 -08:00
Tom Robinson 5478c640cc Refactor of press's objj-analysis-tools in prep for inspecting cibs. 2010-01-27 22:35:19 -08:00
Tom Robinson 7fe3b115f1 Remove legacy image spriting code from press. 2010-01-27 20:46:35 -08:00
Tom Robinson 3ee63b754c Remove theme bundle loading in press for now. 2010-01-27 17:54:28 -08:00
Tom Robinson 378b6c12f3 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-27 17:54:03 -08:00
Tom Robinson ee5817e480 Cleanup objj arguments story. objj-executable and "objj path/to/main.j" are now consistent. 2010-01-27 17:53:05 -08:00
Ross Boucher a354b4acd5 Temporary fix for 0.8 for copy/paste behavior in CPTextField.
Closes #407.
2010-01-27 16:36:39 -08:00
Tom Robinson 8e87a4a941 Make bootstrap warning very explicit. 2010-01-27 10:17:36 -08:00
Francisco Ryan Tolmasky I 42712166e9 Added FileRequest abstraction on top of HTTPRequest to allow synchronous loading in CommonJS.
Reviewed by me.
2010-01-27 07:50:37 -08:00
Francisco Ryan Tolmasky I 2bc31de69d Removed alerts.
Reviewd by me.
2010-01-27 04:01:11 -08:00
Francisco Ryan Tolmasky I fcfeb29be5 Changed #define from RHINO to COMMONJS. Re-enabled recently added document-load-waiting.
Reviewed by me.
2010-01-27 03:58:49 -08:00
Francisco Ryan Tolmasky I a64a270e25 Merge branch 'jake' of git@github.com:280north/cappuccino into loader 2010-01-27 03:17:16 -08:00
Francisco Ryan Tolmasky I 96eebc7d1d Fix for accidentally removing Executable.fileDependencies.
Reviewed by me.
2010-01-27 03:16:46 -08:00
Francisco Ryan Tolmasky I 38fd675f51 Performance improvements and bug fixes.
Reviewed by me.
2010-01-27 02:55:56 -08:00
Tom Robinson 35adaee1bb Initial press cib analysis 2010-01-27 02:27:32 -08:00
Klaas Pieter Annema def314b5ad removed log statements from cptableview 2010-01-27 11:05:31 +01:00
Klaas Pieter Annema 913a18eaaf completed tableview merge 2010-01-27 10:40:51 +01:00
unknown d82b39de19 Remove filename causing problems on Windows as well as line endings in press. 2010-01-27 01:21:32 -08:00
Klaas Pieter Annema cde5d8709c Merge remote branch 'cappuccino/jake' into enstore_jake
Conflicts:
	AppKit/CPTableView.j
2010-01-27 10:08:48 +01:00
Francisco Ryan Tolmasky I ec210c49c5 Beginnings of new loader.
Reviewed by me.
2010-01-27 00:43:54 -08:00
Tom Robinson 07f320def9 Fixed jake tasks for pushing packages to package repo. 2010-01-27 00:08:42 -08:00
Tom Robinson f5fe15d6cb Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-26 23:50:41 -08:00
Nicholas Small da146b0873 Move table view header resources into AppKit/Resources. 2010-01-26 10:53:07 -05:00
Paul BaumgartandRoss Boucher 3b7a77ae0c Minor fix: change emdash to regular hyphen. 2010-01-25 22:21:26 -08:00
tlrobinson 9cb1e28ad1 bootstrap option to install Cappuccino/Objective-J packages. 2010-01-25 20:43:37 -08:00
Ross Boucher 9db7701691 Fixes a bug when changing splitPane status for a CPSplitView.
Closes #419.
2010-01-25 17:03:24 -08:00
Tom Robinson 27aca4c84a bootstrap.sh warning about shell config 2010-01-25 14:19:30 -08:00
Tom Robinson 4e50244dca Handle more bootstrap.sh edge cases. 2010-01-25 14:14:34 -08:00
Tom Robinson 0c21724270 Give debug frameworks higher priority in objj. 2010-01-25 13:35:27 -08:00
Tom Robinson 09306aa2cd Fixed cplutil and updated to use args parser, added lint option, etc. 2010-01-25 12:49:11 -08:00
Randall Luecke 1170673b92 selection did change is no longer posted if selectionShouldChangeInTableView returns NO. Closes 372. Keyboard navigation in tableview now honors selectionShouldChange. 2010-01-24 20:01:58 -05:00
Ross Boucher 712a991c86 Fix a bug introduced by the new document.body code when opening a second platform window. 2010-01-24 15:48:25 -08:00
Ross Boucher e3cdcbc5ab Add CPSpaceKeyCode. Closes #424. 2010-01-24 15:24:59 -08:00
luddepandRoss Boucher 62379b21c1 Quick fix for @"Aristo" being hardcoded in CPAlert.j 2010-01-24 01:17:20 -08:00
Ross Boucher cfde67742c Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-24 01:15:35 -08:00
Ross Boucher 9b01561127 Fix the collection view resizing behavior. 2010-01-24 01:15:10 -08:00
Randall Luecke fb89450b90 Refactored keyboard navigation for CPTableView 2010-01-24 03:39:58 -05:00
Ross Boucher 5a8d491f10 Check the Info.plist for a CPDefaultTheme key for the name of the default theme.
Closes #418.
2010-01-24 00:34:35 -08:00
Ross Boucher 7ffb44e394 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-24 00:10:28 -08:00
Ross Boucher 34a5d9e61b Fix spacing issues in CPViewAnimation. 2010-01-24 00:10:04 -08:00
Randall Luecke e1d43e3651 Merge branch 'jake-table' into jake 2010-01-24 02:39:31 -05:00
Klaas Pieter AnnemaandRandall Luecke c291ad83f1 Implemented visual feedback when dragging in CPTableView
Conflicts:

	AppKit/CPTableView.j
2010-01-24 02:37:25 -05:00
Klaas Pieter AnnemaandRoss Boucher c6a4eb28a8 added cpviewanimation 2010-01-23 23:31:40 -08:00
Randall Luecke dd4735026a Reset position of the tableview in tabletest 2010-01-24 02:31:01 -05:00
Ross Boucher dc0439227e Add an accessor for the filename on CPFlashMovie 2010-01-23 23:28:39 -08:00
Ross Boucher 00f470763f Make CPFlashMovie CPCoding compliant. 2010-01-23 18:08:45 -08:00
Klaas Pieter Annema 05b1cfca31 Merge branch 'jake_original' into jake
Conflicts:
	AppKit/CPTableView.j
2010-01-23 11:38:08 +01:00
cacaodevandRandall Luecke e40696a7af CPTableView: drag & drop improvements
- Default dragView containing dragged rows, works with discrete rows
- scroll-as-you-drag feature
- draggingEntered returns a drag operation. Rearranged a bit the code.
- fixed dragPoint/target row
- Modified test app so you can drag in both ways and also move indexes internally
2010-01-23 02:56:59 -05:00
Ross Boucher bc030c42d9 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-22 19:43:21 -08:00
Ross Boucher 7ce72a31c5 Rather than throwing out the entire cappuccino body, throw out a specific div if that div is available.
("cappuccino-body"). This let's external libraries, esp. flash ones, add things to the body without
Cappuccino getting rid of them as soon as the page loads.

Closes #421.
2010-01-22 19:40:33 -08:00
Tom Robinson cf8989938c Improved sizeOfString IE workaround 2010-01-22 18:38:25 -08:00
Klaas Pieter Annema e09b63183c added cpviewanimation 2010-01-22 20:44:58 +01:00
Klaas Pieter Annema 76717c7177 converted spaces to tabs 2010-01-22 20:37:17 +01:00
Klaas Pieter Annema 6749fa57ad started implementing CPOutlineView drag & drop support 2010-01-22 20:25:14 +01:00
Klaas Pieter Annema 050b75a2df Implemented visual feedback when dragging in CPTableView 2010-01-22 20:17:34 +01:00
Randall Luecke 3f730c94ce Merge branch 'jake' of git://github.com/280north/cappuccino into jake 2010-01-22 10:51:48 -05:00
Randall Luecke 22c931729b Removed additional references to disabled HUD scrollbar knobs. 2010-01-22 10:50:29 -05:00
Klaas Pieter Annema cb658826a3 Merge branch 'jake' into enstore_jake 2010-01-22 10:15:34 +01:00
Ross Boucher 3f8c311ea2 Bring windows forward when opening a sheet.
Closes #391.
2010-01-21 23:24:03 -08:00
Randall Luecke 22aa4d359e Hard coded header view resources into the CPTableView 2010-01-22 02:09:22 -05:00
Ross Boucher c2880ec8e4 Remove support for HTML5 drag and drop from Chrome, because it doesn't work.
We should eventually try and figure out a more specific test for this.
2010-01-21 23:02:12 -08:00
Ross Boucher 108822d4e1 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-21 22:33:06 -08:00
Randall Luecke f79a926b10 Removed references to disabled scroller knob in HUD CPScroller. 2010-01-22 01:22:03 -05:00
cacaodevandRoss Boucher 4eef234736 Fix a bug where drop was always failing in webkit nighties 2010-01-21 22:04:35 -08:00
Klaas Pieter Annema 5abbdfc094 Merge branch 'jake' into enstore_jake 2010-01-21 15:01:21 +01:00
Klaas Pieter Annema c44715bef4 added CPSpaceKeyCode to CPResponder 2010-01-21 11:59:28 +01:00
Randall Luecke b5f55100e9 Merge branch 'jake' of git://github.com/280north/cappuccino into jake 2010-01-20 23:19:18 -05:00
Tom Robinson 4e0404fce6 IE sizeOfString temporary fix. 2010-01-20 17:12:46 -08:00
Tom Robinson f1874eca8a Don't use sudo in jake install by default, add "sudo-install" task. 2010-01-20 15:18:51 -08:00
Tom Robinson 2e1d6f2412 Migrate to use INTERPRETER.Context 2010-01-19 16:58:41 -08:00
Tom Robinson 0395287906 Press bundle callbacks for theme/cib --flatten support. 2010-01-19 15:00:43 -08:00
Francisco Ryan Tolmasky I bda8a5fd6c Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-19 14:46:05 -08:00
Alexander LjungbergandFrancisco Ryan Tolmasky I ded413481c Fixed: under certain circumstances controls would not be drawn despite a call to setNeedsDisplay:YES. A typical symptom of this was custom CPViews' drawRect never being called. The error was caused by _CPDisplayServer throwing away its remaining work whenever the display code of a control called setNeedsLayout. 2010-01-19 14:45:47 -08:00
Tom Robinson a5a6c07b08 Move manual tests to Manual sub dir 2010-01-19 13:16:16 -08:00
Nicholas Small 204df99375 Make CPPanel -becomesKeyOnlyIfNeeded and CPView -needsPanelToBecomeKey work. 2010-01-15 17:23:56 -05:00
Randall Luecke 55dd67a0ad Merge branch 'jake' of git://github.com/280north/cappuccino into jake 2010-01-14 15:02:53 -05:00
tlrobinson 6040ee4ffc Fixed args case "objj -Ifoo bar.j" 2010-01-14 12:01:51 -08:00
Randall Luecke 544ed99d98 Merge branch 'jake' of git://github.com/280north/cappuccino into jake 2010-01-14 14:26:02 -05:00
tlrobinson 7546640fba Correct the args parsing in objj to provide the script name at args[0] instead of "objj" 2010-01-14 11:24:39 -08:00
Francisco Ryan Tolmasky I daf5b88834 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-13 22:40:01 -08:00
Francisco Ryan Tolmasky I c36f975bbf More support for toolbar items and nib2cib. Added support for CPToolbarShowColorsItem.
Reviewed by me.
2010-01-13 22:39:15 -08:00
Scott KyleandRoss Boucher a5e34d9153 Added CGGeometry to CPTableColumn since it's called from sizeToFit 2010-01-13 20:08:00 -08:00
Ross Boucher 57a63440f9 Remove unnecessary comments. 2010-01-13 20:04:23 -08:00
Francisco Ryan Tolmasky I e25a227e4d Fix for updating target/action of toolbar items.
Reviewed by me.
2010-01-13 20:03:01 -08:00
Randall Luecke db7b340b32 Fixed outline view again after scoping fix. 2010-01-13 22:34:39 -05:00
Randall Luecke 7683755137 Fixed scoping issues with last commit. 2010-01-13 22:22:44 -05:00
Randall Luecke 8de71663c2 Fixes for the CPTableView drag operation (selection and drag and drop) after the nasty fix for the outlineview fix for Safari. 2010-01-13 21:30:10 -05:00
cacaodevandRandall Luecke 211a7c7939 Make built-in data views highlightable 2010-01-13 19:36:21 -05:00
Randall Luecke 82ce66af16 Further hack to fix the CPOutlineView which is broken in Safari. 2010-01-13 19:30:11 -05:00
Tom Robinson df4bc13122 A splash of color in the build tools... 2010-01-13 12:58:26 -08:00
Tom Robinson 8f3661d5a4 Partial support for theme/additional bundles in press. 2010-01-13 12:57:31 -08:00
Tom Robinson bb31ac11ca Delete OUTPUT_DIRECTORY if exists and --force on 2010-01-13 03:48:04 -08:00
Tom Robinson 4ef0065c66 Print identifiers in alphabetical order for clarity. 2010-01-13 03:46:27 -08:00
Tom Robinson 476d168a46 Merge branch 'jake' of github.com:280north/cappuccino into jake 2010-01-13 01:57:52 -08:00
Tom Robinson 093c6cdca3 More robust handing of string passed to CPURLRequest instead of CPURLs. 2010-01-13 01:57:04 -08:00
Tom Robinson 345f5e14de Refactor hardcoded Aristo.blend into CPApplication +defaultThemeName 2010-01-13 01:53:23 -08:00
Paul BaumgartandFrancisco Ryan Tolmasky I 5ddfef7eb7 Convert relative paths to absolute when specifying an install_directory for narwhal. 2010-01-13 00:57:44 -08:00
Francisco Ryan Tolmasky I 81d784b5dc Added missing license.
Reviewed by me.
2010-01-12 22:55:58 -08:00
Francisco Ryan Tolmasky I b0b9a7a294 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-12 22:55:50 -08:00
Francisco Ryan Tolmasky I e76ee3c96e A few more changes for CPToolbar nib2cib support and added beginnings of search field support.
Reviewed by me.
2010-01-12 22:54:35 -08:00
Francisco Ryan Tolmasky I 24b495ca43 Temporary fix for CPTableView being broken.
Reviewed by me.
2010-01-12 22:52:34 -08:00
Tom Robinson ff4fd1411e Add --force option, change shorthand --flatten to -l 2010-01-12 22:48:29 -08:00
Francisco Ryan Tolmasky I 03eed5f4f9 Got rid of unecessary code/files.
Reviewed by me.
2010-01-12 19:05:22 -08:00
Francisco Ryan Tolmasky I 1c89968b69 nib2cib support for the new CPToolbar/CPToolbarItem, also improved classes to pick up item property changes (i.e, setLabel:, setAction:, etc.) after the toolbar has been initialized
Conflicts:

	Tools/nib2cib/NSAppKit.j
	Tools/nib2cib/NSToolbarItem.j
2010-01-12 19:02:43 -08:00
Tom Robinson 01ce469a0f Convert objj-analysis-tools.j line endings to Unix style 2010-01-12 18:46:44 -08:00
Tom Robinson c6347a3cf1 Remove relativeToRootPath 2010-01-12 18:42:03 -08:00
Tom Robinson bf7e581445 Add URLMap to pressed --flattened bundles. 2010-01-12 17:24:20 -08:00
Tom Robinson 0fe9253d3b Add some git hooks 2010-01-12 13:05:05 -08:00
Tom Robinson 6a9042fd9c make narwhal-jsc version check optional 2010-01-12 13:01:11 -08:00
Tom Robinson 9e62fdc0b8 added missing CPNull imports 2010-01-12 12:28:32 -08:00
Tom Robinson a33b70f8bd Cleanup of common.jake to properly load built packages, etc. 2010-01-12 03:54:26 -08:00
Tom Robinson bfc06ed81f Merge branch 'jake' of github.com:280north/cappuccino into jake 2010-01-12 02:14:41 -08:00
Francisco Ryan Tolmasky I c3c8ac7ff0 Fix for missing parenthesis causing syntax error.
Reviewed by me.
2010-01-12 01:49:06 -08:00
Ross Boucher bfd0c00708 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-11 22:37:29 -08:00
Ross Boucher ef0c84072b Fix the platform identifying code.
Fix the longstanding IE refresh bug by ensuring document is ready.
Closes #98.
2010-01-11 22:33:08 -08:00
Nicholas Small 066972ff75 Some fixes for last commit. Thanks to Jesse Ross. 2010-01-11 16:43:49 -05:00
Nicholas Small 608853d4fa Added -setFlashVars: and -setParameters: to CPFlashView. Closes #59. 2010-01-11 14:13:05 -05:00
Francisco Ryan Tolmasky I 1774305c2d Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-10 12:19:08 -08:00
Francisco Ryan Tolmasky I 3295966022 Updated Jake package version number.
Reviewed by me.
2010-01-10 12:18:13 -08:00
Randall Luecke 8f43f5a4a1 Added resource for drag and drop image. 2010-01-10 00:37:42 -06:00
Tom Robinson 379f40c1be Cleanup build dir checking, print deprecation warning for STEAM_BUILD 2010-01-09 15:35:31 -08:00
Randall Luecke c2282af879 Removed called to super on keyDown which was invoking a scroll in addition to calling scrollRowToVisible. 2010-01-09 14:21:07 -06:00
Tom Robinson d057b1909f Point to TextMate bundle 2010-01-08 15:36:36 -08:00
Alexander LjungbergandRoss Boucher 3cb3bfc008 Fixed: CPArrayController selectionIndexes returned nil initially rather than an empty index set. 2010-01-08 09:58:54 -08:00
Ross Boucher 2ba4e99114 Merge commit 'luddep/font-improvements' into fonts 2010-01-08 09:43:39 -08:00
Ross Boucher f61a6ba5ff Fix an issue where _CPImageAndTextView, if it had an image, wouldn't show the image if it hadn't already been loaded. In other words, it now listens for image load events and redisplays. 2010-01-08 09:34:43 -08:00
luddep 34a6389a92 CPFont now supports multiple font families. Closes #255. 2010-01-08 18:05:33 +01:00
Francisco Ryan Tolmasky I b675adbbb0 Fix for text being gone in buttons.
Reviewed by me.
2010-01-08 04:03:48 -08:00
Ross Boucher e46da0e2f2 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-07 22:33:57 -08:00
Francisco Ryan Tolmasky I 44b257a749 Removed spaces at the end of lines.
Reviewed by me.
2010-01-07 22:23:32 -08:00
luddepandRoss Boucher fe2599eb35 buttons now momentarily go the the pressed state when clicked programmatically. Closes #187 2010-01-07 22:17:05 -08:00
Randall Luecke d791a189bc added support for HUD scroll bars 2010-01-08 00:15:32 -06:00
Randall Luecke bbc521a2f3 removed call to scrollRowToVisible: the bug is in clipviews and should not be fixed in the tableview itself. 2010-01-08 00:05:24 -06:00
Francisco Ryan Tolmasky I 56f6da606c Missing licenses on a few files.
Reviewed by me.
2010-01-07 19:33:28 -08:00
Francisco Ryan Tolmasky I 3e098b7479 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-07 19:30:53 -08:00
Francisco Ryan Tolmasky I 7e2fe6d5be Fix for white flash when loading Cappuccino apps.
Reviewed by boucher.
2010-01-07 19:30:17 -08:00
Randall Luecke c4b2cf9394 Patch for inline editing in CPTableView and clean up of doubleAction: 2010-01-07 20:35:27 -06:00
Randall Luecke 9ac823833a Fix for TableView drag being started while sometimes selecting 2010-01-07 19:42:31 -06:00
Francisco Ryan Tolmasky I 60132c085c Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-07 17:12:41 -08:00
Francisco Ryan Tolmasky I 5e14e65eb0 Fix for CPArray test not passing.
Reviewed by me.
2010-01-07 16:36:25 -08:00
Randall Luecke 64063fb77d Support for drag and drop in TableTest 2010-01-07 18:31:59 -06:00
Randall Luecke aa309ef27c Implementation of drag and drop, auto resizing columns, keyboard support, scrollToVisible for columns and rows, double click action, deselectAll, and various other bug fixes and features. 2010-01-07 17:34:02 -06:00
Scott KyleandRoss Boucher 4c81c9e21e Fixed typo "Janurary" 2010-01-07 12:26:51 -08:00
Francisco Ryan Tolmasky I f4912eb23b Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-06 22:51:31 -08:00
Francisco Ryan Tolmasky I 7f85b8b33f Tiny bit more support for toolbars in nib2cib.
Reviewed by me.
2010-01-06 21:08:01 -08:00
Tom Robinson 85c68f78da Update for compatibility with latest narwhal. Switch back to 280north/narwhal 2010-01-06 20:00:37 -08:00
Francisco Ryan Tolmasky I af03085d5f Fix for incorrect menu logic.
Reviewed by me.
2010-01-05 19:20:47 -08:00
Francisco Ryan Tolmasky I b7d747ee17 Fixed a bug in CPTreeNode's KVO implementation.
Reviewed by me.
2010-01-05 15:49:16 -08:00
Francisco Ryan Tolmasky I b6f100888a Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2010-01-05 11:15:45 -08:00
Francisco Ryan Tolmasky I 3cfd392e3e Added new automatic undo API to CPUndoManager.
Added archiving support for CPTreeNode.

Reviewd by me.
2010-01-05 11:14:56 -08:00
Ross Boucher 7ed98a8655 Fix a typo pointed out by Bruno on the mailing list. 2010-01-05 09:50:02 -05:00
Ross Boucher d78eb4a4e5 Fix an undefined notification variable 2010-01-04 19:11:10 -05:00
Randall LueckeandRoss Boucher a3d168b646 left unnessisary line... whoops 2010-01-04 10:24:45 -05:00
Randall LueckeandRoss Boucher 5018df511b fix for window overlapping the menu bar if the user dragged it up there. 2010-01-04 10:24:38 -05:00
Ross Boucher 09345a9d53 Use a notificaiton rather than a direct call for windowDidResize:
Closes #393.
2010-01-04 10:21:16 -05:00
Francisco Ryan Tolmasky I 8b17cd3cde Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-31 01:24:51 -08:00
Francisco Ryan Tolmasky I 403fcd8fff Preparing for options fix in Narhwal.
Reviewed by me.
2009-12-30 23:52:55 -08:00
tlrobinson 409be4020b Temporarily use tlrobinson/narwhal/master in bootstrap. 2009-12-29 13:35:48 -08:00
Nicholas Small 24801a220c Merge branch 'jake' of github.com:280north/cappuccino into jake 2009-12-26 19:12:31 -05:00
Nicholas Small 19b9f4e1c1 Enabling an accordion item will cause it to expand. 2009-12-26 19:11:33 -05:00
Francisco Ryan Tolmasky I 48d584df58 Fixed typo in setSubviews:.
Reviewed by me.
2009-12-26 01:20:16 -08:00
Francisco Ryan Tolmasky I dd999a29fd Added applyChange:toKeyPath: and inverseChangedDictionary to support "automatic" undo with KVO.
Reviewed by me.
2009-12-24 19:15:38 -08:00
Francisco Ryan Tolmasky I 75fdfb5a0b Improved observable arrays to support indexOfObject:, indexOfObjectIdenticalTo:, and removeObjectIdenticalTo:.
Reviewed by me.
2009-12-24 18:45:20 -08:00
Francisco Ryan Tolmasky I 6b4db4e9ae Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-23 19:32:43 -08:00
Francisco Ryan Tolmasky I 2571b24f22 Removed TextMate and Xcode files since the ones being used now have their own repos. Linked to them in the README.
Reviewed by me.
2009-12-23 19:31:51 -08:00
Nicholas Small 855a9eea44 Merge branch 'jake' of github.com:280north/cappuccino into jake 2009-12-23 16:51:46 -05:00
Nicholas Small 189e299592 Added CPAccordionView -setEnabled:forItemAtIndex: 2009-12-23 16:50:56 -05:00
Ross Boucher 6cbaa35849 Add CPOperation to Foundation 2009-12-23 11:30:10 -05:00
Ross Boucher cb1cfa4d94 Better support for recursing in CPDictionaryWithJSObject: 2009-12-20 20:32:17 -05:00
Ross Boucher 5bbf893a37 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-20 20:11:59 -05:00
Ross Boucher 3ddbfb5dea Encode the header clip view in the CPCoder methods.
Closes 363.
2009-12-20 20:11:22 -05:00
Francisco Ryan Tolmasky I 5352d062d5 Fix for boundsOrigin and boundsSize being affected by bounds. Also changed UID to return a string instead of a Number.
Reviewed by me.
2009-12-20 17:02:06 -08:00
Randall LueckeandFrancisco Ryan Tolmasky I e15cbfca33 fix bug in CPPlatformWindow where the visible frame for the platform window would offset itself for the menu bar height, even though no menu bar would be displayed because it's not the primaryPlatformWindow 2009-12-20 15:44:39 -08:00
Francisco Ryan Tolmasky I 51b58f911e Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-20 13:01:11 -08:00
Francisco Ryan Tolmasky I 7acfbb9eed Added [CPView setSubviews:] which allows you to add multiple subviews, remove multiple subviews, and reorder multple subviews.
Reviewed by me.
2009-12-20 13:00:25 -08:00
Ross Boucher 4bf9853a25 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-20 13:13:15 -05:00
Ross Boucher 58c6db0a8f Fix the logic behind CPURLConnection's _isLocalFileConnection 2009-12-20 13:12:29 -05:00
tlrobinson aed52a7829 Improved bootstrap.sh further. Prompt to delete existing installations, etc. 2009-12-19 23:16:37 -08:00
Ross Boucher a1e24a3f95 Fix a bug where keyPaths which had a component evaluating to self would send notifications containing the wrong keypath in the observation.
Includes test case.
2009-12-19 17:47:02 -05:00
Ross Boucher 11cff29916 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-19 15:32:52 -05:00
Ross Boucher f184b9bcc4 Add a few KVO tests around arrays 2009-12-19 15:32:23 -05:00
tlrobinson bab0024e0c Cleanup some build scripts 2009-12-19 04:31:11 -08:00
aburkhalterandtlrobinson deed92cff7 Toll-free bridge Error to CPException. Add rhinoException in objj_exception for better error reporting. 2009-12-19 03:49:22 -08:00
Francisco Ryan Tolmasky I a9bc949679 Actual fix for disabled items in CPMenu. Previous fix still selected disabled items and showed submenus for disabled items.
Reviewed by me.
2009-12-18 22:31:12 -08:00
Randall LueckeandRoss Boucher 1411410f4e fixed bug in CPMenu where action would be sent when the user clicked on a disabled menu item. 2009-12-18 18:43:03 -05:00
Ross Boucher 648fbe1b10 Add sendsActionOnEndEditing to the CPCoding methods for CPControl 2009-12-18 15:54:44 -05:00
Ross Boucher 7042f89620 Fix a return type error. Closes #358. 2009-12-17 00:57:09 -05:00
Ross Boucher e235fffb5e Correct HTML escaping and unescaping in Objective-J/plist. Closes 361. 2009-12-17 00:54:00 -05:00
Ross Boucher 6aadd13450 Update CPColorPanel to handle drag and drop correctly, which broke with native drag and drop. Closes 364. 2009-12-17 00:25:49 -05:00
Ross Boucher 349de098af Merge branch 'jake' of git@github.com:280north/cappuccino into jake
Conflicts:
	AppKit/CPMenuItem/CPMenuItem.j
2009-12-16 19:00:48 -05:00
Ross Boucher 5527e585f6 Make Windows handle key equivalents in menus correctly. Make the menu display the string properly on Windows too. 2009-12-16 18:58:21 -05:00
Francisco Ryan Tolmasky I a6e9814dfc Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-16 15:03:27 -08:00
Francisco Ryan Tolmasky I f01a7d3933 Fix for menu items incorrectly leaving out shift symbol if the key equivalent is uppercase.
Reviewed by me.
2009-12-16 15:02:35 -08:00
Nicholas Small d2cd3b899f Fix CPTabViewItem -tabView. 2009-12-16 00:22:35 -05:00
Francisco Ryan Tolmasky I ac2c0d5d84 Update CPUndoManager to post checkpoint notifications and only create run loop performs if undos actually take place.
Reviewed by me.
2009-12-15 16:37:47 -08:00
Ross Boucher f0d0b512ca Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-13 18:30:16 -08:00
Ross Boucher c859ffd0f7 Support for copy/paste/cut and selectedRange/setSelectedRange in CPTextField.
Improvements to the Pasteboard integration code from yesterday.
2009-12-13 18:29:25 -08:00
Tom Robinson 4eb57f3cc5 Merge branch 'jake' of github.com:280north/cappuccino into jake 2009-12-13 15:02:38 -08:00
Tom Robinson 6218bfaf9e Rewrite/cleanup of press. Incomplete, but press --flatten "works" for some value of "work". 2009-12-13 15:01:19 -08:00
Ross Boucher 4d5cdcaeae Fix for the pasteboard changes breaking everything. 2009-12-12 18:36:48 -08:00
Ross Boucher 6ad62a6f2f Add support for native pasteboards to webtop 2009-12-12 14:15:45 -08:00
Ross Boucher 37d4b151d7 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-11 16:55:36 -08:00
Ross Boucher 37c1d804f6 Fix for text shadows sometimes being the wrong color.
Closes #359.
2009-12-11 16:54:38 -08:00
Francisco Ryan Tolmasky I d200df3e9c Typo in last commit.
Reviewed by me.
2009-12-11 12:03:25 -08:00
Francisco Ryan Tolmasky I eb43e416ae Added CPProxy class to support better undo proxying in CPUndoManager.
Closes #370.
Closes #371.

Reviewed by me.
2009-12-11 11:38:26 -08:00
Francisco Ryan Tolmasky I e6244f71bd Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-11 11:16:37 -08:00
Francisco Ryan Tolmasky I 403277ed06 Further refined KVO tests.
Reviewed by me.
2009-12-11 11:16:17 -08:00
Ross Boucher dbe8a59c3c Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-11 10:58:40 -08:00
Ross Boucher a98de54db4 A few additions for pretty printing things and getting better error messages 2009-12-11 10:58:07 -08:00
Francisco Ryan Tolmasky I 7edb7266f2 Added test for old dependent values in KVO.
Reviewed by me.
2009-12-11 10:54:17 -08:00
Nicholas Small d14e077511 Make CPTableView selection notifications behave the same as in Cocoa. 2009-12-10 03:07:22 -05:00
Francisco Ryan Tolmasky I 211c14e316 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-07 18:59:57 -08:00
Francisco Ryan Tolmasky I 4fbc140551 Better descriptions for CPArray.
Reviewed by me.
2009-12-07 18:54:01 -08:00
Ross Boucher ee8e65c80d Fix for alt+character key events not propagating correctly.
Closes #354.
2009-12-05 16:58:26 -08:00
Ross Boucher 1db2e0282a Typo in the new platform window code for cursors 2009-12-04 18:41:57 -08:00
Ross Boucher 2351f73c76 Make the new cursor stuff work across platform windows 2009-12-04 18:07:53 -08:00
Ross Boucher 20a38c3aac Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-04 16:49:22 -08:00
Ross Boucher bca25d0f5f Fix for windows being super floaty 2009-12-04 16:48:43 -08:00
Ross Boucher b26853e4d7 Fix for a path issue with non flattened source files in jake 2009-12-04 16:47:50 -08:00
Francisco Ryan Tolmasky I 39049f82fc Fix for nib2cib incorrectly requiring at least 2 arguments.
Reviewed by me.
2009-12-04 15:02:59 -08:00
Francisco Ryan Tolmasky I a30250f758 Merge branch 'menus' into jake
Closes #73.
Closes #75.
Closes #121.
Closes #130.
Closes #197.

Reviewed by me.
2009-12-04 12:39:49 -08:00
Francisco Ryan Tolmasky I 629737cda3 Apply positioning heuristics to +[CPMenu popUpMenu...] as well.
Reviewed by me.
2009-12-04 12:12:53 -08:00
Francisco Ryan Tolmasky I ec41411675 Fix for disabled menu item shadows, and slighlty better positioning for pop up menus.
Reviewed by me.
2009-12-04 11:55:01 -08:00
Francisco Ryan Tolmasky I becdf2bfeb Fix for menus not having the proper font.
Reviewed by me.
2009-12-04 11:35:40 -08:00
Ross Boucher 1e723945f8 Should have removed rather than commented out these lines 2009-12-04 11:25:20 -08:00
Ross Boucher dfb7599bb6 Remove the cursor hack from CPImageAndTextView, set the cursor globally to the default in CPApplication 2009-12-04 11:22:57 -08:00
Ross Boucher e1d3363ad9 A couple fixes to the CPCursor stuff 2009-12-04 11:12:13 -08:00
cacaodevandRoss Boucher c36c750c5d CPCursor implementation tested in WebKit/FF/IE/Opera. See comments in the file for more details. 2009-12-04 11:02:57 -08:00
Francisco Ryan Tolmasky I c7581c0847 Merge branch 'jake' into menus
Conflicts:
	AppKit/CPMenu.j
2009-12-03 22:50:13 -08:00
Ross Boucher 936d65291f Temporary fix until Francisco merges in the menu branch. 2009-12-03 19:31:52 -08:00
Francisco Ryan Tolmasky I a64030ad93 Merge branch 'jake' into menus 2009-12-03 19:25:38 -08:00
cacaodevandRoss Boucher 01d60ad4e9 CPSearchField changes from issue #194 2009-12-03 19:24:43 -08:00
Francisco Ryan Tolmasky I 06b64c6a87 Fix for a few edge cases, and added showsStateColumn support to nib2cib.
Reviewed by me.
2009-12-03 19:24:03 -08:00
Francisco Ryan Tolmasky I 0eff4e2bc0 Fix for moving to a base menu resetting the child menu.
Reviewed by me.
2009-12-03 17:58:49 -08:00
Ross Boucher 44d6139db2 Fix for some resizing issues in CPWebView. 2009-12-03 17:39:44 -08:00
Francisco Ryan Tolmasky I 506e3004b7 Merge branch 'jake' into menus 2009-12-03 17:02:02 -08:00
Francisco Ryan Tolmasky I 9ce4c7a468 Don't highlight items while scrolling.
Reviewed by me.
2009-12-03 16:59:10 -08:00
Ross Boucher 2fc724e469 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-03 16:29:46 -08:00
Ross Boucher afb69a7f03 Set the created window to not be at 0,0. We need real cascading support. 2009-12-03 16:29:08 -08:00
Ross Boucher cd2dd9f12d Remove dead variables 2009-12-03 16:28:56 -08:00
Francisco Ryan Tolmasky I 29963f74d6 Made menu positioning smarter.
Reviewed by me.
2009-12-03 16:24:35 -08:00
Francisco Ryan Tolmasky I 565a017ebd Merge branch 'jake' into menus 2009-12-03 11:21:35 -08:00
Derek HammerandFrancisco Ryan Tolmasky I 0b85847524 Adding reset to CPAppBootstrapper so that application can be restarted programmatically 2009-12-03 11:20:44 -08:00
Francisco Ryan Tolmasky I cfc46edfb8 Fix for properly positioning pop up button menus.
Reviewed by me.
2009-12-03 01:27:53 -08:00
Francisco Ryan Tolmasky I f250373673 Fix for actions not being sent in submenus.
Reviewed by me.
2009-12-03 00:42:13 -08:00
Francisco Ryan Tolmasky I b0acc13da7 Fix for exceptions when not on a menu item.
Reviewed by me.
2009-12-02 23:08:33 -08:00
Francisco Ryan Tolmasky I d705af8965 Added support for indentation levels in menu items.
Reviewed by me.
2009-12-02 20:41:52 -08:00
Francisco Ryan Tolmasky I a401dfddff Merge branch 'jake' into menus 2009-12-02 20:19:14 -08:00
Francisco Ryan Tolmasky I f579fd925e Fixed state columns not showing up.
Reviewed by me.
2009-12-02 20:18:25 -08:00
Ross Boucher e6d86eaa9b Throw an exception for -1 indexes in CPArray objectAtIndex: 2009-12-02 19:19:18 -08:00
Francisco Ryan Tolmasky I 348e45a5cd Some cleanup and a fix for custom views in menus.
Reviewed by me.
2009-12-02 18:40:47 -08:00
Ross Boucher 2120e9cf2a Potential fix for a drawing issue in IE. 2009-12-02 18:27:18 -08:00
Ross Boucher 3002acc895 Change for the way in which we detect full bridge window close 2009-12-02 18:26:55 -08:00
Francisco Ryan Tolmasky I 0b3c313280 Fix for highlight look in menu bars.
Reviewed by me.
2009-12-02 18:12:50 -08:00
Francisco Ryan Tolmasky I 982ab4b4fa Merge branch 'jake' into menus 2009-12-02 17:18:11 -08:00
Ross Boucher a0ee2f384b Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-02 17:15:17 -08:00
Ross Boucher 56a739655f A whole bunch of textfield and key event fixes. 2009-12-02 17:14:47 -08:00
Francisco Ryan Tolmasky I 150ee44da0 Added background highlight to menu bar and fixed highligh turning off after stopping tracking in menu bar.
Reviewed by me.
2009-12-02 16:39:38 -08:00
Francisco Ryan Tolmasky I 78795e3167 Preliminary menu bar support.
Reviewed by me.
2009-12-02 15:57:52 -08:00
tlrobinson b0dd3cd818 Fix nib2cib. 2009-12-01 20:02:55 -08:00
Francisco Ryan Tolmasky I ef12ec54d7 Added new view for menu bar items.
Reviewed by me.
2009-12-01 19:19:24 -08:00
Francisco Ryan Tolmasky I 495b774965 A bit of cleanup.
Reviewed by me.
2009-12-01 17:49:15 -08:00
Ross Boucher 1381bb5c54 Prevent CPViewController from loading the same cibs lots of times. I think the solution should be made generic and put into CPCib though. Closes #348. 2009-12-01 09:25:49 -08:00
Ross Boucher f1d4794dd1 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-01 09:14:45 -08:00
Thomas BalthazarandRoss Boucher d58473c270 Fix for GHissue #348 : CPViewController should cache the cib 2009-12-01 09:14:30 -08:00
Francisco Ryan Tolmasky I 7adf32f36e Changed menu bar background image.
Reviewed by me.
2009-11-30 23:41:16 -08:00
Francisco Ryan Tolmasky I 5c3beb4160 Fix for _minimumWidth not being defined in the CPMenu class, resulting in minimum widths being applied globally, and menus appearing in strange places in desktop mode.
Reviewed by me.
2009-11-30 23:20:56 -08:00
Francisco Ryan Tolmasky I b82c307007 Added -setMinimumWidth/minimumWidth to CPMenu.
Reviewed by me.
2009-11-30 23:08:05 -08:00
Francisco Ryan Tolmasky I a7010e7598 Accidentally broke normal menu items.
Reviewed by me.
2009-11-30 22:43:36 -08:00
Francisco Ryan Tolmasky I f850cbf780 Better handling of submenu actions.
Reviewed by me.
2009-11-30 22:30:41 -08:00
Tom Robinson 4581fe4f22 Cleanup command line tool args (change objj to include command at args[0]) 2009-11-30 21:45:01 -08:00
Francisco Ryan Tolmasky I 35df54ae99 Merge branch 'jake' into menus 2009-11-30 21:29:27 -08:00
Francisco Ryan Tolmasky I f8a5f91687 Fix for nib2cib leaving cells as targets for menu items.
Reviewed by me.
2009-11-30 21:28:42 -08:00
Francisco Ryan Tolmasky I 4b71557584 Added -popUpMenuPositioningItem:atLocation:inView:callback: and began porting existing uses to it.
Reviewed by me.
2009-11-30 20:54:53 -08:00
Tom Robinson feda903f2f Remove unused junk 2009-11-30 18:45:40 -08:00
Tom Robinson 150e264f0d Remove bake. 2009-11-30 17:21:16 -08:00
Tom Robinson b592f6ae92 Remove submodules 2009-11-30 17:15:37 -08:00
Francisco Ryan Tolmasky I 37ba8fb57d Merge branch 'jake' into menus 2009-11-30 02:02:48 -08:00
Francisco Ryan Tolmasky I 72f80cdbed Cleaned up menu constraints.
Reviewed by me.
2009-11-30 02:01:44 -08:00
Francisco Ryan Tolmasky I c070f20669 Better constraint support, and better support for moving out of submenus.
Reviewed by me.
2009-11-29 19:54:15 -08:00
Stephen Ierodiaconou 0ddb17862c Merge branch 'master' of git://github.com/280north/cappuccino into CPDecimalNumber 2009-11-28 17:02:43 +00:00
Ross Boucher a4d5165a3d Fix for style issues. 2009-11-26 19:53:36 -05:00
Abhinav GuptaandRoss Boucher 4fdddfb585 Fixed CPString's commonPrefixWithString to be faster. 2009-11-26 19:49:41 -05:00
Abhinav GuptaandRoss Boucher 0575e96b60 Added commonPrefixWithString method to CPString and tests for it. 2009-11-26 18:13:01 -05:00
Ross Boucher d0a8749986 Fix a type in CPOutlineView. Closes #265. 2009-11-25 00:09:55 -05:00
Ross Boucher 44fbf8afe2 Add support for encoding dates, courtesy of luddep. 2009-11-24 23:02:38 -05:00
Ross Boucher 1eb9202233 A few style guideline changes. 2009-11-24 22:56:18 -05:00
Alexander LjungbergandRoss Boucher b7da92d225 CPDate initWithString: now takes proper international format strings like NSDate. Similarly CPDate description generates such strings. 2009-11-24 22:42:02 -05:00
Ross Boucher e4f6d0db1f Fixes an issue with HUD style alert panels. Closes #343. 2009-11-24 22:13:20 -05:00
Ross Boucher 0a8bd9f687 Remove the "Cancelled" message that Safari shows when an XHR is cancelled during startup. Closes #344. 2009-11-24 18:38:25 -05:00
Ross Boucher f2608998f9 Fixes a typo in CPRectContainsRect by simply calling out to CGRectContainsRect. We should explore simply removing this method entirely. Includes test cases. Closes #345. 2009-11-24 18:30:31 -05:00
Ross Boucher ffb08d32ce Fix an issue with storing 0 in a CPSet. Includes test cases. Closes #337. 2009-11-24 16:06:32 -05:00
Francisco Ryan Tolmasky I 119e776ddc Make scrolling work in submenus.
Reviewed by me.
2009-11-23 23:35:58 -08:00
Francisco Ryan Tolmasky I 652930d5aa Merge branch 'jake' into menus 2009-11-22 16:43:43 -08:00
Francisco Ryan Tolmasky I e3babe97e4 Update to fix menu item sizes breaking on second open.
Reviewed by me.
2009-11-20 23:34:21 -08:00
Ross Boucher 72d01865ae Add about panel 2009-11-20 18:06:16 -08:00
Ross Boucher b9664681a3 Better error reporting for narwhal-jsc 2009-11-19 15:29:20 -08:00
Ross Boucher fd5c545189 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-19 14:54:51 -08:00
Ross Boucher 0639f4b00f Exit from subjake if the subjake returns non zero status code. Don't exit in the compiler (required for building in Atlas to not kill the process) 2009-11-19 14:48:18 -08:00
Tom Robinson ab49986238 Add --clone option to bootstrap, and prompt for location 2009-11-19 14:18:49 -08:00
Francisco Ryan Tolmasky I a4fdc50d1d Move these back into their own folders.
Reviewed by me.
2009-11-19 14:04:16 -08:00
Francisco Ryan Tolmasky I ed228b6183 Merge branch 'jake' into menus 2009-11-19 14:02:34 -08:00
Francisco Ryan Tolmasky I e0e675531a Temporarily move these out into the main folder.
Reviewed by me.
2009-11-19 14:02:16 -08:00
Francisco Ryan Tolmasky I 44e0879224 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-19 13:26:36 -08:00
Francisco Ryan Tolmasky I 1e6fa93ea2 Fix for NSScrollView breaking nib2cib.
Reviewed by me.
2009-11-19 13:26:02 -08:00
Tom Robinson 2aaed6bffd Replace outdated objj-executable with Narwhal magic. 2009-11-19 00:17:12 -08:00
Francisco Ryan Tolmasky I 2d367a8b47 Fix for not being able to drag window from spaces in toolbar.
Reviewed by me.
2009-11-18 22:08:57 -08:00
Francisco Ryan Tolmasky I 52c18abc5e Fix for class_addMethod with a root class.
Reviewed by me.
2009-11-18 21:56:10 -08:00
Ross Boucher 595c70ed56 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-18 14:28:33 -08:00
Alexander LjungbergandRoss Boucher 9faec8decd Fixed: calling setIsPaneSplitter: on a CPTableView would change the divider width but the subviews would not change size to match. 2009-11-18 14:22:58 -08:00
Tom Robinson 90dc1f6cf8 Reorder shell config file checks. 2009-11-18 01:34:01 -08:00
Francisco Ryan Tolmasky I ba01976151 Added target and action to radio groups.
Reviewed by me.
2009-11-17 19:52:20 -08:00
Francisco Ryan Tolmasky I 4d7f5a8a09 Fix for fixing state after turning setAllowsMixedState to NO.
Reviewed by me.
2009-11-17 19:17:58 -08:00
Ross Boucher 2d01fa6f94 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-17 17:04:12 -08:00
Ross Boucher 970f848b84 Make CPAlert slightly (but only slightly) more externally hackable 2009-11-17 17:03:42 -08:00
Tom Robinson 31feec0465 Flush stdin after writing file to ShrinkSafe process (fixes building in Rhino) 2009-11-17 17:02:07 -08:00
Francisco Ryan Tolmasky I 2466c14300 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-17 14:49:30 -08:00
Francisco Ryan Tolmasky I 49927fcfb7 Fix for building projects where source files are in nested subfolders.
Reviewed by me.
2009-11-17 14:46:54 -08:00
Ross Boucher f612683dfb Taking this out for now. 2009-11-17 10:26:58 -08:00
Ross Boucher 11e6ad2153 Adding a simple way to set a function for the target/action 2009-11-17 09:28:44 -08:00
Klaas Pieter AnnemaandRoss Boucher d041c69e0d Added a check if the window is loaded in CPWindowController 2009-11-17 09:19:05 -08:00
Randall LueckeandRoss Boucher b394052145 fixed tableview typo 2009-11-17 09:16:30 -08:00
Francisco Ryan Tolmasky I bce83e45b5 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-16 18:28:04 -08:00
Francisco Ryan Tolmasky I 77bd8d3a76 Add hide: and hideOthers support.
Reviewed by me.
2009-11-16 18:27:38 -08:00
Tom Robinson 118ece9f1c Implement "which" for bootstrap and switch to 280north repos. 2009-11-16 17:11:05 -08:00
Francisco Ryan Tolmasky I 971956a6ba Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-16 15:09:51 -08:00
Francisco Ryan Tolmasky I 48cd362015 Fix for using unicode characters with capp config.
Reviewed by me.
2009-11-16 15:09:22 -08:00
Tom Robinson b12b1bf662 Incorrect case in require("os") 2009-11-16 14:12:53 -08:00
Francisco Ryan Tolmasky I 6829d502d7 Better support for opening files.
Reviewed by me.
2009-11-16 11:47:06 -08:00
Francisco Ryan Tolmasky I e94ddb4179 First pass at submenus.
Reviewed by me.
2009-11-12 18:20:16 -08: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
Ross Boucher 3635d0ec26 Bindings Checkpoint. 2009-09-21 13:27:50 -07:00
stevegeek 81e15c91f4 Merge branch 'master' of git://github.com/280north/cappuccino 2009-09-21 09:30:21 +01:00
Ross Boucher 105bb7512f Merge branch 'master' of git@github.com:280north/cappuccino into bindings 2009-09-20 22:55:19 -07:00
Ross Boucher b63e50dacb Fix for the objectValue/value thing in bindings. Removed unnecessary code in CPControl 2009-09-20 19:33:03 -07:00
Ross Boucher 417b5c8b97 Merge branch 'master' into bindings 2009-09-20 18:14:17 -07:00
Stephen Ierodiaconou b8afbb66a7 Merge branch 'master' of git://github.com/280north/cappuccino 2009-09-20 10:35:33 +01:00
Francisco Ryan Tolmasky I 08ed16c493 Made CPObjectController's contentObject binding bidirectional.
Reviewed by me.
2009-07-22 23:54:38 -07:00
Francisco Ryan Tolmasky I 734efdf343 Merge branch 'master' into bindings 2009-07-22 19:40:23 -07:00
Francisco Ryan Tolmasky I 1195678893 Removed Framework directories from bindings tests.
Reviewed by me.
2009-07-22 17:54:53 -07:00
Francisco Ryan Tolmasky I 4ad2c2221f Merge branch 'master' into bindings
Conflicts:
	AppKit/CPControl.j
	AppKit/CPSlider.j
	Foundation/CPArray+KVO.j
2009-07-22 16:41:58 -07: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
Ross Boucher 18cf198592 Beginnings of a simple array controller test app. 2009-02-19 01:36:40 -08:00
Ross Boucher 9bbe51fa64 CPArrayController works simply with bindings and arrangedObjects 2009-02-19 01:29:39 -08:00
Ross Boucher 4de3a34a3e CPObjectController now works, as do bindings and CPControls. 2009-02-16 00:37:50 -08:00
Ross Boucher c028425f14 More bindings fixes. 2009-02-09 17:35:25 -08:00
Ross Boucher 7d03d8a58f Some test apps for bindings. 2009-02-07 13:00:27 -07:00
Ross Boucher db0e88d8a7 Various fixes. 2009-02-07 12:59:50 -07:00
Ross Boucher 1b8aca26a3 In progress work on bindings. 2009-02-07 12:55:15 -07:00
Ross Boucher b239053810 First take at CPController, CPObjectController. 2009-02-07 12:55:05 -07:00
Ross Boucher 1acb130be1 Add preliminary support for Key Value Bindings to Cappuccino. 2009-02-07 12:54:59 -07:00
1467 changed files with 182193 additions and 36261 deletions
+5
View File
@@ -4,3 +4,8 @@ Build
Demos
./Aristo
WebSite
.push-package
*.xcodeproj/*.pbxuser
*.xcodeproj/*.perspectivev3
xcuserdata/
!*.xcodeproj/project.pbxproj
-12
View File
@@ -1,12 +0,0 @@
[submodule "External/narwhal"]
path = External/narwhal
url = git://github.com/tlrobinson/narwhal.git
[submodule "External/jack"]
path = External/jack
url = git://github.com/tlrobinson/jack.git
[submodule "External/browserjs"]
path = External/browserjs
url = git://github.com/tlrobinson/browserjs.git
[submodule "External/ojunit"]
path = External/ojunit
url = git://github.com/280north/ojunit.git
+25 -4
View File
@@ -24,25 +24,30 @@
@import "CPAlert.j"
@import "CPAnimation.j"
@import "CPApplication.j"
@import "CPArrayController.j"
@import "CPAttributedString+Additions.j"
@import "CPBezierPath.j"
@import "CPBox.j"
@import "CPBrowser.j"
@import "CPButton.j"
@import "CPButtonBar.j"
@import "CPCheckBox.j"
@import "CPCib.j"
@import "CPCibBindingConnector.j"
@import "CPCibConnector.j"
@import "CPCibControlConnector.j"
@import "CPCibLoading.j"
@import "CPCibOutletConnector.j"
@import "CPClipView.j"
@import "CPCollectionViewItem.j"
@import "CPCollectionView.j"
@import "CPCollectionViewItem.j"
@import "CPColor.j"
@import "CPColorPanel.j"
@import "CPColorWell.j"
@import "CPCompatibility.j"
@import "CPControl.j"
@import "CPCookie.j"
@import "CPCursor.j"
@import "CPDocument.j"
@import "CPDocumentController.j"
@import "CPEvent.j"
@@ -51,32 +56,48 @@
@import "CPFont.j"
@import "CPFontManager.j"
@import "CPGeometry.j"
@import "CPGraphics.j"
@import "CPImage.j"
@import "CPImageView.j"
@import "CPKeyBinding.j"
@import "CPLevelIndicator.j"
@import "CPMenu.j"
@import "CPMenuItem.j"
@import "CPOpenPanel.j"
@import "CPOutlineView.j"
@import "CPPanel.j"
@import "CPPasteboard.j"
@import "CPPopUpButton.j"
@import "CPPredicateEditor.j"
@import "CPPredicateEditorRowTemplate.j"
@import "CPProgressIndicator.j"
@import "CPRadio.j"
@import "CPResponder.j"
@import "CPSearchField.j"
@import "CPScrollView.j"
@import "CPRuleEditor.j"
@import "CPScroller.j"
@import "CPScrollView.j"
@import "CPSearchField.j"
@import "CPSecureTextField.j"
@import "CPSegmentedControl.j"
@import "CPShadow.j"
@import "CPSlider.j"
@import "CPSound.j"
@import "CPSplitView.j"
@import "CPTabView.j"
@import "CPStepper.j"
@import "CPString+Additions.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 "_CPToolTip.j"
@import "CPTreeNode.j"
@import "CPUserDefaultsController.j"
@import "CPView.j"
@import "CPViewAnimation.j"
@import "CPViewController.j"
@import "CPWebView.j"
@import "CPWindow.j"
+68 -13
View File
@@ -26,11 +26,16 @@
@import <Foundation/CPIndexSet.j>
@import <Foundation/CPString.j>
@import <AppKit/CPView.j>
#import "CoreGraphics/CGGeometry.h"
@import "CPView.j"
@import "CPButton.j"
/*!
@ingroup appkit
@class CPAccordionViewItem
<p>A CPAccordionViewItem represents a single section of a CPAccordionView.</p>
*/
@implementation CPAccordionViewItem : CPObject
{
CPString _identifier @accessors(property=identifier);
@@ -43,6 +48,10 @@
return [self initWithIdentifier:@""];
}
/*!
Initializes a new CPAccordionViewItem with the specified identifier. This identifier may
then be used in subsequent methods to provide abstract introspection of the CPAccordionView.
*/
- (id)initWithIdentifier:(CPString)anIdentifier
{
self = [super init];
@@ -55,6 +64,25 @@
@end
/*!
@ingroup appkit
@class CPAccordionView
<p>CPAccordionView provides a container for CPAccordionViewItem objects and manages layout state
for all sub-layout items.</p>
<strong>Example</strong><br />
<pre>
var myAccordionView = [[CPAccordionView alloc] initWithFrame:CGRectMakeZero()];
var firstItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"firstSection"]];
[firstItem setView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection"]];
[secondItem setView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
[myAccordionView addItem:firstItem];
[myAccordionView addItem:secondItem];
[myAccordionView setAutoresizingMask: CPViewWidthSizable | CPViewHeightSizable];
</pre>
*/
@implementation CPAccordionView : CPView
{
CPInteger _dirtyItemIndex;
@@ -64,7 +92,10 @@
CPMutableArray _itemViews;
CPIndexSet _expandedItemIndexes;
}
/*!
Initializes the receiver for usage with the specified bounding rectangle
@return the initialized view
*/
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
@@ -95,13 +126,17 @@
{
return _items;
}
- (void)addItem:(CPAccordionItem)anItem
/*!
Append a CPAccordionViewItem to the receiver. Note that the CPAccordionViewItem must contain
a valid CPView derived component or a TypeError will be generated when the contents of the
ViewItem are disclosed.
*/
- (void)addItem:(CPAccordionViewItem)anItem
{
[self insertItem:anItem atIndex:_items.length];
}
- (void)insertItem:(CPAccordionItem)anItem atIndex:(CPInteger)anIndex
- (void)insertItem:(CPAccordionViewItem)anItem atIndex:(CPInteger)anIndex
{
// FIXME: SHIFT ITEMS RIGHT
[_expandedItemIndexes addIndex:anIndex];
@@ -122,7 +157,7 @@
[self setNeedsLayout];
}
- (void)removeItem:(CPAccordionItem)anItem
- (void)removeItem:(CPAccordionViewItem)anItem
{
[self removeItemAtIndex:[_items indexOfObjectIdenticalTo:anItem]];
}
@@ -178,7 +213,7 @@
if ([itemView isCollapsed])
[self expandItemAtIndex:anIndex];
else
[self collapseItemAtIndex:anIndex];
}
@@ -197,6 +232,20 @@
return indexSet;
}
- (void)setEnabled:(BOOL)isEnabled forItemAtIndex:(CPInteger)anIndex
{
var itemView = _itemViews[anIndex];
if (!itemView)
return;
if (!isEnabled)
[self collapseItemAtIndex:anIndex];
else
[self expandItemAtIndex:anIndex];
[itemView setEnabled:isEnabled];
}
- (void)_invalidateItemsStartingAtIndex:(CPInteger)anIndex
{
if (_dirtyItemIndex === CPNotFound)
@@ -221,7 +270,7 @@
{
if (_items.length <= 0)
return [self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), 0.0)];
if (_dirtyItemIndex === CPNotFound)
return;
@@ -301,6 +350,12 @@
[_headerView setStringValue:aLabel];
}
- (void)setEnabled:(BOOL)isEnabled
{
if ([_headerView respondsToSelector:@selector(setEnabled:)])
[_headerView setEnabled:isEnabled];
}
- (void)setContentView:(CPView)aView
{
if (_contentView === aView)
@@ -312,7 +367,7 @@
_contentView = aView;
[_contentView addObserver:self forKeyPath:@"frame" options:0 context:NULL];
[_contentView addObserver:self forKeyPath:@"frame" options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:NULL];
[self addSubview:_contentView];
@@ -336,7 +391,7 @@
[_contentView setFrameSize:_CGSizeMake(aWidth, contentHeight)];
[self setFrame:_CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)];
}
}
}
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
@@ -353,7 +408,7 @@
/*
else if (aKeyPath === "itemHeaderPrototype")
{
}
*/
}
+578 -184
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
@@ -26,39 +28,34 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@import <AppKit/CPApplication.j>
@import <AppKit/CPButton.j>
@import <AppKit/CPColor.j>
@import <AppKit/CPFont.j>
@import <AppKit/CPImage.j>
@import <AppKit/CPImageView.j>
@import <AppKit/CPPanel.j>
@import <AppKit/CPTextField.j>
@import "CPApplication.j"
@import "CPButton.j"
@import "CPColor.j"
@import "CPFont.j"
@import "CPImage.j"
@import "CPImageView.j"
@import "CPPanel.j"
@import "CPTextField.j"
/*
@global
@group CPAlertStyle
*/
CPWarningAlertStyle = 0;
CPWarningAlertStyle = 0;
/*
@global
@group CPAlertStyle
*/
CPInformationalAlertStyle = 1;
CPInformationalAlertStyle = 1;
/*
@global
@group CPAlertStyle
*/
CPCriticalAlertStyle = 2;
var CPAlertWarningImage,
CPAlertInformationImage,
CPAlertErrorImage;
CPCriticalAlertStyle = 2;
/*!
@ingroup appkit
CPAlert is an alert panel that can be displayed modally to present the
user with a message and one or more options.
@@ -74,41 +71,83 @@ var CPAlertWarningImage,
@delegate -(void)alertDidEnd:(CPAlert)theAlert returnCode:(int)returnCode;
Called when the user dismisses the alert by clicking one of the buttons.
@param theAlert the alert panel that the user dismissed
@param returnCode the index of the button that the user clicked (starting from 0,
@param returnCode the index of the button that the user clicked (starting from 0,
representing the first button added to the alert which appears on the
right, 1 representing the next button to the left and so on)
*/
@implementation CPAlert : CPObject
@implementation CPAlert : CPView
{
CPPanel _alertPanel;
BOOL _showHelp @accessors(property=showsHelp);
BOOL _showSuppressionButton @accessors(property=showsSuppressionButton);
CPAlertStyle _alertStyle @accessors(property=alertStyle);
CPString _title @accessors(property=title);
CPView _accessoryView @accessors(property=accessoryView);
CPImage _icon @accessors(property=icon);
CPArray _buttons @accessors(property=buttons,readonly);
CPCheckBox _suppressionButton @accessors(property=suppressionButton,readonly);
id _delegate @accessors(property=delegate);
id _modalDelegate;
SEL _didEndSelector;
CPWindow _window @accessors(property=window,readonly);
int _defaultWindowStyle;
CPTextField _messageLabel;
CPImageView _alertImageView;
CPTextField _informativeLabel;
CPTextField _messageLabel;
CPButton _alertHelpButton;
CPAlertStyle _alertStyle;
CPString _windowTitle;
int _windowStyle;
int _buttonCount;
CPArray _buttons;
id _delegate;
BOOL _needsLayout;
}
+ (void)initialize
#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
{
if (self != CPAlert)
return;
var alert = [[CPAlert alloc] init];
var bundle = [CPBundle bundleForClass:[self class]];
[alert setMessageText:aMessage];
[alert addButtonWithTitle:defaultButtonTitle];
CPAlertWarningImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-warning.png"]
size:CGSizeMake(32.0, 32.0)];
CPAlertInformationImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-information.png"]
size:CGSizeMake(32.0, 32.0)];
CPAlertErrorImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-error.png"]
size:CGSizeMake(32.0, 32.0)];
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;
}
/*!
@@ -116,162 +155,384 @@ var CPAlertWarningImage,
*/
- (id)init
{
if (self = [super init])
{
_buttonCount = 0;
_buttons = [CPArray array];
_alertStyle = CPWarningAlertStyle;
self = [super init];
[self setWindowStyle:nil];
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
/*!
Sets the window appearance.
@param styleMask - Either CPHUDBackgroundWindowMask or nil for standard.
set the theme to use
@param the theme to use
*/
- (void)setWindowStyle:(int)styleMask
- (void)setTheme:(CPTheme)aTheme
{
_windowStyle = styleMask;
_alertPanel = [[CPPanel alloc] initWithContentRect:CGRectMake(0.0, 0.0, 400.0, 110.0) styleMask:styleMask ? styleMask | CPTitledWindowMask : CPTitledWindowMask];
[_alertPanel setFloatingPanel:YES];
[_alertPanel center];
if (aTheme === [self theme])
return;
[_messageLabel setTextColor:(styleMask & CPHUDBackgroundWindowMask) ? [CPColor whiteColor] : [CPColor blackColor]];
if (aTheme === [CPTheme defaultHudTheme])
_defaultWindowStyle = CPTitledWindowMask | CPHUDBackgroundWindowMask;
else
_defaultWindowStyle = CPTitledWindowMask;
var count = [_buttons count];
for(var i=0; i < count; i++)
{
var button = _buttons[i];
[button setFrameSize:CGSizeMake([button frame].size.width, (styleMask == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
[button setBezelStyle:(styleMask & CPHUDBackgroundWindowMask) ? CPHUDBezelStyle : CPRoundedBezelStyle];
[[_alertPanel contentView] addSubview:button];
}
if (!_messageLabel)
{
var bounds = [[_alertPanel contentView] bounds];
_messageLabel = [[CPTextField alloc] initWithFrame:CGRectMake(57.0, 10.0, CGRectGetWidth(bounds) - 73.0, 62.0)];
[_messageLabel setFont:[CPFont boldSystemFontOfSize:13.0]];
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
[_messageLabel setAlignment:CPJustifiedTextAlignment];
_alertImageView = [[CPImageView alloc] initWithFrame:CGRectMake(15.0, 12.0, 32.0, 32.0)];
}
[[_alertPanel contentView] addSubview:_messageLabel];
[[_alertPanel contentView] addSubview:_alertImageView];
_window = nil; // will be regenerated at next layout
_needsLayout = YES;
[super setTheme:aTheme];
}
/*!
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.
/*! @deprecated
*/
- (void)setTitle:(CPString)aTitle
- (void)setWindowStyle:(int)aStyle
{
_windowTitle = aTitle;
CPLog.warn("DEPRECATED: setWindowStyle: is deprecated. use setTheme: instead");
[self setTheme:(aStyle === CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]];
}
/*!
Gets the window's title.
*/
- (CPString)title
{
return _windowTitle;
}
/*!
Gets the window's style.
/*! @deprecated
*/
- (int)windowStyle
{
return _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;
}
/*!
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];
}
/*!
Return's the receiver's message text body.
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.
You really shouldn't need more than 3 buttons.
*/
- (void)addButtonWithTitle:(CPString)title
{
var bounds = [[_alertPanel contentView] bounds],
button = [[CPButton alloc] initWithFrame:CGRectMake(CGRectGetWidth(bounds) - ((_buttonCount + 1) * 90.0), CGRectGetHeight(bounds) - 34.0, 80.0, (_windowStyle == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
[button setTitle:title];
[button setTarget:self];
[button setTag:_buttonCount];
[button setAction:@selector(_notifyDelegate:)];
[button setBezelStyle:(_windowStyle == CPHUDBackgroundWindowMask) ? CPHUDBezelStyle : CPRoundRectBezelStyle];
[[_alertPanel contentView] addSubview:button];
if (_buttonCount == 0)
[_alertPanel setDefaultButton:button];
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.
_buttonCount++;
[_buttons addObject:button];
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
@@ -279,34 +540,167 @@ var CPAlertWarningImage,
*/
- (void)runModal
{
var theTitle;
switch (_alertStyle)
if (!([_window styleMask] & _defaultWindowStyle))
{
case CPWarningAlertStyle: [_alertImageView setImage:CPAlertWarningImage];
theTitle = @"Warning";
break;
case CPInformationalAlertStyle: [_alertImageView setImage:CPAlertInformationImage];
theTitle = @"Information";
break;
case CPCriticalAlertStyle: [_alertImageView setImage:CPAlertErrorImage];
theTitle = @"Error";
break;
_needsLayout = YES;
[self _createWindowWithStyle:_defaultWindowStyle];
}
[_alertPanel setTitle:_windowTitle ? _windowTitle : theTitle];
[CPApp runModalForWindow:_alertPanel];
[self layout];
[CPApp runModalForWindow:_window];
}
/* @ignore */
- (void)_notifyDelegate:(id)button
{
[CPApp abortModal];
[_alertPanel close];
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
if (_delegate && [_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:[button tag]];
@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";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[CGSizeMake(400.0, 110.0), CGInsetMake(15, 15, 15, 50), 6, 10,
CPJustifiedTextAlignment, [CPColor blackColor], [CPFont boldSystemFontOfSize:13.0], [CPNull null], CGSizeMakeZero(),
CPJustifiedTextAlignment, [CPColor blackColor], [CPFont systemFontOfSize:12.0], [CPNull null], CGSizeMakeZero(),
CGPointMake(15, 12),
[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",
@"informative-text-alignment", @"informative-text-color", @"informative-text-font", @"informative-text-shadow-color", @"informative-text-shadow-offset",
@"image-offset",
@"information-image",
@"warning-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"
]];
}
@end
+117 -40
View File
@@ -21,6 +21,7 @@
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPTimer.j>
@import "CAMediaTimingFunction.j"
@@ -48,14 +49,14 @@ CPAnimationLinear = 3;
ACTUAL_FRAME_RATE = 0;
/*!
/*!
@ingroup appkit
@class CPAnimation
Manages an animation. Contains timing and progress information.
@par Delegate Methods
@delegate -(BOOL)animationShouldStart:(CPAnimation)animation;
Called at the beginning of \c -startAnimation.
@param animation the animation that will start
@@ -81,13 +82,13 @@ ACTUAL_FRAME_RATE = 0;
{
CPTimeInterval _lastTime;
CPTimeInterval _duration;
CPAnimationCurve _animationCurve;
CAMediaTimingFunction _timingFunction;
float _frameRate;
float _progress;
id _delegate;
CPTimer _timer;
}
@@ -101,7 +102,7 @@ ACTUAL_FRAME_RATE = 0;
- (id)initWithDuration:(float)aDuration animationCurve:(CPAnimationCurve)anAnimationCurve
{
self = [super init];
if (self)
{
_progress = 0.0;
@@ -110,14 +111,14 @@ ACTUAL_FRAME_RATE = 0;
[self setAnimationCurve:anAnimationCurve];
}
return self;
}
/*!
Sets the animation's pace.
@param anAnimationCurve the animation's pace
@throws CPInvalidArgumentException if an invalid animation curve is specified
@throws CPInvalidArgumentException if an invalid animation curve is specified
*/
- (void)setAnimationCurve:(CPAnimationCurve)anAnimationCurve
{
@@ -125,13 +126,13 @@ ACTUAL_FRAME_RATE = 0;
{
case CPAnimationEaseInOut: timingFunctionName = kCAMediaTimingFunctionEaseInEaseOut;
break;
case CPAnimationEaseIn: timingFunctionName = kCAMediaTimingFunctionEaseIn;
break;
case CPAnimationEaseOut: timingFunctionName = kCAMediaTimingFunctionEaseOut;
break;
case CPAnimationLinear: timingFunctionName = kCAMediaTimingFunctionLinear;
break;
@@ -139,7 +140,7 @@ ACTUAL_FRAME_RATE = 0;
reason:"Invalid value provided for animation curve"];
break;
}
_animationCurve = anAnimationCurve;
_timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName];
}
@@ -161,7 +162,7 @@ ACTUAL_FRAME_RATE = 0;
{
if (aDuration < 0)
[CPException raise:CPInvalidArgumentException reason:"aDuration can't be negative"];
_duration = aDuration;
}
@@ -182,7 +183,7 @@ ACTUAL_FRAME_RATE = 0;
{
if (frameRate < 0)
[CPException raise:CPInvalidArgumentException reason:"frameRate can't be negative"];
_frameRate = frameRate;
}
@@ -221,13 +222,13 @@ ACTUAL_FRAME_RATE = 0;
// If we're already animating, or our delegate stops us, animate.
if (_timer || _delegate && [_delegate respondsToSelector:@selector(animationShouldStart:)] && ![_delegate animationShouldStart:self])
return;
if (_progress === 1.0)
_progress = 0.0;
ACTUAL_FRAME_RATE = 0;
_lastTime = new Date();
_timer = [CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(animationTimerDidFire:) userInfo:nil repeats:YES];
}
@@ -242,14 +243,14 @@ ACTUAL_FRAME_RATE = 0;
_lastTime = currentTime;
++ACTUAL_FRAME_RATE;
[self setCurrentProgress:progress];
if (progress === 1.0)
{
[_timer invalidate];
_timer = nil;
if ([_delegate respondsToSelector:@selector(animationDidEnd:)])
[_delegate animationDidEnd:self];
}
@@ -262,10 +263,10 @@ ACTUAL_FRAME_RATE = 0;
{
if (!_timer)
return;
[_timer invalidate];
_timer = nil;
if ([_delegate respondsToSelector:@selector(animationDidStop:)])
[_delegate animationDidStop:self];
}
@@ -302,17 +303,17 @@ ACTUAL_FRAME_RATE = 0;
- (float)currentValue
{
var t = [self currentProgress];
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
return [_delegate animation:self valueForProgress:t];
var c1 = [],
c2 = [];
[_timingFunction getControlPointAtIndex:1 values:c1];
[_timingFunction getControlPointAtIndex:2 values:c2];
return CubicBezierAtTime(t,c1[0],c1[1],c2[0],c2[1],_duration);
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));
};
+607 -226
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+62
View File
@@ -0,0 +1,62 @@
/*
* CPAttributedString+Additions.j
* AppKit
*
* Created by Randy Luecke
* Copyright 2011, RCLConcepts, LLC.
*
* 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
*/
/*
AppKit adds two methods to the CPAttributedString class to support drawing string directly in an CPView.
AppKit also adds similar methods to CPString.
*/
@implementation CPAttributedString (AppKitAdditions)
/*!
Draws a string in the current graphics context.
This method and draws the reciver on a single "infinately long" line.
@param aPoint - The starting point to draw the string
*/
- (void)drawAtPoint:(CGPoint)aPoint
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
line = CTLineCreateWithAttributedString([self copy]);
CGContextSetTextPosition(context, aPoint.x, aPoint.y);
CTLineDraw(line, context);
}
/*!
Draws a string in the current graphics context.
@param aRect - The rect for which the string should be drawn into
*/
- (void)drawInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
frameSetter = CTFramesetterCreateWithAttributedString([self copy]),
path = CGPathCreateMutable();
CGPathAddRect(path, nil, aRect);
var frame = CTFramesetterCreateFrame(frameSetter, CPMakeRange(0, [self length]), path, nil);
CTFrameDraw(frame, context);
}
@end
+13 -12
View File
@@ -4,7 +4,7 @@
* Created by Ross Boucher.
* Copyright 2009, 280 North, Inc.
*
* Adapted from Kevin Wojniak, portions Copyright 2009 Kevin Wojniak.
* Adapted from Kevin Wojniak, portions Copyright 2009 Kevin Wojniak.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,26 +20,27 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright 2009 280 North, Inc.
*/
@import <AppKit/CPGraphicsContext.j>
@import <Foundation/CPObject.j>
@import "CPGraphicsContext.j"
// Class defaults
var DefaultLineWidth = 1.0;
/*!
/*!
@ingroup appkit
@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
line segments.
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
be used, which can be set by calling setFill: and setStroke: on any CPColor object (or set: for both).
*/
@@ -64,9 +65,9 @@ var DefaultLineWidth = 1.0;
+ (CPBezierPath)bezierPathWithOvalInRect:(CGRect)rect
{
var path = [self bezierPath];
[path appendBezierPathWithOvalInRect:rect];
return path;
}
@@ -76,9 +77,9 @@ var DefaultLineWidth = 1.0;
+ (CPBezierPath)bezierPathWithRect:(CGRect)rect
{
var path = [self bezierPath];
[path appendBezierPathWithRect:rect];
return path;
}
@@ -183,7 +184,6 @@ var DefaultLineWidth = 1.0;
CGContextBeginPath(ctx);
CGContextAddPath(ctx, _path);
CGContextSetLineWidth(ctx, [self lineWidth]);
CGContextClosePath(ctx);
CGContextStrokePath(ctx);
}
@@ -280,6 +280,7 @@ var DefaultLineWidth = 1.0;
{
CGPathAddPath(_path, nil, other._path);
}
/*!
Remove all path elements; clears path.
*/
+242 -52
View File
@@ -19,25 +19,39 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPView.j"
// CPBoxType
CPBoxPrimary = 0;
CPBoxSecondary = 1;
CPBoxSeparator = 2;
CPBoxOldStyle = 3;
CPBoxCustom = 4;
// CPBorderType
CPNoBorder = 0;
CPLineBorder = 1;
CPLineBorder = 1;
CPBezelBorder = 2;
CPGrooveBorder = 3;
/*!
@ingroup appkit
@class CPBox
A CPBox is a simple view which can display a border.
*/
@implementation CPBox : CPView
{
CPBoxType _boxType;
CPBorderType _borderType;
CPColor _borderColor;
CPColor _fillColor;
float _cornerRadius;
float _borderWidth;
CPSize _contentMargin;
CPView _contentView;
}
@@ -50,18 +64,19 @@ CPGrooveBorder = 3;
[box setFrameFromContentFrame:[aView frame]];
[enclosingView replaceSubview:aView with:box];
[box setContentView:aView];
return box;
}
- (id)initWithFrame:(CPRect)frameRect
{
self = [super initWithFrame:frameRect];
if (self)
{
_borderType = CPBezelBorder;
_fillColor = [CPColor clearColor];
_borderColor = [CPColor blackColor];
@@ -69,7 +84,9 @@ CPGrooveBorder = 3;
_contentMargin = CGSizeMake(0.0, 0.0);
_contentView = [[CPView alloc] initWithFrame:[self bounds]];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self setAutoresizesSubviews:YES];
[self addSubview:_contentView];
}
@@ -78,19 +95,96 @@ CPGrooveBorder = 3;
// Configuring Boxes
/*!
Returns the receiver's border rectangle.
@return the border rectangle of the box
*/
- (CPRect)borderRect
{
return [self bounds];
}
/*!
Returns the receiver's border type. Possible values are:
<pre>
CPNoBorder
CPLineBorder
CPBezelBorder
CPGrooveBorder
</pre>
@return the border type of the box
*/
- (CPBorderType)borderType
{
return _borderType;
}
- (void)setBorderType:(CPBorderType)value
/*!
Sets the receiver's border type. Valid values are:
<pre>
CPNoBorder
CPLineBorder
CPBezelBorder
CPGrooveBorder
</pre>
@param borderType the border type to use
*/
- (void)setBorderType:(CPBorderType)aBorderType
{
_borderType = value;
if (_borderType === aBorderType)
return;
_borderType = aBorderType;
[self setNeedsDisplay:YES];
}
/*!
Returns the receiver's box type. Possible values are:
<pre>
CPBoxPrimary
CPBoxSecondary
CPBoxSeparator
CPBoxOldStyle
CPBoxCustom
</pre>
(In the current implementation, all values act the same except CPBoxSeparator.)
@return the box type of the box.
*/
- (CPBoxType)boxType
{
return _boxType;
}
/*!
Sets the receiver's box type. Valid values are:
<pre>
CPBoxPrimary
CPBoxSecondary
CPBoxSeparator
CPBoxOldStyle
CPBoxCustom
</pre>
(In the current implementation, all values act the same except CPBoxSeparator.)
@param aBoxType the box type of the box.
*/
- (void)setBoxType:(CPBoxType)aBoxType
{
if (_boxType === aBoxType)
return;
_boxType = aBoxType;
[self setNeedsDisplay:YES];
}
@@ -161,9 +255,10 @@ CPGrooveBorder = 3;
return;
[aView setFrame:CGRectInset([self bounds], _contentMargin.width + _borderWidth, _contentMargin.height + _borderWidth)];
[aView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self replaceSubview:_contentView with:aView];
_contentView = aView;
_contentView = aView;
}
- (CPSize)contentViewMargins
@@ -173,9 +268,9 @@ CPGrooveBorder = 3;
- (void)setContentViewMargins:(CPSize)size
{
if(size.width < 0 || size.height < 0)
if (size.width < 0 || size.height < 0)
[CPException raise:CPGenericException reason:@"Margins must be positive"];
_contentMargin = CGSizeMakeCopy(size);
[self setNeedsDisplay:YES];
}
@@ -189,56 +284,151 @@ CPGrooveBorder = 3;
- (void)sizeToFit
{
var contentFrame = [_contentView frame];
[self setFrameSize:CGSizeMake(contentFrame.size.width + _contentMargin.width * 2,
[self setFrameSize:CGSizeMake(contentFrame.size.width + _contentMargin.width * 2,
contentFrame.size.height + _contentMargin.height * 2)];
[_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height)];
}
- (void)drawRect:(CPRect)rect
{
var bounds = [self bounds],
aContext = [[CPGraphicsContext currentContext] graphicsPort],
border2 = _borderWidth/2,
if (_borderType === CPNoBorder)
return;
strokeRect = CGRectMake(bounds.origin.x + border2,
bounds.origin.y + border2,
bounds.size.width - _borderWidth,
bounds.size.height - _borderWidth),
fillRect = CGRectMake(bounds.origin.x + border2,
bounds.origin.y + border2,
bounds.size.width - _borderWidth,
bounds.size.height - _borderWidth);
var bounds = [self bounds];
CGContextSetFillColor(aContext, [self fillColor]);
CGContextSetStrokeColor(aContext, [self borderColor]);
CGContextSetLineWidth(aContext, _borderWidth);
switch(_borderType)
switch (_boxType)
{
case CPLineBorder: CGContextFillRoundedRectangleInRect(aContext, fillRect, _cornerRadius, YES, YES, YES, YES);
CGContextStrokeRoundedRectangleInRect(aContext, strokeRect, _cornerRadius, YES, YES, YES, YES);
break;
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)
return [self _drawHorizontalSeperatorInRect:bounds];
case CPBezelBorder: CGContextFillRoundedRectangleInRect(aContext, fillRect, _cornerRadius, YES, YES, YES, YES);
CGContextSetStrokeColor(aContext, [CPColor colorWithWhite:190.0/255.0 alpha:1.0]);
CGContextBeginPath(aContext);
CGContextMoveToPoint(aContext, strokeRect.origin.x, strokeRect.origin.y);
CGContextAddLineToPoint(aContext, CGRectGetMinX(strokeRect), CGRectGetMaxY(strokeRect)),
CGContextAddLineToPoint(aContext, CGRectGetMaxX(strokeRect), CGRectGetMaxY(strokeRect)),
CGContextAddLineToPoint(aContext, CGRectGetMaxX(strokeRect), CGRectGetMinY(strokeRect)),
CGContextStrokePath(aContext);
CGContextSetStrokeColor(aContext, [CPColor colorWithWhite:142.0/255.0 alpha:1.0]);
CGContextBeginPath(aContext);
CGContextMoveToPoint(aContext, bounds.origin.x, strokeRect.origin.y);
CGContextAddLineToPoint(aContext, CGRectGetMaxX(bounds), CGRectGetMinY(strokeRect));
CGContextStrokePath(aContext);
break;
break;
}
default: break;
switch (_borderType)
{
case CPBezelBorder:
[self _drawBezelBorderInRect:bounds];
break;
default:
case CPLineBorder:
[self _drawLineBorderInRect:bounds];
break;
}
}
- (void)_drawHorizontalSeperatorInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMinY(aRect) + 0.5);
CGContextAddLineToPoint(context, CGRectGetWidth(aRect), CGRectGetMinY(aRect) + 0.5);
CGContextStrokePath(context);
}
- (void)_drawVerticalSeperatorInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, CGRectGetMinX(aRect) + 0.5, CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, CGRectGetMinX(aRect) + 0.5, CGRectGetHeight(aRect));
CGContextStrokePath(context);
}
- (void)_drawBezelBorderInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
sides = [CPMinYEdge, CPMaxXEdge, CPMaxYEdge, CPMinXEdge],
sideGray = 190.0 / 255.0,
grays = [142.0 / 255.0, sideGray, sideGray, sideGray],
borderWidth = _borderWidth;
while (borderWidth--)
aRect = CPDrawTiledRects(aRect, aRect, sides, grays);
CGContextSetFillColor(context, [self fillColor]);
CGContextFillRect(context, aRect);
}
- (void)_drawLineBorderInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
aRect = CGRectInset(aRect, _borderWidth / 2.0, _borderWidth / 2.0);
CGContextSetFillColor(context, [self fillColor]);
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, _borderWidth);
CGContextFillRoundedRectangleInRect(context, aRect, _cornerRadius, YES, YES, YES, YES);
CGContextStrokeRoundedRectangleInRect(context, aRect, _cornerRadius, YES, YES, YES, YES);
}
@end
var CPBoxTypeKey = @"CPBoxTypeKey",
CPBoxBorderTypeKey = @"CPBoxBorderTypeKey",
CPBoxBorderColorKey = @"CPBoxBorderColorKey",
CPBoxFillColorKey = @"CPBoxFillColorKey",
CPBoxCornerRadiusKey = @"CPBoxCornerRadiusKey",
CPBoxBorderWidthKey = @"CPBoxBorderWidthKey",
CPBoxContentMarginKey = @"CPBoxContentMarginKey";
@implementation CPBox (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_boxType = [aCoder decodeIntForKey:CPBoxTypeKey];
_borderType = [aCoder decodeIntForKey:CPBoxBorderTypeKey];
_borderColor = [aCoder decodeObjectForKey:CPBoxBorderColorKey];
_fillColor = [aCoder decodeObjectForKey:CPBoxFillColorKey];
_cornerRadius = [aCoder decodeFloatForKey:CPBoxCornerRadiusKey];
_borderWidth = [aCoder decodeFloatForKey:CPBoxBorderWidthKey];
_contentMargin = [aCoder decodeSizeForKey:CPBoxContentMarginKey];
_contentView = [self subviews][0];
[self setAutoresizesSubviews:YES];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeInt:_boxType forKey:CPBoxTypeKey];
[aCoder encodeInt:_borderType forKey:CPBoxBorderTypeKey];
[aCoder encodeObject:_borderColor forKey:CPBoxBorderColorKey];
[aCoder encodeObject:_fillColor forKey:CPBoxFillColorKey];
[aCoder encodeFloat:_cornerRadius forKey:CPBoxCornerRadiusKey];
[aCoder encodeFloat:_borderWidth forKey:CPBoxBorderWidthKey];
[aCoder encodeSize:_contentMargin forKey:CPBoxContentMarginKey];
}
@end
+1009
View File
File diff suppressed because it is too large Load Diff
+324 -110
View File
@@ -24,31 +24,8 @@
@import "CGGeometry.j"
@import "CPControl.j"
@import "CPStringDrawing.j"
#include "CoreGraphics/CGGeometry.h"
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
/* @group CPCellImagePosition */
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
CPImageRight = 3;
CPImageBelow = 4;
CPImageAbove = 5;
CPImageOverlaps = 6;
/* @group CPButtonState */
CPOnState = 1;
CPOffState = 0;
CPMixedState = -1;
/* @group CPBezelStyle */
@@ -93,9 +70,18 @@ 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;
/*!
@ingroup appkit
@class CPButton
@@ -106,12 +92,9 @@ CPButtonStateMixed = CPThemeState("mixed");
@implementation CPButton : CPControl
{
BOOL _allowsMixedState;
CPString _title;
CPString _alternateTitle;
CPImage _image;
CPImage _alternateImage;
CPInteger _showsStateBy;
CPInteger _highlightsBy;
@@ -120,6 +103,14 @@ CPButtonStateMixed = CPThemeState("mixed");
// NS-style Display Properties
CPBezelStyle _bezelStyle;
CPControlSize _controlSize;
CPString _keyEquivalent;
unsigned _keyEquivalentModifierMask;
CPTimer _continuousDelayTimer;
CPTimer _continuousTimer;
float _periodicDelay;
float _periodicInterval;
}
+ (id)buttonWithTitle:(CPString)aTitle
@@ -138,21 +129,26 @@ CPButtonStateMixed = CPThemeState("mixed");
return button;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return @"button";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMakeZero(), nil]
forKeys:[@"bezel-inset", @"content-inset", @"bezel-color"]];
return [CPDictionary dictionaryWithObjects:[[CPNull null], 0.0, _CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null]]
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];
if (self)
{
// Should we instead override the defaults?
@@ -160,19 +156,32 @@ CPButtonStateMixed = CPThemeState("mixed");
[self setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
[self setValue:CPScaleNone forThemeAttribute:@"image-scaling"];
_controlSize = CPRegularControlSize;
// [self setBezelStyle:CPRoundRectBezelStyle];
[self setBezelStyle:CPRoundRectBezelStyle];
[self setBordered:YES];
[self _init];
}
return self;
}
- (void)_init
{
_controlSize = CPRegularControlSize;
_keyEquivalent = @"";
_keyEquivalentModifierMask = 0;
// Continuous button defaults.
_periodicInterval = 0.05;
_periodicDelay = 0.5;
}
// 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
{
@@ -192,10 +201,14 @@ CPButtonStateMixed = CPThemeState("mixed");
_allowsMixedState = aFlag;
if (!_allowsMixedState)
[self unsetThemeState:CPButtonStateMixed];
if (!_allowsMixedState && [self state] === CPMixedState)
[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))
@@ -204,7 +217,7 @@ CPButtonStateMixed = CPThemeState("mixed");
else if (![anObjectValue isKindOfClass:[CPNumber class]])
anObjectValue = CPOnState;
else if (anObjectValue > CPOnState)
else if (anObjectValue >= CPOnState)
anObjectValue = CPOnState
else if (anObjectValue < CPOffState)
@@ -230,6 +243,13 @@ CPButtonStateMixed = CPThemeState("mixed");
}
}
/*!
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])
@@ -242,8 +262,16 @@ CPButtonStateMixed = CPThemeState("mixed");
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]];
}
@@ -265,17 +293,27 @@ CPButtonStateMixed = CPThemeState("mixed");
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)
return;
_title = aTitle;
[self setNeedsLayout];
[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;
@@ -285,7 +323,7 @@ CPButtonStateMixed = CPThemeState("mixed");
{
if (_alternateTitle === aTitle)
return;
_alternateTitle = aTitle;
[self setNeedsLayout];
@@ -299,18 +337,12 @@ CPButtonStateMixed = CPThemeState("mixed");
- (void)setImage:(CPImage)anImage
{
if (_image === anImage)
return;
_image = anImage;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
[self setValue:anImage forThemeAttribute:@"image"];
}
- (CPImage)image
{
return _image;
return [self valueForThemeAttribute:@"image" inState:CPThemeStateNormal];
}
/*!
@@ -319,13 +351,7 @@ CPButtonStateMixed = CPThemeState("mixed");
*/
- (void)setAlternateImage:(CPImage)anImage
{
if (_alternateImage === anImage)
return;
_alternateImage = anImage;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
[self setValue:anImage forThemeAttribute:@"image" inState:CPThemeStateHighlighted];
}
/*!
@@ -333,7 +359,17 @@ CPButtonStateMixed = CPThemeState("mixed");
*/
- (CPImage)alternateImage
{
return _alternateImage;
return [self valueForThemeAttribute:@"image" inState:CPThemeStateHighlighted];
}
- (void)setImageOffset:(float)theImageOffset
{
[self setValue:theImageOffset forThemeAttribute:@"image-offset"];
}
- (float)imageOffset
{
return [self valueForThemeAttribute:@"image-offset"];
}
- (void)setShowsStateBy:(CPInteger)aMask
@@ -394,13 +430,13 @@ CPButtonStateMixed = CPThemeState("mixed");
[self setShowsStateBy:CPContentsCellMask];
break;
case CPSwitchButton: [CPException raise:CPInvalidArgumentException
case CPSwitchButton: [CPException raise:CPInvalidArgumentException
reason:"The CPSwitchButton type is not supported in Cappuccino, use the CPCheckBox class instead."];
case CPRadioButton: [CPException raise:CPInvalidArgumentException
case CPRadioButton: [CPException raise:CPInvalidArgumentException
reason:"The CPRadioButton type is not supported in Cappuccino, use the CPRadio class instead."];
default: [CPException raise:CPInvalidArgumentException
default: [CPException raise:CPInvalidArgumentException
reason:"Unknown button type."];
}
@@ -416,7 +452,7 @@ CPButtonStateMixed = CPThemeState("mixed");
_imageDimsWhenDisabled = imageShouldDimWhenDisabled;
if (_imageDimsWhenDisabled)
if ([self hasThemeState:CPThemeStateDisabled])
{
[self setNeedsDisplay:YES];
[self setNeedsLayout];
@@ -428,16 +464,45 @@ CPButtonStateMixed = CPThemeState("mixed");
return _imageDimsWhenDisabled;
}
- (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];
}
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
[self highlight:YES];
return [super startTrackingAt:aPoint];
}
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
{
[self highlight:NO];
[self invalidateTimers];
[super stopTracking:lastPoint at:aPoint mouseIsUp:mouseIsUp];
@@ -445,6 +510,21 @@ CPButtonStateMixed = CPThemeState("mixed");
[self setNextState];
}
- (void)invalidateTimers
{
if (_continuousTimer)
{
[_continuousTimer invalidate];
_continuousTimer = nil;
}
if (_continuousDelayTimer)
{
[_continuousDelayTimer invalidate];
_continuousDelayTimer = nil;
}
}
- (CGRect)contentRectForBounds:(CGRect)bounds
{
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
@@ -452,15 +532,16 @@ CPButtonStateMixed = CPThemeState("mixed");
if (_CGInsetIsEmpty(contentInset))
return bounds;
bounds = _CGRectMakeCopy(bounds);
bounds.origin.x += contentInset.left;
bounds.origin.y += contentInset.top;
bounds.size.width -= contentInset.left + contentInset.right;
bounds.size.height -= contentInset.top + contentInset.bottom;
return bounds;
}
- (CGRect)bezelRectForBounds:(CFRect)bounds
- (CGRect)bezelRectForBounds:(CGRect)bounds
{
if (![self isBordered])
return _CGRectMakeZero();
@@ -470,6 +551,7 @@ CPButtonStateMixed = CPThemeState("mixed");
if (_CGInsetIsEmpty(bezelInset))
return bounds;
bounds = _CGRectMakeCopy(bounds);
bounds.origin.x += bezelInset.left;
bounds.origin.y += bezelInset.top;
bounds.size.width -= bezelInset.left + bezelInset.right;
@@ -478,13 +560,20 @@ CPButtonStateMixed = CPThemeState("mixed");
return bounds;
}
/*!
Adjust the size of the button to fit the title and surrounding button image.
*/
- (void)sizeToFit
- (CGSize)_minimumFrameSize
{
var size = [([self title] || " ") sizeWithFont:[self currentValueForThemeAttribute:@"font"]],
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
var size = CGSizeMakeZero(),
contentView = [self ephemeralSubviewNamed:@"content-view"];
if (contentView)
{
[contentView sizeToFit];
size = [contentView frameSize];
}
else
size = [([self title] || " ") sizeWithFont:[self currentValueForThemeAttribute:@"font"]];
var contentInset = [self currentValueForThemeAttribute:@"content-inset"],
minSize = [self currentValueForThemeAttribute:@"min-size"],
maxSize = [self currentValueForThemeAttribute:@"max-size"];
@@ -497,17 +586,30 @@ CPButtonStateMixed = CPThemeState("mixed");
if (maxSize.height >= 0.0)
size.height = MIN(size.height, maxSize.height);
[self setFrameSize:size];
return size;
}
/*!
Adjust the size of the button to fit the title and surrounding button image.
*/
- (void)sizeToFit
{
[self layoutSubviews];
[self setFrameSize:[self _minimumFrameSize]];
if ([self ephemeralSubviewNamed:@"content-view"])
[self layoutSubviews];
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
{
if (aName === "bezel-view")
return [self bezelRectForBounds:[self bounds]];
else if (aName === "content-view")
return [self contentRectForBounds:[self bounds]];
return [super rectForEphemeralSubviewNamed:aName];
}
@@ -518,13 +620,11 @@ CPButtonStateMixed = CPThemeState("mixed");
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
else
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
return [super createEphemeralSubviewNamed:aName];
}
- (void)layoutSubviews
@@ -532,9 +632,8 @@ CPButtonStateMixed = CPThemeState("mixed");
var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:@"content-view"];
if (bezelView)
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
positioned:CPWindowAbove
@@ -543,7 +642,8 @@ CPButtonStateMixed = CPThemeState("mixed");
if (contentView)
{
[contentView setText:([self hasThemeState:CPThemeStateHighlighted] && _alternateTitle) ? _alternateTitle : _title];
[contentView setImage:([self hasThemeState:CPThemeStateHighlighted] && _alternateImage) ? _alternateImage : _image];
[contentView setImage:[self currentValueForThemeAttribute:@"image"]];
[contentView setImageOffset:[self currentValueForThemeAttribute:@"image-offset"]];
[contentView setFont:[self currentValueForThemeAttribute:@"font"]];
[contentView setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
@@ -554,17 +654,10 @@ CPButtonStateMixed = CPThemeState("mixed");
[contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
[contentView setImagePosition:[self currentValueForThemeAttribute:@"image-position"]];
[contentView setImageScaling:[self currentValueForThemeAttribute:@"image-scaling"]];
[contentView setDimsImage:[self hasThemeState:CPThemeStateDisabled] && _imageDimsWhenDisabled];
}
}
- (void)setDefaultButton:(BOOL)shouldBeDefaultButton
{
if (shouldBeDefaultButton)
[self setThemeState:CPThemeStateDefault];
else
[self unsetThemeState:CPThemeStateDefault];
}
- (void)setBordered:(BOOL)shouldBeBordered
{
if (shouldBeBordered)
@@ -578,26 +671,120 @@ CPButtonStateMixed = CPThemeState("mixed");
return [self hasThemeState:CPThemeStateBordered];
}
/*!
Sets the keyboard shortcut for this button. For special keys see
CPEvent.j CP...FunctionKey and CPText.j CP...Character.
@param aString the keyboard shortcut as a string
*/
- (void)setKeyEquivalent:(CPString)aString
{
_keyEquivalent = aString || @"";
// Check if the key equivalent is the enter key
// Treat \r and \n as the same key equivalent. See issue #710.
if (aString === CPNewlineCharacter || aString === CPCarriageReturnCharacter)
[self setThemeState:CPThemeStateDefault];
else
[self unsetThemeState:CPThemeStateDefault];
}
- (void)viewWillMoveToWindow:(CPWindow)aWindow
{
var selfWindow = [self window];
if (selfWindow === aWindow || aWindow === nil)
return;
if ([selfWindow defaultButton] === self)
[selfWindow setDefaultButton:nil];
if ([self keyEquivalent] === CPNewlineCharacter || [self keyEquivalent] === CPCarriageReturnCharacter)
[aWindow setDefaultButton:self];
}
/*!
Returns the keyboard shortcut for this button.
*/
- (CPString)keyEquivalent
{
return _keyEquivalent;
}
/*!
Returns the mask used with this button's key equivalent.
*/
- (void)setKeyEquivalentModifierMask:(unsigned)aMask
{
_keyEquivalentModifierMask = aMask;
}
/*!
Sets the mask to be used with this button's key equivalent.
*/
- (unsigned)keyEquivalentModifierMask
{
return _keyEquivalentModifierMask;
}
/*!
Checks the button's key equivalent against that in the event, and if they
match simulates a button click.
*/
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
{
// Don't handle the key equivalent for the default window because the window will handle it for us
if ([[self window] defaultButton] === self)
return NO;
if (![anEvent _triggersKeyEquivalent:[self keyEquivalent] withModifierMask:[self keyEquivalentModifierMask]])
return NO;
[self performClick:nil];
return YES;
}
@end
@implementation CPButton (NS)
- (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
var CPButtonImageKey = @"CPButtonImageKey",
CPButtonAlternateImageKey = @"CPButtonAlternateImageKey",
CPButtonTitleKey = @"CPButtonTitleKey",
CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey",
CPButtonIsBorderedKey = @"CPButtonIsBorderedKey";
var CPButtonImageKey = @"CPButtonImageKey",
CPButtonAlternateImageKey = @"CPButtonAlternateImageKey",
CPButtonTitleKey = @"CPButtonTitleKey",
CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey",
CPButtonIsBorderedKey = @"CPButtonIsBorderedKey",
CPButtonAllowsMixedStateKey = @"CPButtonAllowsMixedStateKey",
CPButtonImageDimsWhenDisabledKey = @"CPButtonImageDimsWhenDisabledKey",
CPButtonImagePositionKey = @"CPButtonImagePositionKey",
CPButtonKeyEquivalentKey = @"CPButtonKeyEquivalentKey",
CPButtonKeyEquivalentMaskKey = @"CPButtonKeyEquivalentMaskKey",
CPButtonPeriodicDelayKey = @"CPButtonPeriodicDelayKey",
CPButtonPeriodicIntervalKey = @"CPButtonPeriodicIntervalKey";
@implementation CPButton (CPCoding)
@@ -608,21 +795,37 @@ var CPButtonImageKey = @"CPButtonImageKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_controlSize = CPRegularControlSize;
[self _init];
_title = [aCoder decodeObjectForKey:CPButtonTitleKey];
_alternateTitle = [aCoder decodeObjectForKey:CPButtonAlternateTitleKey];
if ([aCoder containsValueForKey:CPButtonAllowsMixedStateKey])
_allowsMixedState = [aCoder decodeBoolForKey:CPButtonAllowsMixedStateKey];
[self setImageDimsWhenDisabled:[aCoder decodeObjectForKey:CPButtonImageDimsWhenDisabledKey]];
if ([aCoder containsValueForKey:CPButtonImagePositionKey])
[self setImagePosition:[aCoder decodeIntForKey:CPButtonImagePositionKey]];
if ([aCoder containsValueForKey:CPButtonKeyEquivalentKey])
[self setKeyEquivalent:CFData.decodeBase64ToUtf16String([aCoder decodeObjectForKey:CPButtonKeyEquivalentKey])];
if ([aCoder containsValueForKey:CPButtonPeriodicDelayKey])
_periodicDelay = [aCoder decodeObjectForKey:CPButtonPeriodicDelayKey];
if ([aCoder containsValueForKey:CPButtonPeriodicIntervalKey])
_periodicInterval = [aCoder decodeObjectForKey:CPButtonPeriodicIntervalKey];
_keyEquivalentModifierMask = [aCoder decodeIntForKey:CPButtonKeyEquivalentMaskKey];
[self setImage:[aCoder decodeObjectForKey:CPButtonImageKey]];
[self setAlternateImage:[aCoder decodeObjectForKey:CPButtonAlternateImageKey]];
[self setTitle:[aCoder decodeObjectForKey:CPButtonTitleKey]];
[self setAlternateTitle:[aCoder decodeObjectForKey:CPButtonAlternateTitleKey]];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
return self;
}
@@ -633,12 +836,23 @@ var CPButtonImageKey = @"CPButtonImageKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_image forKey:CPButtonImageKey];
[aCoder encodeObject:_alternateImage forKey:CPButtonAlternateImageKey];
[self invalidateTimers];
[aCoder encodeObject:_title forKey:CPButtonTitleKey];
[aCoder encodeObject:_alternateTitle forKey:CPButtonAlternateTitleKey];
[aCoder encodeBool:_allowsMixedState forKey:CPButtonAllowsMixedStateKey];
[aCoder encodeBool:[self imageDimsWhenDisabled] forKey:CPButtonImageDimsWhenDisabledKey];
[aCoder encodeInt:[self imagePosition] forKey:CPButtonImagePositionKey];
if (_keyEquivalent)
[aCoder encodeObject:CFData.encodeBase64Utf16String(_keyEquivalent) forKey:CPButtonKeyEquivalentKey];
[aCoder encodeInt:_keyEquivalentModifierMask forKey:CPButtonKeyEquivalentMaskKey];
[aCoder encodeObject:_periodicDelay forKey:CPButtonPeriodicDelayKey];
[aCoder encodeObject:_periodicInterval forKey:CPButtonPeriodicIntervalKey];
}
@end
+244 -28
View File
@@ -1,61 +1,277 @@
@import <AppKit/CPView.j>
#include "CoreGraphics/CGGeometry.h"
@import "CPView.j"
@implementation CPButtonBar : CPControl
@implementation CPButtonBar : CPView
{
BOOL _hasResizeControl;
BOOL _resizeControlIsLeftAligned;
CPArray _buttons;
}
+ (CPString)themeClass
+ (id)plusButton
{
var button = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"plus_button.png"] size:CGSizeMake(11, 12)];
[button setBordered:NO];
[button setImage:image];
[button setImagePosition:CPImageOnly];
return button;
}
+ (id)minusButton
{
var button = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"minus_button.png"] size:CGSizeMake(11, 4)];
[button setBordered:NO];
[button setImage:image];
[button setImagePosition:CPImageOnly];
return button;
}
+ (id)actionPopupButton
{
var button = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"action_button.png"] size:CGSizeMake(22, 14)];
[button addItemWithTitle:nil];
[[button lastItem] setImage:image];
[button setImagePosition:CPImageOnly];
[button setValue:CGInsetMake(0, 0, 0, 0) forThemeAttribute:"content-inset"];
[button setPullsDown:YES];
return button;
}
+ (CPString)defaultThemeClass
{
return @"button-bar";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[nil]
forKeys:[@"bezel-color"]];
return [CPDictionary dictionaryWithObjects:[CGInsetMake(0.0, 0.0, 0.0, 0.0), CGSizeMakeZero(), [CPNull null], [CPNull null], [CPNull null], [CPNull null]]
forKeys:[@"resize-control-inset", @"resize-control-size", @"resize-control-color", @"bezel-color", @"button-bezel-color", @"button-text-color"]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_buttons = [];
[self setNeedsLayout];
}
return self;
}
- (void)awakeFromCib
{
var view = [self superview],
subview = self;
while (view)
{
if ([view isKindOfClass:[CPSplitView class]])
{
var viewIndex = [[view subviews] indexOfObject:subview];
[view setButtonBar:self forDividerAtIndex:viewIndex];
break;
}
subview = view;
view = [view superview];
}
}
- (void)setButtons:(CPArray)buttons
{
_buttons = [CPArray arrayWithArray:buttons];
for (var i = 0, count = [_buttons count]; i < count; i++)
[_buttons[i] setBordered:YES];
[self setNeedsLayout];
}
- (CPArray)buttons
{
return [CPArray arrayWithArray:_buttons];
}
- (void)setHasResizeControl:(BOOL)shouldHaveResizeControl
{
if (_hasResizeControl === shouldHaveResizeControl)
return;
_hasResizeControl = !!shouldHaveResizeControl;
[self setNeedsLayout];
}
- (BOOL)hasResizeControl
{
return _hasResizeControl;
}
- (void)setResizeControlIsLeftAligned:(BOOL)shouldBeLeftAligned
{
if (_resizeControlIsLeftAligned === shouldBeLeftAligned)
return;
_resizeControlIsLeftAligned = !!shouldBeLeftAligned;
[self setNeedsLayout];
}
- (BOOL)resizeControlIsLeftAligned
{
return _resizeControlIsLeftAligned;
}
- (CGRect)resizeControlFrame
{
var inset = [self currentValueForThemeAttribute:@"resize-control-inset"],
size = [self currentValueForThemeAttribute:@"resize-control-size"],
currentSize = [self bounds],
leftOrigin = _resizeControlIsLeftAligned ? 0 : currentSize.size.width - size.width - inset.right - inset.left;
return CGRectMake(leftOrigin, 0, size.width + inset.left + inset.right, size.height + inset.top + inset.bottom);
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
{
if (aName === "bezel-view")
return [self bounds];
if (aName === "resize-control-view")
{
var inset = [self currentValueForThemeAttribute:@"resize-control-inset"],
size = [self currentValueForThemeAttribute:@"resize-control-size"],
currentSize = [self bounds];
if (_resizeControlIsLeftAligned)
return CGRectMake(inset.left, inset.top, size.width, size.height);
else
return CGRectMake(currentSize.size.width - size.width - inset.right, inset.top, size.width, size.height);
}
return [super rectForEphemeralSubviewNamed:aName];
}
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
if (aName === "bezel-view")
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
if (aName === "resize-control-view")
return [[CPView alloc] initWithFrame:CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
return [super createEphemeralSubviewNamed:aName];
}
- (void)layoutSubviews
{
var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:@""];
if (bezelView)
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
[self setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
var normalColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateNormal],
highlightedColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateHighlighted],
disabledColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateDisabled],
textColor = [self valueForThemeAttribute:@"button-text-color" inState:CPThemeStateNormal];
var buttonsNotHidden = [CPArray arrayWithArray:_buttons],
count = [buttonsNotHidden count];
while (count--)
if ([buttonsNotHidden[count] isHidden])
[buttonsNotHidden removeObject:buttonsNotHidden[count]];
var currentButtonOffset = _resizeControlIsLeftAligned ? CGRectGetMaxX([self bounds]) + 1 : -1,
bounds = [self bounds],
height = CGRectGetHeight(bounds) - 1,
frameWidth = CGRectGetWidth(bounds),
resizeRect = _hasResizeControl ? [self rectForEphemeralSubviewNamed:"resize-control-view"] : CGRectMakeZero(),
resizeWidth = CGRectGetWidth(resizeRect),
availableWidth = frameWidth - resizeWidth - 1;
for (var i = 0, count = [buttonsNotHidden count]; i < count; i++)
{
var button = buttonsNotHidden[i],
width = CGRectGetWidth([button frame]);
if (availableWidth > width)
availableWidth -= width;
else
break;
if (_resizeControlIsLeftAligned)
{
[button setFrame:CGRectMake(currentButtonOffset - width, 1, width, height)];
currentButtonOffset -= width - 1;
}
else
{
[button setFrame:CGRectMake(currentButtonOffset, 1, width, height)];
currentButtonOffset += width - 1;
}
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal | CPThemeStateBordered];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted | CPThemeStateBordered];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled | CPThemeStateBordered];
[button setValue:textColor forThemeAttribute:@"text-color" inState:CPThemeStateBordered];
// FIXME shouldn't need this
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[self addSubview:button];
}
if (_hasResizeControl)
{
var resizeControlView = [self layoutEphemeralSubviewNamed:@"resize-control-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:nil];
[resizeControlView setAutoresizingMask: _resizeControlIsLeftAligned ? CPViewMaxXMargin : CPViewMinXMargin];
[resizeControlView setBackgroundColor:[self currentValueForThemeAttribute:@"resize-control-color"]];
}
}
- (void)addSubview:(CPView)aSubview
- (void)setFrameSize:(CGSize)aSize
{
[super addSubview:aSubview];
[aSubview setAutoresizingMask:CPViewMinXMargin];
[super setFrameSize:aSize];
[self setNeedsLayout];
}
@end
var CPButtonBarHasResizeControlKey = @"CPButtonBarHasResizeControlKey",
CPButtonBarResizeControlIsLeftAlignedKey = @"CPButtonBarResizeControlIsLeftAlignedKey",
CPButtonBarButtonsKey = @"CPButtonBarButtonsKey";
@implementation CPButtonBar (CPCoding)
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeBool:_hasResizeControl forKey:CPButtonBarHasResizeControlKey];
[aCoder encodeBool:_resizeControlIsLeftAligned forKey:CPButtonBarResizeControlIsLeftAlignedKey];
[aCoder encodeObject:_buttons forKey:CPButtonBarButtonsKey];
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_buttons = [aCoder decodeObjectForKey:CPButtonBarButtonsKey] || [];
_hasResizeControl = [aCoder decodeBoolForKey:CPButtonBarHasResizeControlKey];
_resizeControlIsLeftAligned = [aCoder decodeBoolForKey:CPButtonBarResizeControlIsLeftAlignedKey];
}
return self;
}
@end
+85 -2
View File
@@ -23,6 +23,8 @@
@import "CPButton.j"
CPCheckBoxImageOffset = 4.0;
@implementation CPCheckBox : CPButton
{
}
@@ -37,11 +39,19 @@
return [self buttonWithTitle:aTitle];
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
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];
@@ -55,10 +65,83 @@
[self setImagePosition:CPImageLeft];
[self setAlignment:CPLeftTextAlignment];
[self setBordered:YES];
[self setBordered:NO];
}
return self;
}
- (void)takeStateFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
{
var count = objects.length,
value = [objects[0] valueForKeyPath:aKeyPath] ? CPOnState : CPOffState;
[self setAllowsMixedState:NO];
[self setState:value];
while (count-- > 1)
{
if (value !== ([objects[count] valueForKeyPath:aKeyPath] ? CPOnState : CPOffState))
{
[self setAllowsMixedState:YES];
[self setState:CPMixedState];
}
}
}
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
{
[self takeStateFromKeyPath:aKeyPath ofObjects:objects];
}
@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
+64 -36
View File
@@ -22,14 +22,12 @@
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
/*!
/*!
@ingroup appkit
@class CPClipView
CPClipView allows you to define a clip rect and display only that portion of its containing view.
CPClipView allows you to define a clip rect and display only that portion of its containing view.
It is used to hold the document view in a CPScrollView.
*/
@implementation CPClipView : CPView
@@ -47,7 +45,7 @@
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_documentView)
{
[defaultCenter
@@ -59,29 +57,29 @@
removeObserver:self
name:CPViewBoundsDidChangeNotification
object:_documentView];
[_documentView removeFromSuperview];
}
_documentView = aView;
if (_documentView)
{
[self addSubview:_documentView];
[_documentView setPostsFrameChangedNotifications:YES];
[_documentView setPostsBoundsChangedNotifications:YES];
[defaultCenter
[_documentView setPostsFrameChangedNotifications:YES];
[_documentView setPostsBoundsChangedNotifications:YES];
[defaultCenter
addObserver:self
selector:@selector(viewFrameChanged:)
name:CPViewFrameDidChangeNotification
name:CPViewFrameDidChangeNotification
object:_documentView];
[defaultCenter
[defaultCenter
addObserver:self
selector:@selector(viewBoundsChanged:)
name:CPViewBoundsDidChangeNotification
name:CPViewBoundsDidChangeNotification
object:_documentView];
}
}
@@ -106,7 +104,7 @@
return _CGPointMakeZero();
var documentFrame = [_documentView frame];
aPoint.x = MAX(0.0, MIN(aPoint.x, MAX(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(_bounds), 0.0)));
aPoint.y = MAX(0.0, MIN(aPoint.y, MAX(_CGRectGetHeight(documentFrame) - _CGRectGetHeight(_bounds), 0.0)));
@@ -117,12 +115,16 @@
{
if (_CGPointEqualToPoint(_bounds.origin, aPoint))
return;
[super setBoundsOrigin:aPoint];
var superview = [self superview];
if([superview isKindOfClass:[CPScrollView class]])
var superview = [self superview],
// This is hack to avoid having to import CPScrollView.
// FIXME: Should CPScrollView be finding out about this on its own somehow?
scrollViewClass = objj_getClass("CPScrollView");
if ([superview isKindOfClass:scrollViewClass])
[superview reflectScrolledClipView:self];
}
@@ -162,37 +164,63 @@
- (void)_constrainScrollPoint
{
var oldScrollPoint = [self bounds].origin;
// Call scrollToPoint: because the current scroll point may no longer make
// Call scrollToPoint: because the current scroll point may no longer make
// sense given the new frame of the document view.
[self scrollToPoint:oldScrollPoint];
// scrollToPoint: takes care of reflectScrollClipView: for us, so bail if
// scrollToPoint: takes care of reflectScrollClipView: for us, so bail if
// the scroll points are not equal (meaning scrollToPoint: didn't early bail).
if (!CGPointEqualToPoint(oldScrollPoint, [self bounds].origin))
return;
// ... and we're in a scroll view of course.
var superview = [self superview];
if ([superview isKindOfClass:[CPScrollView class]])
var superview = [self superview],
// This is hack to avoid having to import CPScrollView.
// FIXME: Should CPScrollView be finding out about this on its own somehow?
scrollViewClass = objj_getClass("CPScrollView");
if ([superview isKindOfClass:scrollViewClass])
[superview reflectScrolledClipView:self];
}
- (BOOL)autoscroll:(CPEvent)anEvent
- (BOOL)autoscroll:(CPEvent)anEvent
{
var bounds = [self bounds],
eventLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil];
eventLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
superview = [self superview],
deltaX = 0,
deltaY = 0;
if (CPRectContainsPoint(bounds, eventLocation))
if (CGRectContainsPoint(bounds, eventLocation))
return NO;
var newRect = CGRectMakeZero();
if (![superview isKindOfClass:[CPScrollView class]] || [superview hasVerticalScroller])
{
if (eventLocation.y < CGRectGetMinY(bounds))
deltaY = CGRectGetMinY(bounds) - eventLocation.y;
else if (eventLocation.y > CGRectGetMaxY(bounds))
deltaY = CGRectGetMaxY(bounds) - eventLocation.y;
if (deltaY < -bounds.size.height)
deltaY = -bounds.size.height;
if (deltaY > bounds.size.height)
deltaY = bounds.size.height;
}
newRect.origin = eventLocation;
newRect.size = CPSizeMake(10, 10);
if (![superview isKindOfClass:[CPScrollView class]] || [superview hasHorizontalScroller])
{
if (eventLocation.x < CGRectGetMinX(bounds))
deltaX = CGRectGetMinX(bounds) - eventLocation.x;
else if (eventLocation.x > CGRectGetMaxX(bounds))
deltaX = CGRectGetMaxX(bounds) - eventLocation.x;
if (deltaX < -bounds.size.width)
deltaX = -bounds.size.width;
if (deltaX > bounds.size.width)
deltaX = bounds.size.width;
}
return [_documentView scrollRectToVisible:newRect];
return [self scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
}
@end
@@ -206,14 +234,14 @@ var CPClipViewDocumentViewKey = @"CPScrollViewDocumentView";
{
if (self = [super initWithCoder:aCoder])
[self setDocumentView:[aCoder decodeObjectForKey:CPClipViewDocumentViewKey]];
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_documentView forKey:CPClipViewDocumentViewKey];
}
+395 -92
View File
@@ -30,16 +30,16 @@
@import "CPCollectionViewItem.j"
/*!
/*!
@ingroup appkit
@class CPCollectionView
This class displays an array as a grid of objects, where each object is represented by a view.
The view is controlled by creating a CPCollectionViewItem and specifying its view, then
This class displays an array as a grid of objects, where each object is represented by a view.
The view is controlled by creating a CPCollectionViewItem and specifying its view, then
setting that item as the collection view prototype.
@par Delegate Methods
@delegate -(void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
Called when the selection in the collection view has changed.
@param collectionView the collection view who's selection changed
@@ -67,35 +67,35 @@
{
CPArray _content;
CPArray _items;
CPData _itemData;
CPCollectionViewItem _itemPrototype;
CPCollectionViewItem _itemForDragging;
CPMutableArray _cachedItems;
unsigned _maxNumberOfRows;
unsigned _maxNumberOfColumns;
CGSize _minItemSize;
CGSize _maxItemSize;
CPArray _backgroundColors;
float _tileWidth;
BOOL _isSelectable;
BOOL _allowsMultipleSelection;
BOOL _allowsEmptySelection;
CPIndexSet _selectionIndexes;
CGSize _itemSize;
float _horizontalMargin;
float _verticalMargin;
unsigned _numberOfRows;
unsigned _numberOfColumns;
id _delegate;
CPEvent _mouseDownEvent;
@@ -104,14 +104,14 @@
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_items = [];
_content = [];
_cachedItems = [];
_itemSize = CGSizeMakeZero();
_minItemSize = CGSizeMakeZero();
_maxItemSize = CGSizeMakeZero();
@@ -120,17 +120,60 @@
_verticalMargin = 5.0;
_tileWidth = -1.0;
_selectionIndexes = [CPIndexSet indexSet];
_allowsEmptySelection = YES;
_isSelectable = YES;
}
return self;
}
/*!
Sets the item prototype to \c anItem
The item prototype should implement the CPCoding protocol
because the item is copied by archiving and unarchiving the
prototypal view.
Example:
<pre>
@implement MyCustomView : CPCollectionViewItem
{
CPArray items @accessors;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
items = [];
}
return self;
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
items = [aCoder decodeObjectForKey:@"KEY"];
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:items forKey:@"KEY"];
[super encodeWithCoder:aCoder];
}
@end
</pre>
This will allow the collection view to create multiple 'clean' copies
of the item prototype which will maintain the original values for item
and all of the properties archived by the super class.
@param anItem the new item prototype
*/
- (void)setItemPrototype:(CPCollectionViewItem)anItem
@@ -196,18 +239,18 @@
// Setting the Content
/*!
Sets the content of the collection view to the content in \c anArray.
This array can be of any type, and each element will be passed to the \c -setRepresentedObject: method.
Sets the content of the collection view to the content in \c anArray.
This array can be of any type, and each element will be passed to the \c -setRepresentedObject: method.
It's the responsibility of your custom collection view item to interpret the object.
@param anArray the content array
*/
- (void)setContent:(CPArray)anArray
{
if (_content == anArray)
return;
// reset the _selectionIndexes
[self setSelectionIndexes:[CPIndexSet indexSet]];
_content = anArray;
[self reloadContent];
}
@@ -236,13 +279,13 @@
{
if (_isSelectable == isSelectable)
return;
_isSelectable = isSelectable;
if (!_isSelectable)
{
var index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
[_items[index] setSelected:NO];
}
@@ -297,23 +340,26 @@
*/
- (void)setSelectionIndexes:(CPIndexSet)anIndexSet
{
if (_selectionIndexes == anIndexSet || !_isSelectable)
if ([_selectionIndexes isEqual:anIndexSet] || !_isSelectable)
return;
var index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
[_items[index] setSelected:NO];
_selectionIndexes = anIndexSet;
var index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
[_items[index] setSelected:YES];
var binderClass = [[self class] _binderClassForBinding:@"selectionIndexes"];
[[binderClass getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
[_delegate collectionViewDidChangeSelection:self]
[_delegate collectionViewDidChangeSelection:self];
}
/*!
@@ -321,24 +367,26 @@
*/
- (CPIndexSet)selectionIndexes
{
return _selectionIndexes;
return [_selectionIndexes copy];
}
/* @ignore */
- (void)reloadContent
{
{
// Remove current views
var count = _items.length;
while (count--)
{
[[_items[count] view] removeFromSuperview];
[_items[count] setSelected:NO];
_cachedItems.push(_items[count]);
}
_items = [];
if (!_itemPrototype || !_content)
if (!_itemPrototype)
return;
var index = 0;
@@ -348,10 +396,14 @@
for (; index < count; ++index)
{
_items.push([self newItemForRepresentedObject:_content[index]]);
[self addSubview:[_items[index] view]];
}
index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
[_items[index] setSelected:YES];
[self tile];
}
@@ -359,49 +411,49 @@
- (void)tile
{
var width = CGRectGetWidth([self bounds]);
if (![_content count] || width == _tileWidth)
if (width == _tileWidth)
return;
// We try to fit as many views per row as possible. Any remaining space is then
// We try to fit as many views per row as possible. Any remaining space is then
// either proportioned out to the views (if their minSize != maxSize) or used as
// margin
var itemSize = CGSizeMakeCopy(_minItemSize);
_numberOfColumns = MAX(1.0, FLOOR(width / itemSize.width));
if (_maxNumberOfColumns > 0)
_numberOfColumns = MIN(_maxNumberOfColumns, _numberOfColumns);
var remaining = width - _numberOfColumns * itemSize.width,
itemsNeedSizeUpdate = NO;
if (remaining > 0 && itemSize.width < _maxItemSize.width)
itemSize.width = MIN(_maxItemSize.width, itemSize.width + FLOOR(remaining / _numberOfColumns));
// When we ONE column and a non-integral width, the FLOORing above can cause the item width to be smaller than the total width.
if (_maxNumberOfColumns == 1 && itemSize.width < _maxItemSize.width && itemSize.width < width)
itemSize.width = MIN(_maxItemSize.width, width);
if (!CGSizeEqualToSize(_itemSize, itemSize))
{
_itemSize = itemSize;
itemsNeedSizeUpdate = YES;
}
var index = 0,
count = _items.length;
if (_maxNumberOfColumns > 0 && _maxNumberOfRows > 0)
count = MIN(count, _maxNumberOfColumns * _maxNumberOfRows);
_numberOfRows = CEIL(count / _numberOfColumns);
_horizontalMargin = FLOOR((width - _numberOfColumns * itemSize.width) / (_numberOfColumns + 1));
var x = _horizontalMargin,
y = -itemSize.height;
for (; index < count; ++index)
{
if (index % _numberOfColumns == 0)
@@ -409,19 +461,28 @@
x = _horizontalMargin;
y += _verticalMargin + itemSize.height;
}
var view = [_items[index] view];
[view setFrameOrigin:CGPointMake(x, y)];
if (itemsNeedSizeUpdate)
[view setFrameSize:_itemSize];
x += itemSize.width + _horizontalMargin;
}
var superview = [self superview],
proposedHeight = y + itemSize.height + _verticalMargin;
if ([superview isKindOfClass:[CPClipView class]])
{
var superviewSize = [superview bounds].size;
proposedHeight = MAX(superviewSize.height, proposedHeight);
}
_tileWidth = width;
[self setFrameSize:CGSizeMake(width, y + itemSize.height + _verticalMargin)];
[self setFrameSize:CGSizeMake(width, proposedHeight)];
_tileWidth = -1.0;
}
@@ -439,9 +500,9 @@
{
if (_maxNumberOfRows == aMaxNumberOfRows)
return;
_maxNumberOfRows = aMaxNumberOfRows;
[self tile];
}
@@ -461,9 +522,9 @@
{
if (_maxNumberOfColumns == aMaxNumberOfColumns)
return;
_maxNumberOfColumns = aMaxNumberOfColumns;
[self tile];
}
@@ -500,9 +561,9 @@
{
if (CGSizeEqualToSize(_minItemSize, aSize))
return;
_minItemSize = CGSizeMakeCopy(aSize);
[self tile];
}
@@ -522,9 +583,9 @@
{
if (CGSizeEqualToSize(_maxItemSize, aSize))
return;
_maxItemSize = CGSizeMakeCopy(aSize);
[self tile];
}
@@ -571,19 +632,54 @@
_mouseDownEvent = anEvent;
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
row = FLOOR(location.y / (_itemSize.height + _verticalMargin)),
column = FLOOR(location.x / (_itemSize.width + _horizontalMargin)),
index = row * _numberOfColumns + column;
index = [self _indexAtPoint:location];
if (index >= 0 && index < _items.length)
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
{
if (_allowsMultipleSelection && ([anEvent modifierFlags] & CPCommandKeyMask || [anEvent modifierFlags] & CPShiftKeyMask))
{
if ([anEvent modifierFlags] & CPCommandKeyMask)
{
var indexes = [_selectionIndexes copy];
if ([indexes containsIndex:index])
[indexes removeIndex:index];
else
[indexes addIndex:index];
}
else if ([anEvent modifierFlags] & CPShiftKeyMask)
{
var firstSelectedIndex = [[self selectionIndexes] firstIndex],
newSelectedRange = nil;
if (index < firstSelectedIndex)
newSelectedRange = CPMakeRange(index, (firstSelectedIndex - index) + 1);
else
newSelectedRange = CPMakeRange(firstSelectedIndex, (index - firstSelectedIndex) + 1);
indexes = [[self selectionIndexes] copy];
[indexes addIndexesInRange:newSelectedRange];
}
}
else
indexes = [CPIndexSet indexSetWithIndex:index];
[self setSelectionIndexes:indexes];
}
else if (_allowsEmptySelection)
[self setSelectionIndexes:[CPIndexSet indexSet]];
}
- (void)mouseDragged:(CPEvent)anEvent
{
var locationInWindow = [anEvent locationInWindow],
mouseDownLocationInWindow = [_mouseDownEvent locationInWindow];
// FIXME: This is because Safari's drag hysteresis is 3px x 3px
if ((ABS(locationInWindow.x - mouseDownLocationInWindow.x) < 3) &&
(ABS(locationInWindow.y - mouseDownLocationInWindow.y) < 3))
return;
if (![_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)])
return;
@@ -591,13 +687,15 @@
if (![_selectionIndexes count])
return;
if ([_delegate respondsToSelector:@selector(collectionView:canDragItemsAtIndexes:withEvent:)] &&
![_delegate collectionView:self canDragItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent])
return;
// Set up the pasteboard
var dragTypes = [_delegate collectionView:self dragTypesForItemsAtIndexes:_selectionIndexes];
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self];
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if (!_itemForDragging)
_itemForDragging = [self newItemForRepresentedObject:_content[[_selectionIndexes firstIndex]]];
else
@@ -638,9 +736,9 @@
{
if (_verticalMargin == aVerticalMargin)
return;
_verticalMargin = aVerticalMargin;
[self tile];
}
@@ -670,17 +768,214 @@
return _delegate;
}
/*!
@ignore
*/
- (CPMenu)menuForEvent:(CPEvent)theEvent
{
if (![[self delegate] respondsToSelector:@selector(collectionView:menuForItemAtIndex:)])
return [super menuForEvent:theEvent];
var location = [self convertPoint:[theEvent locationInWindow] fromView:nil],
index = [self _indexAtPoint:location];
return [_delegate collectionView:self menuForItemAtIndex:index];
}
- (int)_indexAtPoint:(CGPoint)thePoint
{
var row = FLOOR(thePoint.y / (_itemSize.height + _verticalMargin)),
column = FLOOR(thePoint.x / (_itemSize.width + _horizontalMargin));
return row * _numberOfColumns + column;
}
- (CPCollectionViewItem)itemAtIndex:(unsigned)anIndex
{
return [_items objectAtIndex:anIndex];
}
- (CGRect)frameForItemAtIndex:(unsigned)anIndex
{
return [[[self itemAtIndex:anIndex] view] frame];
}
- (CGRect)frameForItemsAtIndexes:(CPIndexSet)anIndexSet
{
var indexArray = [],
frame = CGRectNull;
[anIndexSet getIndexes:indexArray maxCount:-1 inIndexRange:nil];
var index = 0,
count = [indexArray count];
for (; index < count; ++index)
frame = CGRectUnion(frame, [self frameForItemAtIndex:indexArray[index]]);
return frame;
}
@end
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
CPCollectionViewSelectableKey = @"CPCollectionViewSelectableKey",
CPCollectionViewBackgroundColorsKey = @"CPCollectionViewBackgroundColorsKey";
@implementation CPCollectionView (KeyboardInteraction)
- (void)_modifySelectionWithNewIndex:(int)anIndex direction:(int)aDirection expand:(BOOL)shouldExpand
{
anIndex = MIN(MAX(anIndex, 0), [[self items] count] - 1);
if (_allowsMultipleSelection && shouldExpand)
{
var indexes = [_selectionIndexes copy],
bottomAnchor = [indexes firstIndex],
topAnchor = [indexes lastIndex];
// if the direction is backward (-1) check with the bottom anchor
if (aDirection === -1)
[indexes addIndexesInRange:CPMakeRange(anIndex, bottomAnchor - anIndex + 1)];
else
[indexes addIndexesInRange:CPMakeRange(topAnchor, anIndex - topAnchor + 1)];
}
else
indexes = [CPIndexSet indexSetWithIndex:anIndex];
[self setSelectionIndexes:indexes];
[self _scrollToSelection];
}
- (void)_scrollToSelection
{
var frame = [self frameForItemsAtIndexes:[self selectionIndexes]];
if (!CGRectIsNull(frame))
[self scrollRectToVisible:frame];
}
- (void)moveLeft:(id)sender
{
var index = [[self selectionIndexes] firstIndex];
if (index === CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - 1 direction:-1 expand:NO];
}
- (void)moveLeftAndModifySelection:(id)sender
{
var index = [[self selectionIndexes] firstIndex];
if (index === CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - 1 direction:-1 expand:YES];
}
- (void)moveRight:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + 1 direction:1 expand:NO];
}
- (void)moveRightAndModifySelection:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + 1 direction:1 expand:YES];
}
- (void)moveDown:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + [self numberOfColumns] direction:1 expand:NO];
}
- (void)moveDownAndModifySelection:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + [self numberOfColumns] direction:1 expand:YES];
}
- (void)moveUp:(id)sender
{
var index = [[self selectionIndexes] firstIndex];
if (index == CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - [self numberOfColumns] direction:-1 expand:NO];
}
- (void)moveUpAndModifySelection:(id)sender
{
var index = [[self selectionIndexes] firstIndex];
if (index == CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - [self numberOfColumns] direction:-1 expand:YES];
}
- (void)deleteBackward:(id)sender
{
if ([[self delegate] respondsToSelector:@selector(collectionView:shouldDeleteItemsAtIndexes:)])
{
[[self delegate] collectionView:self shouldDeleteItemsAtIndexes:[self selectionIndexes]];
var index = [[self selectionIndexes] firstIndex];
if (index > [[self content] count] - 1)
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:[[self content] count] - 1]];
[self _scrollToSelection];
[self setNeedsDisplay:YES];
}
}
- (void)keyDown:(CPEvent)anEvent
{
[self interpretKeyEvents:[anEvent]];
}
@end
@implementation CPCollectionView (Deprecated)
- (CGRect)rectForItemAtIndex:(int)anIndex
{
_CPReportLenientDeprecation([self class], _cmd, @selector(frameForItemAtIndex:));
// Don't re-compute anything just grab the current frame
// This allows subclasses to override tile without messing this up.
return [self frameForItemAtIndex:anIndex];
}
- (CGRect)rectForItemsAtIndexes:(CPIndexSet)anIndexSet
{
_CPReportLenientDeprecation([self class], _cmd, @selector(frameForItemsAtIndexes:));
return [self frameForItemsAtIndexes:anIndexSet];
}
@end
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
CPCollectionViewMaxNumberOfRowsKey = @"CPCollectionViewMaxNumberOfRowsKey",
CPCollectionViewMaxNumberOfColumnsKey = @"CPCollectionViewMaxNumberOfColumnsKey",
CPCollectionViewSelectableKey = @"CPCollectionViewSelectableKey",
CPCollectionViewAllowsMultipleSelectionKey = @"CPCollectionViewAllowsMultipleSelectionKey",
CPCollectionViewBackgroundColorsKey = @"CPCollectionViewBackgroundColorsKey";
@implementation CPCollectionView (CPCoding)
- (void)awakeFromCib
{
[super awakeFromCib];
if (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()) || CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
{
var item = _itemPrototype;
if (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
_minItemSize = [[item view] frameSize];
else if (CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
_maxItemSize = [[item view] frameSize];
}
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
@@ -693,20 +988,24 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
_cachedItems = [];
_itemSize = CGSizeMakeZero();
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey] || CGSizeMakeZero();
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey] || CGSizeMakeZero();
_maxNumberOfRows = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfRowsKey] || 0;
_maxNumberOfColumns = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfColumnsKey] || 0;
_verticalMargin = [aCoder decodeFloatForKey:CPCollectionViewVerticalMarginKey];
_isSelectable = [aCoder decodeBoolForKey:CPCollectionViewSelectableKey];
_allowsMultipleSelection = [aCoder decodeBoolForKey:CPCollectionViewAllowsMultipleSelectionKey];
[self setBackgroundColors:[aCoder decodeObjectForKey:CPCollectionViewBackgroundColorsKey]];
_tileWidth = -1.0;
_selectionIndexes = [CPIndexSet indexSet];
_allowsEmptySelection = YES;
}
@@ -719,12 +1018,16 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
if (!CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
[aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey];
if (!CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
[aCoder encodeInt:_maxNumberOfRows forKey:CPCollectionViewMaxNumberOfRowsKey];
[aCoder encodeInt:_maxNumberOfColumns forKey:CPCollectionViewMaxNumberOfColumnsKey];
[aCoder encodeBool:_isSelectable forKey:CPCollectionViewSelectableKey];
[aCoder encodeBool:_allowsMultipleSelection forKey:CPCollectionViewAllowsMultipleSelectionKey];
[aCoder encodeFloat:_verticalMargin forKey:CPCollectionViewVerticalMarginKey];
[aCoder encodeObject:_backgroundColors forKey:CPCollectionViewBackgroundColorsKey];
+1
View File
@@ -22,6 +22,7 @@
@import "CPViewController.j"
/*!
Represents an object inside a CPCollectionView.
*/
+112 -147
View File
@@ -32,7 +32,7 @@ var _redComponent = 0,
_greenComponent = 1,
_blueComponent = 2,
_alphaCompnent = 3;
var _hueComponent = 0,
_saturationComponent = 1,
_brightnessComponent = 2;
@@ -54,27 +54,21 @@ var cachedBlackColor,
cachedShadowColor,
cachedClearColor;
/*!
/*!
@ingroup appkit
@code CPColor
\c CPColor can be used to represent color
in an RGB or HSB model with an optional transparency value.</p>
<p>It also provides some class helper methods that
returns instances of commonly used colors.</p>
<p>The class does not have a \c -set: method
like NextStep based frameworks to change the color of
the current context. To change the color of the current
context, use CGContextSetFillColor().
*/
@implementation CPColor : CPObject
{
CPArray _components;
CPImage _patternImage;
CPString _cssString;
CPString _cssString;
}
/*!
@@ -82,12 +76,12 @@ var cachedBlackColor,
Each component should be between the range of 0.0 to 1.0. For
the alpha component, a value of 1.0 is opaque, and 0.0 means
completely transparent.
@param red the red component of the color
@param green the green component of the color
@param blue the blue component of the color
@param alpha the alpha component
@return a color initialized to the values specified
*/
+ (CPColor)colorWithRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
@@ -97,17 +91,17 @@ var cachedBlackColor,
/*!
@deprecated in favor of colorWithRed:green:blue:alpha:
Creates a color in the RGB color space, with an alpha value.
Each component should be between the range of 0.0 to 1.0. For
the alpha component, a value of 1.0 is opaque, and 0.0 means
completely transparent.
@param red the red component of the color
@param green the green component of the color
@param blue the blue component of the color
@param alpha the alpha component
@return a color initialized to the values specified
*/
+ (CPColor)colorWithCalibratedRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
@@ -119,10 +113,10 @@ var cachedBlackColor,
/*!
Creates a new color object with \c white for the RGB components.
For the alpha component, a value of 1.0 is opaque, and 0.0 means completely transparent.
@param white a float between 0.0 and 1.0
@param alpha the alpha component between 0.0 and 1.0
@return a color initialized to the values specified
*/
+ (CPColor)colorWithWhite:(float)white alpha:(float)alpha
@@ -131,14 +125,14 @@ 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.
@param white a float between 0.0 and 1.0
@param alpha the alpha component between 0.0 and 1.0
@return a color initialized to the values specified
*/
+ (CPColor)colorWithCalibratedWhite:(float)white alpha:(float)alpha
@@ -148,11 +142,11 @@ var cachedBlackColor,
/*!
Creates a new color in HSB space.
@param hue the hue value
@param saturation the saturation value
@param brightness the brightness value
@return the initialized color
*/
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness
@@ -162,16 +156,16 @@ var cachedBlackColor,
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness alpha:(float)alpha
{
if(saturation === 0.0)
if (saturation === 0.0)
return [CPColor colorWithCalibratedWhite:brightness / 100.0 alpha:alpha];
var f = hue % 60,
p = (brightness * (100 - saturation)) / 10000,
q = (brightness * (6000 - saturation * f)) / 600000,
t = (brightness * (6000 - saturation * (60 -f))) / 600000,
b = brightness / 100.0;
switch(FLOOR(hue / 60))
switch (FLOOR(hue / 60))
{
case 0: return [CPColor colorWithCalibratedRed: b green: t blue: p alpha: alpha];
case 1: return [CPColor colorWithCalibratedRed: q green: b blue: p alpha: alpha];
@@ -186,7 +180,7 @@ var cachedBlackColor,
Creates an RGB color from a hexadecimal string. For example,
the a string of "FFFFFF" would return a white CPColor.
"FF0000" would return a pure red, "00FF00" would return a
pure blue, and "0000FF" would return a pure green.
pure blue, and "0000FF" would return a pure green.
@param hex a 6 character long string of hex
@@ -194,7 +188,8 @@ var cachedBlackColor,
*/
+ (CPColor)colorWithHexString:(string)hex
{
return [[CPColor alloc] _initWithRGBA: hexToRGB(hex)];
var rgba = hexToRGB(hex);
return rgba ? [[CPColor alloc] _initWithRGBA: rgba] : null;
}
/*!
@@ -397,7 +392,7 @@ var cachedBlackColor,
/*!
Creates a CPColor from a valid CSS RGB string. Example, "rgb(32,64,129)".
@param aString a CSS color string
@return a color initialized to the value in the css string
*/
@@ -409,23 +404,23 @@ var cachedBlackColor,
/* @ignore */
- (id)_initWithCSSString:(CPString)aString
{
if(aString.indexOf("rgb") == CPNotFound)
if (aString.indexOf("rgb") == CPNotFound)
return nil;
self = [super init];
var startingIndex = aString.indexOf("(");
var parts = aString.substring(startingIndex+1).split(',');
var startingIndex = aString.indexOf("("),
parts = aString.substring(startingIndex + 1).split(',');
_components = [
parseInt(parts[0], 10) / 255.0,
parseInt(parts[1], 10) / 255.0,
parseInt(parts[2], 10) / 255.0,
parts[3] ? parseInt(parts[3], 10) / 255.0 : 1.0
]
parts[3] ? parseFloat(parts[3], 10) : 1.0
];
_cssString = aString;
return self;
}
@@ -433,55 +428,20 @@ var cachedBlackColor,
- (id)_initWithRGBA:(CPArray)components
{
self = [super init];
if (self)
{
_components = components;
if (!CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0 && window.Base64 && window.CRC32)
{
var bytes = [0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,0x8,0x3,0x0,0x0,0x0,0x28,0xcb,0x34,0xbb,0x0,0x0,0x3,0x0,0x50,0x4c,0x54,0x45,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x17,0x89,0x99,0x55,0x0,0x0,0x0,0x1,0x74,0x52,0x4e,0x53,0x0,0x40,0xe6,0xd8,0x66,0x0,0x0,0x0,0x10,0x49,0x44,0x41,0x54,0x78,0xda,0x62,0x60,0x0,0x0,0x0,0x0,0xff,0xff,0x3,0x0,0x0,0x2,0x0,0x1,0x24,0x7f,0x24,0xf1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82,0xff];
var r_off = 41;
var g_off = 42;
var b_off = 43;
var a_off = 821;
var plte_crc_off = 809;
var trns_crc_off = 822;
var plte_type_off = 37;
var trns_type_off = 817;
bytes[r_off] = Math.round(_components[0]*255);
bytes[g_off] = Math.round(_components[1]*255);
bytes[b_off] = Math.round(_components[2]*255);
bytes[a_off] = Math.round(_components[3]*255);
// calculate new CRCs
var new_plte_crc = integerToBytes(CRC32.getCRC(bytes, plte_type_off, 4+768), 4);
var new_trns_crc = integerToBytes(CRC32.getCRC(bytes, trns_type_off, 4+1), 4);
// overwrite old CRCs with new ones
for (var i = 0; i < 4; i++)
{
bytes[plte_crc_off+i] = new_plte_crc[i];
bytes[trns_crc_off+i] = new_trns_crc[i];
}
// Base64 encode, strip whitespace and build data URL
var base64image = Base64.encode(bytes); //.replace(/[\s]/g, "");
_cssString = "url(\"data:image/png;base64," + base64image + "\")";
}
else
{
var hasAlpha = CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0;
_cssString = (hasAlpha ? "rgba(" : "rgb(") +
parseInt(_components[0] * 255.0) + ", " +
parseInt(_components[1] * 255.0) + ", " +
parseInt(_components[2] * 255.0) +
(hasAlpha ? (", " + _components[3]) : "") + ")";
}
var hasAlpha = CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0;
_cssString = (hasAlpha ? "rgba(" : "rgb(") +
parseInt(_components[0] * 255.0) + ", " +
parseInt(_components[1] * 255.0) + ", " +
parseInt(_components[2] * 255.0) +
(hasAlpha ? (", " + _components[3]) : "") + ")";
}
return self;
}
@@ -489,13 +449,14 @@ var cachedBlackColor,
- (id)_initWithPatternImage:(CPImage)anImage
{
self = [super init];
if (self)
{
_patternImage = anImage;
_cssString = "url(\"" + [_patternImage filename] + "\")";
_components = [0.0, 0.0, 0.0, 1.0];
}
return self;
}
@@ -557,17 +518,17 @@ var cachedBlackColor,
/*!
Returns a new color with the same RGB as the receiver but a new alpha component.
@param anAlphaComponent the alpha component for the new color
@return a new color object
*/
- (CPColor)colorWithAlphaComponent:(float)anAlphaComponent
{
var components = _components.slice();
components[components.length - 1] = anAlphaComponent;
return [[[self class] alloc] _initWithRGBA:components];
}
@@ -586,37 +547,40 @@ var cachedBlackColor,
var red = ROUND(_components[_redComponent] * 255.0),
green = ROUND(_components[_greenComponent] * 255.0),
blue = ROUND(_components[_blueComponent] * 255.0);
var max = MAX(red, green, blue),
min = MIN(red, green, blue),
delta = max - min;
var brightness = max / 255.0,
saturation = (max != 0) ? delta / max : 0;
var hue;
if(saturation == 0)
if (saturation == 0)
{
hue = 0;
}
else
{
var rr = (max - red) / delta;
var gr = (max - green) / delta;
var br = (max - blue) / delta;
if (red == max)
var rr = (max - red) / delta,
gr = (max - green) / delta,
br = (max - blue) / delta;
if (red == max)
hue = br - gr;
else if (green == max)
else if (green == max)
hue = 2 + rr - br;
else
else
hue = 4 + gr - rr;
hue /= 6;
if (hue < 0)
if (hue < 0)
hue++;
}
return [
ROUND(hue * 360.0),
ROUND(hue * 360.0),
ROUND(saturation * 100.0),
ROUND(brightness * 100.0)
];
@@ -641,7 +605,7 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
*/
- (CPString)hexString
{
return rgbToHex([self redComponent], [self greenComponent], [self blueComponent])
return rgbToHex([self redComponent], [self greenComponent], [self blueComponent]);
}
- (BOOL)isEqual:(CPColor)aColor
@@ -652,7 +616,19 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
if (aColor === self)
return YES;
return [aColor isKindOfClass:CPColor] && [aColor cssString] === [self cssString];
if (![aColor isKindOfClass:CPColor])
return NO;
if (_patternImage || [aColor patternImage])
return [_patternImage isEqual:[aColor patternImage]];
// We don't require the components to be equal beyond 8 bits since otherwise
// simple rounding errors will make two colours which are exactly the same on
// screen compare unequal.
return ROUND([self redComponent] * 255.0) == ROUND([aColor redComponent] * 255.0) &&
ROUND([self greenComponent] * 255.0) == ROUND([aColor greenComponent] * 255.0) &&
ROUND([self blueComponent] * 255.0) == ROUND([aColor blueComponent] * 255.0) &&
[self alphaComponent] == [aColor alphaComponent];
}
- (CPString)description
@@ -664,7 +640,7 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
@implementation CPColor (CoreGraphicsExtensions)
/*!
/*!
Set's the receiver to be the fill and stroke color in the current graphics context
*/
- (void)set
@@ -673,16 +649,16 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
[self setStroke];
}
/*!
/*!
Set's the receiver to be the fill color in the current graphics context
*/
- (void)setFill
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetFillColor(ctx, self);
CGContextSetFillColor(ctx, self);
}
/*!
/*!
Set's the receiver to be the stroke color in the current graphics context
*/
- (void)setStroke
@@ -715,7 +691,7 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
{
if ([aCoder containsValueForKey:CPColorPatternImageKey])
return [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
return [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
}
@@ -733,6 +709,7 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
@end
var hexCharacters = "0123456789ABCDEF";
/*!
@@ -741,51 +718,39 @@ var hexCharacters = "0123456789ABCDEF";
@class CPColor
@return an array of rgb components
*/
function hexToRGB(hex)
var hexToRGB = function(hex)
{
if ( hex.length == 3 )
if (hex.length == 3)
hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
if(hex.length != 6)
if (hex.length != 6)
return null;
hex = hex.toUpperCase();
for(var i=0; i<hex.length; i++)
if(hexCharacters.indexOf(hex.charAt(i)) == -1)
for (var i = 0; i < hex.length; i++)
if (hexCharacters.indexOf(hex.charAt(i)) == -1)
return null;
var red = (hexCharacters.indexOf(hex.charAt(0)) * 16 + hexCharacters.indexOf(hex.charAt(1))) / 255.0;
var green = (hexCharacters.indexOf(hex.charAt(2)) * 16 + hexCharacters.indexOf(hex.charAt(3))) / 255.0;
var blue = (hexCharacters.indexOf(hex.charAt(4)) * 16 + hexCharacters.indexOf(hex.charAt(5))) / 255.0;
var red = (hexCharacters.indexOf(hex.charAt(0)) * 16 + hexCharacters.indexOf(hex.charAt(1))) / 255.0,
green = (hexCharacters.indexOf(hex.charAt(2)) * 16 + hexCharacters.indexOf(hex.charAt(3))) / 255.0,
blue = (hexCharacters.indexOf(hex.charAt(4)) * 16 + hexCharacters.indexOf(hex.charAt(5))) / 255.0;
return [red, green, blue, 1.0];
}
};
function integerToBytes(integer, length) {
if (!length)
length = (integer == 0) ? 1 : Math.round((Math.log(integer)/Math.log(2))/8+0.5);
var bytes = new Array(length);
for (var i = length-1; i >= 0; i--) {
bytes[i] = integer & 255;
integer = integer >> 8
}
return bytes;
}
function rgbToHex(r,g,b) {
var rgbToHex = function(r,g,b)
{
return byteToHex(r) + byteToHex(g) + byteToHex(b);
}
};
function byteToHex(n) {
if (!n || isNaN(n)) return "00";
n = ROUND(MIN(255,MAX(0,256*n)));
return hexCharacters.charAt((n - n % 16) / 16) +
hexCharacters.charAt(n % 16);
}
var byteToHex = function(n)
{
if (!n || isNaN(n))
return "00";
// Toll-Free bridge CPColor to CGColor.
//CGColor.prototype.isa = CPColor;
//[CPColor initialize];
n = FLOOR(MIN(255, MAX(0, 256 * n)));
//http://dev.mootools.net/browser/trunk/Source/Utilities/Color.js?rev=1184
return hexCharacters.charAt((n - n % 16) / 16) +
hexCharacters.charAt(n % 16);
};
+94 -89
View File
@@ -20,11 +20,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPApplication.j"
@import "CPButton.j"
@import "CPCookie.j"
@import "CPPanel.j"
@import "CPView.j"
CPColorPanelColorDidChangeNotification = @"CPColorPanelColorDidChangeNotification";
var PREVIEW_HEIGHT = 20.0,
@@ -35,7 +37,7 @@ var PREVIEW_HEIGHT = 20.0,
var SharedColorPanel = nil,
ColorPickerClasses = [];
/*
A color wheel
@global
@@ -52,7 +54,7 @@ CPSliderColorPickerMode = 2;
CPColorPickerViewWidth = 265,
CPColorPickerViewHeight = 370;
/*!
/*!
@ingroup appkit
@class CPColorPanel
@@ -61,7 +63,7 @@ CPColorPickerViewHeight = 370;
obtain the panel, call the \c +sharedColorPanel method.
*/
@implementation CPColorPanel : CPPanel
{
{
_CPColorPanelToolbar _toolbar;
_CPColorPanelSwatches _swatchView;
_CPColorPanelPreview _previewView;
@@ -80,8 +82,8 @@ CPColorPickerViewHeight = 370;
int _mode;
}
/*!
A list of color pickers is collected here, and any color panel created will contain
/*!
A list of color pickers is collected here, and any color panel created will contain
any picker in this list up to this point. In other words, call before creating a color panel.
*/
+ (void)provideColorPickerClass:(Class)aColorPickerSubclass
@@ -96,7 +98,7 @@ CPColorPickerViewHeight = 370;
{
if (!SharedColorPanel)
SharedColorPanel = [[CPColorPanel alloc] init];
return SharedColorPanel;
}
@@ -107,7 +109,7 @@ CPColorPickerViewHeight = 370;
+ (void)setPickerMode:(CPColorPanelMode)mode
{
var panel = [CPColorPanel sharedColorPanel];
[panel setMode: mode];
[panel setMode:mode];
}
/*
@@ -116,7 +118,7 @@ CPColorPickerViewHeight = 370;
*/
- (id)init
{
self = [super initWithContentRect:CGRectMake(500.0, 50.0, 219.0, 370.0)
self = [super initWithContentRect:CGRectMake(500.0, 50.0, 219.0, 370.0)
styleMask:(CPTitledWindowMask | CPClosableWindowMask | CPResizableWindowMask)];
if (self)
@@ -125,14 +127,14 @@ CPColorPickerViewHeight = 370;
[self setTitle:@"Color Panel"];
[self setLevel:CPFloatingWindowLevel];
[self setFloatingPanel:YES];
[self setBecomesKeyOnlyIfNeeded:YES];
[self setMinSize:CGSizeMake(219.0, 342.0)];
[self setMinSize:CGSizeMake(219.0, 363.0)];
[self setMaxSize:CGSizeMake(323.0, 537.0)];
}
return self;
}
@@ -140,15 +142,15 @@ CPColorPickerViewHeight = 370;
Sets the color of the panel, and updates the picker. Also posts a \c CPColorPanelDidChangeNotification.
*/
- (void)setColor:(CPColor)aColor
{
{
_color = aColor;
[_previewView setBackgroundColor: _color];
[CPApp sendAction:@selector(changeColor:) to:nil from:self];
if (_target && _action)
[CPApp sendAction:_action to:_target from:self];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPColorPanelColorDidChangeNotification
object:self];
@@ -165,7 +167,7 @@ CPColorPickerViewHeight = 370;
- (void)setColor:(CPColor)aColor updatePicker:(BOOL)bool
{
[self setColor:aColor];
if (bool)
[_activePicker setColor:_color];
}
@@ -232,30 +234,30 @@ CPColorPickerViewHeight = 370;
{
var picker = _colorPickers[[sender tag]],
view = [picker provideNewView:NO];
if (!view)
view = [picker provideNewView:YES];
if (view == _currentView)
return;
if (_currentView)
[view setFrame:[_currentView frame]];
else
{
var height = (TOOLBAR_HEIGHT+10+PREVIEW_HEIGHT+5+SWATCH_HEIGHT+32),
var height = (TOOLBAR_HEIGHT + 10 + PREVIEW_HEIGHT + 5 + SWATCH_HEIGHT + 32),
bounds = [[self contentView] bounds];
[view setFrameSize: CPSizeMake(bounds.size.width - 10, bounds.size.height - height)];
[view setFrameOrigin: CPPointMake(5, height)];
[view setFrameSize:CPSizeMake(bounds.size.width - 10, bounds.size.height - height)];
[view setFrameOrigin:CPPointMake(5, height)];
}
[_currentView removeFromSuperview];
[[self contentView] addSubview:view];
_currentView = view;
_activePicker = picker;
[picker setColor:[self color]];
}
@@ -285,7 +287,7 @@ CPColorPickerViewHeight = 370;
_colorPickers = [];
var count = [ColorPickerClasses count];
for (var i=0; i<count; i++)
for (var i = 0; i < count; i++)
{
var currentPickerClass = ColorPickerClasses[i],
currentPicker = [[currentPickerClass alloc] initWithPickerMask:0 colorPanel:self];
@@ -297,29 +299,29 @@ CPColorPickerViewHeight = 370;
bounds = [contentView bounds];
_toolbar = [[CPView alloc] initWithFrame:CGRectMake(0, 6, CGRectGetWidth(bounds), TOOLBAR_HEIGHT)];
[_toolbar setAutoresizingMask: CPViewWidthSizable];
[_toolbar setAutoresizingMask: CPViewWidthSizable];
var totalToolbarWidth = count * ICON_WIDTH + (count - 1) * ICON_PADDING,
leftOffset = (CGRectGetWidth(bounds) - totalToolbarWidth) / 2.0,
buttonForLater = nil;
for (var i=0; i<count; i++)
for (var i = 0; i < count; i++)
{
var image = [_colorPickers[i] provideNewButtonImage],
highlightImage = [_colorPickers[i] provideNewAlternateButtonImage],
button = [[CPButton alloc] initWithFrame:CGRectMake(leftOffset + i*(ICON_WIDTH+ICON_PADDING), 0, ICON_WIDTH, ICON_WIDTH)];
button = [[CPButton alloc] initWithFrame:CGRectMake(leftOffset + i * (ICON_WIDTH + ICON_PADDING), 0, ICON_WIDTH, ICON_WIDTH)];
[button setTag:i];
[button setTarget:self];
[button setAction:@selector(_setPicker:)];
[button setBordered:NO];
[button setAutoresizingMask:CPViewMinXMargin|CPViewMaxXMargin];
[button setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin];
[button setImage:image];
[button setAlternateImage:highlightImage];
[_toolbar addSubview:button];
if (!buttonForLater)
buttonForLater = button;
}
@@ -330,7 +332,7 @@ CPColorPickerViewHeight = 370;
_previewView = [[_CPColorPanelPreview alloc] initWithFrame:CGRectInset([previewBox bounds], 2.0, 2.0)];
[_previewView setColorPanel:self];
[_previewView setAutoresizingMask:CPViewWidthSizable];
[_previewView setAutoresizingMask:CPViewWidthSizable];
[previewBox setBackgroundColor:[CPColor colorWithWhite:0.8 alpha:1.0]];
[previewBox setAutoresizingMask:CPViewWidthSizable];
@@ -338,7 +340,7 @@ CPColorPickerViewHeight = 370;
[previewBox addSubview:_previewView];
var _previewLabel = [[CPTextField alloc] initWithFrame: CPRectMake(10, TOOLBAR_HEIGHT + 10, 60, 15)];
[_previewLabel setStringValue: "Preview:"];
[_previewLabel setStringValue:"Preview:"];
[_previewLabel setTextColor:[CPColor blackColor]];
[_previewLabel setAlignment:CPRightTextAlignment];
@@ -350,8 +352,8 @@ CPColorPickerViewHeight = 370;
_swatchView = [[_CPColorPanelSwatches alloc] initWithFrame:CGRectInset([swatchBox bounds], 1.0, 1.0)];
[_swatchView setColorPanel: self];
[_swatchView setAutoresizingMask: CPViewWidthSizable];
[_swatchView setColorPanel:self];
[_swatchView setAutoresizingMask:CPViewWidthSizable];
[swatchBox addSubview:_swatchView];
@@ -367,9 +369,10 @@ CPColorPickerViewHeight = 370;
[opacityLabel setAlignment:CPRightTextAlignment];
_opacitySlider = [[CPSlider alloc] initWithFrame:CGRectMake(76, TOOLBAR_HEIGHT + PREVIEW_HEIGHT + 34, CGRectGetWidth(bounds) - 86, 20.0)];
[_opacitySlider setMinValue:0.0];
[_opacitySlider setMaxValue:1.0];
[_opacitySlider setAutoresizingMask:CPViewWidthSizable];
[_opacitySlider setTarget:self];
[_opacitySlider setAction:@selector(setOpacity:)];
@@ -415,37 +418,37 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
CPCookie _swatchCookie;
}
-(id)initWithFrame:(CPRect)aFrame
- (id)initWithFrame:(CPRect)aFrame
{
self = [super initWithFrame:aFrame];
[self setBackgroundColor: [CPColor grayColor]];
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
var whiteColor = [CPColor whiteColor];
_swatchCookie = [[CPCookie alloc] initWithName: CPColorPanelSwatchesCookie];
var colorList = [self startingColorList];
_swatches = [];
for(var i=0; i < 50; i++)
for (var i = 0; i < 50; i++)
{
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
var view = [[CPView alloc] initWithFrame: CPRectMake(13*i+1, 1, 12, 12)],
var view = [[CPView alloc] initWithFrame: CPRectMake(13 * i + 1, 1, 12, 12)],
fillView = [[CPView alloc] initWithFrame:CGRectInset([view bounds], 1.0, 1.0)];
[view setBackgroundColor:whiteColor];
[fillView setBackgroundColor: (i < colorList.length) ? colorList[i] : whiteColor];
[view addSubview:fillView];
[self addSubview: view];
_swatches.push(view);
}
return self;
}
@@ -457,7 +460,8 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (CPArray)startingColorList
{
var cookieValue = [_swatchCookie value];
if(cookieValue == "")
if (cookieValue == "")
{
return [
[CPColor blackColor],
@@ -471,11 +475,11 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
[CPColor yellowColor]
];
}
var cookieValue = eval(cookieValue);
var result = [];
for(var i=0; i<cookieValue.length; i++)
var cookieValue = eval(cookieValue),
result = [];
for (var i = 0; i < cookieValue.length; i++)
result.push([CPColor colorWithHexString: cookieValue[i]]);
return result;
@@ -485,12 +489,12 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var result = [];
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
for(var i=0; i<_swatches.length; i++)
for (var i = 0; i < _swatches.length; i++)
result.push([[[_swatches[i] subviews][0] backgroundColor] hexString]);
var future = new Date();
future.setYear(2019);
[_swatchCookie setValue: JSON.stringify(result) expires:future domain: nil];
}
@@ -518,9 +522,10 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (void)mouseUp:(CPEvent)anEvent
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if(point.x > [self bounds].size.width - 1 || point.x < 1)
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
bounds = [self bounds];
if (!CGRectContainsPoint(bounds, point) || point.x > [self bounds].size.width - 1 || point.x < 1)
return NO;
[_colorPanel setColor: [self colorAtIndex:FLOOR(point.x / 13)] updatePicker: YES];
@@ -530,25 +535,25 @@ 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];
var swatch = _swatches[FLOOR(point.x / 13)];
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
_dragColor = [[swatch subviews][0] backgroundColor];
var bounds = CPRectCreateCopy([swatch bounds]);
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
var dragView = [[CPView alloc] initWithFrame: bounds];
var dragView = [[CPView alloc] initWithFrame: bounds],
dragFillView = [[CPView alloc] initWithFrame:CGRectInset(bounds, 1.0, 1.0)];
[dragView setBackgroundColor:[CPColor blackColor]];
[dragFillView setBackgroundColor:_dragColor];
[dragView addSubview:dragFillView];
[self dragView: dragView
@@ -562,20 +567,20 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
{
if(aType == CPColorDragType)
[aPasteboard setData:_dragColor forType:aType];
if (aType == CPColorDragType)
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:_dragColor] forType:aType];
}
- (void)performDragOperation:(id <CPDraggingInfo>)aSender
{
{
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
pasteboard = [aSender draggingPasteboard],
swatch = nil;
if(![pasteboard availableTypeFromArray:[CPColorDragType]] || location.x > [self bounds].size.width - 1 || location.x < 1)
if (![pasteboard availableTypeFromArray:[CPColorDragType]] || location.x > [self bounds].size.width - 1 || location.x < 1)
return NO;
[self setColor:[pasteboard dataForType:CPColorDragType] atIndex: FLOOR(location.x / 13)];
[self setColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] atIndex: FLOOR(location.x / 13)];
}
@end
@@ -589,9 +594,9 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (id)initWithFrame:(CPRect)aFrame
{
self = [super initWithFrame:aFrame];
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
return self;
}
@@ -609,11 +614,11 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var pasteboard = [aSender draggingPasteboard];
if(![pasteboard availableTypeFromArray:[CPColorDragType]])
if (![pasteboard availableTypeFromArray:[CPColorDragType]])
return NO;
var color = [pasteboard dataForType:CPColorDragType];
[_colorPanel setColor: color updatePicker: YES];
var color = [CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]];
[_colorPanel setColor:color updatePicker:YES];
}
- (BOOL)isOpaque
@@ -625,19 +630,19 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPArray arrayWithObject:CPColorDragType] owner:self];
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPColorDragType] owner:self];
var bounds = CPRectMake(0, 0, 15, 15);
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
var dragView = [[CPView alloc] initWithFrame: bounds];
var dragView = [[CPView alloc] initWithFrame: bounds],
dragFillView = [[CPView alloc] initWithFrame:CGRectInset(bounds, 1.0, 1.0)];
[dragView setBackgroundColor:[CPColor blackColor]];
[dragFillView setBackgroundColor:[self backgroundColor]];
[dragView addSubview:dragFillView];
[self dragView: dragView
at: CPPointMake(point.x - bounds.size.width / 2.0, point.y - bounds.size.height / 2.0)
offset: CPPointMake(0.0, 0.0)
@@ -649,8 +654,8 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
{
if(aType == CPColorDragType)
[aPasteboard setData:[self backgroundColor] forType:aType];
if (aType == CPColorDragType)
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:[self backgroundColor]] forType:aType];
}
@end
+39 -38
View File
@@ -21,9 +21,11 @@
*/
@import <Foundation/CPObject.j>
@import "CPColorPanel.j"
/*!
@import "CPView.j"
/*!
@ingroup appkit
@class CPColorPicker
@@ -100,18 +102,18 @@
CPColor _cachedColor;
}
- (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);
_pickerView = [[CPView alloc] initWithFrame:aFrame];
[_pickerView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
[_pickerView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
@@ -134,17 +136,17 @@
[_pickerView addSubview:_brightnessSlider];
}
-(void)brightnessSliderDidChange:(id)sender
- (void)brightnessSliderDidChange:(id)sender
{
[self updateColor];
}
-(void)colorWheelDidChange:(id)sender
- (void)colorWheelDidChange:(id)sender
{
[self updateColor];
}
-(void)updateColor
- (void)updateColor
{
var hue = [_hueSaturationView angle],
saturation = [_hueSaturationView distance],
@@ -221,7 +223,7 @@
float _radius;
}
-(id)initWithFrame:(CPRect)aFrame
- (id)initWithFrame:(CPRect)aFrame
{
self = [super initWithFrame:aFrame];
@@ -239,8 +241,10 @@
_blackWheelImage.style.filter = "alpha(opacity=0)"
_blackWheelImage.style.position = "absolute";
#if PLATFORM(DOM)
_DOMElement.appendChild(_wheelImage);
_DOMElement.appendChild(_blackWheelImage);
#endif
[self setWheelSize:aFrame.size];
@@ -257,19 +261,19 @@
return self;
}
-(void)setWheelBrightness:(float)brightness
- (void)setWheelBrightness:(float)brightness
{
_blackWheelImage.style.opacity = 1.0 - brightness;
_blackWheelImage.style.filter = "alpha(opacity=" + (1.0 - brightness)*100 + ")"
_blackWheelImage.style.filter = "alpha(opacity=" + (1.0 - brightness) * 100 + ")"
}
-(void)setFrameSize:(CPSize)aSize
- (void)setFrameSize:(CPSize)aSize
{
[super setFrameSize:aSize];
[self setWheelSize:aSize];
}
-(void)setWheelSize:(CPSize)aSize
- (void)setWheelSize:(CPSize)aSize
{
var min = MIN(aSize.width, aSize.height);
@@ -292,57 +296,55 @@
[self setAngle:[self degreesToRadians:_angle] distance:(_distance / 100.0) * _radius];
}
-(void)setDelegate:(id)aDelegate
- (void)setDelegate:(id)aDelegate
{
_delegate = aDelegate;
}
-(id)delegate
- (id)delegate
{
return _delegate;
}
-(float)angle
- (float)angle
{
return _angle;
}
-(float)distance
- (float)distance
{
return _distance;
}
-(void)mouseDown:(CPEvent)anEvent
- (void)mouseDown:(CPEvent)anEvent
{
[self reposition:anEvent];
}
-(void)mouseDragged:(CPEvent)anEvent
- (void)mouseDragged:(CPEvent)anEvent
{
[self reposition:anEvent];
}
-(void)reposition:(CPEvent)anEvent
- (void)reposition:(CPEvent)anEvent
{
var bounds = [self bounds],
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
var midX = CGRectGetMidX(bounds);
var midY = CGRectGetMidY(bounds);
var distance = MIN(SQRT((location.x - midX)*(location.x - midX) + (location.y - midY)*(location.y - midY)), _radius);
var angle = ATAN2(location.y - midY, location.x - midX);
location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
midX = CGRectGetMidX(bounds),
midY = CGRectGetMidY(bounds),
distance = MIN(SQRT((location.x - midX) * (location.x - midX) + (location.y - midY) * (location.y - midY)), _radius),
angle = ATAN2(location.y - midY, location.x - midX);
[self setAngle:angle distance:distance];
[_delegate colorWheelDidChange:self];
}
-(void)setAngle:(int)angle distance:(float)distance
- (void)setAngle:(int)angle distance:(float)distance
{
var bounds = [self bounds];
var midX = CGRectGetMidX(bounds);
var midY = CGRectGetMidY(bounds);
var bounds = [self bounds],
midX = CGRectGetMidX(bounds),
midY = CGRectGetMidY(bounds);
_angle = [self radiansToDegrees:angle];
_distance = (distance / _radius) * 100.0;
@@ -350,23 +352,22 @@
[_crosshair setFrameOrigin:CPPointMake(COS(angle) * distance + midX - 2.0, SIN(angle) * distance + midY - 2.0)];
}
-(void)setPositionToColor:(CPColor)aColor
- (void)setPositionToColor:(CPColor)aColor
{
var hsb = [aColor hsbComponents],
bounds = [self bounds];
var angle = [self degreesToRadians:hsb[0]],
bounds = [self bounds],
angle = [self degreesToRadians:hsb[0]],
distance = (hsb[1] / 100.0) * _radius;
[self setAngle:angle distance:distance];
}
-(int)radiansToDegrees:(float)radians
- (int)radiansToDegrees:(float)radians
{
return ((-radians / PI) * 180 + 360) % 360;
}
-(float)degreesToRadians:(float)degrees
- (float)degreesToRadians:(float)degrees
{
return -(((degrees - 360) / 180) * PI);
}
+36 -30
View File
@@ -29,7 +29,7 @@
var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiveNotification";
/*!
/*!
@ingroup appkit
@class CPColorWell
@@ -41,7 +41,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
BOOL _active;
BOOL _bordered;
CPColor _color;
CPView _wellView;
}
@@ -49,19 +49,19 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_active = NO;
_bordered = YES;
_color = [CPColor whiteColor];
[self drawBezelWithHighlight:NO];
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
[self _registerForNotifications];
}
return self;
}
@@ -97,9 +97,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
if (_bordered == bordered)
return;
_bordered = bordered;
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
}
@@ -120,9 +120,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
if (_color == aColor)
return;
_color = aColor;
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
}
@@ -137,7 +137,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
// Activating and Deactivating Color Wells
/*!
Activates the color well, displays the color panel, and makes the panel's current color the same as its own.
Activates the color well, displays the color panel, and makes the panel's current color the same as its own.
If exclusive is \c YES, deactivates any other CPColorWells. \c NO, keeps them active.
@param shouldBeExclusive whether other color wells should be deactivated.
*/
@@ -152,9 +152,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
if ([self isActive])
return;
_active = YES;
[[CPNotificationCenter defaultCenter]
addObserver:self
selector:@selector(colorPanelDidChangeColor:)
@@ -169,9 +169,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
if (![self isActive])
return;
_active = NO;
[[CPNotificationCenter defaultCenter]
removeObserver:self
name:CPColorPanelColorDidChangeNotification
@@ -202,19 +202,19 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
_wellView = [[CPView alloc] initWithFrame:aRect];
[_wellView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self addSubview:_wellView];
}
else
[_wellView setFrame:aRect];
[_wellView setBackgroundColor:_color];
}
- (void)colorPanelDidChangeColor:(CPNotification)aNotification
{
[self takeColorFrom:[aNotification object]];
[self sendAction:[self action] to:[self target]];
}
@@ -231,25 +231,31 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
- (void)mouseDown:(CPEvent)anEvent
{
if (![self isEnabled])
return;
[self drawBezelWithHighlight:YES];
}
- (void)mouseDragged:(CPEvent)anEvent
{
if (![self isEnabled])
return;
[self drawBezelWithHighlight:CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])];
}
-(void)mouseUp:(CPEvent)anEvent
- (void)mouseUp:(CPEvent)anEvent
{
[self drawBezelWithHighlight:NO];
if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]))
if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]) || ![self isEnabled])
return;
[self activate:YES];
var colorPanel = [CPColorPanel sharedColorPanel];
[colorPanel setColor:_color];
[colorPanel orderFront:self];
}
@@ -268,11 +274,11 @@ var CPColorWellColorKey = "CPColorWellColorKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_active = NO;
_bordered = [aCoder decodeObjectForKey:CPColorWellBorderedKey];
_bordered = [aCoder decodeBoolForKey:CPColorWellBorderedKey];
_color = [aCoder decodeObjectForKey:CPColorWellColorKey];
[self drawBezelWithHighlight:NO];
@@ -280,7 +286,7 @@ var CPColorWellColorKey = "CPColorWellColorKey",
[self _registerForNotifications];
}
return self;
}
@@ -290,17 +296,17 @@ var CPColorWellColorKey = "CPColorWellColorKey",
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
// We do this in order to avoid encoding the _wellView, which
// We do this in order to avoid encoding the _wellView, which
// should just automatically be created programmatically as needed.
var actualSubviews = _subviews;
_subviews = [_subviews copy];
[_subviews removeObjectIdenticalTo:_wellView];
[super encodeWithCoder:aCoder];
_subviews = actualSubviews;
[aCoder encodeObject:_color forKey:CPColorWellColorKey];
[aCoder encodeObject:_bordered forKey:CPColorWellBorderedKey];
}
+61 -38
View File
@@ -23,6 +23,7 @@
@import "CPEvent.j"
@import "CPPlatform.j"
// Browser Engines
CPUnknownBrowserEngine = 0;
CPGeckoBrowserEngine = 1;
@@ -31,6 +32,11 @@ CPKHTMLBrowserEngine = 3;
CPOperaBrowserEngine = 4;
CPWebKitBrowserEngine = 5;
// Operating Systems
CPMacOperatingSystem = 0;
CPWindowsOperatingSystem = 1;
CPOtherOperatingSystem = 2;
// Features
CPCSSRGBAFeature = 1 << 5;
@@ -38,20 +44,20 @@ CPHTMLCanvasFeature = 1 << 6;
CPHTMLContentEditableFeature = 1 << 7;
CPHTMLDragAndDropFeature = 1 << 8;
CPJavascriptInnerTextFeature = 1 << 9;
CPJavascriptTextContentFeature = 1 << 10;
CPJavascriptClipboardEventsFeature = 1 << 11;
CPJavascriptClipboardAccessFeature = 1 << 12;
CPJavaScriptInnerTextFeature = 1 << 9;
CPJavaScriptTextContentFeature = 1 << 10;
CPJavaScriptClipboardEventsFeature = 1 << 11;
CPJavaScriptClipboardAccessFeature = 1 << 12;
CPJavaScriptCanvasDrawFeature = 1 << 13;
CPJavaScriptCanvasTransformFeature = 1 << 14;
CPVMLFeature = 1 << 15;
CPJavascriptRemedialKeySupport = 1 << 16;
CPJavaScriptRemedialKeySupport = 1 << 16;
CPJavaScriptShadowFeature = 1 << 20;
CPJavaScriptNegativeMouseWheelValues = 1 << 22;
CPJavaScriptMouseWheelValues_8_15 = 1 << 23
CPJavaScriptMouseWheelValues_8_15 = 1 << 23;
CPOpacityRequiresFilterFeature = 1 << 24;
@@ -59,8 +65,7 @@ CPOpacityRequiresFilterFeature = 1 << 24;
CPInputTypeCanBeChangedFeature = 1 << 25;
CPHTML5DragAndDropSourceYOffBy1 = 1 << 26;
CPSOPDisabledFromFileURLs = 1 << 27;
var USER_AGENT = "",
PLATFORM_ENGINE = CPUnknownBrowserEngine,
@@ -70,27 +75,27 @@ var USER_AGENT = "",
PLATFORM_FEATURES |= CPInputTypeCanBeChangedFeature;
if (typeof window != "undfined" && typeof window.navigator != "undefined")
if (typeof window !== "undefined" && typeof window.navigator !== "undefined")
USER_AGENT = window.navigator.userAgent;
// Opera
if (window.opera)
if (typeof window !== "undefined" && window.opera)
{
PLATFORM_ENGINE = CPOperaBrowserEngine;
PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature;
}
// Internet Explorer
else if (window.attachEvent) // Must follow Opera check.
else if (typeof window !== "undefined" && window.attachEvent) // Must follow Opera check.
{
PLATFORM_ENGINE = CPInternetExplorerBrowserEngine;
// Features we can only be sure of with IE (no known independent tests)
PLATFORM_FEATURES |= CPVMLFeature;
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
PLATFORM_FEATURES |= CPJavaScriptRemedialKeySupport;
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
PLATFORM_FEATURES |= CPOpacityRequiresFilterFeature;
PLATFORM_FEATURES &= ~CPInputTypeCanBeChangedFeature;
@@ -100,15 +105,18 @@ else if (window.attachEvent) // Must follow Opera check.
else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
{
PLATFORM_ENGINE = CPWebKitBrowserEngine;
// Features we can only be sure of with WebKit (no known independent tests)
PLATFORM_FEATURES |= CPCSSRGBAFeature;
PLATFORM_FEATURES |= CPHTMLContentEditableFeature;
PLATFORM_FEATURES |= CPHTMLDragAndDropFeature;
PLATFORM_FEATURES |= CPJavascriptClipboardEventsFeature;
PLATFORM_FEATURES |= CPJavascriptClipboardAccessFeature;
if (USER_AGENT.indexOf("Chrome") === -1)
PLATFORM_FEATURES |= CPHTMLDragAndDropFeature;
PLATFORM_FEATURES |= CPJavaScriptClipboardEventsFeature;
PLATFORM_FEATURES |= CPJavaScriptClipboardAccessFeature;
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
var versionStart = USER_AGENT.indexOf("AppleWebKit/") + "AppleWebKit/".length,
versionEnd = USER_AGENT.indexOf(" ", versionStart),
versionString = USER_AGENT.substring(versionStart, versionEnd),
@@ -116,16 +124,19 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
majorVersion = parseInt(versionString.substring(0, versionDivision)),
minorVersion = parseInt(versionString.substr(versionDivision + 1));
if((USER_AGENT.indexOf("Safari") !== CPNotFound && (majorVersion > 525 || (majorVersion === 525 && minorVersion > 14))) || USER_AGENT.indexOf("Chrome") !== CPNotFound)
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
if ((USER_AGENT.indexOf("Safari") !== CPNotFound && (majorVersion > 525 || (majorVersion === 525 && minorVersion > 14))) || USER_AGENT.indexOf("Chrome") !== CPNotFound)
PLATFORM_FEATURES |= CPJavaScriptRemedialKeySupport;
// FIXME this is a terrible hack to get around this bug:
// https://bugs.webkit.org/show_bug.cgi?id=21548
if (![CPPlatform isBrowser])
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
PLATFORM_FEATURES |= CPJavaScriptRemedialKeySupport;
if (majorVersion < 532 || (majorVersion === 532 && minorVersion < 6))
PLATFORM_FEATURES |= CPHTML5DragAndDropSourceYOffBy1;
if (USER_AGENT.indexOf("Chrome") === CPNotFound)
PLATFORM_FEATURES |= CPSOPDisabledFromFileURLs;
}
// KHTML
@@ -138,12 +149,12 @@ else if (USER_AGENT.indexOf("KHTML") != -1) // Must follow WebKit check.
else if (USER_AGENT.indexOf("Gecko") !== -1) // Must follow KHTML check.
{
PLATFORM_ENGINE = CPGeckoBrowserEngine;
PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature;
var index = USER_AGENT.indexOf("Firefox"),
version = (index === -1) ? 2.0 : parseFloat(USER_AGENT.substring(index + "Firefox".length + 1));
if (version >= 3.0)
PLATFORM_FEATURES |= CPCSSRGBAFeature;
@@ -159,21 +170,21 @@ if (typeof document != "undefined")
if (canvasElement && canvasElement.getContext)
{
PLATFORM_FEATURES |= CPHTMLCanvasFeature;
// Detect Canvas setTransform/transform support
var context = document.createElement("canvas").getContext("2d");
if (context && context.setTransform && context.transform)
PLATFORM_FEATURES |= CPJavaScriptCanvasTransformFeature;
}
var DOMElement = document.createElement("div");
// Detect whether we have innerText or textContent (or neither)
if (DOMElement.innerText != undefined)
PLATFORM_FEATURES |= CPJavascriptInnerTextFeature;
PLATFORM_FEATURES |= CPJavaScriptInnerTextFeature;
else if (DOMElement.textContent != undefined)
PLATFORM_FEATURES |= CPJavascriptTextContentFeature;
PLATFORM_FEATURES |= CPJavaScriptTextContentFeature;
}
function CPFeatureIsCompatible(aFeature)
@@ -183,25 +194,37 @@ function CPFeatureIsCompatible(aFeature)
function CPBrowserIsEngine(anEngine)
{
return PLATFORM_ENGINE == anEngine;
return PLATFORM_ENGINE === anEngine;
}
if (USER_AGENT.indexOf("Mac") != -1)
function CPBrowserIsOperatingSystem(anOperatingSystem)
{
return OPERATING_SYSTEM === anOperatingSystem;
}
OPERATING_SYSTEM = CPOtherOperatingSystem;
if (USER_AGENT.indexOf("Mac") !== -1)
{
OPERATING_SYSTEM = CPMacOperatingSystem;
CPPlatformActionKeyMask = CPCommandKeyMask;
CPUndoKeyEquivalent = @"Z";
CPUndoKeyEquivalent = @"z";
CPRedoKeyEquivalent = @"Z";
CPUndoKeyEquivalentModifierMask = CPCommandKeyMask;
CPRedoKeyEquivalentModifierMask = CPCommandKeyMask | CPShiftKeyMask;
CPRedoKeyEquivalentModifierMask = CPCommandKeyMask;
}
else
{
if (USER_AGENT.indexOf("Windows") !== -1)
OPERATING_SYSTEM = CPWindowsOperatingSystem;
CPPlatformActionKeyMask = CPControlKeyMask;
CPUndoKeyEquivalent = @"Z";
CPRedoKeyEquivalent = @"Y";
CPUndoKeyEquivalent = @"z";
CPRedoKeyEquivalent = @"y";
CPUndoKeyEquivalentModifierMask = CPControlKeyMask;
CPRedoKeyEquivalentModifierMask = CPControlKeyMask;
+416 -148
View File
@@ -23,51 +23,44 @@
@import "CPFont.j"
@import "CPShadow.j"
@import "CPView.j"
@import "CPKeyValueBinding.j"
#include "CoreGraphics/CGGeometry.h"
#include "Platform/Platform.h"
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
CPCenterTextAlignment = 2;
CPJustifiedTextAlignment = 3;
CPNaturalTextAlignment = 4;
/*
@global
@group CPTextAlignment
*/
CPLeftTextAlignment = 0;
/*
@global
@group CPTextAlignment
*/
CPRightTextAlignment = 1;
/*
@global
@group CPTextAlignment
*/
CPCenterTextAlignment = 2;
/*
@global
@group CPTextAlignment
*/
CPJustifiedTextAlignment = 3;
/*
@global
@group CPTextAlignment
*/
CPNaturalTextAlignment = 4;
CPRegularControlSize = 0;
CPSmallControlSize = 1;
CPMiniControlSize = 2;
/*
@global
@group CPControlSize
*/
CPRegularControlSize = 0;
/*
@global
@group CPControlSize
*/
CPSmallControlSize = 1;
/*
@global
@group CPControlSize
*/
CPMiniControlSize = 2;
CPLineBreakByWordWrapping = 0;
CPLineBreakByCharWrapping = 1;
CPLineBreakByClipping = 2;
CPLineBreakByTruncatingHead = 3;
CPLineBreakByTruncatingTail = 4;
CPLineBreakByTruncatingMiddle = 5;
CPTopVerticalTextAlignment = 1;
CPCenterVerticalTextAlignment = 2;
CPBottomVerticalTextAlignment = 3;
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
CPImageRight = 3;
CPImageBelow = 4;
CPImageAbove = 5;
CPImageOverlaps = 6;
CPOnState = 1;
CPOffState = 0;
CPMixedState = -1;
CPControlNormalBackgroundColor = "CPControlNormalBackgroundColor";
CPControlSelectedBackgroundColor = "CPControlSelectedBackgroundColor";
@@ -78,9 +71,9 @@ CPControlTextDidBeginEditingNotification = "CPControlTextDidBeginEditingNotif
CPControlTextDidChangeNotification = "CPControlTextDidChangeNotification";
CPControlTextDidEndEditingNotification = "CPControlTextDidEndEditingNotification";
var CPControlBlackColor = [CPColor blackColor];
var CPControlBlackColor = [CPColor blackColor];
/*!
/*!
@ingroup appkit
@class CPControl
@@ -89,7 +82,7 @@ var CPControlBlackColor = [CPColor blackColor];
@implementation CPControl : CPView
{
id _value;
// Target-Action Support
id _target;
SEL _action;
@@ -101,8 +94,6 @@ var CPControlBlackColor = [CPColor blackColor];
BOOL _trackingWasWithinFrame;
unsigned _trackingMouseDownFlags;
CGPoint _previousTrackingLocation;
CPString _toolTip;
}
+ (CPDictionary)themeAttributes
@@ -112,7 +103,7 @@ var CPControlBlackColor = [CPColor blackColor];
CPLineBreakByClipping,
[CPColor blackColor],
[CPFont systemFontOfSize:12.0],
nil,
[CPNull null],
_CGSizeMakeZero(),
CPImageLeft,
CPScaleToFit,
@@ -131,21 +122,66 @@ var CPControlBlackColor = [CPColor blackColor];
@"max-size"]];
}
+ (void)initialize
{
if (self === [CPControl class])
{
[self exposeBinding:@"value"];
[self exposeBinding:@"objectValue"];
[self exposeBinding:@"stringValue"];
[self exposeBinding:@"integerValue"];
[self exposeBinding:@"intValue"];
[self exposeBinding:@"doubleValue"];
[self exposeBinding:@"floatValue"];
[self exposeBinding:@"enabled"];
}
}
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding === CPValueBinding)
return [_CPValueBinder class];
return [super _binderClassForBinding:theBinding];
}
/*!
Reverse set the binding iff the CPContinuouslyUpdatesValueBindingOption is set.
*/
- (void)_continuouslyReverseSetBinding
{
var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
theBinding = [binderClass getBinding:CPValueBinding forObject:self];
if ([theBinding continuouslyUpdatesValue])
[theBinding reverseSetValueFor:@"objectValue"];
}
- (void)_reverseSetBinding
{
var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
theBinding = [binderClass getBinding:CPValueBinding forObject:self];
[theBinding reverseSetValueFor:@"objectValue"];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_sendActionOn = CPLeftMouseUpMask;
_trackingMouseDownFlags = 0;
}
return self;
}
/*!
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
@@ -154,7 +190,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's target action
Returns the receiver's target action.
*/
- (SEL)action
{
@@ -163,6 +199,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
@@ -180,50 +217,25 @@ 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
*/
- (void)sendAction:(SEL)anAction to:(id)anObject
{
[self _reverseSetBinding];
[CPApp sendAction:anAction to:anObject from:self];
}
- (int)sendActionOn:(int)mask
{
var previousMask = _sendActionOn;
_sendActionOn = mask;
return previousMask;
}
/*!
Sets the tooltip for the receiver.
@param aToolTip the tooltip
*/
/*
-(void)setToolTip:(CPString)aToolTip
{
if (_toolTip == aToolTip)
return;
_toolTip = aToolTip;
#if PLATFORM(DOM)
_DOMElement.title = aToolTip;
#endif
}
*/
/*!
Returns the receiver's tooltip
*/
/*
-(CPString)toolTip
{
return _toolTip;
}
*/
/*!
Returns whether the control can continuously send its action messages.
*/
@@ -235,16 +247,19 @@ 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
if (flag)
_sendActionOn |= CPPeriodicMask;
else
else
_sendActionOn &= ~CPPeriodicMask;
}
/*!
Returns YES if the receiver tracks the mouse outside the frame, otherwise NO.
*/
- (BOOL)tracksMouseOutsideOfFrame
{
return NO;
@@ -253,18 +268,22 @@ var CPControlBlackColor = [CPColor blackColor];
- (void)trackMouse:(CPEvent)anEvent
{
var type = [anEvent type],
currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil];
currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
isWithinFrame = [self tracksMouseOutsideOfFrame] || CGRectContainsPoint([self bounds], currentLocation);
if (type === CPLeftMouseUp)
{
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:YES];
_trackingMouseDownFlags = 0;
if (isWithinFrame)
[self setThemeState:CPThemeStateHovered];
}
else
{
[self unsetThemeState:CPThemeStateHovered];
if (type === CPLeftMouseDown)
{
_trackingMouseDownFlags = [anEvent modifierFlags];
@@ -276,20 +295,20 @@ var CPControlBlackColor = [CPColor blackColor];
{
if (!_trackingWasWithinFrame)
_continuousTracking = [self startTrackingAt:currentLocation];
else if (_continuousTracking)
_continuousTracking = [self continueTracking:_previousTrackingLocation at:currentLocation];
}
else
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:NO];
}
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
if ((_sendActionOn & (1 << type)) && isWithinFrame)
[self sendAction:_action to:_target];
_trackingWasWithinFrame = isWithinFrame;
_previousTrackingLocation = currentLocation;
}
@@ -303,14 +322,45 @@ var CPControlBlackColor = [CPColor blackColor];
return 0;
}
- (void)performClick:(id)sender
/*!
Perform a click on the receiver.
@param sender - The sender object
*/
- (void)performClick:(id)sender
{
if (![self isEnabled])
return;
[self highlight:YES];
[self setState:[self nextState]];
[self sendAction:[self action] to:[self target]];
try
{
[self sendAction:[self action] to:[self target]];
}
catch (e)
{
throw e;
}
finally
{
[CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unhighlightButtonTimerDidFinish:) userInfo:nil repeats:NO];
}
}
/*!
@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;
@@ -319,7 +369,7 @@ var CPControlBlackColor = [CPColor blackColor];
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
[self highlight:YES];
return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
}
@@ -337,12 +387,31 @@ var CPControlBlackColor = [CPColor blackColor];
{
if (![self isEnabled])
return;
[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
{
@@ -350,18 +419,18 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's object value
Sets the receiver's object value.
*/
- (void)setObjectValue:(id)anObject
{
_value = anObject;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
/*!
Returns the receiver's float value
Returns the receiver's float value.
*/
- (float)floatValue
{
@@ -370,7 +439,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Sets the receiver's float value
Sets the receiver's float value.
*/
- (void)setFloatValue:(float)aValue
{
@@ -378,7 +447,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's double value
Returns the receiver's double value.
*/
- (double)doubleValue
{
@@ -387,7 +456,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's double value
Sets the receiver's double value.
*/
- (void)setDoubleValue:(double)anObject
{
@@ -395,7 +464,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's int value
Returns the receiver's int value.
*/
- (int)intValue
{
@@ -404,7 +473,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's int value
Sets the receiver's int value.
*/
- (void)setIntValue:(int)anObject
{
@@ -412,7 +481,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's int value
Returns the receiver's int value.
*/
- (int)integerValue
{
@@ -421,7 +490,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's int value
Sets the receiver's int value.
*/
- (void)setIntegerValue:(int)anObject
{
@@ -429,7 +498,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's int value
Returns the receiver's string value.
*/
- (CPString)stringValue
{
@@ -437,7 +506,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's int value
Sets the receiver's string value.
*/
- (void)setStringValue:(CPString)anObject
{
@@ -484,55 +553,228 @@ var CPControlBlackColor = [CPColor blackColor];
[self setStringValue:[sender stringValue]];
}
- (void)textDidBeginEditing:(CPNotification)note
- (void)textDidBeginEditing:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if([note object] != self)
if ([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
}
- (void)textDidChange:(CPNotification)note
- (void)textDidChange:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if([note object] != self)
if ([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
}
- (void)textDidEndEditing:(CPNotification)note
- (void)textDidEndEditing:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if([note object] != self)
if ([note object] != self)
return;
[self _reverseSetBinding];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
}
#define BRIDGE(UPPERCASE, LOWERCASE, ATTRIBUTENAME) \
/*! Sets the value for ATTRIBUTENAME */\
- (void)set##UPPERCASE:(id)aValue\
{\
[self setValue:aValue forThemeAttribute:ATTRIBUTENAME];\
}\
/*! Returns the current value for ATTRIBUTENAME */\
- (id)LOWERCASE\
{\
return [self valueForThemeAttribute:ATTRIBUTENAME];\
/*!
Sets the text alignment of the control.
<pre>
CPLeftTextAlignment
CPCenterTextAlignment
CPRightTextAlignment
CPJustifiedTextAlignment
CPNaturalTextAlignment
</pre>
*/
- (void)setAlignment:(CPTextAlignment)alignment
{
[self setValue:alignment forThemeAttribute:@"alignment"];
}
BRIDGE(Alignment, alignment, "alignment")
BRIDGE(VerticalAlignment, verticalAlignment, "vertical-alignment")
BRIDGE(LineBreakMode, lineBreakMode, "line-break-mode")
BRIDGE(TextColor, textColor, "text-color")
BRIDGE(Font, font, "font")
BRIDGE(TextShadowColor, textShadowColor, "text-shadow-color")
BRIDGE(TextShadowOffset, textShadowOffset, "text-shadow-offset")
BRIDGE(ImagePosition, imagePosition, "image-position")
BRIDGE(ImageScaling, imageScaling, "image-scaling")
/*!
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"];
}
/*!
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"];
}
/*!
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)
@@ -541,16 +783,29 @@ BRIDGE(ImageScaling, imageScaling, "image-scaling")
[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)
@@ -559,6 +814,9 @@ BRIDGE(ImageScaling, imageScaling, "image-scaling")
[self unsetThemeState:CPThemeStateHighlighted];
}
/*!
Returns YES if the control is highlighted, otherwise NO.
*/
- (BOOL)isHighlighted
{
return [self hasThemeState:CPThemeStateHighlighted];
@@ -569,10 +827,12 @@ BRIDGE(ImageScaling, imageScaling, "image-scaling")
var CPControlValueKey = "CPControlValueKey",
CPControlControlStateKey = @"CPControlControlStateKey",
CPControlIsEnabledKey = "CPControlIsEnabledKey",
CPControlTargetKey = "CPControlTargetKey",
CPControlActionKey = "CPControlActionKey",
CPControlSendActionOnKey = "CPControlSendActionOnKey";
CPControlSendActionOnKey = "CPControlSendActionOnKey",
CPControlSendsActionOnEndEditingKey = "CPControlSendsActionOnEndEditingKey";
var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
@@ -580,6 +840,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
*/
@@ -595,21 +856,28 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
[self setAction:[aCoder decodeObjectForKey:CPControlActionKey]];
[self sendActionOn:[aCoder decodeIntForKey:CPControlSendActionOnKey]];
[self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
}
return self;
}
/*
Archives the control to the provided coder.
@param aCoder the coder to which the control will be archived.
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
if (_value !== nil)
[aCoder encodeObject:_value forKey:CPControlValueKey];
if (_sendsActionOnEndEditing)
[aCoder encodeBool:_sendsActionOnEndEditing forKey:CPControlSendsActionOnEndEditingKey];
var objectValue = [self objectValue];
if (objectValue !== nil)
[aCoder encodeObject:objectValue forKey:CPControlValueKey];
if (_target !== nil)
[aCoder encodeConditionalObject:_target forKey:CPControlTargetKey];
@@ -629,7 +897,7 @@ var _CPControlSizeIdentifiers = [],
_CPControlSizeIdentifiers[CPRegularControlSize] = "Regular";
_CPControlSizeIdentifiers[CPSmallControlSize] = "Small";
_CPControlSizeIdentifiers[CPMiniControlSize] = "Mini";
function _CPControlIdentifierForControlSize(aControlSize)
{
return _CPControlSizeIdentifiers[aControlSize];
@@ -640,21 +908,21 @@ function _CPControlColorWithPatternImage(sizes, aClassName)
var index = 1,
count = arguments.length,
identifier = "";
for (; index < count; ++index)
identifier += arguments[index];
var color = _CPControlCachedColorWithPatternImages[identifier];
if (!color)
{
var bundle = [CPBundle bundleForClass:[CPControl class]];
color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:aClassName + "/" + identifier + ".png"] size:sizes[identifier]]];
_CPControlCachedColorWithPatternImages[identifier] = color;
}
return color;
}
@@ -663,17 +931,17 @@ function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
var index = 2,
count = arguments.length,
identifier = "";
for (; index < count; ++index)
identifier += arguments[index];
var color = _CPControlCachedThreePartImagePattern[identifier];
if (!color)
{
var bundle = [CPBundle bundleForClass:[CPControl class]],
path = aClassName + "/" + identifier;
sizes = sizes[identifier];
color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:[
@@ -681,9 +949,9 @@ function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "1.png"] size:sizes[1]],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "2.png"] size:sizes[2]]
] isVertical:isVertical]];
_CPControlCachedThreePartImagePattern[identifier] = color;
}
return color;
}
+88
View File
@@ -0,0 +1,88 @@
//
// CPController.j
// AppKit
//
// Created by Ross Boucher 1/15/09
// Copyright 280 North
//
// Adapted from GNUStep
// Copyright (C) 2007 Free Software Foundation, Inc
// Released under the LGPL.
//
@import <Foundation/CPObject.j>
var CPControllerDeclaredKeysKey = @"CPControllerDeclaredKeysKey";
@implementation CPController : CPObject
{
CPArray _editors;
CPArray _declaredKeys;
}
- (id)init
{
self = [super init];
if (self)
{
_editors = [];
_declaredKeys = [];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
if ([_declaredKeys count] > 0)
[aCoder encodeObject:_declaredKeys forKey:CPControllerDeclaredKeysKey];
}
- (id)initWithCoder:(CPCoder)aDecoder
{
self = [super init];
if (self)
{
_editors = [];
_declaredKeys = [aDecoder decodeObjectForKey:CPControllerDeclaredKeysKey] || [];
}
return self;
}
- (BOOL)isEditing
{
return [_editors count] > 0;
}
- (BOOL)commitEditing
{
var index = 0,
count = _editors.length;
for (; index < count; ++index)
if (![[_editors objectAtIndex:i] commitEditing])
return NO;
return YES;
}
- (void)discardEditing
{
[_editors makeObjectsPerformSelector:@selector(discardEditing)];
}
- (void)objectDidBeginEditing:(id)anEditor
{
[_editors addObject:anEditor];
}
- (void)objectDidEndEditing:(id)anEditor
{
[_editors removeObject:anEditor];
}
@end
+29 -20
View File
@@ -24,7 +24,7 @@
@import <Foundation/CPString.j>
/*!
/*!
@ingroup appkit
@class CPCookie
CPCookie is the Cappuccino interface to a web browser cookie. You can set the name
@@ -33,7 +33,7 @@
{
CPString _cookieName;
CPString _cookieValue;
CPString _expires;
}
@@ -44,7 +44,7 @@
- (id)initWithName:(CPString)aName
{
self = [super init];
_cookieName = aName;
_cookieValue = [self _readCookieValue];
@@ -83,30 +83,39 @@
*/
- (void)setValue:(CPString)value expires:(CPDate)date domain:(CPString)domain
{
if(date)
var expires = "; expires="+date.toGMTString();
else
if (date)
var expires = "; expires=" + date.toGMTString();
else
var expires = "";
if(domain)
domain = "; domain="+domain;
else
if (domain)
domain = "; domain=" + domain;
else
domain = "";
document.cookie = _cookieName+"="+value+expires+"; path=/"+domain;
#if PLATFORM(DOM)
document.cookie = _cookieName+"="+value+expires+"; path=/"+domain;
#else
_cookieValue = value;
_expires = expires;
#endif
}
/* @ignore */
- (CPString)_readCookieValue
{
var nameEQ = _cookieName + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return "";
#if PLATFORM(DOM)
var nameEQ = _cookieName + "=",
ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++)
{
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
#endif
return "";
}
@end
+248
View File
@@ -0,0 +1,248 @@
/*
Cursor support by browser:
OS X 10.6/Chrome 8 : All
OS X 10.6/Safari 5 : All
OS X 10.6/Firefox 3 : All except disappearingItemCursor (no url() support)
OS X 10.6/Firefox 3.5 : All except disappearingItemCursor (no url() support)
OS X 10.6/Firefox 3.6 : All except disappearingItemCursor, contextualMenuCursor, dragLinkCursor, dragCopyCursor, operationNotAllowedCursor (no url() support)
OS X 10.6/Firefox 4.0b10 : All
OS X/Opera 9 : All except disappearingItemCursor, closedHandCursor, openHandCursor, contextualMenuCursor, dragLinkCursor, dragCopyCursor, operationNotAllowedCursor, resizeUpDownCursor, resizeLeftRightCursor (no url() support)
OS X/Opera 10 : All except disappearingItemCursor, closedHandCursor, contextualMenuCursor, dragLinkCursor, dragCopyCursor, operationNotAllowedCursor (no url() support)
OS X/Opera 11 : All except disappearingItemCursor, closedHandCursor, contextualMenuCursor, dragLinkCursor, dragCopyCursor, operationNotAllowedCursor (no url() support)
Win XP/Chrome 8 : All
Win XP/Safari 5 : All
Win XP/Firefox 3 : All
Win XP/Firefox 3.5 : All
Win XP/Firefox 3.6 : All
Win XP/Firefox 4.0b10 : All
Win XP/Opera 10 : All except disappearingItemCursor, closedHandCursor, openHandCursor, contextualMenuCursor, dragLinkCursor, dragCopyCursor, operationNotAllowedCursor, resizeUpDownCursor, resizeLeftRightCursor (no url() support)
Win XP/Opera 11 : All except disappearingItemCursor, closedHandCursor, openHandCursor, contextualMenuCursor, dragLinkCursor, dragCopyCursor, operationNotAllowedCursor, resizeUpDownCursor, resizeLeftRightCursor (no url() support)
Win XP/IE 7 : All
Win XP/IE 8 : All
*/
@import <Foundation/CPObject.j>
var currentCursor = nil,
cursorStack = [],
cursors = {};
@implementation CPCursor : CPObject
{
CPString _cssString @accessors(readonly);
CPString _hotSpot @accessors(readonly, getter=hotSpot);
CPImage _image @accessors(readonly, getter=image);
BOOL _isSetOnMouseEntered @accessors(readwrite, getter=isSetOnMouseEntered, setter=setOnMouseEntered:);
BOOL _isSetOnMouseExited @accessors(readwrite, getter=isSetOnMouseExited, setter=setOnMouseExited:);
}
- (id)initWithCSSString:(CPString)aString
{
if (self = [super init])
_cssString = aString;
return self;
}
// hotspot is supported in CSS3 (but not IE).
- (id)initWithImage:(CPImage)image hotSpot:(CPPoint)hotSpot
{
_hotSpot = hotSpot;
_image = image;
return [self initWithCSSString:"url(" + [_image filename] + ")" + hotSpot.x + " " + hotSpot.y + ", auto"];
}
// foregroundColor and backgroundColor are ignored in Cocoa as well. See http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSCursor_Class/Reference/Reference.html
- (id)initWithImage:(CPImage)image foregroundColorHint:(CPColor)foregroundColor backgroundColorHint:(CPColor)backgroundColor hotSpot:(CPPoint)aHotSpot
{
return [self initWithImage:image hotSpot:hotSpot];
}
+ (void)hide
{
[self _setCursorCSS:"none"]; // Not supported in IE
}
+ (void)unhide
{
[self _setCursorCSS:[currentCursor _cssString]];
}
+ (void)setHiddenUntilMouseMoves:(BOOL)flag
{
if (flag)
[CPCursor hide];
else
[CPCursor unhide];
}
- (void)pop
{
[CPCursor pop];
}
+ (void)pop
{
if (cursorStack.length > 1)
{
cursorStack.pop();
currentCursor = cursorStack[cursorStack.length - 1];
}
}
- (void)push
{
currentCursor = cursorStack.push(self);
}
- (void)set
{
currentCursor = self;
#if PLATFORM(DOM)
[[self class] _setCursorCSS:_cssString];
#endif
}
- (void)mouseEntered:(CPEvent)event
{
}
- (void)mouseExited:(CPEvent)event
{
}
+ (CPCursor)currentCursor
{
return currentCursor;
}
+ (void)_setCursorCSS:(CPString)aString
{
#if PLATFORM(DOM)
var platformWindows = [[CPPlatformWindow visiblePlatformWindows] allObjects];
for (var i = 0, count = [platformWindows count]; i < count; i++)
platformWindows[i]._DOMBodyElement.style.cursor = aString;
#endif
}
// Internal method that is used to return the system cursors. Caches the system cursors for performance.
+ (CPCursor)_systemCursorWithName:(CPString)cursorName cssString:(CPString)aString hasImage:(BOOL)doesHaveImage
{
var cursor = cursors[cursorName];
if (typeof cursor === 'undefined')
{
var cssString;
if (doesHaveImage)
cssString = @"url(" + [[CPBundle bundleForClass:self] resourcePath] + @"/CPCursor/" + cursorName + ".cur), " + aString;
else
cssString = aString
cursor = [[CPCursor alloc] initWithCSSString:cssString];
cursors[cursorName] = cursor;
}
return cursor;
}
+ (CPCursor)arrowCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:"default" hasImage:NO];
}
+ (CPCursor)crosshairCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"crosshair" hasImage:NO];
}
+ (CPCursor)IBeamCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"text" hasImage:NO];
}
+ (CPCursor)pointingHandCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"pointer" hasImage:NO];
}
+ (CPCursor)resizeDownCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"s-resize" hasImage:NO];
}
+ (CPCursor)resizeUpCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"n-resize" hasImage:NO];
}
+ (CPCursor)resizeLeftCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"w-resize" hasImage:NO];
}
+ (CPCursor)resizeRightCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"e-resize" hasImage:NO];
}
+ (CPCursor)resizeLeftRightCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"col-resize" hasImage:NO];
}
+ (CPCursor)resizeUpDownCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"row-resize" hasImage:NO];
}
+ (CPCursor)operationNotAllowedCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"not-allowed" hasImage:NO];
}
+ (CPCursor)dragCopyCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"copy" hasImage:YES];
}
+ (CPCursor)dragLinkCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"alias" hasImage:YES];
}
+ (CPCursor)contextualMenuCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"context-menu" hasImage:YES];
}
+ (CPCursor)openHandCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"move" hasImage:YES];
}
+ (CPCursor)closedHandCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"-moz-grabbing" hasImage:YES];
}
+ (CPCursor)disappearingItemCursor
{
return [CPCursor _systemCursorWithName:CPStringFromSelector(_cmd) cssString:@"auto" hasImage:YES];
}
@end
@implementation CPCursor(CPCoding)
- (id)initWithCoder:(CPCoder)coder
{
if (self = [super init])
_cssString = [coder decodeObjectForKey:@"CPCursorNameKey"];
return self;
}
- (void)encodeWithCoder:(CPCoder)coder
{
[coder encodeObject:_cssString forKey:@"CPCursorNameKey"];
}
@end
+62 -58
View File
@@ -23,6 +23,7 @@
@import <Foundation/CPString.j>
@import <Foundation/CPArray.j>
@import "CPApplication.j"
@import "CPResponder.j"
@import "CPSavePanel.j"
@import "CPViewController.j"
@@ -82,12 +83,12 @@ CPDocumentDidFailToSaveNotification = @"CPDocumentDidFailToSaveNotification";
var CPDocumentUntitledCount = 0;
/*!
/*!
@ingroup appkit
@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.
*/
@@ -120,7 +121,7 @@ var CPDocumentUntitledCount = 0;
- (id)init
{
self = [super init];
if (self)
{
_windowControllers = [];
@@ -131,7 +132,7 @@ var CPDocumentUntitledCount = 0;
[self setNextResponder:CPApp];
}
return self;
}
@@ -144,10 +145,10 @@ var CPDocumentUntitledCount = 0;
- (id)initWithType:(CPString)aType error:({CPError})anError
{
self = [self init];
if (self)
[self setFileType:aType];
return self;
}
@@ -165,7 +166,7 @@ var CPDocumentUntitledCount = 0;
- (id)initWithContentsOfURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo
{
self = [self init];
if (self)
{
[self setFileURL:anAbsoluteURL];
@@ -173,7 +174,7 @@ var CPDocumentUntitledCount = 0;
[self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
}
return self;
}
@@ -190,7 +191,7 @@ var CPDocumentUntitledCount = 0;
- (id)initForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo
{
self = [self init];
if (self)
{
[self setFileURL:anAbsoluteURL];
@@ -198,7 +199,7 @@ var CPDocumentUntitledCount = 0;
[self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
}
return self;
}
@@ -207,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
@@ -280,7 +281,11 @@ var CPDocumentUntitledCount = 0;
else if (viewController)
{
var view = [viewController view],
theWindow = [[CPWindow alloc] initWithContentRect:[view frame] styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
viewFrame = [view frame];
viewFrame.origin = CGPointMake(50, 50);
var theWindow = [[CPWindow alloc] initWithContentRect:viewFrame styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
windowController = [[CPWindowController alloc] initWithWindow:theWindow];
}
@@ -377,14 +382,14 @@ var CPDocumentUntitledCount = 0;
{
if (_fileURL)
return [_fileURL lastPathComponent];
if (!_untitledDocumentIndex)
_untitledDocumentIndex = ++CPDocumentUntitledCount;
if (_untitledDocumentIndex == 1)
return @"Untitled";
return @"Untitled " + _untitledDocumentIndex;
if (_untitledDocumentIndex == 1)
return @"Untitled";
return @"Untitled " + _untitledDocumentIndex;
}
- (CPString)viewCibName
@@ -453,7 +458,7 @@ var CPDocumentUntitledCount = 0;
return;
_fileURL = aFileURL;
[_windowControllers makeObjectsPerformSelector:@selector(synchronizeWindowTitleWithDocumentName)];
}
@@ -480,14 +485,14 @@ var CPDocumentUntitledCount = 0;
else
[_writeRequest setHTTPMethod:@"PUT"];
[_writeRequest setHTTPBody:[data string]];
[_writeRequest setHTTPBody:[data rawString]];
[_writeRequest setValue:@"close" forHTTPHeaderField:@"Connection"];
if (aSaveOperation == CPSaveOperation)
if (aSaveOperation === CPSaveOperation)
[_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
if (aSaveOperation != CPSaveToOperation)
if (aSaveOperation !== CPSaveToOperation)
[self updateChangeCount:CPChangeCleared];
// FIXME: Oh man is this every looking for trouble, we need to handle login at the Cappuccino level, with HTTP Errors.
@@ -505,21 +510,21 @@ var CPDocumentUntitledCount = 0;
// If we got this far and it wasn't an HTTP request, then everything is fine.
if (![aResponse isKindOfClass:[CPHTTPURLResponse class]])
return;
var statusCode = [aResponse statusCode];
// Nothing to do if everything is hunky dory.
if (statusCode === 200)
return;
var session = aConnection.session;
if (aConnection == _readConnection)
{
[aConnection cancel];
alert("There was an error retrieving the document.");
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
}
else
@@ -528,23 +533,23 @@ var CPDocumentUntitledCount = 0;
if (statusCode == 409)
{
[aConnection cancel];
if (confirm("There already exists a file with that name, would you like to overwrite it?"))
{
[_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
[aConnection start];
}
else
else
{
if (session.saveOperation != CPSaveToOperation)
{
_changeCount += session.changeCount;
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
}
_writeRequest = nil;
objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo);
[self _sendDocumentSavedNotification:NO];
}
@@ -559,11 +564,11 @@ var CPDocumentUntitledCount = 0;
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)aData
{
var session = aConnection.session;
// READ
if (aConnection == _readConnection)
{
[self readFromData:[CPData dataWithString:aData] ofType:session.fileType error:nil];
[self readFromData:[CPData dataWithRawString:aData] ofType:session.fileType error:nil];
objj_msgSend(session.delegate, session.didReadSelector, self, YES, session.contextInfo);
}
@@ -571,9 +576,9 @@ var CPDocumentUntitledCount = 0;
{
if (session.saveOperation != CPSaveToOperation)
[self setFileURL:session.absoluteURL];
_writeRequest = nil;
objj_msgSend(session.delegate, session.didSaveSelector, self, YES, session.contextInfo);
[self _sendDocumentSavedNotification:YES];
}
@@ -586,17 +591,17 @@ var CPDocumentUntitledCount = 0;
- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
{
var session = aConnection.session;
if (_readConnection == aConnection)
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
else
{
{
if (session.saveOperation != CPSaveToOperation)
{
_changeCount += session.changeCount;
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
}
}
_writeRequest = nil;
@@ -639,9 +644,9 @@ var CPDocumentUntitledCount = 0;
else if (aChangeType == CPChangeCleared)
_changeCount = 0;
/*else if (aChangeType == CPCHangeReadOtherContents)
else if (aChangeType == CPChangeAutosaved)*/
else if (aChangeType == CPChangeAutosaved)*/
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
}
@@ -681,9 +686,9 @@ var CPDocumentUntitledCount = 0;
{
if (_hasUndoManager == aFlag)
return;
_hasUndoManager = aFlag;
if (!_hasUndoManager)
[self setUndoManager:nil];
}
@@ -692,7 +697,7 @@ var CPDocumentUntitledCount = 0;
- (void)_undoManagerWillCloseGroup:(CPNotification)aNotification
{
var undoManager = [aNotification object];
if ([undoManager isUndoing] || [undoManager isRedoing])
return;
@@ -719,13 +724,13 @@ var CPDocumentUntitledCount = 0;
- (void)setUndoManager:(CPUndoManager)anUndoManager
{
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_undoManager)
{
[defaultCenter removeObserver:self
name:CPUndoManagerDidUndoChangeNotification
object:_undoManager];
[defaultCenter removeObserver:self
name:CPUndoManagerDidRedoChangeNotification
object:_undoManager];
@@ -734,17 +739,17 @@ var CPDocumentUntitledCount = 0;
name:CPUndoManagerWillCloseUndoGroupNotification
object:_undoManager];
}
_undoManager = anUndoManager;
if (_undoManager)
{
[defaultCenter addObserver:self
selector:@selector(_undoManagerDidUndoChange:)
name:CPUndoManagerDidUndoChangeNotification
object:_undoManager];
[defaultCenter addObserver:self
selector:@selector(_undoManagerDidRedoChange:)
name:CPUndoManagerDidRedoChangeNotification
@@ -770,7 +775,7 @@ var CPDocumentUntitledCount = 0;
return _undoManager;
}
/*
Implemented as a delegate of a CPWindow
@ignore
@@ -799,7 +804,7 @@ var CPDocumentUntitledCount = 0;
[[CPNotificationCenter defaultCenter]
postNotificationName:CPDocumentWillSaveNotification
object:self];
[self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
}
else
@@ -857,7 +862,7 @@ var CPDocumentUntitledCount = 0;
[[CPDocumentController sharedDocumentController] removeDocument:self];
}
- (void)shouldCloseWindowController:(CPWindowController)controller delegate:(id)delegate shouldCloseSelector:(SEL)selector contextInfo:(Object)info
- (void)shouldCloseWindowController:(CPWindowController)controller delegate:(id)delegate shouldCloseSelector:(SEL)selector contextInfo:(Object)info
{
if ([controller shouldCloseDocument] || ([_windowControllers count] < 2 && [_windowControllers indexOfObject:controller] !== CPNotFound))
[self canCloseDocumentWithDelegate:self shouldCloseSelector:@selector(_document:shouldClose:context:) contextInfo:{delegate:delegate, selector:selector, context:info}];
@@ -874,7 +879,7 @@ var CPDocumentUntitledCount = 0;
objj_msgSend(context.delegate, context.selector, aDocument, shouldClose, context.context);
}
- (void)canCloseDocumentWithDelegate:(id)aDelegate shouldCloseSelector:(SEL)aSelector contextInfo:(Object)context
- (void)canCloseDocumentWithDelegate:(id)aDelegate shouldCloseSelector:(SEL)aSelector contextInfo:(Object)context
{
if (![self isDocumentEdited])
return [aDelegate respondsToSelector:aSelector] && objj_msgSend(aDelegate, aSelector, self, YES, context);
@@ -884,8 +889,7 @@ var CPDocumentUntitledCount = 0;
[_canCloseAlert setDelegate:self];
[_canCloseAlert setAlertStyle:CPWarningAlertStyle];
[_canCloseAlert setTitle:@"Unsaved Document"];
[_canCloseAlert setMessageText:sprintf(@"Do you want to save the changes you've made to the document \"%@\"?",
[self displayName] || [self fileName])];
[_canCloseAlert setMessageText:@"Do you want to save the changes you've made to the document \"" + ([self displayName] || [self fileName]) + "\"?"];
[_canCloseAlert addButtonWithTitle:@"Save"];
[_canCloseAlert addButtonWithTitle:@"Cancel"];
+30 -28
View File
@@ -24,12 +24,12 @@
@import <Foundation/CPBundle.j>
@import "CPDocument.j"
@import "CPOpenPanel.j";
@import "CPOpenPanel.j"
var CPSharedDocumentController = nil;
/*!
/*!
@ingroup appkit
@class CPDocumentController
This class is responsible for managing an application's open documents.
@@ -41,7 +41,7 @@ var CPSharedDocumentController = nil;
}
/*!
Returns the singleton instance of the application's document controller. If it has not
Returns the singleton instance of the application's document controller. If it has not
been created yet, it will be created then returned.
@return a CPDocumentController
*/
@@ -49,7 +49,7 @@ var CPSharedDocumentController = nil;
{
if (!CPSharedDocumentController)
[[self alloc] init];
return CPSharedDocumentController;
}
@@ -59,11 +59,11 @@ var CPSharedDocumentController = nil;
- (id)init
{
self = [super init];
if (self)
{
_documents = [[CPArray alloc] init];
if (!CPSharedDocumentController)
CPSharedDocumentController = self;
@@ -85,16 +85,16 @@ var CPSharedDocumentController = nil;
{
var index = 0,
count = [_documents count];
for (; index < count; ++index)
for (; index < count; ++index)
{
var theDocument = _documents[index];
if ([[theDocument fileURL] isEqual:aURL])
return theDocument;
if ([[theDocument fileURL] isEqual:aURL])
return theDocument;
}
return nil;
return nil;
}
/*!
@@ -105,10 +105,10 @@ var CPSharedDocumentController = nil;
- (void)openUntitledDocumentOfType:(CPString)aType display:(BOOL)shouldDisplay
{
var theDocument = [self makeUntitledDocumentOfType:aType error:nil];
if (theDocument)
[self addDocument:theDocument];
if (shouldDisplay)
{
[theDocument makeWindowControllers];
@@ -146,6 +146,8 @@ var CPSharedDocumentController = nil;
result = [self makeDocumentWithContentsOfURL:anAbsoluteURL ofType:type delegate:self didReadSelector:@selector(document:didRead:contextInfo:) contextInfo:[CPDictionary dictionaryWithObject:shouldDisplay forKey:@"shouldDisplay"]];
[self addDocument:result];
if (result)
[self noteNewRecentDocument:result];
}
@@ -175,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
{
@@ -207,9 +209,8 @@ var CPSharedDocumentController = nil;
if (!didRead)
return;
[self addDocument:aDocument];
[aDocument makeWindowControllers];
if ([aContextInfo objectForKey:@"shouldDisplay"])
[aDocument showWindows];
}
@@ -223,7 +224,7 @@ var CPSharedDocumentController = nil;
[self openUntitledDocumentOfType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] display:YES];
}
-(void)openDocument:(id)aSender
- (void)openDocument:(id)aSender
{
var openPanel = [CPOpenPanel openPanel];
@@ -275,17 +276,17 @@ var CPSharedDocumentController = nil;
{
var index = 0,
count = _documentTypes.length,
extension = [[anAbsoluteURL pathExtension] lowercaseString],
starType = nil;
for (; index < count; ++index)
{
var documentType = _documentTypes[index],
extensions = [documentType objectForKey:@"CFBundleTypeExtensions"],
extensionIndex = 0,
extensionCount = extensions.length;
for (; extensionIndex < extensionCount; ++extensionIndex)
{
var thisExtension = [extensions[extensionIndex] lowercaseString];
@@ -311,11 +312,11 @@ var CPSharedDocumentController = nil;
for (;i < count; ++i)
{
var documentType = _documentTypes[i];
if ([documentType objectForKey:@"CPBundleTypeName"] == aType)
return documentType;
}
return nil;
}
@@ -335,7 +336,7 @@ var CPSharedDocumentController = nil;
@implementation CPDocumentController (Closing)
- (void)closeAllDocumentsWithDelegate:(id)aDelegate didCloseAllSelector:(SEL)didCloseSelector contextInfo:(Object)info
- (void)closeAllDocumentsWithDelegate:(id)aDelegate didCloseAllSelector:(SEL)didCloseSelector contextInfo:(Object)info
{
var context = {
delegate: aDelegate,
@@ -389,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];
}
+138 -59
View File
@@ -20,52 +20,32 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CPView.j>
@import <AppKit/CPEvent.j>
@import <AppKit/CPPasteboard.j>
@import <AppKit/CPImageView.j>
#import "CoreGraphics/CGGeometry.h"
#import "Platform/Platform.h"
@import "CPApplication.j"
@import "CPEvent.j"
@import "CPImageView.j"
@import "CPPasteboard.j"
@import "CPView.j"
@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])
var CPDragServerPreviousEvent = nil,
CPDragServerAutoscrollInterval = nil;
/*
var CPDragServerAutoscroll = function()
{
[CPDragServerSource autoscroll:CPDragServerPreviousEvent];
}
var CPDragServerPreviousEvent = nil,
CPDragServerPeriodicUpdateInterval = 0.05;
if (CPDragServerAutoscrollInterval === nil)
{
if ([CPDragServerSource respondsToSelector:@selector(autoscroll:)])
CPDragServerAutoscrollInterval = setInterval(CPDragServerAutoscroll, 100);
}
var CPSharedDragServer = nil;
CPDragServerPreviousEvent = anEvent;
if (CPDragServerAutoscrollInterval !== nil)
clearInterval(CPDragServerAutoscrollInterval);
CPDragServerAutoscrollInterval = nil;
*/
var CPSharedDragServer = nil;
var CPDragServerSource = nil;
var CPDragServerDraggingInfo = nil;
var CPDragServerSource = nil,
CPDragServerDraggingInfo = nil;
/*
CPDraggingInfo is a container of information about a specific dragging session.
@@ -127,7 +107,7 @@ var CPDragServerDraggingInfo = nil;
@end
var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
CPDraggingSource_draggedImage_endAt_operation_ = 1 << 1,
CPDraggingSource_draggedImage_endedAt_operation_ = 1 << 1,
CPDraggingSource_draggedView_movedTo_ = 1 << 2,
CPDraggingSource_draggedView_endedAt_operation_ = 1 << 3;
@@ -150,6 +130,13 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
CGPoint _draggingLocation;
id _draggingDestination;
BOOL _draggingDestinationWantsPeriodicUpdates;
CGPoint _startDragLocation;
BOOL _shouldSlideBack;
unsigned _dragOperation;
CPTimer _draggingUpdateTimer;
}
/*
@@ -189,6 +176,11 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
return self;
}
- (id)draggingDestination
{
return _draggingDestination;
}
- (CGPoint)draggingLocation
{
return _draggingLocation
@@ -225,42 +217,112 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
- (CPDragOperation)draggingUpdatedInPlatformWindow:(CPPlatformWindow)aPlatformWindow location:(CGPoint)aLocation
{
var dragOperation = CPDragOperationCopy;
[_draggingUpdateTimer invalidate];
_draggingUpdateTimer = nil;
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 && [_draggingDestination respondsToSelector:@selector(draggingExited:)])
if ([_draggingDestination respondsToSelector:@selector(draggingExited:)])
[_draggingDestination draggingExited:CPDragServerDraggingInfo];
_draggingDestination = draggingDestination;
if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingEntered:)])
if ([_draggingDestination respondsToSelector:@selector(wantsPeriodicDraggingUpdates)])
_draggingDestinationWantsPeriodicUpdates = [_draggingDestination wantsPeriodicDraggingUpdates];
else
_draggingDestinationWantsPeriodicUpdates = YES;
if ([_draggingDestination respondsToSelector:@selector(draggingEntered:)])
dragOperation = [_draggingDestination draggingEntered:CPDragServerDraggingInfo];
}
else if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingUpdated:)])
else if ([_draggingDestination respondsToSelector:@selector(draggingUpdated:)])
dragOperation = [_draggingDestination draggingUpdated:CPDragServerDraggingInfo];
if (!_draggingDestination)
dragOperation = CPDragOperationNone;
else
{
if (_draggingDestinationWantsPeriodicUpdates)
_draggingUpdateTimer = [CPTimer scheduledTimerWithTimeInterval:CPDragServerPeriodicUpdateInterval
target:self
selector:@selector(_sendPeriodicDraggingUpdate:)
userInfo:[CPDictionary dictionaryWithJSObject:{platformWindow:aPlatformWindow, location:aLocation}]
repeats:NO];
var scrollView = [_draggingDestination isKindOfClass:[CPView class]] ? [_draggingDestination enclosingScrollView] : nil;
if (scrollView)
{
var contentView = [scrollView contentView],
bounds = [contentView bounds],
insetBounds = CGRectInset(bounds, 30, 30),
eventLocation = [contentView convertPoint:_draggingLocation fromView:nil],
deltaX = 0,
deltaY = 0;
if (!CGRectContainsPoint(insetBounds, eventLocation))
{
if ([scrollView hasVerticalScroller])
{
if (eventLocation.y < _CGRectGetMinY(insetBounds))
deltaY = _CGRectGetMinY(insetBounds) - eventLocation.y;
else if (eventLocation.y > _CGRectGetMaxY(insetBounds))
deltaY = _CGRectGetMaxY(insetBounds) - eventLocation.y;
if (deltaY < -insetBounds.size.height)
deltaY = -insetBounds.size.height;
if (deltaY > insetBounds.size.height)
deltaY = insetBounds.size.height;
}
if ([scrollView hasHorizontalScroller])
{
if (eventLocation.x < _CGRectGetMinX(insetBounds))
deltaX = _CGRectGetMinX(insetBounds) - eventLocation.x;
else if (eventLocation.x > _CGRectGetMaxX(insetBounds))
deltaX = _CGRectGetMaxX(insetBounds) - eventLocation.x;
if (deltaX < -insetBounds.size.width)
deltaX = -insetBounds.size.width;
if (deltaX > insetBounds.size.width)
deltaX = insetBounds.size.width;
}
var scrollPoint = _CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY);
[contentView scrollToPoint:scrollPoint];
[[scrollView _headerView] scrollPoint:scrollPoint];
}
}
}
return dragOperation;
}
- (void)_sendPeriodicDraggingUpdate:(CPTimer)aTimer
{
var userInfo = [aTimer userInfo];
_dragOperation = [self draggingUpdatedInPlatformWindow:[userInfo objectForKey:@"platformWindow"]
location:[userInfo objectForKey:@"location"]];
}
- (void)draggingEndedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation operation:(CPDragOperation)anOperation
{
[_draggingUpdateTimer invalidate];
_draggingUpdateTimer = nil;
[_draggedView removeFromSuperview];
if (![CPPlatform supportsDragAndDrop])
[_draggedWindow orderOut:self];
if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_endAt_operation_)
if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_endedAt_operation_)
[_draggingSource draggedImage:[_draggedView image] endedAt:aLocation operation:anOperation];
else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_endedAt_operation_)
[_draggingSource draggedView:_draggedView endedAt:aLocation operation:anOperation];
@@ -269,8 +331,8 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
- (void)performDragOperationInPlatformWindow:(CPPlatformWindow)aPlatformWindow
{
if (_draggingDestination &&
(![_draggingDestination respondsToSelector:@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
if (_draggingDestination &&
(![_draggingDestination respondsToSelector:@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
(![_draggingDestination respondsToSelector:@selector(performDragOperation:)] || [_draggingDestination performDragOperation:CPDragServerDraggingInfo]) &&
[_draggingDestination respondsToSelector:@selector(concludeDragOperation:)])
[_draggingDestination concludeDragOperation:CPDragServerDraggingInfo];
@@ -296,6 +358,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
_draggingPasteboard = aPasteboard || [CPPasteboard pasteboardWithName:CPDragPboard];
_draggingSource = aSourceObject;
_draggingDestination = nil;
_shouldSlideBack = slideBack;
// The offset is based on the distance from where we want the view to be initially from where the mouse is initially
// Hence the use of mouseDownEvent's location and view's location in global coordinates.
@@ -310,7 +373,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
_draggingOffset = _CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y);
}
else
_draggingOffset = _CGSizeMakerZero();
_draggingOffset = _CGSizeMakeZero();
if ([CPPlatform isBrowser])
[_draggedWindow setPlatformWindow:[aWindow platformWindow]];
@@ -320,7 +383,8 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
var mouseLocation = [CPEvent mouseLocation];
// Place it where the mouse pointer is.
[_draggedWindow setFrameOrigin:_CGPointMake(mouseLocation.x - _draggingOffset.width, mouseLocation.y - _draggingOffset.height)];
_startDragLocation = _CGPointMake(mouseLocation.x - _draggingOffset.width, mouseLocation.y - _draggingOffset.height);
[_draggedWindow setFrameOrigin:_startDragLocation];
[_draggedWindow setFrameSize:[aView frame].size];
[[_draggedWindow contentView] addSubview:aView];
@@ -332,8 +396,8 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
if ([_draggingSource respondsToSelector:@selector(draggedImage:movedTo:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_movedTo_;
if ([_draggingSource respondsToSelector:@selector(draggedImage:endAt:operation:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_endAt_operation_;
if ([_draggingSource respondsToSelector:@selector(draggedImage:endedAt:operation:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_endedAt_operation_;
}
else
{
@@ -385,19 +449,34 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
if (type === CPLeftMouseUp)
{
[self performDragOperationInPlatformWindow:platformWindow];
[self draggingEndedInPlatformWindow:platformWindow globalLocation:platformWindowLocation operation:CPDragOperationNone];
// Make sure we do not finalize (cancel) the drag if the last drag update was disallowed
if (_dragOperation !== CPDragOperationNone)
[self performDragOperationInPlatformWindow:platformWindow];
[self draggingEndedInPlatformWindow:platformWindow globalLocation:platformWindowLocation operation:_dragOperation];
// Stop tracking events.
return;
}
[self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation];
[self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation];
else if (type === CPKeyDown)
{
var characters = [anEvent characters];
if (characters === CPEscapeFunctionKey)
{
_dragOperation = CPDragOperationNone;
[self draggingEndedInPlatformWindow:platformWindow globalLocation:CGPointMakeZero() operation:_dragOperation];
return;
}
}
else
{
[self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation];
_dragOperation = [self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation];
}
// If we're not a mouse up, then we're going to want to grab the next event.
[CPApp setTarget:self selector:@selector(trackDragging:)
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPKeyDownMask
untilDate:nil inMode:0 dequeue:NO];
}
+213 -53
View File
@@ -21,8 +21,7 @@
*/
@import <Foundation/CPObject.j>
#include "CoreGraphics/CGGeometry.h"
@import "CPText.j"
CPLeftMouseDown = 1;
@@ -41,7 +40,7 @@ CPAppKitDefined = 13;
CPSystemDefined = 14;
CPApplicationDefined = 15;
CPPeriodic = 16;
CPCursorUpdate = 17;
CPCursorUpdate = 17;
CPScrollWheel = 22;
CPOtherMouseDown = 25;
CPOtherMouseUp = 26;
@@ -52,8 +51,7 @@ CPTouchStart = 28;
CPTouchMove = 29;
CPTouchEnd = 30;
CPTouchCancel = 31;
CPAlphaShiftKeyMask = 1 << 16;
CPShiftKeyMask = 1 << 17;
CPControlKeyMask = 1 << 18;
@@ -87,13 +85,89 @@ CPPeriodicMask = 1 << CPPeriodic;
CPScrollWheelMask = 1 << CPScrollWheel;
CPAnyEventMask = 0xffffffff;
CPDOMEventDoubleClick = "dblclick",
CPDOMEventMouseDown = "mousedown",
CPDOMEventMouseUp = "mouseup",
CPDOMEventMouseMoved = "mousemove",
CPDOMEventMouseDragged = "mousedrag",
CPDOMEventKeyUp = "keyup",
CPDOMEventKeyDown = "keydown",
CPUpArrowFunctionKey = "\uF700";
CPDownArrowFunctionKey = "\uF701";
CPLeftArrowFunctionKey = "\uF702";
CPRightArrowFunctionKey = "\uF703";
CPF1FunctionKey = "\uF704";
CPF2FunctionKey = "\uF705";
CPF3FunctionKey = "\uF706";
CPF4FunctionKey = "\uF707";
CPF5FunctionKey = "\uF708";
CPF6FunctionKey = "\uF709";
CPF7FunctionKey = "\uF70A";
CPF8FunctionKey = "\uF70B";
CPF9FunctionKey = "\uF70C";
CPF10FunctionKey = "\uF70D";
CPF11FunctionKey = "\uF70E";
CPF12FunctionKey = "\uF70F";
CPF13FunctionKey = "\uF710";
CPF14FunctionKey = "\uF711";
CPF15FunctionKey = "\uF712";
CPF16FunctionKey = "\uF713";
CPF17FunctionKey = "\uF714";
CPF18FunctionKey = "\uF715";
CPF19FunctionKey = "\uF716";
CPF20FunctionKey = "\uF717";
CPF21FunctionKey = "\uF718";
CPF22FunctionKey = "\uF719";
CPF23FunctionKey = "\uF71A";
CPF24FunctionKey = "\uF71B";
CPF25FunctionKey = "\uF71C";
CPF26FunctionKey = "\uF71D";
CPF27FunctionKey = "\uF71E";
CPF28FunctionKey = "\uF71F";
CPF29FunctionKey = "\uF720";
CPF30FunctionKey = "\uF721";
CPF31FunctionKey = "\uF722";
CPF32FunctionKey = "\uF723";
CPF33FunctionKey = "\uF724";
CPF34FunctionKey = "\uF725";
CPF35FunctionKey = "\uF726";
CPInsertFunctionKey = "\uF727";
CPDeleteFunctionKey = "\uF728";
CPHomeFunctionKey = "\uF729";
CPBeginFunctionKey = "\uF72A";
CPEndFunctionKey = "\uF72B";
CPPageUpFunctionKey = "\uF72C";
CPPageDownFunctionKey = "\uF72D";
CPPrintScreenFunctionKey = "\uF72E";
CPScrollLockFunctionKey = "\uF72F";
CPPauseFunctionKey = "\uF730";
CPSysReqFunctionKey = "\uF731";
CPBreakFunctionKey = "\uF732";
CPResetFunctionKey = "\uF733";
CPStopFunctionKey = "\uF734";
CPMenuFunctionKey = "\uF735";
CPUserFunctionKey = "\uF736";
CPSystemFunctionKey = "\uF737";
CPPrintFunctionKey = "\uF738";
CPClearLineFunctionKey = "\uF739";
CPClearDisplayFunctionKey = "\uF73A";
CPInsertLineFunctionKey = "\uF73B";
CPDeleteLineFunctionKey = "\uF73C";
CPInsertCharFunctionKey = "\uF73D";
CPDeleteCharFunctionKey = "\uF73E";
CPPrevFunctionKey = "\uF73F";
CPNextFunctionKey = "\uF740";
CPSelectFunctionKey = "\uF741";
CPExecuteFunctionKey = "\uF742";
CPUndoFunctionKey = "\uF743";
CPRedoFunctionKey = "\uF744";
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";
@@ -104,9 +178,10 @@ CPDOMEventTouchEnd = "touchend";
CPDOMEventTouchCancel = "touchcancel";
var _CPEventPeriodicEventPeriod = 0,
_CPEventPeriodicEventTimer = nil;
_CPEventPeriodicEventTimer = nil,
_CPEventUpperCaseRegex = new RegExp("[A-Z]");
/*!
/*!
@ingroup appkit
@class CPEvent
CPEvent encapsulates the details of a Cappuccino keyboard or mouse event.
@@ -128,7 +203,7 @@ var _CPEventPeriodicEventPeriod = 0,
BOOL _isARepeat;
unsigned _keyCode;
DOMEvent _DOMEvent;
float _deltaX;
float _deltaY;
float _deltaZ;
@@ -136,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
@@ -155,12 +231,13 @@ var _CPEventPeriodicEventPeriod = 0,
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)repeatKey keyCode:(unsigned short)code
{
return [[self alloc] _initKeyEventWithType:anEventType location:aPoint modifierFlags:modifierFlags
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext
characters:characters charactersIgnoringModifiers:unmodCharacters isARepeat:repeatKey keyCode:code];
}
/*!
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
@@ -173,7 +250,7 @@ var _CPEventPeriodicEventPeriod = 0,
@throws CPInternalInconsistencyException if an invalid event type is provided
@return the new mouse event
*/
+ (id)mouseEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
+ (id)mouseEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
{
@@ -182,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
@@ -203,16 +281,28 @@ var _CPEventPeriodicEventPeriod = 0,
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext subtype:aSubtype data1:aData1 data2:aData2];
}
- (id)_initWithType:(CPEventType)anEventType
{
if (self = [super init])
{
_type = anEventType;
// Make sure these are 0 rather than nil.
_deltaX = 0;
_deltaY = 0;
_deltaZ = 0;
}
return self;
}
/* @ignore */
- (id)_initMouseEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned)modifierFlags
- (id)_initMouseEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
{
self = [super init];
if (self)
if (self = [self _initWithType:anEventType])
{
_type = anEventType;
_location = CPPointCreateCopy(aPoint);
_modifierFlags = modifierFlags;
_timestamp = aTimestamp;
@@ -222,7 +312,7 @@ var _CPEventPeriodicEventPeriod = 0,
_pressure = aPressure;
_window = [CPApp windowWithWindowNumber:aWindowNumber];
}
return self;
}
@@ -231,11 +321,8 @@ var _CPEventPeriodicEventPeriod = 0,
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)isARepeat keyCode:(unsigned short)code
{
self = [super init];
if (self)
if (self = [self _initWithType:anEventType])
{
_type = anEventType;
_location = CPPointCreateCopy(aPoint);
_modifierFlags = modifierFlags;
_timestamp = aTimestamp;
@@ -246,7 +333,7 @@ var _CPEventPeriodicEventPeriod = 0,
_keyCode = code;
_windowNumber = aWindowNumber;
}
return self;
}
@@ -255,11 +342,8 @@ var _CPEventPeriodicEventPeriod = 0,
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
subtype:(short)aSubtype data1:(int)aData1 data2:(int)aData2
{
self = [super init];
if (self)
if (self = [self _initWithType:anEventType])
{
_type = anEventType;
_location = CPPointCreateCopy(aPoint);
_modifierFlags = modifierFlags;
_timestamp = aTimestamp;
@@ -267,17 +351,17 @@ var _CPEventPeriodicEventPeriod = 0,
_subtype = aSubtype;
_data1 = aData1;
_data2 = aData2;
}
}
return self;
}
/*!
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
@@ -285,8 +369,19 @@ var _CPEventPeriodicEventPeriod = 0,
return _CGPointMakeCopy(_location);
}
- (CGPoint)globalLocation
{
var theWindow = [self window],
location = [self locationInWindow];
if (theWindow)
return [theWindow convertBaseToGlobal:location];
return location;
}
/*!
Returns event information as a bit mask
Returns event information as a bit mask.
*/
- (unsigned)modifierFlags
{
@@ -294,7 +389,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns the time the event occurred
Returns the time the event occurred.
*/
- (CPTimeInterval)timestamp
{
@@ -310,7 +405,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns the event's associated window
Returns the event's associated window.
*/
- (CPWindow)window
{
@@ -334,11 +429,14 @@ var _CPEventPeriodicEventPeriod = 0,
*/
- (int)buttonNumber
{
return _buttonNumber;
if (_type === CPRightMouseDown || _type === CPRightMouseUp || _type === CPRightMouseDragged)
return 1;
return 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
{
@@ -346,7 +444,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
@@ -356,6 +455,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
@@ -365,6 +465,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
@@ -374,6 +475,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
@@ -406,7 +508,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.
*/
@@ -431,37 +533,95 @@ var _CPEventPeriodicEventPeriod = 0,
return _deltaZ;
}
- (BOOL)_triggersKeyEquivalent:(CPString)aKeyEquivalent withModifierMask:aKeyEquivalentModifierMask
{
if (!aKeyEquivalent)
return NO;
if (_CPEventUpperCaseRegex.test(aKeyEquivalent))
aKeyEquivalentModifierMask |= CPShiftKeyMask;
// Windows and Linux don't have command keys, so just switch it to ctrl.
if (!CPBrowserIsOperatingSystem(CPMacOperatingSystem) && (aKeyEquivalentModifierMask & CPCommandKeyMask))
{
aKeyEquivalentModifierMask |= CPControlKeyMask;
aKeyEquivalentModifierMask &= ~CPCommandKeyMask;
}
if ((_modifierFlags & (CPShiftKeyMask | CPAlternateKeyMask | CPCommandKeyMask | CPControlKeyMask)) !== aKeyEquivalentModifierMask)
return NO;
// Treat \r and \n as the same key equivalent. See issue #710.
if (_characters === CPNewlineCharacter || _characters === CPCarriageReturnCharacter)
return CPNewlineCharacter === aKeyEquivalent || CPCarriageReturnCharacter === aKeyEquivalent;
return [_characters caseInsensitiveCompare:aKeyEquivalent] === CPOrderedSame;
}
- (BOOL)_couldBeKeyEquivalent
{
// FIXME: More cases? Space?
return _type === CPKeyDown &&
_modifierFlags & (CPCommandKeyMask | CPControlKeyMask) &&
[_characters length] > 0;
if (_type !== CPKeyDown)
return NO;
var characterCount = _characters.length;
if (!characterCount)
return NO;
if (_modifierFlags & (CPCommandKeyMask | CPControlKeyMask))
return YES;
for (var i = 0; i < characterCount; i++)
{
switch (_characters.charAt(i))
{
case CPBackspaceCharacter:
case CPDeleteCharacter:
case CPDeleteFunctionKey:
case CPTabCharacter:
case CPCarriageReturnCharacter:
case CPNewlineCharacter:
case CPSpaceFunctionKey:
case CPEscapeFunctionKey:
case CPPageUpFunctionKey:
case CPPageDownFunctionKey:
case CPLeftArrowFunctionKey:
case CPUpArrowFunctionKey:
case CPRightArrowFunctionKey:
case CPDownArrowFunctionKey:
case CPEndFunctionKey:
case CPHomeFunctionKey:
return YES;
}
}
// FIXME: More cases?
return NO;
}
/*!
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
*/
+ (void)startPeriodicEventsAfterDelay:(CPTimeInterval)aDelay withPeriod:(CPTimeInterval)aPeriod
{
_CPEventPeriodicEventPeriod = aPeriod;
// FIXME: OH TIMERS!!!
_CPEventPeriodicEventTimer = window.setTimeout(function() { _CPEventPeriodicEventTimer = window.setInterval(_CPEventFirePeriodEvent, aPeriod * 1000.0); }, aDelay * 1000.0);
}
/*!
Stops the periodic events from being generated
Stops the periodic events from being generated.
*/
+ (void)stopPeriodicEvents
{
if (_CPEventPeriodicEventTimer === nil)
return;
window.clearTimeout(_CPEventPeriodicEventTimer);
_CPEventPeriodicEventTimer = nil;
}
+32 -8
View File
@@ -22,7 +22,8 @@
@import <Foundation/CPObject.j>
/*!
/*!
@ingroup appkit
@class CPFlashMovie
@@ -30,7 +31,7 @@
*/
@implementation CPFlashMovie : CPObject
{
CPString _fileName;
CPString _filename;
}
/*!
@@ -38,9 +39,9 @@
@param aFilename the swf to load
@return the initialized CPFlashMovie
*/
+ (id)flashMovieWithFile:(CPString)aFileName
+ (id)flashMovieWithFile:(CPString)aFilename
{
return [[self alloc] initWithFile:aFileName];
return [[self alloc] initWithFile:aFilename];
}
/*!
@@ -48,14 +49,37 @@
@param aFilename the swf to load
@return the initialized CPFlashMovie
*/
- (id)initWithFile:(CPString)aFileName
- (id)initWithFile:(CPString)aFilename
{
self = [super init];
if (self)
_fileName = aFileName;
_filename = aFilename;
return self;
}
- (CPString)filename
{
return _filename;
}
@end
var CPFlashMovieFilenameKey = "CPFlashMovieFilenameKey";
@implementation CPFlashMovie (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
_filename = [aCoder decodeObjectForKey:CPFlashMovieFilenameKey];
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_filename forKey:CPFlashMovieFilenameKey];
}
@end
+132 -38
View File
@@ -24,55 +24,58 @@
@import "CPView.j"
var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
/*!
@ingroup appkit
*/
@implementation CPFlashView : CPView
{
CPFlashMovie _flashMovie;
DOMElement _DOMEmbedElement;
DOMElement _DOMMParamElement;
CPDictionary _params;
CPDictionary _paramElements;
#if PLATFORM(DOM)
DOMElement _DOMParamElement;
DOMElement _DOMObjectElement;
DOMElement _DOMInnerObjectElement;
#endif
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_DOMObjectElement = document.createElement("object");
_DOMObjectElement.width = "100%";
_DOMObjectElement.height = "100%";
_DOMObjectElement.style.top = "0px";
_DOMObjectElement.style.left = "0px";
_DOMParamElement = document.createElement("param");
_DOMParamElement.name = "movie";
_DOMObjectElement.appendChild(_DOMParamElement);
var param = document.createElement("param");
param.name = "wmode";
param.value = "transparent";
_DOMObjectElement.appendChild(param);
_DOMEmbedElement = document.createElement("embed");
#if PLATFORM(DOM)
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
_DOMObjectElement = document.createElement(@"object");
_DOMObjectElement.width = @"100%";
_DOMObjectElement.height = @"100%";
_DOMObjectElement.style.top = @"0px";
_DOMObjectElement.style.left = @"0px";
_DOMObjectElement.type = @"application/x-shockwave-flash";
_DOMObjectElement.setAttribute(@"classid", IEFlashCLSID);
_DOMEmbedElement.type = "application/x-shockwave-flash";
_DOMEmbedElement.setAttribute("wmode", "transparent");
_DOMEmbedElement.width = "100%";
_DOMEmbedElement.height = "100%";
_DOMParamElement = document.createElement(@"param");
_DOMParamElement.name = @"movie";
// IE requires this thing to be in the _DOMElement and not the _DOMObjectElement.
_DOMElement.appendChild(_DOMEmbedElement);
_DOMElement.appendChild(_DOMObjectElement);
_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;
}
@@ -80,13 +83,17 @@
{
if (_flashMovie == aFlashMovie)
return;
_flashMovie = aFlashMovie;
_DOMParamElement.value = aFlashMovie._fileName;
if (_DOMEmbedElement)
_DOMEmbedElement.src = aFlashMovie._fileName;
#if PLATFORM(DOM)
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
_DOMParamElement.value = [aFlashMovie filename];
_DOMInnerObjectElement.data = [aFlashMovie filename];
}
else
[self _rebuildIEObjects];
#endif
}
- (CPFlashMovie)flashMovie
@@ -94,6 +101,93 @@
return _flashMovie;
}
- (void)setFlashVars:(CPDictionary)aDictionary
{
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];
}
- (CPDictionary)flashVars
{
return [_params objectForKey:@"flashvars"];
}
- (void)setParameters:(CPDictionary)aDictionary
{
#if PLATFORM(DOM)
if (_paramElements && !CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
var elements = [_paramElements allValues],
count = [elements count];
for (var i = 0; i < count; i++)
_DOMObjectElement.removeChild([elements objectAtIndex:i]);
}
#endif
if (!_params)
_params = aDictionary;
else
[_params addEntriesFromDictionary:aDictionary];
#if PLATFORM(DOM)
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
_paramElements = [CPDictionary dictionary];
var enumerator = [_params keyEnumerator],
key;
while (_DOMObjectElement && (key = [enumerator nextObject]))
{
var param = document.createElement(@"param");
param.name = key;
param.value = [_params objectForKey:key];
_DOMObjectElement.appendChild(param);
[_paramElements setObject:param forKey:key];
}
}
else
[self _rebuildIEObjects];
#endif
}
- (CPDictionary)parameters
{
return _params;
}
#if PLATFORM(DOM)
- (void)_rebuildIEObjects
{
_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
- (void)mouseDragged:(CPEvent)anEvent
{
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
+264 -29
View File
@@ -20,91 +20,254 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
var _CPFonts = {};
_CPFontSystemFontFace = @"Arial";
@import <Foundation/CPObject.j>
@import <Foundation/CPBundle.j>
#define _CPCachedFont(aName, aSize, isBold) _CPFonts[(isBold ? @"bold " : @"") + ROUND(aSize) + @"px '" + aName + @"'"]
@import "CPView.j"
/*!
CPFontDefaultSystemFontFace = @"Arial, sans-serif";
CPFontDefaultSystemFontSize = 12;
var _CPFonts = {},
_CPFontSystemFontFace = CPFontDefaultSystemFontFace,
_CPFontSystemFontSize = 12,
_CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "),
_CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g");
#define _CPFontNormalizedNames(aName) _CPFontNormalizedNameArray(aName).join(", ")
#define _CPCachedFont(aName, aSize, isBold, isItalic) _CPFonts[_CPFontCreateCSSString(_CPFontNormalizedNames(aName), aSize, isBold, isItalic)]
/*!
@ingroup appkit
@class CPFont
The CPFont class allows control of the fonts used for displaying text anywhere on the screen. The primary method for getting a particular font is through one of the class methods that take a name and/or size as arguments, and return the appropriate CPFont.
The CPFont class allows control of the fonts used for displaying text anywhere on the screen.
The primary method for getting a particular font is through one of the class methods that take
a name and/or size as arguments, and return the appropriate CPFont.
By default the system font face/size is Arial 12px, with a fallback to sans-serif. You may
configure this at runtime in two ways:
- By sending [CPFont @link CPFont::setSystemFontFace: setSystemFontFace:@endlink] and/or [CPFont @link CPFont::setSystemFontSize: setSystemFontSize:@endlink].
- By configuring Info.plist for your application or for AppKit. You can set the font face
by adding a CPSystemFontFace string item to the Info.plist, and you can set the font size
by adding a CPSystemFontSize integer item to the Info.plist.
Note that in either case, you can specify a comma-delimited list of fonts as the font face.
The browser will use the first available font in the list. CPFont always ensures that Arial
and sans-serif are in the generated CSS string, so there is no need to add them to the end
of your font list.
If you are using nib2cib, you should use the second method (using Info.plist),
and be sure to run nib2cib again any time you modify the CPSystemFontFace or CPSystemFontSize items.
For example, you might add this to your application's Info.plist to set the system font to Lucida Grande,
with an automatic fallback to Arial or sans-serif:
@code
<key>CPSystemFontFace</key>
<string>Lucida Grande</string>
@endcode
*/
@implementation CPFont : CPObject
{
CPString _name;
float _size;
BOOL _isBold;
float _ascender;
float _descender;
float _lineHeight;
BOOL _isBold @accessors(readonly, getter=isBold);
BOOL _isItalic @accessors(readonly, getter=isItalic);
CPString _cssString;
}
+ (void)initialize
{
var systemFontFace = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPSystemFontFace"];
if (!systemFontFace)
systemFontFace = [[CPBundle bundleForClass:[CPView class]] objectForInfoDictionaryKey:@"CPSystemFontFace"];
if (systemFontFace)
[self setSystemFontFace:systemFontFace];
var systemFontSize = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPSystemFontSize"];
if (!systemFontSize)
systemFontSize = [[CPBundle bundleForClass:[CPView class]] objectForInfoDictionaryKey:@"CPSystemFontSize"];
if (systemFontSize)
_CPFontSystemFontSize = systemFontSize;
}
/*!
Returns the default system font face, which may consist of several comma-separated family names.
*/
+ (CPString)systemFontFace
{
return _CPFontSystemFontFace;
}
/*!
Sets the default system font face, which may consist of several comma-separated family names.
*/
+ (CPString)setSystemFontFace:(CPString)aFace
{
_CPFontSystemFontFace = _CPFontNormalizedNames(aFace);
}
/*!
Returns the default system font size.
*/
+ (float)systemFontSize
{
return _CPFontSystemFontSize;
}
/*!
Sets the default system font size.
*/
+ (float)setSystemFontSize:(float)size
{
if (size > 0)
_CPFontSystemFontSize = size;
}
/*!
Returns a font with the specified name and size.
@param aName the name of the font
@param aSize the size of the font (in points)
@param aSize the size of the font (in px)
@return the requested font
*/
+ (CPFont)fontWithName:(CPString)aName size:(float)aSize
{
return _CPCachedFont(aName, aSize, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO];
return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO italic:NO];
}
/*!
Returns a font with the specified name, size and style.
@param aName the name of the font
@param aSize the size of the font (in px)
@param italic whether the font should be italicized
@return the requested font
*/
+ (CPFont)fontWithName:(CPString)aName size:(float)aSize italic:(BOOL)italic
{
return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO italic:italic];
}
/*!
Returns a bold font with the specified name and size.
@param aName the name of the font
@param aSize the size of the font (in points)
@param aSize the size of the font (in px)
@return the requested bold font
*/
+ (CPFont)boldFontWithName:(CPString)aName size:(float)aSize
{
return _CPCachedFont(aName, aSize, YES) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES];
return _CPCachedFont(aName, aSize, YES, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES italic:NO];
}
/*!
Returns a bold font with the specified name, size and style.
@param aName the name of the font
@param aSize the size of the font (in px)
@param italic whether the font should be italicized
@return the requested font
*/
+ (CPFont)boldFontWithName:(CPString)aName size:(float)aSize italic:(BOOL)italic
{
return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES italic:italic];
}
/*!
Returns the system font scaled to the specified size
@param aSize the size of the font (in points)
@param aSize the size of the font (in px)
@return the requested system font
*/
+ (CPFont)systemFontOfSize:(CPSize)aSize
{
return _CPCachedFont(_CPFontSystemFontFace, aSize, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:NO];
return _CPCachedFont(_CPFontSystemFontFace, aSize, NO, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:NO italic:NO];
}
/*!
Returns the bold system font scaled to the specified size
@param aSize the size of the font (in points)
@param aSize the size of the font (in px)
@return the requested bold system font
*/
+ (CPFont)boldSystemFontOfSize:(CPSize)aSize
{
return _CPCachedFont(_CPFontSystemFontFace, aSize, YES) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:YES];
return _CPCachedFont(_CPFontSystemFontFace, aSize, YES, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:YES italic:NO];
}
/* FIXME Font Descriptor
@ignore
*/
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold
{
{
return [self _initWithName:aName size:aSize bold:isBold italic:NO];
}
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold italic:(BOOL)isItalic
{
self = [super init];
if (self)
{
_name = aName;
_name = _CPFontNormalizedNames(aName);
_size = aSize;
_ascender = 0;
_descender = 0;
_lineHeight = 0;
_isBold = isBold;
_cssString = (_isBold ? @"bold " : @"") + ROUND(aSize) + @"px '" + aName + @"'";
_isItalic = isItalic;
_cssString = _CPFontCreateCSSString(_name, _size, _isBold, _isItalic);
_CPFonts[_cssString] = self;
}
return self;
}
/*!
Returns the font size (in points)
Returns the distance of the longest ascender's top y-coordinate from the baseline (in CSS px)
*/
- (float)ascender
{
if (!_ascender)
[self _getMetrics];
return _ascender;
}
/*!
Returns the bottom y coordinate (in CSS px), offset from the baseline, of the receiver's longest descender.
Thus, if the longest descender extends 2 px below the baseline, descender will return 2.
*/
- (float)descender
{
if (!_descender)
[self _getMetrics];
return _descender;
}
/*!
Returns the default line height.
NOTE: This was moved from NSFont to NSLayoutManager in Cocoa, but since there is no CPLayoutManager, it has been kept here.
*/
- (float)defaultLineHeightForFont
{
if (!_lineHeight)
[self _getMetrics];
return _lineHeight;
}
/*!
Returns the font size (in CSS px)
*/
- (float)size
{
@@ -127,11 +290,36 @@ var _CPFonts = {};
return _name;
}
- (BOOL)isEqual:(id)anObject
{
return [anObject isKindOfClass:[CPFont class]] && [anObject cssString] === _cssString;
}
- (CPString)description
{
return [CPString stringWithFormat:@"%@ %@", [super description], [self cssString]];
}
- (id)copy
{
return [[CPFont alloc] _initWithName:_name size:_size bold:_isBold italic:_isItalic];
}
- (void)_getMetrics
{
var metrics = [CPString metricsOfFont:self];
_ascender = [metrics objectForKey:@"ascender"];
_descender = [metrics objectForKey:@"descender"];
_lineHeight = [metrics objectForKey:@"lineHeight"];
}
@end
var CPFontNameKey = @"CPFontNameKey",
CPFontSizeKey = @"CPFontSizeKey",
CPFontIsBoldKey = @"CPFontIsBoldKey";
var CPFontNameKey = @"CPFontNameKey",
CPFontSizeKey = @"CPFontSizeKey",
CPFontIsBoldKey = @"CPFontIsBoldKey",
CPFontIsItalicKey = @"CPFontIsItalicKey";
@implementation CPFont (CPCoding)
@@ -142,9 +330,12 @@ var CPFontNameKey = @"CPFontNameKey",
*/
- (id)initWithCoder:(CPCoder)aCoder
{
return [self _initWithName:[aCoder decodeObjectForKey:CPFontNameKey]
size:[aCoder decodeFloatForKey:CPFontSizeKey]
bold:[aCoder decodeBoolForKey:CPFontIsBoldKey]];
var fontName = [aCoder decodeObjectForKey:CPFontNameKey],
size = [aCoder decodeFloatForKey:CPFontSizeKey],
isBold = [aCoder decodeBoolForKey:CPFontIsBoldKey],
isItalic = [aCoder decodeBoolForKey:CPFontIsItalicKey];
return [self _initWithName:fontName size:size bold:isBold italic:isItalic];
}
/*!
@@ -156,6 +347,50 @@ var CPFontNameKey = @"CPFontNameKey",
[aCoder encodeObject:_name forKey:CPFontNameKey];
[aCoder encodeFloat:_size forKey:CPFontSizeKey];
[aCoder encodeBool:_isBold forKey:CPFontIsBoldKey];
[aCoder encodeBool:_isItalic forKey:CPFontIsItalicKey];
}
@end
// aName must be normalized
var _CPFontCreateCSSString = function(aName, aSize, isBold, isItalic)
{
var properties = (isItalic ? "italic " : "") + (isBold ? "bold " : "") + aSize + "px ";
return properties + _CPFontConcatNameWithFallback(aName);
};
var _CPFontConcatNameWithFallback = function(aName)
{
var names = _CPFontNormalizedNameArray(aName),
fallbackFaces = _CPFontFallbackFaces.slice(0);
// Remove the fallback names used in the names passed in
for (var i = 0; i < names.length; ++i)
{
for (var j = 0; j < fallbackFaces.length; ++j)
{
if (names[i].toLowerCase() === fallbackFaces[j].toLowerCase())
{
fallbackFaces.splice(j, 1);
break;
}
}
if (names[i].indexOf(" ") > 0)
names[i] = '"' + names[i] + '"';
}
return names.concat(fallbackFaces).join(", ");
};
var _CPFontNormalizedNameArray = function(aName)
{
var names = aName.split(",");
for (var i = 0; i < names.length; ++i)
names[i] = names[i].replace(_CPFontStripRegExp, "");
return names;
};
+40 -34
View File
@@ -22,7 +22,7 @@
@import <Foundation/CPObject.j>
@import <AppKit/CPFont.j>
@import "CPFont.j"
var CPSharedFontManager = nil,
@@ -45,13 +45,13 @@ var CPSharedFontManager = nil,
{
if (!CPSharedFontManager)
CPSharedFontManager = [[CPFontManagerFactory alloc] init];
return CPSharedFontManager;
}
// Changing the Default Font Conversion Classes
/*!
Sets the class that will be used to create the applcation's
Sets the class that will be used to create the application's
font manager.
*/
+ (void)setFontManagerFactory:(Class)aClass
@@ -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]];
+32 -18
View File
@@ -70,8 +70,8 @@ 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);
return CPRectMake( aRect.origin.x + dX, aRect.origin.y + dY,
aRect.size.width - 2 * dX, aRect.size.height - 2 * dY);
}
/*!
@@ -96,13 +96,13 @@ function CPRectIntegral(aRect)
function CPRectIntersection(lhsRect, rhsRect)
{
var intersection = CPRectMake(
Math.max(CPRectGetMinX(lhsRect), CPRectGetMinX(rhsRect)),
Math.max(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
Math.max(CPRectGetMinX(lhsRect), CPRectGetMinX(rhsRect)),
Math.max(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
0, 0);
intersection.size.width = Math.min(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)) - CPRectGetMinX(intersection);
intersection.size.height = Math.min(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect)) - CPRectGetMinY(intersection);
return CPRectIsEmpty(intersection) ? CPRectMakeZero() : intersection;
}
@@ -160,13 +160,13 @@ function CPRectStandardize(aRect)
standardized.origin.x += width;
standardized.size.width = -width;
}
if (height < 0.0)
{
standardized.origin.y += height;
standardized.size.height = -height;
}
return standardized;
}
@@ -183,7 +183,7 @@ function CPRectUnion(lhsRect, rhsRect)
minY = Math.min(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
maxX = Math.max(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)),
maxY = Math.max(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect));
return CPRectMake(minX, minY, maxX - minX, maxY - minY);
}
@@ -222,8 +222,8 @@ function CPRectContainsPoint(aRect, aPoint)
{
return aPoint.x >= CPRectGetMinX(aRect) &&
aPoint.y >= CPRectGetMinY(aRect) &&
aPoint.x < CPRectGetMaxX(aRect) &&
aPoint.y < CPRectGetMaxY(aRect);
aPoint.x < CPRectGetMaxX(aRect) &&
aPoint.y < CPRectGetMaxY(aRect);
}
/*!
@@ -234,9 +234,9 @@ function CPRectContainsPoint(aRect, aPoint)
@param possibleInner the CGRect to test if it fits inside \c possibleOuter.
@return BOOL \c YES if \c possibleInner fits inside \c possibleOuter.
*/
function CPRectContainsRect(lhsRect, rhsRect)
function CPRectContainsRect(possibleOuter, possibleInner)
{
return CPRectEqualToRect(CPUnionRect(lhsRect, rhsRect), rhsRect);
return CGRectContainsRect(possibleOuter, possibleInner);
}
/*!
@@ -261,7 +261,7 @@ function CPPointEqualToPoint(lhsPoint, rhsPoint)
*/
function CPRectEqualToRect(lhsRect, rhsRect)
{
return CPPointEqualToPoint(lhsRect.origin, rhsRect.origin) &&
return CPPointEqualToPoint(lhsRect.origin, rhsRect.origin) &&
CPSizeEqualToSize(lhsRect.size, rhsRect.size);
}
@@ -380,6 +380,20 @@ function CPRectIsNull(aRect)
return aRect.size.width <= 0.0 || aRect.size.height <= 0.0;
}
/*!
Creates two rectangles -- slice and rem -- from inRect, by dividing inRect
with a line that's parallel to the side of inRect specified by edge.
The size of slice is determined by amount, which specifies the distance from edge.
slice and rem must not be NULL.
@group CGRect
*/
function CPDivideRect(inRect, slice, rem, amount, edge)
{
CGRectDivide(inRect, slice, rem, amount, edge);
}
/*!
Returns \c YES if the two CGSizes are identical.
@group CGSize
@@ -434,7 +448,7 @@ function CPStringFromRect(aRect)
function CPPointFromString(aString)
{
var comma = aString.indexOf(',');
return { x:parseFloat(aString.substr(1, comma - 1), 10), y:parseFloat(aString.substring(comma + 1, aString.length), 10) };
}
@@ -447,7 +461,7 @@ function CPPointFromString(aString)
function CPSizeFromString(aString)
{
var comma = aString.indexOf(',');
return { width:parseFloat(aString.substr(1, comma - 1), 10), height:parseFloat(aString.substring(comma + 1, aString.length), 10) };
}
@@ -460,7 +474,7 @@ function CPSizeFromString(aString)
function CPRectFromString(aString)
{
var comma = aString.indexOf(',', aString.indexOf(',') + 1);
return { origin:CPPointFromString(aString.substr(1, comma - 1)), size:CPSizeFromString(aString.substring(comma + 2, aString.length)) };
}
@@ -504,6 +518,6 @@ function CPPointMakeZero()
return CPPointMake(0, 0, 0);
}
/*!
/*!
@}
*/
+108
View File
@@ -0,0 +1,108 @@
/*
* CPGraphics.j
* AppKit
*
* Created by Francisco Tolmasky.
* 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 "CPColor.j"
@import "CPGraphicsContext.j"
function CPDrawTiledRects(
/* CGRect */ boundsRect,
/* CGRect */ clipRect,
/* CPRectEdge[] */ sides,
/* float[] */ grays)
{
if (sides.length != grays.length)
[CPException raise:CPInvalidArgumentException reason:@"sides (length: " + sides.length + ") and grays (length: " + grays.length + ") must have the same length."];
var colors = [];
for (var i = 0; i < grays.length; ++i)
colors.push([CPColor colorWithCalibratedWhite:grays[i] alpha:1.0]);
return CPDrawColorTiledRects(boundsRect, clipRect, sides, colors);
}
function CPDrawColorTiledRects(
/* CGRect */ boundsRect,
/* CGRect */ clipRect,
/* CPRectEdge[] */ sides,
/* CPColor[] */ colors)
{
if (sides.length != colors.length)
[CPException raise:CPInvalidArgumentException reason:@"sides (length: " + sides.length + ") and colors (length: " + colors.length + ") must have the same length."];
var resultRect = _CGRectMakeCopy(boundsRect),
slice = _CGRectMakeZero(),
remainder = _CGRectMakeZero(),
context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(context);
CGContextSetLineWidth(context, 1.0);
for (var sideIndex = 0; sideIndex < sides.length; ++sideIndex)
{
var side = sides[sideIndex];
CGRectDivide(resultRect, slice, remainder, 1.0, side);
resultRect = remainder;
slice = CGRectIntersection(slice, clipRect);
// Cocoa docs say that only slices that are within the clipRect are actually drawn
if (_CGRectIsEmpty(slice))
continue;
var minX, maxX, minY, maxY;
if (side == CPMinXEdge || side == CPMaxXEdge)
{
// Make sure we have at least 1 pixel to draw a line
if (_CGRectGetWidth(slice) < 1.0)
continue;
minX = _CGRectGetMinX(slice) + 0.5;
maxX = minX;
minY = _CGRectGetMinY(slice);
maxY = _CGRectGetMaxY(slice);
}
else // CPMinYEdge || CPMaxYEdge
{
// Make sure we have at least 1 pixel to draw a line
if (_CGRectGetHeight(slice) < 1.0)
continue;
minX = _CGRectGetMinX(slice);
maxX = _CGRectGetMaxX(slice);
minY = _CGRectGetMinY(slice) + 0.5;
maxY = minY;
}
CGContextBeginPath(context);
CGContextMoveToPoint(context, minX, minY);
CGContextAddLineToPoint(context, maxX, maxY);
CGContextSetStrokeColor(context, colors[sideIndex]);
CGContextStrokePath(context);
}
CGContextRestoreGState(context);
return resultRect;
}
+9 -4
View File
@@ -20,7 +20,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
var CPGraphicsContextCurrent = nil;
@import <Foundation/CPObject.j>
@import "CGContext.j"
var CPGraphicsContextCurrent = nil;
/*!
@ingroup appkit
@@ -28,7 +33,7 @@ var CPGraphicsContextCurrent = nil;
*/
@implementation CPGraphicsContext : CPObject
{
CPContext _graphicsPort;
CGContext _graphicsPort;
}
/*!
@@ -66,10 +71,10 @@ var CPGraphicsContextCurrent = nil;
- (id)initWithGraphicsPort:(CPContext)aGraphicsPort
{
self = [super init];
if (self)
_graphicsPort = aGraphicsPort;
return self;
}
+94 -29
View File
@@ -19,7 +19,7 @@
* 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/CPBundle.j>
@import <Foundation/CPNotificationCenter.j>
@import <Foundation/CPObject.j>
@@ -28,6 +28,7 @@
@import "CPGeometry.j"
CPImageLoadStatusInitialized = 0;
CPImageLoadStatusLoading = 1;
CPImageLoadStatusCompleted = 2;
@@ -38,18 +39,33 @@ CPImageLoadStatusReadError = 6;
CPImageDidLoadNotification = @"CPImageDidLoadNotification";
// Image Names
CPImageNameColorPanel = @"CPImageNameColorPanel";
CPImageNameColorPanelHighlighted = @"CPImageNameColorPanelHighlighted";
var imagesForNames = { },
AppKitImageForNames = { };
AppKitImageForNames[CPImageNameColorPanel] = CGSizeMake(26.0, 29.0);
AppKitImageForNames[CPImageNameColorPanelHighlighted] = CGSizeMake(26.0, 29.0);
function CPImageInBundle(aFilename, aSize, aBundle)
{
if (!aBundle)
aBundle = [CPBundle mainBundle];
if (aSize)
return [[CPImage alloc] initWithContentsOfFile:[aBundle pathForResource:aFilename] size:aSize];
return [[CPImage alloc] initWithContentsOfFile:[aBundle pathForResource:aFilename]];
}
/*!
function CPAppKitImage(aFilename, aSize)
{
return CPImageInBundle(aFilename, aSize, [CPBundle bundleForClass:[CPView class]]);
}
/*!
@ingroup appkit
@class CPImage
@@ -57,7 +73,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
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
@@ -74,10 +90,11 @@ function CPImageInBundle(aFilename, aSize, aBundle)
{
CGSize _size;
CPString _filename;
CPString _name;
id _delegate;
unsigned _loadStatus;
Image _image;
}
@@ -97,14 +114,14 @@ function CPImageInBundle(aFilename, aSize, aBundle)
- (id)initByReferencingFile:(CPString)aFilename size:(CGSize)aSize
{
self = [super init];
if (self)
{
_size = CPSizeCreateCopy(aSize);
_filename = aFilename;
_loadStatus = CPImageLoadStatusInitialized;
}
return self;
}
@@ -117,10 +134,10 @@ function CPImageInBundle(aFilename, aSize, aBundle)
- (id)initWithContentsOfFile:(CPString)aFilename size:(CGSize)aSize
{
self = [self initByReferencingFile:aFilename size:aSize];
if (self)
[self load];
return self;
}
@@ -133,10 +150,10 @@ function CPImageInBundle(aFilename, aSize, aBundle)
- (id)initWithContentsOfFile:(CPString)aFilename
{
self = [self initByReferencingFile:aFilename size:CGSizeMake(-1, -1)];
if (self)
[self load];
return self;
}
@@ -165,6 +182,50 @@ function CPImageInBundle(aFilename, aSize, aBundle)
return _size;
}
+ (id)imageNamed:(CPString)aName
{
var image = imagesForNames[aName];
if (image)
return image;
var imageOrSize = AppKitImageForNames[aName];
if (!imageOrSize)
return nil;
if (!imageOrSize.isa)
{
imageOrSize = CPAppKitImage("CPImage/" + aName + ".png", imageOrSize);
[imageOrSize setName:aName];
AppKitImageForNames[aName] = imageOrSize;
}
return imageOrSize;
}
- (BOOL)setName:(CPString)aName
{
if (_name === aName)
return YES;
if (imagesForNames[aName])
return NO;
_name = aName;
imagesForNames[aName] = self;
return YES;
}
- (CPString)name
{
return _name;
}
/*!
Sets the receiver's delegate.
@param the delegate
@@ -200,9 +261,10 @@ function CPImageInBundle(aFilename, aSize, aBundle)
{
if (_loadStatus == CPImageLoadStatusLoading || _loadStatus == CPImageLoadStatusCompleted)
return;
_loadStatus = CPImageLoadStatusLoading;
#if PLATFORM(DOM)
_image = new Image();
var isSynchronous = YES;
@@ -219,7 +281,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
}
[self _derefFromImage];
}
_image.onerror = function ()
{
if (isSynchronous)
@@ -231,7 +293,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
}
[self _derefFromImage];
}
_image.onabort = function ()
{
if (isSynchronous)
@@ -243,10 +305,13 @@ function CPImageInBundle(aFilename, aSize, aBundle)
}
[self _derefFromImage];
}
_image.src = _filename;
isSynchronous = NO;
// onload and friends may fire after this point but BEFORE the end of the run loop,
// crazy, I know. So don't set isSynchronous here, rather wait a bit longer.
window.setTimeout(function() { isSynchronous = NO; }, 0);
#endif
}
- (BOOL)isThreePartImage
@@ -279,7 +344,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
[[CPNotificationCenter defaultCenter]
postNotificationName:CPImageDidLoadNotification
object:self];
if ([_delegate respondsToSelector:@selector(imageDidLoad:)])
[_delegate imageDidLoad:self];
}
@@ -288,7 +353,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
- (void)_imageDidError
{
_loadStatus = CPImageLoadStatusReadError;
if ([_delegate respondsToSelector:@selector(imageDidError:)])
[_delegate imageDidError:self];
}
@@ -297,7 +362,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
- (void)_imageDidAbort
{
_loadStatus = CPImageLoadStatusCancelled;
if ([_delegate respondsToSelector:@selector(imageDidAbort:)])
[_delegate imageDidAbort:self];
}
@@ -337,7 +402,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
- (id)initWithImageSlices:(CPArray)imageSlices isVertical:(BOOL)isVertical
{
self = [super init];
if (self)
{
_imageSlices = imageSlices;
@@ -382,13 +447,13 @@ var CPThreePartImageImageSlicesKey = @"CPThreePartImageImageSlicesKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_imageSlices = [aCoder decodeObjectForKey:CPThreePartImageImageSlicesKey];
_isVertical = [aCoder decodeBoolForKey:CPThreePartImageIsVerticalKey];
}
return self;
}
@@ -409,10 +474,10 @@ var CPThreePartImageImageSlicesKey = @"CPThreePartImageImageSlicesKey",
- (id)initWithImageSlices:(CPArray)imageSlices
{
self = [super init];
if (self)
_imageSlices = imageSlices;
return self;
}
@@ -445,10 +510,10 @@ var CPNinePartImageImageSlicesKey = @"CPNinePartImageImageSlicesKey";
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
_imageSlices = [aCoder decodeObjectForKey:CPNinePartImageImageSlicesKey];
return self;
}
+140 -64
View File
@@ -26,31 +26,24 @@
@import "CPImage.j"
@import "CPShadowView.j"
#include "Platform/Platform.h"
#include "Platform/DOM/CPDOMDisplayServer.h"
#include "CoreGraphics/CGGeometry.h"
/*
@global
@group CPImageScaling
*/
CPScaleProportionally = 0;
/*
@global
@group CPImageScaling
*/
CPScaleToFit = 1;
/*
@global
@group CPImageScaling
*/
CPScaleNone = 2;
CPImageAlignCenter = 0;
CPImageAlignTop = 1;
CPImageAlignTopLeft = 2;
CPImageAlignTopRight = 3;
CPImageAlignLeft = 4;
CPImageAlignBottom = 5;
CPImageAlignBottomLeft = 6;
CPImageAlignBottomRight = 7;
CPImageAlignRight = 8;
var CPImageViewShadowBackgroundColor = nil,
CPImageViewEmptyPlaceholderImage = nil;
var CPImageViewShadowBackgroundColor = nil;
var LEFT_SHADOW_INSET = 3.0,
RIGHT_SHADOW_INSET = 3.0,
TOP_SHADOW_INSET = 3.0,
@@ -58,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
@@ -66,20 +59,28 @@ var LEFT_SHADOW_INSET = 3.0,
*/
@implementation CPImageView : CPControl
{
DOMElement _DOMImageElement;
BOOL _hasShadow;
CPView _shadowView;
DOMElement _DOMImageElement;
BOOL _isEditable;
BOOL _hasShadow;
CPView _shadowView;
CGRect _imageRect;
BOOL _isEditable;
CGRect _imageRect;
CPImageAlignment _imageAlignment;
}
+ (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)
@@ -95,11 +96,11 @@ var LEFT_SHADOW_INSET = 3.0,
}
CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement);
_DOMImageElement.style.visibility = "hidden";
#endif
}
return self;
}
@@ -120,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] : "";
_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;
@@ -161,7 +162,7 @@ var LEFT_SHADOW_INSET = 3.0,
- (void)imageDidLoad:(CPNotification)aNotification
{
[self hideOrDisplayContents];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -183,28 +184,52 @@ 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];
}
/*!
Sets the type of image alignment that should be used to
render the image.
@param anImageAlignment the type of scaling to use
*/
- (void)setImageAlignment:(CPImageAlignment)anImageAlignment
{
if (_imageAlignment == anImageAlignment)
return;
_imageAlignment = anImageAlignment;
if (![self image])
return;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
- (unsigned)imageAlignment
{
return _imageAlignment;
}
/*!
Sets the type of image scaling that should be used to
render the image.
@@ -213,18 +238,23 @@ 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];
}
- (unsigned)imageScaling
{
return [self currentValueForThemeAttribute:@"image-scaling"];
}
/*!
Toggles the display of the image view.
*/
@@ -284,7 +314,7 @@ var LEFT_SHADOW_INSET = 3.0,
else
{
var size = [image size];
if (size.width == -1 && size.height == -1)
return;
@@ -301,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
@@ -318,7 +348,7 @@ var LEFT_SHADOW_INSET = 3.0,
width = size.width;
height = size.height;
}
if (imageScaling == CPScaleNone)
{
#if PLATFORM(DOM)
@@ -327,8 +357,46 @@ var LEFT_SHADOW_INSET = 3.0,
#endif
}
var x = (boundsWidth - width) / 2.0,
y = (boundsHeight - height) / 2.0;
var x,
y;
switch (_imageAlignment)
{
case CPImageAlignLeft:
case CPImageAlignTopLeft:
case CPImageAlignBottomLeft:
x = 0.0;
break;
case CPImageAlignRight:
case CPImageAlignTopRight:
case CPImageAlignBottomRight:
x = boundsWidth - width;
break;
default:
x = (boundsWidth - width) / 2.0;
break;
}
switch (_imageAlignment)
{
case CPImageAlignTop:
case CPImageAlignTopLeft:
case CPImageAlignTopRight:
y = 0.0;
break;
case CPImageAlignBottom:
case CPImageAlignBottomLeft:
case CPImageAlignBottomRight:
y = boundsHeight - height;
break;
default:
y = (boundsHeight - height) / 2.0;
break;
}
#if PLATFORM(DOM)
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, x, y);
@@ -336,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)];
}
@@ -374,20 +442,26 @@ var LEFT_SHADOW_INSET = 3.0,
return _isEditable;
}
- (void)performDragOperation:(CPDraggingInfo)aSender
- (BOOL)performDragOperation:(CPDraggingInfo)aSender
{
var images = [CPKeyedUnarchiver unarchiveObjectWithData:[[aSender draggingPasteboard] dataForType:CPImagesPboardType]];
if ([images count])
{
[self setImage:images[0]];
[self sendAction:[self action] to:[self target]];
}
return YES;
}
@end
var CPImageViewImageKey = @"CPImageViewImageKey",
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
var CPImageViewImageKey = @"CPImageViewImageKey",
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
CPImageViewImageAlignmentKey = @"CPImageViewImageAlignmentKey",
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
@implementation CPImageView (CPCoding)
@@ -412,7 +486,7 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
#endif
self = [super initWithCoder:aCoder];
if (self)
{
#if PLATFORM(DOM)
@@ -420,14 +494,15 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
#endif
[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;
}
@@ -438,22 +513,23 @@ 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];
if (_isEditable)
[aCoder encodeBool:_isEditable forKey:CPImageViewIsEditableKey];
+263
View File
@@ -0,0 +1,263 @@
/*
* CPKeyBinding.j
* AppKit
*
* Created by Nicholas Small.
* 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 <Foundation/CPObject.j>
@import "CPEvent.j"
CPStandardKeyBindings = {
@"@.": @"cancelOperation:",
@"^a": @"moveToBeginningOfParagraph:",
@"^$a": @"moveToBeginningOfParagraphAndModifySelection:",
@"^b": @"moveBackward:",
@"^$b": @"moveBackwardAndModifySelection:",
@"^~b": @"moveWordBackward:",
@"^~$b": @"moveWordBackwardAndModifySelection:",
@"^d": @"deleteForward:",
@"^e": @"moveToEndOfParagraph:",
@"^$e": @"moveToEndOfParagraphAndModifySelection:",
@"^f": @"moveForward:",
@"^$f": @"moveForwardAndModifySelection:",
@"^~f": @"moveWordForward:",
@"^~$f": @"moveWordForwardAndModifySelection:",
@"^h": @"deleteBackward:",
@"^k": @"deleteToEndOfParagraph:",
@"^l": @"centerSelectionInVisibleArea:",
@"^n": @"moveDown:",
@"^$n": @"moveDownAndModifySelection:",
@"^o": [@"insertNewlineIgnoringFieldEditor:", @"moveBackward:"],
@"^p": @"moveUp:",
@"^$p": @"moveUpAndModifySelection:",
@"^t": @"transpose:",
@"^v": @"pageDown:",
@"^$v": @"pageDownAndModifySelection:",
@"^y": @"yank:"
};
CPStandardKeyBindings[CPNewlineCharacter] = @"insertNewline:";
CPStandardKeyBindings[CPCarriageReturnCharacter] = @"insertNewline:";
CPStandardKeyBindings[CPEnterCharacter] = @"insertNewline:";
CPStandardKeyBindings[@"~" + CPNewlineCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"~" + CPCarriageReturnCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"~" + CPEnterCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"^" + CPNewlineCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[@"^" + CPCarriageReturnCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[@"^" + CPEnterCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[CPBackspaceCharacter] = @"deleteBackward:";
CPStandardKeyBindings[@"~" + CPBackspaceCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[CPDeleteCharacter] = @"deleteBackward:";
CPStandardKeyBindings[@"@" + CPDeleteCharacter] = @"deleteToBeginningOfLine:";
CPStandardKeyBindings[@"~" + CPDeleteCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[@"^" + CPDeleteCharacter] = @"deleteBackwardByDecomposingPreviousCharacter:";
CPStandardKeyBindings[@"^~" + CPDeleteCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[CPDeleteFunctionKey] = @"deleteForward:";
CPStandardKeyBindings[@"~" + CPDeleteFunctionKey] = @"deleteWordForward:";
CPStandardKeyBindings[CPTabCharacter] = @"insertTab:";
CPStandardKeyBindings[@"~" + CPTabCharacter] = @"insertTabIgnoringFieldEditor:";
CPStandardKeyBindings[@"^" + CPTabCharacter] = @"selectNextKeyView:";
CPStandardKeyBindings[CPBackTabCharacter] = @"insertBacktab:";
CPStandardKeyBindings[@"^" + CPBackTabCharacter] = @"selectPreviousKeyView:";
CPStandardKeyBindings[CPEscapeFunctionKey] = @"cancelOperation:";
CPStandardKeyBindings[@"~" + CPEscapeFunctionKey] = @"complete:";
CPStandardKeyBindings[CPF5FunctionKey] = @"complete:";
CPStandardKeyBindings[CPLeftArrowFunctionKey] = @"moveLeft:";
CPStandardKeyBindings[@"~" + CPLeftArrowFunctionKey] = @"moveWordLeft:";
CPStandardKeyBindings[@"^" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLine:";
CPStandardKeyBindings[@"@" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLine:";
CPStandardKeyBindings[@"$" + CPLeftArrowFunctionKey] = @"moveLeftAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPLeftArrowFunctionKey] = @"moveWordLeftAndModifySelection:";
CPStandardKeyBindings[@"$^" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPLeftArrowFunctionKey] = @"makeBaseWritingDirectionRightToLeft:";
CPStandardKeyBindings[@"@^~" + CPLeftArrowFunctionKey] = @"makeTextWritingDirectionRightToLeft:";
CPStandardKeyBindings[CPRightArrowFunctionKey] = @"moveRight:";
CPStandardKeyBindings[@"~" + CPRightArrowFunctionKey] = @"moveWordRight:";
CPStandardKeyBindings[@"^" + CPRightArrowFunctionKey] = @"moveToRightEndOfLine:";
CPStandardKeyBindings[@"@" + CPRightArrowFunctionKey] = @"moveToRightEndOfLine:";
CPStandardKeyBindings[@"$" + CPRightArrowFunctionKey] = @"moveRightAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPRightArrowFunctionKey] = @"moveWordRightAndModifySelection:";
CPStandardKeyBindings[@"$^" + CPRightArrowFunctionKey] = @"moveToRightEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPRightArrowFunctionKey] = @"moveToRightEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPRightArrowFunctionKey] = @"makeBaseWritingDirectionLeftToRight:";
CPStandardKeyBindings[@"@^~" + CPRightArrowFunctionKey] = @"makeTextWritingDirectionLeftToRight:";
CPStandardKeyBindings[CPUpArrowFunctionKey] = @"moveUp:";
CPStandardKeyBindings[@"~" + CPUpArrowFunctionKey] = [@"moveBackward:", @"moveToBeginningOfParagraph:"];
CPStandardKeyBindings[@"^" + CPUpArrowFunctionKey] = @"scrollPageUp:";
CPStandardKeyBindings[@"@" + CPUpArrowFunctionKey] = @"moveToBeginningOfDocument:";
CPStandardKeyBindings[@"$" + CPUpArrowFunctionKey] = @"moveUpAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPUpArrowFunctionKey] = @"moveParagraphBackwardAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPUpArrowFunctionKey] = @"moveToBeginningOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPDownArrowFunctionKey] = @"moveDown:";
CPStandardKeyBindings[@"~" + CPDownArrowFunctionKey] = [@"moveForward:", @"moveToEndOfParagraph:"];
CPStandardKeyBindings[@"^" + CPDownArrowFunctionKey] = @"scrollPageDown:";
CPStandardKeyBindings[@"@" + CPDownArrowFunctionKey] = @"moveToEndOfDocument:";
CPStandardKeyBindings[@"$" + CPDownArrowFunctionKey] = @"moveDownAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPDownArrowFunctionKey] = @"moveParagraphForwardAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPDownArrowFunctionKey] = @"moveToEndOfDocumentAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPDownArrowFunctionKey] = @"makeBaseWritingDirectionNatural:";
CPStandardKeyBindings[@"@^~" + CPDownArrowFunctionKey] = @"makeTextWritingDirectionNatural:";
CPStandardKeyBindings[CPHomeFunctionKey] = @"scrollToBeginningOfDocument:";
CPStandardKeyBindings[@"$" + CPHomeFunctionKey] = @"moveToBeginningOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPEndFunctionKey] = @"scrollToEndOfDocument:";
CPStandardKeyBindings[@"$" + CPEndFunctionKey] = @"moveToEndOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPPageUpFunctionKey] = @"scrollPageUp:";
CPStandardKeyBindings[@"~" + CPPageUpFunctionKey] = @"pageUp:";
CPStandardKeyBindings[@"$" + CPPageUpFunctionKey] = @"pageUpAndModifySelection:";
CPStandardKeyBindings[CPPageDownFunctionKey] = @"scrollPageDown:";
CPStandardKeyBindings[@"~" + CPPageDownFunctionKey] = @"pageDown:";
CPStandardKeyBindings[@"$" + CPPageDownFunctionKey] = @"pageDownAndModifySelection:";
var CPKeyBindingCache = {};
@implementation CPKeyBinding : CPObject
{
CPString _key;
unsigned _modifierFlags;
CPArray _selectors;
CPString _cacheName;
}
+ (void)initialize
{
if ([self class] !== CPKeyBinding)
return;
[self createKeyBindingsFromJSObject:CPStandardKeyBindings];
}
+ (void)createKeyBindingsFromJSObject:(JSObject)anObject
{
var binding;
for (binding in anObject)
[self cacheKeyBinding:[[CPKeyBinding alloc] initWithPhysicalKeyString:binding selectors:anObject[binding]]];
}
+ (void)cacheKeyBinding:(CPKeyBinding)aBinding
{
if (!aBinding)
return;
CPKeyBindingCache[[aBinding _cacheName]] = aBinding;
}
+ (CPKeyBinding)keyBindingForKey:(CPString)aKey modifierFlags:(unsigned)aFlag
{
var tempBinding = [[self alloc] initWithKey:aKey modifierFlags:aFlag selectors:nil];
return CPKeyBindingCache[[tempBinding _cacheName]];
}
+ (CPArray)selectorsForKey:(CPString)aKey modifierFlags:(unsigned)aFlag
{
return [[self keyBindingForKey:aKey modifierFlags:aFlag] selectors];
}
- (id)initWithPhysicalKeyString:(CPString)binding selectors:(CPArray)selectors
{
var components = binding.split(@""),
modifierFlags = ([components containsObject:@"$"] ? CPShiftKeyMask : 0) |
([components containsObject:@"^"] ? CPControlKeyMask : 0) |
([components containsObject:@"~"] ? CPAlternateKeyMask : 0) |
([components containsObject:@"@"] ? CPCommandKeyMask : 0);
if (![selectors isKindOfClass:CPArray])
selectors = [selectors];
return [self initWithKey:[components lastObject] modifierFlags:modifierFlags selectors:selectors];
}
- (id)initWithKey:(CPString)aKey modifierFlags:(unsigned)aFlag selectors:(CPArray)selectors
{
self = [super init];
if (self)
{
_key = aKey;
_modifierFlags = aFlag;
_selectors = selectors;
// We normalize our key binding string in order to properly cache it.
// We want to ensure the modifiers are always in the same order.
var cacheName = [];
if (_modifierFlags & CPCommandKeyMask)
cacheName.push(@"@");
if (_modifierFlags & CPControlKeyMask)
cacheName.push(@"^");
if (_modifierFlags & CPAlternateKeyMask)
cacheName.push(@"~");
if (_modifierFlags & CPShiftKeyMask)
cacheName.push(@"$");
cacheName.push(_key);
_cacheName = cacheName.join(@"");
}
return self;
}
- (CPString)key
{
return _key;
}
- (unsigned)modifierFlags
{
return _modifierFlags;
}
- (CPArray)selectors
{
return _selectors;
}
- (CPString)_cacheName
{
return _cacheName;
}
- (BOOL)isEqual:(CPKeyBinding)rhs
{
return _key === [rhs key] && _modifierFlags === [rhs modifierFlags];
}
- (CPString)description
{
return [CPString stringWithFormat:@"<KeyBinding string: '%@' modifierFlags: 0x%lx selectors: %@>", _key, _modifierFlags, _selectors];
}
@end
+521
View File
@@ -0,0 +1,521 @@
/*
* CPKeyValueBinding.j
* AppKit
*
* Created by Ross Boucher 1/13/09
* Copyright 280 North, Inc.
*
* Adapted from GNUStep
* Released under the LGPL.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPArray.j>
@import <Foundation/CPDictionary.j>
@import <Foundation/CPValueTransformer.j>
var exposedBindingsMap = [CPDictionary new],
bindingsMap = [CPDictionary new];
var CPBindingOperationAnd = 0,
CPBindingOperationOr = 1;
@implementation CPBinder : CPObject
{
CPDictionary _info;
id _source;
JSObject _suppressedNotifications;
}
+ (void)exposeBinding:(CPString)aBinding forClass:(Class)aClass
{
var bindings = [exposedBindingsMap objectForKey:[aClass UID]];
if (!bindings)
{
bindings = [];
[exposedBindingsMap setObject:bindings forKey:[aClass UID]];
}
bindings.push(aBinding);
}
+ (CPArray)exposedBindingsForClass:(Class)aClass
{
return [[exposedBindingsMap objectForKey:[aClass UID]] copy];
}
+ (CPBinder)getBinding:(CPString)aBinding forObject:(id)anObject
{
return [[bindingsMap objectForKey:[anObject UID]] objectForKey:aBinding];
}
+ (CPDictionary)infoForBinding:(CPString)aBinding forObject:(id)anObject
{
var theBinding = [self getBinding:aBinding forObject:anObject];
if (theBinding)
return theBinding._info;
return nil;
}
+ (CPDictionary)allBindingsForObject:(id)anObject
{
return [bindingsMap objectForKey:[anObject UID]];
}
+ (void)unbind:(CPString)aBinding forObject:(id)anObject
{
var bindings = [bindingsMap objectForKey:[anObject UID]];
if (!bindings)
return;
var theBinding = [bindings objectForKey:aBinding];
if (!theBinding)
return;
var infoDictionary = theBinding._info,
observedObject = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey];
[observedObject removeObserver:theBinding forKeyPath:keyPath];
[bindings removeObjectForKey:aBinding];
}
+ (void)unbindAllForObject:(id)anObject
{
var bindings = [bindingsMap objectForKey:[anObject UID]];
if (!bindings)
return;
var allKeys = [bindings allKeys],
count = allKeys.length;
while (count--)
[anObject unbind:[bindings objectForKey:allKeys[count]]];
[bindingsMap removeObjectForKey:[anObject UID]];
}
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
{
self = [super init];
if (self)
{
_source = aSource;
_info = [CPDictionary dictionaryWithObjects:[aDestination, aKeyPath] forKeys:[CPObservedObjectKey, CPObservedKeyPathKey]];
_suppressedNotifications = {};
if (options)
[_info setObject:options forKey:CPOptionsKey];
[aDestination addObserver:self forKeyPath:aKeyPath options:CPKeyValueObservingOptionNew context:aBinding];
var bindings = [bindingsMap objectForKey:[_source UID]];
if (!bindings)
{
bindings = [CPDictionary new];
[bindingsMap setObject:bindings forKey:[_source UID]];
}
[bindings setObject:self forKey:aName];
[self setValueFor:aBinding];
}
return self;
}
- (void)setValueFor:(CPString)aBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath];
newValue = [self transformValue:newValue withOptions:options];
[_source setValue:newValue forKey:aBinding];
}
- (void)reverseSetValueFor:(CPString)aBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [_source valueForKeyPath:aBinding];
newValue = [self reverseTransformValue:newValue withOptions:options];
[destination setValue:newValue forKeyPath:keyPath];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
{
if (!changes)
return;
var objectSuppressions = _suppressedNotifications[[anObject UID]];
if (objectSuppressions && objectSuppressions[aKeyPath])
return;
[self setValueFor:context];
}
- (id)transformValue:(id)aValue withOptions:(CPDictionary)options
{
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
if (valueTransformerName)
{
valueTransformer = [CPValueTransformer valueTransformerForName:valueTransformerName];
if (!valueTransformer)
{
var valueTransformerClass = CPClassFromString(valueTransformerName);
if (valueTransformerClass)
{
valueTransformer = [[valueTransformerClass alloc] init];
[valueTransformerClass setValueTransformer:valueTransformer forName:valueTransformerName];
}
}
}
else
valueTransformer = [options objectForKey:CPValueTransformerBindingOption];
if (valueTransformer)
aValue = [valueTransformer transformedValue:aValue];
if (aValue === undefined || aValue === nil || aValue === [CPNull null])
aValue = [options objectForKey:CPNullPlaceholderBindingOption] || nil;
return aValue;
}
- (id)reverseTransformValue:(id)aValue withOptions: (CPDictionary)options
{
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
if (valueTransformerName)
valueTransformer = [CPValueTransformer valueTransformerForName:valueTransformerName];
else
valueTransformer = [options objectForKey:CPValueTransformerBindingOption];
if (valueTransformer && [[valueTransformer class] allowsReverseTransformation])
aValue = [valueTransformer reverseTransformedValue:aValue];
return aValue;
}
- (BOOL)continuouslyUpdatesValue
{
var options = [_info objectForKey:CPOptionsKey];
return [[options objectForKey:CPContinuouslyUpdatesValueBindingOption] boolValue];
}
- (BOOL)handlesContentAsCompoundValue
{
var options = [_info objectForKey:CPOptionsKey];
return [[options objectForKey:CPHandlesContentAsCompoundValueBindingOption] boolValue];
}
/*!
Use this to avoid reacting to the notifications coming out of a reverseTransformedValue:.
*/
- (void)suppressSpecificNotificationFromObject:(id)anObject keyPath:(CPString)aKeyPath
{
if (!anObject)
return;
var uid = [anObject UID],
objectSuppressions = _suppressedNotifications[uid];
if (!objectSuppressions)
_suppressedNotifications[uid] = objectSuppressions = {};
objectSuppressions[aKeyPath] = YES;
}
/*!
Use this to cancel suppressSpecificNotificationFromObject:keyPath:.
*/
- (void)unsuppressSpecificNotificationFromObject:(id)anObject keyPath:(CPString)aKeyPath
{
if (!anObject)
return;
var uid = [anObject UID],
objectSuppressions = _suppressedNotifications[uid];
if (!objectSuppressions)
return;
delete objectSuppressions[aKeyPath];
}
@end
@implementation CPObject (KeyValueBindingCreation)
+ (void)exposeBinding:(CPString)aBinding
{
[CPBinder exposeBinding:aBinding forClass:[self class]];
}
+ (Class)_binderClassForBinding:(CPString)theBinding
{
return [CPBinder class];
}
- (CPArray)exposedBindings
{
var exposedBindings = [],
theClass = [self class];
while (theClass)
{
var temp = [CPBinder exposedBindingsForClass:theClass];
if (temp)
[exposedBindings addObjectsFromArray:temp];
theClass = [theClass superclass];
}
return exposedBindings;
}
- (Class)valueClassForBinding:(CPString)binding
{
return [CPString class];
}
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
{
if (!anObject || !aKeyPath)
return CPLog.error("Invalid object or path on "+self+" for "+aBinding);
//if (![[self exposedBindings] containsObject:aBinding])
// CPLog.warn("No binding exposed on "+self+" for "+aBinding);
var binderClass = [[self class] _binderClassForBinding:aBinding];
[self unbind:aBinding];
[[binderClass alloc] initWithBinding:[self _replacementKeyPathForBinding:aBinding] name:aBinding to:anObject keyPath:aKeyPath options:options from:self];
}
- (CPDictionary)infoForBinding:(CPString)aBinding
{
return [CPBinder infoForBinding:aBinding forObject:self];
}
- (void)unbind:(CPString)aBinding
{
var binderClass = [[self class] _binderClassForBinding:aBinding];
[binderClass unbind:aBinding forObject:self];
}
- (id)_replacementKeyPathForBinding:(CPString)binding
{
return binding;
}
@end
/*!
@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 UID]];
if (!bindings)
return;
[_source setValue:resolveMultipleValues(aBinding, bindings, CPBindingOperationOr) forKey:aBinding];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
{
[self setValueFor:context];
}
@end
@implementation _CPKeyValueAndBinding : CPBinder
{
}
- (void)setValueFor:(CPString)aBinding
{
var bindings = [bindingsMap objectForKey:[_source UID]];
if (!bindings)
return;
[_source setValue:resolveMultipleValues(aBinding, bindings, CPBindingOperationAnd) forKey:aBinding];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObejct change:(CPDictionary)changes context:(id)context
{
[self setValueFor:context];
}
@end
var resolveMultipleValues = function resolveMultipleValues(/*CPString*/key, /*CPDictionary*/bindings, /*GSBindingOperationKind*/operation)
{
var bindingName = key,
theBinding,
count = 1;
while (theBinding = [bindings objectForKey:bindingName])
{
var infoDictionary = theBinding._info,
object = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey],
options = [infoDictionary objectForKey:CPOptionsKey];
var value = [theBinding transformValue:[object valueForKeyPath:keyPath] withOptions:options];
if (value == operation)
return operation;
bindingName = [CPString stringWithFormat:@"%@%i", key, ++count];
}
return !operation;
}
var invokeAction = function invokeAction(/*CPString*/targetKey, /*CPString*/argumentKey, /*CPDictionary*/bindings)
{
var theBinding = [bindings objectForKey:targetKey],
infoDictionary = theBinding._info,
object = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey],
options = [infoDictionary objectForKey:CPOptionsKey],
target = [object valueForKeyPath:keyPath],
selector = [options objectForKey:CPSelectorNameBindingOption];
if (!target || !selector)
return;
var invocation = [CPInvocation invocationWithMethodSignature:[target methodSignatureForSelector:selector]];
[invocation setSelector:selector];
var bindingName = argumentKey,
count = 1;
while (theBinding = [bindings objectForKey:bindingName])
{
infoDictionary = theBinding._info;
keyPath = [infoDictionary objectForKey:CPObserverKeyPathKey];
object = [[infoDictionary objectForKey:CPObservedObjectKey] valueForKeyPath:keyPath];
if (object)
[invocation setArgument:object atIndex:++count];
bindingName = [CPString stringWithFormat:@"%@%i", argumentKey, count];
}
[invocation invoke];
}
// Keys in options dictionary
// Keys in dictionary returned by infoForBinding
CPObservedObjectKey = @"CPObservedObjectKey";
CPObservedKeyPathKey = @"CPObservedKeyPathKey";
CPOptionsKey = @"CPOptionsKey";
// special markers
CPMultipleValuesMarker = @"CPMultipleValuesMarker";
CPNoSelectionMarker = @"CPNoSelectionMarker";
CPNotApplicableMarker = @"CPNotApplicableMarker";
CPNullMarker = @"CPNullMarker";
// Binding name constants
CPAlignmentBinding = @"alignment";
CPEditableBinding = @"editable";
CPEnabledBinding = @"enabled";
CPFontBinding = @"font";
CPHiddenBinding = @"hidden";
CPSelectedIndexBinding = @"selectedIndex";
CPTextColorBinding = @"textColor";
CPToolTipBinding = @"toolTip";
CPValueBinding = @"value";
//Binding options constants
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)
{
return anObject === CPMultipleValuesMarker || anObject === CPNoSelectionMarker || anObject === CPNotApplicableMarker || anObject === CPNullMarker;
}
+412
View File
@@ -0,0 +1,412 @@
/*
* CPLevelIndicator.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2011, WireLoad 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 "CPControl.j"
CPTickMarkBelow = 0;
CPTickMarkAbove = 1;
CPTickMarkLeft = CPTickMarkAbove;
CPTickMarkRight = CPTickMarkBelow;
CPRelevancyLevelIndicatorStyle = 0;
CPContinuousCapacityLevelIndicatorStyle = 1;
CPDiscreteCapacityLevelIndicatorStyle = 2;
CPRatingLevelIndicatorStyle = 3;
var _CPLevelIndicatorBezelColor = nil,
_CPLevelIndicatorSegmentEmptyColor = nil,
_CPLevelIndicatorSegmentNormalColor = nil,
_CPLevelIndicatorSegmentWarningColor = nil,
_CPLevelIndicatorSegmentCriticalColor = nil,
_CPLevelIndicatorSpacing = 1;
/*!
@ingroup appkit
@class CPLevelIndicator
CPLevelIndicator is a control which indicates a value visually on a scale.
*/
@implementation CPLevelIndicator : CPControl
{
CPLevelIndicator _levelIndicatorStyle @accessors(property=levelIndicatorStyle);
double _minValue @accessors(property=minValue);
double _maxValue @accessors(property=maxValue);
double _warningValue @accessors(property=warningValue);
double _criticalValue @accessors(property=criticalValue);
CPTickMarkPosition _tickMarkPosition @accessors(property=tickMarkPosition);
int _numberOfTickMarks @accessors(property=numberOfTickMarks);
int _numberOfMajorTickMarks @accessors(property=numberOfMajorTickMarks);
BOOL _isEditable;
BOOL _isTracking;
}
+ (void)initialize
{
var bundle = [CPBundle bundleForClass:CPLevelIndicator];
_CPLevelIndicatorBezelColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-bezel-left.png"] size:CGSizeMake(3.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-bezel-center.png"] size:CGSizeMake(1.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-bezel-right.png"] size:CGSizeMake(3.0, 18.0)]
]
isVertical:NO
]];
_CPLevelIndicatorSegmentEmptyColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-empty-left.png"] size:CGSizeMake(3.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-empty-center.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-empty-right.png"] size:CGSizeMake(3.0, 17.0)]
]
isVertical:NO
]];
_CPLevelIndicatorSegmentNormalColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-normal-left.png"] size:CGSizeMake(3.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-normal-center.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-normal-right.png"] size:CGSizeMake(3.0, 17.0)]
]
isVertical:NO
]];
_CPLevelIndicatorSegmentWarningColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-warning-left.png"] size:CGSizeMake(3.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-warning-center.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-warning-right.png"] size:CGSizeMake(3.0, 17.0)]
]
isVertical:NO
]];
_CPLevelIndicatorSegmentCriticalColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-critical-left.png"] size:CGSizeMake(3.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-critical-center.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-critical-right.png"] size:CGSizeMake(3.0, 17.0)]
]
isVertical:NO
]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_levelIndicatorStyle = CPDiscreteCapacityLevelIndicatorStyle;
_maxValue = 2;
_warningValue = 2;
_criticalValue = 2;
[self _init];
}
return self;
}
- (void)_init
{
}
- (void)layoutSubviews
{
var bezelView = [self layoutEphemeralSubviewNamed:"bezel"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
// TODO Make themable.
[bezelView setBackgroundColor:_CPLevelIndicatorBezelColor];
var segmentCount = _maxValue - _minValue;
if (segmentCount <= 0)
return;
var filledColor = _CPLevelIndicatorSegmentNormalColor,
value = [self doubleValue];
if (value < _criticalValue)
filledColor = _CPLevelIndicatorSegmentCriticalColor;
else if (value < _warningValue)
filledColor = _CPLevelIndicatorSegmentWarningColor;
for (var i = 0; i < segmentCount; i++)
{
var segmentView = [self layoutEphemeralSubviewNamed:"segment-bezel-" + i
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:bezelView];
[segmentView setBackgroundColor:(_minValue + i) < value ? filledColor : _CPLevelIndicatorSegmentEmptyColor];
}
}
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
{
// TODO Put into theme attributes.
var bezelHeight = 18,
segmentHeight = 17,
bounds = _CGRectCreateCopy([self bounds]);
if (aViewName == "bezel")
{
bounds.origin.y = (_CGRectGetHeight(bounds) - bezelHeight) / 2.0;
bounds.size.height = bezelHeight;
return bounds;
}
else if (aViewName.indexOf("segment-bezel") === 0)
{
var segment = parseInt(aViewName.substring("segment-bezel-".length), 10),
segmentCount = _maxValue - _minValue;
if (segment >= segmentCount)
return _CGRectMakeZero();
var basicSegmentWidth = bounds.size.width / segmentCount,
segmentFrame = CGRectCreateCopy([self bounds]);
segmentFrame.origin.y = (_CGRectGetHeight(bounds) - bezelHeight) / 2.0;
segmentFrame.origin.x = FLOOR(segment * basicSegmentWidth);
segmentFrame.size.width = (segment == segmentCount - 1) ? bounds.size.width - segmentFrame.origin.x : FLOOR(((segment + 1) * basicSegmentWidth)) - FLOOR((segment * basicSegmentWidth)) - _CPLevelIndicatorSpacing;
segmentFrame.size.height = segmentHeight;
return segmentFrame;
}
return _CGRectMakeZero();
}
/*!
Sets whether or not the receiver level indicator can be edited.
*/
- (void)setEditable:(BOOL)shouldBeEditable
{
if (_isEditable === shouldBeEditable)
return;
_isEditable = shouldBeEditable;
}
/*!
Returns \c YES if the textfield is currently editable by the user.
*/
- (BOOL)isEditable
{
return _isEditable;
}
- (CPView)hitTest:(CPPoint)aPoint
{
// Don't swallow clicks when displayed in a table.
if (![self isEditable])
return nil;
return [super hitTest:aPoint];
}
- (void)mouseDown:(CPEvent)anEvent
{
if (![self isEditable] || ![self isEnabled])
return;
[self _trackMouse:anEvent];
}
- (void)_trackMouse:(CPEvent)anEvent
{
var type = [anEvent type];
if (type == CPLeftMouseDown || type == CPLeftMouseDragged)
{
var segmentCount = _maxValue - _minValue;
if (segmentCount <= 0)
return;
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
bounds = [self bounds],
oldValue = [self doubleValue];
newValue = oldValue;
// Moving the mouse outside of the widget to the left sets it
// to its minimum, and moving outside on the right sets it to
// its maximum.
if (type == CPLeftMouseDragged && location.x < 0)
{
newValue = _minValue;
}
else if (type == CPLeftMouseDragged && location.x > bounds.size.width)
{
newValue = _maxValue;
}
else
{
for (var i = 0; i < segmentCount; i++)
{
var rect = [self rectForEphemeralSubviewNamed:"segment-bezel-" + i];
// Once we're tracking the mouse, we only care about horizontal mouse movement.
if (location.x >= CGRectGetMinX(rect) && location.x < CGRectGetMaxX(rect))
{
newValue = (_minValue + i + 1);
break;
}
}
}
if (newValue != oldValue)
[self setDoubleValue:newValue];
// Track the mouse to support click and slide value editing.
_isTracking = YES;
[CPApp setTarget:self selector:@selector(_trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
if ([self isContinuous])
[self sendAction:[self action] to:[self target]];
}
else if (_isTracking)
{
_isTracking = NO;
[self sendAction:[self action] to:[self target]];
}
}
/*
- (CPLevelIndicatorStyle)style;
- (void)setLevelIndicatorStyle:(CPLevelIndicatorStyle)style;
*/
- (void)setMinValue:(double)minValue
{
if (_minValue === minValue)
return;
_minValue = minValue;
[self setNeedsLayout];
}
- (void)setMaxValue:(double)maxValue
{
if (_maxValue === maxValue)
return;
_maxValue = maxValue;
[self setNeedsLayout];
}
- (void)setWarningValue:(double)warningValue;
{
if (_warningValue === warningValue)
return;
_warningValue = warningValue;
[self setNeedsLayout];
}
- (void)setCriticalValue:(double)criticalValue;
{
if (_criticalValue === criticalValue)
return;
_criticalValue = criticalValue;
[self setNeedsLayout];
}
/*
- (CPTickMarkPosition)tickMarkPosition;
- (void)setTickMarkPosition:(CPTickMarkPosition)position;
- (int)numberOfTickMarks;
- (void)setNumberOfTickMarks:(int)count;
- (int)numberOfMajorTickMarks;
- (void)setNumberOfMajorTickMarks:(int)count;
- (double)tickMarkValueAtIndex:(int)index;
- (CGRect)rectOfTickMarkAtIndex:(int)index;
*/
@end
var CPLevelIndicatorStyleKey = "CPLevelIndicatorStyleKey",
CPLevelIndicatorMinValueKey = "CPLevelIndicatorMinValueKey",
CPLevelIndicatorMaxValueKey = "CPLevelIndicatorMaxValueKey",
CPLevelIndicatorWarningValueKey = "CPLevelIndicatorWarningValueKey",
CPLevelIndicatorCriticalValueKey = "CPLevelIndicatorCriticalValueKey",
CPLevelIndicatorTickMarkPositionKey = "CPLevelIndicatorTickMarkPositionKey",
CPLevelIndicatorNumberOfTickMarksKey = "CPLevelIndicatorNumberOfTickMarksKey",
CPLevelIndicatorNumberOfMajorTickMarksKey = "CPLevelIndicatorNumberOfMajorTickMarksKey",
CPLevelIndicatorIsEditableKey = "CPLevelIndicatorIsEditableKey";
@implementation CPLevelIndicator (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_levelIndicatorStyle = [aCoder decodeIntForKey:CPLevelIndicatorStyleKey];
_minValue = [aCoder decodeDoubleForKey:CPLevelIndicatorMinValueKey];
_maxValue = [aCoder decodeDoubleForKey:CPLevelIndicatorMaxValueKey];
_warningValue = [aCoder decodeDoubleForKey:CPLevelIndicatorWarningValueKey];
_criticalValue = [aCoder decodeDoubleForKey:CPLevelIndicatorCriticalValueKey];
_tickMarkPosition = [aCoder decodeIntForKey:CPLevelIndicatorTickMarkPositionKey];
_numberOfTickMarks = [aCoder decodeIntForKey:CPLevelIndicatorNumberOfTickMarksKey];
_numberOfMajorTickMarks = [aCoder decodeIntForKey:CPLevelIndicatorNumberOfMajorTickMarksKey];
_isEditable = [aCoder decodeBoolForKey:CPLevelIndicatorIsEditableKey];
[self _init];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeInt:_levelIndicatorStyle forKey:CPLevelIndicatorStyleKey];
[aCoder encodeDouble:_minValue forKey:CPLevelIndicatorMinValueKey];
[aCoder encodeDouble:_maxValue forKey:CPLevelIndicatorMaxValueKey];
[aCoder encodeDouble:_warningValue forKey:CPLevelIndicatorWarningValueKey];
[aCoder encodeDouble:_criticalValue forKey:CPLevelIndicatorCriticalValueKey];
[aCoder encodeInt:_tickMarkPosition forKey:CPLevelIndicatorTickMarkPositionKey];
[aCoder encodeInt:_numberOfTickMarks forKey:CPLevelIndicatorNumberOfTickMarksKey];
[aCoder encodeInt:_numberOfMajorTickMarks forKey:CPLevelIndicatorNumberOfMajorTickMarksKey];
[aCoder encodeBool:_isEditable forKey:CPLevelIndicatorIsEditableKey];
}
@end
-2014
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+553
View File
@@ -0,0 +1,553 @@
@import "CPPanel.j"
@import "_CPMenuWindow.j"
var MENUBAR_HEIGHT = 28.0,
MENUBAR_MARGIN = 10.0,
MENUBAR_LEFT_MARGIN = 10.0,
MENUBAR_RIGHT_MARGIN = 10.0;
var _CPMenuBarWindowBackgroundColor = nil,
_CPMenuBarWindowFont = nil;
@implementation _CPMenuBarWindow : CPPanel
{
CPMenu _menu;
CPView _highlightView;
CPArray _menuItemViews;
CPMenuItem _trackingMenuItem;
CPImageView _iconImageView;
CPTextField _titleField;
CPColor _textColor;
CPColor _titleColor;
CPColor _textShadowColor;
CPColor _titleShadowColor;
CPColor _highlightColor;
CPColor _highlightTextColor;
CPColor _highlightTextShadowColor;
}
+ (void)initialize
{
if (self != [_CPMenuBarWindow class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPMenuBarWindowFont = [CPFont boldSystemFontOfSize:12.0];
}
+ (CPFont)font
{
return _CPMenuBarWindowFont;
}
- (id)init
{
// This only shows up in browser land, so don't bother calculating metrics in desktop.
var contentRect = [[CPPlatformWindow primaryPlatformWindow] contentBounds];
contentRect.size.height = MENUBAR_HEIGHT;
self = [super initWithContentRect:contentRect styleMask:CPBorderlessWindowMask];
if (self)
{
[self setLevel:CPMainMenuWindowLevel];
[self setAutoresizingMask:CPWindowWidthSizable];
var contentView = [self contentView];
[contentView setAutoresizesSubviews:NO];
[self setBecomesKeyOnlyIfNeeded:YES];
//
_iconImageView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 16.0, 16.0)];
[contentView addSubview:_iconImageView];
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_titleField setFont:[CPFont boldSystemFontOfSize:13.0]];
[_titleField setAlignment:CPCenterTextAlignment];
[_titleField setTextShadowOffset:CGSizeMake(0, 1)];
[contentView addSubview:_titleField];
}
return self;
}
- (void)setTitle:(CPString)aTitle
{
#if PLATFORM(DOM)
var bundleName = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPBundleName"];
if (![bundleName length])
document.title = aTitle;
else if ([aTitle length])
document.title = aTitle + @" - " + bundleName;
else
document.title = bundleName;
#endif
[_titleField setStringValue:aTitle];
[_titleField sizeToFit];
[self tile];
}
- (void)setIconImage:(CPImage)anImage
{
[_iconImageView setImage:anImage];
[_iconImageView setHidden:anImage == nil];
[self tile];
}
- (void)setIconImageAlphaValue:(float)anAlphaValue
{
[_iconImageView setAlphaValue:anAlphaValue];
}
- (void)setColor:(CPColor)aColor
{
if (!aColor)
{
if (!_CPMenuBarWindowBackgroundColor)
_CPMenuBarWindowBackgroundColor = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[_CPMenuBarWindow class]] pathForResource:@"_CPMenuBarWindow/_CPMenuBarWindowBackground.png"] size:CGSizeMake(1.0, 28.0)]];
[[self contentView] setBackgroundColor:_CPMenuBarWindowBackgroundColor];
}
else
[[self contentView] setBackgroundColor:aColor];
}
- (void)setTextColor:(CPColor)aColor
{
if (_textColor == aColor)
return;
_textColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setTextColor:) withObject:_textColor];
}
- (void)setTitleColor:(CPColor)aColor
{
if (_titleColor == aColor)
return;
_titleColor = aColor;
[_titleField setTextColor:aColor ? aColor : [CPColor blackColor]];
}
- (void)setTextShadowColor:(CPColor)aColor
{
if (_textShadowColor == aColor)
return;
_textShadowColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setTextShadowColor:) withObject:_textShadowColor];
}
- (void)setTitleShadowColor:(CPColor)aColor
{
if (_titleShadowColor == aColor)
return;
_titleShadowColor = aColor;
[_titleField setTextShadowColor:aColor ? aColor : [CPColor whiteColor]];
}
- (void)setHighlightColor:(CPColor)aColor
{
if (_highlightColor == aColor)
return;
_highlightColor = aColor;
}
- (void)setHighlightTextColor:(CPColor)aColor
{
if (_highlightTextColor == aColor)
return;
_highlightTextColor = aColor;
// [_menuItemViews makeObjectsPerformSelector:@selector(setActivateColor:) withObject:_highlightTextColor];
}
- (void)setHighlightTextShadowColor:(CPColor)aColor
{
if (_highlightTextShadowColor == aColor)
return;
_highlightTextShadowColor = aColor;
// [_menuItemViews makeObjectsPerformSelector:@selector(setActivateShadowColor:) withObject:_highlightTextShadowColor];
}
- (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];
var items = [_menu itemArray],
count = items.length;
while (count--)
[[items[count] _menuItemView] removeFromSuperview];
}
_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];
}
_menuItemViews = [];
var contentView = [self contentView],
items = [_menu itemArray],
count = items.length;
for (index = 0; index < count; ++index)
{
var item = items[index],
menuItemView = [item _menuItemView];
_menuItemViews.push(menuItemView);
[menuItemView setTextColor:_textColor];
[menuItemView setHidden:[item isHidden]];
[menuItemView synchronizeWithMenuItem];
[contentView addSubview:menuItemView];
}
[self tile];
}
- (void)menuDidChangeItem:(CPNotification)aNotification
{
var menuItem = [_menu itemAtIndex:[[aNotification userInfo] objectForKey:@"CPMenuItemIndex"]],
menuItemView = [menuItem _menuItemView];
[menuItemView setHidden:[menuItem isHidden]];
[menuItemView synchronizeWithMenuItem];
[self tile];
}
- (void)menuDidAddItem:(CPNotification)aNotification
{
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"],
menuItem = [_menu itemAtIndex:index],
menuItemView = [menuItem _menuItemView];
[_menuItemViews insertObject:menuItemView atIndex:index];
[menuItemView setTextColor:_textColor];
[menuItemView setHidden:[menuItem isHidden]];
[menuItemView synchronizeWithMenuItem];
[[self contentView] addSubview:menuItemView];
[self tile];
}
- (void)menuDidRemoveItem:(CPNotification)aNotification
{
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"],
menuItemView = [_menuItemViews objectAtIndex:index];
[_menuItemViews removeObjectAtIndex:index];
[menuItemView removeFromSuperview];
[self tile];
}
- (void)mouseDown:(CPEvent)anEvent
{
var constraintRect = CGRectInset([[self platformWindow] visibleFrame], 5.0, 0.0);
constraintRect.size.height -= 5.0;
[[_CPMenuManager sharedMenuManager]
beginTracking:anEvent
menuContainer:self
constraintRect:constraintRect
callback:function(aMenuContainer, aMenu)
{
[aMenu _performActionOfHighlightedItemChain];
[aMenu _highlightItemAtIndex:CPNotFound];
}];
}
- (CPFont)font
{
[CPFont systemFontOfSize:12.0];
}
- (void)tile
{
var items = [_menu itemArray],
index = 0,
count = items.length,
x = MENUBAR_LEFT_MARGIN,
y = 0.0,
isLeftAligned = YES;
for (; index < count; ++index)
{
var item = items[index];
if ([item isSeparatorItem])
{
x = CGRectGetWidth([self frame]) - MENUBAR_RIGHT_MARGIN;
isLeftAligned = NO;
continue;
}
if ([item isHidden])
continue;
var menuItemView = [item _menuItemView],
frame = [menuItemView frame];
if (isLeftAligned)
{
[menuItemView setFrame:CGRectMake(x, 0.0, CGRectGetWidth(frame), MENUBAR_HEIGHT)];
x += CGRectGetWidth([menuItemView frame]);
}
else
{
[menuItemView setFrame:CGRectMake(x - CGRectGetWidth(frame), 0.0, CGRectGetWidth(frame), MENUBAR_HEIGHT)];
x = CGRectGetMinX([menuItemView frame]);
}
}
var bounds = [[self contentView] bounds],
titleFrame = [_titleField frame];
if ([_iconImageView isHidden])
[_titleField setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(titleFrame)) / 2.0, (CGRectGetHeight(bounds) - CGRectGetHeight(titleFrame)) / 2.0)];
else
{
var iconFrame = [_iconImageView frame],
iconWidth = CGRectGetWidth(iconFrame),
totalWidth = iconWidth + CGRectGetWidth(titleFrame);
[_iconImageView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - totalWidth) / 2.0, (CGRectGetHeight(bounds) - CGRectGetHeight(iconFrame)) / 2.0)];
[_titleField setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - totalWidth) / 2.0 + iconWidth, (CGRectGetHeight(bounds) - CGRectGetHeight(titleFrame)) / 2.0)];
}
}
- (void)setFrame:(CGRect)aRect display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
{
var size = [self frame].size;
[super setFrame:aRect display:shouldDisplay animate:shouldAnimate];
if (!_CGSizeEqualToSize(size, aRect.size))
[self tile];
}
@end
@implementation _CPMenuBarWindow (CPMenuContainer)
- (BOOL)isMenuBar
{
return YES;
}
- (CGRect)globalFrame
{
return [self frame];
}
- (_CPManagerScrollingState)scrollingStateForPoint:(CGPoint)aGlobalLocation
{
return _CPMenuManagerScrollingStateNone;
}
- (CPInteger)itemIndexAtPoint:(CGPoint)aPoint
{
var items = [_menu itemArray],
index = items.length;
while (index--)
{
var item = items[index];
if ([item isHidden] || [item isSeparatorItem])
continue;
if (CGRectContainsPoint([self rectForItemAtIndex:index], aPoint))
return index;
}
return CPNotFound;
}
- (CGRect)rectForItemAtIndex:(CPInteger)anIndex
{
var menuItem = [_menu itemAtIndex:anIndex === CPNotFound ? 0 : anIndex];
return [[menuItem _menuItemView] frame];
}
@end
@implementation _CPMenuBarView : _CPMenuView
{
}
- (CGRect)rectForItemAtIndex:(int)anIndex
{
return [_menuItemViews[anIndex === CPNotFound ? 0 : anIndex] frame];
}
- (int)itemIndexAtPoint:(CGPoint)aPoint
{
var bounds = [self bounds];
if (!CGRectContainsPoint(bounds, aPoint))
return CPNotFound;
var x = aPoint.x,
low = 0,
high = _visibleMenuItemInfos.length - 1;
while (low <= high)
{
var middle = FLOOR(low + (high - low) / 2),
info = _visibleMenuItemInfos[middle],
frame = [info.view frame];
if (x < CGRectGetMinX(frame))
high = middle - 1;
else if (x > CGRectGetMaxX(frame))
low = middle + 1;
else
return info.index;
}
return CPNotFound;
}
- (void)tile
{
var items = [_menu itemArray],
index = 0,
count = items.length,
x = MENUBAR_LEFT_MARGIN,
y = 0.0,
isLeftAligned = YES;
for (; index < count; ++index)
{
var item = items[index];
if ([item isSeparatorItem])
{
x = CGRectGetWidth([self frame]) - MENUBAR_RIGHT_MARGIN;
isLeftAligned = NO;
continue;
}
if ([item isHidden])
continue;
var menuItemView = [item _menuItemView],
frame = [menuItemView frame];
if (isLeftAligned)
{
[menuItemView setFrameOrigin:CGPointMake(x, (MENUBAR_HEIGHT - 1.0 - CGRectGetHeight(frame)) / 2.0)];
x += CGRectGetWidth([menuItemView frame]) + MENUBAR_MARGIN;
}
else
{
[menuItemView setFrameOrigin:CGPointMake(x - CGRectGetWidth(frame), (MENUBAR_HEIGHT - 1.0 - CGRectGetHeight(frame)) / 2.0)];
x = CGRectGetMinX([menuItemView frame]) - MENUBAR_MARGIN;
}
}
var bounds = [[self contentView] bounds],
titleFrame = [_titleField frame];
if ([_iconImageView isHidden])
[_titleField setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(titleFrame)) / 2.0, (CGRectGetHeight(bounds) - CGRectGetHeight(titleFrame)) / 2.0)];
else
{
var iconFrame = [_iconImageView frame],
iconWidth = CGRectGetWidth(iconFrame),
totalWidth = iconWidth + CGRectGetWidth(titleFrame);
[_iconImageView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - totalWidth) / 2.0, (CGRectGetHeight(bounds) - CGRectGetHeight(iconFrame)) / 2.0)];
[_titleField setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - totalWidth) / 2.0 + iconWidth, (CGRectGetHeight(bounds) - CGRectGetHeight(titleFrame)) / 2.0)];
}
}
@end
+655
View File
@@ -0,0 +1,655 @@
@import <Foundation/CPObject.j>
_CPMenuManagerScrollingStateUp = -1,
_CPMenuManagerScrollingStateDown = 1,
_CPMenuManagerScrollingStateNone = 0;
var STICKY_TIME_INTERVAL = 500,
SharedMenuManager = nil;
@implementation _CPMenuManager: CPObject
{
CPTimeInterval _startTime;
int _scrollingState;
CGPoint _lastGlobalLocation;
CPView _lastMouseOverMenuView;
CGRect _constraintRect;
CPMutableArray _menuContainerStack;
Function _trackingCallback;
CPString _keyBuffer;
CPMenuItem _previousActiveItem;
int _showTimerID;
}
+ (_CPMenuManager)sharedMenuManager
{
if (!SharedMenuManager)
SharedMenuManager = [[_CPMenuManager alloc] init];
return SharedMenuManager;
}
- (id)init
{
if (SharedMenuManager)
return SharedMenuManager;
return [super init];
}
- (id)trackingMenuContainer
{
return _menuContainerStack[0];
}
- (CPMenu)trackingMenu
{
return [[self trackingMenuContainer] menu];
}
- (void)beginTracking:(CPEvent)anEvent
menuContainer:(id)aMenuContainer
constraintRect:(CGRect)aRect
callback:(Function)aCallback
{
var menu = [aMenuContainer menu];
CPApp._activeMenu = menu;
_startTime = [anEvent timestamp];//new Date();
_scrollingState = _CPMenuManagerScrollingStateNone;
_constraintRect = aRect;
_menuContainerStack = [aMenuContainer];
_trackingCallback = aCallback;
if (menu === [CPApp mainMenu])
{
var globalLocation = [anEvent globalLocation],
// Find which menu window the mouse is currently on top of
menuLocation = [aMenuContainer convertGlobalToBase:globalLocation],
// Find out the item the mouse is currently on top of
activeItemIndex = [aMenuContainer itemIndexAtPoint:menuLocation],
activeItem = activeItemIndex !== CPNotFound ? [menu itemAtIndex:activeItemIndex] : nil;
_menuBarButtonItemIndex = activeItemIndex;
_menuBarButtonMenuContainer = aMenuContainer;
if ([activeItem _isMenuBarButton])
return [self trackMenuBarButtonEvent:anEvent];
}
[self trackEvent:anEvent];
}
- (void)trackEvent:(CPEvent)anEvent
{
var type = [anEvent type],
trackingMenu = [self trackingMenu];
// Close Menu Event.
if (type === CPAppKitDefined)
return [self completeTracking];
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPKeyDownMask | CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPAppKitDefinedMask | CPScrollWheelMask untilDate:nil inMode:nil dequeue:YES];
if (type === CPKeyDown)
{
var menu = trackingMenu,
submenu = [[menu highlightedItem] submenu];
// get the current active menu
while (submenu && [submenu._menuWindow isVisible])
{
menu = submenu;
submenu = [[menu highlightedItem] submenu];
}
if ([menu numberOfItems])
[self interpretKeyEvent:anEvent forMenu:menu];
return;
}
if (_keyBuffer)
{
if (([CPDate date] - _startTime) > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] / 2))
[self selectNextItemBeginningWith:_keyBuffer inMenu:menu clearBuffer:YES];
if (type === CPPeriodic)
return;
}
// Periodic events don't have a valid location.
var globalLocation = type === CPPeriodic ? _lastGlobalLocation : [anEvent globalLocation];
// Remember this for the next periodic event.
_lastGlobalLocation = globalLocation;
if (!_lastGlobalLocation)
return;
// Find which menu window the mouse is currently on top of
var activeMenuContainer = [self menuContainerForPoint:globalLocation],
activeMenu = [activeMenuContainer menu],
menuLocation = [activeMenuContainer convertGlobalToBase:globalLocation],
// Find out the item the mouse is currently on top of
activeItemIndex = activeMenuContainer ? [activeMenuContainer itemIndexAtPoint:menuLocation] : CPNotFound,
activeItem = activeItemIndex !== CPNotFound ? [activeMenu itemAtIndex:activeItemIndex] : nil;
// If the item isn't enabled its as if we clicked on nothing.
if (![activeItem isEnabled] || [activeItem _isMenuBarButton])
{
activeItemIndex = CPNotFound;
activeItem = nil;
}
var mouseOverMenuView = [activeItem view];
if (type === CPScrollWheel)
[activeMenuContainer scrollByDelta:[anEvent deltaY]];
if (type === CPPeriodic)
{
if (_scrollingState === _CPMenuManagerScrollingStateUp)
[activeMenuContainer scrollUp];
else if (_scrollingState === _CPMenuManagerScrollingStateDown)
[activeMenuContainer scrollDown];
}
// If we're over a custom menu view...
if (mouseOverMenuView)
{
if (!_lastMouseOverMenuView)
[activeMenu _highlightItemAtIndex:CPNotFound];
if (_lastMouseOverMenuView != mouseOverMenuView)
{
[mouseOverMenuView mouseExited:anEvent];
// FIXME: Possibly multiple of these?
[_lastMouseOverMenuView mouseEntered:anEvent];
_lastMouseOverMenuView = mouseOverMenuView;
}
var menuContainerWindow = activeMenuContainer;
if (![menuContainerWindow isKindOfClass:[CPWindow class]])
menuContainerWindow = [menuContainerWindow window];
[menuContainerWindow
sendEvent:[CPEvent mouseEventWithType:type
location:menuLocation
modifierFlags:[anEvent modifierFlags]
timestamp:[anEvent timestamp]
windowNumber:menuContainerWindow
context:nil
eventNumber:0
clickCount:[anEvent clickCount]
pressure:[anEvent pressure]]];
}
else
{
if (_lastMouseOverMenuView)
{
[_lastMouseOverMenuView mouseExited:anEvent];
_lastMouseOverMenuView = nil;
}
[activeMenu _highlightItemAtIndex:activeItemIndex];
if (type === CPMouseMoved || type === CPLeftMouseDragged || type === CPLeftMouseDown || type === CPPeriodic)
{
var oldScrollingState = _scrollingState;
_scrollingState = [activeMenuContainer scrollingStateForPoint:globalLocation];
if (_scrollingState !== oldScrollingState)
{
if (_scrollingState === _CPMenuManagerScrollingStateNone)
[CPEvent stopPeriodicEvents];
else if (oldScrollingState === _CPMenuManagerScrollingStateNone)
[CPEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.04];
}
}
else if (type === CPLeftMouseUp && ([anEvent timestamp] - _startTime > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] * 5)))
[trackingMenu cancelTracking];
}
// Prevent previous selected menu items from opening by stopping the timer if a
// new item is selected before the timer runs out
if (_previousActiveItem !== activeItem)
{
clearTimeout(_showTimerID);
_showTimerID = undefined;
}
// If the item has a submenu, show it.
if ([activeItem hasSubmenu])// && [activeItem action] === @selector(submenuAction:))
{
var activeItemRect = [activeMenuContainer rectForItemAtIndex:activeItemIndex],
newMenuOrigin;
if ([activeMenuContainer isMenuBar])
newMenuOrigin = CGPointMake(CGRectGetMinX(activeItemRect), CGRectGetMaxY(activeItemRect));
else
newMenuOrigin = CGPointMake(CGRectGetMaxX(activeItemRect), CGRectGetMinY(activeItemRect));
newMenuOrigin = [activeMenuContainer convertBaseToGlobal:newMenuOrigin];
// Only start a new timer if the previous was cancelled
if (_showTimerID === undefined)
{
// Close the current menu item because we are going to select a new one after a short delay
[self showMenu:nil fromMenu:activeMenu atPoint:CGPointMakeZero()];
if (![activeMenuContainer isMenuBar])
{
_showTimerID = setTimeout(function()
{
[self showMenu:[activeItem submenu] fromMenu:[activeItem menu] atPoint:newMenuOrigin];
}, 250);
}
else
[self showMenu:[activeItem submenu] fromMenu:[activeItem menu] atPoint:newMenuOrigin];
}
}
// This handles both the case where we've moved away from the menu, and where
// we've moved to an item without a submenu.
else
[self showMenu:nil fromMenu:activeMenu atPoint:CGPointMakeZero()];
_previousActiveItem = activeItem;
}
- (void)trackMenuBarButtonEvent:(CPEvent)anEvent
{
var type = [anEvent type];
if (type === CPAppKitDefined)
return [self completeTracking];
var globalLocation = [anEvent globalLocation],
// Find which menu window the mouse is currently on top of
menu = [self trackingMenu],
trackingMenuContainer = [self trackingMenuContainer],
menuLocation = [trackingMenuContainer convertGlobalToBase:globalLocation];
if ([trackingMenuContainer itemIndexAtPoint:menuLocation] === _menuBarButtonItemIndex)
[menu _highlightItemAtIndex:_menuBarButtonItemIndex];
else
[menu _highlightItemAtIndex:CPNotFound];
[CPApp setTarget:self selector:@selector(trackMenuBarButtonEvent:) forNextEventMatchingMask:CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPAppKitDefinedMask untilDate:nil inMode:nil dequeue:YES];
if (type === CPLeftMouseUp)
[menu cancelTracking];
}
- (void)completeTracking
{
var trackingMenu = [self trackingMenu];
// Stop all periodic events at this point.
[CPEvent stopPeriodicEvents];
// Hide all submenus.
[self showMenu:nil fromMenu:trackingMenu atPoint:nil];
var delegate = [trackingMenu delegate];
if ([delegate respondsToSelector:@selector(menuDidClose:)])
[delegate menuDidClose:trackingMenu];
if (_trackingCallback)
_trackingCallback([self trackingMenuContainer], trackingMenu);
[[CPNotificationCenter defaultCenter] postNotificationName:CPMenuDidEndTrackingNotification
object:trackingMenu];
CPApp._activeMenu = nil;
}
- (id)menuContainerForPoint:(float)aGlobalLocation
{
var count = [_menuContainerStack count],
firstMenuContainer = _menuContainerStack[0];
// Trivial case.
if (count === 1)
return firstMenuContainer;
var firstMenuWindowIndex = 0,
lastMenuWindowIndex = count - 1;
// If the first menu container is a bar, then it has to fall strictly within its bounds.
if ([firstMenuContainer isMenuBar])
{
if (CGRectContainsPoint([firstMenuContainer globalFrame], aGlobalLocation))
return firstMenuContainer;
firstMenuWindowIndex = 1;
}
var index = count,
x = aGlobalLocation.x,
closerDeltaX = Infinity,
closerMenuContainer = nil;
while (index-- > firstMenuWindowIndex)
{
var menuContainer = _menuContainerStack[index],
menuContainerFrame = [menuContainer globalFrame],
menuContainerMinX = _CGRectGetMinX(menuContainerFrame),
menuContainerMaxX = _CGRectGetMaxX(menuContainerFrame);
// If within the x bounds of this menu container, return it.
if (x < menuContainerMaxX && x >= menuContainerMinX)
return menuContainer;
// If this is either the first or last menu *window*, check to see how close we are to it.
if (index === firstMenuWindowIndex || index === lastMenuWindowIndex)
{
var deltaX = ABS(x < menuContainerMinX ? menuContainerMinX - x : menuContainerMaxX - x);
if (deltaX < closerDeltaX)
{
closerMenuContainer = menuContainer;
closerDeltaX = deltaX;
}
}
}
return closerMenuContainer;
}
- (void)showMenu:(CPMenu)newMenu fromMenu:(CPMenu)baseMenu atPoint:(CGPoint)aGlobalLocation
{
var count = _menuContainerStack.length,
index = count;
// Hide all menus up to the base menu...
while (index--)
{
var menuContainer = _menuContainerStack[index],
menu = [menuContainer menu];
// If we reach the base menu, or this menu is already being shown, break.
if (menu === baseMenu)
break;
// If this menu is already being shown, unhighlight and return.
if (menu === newMenu)//&& [menu supermenu] === baseMenu)
return [newMenu _highlightItemAtIndex:CPNotFound];
[menuContainer orderOut:self];
[menuContainer setMenu:nil];
[_CPMenuWindow poolMenuWindow:menuContainer];
[_menuContainerStack removeObjectAtIndex:index];
}
if (!newMenu)
return;
// Unhighlight any previously highlighted item.
[newMenu _highlightItemAtIndex:CPNotFound];
var menuWindow = [_CPMenuWindow menuWindowWithMenu:newMenu font:[_menuContainerStack[0] font]];
[_menuContainerStack addObject:menuWindow];
[menuWindow setConstraintRect:_constraintRect];
// If our parent menu is a menu bar...
if (baseMenu === [self trackingMenu] && [[self trackingMenuContainer] isMenuBar])
[menuWindow setBackgroundStyle:_CPMenuWindowMenuBarBackgroundStyle];
else
[menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle];
[menuWindow setFrameOrigin:aGlobalLocation];
[menuWindow orderFront:self];
}
/// handle keyboard navigation
- (void)interpretKeyEvent:(CPEvent)anEvent forMenu:(CPMenu)menu
{
var modifierFlags = [anEvent modifierFlags],
character = [anEvent charactersIgnoringModifiers],
selectorNames = [CPKeyBinding selectorsForKey:character modifierFlags:modifierFlags];
if (selectorNames)
{
var iter = [selectorNames objectEnumerator],
obj;
while (obj = [iter nextObject])
{
var aSelector = CPSelectorFromString(obj);
if ([self respondsToSelector:aSelector])
[self performSelector:aSelector withObject:menu];
}
}
else if (!(modifierFlags & (CPCommandKeyMask | CPControlKeyMask)))
{
if (!_keyBuffer)
{
_startTime = [CPDate date];
_keyBuffer = character;
[CPEvent stopPeriodicEvents];
[CPEvent startPeriodicEventsAfterDelay:0.1 withPeriod:0.1];
}
else
_keyBuffer += character;
[self selectNextItemBeginningWith:_keyBuffer inMenu:menu clearBuffer:NO];
_lastGlobalLocation = Nil;
}
}
- (void)selectNextItemBeginningWith:(CPString)characters inMenu:(CPMenu)menu clearBuffer:(BOOL)shouldClear
{
var iter = [[menu itemArray] objectEnumerator],
obj;
while (obj = [iter nextObject])
{
if ([obj isHidden] || ![obj isEnabled])
continue;
if ([[[obj title] commonPrefixWithString:characters options:CPCaseInsensitiveSearch] length] == [characters length])
{
[menu _highlightItemAtIndex:iter._index];
break;
}
}
if (shouldClear)
{
[CPEvent stopPeriodicEvents];
_keyBuffer = Nil;
}
else
_startTime = [CPDate date];
}
- (void)scrollToBeginningOfDocument:(CPMenu)menu
{
[menu _highlightItemAtIndex:0];
}
- (void)scrollToEndOfDocument:(CPMenu)menu
{
[menu _highlightItemAtIndex:[menu numberOfItems] - 1];
}
- (void)scrollPageDown:(CPMenu)menu
{
var menuWindow = menu._menuWindow,
menuClipView = menuWindow._menuClipView,
bottom = [menuClipView bounds].size.height,
first = [menuWindow itemIndexAtPoint:CGPointMake(1, 10)],
last = [menuWindow itemIndexAtPoint:CGPointMake(1, bottom)],
current = [menu indexOfItem:[menu highlightedItem]];
if (current == CPNotFound)
{
[menu _highlightItemAtIndex:0];
return;
}
next = current + (last - first);
if (next < [menu numberOfItems])
[menu _highlightItemAtIndex:next];
else
[menu _highlightItemAtIndex:[menu numberOfItems] - 1];
var item = [menu highlightedItem];
if ([item isSeparatorItem] || [item isHidden] || ![item isEnabled])
[self moveDown:menu];
}
- (void)scrollPageUp:(CPMenu)menu
{
var menuWindow = menu._menuWindow,
menuClipView = menuWindow._menuClipView,
bottom = [menuClipView bounds].size.height,
first = [menuWindow itemIndexAtPoint:CGPointMake(1, 10)],
last = [menuWindow itemIndexAtPoint:CGPointMake(1, bottom)],
current = [menu indexOfItem:[menu highlightedItem]];
if (current == CPNotFound)
{
[menu _highlightItemAtIndex:0];
return;
}
next = current - (last - first);
if (next < 0)
[menu _highlightItemAtIndex:0];
else
[menu _highlightItemAtIndex:next];
var item = [menu highlightedItem];
if ([item isSeparatorItem] || [item isHidden] || ![item isEnabled])
[self moveUp:menu];
}
- (void)moveLeft:(CPMenu)menu
{
if ([menu supermenu])
{
if ([menu supermenu] == [CPApp mainMenu])
{
[self showMenu:nil fromMenu:[menu supermenu] atPoint:CGPointMakeZero()];
[self moveUp:[CPApp mainMenu]];
var activeItem = [[CPApp mainMenu] highlightedItem],
menuLocation = CGPointMake([[activeItem _menuItemView] frameOrigin].x , [[activeItem _menuItemView] frameSize].height);
[self showMenu:[activeItem submenu] fromMenu:[activeItem menu] atPoint:menuLocation];
}
else
[self showMenu:nil fromMenu:[menu supermenu] atPoint:CGPointMakeZero()];
}
}
- (void)moveRight:(CPMenu)menu
{
var activeItem = [menu highlightedItem];
if ([activeItem hasSubmenu])
{
if ([[activeItem submenu] numberOfItems])
{
var activeItemIndex = [menu indexOfItem:activeItem],
activeMenuContainer = menu._menuWindow,
activeItemRect = [activeMenuContainer rectForItemAtIndex:activeItemIndex],
newMenuOrigin;
if ([activeMenuContainer isMenuBar])
newMenuOrigin = CGPointMake(CGRectGetMinX(activeItemRect), CGRectGetMaxY(activeItemRect));
else
newMenuOrigin = CGPointMake(CGRectGetMaxX(activeItemRect), CGRectGetMinY(activeItemRect));
newMenuOrigin = [activeMenuContainer convertBaseToGlobal:newMenuOrigin];
[self showMenu:[activeItem submenu] fromMenu:[activeItem menu] atPoint:newMenuOrigin];
[self moveDown:[activeItem submenu]];
}
}
else if ([self trackingMenu] == [CPApp mainMenu])
{
[self showMenu:nil fromMenu:menu atPoint:CGPointMakeZero()];
[self moveDown:[CPApp mainMenu]];
var activeItem = [[CPApp mainMenu] highlightedItem],
menuLocation = CGPointMake([[activeItem _menuItemView] frameOrigin].x , [[activeItem _menuItemView] frameSize].height);
[self showMenu:[activeItem submenu] fromMenu:[activeItem menu] atPoint:menuLocation];
}
}
- (void)moveDown:(CPMenu)menu
{
var index = menu._highlightedIndex + 1;
if (index < [menu numberOfItems])
{
[menu _highlightItemAtIndex:index];
var item = [menu highlightedItem];
if ([item isSeparatorItem] || [item isHidden] || ![item isEnabled])
[self moveDown:menu];
}
}
- (void)moveUp:(CPMenu)menu
{
var index = menu._highlightedIndex - 1;
if (index < 0)
return;
[menu _highlightItemAtIndex:index];
var item = [menu highlightedItem];
if ([item isSeparatorItem] || [item isHidden] || ![item isEnabled])
[self moveUp:menu];
}
- (void)insertNewline:(CPMenu)menu
{
if ([[menu highlightedItem] hasSubmenu])
[self moveRight:menu];
else
[menu cancelTracking]
}
- (void)cancelOperation:(CPMenu)menu
{
[menu _highlightItemAtIndex:CPNotFound];
[CPEvent stopPeriodicEvents];
[[self trackingMenu] cancelTracking];
}
@end
+562
View File
@@ -0,0 +1,562 @@
@import "CPWindow.j"
var _CPMenuWindowPool = [],
_CPMenuWindowPoolCapacity = 5,
_CPMenuWindowBackgroundColors = [];
_CPMenuWindowMenuBarBackgroundStyle = 0;
_CPMenuWindowPopUpBackgroundStyle = 1;
_CPMenuWindowAttachedMenuBackgroundStyle = 2;
var STICKY_TIME_INTERVAL = 500,
TOP_MARGIN = 5.0,
LEFT_MARGIN = 1.0,
RIGHT_MARGIN = 1.0,
BOTTOM_MARGIN = 5.0,
SCROLL_INDICATOR_HEIGHT = 16.0;
/*
@ignore
*/
@implementation _CPMenuWindow : CPWindow
{
_CPMenuView _menuView;
CPClipView _menuClipView;
CPImageView _moreAboveView;
CPImageView _moreBelowView;
CGRect _unconstrainedFrame;
CGRect _constraintRect;
}
+ (id)menuWindowWithMenu:(CPMenu)aMenu font:(CPFont)aFont
{
var menuWindow = nil;
if (_CPMenuWindowPool.length)
{
menuWindow = _CPMenuWindowPool.pop();
// Do this so that coordinates will be accurate.
[menuWindow setFrameOrigin:CGPointMakeZero()];
}
else
menuWindow = [[_CPMenuWindow alloc] init];
[menuWindow setFont:aFont];
[menuWindow setMenu:aMenu];
[menuWindow setMinWidth:[aMenu minimumWidth]];
return menuWindow;
}
+ (void)poolMenuWindow:(_CPMenuWindow)aMenuWindow
{
if (!aMenuWindow || _CPMenuWindowPool.length >= _CPMenuWindowPoolCapacity)
return;
_CPMenuWindowPool.push(aMenuWindow);
}
+ (void)initialize
{
if (self != [_CPMenuWindow class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPMenuWindowMoreAboveImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowMoreAbove.png"] size:CGSizeMake(38.0, 18.0)];
_CPMenuWindowMoreBelowImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowMoreBelow.png"] size:CGSizeMake(38.0, 18.0)];
}
- (id)initWithContentRect:(CGRect)aRect styleMask:(unsigned)aStyleMask
{
_constraintRect = _CGRectMakeZero();
_unconstrainedFrame = _CGRectMakeZero();
self = [super initWithContentRect:aRect styleMask:CPBorderlessWindowMask];
if (self)
{
[self setLevel:CPPopUpMenuWindowLevel];
[self setHasShadow:YES];
[self setShadowStyle:CPMenuWindowShadowStyle];
[self setAcceptsMouseMovedEvents:YES];
var contentView = [self contentView];
_menuView = [[_CPMenuView alloc] initWithFrame:CGRectMakeZero()];
_menuClipView = [[CPClipView alloc] initWithFrame:CGRectMake(LEFT_MARGIN, TOP_MARGIN, 0.0, 0.0)];
[_menuClipView setDocumentView:_menuView];
[contentView addSubview:_menuClipView];
_moreAboveView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
[_moreAboveView setImage:_CPMenuWindowMoreAboveImage];
[_moreAboveView setFrameSize:[_CPMenuWindowMoreAboveImage size]];
[contentView addSubview:_moreAboveView];
_moreBelowView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
[_moreBelowView setImage:_CPMenuWindowMoreBelowImage];
[_moreBelowView setFrameSize:[_CPMenuWindowMoreBelowImage size]];
[contentView addSubview:_moreBelowView];
[self setShadowStyle:CPWindowShadowStyleMenu];
}
return self;
}
+ (float)_standardLeftMargin
{
return LEFT_MARGIN;
}
- (void)setFont:(CPFont)aFont
{
[_menuView setFont:aFont];
}
- (CPFont)font
{
return [_menuView font];
}
+ (CPColor)backgroundColorForBackgroundStyle:(_CPMenuWindowBackgroundStyle)aBackgroundStyle
{
var color = _CPMenuWindowBackgroundColors[aBackgroundStyle];
if (!color)
{
var bundle = [CPBundle bundleForClass:[self class]];
if (aBackgroundStyle == _CPMenuWindowPopUpBackgroundStyle)
color = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded0.png"] size:CGSizeMake(4.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow1.png"] size:CGSizeMake(1.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded2.png"] size:CGSizeMake(4.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow3.png"] size:CGSizeMake(4.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow4.png"] size:CGSizeMake(1.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow5.png"] size:CGSizeMake(4.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded6.png"] size:CGSizeMake(4.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow7.png"] size:CGSizeMake(1.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded8.png"] size:CGSizeMake(4.0, 4.0)]
]]];
else if (aBackgroundStyle == _CPMenuWindowMenuBarBackgroundStyle)
color = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow3.png"] size:CGSizeMake(4.0, 0.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow4.png"] size:CGSizeMake(1.0, 0.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow5.png"] size:CGSizeMake(4.0, 0.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow3.png"] size:CGSizeMake(4.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow4.png"] size:CGSizeMake(1.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow5.png"] size:CGSizeMake(4.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded6.png"] size:CGSizeMake(4.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow7.png"] size:CGSizeMake(1.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded8.png"] size:CGSizeMake(4.0, 4.0)]
]]];
_CPMenuWindowBackgroundColors[aBackgroundStyle] = color;
}
return color;
}
- (void)setBackgroundStyle:(_CPMenuWindowBackgroundStyle)aBackgroundStyle
{
[self setBackgroundColor:[[self class] backgroundColorForBackgroundStyle:aBackgroundStyle]];
}
- (void)setMenu:(CPMenu)aMenu
{
[aMenu _setMenuWindow:self];
[_menuView setMenu:aMenu];
var menuViewSize = [_menuView frame].size;
[self setFrameSize:CGSizeMake(LEFT_MARGIN + menuViewSize.width + RIGHT_MARGIN, TOP_MARGIN + menuViewSize.height + BOTTOM_MARGIN)];
[_menuView scrollPoint:CGPointMake(0.0, 0.0)];
[_menuClipView setFrame:CGRectMake(LEFT_MARGIN, TOP_MARGIN, menuViewSize.width, menuViewSize.height)];
}
- (void)setMinWidth:(float)aWidth
{
var size = [self unconstrainedFrame].size;
[self setFrameSize:CGSizeMake(MAX(size.width, aWidth), size.height)];
}
- (CPMenu)menu
{
return [_menuView menu];
}
- (_CPMenuView)_menuView
{
return _menuView;
}
- (void)orderFront:(id)aSender
{
[[self menu] update];
[self setFrame:_unconstrainedFrame];
[super orderFront:aSender];
}
- (void)setConstraintRect:(CGRect)aRect
{
_constraintRect = aRect;
[self setFrame:_unconstrainedFrame];
}
- (CGRect)unconstrainedFrame
{
return _CGRectMakeCopy(_unconstrainedFrame);
}
// We need this because if not this will call setFrame: with -frame instead of -unconstrainedFrame, turning
// the constrained frame into the unconstrained frame.
- (void)setFrameOrigin:(CGPoint)aPoint
{
[super setFrame:_CGRectMake(aPoint.x, aPoint.y, _CGRectGetWidth(_unconstrainedFrame), _CGRectGetHeight(_unconstrainedFrame))];
}
- (void)setFrameSize:(CGSize)aSize
{
[super setFrame:_CGRectMake(_CGRectGetMinX(_unconstrainedFrame), _CGRectGetMinY(_unconstrainedFrame), aSize.width, aSize.height)];
}
- (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
{
// FIXME: There are integral window issues with platform windows.
// FIXME: This gets called far too often.
_unconstrainedFrame = _CGRectMakeCopy(aFrame);
var constrainedFrame = CGRectIntersection(_unconstrainedFrame, _constraintRect);
// We don't want to simply intersect the visible frame and the unconstrained frame.
// We should be allowing as much of the width to fit as possible (pushing back and forward).
constrainedFrame.origin.x = CGRectGetMinX(_unconstrainedFrame);
constrainedFrame.size.width = CGRectGetWidth(_unconstrainedFrame);
if (CGRectGetWidth(constrainedFrame) > CGRectGetWidth(_constraintRect))
constrainedFrame.size.width = CGRectGetWidth(_constraintRect);
if (CGRectGetMaxX(constrainedFrame) > CGRectGetMaxX(_constraintRect))
constrainedFrame.origin.x -= CGRectGetMaxX(constrainedFrame) - CGRectGetMaxX(_constraintRect);
if (CGRectGetMinX(constrainedFrame) < CGRectGetMinX(_constraintRect))
constrainedFrame.origin.x = CGRectGetMinX(_constraintRect);
[super setFrame:constrainedFrame display:shouldDisplay animate:shouldAnimate];
// This needs to happen before changing the frame.
var menuViewOrigin = CGPointMake(CGRectGetMinX(aFrame) + LEFT_MARGIN, CGRectGetMinY(aFrame) + TOP_MARGIN),
moreAbove = menuViewOrigin.y < CGRectGetMinY(constrainedFrame) + TOP_MARGIN,
moreBelow = menuViewOrigin.y + CGRectGetHeight([_menuView frame]) > CGRectGetMaxY(constrainedFrame) - BOTTOM_MARGIN,
topMargin = TOP_MARGIN,
bottomMargin = BOTTOM_MARGIN,
contentView = [self contentView],
bounds = [contentView bounds];
if (moreAbove)
{
topMargin += SCROLL_INDICATOR_HEIGHT;
var frame = [_moreAboveView frame];
[_moreAboveView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(frame)) / 2.0, (TOP_MARGIN + SCROLL_INDICATOR_HEIGHT - CGRectGetHeight(frame)) / 2.0)];
}
[_moreAboveView setHidden:!moreAbove];
if (moreBelow)
{
bottomMargin += SCROLL_INDICATOR_HEIGHT;
[_moreBelowView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth([_moreBelowView frame])) / 2.0, CGRectGetHeight(bounds) - SCROLL_INDICATOR_HEIGHT - BOTTOM_MARGIN)];
}
[_moreBelowView setHidden:!moreBelow];
var clipFrame = CGRectMakeZero();
clipFrame.origin.x = LEFT_MARGIN;
clipFrame.origin.y = topMargin;
clipFrame.size.width = CGRectGetWidth(constrainedFrame) - LEFT_MARGIN - RIGHT_MARGIN;
clipFrame.size.height = CGRectGetHeight(constrainedFrame) - topMargin - bottomMargin;
[_menuClipView setFrame:clipFrame];
[_menuView setFrameSize:CGSizeMake(CGRectGetWidth(clipFrame), CGRectGetHeight([_menuView frame]))];
[_menuView scrollPoint:CGPointMake(0.0, [self convertBaseToGlobal:clipFrame.origin].y - menuViewOrigin.y)];
}
- (BOOL)hasMinimumNumberOfVisibleItems
{
var visibleRect = [_menuView visibleRect];
// Clearly if the entire view isn't visible the minimum won't be visible.
if (CGRectIsEmpty(visibleRect))
return NO;
var numberOfUnhiddenItems = [_menuView numberOfUnhiddenItems],
minimumNumberOfVisibleItems = MIN(numberOfUnhiddenItems, 3),
count = 0,
index = [_menuView itemIndexAtPoint:[_menuView convertPoint:[_menuClipView frame].origin fromView:nil]];
for (; index < numberOfUnhiddenItems && count < minimumNumberOfVisibleItems; ++index)
{
var itemRect = [_menuView rectForUnhiddenItemAtIndex:index],
visibleItemRect = CGRectIntersection(visibleRect, itemRect);
// As soon as we get to the first unhidden item that is no longer visible, stop.
if (CGRectIsEmpty(visibleItemRect))
break;
// If the item is *completely* visible, count it.
if (CGRectEqualToRect(visibleItemRect, itemRect))
++count;
}
return count >= minimumNumberOfVisibleItems;
}
- (BOOL)canScrollUp
{
return ![_moreAboveView isHidden];
}
- (BOOL)canScrollDown
{
return ![_moreBelowView isHidden];
}
- (BOOL)canScroll
{
return [self canScrollUp] || [self canScrollDown];
}
- (void)scrollByDelta:(float)theDelta
{
if (theDelta === 0.0)
return;
if (theDelta > 0.0 && ![self canScrollDown])
return;
if (theDelta < 0.0 && ![self canScrollUp])
return;
_unconstrainedFrame.origin.y -= theDelta;
[self setFrame:_unconstrainedFrame];
}
- (void)scrollUp
{
[self scrollByDelta:-10.0];
}
- (void)scrollDown
{
[self scrollByDelta:10.0];
}
@end
@implementation _CPMenuWindow (CPMenuContainer)
- (CGRect)globalFrame
{
return [self frame];
}
- (BOOL)isMenuBar
{
return NO;
}
- (_CPManagerScrollingState)scrollingStateForPoint:(CGPoint)aGlobalLocation
{
var frame = [self frame];
if (!CPRectContainsPoint(frame,aGlobalLocation) || ![self canScroll])
return _CPMenuManagerScrollingStateNone;
// If we're at or above of the top scroll indicator...
if (aGlobalLocation.y < CGRectGetMinY(frame) + TOP_MARGIN + SCROLL_INDICATOR_HEIGHT && ![_moreAboveView isHidden])
return _CPMenuManagerScrollingStateUp;
// If we're at or below the bottom scroll indicator...
if (aGlobalLocation.y > CGRectGetMaxY(frame) - BOTTOM_MARGIN - SCROLL_INDICATOR_HEIGHT && ![_moreBelowView isHidden])
return _CPMenuManagerScrollingStateDown;
return _CPMenuManagerScrollingStateNone;
}
- (float)deltaYForItemAtIndex:(int)anIndex
{
return TOP_MARGIN + CGRectGetMinY([_menuView rectForItemAtIndex:anIndex]);
}
- (CGPoint)rectForItemAtIndex:(int)anIndex
{
return [_menuView convertRect:[_menuView rectForItemAtIndex:anIndex] toView:nil];
}
- (int)itemIndexAtPoint:(CGPoint)aPoint
{
// Don't return indexes of items that aren't visible.
if (!CGRectContainsPoint([_menuClipView bounds], [_menuClipView convertPoint:aPoint fromView:nil]))
return NO;
return [_menuView itemIndexAtPoint:[_menuView convertPoint:aPoint fromView:nil]];
}
@end
/*
@ignore
*/
@implementation _CPMenuView : CPView
{
CPArray _menuItemViews;
CPArray _visibleMenuItemInfos;
CPFont _font @accessors(property=font);
}
- (unsigned)numberOfUnhiddenItems
{
return _visibleMenuItemInfos.length;
}
- (CGRect)rectForUnhiddenItemAtIndex:(int)anIndex
{
return [self rectForItemAtIndex:_visibleMenuItemInfos[anIndex].index];
}
- (CGRect)rectForItemAtIndex:(int)anIndex
{
return [_menuItemViews[anIndex === CPNotFound ? 0 : anIndex] frame];
}
- (int)itemIndexAtPoint:(CGPoint)aPoint
{
var x = aPoint.x,
bounds = [self bounds];
if (x < CGRectGetMinX(bounds) || x > CGRectGetMaxX(bounds))
return CPNotFound;
var y = aPoint.y,
low = 0,
high = _visibleMenuItemInfos.length - 1;
while (low <= high)
{
var middle = FLOOR(low + (high - low) / 2),
info = _visibleMenuItemInfos[middle],
frame = [info.view frame];
if (y < CGRectGetMinY(frame))
high = middle - 1;
else if (y > CGRectGetMaxY(frame))
low = middle + 1;
else
return info.index;
}
return CPNotFound;
}
- (void)tile
{
[_menuItemViews makeObjectsPerformSelector:@selector(removeFromSuperview)];
_menuItemViews = [];
_visibleMenuItemInfos = [];
var menu = [self menu];
if (!menu)
return;
var items = [menu itemArray],
index = 0,
count = [items count],
maxWidth = 0,
y = 0,
showsStateColumn = [menu showsStateColumn];
for (; index < count; ++index)
{
var item = items[index],
view = [item _menuItemView];
_menuItemViews.push(view);
if ([item isHidden])
continue;
_visibleMenuItemInfos.push({ view:view, index:index });
[view setFont:_font];
[view setShowsStateColumn:showsStateColumn];
[view synchronizeWithMenuItem];
[view setFrameOrigin:CGPointMake(0.0, y)];
[self addSubview:view];
var size = [view minSize],
width = size.width;
if (maxWidth < width)
maxWidth = width;
y += size.height;
}
for (index = 0; index < count; ++index)
{
var view = _menuItemViews[index];
[view setFrameSize:CGSizeMake(maxWidth, CGRectGetHeight([view frame]))];
}
[self setAutoresizesSubviews:NO];
[self setFrameSize:CGSizeMake(maxWidth, y)];
[self setAutoresizesSubviews:YES];
}
- (void)setMenu:(CPMenu)aMenu
{
[super setMenu:aMenu];
[self tile];
}
@end
@@ -24,11 +24,32 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@import <AppKit/CPImage.j>
@import <AppKit/CPMenu.j>
@import <AppKit/CPView.j>
@import "CPImage.j"
@import "CPMenu.j"
@import "CPView.j"
@import "_CPMenuItemView.j"
/*!
var CPMenuItemStringRepresentationDictionary = [CPDictionary dictionary];
[CPMenuItemStringRepresentationDictionary setObject:"\u238B" forKey:CPEscapeFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u21E5" forKey:CPTabCharacter];
[CPMenuItemStringRepresentationDictionary setObject:"\u21E4" forKey:CPBackTabCharacter];
[CPMenuItemStringRepresentationDictionary setObject:"\u2423" forKey:CPSpaceFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u23CE" forKey:CPCarriageReturnCharacter];
[CPMenuItemStringRepresentationDictionary setObject:"\u232B" forKey:CPBackspaceCharacter];
[CPMenuItemStringRepresentationDictionary setObject:"\u232B" forKey:CPDeleteFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u2326" forKey:CPDeleteCharacter];
[CPMenuItemStringRepresentationDictionary setObject:"\u21F1" forKey:CPHomeFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u21F2" forKey:CPEndFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u21DE" forKey:CPPageUpFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u21DF" forKey:CPPageDownFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u2191" forKey:CPUpArrowFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u2193" forKey:CPDownArrowFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u2190" forKey:CPLeftArrowFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u2192" forKey:CPRightArrowFunctionKey];
[CPMenuItemStringRepresentationDictionary setObject:"\u2327" forKey:CPClearDisplayFunctionKey];
/*!
@ingroup appkit
@class CPMenuItem
@@ -42,39 +63,41 @@
CPString _title;
//CPAttributedString _attributedTitle;
CPFont _font;
id _target;
SEL _action;
BOOL _isEnabled;
BOOL _isHidden;
int _tag;
int _state;
CPImage _image;
CPImage _alternateImage;
CPImage _onStateImage;
CPImage _offStateImage;
CPImage _mixedStateImage;
CPMenu _submenu;
CPMenu _menu;
CPString _keyEquivalent;
unsigned _keyEquivalentModifierMask;
int _mnemonicLocation;
BOOL _isAlternate;
int _indentationLevel;
CPString _toolTip;
id _representedObject;
CPView _view;
int _changeCount;
_CPMenuItemView _menuItemView;
}
@@ -93,25 +116,29 @@
- (id)initWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent
{
self = [super init];
if (self)
{
_changeCount = 0;
_isSeparator = NO;
_title = aTitle;
_action = anAction;
_isEnabled = YES;
_isHidden = NO;
_tag = 0;
_state = CPOffState;
_keyEquivalent = aKeyEquivalent || @"";
_keyEquivalentModifierMask = CPPlatformActionKeyMask;
_indentationLevel = 0;
_mnemonicLocation = CPNotFound;
}
return self;
}
@@ -125,10 +152,17 @@
if ([_menu autoenablesItems])
return;
_isEnabled = isEnabled;
[self _setEnabled:isEnabled];
}
- (void)_setEnabled:(BOOL)isEnabled
{
if (_isEnabled === isEnabled)
return;
_isEnabled = !!isEnabled;
[_menuItemView setDirty];
[_menu itemChanged:self];
}
@@ -149,7 +183,7 @@
{
if (_isHidden == isHidden)
return;
_isHidden = isHidden;
[_menu itemChanged:self];
@@ -170,9 +204,9 @@
{
if (_isHidden)
return YES;
var supermenu = [_menu supermenu];
if ([[supermenu itemAtIndex:[supermenu indexOfItemWithSubmenu:_menu]] isHiddenOrHasHiddenAncestor])
return YES;
@@ -225,11 +259,11 @@
if (_title == aTitle)
return;
_title = aTitle;
[_menuItemView setDirty];
[_menu itemChanged:self];
}
@@ -257,11 +291,11 @@
{
if (_font == aFont)
return;
_font = aFont;
[_menu itemChanged:self];
[_menuItemView setDirty];
}
@@ -313,9 +347,9 @@ CPOffState
{
if (_state == aState)
return;
_state = aState;
[_menu itemChanged:self];
[_menuItemView setDirty];
@@ -343,11 +377,11 @@ CPOffState
{
if (_image == anImage)
return;
_image = anImage;
[_menuItemView setDirty];
[_menu itemChanged:self];
}
@@ -385,7 +419,7 @@ CPOffState
{
if (_onStateImage == anImage)
return;
_onStateImage = anImage;
[_menu itemChanged:self];
}
@@ -406,7 +440,7 @@ CPOffState
{
if (_offStateImage == anImage)
return;
_offStateImage = anImage;
[_menu itemChanged:self];
}
@@ -427,7 +461,7 @@ CPOffState
{
if (_mixedStateImage == anImage)
return;
_mixedStateImage = anImage;
[_menu itemChanged:self];
}
@@ -441,27 +475,39 @@ CPOffState
return _mixedStateImage;
}
// Managing Subemenus
// Managing Submenus
/*!
Sets the submenu for this item
@param aMenu the submenu
*/
- (void)setSubmenu:(CPMenu)aMenu
{
var supermenu = [_submenu supermenu];
if (supermenu == self)
if (_submenu === aMenu)
return;
var supermenu = [_submenu supermenu];
if (supermenu)
return alert("bad");
[_submenu setSupermenu:_menu];
[CPException raise:CPInvalidArgumentException
reason: @"Can't add submenu \"" + [aMenu title] + "\" to item \"" + [self title] + "\", because it is already submenu of \"" + [[aMenu supermenu] title] + "\""];
_submenu = aMenu;
if (_submenu)
{
[_submenu setSupermenu:_menu];
[self setTarget:_menu];
[self setAction:@selector(submenuAction:)];
}
else
{
[self setTarget:nil];
[self setAction:NULL];
}
[_menuItemView setDirty];
[_menu itemChanged:self];
}
@@ -570,6 +616,47 @@ CPControlKeyMask
return _keyEquivalentModifierMask;
}
- (CPString)keyEquivalentStringRepresentation
{
if (![_keyEquivalent length])
return @"";
var string = _keyEquivalent.toUpperCase(),
needsShift = _keyEquivalentModifierMask & CPShiftKeyMask ||
(string === _keyEquivalent && _keyEquivalent.toLowerCase() !== _keyEquivalent.toUpperCase());
if ([CPMenuItemStringRepresentationDictionary objectForKey:string])
string = [CPMenuItemStringRepresentationDictionary objectForKey:string];
if (CPBrowserIsOperatingSystem(CPMacOperatingSystem))
{
if (_keyEquivalentModifierMask & CPCommandKeyMask)
string = "\u2318" + string;
if (needsShift)
string = "\u21E7" + string;
if (_keyEquivalentModifierMask & CPAlternateKeyMask)
string = "\u2325" + string;
if (_keyEquivalentModifierMask & CPControlKeyMask)
string = "\u2303" + string;
}
else
{
if (needsShift)
string = "Shift-" + string;
if (_keyEquivalentModifierMask & CPAlternateKeyMask)
string = "Alt-" + string;
if (_keyEquivalentModifierMask & CPControlKeyMask || _keyEquivalentModifierMask & CPCommandKeyMask)
string = "Ctrl-" + string;
}
return string;
}
// Managing Mnemonics
/*!
Sets the index of the mnemonic character in the title. The character
@@ -590,20 +677,20 @@ 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
{
var location = [aTitle rangeOfString:@"&"].location;
if (location == CPNotFound)
[self setTitle:aTitle];
else
{
[self setTitle:[aTitle substringToIndex:location] + [aTitle substringFromIndex:location + 1]];
[self setMnemonicLocation:location];
}
}
}
/*!
@@ -643,8 +730,8 @@ CPControlKeyMask
- (void)setIndentationLevel:(unsigned)aLevel
{
if (aLevel < 0)
[CPException raise:CPInvalidArgumentException reason:"setIndentationLevel: argument must be greater than 0."];
[CPException raise:CPInvalidArgumentException reason:"setIndentationLevel: argument must be greater than or equal to 0."];
_indentationLevel = MIN(15, aLevel);
}
@@ -703,11 +790,11 @@ CPControlKeyMask
{
if (_view === aView)
return;
_view = aView;
[_menuItemView setDirty];
[_menu itemChanged:self];
}
@@ -729,7 +816,48 @@ CPControlKeyMask
return [[self menu] highlightedItem] == self;
}
//
#pragma mark CPObject Overrides
/*!
Returns a copy of the item. The copy does not belong If the item has a submenu, it is NOT copied.
*/
- (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 setTarget:_target];
[item setAction:_action];
[item setEnabled:_isEnabled];
[item setHidden:_isHidden]
[item setTag:_tag];
[item setState:_state];
[item setImage:_image];
[item setAlternateImage:_alternateImage];
[item setOnStateImage:_onStateImage];
[item setOffStateImage:_offStateImage];
[item setMixedStateImage:_mixedStateImage];
[item setKeyEquivalent:_keyEquivalent];
[item setKeyEquivalentModifierMask:_keyEquivalentModifierMask];
[item setMnemonicLocation:_mnemonicLocation];
[item setAlternate:_isAlternate];
[item setIndentationLevel:_indentationLevel];
[item setToolTip:_toolTip];
[item setRepresentedObject:_representedObject];
return item;
}
- (id)mutableCopy
{
return [self copy];
}
#pragma mark Internal
/*
@ignore
@@ -738,10 +866,25 @@ CPControlKeyMask
{
if (!_menuItemView)
_menuItemView = [[_CPMenuItemView alloc] initWithFrame:CGRectMakeZero() forMenuItem:self];
return _menuItemView;
}
- (BOOL)_isSelectable
{
return ![self submenu] || [self action] !== @selector(submenuAction:) || [self target] !== [self menu];
}
- (BOOL)_isMenuBarButton
{
return ![self submenu] && [self menu] === [CPApp mainMenu];
}
- (CPString)description
{
return [super description] + @" target: " + [self target] + @" action: " + CPStringFromSelector([self action]);
}
@end
var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
@@ -765,6 +908,8 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
CPMenuItemKeyEquivalentKey = @"CPMenuItemKeyEquivalentKey",
CPMenuItemKeyEquivalentModifierMaskKey = @"CPMenuItemKeyEquivalentModifierMaskKey",
CPMenuItemIndentationLevelKey = @"CPMenuItemIndentationLevelKey",
CPMenuItemRepresentedObjectKey = @"CPMenuItemRepresentedObjectKey",
CPMenuItemViewKey = @"CPMenuItemViewKey";
@@ -780,15 +925,16 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_changeCount = 0;
_isSeparator = [aCoder containsValueForKey:CPMenuItemIsSeparatorKey] && [aCoder decodeBoolForKey:CPMenuItemIsSeparatorKey];
_title = [aCoder decodeObjectForKey:CPMenuItemTitleKey];
// _font;
_target = [aCoder decodeObjectForKey:CPMenuItemTargetKey];
_action = [aCoder decodeObjectForKey:CPMenuItemActionKey];
@@ -796,7 +942,6 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
_isHidden = DEFAULT_VALUE(CPMenuItemIsHiddenKey, NO);
_tag = DEFAULT_VALUE(CPMenuItemTagKey, 0);
_state = DEFAULT_VALUE(CPMenuItemStateKey, CPOffState);
// int _state;
_image = DEFAULT_VALUE(CPMenuItemImageKey, nil);
_alternateImage = DEFAULT_VALUE(CPMenuItemAlternateImageKey, nil);
@@ -804,8 +949,9 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
// CPImage _offStateImage;
// CPImage _mixedStateImage;
_submenu = DEFAULT_VALUE(CPMenuItemSubmenuKey, nil);
// This order matters because setSubmenu: needs _menu to be around.
_menu = DEFAULT_VALUE(CPMenuItemMenuKey, nil);
[self setSubmenu:DEFAULT_VALUE(CPMenuItemSubmenuKey, nil)];
_keyEquivalent = [aCoder decodeObjectForKey:CPMenuItemKeyEquivalentKey] || @"";
_keyEquivalentModifierMask = [aCoder decodeObjectForKey:CPMenuItemKeyEquivalentModifierMaskKey] || 0;
@@ -813,14 +959,16 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
// int _mnemonicLocation;
// BOOL _isAlternate;
// int _indentationLevel;
// Default is 0.
[self setIndentationLevel:[aCoder decodeIntForKey:CPMenuItemIndentationLevelKey] || 0];
// CPString _toolTip;
_representedObject = DEFAULT_VALUE(CPMenuItemRepresentedObjectKey, nil);
_view = DEFAULT_VALUE(CPMenuItemViewKey, nil);
}
return self;
}
@@ -834,11 +982,11 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
[aCoder encodeBool:_isSeparator forKey:CPMenuItemIsSeparatorKey];
[aCoder encodeObject:_title forKey:CPMenuItemTitleKey];
[aCoder encodeObject:_target forKey:CPMenuItemTargetKey];
[aCoder encodeObject:_action forKey:CPMenuItemActionKey];
ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES);
ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES);
ENCODE_IFNOT(CPMenuItemIsHiddenKey, _isHidden, NO);
ENCODE_IFNOT(CPMenuItemTagKey, _tag, 0);
@@ -846,7 +994,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
ENCODE_IFNOT(CPMenuItemImageKey, _image, nil);
ENCODE_IFNOT(CPMenuItemAlternateImageKey, _alternateImage, nil);
ENCODE_IFNOT(CPMenuItemSubmenuKey, _submenu, nil);
ENCODE_IFNOT(CPMenuItemMenuKey, _menu, nil);
@@ -856,423 +1004,11 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
if (_keyEquivalentModifierMask)
[aCoder encodeObject:_keyEquivalentModifierMask forKey:CPMenuItemKeyEquivalentModifierMaskKey];
if (_indentationLevel > 0)
[aCoder encodeInt:_indentationLevel forKey:CPMenuItemIndentationLevelKey];
ENCODE_IFNOT(CPMenuItemRepresentedObjectKey, _representedObject, nil);
ENCODE_IFNOT(CPMenuItemViewKey, _view, nil);
}
@end
var LEFT_MARGIN = 3.0,
RIGHT_MARGIN = 16.0,
STATE_COLUMN_WIDTH = 14.0,
INDENTATION_WIDTH = 17.0,
VERTICAL_MARGIN = 4.0;
var _CPMenuItemSelectionColor = nil,
_CPMenuItemTextShadowColor = nil,
_CPMenuItemDefaultStateImages = [],
_CPMenuItemDefaultStateHighlightedImages = [];
/*
@ignore
*/
@implementation _CPMenuItemView : CPView
{
CPMenuItem _menuItem;
CPFont _font;
CPColor _textColor;
CPColor _textShadowColor;
CPColor _activateColor;
CPColor _activateShadowColor;
CGSize _minSize;
BOOL _isDirty;
BOOL _showsStateColumn;
BOOL _belongsToMenuBar;
CPImageView _stateView;
_CPImageAndTextView _imageAndTextView;
CPView _submenuView;
}
+ (void)initialize
{
if (self != [_CPMenuItemView class])
return;
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]
var bundle = [CPBundle bundleForClass:self];
_CPMenuItemDefaultStateImages[CPOffState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil;
_CPMenuItemDefaultStateImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnState.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateHighlightedImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnStateHighlighted.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateImages[CPMixedState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPMixedState] = nil;
}
+ (float)leftMargin
{
return LEFT_MARGIN + STATE_COLUMN_WIDTH;
}
- (id)initWithFrame:(CGRect)aFrame forMenuItem:(CPMenuItem)aMenuItem
{
self = [super initWithFrame:aFrame];
if (self)
{
_menuItem = aMenuItem;
_showsStateColumn = YES;
_isDirty = YES;
[self setAutoresizingMask:CPViewWidthSizable];
[self synchronizeWithMenuItem];
}
return self;
}
- (CGSize)minSize
{
return _minSize;
}
- (void)setDirty
{
_isDirty = YES;
}
- (void)synchronizeWithMenuItem
{
if (!_isDirty)
return;
_isDirty = NO;
var view = [_menuItem view];
if ([_menuItem isSeparatorItem])
{
var line = [[CPView alloc] initWithFrame:CGRectMake(0.0, 5.0, 10.0, 1.0)];
view = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 10.0)];
[view setAutoresizingMask:CPViewWidthSizable];
[line setAutoresizingMask:CPViewWidthSizable];
[line setBackgroundColor:[CPColor lightGrayColor]];
[view addSubview:line];
}
if (view)
{
[_imageAndTextView removeFromSuperview];
_imageAndTextView = nil;
[_stateView removeFromSuperview];
_stateView = nil;
[_submenuView removeFromSuperview];
_submenuView = nil;
_minSize = [view frame].size;
[self setFrameSize:_minSize];
[self addSubview:view];
return;
}
// State Column
var x = _belongsToMenuBar ? 0.0 : (LEFT_MARGIN + [_menuItem indentationLevel] * INDENTATION_WIDTH);
if (_showsStateColumn)
{
if (!_stateView)
{
_stateView = [[CPImageView alloc] initWithFrame:CGRectMake(x, (CGRectGetHeight([self frame]) - STATE_COLUMN_WIDTH) / 2.0, STATE_COLUMN_WIDTH, STATE_COLUMN_WIDTH)];
[_stateView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin];
[self addSubview:_stateView];
}
var state = [_menuItem state];
switch (state)
{
case CPOffState:
case CPOnState:
case CPMixedState: [_stateView setImage:_CPMenuItemDefaultStateImages[state]];
break;
default: [_stateView setImage:nil];
}
x += STATE_COLUMN_WIDTH;
}
else
{
[_stateView removeFromSuperview];
_stateView = nil;
}
// Image and Title
if (!_imageAndTextView)
{
_imageAndTextView = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
[_imageAndTextView setImagePosition:CPImageLeft];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[self addSubview:_imageAndTextView];
}
var font = [_menuItem font];
if (!font)
font = _font;
[_imageAndTextView setFont:font];
[_imageAndTextView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_imageAndTextView setImage:[_menuItem image]];
[_imageAndTextView setText:[_menuItem title]];
[_imageAndTextView setTextColor:[self textColor]];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0, 1)];
[_imageAndTextView setFrameOrigin:CGPointMake(x, VERTICAL_MARGIN)];
[_imageAndTextView sizeToFit];
var frame = [_imageAndTextView frame];
// frame.size.height += 1.0;
// [_imageAndTextView setFrame:frame];
frame.size.height += 2 * VERTICAL_MARGIN;
x += CGRectGetWidth(frame);
// Submenu Arrow
if ([_menuItem hasSubmenu])
{
x += 3.0;
if (!_submenuView)
{
_submenuView = [[_CPMenuItemArrowView alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)];
[self addSubview:_submenuView];
}
[_submenuView setHidden:NO];
[_submenuView setColor:_belongsToMenuBar ? [self textColor] : nil];
[_submenuView setFrameOrigin:CGPointMake(x, (CGRectGetHeight(frame) - 10.0) / 2.0)];
x += 10.0;
}
else
[_submenuView setHidden:YES];
_minSize = CGSizeMake(x + (_belongsToMenuBar ? 0.0 : RIGHT_MARGIN) + 3.0, CGRectGetHeight(frame));
[self setFrameSize:_minSize];
}
- (CGFloat)overlapOffsetWidth
{
return LEFT_MARGIN + ([[_menuItem menu] showsStateColumn] ? STATE_COLUMN_WIDTH : 0.0);
}
- (void)setShowsStateColumn:(BOOL)shouldShowStateColumn
{
_showsStateColumn = shouldShowStateColumn;
}
- (void)setBelongsToMenuBar:(BOOL)shouldBelongToMenuBar
{
_belongsToMenuBar = shouldBelongToMenuBar;
}
- (void)highlight:(BOOL)shouldHighlight
{
// ASSERT(![_menuItem view]);
if (_belongsToMenuBar)
[_imageAndTextView setImage:shouldHighlight ? [_menuItem alternateImage] : [_menuItem image]];
else if ([_menuItem isEnabled])
{
if (shouldHighlight)
{
[self setBackgroundColor:_CPMenuItemSelectionColor];
[_imageAndTextView setTextColor:[CPColor whiteColor]];
[_imageAndTextView setTextShadowColor:_CPMenuItemTextShadowColor];
}
else
{
[self setBackgroundColor:nil];
[_imageAndTextView setTextColor:[self textColor]];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
}
var state = [_menuItem state];
switch (state)
{
case CPOffState:
case CPOnState:
case CPMixedState: [_stateView setImage:shouldHighlight ? _CPMenuItemDefaultStateHighlightedImages[state] : _CPMenuItemDefaultStateImages[state]];
break;
default: [_stateView setImage:nil];
}
}
}
- (void)activate:(BOOL)shouldActivate
{
[_imageAndTextView setImage:[_menuItem image]];
if (shouldActivate)
{
[_imageAndTextView setTextColor:[self activateColor] || [CPColor whiteColor]];
[_imageAndTextView setTextShadowColor:[self activateShadowColor] || [CPColor blackColor]];
[_submenuView setColor:[self activateColor] || [CPColor whiteColor]];
}
else
{
[_imageAndTextView setTextColor:[self textColor]];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_submenuView setColor:[self textColor]];
}
}
- (BOOL)eventOnSubmenu:(CPEvent)anEvent
{
if (![_menuItem hasSubmenu])
return NO;
return CGRectContainsPoint([_submenuView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]);
}
- (BOOL)isHidden
{
return [_menuItem isHidden];
}
- (CPMenuItem)menuItem
{
return _menuItem;
}
- (void)setFont:(CPFont)aFont
{
if (_font == aFont)
return;
_font = aFont;
[self setDirty];
}
- (void)setTextColor:(CPColor)aColor
{
if (_textColor == aColor)
return;
_textColor = aColor;
[_imageAndTextView setTextColor:[self textColor]];
[_submenuView setColor:[self textColor]];
}
- (CPColor)textColor
{
return [_menuItem isEnabled] ? (_textColor ? _textColor : [CPColor colorWithCalibratedRed:70.0 / 255.0 green:69.0 / 255.0 blue:69.0 / 255.0 alpha:1.0]) : [CPColor lightGrayColor];
}
- (void)setTextShadowColor:(CPColor)aColor
{
if (_textShadowColor == aColor)
return;
_textShadowColor = aColor;
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
//[_submenuView setColor:[self textColor]];
}
- (CPColor)textShadowColor
{
return [_menuItem isEnabled] ? (_textShadowColor ? _textShadowColor : [CPColor colorWithWhite:1.0 alpha:0.8]) : [CPColor colorWithWhite:0.8 alpha:0.8];
}
- (void)setActivateColor:(CPColor)aColor
{
_activateColor = aColor;
}
- (CPColor)activateColor
{
return _activateColor;
}
- (void)setActivateShadowColor:(CPColor)aColor
{
_activateShadowColor = aColor;
}
- (CPColor)activateShadowColor
{
return _activateShadowColor;
}
@end
@implementation _CPMenuItemArrowView : CPView
{
CPColor _color;
}
- (void)setColor:(CPColor)aColor
{
if (_color == aColor)
return;
_color = aColor;
[self setNeedsDisplay:YES];
}
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextBeginPath(context);
CGContextMoveToPoint(context, 1.0, 4.0);
CGContextAddLineToPoint(context, 9.0, 4.0);
CGContextAddLineToPoint(context, 5.0, 8.0);
CGContextAddLineToPoint(context, 1.0, 4.0);
CGContextClosePath(context);
CGContextSetFillColor(context, _color);
CGContextFillPath(context);
}
@end
+239
View File
@@ -0,0 +1,239 @@
@import "CPView.j"
var HORIZONTAL_MARGIN = 8.0,
SUBMENU_INDICATOR_MARGIN = 3.0,
VERTICAL_MARGIN = 4.0;
var SelectionColor = nil,
SUBMENU_INDICATOR_COLOR = nil,
_CPMenuItemSelectionColor = nil,
_CPMenuItemTextShadowColor = nil,
_CPMenuItemDefaultStateImages = [],
_CPMenuItemDefaultStateHighlightedImages = [];
@implementation _CPMenuItemMenuBarView : CPView
{
CPMenuItem _menuItem @accessors(property=menuItem);
CPFont _font;
CPColor _textColor;
CPColor _textShadowColor;
BOOL _isDirty;
_CPImageAndTextView _imageAndTextView;
CPView _submenuIndicatorView;
}
+ (void)initialize
{
if (self !== [_CPMenuItemMenuBarView class])
return;
var bundle = [CPBundle bundleForClass:self];
SelectionColor = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuBarWindow/_CPMenuBarWindowBackgroundSelected.png"] size:CGSizeMake(1.0, 28.0)]];
SUBMENU_INDICATOR_COLOR = [CPColor grayColor];
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
_CPMenuItemDefaultStateImages[CPOffState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil;
_CPMenuItemDefaultStateImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnState.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateHighlightedImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnStateHighlighted.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateImages[CPMixedState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPMixedState] = nil;
}
+ (id)view
{
return [[self alloc] init];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_imageAndTextView = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(HORIZONTAL_MARGIN, 0.0, 0.0, 0.0)];
[_imageAndTextView setImagePosition:CPImageLeft];
[_imageAndTextView setImageOffset:3.0];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_imageAndTextView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin];
[self addSubview:_imageAndTextView];
_submenuIndicatorView = [[_CPMenuItemMenuBarSubmenuIndicatorView alloc] initWithFrame:CGRectMake(0.0, 0.0, 9.0, 6.0)];
[_submenuIndicatorView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin];
[self addSubview:_submenuIndicatorView];
[self setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
}
return self;
}
- (CPColor)textColor
{
if (![_menuItem isEnabled])
return [CPColor lightGrayColor];
return _textColor || [CPColor colorWithCalibratedRed:70.0 / 255.0 green:69.0 / 255.0 blue:69.0 / 255.0 alpha:1.0];
}
- (CPColor)textShadowColor
{
if (![_menuItem isEnabled])
return [CPColor colorWithWhite:0.8 alpha:0.8];
return _textShadowColor || [CPColor colorWithWhite:1.0 alpha:0.8];
}
- (void)update
{
var x = HORIZONTAL_MARGIN,
height = 0.0;
[_imageAndTextView setFont:[_menuItem font] || [_CPMenuBarWindow font]];
[_imageAndTextView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_imageAndTextView setImage:[_menuItem image]];
[_imageAndTextView setText:[_menuItem title]];
[_imageAndTextView setTextColor:[self textColor]];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_imageAndTextView sizeToFit];
var imageAndTextViewFrame = [_imageAndTextView frame];
imageAndTextViewFrame.origin.x = x;
x += CGRectGetWidth(imageAndTextViewFrame);
height = MAX(height, CGRectGetHeight(imageAndTextViewFrame));
var hasSubmenuIndicator = [_menuItem hasSubmenu] && [_menuItem action];
if (hasSubmenuIndicator)
{
[_submenuIndicatorView setHidden:NO];
[_submenuIndicatorView setColor:[self textColor]];
[_submenuIndicatorView setShadowColor:[self textShadowColor]];
var submenuViewFrame = [_submenuIndicatorView frame];
submenuViewFrame.origin.x = x + SUBMENU_INDICATOR_MARGIN;
x = CGRectGetMaxX(submenuViewFrame);
height = MAX(height, CGRectGetHeight(submenuViewFrame));
}
else
[_submenuIndicatorView setHidden:YES];
height += 2.0 * VERTICAL_MARGIN;
imageAndTextViewFrame.origin.y = FLOOR((height - CGRectGetHeight(imageAndTextViewFrame)) / 2.0);
[_imageAndTextView setFrame:imageAndTextViewFrame];
if (hasSubmenuIndicator)
{
submenuViewFrame.origin.y = FLOOR((height - CGRectGetHeight(submenuViewFrame)) / 2.0) + 1.0;
[_submenuIndicatorView setFrame:submenuViewFrame];
}
_minSize = CGSizeMake(x + HORIZONTAL_MARGIN, height);
[self setAutoresizesSubviews:NO];
[self setFrameSize:_minSize];
[self setAutoresizesSubviews:YES];
}
- (void)highlight:(BOOL)shouldHighlight
{
// FIXME: This should probably be even throw.
if (![_menuItem isEnabled])
shouldHighlight = NO;
if (shouldHighlight)
{
if (![_menuItem _isMenuBarButton])
[self setBackgroundColor:SelectionColor];
[_imageAndTextView setImage:[_menuItem alternateImage] || [_menuItem image]];
[_imageAndTextView setTextColor:[CPColor whiteColor]];
[_imageAndTextView setTextShadowColor:_CPMenuItemTextShadowColor];
[_submenuIndicatorView setColor:[CPColor whiteColor]];
[_submenuIndicatorView setShadowColor:[CPColor colorWithWhite:0.1 alpha:0.7]];
}
else
{
[self setBackgroundColor:nil];
[_imageAndTextView setImage:[_menuItem image]];
[_imageAndTextView setTextColor:[self textColor]];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_submenuIndicatorView setColor:[self textColor]];
[_submenuIndicatorView setShadowColor:[self textShadowColor]];
}
}
@end
@implementation _CPMenuItemMenuBarSubmenuIndicatorView : CPView
{
CPColor _color;
CPColor _shadowColor;
}
- (void)setColor:(CPColor)aColor
{
if (_color === aColor)
return;
_color = aColor;
[self setNeedsDisplay:YES];
}
- (void)setShadowColor:(CPColor)aColor
{
if (_shadowColor === aColor)
return;
_shadowColor = aColor;
[self setNeedsDisplay:YES];
}
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds];
bounds.size.height -= 1.0;
bounds.size.width -= 2.0;
bounds.origin.x += 1.0;
CGContextBeginPath(context);
CGContextMoveToPoint(context, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
CGContextAddLineToPoint(context, CGRectGetMidX(bounds), CGRectGetMaxY(bounds));
CGContextClosePath(context);
CGContextSetShadowWithColor(context, CGSizeMake(0.0, 1.0), 1.1, _shadowColor || [CPColor whiteColor]);
CGContextSetFillColor(context, _color || [CPColor blackColor]);
CGContextFillPath(context);
}
@end
@@ -0,0 +1,38 @@
@import "CPView.j"
@implementation _CPMenuItemSeparatorView : CPView
{
}
+ (id)view
{
return [[self alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 10.0)];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
[self setAutoresizingMask:CPViewWidthSizable];
return self;
}
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds];
CGContextBeginPath(context);
CGContextMoveToPoint(context, CGRectGetMinX(bounds), FLOOR(CGRectGetMidY(bounds)) - 0.5);
CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), FLOOR(CGRectGetMidY(bounds)) - 0.5);
CGContextSetStrokeColor(context, [CPColor lightGrayColor]);
CGContextStrokePath(context);
}
@end
+306
View File
@@ -0,0 +1,306 @@
@import "CPControl.j"
var LEFT_MARGIN = 3.0,
RIGHT_MARGIN = 14.0 + 3.0,
STATE_COLUMN_WIDTH = 14.0,
INDENTATION_WIDTH = 17.0,
VERTICAL_MARGIN = 4.0,
RIGHT_COLUMNS_MARGIN = 30.0,
KEY_EQUIVALENT_MARGIN = 10.0;
var SUBMENU_INDICATOR_COLOR = nil,
_CPMenuItemSelectionColor = nil,
_CPMenuItemTextShadowColor = nil,
_CPMenuItemDefaultStateImages = [],
_CPMenuItemDefaultStateHighlightedImages = [];
@implementation _CPMenuItemStandardView : CPView
{
CPMenuItem _menuItem @accessors(property=menuItem);
CPFont _font;
CPColor _textColor;
CPColor _textShadowColor;
CGSize _minSize @accessors(readonly, property=minSize);
BOOL _isDirty;
CPImageView _stateView;
_CPImageAndTextView _imageAndTextView;
_CPImageAndTextView _keyEquivalentView;
CPView _submenuIndicatorView;
}
+ (void)initialize
{
if (self !== [_CPMenuItemStandardView class])
return;
SUBMENU_INDICATOR_COLOR = [CPColor grayColor];
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
var bundle = [CPBundle bundleForClass:self];
_CPMenuItemDefaultStateImages[CPOffState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil;
_CPMenuItemDefaultStateImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnState.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateHighlightedImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnStateHighlighted.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateImages[CPMixedState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPMixedState] = nil;
}
+ (id)view
{
return [[self alloc] init];
}
+ (float)_standardLeftMargin
{
return LEFT_MARGIN + STATE_COLUMN_WIDTH;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_stateView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
[_stateView setImageScaling:CPScaleNone];
[self addSubview:_stateView];
_imageAndTextView = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
[_imageAndTextView setImagePosition:CPImageLeft];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[self addSubview:_imageAndTextView];
_keyEquivalentView = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
[_keyEquivalentView setImagePosition:CPNoImage];
[_keyEquivalentView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_keyEquivalentView setAutoresizingMask:CPViewMinXMargin];
[self addSubview:_keyEquivalentView];
_submenuIndicatorView = [[_CPMenuItemSubmenuIndicatorView alloc] initWithFrame:CGRectMake(0.0, 0.0, 8.0, 10.0)];
[_submenuIndicatorView setColor:SUBMENU_INDICATOR_COLOR];
[_submenuIndicatorView setAutoresizingMask:CPViewMinXMargin];
[self addSubview:_submenuIndicatorView];
[self setAutoresizingMask:CPViewWidthSizable];
}
return self;
}
- (CPColor)textColor
{
if (![_menuItem isEnabled])
return [CPColor lightGrayColor];
return _textColor || [CPColor colorWithCalibratedRed:70.0 / 255.0 green:69.0 / 255.0 blue:69.0 / 255.0 alpha:1.0];
}
- (CPColor)textShadowColor
{
if (![_menuItem isEnabled])
return nil;
return _textShadowColor || [CPColor colorWithWhite:1.0 alpha:0.8];
}
- (void)setFont:(CPFont)aFont
{
_font = aFont;
}
- (void)update
{
var x = LEFT_MARGIN + [_menuItem indentationLevel] * INDENTATION_WIDTH,
height = 0.0,
hasStateColumn = [[_menuItem menu] showsStateColumn];
if (hasStateColumn)
{
[_stateView setHidden:NO];
[_stateView setImage:_CPMenuItemDefaultStateImages[[_menuItem state]] || nil];
x += STATE_COLUMN_WIDTH;
}
else
[_stateView setHidden:YES];
[_imageAndTextView setFont:[_menuItem font] || _font];
[_imageAndTextView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_imageAndTextView setImage:[_menuItem image]];
[_imageAndTextView setText:[_menuItem title]];
[_imageAndTextView setTextColor:[self textColor]];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_imageAndTextView sizeToFit];
var imageAndTextViewFrame = [_imageAndTextView frame];
imageAndTextViewFrame.origin.x = x;
x += CGRectGetWidth(imageAndTextViewFrame);
height = MAX(height, CGRectGetHeight(imageAndTextViewFrame));
var hasKeyEquivalent = !![_menuItem keyEquivalent],
hasSubmenu = [_menuItem hasSubmenu];
if (hasKeyEquivalent || hasSubmenu)
x += RIGHT_COLUMNS_MARGIN;
if (hasKeyEquivalent)
{
[_keyEquivalentView setFont:[_menuItem font] || _font];
[_keyEquivalentView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_keyEquivalentView setImage:[_menuItem image]];
[_keyEquivalentView setText:[_menuItem keyEquivalentStringRepresentation]];
[_keyEquivalentView setTextColor:[self textColor]];
[_keyEquivalentView setTextShadowColor:[self textShadowColor]];
[_keyEquivalentView setTextShadowOffset:CGSizeMake(0, 1)];
[_keyEquivalentView setFrameOrigin:CGPointMake(x, VERTICAL_MARGIN)];
[_keyEquivalentView sizeToFit];
var keyEquivalentViewFrame = [_keyEquivalentView frame];
keyEquivalentViewFrame.origin.x = x;
x += CGRectGetWidth(keyEquivalentViewFrame);
height = MAX(height, CGRectGetHeight(keyEquivalentViewFrame));
if (hasSubmenu)
x += RIGHT_COLUMNS_MARGIN;
}
else
[_keyEquivalentView setHidden:YES];
if (hasSubmenu)
{
[_submenuIndicatorView setHidden:NO];
var submenuViewFrame = [_submenuIndicatorView frame];
submenuViewFrame.origin.x = x;
x += CGRectGetWidth(submenuViewFrame);
height = MAX(height, CGRectGetHeight(submenuViewFrame));
}
else
[_submenuIndicatorView setHidden:YES];
height += 2.0 * VERTICAL_MARGIN;
imageAndTextViewFrame.origin.y = FLOOR((height - CGRectGetHeight(imageAndTextViewFrame)) / 2.0);
[_imageAndTextView setFrame:imageAndTextViewFrame];
if (hasStateColumn)
[_stateView setFrameSize:CGSizeMake(STATE_COLUMN_WIDTH, height)];
if (hasKeyEquivalent)
{
keyEquivalentViewFrame.origin.y = FLOOR((height - CGRectGetHeight(keyEquivalentViewFrame)) / 2.0);
[_keyEquivalentView setFrame:keyEquivalentViewFrame];
}
if (hasSubmenu)
{
submenuViewFrame.origin.y = FLOOR((height - CGRectGetHeight(submenuViewFrame)) / 2.0);
[_submenuIndicatorView setFrame:submenuViewFrame];
}
_minSize = CGSizeMake(x + RIGHT_MARGIN, height);
[self setAutoresizesSubviews:NO];
[self setFrameSize:_minSize];
[self setAutoresizesSubviews:YES];
}
- (void)highlight:(BOOL)shouldHighlight
{
// FIXME: This should probably be even throw.
if (![_menuItem isEnabled])
return;
if (shouldHighlight)
{
[self setBackgroundColor:_CPMenuItemSelectionColor];
[_imageAndTextView setImage:[_menuItem alternateImage] || [_menuItem image]];
[_imageAndTextView setTextColor:[CPColor whiteColor]];
[_keyEquivalentView setTextColor:[CPColor whiteColor]];
[_submenuIndicatorView setColor:[CPColor whiteColor]];
[_imageAndTextView setTextShadowColor:_CPMenuItemTextShadowColor];
[_keyEquivalentView setTextShadowColor:_CPMenuItemTextShadowColor];
}
else
{
[self setBackgroundColor:nil];
[_imageAndTextView setImage:[_menuItem image]];
[_imageAndTextView setTextColor:[self textColor]];
[_keyEquivalentView setTextColor:[self textColor]];
[_submenuIndicatorView setColor:SUBMENU_INDICATOR_COLOR];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_keyEquivalentView setTextShadowColor:[self textShadowColor]];
}
if ([[_menuItem menu] showsStateColumn])
{
if (shouldHighlight)
[_stateView setImage:_CPMenuItemDefaultStateHighlightedImages[[_menuItem state]] || nil];
else
[_stateView setImage:_CPMenuItemDefaultStateImages[[_menuItem state]] || nil];
}
}
@end
@implementation _CPMenuItemSubmenuIndicatorView : CPView
{
CPColor _color;
}
- (void)setColor:(CPColor)aColor
{
if (_color === aColor)
return;
_color = aColor;
[self setNeedsDisplay:YES];
}
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds];
CGContextBeginPath(context);
CGContextMoveToPoint(context, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), CGRectGetMidY(bounds));
CGContextAddLineToPoint(context, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
CGContextClosePath(context);
CGContextSetFillColor(context, _color);
CGContextFillPath(context);
}
@end
+256
View File
@@ -0,0 +1,256 @@
@import <AppKit/CPControl.j>
@import "_CPMenuItemSeparatorView.j"
@import "_CPMenuItemStandardView.j"
@import "_CPMenuItemMenuBarView.j"
var LEFT_MARGIN = 3.0,
RIGHT_MARGIN = 16.0,
STATE_COLUMN_WIDTH = 14.0,
INDENTATION_WIDTH = 17.0,
VERTICAL_MARGIN = 4.0;
var _CPMenuItemSelectionColor = nil,
_CPMenuItemTextShadowColor = nil,
_CPMenuItemDefaultStateImages = [],
_CPMenuItemDefaultStateHighlightedImages = [];
/*
@ignore
*/
@implementation _CPMenuItemView : CPView
{
CPMenuItem _menuItem;
CPView _view;
CPFont _font;
CPColor _textColor;
CPColor _textShadowColor;
CGSize _minSize;
BOOL _isDirty;
BOOL _showsStateColumn;
_CPImageAndTextView _imageAndTextView;
CPView _submenuView;
}
+ (void)initialize
{
if (self != [_CPMenuItemView class])
return;
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
var bundle = [CPBundle bundleForClass:self];
_CPMenuItemDefaultStateImages[CPOffState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil;
_CPMenuItemDefaultStateImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnState.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateHighlightedImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnStateHighlighted.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateImages[CPMixedState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPMixedState] = nil;
}
+ (float)leftMargin
{
return LEFT_MARGIN + STATE_COLUMN_WIDTH;
}
- (id)initWithFrame:(CGRect)aFrame forMenuItem:(CPMenuItem)aMenuItem
{
self = [super initWithFrame:aFrame];
if (self)
{
_menuItem = aMenuItem;
_showsStateColumn = YES;
_isDirty = YES;
[self setAutoresizingMask:CPViewWidthSizable];
[self synchronizeWithMenuItem];
}
return self;
}
- (CGSize)minSize
{
return _minSize;
}
- (void)setDirty
{
_isDirty = YES;
}
- (void)synchronizeWithMenuItem
{
var menuItemView = [_menuItem view];
if ([_menuItem isSeparatorItem])
{
if (![_view isKindOfClass:[_CPMenuItemSeparatorView class]])
{
[_view removeFromSuperview];
_view = [_CPMenuItemSeparatorView view];
}
}
else if (menuItemView)
{
if (_view !== menuItemView)
{
[_view removeFromSuperview];
_view = menuItemView;
}
}
else if ([_menuItem menu] == [CPApp mainMenu])
{
if (![_view isKindOfClass:[_CPMenuItemMenuBarView class]])
{
[_view removeFromSuperview];
_view = [_CPMenuItemMenuBarView view];
}
[_view setMenuItem:_menuItem];
}
else
{
if (![_view isKindOfClass:[_CPMenuItemStandardView class]])
{
[_view removeFromSuperview];
_view = [_CPMenuItemStandardView view];
}
[_view setMenuItem:_menuItem];
}
if ([_view superview] !== self)
[self addSubview:_view];
if ([_view respondsToSelector:@selector(update)])
[_view update];
_minSize = [_view frame].size;
[self setAutoresizesSubviews:NO];
[self setFrameSize:_minSize];
[self setAutoresizesSubviews:YES];
}
- (void)setShowsStateColumn:(BOOL)shouldShowStateColumn
{
_showsStateColumn = shouldShowStateColumn;
}
- (void)highlight:(BOOL)shouldHighlight
{
if ([_view respondsToSelector:@selector(highlight:)])
[_view highlight:shouldHighlight];
}
- (BOOL)eventOnSubmenu:(CPEvent)anEvent
{
if (![_menuItem hasSubmenu])
return NO;
return CGRectContainsPoint([_submenuView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]);
}
- (BOOL)isHidden
{
return [_menuItem isHidden];
}
- (CPMenuItem)menuItem
{
return _menuItem;
}
- (void)setFont:(CPFont)aFont
{
if (_font === aFont)
return;
_font = aFont;
if ([_view respondsToSelector:@selector(setFont:)])
[_view setFont:aFont];
[self setDirty];
}
- (void)setTextColor:(CPColor)aColor
{
if (_textColor == aColor)
return;
_textColor = aColor;
[_imageAndTextView setTextColor:[self textColor]];
[_submenuView setColor:[self textColor]];
}
- (CPColor)textColor
{
return nil;
}
- (void)setTextShadowColor:(CPColor)aColor
{
if (_textShadowColor == aColor)
return;
_textShadowColor = aColor;
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
//[_submenuView setColor:[self textColor]];
}
- (CPColor)textShadowColor
{
return [_menuItem isEnabled] ? (_textShadowColor ? _textShadowColor : [CPColor colorWithWhite:1.0 alpha:0.8]) : [CPColor colorWithWhite:0.8 alpha:0.8];
}
@end
@implementation _CPMenuItemArrowView : CPView
{
CPColor _color;
}
- (void)setColor:(CPColor)aColor
{
if (_color == aColor)
return;
_color = aColor;
[self setNeedsDisplay:YES];
}
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextBeginPath(context);
CGContextMoveToPoint(context, 1.0, 4.0);
CGContextAddLineToPoint(context, 9.0, 4.0);
CGContextAddLineToPoint(context, 5.0, 8.0);
CGContextAddLineToPoint(context, 1.0, 4.0);
CGContextClosePath(context);
CGContextSetFillColor(context, _color);
CGContextFillPath(context);
}
@end
+799
View File
@@ -0,0 +1,799 @@
/*
* CPObjectController.j
* AppKit
*
* Created by Ross Boucher.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPDictionary.j>
@import <Foundation/CPCountedSet.j>
@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;
CPCountedSet _observedKeys;
}
+ (id)initialize
{
[self exposeBinding:@"editable"];
[self exposeBinding:@"contentObject"];
}
+ (CPSet)keyPathsForValuesAffectingContentObject
{
return [CPSet setWithObjects:"content"];
}
+ (BOOL)automaticallyNotifiesObserversForKey:(CPString)aKey
{
if (aKey === @"contentObject")
return NO;
return YES;
}
+ (CPSet)keyPathsForValuesAffectingCanAdd
{
return [CPSet setWithObject:"editable"];
}
+ (CPSet)keyPathsForValuesAffectingCanInsert
{
return [CPSet setWithObject:"editable"];
}
+ (CPSet)keyPathsForValuesAffectingCanRemove
{
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])
{
[self setContent:aContent];
[self setEditable:YES];
[self setObjectClass:[CPMutableDictionary class]];
_observedKeys = [[CPCountedSet alloc] init];
}
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"];
[self _selectionWillChange];
_contentObject = aContent;
[self didChangeValueForKey:@"contentObject"];
[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;
}
/*!
@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];
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];
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] 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)
_selection = [[CPControllerSelectionProxy alloc] initWithController:self];
[_selection controllerDidChange];
[self didChangeValueForKey:@"selection"];
}
/*!
@return id - Returns the keys which are being observed.
*/
- (id)observedKeys
{
return _observedKeys;
}
- (void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
[_observedKeys addObject:aKeyPath];
[super addObserver:anObserver forKeyPath:aKeyPath options:options context:context];
}
- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath
{
[_observedKeys removeObject:aKeyPath];
[super removeObserver:anObserver forKeyPath:aKeyPath];
}
@end
var CPObjectControllerContentKey = @"CPObjectControllerContentKey",
CPObjectControllerObjectClassNameKey = @"CPObjectControllerObjectClassNameKey",
CPObjectControllerIsEditableKey = @"CPObjectControllerIsEditableKey",
CPObjectControllerAutomaticallyPreparesContentKey = @"CPObjectControllerAutomaticallyPreparesContentKey";
@implementation CPObjectController (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
var objectClassName = [aCoder decodeObjectForKey:CPObjectControllerObjectClassNameKey],
objectClass = CPClassFromString(objectClassName);
[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];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:[self content] forKey:CPObjectControllerContentKey];
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];
}
- (void)awakeFromCib
{
if (![self content] && [self automaticallyPreparesContent])
[self prepareContent];
}
@end
@implementation _CPObservationProxy : CPObject
{
id _keyPath;
id _observer;
id _object;
BOOL _notifyObject;
id _context;
int _options;
}
- (id)initWithKeyPath:(id)aKeyPath observer:(id)anObserver object:(id)anObject
{
if (self = [super init])
{
_keyPath = aKeyPath;
_observer = anObserver;
_object = anObject;
}
return self;
}
- (id)observer
{
return _observer;
}
- (id)keyPath
{
return _keyPath;
}
- (id)context
{
return _context;
}
- (int)options
{
return _options;
}
- (void)setNotifyObject:(BOOL)notify
{
_notifyObject = notify;
}
- (BOOL)isEqual:(id)anObject
{
if ([anObject class] === [self class])
{
if (anObject._observer === _observer && [anObject._keyPath isEqual:_keyPath] && [anObject._object isEqual:_object])
return YES;
}
return NO;
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
{
if (_notifyObject)
[_object observeValueForKeyPath:aKeyPath ofObject:_object change:change context:context];
[_observer observeValueForKeyPath:aKeyPath ofObject:_object change:change context:context];
}
- (CPString)description
{
return [super description] + [CPString stringWithFormat:@"observation proxy for %@ on key path %@", _observer, _keyPath];
}
@end
// FIXME: This should subclass CPMutableArray not _CPJavaScriptArray
@implementation _CPObservableArray : _CPJavaScriptArray
{
CPArray _observationProxies;
}
+ (id)alloc
{
var a = [];
a.isa = self;
var ivars = class_copyIvarList(self),
count = ivars.length;
while (count--)
a[ivar_getName(ivars[count])] = nil;
return a;
}
- (CPString)description
{
return "<_CPObservableArray: " + [super description] + " >";
}
- (id)initWithArray:(CPArray)anArray
{
self = [super initWithArray:anArray];
self.isa = [_CPObservableArray class];
self._observationProxies = [];
return self;
}
- (void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
if (aKeyPath.indexOf("@") === 0)
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self];
proxy._options = options;
proxy._context = context;
[_observationProxies addObject:proxy];
var dotIndex = aKeyPath.indexOf("."),
remaining = aKeyPath.substring(dotIndex + 1),
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self addObserver:proxy toObjectsAtIndexes:indexes forKeyPath:remaining options:options context:context];
}
else
{
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self addObserver:anObserver toObjectsAtIndexes:indexes forKeyPath:aKeyPath options:options context:context];
}
}
- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath
{
if (aKeyPath.indexOf("@") === 0)
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self],
index = [_observationProxies indexOfObject:proxy];
proxy = [_observationProxies objectAtIndex:index];
var dotIndex = aKeyPath.indexOf("."),
remaining = aKeyPath.substring(dotIndex + 1),
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self removeObserver:proxy fromObjectsAtIndexes:indexes forKeyPath:remaining];
}
else
{
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self removeObserver:anObserver fromObjectsAtIndexes:indexes forKeyPath:aKeyPath];
}
}
- (void)insertObject:(id)anObject atIndex:(unsigned)anIndex
{
for (var i = 0, count = [_observationProxies count]; i < count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super insertObject:anObject atIndex:anIndex];
}
- (void)removeObjectAtIndex:(unsigned)anIndex
{
for (var i = 0, count = [_observationProxies count]; i < count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[anObject removeObserver:proxy forKeyPath:keyPath];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super removeObjectAtIndex:anIndex];
}
- (_CPObservableArray)objectsAtIndexes:(CPIndexSet)theIndexes
{
return [_CPObservableArray arrayWithArray:[super objectsAtIndexes:theIndexes]];
}
- (void)addObject:(id)anObject
{
[self insertObject:anObject atIndex:[self count]];
}
- (void)removeLastObject
{
[self removeObjectAtIndex:[self count]];
}
- (void)replaceObjectAtIndex:(unsigned)anIndex withObject:(id)anObject
{
var currentObject = [self objectAtIndex:anIndex];
for (var i = 0, count = [_observationProxies count]; i < count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[currentObject removeObserver:proxy forKeyPath:keyPath];
[anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super replaceObjectAtIndex:anIndex withObject:anObject];
}
@end
@implementation CPControllerSelectionProxy : CPObject
{
id _controller;
id _keys;
CPDictionary _cachedValues;
CPArray _observationProxies;
Object _observedObjectsByKeyPath;
}
- (id)initWithController:(id)aController
{
if (self = [super init])
{
_cachedValues = [CPDictionary dictionary];
_observationProxies = [CPArray array];
_controller = aController;
_observedObjectsByKeyPath = {};
}
return self;
}
- (id)_controllerMarkerForValues:(CPArray)theValues
{
var count = [theValues count];
if (!count)
value = CPNoSelectionMarker;
else if (count === 1)
value = [theValues objectAtIndex:0];
else
{
if ([_controller alwaysUsesMultipleValuesMarker])
value = CPMultipleValuesMarker;
else
{
value = [theValues objectAtIndex:0];
for (var i = 0, count= [theValues count]; i < count && value != CPMultipleValuesMarker; i++)
{
if (![value isEqual:[theValues objectAtIndex:i]])
value = CPMultipleValuesMarker;
}
}
}
if (value === nil || value.isa && [value isEqual:[CPNull null]])
value = CPNullMarker;
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];
// Allow handlesContentAsCompoundValue to work, based on observation of Cocoa's
// NSArrayController - when handlesContentAsCompoundValue and setValue:forKey:@"selection.X"
// is called, the array controller causes the compound value to be rewritten if
// handlesContentAsCompoundValue == YES. Note that
// A) this doesn't use observation (observe: X is not visible in backtraces)
// B) it only happens through the selection proxy and not on arrangedObject.X, content.X
// or even selectedObjects.X.
// FIXME The main code for this should somehow be in CPArrayController and also work
// for table based row edits.
[[CPBinder getBinding:@"contentArray" forObject:_controller] _contentArrayDidChange];
}
- (void)setValue:(id)theValue forKey:(CPString)theKeyPath
{
[self setValue:theKeyPath forKeyPath:theKeyPath];
}
- (unsigned)count
{
return [_cachedValues count];
}
- (id)keyEnumerator
{
return [_cachedValues keyEnumerator];
}
- (void)controllerWillChange
{
_keys = [_cachedValues allKeys];
if (!_keys)
return;
for (var i = 0, count = _keys.length; i < count; i++)
[self willChangeValueForKey:_keys[i]];
[_cachedValues removeAllObjects];
}
- (void)controllerDidChange
{
[_cachedValues removeAllObjects];
if (!_keys)
return;
for (var i = 0, count = _keys.length; i < count; i++)
[self didChangeValueForKey:_keys[i]];
_keys = nil;
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
{
[_cachedValues removeObjectForKey:aKeyPath];
}
- (void)addObserver:(id)anObject forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self];
[proxy setNotifyObject:YES];
[_observationProxies addObject:proxy];
// 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
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self],
index = [_observationProxies indexOfObject:proxy];
var observedObjects = _observedObjectsByKeyPath[aKeyPath];
[observedObjects removeObserver:[_observationProxies objectAtIndex:index] forKeyPath:aKeyPath];
[_observationProxies removeObjectAtIndex:index];
_observedObjects = nil;
}
@end
+22 -1
View File
@@ -1,5 +1,26 @@
/*
* CPOpenPanel.j
* AppKit
*
* Created by Ross Boucher.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CPPanel.j>
@import "CPPanel.j"
@implementation CPOpenPanel : CPPanel
+1298 -194
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
{
+110 -40
View File
@@ -25,8 +25,6 @@
@import <Foundation/CPDictionary.j>
@import <Foundation/CPPropertyListSerialization.j>
#include "Platform/Platform.h"
CPGeneralPboard = @"CPGeneralPboard";
CPFontPboard = @"CPFontPboard";
@@ -43,26 +41,31 @@ CPURLPboardType = @"CPURLPboardType";
CPImagesPboardType = @"CPImagesPboardType";
CPVideosPboardType = @"CPVideosPboardType";
UTF8PboardType = @"public.utf8-plain-text";
// Deprecated
CPImagePboardType = @"CPImagePboardType";
var CPPasteboards = nil;
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;
WebScriptObject _nativePasteboard;
}
/*
@@ -74,8 +77,11 @@ var CPPasteboards = nil;
return;
[self setVersion:1.0];
CPPasteboards = [CPDictionary dictionary];
if (typeof window.cpPasteboardWithName !== "undefined")
supportsNativePasteboard = YES;
}
/*!
@@ -94,13 +100,13 @@ var CPPasteboards = nil;
+ (id)pasteboardWithName:(CPString)aName
{
var pasteboard = [CPPasteboards objectForKey:aName];
if (pasteboard)
return pasteboard;
pasteboard = [[CPPasteboard alloc] _initWithName:aName];
[CPPasteboards setObject:pasteboard forKey:aName];
return pasteboard;
}
@@ -108,18 +114,24 @@ 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)
{
_nativePasteboard = window.cpPasteboardWithName(aName);
[self _synchronizePasteboard];
}
}
return self;
}
@@ -133,20 +145,29 @@ 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];
}
if (_nativePasteboard)
{
var nativeTypes = [types copy];
if ([types containsObject:CPStringPboardType])
nativeTypes.push(UTF8PboardType);
_nativePasteboard.addTypes_(nativeTypes);
}
return ++_changeCount;
}
@@ -157,6 +178,12 @@ var CPPasteboards = nil;
@return the pasteboard's change count
*/
- (unsigned)declareTypes:(CPArray)types owner:(id)anOwner
{
[self _declareTypes:types owner:anOwner updateNativePasteboard:YES];
}
/*! @ignore */
- (unsigned)_declareTypes:(CPArray)types owner:(id)anOwner updateNativePasteboard:(BOOL)shouldUpdate
{
[_types setArray:types];
@@ -164,10 +191,19 @@ var CPPasteboards = nil;
_provided = [CPDictionary dictionary];
var count = _types.length;
while (count--)
[_owners setObject:anOwner forKey:_types[count]];
if (_nativePasteboard && shouldUpdate)
{
var nativeTypes = [types copy];
if ([types containsObject:CPStringPboardType])
nativeTypes.push(UTF8PboardType);
_nativePasteboard.declareTypes_(nativeTypes);
_changeCount = _nativePasteboard.changeCount();
}
return ++_changeCount;
}
@@ -180,7 +216,10 @@ var CPPasteboards = nil;
- (BOOL)setData:(CPData)aData forType:(CPString)aType
{
[_provided setObject:aData forKey:aType];
if (aType === CPStringPboardType)
[self setData:aData forType:UTF8PboardType];
return YES;
}
@@ -192,7 +231,7 @@ var CPPasteboards = nil;
*/
- (BOOL)setPropertyList:(id)aPropertyList forType:(CPString)aType
{
return [self setData:[CPPropertyListSerialization dataFromPropertyList:aPropertyList format:CPPropertyListXMLFormat_v1_0 errorDescription:nil] forType:aType];
return [self setData:[CPPropertyListSerialization dataFromPropertyList:aPropertyList format:CPPropertyList280NorthFormat_v1_0] forType:aType];
}
/*!
@@ -203,7 +242,7 @@ var CPPasteboards = nil;
*/
- (void)setString:(CPString)aString forType:(CPString)aType
{
return [self setPropertyList:aString forType:aType];
[self setPropertyList:aString forType:aType];
}
// Determining Types
@@ -223,6 +262,7 @@ var CPPasteboards = nil;
*/
- (CPArray)types
{
[self _synchronizePasteboard];
return _types;
}
@@ -243,24 +283,54 @@ 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];
++_changeCount;
return [_provided objectForKey:aType];
}
if (aType === CPStringPboardType)
return [self dataForType:UTF8PboardType];
return nil;
}
- (void)_synchronizePasteboard
{
if (_nativePasteboard && _nativePasteboard.changeCount() > _changeCount)
{
var nativeTypes = [_nativePasteboard.types() copy];
if ([nativeTypes containsObject:UTF8PboardType])
nativeTypes.push(CPStringPboardType);
[self _declareTypes:nativeTypes owner:self updateNativePasteboard:NO];
_changeCount = _nativePasteboard.changeCount();
}
}
/*! @ignore
method provided for integration with native pasteboard
*/
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
{
if (aType === CPStringPboardType)
{
var string = _nativePasteboard.stringForType_(UTF8PboardType);
[self setString:string forType:CPStringPboardType];
[self setString:string forType:UTF8PboardType];
}
else
[self setString:_nativePasteboard.stringForType_(aType) forType:aType];
}
/*!
Returns the property list for the specified data type
@param aType the requested data type
@@ -269,10 +339,10 @@ var CPPasteboards = nil;
- (id)propertyListForType:(CPString)aType
{
var data = [self dataForType:aType];
if (data)
return [CPPropertyListSerialization propertyListFromData:data format:CPPropertyListXMLFormat_v1_0 errorDescription:nil];
return [CPPropertyListSerialization propertyListFromData:data format:CPPropertyList280NorthFormat_v1_0];
return nil;
}
@@ -290,9 +360,9 @@ var CPPasteboards = nil;
- (CPString)_generateStateUID
{
var bits = 32;
_stateUID = @"";
while (bits--)
_stateUID += FLOOR(RAND() * 16.0).toString(16).toUpperCase();
@@ -343,7 +413,7 @@ var DOMDataTransferPasteboard = nil;
if (type === CPStringPboardType)
_dataTransfer.setData(type, [aPasteboard stringForType:type]);
else
_dataTransfer.setData(type, [[aPasteboard dataForType:type] string]);
_dataTransfer.setData(type, [[aPasteboard dataForType:type] rawString]);
}
}
@@ -357,9 +427,9 @@ var DOMDataTransferPasteboard = nil;
var dataString = _dataTransfer.getData(aType);
if (aType === CPStringPboardType)
return [CPData dataFromPropertyList:dataString format:kCFPropertyList280NorthFormat_v1_0 errorDescription:0];
return [CPData dataFromPropertyList:dataString format:kCFPropertyList280NorthFormat_v1_0];
return [CPData dataWithString:dataString];
return [CPData dataWithRawString:dataString];
}
- (id)propertyListForType:(CPString)aType
@@ -367,7 +437,7 @@ var DOMDataTransferPasteboard = nil;
if (aType === CPStringPboardType)
return _dataTransfer.getData(aType);
return [CPPropertyListSerialization propertyListFromData:[self dataForType:aType] format:CPPropertyListUnknownFormat errorDescription:nil];
return [CPPropertyListSerialization propertyListFromData:[self dataForType:aType] format:CPPropertyListUnknownFormat];
}
@end
+325 -255
View File
@@ -25,14 +25,12 @@
@import "CPMenu.j"
@import "CPMenuItem.j"
#include "CoreGraphics/CGGeometry.h"
var VISIBLE_MARGIN = 7.0;
var VISIBLE_MARGIN = 7.0;
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
/*!
@ingroup appkit
@class CPPopUpButton
@@ -40,17 +38,30 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
@implementation CPPopUpButton : CPButton
{
int _selectedIndex;
CPUInteger _selectedIndex;
CPRectEdge _preferredEdge;
CPMenu _menu;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
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
@@ -60,21 +71,27 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
- (id)initWithFrame:(CGRect)aFrame pullsDown:(BOOL)shouldPullDown
{
self = [super initWithFrame:aFrame];
if (self)
{
_selectedIndex = CPNotFound;
[self selectItemAtIndex:CPNotFound];
_preferredEdge = CPMaxYEdge;
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
[self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"];
[self setValue:CPLineBreakByTruncatingTail forThemeAttribute:@"line-break-mode"];
[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;
}
@@ -87,6 +104,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.
*/
@@ -100,7 +120,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if (!changed)
return;
var items = [_menu itemArray];
var items = [[self menu] itemArray];
if ([items count] <= 0)
return;
@@ -125,46 +145,46 @@ 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
{
var index = 0,
count = [titles count];
for (; index < count; ++index)
[self addItemWithTitle:titles[index]];
}
/*!
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
{
var items = [self itemArray],
count = [items count];
while (count--)
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];
}
/*!
@@ -172,10 +192,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (void)removeAllItems
{
var count = [_menu numberOfItems];
while (count--)
[_menu removeItemAtIndex:0];
[[self menu] removeAllItems];
}
/*!
@@ -194,7 +211,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (void)removeItemAtIndex:(int)anIndex
{
[_menu removeItemAtIndex:anIndex];
[[self menu] removeItemAtIndex:anIndex];
[self synchronizeTitleAndSelectedItem];
}
@@ -204,10 +221,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];
}
/*!
@@ -226,13 +245,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
@@ -249,22 +275,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
@@ -283,84 +337,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];
}
/*!
@@ -368,7 +352,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPArray)itemArray
{
return [_menu itemArray];
return [[self menu] itemArray];
}
/*!
@@ -377,7 +361,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPMenuItem)itemAtIndex:(unsigned)anIndex
{
return [_menu itemAtIndex:anIndex];
return [[self menu] itemAtIndex:anIndex];
}
/*!
@@ -386,7 +370,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPString)itemTitleAtIndex:(unsigned)anIndex
{
return [[_menu itemAtIndex:anIndex] title];
return [[[self menu] itemAtIndex:anIndex] title];
}
/*!
@@ -396,12 +380,13 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
var titles = [],
items = [self itemArray],
index = 0,
count = [items count];
for (; index < count; ++index)
items.push([items[index] title]);
titles.push([items[index] title]);
return titles;
}
/*!
@@ -410,7 +395,13 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPMenuItem)itemWithTitle:(CPString)aTitle
{
return [_menu itemAtIndex:[_menu indexOfItemWithTitle:aTitle]];
var menu = [self menu],
itemIndex = [menu indexOfItemWithTitle:aTitle];
if (itemIndex === CPNotFound)
return nil;
return [menu itemAtIndex:itemIndex];
}
/*!
@@ -418,7 +409,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (CPMenuItem)lastItem
{
return [[_menu itemArray] lastObject];
return [[[self menu] itemArray] lastObject];
}
// Getting the Indices of Menu Items
@@ -428,7 +419,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (int)indexOfItem:(CPMenuItem)aMenuItem
{
return [_menu indexOfItem:aMenuItem];
return [[self menu] indexOfItem:aMenuItem];
}
/*!
@@ -437,16 +428,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];
}
/*!
@@ -457,7 +448,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
- (int)indexOfItemWithRepresentedObject:(id)anObject
{
return [_menu indexOfItemWithRepresentedObject:anObject];
return [[self menu] indexOfItemWithRepresentedObject:anObject];
}
/*!
@@ -469,7 +460,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
@@ -484,7 +475,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.
*/
@@ -505,7 +496,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if ([self pullsDown])
{
var items = [_menu itemArray];
var items = [[self menu] itemArray];
if ([items count] <= 0)
[self addItemWithTitle:aTitle];
@@ -519,14 +510,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
else
{
var index = [self indexOfItemWithTitle:aTitle];
if (index < 0)
{
[self addItemWithTitle:aTitle];
index = [self numberOfItems] - 1;
}
[self selectItemAtIndex:index];
}
}
@@ -553,8 +544,8 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if ([self pullsDown])
{
var items = [_menu itemArray];
var items = [[self menu] itemArray];
if ([items count] > 0)
item = items[0];
}
@@ -565,94 +556,169 @@ 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"];
if (_selectedIndex < 0)
[self selectItemAtIndex:0];
else if (index == _selectedIndex)
var pullsDown = [self pullsDown];
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];
[items[0] setHidden:YES];
if (items.length > 0)
[items[1] setHidden:NO];
aKeyPath = @"menu.items";
[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
{
if (![self isEnabled] || ![self numberOfItems])
return;
[self highlight:YES];
var menu = [self menu],
theWindow = [self window],
menuWindow = [_CPMenuWindow menuWindowWithMenu:menu font:[self font]];
[menuWindow setDelegate:self];
[menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle];
// Pull Down Menus show up directly below their buttons.
bounds = [self bounds],
minimumWidth = CGRectGetWidth(bounds);
// FIXME: setFont: should set the font on the menu.
[menu setFont:[self font]];
if ([self pullsDown])
var menuOrigin = [theWindow convertBaseToGlobal:[self convertPoint:CGPointMake(0.0, CGRectGetMaxY([self bounds])) toView:nil]];
// Pop Up Menus attempt to show up "on top" of the selected item.
{
var positionedItem = nil,
location = CGPointMake(0.0, CGRectGetMaxY(bounds));
}
else
{
var contentRect = [self contentRectForBounds:bounds],
positionedItem = [self selectedItem],
standardLeftMargin = [_CPMenuWindow _standardLeftMargin] + [_CPMenuItemStandardView _standardLeftMargin],
location = CGPointMake(CGRectGetMinX(contentRect) - standardLeftMargin, 0.0);
minimumWidth += standardLeftMargin;
// To ensure the selected item is highlighted correctly, unset the highlighted item
[menu _highlightItemAtIndex:CPNotFound];
}
[menu setMinimumWidth:minimumWidth];
[menu
_popUpMenuPositioningItem:positionedItem
atLocation:location
topY:CGRectGetMinY(bounds)
bottomY:CGRectGetMaxY(bounds)
inView:self
callback:function(aMenu)
{
[self highlight:NO];
var highlightedItem = [aMenu highlightedItem];
if ([highlightedItem _isSelectable])
[self selectItem:highlightedItem];
}];
/*
else
{
// This is confusing, I KNOW, so let me explain it to you.
@@ -660,43 +726,19 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
// 1. So calculate where our content is, then calculate where the menu item is.
// 2. Move LEFT by whatever indentation we have (offsetWidths, aka, window margin, item margin, etc).
// 3. MOVE UP by the difference in sizes of the content and menu item, this will only work if the content is vertically centered.
var contentRect = [self convertRect:[self contentRectForBounds:[self bounds]] toView:nil],
var contentRect = [self convertRect:[self contentRectForBounds:bounds] toView:nil],
menuOrigin = [theWindow convertBaseToGlobal:contentRect.origin],
menuItemRect = [menuWindow rectForItemAtIndex:_selectedIndex];
menuOrigin.x -= CGRectGetMinX(menuItemRect) + [menuWindow overlapOffsetWidth] + [[[menu itemAtIndex:_selectedIndex] _menuItemView] overlapOffsetWidth];
menuOrigin.y -= CGRectGetMinY(menuItemRect) + (CGRectGetHeight(menuItemRect) - CGRectGetHeight(contentRect)) / 2.0;
}
[menuWindow setFrameOrigin:menuOrigin];
var menuMaxX = CGRectGetMaxX([menuWindow frame]),
buttonMaxX = [theWindow convertBaseToGlobal:CGPointMake(CGRectGetMaxX([self convertRect:[self bounds] toView:nil]), 0.0)].x;
if (menuMaxX < buttonMaxX)
[menuWindow setMinWidth:CGRectGetWidth([menuWindow frame]) + buttonMaxX - menuMaxX - ([self pullsDown] ? 0.0 : VISIBLE_MARGIN)];
[menuWindow orderFront:self];
[menuWindow beginTrackingWithEvent:anEvent sessionDelegate:self didEndSelector:@selector(menuWindowDidFinishTracking:highlightedItem:)];
*/
}
/*
@ignore
*/
- (void)menuWindowDidFinishTracking:(_CPMenuWindow)aMenuWindow highlightedItem:(CPMenuItem)aMenuItem
- (void)rightMouseDown:(CPEvent)anEvent
{
[_CPMenuWindow poolMenuWindow:aMenuWindow];
[self highlight:NO];
var index = [_menu indexOfItem:aMenuItem];
if (index == CPNotFound)
return;
[self selectItemAtIndex:index];
[CPApp sendAction:[aMenuItem action] to:[aMenuItem target] from:aMenuItem];
// Disable standard CPView behavior which incorrectly displays the menu as a 'context menu'.
}
- (void)_popUpItemAction:(id)aSender
@@ -704,11 +746,39 @@ 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,
value = [objects[0] valueForKeyPath:aKeyPath];
[self selectItemWithTag:value];
[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)
/*!
@@ -721,30 +791,30 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
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
+106 -80
View File
@@ -20,11 +20,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CGGeometry.j>
@import <AppKit/CPImageView.j>
@import <AppKit/CPView.j>
#include "CoreGraphics/CGGeometry.h"
@import "CGGeometry.j"
@import "CPImageView.j"
@import "CPView.j"
/*
@@ -49,7 +47,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
CPProgressIndicatorStyleIdentifiers = nil,
CPProgressIndicatorStyleSizes = nil;
/*!
/*!
@ingroup appkit
@class CPProgressIndicator
@@ -61,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;
}
@@ -84,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:
@@ -97,81 +95,68 @@ 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] = [];
CPProgressIndicatorBezelBorderViewPool[start][CPMiniControlSize] = [];
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
var prefix = CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle];
// Bar Style
var prefixes = [
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle],
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle]
];
CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
prefix = CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle];
CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = _CGSizeMake(1.0, 9.0);
CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = _CGSizeMake(1.0, 9.0);
CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = _CGSizeMake(1.0, 9.0);
// HUD Bar Style
prefix = CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle];
CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
prefix = CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle];
CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = _CGSizeMake(1.0, 9.0);
CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = _CGSizeMake(1.0, 9.0);
CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = _CGSizeMake(1.0, 9.0);
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)];
CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = [_CGSizeMake(3.0, 16.0), _CGSizeMake(1.0, 16.0), _CGSizeMake(3.0, 16.0)];
CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = [_CGSizeMake(3.0, 16.0), _CGSizeMake(1.0, 16.0), _CGSizeMake(3.0, 16.0)];
}
}
- (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;
}
@@ -189,7 +174,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
- (void)startAnimation:(id)aSender
{
_isAnimating = YES;
[self _hideOrDisplay];
}
@@ -228,7 +213,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
- (void)setDoubleValue:(double)aValue
{
_doubleValue = MIN(MAX(aValue, _minValue), _maxValue);
[self drawBar];
}
@@ -283,7 +268,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_controlSize == aControlSize)
return;
_controlSize = aControlSize;
[self updateBackgroundColor];
@@ -305,7 +290,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
/*
Not yet impemented.
Not yet implemented.
*/
- (CPControlTint)controlTint
{
@@ -335,7 +320,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_isIndeterminate == isIndeterminate)
return;
_isIndeterminate = isIndeterminate;
[self updateBackgroundColor];
@@ -357,9 +342,9 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_style == aStyle)
return;
_style = aStyle;
[self updateBackgroundColor];
}
@@ -372,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)];
}
/*!
@@ -385,11 +369,11 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_isDisplayedWhenStoppedSet && _isDisplayedWhenStopped == isDisplayedWhenStopped)
return;
_isDisplayedWhenStoppedSet = YES;
_isDisplayedWhenStopped = isDisplayedWhenStopped;
[self _hideOrDisplay];
}
@@ -400,10 +384,10 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_isDisplayedWhenStoppedSet)
return _isDisplayedWhenStopped;
if (_style == CPProgressIndicatorBarStyle || _style == CPProgressIndicatorHUDBarStyle)
return YES;
return NO;
}
@@ -416,7 +400,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
- (void)setFrameSize:(CGSize)aSize
{
[super setFrameSize:aSize];
[self drawBar];
}
@@ -425,24 +409,28 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_style == CPProgressIndicatorSpinningStyle)
return;
if (!_barView)
{
_barView = [[CPView alloc] initWithFrame:CGRectMake(2.0, 2.0, 0.0, 9.0)];
[_barView setBackgroundColor:[CPColor redColor]];
_barView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 16.0)];
[self addSubview:_barView];
}
[_barView setBackgroundColor:_CPControlColorWithPatternImage(
[_barView setBackgroundColor:_CPControlThreePartImagePattern(
NO,
CPProgressIndicatorStyleSizes,
CPProgressIndicatorClassName,
@"Bar",
CPProgressIndicatorStyleIdentifiers[_style],
_CPControlIdentifierForControlSize(_controlSize))];
[_barView setFrameSize:CGSizeMake(CGRectGetWidth([self bounds]) * (_doubleValue - _minValue) / (_maxValue - _minValue) - 4.0, 9.0)];
var width = CGRectGetWidth([self bounds]),
barWidth = width * ((_doubleValue - _minValue) / (_maxValue - _minValue));
if (barWidth > 0.0 && barWidth < 4.0)
barWidth = 4.0;
[_barView setFrameSize:CGSizeMake(barWidth, 16.0)];
}
/* @ignore */
@@ -453,9 +441,9 @@ var CPProgressIndicatorSpinningStyleColors = nil,
if (_style == CPProgressIndicatorSpinningStyle)
{
[_barView removeFromSuperview];
_barView = nil;
[self setBackgroundColor:CPProgressIndicatorSpinningStyleColors[_controlSize]];
}
else
@@ -467,7 +455,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
@"BezelBorder",
CPProgressIndicatorStyleIdentifiers[_style],
_CPControlIdentifierForControlSize(_controlSize))];
[self drawBar];
}
}
@@ -476,3 +464,41 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
@end
@implementation CPProgressIndicator (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_minValue = [aCoder decodeObjectForKey:@"_minValue"];
_maxValue = [aCoder decodeObjectForKey:@"_maxValue"];
_doubleValue = [aCoder decodeObjectForKey:@"_doubleValue"];
_controlSize = [aCoder decodeObjectForKey:@"_controlSize"];
_isIndeterminate = [aCoder decodeObjectForKey:@"_isIndeterminate"];
_style = [aCoder decodeObjectForKey:@"_style"];
_isAnimating = [aCoder decodeObjectForKey:@"_isAnimating"];
_isDisplayedWhenStoppedSet = [aCoder decodeObjectForKey:@"_isDisplayedWhenStoppedSet"];
_isDisplayedWhenStopped = [aCoder decodeObjectForKey:@"_isDisplayedWhenStopped"];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_minValue forKey:@"_minValue"];
[aCoder encodeObject:_maxValue forKey:@"_maxValue"];
[aCoder encodeObject:_doubleValue forKey:@"_doubleValue"];
[aCoder encodeObject:_controlSize forKey:@"_controlSize"];
[aCoder encodeObject:_isIndeterminate forKey:@"_isIndeterminate"];
[aCoder encodeObject:_style forKey:@"_style"];
[aCoder encodeObject:_isAnimating forKey:@"_isAnimating"];
[aCoder encodeObject:_isDisplayedWhenStoppedSet forKey:@"_isDisplayedWhenStoppedSet"];
[aCoder encodeObject:_isDisplayedWhenStopped forKey:@"_isDisplayedWhenStopped"];
}
@end
+24 -15
View File
@@ -25,28 +25,29 @@
@import "CPButton.j"
/*!
@ingroup appkit
from this mailing list thread:
http://groups.google.com/group/objectivej/browse_thread/thread/7c41cbd9cbee9ea3
http://groups.google.com/group/objectivej/browse_thread/thread/7c41cbd9cbee9ea3
-----------------------------------
Creating a checkbox is easy enough:
checkbox = [[CPCheckBox alloc] initWithFrame:aFrame];
That's basically all there is to it. Radio buttons are very similar,
the key difference is the introduction of a new class CPRadioGroup,
which defines which radio buttons are part of the same group:
[myRadioButton setRadioGroup:aRadioGroup];
Every radio button receives a unique radio group by default (so if you
do nothing further, they will all behave independently), but you can
use an existing radio button's group with other buttons as so:
button1 = [[CPRadio alloc] initWithFrame:aFrame];
...
button2 = [[CPRadio alloc] initWithFrame:aFrame radioGroup:[button1
@@ -55,13 +56,16 @@
button3 = [[CPRadio alloc] initWithFrame:aFrame radioGroup:[button1
radioGroup]];
...etc...
Here, all the radio buttons will act "together". [[button1 radioGroup]
allRadios] returns every button that's part of this group, and
[[button1 radioGroup] selectedRadio] returns the currently selected
option.
*/
CPRadioImageOffset = 4.0;
@implementation CPRadio : CPButton
{
CPRadioGroup _radioGroup;
@@ -86,7 +90,7 @@
return button;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return @"radio";
}
@@ -95,7 +99,7 @@
- (id)initWithFrame:(CGRect)aFrame radioGroup:(CPRadioGroup)aRadioGroup
{
self = [super initWithFrame:aFrame];
if (self)
{
[self setRadioGroup:aRadioGroup];
@@ -109,8 +113,8 @@
[self setBordered:YES];
}
return self;
return self;
}
- (id)initWithFrame:(CGRect)aFrame
@@ -141,7 +145,7 @@
- (void)setObjectValue:(id)aValue
{
[super setObjectValue:aValue];
if ([self state] === CPOnState)
[_radioGroup _setSelectedRadio:self];
}
@@ -175,6 +179,9 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
{
CPSet _radios;
CPRadio _selectedRadio;
id _target @accessors(property=target);
SEL _action @accessors(property=action);
}
- (id)init
@@ -213,6 +220,8 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
[_selectedRadio setState:CPOffState];
_selectedRadio = aRadio;
[CPApp sendAction:_action to:_target from:self];
}
- (CPRadio)selectedRadio
+78 -52
View File
@@ -23,19 +23,23 @@
@import <Foundation/CPObject.j>
CPDeleteKeyCode = 8;
CPTabKeyCode = 9;
CPReturnKeyCode = 13;
CPEscapeKeyCode = 27;
CPLeftArrowKeyCode = 37;
CPUpArrowKeyCode = 38;
CPRightArrowKeyCode = 39;
CPDownArrowKeyCode = 40;
CPDeleteKeyCode = 8;
CPTabKeyCode = 9;
CPReturnKeyCode = 13;
CPEscapeKeyCode = 27;
CPSpaceKeyCode = 32;
CPPageUpKeyCode = 33;
CPPageDownKeyCode = 34;
CPLeftArrowKeyCode = 37;
CPUpArrowKeyCode = 38;
CPRightArrowKeyCode = 39;
CPDownArrowKeyCode = 40;
CPDeleteForwardKeyCode = 46;
/*!
@ingroup appkit
@class CPResponder
Subclasses of CPResonder can be part of the responder chain.
*/
@implementation CPResponder : CPObject
@@ -101,38 +105,24 @@ CPDownArrowKeyCode = 40;
for (; index < count; ++index)
{
var event = events[index];
var event = events[index],
modifierFlags = [event modifierFlags],
character = [event charactersIgnoringModifiers],
selectorNames = [CPKeyBinding selectorsForKey:character modifierFlags:modifierFlags];
switch([event keyCode])
if (selectorNames)
{
case CPLeftArrowKeyCode: [self doCommandBySelector:@selector(moveLeft:)];
break;
case CPRightArrowKeyCode: [self doCommandBySelector:@selector(moveRight:)];
break;
case CPUpArrowKeyCode: [self doCommandBySelector:@selector(moveUp:)];
break;
case CPDownArrowKeyCode: [self doCommandBySelector:@selector(moveDown:)];
break;
case CPDeleteKeyCode: [self doCommandBySelector:@selector(deleteBackward:)];
break;
case CPReturnKeyCode:
case 3: [self doCommandBySelector:@selector(insertLineBreak:)];
break;
case CPEscapeKeyCode: [self doCommandBySelector:@selector(cancel:)];
break;
for (var s = 0, scount = selectorNames.length; s < scount; s++)
{
var selector = selectorNames[s];
if (!selector)
continue;
case CPTabKeyCode: var shift = [event modifierFlags] & CPShiftKeyMask;
if (!shift)
[self doCommandBySelector:@selector(insertTab:)];
else
[self doCommandBySelector:@selector(insertBackTab:)];
break;
default: [self insertText:[event characters]];
[self doCommandBySelector:CPSelectorFromString(selector)];
}
}
else if (!(modifierFlags & (CPCommandKeyMask | CPControlKeyMask)) && [self respondsToSelector:@selector(insertText:)])
[self insertText:[event characters]];
}
}
@@ -145,6 +135,15 @@ CPDownArrowKeyCode = 40;
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the user has clicked the right mouse down in its area.
@param anEvent contains information about the right click
*/
- (void)rightMouseDown:(CPEvent)anEvent
{
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the user has initiated a drag
over it. A drag is a mouse movement while the left button is down.
@@ -164,6 +163,15 @@ CPDownArrowKeyCode = 40;
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the user has released the right mouse button.
@param anEvent contains information about the release
*/
- (void)rightMouseUp:(CPEvent)anEvent
{
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the user has moved the mouse (with no buttons down).
@param anEvent contains information about the movement
@@ -214,11 +222,27 @@ CPDownArrowKeyCode = 40;
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*
FIXME This description is bad.
Based on \c anEvent, the receiver should simulate the event.
@param anEvent the event to simulate
@return \c YES if the event receiver simulated the event
/*!
Notifies the receiver that the user has pressed or released a modifier key (Shift, Control, and so on).
@param anEvent information about the key press
*/
- (void)flagsChanged:(CPEvent)anEvent
{
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Overridden by subclasses to handle a key equivalent.
If the character code or codes in \c anEvent match the receivers key equivalent,
the receiver should respond to the event and return \c YES. The default implementation
does nothing and returns \c NO.
You should extract the characters for a key equivalent using
\ref CPEvent::charactersIgnoringModifiers "[anEvent charactersIgnoringModifiers]".
@param anEvent An event object that represents the key equivalent pressed
@return \c YES if theEvent is a key equivalent that the receiver handled, \c NO if it is not a key equivalent that it should handle.
*/
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
{
@@ -244,10 +268,6 @@ CPDownArrowKeyCode = 40;
[[self nextResponder] insertNewline:aSender];
}
- (void)cancel:(id)sender
{
}
- (void)insertTab:(id)sender
{
}
@@ -287,10 +307,10 @@ CPDownArrowKeyCode = 40;
*/
- (BOOL)tryToPerform:(SEL)aSelector with:(id)anObject
{
if([self respondsToSelector:aSelector])
if ([self respondsToSelector:aSelector])
{
[self performSelector:aSelector withObject:anObject];
return YES;
}
@@ -329,7 +349,8 @@ CPDownArrowKeyCode = 40;
@end
var CPResponderNextResponderKey = @"CPResponderNextResponderKey";
var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
CPResponderMenuKey = @"CPResponderMenuKey";
@implementation CPResponder (CPCoding)
@@ -341,10 +362,13 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey";
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
_nextResponder = [aCoder decodeObjectForKey:CPResponderNextResponderKey];
{
[self setNextResponder:[aCoder decodeObjectForKey:CPResponderNextResponderKey]];
[self setMenu:[aCoder decodeObjectForKey:CPResponderMenuKey]];
}
return self;
}
@@ -357,6 +381,8 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey";
// This will come out nil on the other side with decodeObjectForKey:
if (_nextResponder !== nil)
[aCoder encodeConditionalObject:_nextResponder forKey:CPResponderNextResponderKey];
[aCoder encodeObject:_menu forKey:CPResponderMenuKey];
}
@end
+504
View File
@@ -0,0 +1,504 @@
/*
* CPPredicateEditor.j
* AppKit
*
* Created by cacaodev.
* Copyright 2011, cacaodev.
*
* 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 "CPRuleEditor.j"
@import "_CPPredicateEditorTree.j"
@import "_CPPredicateEditorRowNode.j"
@import "CPPredicateEditorRowTemplate.j"
@implementation CPPredicateEditor : CPRuleEditor
{
CPArray _allTemplates;
CPArray _rootTrees;
CPArray _rootHeaderTrees;
id _predicateTarget @accessors(property=target);
SEL _predicateAction @accessors(property=action);
}
#pragma mark public methods
/*!
@ingroup appkit
@class CPPredicateEditor
@brief CPPredicateEditor is a subclass of CPRuleEditor that is specialized for editing CPPredicate objects.
CPPredicateEditor provides a CPPredicate property—objectValue (inherited from CPControl)—that you can get and set directly, and that you can bind using bindings (you typically configure a predicate editor in Interface Builder). CPPredicateEditor depends on another class, CPPredicateEditorRowTemplate, that describes the available predicates and how to display them.
Unlike CPRuleEditor, CPPredicateEditor does not depend on its delegate to populate its rows (and does not call the populating delegate methods). Instead, its rows are populated from its objectValue property (an instance of CPPredicate). CPPredicateEditor relies on instances CPPredicateEditorRowTemplate, which are responsible for mapping back and forth between the displayed view values and various predicates.
CPPredicateEditor exposes one property, rowTemplates, which is an array of CPPredicateEditorRowTemplate objects.
*/
/*!
@brief Returns the row templates for the receiver.
@return The row templates for the receiver.
@discussion Until otherwise set, this contains a single compound CPPredicateEditorRowTemplate object.
@see setRowTemplates:
*/
- (CPArray)rowTemplates
{
return _allTemplates;
}
/*!
@brief Sets the row templates for the receiver.
@param rowTemplates An array of CPPredicateEditorRowTemplate objects.
@see rowTemplates
*/
- (void)setRowTemplates:(id)rowTemplates
{
if (_allTemplates == rowTemplates)
return;
_allTemplates = rowTemplates;
[self _updateItemsByCompoundTemplates];
[self _updateItemsBySimpleTemplates];
if ([self numberOfRows] > 0)
{
var predicate = [super predicate];
[self _reflectPredicate:predicate];
}
}
/*! @cond */
- (void)_initRuleEditorShared
{
[super _initRuleEditorShared];
_rootTrees = [CPArray array];
_rootHeaderTrees = [CPArray array];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self != nil)
{
var initialTemplate = [[CPPredicateEditorRowTemplate alloc] initWithCompoundTypes:[CPAndPredicateType, CPOrPredicateType]];
_allTemplates = [CPArray arrayWithObject:initialTemplate];
}
return self;
}
- (id)objectValue
{
return [super predicate];
}
- (void)_updateItemsBySimpleTemplates
{
var templates = [CPMutableArray array],
count = [_allTemplates count],
t;
while (count--)
{
var t = _allTemplates[count];
if ([t _rowType] == CPRuleEditorRowTypeSimple)
[templates insertObject:t atIndex:0];
}
var trees = [self _constructTreesForTemplates:templates];
if ([trees count] > 0)
_rootTrees = [self _mergeTree:trees];
}
- (void)_updateItemsByCompoundTemplates
{
var templates = [CPMutableArray array],
count = [_allTemplates count],
t;
while (count--)
{
var t = _allTemplates[count];
if ([t _rowType] == CPRuleEditorRowTypeCompound)
[templates insertObject:t atIndex:0];
}
var trees = [self _constructTreesForTemplates:templates];
if ([trees count] > 0)
_rootHeaderTrees = [self _mergeTree:trees];
}
- (CPArray)_constructTreesForTemplates:(id)templates
{
var trees = [CPMutableArray array],
count = [templates count];
for (var i = 0; i < count; i++)
{
var tree = [self _constructTreeForTemplate:templates[i]];
[trees addObjectsFromArray:tree];
}
return trees;
}
- (id)_mergeTree:(id)tree
{
var merged = [CPMutableArray array],
titles = [CPMutableArray array],
count = [tree count];
for (var i = 0; i < count; i++)
{
var t = tree[i],
title = [CPString stringWithString:[t title]];
if ([titles containsObject:title])
{
CPLogConsole("CPPredicateEditor does not support templates merging yet. Ignoring duplicate template: " + [t description]);
continue;
}
[merged addObject:t];
[titles addObject:title];
}
return merged;
}
- (id)_constructTreeForTemplate:(CPPredicateEditorRowTemplate)aTemplate
{
var tree = [CPArray array],
templateViews = [aTemplate templateViews],
count = [templateViews count];
while (count--)
{
var children = [CPArray array],
itemsCount = 0,
menuIndex = -1,
itemsArray,
templateView = [templateViews objectAtIndex:count],
isPopup = [templateView isKindOfClass:[CPPopUpButton class]];
if (isPopup)
{
itemArray = [[templateView itemArray] valueForKey:@"title"];
itemsCount = [itemArray count],
menuIndex = 0;
}
for (; menuIndex < itemsCount; menuIndex++)
{
var item = [_CPPredicateEditorTree new];
[item setIndexIntoTemplate:count];
[item setTemplate:aTemplate];
[item setMenuItemIndex:menuIndex];
if (isPopup)
[item setTitle:[itemArray objectAtIndex:menuIndex]];
[children addObject:item];
}
[children makeObjectsPerformSelector:@selector(setChildren:) withObject:tree];
tree = children;
}
return tree;
}
#pragma mark Set the Predicate
- (void)setObjectValue:(id)objectValue
{
if (![[objectValue predicateFormat] isEqualToString:[[super predicate] predicateFormat]]) // ??
[self _reflectPredicate:objectValue];
}
- (void)_reflectPredicate:(id)predicate
{
var animation = _currentAnimation;
_currentAnimation = nil;
if (predicate != nil)
{
if ((_nestingMode == CPRuleEditorNestingModeSimple || _nestingMode == CPRuleEditorNestingModeCompound)
&& [predicate isKindOfClass:[CPComparisonPredicate class]])
predicate = [[CPCompoundPredicate alloc] initWithType:[self _compoundPredicateTypeForRootRows] subpredicates:[CPArray arrayWithObject:predicate]];
var row = [self _rowObjectFromPredicate:predicate];
if (row != nil)
[_boundArrayOwner setValue:[CPArray arrayWithObject:row] forKey:_boundArrayKeyPath];
}
[self setAnimation:animation];
}
- (id)_rowObjectFromPredicate:(CPPredicate)predicate
{
var quality, // TODO: We should use this ref somewhere !
type,
matchedTemplate = [CPPredicateEditorRowTemplate _bestMatchForPredicate:predicate inTemplates:[self rowTemplates] quality:quality];
if (matchedTemplate == nil)
return nil;
var copyTemplate = [matchedTemplate copy],
subpredicates = [matchedTemplate displayableSubpredicatesOfPredicate:predicate];
if (subpredicates == nil)
{
[copyTemplate _setComparisonPredicate:predicate];
type = CPRuleEditorRowTypeSimple;
}
else
{
[copyTemplate _setCompoundPredicate:predicate];
type = CPRuleEditorRowTypeCompound;
}
var row = [self _rowFromTemplate:copyTemplate originalTemplate:matchedTemplate withRowType:type];
if (subpredicates == nil)
return row;
var count = [subpredicates count],
subrows = [CPMutableArray array];
for (var i = 0; i < count; i++)
{
var subrow = [self _rowObjectFromPredicate:subpredicates[i]];
if (subrow != nil)
[subrows addObject:subrow];
}
[row setValue:subrows forKey:[super subrowsKeyPath]];
return row;
}
- (id)_rowFromTemplate:(CPPredicateEditorRowTemplate)aTemplate originalTemplate:(CPPredicateEditorRowTemplate)originalTemplate withRowType:(CPRuleEditorRowType)rowType
{
var criteria = [CPArray array],
values = [CPArray array],
templateViews = [aTemplate templateViews],
rootItems,
count;
rootItems = (rowType == CPRuleEditorRowTypeSimple) ? _rootTrees : _rootHeaderTrees;
while ((count = [rootItems count]) > 0)
{
var treeChild;
for (var i = 0; i < count; i++)
{
treeChild = [rootItems objectAtIndex:i];
var currentView = [templateViews objectAtIndex:[treeChild indexIntoTemplate]],
menuItemIndex = [treeChild menuItemIndex];
if (menuItemIndex == -1 || [[treeChild title] isEqual:[currentView titleOfSelectedItem]])
{
var node = [_CPPredicateEditorRowNode rowNodeFromTree:treeChild];
[node applyTemplate:aTemplate withViews:templateViews forOriginalTemplate:originalTemplate];
[criteria addObject:node];
[values addObject:[node displayValue]];
break;
}
}
rootItems = [treeChild children];
}
var row = [CPDictionary dictionaryWithObjectsAndKeys:criteria, @"criteria", values, @"displayValues", rowType, @"rowType"];
return row;
}
#pragma mark Get the predicate
- (void)_updatePredicate
{
[self willChangeValueForKey:@"objectValue"];
[self _updatePredicateFromRows];
[self didChangeValueForKey:@"objectValue"];
}
- (void)_updatePredicateFromRows
{
var rootRowsArray = [super _rootRowsArray],
subpredicates = [CPMutableArray array],
count = count2 = [rootRowsArray count],
predicate;
while (count--)
{
var item = [rootRowsArray objectAtIndex:count],
subpredicate = [self _predicateFromRowItem:item];
if (subpredicate != nil)
[subpredicates insertObject:subpredicate atIndex:0];
}
if (_nestingMode != CPRuleEditorNestingModeList && count2 == 1)
predicate = [subpredicates lastObject];
else
predicate = [[CPCompoundPredicate alloc] initWithType:[self _compoundPredicateTypeForRootRows] subpredicates:subpredicates];
[super _setPredicate:predicate];
}
- (id)_predicateFromRowItem:(id)rowItem
{
var subpredicates = [CPArray array],
rowType = [rowItem valueForKey:_typeKeyPath];
if (rowType == CPRuleEditorRowTypeCompound)
{
var subrows = [rowItem valueForKey:_subrowsArrayKeyPath],
count = [subrows count];
for (var i = 0; i < count; i++)
{
var subrow = [subrows objectAtIndex:i];
var predicate = [self _predicateFromRowItem:subrow];
[subpredicates addObject:predicate];
}
}
var criteria = [rowItem valueForKey:_itemsKeyPath],
displayValues = [rowItem valueForKey:_valuesKeyPath],
count = [criteria count],
lastItem = [criteria lastObject],
template = [lastItem templateForRow],
templateViews = [template templateViews];
for (var j = 0; j < count; j++)
{
var view = [templateViews objectAtIndex:j],
value = [displayValues objectAtIndex:j];
[[criteria objectAtIndex:j] setTemplateViews:templateViews];
if ([view isKindOfClass:[CPPopUpButton class]])
[view selectItemWithTitle:value];
else if ([view respondsToSelector:@selector(setObjectValue:)])
[view setObjectValue:[value objectValue]];
}
return [template predicateWithSubpredicates:subpredicates];
}
- (CPCompoundPredicateType)_compoundPredicateTypeForRootRows
{
return CPAndPredicateType;
}
#pragma mark Control delegate
- (void)_sendRuleAction
{
[self _updatePredicate];
[super _sendRuleAction];
}
- (BOOL)_sendsActionOnIncompleteTextChange
{
return NO;
}
/*
- (void)_setDefaultTargetAndActionOnView:(CPView)view
{
if ([view isKindOfClass:[CPControl class]])
{
[view setTarget:self];
[view setAction:@selector(_templateControlValueDidChange:)];
}
}
- (void)_templateControlValueDidChange:(id)sender
{
}
- (void)controlTextDidBeginEditing:(CPNotification)notification
{
}
- (void)controlTextDidEndEditing:(CPNotification)notification
{
}
- (void)controlTextDidChange:(CPNotification)notification
{
}
*/
#pragma mark RuleEditor delegate methods
- (int)_queryNumberOfChildrenOfItem:(id)rowItem withRowType:(int)type
{
if (rowItem == nil)
{
var trees = (type == CPRuleEditorRowTypeSimple) ? _rootTrees : _rootHeaderTrees;
return [trees count];
}
return [[rowItem children] count];
}
- (id)_queryChild:(int)childIndex ofItem:(id)rowItem withRowType:(int)type
{
if (rowItem == nil)
{
var trees = (type == CPRuleEditorRowTypeSimple) ? _rootTrees : _rootHeaderTrees;
return [_CPPredicateEditorRowNode rowNodeFromTree:trees[childIndex]];
}
return [[rowItem children] objectAtIndex:childIndex];
}
- (id)_queryValueForItem:(id)rowItem inRow:(int)rowIndex
{
return [rowItem displayValue];
}
@end
var CPPredicateTemplatesKey = @"CPPredicateTemplates";
@implementation CPPredicateEditor (CPCoding)
- (id)initWithCoder:(id)aCoder
{
self = [super initWithCoder:aCoder];
if (self != nil)
{
var nibTemplates = [aCoder decodeObjectForKey:CPPredicateTemplatesKey];
if (nibTemplates != nil)
[self setRowTemplates:nibTemplates];
}
return self;
}
- (void)encodeWithCoder:(id)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_allTemplates forKey:CPPredicateTemplatesKey];
}
@end
/*! @endcond */
@@ -0,0 +1,788 @@
/*
* CPPredicateEditorRowTemplate.j
* AppKit
*
* Created by cacaodev.
* Copyright 2011, cacaodev.
*
* 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
*/
CPUndefinedAttributeType = 0,
CPInteger16AttributeType = 100,
CPInteger32AttributeType = 200,
CPInteger64AttributeType = 300,
CPDecimalAttributeType = 400,
CPDoubleAttributeType = 500,
CPFloatAttributeType = 600,
CPStringAttributeType = 700,
CPBooleanAttributeType = 800,
CPDateAttributeType = 900,
CPBinaryDataAttributeType = 1000,
CPTransformableAttributeType = 1800;
@implementation CPPredicateEditorRowTemplate : CPObject
{
int _templateType @accessors(readwrite, getter=_templateType, setter=_setTemplateType:);
unsigned _predicateOptions @accessors(readwrite, setter=_setOptions:);
unsigned _predicateModifier @accessors(readwrite, setter=_setModifier:);
unsigned _leftAttributeType @accessors(readwrite, getter=leftAttributeType, setter=_setLeftAttributeType:);
unsigned _rightAttributeType @accessors(readwrite, getter=rightAttributeType, setter=_setRightAttributeType:);
BOOL _leftIsWildcard @accessors(property=leftIsWildcard);
BOOL _rightIsWildcard @accessors(property=rightIsWildcard);
CPArray _views @accessors(setter=setTemplateViews:);
}
/*!
@ingroup appkit
@class CPPredicateEditorRowTemplate
@brief CPPredicateEditorRowTemplate describes available predicates and how to display them.
You can create instances of CPPredicateEditorRowTemplate programmatically or in Interface Builder. By default, a non-compound row template has three views: a popup (or static text field) on the left, a popup or static text field for operators, and either a popup or other view on the right. You can subclass CPPredicateEditorRowTemplate to create a row template with different numbers or types of views.
CPPredicateEditorRowTemplate is a concrete class, but it has five primitive methods which are called by CPPredicateEditor: -#templateViews, -#matchForPredicate:, -#setPredicate:, -#displayableSubpredicatesOfPredicate:, and -#predicateWithSubpredicates:. CPPredicateEditorRowTemplate implements all of them, but you can override them for custom templates. The primitive methods are used by an instance of CPPredicateEditor as follows.
First, an instance of CPPredicateEditor is created, and some row templates are set on it—either through a nib file or programmatically. The first thing predicate editor does is ask each of the templates for their views, using templateViews.
After setting up the predicate editor, you typically send it a CPPredicateEditor#setObjectValue: message to restore a saved predicate. CPPredicateEditor needs to determine which of its templates should display each predicate in the predicate tree. It does this by sending each of its row templates a matchForPredicate: message and choosing the one that returns the highest value.
After finding the best match for a predicate, CPPredicateEditor copies that template to get fresh views, inserts them into the proper row, and then sets the predicate on the template using setPredicate:. Within that method, the CPPredicateEditorRowTemplate object must set its views' values to represent that predicate.
CPPredicateEditorRowTemplate next asks the template for the “displayable sub-predicates” of the predicate by sending a -#displayableSubpredicatesOfPredicate: message. If a template represents a predicate in its entirety, or if the predicate has no subpredicates, it can return nil for this. Otherwise, it should return a list of predicates to be made into sub-rows of that template's row. The whole process repeats for each sub-predicate.
At this point, the user sees the predicate that was saved. If the user then makes some changes to the views of the templates, this causes CPPredicateEditor to recompute its predicate by asking each of the templates to return the predicate represented by the new view values, passing in the subpredicates represented by the sub-rows (an empty array if there are none, or nil if they aren't supported by that predicate type).
*/
/*!
@name Initializing a Template
*/
/*!
@brief Initializes and returns a “pop-up-pop-up-pop-up”-style row template.
@param leftExpressions An array of CPExpression objects that represent the left hand side of a predicate.
@param rightExpressions An array of CPExpression objects that represent the right hand side of a predicate.
@param modifier A modifier for the predicate (see @c CPComparisonPredicateModifier for possible values).
@param operators An array of CPNumber objects specifying the operator type (see @c CPPredicateOperatorType for possible values).
@param options Options for the predicate (see @c CPComparisonPredicateOptions for possible values).
@return A row template of the “pop-up-pop-up-pop-up”-form, with the left and right popups representing the left and right expression arrays -#leftExpressions and -#rightExpressions, and the center popup representing the operators.
*/
- (id)initWithLeftExpressions:(CPArray)leftExpressions rightExpressions:(CPArray)rightExpressions modifier:(int)modifier operators:(CPArray)operators options:(int)options
{
self = [super init];
if (self != nil)
{
_templateType = 1;
_leftIsWildcard = NO;
_rightIsWildcard = NO;
_leftAttributeType = 0;
_rightAttributeType = 0;
_predicateModifier = modifier;
_predicateOptions = options;
var leftView = [self _viewFromExpressions:leftExpressions],
rightView = [self _viewFromExpressions:rightExpressions],
middleView = [self _viewFromOperatorTypes:operators];
_views = [[CPArray alloc] initWithObjects:leftView, middleView, rightView];
}
return self;
}
/*!
@brief Initializes and returns a “pop-up-pop-up-view”-style row template.
@param leftExpressions An array of CPExpression objects that represent the left hand side of a predicate.
@param attributeType An attribute type for the right hand side of a predicate. This value dictates the type of view created, and how the controls object value is coerced before putting it into a predicate.
@param modifier A modifier for the predicate (see @c CPComparisonPredicateModifier for possible values).
@param operators An array of CPNumber objects specifying the operator type (see @c CPPredicateOperatorType for possible values).
@param options Options for the predicate (see CPComparisonPredicateOptions for possible values).
@return A row template initialized using the given arguments.
*/
- (id)initWithLeftExpressions:(CPArray )leftExpressions rightExpressionAttributeType:(CPAttributeType)attributeType modifier:(CPComparisonPredicateModifier)modifier operators:(CPArray )operators options:(int)options
{
self = [super init];
if (self != nil)
{
var leftView = [self _viewFromExpressions:leftExpressions],
middleView = [self _viewFromOperatorTypes:operators],
rightView = [self _viewFromAttributeType:attributeType];
_templateType = 1;
_leftIsWildcard = NO;
_rightIsWildcard = YES;
_leftAttributeType = 0;
_rightAttributeType = attributeType;
_predicateModifier = modifier;
_predicateOptions = options;
_views = [[CPArray alloc] initWithObjects:leftView, middleView, rightView];
}
return self;
}
/*!
@brief Initializes and returns a row template suitable for displaying compound predicates.
@param compoundTypes An array of CPNumber objects specifying compound predicate types. See @c CPCompoundPredicateTypes for possible values.
@return A row template initialized for displaying compound predicates of the types specified by @a compoundTypes.
@discussion CPPredicateEditor contains such a template by default.
*/
- (id)initWithCompoundTypes:(CPArray )compoundTypes
{
self = [super init];
if (self != nil)
{
var leftView = [self _viewFromCompoundTypes:compoundTypes],
rightView = [[CPPopUpButton alloc] init];
[rightView addItemWithTitle:@"of the following are true"];
_templateType = 2;
_leftIsWildcard = NO;
_rightIsWildcard = NO;
_rightAttributeType = 0;
_views = [[CPArray alloc] initWithObjects:leftView, rightView];
}
return self;
}
/*!
@name Primitive Methods
*/
/*!
@brief Returns a positive number if the receiver can represent a given predicate, and 0 if it cannot.
@return A positive number if the template can represent predicate, and @c 0 if it cannot.
@discussion By default, returns values in the range @c 0 to @c 1.
The highest match among all the templates determines which template is responsible for displaying the predicate. You can override this to determine which predicates your custom template handles.
*/
- (double)matchForPredicate:(CPPredicate)predicate
{
// How exactly this value (float 0-1) is computed ?
if ([self _templateType] == 2 && [predicate isKindOfClass:[CPCompoundPredicate class]])
{
if ([[self compoundTypes] containsObject:[predicate compoundPredicateType]])
return 1;
}
else if ([self _templateType] == 1 && [predicate isKindOfClass:[CPComparisonPredicate class]])
{
if (!_leftIsWildcard && ![[self leftExpressions] containsObject:[predicate leftExpression]])
return 0;
if (![[self operators] containsObject:[predicate predicateOperatorType]])
return 0;
if (!_rightIsWildcard && ![[self rightExpressions] containsObject:[predicate rightExpression]]) return 0;
return 1;
}
return 0;
}
/*!
@brief Returns the views for the receiver.
@return The views for the receiver.
@discussion Instances of CPPopUpButton are treated specially by CPPredicateEditor; their menu items are merged into a single popup button, and matching menu item titles are combined. In this way, a single tree is built from the separate templates.
*/
- (CPArray)templateViews
{
return _views;
}
/*!
@brief Sets the value of the views according to the given predicate.
@param predicate The predicate value for the receiver.
@discussion This method is only called if -#matchForPredicate: returned a positive value for the receiver.
You can override this to set the values of custom views.
*/
- (void)setPredicate:(CPPredicate)predicate
{
if (_templateType == 2)
[self _setCompoundPredicate:predicate];
else
[self _setComparisonPredicate:predicate];
}
/*!
@brief Returns the subpredicates that should be made sub-rows of a given predicate.
@param predicate A predicate object.
@return The subpredicates that should be made sub-rows of @a predicate. For compound predicates (instances of CPCompoundPredicate), the array of subpredicates; for other types of predicate, returns @c nil. If a template represents a predicate in its entirety, or if the predicate has no subpredicates, returns @c nil.
@discussion You can override this method to create custom templates that handle complicated compound predicates.
*/
- (CPArray)displayableSubpredicatesOfPredicate:(CPPredicate)predicate
{
if ([predicate isKindOfClass:[CPCompoundPredicate class]])
{
var subpredicates = [predicate subpredicates];
if ([subpredicates count] == 0)
return nil;
return subpredicates;
}
return nil;
}
/*!
@brief Returns the predicate represented by the receivers views' values and the given sub-predicates.
@param subpredicates An array of predicates.
@return The predicate represented by the values of the template's views and the given @a subpredicates. You can override this method to return the predicate represented by your custom views.
@discussion This method is only called if -#matchForPredicate: returned a positive value for the receiver.
You can override this method to return the predicate represented by a custom view.
*/
- (CPPredicate)predicateWithSubpredicates:(CPArray)subpredicates
{
if (_templateType == 2)
{
var type = [[_views[0] selectedItem] representedObject];
return [[CPCompoundPredicate alloc] initWithType:type subpredicates:subpredicates];
}
if (_templateType == 1)
{
var lhs = [self _leftExpression],
rhs = [self _rightExpression],
operator = [[_views[1] selectedItem] representedObject];
return [CPComparisonPredicate predicateWithLeftExpression:lhs
rightExpression:rhs
modifier:[self modifier]
type:operator
options:[self options]];
}
return nil;
}
/*!
@name Information About a Row Template
*/
/*!
@brief Returns the left hand expressions for the receiver.
@return The left hand expressions for the receiver.
*/
- (CPArray)leftExpressions
{
if (_templateType ==1 && !_leftIsWildcard)
{
var view = [_views objectAtIndex:0];
return [[view itemArray] valueForKey:@"representedObject"];
}
return nil;
}
/*!
@brief Returns the right hand expressions for the receiver.
@return The right hand expressions for the receiver.
*/
- (CPArray)rightExpressions
{
if (_templateType == 1 && !_rightIsWildcard)
{
var view = [_views objectAtIndex:2];
return [[view itemArray] valueForKey:@"representedObject"];
}
return nil;
}
/*!
@brief Returns the compound predicate types for the receiver.
@return An array of CPNumber objects specifying compound predicate types. See @c CompoundPredicateTypes for possible values.
*/
- (CPArray)compoundTypes
{
if (_templateType == 2)
{
var view = [_views objectAtIndex:0];
return [[view itemArray] valueForKey:@"representedObject"];
}
return nil;
}
/*!
@brief Returns the comparison predicate modifier for the receiver.
@return The comparison predicate modifier for the receiver.
*/
- (CPComparisonPredicateModifier)modifier
{
if (_templateType == 1)
return _predicateModifier;
return nil;
}
/*!
@brief Returns Returns the array of operators for the receiver.
@return The array of operators for the receiver.
*/
- (CPArray)operators
{
if (_templateType == 1)
{
var view = [_views objectAtIndex:1];
return [[view itemArray] valueForKey:@"representedObject"];
}
return nil;
}
/*!
@brief Returns the comparison predicate options for the receiver.
@return The comparison predicate options for the receiver. See @c CPComparisonPredicateOptions for possible values. Returns @c 0 if this does not apply (for example, for a compound template initialized with -#initWithCompoundTypes:).
*/
- (int)options
{
if (_templateType == 1)
return _predicateOptions;
return nil;
}
/*!
@brief Returns the attribute type of the receivers right expression.
@return The attribute type of the receivers right expression.
*/
- (CPAttributeType)rightExpressionAttributeType
{
return _rightAttributeType;
}
/*!
@brief Returns the attribute type of the receivers left expression.
@return The attribute type of the receivers left expression.
*/
- (CPAttributeType)leftExpressionAttributeType
{
return _leftAttributeType;
}
/*! @cond */
+ (id)_bestMatchForPredicate:(CPPredicate)predicate inTemplates:(CPArray)templates quality:(double)quality
{
var count = [templates count],
match_value = 0,
templateIndex = CPNotFound,
i;
for (i = 0; i < count; i++)
{
var template = [templates objectAtIndex:i],
amatch = [template matchForPredicate:predicate];
if (amatch > match_value)
{
templateIndex = i;
match_value = amatch;
}
}
if (templateIndex == CPNotFound)
{
[CPException raise:CPRangeException reason:@"Unable to find template matching predicate: " + [predicate predicateFormat]];
return nil;
}
return [templates objectAtIndex:templateIndex];
}
- (void)_setCompoundPredicate:(CPCompoundPredicate)predicate
{
var left = [_views objectAtIndex:0],
type = [predicate compoundPredicateType],
index = [left indexOfItemWithRepresentedObject:type];
[left selectItemAtIndex:index];
}
- (void)_setComparisonPredicate:(CPComparisonPredicate)predicate
{
var left = [_views objectAtIndex:0],
middle = [_views objectAtIndex:1],
right = [_views objectAtIndex:2],
leftExpression = [predicate leftExpression],
rightExpression = [predicate rightExpression],
operator = [predicate predicateOperatorType];
if (_leftIsWildcard)
[left setObjectValue:[leftExpression constantValue]];
else
{
var index = [left indexOfItemWithRepresentedObject:leftExpression];
[left selectItemAtIndex:index];
}
var op_index = [middle indexOfItemWithRepresentedObject:operator];
[middle selectItemAtIndex:op_index];
if (_rightIsWildcard)
[right setObjectValue:[rightExpression constantValue]];
else
{
var index = [right indexOfItemWithRepresentedObject:rightExpression];
[right selectItemAtIndex:index];
}
}
- (CPExpression)_leftExpression
{
return [self _expressionFromView:_views[0] forAttributeType:_leftAttributeType];
}
- (CPExpression)_rightExpression
{
return [self _expressionFromView:_views[2] forAttributeType:_rightAttributeType];
}
- (CPExpression)_expressionFromView:(CPView)aView forAttributeType:(CPAttributeType)attributeType
{
if (attributeType == 0)
return [[aView selectedItem] representedObject];
var value;
if (attributeType >= CPInteger16AttributeType && attributeType <= CPFloatAttributeType)
value = [aView intValue];
else if (attributeType == CPBooleanAttributeType)
value = [aView state];
else
value = [aView stringValue];
return [CPExpression expressionForConstantValue:value];
}
- (int)_rowType
{
return (_templateType - 1);
}
- (id)copy
{
return [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:self]];
}
+ (id)_operatorsForAttributeType:(CPAttributeType)attributeType
{
var operators_array = [CPMutableArray array];
switch (attributeType)
{
case CPInteger16AttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPInteger32AttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPInteger64AttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPDecimalAttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPDoubleAttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPFloatAttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPStringAttributeType : [operators_array addObjects:99,4,5,8,9];
break;
case CPBooleanAttributeType : [operators_array addObjects:4,5];
break;
case CPDateAttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
default : CPLogConsole("Cannot create operators for an CPAttributeType " + attributeType);
break;
}
return operators_array;
}
- (int)_templateType
{
return _templateType;
}
- (id)_displayValueForPredicateOperator:(int)operator
{
var value;
switch (operator)
{
case CPLessThanPredicateOperatorType : value = @"is less than";
break;
case CPLessThanOrEqualToPredicateOperatorType : value = @"is less than or equal to";
break;
case CPGreaterThanPredicateOperatorType : value = @"is greater than";
break;
case CPGreaterThanOrEqualToPredicateOperatorType : value = @"is greater than or equal to";
break;
case CPEqualToPredicateOperatorType : value = @"is";
break;
case CPNotEqualToPredicateOperatorType : value = @"is not";
break;
case CPMatchesPredicateOperatorType : value = @"matches";
break;
case CPLikePredicateOperatorType : value = @"is like";
break;
case CPBeginsWithPredicateOperatorType : value = @"begins with";
break;
case CPEndsWithPredicateOperatorType : value = @"ends with";
break;
case CPInPredicateOperatorType : value = @"in";
break;
case CPContainsPredicateOperatorType : value = @"contains";
break;
case CPBetweenPredicateOperatorType : value = @"between";
break;
default : CPLogConsole(@"unknown predicate operator %d" + operator);
}
return value;
}
- (id)_displayValueForCompoundPredicateType:(unsigned int)predicateType
{
var value;
switch (predicateType)
{
case CPNotPredicateType: value = @"None";
break;
case CPAndPredicateType: value = @"All";
break;
case CPOrPredicateType: value = @"Any";
break;
default : value = [CPString stringWithFormat:@"unknown compound predicate type %d",predicateType];
}
return value;
}
- (id)_displayValueForConstantValue:(id)value
{
return [value description]; // number, date, string, ... localize
}
- (id)_displayValueForKeyPath:(CPString)keyPath
{
return keyPath; // localize
}
- (CPPopUpButton)_viewFromExpressions:(CPArray)expressions
{
var popup = [[CPPopUpButton alloc] initWithFrame:CPMakeRect(0, 0, 100, 18)],
count = [expressions count];
for (var i = 0; i < count; i++)
{
var exp = expressions[i],
type = [exp expressionType],
title;
switch (type)
{
case CPKeyPathExpressionType: title = [self _displayValueForKeyPath:[exp keyPath]];
break;
case CPConstantValueExpressionType: title = [self _displayValueForConstantValue:[exp constantValue]];
break;
default: [CPException raise:CPInvalidArgumentException reason:@"Invalid Expression type " + type];
break;
}
var item = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
[item setRepresentedObject:exp];
[popup addItem:item];
}
[popup sizeToFit];
return popup;
}
- (CPPopUpButton)_viewFromOperatorTypes:(CPArray)operators
{
var popup = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 100, 18)],
count = [operators count];
for (var i = 0; i < count; i++)
{
var op = operators[i],
title = [self _displayValueForPredicateOperator:op],
item = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
[item setRepresentedObject:op];
[popup addItem:item];
}
[popup sizeToFit];
return popup;
}
- (CPView)_viewFromCompoundTypes:(CPArray)compoundTypes
{
var popup = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 100, 18)],
count = [compoundTypes count];
for (var i = 0; i < count; i++)
{
var type = compoundTypes[i],
title = [self _displayValueForCompoundPredicateType:type],
item = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
[item setRepresentedObject:type];
[popup addItem:item];
}
[popup sizeToFit];
return popup;
}
- (CPView)_viewFromAttributeType:(CPAttributeType)attributeType
{
var view;
if (attributeType >= CPInteger16AttributeType && attributeType <= CPFloatAttributeType)
{
view = [self _textFieldWithFrame:CGRectMake(0, 0, 50, 26)];
}
else if (attributeType == CPStringAttributeType)
{
view = [self _textFieldWithFrame:CGRectMake(0, 0, 150, 26)];
}
else if (attributeType == CPBooleanAttributeType)
{
view = [[CPCheckBox alloc] initWithFrame:CGRectMake(0, 0, 50, 26)];
}
else if (attributeType == CPDateAttributeType)
view = [[CPDatePicker alloc] initWithFrame:CGRectMake(0, 0, 150, 26)];
else
return nil;
[view setTag:attributeType];
return view;
}
- (CPTextField)_textFieldWithFrame:(CGRect)frame
{
var textField = [[CPTextField alloc] initWithFrame:frame];
[textField setBezeled:YES];
[textField setBezelStyle:CPTextFieldSquareBezel];
[textField setBordered:YES];
[textField setEditable:YES];
[textField setFont:[CPFont systemFontOfSize:10]];
return textField;
}
- (void)_setOptions:(unsigned int)options
{
_predicateOptions = options;
}
- (void)_setModifier:(unsigned int)modifier
{
_predicateModifier = modifier;
}
- (CPString)description
{
if (_templateType == 2)
return [CPString stringWithFormat:@"<%@ %p %@>",[self className],self,[[self compoundTypes] componentsJoinedByString:@", "]];
else if (_templateType == 1 && _rightIsWildcard)
return [CPString stringWithFormat:@"<%@ %p [%@] [%@] %d>",[self className],self,[[self leftExpressions] componentsJoinedByString:@", "],[[self operators] componentsJoinedByString:@", "],[self rightExpressionAttributeType]];
else
return [CPString stringWithFormat:@"<%@ %p [%@] [%@] [%@]>",[self className],self,[[self leftExpressions] componentsJoinedByString:@", "],[[self operators] componentsJoinedByString:@", "],[[self rightExpressions] componentsJoinedByString:@", "]];
}
/*
- (void)_setLeftExpressionObject:(id)object
{
}
- (void)_setRightExpressionObject:(id)object
{
}
- (BOOL)_predicateIsNoneAreTrue:(id)predicate
{
}
- (id)_viewFromExpressionObject:(id)object
{
}
*/
@end
var CPPredicateTemplateTypeKey = @"CPPredicateTemplateType",
CPPredicateTemplateOptionsKey = @"CPPredicateTemplateOptions",
CPPredicateTemplateModifierKey = @"CPPredicateTemplateModifier",
CPPredicateTemplateLeftAttributeTypeKey = @"CPPredicateTemplateLeftAttributeType",
CPPredicateTemplateRightAttributeTypeKey = @"CPPredicateTemplateRightAttributeType",
CPPredicateTemplateLeftIsWildcardKey = @"CPPredicateTemplateLeftIsWildcard",
CPPredicateTemplateRightIsWildcardKey = @"CPPredicateTemplateRightIsWildcard",
CPPredicateTemplateViewsKey = @"CPPredicateTemplateViews";
@implementation CPPredicateEditorRowTemplate (CPCoding)
- (id)initWithCoder:(CPCoder)coder
{
self = [super init];
if (self != nil)
{
_templateType = [coder decodeIntForKey:CPPredicateTemplateTypeKey];
_predicateOptions = [coder decodeIntForKey:CPPredicateTemplateOptionsKey];
_predicateModifier = [coder decodeIntForKey:CPPredicateTemplateModifierKey];
_leftAttributeType = [coder decodeIntForKey:CPPredicateTemplateLeftAttributeTypeKey];
_rightAttributeType = [coder decodeIntForKey:CPPredicateTemplateRightAttributeTypeKey];
_leftIsWildcard = [coder decodeBoolForKey:CPPredicateTemplateLeftIsWildcardKey];
_rightIsWildcard = [coder decodeBoolForKey:CPPredicateTemplateRightIsWildcardKey];
_views = [coder decodeObjectForKey:CPPredicateTemplateViewsKey];
// In Xcode 4, when the menu item title == template's expression keypath, representedObject is empty.
// So we need to regenerate expressions from titles.
if (_templateType == 1 && _leftIsWildcard == NO)
{
var itemArray = [_views[0] itemArray],
count = [itemArray count];
for (var i = 0; i < count; i++)
{
var item = itemArray[i];
if ([item representedObject] == nil)
{
var exp = [CPExpression expressionForKeyPath:[item title]];
[item setRepresentedObject:exp];
}
}
}
}
return self;
}
- (void)encodeWithCoder:(CPCoder)coder
{
[coder encodeInt:_templateType forKey:CPPredicateTemplateTypeKey];
[coder encodeInt:_predicateOptions forKey:CPPredicateTemplateOptionsKey];
[coder encodeInt:_predicateModifier forKey:CPPredicateTemplateModifierKey];
[coder encodeInt:_leftAttributeType forKey:CPPredicateTemplateLeftAttributeTypeKey];
[coder encodeInt:_rightAttributeType forKey:CPPredicateTemplateRightAttributeTypeKey];
[coder encodeBool:_leftIsWildcard forKey:CPPredicateTemplateLeftIsWildcardKey];
[coder encodeBool:_rightIsWildcard forKey:CPPredicateTemplateRightIsWildcardKey];
[coder encodeObject:_views forKey:CPPredicateTemplateViewsKey];
}
@end
/*! @endcond */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,132 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
@class _CPPredicateEditorTree;
@implementation _CPPredicateEditorRowNode : CPObject
{
_CPPredicateEditorTree tree @accessors;
CPMutableArray templateViews @accessors;
CPMutableArray copiedTemplateContainer @accessors;
CPArray children @accessors(copy);
}
+ (id)rowNodeFromTree:(id)aTree
{
var mapTable = {};
return [_CPPredicateEditorRowNode _rowNodeFromTree:aTree withTemplateTable:mapTable];
}
+ (id)_rowNodeFromTree:(id)aTree withTemplateTable:(id)templateTable
{
var node,
views,
copiedContainer;
node = [[_CPPredicateEditorRowNode alloc] init];
node.tree = aTree;
var template = [aTree template],
uuid = [template UID];
var cachedNode = templateTable[uuid];
if (cachedNode == nil)
{
views = [CPMutableArray array];
copiedContainer = [CPMutableArray array];
templateTable[uuid] = node;
}
else
{
views = [cachedNode templateViews];
copiedContainer = [cachedNode copiedTemplateContainer];
}
node.templateViews = views;
node.copiedTemplateContainer = copiedContainer;
var nodeChildren = [CPMutableArray array],
treeChildren = [aTree children],
count = [treeChildren count];
for (var i = 0; i < count; i++)
{
var treeChild = treeChildren[i],
child = [_CPPredicateEditorRowNode _rowNodeFromTree:treeChild withTemplateTable:templateTable];
[nodeChildren addObject:child];
}
[node setChildren:nodeChildren];
return node;
}
- (BOOL)applyTemplate:(id)template withViews:(id)views forOriginalTemplate:(id)originalTemplate
{
var t = [tree template];
if (t !== template)
{
[templateViews setArray:views];
[copiedTemplateContainer removeAllObjects];
[copiedTemplateContainer addObject:template];
}
var count = [children count];
for (var i; i < count; i++)
[children[i] applyTemplate:template withViews:views forOriginalTemplate:originalTemplate];
}
- (BOOL)isEqual:(id)node
{
if (![node isKindOfClass:[_CPPredicateEditorRowNode class]])
return NO;
return (tree === [node tree]);
}
- (void)copyTemplateIfNecessary
{
if ([copiedTemplateContainer count] == 0)
{
CPLogConsole("COPYING TEMPLATE");
var copy = [[tree template] copy];
[copiedTemplateContainer addObject:copy];
[templateViews addObjectsFromArray:[copy templateViews]];
}
}
- (CPView)templateView
{
[self copyTemplateIfNecessary];
return [templateViews objectAtIndex:[tree indexIntoTemplate]];
}
- (id)templateForRow
{
[self copyTemplateIfNecessary];
return [copiedTemplateContainer lastObject];
}
- (CPString)title
{
return [tree title];
}
- (id)displayValue
{
var title = [self title];
if (title != nil)
return title;
return [self templateView];
}
- (CPString)description
{
return [CPString stringWithFormat:@"<%@ %@ %@ tree:%@ tviews:%@", [self className],[self UID], [self title], [tree UID], [templateViews description]];
}
@end
@@ -0,0 +1,33 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
@implementation _CPPredicateEditorTree : CPObject
{
CPPredicateEditorRowTemplate template @accessors;
CPString title @accessors(copy);
CPArray children @accessors(copy);
CPInteger indexIntoTemplate @accessors;
CPInteger menuItemIndex @accessors;
}
- (id)copy
{
var tree = [[_CPPredicateEditorTree alloc] init];
[tree setTemplate:template];
[tree setTitle:title];
[tree setMenuItemIndex:menuItemIndex];
[tree setIndexIntoTemplate:indexIntoTemplate];
[tree setChildren:children];
return tree;
}
- (CPString)description
{
return [CPString stringWithFormat:@"<%@: %p (%@) [%d-%d] T:%p at:%d> [\r%@\r]", [self className], self, title, indexIntoTemplate, menuItemIndex, template, [template rightExpressionAttributeType], children];
}
@end
@@ -0,0 +1,75 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPDictionary.j>
@import <Foundation/CPString.j>
var regex = new RegExp("\"(.+)\"\\s*=\\s*\"(.+)\"\\s*;\\s*(//.+)?");
@implementation _CPRuleEditorLocalizer : CPObject
{
CPDictionary _dictionary @accessors(property=dictionary);
CPURLConnection connection;
CPURLRequest resquest;
}
- (void)loadContentOfURL:(CPURL)aURL
{
request = [CPURLRequest requestWithURL:aURL];
connection = [CPURLConnection connectionWithRequest:request delegate:self];
}
- (void)reloadIfNeeded
{
if (connection != nil) // Connection waiting
{
connection = nil;
var data = [CPURLConnection sendSynchronousRequest:request returningResponse:NULL];
[self loadContent:[data rawString]];
}
}
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)rawString
{
if (connection != nil && rawString != nil)
[self loadContent:rawString];
connection = nil;
}
- (void)loadContent:(CPString)aContent
{
var dict = [CPDictionary dictionary],
lines = [aContent componentsSeparatedByString:"\n"],
count = [lines count];
for (var i = 0 ; i < count ; i++)
{
var line = [lines objectAtIndex:i];
if (line.length > 1)
{
var match = regex.exec(line);
if (match.length >= 3)
[dict setObject:match[2] forKey:match[1]];
}
}
_dictionary = [CPDictionary dictionaryWithDictionary:dict];
}
- (CPString)localizedStringForString:(CPString)aString
{
[self reloadIfNeeded];
if (_dictionary != nil && aString != nil)
{
var localized = [_dictionary objectForKey:aString];
if (localized != nil)
return localized;
}
return aString;
}
@@ -0,0 +1,157 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
var GRADIENT_NORMAL,
GRADIENT_HIGHLIGHTED,
IE_FILTER = "progid:DXImageTransform.Microsoft.gradient(startColorstr='#fcfcfc', endColorstr='#dfdfdf')";
@implementation _CPRuleEditorPopUpButton : CPPopUpButton
{
CPInteger radius;
}
+ (void)initialize
{
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
{
GRADIENT_NORMAL = "-webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)))",
GRADIENT_HIGHLIGHTED = "-webkit-gradient(linear, left top, left bottom, from(rgb(223, 223, 223)), to(rgb(252, 252, 252)))";
}
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
{
GRADIENT_NORMAL = "-moz-linear-gradient(top, rgb(252, 252, 252), rgb(223, 223, 223))",
GRADIENT_HIGHLIGHTED = "-moz-linear-gradient(top, rgb(223, 223, 223), rgb(252, 252, 252))";
}
}
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
var style = _DOMElement.style;
style.backgroundImage = GRADIENT_NORMAL;
style.border = "1px solid rgb(189, 189, 189)";
style.filter = IE_FILTER;
[self setTextColor:[CPColor colorWithWhite:101/255 alpha:1]];
[self setBordered:NO];
}
return self;
}
- (id)hitTest:(CPPoint)point
{
var slice = [self superview];
if (!CPRectContainsPoint([self frame], point) || ![self sliceIsEditable])
return nil;
return self;
}
- (void)setHighlighted:(BOOL)shouldHighlight
{
_DOMElement.style.backgroundImage = (shouldHighlight) ? GRADIENT_HIGHLIGHTED : GRADIENT_NORMAL;
}
- (BOOL)sliceIsEditable
{
return [[self superview] isEditable];
}
- (BOOL)trackMouse:(CPEvent)theEvent
{
if (![self sliceIsEditable])
return NO;
return [super trackMouse:theEvent];
}
- (CGRect)contentRectForBounds:(CGRect)bounds
{
var contentRect = [super contentRectForBounds:bounds];
contentRect.origin.x += radius;
contentRect.size.width -= 2 * radius;
return contentRect;
}
- (void)layoutSubviews
{
radius = FLOOR(CGRectGetHeight([self bounds])/2);
var style = _DOMElement.style,
radiusCSS = radius + "px";
//style.webkitBorderRadius = radiusCSS;
//style.mozBorderRadius = radiusCSS;
style.borderRadius = radiusCSS;
[super layoutSubviews];
}
- (void)drawRect:(CGRect)aRect
{
var bounds = [self bounds],
context = [[CPGraphicsContext currentContext] graphicsPort];
var arrow_width = FLOOR(CGRectGetHeight(bounds)/3.5);
CGContextTranslateCTM(context, CGRectGetWidth(bounds) - radius - arrow_width, CGRectGetHeight(bounds) / 2);
var arrowsPath = [CPBezierPath bezierPath];
[arrowsPath moveToPoint:CGPointMake(0, 1)];
[arrowsPath lineToPoint:CGPointMake(arrow_width, 1)];
[arrowsPath lineToPoint:CGPointMake(arrow_width/2, arrow_width + 1)];
[arrowsPath closePath];
CGContextSetFillColor(context, [CPColor colorWithWhite:101/255 alpha:1]);
[arrowsPath fill];
CGContextScaleCTM(context, 1 , -1);
[arrowsPath fill];
}
@end
@implementation _CPRuleEditorButton : CPButton
{
CPInteger radius;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
[self setFont:[CPFont boldFontWithName:@"Apple Symbol" size:12.0]];
[self setTextColor:[CPColor colorWithWhite:150/255 alpha:1]];
[self setAlignment:CPCenterTextAlignment];
[self setAutoresizingMask:CPViewMinXMargin];
[self setImagePosition:CPImageOnly];
[self setBordered:NO];
var style = _DOMElement.style;
style.border = "1px solid rgb(189, 189, 189)";
style.filter = IE_FILTER;
}
return self;
}
- (void)layoutSubviews
{
radius = FLOOR(CGRectGetHeight([self bounds])/2);
var style = _DOMElement.style,
radiusCSS = radius + "px";
style.borderRadius = radiusCSS;
style.backgroundImage = ([self isHighlighted]) ? GRADIENT_HIGHLIGHTED : GRADIENT_NORMAL;
[super layoutSubviews];
}
@end
@@ -0,0 +1,109 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
@implementation _CPRuleEditorViewSlice : CPView
{
CPRuleEditor _ruleEditor;
int _indentation @accessors(property=indentation);
int _rowIndex @accessors(property=rowIndex);
CPRect _animationTargetRect @accessors(property=_animationTargetRect);
BOOL _selected @accessors(getter=_isSelected, setter=_setSelected:);
BOOL _lastSelected @accessors(getter=_isLastSelected, setter=_setLastSelected:);
CPColor _backgroundColor @accessors(property=backgroundColor);
}
- (void)removeFromSuperview
{
[super removeFromSuperview];
}
- (id)initWithFrame:(CGRect)frame ruleEditorView:(id)editor
{
if (self = [super initWithFrame:frame])
{
_ruleEditor = editor;
_selected = NO;
_lastSelected = NO;
}
return self;
}
- (void)_setSelected:(BOOL)select
{
if (select == _selected)
return;
var selector = select ? @"setThemeState:" : @"unsetThemeState:";
[[self subviews] makeObjectsPerformSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelectedDataView];
_selected = select;
}
- (void)drawRect:(CPRect)rect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds],
maxX = CGRectGetWidth(bounds) - 2,
maxY = CGRectGetHeight(bounds);
// Draw background
if ([self _isSelected])
_backgroundColor = [_ruleEditor _selectedRowColor];
else
{
var colors = [_ruleEditor _backgroundColors],
count = [colors count];
_backgroundColor = [colors objectAtIndex:(_rowIndex % count)];
}
CGContextSetFillColor(context, _backgroundColor);
CGContextFillRect(context, rect);
// Draw Top Border
CGContextBeginPath(context);
CGContextMoveToPoint(context, 1, 0);
CGContextAddLineToPoint(context, maxX, 0);
CGContextClosePath(context);
CGContextSetStrokeColor(context, [_ruleEditor _sliceTopBorderColor]);
CGContextStrokePath(context);
// Draw Bottom Border
CGContextBeginPath(context);
CGContextMoveToPoint(context, 1, maxY - 0.5);
CGContextAddLineToPoint(context, maxX, maxY - 0.5);
CGContextClosePath(context);
var bottomColor = (_rowIndex == [_ruleEditor _lastRow]) ? [_ruleEditor _sliceLastBottomBorderColor] : [_ruleEditor _sliceBottomBorderColor];
CGContextSetStrokeColor(context, bottomColor);
CGContextStrokePath(context);
}
- (void)mouseDown:(CPEvent)theEvent
{
if (editable)
[_ruleEditor _mouseDownOnSlice:self withEvent:theEvent];
}
- (void)mouseUp:(CPEvent)theEvent
{
if (editable)
[_ruleEditor _mouseUpOnSlice:self withEvent:theEvent];
}
/*
- (void)rightMouseDown:(CPEvent)theEvent
{
[_ruleEditor _rightMouseDownOnSlice:self withEvent:theEvent];
}
*/
// =========
// ! DEBUG
// =========
- (CPString)description
{
return [CPString stringWithFormat:@"<%@ %p index:%d indentation:%d>",[self className],self,[self rowIndex],[self indentation]];
}
@end
@@ -0,0 +1,512 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
@import "_CPRuleEditorViewSlice.j"
@import "_CPRuleEditorPopUpButton.j"
@import "CPRuleEditor.j"
var CONTROL_HEIGHT = 16.,
BUTTON_HEIGHT = 16.;
@implementation _CPRuleEditorViewSliceRow : _CPRuleEditorViewSlice
{
CPMutableArray _ruleOptionViews;
CPMutableArray _ruleOptionFrames;
CPMutableArray _correspondingRuleItems;
CPMutableArray _ruleOptionInitialViewFrames;
CPButton _addButton;
CPButton _subtractButton;
BOOL editable;
CPRuleEditorRowType _rowType @accessors;
CPRuleEditorRowType _plusButtonRowType;
}
- (id)initWithFrame:(CGRect)frame ruleEditorView:(id)editor
{
if (self = [super initWithFrame:frame ruleEditorView:editor])
[self _initShared];
return self;
}
- (void)_initShared
{
_correspondingRuleItems = [[CPMutableArray alloc] init];
_ruleOptionFrames = [[CPMutableArray alloc] init];
_ruleOptionInitialViewFrames = [[CPMutableArray alloc] init];
_ruleOptionViews = [[CPMutableArray alloc] init];
editable = [_ruleEditor isEditable];
_addButton = [self _createAddRowButton];
_subtractButton = [self _createDeleteRowButton];
//[_addButton setToolTip:[_ruleEditor _toolTipForAddSimpleRowButton]];
//[_subtractButton setToolTip:[_ruleEditor _toolTipForDeleteRowButton]];
[_addButton setHidden:!editable];
[_subtractButton setHidden:!editable];
[self addSubview:_addButton];
[self addSubview:_subtractButton];
[self setAutoresizingMask:CPViewWidthSizable];
var center = [CPNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(_textDidChange:) name:CPControlTextDidChangeNotification object:nil];
}
- (CPButton)_createAddRowButton
{
var button = [[_CPRuleEditorButton alloc] initWithFrame:CGRectMakeZero()];
[button setImage:[_ruleEditor _addImage]];
[button setAction:@selector(_addOption:)];
[button setTarget:self];
[button setAutoresizingMask:CPViewMinXMargin];
return button;
}
- (CPButton)_createDeleteRowButton
{
var button = [[_CPRuleEditorButton alloc] initWithFrame:CGRectMakeZero()];
[button setImage:[_ruleEditor _removeImage]];
[button setAction:@selector(_deleteOption:)];
[button setTarget:self];
[button setAutoresizingMask:CPViewMinXMargin];
return button;
}
- (CPMenuItem)_createMenuItemWithTitle:(CPString )title
{
title = [[_ruleEditor standardLocalizer] localizedStringForString:title];
var mItem = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
return mItem;
}
- (CPPopUpButton)_createPopUpButtonWithItems:(CPArray)itemsArray selectedItemIndex:(int)index
{
var title = [[itemsArray objectAtIndex:index] title];
var font = [_ruleEditor font],
width = [title sizeWithFont:font].width + 20,
rect = CGRectMake(0, 0, (width - width % 40) + 80, CONTROL_HEIGHT);
var popup = [[_CPRuleEditorPopUpButton alloc] initWithFrame:rect];
[popup setValue:font forThemeAttribute:@"font"];
var count = [itemsArray count];
for (var i = 0; i < count; i++)
[popup addItem:[itemsArray objectAtIndex:i]];
[popup selectItemAtIndex:index];
return popup;
}
- (CPMenuItem)_createMenuSeparatorItem
{
return [CPMenuItem separatorItem];
}
- (_CPRuleEditorTextField)_createStaticTextFieldWithStringValue:(CPString )text
{
text = [[_ruleEditor standardLocalizer] localizedStringForString:text];
var textField = [[_CPRuleEditorTextField alloc] initWithFrame:CPMakeRect(0, 0, 200, CONTROL_HEIGHT)];
var font = [_ruleEditor font];
font = [CPFont fontWithName:font._name size:font._size + 2];
[textField setValue:font forThemeAttribute:@"font"];
[textField setStringValue:text];
[textField sizeToFit];
return textField;
}
- (void)_addOption:(id)sender
{
if (_rowIndex == [_ruleEditor numberOfRows] - 1)
[self setNeedsDisplay:YES];
var type = _plusButtonRowType;
if ([_ruleEditor nestingMode] == CPRuleEditorNestingModeCompound && ([[CPApp currentEvent] modifierFlags] & CPAlternateKeyMask))
type = CPRuleEditorRowTypeCompound;
[_ruleEditor _addOptionFromSlice:self ofRowType:type];
}
- (void)_deleteOption:(id)sender
{
[_ruleEditor _deleteSlice:self];
}
- (void)_ruleOptionPopupChangedAction:(CPMenuItem )sender
{
var layoutdict = [sender representedObject],
newItem = [layoutdict objectForKey:@"item"],
indexInCriteria = [layoutdict objectForKey:@"indexInCriteria"],
oldItem = [_correspondingRuleItems objectAtIndex:indexInCriteria];
if (![newItem isEqual:oldItem])
{
[_correspondingRuleItems replaceObjectAtIndex:indexInCriteria withObject:newItem];
[_ruleEditor _changedItem:oldItem toItem:newItem inRow:_rowIndex atCriteriaIndex:indexInCriteria];
}
}
- (BOOL)validateMenuItem:(CPMenuItem )menuItem
{
return [_ruleEditor _validateItem:menuItem value:[[menuItem representedObject] valueForKey:@"item"] inRow:_rowIndex];
}
- (void)_emptyRulePartSubviews
{
var count = [_ruleOptionViews count];
while (count--)
[_ruleOptionViews[count] removeFromSuperview];
[_ruleOptionViews removeAllObjects];
[_ruleOptionFrames removeAllObjects];
[_ruleOptionInitialViewFrames removeAllObjects];
}
- (void)_reconfigureSubviews
{
var ruleItems,
criteria,
repObject,
menuItem,
ruleView,
criterion,
parent,
numberOfCriteria,
numberOfChildren,
firstResponderIndex;
var ruleItems = [CPMutableArray array];
[self _emptyRulePartSubviews];
criteria = [_ruleEditor criteriaForRow:_rowIndex];
numberOfCriteria = [criteria count];
firstResponderIndex = numberOfCriteria - 1;
var responder = [[self window] firstResponder];
if (responder)
firstResponderIndex = [_ruleOptionViews indexOfObjectIdenticalTo:responder];
for (var i = 0; i < numberOfCriteria; i++)
{
ruleView = nil;
parent = nil;
criterion = [criteria objectAtIndex:i];
if (i > 0)
parent = [criteria objectAtIndex:i - 1];
var childItems = [],
childValues = [];
[_ruleEditor _getAllAvailableItems:childItems values:childValues asChildrenOfItem:parent inRow:_rowIndex];
numberOfChildren = [childItems count];
if (numberOfChildren > 1)
{
var menuItems = [CPMutableArray arrayWithCapacity:numberOfChildren];
var selectedIndex = [childItems indexOfObject:criterion];
if (selectedIndex == CPNotFound)
break;
for (var j = 0; j < numberOfChildren; ++j)
{
var childItem = [childItems objectAtIndex:j];
var childValue = [childValues objectAtIndex:j];
if ([childValue isKindOfClass:[CPMenuItem class]])
{
[[childValue menu] removeItem:childValue];
menuItem = childValue;
}
else
{
if ([childValue isEqualToString:@""])
menuItem = [self _createMenuSeparatorItem];
else
{
menuItem = [self _createMenuItemWithTitle:childValue];
[menuItem setTarget:self];
[menuItem setAction:@selector(_ruleOptionPopupChangedAction:)];
}
}
repObject = [CPDictionary dictionaryWithObjectsAndKeys:childItem, @"item", childValue, @"value", i, @"indexInCriteria"];
[menuItem setRepresentedObject:repObject];
[menuItems addObject:menuItem];
}
ruleView = [self _createPopUpButtonWithItems:menuItems selectedItemIndex:selectedIndex];
}
else
{
var value = [childValues objectAtIndex:0];
var type = [value valueType];
if (type === 0)
ruleView = [self _createStaticTextFieldWithStringValue:value];
else
{
if (type !== 1)
{
[CPException raise:CPInternalInconsistencyException reason:@"Display value must be a string or a menu item"];
continue;
}
ruleView = value;
[ruleView setTarget:self];
[ruleView setAction:@selector(_sendRuleAction:)];
if ([ruleView respondsToSelector:@selector(setDelegate:)])
[ruleView setDelegate:self];
}
}
if (ruleView != nil)
{
[_ruleOptionViews addObject:ruleView];
var frame = [ruleView frame];
[_ruleOptionInitialViewFrames addObject:frame];
[_ruleOptionFrames addObject:frame];
if (!criterion)
criterion = [CPNull null];
[ruleItems addObject:criterion];
}
}
[_correspondingRuleItems setArray:ruleItems];
if (!editable)
[self _updateEnabledStateForSubviews];
[self _relayoutSubviewsWidthChanged:YES];
if (firstResponderIndex != CPNotFound)
{
var aView = [_ruleOptionViews objectAtIndex:firstResponderIndex];
[[self window] makeFirstResponder:aView]; // This is not working. bug in CPPopUpButton firstResponder ?
}
//[self setNeedsDisplay:YES];
}
- (void)_updateEnabledStateForSubviews
{
[_ruleOptionViews makeObjectsPerformSelector:@selector(setEnabled:) withObject:NO];
}
- (void)layoutSubviews
{
// CPLogConsole(_cmd);
[self _relayoutSubviewsWidthChanged:YES];
}
- (void)_relayoutSubviewsWidthChanged:(BOOL)widthChanged
{
var optionViewOriginX,
leftHorizontalPadding,
leftButtonMinX,
rowHeight = [_ruleEditor rowHeight],
count = [_ruleOptionViews count],
sliceFrame = [self frame];
var buttonFrame = CGRectMake(CGRectGetWidth(sliceFrame) - BUTTON_HEIGHT - [self _rowButtonsRightHorizontalPadding], ([_ruleEditor rowHeight] - BUTTON_HEIGHT)/2 - 2, BUTTON_HEIGHT, BUTTON_HEIGHT);
[_addButton setFrame:buttonFrame];
buttonFrame.origin.x -= BUTTON_HEIGHT + [self _rowButtonsInterviewHorizontalPadding];
[_subtractButton setFrame:buttonFrame];
if (widthChanged)
{
optionViewOriginX = [self _leftmostViewFixedHorizontalPadding] + [self _indentationHorizontalPadding] * _indentation;
leftHorizontalPadding = [self _rowButtonsLeftHorizontalPadding];
leftButtonMinX = CGRectGetMinX(buttonFrame);
}
for (var i = 0; i < count; i++)
{
var ruleOptionView = _ruleOptionViews[i],
optionFrame = _ruleOptionFrames[i];
optionFrame.origin.y = (rowHeight - CGRectGetHeight(optionFrame))/2 - 2;
if (widthChanged)
{
optionFrame.origin.x = optionViewOriginX;
if (i == count - 1 && ![self _isRulePopup:ruleOptionView])
{
var initialFrame = _ruleOptionInitialViewFrames[i];
optionFrame.size.width = MIN(CGRectGetWidth(initialFrame), leftButtonMinX - leftHorizontalPadding - optionViewOriginX);
}
}
[ruleOptionView setFrame:optionFrame];
[self addSubview:ruleOptionView];
if (widthChanged)
optionViewOriginX += CGRectGetWidth(optionFrame) + [self _interviewHorizontalPadding];
}
}
- (void)_updateButtonVisibilities
{
[_addButton setHidden:[_ruleEditor _shouldHideAddButtonForSlice:self]];
[_subtractButton setHidden:[_ruleEditor _shouldHideSubtractButtonForSlice:self]];
}
- (void)_configurePlusButtonByRowType:(CPRuleEditorRowType)type
{
[self _setRowTypeToAddFromPlusButton:type];
}
- (BOOL)isEditable
{
return editable;
}
- (void)setEditable:(BOOL)value
{
editable = value;
// [self _updateEnabledStateForSubviews];
[self _updateButtonVisibilities];
}
- (float)_alignmentGridWidth
{
return [_ruleEditor _alignmentGridWidth];
}
- (float)_indentationHorizontalPadding
{
return 30.;
}
- (float)_interviewHorizontalPadding
{
return 6.;
}
- (float)_leftmostViewFixedHorizontalPadding
{
return 7.;
}
- (float)_minimumVerticalPopupPadding
{
return 2.;
}
- (float)_rowButtonsInterviewHorizontalPadding
{
return 6.;
}
- (float)_rowButtonsLeftHorizontalPadding
{
return 10.;
}
- (float)_rowButtonsRightHorizontalPadding
{
return 10.;
}
- (void)_setRowTypeToAddFromPlusButton:(int)type
{
_plusButtonRowType = type;
}
- (void)setNeedsDisplay:(BOOL)flag
{
[super setNeedsDisplay:flag];
}
- (BOOL)_nestingModeShouldHideAddButton
{
return [_ruleEditor _applicableNestingMode] == CPRuleEditorNestingModeSingle;
}
- (BOOL)_nestingModeShouldHideSubtractButton
{
return [_ruleEditor _applicableNestingMode] == CPRuleEditorNestingModeSingle;
}
- (BOOL)containsDisplayValue:(id)value
{
return [[_ruleEditor displayValuesForRow:_rowIndex] containsObject:value];
// Ou alors avec _correspondingRuleItems
}
- (void)viewDidMoveToWindow
{
[self layoutSubviews];
}
- (void)drawRect:(CPRect)rect
{
[super drawRect:rect];
}
- (BOOL)_isRulePopup:(CPView)view
{
if ([view isKindOfClass:[_CPRuleEditorPopUpButton class]])
return YES;
return NO;
}
- (BOOL)_isRuleStaticTextField:(CPView)view
{
if ([view isKindOfClass:[_CPRuleEditorTextField class]])
return YES;
return NO;
}
- (void)_sendRuleAction:(id)sender
{
[_ruleEditor _sendRuleAction];
}
- (void)_textDidChange:(CPNotification)aNotif
{
if ([[aNotif object] superview] == self && [_ruleEditor _sendsActionOnIncompleteTextChange])
[_ruleEditor _sendRuleAction];
}
@end
@implementation _CPRuleEditorTextField : CPTextField
{
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self != nil)
{
[self setBordered:NO];
[self setEditable:NO];
[self setDrawsBackground:NO];
}
return self;
}
- (id)hitTest:(CPPoint)point
{
if (!CPRectContainsPoint([self frame], point))
return nil;
return [self superview];
}
@end
+22 -1
View File
@@ -1,5 +1,26 @@
/*
* CPSavePanel.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CPPanel.j>
@import "CPPanel.j"
@implementation CPSavePanel : CPPanel
+40 -4
View File
@@ -1,16 +1,52 @@
/*
* CPScreen.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
/*!
@ingroup appkit
@class CPScreen
#import "CoreGraphics/CGGeometry.h"
A CPScreen object describes the attributes of a display device available
to Cappuccino.
*/
@implementation CPScreen : CPObject
{
}
/*!
Returns the position and size of the visible area of the receiving screen.
This will normally be smaller than the full size of the screen to account
for system UI elements. For example, on a Mac the top of the visible frame
is placed below the bottom of the menu bar.
@return the visible screen rectangle
*/
- (CGRect)visibleFrame
{
#if PLATFORM(DOM)
return _CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight);
#else
return _CGRectMakeZero();
#endif
}
@end
@end
+463 -126
View File
@@ -20,14 +20,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPView.j"
@import "CPBox.j"
@import "CPClipView.j"
@import "CPScroller.j"
#include "CoreGraphics/CGGeometry.h"
@import "CPView.j"
/*!
/*!
@ingroup appkit
@class CPScrollView
@@ -37,23 +36,39 @@
*/
@implementation CPScrollView : CPView
{
CPClipView _contentView;
CPClipView _headerClipView;
CPView _cornerView;
CPClipView _contentView;
CPClipView _headerClipView;
CPView _cornerView;
CPView _bottomCornerView;
BOOL _hasVerticalScroller;
BOOL _hasHorizontalScroller;
BOOL _autohidesScrollers;
CPScroller _verticalScroller;
CPScroller _horizontalScroller;
int _recursionCount;
float _verticalLineScroll;
float _verticalPageScroll;
float _horizontalLineScroll;
float _horizontalPageScroll;
BOOL _hasVerticalScroller;
BOOL _hasHorizontalScroller;
BOOL _autohidesScrollers;
CPScroller _verticalScroller;
CPScroller _horizontalScroller;
int _recursionCount;
float _verticalLineScroll;
float _verticalPageScroll;
float _horizontalLineScroll;
float _horizontalPageScroll;
CPBorderType _borderType;
}
+ (CPString)defaultThemeClass
{
return @"scrollview"
}
+ (CPDictionary)themeAttributes
{
return [CPDictionary dictionaryWithJSObject:{
@"bottom-corner-color": [CPColor whiteColor],
@"border-color": [CPColor blackColor]
}];
}
- (id)initWithFrame:(CGRect)aFrame
@@ -68,14 +83,18 @@
_horizontalLineScroll = 10.0;
_horizontalPageScroll = 10.0;
_contentView = [[CPClipView alloc] initWithFrame:[self bounds]];
_borderType = CPNoBorder;
_contentView = [[CPClipView alloc] initWithFrame:[self _insetBounds]];
[self addSubview:_contentView];
_headerClipView = [[CPClipView alloc] init];
[self addSubview:_headerClipView];
_bottomCornerView = [[CPView alloc] init];
[self addSubview:_bottomCornerView];
[self setHasVerticalScroller:YES];
[self setHasHorizontalScroller:YES];
}
@@ -83,11 +102,70 @@
return self;
}
// Calculating Layout
+ (CGSize)contentSizeForFrameSize:(CGSize)frameSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType
{
var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType],
scrollerWidth = [CPScroller scrollerWidth];
if (hFlag)
bounds.size.height -= scrollerWidth;
if (vFlag)
bounds.size.width -= scrollerWidth;
return bounds.size;
}
+ (CGSize)frameSizeForContentSize:(CGSize)contentSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType
{
var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) borderType:borderType],
widthInset = contentSize.width - bounds.size.width,
heightInset = contentSize.height - bounds.size.height,
frameSize = _CGSizeMake(contentSize.width + widthInset, contentSize.height + heightInset),
scrollerWidth = [CPScroller scrollerWidth];
if (hFlag)
frameSize.height -= scrollerWidth;
if (vFlag)
frameSize.width -= scrollerWidth;
return frameSize;
}
+ (CGRect)_insetBounds:(CGRect)bounds borderType:(CPBorderType)borderType
{
switch (borderType)
{
case CPLineBorder:
case CPBezelBorder:
return _CGRectInset(bounds, 1.0, 1.0);
case CPGrooveBorder:
bounds = _CGRectInset(bounds, 2.0, 2.0);
++bounds.origin.y;
--bounds.size.height;
return bounds;
case CPNoBorder:
default:
return bounds;
}
}
- (CGRect)_insetBounds
{
return [[self class] _insetBounds:[self bounds] borderType:_borderType];
}
// Determining component sizes
/*!
Returns the size of the scroll view's content view.
*/
- (CGRect)contentSize
- (CGSize)contentSize
{
return [_contentView frame].size;
}
@@ -106,7 +184,7 @@
*/
- (void)setContentView:(CPClipView)aContentView
{
if (_contentView !== aContentView || !aContentView)
if (_contentView === aContentView || !aContentView)
return;
var documentView = [aContentView documentView];
@@ -153,16 +231,16 @@
*/
- (void)reflectScrolledClipView:(CPClipView)aClipView
{
if(_contentView !== aClipView)
if (_contentView !== aClipView)
return;
if (_recursionCount > 5)
return;
++_recursionCount;
var documentView = [self documentView];
if (!documentView)
{
if (_autohidesScrollers)
@@ -176,7 +254,7 @@
// [_horizontalScroller setEnabled:NO];
}
[_contentView setFrame:[self bounds]];
[_contentView setFrame:[self _insetBounds]];
[_headerClipView setFrame:_CGRectMakeZero()];
--_recursionCount;
@@ -185,7 +263,7 @@
}
var documentFrame = [documentView frame], // the size of the whole document
contentFrame = [self bounds], // assume it takes up the entire size of the scrollview (no scrollers)
contentFrame = [self _insetBounds], // assume it takes up the entire size of the scrollview (no scrollers)
headerClipViewFrame = [self _headerClipViewFrame],
headerClipViewHeight = _CGRectGetHeight(headerClipViewFrame);
@@ -235,11 +313,10 @@
if (shouldShowVerticalScroller)
{
var verticalScrollerY = MAX(_CGRectGetHeight([self _cornerViewFrame]), headerClipViewHeight),
verticalScrollerHeight = _CGRectGetHeight([self bounds]) - verticalScrollerY;
var verticalScrollerY =
MAX(_CGRectGetMinY(contentFrame), MAX(_CGRectGetMaxY([self _cornerViewFrame]), _CGRectGetMaxY(headerClipViewFrame)));
if (shouldShowHorizontalScroller)
verticalScrollerHeight -= horizontalScrollerHeight;
var verticalScrollerHeight = _CGRectGetMaxY(contentFrame) - verticalScrollerY;
[_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height];
[_verticalScroller setKnobProportion:_CGRectGetHeight(contentFrame) / _CGRectGetHeight(documentFrame)];
@@ -250,12 +327,12 @@
[_verticalScroller setFloatValue:0.0];
[_verticalScroller setKnobProportion:1.0];
}
if (shouldShowHorizontalScroller)
{
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
[_horizontalScroller setKnobProportion:_CGRectGetWidth(contentFrame) / _CGRectGetWidth(documentFrame)];
[_horizontalScroller setFrame:_CGRectMake(0.0, _CGRectGetMaxY(contentFrame), _CGRectGetWidth(contentFrame), horizontalScrollerHeight)];
[_horizontalScroller setFrame:_CGRectMake(_CGRectGetMinX(contentFrame), _CGRectGetMaxY(contentFrame), _CGRectGetWidth(contentFrame), horizontalScrollerHeight)];
}
else if (wasShowingHorizontalScroller)
{
@@ -265,11 +342,45 @@
[_contentView setFrame:contentFrame];
[_headerClipView setFrame:headerClipViewFrame];
[[_headerClipView documentView] setNeedsDisplay:YES];
[_cornerView setFrame:[self _cornerViewFrame]];
[[self bottomCornerView] setFrame:[self _bottomCornerViewFrame]];
[[self bottomCornerView] setBackgroundColor:[self currentValueForThemeAttribute:@"bottom-corner-color"]];
--_recursionCount;
}
// Managing Graphics Attributes
/*!
Sets the type of border to be drawn around the view.
Valid types are:
<pre>
CPNoBorder
CPLineBorder
CPBezelBorder
CPGrooveBorder</pre>
*/
- (void)setBorderType:(CPBorderType)borderType
{
if (_borderType == borderType)
return;
_borderType = borderType;
[self reflectScrolledClipView:_contentView];
[self setNeedsDisplay:YES];
}
/*!
Returns the border type drawn around the view.
*/
- (CPBorderType)borderType
{
return _borderType;
}
// Managing Scrollers
/*!
Sets the scroll view's horizontal scroller.
@@ -279,13 +390,13 @@
{
if (_horizontalScroller === aScroller)
return;
[_horizontalScroller removeFromSuperview];
[_horizontalScroller setTarget:nil];
[_horizontalScroller setAction:nil];
_horizontalScroller = aScroller;
[_horizontalScroller setTarget:self];
[_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)];
@@ -315,7 +426,12 @@
_hasHorizontalScroller = shouldHaveHorizontalScroller;
if (_hasHorizontalScroller && !_horizontalScroller)
[self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, _CGRectGetWidth([self bounds]), [CPScroller scrollerWidth])]];
{
var bounds = [self _insetBounds];
[self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(_CGRectGetWidth(bounds), [CPScroller scrollerWidth] + 1), [CPScroller scrollerWidth])]];
[[self horizontalScroller] setFrameSize:CGSizeMake(_CGRectGetWidth(bounds), [CPScroller scrollerWidth])];
}
[self reflectScrolledClipView:_contentView];
}
@@ -336,13 +452,13 @@
{
if (_verticalScroller === aScroller)
return;
[_verticalScroller removeFromSuperview];
[_verticalScroller setTarget:nil];
[_verticalScroller setAction:nil];
_verticalScroller = aScroller;
[_verticalScroller setTarget:self];
[_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)];
@@ -373,7 +489,12 @@
_hasVerticalScroller = shouldHaveVerticalScroller;
if (_hasVerticalScroller && !_verticalScroller)
[self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidth], _CGRectGetHeight([self bounds]))]];
{
var bounds = [self _insetBounds];
[self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidth], MAX(_CGRectGetHeight(bounds), [CPScroller scrollerWidth] + 1))]];
[[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidth], _CGRectGetHeight(bounds))];
}
[self reflectScrolledClipView:_contentView];
}
@@ -387,7 +508,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.
*/
@@ -397,7 +518,7 @@
return;
_autohidesScrollers = autohidesScrollers;
[self reflectScrolledClipView:_contentView];
}
@@ -439,9 +560,7 @@
- (CPView)_headerView
{
var headerClipViewSubviews = [_headerClipView subviews];
return [headerClipViewSubviews count] ? headerClipViewSubviews[0] : nil;
return [_headerClipView documentView];
}
- (CGRect)_cornerViewFrame
@@ -449,11 +568,11 @@
if (!_cornerView)
return _CGRectMakeZero();
var bounds = [self bounds],
var bounds = [self _insetBounds],
frame = [_cornerView frame];
frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame);
frame.origin.y = 0;
frame.origin.y = _CGRectGetMinY(bounds);
return frame;
}
@@ -465,7 +584,7 @@
if (!headerView)
return _CGRectMakeZero();
var frame = [self bounds];
var frame = [self _insetBounds];
frame.size.height = _CGRectGetHeight([headerView frame]);
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
@@ -473,33 +592,69 @@
return frame;
}
- (CGRect)_bottomCornerViewFrame
{
if ([[self horizontalScroller] isHidden] || [[self verticalScroller] isHidden])
return CGRectMakeZero();
var verticalFrame = [[self verticalScroller] frame],
bottomCornerFrame = CGRectMakeZero();
bottomCornerFrame.origin.x = CGRectGetMinX(verticalFrame);
bottomCornerFrame.origin.y = CGRectGetMaxY(verticalFrame);
bottomCornerFrame.size.width = [CPScroller scrollerWidth];
bottomCornerFrame.size.height = [CPScroller scrollerWidth];
return bottomCornerFrame;
}
- (void)setBottomCornerView:(CPView)aBottomCornerView
{
if (_bottomCornerView === aBottomCornerView)
return;
[_bottomCornerView removeFromSuperview];
[aBottomCornerView setFrame:[self _bottomCornerViewFrame]];
[self addSubview:aBottomCornerView];
_bottomCornerView = aBottomCornerView;
[self _updateCornerAndHeaderView];
}
- (CPView)bottomCornerView
{
return _bottomCornerView;
}
/* @ignore */
- (void)_verticalScrollerDidScroll:(CPScroller)aScroller
{
var value = [aScroller floatValue],
documentFrame = [[_contentView documentView] frame];
var value = [aScroller floatValue],
documentFrame = [[_contentView documentView] frame],
contentBounds = [_contentView bounds];
switch ([_verticalScroller hitPart])
{
case CPScrollerDecrementLine: contentBounds.origin.y -= _verticalLineScroll;
break;
case CPScrollerIncrementLine: contentBounds.origin.y += _verticalLineScroll;
break;
case CPScrollerDecrementPage: contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
break;
case CPScrollerIncrementPage: contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
break;
case CPScrollerKnobSlot:
case CPScrollerKnob:
// We want integral bounds!
default: contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)));
}
[_contentView scrollToPoint:contentBounds.origin];
}
@@ -509,21 +664,21 @@
var value = [aScroller floatValue],
documentFrame = [[self documentView] frame],
contentBounds = [_contentView bounds];
switch ([_horizontalScroller hitPart])
{
case CPScrollerDecrementLine: contentBounds.origin.x -= _horizontalLineScroll;
break;
case CPScrollerIncrementLine: contentBounds.origin.x += _horizontalLineScroll;
break;
case CPScrollerDecrementPage: contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
break;
case CPScrollerIncrementPage: contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
break;
case CPScrollerKnobSlot:
case CPScrollerKnob:
// We want integral bounds!
@@ -548,7 +703,7 @@
/*
@ignore
*/
-(void)resizeSubviewsWithOldSize:(CGSize)aSize
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
{
[self reflectScrolledClipView:_contentView];
}
@@ -560,7 +715,7 @@
*/
- (void)setLineScroll:(float)aLineScroll
{
[self setHorizonalLineScroll:aLineScroll];
[self setHorizontalLineScroll:aLineScroll];
[self setVerticalLineScroll:aLineScroll];
}
@@ -643,7 +798,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
{
@@ -658,74 +813,238 @@
return _verticalPageScroll;
}
// CPView Overrides
- (void)drawRect:(CPRect)aRect
{
[super drawRect:aRect];
if (_borderType == CPNoBorder)
return;
var strokeRect = [self bounds],
context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetLineWidth(context, 1);
switch (_borderType)
{
case CPLineBorder:
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"border-color"]);
CGContextStrokeRect(context, _CGRectInset(strokeRect, 0.5, 0.5));
break;
case CPBezelBorder:
[self _drawGrayBezelInContext:context bounds:strokeRect];
break;
case CPGrooveBorder:
[self _drawGrooveInContext:context bounds:strokeRect];
break;
default:
break;
}
}
- (void)_drawGrayBezelInContext:(CGContext)context bounds:(CGRect)aRect
{
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:142.0 / 255.0 alpha:1.0]);
var y = _CGRectGetMinY(aRect) + 0.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect), y);
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 1.0, y);
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 1.0, y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y);
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:142.0 / 255.0 alpha:1.0]);
CGContextMoveToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect), y);
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:190.0 / 255.0 alpha:1.0]);
var x = _CGRectGetMaxX(aRect) - 0.5;
CGContextMoveToPoint(context, x, _CGRectGetMinY(aRect) + 1.0);
CGContextAddLineToPoint(context, x, _CGRectGetMaxY(aRect));
CGContextMoveToPoint(context, x - 0.5, _CGRectGetMaxY(aRect) - 0.5);
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect), _CGRectGetMaxY(aRect) - 0.5);
x = _CGRectGetMinX(aRect) + 0.5;
CGContextMoveToPoint(context, x, _CGRectGetMaxY(aRect));
CGContextAddLineToPoint(context, x, _CGRectGetMinY(aRect) + 1.0);
CGContextStrokePath(context);
}
- (void)_drawGrooveInContext:(CGContext)context bounds:(CGRect)aRect
{
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:159.0 / 255.0 alpha:1.0]);
var y = _CGRectGetMinY(aRect) + 0.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect), y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect), y);
var x = _CGRectGetMaxX(aRect) - 1.5;
CGContextMoveToPoint(context, x, _CGRectGetMinY(aRect) + 2.0);
CGContextAddLineToPoint(context, x, _CGRectGetMaxY(aRect) - 1.0);
y = _CGRectGetMaxY(aRect) - 1.5;
CGContextMoveToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y);
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 2.0, y);
x = _CGRectGetMinX(aRect) + 0.5;
CGContextMoveToPoint(context, x, _CGRectGetMaxY(aRect));
CGContextAddLineToPoint(context, x, _CGRectGetMinY(aRect));
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor whiteColor]);
var rect = _CGRectOffset(aRect, 1.0, 1.0);
rect.size.width -= 1.0;
rect.size.height -= 1.0;
CGContextStrokeRect(context, _CGRectInset(rect, 0.5, 0.5));
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
y = _CGRectGetMinY(aRect) + 2.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 2.0, y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect) - 2.0, y);
CGContextStrokePath(context);
}
// CPResponder Overrides
/*!
Handles a scroll wheel event from the user.
@param anEvent the scroll wheel event
*/
- (void)scrollWheel:(CPEvent)anEvent
{
var documentFrame = [[self documentView] frame],
contentBounds = [_contentView bounds];
// We want integral bounds!
contentBounds.origin.x = ROUND(contentBounds.origin.x + [anEvent deltaX] * _horizontalLineScroll);
contentBounds.origin.y = ROUND(contentBounds.origin.y + [anEvent deltaY] * _verticalLineScroll);
[_contentView scrollToPoint:contentBounds.origin];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)];
[self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] deltaY:[anEvent deltaY]];
}
- (void)keyDown:(CPEvent)anEvent
- (void)_respondToScrollWheelEventWithDeltaX:(float)deltaX deltaY:(float)deltaY
{
var keyCode = [anEvent keyCode],
var documentFrame = [[self documentView] frame],
contentBounds = [_contentView bounds],
contentFrame = [_contentView frame],
enclosingScrollView = [self enclosingScrollView];
// We want integral bounds!
contentBounds.origin.x = ROUND(contentBounds.origin.x + deltaX);
contentBounds.origin.y = ROUND(contentBounds.origin.y + deltaY);
var constrainedOrigin = [_contentView constrainScrollPoint:CGPointCreateCopy(contentBounds.origin)],
extraX = contentBounds.origin.x - constrainedOrigin.x,
extraY = contentBounds.origin.y - constrainedOrigin.y;
[_contentView scrollToPoint:constrainedOrigin];
[_headerClipView scrollToPoint:CGPointMake(constrainedOrigin.x, 0.0)];
if (extraX || extraY)
[enclosingScrollView _respondToScrollWheelEventWithDeltaX:extraX deltaY:extraY];
}
- (void)scrollPageUp:(id)sender
{
var contentBounds = [_contentView bounds];
[self moveByOffset:CGSizeMake(0.0, -(_CGRectGetHeight(contentBounds) - _verticalPageScroll))];
}
- (void)scrollPageDown:(id)sender
{
var contentBounds = [_contentView bounds];
[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)];
}
- (void)moveRight:(id)sender
{
[self moveByOffset:CGSizeMake(_horizontalLineScroll, 0.0)];
}
- (void)moveUp:(id)sender
{
[self moveByOffset:CGSizeMake(0.0, -_verticalLineScroll)];
}
- (void)moveDown:(id)sender
{
[self moveByOffset:CGSizeMake(0.0, _verticalLineScroll)];
}
- (void)moveByOffset:(CGSize)aSize
{
var documentFrame = [[self documentView] frame],
contentBounds = [_contentView bounds];
switch (keyCode)
{
case 33: /*pageup*/
contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
break;
case 34: /*pagedown*/
contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
break;
case 38: /*up arrow*/
contentBounds.origin.y -= _verticalLineScroll;
break;
case 40: /*down arrow*/
contentBounds.origin.y += _verticalLineScroll;
break;
case 37: /*left arrow*/
contentBounds.origin.x -= _horizontalLineScroll;
break;
case 49: /*right arrow*/
contentBounds.origin.x += _horizontalLineScroll;
break;
default: return [super keyDown:anEvent];
}
contentBounds.origin.x += aSize.width;
contentBounds.origin.y += aSize.height;
[_contentView scrollToPoint:contentBounds.origin];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin, 0)];
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0)];
}
@end
var CPScrollViewContentViewKey = "CPScrollViewContentView",
CPScrollViewVLineScrollKey = "CPScrollViewVLineScroll",
CPScrollViewHLineScrollKey = "CPScrollViewHLineScroll",
CPScrollViewVPageScrollKey = "CPScrollViewVPageScroll",
CPScrollViewHPageScrollKey = "CPScrollViewHPageScroll",
CPScrollViewHasVScrollerKey = "CPScrollViewHasVScroller",
CPScrollViewHasHScrollerKey = "CPScrollViewHasHScroller",
CPScrollViewVScrollerKey = "CPScrollViewVScroller",
CPScrollViewHScrollerKey = "CPScrollViewHScroller",
CPScrollViewAutohidesScrollerKey = "CPScrollViewAutohidesScroller";
var CPScrollViewContentViewKey = @"CPScrollViewContentView",
CPScrollViewHeaderClipViewKey = @"CPScrollViewHeaderClipViewKey",
CPScrollViewVLineScrollKey = @"CPScrollViewVLineScroll",
CPScrollViewHLineScrollKey = @"CPScrollViewHLineScroll",
CPScrollViewVPageScrollKey = @"CPScrollViewVPageScroll",
CPScrollViewHPageScrollKey = @"CPScrollViewHPageScroll",
CPScrollViewHasVScrollerKey = @"CPScrollViewHasVScroller",
CPScrollViewHasHScrollerKey = @"CPScrollViewHasHScroller",
CPScrollViewVScrollerKey = @"CPScrollViewVScroller",
CPScrollViewHScrollerKey = @"CPScrollViewHScroller",
CPScrollViewAutohidesScrollerKey = @"CPScrollViewAutohidesScroller",
CPScrollViewCornerViewKey = @"CPScrollViewCornerViewKey",
CPScrollViewBottomCornerViewKey = @"CPScrollViewBottomCornerViewKey",
CPScrollViewBorderTypeKey = @"CPScrollViewBorderTypeKey";
@implementation CPScrollView (CPCoding)
@@ -738,40 +1057,58 @@ var CPScrollViewContentViewKey = "CPScrollViewContentView",
_horizontalLineScroll = [aCoder decodeFloatForKey:CPScrollViewHLineScrollKey];
_horizontalPageScroll = [aCoder decodeFloatForKey:CPScrollViewHPageScrollKey];
_contentView = [aCoder decodeObjectForKey:CPScrollViewContentViewKey];
_headerClipView = [aCoder decodeObjectForKey:CPScrollViewHeaderClipViewKey];
if (!_headerClipView)
{
_headerClipView = [[CPClipView alloc] init];
[self addSubview:_headerClipView];
}
_verticalScroller = [aCoder decodeObjectForKey:CPScrollViewVScrollerKey];
_horizontalScroller = [aCoder decodeObjectForKey:CPScrollViewHScrollerKey];
_hasVerticalScroller = [aCoder decodeBoolForKey:CPScrollViewHasVScrollerKey];
_hasHorizontalScroller = [aCoder decodeBoolForKey:CPScrollViewHasHScrollerKey];
_autohidesScrollers = [aCoder decodeBoolForKey:CPScrollViewAutohidesScrollerKey];
// Do to the anything goes nature of decoding, our subviews may not exist yet, so layout at the end of the run loop when we're sure everything is in a correct state.
[[CPRunLoop currentRunLoop] performSelector:@selector(reflectScrolledClipView:) target:self argument:_contentView order:0 modes:[CPDefaultRunLoopMode]];
_borderType = [aCoder decodeIntForKey:CPScrollViewBorderTypeKey];
_cornerView = [aCoder decodeObjectForKey:CPScrollViewCornerViewKey];
_bottomCornerView = [aCoder decodeObjectForKey:CPScrollViewBottomCornerViewKey];
// Due to the anything goes nature of decoding, our subviews may not exist yet, so layout at the end of the run loop when we're sure everything is in a correct state.
[[CPRunLoop currentRunLoop] performSelector:@selector(_updateCornerAndHeaderView) target:self argument:_contentView order:0 modes:[CPDefaultRunLoopMode]];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_contentView forKey:CPScrollViewContentViewKey];
[aCoder encodeObject:_headerClipView forKey:CPScrollViewHeaderClipViewKey];
[aCoder encodeObject:_verticalScroller forKey:CPScrollViewVScrollerKey];
[aCoder encodeObject:_horizontalScroller forKey:CPScrollViewHScrollerKey];
[aCoder encodeFloat:_verticalLineScroll forKey:CPScrollViewVLineScrollKey];
[aCoder encodeFloat:_verticalPageScroll forKey:CPScrollViewVPageScrollKey];
[aCoder encodeFloat:_horizontalLineScroll forKey:CPScrollViewHLineScrollKey];
[aCoder encodeFloat:_horizontalPageScroll forKey:CPScrollViewHPageScrollKey];
[aCoder encodeBool:_hasVerticalScroller forKey:CPScrollViewHasVScrollerKey];
[aCoder encodeBool:_hasHorizontalScroller forKey:CPScrollViewHasHScrollerKey];
[aCoder encodeBool:_autohidesScrollers forKey:CPScrollViewAutohidesScrollerKey];
[aCoder encodeObject:_cornerView forKey:CPScrollViewCornerViewKey];
[aCoder encodeObject:_bottomCornerView forKey:CPScrollViewBottomCornerViewKey];
[aCoder encodeInt:_borderType forKey:CPScrollViewBorderTypeKey];
}
@end
+120 -89
View File
@@ -22,8 +22,6 @@
@import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
// CPScroller Constants
CPScrollerNoPart = 0;
@@ -41,9 +39,9 @@ CPNoScrollerParts = 0;
CPOnlyScrollerArrows = 1;
CPAllScrollerParts = 2;
/*!
/*!
@ingroup appkit
@class CPScroller
@class CPScroller
*/
var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScrollerIncrementLine, CPScrollerKnob],
@@ -72,24 +70,25 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
CGPoint _trackingStartPoint;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return "scroller";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[ nil, nil, nil, nil,
_CGSizeMakeZero(), _CGSizeMakeZero(), _CGInsetMakeZero(), _CGInsetMakeZero(), _CGSizeMakeZero()]
forKeys:[ @"knob-slot-color",
@"decrement-line-color",
@"increment-line-color",
@"knob-color",
@"decrement-line-size",
@"increment-line-size",
@"track-inset",
@"knob-inset",
@"minimum-knob-length"]];
return [CPDictionary dictionaryWithJSObject:{
@"scroller-width": 15.0,
@"knob-slot-color": [CPColor lightGrayColor],
@"decrement-line-color": [CPNull null],
@"increment-line-color": [CPNull null],
@"knob-color": [CPColor grayColor],
@"decrement-line-size":_CGSizeMakeZero(),
@"increment-line-size":_CGSizeMakeZero(),
@"track-inset":_CGInsetMakeZero(),
@"knob-inset": _CGInsetMakeZero(),
@"minimum-knob-length":21.0
}]
}
@@ -98,7 +97,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_controlSize = CPRegularControlSize;
@@ -106,7 +105,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
[self setFloatValue:0.0];
[self setKnobProportion:1.0];
_hitPart = CPScrollerNoPart;
[self _calculateIsVertical];
@@ -121,7 +120,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
*/
+ (float)scrollerWidth
{
return 15.0;//[self scrollerWidthForControlSize:CPRegularControlSize];
return [[[CPScroller alloc] init] currentValueForThemeAttribute:@"scroller-width"];
}
/*!
@@ -130,7 +129,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
*/
+ (float)scrollerWidthForControlSize:(CPControlSize)aControlSize
{
return 15.0;//_CPScrollerWidths[aControlSize];
return [self scrollerWidth];
}
/*!
@@ -180,10 +179,10 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (id)currentValueForThemeAttribute:(CPString)anAttributeName
{
var themeState = _themeState;
if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName)
themeState &= ~CPThemeStateHighlighted;
return [self valueForThemeAttribute:anAttributeName inState:themeState];
}
@@ -205,25 +204,25 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (CPScrollerPart)testPart:(CGPoint)aPoint
{
aPoint = [self convertPoint:aPoint fromView:nil];
// The ordering of these tests is important. We check the knob and
// The ordering of these tests is important. We check the knob and
// page rects first since they may overlap with the arrows.
if (CGRectContainsPoint([self rectForPart:CPScrollerKnob], aPoint))
return CPScrollerKnob;
if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementPage], aPoint))
return CPScrollerDecrementPage;
if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementPage], aPoint))
return CPScrollerIncrementPage;
if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementLine], aPoint))
return CPScrollerDecrementLine;
if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementLine], aPoint))
return CPScrollerIncrementLine;
if (CGRectContainsPoint([self rectForPart:CPScrollerKnobSlot], aPoint))
return CPScrollerKnobSlot;
@@ -241,16 +240,16 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
if (_knobProportion === 1.0)
{
_usableParts = CPNoScrollerParts;
_partRects[CPScrollerDecrementPage] = _CGRectMakeZero();
_partRects[CPScrollerKnob] = _CGRectMakeZero();
_partRects[CPScrollerIncrementPage] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementPage] = CGRectMakeZero();
_partRects[CPScrollerKnob] = CGRectMakeZero();
_partRects[CPScrollerIncrementPage] = CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = CGRectMakeZero();
_partRects[CPScrollerIncrementLine] = CGRectMakeZero();
// In this case, the slot is the entirety of the scroller.
_partRects[CPScrollerKnobSlot] = _CGRectMakeCopy(bounds);
_partRects[CPScrollerKnobSlot] = CGRectMakeCopy(bounds);
return;
}
@@ -260,46 +259,65 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
var knobInset = [self currentValueForThemeAttribute:@"knob-inset"],
trackInset = [self currentValueForThemeAttribute:@"track-inset"],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
height = _CGRectGetHeight(bounds);
if ([self isVertical])
{
var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
incrementLineSize = [self currentValueForThemeAttribute:"increment-line-size"],
effectiveDecrementLineHeight = decrementLineSize.height + trackInset.top,
effectiveIncrementLineHeight = incrementLineSize.height + trackInset.bottom,
slotHeight = height - effectiveDecrementLineHeight - effectiveIncrementLineHeight,
slotSize = height - effectiveDecrementLineHeight - effectiveIncrementLineHeight,
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
knobWidth = width - knobInset.left - knobInset.right,
knobHeight = MAX(minimumKnobLength, (slotHeight * _knobProportion)),
knobLocation = effectiveDecrementLineHeight + (slotHeight - knobHeight) * [self floatValue];
knobHeight = MAX(minimumKnobLength, (slotSize * _knobProportion)),
knobLocation = effectiveDecrementLineHeight + (slotSize - knobHeight) * [self floatValue];
_partRects[CPScrollerDecrementPage] = _CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight);
_partRects[CPScrollerKnob] = _CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight);
_partRects[CPScrollerIncrementPage] = _CGRectMake(0.0, knobLocation + knobHeight, width, height - (knobLocation + knobHeight) - effectiveIncrementLineHeight);
_partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotHeight);
_partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotSize);
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height);
}
_partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height);
if (height < knobHeight + decrementLineSize.height + incrementLineSize.height + trackInset.top + trackInset.bottom)
_partRects[CPScrollerKnob] = _CGRectMakeZero();
if (height < decrementLineSize.height + incrementLineSize.height - 2)
{
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, 0, width - trackInset.left - trackInset.right, height);
}
}
else
{
var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
incrementLineSize = [self currentValueForThemeAttribute:"increment-line-size"],
effectiveDecrementLineWidth = decrementLineSize.width + trackInset.left,
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right;
slotWidth = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth,
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right,
slotSize = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth,
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
knobWidth = MAX(minimumKnobLength, (slotWidth * _knobProportion)),
knobWidth = MAX(minimumKnobLength, (slotSize * _knobProportion)),
knobHeight = height - knobInset.top - knobInset.bottom,
knobLocation = effectiveDecrementLineWidth + (slotWidth - knobWidth) * [self floatValue];
knobLocation = effectiveDecrementLineWidth + (slotSize - knobWidth) * [self floatValue];
_partRects[CPScrollerDecrementPage] = _CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height);
_partRects[CPScrollerKnob] = _CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight);
_partRects[CPScrollerIncrementPage] = _CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - effectiveIncrementLineWidth, height);
_partRects[CPScrollerKnobSlot] = _CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotWidth, height - trackInset.top - trackInset.bottom);
_partRects[CPScrollerKnobSlot] = _CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotSize, height - trackInset.top - trackInset.bottom);
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = _CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height);
if (width < knobWidth + decrementLineSize.width + incrementLineSize.width + trackInset.left + trackInset.right)
_partRects[CPScrollerKnob] = _CGRectMakeZero();
if (width < decrementLineSize.width + incrementLineSize.width - 2)
{
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = _CGRectMake(0.0, 0.0, width, slotSize);
}
}
}
@@ -339,9 +357,9 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (CPView)createViewForPart:(CPScrollerPart)aPart
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
@@ -355,7 +373,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
@@ -369,12 +387,12 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
for (; index < count; ++index)
{
var part = PARTS_ARRANGEMENT[index];
if (index === 0)
view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowBelow relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index + 1]];
else
view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowAbove relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index - 1]];
if (view)
[view setBackgroundColor:[self currentValueForThemeAttribute:NAMES_FOR_PARTS[part] + "-color"]];
}
@@ -384,7 +402,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
Caches images for the scroll arrow and knob.
*/
- (void)drawParts
{
{
[self drawKnobSlot];
[self drawKnob];
[self drawArrow:CPScrollerDecrementArrow highlight:NO];
@@ -407,37 +425,37 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (void)trackKnob:(CPEvent)anEvent
{
var type = [anEvent type];
if (type === CPLeftMouseUp)
{
_hitPart = CPScrollerNoPart;
return;
}
if (type === CPLeftMouseDown)
{
_trackingFloatValue = [self floatValue];
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
}
else if (type === CPLeftMouseDragged)
{
var knobRect = [self rectForPart:CPScrollerKnob],
knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
remainder = ![self isVertical] ? (_CGRectGetWidth(knobSlotRect) - _CGRectGetWidth(knobRect)) : (_CGRectGetHeight(knobSlotRect) - _CGRectGetHeight(knobRect));
if (remainder <= 0)
[self setFloatValue:0.0];
else
{
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
delta = ![self isVertical] ? location.x - _trackingStartPoint.x : location.y - _trackingStartPoint.y;
[self setFloatValue:_trackingFloatValue + delta / remainder];
}
}
[CPApp setTarget:self selector:@selector(trackKnob:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
[self sendAction:[self action] to:[self target]];
@@ -455,26 +473,26 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
{
[self highlight:NO];
[CPEvent stopPeriodicEvents];
_hitPart = CPScrollerNoPart;
return;
}
if (type === CPLeftMouseDown)
{
_trackingPart = [self hitPart];
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if ([anEvent modifierFlags] & CPAlternateKeyMask)
{
if (_trackingPart == CPScrollerDecrementLine)
_hitPart = CPScrollerDecrementPage;
else if (_trackingPart == CPScrollerIncrementLine)
_hitPart = CPScrollerIncrementPage;
else if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage)
{
var knobRect = [self rectForPart:CPScrollerKnob],
@@ -483,42 +501,42 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
remainder = (![self isVertical] ? _CGRectGetWidth(knobSlotRect) : _CGRectGetHeight(knobSlotRect)) - knobWidth;
[self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - _CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - _CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder];
_hitPart = CPScrollerKnob;
[self sendAction:[self action] to:[self target]];
[self sendAction:[self action] to:[self target]];
// Now just track the knob.
return [self trackKnob:anEvent];
}
}
[self highlight:YES];
[self sendAction:[self action] to:[self target]];
[CPEvent startPeriodicEventsAfterDelay:0.5 withPeriod:0.04];
}
else if (type === CPLeftMouseDragged)
{
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage)
{
var hitPart = [self testPart:[anEvent locationInWindow]];
if (hitPart == CPScrollerDecrementPage || hitPart == CPScrollerIncrementPage)
{
_trackingPart = hitPart;
_hitPart = hitPart;
}
}
[self highlight:CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint)];
}
else if (type == CPPeriodic && CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint))
[self sendAction:[self action] to:[self target]];
[CPApp setTarget:self selector:@selector(trackScrollButtons:) forNextEventMatchingMask:CPPeriodicMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
@@ -550,15 +568,15 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
{
if (![self isEnabled])
return;
_hitPart = [self testPart:[anEvent locationInWindow]];
switch (_hitPart)
{
case CPScrollerKnob: return [self trackKnob:anEvent];
case CPScrollerDecrementLine:
case CPScrollerIncrementLine:
case CPScrollerDecrementLine:
case CPScrollerIncrementLine:
case CPScrollerDecrementPage:
case CPScrollerIncrementPage: return [self trackScrollButtons:anEvent];
}
@@ -584,19 +602,32 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize",
_knobProportion = [aCoder decodeFloatForKey:CPScrollerKnobProportionKey];
_partRects = [];
_hitPart = CPScrollerNoPart;
[self _calculateIsVertical];
// Adjust the size of the scroller if the size from cib
// isn't equal to the scrollerWidth
var frame = [self frame],
scrollerWidth = [CPScroller scrollerWidth];
if ([self isVertical] && CGRectGetWidth(frame) !== scrollerWidth)
frame.size.width = scrollerWidth;
if (![self isVertical] && CGRectGetHeight(frame) !== scrollerWidth)
frame.size.height = scrollerWidth;
[self setFrame:frame];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeInt:_controlSize forKey:CPScrollerControlSizeKey];
[aCoder encodeFloat:_knobProportion forKey:CPScrollerKnobProportionKey];
}
+398 -296
View File
@@ -20,42 +20,33 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPButton.j"
@import "CPTextField.j"
#include "Platform/Platform.h"
/*!
@global
@group Menu tags
*/
CPSearchFieldRecentsTitleMenuItemTag = 1000;
/*!
@global
@group Menu tags
*/
CPSearchFieldRecentsMenuItemTag = 1001;
/*!
@global
@group Menu tags
*/
CPSearchFieldClearRecentsMenuItemTag = 1002;
/*!
@global
@group Menu tags
*/
CPSearchFieldNoRecentsMenuItemTag = 1003;
CPSearchFieldRecentsTitleMenuItemTag = 1000;
CPSearchFieldRecentsMenuItemTag = 1001;
CPSearchFieldClearRecentsMenuItemTag = 1002;
CPSearchFieldNoRecentsMenuItemTag = 1003;
var CPSearchFieldSearchImage = nil,
CPSearchFieldFindImage = nil,
CPSearchFieldCancelImage = nil,
CPSearchFieldCancelPressedImage = nil;
/*!
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
{
@@ -66,80 +57,83 @@ var CPSearchFieldSearchImage = nil,
CPString _recentsAutosaveName;
CPArray _recentSearches;
int _maximumRecents;
BOOL _sendsWholeSearchString;
BOOL _sendsSearchStringImmediately;
BOOL _canResignFirstResponder;
CPTimer _partialStringTimer;
}
+ (CPString)defaultThemeClass
{
return @"searchfield"
}
+ (void)initialize
{
if (self != [CPSearchField class])
return;
var bundle = [CPBundle bundleForClass:self];
CPSearchFieldSearchImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldSearch.png"]];
CPSearchFieldFindImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldFind.png"]];
CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"]];
CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"]];
CPSearchFieldSearchImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldSearch.png"] size:_CGSizeMake(SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
CPSearchFieldFindImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldFind.png"] size:_CGSizeMake(SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"] size:_CGSizeMake(CANCEL_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"] size:_CGSizeMake(CANCEL_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
}
- (id)initWithFrame:(CPRect)frame
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self != nil)
{
_recentSearches = [CPArray array];
_maximumRecents = 10;
_sendsWholeSearchString = NO;
_sendsSearchStringImmediately = NO;
[self setBezeled:YES];
[self setBezelStyle:CPTextFieldRoundedBezel];
[self setBordered:YES];
[self setEditable:YES];
[self setDelegate:self];
_cancelButton = [[CPButton alloc] initWithFrame:CPMakeRect(frame.size.width - 27,(frame.size.height-22)/2,22,22)];
[self resetCancelButton];
[_cancelButton setHidden:YES];
[_cancelButton setAutoresizingMask:CPViewMinXMargin];
[self addSubview:_cancelButton];
_searchButton = [[CPButton alloc] initWithFrame:CPMakeRect(5,(frame.size.height-25)/2,25,25)];
[_searchButton setBezelStyle:CPRegularSquareBezelStyle];
[_searchButton setAutoresizingMask:CPViewMaxXMargin]
[_searchButton setBordered:NO];
[_searchButton setImageScaling:CPScaleToFit];
if (self = [super initWithFrame:frame])
{
_maximumRecents = 10;
_sendsWholeSearchString = NO;
_sendsSearchStringImmediately = NO;
_recentsAutosaveName = nil;
[self _init];
#if PLATFORM(DOM)
_cancelButton._DOMElement.style.cursor = "default";
_searchButton._DOMElement.style.cursor = "default";
_cancelButton._DOMElement.style.cursor = "default";
_searchButton._DOMElement.style.cursor = "default";
#endif
[self setSearchMenuTemplate:[self _searchMenuTemplate]];
[self addSubview:_searchButton];
}
}
return self;
}
- (id)copy
- (void)_init
{
var copy = [super copy];
[copy setCancelButton:[_cancelButton copy]];
[copy setSearchButton:[_searchButton copy]];
[copy setrecentsAutosaveName:[_recentsAutosaveName copy]];
[copy setSendsWholeSearchString:[_sendsWholeSearchString copy]];
[copy setSendsSearchStringImmediately:[_sendsSearchStringImmediately copy]];
[copy setMaximumRecents:_maximumRecents];
[copy setSearchMenutemplate:[_searchMenuTemplate copy]];
return copy;
_recentSearches = [CPArray array];
[self setBezeled:YES];
[self setBezelStyle:CPTextFieldRoundedBezel];
[self setBordered:YES];
[self setEditable:YES];
[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;
}
- (void)viewWillMoveToSuperview:(CPView)aView
{
[super viewWillMoveToSuperview:aView];
// First we remove any observer that may have been in place to avoid memory leakage.
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPControlTextDidChangeNotification object:self];
// Register the observe here if we need to.
if (aView)
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_searchFieldTextDidChange:) name:CPControlTextDidChangeNotification object:self];
}
// Managing Buttons
@@ -148,8 +142,16 @@ var CPSearchFieldSearchImage = nil,
@param button The search button.
*/
- (void)setSearchButton:(CPButton)button
{
_searchButton = button;
{
if (button != _searchButton)
{
[_searchButton removeFromSuperview];
_searchButton = button;
[_searchButton setFrame:[self searchButtonRectForBounds:[self bounds]]];
[_searchButton setAutoresizingMask:CPViewMaxXMargin];
[self addSubview:_searchButton];
}
}
/*!
@@ -167,27 +169,13 @@ var CPSearchFieldSearchImage = nil,
*/
- (void)resetSearchButton
{
var searchButtonImage,
action,
target,
button = [self searchButton];
if (_searchMenuTemplate == nil)
{
searchButtonImage = CPSearchFieldSearchImage;
action = [self action];
target = [self target];
}
else
{
searchButtonImage = CPSearchFieldFindImage;
action = @selector(_showMenu:);
target = self;
}
var button = [self searchButton],
searchButtonImage = (_searchMenuTemplate === nil) ? CPSearchFieldSearchImage : CPSearchFieldFindImage;
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImage:searchButtonImage];
[button setTarget:target];
[button setAction:action];
[button setAutoresizingMask:CPViewMaxXMargin];
}
/*!
@@ -196,7 +184,18 @@ var CPSearchFieldSearchImage = nil,
*/
- (void)setCancelButton:(CPButton)button
{
_cancelButton = button;
if (button != _cancelButton)
{
[_cancelButton removeFromSuperview];
_cancelButton = button;
[_cancelButton setFrame:[self cancelButtonRectForBounds:[self bounds]]];
[_cancelButton setAutoresizingMask:CPViewMinXMargin];
[_cancelButton setTarget:self];
[_cancelButton setAction:@selector(cancelOperation:)];
[self _updateCancelButtonVisibility];
[self addSubview:_cancelButton];
}
}
/*!
@@ -210,18 +209,18 @@ var CPSearchFieldSearchImage = nil,
/*!
Resets the cancel button to its default attributes.
This method resets the target, action, regular image, and pressed image. By default, when users click the cancel button, the delete: action message is sent up the responder chain. This method gives you a way to customize the cancel button for specific situations and then reset the button defaults without having to undo changes individually.
This method resets the target, action, regular image, and pressed image. This method gives you a way to customize the cancel button for specific situations and then reset the button defaults without having to undo changes individually.
*/
- (void)resetCancelButton
{
var button = [self cancelButton];
[button setBezelStyle:CPRegularSquareBezelStyle];
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImage:CPSearchFieldCancelImage];
[button setAlternateImage:CPSearchFieldCancelPressedImage];
[button setAutoresizingMask:CPViewMinXMargin];
[button setTarget:self];
[button setAction:@selector(_searchFieldCancel:)];
[button setAction:@selector(cancelOperation:)];
}
// Custom Layout
@@ -231,23 +230,25 @@ var CPSearchFieldSearchImage = nil,
@return The updated bounding rectangle to use for the search text field. The default value is the value passed into the rect parameter.
Subclasses can override this method to return a new bounding rectangle for the text-field object. You might use this method to provide a custom layout for the search field control.
*/
- (CPRect)searchTextRectForBounds:(CPRect)rect
- (CGRect)searchTextRectForBounds:(CGRect)rect
{
var leftOffset = 0, width = rect.size.width;
var leftOffset = 0,
width = _CGRectGetWidth(rect),
bounds = [self bounds];
if (_searchButton)
{
var searchRect = [_searchButton frame];
leftOffset = searchRect.origin.x + searchRect.size.width;
var searchBounds = [self searchButtonRectForBounds:bounds];
leftOffset = _CGRectGetMaxX(searchBounds) + 2;
}
if (_cancelButton)
{
var cancelRect = [_cancelButton frame];
width = cancelRect.origin.x - leftOffset;
var cancelRect = [self cancelButtonRectForBounds:bounds];
width = _CGRectGetMinX(cancelRect) - leftOffset;
}
return CPMakeRect(leftOffset,rect.origin.y,width,rect.size.height);
return _CGRectMake(leftOffset, _CGRectGetMinY(rect), width, _CGRectGetHeight(rect));
}
/*!
@@ -255,9 +256,9 @@ var CPSearchFieldSearchImage = nil,
@param rect The current bounding rectangle for the search button.
Subclasses can override this method to return a new bounding rectangle for the search button. You might use this method to provide a custom layout for the search field control.
*/
- (CPRect)searchButtonRectForBounds:(CPRect)rect // fix
- (CGRect)searchButtonRectForBounds:(CGRect)rect
{
return [_searchButton frame];
return _CGRectMake(5, (_CGRectGetHeight(rect) - BUTTON_DEFAULT_HEIGHT) / 2, SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT);
}
/*!
@@ -265,9 +266,9 @@ var CPSearchFieldSearchImage = nil,
@param rect The updated bounding rectangle to use for the cancel button. The default value is the value passed into the rect parameter.
Subclasses can override this method to return a new bounding rectangle for the cancel button. You might use this method to provide a custom layout for the search field control.
*/
- (CPRect)cancelButtonRectForBounds:(CPRect)rect
- (CGRect)cancelButtonRectForBounds:(CGRect)rect
{
return [_cancelButton frame];
return _CGRectMake(_CGRectGetWidth(rect) - CANCEL_BUTTON_DEFAULT_WIDTH - 5, (_CGRectGetHeight(rect) - CANCEL_BUTTON_DEFAULT_WIDTH) / 2, BUTTON_DEFAULT_HEIGHT, BUTTON_DEFAULT_HEIGHT);
}
// Managing Menu Templates
@@ -285,11 +286,12 @@ var CPSearchFieldSearchImage = nil,
@param menu The menu template to use.
The receiver looks for the tag constants described in ŇMenu tagsÓ to determine how to populate the menu with items related to recent searches. See ŇConfiguring a Search MenuÓ for a sample of how you might set up the search menu template.
*/
- (void)setSearchMenuTemplate:(CPMenu)menu
- (void)setSearchMenuTemplate:(CPMenu)aMenu
{
_searchMenuTemplate = menu;
_searchMenuTemplate = aMenu;
[self resetSearchButton];
[self _loadRecentSearchList];
[self _updateSearchMenu];
}
@@ -299,8 +301,8 @@ var CPSearchFieldSearchImage = nil,
@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;
}
/*!
@@ -317,8 +319,8 @@ var CPSearchFieldSearchImage = nil,
@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;
}
/*!
@@ -336,7 +338,7 @@ var CPSearchFieldSearchImage = nil,
@return The maximum number of search strings that can appear in the menu. This value is between 0 and 254.
*/
- (int)maximumRecents
{
{
return _maximumRecents;
}
@@ -350,13 +352,13 @@ var CPSearchFieldSearchImage = nil,
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
{
@@ -370,10 +372,10 @@ var CPSearchFieldSearchImage = nil,
*/
- (void)setRecentSearches:(CPArray)searches
{
var max = MIN([self maximumRecents],[searches count]);
var searches = [searches subarrayWithRange:CPMakeRange(0,max)];
var max = MIN([self maximumRecents], [searches count]),
searches = [searches subarrayWithRange:CPMakeRange(0, max)];
_recentSearches = searches;
[self _autosaveRecentSearchList];
}
@@ -383,7 +385,7 @@ var CPSearchFieldSearchImage = nil,
*/
- (CPString)recentsAutosaveName
{
return _recentsAutosaveName;
return _recentsAutosaveName;
}
/*!
@@ -392,25 +394,26 @@ var CPSearchFieldSearchImage = nil,
*/
- (void)setRecentsAutosaveName:(CPString)name
{
if (_recentsAutosaveName != nil)
[self _deregisterForAutosaveNotification];
_recentsAutosaveName = name;
if(name != nil)
if (_recentsAutosaveName != nil)
[self _registerForAutosaveNotification];
else
[self _deregisterForAutosaveNotification];
}
// Private methods and subclassing
- (CPRect)contentRectForBounds:(CPRect)bounds
- (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
@@ -425,177 +428,285 @@ var CPSearchFieldSearchImage = nil,
- (void)_updateCancelButtonVisibility
{
[_cancelButton setHidden:([[self stringValue] length] == 0)];
[_cancelButton setHidden:([[self stringValue] length] === 0)];
}
- (void)controlTextDidChange:(CPNotification)aNotification
- (void)_searchFieldTextDidChange:(CPNotification)aNotification
{
if(!_sendsWholeSearchString)
if (![self sendsWholeSearchString])
{
if(_sendsSearchStringImmediately)
if ([self sendsSearchStringImmediately])
[self _sendPartialString];
else
{
[_partialStringTimer invalidate];
var timeInterval = [CPSearchField _keyboardDelayForPartialSearchString:[self stringValue]];
_partialStringTimer = [CPTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(_sendPartialString) userInfo:nil repeats:NO];
_partialStringTimer = [CPTimer scheduledTimerWithTimeInterval:timeInterval
target:self
selector:@selector(_sendPartialString)
userInfo:nil
repeats:NO];
}
}
[self _updateCancelButtonVisibility];
}
- (void)_sendAction:(id)sender
{
[self sendAction:[self action] to:[self target]];
}
- (void)sendAction:(SEL)anAction to:(id)anObject
{
[super sendAction:anAction to:anObject];
[_partialStringTimer invalidate];
var current_value = [self objectValue];
if(current_value != nil && current_value != "" && ![_recentSearches containsObject:current_value])
{
[self _addStringToRecentSearches:current_value];
[self _updateSearchMenu];
}
[self _addStringToRecentSearches:[self stringValue]];
[self _updateCancelButtonVisibility];
}
- (void)_addStringToRecentSearches:(CPString)string
{
var newSearches = [CPMutableArray arrayWithArray:_recentSearches];
[newSearches addObject:string];
[self setRecentSearches:newSearches];
if (string === nil || string === @"" || [_recentSearches containsObject:string])
return;
var searches = [CPMutableArray arrayWithArray:_recentSearches];
[searches addObject:string];
[self setRecentSearches:searches];
[self _updateSearchMenu];
}
- (BOOL)trackMouse:(CPEvent)event
- (CPView)hitTest:(CGPoint)aPoint
{
var rect;
var point;
var location = [event locationInWindow];
point = [self convertPoint:location fromView:nil];
rect = [self searchButtonRectForBounds:[self frame]];
if (CPRectContainsPoint(rect,point))
{
return [[self searchButton] trackMouse:event];
}
rect = [self cancelButtonRectForBounds:[self frame]];
if (CPRectContainsPoint(rect,point))
{
return [[self cancelButton] trackMouse:event];
}
return [super trackMouse:event];
// Make sure a hit anywhere within the search field returns the search field itself
if (_CGRectContainsPoint([self frame], aPoint))
return self;
else
return nil;
}
- (CPMenu)_searchMenuTemplate
- (BOOL)resignFirstResponder
{
var template, item;
template = [[CPMenu alloc] init];
item = [[CPMenuItem alloc] initWithTitle:@"Recent searches" action:NULL keyEquivalent:@""];
return _canResignFirstResponder && [super resignFirstResponder];
}
- (void)mouseDown:(CPEvent)anEvent
{
var location = [anEvent locationInWindow],
point = [self convertPoint:location fromView:nil];
if (_CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point))
{
if (_searchMenuTemplate == nil)
[self _sendAction:self];
else
[self _showMenu];
}
else if (_CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point))
[_cancelButton mouseDown:anEvent];
else
[super mouseDown:anEvent];
}
/*!
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:)
keyEquivalent:@""];
[item setTag:700];
[item setTarget:self];
[template addItem:item];
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],
item;
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:) keyEquivalent:@""];
item = [[CPMenuItem alloc] initWithTitle:@"Recent search item"
action:@selector(_searchFieldSearch:)
keyEquivalent:@""];
[item setTag:CPSearchFieldRecentsMenuItemTag];
[item setTarget:self];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"Clear recent searches" action:@selector(_searchFieldClearRecents:) keyEquivalent:@""];
item = [[CPMenuItem alloc] initWithTitle:@"Clear Recent Searches"
action:@selector(_searchFieldClearRecents:)
keyEquivalent:@""];
[item setTag:CPSearchFieldClearRecentsMenuItemTag];
[item setTarget:self];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"No recent searches" action:NULL keyEquivalent:@""];
item = [[CPMenuItem alloc] initWithTitle:@"No Recent Searches"
action:nil
keyEquivalent:@""];
[item setTag:CPSearchFieldNoRecentsMenuItemTag];
[item setEnabled:NO];
[template addItem:item];
return template;
}
- (void)_updateSearchMenu
{
if(_searchMenuTemplate == nil)
if (_searchMenuTemplate === nil)
return;
var i, menu = [[CPMenu alloc] init];
var countOfRecents = [_recentSearches count];
for (i = 0; i < [_searchMenuTemplate numberOfItems]; i++)
var menu = [[CPMenu alloc] init],
countOfRecents = [_recentSearches count],
numberOfItems = [_searchMenuTemplate numberOfItems];
for (var i = 0; i < numberOfItems; i++)
{
var item = [_searchMenuTemplate itemAtIndex:i];
var tag = [item tag];
if(tag == CPSearchFieldClearRecentsMenuItemTag && countOfRecents != 0)
var item = [[_searchMenuTemplate itemAtIndex:i] copy];
switch ([item tag])
{
var separator = [CPMenuItem separatorItem];
[menu addItem:separator];
}
if (!(tag == CPSearchFieldRecentsTitleMenuItemTag && countOfRecents == 0) &&
!(tag == CPSearchFieldClearRecentsMenuItemTag && countOfRecents == 0) &&
!(tag == CPSearchFieldNoRecentsMenuItemTag && countOfRecents != 0) &&
!(tag == CPSearchFieldRecentsMenuItemTag))
{
var templateItem = [[CPMenuItem alloc] initWithTitle:[item title] action:[item action] keyEquivalent:[item keyEquivalent]];
[templateItem setTarget:[item target]];
[templateItem setEnabled:[item isEnabled]];
[templateItem setTag:[item tag]];
[menu addItem:templateItem];
}
else if (tag == CPSearchFieldRecentsMenuItemTag)
{
var j;
for (j = 0; j < countOfRecents; j++)
case CPSearchFieldRecentsTitleMenuItemTag:
if (countOfRecents === 0)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
break;
case CPSearchFieldRecentsMenuItemTag:
{
var rencentItem = [[CPMenuItem alloc] initWithTitle:[_recentSearches objectAtIndex:j] action:[item action] keyEquivalent:[item keyEquivalent]];
[rencentItem setTarget:[item target]];
[menu addItem:rencentItem];
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
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;
}
[item setEnabled:([item isEnabled] && [item action] != nil && [item target] != nil)];
[menu addItem:item];
}
[menu setDelegate:self];
_searchMenu = menu;
}
- (void)_showMenu:(id)sender
- (void)_addSeparatorToMenu:(CPMenu)aMenu
{
if(_searchMenu == nil || ![self isEnabled])
var separator = [CPMenuItem separatorItem];
[separator setEnabled:NO];
[aMenu addItem:separator];
}
- (void)menuWillOpen:(CPMenu)menu
{
_canResignFirstResponder = NO;
}
- (void)menuDidClose:(CPMenu)menu
{
_canResignFirstResponder = YES;
[self becomeFirstResponder];
}
- (void)_showMenu
{
if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled])
return;
[super selectText:nil];
var origin = CPMakePoint([self frame].origin.x, [self frame].origin.y + [self frame].size.height);
var anEvent = [CPEvent keyEventWithType:CPRightMouseDown location:origin modifierFlags:0 timestamp:[CPDate date] windowNumber:1 context:[[CPGraphicsContext currentContext] graphicsPort] characters:"" charactersIgnoringModifiers:"" isARepeat:NO keyCode:0];
[CPMenu popUpContextMenu:_searchMenu withEvent:anEvent forView:sender];
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];
}
- (void)_sendPartialString
{
[[self target] performSelector:[self action] withObject:self];
[super sendAction:[self action] to:[self target]];
[_partialStringTimer invalidate];
}
- (void)_searchFieldCancel:(id)sender
{
[self setObjectValue:nil];
[self _sendPartialString];
- (void)cancelOperation:(id)sender
{
[self setObjectValue:@""];
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
[self _updateCancelButtonVisibility];
[sender setHidden:YES];
}
- (void)_searchFieldSearch:(id)sender
{
[self setObjectValue:[sender title]];
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];
}
@@ -603,104 +714,95 @@ var CPSearchFieldSearchImage = nil,
{
[self setRecentSearches:[CPArray array]];
[self _updateSearchMenu];
[self setStringValue:@""];
[self _updateCancelButtonVisibility];
}
- (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];
}
- (void)_updateAutosavedRecents:(id)notification
{
var name = [notification object];
var list = [self recentSearches];
[[CPUserDefaults standardUserDefaults] setObject:list forKey:name];
}
- (void)_autosaveRecentSearchList
{
if(_recentsAutosaveName != nil)
[[CPNotificationCenter defaultCenter] postNotificationName:@"CPAutosavedRecentsChangedNotification" object:_recentsAutosaveName];
[[CPUserDefaults standardUserDefaults] setObject:_recentSearches forKey:name];
}
- (void)_loadRecentSearchList
{
var list,
name = [self recentsAutosaveName];
list = [[CPUserDefaults standardUserDefaults] objectForKey:name];
_recentSearches = list;
}
var name = [self recentsAutosaveName];
if (name === nil)
return;
/*
- (BOOL)trackMouse:(CPEvent)theEvent inRect:(CPRect)cellFrame ofView:(CPView)aTextView untilMouseUp:(BOOL)flag
{
}
var list = [[CPUserDefaults standardUserDefaults] objectForKey:name];
- (BOOL)_trimRecentSearchList
{
if (list !== nil)
_recentSearches = list;
}
- (void)_trackButton:(CPButton)button forEvent:(CPEvent)event inRect:(CPRect)rect ofView:(id)view
{
}
- (id)_selectOrEdit:(CPRect)rect inView:(id)view target:(id)target editor:(id)editor event:(id)event start:(int)start end:(int)end
{
}
- (void)resetCursorRect:(CPRect)rect inView:(id)view
{
}
*/
@end
var CPSearchButtonKey = @"CPSearchButtonKey",
CPCancelButtonKey = @"CPCancelButtonKey",
CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey",
CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey",
CPMaximumRecentsKey = @"CPMaximumRecentsKey",
CPSearchMenuTemplateKey = @"CPSearchMenuTemplateKey";
CPSearchMenuTemplateKey = @"CPSearchMenuTemplateKey";
@implementation CPSearchField (CPCoding)
- (void)encodeWithCoder:(CPCoder)coder
{
[_searchButton removeFromSuperview];
[_cancelButton removeFromSuperview];
[super encodeWithCoder:coder];
[coder encodeObject:_searchButton forKey:CPSearchButtonKey];
[coder encodeObject:_cancelButton forKey:CPCancelButtonKey];
[coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey];
if (_searchButton)
[self addSubview:_searchButton];
if (_cancelButton)
[self addSubview:_cancelButton];
[coder encodeBool:_sendsWholeSearchString forKey:CPSendsWholeSearchStringKey];
[coder encodeBool:_sendsSearchStringImmediately forKey:CPSendsSearchStringImmediatelyKey];
[coder encodeInt:_maximumRecents forKey:CPMaximumRecentsKey];
[coder encodeObject:_searchMenuTemplate forKey:CPSearchMenuTemplateKey];
if (_recentsAutosaveName)
[coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey];
if (_searchMenuTemplate)
[coder encodeObject:_searchMenuTemplate forKey:CPSearchMenuTemplateKey];
}
- (id)initWithCoder:(CPCoder)coder
{
self = [super initWithCoder:coder];
_searchButton = [coder decodeObjectForKey:CPSearchButtonKey];
_cancelButton = [coder decodeObjectForKey:CPCancelButtonKey];
_recentsAutosaveName = [coder decodeObjectForKey:CPRecentsAutosaveNameKey];
_sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey];
_sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey];
_maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey];
[self setSearchMenuTemplate:[coder decodeObjectForKey:CPSearchMenuTemplateKey]];
[self resetCancelButton];
[self setDelegate:self];
if (self = [super initWithCoder:coder])
{
[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];
}
return self;
}
@end
@end
+22
View File
@@ -1,6 +1,28 @@
/*
* CPSecureTextField.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPTextField.j"
/*!
@ingroup appkit
*/
+185 -168
View File
@@ -24,25 +24,12 @@
@import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
/*
@global
@group CPSegmentSwitchTracking
*/
CPSegmentSwitchTrackingSelectOne = 0;
/*
@global
@group CPSegmentSwitchTracking
*/
CPSegmentSwitchTrackingSelectAny = 1;
/*
@global
@group CPSegmentSwitchTracking
*/
CPSegmentSwitchTrackingMomentary = 2;
/*!
/*!
@ingroup appkit
@class CPSegmentedControl
@@ -61,14 +48,14 @@ CPSegmentSwitchTrackingMomentary = 2;
BOOL _trackingHighlighted;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return "segmented-control";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[CPCenterTextAlignment, CPCenterVerticalTextAlignment, CPImageLeft, CPScaleNone, _CGInsetMakeZero(), _CGInsetMakeZero(), nil, nil, nil, nil, 1.0, 24.0]
return [CPDictionary dictionaryWithObjects:[CPCenterTextAlignment, CPCenterVerticalTextAlignment, CPImageLeft, CPScaleNone, _CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], [CPNull null], 1.0, 24.0]
forKeys:[@"alignment", @"vertical-alignment", @"image-position", @"image-scaling", @"bezel-inset", @"content-inset", @"left-segment-bezel-color", @"right-segment-bezel-color", @"center-segment-bezel-color", @"divider-bezel-color", @"divider-thickness", @"default-height"]];
}
@@ -76,16 +63,16 @@ CPSegmentSwitchTrackingMomentary = 2;
{
_segments = [];
_themeStates = [];
self = [super initWithFrame:aRect];
if (self)
{
_selectedSegment = -1;
_trackingMode = CPSegmentSwitchTrackingSelectOne;
}
return self;
}
@@ -94,7 +81,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (int)selectedTag
{
return _segments[_selectedSegment].tag;
return [_segments[_selectedSegment] tag];
}
// Specifying the number of segments
@@ -106,11 +93,13 @@ 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)
{
{
for (var index = _segments.length; index < aCount; ++index)
{
_segments[index] = [[_CPSegmentItem alloc] init];
@@ -126,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];
}
@@ -163,15 +160,15 @@ CPSegmentSwitchTrackingMomentary = 2;
- (BOOL)selectSegmentWithTag:(int)aTag
{
var index = 0;
for (; index < _segments.length; ++index)
if (_segments[index].tag == aTag)
{
[self setSelectedSegment:index];
return YES;
}
return NO;
}
@@ -186,28 +183,28 @@ CPSegmentSwitchTrackingMomentary = 2;
{
if (_trackingMode == aTrackingMode)
return;
_trackingMode = aTrackingMode;
if (_trackingMode == CPSegmentSwitchTrackingSelectOne)
{
var index = 0,
selected = NO;
for (; index < _segments.length; ++index)
if (_segments[index].selected)
if ([_segments[index] selected])
if (selected)
[self setSelected:NO forSegment:index];
else
selected = YES;
}
else if (_trackingMode == CPSegmentSwitchTrackingMomentary)
{
var index = 0;
for (; index < _segments.length; ++index)
if (_segments[index].selected)
if ([_segments[index] selected])
[self setSelected:NO forSegment:index];
}
}
@@ -229,8 +226,8 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setWidth:(float)aWidth forSegment:(unsigned)aSegment
{
_segments[aSegment].width = aWidth;
[_segments[aSegment] setWidth:aWidth];
[self tileWithChangedSegment:aSegment];
}
@@ -241,7 +238,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (float)widthForSegment:(unsigned)aSegment
{
return _segments[aSegment].width;
return [_segments[aSegment] width];
}
/*!
@@ -252,9 +249,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setImage:(CPImage)anImage forSegment:(unsigned)aSegment
{
var segment = _segments[aSegment];
segment.image = anImage;
[_segments[aSegment] setImage:anImage];
[self tileWithChangedSegment:aSegment];
}
@@ -266,7 +261,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (CPImage)imageForSegment:(unsigned)aSegment
{
return _segments[aSegment].image;
return [_segments[aSegment] image];
}
/*!
@@ -277,10 +272,8 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setLabel:(CPString)aLabel forSegment:(unsigned)aSegment
{
var segment = _segments[aSegment];
_segments[aSegment].label = aLabel;
[_segments[aSegment] setLabel:aLabel];
[self tileWithChangedSegment:aSegment];
}
@@ -291,7 +284,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (CPString)labelForSegment:(unsigned)aSegment
{
return _segments[aSegment].label;
return [_segments[aSegment] label];
}
/*!
@@ -302,7 +295,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setMenu:(CPMenu)aMenu forSegment:(unsigned)aSegment
{
_segments[aSegment].menu = aMenu;
[_segments[aSegment] setMenu:aMenu];
}
/*!
@@ -312,7 +305,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (CPMenu)menuForSegment:(unsigned)aSegment
{
return _segments[aSegment].menu;
return [_segments[aSegment] menu];
}
/*!
@@ -325,12 +318,12 @@ CPSegmentSwitchTrackingMomentary = 2;
- (void)setSelected:(BOOL)isSelected forSegment:(unsigned)aSegment
{
var segment = _segments[aSegment];
// If we're already in this state, bail.
if (segment.selected == isSelected)
if ([segment selected] == isSelected)
return;
segment.selected = isSelected;
[segment setSelected:isSelected];
_themeStates[aSegment] = isSelected ? CPThemeStateSelected : CPThemeStateNormal;
@@ -338,18 +331,18 @@ CPSegmentSwitchTrackingMomentary = 2;
if (isSelected)
{
var oldSelectedSegment = _selectedSegment;
_selectedSegment = aSegment;
if (_trackingMode == CPSegmentSwitchTrackingSelectOne && oldSelectedSegment != aSegment && oldSelectedSegment != -1)
{
_segments[oldSelectedSegment].selected = NO;
[_segments[oldSelectedSegment] setSelected:NO];
_themeStates[oldSelectedSegment] = CPThemeStateNormal;
[self drawSegmentBezel:oldSelectedSegment highlight:NO];
}
}
if (_trackingMode != CPSegmentSwitchTrackingMomentary)
[self drawSegmentBezel:aSegment highlight:NO];
@@ -364,18 +357,23 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (BOOL)isSelectedForSegment:(unsigned)aSegment
{
return _segments[aSegment].selected;
return [_segments[aSegment] selected];
}
/*!
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
{
_segments[aSegment].enabled = isEnabled;
[_segments[aSegment] setEnabled:isEnabled];
if (isEnabled)
_themeStates[aSegment] &= ~CPThemeStateDisabled;
else
_themeStates[aSegment] |= CPThemeStateDisabled;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
@@ -388,7 +386,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (BOOL)isEnabledForSegment:(unsigned)aSegment
{
return _segments[aSegment].enabled;
return [_segments[aSegment] enabled];
}
/*!
@@ -398,7 +396,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setTag:(int)aTag forSegment:(unsigned)aSegment
{
_segments[aSegment].tag = aTag;
[_segments[aSegment] setTag:aTag];
}
/*!
@@ -407,7 +405,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (int)tagForSegment:(unsigned)aSegment
{
return _segments[aSegment].tag;
return [_segments[aSegment] tag];
}
// Drawings
@@ -462,30 +460,28 @@ CPSegmentSwitchTrackingMomentary = 2;
}
else if (aName === "right-segment-bezel")
{
var lastSegmentLeftOffset = [self _leftOffsetForSegment:[self _indexOfLastSegment]];
return CPRectMake(lastSegmentLeftOffset + [self widthForSegment:[self _indexOfLastSegment]] - contentInset.right,
return CPRectMake(CGRectGetWidth([self bounds]) - contentInset.right,
bezelInset.top,
contentInset.right,
height);
}
else if (aName.substring(0, "segment-bezel".length) == "segment-bezel")
else if (aName.indexOf("segment-bezel") === 0)
{
var segment = parseInt(aName.substring("segment-bezel-".length), 10),
frame = CGRectCreateCopy(_segments[segment].frame);
frame = CGRectCreateCopy([_segments[segment] frame]);
if (segment == 0)
if (segment === 0)
{
frame.origin.x += contentInset.left;
frame.size.width -= contentInset.left;
}
if (segment == _segments.length - 1)
frame.size.width -= contentInset.right;
if (segment === _segments.length - 1)
frame.size.width = CGRectGetWidth([self bounds]) - contentInset.right - frame.origin.x;
return frame;
}
else if (aName.substring(0, "divider-bezel".length) == "divider-bezel")
else if (aName.indexOf("divider-bezel") === 0)
{
var segment = parseInt(aName.substring("divider-bezel-".length), 10),
width = [self widthForSegment:segment],
@@ -494,7 +490,7 @@ CPSegmentSwitchTrackingMomentary = 2;
return CGRectMake(left + width, bezelInset.top, thickness, height);
}
else if (aName.substring(0, "segment-content".length) == "segment-content")
else if (aName.indexOf("segment-content") === 0)
{
var segment = parseInt(aName.substring("segment-content-".length), 10);
@@ -506,7 +502,7 @@ CPSegmentSwitchTrackingMomentary = 2;
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
if (aName.substring(0, "segment-content".length) == "segment-content")
if ([aName hasPrefix:@"segment-content"])
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
@@ -517,50 +513,56 @@ CPSegmentSwitchTrackingMomentary = 2;
if (_segments.length <= 0)
return;
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
inState:_themeStates[0]];
var themeState = _themeStates[0];
var leftBezelView = [self layoutEphemeralSubviewNamed:@"left-segment-bezel"
themeState |= _themeState & CPThemeStateDisabled;
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
inState:themeState],
leftBezelView = [self layoutEphemeralSubviewNamed:@"left-segment-bezel"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[leftBezelView setBackgroundColor:leftCapColor];
var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color"
inState:_themeStates[_themeStates.length - 1]];
var themeState = _themeStates[_themeStates.length - 1];
var rightBezelView = [self layoutEphemeralSubviewNamed:@"right-segment-bezel"
themeState |= _themeState & CPThemeStateDisabled;
var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color"
inState:themeState],
rightBezelView = [self layoutEphemeralSubviewNamed:@"right-segment-bezel"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[rightBezelView setBackgroundColor:rightCapColor];
for (var i=0, count = _themeStates.length; i<count; i++)
for (var i = 0, count = _themeStates.length; i < count; i++)
{
var themeState = _themeStates[i];
themeState |= _themeState & CPThemeStateDisabled;
var bezelColor = [self valueForThemeAttribute:@"center-segment-bezel-color"
inState:themeState];
var bezelColor = [self valueForThemeAttribute:@"center-segment-bezel-color"
inState:themeState],
var bezelView = [self layoutEphemeralSubviewNamed:"segment-bezel-"+i
positioned:CPWindowBelow
bezelView = [self layoutEphemeralSubviewNamed:"segment-bezel-" + i
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[bezelView setBackgroundColor:bezelColor];
//layout image/title views
var segment = _segments[i];
var contentView = [self layoutEphemeralSubviewNamed:@"segment-content-"+i
// layout image/title views
var segment = _segments[i],
contentView = [self layoutEphemeralSubviewNamed:@"segment-content-" + i
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"segment-bezel-"+i];
relativeToEphemeralSubviewNamed:@"segment-bezel-" + i];
[contentView setText:segment.label];
[contentView setImage:segment.image];
[contentView setText:[segment label]];
[contentView setImage:[segment image]];
[contentView setFont:[self valueForThemeAttribute:@"font" inState:themeState]];
[contentView setTextColor:[self valueForThemeAttribute:@"text-color" inState:themeState]];
@@ -569,27 +571,27 @@ CPSegmentSwitchTrackingMomentary = 2;
[contentView setLineBreakMode:[self valueForThemeAttribute:@"line-break-mode" inState:themeState]];
[contentView setTextShadowColor:[self valueForThemeAttribute:@"text-shadow-color" inState:themeState]];
[contentView setTextShadowOffset:[self valueForThemeAttribute:@"text-shadow-offset" inState:themeState]];
[contentView setImageScaling:[self valueForThemeAttribute:@"image-scaling" inState:themeState]];
if (segment.image && segment.label)
[contentView setImageScaling:[self valueForThemeAttribute:@"image-scaling" inState:themeState]];
if ([segment image] && [segment label])
[contentView setImagePosition:[self valueForThemeAttribute:@"image-position" inState:themeState]];
else if (segment.image)
else if ([segment image])
[contentView setImagePosition:CPImageOnly];
if (i == count - 1)
continue;
var borderState = _themeStates[i] | _themeStates[i+1];
var borderState = _themeStates[i] | _themeStates[i + 1];
borderState = (borderState & CPThemeStateSelected & ~CPThemeStateHighlighted) ? CPThemeStateSelected : CPThemeStateNormal;
borderState |= _themeState & CPThemeStateDisabled;
var borderColor = [self valueForThemeAttribute:@"divider-bezel-color"
inState:borderState];
inState:borderState],
var borderView = [self layoutEphemeralSubviewNamed:"divider-bezel-"+i
positioned:CPWindowBelow
borderView = [self layoutEphemeralSubviewNamed:"divider-bezel-" + i
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[borderView setBackgroundColor:borderColor];
@@ -612,48 +614,53 @@ CPSegmentSwitchTrackingMomentary = 2;
return;
var segment = _segments[aSegment],
segmentWidth = segment.width,
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)
{
if (segment.image && segment.label)
segmentWidth = [segment.label sizeWithFont:font].width + [segment.image size].width + contentInset.left + contentInset.right;
if ([segment image] && [segment label])
segmentWidth = [[segment label] sizeWithFont:font].width + [[segment image] size].width + contentInset.left + contentInset.right;
else if (segment.image)
segmentWidth = [segment.image size].width + contentInset.left + contentInset.right;
segmentWidth = [[segment image] size].width + contentInset.left + contentInset.right;
else if (segment.label)
segmentWidth = [segment.label sizeWithFont:font].width + contentInset.left + contentInset.right;
segmentWidth = [[segment label] sizeWithFont:font].width + contentInset.left + contentInset.right;
else
segmentWidth = 0.0;
}
var delta = segmentWidth - CGRectGetWidth(segment.frame);
var delta = segmentWidth - CGRectGetWidth([segment frame]);
if (!delta)
return;
{
[self setNeedsLayout];
[self setNeedsDisplay:YES];
// Update Contorl Size
return;
}
// Update control size
var frame = [self frame];
[self setFrameSize:CGSizeMake(CGRectGetWidth(frame) + delta, CGRectGetHeight(frame))];
// Update Segment Width
segment.width = segmentWidth;
segment.frame = [self frameForSegment:aSegment];;
// Update segment width
[segment setWidth:segmentWidth];
[segment setFrame:[self frameForSegment:aSegment]];
// Update Following Segments Widths
// Update following segments widths
var index = aSegment + 1;
for (; index < _segments.length; ++index)
{
_segments[index].frame.origin.x += delta;
[_segments[index] frame].origin.x += delta;
[self drawSegmentBezel:index highlight:NO];
[self drawSegment:index highlight:NO];
}
[self drawSegmentBezel:aSegment highlight:NO];
[self drawSegment:aSegment highlight:NO];
@@ -699,11 +706,20 @@ CPSegmentSwitchTrackingMomentary = 2;
{
var location = [self convertPoint:aPoint fromView:nil],
count = _segments.length;
while (count--)
if (CGRectContainsPoint(_segments[count].frame, aPoint))
if (CGRectContainsPoint([_segments[count] frame], aPoint))
return count;
if (_segments.length)
{
var adjustedLastFrame = CGRectCreateCopy([_segments[_segments.length - 1] frame]);
adjustedLastFrame.size.width = CGRectGetWidth([self bounds]) - adjustedLastFrame.origin.x;
if (CGRectContainsPoint(adjustedLastFrame, aPoint))
return _segments.length - 1;
}
return -1;
}
@@ -711,7 +727,7 @@ CPSegmentSwitchTrackingMomentary = 2;
{
if (![self isEnabled])
return;
[self trackSegment:anEvent];
}
@@ -725,74 +741,76 @@ CPSegmentSwitchTrackingMomentary = 2;
@param anEvent the event to handle
*/
- (void)trackSegment:(CPEvent)anEvent
{
{
var type = [anEvent type],
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if (type == CPLeftMouseUp)
{
if (_trackingSegment == -1)
return;
if (CGRectContainsPoint(_segments[_trackingSegment].frame, location))
if (_trackingSegment === [self testSegment:location])
{
if (_trackingMode == CPSegmentSwitchTrackingSelectAny)
{
[self setSelected:![self isSelectedForSegment:_trackingSegment] forSegment:_trackingSegment];
// With ANY, _selectedSegment means last pressed.
_selectedSegment = _trackingSegment;
}
else
[self setSelected:YES forSegment:_trackingSegment];
[self sendAction:[self action] to:[self target]];
if (_trackingMode == CPSegmentSwitchTrackingMomentary)
{
[self setSelected:NO forSegment:_trackingSegment];
_selectedSegment = -1;
}
}
[self drawSegmentBezel:_trackingSegment highlight:NO];
_trackingSegment = -1;
return;
}
if (type == CPLeftMouseDown)
{
_trackingHighlighted = YES;
_trackingSegment = [self testSegment:location];
[self drawSegmentBezel:_trackingSegment highlight:YES];
var trackingSegment = [self testSegment:location];
if (trackingSegment > -1 && [self isEnabledForSegment:trackingSegment])
{
_trackingHighlighted = YES;
_trackingSegment = trackingSegment;
[self drawSegmentBezel:_trackingSegment highlight:YES];
}
}
else if (type == CPLeftMouseDragged)
{
if (_trackingSegment == -1)
return;
var highlighted = CGRectContainsPoint(_segments[_trackingSegment].frame, location);
var highlighted = [self testSegment:location] === _trackingSegment;
if (highlighted != _trackingHighlighted)
{
_trackingHighlighted = highlighted;
[self drawSegmentBezel:_trackingSegment highlight:_trackingHighlighted];
}
}
[CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (void)setFont:(CPFont)aFont
{
[super setFont:aFont];
[self tileWithChangedSegment:0];
}
@@ -808,12 +826,12 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
var frame = [self frame],
originalWidth = frame.size.width;
frame.size.width = 0;
[self setFrame:frame];
@@ -824,38 +842,38 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
if ([aCoder containsValueForKey:CPSegmentedControlSelectedKey])
_selectedSegment = [aCoder decodeIntForKey:CPSegmentedControlSelectedKey];
else
else
_selectedSegment = -1;
if ([aCoder containsValueForKey:CPSegmentedControlTrackingModeKey])
_trackingMode = [aCoder decodeIntForKey:CPSegmentedControlTrackingModeKey];
else
_trackingMode = CPSegmentSwitchTrackingSelectOne;
// HACK
for (var i = 0; i < _segments.length; i++)
{
_themeStates[i] = _segments[i].selected ? CPThemeStateSelected : CPThemeStateNormal;
_themeStates[i] = [_segments[i] selected] ? CPThemeStateSelected : CPThemeStateNormal;
[self tileWithChangedSegment:i];
}
var difference = MAX(originalWidth - [self frame].size.width, 0.0),
remainingWidth = FLOOR(difference / _segments.length);
for (var i=0; i < _segments.length; i++)
[self setWidth:_segments[i].width + remainingWidth forSegment:i];
for (var i = 0; i < _segments.length; i++)
[self setWidth:[_segments[i] width] + remainingWidth forSegment:i];
[self tileWithChangedSegment:0];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_segments forKey:CPSegmentedControlSegmentsKey];
[aCoder encodeInt:_selectedSegment forKey:CPSegmentedControlSelectedKey];
[aCoder encodeInt:_segmentStyle forKey:CPSegmentedControlSegmentStyleKey];
@@ -867,15 +885,15 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
@implementation _CPSegmentItem : CPObject
{
CPImage image;
CPString label;
CPMenu menu;
BOOL selected;
BOOL enabled;
int tag;
int width;
CPImage image @accessors;
CPString label @accessors;
CPMenu menu @accessors;
BOOL selected @accessors;
BOOL enabled @accessors;
int tag @accessors;
int width @accessors;
CGRect frame;
CGRect frame @accessors;
}
- (id)init
@@ -886,8 +904,8 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
label = @"";
menu = nil;
selected = NO;
enabled = NO;
tag = 0;
enabled = YES;
tag = -1;
width = 0;
frame = CGRectMakeZero();
@@ -910,7 +928,7 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
image = [aCoder decodeObjectForKey:CPSegmentItemImageKey];
@@ -923,7 +941,7 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
frame = CGRectMakeZero();
}
return self;
}
@@ -939,4 +957,3 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
}
@end
+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;
}
+41 -18
View File
@@ -28,19 +28,17 @@
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
CPLightShadow = 0;
CPHeavyShadow = 1;
var CPShadowViewLightBackgroundColor = nil,
CPShadowViewHeavyBackgroundColor = nil;
var LIGHT_LEFT_INSET = 3.0,
LIGHT_RIGHT_INSET = 3.0,
LIGHT_TOP_INSET = 3.0,
LIGHT_BOTTOM_INSET = 5.0,
HEAVY_LEFT_INSET = 7.0,
HEAVY_RIGHT_INSET = 7.0,
HEAVY_TOP_INSET = 5.0,
@@ -61,51 +59,76 @@ var LIGHT_LEFT_INSET = 3.0,
return;
var bundle = [CPBundle bundleForClass:[self class]];
CPShadowViewLightBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTopLeft.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTop.png"] size:CGSizeMake(1.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTopRight.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightLeft.png"] size:CGSizeMake(9.0, 1.0)],
nil,
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightRight.png"] size:CGSizeMake(9.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomLeft.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottom.png"] size:CGSizeMake(1.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomRight.png"] size:CGSizeMake(9.0, 9.0)]
]]];
CPShadowViewHeavyBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTopLeft.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTop.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTopRight.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyLeft.png"] size:CGSizeMake(17.0, 1.0)],
nil,
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyRight.png"] size:CGSizeMake(17.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomLeft.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottom.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomRight.png"] size:CGSizeMake(17.0, 17.0)]
]]];
}
+ (id)shadowViewEnclosingView:(CPView)aView
{
return [self shadowViewEnclosingView:aView withWeight:CPLightShadow];
}
+ (id)shadowViewEnclosingView:(CPView)aView withWeight:(CPShadowWeight)aWeight
{
var shadowView = [[CPShadowView alloc] initWithFrame:[aView frame]];
[shadowView setWeight:aWeight];
var size = [shadowView frame].size,
width = size.width - [shadowView leftInset] - [shadowView rightInset],
height = size.height - [shadowView topInset] - [shadowView bottomInset],
enclosingView = [aView superview];
[shadowView setHitTests:[aView hitTests]];
[shadowView setAutoresizingMask:[aView autoresizingMask]];
[aView removeFromSuperview];
[shadowView addSubview:aView];
[aView setFrame:CGRectMake([shadowView leftInset], [shadowView topInset], width, height)]
[enclosingView addSubview:shadowView];
return shadowView;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_weight = CPLightShadow;
[self setBackgroundColor:CPShadowViewLightBackgroundColor];
[self setHitTests:NO];
}
return self;
}
@@ -113,9 +136,9 @@ var LIGHT_LEFT_INSET = 3.0,
{
if (_weight == aWeight)
return;
_weight = aWeight;
if (_weight == CPLightShadow)
[self setBackgroundColor:CPShadowViewLightBackgroundColor];
@@ -147,7 +170,7 @@ var LIGHT_LEFT_INSET = 3.0,
{
if (_weight == CPLightShadow)
return LIGHT_LEFT_INSET + LIGHT_RIGHT_INSET;
return HEAVY_LEFT_INSET + HEAVY_RIGHT_INSET;
}
@@ -155,7 +178,7 @@ var LIGHT_LEFT_INSET = 3.0,
{
if (_weight == CPLightShadow)
return LIGHT_TOP_INSET + LIGHT_BOTTOM_INSET;
return HEAVY_TOP_INSET + HEAVY_BOTTOM_INSET;
}
+57 -44
View File
@@ -22,7 +22,6 @@
@import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
/*! SLIDER STATES */
@@ -42,14 +41,14 @@ CPCircularSlider = 1;
BOOL _isVertical;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return "slider";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[nil, _CGSizeMakeZero(), 0.0, nil]
return [CPDictionary dictionaryWithObjects:[[CPNull null], _CGSizeMakeZero(), 0.0, [CPNull null]]
forKeys:[@"knob-color", @"knob-size", @"track-width", @"track-color"]];
}
@@ -61,14 +60,14 @@ CPCircularSlider = 1;
{
_minValue = 0.0;
_maxValue = 100.0;
[self setObjectValue:50.0];
[self setContinuous:YES];
[self _recalculateIsVertical];
}
return self;
}
@@ -76,11 +75,11 @@ CPCircularSlider = 1;
{
if (_minValue === aMinimumValue)
return;
_minValue = aMinimumValue;
var doubleValue = [self doubleValue];
if (doubleValue < _minValue)
[self setDoubleValue:_minValue];
@@ -98,11 +97,11 @@ CPCircularSlider = 1;
{
if (_maxValue === aMaximumValue)
return;
_maxValue = aMaximumValue;
var doubleValue = [self doubleValue];
if (doubleValue > _maxValue)
[self setDoubleValue:_maxValue];
@@ -169,27 +168,27 @@ CPCircularSlider = 1;
bounds.size.height = trackWidth;
}
}
return bounds;
}
- (CGRect)knobRectForBounds:(CGRect)bounds
{
var knobSize = [self currentValueForThemeAttribute:@"knob-size"];
if (knobSize.width <= 0 || knobSize.height <= 0)
return _CGRectMakeZero();
var knobRect = _CGRectMake(0.0, 0.0, knobSize.width, knobSize.height),
trackRect = [self trackRectForBounds:bounds];
// No track, do our best to approximate a place for this thing.
if (!trackRect || _CGRectIsEmpty(trackRect))
trackRect = bounds;
if ([self hasThemeState:CPThemeStateCircular])
{
var angle = 3*PI_2 - (1.0 - [self doubleValue] - _minValue) / (_maxValue - _minValue) * PI2,
var angle = 3 * PI_2 - (1.0 - [self doubleValue] - _minValue) / (_maxValue - _minValue) * PI2,
radius = CGRectGetWidth(trackRect) / 2.0 - 8.0;
knobRect.origin.x = radius * COS(angle) + CGRectGetMidX(trackRect) - 3.0;
@@ -198,7 +197,7 @@ CPCircularSlider = 1;
else if ([self isVertical])
{
knobRect.origin.x = _CGRectGetMidX(trackRect) - knobSize.width / 2.0;
knobRect.origin.y = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height);
knobRect.origin.y = ((_maxValue - [self doubleValue]) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height);
}
else
{
@@ -213,10 +212,10 @@ CPCircularSlider = 1;
{
if (aName === "track-view")
return [self trackRectForBounds:[self bounds]];
else if (aName === "knob-view")
return [self knobRectForBounds:[self bounds]];
return [super rectForEphemeralSubviewNamed:aName];
}
@@ -225,12 +224,12 @@ CPCircularSlider = 1;
if (aName === "track-view" || aName === "knob-view")
{
var view = [[CPView alloc] init];
[view setHitTests:NO];
return view;
}
return [super createEphemeralSubviewNamed:aName];
}
@@ -256,7 +255,7 @@ CPCircularSlider = 1;
var bounds = [self bounds],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
_isVertical = width < height ? 1 : (width > height ? 0 : -1);
if (_isVertical === 1)
@@ -282,7 +281,7 @@ CPCircularSlider = 1;
var knobView = [self layoutEphemeralSubviewNamed:@"knob-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"track-view"];
if (knobView)
[knobView setBackgroundColor:[self currentValueForThemeAttribute:"knob-color"]];
}
@@ -320,7 +319,7 @@ CPCircularSlider = 1;
var minValue = [self minValue];
return MAX(0.0, MIN(1.0, (aPoint.y - _CGRectGetMinY(trackRect)) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue;
return MAX(0.0, MIN(1.0, (_CGRectGetMaxY(trackRect) - aPoint.y) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue;
}
else
{
@@ -339,44 +338,43 @@ CPCircularSlider = 1;
{
var bounds = [self bounds],
knobRect = [self knobRectForBounds:_CGRectMakeCopy(bounds)];
if (_CGRectContainsPoint(knobRect, aPoint))
_dragOffset = _CGSizeMake(_CGRectGetMidX(knobRect) - aPoint.x, _CGRectGetMidY(knobRect) - aPoint.y);
else
else
{
var trackRect = [self trackRectForBounds:bounds];
if (trackRect && _CGRectContainsPoint(trackRect, aPoint))
{
_dragOffset = _CGSizeMakeZero();
[self setObjectValue:[self _valueAtPoint:aPoint]];
}
else
return NO;
}
[self setHighlighted:YES];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
return YES;
return YES;
}
- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
{
[self setObjectValue:[self _valueAtPoint:_CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
return YES;
}
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
{
[self setHighlighted:NO];
if ([_target respondsToSelector:@selector(sliderDidFinish:)])
[_target sliderDidFinish:self];
@@ -384,18 +382,35 @@ CPCircularSlider = 1;
[self setNeedsDisplay:YES];
}
- (BOOL)isContinuous
{
return (_sendActionOn & CPLeftMouseDraggedMask) !== 0;
}
/*!
@ignore
shoudl we have _continuous?
should we have _continuous?
*/
- (void)setContinuous:(BOOL)flag
{
if (flag)
_sendActionOn |= CPLeftMouseDraggedMask;
else
else
_sendActionOn &= ~CPLeftMouseDraggedMask;
}
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
{
var count = objects.length,
value = [objects[0] valueForKeyPath:aKeyPath];
[self setObjectValue:value];
while (count-- > 1)
if (value !== ([objects[count] valueForKeyPath:aKeyPath]))
return [self setFloatValue:1.0];
}
@end
var CPSliderMinValueKey = "CPSliderMinValueKey",
@@ -415,8 +430,6 @@ var CPSliderMinValueKey = "CPSliderMinValueKey",
{
_altIncrementValue = [aCoder decodeDoubleForKey:CPSliderAltIncrValueKey];
[self setContinuous:YES];
[self _recalculateIsVertical];
[self setNeedsLayout];
@@ -442,14 +455,14 @@ var CPSliderMinValueKey = "CPSliderMinValueKey",
- (id)value
{
CPLog.warn("[CPSlider value] is deprecated, use doubleValue or objectValue instead.");
return [self doubleValue];
return [self doubleValue];
}
- (void)setValue:(id)aValue
{
CPLog.warn("[CPSlider setValue:] is deprecated, use setDoubleValue: or setObjectValue: instead.");
[self setObjectValue:aValue];
}
+157 -198
View File
@@ -20,22 +20,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPView.j"
@import "CPColorPicker.j"
/*
@ignore
*/
@implementation CPSliderColorPicker : CPColorPicker
{
{
CPView _contentView;
CPSlider _redSlider;
CPSlider _greenSlider;
CPSlider _blueSlider;
CPSlider _hueSlider;
CPSlider _saturationSlider;
CPSlider _brightnessSlider;
CPTextField _rgbLabel;
CPTextField _hsbLabel;
CPTextField _redLabel;
@@ -45,251 +47,162 @@
CPTextField _saturationLabel;
CPTextField _brightnessLabel;
CPTextField _hexLabel;
DOMElement _redValue;
DOMElement _greenValue;
DOMElement _blueValue;
DOMElement _hueValue;
DOMElement _saturationValue;
DOMElement _brightnessValue;
DOMElement _hexValue;
CPTextField _hexValue;
CPTextField _hexValue;
CPTextField _redValue;
CPTextField _greenValue;
CPTextField _blueValue;
CPTextField _hueValue;
CPTextField _saturationValue;
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, 37, 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];
[_redSlider setAction: @selector(sliderChanged:)];
[_redSlider setAutoresizingMask: CPViewWidthSizable];
var updateFunction = function(aDOMEvent)
{
if(isNaN(this.value))
return;
switch(this)
{
case _redValue: [_redSlider setFloatValue:MAX(MIN(ROUND(this.value), 255) / 255.0, 0)];
//[self sliderChanged: _redSlider];
break;
case _greenValue: [_greenSlider setFloatValue:MAX(MIN(ROUND(this.value), 255) / 255.0, 0)];
//[self sliderChanged: _greenSlider];
break;
case _blueValue: [_blueSlider setFloatValue:MAX(MIN(ROUND(this.value), 255) / 255.0, 0)];
//[self sliderChanged: _blueSlider];
break;
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(this.value), 360), 0)];
//[self sliderChanged: _hueSlider];
break;
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(this.value), 100), 0)];
//[self sliderChanged: _saturationSlider];
break;
// red value input box
_redValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 30, 45, 28)];
[_redValue setAutoresizingMask: CPViewMinXMargin];
[_redValue setEditable: YES];
[_redValue setBezeled: YES];
[_redValue setDelegate: self];
[_contentView addSubview: _redValue];
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(this.value), 100), 0)];
//[self sliderChanged: _brightnessSlider];
break;
}
this.blur();
};
var keypressFunction = function(aDOMEvent)
{
aDOMEvent = aDOMEvent || window.event;
if (aDOMEvent.keyCode == 13)
{
updateFunction(aDOMEvent);
if(aDOMEvent.preventDefault)
aDOMEvent.preventDefault();
else if(aDOMEvent.stopPropagation)
aDOMEvent.stopPropagation();
}
}
//red value input box
var redValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 35, 45, 20)];
[redValue setAutoresizingMask: CPViewMinXMargin];
_redValue = document.createElement("input");
_redValue.style.width = "40px";
_redValue.style.backgroundColor = "transparent";
_redValue.style.border = "1px solid black";
_redValue.style.color = "black";
_redValue.style.position = "absolute";
_redValue.style.top = "0px";
_redValue.style.left = "0px";
_redValue.onchange = updateFunction;
redValue._DOMElement.appendChild(_redValue);
[_contentView addSubview: redValue];
_greenLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 58, 15, 20)];
_greenLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 63, 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, 61, aFrame.size.width - 70, 20)];
[_greenSlider setMaxValue: 1.0];
[_greenSlider setMinValue: 0.0];
[_greenSlider setTarget: self];
[_greenSlider setAction: @selector(sliderChanged:)];
[_greenSlider setAutoresizingMask: CPViewWidthSizable];
//green value input box
var greenValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 58, 45, 20)];
[greenValue setAutoresizingMask: CPViewMinXMargin];
// green value input box
_greenValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 56, 45, 28)];
[_greenValue setAutoresizingMask: CPViewMinXMargin];
[_greenValue setEditable: YES];
[_greenValue setBezeled: YES];
[_greenValue setDelegate: self];
[_contentView addSubview: _greenValue];
_greenValue = _redValue.cloneNode(false);
_greenValue.onchange = updateFunction;
greenValue._DOMElement.appendChild(_greenValue);
[_contentView addSubview: greenValue];
_blueLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 81, 15, 20)];
_blueLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 90, 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, 87, aFrame.size.width - 70, 20)];
[_blueSlider setMaxValue: 1.0];
[_blueSlider setMinValue: 0.0];
[_blueSlider setTarget: self];
[_blueSlider setAction: @selector(sliderChanged:)];
[_blueSlider setAutoresizingMask: CPViewWidthSizable];
//blue value input box
var blueValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 81, 45, 20)];
[blueValue setAutoresizingMask: CPViewMinXMargin];
// blue value input box
_blueValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 82, 45, 28)];
[_blueValue setAutoresizingMask: CPViewMinXMargin];
[_blueValue setEditable: YES];
[_blueValue setBezeled: YES];
[_blueValue setDelegate: self];
[_contentView addSubview: _blueValue];
_blueValue = _redValue.cloneNode(false);
_blueValue.onchange = updateFunction;
blueValue._DOMElement.appendChild(_blueValue);
[_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, 143, aFrame.size.width - 70, 20)];
[_hueSlider setMaxValue: 359.0];
[_hueSlider setMinValue: 0.0];
[_hueSlider setTarget: self];
[_hueSlider setAction: @selector(sliderChanged:)];
[_hueSlider setAutoresizingMask: CPViewWidthSizable];
//red value input box
var hueValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 145, 45, 20)];
[hueValue setAutoresizingMask: CPViewMinXMargin];
// hue value input box
_hueValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 138, 45, 28)];
[_hueValue setAutoresizingMask: CPViewMinXMargin];
[_hueValue setEditable: YES];
[_hueValue setBezeled: YES];
[_hueValue setDelegate: self];
[_contentView addSubview: _hueValue];
_hueValue = _redValue.cloneNode(false);
_hueValue.onchange = updateFunction;
hueValue._DOMElement.appendChild(_hueValue);
[_contentView addSubview: hueValue];
_saturationLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 168, 15, 20)];
_saturationLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 170, 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];
[_saturationSlider setAction: @selector(sliderChanged:)];
[_saturationSlider setAutoresizingMask: CPViewWidthSizable];
//green value input box
var saturationValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 168, 45, 20)];
[saturationValue setAutoresizingMask: CPViewMinXMargin];
// saturation value input box
_saturationValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 164, 45, 28)];
[_saturationValue setAutoresizingMask: CPViewMinXMargin];
[_saturationValue setEditable: YES];
[_saturationValue setBezeled: YES];
[_saturationValue setDelegate: self];
[_contentView addSubview: _saturationValue];
_saturationValue = _redValue.cloneNode(false);
_saturationValue.onchange = updateFunction;
saturationValue._DOMElement.appendChild(_saturationValue);
[_contentView addSubview: saturationValue];
_brightnessLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 191, 15, 20)];
_brightnessLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 196, 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, 194, aFrame.size.width - 70, 20)];
[_brightnessSlider setMaxValue: 100.0];
[_brightnessSlider setMinValue: 0.0];
[_brightnessSlider setTarget: self];
[_brightnessSlider setAction: @selector(sliderChanged:)];
[_brightnessSlider setAutoresizingMask: CPViewWidthSizable];
//blue value input box
var brightnessValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 191, 45, 20)];
[brightnessValue setAutoresizingMask: CPViewMinXMargin];
// brightness value input box
_brightnessValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 190, 45, 28)];
[_brightnessValue setAutoresizingMask: CPViewMinXMargin];
[_brightnessValue setEditable: YES];
[_brightnessValue setBezeled: YES];
[_brightnessValue setDelegate: self];
[_contentView addSubview: _brightnessValue];
_brightnessValue = _redValue.cloneNode(false);
_brightnessValue.onchange = updateFunction;
brightnessValue._DOMElement.appendChild(_brightnessValue);
[_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]];
//hex input box
_hexValue = _redValue.cloneNode(false);
_hexValue.style.top = "228px";
_hexValue.style.width = "80px";
_hexValue.style.left = "35px";
_hexValue.onkeypress = function(aDOMEvent)
{
aDOMEvent = aDOMEvent || window.event;
if (aDOMEvent.keyCode == 13)
{
var newColor = [CPColor colorWithHexString: this.value];
if(newColor)
{
[self setColor: newColor];
[[self colorPanel] setColor: newColor];
}
if(aDOMEvent.preventDefault)
aDOMEvent.preventDefault();
else if(aDOMEvent.stopPropagation)
aDOMEvent.stopPropagation();
this.blur();
}
};
_contentView._DOMElement.appendChild(_hexValue);
//hex input box
_hexValue = [[CPTextField alloc] initWithFrame: CGRectMake(32, 225, 80, 28)];
[_hexValue setEditable: YES];
[_hexValue setBezeled: YES];
[_hexValue setDelegate: self];
[_contentView addSubview: _hexValue];
[_contentView addSubview: _rgbLabel];
[_contentView addSubview: _redLabel];
[_contentView addSubview: _greenLabel];
@@ -297,7 +210,7 @@
[_contentView addSubview: _redSlider];
[_contentView addSubview: _greenSlider];
[_contentView addSubview: _blueSlider];
[_contentView addSubview: _hsbLabel];
[_contentView addSubview: _hueLabel];
[_contentView addSubview: _saturationLabel];
@@ -305,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:
@@ -341,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];
@@ -369,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]];
@@ -380,7 +293,7 @@
- (void)updateHex:(CPColor)aColor
{
_hexValue.value = [aColor hexString];
[_hexValue setStringValue:[aColor hexString]];
}
- (void)updateRGBSliders:(CPColor)aColor
@@ -394,13 +307,13 @@
- (void)updateLabels
{
_hueValue.value = ROUND([_hueSlider floatValue]);
_saturationValue.value = ROUND([_saturationSlider floatValue]);
_brightnessValue.value = ROUND([_brightnessSlider floatValue]);
_redValue.value = ROUND([_redSlider floatValue] * 255);
_greenValue.value = ROUND([_greenSlider floatValue] * 255);
_blueValue.value = ROUND([_blueSlider floatValue] * 255);
[_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)];
}
- (CPImage)provideNewButtonImage
@@ -413,4 +326,50 @@
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:CPColorPicker] pathForResource:"slider_button_h.png"] size:CGSizeMake(32, 32)];
}
- (void)controlTextDidEndEditing:(CPNotification)aNotification
{
var field = [aNotification object],
value = [[field stringValue] stringByTrimmingWhitespace];
if (field === _hexValue)
{
var newColor = [CPColor colorWithHexString: value];
if (newColor)
{
[self setColor: newColor];
[[self colorPanel] setColor: newColor];
}
}
else
{
switch (field)
{
case _redValue: [_redSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _redSlider];
break;
case _greenValue: [_greenSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _greenSlider];
break;
case _blueValue: [_blueSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _blueSlider];
break;
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(value), 360), 0)];
[self sliderChanged: _hueSlider];
break;
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
[self sliderChanged: _saturationSlider];
break;
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
[self sliderChanged: _brightnessSlider];
break;
}
}
}
@end
+303
View File
@@ -0,0 +1,303 @@
/*
* 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;
CPSoundLoadStateError = 3;
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()
{
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
[self _soundDidload];
}, true);
_audioTag.addEventListener("ended", function()
{
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
[self _soundDidEnd];
}, true);
_audioTag.addEventListener("error", function()
{
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
[self _soundError];
}, true);
}
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];
}
/*! @ignore
*/
- (void)_soundError
{
_loadStatus = CPSoundLoadStateError;
CPLog.error("Cannot load sound. Maybe the format of your sound is not compatible with your browser.");
}
#pragma mark -
#pragma mark Media controls
/*!
Play the sound.
@return YES when the receiver is playing its audio data, NO otherwise.
*/
- (BOOL)play
{
if ((_loadStatus !== CPSoundLoadStateCanBePlayed)
|| (_playBackStatus === CPSoundPlayBackStatePlay))
return NO;
_audioTag.play();
_playBackStatus = CPSoundPlayBackStatePlay;
return YES;
}
/*!
Stop the sound.
@return YES when the receiver is playing its audio data, NO otherwise.
*/
- (BOOL)stop
{
if ((_loadStatus !== CPSoundLoadStateCanBePlayed)
|| (_playBackStatus === CPSoundPlayBackStateStop))
return NO;
_audioTag.pause();
_audioTag.currentTime = 0.0;
_playBackStatus = CPSoundPlayBackStateStop;
if (_delegate && [_delegate respondsToSelector:@selector(sound:didFinishPlaying:)])
[_delegate sound:self didFinishPlaying:YES];
return YES;
}
/*!
Pause the sound.
@return YES when the receiver is playing its audio data, NO otherwise.
*/
- (BOOL)pause
{
if ((_loadStatus !== CPSoundLoadStateCanBePlayed)
|| (_playBackStatus === CPSoundPlayBackStatePause))
return NO;
_audioTag.pause();
_playBackStatus = CPSoundPlayBackStatePause;
return YES;
}
/*!
Resume playback of a paused sound.
@return YES when the receiver is playing its audio data, NO otherwise.
*/
- (BOOL)resume
{
if ((_loadStatus !== CPSoundLoadStateCanBePlayed)
|| (_playBackStatus !== CPSoundPlayBackStatePause))
return NO;
_audioTag.play();
_playBackStatus = CPSoundPlayBackStatePlay;
return YES;
}
/*!
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
+442 -120
View File
@@ -20,13 +20,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPButtonBar.j"
@import "CPImage.j"
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
#include "Platform/Platform.h"
#include "Platform/DOM/CPDOMDisplayServer.h"
CPSplitViewDidResizeSubviewsNotification = @"CPSplitViewDidResizeSubviewsNotification";
CPSplitViewWillResizeSubviewsNotification = @"CPSplitViewWillResizeSubviewsNotification";
@@ -36,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
@@ -43,18 +48,32 @@ var CPSplitViewHorizontalImage = nil,
id _delegate;
BOOL _isVertical;
BOOL _isPaneSplitter;
int _currentDivider;
float _initialOffset;
float _preCollapsePosition;
CPString _originComponent;
CPString _sizeComponent;
CPArray _DOMDividerElements;
CPString _dividerImagePath;
int _drawingDivider;
BOOL _needsResizeSubviews;
CPArray _buttonBars;
}
+ (CPString)defaultThemeClass
{
return @"splitview";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[1.0, 10.0, [CPColor grayColor]]
forKeys:[@"divider-thickness", @"pane-divider-thickness", @"pane-divider-color"]];
}
/*
@@ -75,36 +94,49 @@ var CPSplitViewHorizontalImage = nil,
if (self = [super initWithFrame:aFrame])
{
_currentDivider = CPNotFound;
_DOMDividerElements = [];
_buttonBars = [];
[self _setVertical:YES];
}
return self;
}
/*!
Returns the thickness of the divider.
@return float - the thickness of the divider.
*/
- (float)dividerThickness
{
return _isPaneSplitter ? 1.0 : 10.0;
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])
return;
// Just re-adjust evenly.
var frame = [self frame],
dividerThickness = [self dividerThickness];
[self _postNotificationWillResize];
var eachSize = ROUND((frame.size[_sizeComponent] - dividerThickness * (_subviews.length - 1)) / _subviews.length),
index = 0,
count = _subviews.length;
@@ -115,9 +147,9 @@ var CPSplitViewHorizontalImage = nil,
else
for (; index < count; ++index)
[_subviews[index] setFrame:CGRectMake(0, ROUND((eachSize + dividerThickness) * index), frame.size.width, eachSize)];
[self setNeedsDisplay:YES];
[self _postNotificationDidResize];
}
@@ -125,75 +157,102 @@ var CPSplitViewHorizontalImage = nil,
- (BOOL)_setVertical:(BOOL)shouldBeVertical
{
var changed = (_isVertical != shouldBeVertical);
_isVertical = shouldBeVertical;
_originComponent = [self isVertical] ? "x" : "y";
_sizeComponent = [self isVertical] ? "width" : "height";
_dividerImagePath = [self isVertical] ? [CPSplitViewVerticalImage filename] : [CPSplitViewHorizontalImage filename];
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)
return;
_isPaneSplitter = shouldBePaneSplitter;
#if PLATFORM(DOM)
_DOMDividerElements = [];
#endif
if (_DOMDividerElements[_drawingDivider])
[self _setupDOMDivider];
// The divider changes size when pane splitter mode is toggled, so the
// subviews need to change size too.
_needsResizeSubviews = YES;
[self setNeedsDisplay:YES];
}
- (void)didAddSubview:(CPView)aSubview
{
_needsResizeSubviews = YES;
// [self adjustSubviews];
}
/*!
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],
rect = CGRectMakeZero();
rect.size = [self frame].size;
rect.size[_sizeComponent] = [self dividerThickness];
rect.origin[_originComponent] = frame.origin[_originComponent] + frame.size[_sizeComponent];
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];
var padding = 2;
var realRect = [self rectOfDividerAtIndex:aDivider],
padding = 2;
realRect.size[_sizeComponent] += padding * 2;
realRect.origin[_originComponent] -= padding;
return realRect;
}
- (void)drawRect:(CGRect)rect
{
var count = [_subviews count] - 1;
while ((count--) > 0)
{
_drawingDivider = count;
@@ -201,35 +260,68 @@ var CPSplitViewHorizontalImage = nil,
}
}
/*!
@ignore
Because we're use drawRect: to draw the dividers, but use DOM elements instead of CoreGraphics
We must remove those DOM elements (the splitters) when the subview is removed.
*/
- (void)willRemoveSubview:(CPView)aView
{
#if PLATFORM(DOM)
var dividerToRemove = _DOMDividerElements.pop();
// The divider may not exist if we never rendered out the DOM.
if (dividerToRemove)
CPDOMDisplayServerRemoveChild(_DOMElement, dividerToRemove);
#endif
_needsResizeSubviews = YES;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
- (void)layoutSubviews
{
[self _adjustSubviewsWithCalculatedSize]
}
/*!
Draws the divider at a given rect.
@param aRect - the rect of the divider to draw.
*/
- (void)drawDividerInRect:(CGRect)aRect
{
#if PLATFORM(DOM)
if (!_DOMDividerElements[_drawingDivider])
{
_DOMDividerElements[_drawingDivider] = document.createElement("div");
_DOMDividerElements[_drawingDivider].style.cursor = "move";
_DOMDividerElements[_drawingDivider].style.position = "absolute";
_DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat";
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
}
if (_isPaneSplitter)
{
_DOMDividerElements[_drawingDivider].style.backgroundColor = "#A5A5A5";
_DOMDividerElements[_drawingDivider].style.backgroundImage = "";
}
else
{
_DOMDividerElements[_drawingDivider].style.backgroundColor = "";
_DOMDividerElements[_drawingDivider].style.backgroundImage = "url('"+_dividerImagePath+"')";
}
}
[self _setupDOMDivider];
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect));
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect));
#endif
}
- (void)_setupDOMDivider
{
if (_isPaneSplitter)
{
_DOMDividerElements[_drawingDivider].style.backgroundColor = "";
_DOMDividerElements[_drawingDivider].style.backgroundImage = "url('"+_dividerImagePath+"')";
}
else
{
_DOMDividerElements[_drawingDivider].style.backgroundColor = [[self currentValueForThemeAttribute:@"pane-divider-color"] cssString];
_DOMDividerElements[_drawingDivider].style.backgroundImage = "";
}
}
- (void)viewWillDraw
{
[self _adjustSubviewsWithCalculatedSize];
@@ -239,13 +331,13 @@ var CPSplitViewHorizontalImage = nil,
{
if (!_needsResizeSubviews)
return;
_needsResizeSubviews = NO;
var subviews = [self subviews],
count = subviews.length,
oldSize = CGSizeMakeZero();
if ([self isVertical])
{
oldSize.width += [self dividerThickness] * (count - 1);
@@ -256,10 +348,10 @@ var CPSplitViewHorizontalImage = nil,
oldSize.width = CGRectGetWidth([self frame]);
oldSize.height += [self dividerThickness] * (count - 1);
}
while (count--)
oldSize[_sizeComponent] += [subviews[count] frame].size[_sizeComponent];
[self resizeSubviewsWithOldSize:oldSize];
}
@@ -268,31 +360,41 @@ var CPSplitViewHorizontalImage = nil,
var frame = [_subviews[anIndex] frame],
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent],
effectiveRect = [self effectiveRectOfDividerAtIndex:anIndex],
buttonBar = _buttonBars[anIndex],
buttonBarRect = null,
additionalRect = null;
if (buttonBar != null)
{
buttonBarRect = [buttonBar resizeControlFrame];
buttonBarRect.origin = [self convertPoint:buttonBarRect.origin fromView:buttonBar];
}
if ([_delegate respondsToSelector:@selector(splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:)])
effectiveRect = [_delegate splitView:self effectiveRect:effectiveRect forDrawnRect:effectiveRect ofDividerAtIndex:anIndex];
if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
additionalRect = [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex];
return CGRectContainsPoint(effectiveRect, aPoint) || (additionalRect && CGRectContainsPoint(additionalRect, aPoint));
return CGRectContainsPoint(effectiveRect, aPoint) ||
(additionalRect && CGRectContainsPoint(additionalRect, aPoint)) ||
(buttonBarRect && CGRectContainsPoint(buttonBarRect, aPoint));
}
- (CPView)hitTest:(CGPoint)aPoint
{
if ([self isHidden] || ![self hitTests] || !CGRectContainsPoint([self frame], aPoint))
return nil;
var point = [self convertPoint:aPoint fromView:[self superview]];
var count = [_subviews count] - 1;
var point = [self convertPoint:aPoint fromView:[self superview]],
count = [_subviews count] - 1;
for (var i = 0; i < count; i++)
{
if ([self cursorAtPoint:point hitDividerAtIndex:i])
return self;
}
return [super hitTest:aPoint];
}
@@ -309,12 +411,13 @@ var CPSplitViewHorizontalImage = nil,
if (_currentDivider != CPNotFound)
{
_currentDivider = CPNotFound;
[self _updateResizeCursor:anEvent];
[self _postNotificationDidResize];
}
return;
}
if (type == CPLeftMouseDown)
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
@@ -331,21 +434,21 @@ var CPSplitViewHorizontalImage = nil,
if ([anEvent clickCount] == 2 &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)])
{
{
var minPosition = [self minPossiblePositionOfDividerAtIndex:i],
maxPosition = [self maxPossiblePositionOfDividerAtIndex:i];
if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
{
if ([self isSubviewCollapsed:_subviews[i]])
[self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
[self setPosition:_preCollapsePosition ? _preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
else
[self setPosition:minPosition ofDividerAtIndex:i];
}
else if ([_delegate splitView:self canCollapseSubview:_subviews[i+1]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i+1] forDoubleClickOnDividerAtIndex:i])
else if ([_delegate splitView:self canCollapseSubview:_subviews[i + 1]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i + 1] forDoubleClickOnDividerAtIndex:i])
{
if ([self isSubviewCollapsed:_subviews[i+1]])
[self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
if ([self isSubviewCollapsed:_subviews[i + 1]])
[self setPosition:_preCollapsePosition ? _preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
else
[self setPosition:maxPosition ofDividerAtIndex:i];
}
@@ -363,14 +466,16 @@ var CPSplitViewHorizontalImage = nil,
if (_currentDivider === CPNotFound)
return;
}
else if (type == CPLeftMouseDragged && _currentDivider != CPNotFound)
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
[self setPosition:(point[_originComponent] + _initialOffset) ofDividerAtIndex:_currentDivider];
// Cursor might change if we reach a resize limit.
[self _updateResizeCursor:anEvent];
}
[CPApp setTarget:self selector:@selector(trackDivider:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
@@ -380,32 +485,116 @@ var CPSplitViewHorizontalImage = nil,
[self trackDivider:anEvent];
}
- (void)viewDidMoveToWindow
{
// Enable split view resize cursors. Commented out pending CPTrackingArea implementation.
//[[self window] setAcceptsMouseMovedEvents:YES];
}
- (void)mouseEntered:(CPEvent)anEvent
{
// Tracking code handles cursor by itself.
if (_currentDivider == CPNotFound)
[self _updateResizeCursor:anEvent];
}
- (void)mouseMoved:(CPEvent)anEvent
{
if (_currentDivider == CPNotFound)
[self _updateResizeCursor:anEvent];
}
- (void)mouseExited:(CPEvent)anEvent
{
if (_currentDivider == CPNotFound)
// FIXME: we should use CPCursor push/pop (if previous currentCursor != arrow).
[[CPCursor arrowCursor] set];
}
- (void)_updateResizeCursor:(CPEvent)anEvent
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if ([anEvent type] === CPLeftMouseUp && ![[self window] acceptsMouseMovedEvents])
{
[[CPCursor arrowCursor] set];
return;
}
for (var i = 0, count = [_subviews count] - 1; i < count; i++)
{
// If we are currently tracking, keep the resize cursor active even outside of hit areas.
if (_currentDivider === i || (_currentDivider == CPNotFound && [self cursorAtPoint:point hitDividerAtIndex:i]))
{
var frame = [_subviews[i] frame],
size = frame.size[_sizeComponent],
startPosition = frame.origin[_originComponent] + size,
canShrink = [self _realPositionForPosition:startPosition - 1 ofDividerAtIndex:i] < startPosition,
canGrow = [self _realPositionForPosition:startPosition + 1 ofDividerAtIndex:i] > startPosition,
cursor = [CPCursor arrowCursor];
if (size === 0)
canGrow = YES; // Subview is collapsed.
else if (!canShrink &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i]])
canShrink = YES; // Subview is collapsible.
if (_isVertical && canShrink && canGrow)
cursor = [CPCursor resizeLeftRightCursor];
else if (_isVertical && canShrink)
cursor = [CPCursor resizeLeftCursor];
else if (_isVertical && canGrow)
cursor = [CPCursor resizeRightCursor];
else if (canShrink && canGrow)
cursor = [CPCursor resizeUpDownCursor];
else if (canShrink)
cursor = [CPCursor resizeUpCursor];
else if (canGrow)
cursor = [CPCursor resizeDownCursor];
[cursor set];
return;
}
}
[[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];
if (dividerIndex + 1 < [_subviews count] - 1)
return frame.origin[_originComponent] + frame.size[_sizeComponent] - [self dividerThickness];
else
else
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)
{
var frame = [_subviews[dividerIndex - 1] frame];
return frame.origin[_originComponent] + frame.size[_sizeComponent] + [self dividerThickness];
}
else
else
return 0;
}
- (void)setPosition:(float)position ofDividerAtIndex:(int)dividerIndex
- (int)_realPositionForPosition:(float)position ofDividerAtIndex:(int)dividerIndex
{
[self _adjustSubviewsWithCalculatedSize];
// not sure where this should override other positions?
if ([_delegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)])
position = [_delegate splitView:self constrainSplitPosition:position ofSubviewAt:dividerIndex];
@@ -414,47 +603,69 @@ var CPSplitViewHorizontalImage = nil,
proposedMin = [self minPossiblePositionOfDividerAtIndex:dividerIndex],
actualMax = proposedMax,
actualMin = proposedMin;
if([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
actualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
if([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
actualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
var frame = [self frame],
viewA = _subviews[dividerIndex],
frameA = [viewA frame],
viewB = _subviews[dividerIndex + 1],
frameB = [viewB frame];
var viewA = _subviews[dividerIndex],
realPosition = MAX(MIN(position, actualMax), actualMin);
var realPosition = MAX(MIN(position, actualMax), actualMin);
if (position < proposedMin + (actualMin - proposedMin) / 2)
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
if ([_delegate splitView:self canCollapseSubview:viewA])
realPosition = proposedMin;
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];
var realPosition = [self _realPositionForPosition:position ofDividerAtIndex:dividerIndex];
var viewA = _subviews[dividerIndex],
frameA = [viewA frame],
viewB = _subviews[dividerIndex + 1],
frameB = [viewB frame];
_preCollapsePosition = 0;
var preSize = frameA.size[_sizeComponent];
frameA.size[_sizeComponent] = realPosition - frameA.origin[_originComponent];
if (preSize !== 0 && frameA.size[_sizeComponent] === 0)
_preCollapsePosition = preSize;
[_subviews[dividerIndex] setFrame:frameA];
preSize = frameB.size[_sizeComponent];
frameB.size[_sizeComponent] = frameB.origin[_originComponent] + frameB.size[_sizeComponent] - realPosition - [self dividerThickness];
if (preSize !== 0 && frameB.size[_sizeComponent] === 0)
_preCollapsePosition = preSize;
frameB.origin[_originComponent] = realPosition + [self dividerThickness];
[_subviews[dividerIndex + 1] setFrame:frameB];
[self setNeedsDisplay:YES];
}
- (void)setFrameSize:(CGSize)aSize
{
[self _adjustSubviewsWithCalculatedSize];
[super setFrameSize:aSize];
[self setNeedsDisplay:YES];
}
- (void)resizeSubviewsWithOldSize:(CPSize)oldSize
{
{
if ([_delegate respondsToSelector:@selector(splitView:resizeSubviewsWithOldSize:)])
{
[_delegate splitView:self resizeSubviewsWithOldSize:oldSize];
@@ -462,7 +673,7 @@ var CPSplitViewHorizontalImage = nil,
}
[self _postNotificationWillResize];
var index = 0,
count = [_subviews count],
bounds = [self bounds],
@@ -492,8 +703,8 @@ var CPSplitViewHorizontalImage = nil,
var nonSizableSpace = totalSizableSpace ? bounds.size[_sizeComponent] - totalSizableSpace : 0,
remainingFlexibleSpace = bounds.size[_sizeComponent] - oldSize[_sizeComponent],
oldDimension = (oldSize[_sizeComponent]- totalDividers*dividerThickness - nonSizableSpace),
ratio = oldDimension <= 0 ? 0 : (bounds.size[_sizeComponent] - totalDividers*dividerThickness - nonSizableSpace) / oldDimension;
oldDimension = (oldSize[_sizeComponent] - totalDividers * dividerThickness - nonSizableSpace),
ratio = oldDimension <= 0 ? 0 : (bounds.size[_sizeComponent] - totalDividers * dividerThickness - nonSizableSpace) / oldDimension;
for (index = 0; index < count; ++index)
{
@@ -501,21 +712,22 @@ 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];
else
alert("SHOULD NEVER GET HERE");
if (index + 1 === count)
viewFrame.size[_sizeComponent] = bounds.size[_sizeComponent] - viewFrame.origin[_originComponent];
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
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;
[view setFrame:viewFrame];
}
@@ -523,13 +735,73 @@ var CPSplitViewHorizontalImage = nil,
[self _postNotificationDidResize];
}
/*!
Sets the delegate of the receiver.
Possible delegate methods to implement are listed below.
Notifies the delegate when the subviews have resized.
@code
- (void)splitViewDidResizeSubviews:(CPNotification)aNotification;
@endcode
Notifies the delegate when the subviews will be resized.
@code
- (void)splitViewWillResizeSubviews:(CPNotification)aNotification;
@endcode
Lets the delegate specify a different rect for which the user can drag the splitView divider.
@code
- (CGRect)splitView:(CPSplitView)aSplitView effectiveRect:(CGRect)aRect forDrawnRect:(CGRect)aDrawnRect ofDividerAtIndex:(int)aDividerIndex;
@endcode
Lets the delegate specify an additional rect for which the user can drag the splitview divider.
@code
- (CGRect)splitView:(CPSplitView)aSplitView additionalEffectiveRectOfDividerAtIndex:(int)indexOfDivider;
@endcode
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.
@code
- (BOOL)splitView:(CPSplitView)aSplitView canCollapseSubview:(CPView)aSubview;
@endcode
Notifies the delegate that the subview at indexOfDivider 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.
@code
- (BOOL)splitView:(CPSplitView)aSplitView shouldCollapseSubview:(CPView)aSubview forDoubleClickOnDividerAtIndex:(int)indexOfDivider;
@endcode
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.
@code
- (float)splitView:(CPSplitView)aSpiltView constrainSplitPosition:(float)proposedPosition ofSubviewAt:(int)subviewIndex;
@endcode
Allows the delegate to constrain the minimum position of a subview.
@code
- (float)splitView:(CPSplitView)aSplitView constrainMinCoordinate:(float)proposedMin ofSubviewAt:(int)subviewIndex;
@endcode
Allows the delegate to constrain the maximum position of a subview.
@code
- (float)splitView:(CPSplitView)aSplitView constrainMaxCoordinate:(float)proposedMax ofSubviewAt:(int)subviewIndex;
@endcode
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.
@code
- (void)splitView:(CPSplitView)aSplitView resizeSubviewsWithOldSize:(CGSize)oldSize;
@endcode
@param delegate - The delegate of the splitview.
*/
- (void)setDelegate:(id)delegate
{
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewDidResizeSubviewsNotification object:self];
if ([_delegate respondsToSelector:@selector(splitViewWillResizeSubviews:)])
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewWillResizeSubviewsNotification object:self];
_delegate = delegate;
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
@@ -544,6 +816,50 @@ var CPSplitViewHorizontalImage = nil,
object:self];
}
/*!
Set the button bar who's resize control should act as a control for this splitview.
Each divider can have at most one button bar assigned to it, and that button bar must be
a subview of one of the split view's subviews.
Calling this method with nil as the button bar will remove any currently assigned button bar
for the divider at that index. Indexes will not be adjusted as new subviews are added, so you
should usually call this method after adding all the desired subviews to the split view.
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
{
if (!aButtonBar)
{
_buttonBars[dividerIndex] = nil;
return;
}
var view = [aButtonBar superview],
subview = aButtonBar;
while (view && view !== self)
{
subview = view;
view = [view superview];
}
if (view !== self)
[CPException raise:CPInvalidArgumentException
reason:@"CPSplitView button bar must be a subview of the split view."];
var viewIndex = [[self subviews] indexOfObject:subview];
[aButtonBar setHasResizeControl:YES];
[aButtonBar setResizeControlIsLeftAligned:dividerIndex < viewIndex];
_buttonBars[dividerIndex] = aButtonBar;
}
- (void)_postNotificationWillResize
{
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewWillResizeSubviewsNotification object:self];
@@ -558,7 +874,8 @@ var CPSplitViewHorizontalImage = nil,
var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
CPSplitViewIsVerticalKey = "CPSplitViewIsVerticalKey",
CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey";
CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey",
CPSplitViewButtonBarsKey = "CPSplitViewButtonBarsKey";
@implementation CPSplitView (CPCoding)
@@ -569,19 +886,21 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_currentDivider = CPNotFound;
_DOMDividerElements = [];
_delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];;
_buttonBars = [aCoder decodeObjectForKey:CPSplitViewButtonBarsKey] || [];
[self setDelegate:[aCoder decodeObjectForKey:CPSplitViewDelegateKey]];
_isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey];
[self _setVertical:[aCoder decodeBoolForKey:CPSplitViewIsVerticalKey]];
}
return self;
}
@@ -592,9 +911,12 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
//FIXME how should we handle this?
//[aCoder encodeObject:_buttonBars forKey:CPSplitViewButtonBarsKey];
[aCoder encodeConditionalObject:_delegate forKey:CPSplitViewDelegateKey];
[aCoder encodeBool:_isVertical forKey:CPSplitViewIsVerticalKey];
[aCoder encodeBool:_isPaneSplitter forKey:CPSplitViewIsPaneSplitterKey];
}
+246
View File
@@ -0,0 +1,246 @@
/*
* 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);
CPButton _buttonDown;
CPButton _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 = [[CPButton 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 = [[CPButton 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
+72
View File
@@ -0,0 +1,72 @@
/*
* CPString+Additions.j
* AppKit
*
* Created by Randy Luecke
* Copyright 2011, RCLConcepts, LLC.
*
* 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
*/
/*
AppKit adds two methods to the CPString class to support drawing string directly in an CPView.
AppKit also adds similar methods to CPAttributedString.
The two drawing methods draw a string object with a single set of attributes that apply to the entire string.
To draw a string with multiple attributes, such as multiple text fonts, you must use an attributed string.
*/
@implementation CPString (AppKitAdditions)
/*!
Draws a string in the current graphics context.
This method applies the attributes to the entier string
and displays it on a single "infinately long" line.
@param aPoint - The starting point to draw the string
@param attributes - the dictionary of attributes to apply to the string
*/
- (void)drawAtPoint:(CGPoint)aPoint withAttributes:(CPDictionary)attributes
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
run = _CTRunCreate([self copy], attributes);
CGContextSetTextPosition(context, aPoint.x, aPoint.y);
CTRunDraw(run, context, nil);
}
/*!
Draws a string in the current graphics context.
This method applies the attributes to the entier string
and displays it within the given rect.
@param aRect - The rect for which the string should be drawn into
@param attributes - the dictionary of attributes to apply to the string
*/
- (void)drawInRect:(CGRect)aRect withAttributes:(CPDictionary)attributes
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
string = [[CPAttributedString alloc] initWithString:self attributes:attributes];
frameSetter = CTFramesetterCreateWithAttributedString(string),
path = CGPathCreateMutable();
CGPathAddRect(path, nil, aRect);
var frame = CTFramesetterCreateFrame(frameSetter, CPMakeRange(0, [string length]), path, nil);
CTFrameDraw(frame, context);
}
@end
+25 -1
View File
@@ -25,8 +25,20 @@
@import "CPPlatformString.j"
var CPStringSizeWithFontInWidthCache = {};
CPStringSizeCachingEnabled = YES;
@implementation CPString (CPStringDrawing)
/*!
Returns a dictionary with the items "ascender", "descender", "lineHeight"
*/
+ (CPDictionary)metricsOfFont:(CPFont)aFont
{
return [CPPlatformString metricsOfFont:aFont];
}
/*!
Returns the string
*/
@@ -42,7 +54,19 @@
- (CGSize)sizeWithFont:(CPFont)aFont inWidth:(float)aWidth
{
return [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth];
if (!CPStringSizeCachingEnabled)
return [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth];
var cacheKey = self + [aFont cssString] + aWidth,
size = CPStringSizeWithFontInWidthCache[cacheKey];
if (size === undefined)
{
size = [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth];
CPStringSizeWithFontInWidthCache[cacheKey] = size;
}
return CGSizeMakeCopy(size);
}
@end
+258 -546
View File
File diff suppressed because it is too large Load Diff
+22 -12
View File
@@ -22,7 +22,7 @@
@import <Foundation/CPObject.j>
@import <AppKit/CPView.j>
@import "CPView.j"
/*
@@ -44,7 +44,7 @@ CPBackgroundTab = 1;
*/
CPPressedTab = 2;
/*!
/*!
@ingroup appkit
@class CPTabViewItem
@@ -55,9 +55,11 @@ CPPressedTab = 2;
{
id _identifier;
CPString _label;
CPView _view;
CPView _auxiliaryView;
CPTabView _tabView;
}
- (id)init
@@ -72,10 +74,10 @@ CPPressedTab = 2;
- (id)initWithIdentifier:(id)anIdentifier
{
self = [super init];
if (self)
_identifier = anIdentifier;
return self;
}
@@ -143,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
{
@@ -152,7 +154,7 @@ CPPressedTab = 2;
}
/*!
Returns the tab's auxillary view
Returns the tab's auxiliary view
*/
- (CPView)auxiliaryView
{
@@ -168,6 +170,14 @@ CPPressedTab = 2;
return _tabView;
}
/*!
@ignore
*/
- (void)_setTabView:(CPTabView)aView
{
_tabView = aView;
}
@end
var CPTabViewItemIdentifierKey = "CPTabViewItemIdentifierKey",
@@ -181,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;
}
@@ -198,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];
}
+432 -64
View File
@@ -22,28 +22,28 @@
@import <Foundation/CPDictionary.j>
@import <Foundation/CPObject.j>
@import <Foundation/CPIndexSet.j>
@import <Foundation/CPSortDescriptor.j>
@import <Foundation/CPString.j>
@import "CPTableHeaderView.j"
/*
@global
@class CPTableColumn
*/
CPTableColumnNoResizing = 0;
/*
@global
@class CPTableColumn
*/
CPTableColumnAutoresizingMask = 1;
/*
@global
@class CPTableColumn
*/
CPTableColumnUserResizingMask = 2;
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,19 +54,29 @@ CPTableColumnUserResizingMask = 2;
float _width;
float _minWidth;
float _maxWidth;
unsigned _resizingMask;
id _identifier;
BOOL _isEditable;
CPSortDescriptor _sortDescriptorPrototype;
BOOL _isHidden;
CPString _headerToolTip;
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];
@@ -78,25 +88,64 @@ CPTableColumnUserResizingMask = 2;
_width = 100.0;
_minWidth = 10.0;
_maxWidth = 1000000.0;
_resizingMask = CPTableColumnAutoresizingMask | CPTableColumnUserResizingMask;
_disableResizingPosting = NO;
[self setIdentifier:anIdentifier];
[self setHeaderView:[CPTextField new]];
var header = [[_CPTableColumnHeaderView alloc] initWithFrame:CGRectMakeZero()];
[self setHeaderView:header];
[self setDataView:[CPTextField new]];
}
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;
@@ -117,26 +166,38 @@ CPTableColumnUserResizingMask = 2;
if (tableView)
{
var index = [[tableView tableColumns] indexOfObjectIdenticalTo:self];
var index = [[tableView tableColumns] indexOfObjectIdenticalTo:self],
dirtyTableColumnRangeIndex = tableView._dirtyTableColumnRangeIndex;
// FIXME: THIS IS HORRIBLE. Don't just reload everything when a table column changes, just relayout the changed widths.
tableView._reloadAllRows = YES;
tableView._dirtyTableColumnRangeIndex = tableView._dirtyTableColumnRangeIndex < 0 ? index : MIN(index, tableView._dirtyTableColumnRangeIndex);
if (dirtyTableColumnRangeIndex < 0)
tableView._dirtyTableColumnRangeIndex = index;
else
tableView._dirtyTableColumnRangeIndex = MIN(index, tableView._dirtyTableColumnRangeIndex);
var rows = tableView._exposedRows,
columns = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(index, [tableView._exposedColumns lastIndex] - index + 1)];
// FIXME: Would be faster with some sort of -setNeedsDisplayInColumns: that updates a dirtyTableColumnForDisplay cache; then marked columns would relayout their data views at display time.
[tableView _layoutDataViewsInRows:rows columns:columns];
[tableView tile];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPTableViewColumnDidResizeNotification
object:tableView
userInfo:[CPDictionary dictionaryWithObjects:[self, oldWidth] forKeys:[@"CPTableColumn", "CPOldWidth"]]];
if (!_disableResizingPosting)
[self _postDidResizeNotificationWithOldWidth:oldWidth];
}
}
/*!
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;
@@ -153,11 +214,18 @@ CPTableColumnUserResizingMask = 2;
[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;
@@ -168,27 +236,48 @@ CPTableColumnUserResizingMask = 2;
_maxWidth = aMaxWidth;
var width = [self width],
newWidth = MAX(width, [self maxWidth]);
newWidth = MIN(width, [self maxWidth]);
if (width !== newWidth)
[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;
}
- (float)resizingMask
/*!
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]);
@@ -202,7 +291,16 @@ CPTableColumnUserResizingMask = 2;
[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)
@@ -216,19 +314,88 @@ CPTableColumnUserResizingMask = 2;
[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 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.
Example:
@code
[tableColumn setDataView:someView]; // snapshot taken
[[tableColumn dataView] setSomething:x]; //won't work
@endcode
This doesn't work because the snapshot is taken before the new property is applied. Instead, do:
@code
[someView setSomething:x];
[tableColumn setDataView:someView];
@endcode
@note you should implement CPKeyedArchiving otherwise you might see unexpected results.
This is done by adding the following methods to your class:
@endnote
@code
- (id)initWithCoder(CPCoder)aCoder;
- (void)encodeWithCoder:(CPCoder)aCoder;
@endcode
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:
@code
- (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"];
}
@endcode
@section Themeing
When you set a dataview and it is added to the tableview the theme state will be set to \c CPThemeStateTableDataView
When the dataview becomes selected the theme state will be set to \c CPThemeStateSelectedDataView.
If the dataview shows up in a group row of the tableview the theme state will be set to \c CPThemeStateGroupRow.
You should overide \c setThemeState: and \c unsetThemeState: to handle these theme state changes in your dataview.
*/
- (void)setDataView:(CPView)aView
{
if (_dataView === aView)
return;
if (_dataView)
_dataViewData[[_dataView UID]] = nil;
[aView setThemeState:CPThemeStateTableDataView];
_dataView = aView;
_dataViewData[[aView UID]] = [CPKeyedArchiver archivedDataWithRootObject:aView];
}
@@ -242,7 +409,7 @@ CPTableColumnUserResizingMask = 2;
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.
*/
@@ -251,14 +418,17 @@ CPTableColumnUserResizingMask = 2;
return [self dataView];
}
/*!
@ignore
*/
- (id)_newDataViewForRow:(int)aRowIndex
{
var dataView = [self dataViewForRow:aRowIndex],
dataViewUID = [dataView UID];
var x = [self tableView]._cachedDataViews[dataViewUID];
if (x && x.length)
return x.pop();
var x = [self tableView]._cachedDataViews[dataViewUID];
if (x && x.length)
return x.pop();
// if we haven't cached an archive of the data view, do it now
if (!_dataViewData[dataViewUID])
@@ -266,13 +436,17 @@ return x.pop();
// unarchive the data view cache
var newDataView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[dataViewUID]];
newDataView.identifier = dataViewUID;
newDataView.identifier = dataViewUID;
// make sure only we have control over the size and placement
[newDataView setAutoresizingMask:CPViewNotSizable];
return newDataView;
}
//Setting the Identifier
/*
/*!
Sets the receiver identifier to anIdentifier.
*/
- (void)setIdentifier:(id)anIdentifier
@@ -280,7 +454,7 @@ newDataView.identifier = dataViewUID;
_identifier = anIdentifier;
}
/*
/*!
Returns the object used by the data source to identify the attribute corresponding to the receiver.
*/
- (id)identifier
@@ -290,7 +464,7 @@ newDataView.identifier = dataViewUID;
//Controlling Editability
/*
/*!
Controls whether the user can edit cells in the receiver by double-clicking them.
*/
- (void)setEditable:(BOOL)shouldBeEditable
@@ -298,33 +472,50 @@ newDataView.identifier = dataViewUID;
_isEditable = shouldBeEditable;
}
/*
Returns YES if the user can edit cells associated with the receiver by double-clicking the
column in the NSTableView, NO otherwise.
/*!
Returns YES if the user can edit cells associated with the receiver by double-clicking the
column in the CPTableView, NO otherwise.
*/
- (BOOL)isEditable
{
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
if (_isHidden === shouldBeHidden)
return;
_isHidden = shouldBeHidden;
[[self headerView] setHidden:shouldBeHidden];
[[self tableView] _tableColumnVisibilityDidChange:self];
}
/*!
Returns the visibility status of the column.
*/
- (BOOL)isHidden
{
return _isHidden;
@@ -332,8 +523,8 @@ newDataView.identifier = dataViewUID;
//Setting Tool Tips
/*
Sets the tooltip string that is displayed when the cursor pauses over the
/*!
Sets the tooltip string that is displayed when the cursor pauses over the
header cell of the receiver.
*/
- (void)setHeaderToolTip:(CPString)aToolTip
@@ -341,11 +532,160 @@ newDataView.identifier = dataViewUID;
_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]
userInfo:[CPDictionary dictionaryWithObjects:[self, oldWidth] forKeys:[@"CPTableColumn", "CPOldWidth"]]];
}
@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];
if (![aBinding isEqual:@"someListOfExceptedBindings(notAcceptedBindings)"])
[[self tableView] _establishBindingsIfUnbound:anObject];
}
/*!
@ignore
*/
- (void)_prepareDataView:(CPView)aDataView forRow:(unsigned)aRow
{
var bindingsDictionary = [CPBinder allBindingsForObject:self],
keys = [bindingsDictionary allKeys];
for (var i = 0, count = [keys count]; i < count; i++)
{
var bindingName = keys[i],
bindingPath = [aDataView _replacementKeyPathForBinding:bindingName],
binding = [bindingsDictionary objectForKey:bindingName],
bindingInfo = binding._info,
destination = [bindingInfo objectForKey:CPObservedObjectKey],
keyPath = [bindingInfo objectForKey:CPObservedKeyPathKey],
dotIndex = keyPath.lastIndexOf("."),
value;
if (dotIndex === CPNotFound)
value = [[destination valueForKeyPath:keyPath] objectAtIndex:aRow];
else
{
/*
Optimize the prototypical use case where the key path describes a value
in an array. Without this optimization, we call CPArray's valueForKey
which generates as many values as objects in the array, of which we then
pick one and throw away the rest.
The optimization is to get the array and access the value directly. This
turns the operation into a single access regardless of how long the model
array is.
*/
var firstPart = keyPath.substring(0, dotIndex),
secondPart = keyPath.substring(dotIndex + 1),
firstValue = [destination valueForKeyPath:firstPart];
if ([firstValue isKindOfClass:CPArray])
value = [[firstValue objectAtIndex:aRow] valueForKeyPath:secondPart];
else
value = [[firstValue valueForKeyPath:secondPart] objectAtIndex:aRow];
}
value = [binding transformValue:value withOptions:[bindingInfo objectForKey:CPOptionsKey]];
[aDataView setValue:value forKey:@"objectValue"];
}
}
/*!
@ignore
*/
- (void)_reverseSetDataView:(CPView)aDataView forRow:(unsigned)aRow
{
var bindingsDictionary = [CPBinder allBindingsForObject:self],
keys = [bindingsDictionary allKeys],
newValue = [aDataView valueForKey:@"objectValue"];
for (var i = 0, count = [keys count]; i < count; i++)
{
var bindingName = keys[i],
bindingPath = [aDataView _replacementKeyPathForBinding:bindingName],
binding = [bindingsDictionary objectForKey:bindingName],
bindingInfo = binding._info,
destination = [bindingInfo objectForKey:CPObservedObjectKey],
keyPath = [bindingInfo objectForKey:CPObservedKeyPathKey],
dotIndex = keyPath.lastIndexOf(".");
if (dotIndex === CPNotFound)
[[destination valueForKeyPath:keyPath] replaceObjectAtIndex:aRow withObject:newValue];
else
{
var firstPart = keyPath.substring(0, dotIndex),
secondPart = keyPath.substring(dotIndex + 1),
firstValue = [destination valueForKeyPath:firstPart];
if ([firstValue isKindOfClass:CPArray])
[[firstValue objectAtIndex:aRow] setValue:newValue forKeyPath:secondPart];
else
[[firstValue valueForKeyPath:secondPart] replaceObjectAtIndex:aRow withObject:newValue];
}
}
}
//- (void)objectValue
//{
// return nil;
//}
@end
var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
@@ -354,10 +694,16 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
CPTableColumnWidthKey = @"CPTableColumnWidthKey",
CPTableColumnMinWidthKey = @"CPTableColumnMinWidthKey",
CPTableColumnMaxWidthKey = @"CPTableColumnMaxWidthKey",
CPTableColumnResizingMaskKey = @"CPTableColumnResizingMaskKey";
CPTableColumnResizingMaskKey = @"CPTableColumnResizingMaskKey",
CPTableColumnIsHiddenKey = @"CPTableColumnIsHiddenKey",
CPSortDescriptorPrototypeKey = @"CPSortDescriptorPrototypeKey",
CPTableColumnIsEditableKey = @"CPTableColumnIsEditableKey";
@implementation CPTableColumn (CPCoding)
/*!
@ignore
*/
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
@@ -371,65 +717,87 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
_maxWidth = [aCoder decodeFloatForKey:CPTableColumnMaxWidthKey];
[self setIdentifier:[aCoder decodeObjectForKey:CPTableColumnIdentifierKey]];
// [self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
// [self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
[self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
[self setHeaderView:[CPTextField new]];
[self setDataView:[CPTextField new]];
_resizingMask = [aCoder decodeIntForKey:CPTableColumnResizingMaskKey];
_isHidden = [aCoder decodeBoolForKey:CPTableColumnIsHiddenKey];
_isEditable = [aCoder decodeBoolForKey:CPTableColumnIsEditableKey];
// _resizingMask = [aCoder decodeBoolForKey:CPTableColumnResizingMaskKey];
_sortDescriptorPrototype = [aCoder decodeObjectForKey:CPSortDescriptorPrototypeKey];
}
return self;
}
/*!
@ignore
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_identifier forKey:CPTableColumnIdentifierKey];
[aCoder encodeObject:_width forKey:CPTableColumnWidthKey];
[aCoder encodeObject:_minWidth forKey:CPTableColumnMinWidthKey];
[aCoder encodeObject:_maxWidth forKey:CPTableColumnMaxWidthKey];
[aCoder encodeFloat:_width forKey:CPTableColumnWidthKey];
[aCoder encodeFloat:_minWidth forKey:CPTableColumnMinWidthKey];
[aCoder encodeFloat:_maxWidth forKey:CPTableColumnMaxWidthKey];
// [aCoder encodeObject:_headerView forKey:CPTableColumnHeaderViewKey];
// [aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
[aCoder encodeObject:_headerView forKey:CPTableColumnHeaderViewKey];
[aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
// [aCoder encodeObject:_resizingMask forKey:CPTableColumnResizingMaskKey];
[aCoder encodeObject:_resizingMask forKey:CPTableColumnResizingMaskKey];
[aCoder encodeBool:_isHidden forKey:CPTableColumnIsHiddenKey];
[aCoder encodeBool:_isEditable forKey:CPTableColumnIsEditableKey];
[aCoder encodeObject:_sortDescriptorPrototype forKey:CPSortDescriptorPrototypeKey];
}
@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
reason:@"dataCellForRow: is not supported. Use -dataViewForRow:row instead."];
}
@end
@end
+617 -70
View File
@@ -20,126 +20,673 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPIndexSet.j>
@import "CPTableColumn.j"
@import "CPTableView.j"
@import "CPView.j"
@implementation CPTableHeaderView : CPView
@implementation _CPTableColumnHeaderView : CPView
{
int _resizedColumn @accessors(readonly, property=resizedColumn);
int _draggedColumn @accessors(readonly, property=draggedColumn);
float _draggedDistance @accessors(readonly, property=draggedDistance);
CPTableView _tableView @accessors(property=tableView);
_CPImageAndTextView _textField;
}
- (void)initWithFrame:(CGRect)aFrame
+ (CPString)defaultThemeClass
{
return @"columnHeader";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPNull null], CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], CGSizeMakeZero()]
forKeys:[@"background-color", @"text-alignment", @"text-inset", @"text-color", @"text-font", @"text-shadow-color", @"text-shadow-offset"]];
}
- (void)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
[self _init];
return self;
}
- (void)_init
{
_textField = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
[_textField setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_textField setLineBreakMode:CPLineBreakByTruncatingTail];
[_textField setAlignment:CPLeftTextAlignment];
[_textField setVerticalAlignment:CPCenterVerticalTextAlignment];
[self addSubview:_textField];
}
- (void)layoutSubviews
{
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
var inset = [self currentValueForThemeAttribute:@"text-inset"],
bounds = [self bounds];
[_textField setFrame:_CGRectMake(inset.right, inset.top, bounds.size.width - inset.right - inset.left, bounds.size.height - inset.top - inset.bottom)];
[_textField setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
[_textField setFont:[self currentValueForThemeAttribute:@"text-font"]];
[_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
[_textField setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
[_textField setAlignment:[self currentValueForThemeAttribute:@"text-alignment"]];
}
- (void)setStringValue:(CPString)string
{
[_textField setText:string];
}
- (CPString)stringValue
{
return [_textField text];
}
- (void)textField
{
return _textField;
}
- (void)sizeToFit
{
[_textField sizeToFit];
}
- (void)setFont:(CPFont)aFont
{
[self setValue:aFont forThemeAttribute:"text-font"];
}
- (void)_setIndicatorImage:(CPImage)anImage
{
if (anImage)
{
[_textField setImage:anImage];
[_textField setImagePosition:CPImageRight];
}
else
{
[_textField setImagePosition:CPNoImage];
}
}
@end
var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringValueKey",
_CPTableColumnHeaderViewFontKey = @"_CPTableColumnHeaderViewFontKey",
_CPTableColumnHeaderViewImageKey = @"_CPTableColumnHeaderViewImageKey";
@implementation _CPTableColumnHeaderView (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
[self _init];
[self _setIndicatorImage:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewImageKey]];
[self setStringValue:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewStringValueKey]];
[self setFont:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewFontKey]];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:[_textField text] forKey:_CPTableColumnHeaderViewStringValueKey];
[aCoder encodeObject:[_textField image] forKey:_CPTableColumnHeaderViewImageKey];
[aCoder encodeObject:[_textField font] forKey:_CPTableColumnHeaderViewFontKey];
}
@end
@implementation CPTableHeaderView : CPView
{
CGPoint _mouseDownLocation;
CGPoint _previousTrackingLocation;
int _activeColumn;
int _pressedColumn;
BOOL _isResizing;
BOOL _isDragging;
BOOL _isTrackingColumn;
BOOL _drawsColumnLines;
float _columnOldWidth;
CPTableView _tableView @accessors(property=tableView);
}
+ (CPString)defaultThemeClass
{
return @"tableHeaderRow";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPColor grayColor]]
forKeys:[@"background-color", @"divider-color"]];
}
- (void)_init
{
_mouseDownLocation = _CGPointMakeZero();
_previousTrackingLocation = _CGPointMakeZero();
_activeColumn = -1;
_pressedColumn = -1;
_isResizing = NO;
_isDragging = NO;
_isTrackingColumn = NO;
_drawsColumnLines = YES;
_columnOldWidth = 0.0;
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_resizedColumn = CPNotFound;
_draggedColumn = CPNotFound;
_draggedDistance = 0.0;
}
[self _init];
return self;
}
- (int)columnAtPoint:(CGPoint)aPoint
{
if (!CGRectContainsPoint([self bounds], aPoint))
return CPNotFound;
// at this point, we can essentially ignore height, because all columns have equal heights
// and that height is equal to the height of our own bounds, which we know we are inside of
var index = 0,
count = [[_tableView tableColumns] count],
tableSpacing = [_tableView intercellSpacing],
tableColumns = [_tableView tableColumns],
leftOffset = 0,
pointX = aPoint.x;
for (; index < count; index++)
{
var width = [tableColumns[index] width] + tableSpacing.width;
if (pointX >= leftOffset && pointX < leftOffset + width)
return index;
leftOffset += width;
}
return CPNotFound;
return [_tableView columnAtPoint:CGPointMake(aPoint.x, aPoint.y)];
}
- (CGRect)headerRectOfColumn:(int)aColumnIndex
{
var headerRect = CGRectMakeCopy([self bounds]),
columnRect = [_tableView rectOfColumn:aColumnIndex];
headerRect.origin.x = _CGRectGetMinX(columnRect);
headerRect.size.width = _CGRectGetWidth(columnRect);
return headerRect;
}
- (void)setDrawsColumnLines:(BOOL)aFlag
{
_drawsColumnLines = aFlag;
}
- (BOOL)drawsColumnLines
{
return _drawsColumnLines;
}
- (CGRect)_cursorRectForColumn:(int)column
{
if (column == -1 || !([_tableView._tableColumns[column] resizingMask] & CPTableColumnUserResizingMask))
return _CGRectMakeZero();
var rect = [self headerRectOfColumn:column];
rect.origin.x = _CGRectGetMaxX(rect) - 5;
rect.size.width = 20;
return rect;
}
- (void)_setPressedColumn:(CPInteger)column
{
if (_pressedColumn != -1)
{
var headerView = [_tableView._tableColumns[_pressedColumn] headerView];
[headerView unsetThemeState:CPThemeStateHighlighted];
}
if (column != -1)
{
var headerView = [_tableView._tableColumns[column] headerView];
[headerView setThemeState:CPThemeStateHighlighted];
}
_pressedColumn = column;
}
- (void)mouseDown:(CPEvent)theEvent
{
[self trackMouse:theEvent];
}
- (void)trackMouse:(CPEvent)theEvent
{
var type = [theEvent type],
currentLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil];
// Take the right columns resize tracking area into account
currentLocation.x -= 5.0;
var columnIndex = [self columnAtPoint:currentLocation],
shouldResize = [self shouldResizeTableColumn:columnIndex at:_CGPointMake(currentLocation.x + 5.0, currentLocation.y)];
if (type === CPLeftMouseUp)
{
if (shouldResize)
[self stopResizingTableColumn:_activeColumn at:currentLocation];
else if ([self _shouldStopTrackingTableColumn:columnIndex at:currentLocation])
{
[_tableView _didClickTableColumn:columnIndex modifierFlags:[theEvent modifierFlags]];
[self stopTrackingTableColumn:columnIndex at:currentLocation];
_isTrackingColumn = NO;
}
[self _updateResizeCursor:[CPApp currentEvent]];
_activeColumn = CPNotFound;
return;
}
if (type === CPLeftMouseDown)
{
if (columnIndex === -1)
return;
_mouseDownLocation = currentLocation;
_activeColumn = columnIndex;
[_tableView _sendDelegateDidMouseDownInHeader:columnIndex];
if (shouldResize)
[self startResizingTableColumn:columnIndex at:currentLocation];
else
{
[self startTrackingTableColumn:columnIndex at:currentLocation];
_isTrackingColumn = YES;
}
}
else if (type === CPLeftMouseDragged)
{
if (shouldResize)
[self continueResizingTableColumn:_activeColumn at:currentLocation];
else
{
if (_activeColumn === columnIndex && _CGRectContainsPoint([self headerRectOfColumn:columnIndex], currentLocation))
{
if (_isTrackingColumn && _pressedColumn !== -1)
{
if (![self continueTrackingTableColumn:columnIndex at:currentLocation])
return; // Stop tracking the column, because it's being dragged
} else
[self startTrackingTableColumn:columnIndex at:currentLocation];
} else if (_isTrackingColumn && _pressedColumn !== -1)
[self stopTrackingTableColumn:_activeColumn at:currentLocation];
}
}
_previousTrackingLocation = currentLocation;
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (void)startTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
[self _setPressedColumn:aColumnIndex];
}
- (BOOL)continueTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
if ([self _shouldDragTableColumn:aColumnIndex at:aPoint])
{
var columnRect = [self headerRectOfColumn:aColumnIndex],
offset = _CGPointMakeZero(),
view = [_tableView _dragViewForColumn:aColumnIndex event:[CPApp currentEvent] offset:offset],
viewLocation = _CGPointMakeZero();
viewLocation.x = ( _CGRectGetMinX(columnRect) + offset.x ) + ( aPoint.x - _mouseDownLocation.x );
viewLocation.y = _CGRectGetMinY(columnRect) + offset.y;
[self dragView:view at:viewLocation offset:_CGSizeMakeZero() event:[CPApp currentEvent]
pasteboard:[CPPasteboard pasteboardWithName:CPDragPboard] source:self slideBack:YES];
return NO;
}
return YES;
}
- (BOOL)_shouldStopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
return _isTrackingColumn && _activeColumn === aColumnIndex &&
_CGRectContainsPoint([self headerRectOfColumn:aColumnIndex], aPoint);
}
- (void)stopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
[self _setPressedColumn:CPNotFound];
[self _updateResizeCursor:[CPApp currentEvent]];
}
- (BOOL)_shouldDragTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
return [_tableView allowsColumnReordering] && ABS(aPoint.x - _mouseDownLocation.x) >= 10.0;
}
- (CGRect)_headerRectOfLastVisibleColumn
{
var tableColumns = [_tableView tableColumns],
tableSpacing = [_tableView intercellSpacing],
bounds = [self bounds];
columnIndex = [tableColumns count];
if (aColumnIndex < 0 || aColumnIndex > [tableColumns count])
[CPException raise:"invalid" reason:"tried to get headerRectOfColumn: on invalid column"];
while (columnIndex--)
{
var tableColumn = [tableColumns objectAtIndex:columnIndex];
bounds.size.width = [tableColumns[aColumnIndex] width] + tableSpacing.width;
if (![tableColumn isHidden])
return [self headerRectOfColumn:columnIndex];
}
while (--aColumnIndex >= 0)
bounds.origin.x += [tableColumns[aColumnIndex] width] + tableSpacing.width;
return nil;
}
return bounds;
- (void)_constrainDragView:(CPView)theDragView at:(CGPoint)aPoint
{
var tableColumns = [_tableView tableColumns],
lastColumnRect = [self _headerRectOfLastVisibleColumn],
activeColumnRect = [self headerRectOfColumn:_activeColumn],
dragWindow = [theDragView window],
frame = [dragWindow frame];
// Convert the frame origin from the global coordinate system to the windows' coordinate system
frame.origin = [[self window] convertGlobalToBase:frame.origin];
// the from the window to the view
frame.origin = [self convertPoint:frame.origin fromView:nil];
// This effectively clamps the value between the minimum and maximum
frame.origin.x = MAX(0.0, MIN(_CGRectGetMinX(frame), _CGRectGetMaxX(lastColumnRect) - _CGRectGetWidth(activeColumnRect)));
// Make sure the column cannot move vertically
frame.origin.y = _CGRectGetMinY(lastColumnRect);
// Convert the calculated origin back to the window coordinate system
frame.origin = [self convertPoint:frame.origin toView:nil];
// Then back to the global coordinate system
frame.origin = [[self window] convertBaseToGlobal:frame.origin];
[dragWindow setFrame:frame];
}
- (void)_moveColumn:(int)aFromIndex toColumn:(int)aToIndex
{
[_tableView moveColumn:aFromIndex toColumn:aToIndex];
_activeColumn = aToIndex;
_pressedColumn = _activeColumn;
}
- (void)draggedView:(CPView)aView beganAt:(CGPoint)aPoint
{
_isDragging = YES;
var column = [[_tableView tableColumns] objectAtIndex:_activeColumn];
[[column headerView] setHidden:YES];
[_tableView _setDraggedColumn:column];
[self setNeedsDisplay:YES];
}
- (void)draggedView:(CPView)aView movedTo:(CGPoint)aPoint
{
[self _constrainDragView:aView at:aPoint];
var dragWindow = [aView window],
dragWindowFrame = [dragWindow frame];
var hoverPoint = CGPointCreateCopy(aPoint);
if (aPoint.x < _previousTrackingLocation.x)
hoverPoint = _CGPointMake(_CGRectGetMinX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
else if (aPoint.x > _previousTrackingLocation.x)
hoverPoint = _CGPointMake(_CGRectGetMaxX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
// Convert the hover point from the global coordinate system to windows' coordinate system
hoverPoint = [[self window] convertGlobalToBase:hoverPoint];
// then to the view
hoverPoint = [self convertPoint:hoverPoint fromView:nil];
var hoveredColumn = [self columnAtPoint:hoverPoint];
if (hoveredColumn !== -1)
{
var columnRect = [self headerRectOfColumn:hoveredColumn],
columnCenterPoint = [self convertPoint:CGPointMake(_CGRectGetMidX(columnRect), _CGRectGetMidY(columnRect)) fromView:self];
if (hoveredColumn < _activeColumn && hoverPoint.x < columnCenterPoint.x)
[self _moveColumn:_activeColumn toColumn:hoveredColumn];
else if (hoveredColumn > _activeColumn && hoverPoint.x > columnCenterPoint.x)
[self _moveColumn:_activeColumn toColumn:hoveredColumn];
}
_previousTrackingLocation = aPoint;
}
- (void)draggedView:(CPImage)aView endedAt:(CGPoint)aLocation operation:(CPDragOperation)anOperation
{
_isDragging = NO;
_isTrackingColumn = NO; // We need to do this explicitly because the mouse up section of trackMouse is never reached
[_tableView _setDraggedColumn:nil];
[[[[_tableView tableColumns] objectAtIndex:_activeColumn] headerView] setHidden:NO];
[self stopTrackingTableColumn:_activeColumn at:aLocation];
[self setNeedsDisplay:YES];
}
- (BOOL)shouldResizeTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
if (_isResizing)
return YES;
if (_isTrackingColumn)
return NO;
return [_tableView allowsColumnResizing] && _CGRectContainsPoint([self _cursorRectForColumn:aColumnIndex], aPoint);
}
- (void)startResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
_isResizing = YES;
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
[tableColumn setDisableResizingPosting:YES];
[_tableView setDisableAutomaticResizing:YES];
}
- (void)continueResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex],
newWidth = [tableColumn width] + aPoint.x - _previousTrackingLocation.x;
if (newWidth < [tableColumn minWidth])
[[CPCursor resizeRightCursor] set];
else if (newWidth > [tableColumn maxWidth])
[[CPCursor resizeLeftCursor] set];
else
{
_tableView._lastColumnShouldSnap = NO;
[tableColumn setWidth:newWidth];
[[CPCursor resizeLeftRightCursor] set];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
}
- (void)stopResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
[tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
[tableColumn setDisableResizingPosting:NO];
[_tableView setDisableAutomaticResizing:NO];
_isResizing = NO;
}
- (void)_updateResizeCursor:(CPEvent)theEvent
{
// never get stuck in resize cursor mode (FIXME take out when we turn on tracking rects)
if (![_tableView allowsColumnResizing] || ([theEvent type] === CPLeftMouseUp && ![[self window] acceptsMouseMovedEvents]))
{
[[CPCursor arrowCursor] set];
return;
}
var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
mouseOverLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
overColumn = [self columnAtPoint:mouseOverLocation];
if (overColumn >= 0 && _CGRectContainsPoint([self _cursorRectForColumn:overColumn], mouseLocation))
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn],
width = [tableColumn width];
if (width == [tableColumn minWidth])
[[CPCursor resizeRightCursor] set];
else if (width == [tableColumn maxWidth])
[[CPCursor resizeLeftCursor] set];
else
[[CPCursor resizeLeftRightCursor] set];
}
else
[[CPCursor arrowCursor] set];
}
- (void)mouseEntered:(CPEvent)theEvent
{
[self _updateResizeCursor:theEvent];
}
- (void)mouseMoved:(CPEvent)theEvent
{
[self _updateResizeCursor:theEvent];
}
- (void)mouseExited:(CPEvent)theEvent
{
// FIXME: we should use CPCursor push/pop (if previous currentCursor != arrow).
[[CPCursor arrowCursor] set];
}
- (void)layoutSubviews
{
var tableColumns = [_tableView tableColumns],
count = [tableColumns count],
columnRect = [self bounds],
spacing = [_tableView intercellSpacing];
for (i = 0; i < count; ++i)
var tableColumns = [_tableView tableColumns],
count = [tableColumns count];
for (var i = 0; i < count; i++)
{
var column = [tableColumns objectAtIndex:i],
headerView = [column headerView];
headerView = [column headerView],
frame = [self headerRectOfColumn:i];
columnRect.size.width = [column width] + spacing.width;
// Make space for the gridline on the right.
frame.origin.x -= 0.5;
frame.size.width -= 1.0;
frame.size.height -= 0.5;
// Note: we're not adding in intercell spacing here. This setting only affects the regular
// table cell data views, not the header. Verified in Cocoa on March 29th, 2011.
[headerView setFrame:columnRect];
[headerView setFrame:frame];
columnRect.origin.x += [column width] + spacing.width;
[self addSubview:headerView];
if ([headerView superview] != self)
[self addSubview:headerView];
}
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
}
- (void)drawRect:(CGRect)aRect
{
[[_tableView gridColor] setStroke];
if (!_tableView || ![self drawsColumnLines])
return;
var context = [[CPGraphicsContext currentContext] graphicsPort],
exposedColumnIndexes = exposedColumnIndexes = [_tableView columnIndexesInRect:aRect],
columnsArray = [];
exposedColumnIndexes = [_tableView columnIndexesInRect:aRect],
columnsArray = [],
tableColumns = [_tableView tableColumns],
exposedTableColumns = _tableView._exposedColumns,
firstIndex = [exposedTableColumns firstIndex],
exposedRange = CPMakeRange(firstIndex, [exposedTableColumns lastIndex] - firstIndex + 1);
[exposedColumnIndexes getIndexes:columnsArray maxCount:-1 inIndexRange:nil];
CGContextSetLineWidth(context, 1);
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"divider-color"]);
[exposedColumnIndexes getIndexes:columnsArray maxCount:-1 inIndexRange:exposedRange];
var columnArrayIndex = 0,
columnArrayCount = columnsArray.length;
columnArrayCount = columnsArray.length,
columnMaxX;
for(; columnArrayIndex < columnArrayCount; ++columnArrayIndex)
CGContextBeginPath(context);
for (; columnArrayIndex < columnArrayCount; columnArrayIndex++)
{
// grab each column rect and add horizontal lines
var columnToStroke = [self headerRectOfColumn:columnArrayIndex];
// grab each column rect and add vertical lines
var columnIndex = columnsArray[columnArrayIndex],
columnToStroke = [self headerRectOfColumn:columnIndex];
CGContextBeginPath(context);
CGContextMoveToPoint(context, ROUND(columnToStroke.origin.x + columnToStroke.size.width) - 0.5, ROUND(columnToStroke.origin.y) - 0.5);
CGContextAddLineToPoint(context, ROUND(columnToStroke.origin.x + columnToStroke.size.width) - 0.5, ROUND(columnToStroke.origin.y + columnToStroke.size.height) - 0.5);
CGContextSetLineWidth(context, 1);
CGContextStrokePath(context);
columnMaxX = _CGRectGetMaxX(columnToStroke);
CGContextMoveToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMinY(columnToStroke)));
CGContextAddLineToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMaxY(columnToStroke)));
}
CGContextClosePath(context);
CGContextStrokePath(context);
/*if (_isDragging)
{
CGContextSetFillColor(context, [CPColor grayColor]);
CGContextFillRect(context, [self headerRectOfColumn:_activeColumn])
}*/
}
@end
var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey",
CPTableHeaderViewDrawsColumnLines = @"CPTableHeaderViewDrawsColumnLines";
@implementation CPTableHeaderView (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
[self _init];
_tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
// 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;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_tableView forKey:CPTableHeaderViewTableViewKey];
[aCoder encodeBool:_drawsColumnLines forKey:CPTableHeaderViewDrawsColumnLines];
}
@end
+3572 -418
View File
File diff suppressed because it is too large Load Diff
+30
View File
@@ -0,0 +1,30 @@
/*
* CPText.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2010, WireLoad, LLC.
*
* 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
*/
CPEnterCharacter = "\u0003";
CPBackspaceCharacter = "\u0008";
CPTabCharacter = "\u0009";
CPNewlineCharacter = "\u000a";
CPFormFeedCharacter = "\u000c";
CPCarriageReturnCharacter = "\u000d";
CPBackTabCharacter = "\u0019";
CPDeleteCharacter = "\u007f";
+565 -150
View File
File diff suppressed because it is too large Load Diff
+189 -20
View File
@@ -22,10 +22,12 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@import <Foundation/CPKeyedUnarchiver.j>
var CPThemesByName = { },
CPThemeDefaultTheme = nil;
var CPThemesByName = { },
CPThemeDefaultTheme = nil,
CPThemeDefaultHudTheme = nil;
/*!
@@ -48,6 +50,27 @@ var CPThemesByName = { },
return CPThemeDefaultTheme;
}
/*!
Set the default HUD theme. If set to nil, the default described in defaultHudTheme
will be used.
*/
+ (void)setDefaultHudTheme:(CPTheme)aTheme
{
CPThemeDefaultHudTheme = aTheme;
}
/*!
The default HUD theme is (sometimes) used for windows with the CPHUDBackgroundWindowMask
style mask. The default is theme with the name of the default theme with -HUD appended
at the end.
*/
+ (CPTheme)defaultHudTheme
{
if (!CPThemeDefaultHudTheme)
CPThemeDefaultHudTheme = [CPTheme themeNamed:[[self defaultTheme] name] + "-HUD"];
return CPThemeDefaultHudTheme;
}
+ (CPTheme)themeNamed:(CPString)aName
{
return CPThemesByName[aName];
@@ -73,9 +96,110 @@ var CPThemesByName = { },
return _name;
}
- (_CPThemeAttribute)_attributeWithName:(CPString)aName forClass:(CPString)aClass
/*!
Returns an array of names of themed classes defined in this theme, as found in its
ThemeDescriptors.j file.
NOTE: The names are not class names (such as "CPButton"), but the names returned
by the class' +defaultThemeClass method. For example, the name for CPCheckBox is "check-box",
as defined in CPCheckBox::themeClass.
*/
- (CPArray)classNames
{
var attributes = [_attributes objectForKey:aClass];
return [_attributes allKeys];
}
/*!
Returns a dictionary of all theme attributes defined for the given class, as found in the
theme's ThemeDescriptors.j file. The keys of the dictionary are attribute names, and the values
are instances of _CPThemeAttribute.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aClass The themed class whose attributes you want to retrieve
@return A dictionary of attributes or nil
*/
- (CPDictionary)attributesForClass:(id)aClass
{
if (!aClass)
return nil;
var className = nil;
if ([aClass isKindOfClass:[CPString class]])
{
// See if it is a class name
var theClass = CPClassFromString(aClass);
if (theClass)
aClass = theClass;
else
className = aClass;
}
if (!className)
{
if ([aClass isKindOfClass:[CPView class]])
{
if ([aClass respondsToSelector:@selector(defaultThemeClass)])
className = [aClass defaultThemeClass];
else if ([aClass respondsToSelector:@selector(themeClass)])
{
CPLog.warn(@"%@ themeClass is deprecated in favor of defaultThemeClass",CPStringFromClass([anObject class]));
className = [aClass themeClass];
}
else
return nil;
}
else
[CPException raise:CPInvalidArgumentException reason:@"aClass must be a class object or a string."];
}
return [_attributes objectForKey:className];
}
/*!
Returns an array of names of all theme attributes defined for the given class, as found in the
theme's ThemeDescriptors.j file.
The \c aClass parameter can be one of the following:
- A class instance, for example the result of [CPCheckBox class]. The class must be a subclass
of CPView.
- A class name, for example "CPCheckBox".
- A themed class name, for example "check-box".
If \c aClass does not refer to a themed class in this theme, nil is returned.
@param aClass The themed class whose attributes you want to retrieve
@return An array of attribute names or nil
*/
- (CPDictionary)attributeNamesForClass:(id)aClass
{
var attributes = [self attributesForClass:aClass];
if (attributes)
return [attributes allKeys];
else
return [CPArray array];
}
/*!
Returns a theme attribute defined for the given class, as found in the
theme's ThemeDescriptors.j file.
\c aName should be the attribute name as you would pass to the method
CPView::valueForThemeAttribute:.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aName The name of the attribute you want to retrieve
@param aClass The themed class in which to look for the attribute
@return An instance of _CPThemeAttribute or nil
*/
- (_CPThemeAttribute)attributeWithName:(CPString)aName forClass:(id)aClass
{
var attributes = [self attributesForClass:aClass];
if (!attributes)
return nil;
@@ -83,12 +207,53 @@ var CPThemesByName = { },
return [attributes objectForKey:aName];
}
/*!
Returns the value for a theme attribute in its normal state, as defined for the given class
in the theme's ThemeDescriptors.j file.
\c aName should be the attribute name as you would pass to the method
CPView::valueForThemeAttribute:.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aName The name of the attribute whose value you want to retrieve
@param aClass The themed class in which to look for the attribute
@return A value or nil
*/
- (id)valueForAttributeWithName:(CPString)aName forClass:(id)aClass
{
return [self valueForAttributeWithName:aName inState:CPThemeStateNormal forClass:aClass];
}
/*!
Returns the value for a theme attribute in a given state, as defined for the given class
in the theme's ThemeDescriptors.j file. This is the equivalent of the method
CPView::valueForThemeAttribute:inState:, but retrieves the value from the theme definition as
opposed to a single view's current theme state.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aName The name of the attribute whose value you want to retrieve
@param aState The state qualifier for the attribute
@param aClass The themed class in which to look for the attribute
@return A value or nil
*/
- (id)valueForAttributeWithName:(CPString)aName inState:(CPThemeState)aState forClass:(id)aClass
{
var attribute = [self attributeWithName:aName forClass:aClass];
if (!attribute)
return nil;
return [attribute valueForState:aState];
}
- (void)takeThemeFromObject:(id)anObject
{
var attributes = [anObject _themeAttributeDictionary],
attributeName = nil,
attributeNames = [attributes keyEnumerator],
objectThemeClass = [[anObject class] themeClass];
objectThemeClass = [anObject themeClass];
while (attributeName = [attributeNames nextObject])
[self _recordAttribute:[attributes objectForKey:attributeName] forClass:objectThemeClass];
@@ -240,8 +405,12 @@ 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");
CPThemeStateSelectedDataView = CPThemeStateSelectedTableDataView = CPThemeState("selectedTableDataView");
CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
CPThemeStateBezeled = CPThemeState("bezeled");
CPThemeStateBordered = CPThemeState("bordered");
CPThemeStateEditable = CPThemeState("editable");
@@ -254,10 +423,10 @@ CPThemeStateCircular = CPThemeState("circular");
{
CPString _name;
id _defaultValue;
CPDictionary _values;
CPDictionary _values @accessors(readonly, getter=values);
JSObject _cache;
CPThemeAttribute _parentAttribute;
_CPThemeAttribute _parentAttribute;
}
- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue
@@ -378,7 +547,7 @@ CPThemeStateCircular = CPThemeState("circular");
return value;
}
- (void)setParentAttribute:(CPThemeAttribute)anAttribute
- (void)setParentAttribute:(_CPThemeAttribute)anAttribute
{
if (_parentAttribute === anAttribute)
return;
@@ -387,7 +556,7 @@ CPThemeStateCircular = CPThemeState("circular");
_parentAttribute = anAttribute;
}
- (CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
- (_CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
{
var mergedAttribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue];
@@ -472,15 +641,15 @@ CPThemeStateCircular = CPThemeState("circular");
@end
var cachedNumberOfOnes = [ 0 /*000000*/, 1 /*000001*/, 1 /*000010*/, 2 /*000011*/, 1 /*000100*/, 2 /*000101*/, 2 /*000110*/,
3 /*000111*/, 1 /*001000*/, 2 /*001001*/, 2 /*001010*/, 3 /*001011*/, 2 /*001100*/, 3 /*001101*/,
3 /*001110*/, 4 /*001111*/, 1 /*010000*/, 2 /*010001*/, 2 /*010010*/, 3 /*010011*/, 2 /*010100*/,
3 /*010101*/, 3 /*010110*/, 4 /*010111*/, 2 /*011000*/, 3 /*011001*/, 3 /*011010*/, 4 /*011011*/,
3 /*011100*/, 4 /*011101*/, 4 /*011110*/, 5 /*011111*/, 1 /*100000*/, 2 /*100001*/, 2 /*100010*/,
3 /*100011*/, 2 /*100100*/, 3 /*100101*/, 3 /*100110*/, 4 /*100111*/, 2 /*101000*/, 3 /*101001*/,
3 /*101010*/, 4 /*101011*/, 3 /*101100*/, 4 /*101101*/, 4 /*101110*/, 5 /*101111*/, 2 /*110000*/,
3 /*110001*/, 3 /*110010*/, 4 /*110011*/, 3 /*110100*/, 4 /*110101*/, 4 /*110110*/, 5 /*110111*/,
3 /*111000*/, 4 /*111001*/, 4 /*111010*/, 5 /*111011*/, 4 /*111100*/, 5 /*111101*/, 5 /*111110*/,
var cachedNumberOfOnes = [ 0 /*000000*/, 1 /*000001*/, 1 /*000010*/, 2 /*000011*/, 1 /*000100*/, 2 /*000101*/, 2 /*000110*/,
3 /*000111*/, 1 /*001000*/, 2 /*001001*/, 2 /*001010*/, 3 /*001011*/, 2 /*001100*/, 3 /*001101*/,
3 /*001110*/, 4 /*001111*/, 1 /*010000*/, 2 /*010001*/, 2 /*010010*/, 3 /*010011*/, 2 /*010100*/,
3 /*010101*/, 3 /*010110*/, 4 /*010111*/, 2 /*011000*/, 3 /*011001*/, 3 /*011010*/, 4 /*011011*/,
3 /*011100*/, 4 /*011101*/, 4 /*011110*/, 5 /*011111*/, 1 /*100000*/, 2 /*100001*/, 2 /*100010*/,
3 /*100011*/, 2 /*100100*/, 3 /*100101*/, 3 /*100110*/, 4 /*100111*/, 2 /*101000*/, 3 /*101001*/,
3 /*101010*/, 4 /*101011*/, 3 /*101100*/, 4 /*101101*/, 4 /*101110*/, 5 /*101111*/, 2 /*110000*/,
3 /*110001*/, 3 /*110010*/, 4 /*110011*/, 3 /*110100*/, 4 /*110101*/, 4 /*110110*/, 5 /*110111*/,
3 /*111000*/, 4 /*111001*/, 4 /*111010*/, 5 /*111011*/, 4 /*111100*/, 5 /*111101*/, 5 /*111110*/,
6 /*111111*/ ];
var numberOfOnes = function(aNumber)
@@ -551,7 +720,7 @@ function CPThemeAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme,
}
if (aTheme && aClass)
[attribute setParentAttribute:[aTheme _attributeWithName:anAttributeName forClass:aClass]];
[attribute setParentAttribute:[aTheme attributeWithName:anAttributeName forClass:aClass]];
return attribute;
}
@@ -585,4 +754,4 @@ for (i = 0;i < Math.pow(2,6);++i)
}
print(str+']');
*/
*/
+36 -12
View File
@@ -22,9 +22,10 @@
@import <Foundation/CPObject.j>
@import <AppKit/CPTheme.j>
@import <AppKit/_CPCibCustomResource.j>
@import <AppKit/_CPCibKeyedUnarchiver.j>
@import "CPTheme.j"
@import "_CPCibCustomResource.j"
@import "_CPCibKeyedUnarchiver.j"
/*!
@ingroup appkit
@@ -33,39 +34,62 @@
@implementation CPThemeBlend : CPObject
{
CPBundle _bundle;
CPArray _themes @accessors(readonly, getter=themes);
CPArray _themes;
id _loadDelegate;
}
- (id)initWithContentsOfURL:(CPURL)aURL
{
self = [super init];
if (self)
{
_bundle = [[CPBundle alloc] initWithPath:aURL + "/Info.plist"];
_bundle = [[CPBundle alloc] initWithPath:aURL];
}
return self;
}
/*!
Returns an array of names of the keyed theme archives that make up this blend.
Each item in the array will have the extension ".keyedtheme".
*/
- (CPArray)themes
{
return _themes;
}
/*!
Returns an array of names of the themes that make up this blend.
*/
- (CPArray)themeNames
{
var names = [];
for (var i = 0; i < _themes.length; ++i)
names.push(_themes[i].substring(0, _themes[i].indexOf(".keyedtheme")));
return names;
}
- (void)loadWithDelegate:(id)aDelegate
{
_loadDelegate = aDelegate;
[_bundle loadWithDelegate:self];
}
- (void)bundleDidFinishLoading:(CPBundle)aBundle
{
var themes = [_bundle objectForInfoDictionaryKey:@"CPKeyedThemes"],
count = themes.length;
_themes = [_bundle objectForInfoDictionaryKey:@"CPKeyedThemes"];
var count = _themes.length;
while (count--)
{
var path = [aBundle pathForResource:themes[count]],
var path = [aBundle pathForResource:_themes[count]],
unarchiver = [[_CPThemeKeyedUnarchiver alloc]
initForReadingWithData:[CPData dataWithString:objj_files[path].contents]
initForReadingWithData:[[CPURL URLWithString:path] staticResourceData]
bundle:_bundle];
[unarchiver decodeObjectForKey:@"root"];
+1294
View File
File diff suppressed because it is too large Load Diff
+247 -131
View File
@@ -28,8 +28,6 @@
@import "CPPopUpButton.j"
@import "CPToolbarItem.j"
#include "CoreGraphics/CGGeometry.h"
/*
@global
@@ -52,13 +50,13 @@ CPToolbarDisplayModeIconOnly = 2;
*/
CPToolbarDisplayModeLabelOnly = 3;
var CPToolbarsByIdentifier = nil;
var CPToolbarConfigurationsByIdentifier = nil;
var CPToolbarsByIdentifier = nil,
CPToolbarConfigurationsByIdentifier = nil;
/*!
@ingroup appkit
@class CPToolbar
A CPToolbar is displayed at the top of a window with multiple
buttons (tools) that offer the user quick access to features.
@@ -73,7 +71,7 @@ var CPToolbarConfigurationsByIdentifier = nil;
Called to obtain the toolbar's default item identifiers. Required.
@param toolbar the toolbar to obtain identifiers for
@return an array of default item identifiers in the order on the toolbar
@delegate - (CPToolbarItem)toolbar:(CPToolbar)toolbar itemForItemIdentifier:(CPString)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag;
Called to obtain a toolbar item. Required.
@param toolbar the toolbar the item belongs to
@@ -89,19 +87,19 @@ var CPToolbarConfigurationsByIdentifier = nil;
BOOL _showsBaselineSeparator;
BOOL _allowsUserCustomization;
BOOL _isVisible;
id _delegate;
CPArray _itemIdentifiers;
CPDictionary _identifiedItems;
CPArray _defaultItems;
CPArray _allowedItems;
CPArray _selectableItems;
CPArray _items;
CPArray _itemsSortedByVisibilityPriority;
CPView _toolbarView;
CPWindow _window;
}
@@ -111,7 +109,7 @@ var CPToolbarConfigurationsByIdentifier = nil;
{
if (self != [CPToolbar class])
return;
CPToolbarsByIdentifier = [CPDictionary dictionary];
CPToolbarConfigurationsByIdentifier = [CPDictionary dictionary];
}
@@ -120,13 +118,13 @@ var CPToolbarConfigurationsByIdentifier = nil;
+ (void)_addToolbar:(CPToolbar)toolbar forIdentifier:(CPString)identifier
{
var toolbarsSharingIdentifier = [CPToolbarsByIdentifier objectForKey:identifier];
if (!toolbarsSharingIdentifier)
{
toolbarsSharingIdentifier = []
[CPToolbarsByIdentifier setObject:toolbarsSharingIdentifier forKey:identifier];
}
[toolbarsSharingIdentifier addObject:toolbar];
}
@@ -143,17 +141,17 @@ var CPToolbarConfigurationsByIdentifier = nil;
- (id)initWithIdentifier:(CPString)anIdentifier
{
self = [super init];
if (self)
{
_items = [];
_identifier = anIdentifier;
_isVisible = YES;
[CPToolbar _addToolbar:self forIdentifier:_identifier];
}
return self;
}
@@ -163,7 +161,7 @@ var CPToolbarConfigurationsByIdentifier = nil;
*/
- (void)setDisplayMode:(CPToolbarDisplayMode)aDisplayMode
{
}
/*!
@@ -198,7 +196,7 @@ var CPToolbarConfigurationsByIdentifier = nil;
{
if (_isVisible === aFlag)
return;
_isVisible = aFlag;
[_window _noteToolbarChanged];
@@ -220,11 +218,11 @@ var CPToolbarConfigurationsByIdentifier = nil;
*/
- (void)setDelegate:(id)aDelegate
{
if (_delegate == aDelegate)
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
[self _reloadToolbarItems];
}
@@ -240,57 +238,68 @@ var CPToolbarConfigurationsByIdentifier = nil;
if (!_toolbarView)
{
_toolbarView = [[_CPToolbarView alloc] initWithFrame:CPRectMake(0.0, 0.0, 1200.0, 59.0)];
[_toolbarView setToolbar:self];
[_toolbarView setAutoresizingMask:CPViewWidthSizable];
[_toolbarView reloadToolbarItems];
}
return _toolbarView;
}
/* @ignore */
- (void)_reloadToolbarItems
{
if (!_delegate)
return;
// As of OS X 10.5 (Leopard), toolbar items can be set in IB and a
// toolbar delegate is optional. Toolbar items can be combined from
// both IB and a delegate (see Apple's NSToolbar guide for IB, for more details).
var count = [_itemIdentifiers count];
if (!count)
// _defaultItems may have been loaded from Cib
_itemIdentifiers = [_defaultItems valueForKey:@"itemIdentifier"] || [];
if (_delegate)
{
_itemIdentifiers = [[_delegate toolbarDefaultItemIdentifiers:self] mutableCopy];
count = [_itemIdentifiers count];
var itemIdentifiersFromDelegate = [[_delegate toolbarDefaultItemIdentifiers:self] mutableCopy];
if (itemIdentifiersFromDelegate)
_itemIdentifiers = [_itemIdentifiers arrayByAddingObjectsFromArray:itemIdentifiersFromDelegate];
}
var index = 0,
count = [_itemIdentifiers count];
_items = [];
var index = 0;
for (; index < count; ++index)
{
var identifier = _itemIdentifiers[index],
item = [CPToolbarItem _standardItemWithItemIdentifier:identifier];
// May come from a Cib.
if (!item)
item = [_identifiedItems objectForKey:identifier];
if (!item && _delegate)
item = [_delegate toolbar:self itemForItemIdentifier:identifier willBeInsertedIntoToolbar:YES];
item = [item copy];
if (item == nil)
if (item === nil)
[CPException raise:CPInvalidArgumentException
reason:sprintf(@"_delegate %s returned nil toolbar item returned for identifier %s", _delegate, identifier)];
reason:@"Toolbar delegate " + _delegate + " returned nil toolbar item for identifier \"" + identifier + "\""];
item._toolbar = self;
[_items addObject:item];
}
// _items = [[self _defaultToolbarItems] mutableCopy];
// Store items sorted by priority. We want items to be removed first at the end of the array,
// items to be removed last at the front.
_itemsSortedByVisibilityPriority = [_items sortedArrayUsingFunction:_CPToolbarItemVisibilityPriorityCompare context:NULL];
[_toolbarView reloadToolbarItems];
}
@@ -318,7 +327,11 @@ var CPToolbarConfigurationsByIdentifier = nil;
return _itemsSortedByVisibilityPriority;
}
- (void)validateVisibleToolbarItems
/*!
Validates the visible toolbar items by sending a validate message to
each visible toolbar item.
*/
- (void)validateVisibleItems
{
var toolbarItems = [self visibleItems],
count = [toolbarItems count];
@@ -339,9 +352,9 @@ var CPToolbarConfigurationsByIdentifier = nil;
item = [[_delegate toolbar:self itemForItemIdentifier:identifier willBeInsertedIntoToolbar:toolbar] copy];
if (!item)
[CPException raise:CPInvalidArgumentException
reason:sprintf(@"_delegate %s returned nil toolbar item returned for identifier %s", _delegate, identifier)];
reason:@"Toolbar delegate " + _delegate + " returned nil toolbar item for identifier " + identifier];
}
[_identifiedItems setObject:item forKey:identifier];
}
@@ -350,7 +363,7 @@ var CPToolbarConfigurationsByIdentifier = nil;
/* @ignore */
- (id)_itemsWithIdentifiers:(CPArray)identifiers
{
{
var items = [];
for (var i = 0; i < identifiers.length; i++)
[items addObject:[self _itemForItemIdentifier:identifiers[i] willBeInsertedIntoToolbar:NO]];
@@ -359,28 +372,62 @@ var CPToolbarConfigurationsByIdentifier = nil;
}
/* @ignore */
-(id)_defaultToolbarItems
- (id)_defaultToolbarItems
{
if (!_defaultItems)
if ([_delegate respondsToSelector:@selector(toolbarDefaultItemIdentifiers:)])
_defaultItems = [self _itemsWithIdentifiers:[_delegate toolbarDefaultItemIdentifiers:self]];
if (!_defaultItems && [_delegate respondsToSelector:@selector(toolbarDefaultItemIdentifiers:)])
{
_defaultItems = [];
var identifiers = [_delegate toolbarDefaultItemIdentifiers:self],
index = 0,
count = [identifiers count];
for (; index < count; ++index)
[_defaultItems addObject:[self _itemForItemIdentifier:identifiers[index] willBeInsertedIntoToolbar:NO]];
}
return _defaultItems;
}
/*!
Notifies the toolbar that an item has been changed. This will cause the toolbar to reload its items.
@param anItem the item that has been changed
*/
- (void)toolbarItemDidChange:(CPToolbarItem)anItem
{
if ([_identifiedItems objectForKey:[anItem itemIdentifier]])
[_identifiedItems setObject:anItem forKey:[anItem itemIdentifier]];
var index = 0,
count = [_items count];
for (; index <= count; ++index)
{
var item = _items[index];
if ([item itemIdentifier] === [anItem itemIdentifier])
{
_items[index] = anItem;
_itemsSortedByVisibilityPriority = [_items sortedArrayUsingFunction:_CPToolbarItemVisibilityPriorityCompare context:NULL];
[_toolbarView reloadToolbarItems];
}
}
}
@end
var CPToolbarIdentifierKey = "CPToolbarIdentifierKey",
CPToolbarDisplayModeKey = "CPToolbarDisplayModeKey",
CPToolbarShowsBaselineSeparatorKey = "CPToolbarShowsBaselineSeparatorKey",
CPToolbarAllowsUserCustomizationKey = "CPToolbarAllowsUserCustomizationKey",
CPToolbarIsVisibleKey = "CPToolbarIsVisibleKey",
CPToolbarDelegateKey = "CPToolbarDelegateKey",
CPToolbarIdentifiedItemsKey = "CPToolbarIdentifiedItemsKey",
CPToolbarDefaultItemsKey = "CPToolbarDefaultItemsKey",
CPToolbarAllowedItemsKey = "CPToolbarAllowedItemsKey",
CPToolbarSelectableItemsKey = "CPToolbarSelectableItemsKey";
var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
CPToolbarDisplayModeKey = @"CPToolbarDisplayModeKey",
CPToolbarShowsBaselineSeparatorKey = @"CPToolbarShowsBaselineSeparatorKey",
CPToolbarAllowsUserCustomizationKey = @"CPToolbarAllowsUserCustomizationKey",
CPToolbarIsVisibleKey = @"CPToolbarIsVisibleKey",
CPToolbarDelegateKey = @"CPToolbarDelegateKey",
CPToolbarIdentifiedItemsKey = @"CPToolbarIdentifiedItemsKey",
CPToolbarDefaultItemsKey = @"CPToolbarDefaultItemsKey",
CPToolbarAllowedItemsKey = @"CPToolbarAllowedItemsKey",
CPToolbarSelectableItemsKey = @"CPToolbarSelectableItemsKey";
@implementation CPToolbar (CPCoding)
@@ -391,26 +438,46 @@ var CPToolbarIdentifierKey = "CPToolbarIdentifierKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_identifier = [aCoder decodeObjectForKey:CPToolbarIdentifierKey];
_displayMode = [aCoder decodeIntForKey:CPToolbarDisplayModeKey];
_showsBaselineSeparator = [aCoder decodeBoolForKey:CPToolbarShowsBaselineSeparatorKey];
_allowsUserCustomization = [aCoder decodeBoolForKey:CPToolbarAllowsUserCustomizationKey];
_isVisible = [aCoder decodeBoolForKey:CPToolbarIsVisibleKey];
_identifiedItems = [aCoder decodeObjectForKey:CPToolbarIdentifiedItemsKey];
_defaultItems = [aCoder decodeObjectForKey:CPToolbarDefaultItemsKey];
_allowedItems = [aCoder decodeObjectForKey:CPToolbarAllowedItemsKey];
_selectableItems = [aCoder decodeObjectForKey:CPToolbarSelectableItemsKey];
_identifier = [aCoder decodeObjectForKey:CPToolbarIdentifierKey];
_displayMode = [aCoder decodeIntForKey:CPToolbarDisplayModeKey];
_showsBaselineSeparator = [aCoder decodeBoolForKey:CPToolbarShowsBaselineSeparatorKey];
_allowsUserCustomization = [aCoder decodeBoolForKey:CPToolbarAllowsUserCustomizationKey];
_isVisible = [aCoder decodeBoolForKey:CPToolbarIsVisibleKey];
_identifiedItems = [aCoder decodeObjectForKey:CPToolbarIdentifiedItemsKey];
_defaultItems = [aCoder decodeObjectForKey:CPToolbarDefaultItemsKey];
_allowedItems = [aCoder decodeObjectForKey:CPToolbarAllowedItemsKey];
_selectableItems = [aCoder decodeObjectForKey:CPToolbarSelectableItemsKey];
[[_identifiedItems allValues] makeObjectsPerformSelector:@selector(_setToolbar:) withObject:self];
_items = [];
[CPToolbar _addToolbar:self forIdentifier:_identifier];
// This won't come from a Cib, but can come from manual encoding.
[self setDelegate:[aCoder decodeObjectForKey:CPToolbarDelegateKey]];
// 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. 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?
// Do this at the end of the run loop to allow all the cib-stuff to
// finish (establishing connections, etc.).
[[CPRunLoop currentRunLoop]
performSelector:@selector(_reloadToolbarItems)
target:self
argument:nil
order:0 modes:[CPDefaultRunLoopMode]];
}
return self;
}
@@ -420,18 +487,18 @@ var CPToolbarIdentifierKey = "CPToolbarIdentifierKey",
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_identifier forKey:CPToolbarIdentifierKey];
[aCoder encodeInt:_displayMode forKey:CPToolbarDisplayModeKey];
[aCoder encodeBool:_showsBaselineSeparator forKey:CPToolbarShowsBaselineSeparatorKey];
[aCoder encodeObject:_identifier forKey:CPToolbarIdentifierKey];
[aCoder encodeInt:_displayMode forKey:CPToolbarDisplayModeKey];
[aCoder encodeBool:_showsBaselineSeparator forKey:CPToolbarShowsBaselineSeparatorKey];
[aCoder encodeBool:_allowsUserCustomization forKey:CPToolbarAllowsUserCustomizationKey];
[aCoder encodeBool:_isVisible forKey:CPToolbarIsVisibleKey];
[aCoder encodeObject:_identifiedItems forKey:CPToolbarIdentifiedItemsKey];
[aCoder encodeObject:_defaultItems forKey:CPToolbarDefaultItemsKey];
[aCoder encodeObject:_allowedItems forKey:CPToolbarAllowedItemsKey];
[aCoder encodeObject:_selectableItems forKey:CPToolbarSelectableItemsKey];
[aCoder encodeConditionalObject:_delegate forKey:CPToolbarDelegateKey];
[aCoder encodeBool:_isVisible forKey:CPToolbarIsVisibleKey];
[aCoder encodeObject:_identifiedItems forKey:CPToolbarIdentifiedItemsKey];
[aCoder encodeObject:_defaultItems forKey:CPToolbarDefaultItemsKey];
[aCoder encodeObject:_allowedItems forKey:CPToolbarAllowedItemsKey];
[aCoder encodeObject:_selectableItems forKey:CPToolbarSelectableItemsKey];
[aCoder encodeConditionalObject:_delegate forKey:CPToolbarDelegateKey];
}
@end
@@ -454,10 +521,10 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
@implementation _CPToolbarView : CPView
{
CPToolbar _toolbar;
CPIndexSet _flexibleWidthIndexes;
CPIndexSet _visibleFlexibleWidthIndexes;
CPDictionary _itemInfos;
JSObject _viewsForToolbarItems;
@@ -467,7 +534,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
CPPopUpButton _additionalItemsButton;
CPColor _labelColor;
CPColor _labelShadowColor;
float _minWidth;
BOOL _FIXME_isHUD;
@@ -475,11 +542,11 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
+ (void)initialize
{
if (self != [_CPToolbarView class])
if (self !== [_CPToolbarView class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPToolbarViewExtraItemsImage = [[CPImage alloc] initWithContentsOfFile: [bundle pathForResource:"_CPToolbarView/_CPToolbarViewExtraItemsImage.png"] size: CPSizeMake(10.0, 15.0)];
_CPToolbarViewExtraItemsAlternateImage = [[CPImage alloc] initWithContentsOfFile: [bundle pathForResource:"_CPToolbarView/_CPToolbarViewExtraItemsAlternateImage.png"] size:CGSizeMake(10.0, 15.0)];
@@ -488,23 +555,24 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_minWidth = 0;
_labelColor = [CPColor blackColor];
_labelShadowColor = [CPColor colorWithWhite:1.0 alpha:0.75];
_additionalItemsButton = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 15.0) pullsDown:YES];
[_additionalItemsButton setBordered:NO];
[_additionalItemsButton setImagePosition:CPImageOnly];
[[_additionalItemsButton menu] setShowsStateColumn:NO];
[[_additionalItemsButton menu] setAutoenablesItems:NO];
[_additionalItemsButton setAlternateImage:_CPToolbarViewExtraItemsAlternateImage];
}
return self;
}
@@ -551,17 +619,17 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
minWidth = _minWidth,
// FIXME: This should be a CPSet.
invisibleItemsSortedByPriority = [];
_visibleItems = items;
// We only have hidden items if our actual width is smaller than our
// We only have hidden items if our actual width is smaller than our
// minimum width for hiding items.
if (itemsWidth < minWidth)
{
itemsWidth -= TOOLBAR_EXTRA_ITEMS_WIDTH;
_visibleItems = [_visibleItems copy];
var itemsSortedByVisibilityPriority = [_toolbar itemsSortedByVisibilityPriority],
count = itemsSortedByVisibilityPriority.length;
@@ -599,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--)
@@ -620,18 +688,18 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
[view setHidden:NO];
}
var remainingSpace = itemsWidth - minWidth,
proportionate = 0.0;
// Continue to distribute space proportionately while we have it,
// and there are flexible items left that want it. (Those with max
// Continue to distribute space proportionately while we have it,
// and there are flexible items left that want it. (Those with max
// widths may eventually not want it anymore).
while (remainingSpace && [flexibleItemIndexes count])
{
// Divy out the space.
proportionate += remainingSpace / [flexibleItemIndexes count];
// Reset the remaining space to 0
remainingSpace = 0.0;
@@ -654,7 +722,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
[view setFrameSize:CGSizeMake(constrainedWidth, height)];
}
}
// Now that all the visible items are the correct width, give them their final frames.
var index = 0,
count = _visibleItems.length,
@@ -676,9 +744,9 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
{
var index = 0,
count = [items count];
_invisibleItems = [];
for (; index < count; ++index)
{
var item = items[index];
@@ -731,19 +799,30 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
hasNonSeparatorItem = YES;
[_additionalItemsButton addItemWithTitle:[item label]];
var menuItem = [_additionalItemsButton itemArray][index + 1];
var menuItem = [[CPMenuItem alloc] initWithTitle:[item label] action:@selector(didSelectMenuItem:) keyEquivalent:nil];
[menuItem setRepresentedObject:item];
[menuItem setImage:[item image]];
[menuItem setTarget:[item target]];
[menuItem setAction:[item action]];
[menuItem setTarget:self];
[menuItem setEnabled:[item isEnabled]];
[_additionalItemsButton addItem:menuItem];
}
}
else
[_additionalItemsButton removeFromSuperview];
}
/*
Used privately.
@ignore
*/
- (void)didSelectMenuItem:(id)aSender
{
var toolbarItem = [aSender representedObject];
[CPApp sendAction:[toolbarItem action] to:[toolbarItem target] from:toolbarItem];
}
- (void)reloadToolbarItems
@@ -751,14 +830,14 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
// Get rid of all our current subviews.
var subviews = [self subviews],
count = subviews.length;
while (count--)
[subviews[count] removeFromSuperview];
// Populate with new subviews.
var items = [_toolbar items],
index = 0;
count = items.length;
_minWidth = TOOLBAR_ITEM_MARGIN;
@@ -770,11 +849,15 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
view = [[_CPToolbarItemView alloc] initWithToolbarItem:item toolbar:self];
_viewsForToolbarItems[[item UID]] = view;
if ([item toolTip] && [view respondsToSelector:@selector(setToolTip:)])
[view setToolTip:[item toolTip]];
[self addSubview:view];
_minWidth += [view minSize].width + TOOLBAR_ITEM_MARGIN;
}
[self tile];
}
@@ -785,13 +868,13 @@ var _CPToolbarItemVisibilityPriorityCompare = function(lhs, rhs)
{
var lhsVisibilityPriority = [lhs visibilityPriority],
rhsVisibilityPriority = [rhs visibilityPriority];
if (lhsVisibilityPriority == rhsVisibilityPriority)
return CPOrderedSame;
if (lhsVisibilityPriority > rhsVisibilityPriority)
return CPOrderedAscending;
return CPOrderedDescending;
}
@@ -837,7 +920,16 @@ var TOP_MARGIN = 5.0,
_toolbar = aToolbar;
[_toolbarItem addObserver:self forKeyPath:"enabled" options:0 context:NULL];
var keyPaths = [@"label", @"image", @"alternateImage", @"minSize", @"maxSize", @"target", @"action", @"enabled"],
index = 0,
count = [keyPaths count];
for (; index < count; ++index)
[_toolbarItem
addObserver:self
forKeyPath:keyPaths[index]
options:0
context:NULL];
}
return self;
@@ -904,7 +996,7 @@ var TOP_MARGIN = 5.0,
{
_imageView = [[CPImageView alloc] initWithFrame:[self bounds]];
[_imageView setImageScaling:CPScaleNone];
[_imageView setImageScaling:CPScaleProportionally];
[self addSubview:_imageView];
}
@@ -918,10 +1010,12 @@ var TOP_MARGIN = 5.0,
[_labelField setStringValue:[_toolbarItem label]];
[_labelField sizeToFit]; // FIXME
[self setEnabled:[_toolbarItem isEnabled]];
_labelSize = [_labelField frame].size;
_minSize = CGSizeMake(MAX(_labelSize.width, minSize.width), _labelSize.height + minSize.height + LABEL_MARGIN + TOP_MARGIN);
_maxSize = CGSizeMake(MAX(_labelSize.width, minSize.width), 100000000.0);
_maxSize = CGSizeMake(MIN(_labelSize.width, maxSize.width), 100000000.0);
[_toolbar tile];
}
@@ -957,7 +1051,14 @@ var TOP_MARGIN = 5.0,
- (void)mouseDown:(CPEvent)anEvent
{
if ([_toolbarItem view])
return;
return [[self nextResponder] mouseDown:anEvent];
var identifier = [_toolbarItem itemIdentifier];
if (identifier === CPToolbarSpaceItemIdentifier ||
identifier === CPToolbarFlexibleSpaceItemIdentifier ||
identifier === CPToolbarSeparatorItemIdentifier)
return [[self nextResponder] mouseDown:anEvent];
[super mouseDown:anEvent];
}
@@ -976,6 +1077,8 @@ var TOP_MARGIN = 5.0,
[_imageView setAlphaValue:0.5];
[_labelField setAlphaValue:0.5];
}
[_toolbar tile];
}
- (CPColor)FIXME_labelColor
@@ -1020,14 +1123,27 @@ var TOP_MARGIN = 5.0,
[_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
}
- (void)sendAction:(SEL)anAction to:(id)aSender
{
[CPApp sendAction:anAction to:aSender from:_toolbarItem];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath
ofObject:(id)anObject
change:(CPDictionary)aChange
context:(id)aContext
{
// FIXME: Not clear if -synchronizeWindowTitleWithDocumentName is the best way to go.
if (aKeyPath === "enabled")
[self setEnabled:[anObject isEnabled]];
else if (aKeyPath === @"target")
[self setTarget:[anObject target]];
else if (aKeyPath === @"action")
[self setAction:[anObject action]];
else
[self updateFromItem];
}
@end
+154 -83
View File
@@ -23,40 +23,24 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@import <AppKit/CPImage.j>
@import <AppKit/CPView.j>
@import "CPImage.j"
@import "CPView.j"
/*
@global
@class CPToolbarItem
*/
CPToolbarItemVisibilityPriorityStandard = 0;
/*
@global
@class CPToolbarItem
*/
CPToolbarItemVisibilityPriorityLow = -1000;
/*
@global
@class CPToolbarItem
*/
CPToolbarItemVisibilityPriorityHigh = 1000;
/*
@global
@class CPToolbarItem
*/
CPToolbarItemVisibilityPriorityUser = 2000;
CPToolbarSeparatorItemIdentifier = @"CPToolbarSeparatorItemIdentifier";
CPToolbarSpaceItemIdentifier = @"CPToolbarSpaceItemIdentifier";
CPToolbarFlexibleSpaceItemIdentifier = @"CPToolbarFlexibleSpaceItemIdentifier";
CPToolbarShowColorsItemIdentifier = @"CPToolbarShowColorsItemIdentifier";
CPToolbarShowFontsItemIdentifier = @"CPToolbarShowFontsItemIdentifier";
CPToolbarCustomizeToolbarItemIdentifier = @"CPToolbarCustomizeToolbarItemIdentifier";
CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
CPToolbarSeparatorItemIdentifier = @"CPToolbarSeparatorItem";
CPToolbarSpaceItemIdentifier = @"CPToolbarSpaceItem";
CPToolbarFlexibleSpaceItemIdentifier = @"CPToolbarFlexibleSpaceItem";
CPToolbarShowColorsItemIdentifier = @"CPToolbarShowColorsItem";
CPToolbarShowFontsItemIdentifier = @"CPToolbarShowFontsItem";
CPToolbarCustomizeToolbarItemIdentifier = @"CPToolbarCustomizeToolbarItem";
CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
/*!
/*!
@ingroup appkit
@class CPToolbarItem
@@ -81,7 +65,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
CPView _view;
CGSize _minSize;
CGSize _maxSize;
CGSize _maxSize;
int _visibilityPriority;
@@ -102,20 +86,21 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
- (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;
}
@@ -136,6 +121,12 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
return _toolbar;
}
/* @ignore */
- (void)_setToolbar:(CPToolbar)aToolbar
{
_toolbar = aToolbar;
}
/*!
Returns the item's label
*/
@@ -179,7 +170,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if ([_view respondsToSelector:@selector(toolTip)])
return [_view toolTip];
return _toolTip;
}
@@ -190,8 +181,8 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
- (void)setToolTip:(CPString)aToolTip
{
if ([_view respondsToSelector:@selector(setToolTip:)])
[view setToolTip:aToolTip];
[_view setToolTip:aToolTip];
_toolTip = aToolTip;
}
@@ -202,7 +193,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if ([_view respondsToSelector:@selector(tag)])
return [_view tag];
return _tag;
}
@@ -214,7 +205,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if ([_view respondsToSelector:@selector(setTag:)])
[_view setTag:aTag];
_tag = aTag;
}
@@ -225,12 +216,12 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
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
*/
@@ -238,7 +229,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if (!_view)
_target = aTarget;
else if ([_view respondsToSelector:@selector(setTarget:)])
[_view setTarget:aTarget];
}
@@ -250,7 +241,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if (_view)
return [_view respondsToSelector:@selector(action)] ? [_view action] : nil;
return _action;
}
@@ -274,7 +265,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if ([_view respondsToSelector:@selector(isEnabled)])
return [_view isEnabled];
return _isEnabled;
}
@@ -286,7 +277,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if ([_view respondsToSelector:@selector(setEnabled:)])
[_view setEnabled:shouldBeEnabled];
_isEnabled = shouldBeEnabled;
}
@@ -297,7 +288,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if ([_view respondsToSelector:@selector(image)])
return [_view image];
return _image;
}
@@ -311,12 +302,12 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
[_view setImage:anImage];
_image = anImage;
if (!_image)
return;
if (_minSize.width == 0 && _minSize.height == 0 &&
_maxSize.width == 0 && _maxSize.height == 0)
if (_minSize.width === 0 && _minSize.height === 0 &&
_maxSize.width === 0 && _maxSize.height === 0)
{
var imageSize = [_image size];
@@ -336,7 +327,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if ([_view respondsToSelector:@selector(setAlternateImage:)])
[_view setAlternateImage:anImage];
_alternateImage = anImage;
}
@@ -347,7 +338,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if ([_view respondsToSelector:@selector(alternateIamge)])
return [_view alternateImage];
return _alternateImage;
}
@@ -367,7 +358,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
{
if (_view == aView)
return;
_view = aView;
if (_view)
@@ -375,7 +366,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
// Tags get forwarded.
if (_tag !== 0 && [_view respondsToSelector:@selector(setTag:)])
[_view setTag:_tag];
_target = nil;
_action = nil;
}
@@ -395,8 +386,11 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
*/
- (void)setMinSize:(CGSize)aMinSize
{
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));
}
@@ -415,8 +409,11 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
*/
- (void)setMaxSize:(CGSize)aMaxSize
{
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));
}
@@ -453,6 +450,9 @@ CPToolbarItemVisibilityPriorityUser
- (void)validate
{
var action = [self action],
target = [self target];
// View items do not do any target-action analysis.
if (_view)
{
@@ -462,13 +462,9 @@ CPToolbarItemVisibilityPriorityUser
return;
}
var action = [self action];
if (!action)
return [self setEnabled:NO];
var target = [self target];
if (target && ![target respondsToSelector:action])
return [self setEnabled:NO];
@@ -495,15 +491,97 @@ CPToolbarItemVisibilityPriorityUser
@end
var CPToolbarItemItemIdentifierKey = @"CPToolbarItemItemIdentifierKey",
CPToolbarItemLabelKey = @"CPToolbarItemLabelKey",
CPToolbarItemPaletteLabelKey = @"CPToolbarItemPaletteLabelKey",
CPToolbarItemToolTipKey = @"CPToolbarItemToolTipKey",
CPToolbarItemTagKey = @"CPToolbarItemTagKey",
CPToolbarItemTargetKey = @"CPToolbarItemTargetKey",
CPToolbarItemActionKey = @"CPToolbarItemActionKey",
CPToolbarItemEnabledKey = @"CPToolbarItemEnabledKey",
CPToolbarItemImageKey = @"CPToolbarItemImageKey",
CPToolbarItemAlternateImageKey = @"CPToolbarItemAlternateImageKey",
CPToolbarItemViewKey = @"CPToolbarItemViewKey",
CPToolbarItemMinSizeKey = @"CPToolbarItemMinSizeKey",
CPToolbarItemMaxSizeKey = @"CPToolbarItemMaxSizeKey",
CPToolbarItemVisibilityPriorityKey = @"CPToolbarItemVisibilityPriorityKey",
CPToolbarItemAutovalidatesKey = @"CPToolbarItemAutovalidatesKey";
@implementation CPToolbarItem (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_itemIdentifier = [aCoder decodeObjectForKey:CPToolbarItemItemIdentifierKey];
_minSize = [aCoder decodeSizeForKey:CPToolbarItemMinSizeKey];
_maxSize = [aCoder decodeSizeForKey:CPToolbarItemMaxSizeKey];
[self setLabel:[aCoder decodeObjectForKey:CPToolbarItemLabelKey]];
[self setPaletteLabel:[aCoder decodeObjectForKey:CPToolbarItemPaletteLabelKey]];
[self setToolTip:[aCoder decodeObjectForKey:CPToolbarItemToolTipKey]];
[self setTag:[aCoder decodeObjectForKey:CPToolbarItemTagKey]];
[self setTarget:[aCoder decodeObjectForKey:CPToolbarItemTargetKey]];
[self setAction:CPSelectorFromString([aCoder decodeObjectForKey:CPToolbarItemActionKey])];
[self setEnabled:[aCoder decodeBoolForKey:CPToolbarItemEnabledKey]];
[self setImage:[aCoder decodeObjectForKey:CPToolbarItemImageKey]];
[self setAlternateImage:[aCoder decodeObjectForKey:CPToolbarItemAlternateImageKey]];
[self setView:[aCoder decodeObjectForKey:CPToolbarItemViewKey]];
[self setVisibilityPriority:[aCoder decodeIntForKey:CPToolbarItemVisibilityPriorityKey]];
[self setAutovalidates:[aCoder decodeBoolForKey:CPToolbarItemAutovalidatesKey]];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_itemIdentifier forKey:CPToolbarItemItemIdentifierKey];
[aCoder encodeObject:[self label] forKey:CPToolbarItemLabelKey];
[aCoder encodeObject:[self paletteLabel] forKey:CPToolbarItemPaletteLabelKey];
[aCoder encodeObject:[self toolTip] forKey:CPToolbarItemToolTipKey];
[aCoder encodeObject:[self tag] forKey:CPToolbarItemTagKey];
[aCoder encodeObject:[self target] forKey:CPToolbarItemTargetKey];
[aCoder encodeObject:[self action] forKey:CPToolbarItemActionKey];
[aCoder encodeObject:[self isEnabled] forKey:CPToolbarItemEnabledKey];
[aCoder encodeObject:[self image] forKey:CPToolbarItemImageKey];
[aCoder encodeObject:[self alternateImage] forKey:CPToolbarItemAlternateImageKey];
[aCoder encodeObject:[self view] forKey:CPToolbarItemViewKey];
[aCoder encodeSize:[self minSize] forKey:CPToolbarItemMinSizeKey];
[aCoder encodeSize:[self maxSize] forKey:CPToolbarItemMaxSizeKey];
[aCoder encodeObject:[self visibilityPriority] forKey:CPToolbarItemVisibilityPriorityKey];
[aCoder encodeBool:[self autovalidates] forKey:CPToolbarItemAutovalidatesKey];
}
@end
@implementation CPToolbarItem (CPCopying)
- (id)copy
{
var copy = [[[self class] alloc] initWithItemIdentifier:_itemIdentifier];
if (_view)
[copy setView:[CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:_view]]];
[copy _setToolbar:_toolbar];
[copy setLabel:_label];
[copy setPaletteLabel:_paletteLabel];
[copy setToolTip:[self toolTip]];
@@ -511,7 +589,7 @@ CPToolbarItemVisibilityPriorityUser
[copy setTag:[self tag]];
[copy setTarget:[self target]];
[copy setAction:[self action]];
[copy setEnabled:[self isEnabled]];
[copy setImage:[self image]];
@@ -519,9 +597,10 @@ CPToolbarItemVisibilityPriorityUser
[copy setMinSize:_minSize];
[copy setMaxSize:_maxSize];
[copy setVisibilityPriority:_visibilityPriority];
[copy setVisibilityPriority:[self visibilityPriority]];
[copy setAutovalidates:[self autovalidates]];
return copy;
}
@@ -534,32 +613,24 @@ CPToolbarItemVisibilityPriorityUser
/* @ignore */
+ (CPToolbarItem)_standardItemWithItemIdentifier:(CPString)anItemIdentifier
{
var item = [[CPToolbarItem alloc] initWithItemIdentifier:anItemIdentifier];
switch (anItemIdentifier)
{
case CPToolbarSeparatorItemIdentifier: [item setMinSize:CGSizeMake(2.0, 0.0)];
[item setMaxSize:CGSizeMake(2.0, 100000.0)];
return item;
case CPToolbarSpaceItemIdentifier: [item setMinSize:CGSizeMake(32.0, 32.0)];
[item setMaxSize:CGSizeMake(32.0, 32.0)];
return item;
case CPToolbarFlexibleSpaceItemIdentifier: [item setMinSize:CGSizeMake(32.0, 32.0)];
[item setMaxSize:CGSizeMake(10000.0, 32.0)];
return item;
case CPToolbarShowColorsItemIdentifier: return nil;
case CPToolbarSeparatorItemIdentifier: return [_CPToolbarSeparatorItem new];
case CPToolbarSpaceItemIdentifier: return [_CPToolbarSpaceItem new];
case CPToolbarFlexibleSpaceItemIdentifier: return [_CPToolbarFlexibleSpaceItem new];
case CPToolbarShowColorsItemIdentifier: return [_CPToolbarShowColorsItem new];
case CPToolbarShowFontsItemIdentifier: return nil;
case CPToolbarCustomizeToolbarItemIdentifier: return nil;
case CPToolbarPrintItemIdentifier: return nil;
}
return nil;
}
@end
@import "_CPToolbarFlexibleSpaceItem.j"
@import "_CPToolbarShowColorsItem.j"
@import "_CPToolbarSeparatorItem.j"
@import "_CPToolbarSpaceItem.j"
+59 -9
View File
@@ -1,13 +1,14 @@
@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 @accessors(readonly, property=childNodes);
CPMutableArray _childNodes;
}
+ (id)treeNodeWithRepresentedObject:(id)anObject
@@ -33,16 +34,23 @@
return [_childNodes count] <= 0;
}
- (CPArray)childNodes
{
return [_childNodes copy];
}
- (CPMutableArray)mutableChildNodes
{
return [self mutableArrayValueForKey:@"childNodes"];
}
- (void)insertObject:(id)anObject inChildNodesAtIndex:(CPInteger)anIndex
- (void)insertObject:(id)aTreeNode inChildNodesAtIndex:(CPInteger)anIndex
{
anObject._parentNode = self;
[[aTreeNode._parentNode mutableChildNodes] removeObjectIdenticalTo:aTreeNode];
[_childNodes addObject:anObject];
aTreeNode._parentNode = self;
[_childNodes insertObject:aTreeNode atIndex:anIndex];
}
- (void)removeObjectFromChildNodesAtIndex:(CPInteger)anIndex
@@ -52,13 +60,14 @@
[_childNodes removeObjectAtIndex:anIndex];
}
- (void)replaceObjectFromChildNodesAtIndex:(CPInteger)anIndex withObject:(id)anObject
- (void)replaceObjectFromChildNodesAtIndex:(CPInteger)anIndex withObject:(id)aTreeNode
{
var oldObject = [_childNodes objectAtIndex:anIndex];
var oldTreeNode = [_childNodes objectAtIndex:anIndex];
oldObject._parentNode = nil;
oldTreeNode._parentNode = nil;
aTreeNode._parentNode = self;
[_childNodes replaceObjectAtIndex:anIndex withObject:anObject];
[_childNodes replaceObjectAtIndex:anIndex withObject:aTreeNode];
}
- (id)objectInChildNodesAtIndex:(CPInteger)anIndex
@@ -79,4 +88,45 @@
[_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",
CPTreeNodeParentNodeKey = @"CPTreeNodeParentNodeKey",
CPTreeNodeChildNodesKey = @"CPTreeNodeChildNodesKey";
@implementation CPTreeNode (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_representedObject = [aCoder decodeObjectForKey:CPTreeNodeRepresentedObjectKey];
_parentNode = [aCoder decodeObjectForKey:CPTreeNodeParentNodeKey];
_childNodes = [aCoder decodeObjectForKey:CPTreeNodeChildNodesKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_representedObject forKey:CPTreeNodeRepresentedObjectKey];
[aCoder encodeConditionalObject:_parentNode forKey:CPTreeNodeParentNodeKey];
[aCoder encodeObject:_childNodes forKey:CPTreeNodeChildNodesKey];
}
@end

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