Compare commits

...
895 Commits
Author SHA1 Message Date
Alexander Ljungberg 9cbc52e858 Cappuccino v0.9.6 RC2. 2012-08-22 22:35:53 +01:00
Alexander Ljungberg 3cdf4fbc88 RC2 bootstrap. 2012-08-21 23:18:24 +01:00
Alexander Ljungberg b032c9e455 Fixed: objcc --includeTypeSignatures typo. 2012-08-21 22:37:08 +01:00
Alexander Ljungberg 6d4ce10150 Formatting. 2012-08-21 01:24:36 +01:00
Alexander Ljungberg 8b227798e1 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-08-19 17:32:09 +01:00
Alexander Ljungberg 1514e8e981 Fixed: don't crash in unit tests if using Rhino.
Apparently Rhino doesn't have `<input element>.setAttribute` and an error would be thrown in `CPCompatibility.j`: `Cannot find function setAttribute in object [object Object].`
2012-08-19 17:16:09 +01:00
Alexander Ljungberg 4fbd0fdc42 Unit test KVCArray setArray: behaviour. 2012-08-19 16:50:09 +01:00
Antoine Mercadal fea31d54f8 Update comments to remove references to .xCodeSupport 2012-08-17 20:14:26 -07:00
Alexander Ljungberg 3dffbd6071 Refs #1001. Make it easy to test text field cut/paste behaviour. 2012-08-16 19:13:59 +01:00
Alexander Ljungberg 876757e748 Refs #1001. Don't use old cut/paste workaround if oninput fix is available. 2012-08-16 19:13:30 +01:00
Alexander Ljungberg 7abaa30526 Refs #1001. Fixed: text field cut/paste by context menu would not trigger a change notification.
Also just regular copy and paste could fail to trigger notifications.
2012-08-16 19:03:18 +01:00
Alexander Ljungberg 1a467f9208 Test text fields with various sizes. 2012-08-15 18:31:39 +01:00
Alexander Ljungberg 54d5f4b0a4 Fixed: horizontal text jump when editing text fields in some browsers.
We were compensating for a bug in Safari, older versions of Chrome and Firefox in our input placement. But new Chrome and neither IE 8 nor IE 9 needed it which resulted in the text being off in those browsers.
2012-08-15 18:31:20 +01:00
Alexander Ljungberg ca3a4f9b9c Fixed: text field font size while editing was wrong in Internet Explorer.
Tested in Internet Explorer 8 and 9.
2012-08-15 18:12:53 +01:00
Alexander Ljungberg d53b8c5b1f Fixed: in Firefox the text of edited text fields would "jump" down 1 px.
Locking down the line height and vertical alignment explicitly seems to work in Safari 6, Chrome 21, Firefox 14 and IE 8 (although Chrome and IE exhibit some unrelated horizontal jumping.)
2012-08-15 17:13:34 +01:00
Alexander Ljungberg 1e49704062 Fixed: the size with string fix broke metricsOfFont:. 2012-08-15 15:36:15 +01:00
Alexander Ljungberg d95268b548 Refs #1654. Fix up missing bits. 2012-08-15 13:38:49 +01:00
Alexander Ljungberg e9bafa8f13 Merge pull request #1654 from slevenbits/key-window-style
Inactive (non-key) window titles. Layout tweaks.
2012-08-15 02:07:11 +01:00
Alexander Ljungberg ef66334292 Inactive HUD window title.
Also fix close and title positioning.
2012-08-15 02:03:48 +01:00
Alexander Ljungberg aa17d8c700 Pull up window title code to a superclass for reuse. 2012-08-15 01:38:25 +01:00
Alexander Ljungberg 9f59ac96dd Inactive window title, start on window theming support.
Now the key window can be recognised by the window title.
2012-08-15 01:03:08 +01:00
Alexander Ljungberg 425888ee1f Fixed: in recent revisions vertical text centring was off by 1 upwards, including window titles.
This was caused by making text display generally 1 px taller to allow for fractional pixels at the bottom to show. This should however not be allowed to affect positioning (even if there is a fractional pixel below vertically centred text the text should not move up 0.5 px.)
2012-08-15 00:52:45 +01:00
Alexander Ljungberg f72615dcbe Fixed: non-key window text fields tried to receive input, looked active.
Only the first responder of the key window should receive text input. This is important in multi-window apps or windows with sheets.

In the multi window case it should be possible to switch between two windows with first responder text fields and keep right on typing. First responder status should not be lost, but new typing should always go into the first responder text field of the key window.

For sheets, a text field which was active when the sheet opened should not receive input nor look active while the sheet is open.
2012-08-14 23:41:09 +01:00
Alexander Ljungberg e3d0d69918 Refs #1364. Avoid repeated makeFirstResponder: calls within sheet parent.
If a window contained a text field which was the initial first responder, and the window was displaying a sheet, clicking on the window would cause the text field to alternate between being the first responder and not.

This was caused by the window `orderFront:` setting its first responder to the initial responder if there wasn't any responder yet. This would cause the text field to focus, even that the window wasn't the key window, and then on the next click the text field would blur which would make the text field automatically resign its first responder status.

The solution is to leave the first responder status alone if a window which isn't the key window is `orderFront:`ed. This appears to be more sensible UX in general. You don't expect the first responder of non-key windows to change when you click it's background.
2012-08-14 22:43:01 +01:00
Alexander Ljungberg 77266e0b3c Refs #1364. Don't orderFront: sheet parent view twice.
The sheet's orderFront: already calls the parent window's orderFront:, no need to call it by hand.
2012-08-14 03:10:08 +01:00
Alexander Ljungberg 64bbe0c641 Refs #1364. Fixed: incorrect key window change when displaying a sheet.
When the key window changes the previous window's resignKeyWindow must be called.
2012-08-14 02:39:18 +01:00
Alexander Ljungberg 120cea8734 Refs #1364. Fix CPTextField test to work with new sheet changes. 2012-08-14 00:15:03 +01:00
Alexander Ljungberg 5a8c94183a Refs #1364. Formatting, don't shadow window global. 2012-08-11 19:35:05 +01:00
Alexander Ljungberg de8e08f4f4 Refs #1364. Add an index-debug.html to test app. 2012-08-11 16:11:04 +01:00
Alexander Ljungberg 1e55b79b49 Merge pull request #1364 from walisser/master
Doc-modal/window-modal sheets and other sheet issues [+1]
2012-08-11 15:59:52 +01:00
aparajita dcdc7cef65 Merge pull request #1652 from slevenbits/stringValue-fix
stringValue fix
2012-08-09 20:33:31 -07:00
Aparajita Fishman 6e40020906 Allow nil value in presence of formatter, the formatter may want to format that 2012-08-09 20:31:26 -07:00
Alexander Ljungberg c4c7da3967 Merge pull request #1651 from slevenbits/stringsize-fix
Fixed: wrong text sizing across the board for custom fonts.
2012-08-10 03:47:36 +01:00
Alexander Ljungberg 580da9caef Fixed: wrong text sizing across the board for custom fonts.
If a custom font was used with the CSS @font-face syntax, Cappuccino would calculate the wrong sizes for strings throughout. This could result in e.g. cut off sizeToFit labels.

The sizing tests were being performed inside of an iframe and that iframe would not have the same CSS @font-face declarations. For maximum fidelity all string size tests are now performed in the main document, just off screen.
2012-08-10 03:46:09 +01:00
Antoine Mercadal 657baf9135 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2012-08-09 12:52:11 -07:00
Antoine Mercadal 15c75f05e5 Update some labels 2012-08-09 12:51:43 -07:00
aparajita a8553c7c10 Merge pull request #1648 from slevenbits/fix-xcc-warnings
Fix compiler warnings
2012-08-09 12:19:16 -07:00
Aparajita Fishman 2b6d8697d5 Fix compiler warnings 2012-08-09 12:17:31 -07:00
Antoine Mercadal dcd3995230 remove old pbxproj sample 2012-08-09 11:42:05 -07:00
Antoine Mercadal ad88dabfd1 Update NativeHost.xcodeproj to build on new Xcode 2012-08-09 10:04:08 -07:00
Antoine Mercadal 4e13f3f2fd Add reference to .j too in a group called Sources 2012-08-08 22:35:35 -07:00
Antoine Mercadal 6a2d7bd2df Remove useless product group 2012-08-08 22:34:58 -07:00
Antoine Mercadal 81c1f0c7c9 don't be stupid 2012-08-08 22:34:40 -07:00
Antoine Mercadal cfd6928baa make XcodeSupport hidden 2012-08-08 21:56:33 -07:00
Antoine Mercadal 7b9582181c By default ignore *.xcodeproj and DS_Store 2012-08-08 21:53:25 -07:00
Antoine Mercadal 455ec8e3ae Simplify the FSEvent callback.
Events are not so reliable, there are many flaws and special cases (like trashing a folder etc)
In order to simplify the process is the following

- We receive an event
- We tidy up the shadow files
- We check if the given path exists
- If it's a folder, we continue
- If it's a file and it exists : we run handleFileModification
- If it's a file and it doesn't exist: we run handleFileRemoval
2012-08-08 21:51:38 -07:00
Antoine Mercadal ea31bd2be2 make XcodeCapp compatible with Xcode 4.4 2012-08-08 19:08:16 -07:00
Antoine Mercadal bf6c0c95eb Update Xcode project 2012-08-08 19:05:07 -07:00
Antoine Mercadal bb20a8f4ff pbxprojModifier.py now uses the mod_pbxproj 2012-08-08 19:04:52 -07:00
Antoine Mercadal cc18a5d3e2 Update default PBXProj 2012-08-08 19:04:30 -07:00
Antoine Mercadal 88287c6c2d add attribute to hold the pbxmodifier script 2012-08-08 19:04:04 -07:00
Antoine Mercadal 0fd0a05cd1 basic support for removing a reference of a file 2012-08-08 19:03:44 -07:00
Antoine Mercadal b0b084dbe8 add necessary imports 2012-08-08 16:02:00 -07:00
Antoine Mercadal 41a6621ac2 Make XCC generating .m files with @property for outlets
This is step 1 to have XCC working with Xcode 4.4.
2012-08-08 14:59:29 -07:00
Alexander Ljungberg 9fb73e26dc Merge pull request #1645 from slevenbits/isViewLoaded
Added CPViewController -isViewLoaded, fixed CPWindowController -setViewController to use that
2012-08-07 12:29:59 +01:00
Aparajita Fishman 59e8160f18 Added CPViewController -isViewLoaded, fixed CPWindowController -setViewController to use that
Before this fix, CPWindowController -setViewController was unconditionally loading the view, which should not happen.
2012-08-06 17:33:58 -07:00
Alexander Ljungberg fdf3e499be Merge pull request #1644 from slevenbits/CPArrayController-preserveSelectionFix
Fix wrong indexes are selected when removing arranged objects.
2012-08-06 13:53:31 +01:00
Ilya Kulakov c1ace9a7c3 Fix wrong indexes are selected when removing arranged objects. 2012-08-06 19:19:13 +07:00
Alexander Ljungberg f9a1d7240e Merge pull request #1643 from slevenbits/cpdecimalnumber-fix
fix CPDecimalMakeString to support '.003' and '-.003' style numbers
2012-08-05 12:34:40 +01:00
Eric Wong def8016f44 code style change 2012-08-05 09:35:44 +08:00
Eric Wong 175c70d99e fix a new bug in CPDecimalMakeWithString and remove some test cases 2012-08-05 08:37:44 +08:00
Darrell Walisser 872d65b824 -fix docs for new delegate methods 2012-08-04 14:06:11 -04:00
Darrell Walisser 339937a316 -support for tags on NSCell, useful for radio groups 2012-08-04 13:58:31 -04:00
Darrell Walisser eed93dc30d -capp_lint 2012-08-04 13:57:56 -04:00
Darrell Walisser bff22779ae -capp_lint 2012-08-04 13:53:05 -04:00
Darrell Walisser 24ef4d41d2 -capp_lint
-enable close buttons based on context
-remove stuff that doesn't work
2012-08-04 13:20:35 -04:00
Eric Wong 9f1a8fa7a2 enable '.003' or '-.003' style number in CPDecimalMakeWithString function and add new test cases 2012-08-04 23:04:40 +08:00
Alexander Ljungberg 729d2493cd Merge pull request #1642 from slevenbits/currency-formatter
`CPNumberFormatter` improvements.
2012-08-04 14:10:39 +01:00
Alexander Ljungberg 4d8758f755 Fix CPTextFieldTest. 2012-08-04 13:58:29 +01:00
Alexander Ljungberg 31ea0da526 CPNumberFormatter generatesDecimalNumbers support, enabled by default. 2012-08-04 13:45:45 +01:00
Alexander Ljungberg 3a2bf36359 Very basic CPNumberFormattercurrency style. 2012-08-04 13:37:42 +01:00
Alexander Ljungberg dc0c63ccc3 Extend CPNumberFormatter CPCoding support and fix rounding default. 2012-08-04 02:31:43 +01:00
Alexander Ljungberg 534635cbc2 Fix CPNumberFormatter maximum/minimum fraction digits property name. 2012-08-04 01:21:42 +01:00
Alexander Ljungberg a7f22a0c5a Correct CPNumberFormatter maximumFractionalDigits default. 2012-08-04 01:09:51 +01:00
Alexander Ljungberg b279a92e4c CPNumberFormatter setMinimumFractionDigits: support. 2012-08-04 00:55:41 +01:00
Alexander Ljungberg 055dd7229e Properly allow CPNumberFormatter to operate on most CPNumber types.
This only worked by accident before.
2012-08-04 00:48:45 +01:00
Antoine Mercadal 0922f3dab7 Merge pull request #1573 from mrcarlberg/binding_support_popup_button
Added key value binding support for CPPopupButton
2012-08-02 15:58:15 -07:00
Alexander Ljungberg b4cfa8cefb CPEvent description. 2012-08-02 15:53:27 +01:00
Alexander Ljungberg 6b660a0c76 Fixed: CPEvent data1 and data2 weren't stored right.
They were stored in globals instead of ivars, allowing only one data1 or data2 in the whole app.
2012-08-02 15:53:04 +01:00
Alexander Ljungberg 1ccd89ddd8 Refs #1640. Unit test. 2012-08-02 15:44:19 +01:00
Alexander Ljungberg cbb710cde7 Merge pull request #1640 from slevenbits/CPEvent-modifierFlags
Add +[CPEvent modifierFlags]
2012-08-02 14:36:17 +01:00
Ilya Kulakov d3b38ac5e8 Add +[CPEvent modifierFlags]. 2012-08-02 17:37:40 +07:00
Alexander Ljungberg 1fb09dcfae Fix typo. 2012-08-02 00:53:30 +01:00
Alexander Ljungberg f06be56fa3 Fixed: accidental global. 2012-08-02 00:45:33 +01:00
Alexander Ljungberg 9768ea4af9 Fixed: multiple rows of tokens in token fields wouldn't scroll right.
In recent versions, moving the cursor to a new row of tokens would place the scroll point somewhere halfway between the two rows of tokens.
2012-08-02 00:44:58 +01:00
Alexander Ljungberg 26c26914da Fixed: token field scrolling away from selected token.
Sometimes clicking a token would cause the token field to scroll to some other spot. This appears to have been caused by the inactive input element gaining focus.

We no longer need the input element for keyboard navigation so we can hide it entirely when it's not used to input a new token. Also, avoid focusing the input element needlessly.
2012-08-02 00:38:21 +01:00
Alexander Ljungberg 41783e87a3 Fixed: in recent builds token field text didn't align.
Text inside of tokens appeared 1 px higher than text typed in the text field area.
2012-08-01 21:12:53 +01:00
Alexander Ljungberg 299998b247 Merge pull request #1639 from slevenbits/tokenfield-fix
Fixed: token fields would sometimes unexpectedly steal first responder status.
2012-08-01 21:02:44 +01:00
Alexander Ljungberg 90ae5766e6 Fixed: token fields would sometimes unexpectedly steal first responder status.
If an autocomplete choice was made followed by immediately focusing on another control, the token field would reclaim first responder status a moment later.
2012-08-01 19:18:40 +01:00
Alexander Ljungberg 31ab70d6fc Refs #1530. Fixed: table views could not be interacted with if they couldn't become the first responder. 2012-08-01 18:59:54 +01:00
Alexander Ljungberg 7537f4d032 Eliminate some duplicate methods. 2012-08-01 16:35:34 +01:00
Darrell Walisser 32c5c82cb9 -removed unused import 2012-07-29 14:04:06 -04:00
Darrell Walisser 1c18862e0f -added manual test 2012-07-29 12:54:34 -04:00
Darrell Walisser 97b3679101 Merge remote-tracking branch 'upstream/master'
Conflicts:
	AppKit/CPApplication.j
	AppKit/CPWindow/_CPDocModalWindowView.j
2012-07-29 12:31:47 -04:00
Alexander Ljungberg 22b882648b Formatting. 2012-07-28 02:06:05 +01:00
Alexander Ljungberg a8150a84be Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-28 01:59:06 +01:00
Alexander Ljungberg df5a7104b1 Fixes #1638. The case of the incomplete optimisation. 2012-07-28 01:58:41 +01:00
aparajita 2400b6aeab Merge pull request #1637 from cacaodev/CPCib-initWithCibNamed
CPCib -initWithContentsOfURL: return nil if the requested data is nil.
2012-07-27 14:51:22 -07:00
cacaodev f42b241469 CPCib -initWithContentsOfURL: return nil if the requested data is nil 2012-07-27 20:19:20 +02:00
aparajita 4c86c75b5f Merge pull request #1635 from wmeddie/patch-1
Removed tailing comma from CPColorWithImages call.
2012-07-27 10:18:56 -07:00
Eduardo Gonzalez 9d2bdea8d9 Removed tailing comma from CPColorWithImages call.
The extra comma causes IE to think it was passed an array with 4
values and causes CPColorWithImages to return a NinePartImage even
though it only has three parts.
2012-07-27 20:51:29 +09:00
Alexander Ljungberg bd0114aa06 Refs #1632. Remove debug logging. 2012-07-26 13:42:01 +01:00
Alexander Ljungberg 43506e708d Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-26 13:32:20 +01:00
Alexander Ljungberg 3e218d6aec Refs #1632. Unit test for CPUndoManagerDidCloseUndoGroupNotification. 2012-07-26 13:32:01 +01:00
Alexander Ljungberg bf3c22f42c Merge pull request #1632 from slevenbits/cpundomanager-notification
Starting from 10.7 NSUndoManager posts NSUndoManagerDidCloseUndoGroupNotification
2012-07-26 13:05:40 +01:00
Antoine Mercadal dcee0e5057 Revert "small fix in theme to avoid 1px offset when editing a CPTextField"
This reverts commit fa1441cf71.
2012-07-25 18:19:15 -07:00
Antoine Mercadal 673c3c19f0 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2012-07-25 12:00:36 -07:00
Antoine Mercadal fa1441cf71 small fix in theme to avoid 1px offset when editing a CPTextField 2012-07-25 12:00:09 -07:00
Ilya Kulakov c57ef67784 Starting from 10.7 NSUndoManager posts NSUndoManagerDidCloseUndoGroupNotification. 2012-07-25 17:02:06 +07:00
Alexander Ljungberg b1e519fd62 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-24 20:09:58 +02:00
Alexander Ljungberg b51a2e25c2 Refs #1631. Unit test last index of index set with a single index. 2012-07-24 20:09:18 +02:00
aparajita 7b2835028a Merge pull request #1628 from cacaodev/CPCib-instantiateCibWithOwner_topLevelObjects_
CPCib -instantiateCibWithOwner:topLevelObjects:
2012-07-23 14:02:09 -07:00
Alexander Ljungberg 9eee7a214e Refs #1630. Add test. 2012-07-23 15:35:52 +02:00
Alexander Ljungberg d0b152c638 Merge pull request #1630 from slevenbits/cparray-fix
Fix CPArray should throw an exception when observer is added/removed.
2012-07-23 15:34:38 +02:00
Alexander Ljungberg 6d08f0d60b Formatting. 2012-07-23 15:26:03 +02:00
Alexander Ljungberg aab8ade15b Refs #1629. Fixed: aSet removeObject: for an object not a member is not an error. 2012-07-23 15:25:52 +02:00
cacaodev 5456bad23d Remove unwanted import in AppController test app 2012-07-23 14:59:48 +02:00
Alexander Ljungberg 8e6634168a Merge pull request #1629 from slevenbits/cpset-fix
Fix CPSet's member never checks equality of objects at Objj level.
2012-07-23 14:56:29 +02:00
Ilya Kulakov a3179080d3 Fix CPArray should throw an exception when observer is added/removed. 2012-07-23 19:48:05 +07:00
Ilya Kulakov 985759ce91 Fix CPSet's member never checks equality of objects at Objj level. 2012-07-23 19:34:40 +07:00
Martin Carlberg a688a3de79 Added test case for selectedIndex binding with CPInsertsNullPlaceholderBindingOption 2012-07-23 12:14:53 +02:00
Martin Carlberg 2184c7ca4d Fixed code format issues 2012-07-23 12:12:55 +02:00
Martin Carlberg f6b378513d Merge branch 'master' of https://github.com/cappuccino/cappuccino into binding_support_popup_button
Conflicts:
	AppKit/CPKeyValueBinding.j
	AppKit/CPPopUpButton.j
	Tests/AppKit/CPPopUpButtonTest.j
2012-07-23 11:19:21 +02:00
cacaodev 02a89e2343 CPCib -instantiateCibWithOwner:(id)anOwner topLevelObjects:(CPArray)topLevelObjects : allow anOwner to be nil 2012-07-22 22:08:31 +02:00
Alexander Ljungberg 8d1a5ac6b9 Format code. 2012-07-21 13:24:13 +01:00
Alexander Ljungberg 030bd9388b Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-21 13:13:28 +01:00
Alexander Ljungberg a78c1bf03a Refs #1624. Fix grouping separator support.
`perMillSymbol` was incorrectly used as the grouping separator.
2012-07-21 13:13:14 +01:00
Alexander Ljungberg 7e562fa3aa Fixes #1624. Fix grouping for CPNumberFormatter. 2012-07-21 13:08:54 +01:00
aparajita 5caf76fb3a Merge pull request #1536 from mrcarlberg/main_bundle_path_commonjs
Fixed mainBundle having no '/' at the end when running in CommonJS. This would make relative paths fail.
2012-07-20 17:18:16 -07:00
aparajita 30509823bb Merge pull request #1620 from ggsato/removingFirstObjectImprovement
fixed a bug that removeObject shows empty selection if an object at index 0 was removed
2012-07-20 16:24:15 -07:00
Alexander Ljungberg 835bd59330 Fixed: popovers in modal windows couldn't be interacted with.
This prevented e.g. date picker popovers in sheet dialogs.
2012-07-19 16:34:15 +01:00
Alexander Ljungberg e73cb7d363 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-19 01:05:48 +01:00
Alexander Ljungberg 8aee458022 nib2cib support for button and radio button tags. 2012-07-19 01:05:09 +01:00
Aparajita Fishman 20eb62b3d2 Use the proper modern DOCTYPE 2012-07-18 14:48:23 -07:00
Alexander Ljungberg f4f9e8880c Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-18 19:21:43 +01:00
Alexander Ljungberg b0a56f1690 Fixed: removing selected CPPopUpButton item.
When the selected item of a `CPPopUpButton` is removed the first item should become selected. This matches Cocoa's behaviour.
2012-07-18 19:21:20 +01:00
Aparajita Fishman 8444f808f6 By default controls will track the system font size
Use current system font size elsewhere
2012-07-18 09:53:09 -07:00
Aparajita Fishman b959f13a0c Merge branch 'master' of github.com:cappuccino/cappuccino into upstream 2012-07-17 15:11:13 -07:00
Aparajita Fishman f0163e13c9 Added CGInsetMakeInvertedCopy 2012-07-17 15:10:58 -07:00
Alexander Ljungberg a89ca14abe Merge pull request #1622 from slevenbits/tableview-column-move-notify
Notify when a `CPTableView` column moves.
2012-07-17 22:59:53 +01:00
Alexander Ljungberg 9b77f1b7ac Notify when a CPTableView column moves.
Both through `CPNotificationCenter` and to the delegate.
2012-07-17 22:57:36 +01:00
Alexander Ljungberg e68077d159 Merge pull request #1621 from slevenbits/cpdictionary-enumerate
`CPDictionary enumerateKeysAndObjectsUsingBlock:`.
2012-07-17 20:51:22 +01:00
Alexander Ljungberg 5724dfe21d CPDictionary enumerateKeysAndObjectsUsingBlock:. 2012-07-17 20:48:52 +01:00
ggsato 364208e029 fixed a bug that removeObject shows empty selection if an object at index 0 was removed 2012-07-17 15:36:18 +09:00
Alexander Ljungberg fea0299033 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-16 03:16:31 +01:00
Alexander Ljungberg c1dd821c6e Merge pull request #1618 from slevenbits/fontmanager
New `CPFontManager` methods.
2012-07-16 03:16:21 +01:00
Alexander Ljungberg 6a67243460 CPFontManager convertFont:toFace:. 2012-07-16 03:11:21 +01:00
Alexander Ljungberg 7f1b396ce8 CPFontManager weightOfFont: and traitsOfFont:. 2012-07-15 23:39:29 +01:00
Alexander Ljungberg 1e5bccd48e CPFontManager convertFont:, convertFont:toHaveTrait: and addFontTrait:. 2012-07-15 23:38:32 +01:00
Alexander Ljungberg d016e8a5e8 CPFontManager setSelectedFont:isMultiple: and other basic properties. 2012-07-15 21:45:50 +01:00
Alexander Ljungberg fc49574947 Test CPFontManager. 2012-07-15 21:01:29 +01:00
aparajita 2c0cf72a60 Merge pull request #1617 from slevenbits/dictionary-key-methods
CPDictionary key methods


keysOfEntriesPassingTest:
keysOfEntriesWithOptions:passingTest:
keysSortedByValueUsingComparator:
2012-07-15 09:30:31 -07:00
Aparajita Fishman c4dc9c8bdb CPDictionary key methods
keysOfEntriesPassingTest:
keysOfEntriesWithOptions:passingTest:
keysSortedByValueUsingComparator:
2012-07-15 09:27:04 -07:00
Aparajita Fishman dec7ca1e19 Make NSClipView obey the Draw Background checkbox in IB 2012-07-14 10:32:21 -07:00
Alexander Ljungberg ccb6b3b4a2 Code formatting. 2012-07-14 14:11:38 +01:00
Alexander Ljungberg 5658ea2c1e Merge pull request #1616 from slevenbits/kvo-willchange-fix-2
Fix crash if an observer is set between willChange…/didChange…
2012-07-14 13:58:18 +01:00
Ilya Kulakov 3886f27acd Fix crash if an observer is set between willChange…/didChange…
When you add an observer to an object first time, its class is
implicitly changed to a KVO_originalClassName (subclass of original
class). This subclass adds willChange…/didChange… methods for
observable properties.
If you send willChange… before you add an observer, it does nothing.
But if you send didChange… just after, the app will crash, because
new KVO_originalClassName nerver receives willChange…

The idea is to maintain counter of all received willChange… messages
(per key) and decrease it in didChange…
When KVO_originalClassName is created and didChange… is received
(without opening willChange… to new class), exception is not thrown
immediately, but the counter is checked first.
If it's greater than 0, then didChange… just closes
an unboserved willChange… Otherwise exception is thrown, as expected.
2012-07-14 19:32:25 +07:00
aparajita 76738a0208 Merge pull request #1615 from slevenbits/text-size-theming
Text size and theming enhancements

- _CPImageAndTextView adds extra pixels to allow for fractional pixels in -sizeToFit.

- NSButton now allows buttons that are not fixed height, if the theme allows it.

- Documented the mapping between bezel style constants and their IB style names.
2012-07-13 21:04:41 -07:00
Aparajita Fishman 32dc0826cb Text size and theming enhancements
- _CPImageAndTextView adds extra pixels to allow for fractional pixels in -sizeToFit.

- NSButton now allows buttons that are not fixed height, if the theme allows it.

- Documented the mapping between bezel style constants and their IB style names.
2012-07-13 21:00:02 -07:00
Aparajita Fishman 590b7ec704 format strings was not set in the xib 2012-07-13 20:26:57 -07:00
Aparajita Fishman 98b735b185 Install imagesize binary in both debug/release so that it works when install-debug-symlinks is used 2012-07-13 20:07:25 -07:00
Aparajita Fishman dd686a0fca Fixed spelling error in test app 2012-07-13 18:23:08 -07:00
aparajita 3fe2e4487e Merge pull request #1571 from tancred/xcodecapp_fix_wrong_format_specifier
Corrected the format specifier for a logging statement in XcodeCapp.
2012-07-13 07:51:07 -07:00
cacaodevandAparajita Fishman 2cf9fdf0d0 Check for sendsActionOnEndEditing 2012-07-13 07:45:08 -07:00
cacaodevandAparajita Fishman 7c01f14bfe Fix for #1593 2012-07-13 07:44:48 -07:00
Alexander Ljungberg 716c340825 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-13 15:11:46 +01:00
aparajita 625e47a725 Merge pull request #1591 from claimable/master
Fix for CPPredicateEditor Action Bug

Make sure the predicate value editor sends its action when resigning, so the predicate is updated.
2012-07-13 07:07:25 -07:00
Alexander Ljungberg 2ca3f657f9 Refs #1530. Fix CPTableViewTest to work regardless of #1530 decision. 2012-07-13 13:24:43 +01:00
Alexander Ljungberg b038b6baf6 Fixed: browser propagation control when not in browser.
This would lead to a `[CPPlatformWindow _willPropagateCurrentDOMEvent] unrecognized selector sent to instance` error if an event was sent in a non DOM environment.
2012-07-13 12:41:26 +01:00
Alexander Ljungberg 9abb79d191 Merge pull request #1612 from slevenbits/cpgeometry-improvements
Cpgeometry improvements
2012-07-13 11:37:02 +01:00
Malte Tancred c3740c548d Corrected the corrected format specifier for the flags variable. 2012-07-13 08:11:24 +02:00
aparajita 629f12a851 Merge pull request #1543 from cacaodev/CPTableView-content-binding
Added support for using bindings with CPTableView content (as opposed to CPTableColumn value bindings)
2012-07-12 19:58:12 -07:00
aparajita e4de525a09 Merge pull request #1552 from mrcarlberg/outlineview_disclosure_width
Width of disclosure button determined by current disclosure control
2012-07-12 19:38:52 -07:00
aparajita 1a4e5a345d Merge pull request #1576 from ggsato/fixForOpeningExistingDocument
fixed needsUntitled evaluation

An untitled window will only open if ALL documents fail to load.
2012-07-12 19:29:07 -07:00
Alexander Ljungberg a4ae36929b Fix CPGeometry.j import.
CPGeometry.j is now in Foundation.
2012-07-13 01:29:01 +01:00
Alexander Ljungberg b9b98a39bb Avoid Foundation depending on AppKit.
CPGeometry.j and CGGeometry.j now share their implementation in two private API classes in the lower layer Foundation.
2012-07-13 01:28:38 +01:00
Alexander Ljungberg ae4b7cb58e Sort imports. 2012-07-13 01:26:14 +01:00
Aparajita Fishman f7d67e4b87 Cleanup, documented hacks 2012-07-12 17:20:30 -07:00
Antoine Mercadal 20c7ed0034 fix CPTextField baseline alignement 2012-07-12 15:23:17 -07:00
Antoine Mercadal 5c00ea627e Add manual test case for label baseline alignment 2012-07-12 15:10:04 -07:00
Vladimir Shevchenko ff074294ee mistakes corrected 2012-07-13 03:47:34 +07:00
Vladimir Shevchenko 028965e708 mistakes corrected 2012-07-13 03:43:12 +07:00
Vladimir Shevchenko 28b48edf02 Completed aliases and tests 2012-07-13 01:52:06 +07:00
Aparajita Fishman 86b83338c0 CPRuleEditor fixes
- Fixed case where no format strings are specified in xib (which ends up being an empty string).

- Fixed case where malformed strings file would not match regex.

- General cleanup.
2012-07-12 10:16:49 -07:00
aparajita 25f51eb5cd Merge pull request #1602 from mrcarlberg/sort_using_descriptors_with_key_path
Fixed sortUsingDescriptors: so it can handle sort descriptors with a key path
2012-07-12 08:19:46 -07:00
aparajita 7586af8f91 Merge pull request #1606 from slevenbits/system-font
Overhaul of system font handling

- System fonts now track the currently configured system font at runtime.
- You can specify CPFontCurrentSystemSize as a system font size to track the currently configured system font size at runtime.
- Theme fonts and nib2cib now determine face and size at runtime, there is no need to recompile if the system font is changed in Info.plist.
- All hard-coded references to 12.0 as a system font size have been replaced by the current system font size.
- Documented the font substitution algorithm and how to use custom fonts in the CPFont class docs.
- See Tests/Manual/FontEnhancementTest for a demo.
2012-07-12 07:01:30 -07:00
Vladimir Shevchenko d6b9daf7ca Fixed documentation & spaces 2012-07-12 02:47:12 +07:00
Vladimir Shevchenko 2905cd1586 Linked methods from CPGeometry to CGGeometry + added unit tests 2012-07-12 00:19:10 +07:00
aparajita 7a6009f2e3 Merge pull request #1610 from slevenbits/text-clip-fix
Text clip fix


Currently when controls and text fields size to fit text, they use a to determine the correct height/width. Some browsers do not account for fractional pixels that arise from antialiasing. Cappuccino views must clip their contents, so the fractional pixels get clipped, and depending on the font this can be quite noticeable.

This patch adds 1 pixel when necessary to ensure no clipping occurs.
2012-07-11 09:19:46 -07:00
Vladimir Shevchenko a6d6fb1a1e CPGeometry moved to Foundation 2012-07-11 16:29:30 +07:00
Aparajita Fishman 4af061516c CPTableColumn -setHidden documentation was backwards. 2012-07-10 21:53:51 -07:00
Aparajita Fishman df9611cc2c Cleanup 2012-07-10 18:53:41 -07:00
Aparajita Fishman 99cd246ed8 Fix clipping of text due to fractional pixels 2012-07-10 18:08:33 -07:00
Aparajita Fishman 872df9fe39 Fixed window positioning 2012-07-10 17:35:42 -07:00
Aparajita Fishman ec4bfa00ee Per Cocoa, 0 size means create a static font in the current system font size. Added tests. 2012-07-10 16:40:44 -07:00
Aparajita Fishman 68c001e0c0 Don't attempt show CPScrollView, CPScroller or tooltips in the showcase, it doesn't work 2012-07-10 15:36:33 -07:00
Aparajita Fishman 5e40d6702e jake clobber should only clobber the theme, not Cappuccino 2012-07-10 12:47:55 -07:00
Aparajita Fishman a3d4dc2f9a Wrap _DOMElement access in #if PLATFORM(DOM), cleanup 2012-07-09 22:19:26 -07:00
aparajita a8d1224097 Merge pull request #1607 from slevenbits/archive-formatter
CPControl archives/unarchives its formatter

This allows you to use a formatter with a table column's data view.
2012-07-09 21:32:24 -07:00
Aparajita Fishman 73fea44aa2 CPControl now archives/unarchives its formatter
This allows you to use a formatter with a table column's data view.
2012-07-09 21:30:09 -07:00
Aparajita Fishman 309463f15d Fixed parameter name 2012-07-09 16:50:31 -07:00
Aparajita Fishman 37a89a7b0a Cleanup 2012-07-09 15:47:26 -07:00
Aparajita Fishman 6b6f5d98e4 Overhaul of system font handling
- System fonts now track the currently configured system font at runtime.
- You can specify CPFontCurrentSystemSize as a system font size to track the currently configured system font size at runtime.
- Theme fonts and nib2cib now determine face and size at runtime, there is no need to recompile if the system font is changed in Info.plist.
- All hard-coded references to 12.0 as a system font size have been replaced by the current system font size.
2012-07-09 15:29:56 -07:00
Antoine Mercadal 2712a4d45c removed debug console.log 2012-07-09 15:05:03 -07:00
Antoine Mercadal d93fa98d1e Merge branch 'master' of https://github.com/cappuccino/cappuccino 2012-07-09 15:04:17 -07:00
Antoine Mercadal 63616cc50a fix enter key not working to select items in CPComboBox. With the help of @aparajita 2012-07-09 15:03:59 -07:00
Alexander Ljungberg eb643a2df8 Simplify code. 2012-07-09 20:31:29 +01:00
Alexander Ljungberg 81f958eee1 Merge pull request #1605 from slevenbits/colorwell-styling
`CPColorWell` and `CPColorPanel` updates.
2012-07-09 20:17:49 +01:00
Alexander Ljungberg 613f61a898 Unit test CPColorWell archiving. 2012-07-09 20:03:19 +01:00
Alexander Ljungberg 77a009c9a6 Highlighted and disabled looks for bordered CPColorWell. 2012-07-09 19:53:57 +01:00
Alexander Ljungberg 2d8a849d12 nib2cib size fix for bordered CPColorWell. 2012-07-09 19:19:38 +01:00
Alexander Ljungberg b09908e6af Themable CPColorWell with Aristo look when bordered. 2012-07-09 19:18:46 +01:00
Antoine Mercadal ad74e93ea2 use CPPopUpMenuWindowLevel for _CPPopUpList's window level 2012-07-09 10:20:18 -07:00
Alexander Ljungberg 754311d2e2 More colour panel clean up. 2012-07-09 16:06:09 +01:00
Alexander Ljungberg f6514f3c64 Fix CPColorPanel errors and code style. 2012-07-09 15:57:24 +01:00
Alexander Ljungberg f398185aad CGRectInsetByInset geometry function.
This operation appears again and again in Cappuccino.
2012-07-09 15:44:13 +01:00
Alexander Ljungberg 4390bea31f Simplify CPColorWell drawing and mouse handling.
Use standard CPControl mouse handling and highlighting.

Switch to setNeedsLayout based drawing and hook up first themed property.
2012-07-09 13:01:44 +01:00
Alexander Ljungberg 660c98d6e5 Use theme system for CPColorWell bordered state.
This is more consistent with the rest of Cappuccino and prepares for theming support.
2012-07-09 12:20:47 +01:00
Alexander Ljungberg 1154a629a7 Code formatting. 2012-07-09 11:11:37 +01:00
Alexander Ljungberg 09e235eb60 Refs #1603. Optimise slightly. 2012-07-08 21:26:47 +01:00
Alexander Ljungberg 9dab0f083d Merge pull request #1603 from slevenbits/indexset-passingtest
Add *passingTest methods to CPIndexSet
2012-07-08 21:26:05 +01:00
Ilya Kulakov 6dd44687c5 Implement *passingTest methods of CPIndexSet. 2012-07-09 02:40:47 +07:00
Alexander Ljungberg 1a639afd99 Typos. 2012-07-08 14:13:21 +01:00
Antoine Mercadal 72cc494df4 fix bug showing the CPComboBox's list under popover 2012-07-06 16:02:40 -07:00
cacaodev f516078510 PR #1573
Support value transformers for CPContent and CPContentValues bindings.
Made _CPPopUpContentValuesBinder a subclass of CPPopUpContentBinder and reuse setContent:.
Fixed a bug in selectedIndex binding set and reverse set when insertsNull options is on.
_CPPopUPSelectionBinder : simplified the code for getting the unique selection binder in use.
ojunit and manual tests for contentvalues + value transformer.
2012-07-06 22:35:37 +02:00
cacaodev 6a1e5840b5 Merge remote-tracking branch 'mrcarlberg/binding_support_popup_button' into binding_support_popup_button
Conflicts:
	AppKit/CPPopUpButton.j
2012-07-06 22:30:12 +02:00
aparajita 98fbf3abc1 Merge pull request #1601 from slevenbits/CPComboBox
CPComboBox and CPTextField enhancements

- Full Cocoa-compliant implementation of CPComboBox and CPComboBoxDelegate.

- Better focus ring for CPTextField and all subclasses.

- CPTextField and its subclasses draw disabled contents differently, per Cocoa.
2012-07-06 13:24:01 -07:00
Martin Carlberg e265d09034 Fixed sortUsingDescriptors: so it can handle sort descriptors
with a key path instead of just a key.
Also added a test case for this.
2012-07-06 20:52:33 +02:00
Martin Carlberg dbb88b8a17 Included content and contentValue bindings improvments from cacaodev
Fixed a small typo error
2012-07-06 20:06:19 +02:00
Alexander Ljungberg 34e7d4abe5 Merge pull request #1600 from slevenbits/window-controller-container-view
Window controller container view
2012-07-06 16:36:26 +01:00
Ilya KulakovandAlexander Ljungberg f434717372 Fix style. 2012-07-06 16:03:29 +01:00
Ilya KulakovandAlexander Ljungberg 88f8581dcc Implement -[CPWindowController setViewControllerContainerView:], fix -[CPWindowController setViewControllerView:]
Container view is responsible for laying out its views.
Container view is a content view of the window.
If there is no container view, view controller's view is a content view of the window.
2012-07-06 16:03:29 +01:00
Alexander Ljungberg 552ba68187 Refs #1599. Fix teacher.car.year unit test message. 2012-07-06 15:53:19 +01:00
Alexander Ljungberg cff29904d7 Refs #1599. Format code. 2012-07-06 15:53:03 +01:00
Alexander Ljungberg b1774cdccf Merge pull request #1599 from slevenbits/kvo-fix
Wrong key path and change send to the observer
2012-07-06 15:38:50 +01:00
Aparajita Fishman 32737e0b72 CPComboBox and CPTextField enhancements
- Full Cocoa-compliant implementation of CPComboBox and CPComboBoxDelegate.

- Better focus ring for CPTextField and all subclasses.

- CPTextField and its subclasses draw disabled contents differently, per Cocoa.
2012-07-06 00:15:23 -07:00
aparajita b54ce4d782 Merge pull request #1597 from slevenbits/cptableview-grid
Make the default grid color in IB show correctly in CPTableView.

- Changed the default grid color from #dce0e2 to #ccc.
- Fixed NSColor to recognize the named color "gridColor" and set it to #ccc.
- NSTableView always saves the grid color from IB.
2012-07-05 16:16:30 -07:00
Aparajita Fishman b6adf26549 Make Alexander happy. ;-) 2012-07-05 12:26:55 -07:00
Aparajita Fishman d0bfde1887 Annotate indexOfObject methods, use "index" instead of "idx" 2012-07-05 11:34:01 -07:00
Ilya Kulakov 4094a1f826 Fix wrong change is sent to observer when top level object is changed.
When you change the top level object, observer MUST receive value
for the key path of the previous top level object as old and
value for the key path of the new top level object as new.
2012-07-05 17:59:29 +07:00
Alexander Ljungberg 8afb67521d Annotate indexesOfObjectsPassingTest: function signature. 2012-07-04 23:26:07 +01:00
Alexander Ljungberg 34be9cea3a Refs #1559. Fix split view autosave test. 2012-07-04 23:17:38 +01:00
Aparajita Fishman 618194996a Fixed CPString -hasSuffix docs 2012-07-04 17:29:28 -04:00
cacaodev 42f49795af Ignore Value Transformers, no error and log an info message. 2012-07-04 23:18:47 +02:00
aparajita e444a5d60a Merge pull request #1598 from slevenbits/array-filters-fix
Fixed the method names committed in 0f5a6b4e5e
2012-07-04 14:16:14 -07:00
Aparajita Fishman 593f3c2109 Fixed the method names 2012-07-04 17:03:53 -04:00
Aparajita Fishman e9fb821721 Make the default grid color in IB show correctly in CPTableView
Currently #888888 is being used as the default, mainly because NSColor.j doesn't recognize the "gridColor" named color, and the cached color in the .xib is #888888 for some reason. Actually the default grid color is #CCCCCC.
2012-07-04 16:39:47 -04:00
aparajita a4afe1bde9 Merge pull request #1596 from slevenbits/cptableview-typos
Added missing @
2012-07-04 13:29:45 -07:00
Aparajita Fishman 1d29fda5fd Added missing @ 2012-07-04 16:25:59 -04:00
aparajita 16b7093e19 Merge pull request #1595 from slevenbits/array-filters
Added CPArray -indexesOfObjectPassingTest methods
2012-07-04 12:46:51 -07:00
Aparajita Fishman 0f5a6b4e5e Added CPArray -indexesOfObjectPassingTest methods 2012-07-04 15:41:45 -04:00
cacaodev c7a8124be8 CPPopUpButtonTest test CPContentValuesBinding with value transformer. Currently failing. 2012-07-04 17:55:39 +02:00
Alexander Ljungberg c3c74a13c0 Merge pull request #1592 from slevenbits/splitview-autosave-improvement
Improve split view autosave.
2012-07-03 23:58:08 +01:00
Alexander Ljungberg cde50cc8b4 Refs #1558. Better ivar name and type. 2012-07-03 13:57:11 +01:00
Alexander Ljungberg fcc11b8969 Fixes #1559. Nested split view autosave and better override support.
Nested split views now correctly restore their divider positions by restoring "top down". E.g. a nesting split view is restored before the nested split view so that the nested split view has the correct frame size for the position it is restoring.

This commit also makes it easier to override autosave restores in a subclass or a controller's `viewDidLoad`. Now if `setPosition:ofDividerAtIndex:` is called after the split view's `initWithCoder:` has finished, but before the final autosave restore has occurred, the autosave restore is cancelled. This preserves whatever the modification the programmer intended to make instead of overwriting it with the autosaved position.

This commit also fixes a bug where an autosaved position would not be restored, or would be restored at an unexpected time, if `setFrameSize:` was not sent to the split view shortly after its `initWithCoder:`. (Such a `setFrameSize:` message is often sent due to a window `setFullPlatformWindow:` call in `AppController.j`'s `awakeFromCib`, but it's not necessarily sent.)
2012-07-03 13:53:52 +01:00
Alexander Ljungberg c9b7d1e842 Refs #1559. Autosave split view positions for frame size changes.
This covers the case where the whole split view is resized and the divider moves as a consequence. For example if the split view was made much smaller the fixed position of the divider previously autosaved might not even be inside of the split view frame anymore, and on restore from autosave that side of the split view might unexpectedly become collapsed.

The new behaviour also more closely matches Cocoa's, although there is still a slight difference in implementation.
2012-07-03 13:44:59 +01:00
Martin Carlberg e5f4a7c39a Added support for CPNullPlaceholderBindingOption and made some clean up of code 2012-07-03 12:36:19 +02:00
Alexander Ljungberg 814e72879e Manual test for split view autosave. 2012-07-03 11:09:39 +01:00
Alexander Ljungberg 5f9463a030 Refs #1558. Test all split view divider types. 2012-07-03 10:54:27 +01:00
Alexander Ljungberg 37d4a06aa4 Fixes #1558. Support "thick divider" split view style in nib2cib.
The thick divider style is converted to the pane splitter style in nib2cib since we only use two styles in Cappuccino.
2012-07-03 10:44:07 +01:00
aparajita fb590550cd Merge pull request #1589 from slevenbits/nib2cib-fixes
nib2cib fixes
2012-07-02 06:57:09 -07:00
Aparajita Fishman 2f27291c53 Tweaked debug output of custom image resources in nib2cib 2012-07-02 09:55:52 -04:00
Aparajita Fishman fc23863d85 Added support for alternate button title in nib2cib 2012-07-02 09:55:52 -04:00
aparajita 8651a59f43 Merge pull request #1587 from slevenbits/non-bordered-buttons
Non-bordered buttons should retain their size, not shrink to fit
2012-07-02 06:41:49 -07:00
Aparajita Fishman 2f1e9d76ec Non-bordered buttons should retain their size, not shrink to fit. 2012-07-02 09:40:00 -04:00
Mike Holman 2e1a72030e Fix CPPredicateEditor CPTextField action bug. 2012-07-02 16:17:35 +08:00
aparajita c9f32ac77b Merge pull request #1584 from slevenbits/splitview-autosave
CPSplitView autosave optimization
2012-06-30 13:34:50 -07:00
Aparajita Fishman 6efa30c52a autosave of position should not happen until divider tracking is completely done.
Also renamed a local variable that looked like an ivar.
2012-06-30 16:19:06 -04:00
Martin Carlberg ef30e21506 Missed to remove some line in manual merge 2012-06-30 09:20:50 +02:00
Martin Carlberg 70b5f9ee98 Merge branch 'popup_button_binder_subclass' of https://github.com/cacaodev/cappuccino into binding_support_popup_button
Conflicts:
	AppKit/CPPopUpButton.j
2012-06-30 08:41:14 +02:00
aparajita 3137839322 Merge pull request #1583 from slevenbits/splitview-userinfo
Splitview userinfo
2012-06-29 13:11:23 -07:00
Aparajita Fishman 345a865cc8 Post OS X 10.5, Cocoa adds a userInfo with the divider index when the user drags the divider 2012-06-29 13:09:47 -07:00
aparajita 2a4ef4394c Merge pull request #1582 from slevenbits/nib2cib-images
nib2cib image fixes
2012-06-29 11:33:13 -07:00
Aparajita Fishman 3ba5be1ec6 nib2cib image fixes
- nib2cib will now log the path and size of custom image resources in super verbose mode.

- Alternate images for buttons were not being set by nib2cib, that has been fixed.

- Fixed the name of the imagesize binary in the Xcode project.
2012-06-29 11:29:53 -07:00
Aparajita Fishman 606f3dfe6b Replaced Java-based image utility with Cocoa command line app, cleaned up some fontinfo stuff 2012-06-29 11:29:46 -07:00
cacaodev c865644e6c Test for CPPopUpButton bindings. 2012-06-29 19:42:20 +02:00
Martin Carlbergandcacaodev fec1586380 CPPopUpButton bindings support (set for all and reverse for selection related bindings) using a CPBinder subclass instead of dedicated selectors. 2012-06-29 19:40:23 +02:00
cacaodev 8e2afde3e4 CPKeyValueBinding -reverseSetValueFor: -> extract a method for getting the source value for a given binding. the goal is to facilitate subclassing. 2012-06-29 19:37:35 +02:00
Aparajita Fishman 5410884e03 Fixed the documentation for CPArray -indexOfObject methods 2012-06-29 09:02:35 -07:00
Aparajita Fishman e9ceb1d0c6 Documentation tweak 2012-06-28 15:25:39 -07:00
Alexander Ljungberg 8d14bdd819 CPToolbar autovalidate. 2012-06-28 22:41:41 +01:00
Alexander Ljungberg 23f3a01e3c Merge pull request #1579 from slevenbits/cptoolbar-delegate
CPToolbar delegate fix
2012-06-28 20:27:23 +01:00
aparajita 3540dd1c26 Merge pull request #1578 from slevenbits/initialize-fix
Implement missing +initialize checks and regularize checks
2012-06-28 12:09:42 -07:00
Aparajita Fishman cae5486ec6 Added missing class checks in +initialize, regularized checking code 2012-06-28 12:05:18 -07:00
Alexander Ljungberg a769618e3e Don't copy an array we'll copy again 2 lines later.
If the delegate returns nil we're just copying nil, and if it does return an array we only use it for a single read-only `arrayByAddingObjectsFromArray:`.
2012-06-28 19:15:20 +01:00
Alexander Ljungberg 80d537958e Fixed: CPToolbar delegate toolbarDefaultItemIdentifiers: is optional.
This fix makes it possible for a toolbar defined in a cib to have a delegate set without defining `toolbarDefaultItemIdentifiers:` like in Cocoa. You might be implementing other delegate methods.
2012-06-28 19:12:05 +01:00
aparajita d923fb56e2 Merge pull request #1577 from slevenbits/key-loop-fix
Key loop fix
2012-06-28 10:06:30 -07:00
Aparajita Fishman 7747bbffcf Fixed key loop calculation, might as well use _initialFirstResponder instance variable instead of accessor 2012-06-28 10:01:07 -07:00
ggsato db47d8fb85 fixed needsUntitled evaluation 2012-06-28 12:01:37 +09:00
Alexander Ljungberg c52315cd8d Refs #1572. Merge extra commit re highlights. 2012-06-25 21:58:02 +01:00
Alexander Ljungberg a2787f8783 Formatting. 2012-06-25 21:57:28 +01:00
Ilya Kulakov 913308d886 Refs #1572. Fix highlighted status is not preserved.
When higlightsBy == CPNoCellMask and showsStateBy == CPChangeBackgroundCellMask
higlighted status must be preserved when a user switch state from Off to On.
2012-06-26 03:54:59 +07:00
Alexander Ljungberg 21bb383193 Refs #1527. Fix button performClick: highlight.
Critically this is what enables button highlighting on key equivalents.
2012-06-25 18:13:16 +01:00
Alexander Ljungberg bd83885eca Refs #1527. Backwards compatibility.
If no highlight or state masks were encoded (button was encoded prior to them being added), make sure to let the default settings stand.
2012-06-25 17:42:31 +01:00
Alexander Ljungberg d34d139658 Refs #1572. Default CPButton type.
If a button is created in code it should act like a regular momentary push in button by default.
2012-06-25 17:21:56 +01:00
Alexander Ljungberg f5c201c0be Refs #1572. Fixed: CPPushInCellMask in showsStateBy.
Code didn't match comment.
2012-06-25 17:18:07 +01:00
Alexander Ljungberg 10fcc0c452 Refs #1572. Minor fixes. 2012-06-25 16:26:44 +01:00
Alexander Ljungberg 378822b777 Merge pull request #1572 from slevenbits/cpbutton-masks
CPButton and subclasses respect highlightsBy and showsStateBy masks now.

Conflicts:
	AppKit/CPButton.j
	Tests/Manual/CPButtonTest/AppController.j
	Tests/Manual/CPButtonTest/Info.plist
	Tests/Manual/CPButtonTest/Resources/MainMenu.cib
	Tests/Manual/CPButtonTest/Resources/MainMenu.xib
2012-06-25 16:05:03 +01:00
Alexander Ljungberg edebb81ed4 Merge pull request #1570 from aradabaugh/cpbutton-types
Enable additional button types for CPButton
2012-06-25 15:40:23 +01:00
Ilya Kulakov 7cf3ac3b40 CPButton and subclasses respect highlightsBy and showsStateBy now. 2012-06-25 18:57:10 +07:00
Ilya Kulakov c46c365823 Extenend CPButtonTest to test highlightsBy and showsStateBy. 2012-06-25 18:57:06 +07:00
Ilya Kulakov 66f5e1fb64 Take into account highlightsBy and showsStateBy when decoding cib.
nib2cib was modified to take into account these variables
during conversion nib->cib.
2012-06-25 18:57:01 +07:00
Ilya Kulakov c80417c433 Add highlightsBy method that returns current higlightsBy mask. 2012-06-25 18:56:56 +07:00
Martin Carlberg 32e3df1e80 Added key value binding support for CPPopupButton 2012-06-25 08:23:14 +02:00
Malte Tancred 3f65153d4f Corrected the format specifier for the flags variable. 2012-06-23 22:46:25 +02:00
Adam Radabaugh 5fbf0f83cb Make the check for CPOnOffButton tracking correctly use the highlights mask. 2012-06-23 14:26:46 -06:00
Adam Radabaugh 84c8427bb4 Merge branch master 2012-06-23 14:21:45 -06:00
cacaodev 539a8f0ca9 An OJTest for the table view's content binding 2012-06-22 21:59:41 +02:00
Alexander Ljungberg d39849b297 Improve token field keyboard navigation when tokens are selected.
If one or more token is selected and the left arrow key is pressed, collapse the selection to the left of the first selected token.

Similarly, on right arrow key collapse to the right of the last token.

Note that shift-left and shift-right have no effect if the first or last token respectively in the field are already selected.
2012-06-21 19:24:22 +01:00
Alexander Ljungberg 7764921c21 Select all support for CPTokenField.
Cmd-A (Mac) or Ctrl-A (other) finishes any ongoing editing and selects all tokens in a token field.

This commit also adds support for the `selectText:` and `selectAll:` methods.
2012-06-21 19:17:34 +01:00
Alexander Ljungberg 26ceb25e7b Merge pull request #1569 from slevenbits/rwelephant-token-field
Token field improved autocomplete, key bindings support, clean up
2012-06-21 10:32:33 -07:00
Aparajita Fishman 13423e43d5 Removed stray console.log 2012-06-20 11:05:22 -07:00
Aparajita Fishman 45da163230 text tweak 2012-06-18 09:31:34 -07:00
aparajita 281e3c925c Merge pull request #1566 from slevenbits/CPArrayController-tweaks
CPArrayController tweaks
2012-06-18 09:03:22 -07:00
Aparajita Fishman 6f50900b1b Added missing removeObjectAtArrangedObjectIndex, added missing return 2012-06-18 09:00:59 -07:00
Alexander Ljungberg 2200e40001 Fixed: browser shortcuts wouldn't work when a token field was active.
We now leave the default propagation policy of Cappuccino in place, which normally is NO for regular characters but YES for things which could be shortcuts.
2012-06-16 12:31:50 +01:00
Alexander Ljungberg 44b609f604 Don't make space for editing in token field if tokens are selected.
If the editor is placed while there is a token selection it can cause the token view to become scrollable to a white area at the bottom even that there is no editing cursor. And even if the editor is not at the bottom, the empty space made for the editor makes no sense when no editing cursor is visible.
2012-06-16 12:31:50 +01:00
Alexander Ljungberg d5918157ff Overwrite selected tokens by typing support.
If tokens are selected in `CPTokenField` and new text is entered, the selected tokens are overwritten by the newly entered text.
2012-06-16 12:31:50 +01:00
Alexander Ljungberg 19b53746cf Fix nil representedObjectForEditingString: response handling.
If `tokenField: representedObjectForEditingString:` returns nil, act the same as if the delegate method didn't exist. This matches Cocoa.
2012-06-16 12:31:50 +01:00
Alexander Ljungberg d0769ec360 Oops. Fix object value fix. 2012-06-16 12:31:49 +01:00
Alexander Ljungberg 3c20bf8ad6 Allow token field insertText: to be somewhat overridden.
If `insertText:` is overridden to do nothing, nothing in inserted.
2012-06-16 12:31:49 +01:00
Alexander Ljungberg 3eab2a528f Make token field object value more like Cocoa.
If a half typed token is in the field, Cocoa tries to convert it to a representedObject before responding to objectValue. Now CPTokenField does the same.
2012-06-16 12:31:49 +01:00
Alexander Ljungberg fb404a0671 Hide private token field API. Fix return type. 2012-06-16 12:31:49 +01:00
Alexander Ljungberg 6d6cf52180 Minor token field optimisation. 2012-06-16 12:31:49 +01:00
Alexander Ljungberg e9ba326610 Inlineable range functions. 2012-06-16 12:31:49 +01:00
Alexander Ljungberg 55ca956f50 Remove nonstandard CPCopyRange. 2012-06-16 12:31:49 +01:00
Alexander Ljungberg f43c643d5a Allow token field subclasses to override defaultCompletionDelay.
Also fixed incorrect return type.
2012-06-16 12:31:49 +01:00
Alexander Ljungberg 69f5fc536c Key bindings support for token field.
Also improve compatibility with `CPTextField` superclass and subclassing support by properly using `interpretKeyEvents:` like `CPTextField`.
2012-06-16 12:31:49 +01:00
Alexander Ljungberg 132ac7c03f Token field 'keyUp:' support. 2012-06-16 12:31:49 +01:00
Alexander Ljungberg 5683af9bc8 Improve token field subclassing support.
Token field now triggers autocompletion from textDidChange: which better meets the expectations of Cappuccino programmers, and is closer to how Cocoa does it.

Eliminated custom non-Cappuccino key press handler.
2012-06-16 12:31:48 +01:00
Alexander Ljungberg 429933f601 Fix token field keyDown: handling.
`CPTokenField` had custom key down handling making it function poorly with Cappuccino's event handling and subclasses.
2012-06-16 12:31:48 +01:00
Alexander Ljungberg 317364681a Fixed: make sure autocomplete menu fits within browser. 2012-06-16 12:31:48 +01:00
Alexander Ljungberg 9575fd7771 Autosize token field autocomplete menu.
The new menu is much more efficient for the user:

* Less tall items makes it much easier to select among many completions.
* Exactly wide enough for widest item.
* Tall enough to show all items (instead of just 3 as before).
* Uses a maximum width and height defined by the screen edges and some Cocoa-like constants.
2012-06-16 12:31:48 +01:00
Alexander Ljungberg 85cfb18906 Place token autocomplete underneath what's being completed.
This matches Cocoa.
2012-06-16 12:31:48 +01:00
Alexander Ljungberg 33fe1573ad Ensure autocomplete menu is on top.
The menu should appear above other normal windows and controls like a regular CPMenu. To do this, put the pop up in its own window with the `CPPopUpMenuWindowLevel` window level.
2012-06-16 12:31:48 +01:00
Alexander Ljungberg 2574fac44a Remove token field reference. 2012-06-16 12:31:48 +01:00
Alexander Ljungberg b166995327 Move autocomplete into reusable class. 2012-06-16 12:31:48 +01:00
Alexander Ljungberg feaf9c6f20 Improve CPTokenField autocomplete scrolling. 2012-06-16 12:31:48 +01:00
Alexander Ljungberg 0ef03d31b8 Refactor CPTokenField autocomplete.
The new code is simpler (single responsibility principle) and makes it easier to improve on autocomplete.
2012-06-16 12:31:48 +01:00
Alexander Ljungberg 80ee88d3a7 Hide another non-public API in CPTokenField. 2012-06-16 12:31:48 +01:00
Alexander Ljungberg bbc45dd947 Support tokenField:representedObjectForEditingString: delegate method.
This improves support for represented objects and is used both when an autocompletion suggestion is used or when the name of a token is typed in by hand.

The behaviour of taking an array of strings from `completionsForSubstring` and then asking for a represented object once a choice has been accepted matches the behaviour of Cocoa.
2012-06-16 12:31:47 +01:00
Alexander Ljungberg d07ee3ea23 Hide non-public API in CPTokenField.
Also improve documentation.
2012-06-16 12:31:47 +01:00
Alexander Ljungberg 7ffd65476b Fixed: token field auto completions.
Auto completions are strings, not represented objects. Revert "Fix CPTokenField autocompletion to deal with represented objects"

This reverts commit 8b9a0edeba.
2012-06-16 12:31:47 +01:00
Alexander Ljungberg ca0a07cab8 Formatting. 2012-06-16 12:31:47 +01:00
Antoine Mercadal 0d29f15b70 Merge pull request #1513 from BlairDuncan/MenuTimestampFix
Fix for menu selection that was broken with the change to CPEvent timestamp
2012-06-14 17:02:06 -07:00
Antoine Mercadal 714d36d8c8 Merge branch 'CPImageView-bindings' of https://github.com/cacaodev/cappuccino into pull1534 2012-06-14 13:05:04 -07:00
Antoine Mercadal cd94819099 Merge branch 'issue1435' of https://github.com/stewa/cappuccino into issue1435 2012-06-14 11:58:49 -07:00
Antoine Mercadal 52199776d5 Merge pull request #1537 from mrcarlberg/cptableview_selection_radius
Added a themed attribute for round rect selection of rows. [+1]
2012-06-14 10:29:58 -07:00
Antoine Mercadal f8df87edcf Merge pull request #1561 from tancred/xcodeapp_always_creates_support_sources
Create support sources folder if necessary.

Reviewed.
2012-06-14 10:27:43 -07:00
Antoine Mercadal dc68daa859 Merge pull request #1564 from tancred/xcodecapp_sync_last_event_id_more_frequently
Make XcodeCapp synchronize file system event status more frequently.

Reviewed.
2012-06-14 10:24:40 -07:00
Malte Tancred 1fd021770e Split -synchronizeLastEventId in two methods.
The first method (updateUserDefaultsWithLastEventId) just
sets the default while the other (synchronizeUserDefaultsWithDisk)
forces a synchronization with the disk.
2012-06-14 11:43:52 +02:00
Antoine Mercadal 6f32e598e9 Add manual tests for disabled button with image 2012-06-13 15:22:53 -07:00
Antoine Mercadal 19794b06ab nib2cib sets _imageDimsWhenDisabled to YES for buttons 2012-06-13 15:22:26 -07:00
Antoine Mercadal ecdb064a5b Makes CPButton to dim image when disabled by default 2012-06-13 15:21:45 -07:00
Antoine Mercadal d67a03bfb4 make disabled buttonbar buttons more visible 2012-06-13 14:30:26 -07:00
Antoine Mercadal c361d7a52a Merge branch 'new-cpbuttonbar-artwork' 2012-06-13 10:12:05 -07:00
Malte Tancred 0018be6fd8 Make XcodeCapp synchronize file system event status more frequently.
This is a small fix that makes XcodeCapp update the latestEventId value
in the defaults database at the end of each FSEvents callback.

Prior to this fix, the synchronization was performed only when the user
actively decided to stop listening to a project.
2012-06-13 10:37:08 +02:00
Antoine Mercadal 4a4aa5fc10 update artwork for CPButtonBar 2012-06-12 19:03:32 -07:00
Alexander Ljungberg 8791195673 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-06-13 02:21:07 +01:00
Alexander Ljungberg 72374257ef Minor optimisation and clean up. 2012-06-13 02:20:58 +01:00
Alexander Ljungberg 1b9def2101 Allow asymmetric toolbar margins. Foundation for theming.
Toolbars cannot be themed yet but when theming becomes possible this code should adapt readily.
2012-06-13 02:17:13 +01:00
Alexander Ljungberg 7a467e249e Manual test for toolbars. 2012-06-13 01:40:59 +01:00
Alexander Ljungberg a66942b1b1 Fix and tweak toolbar margins. 2012-06-13 01:40:20 +01:00
Alexander Ljungberg acd3425c43 Dynamic CPToolbar height,
* Support for tall custom widgets. You can now finally have that CPTableView you always wanted in your toolbar.
* "Labels only" mode now makes sense, resulting in a narrow text only toolbar instead of a very tall toolbar with centred labels.
* Use any size toolbar icons such as 48x48 and the toolbar adapts automatically (unlike Cocoa).
2012-06-13 01:26:33 +01:00
Alexander Ljungberg 70bc45ba12 Toolbar CPToolbarDisplayModeIconOnly support. 2012-06-12 23:26:43 +01:00
Alexander Ljungberg 026c210e64 Toolbar CPToolbarDisplayModeIconOnly support. 2012-06-12 23:05:16 +01:00
Alexander Ljungberg 3bc1849041 Improve toolbar item layout.
The height of all items is determined by the tallest item, like in Cocoa. But unlike Cocoa our toolbar is presently fixed height so in order to make this look well for small or large items, the whole row of items is now vertically centred, making the allocation of margin above and below automatic.

Furthermore if a toolbar item has a small view or a small icon, it is now centred within the available space above the label. For example, for a tiny icon in one item next to a normal size icon the tiny icon would be centre aligned with the larger icon.
2012-06-12 23:04:33 +01:00
Antoine Mercadal 17668aca17 Merge remote-tracking branch 'upstream/master' 2012-06-12 11:59:26 -07:00
Antoine Mercadal 2a48b0ca54 make actualResizeEvent a private method 2012-06-12 11:57:19 -07:00
Antoine Mercadal 5acc15ea9e Merge https://github.com/jivadevoe/cappuccino into pr-1545 2012-06-12 11:45:34 -07:00
Malte Tancred 52fff2056b Fixed code standard issues. 2012-06-12 17:44:17 +02:00
Alexander Ljungberg 2a955884b8 Fix header. 2012-06-11 13:14:00 +01:00
Alexander Ljungberg ad5403b538 Setting the shadow style just once will do. 2012-06-11 13:13:36 +01:00
Alexander Ljungberg f538cbc51d Re #1560. Remove obsolete function. 2012-06-10 01:18:56 +01:00
Alexander Ljungberg e232b18b94 Merge pull request #1560 from mrcarlberg/cappuccino
---

I needed to sort a lot of objects and was not impressed by the speed.
Sharing my improvements...
2012-06-10 01:00:40 +01:00
Alexander Ljungberg fcf62080d6 Re #1562. Make native comparison more realistic.
This might have a small speed implication.
2012-06-10 00:59:08 +01:00
Alexander Ljungberg 58103ce0f3 Re #1562. Also performance test selector sort.
It looks like issue #1560 will cause a different sorting function to be used for selectors vs descriptors so performance of both should be monitored for regressions.
2012-06-10 00:58:27 +01:00
Alexander Ljungberg 0827f584be Re #1562. Simplify. 2012-06-10 00:39:37 +01:00
Alexander Ljungberg f042996e7f Re #1562. Only load sort text for tests which use it. 2012-06-09 23:16:52 +01:00
Alexander Ljungberg 7b307a6fb4 Re #1562. Format code. 2012-06-09 23:08:27 +01:00
Alexander Ljungberg bb8a7bacdc Merge pull request #1562 from cacaodev/cappuccino
---

for random numeric array and text array.
2012-06-09 16:49:23 +01:00
Martin Carlberg 0696b22971 Fixed formatting 2012-06-08 20:18:22 +02:00
Martin Carlberg d7ff93f7f2 SortUsingDescriptors: Using the selector in the descriptor instead of always using compare: 2012-06-08 19:48:39 +02:00
cacaodev 0483f9d714 CPArrayPerformanceTest: fixed native sort testing, added tests for random numeric array and text array 2012-06-08 18:19:37 +02:00
Malte Tancred 56c0f7f6f1 Create support sources folder if necessary.
Make sure the the xCodeSupport/Sources folder is always
present. The objj tool will fail if it's missing.

The Sources folder could be missing if it's not checked
into a repos for example.
2012-06-08 13:21:47 +02:00
Martin Carlberg dc30092b60 A very fast sortUsingDescriptors:
I needed to sort a lot of objects and was not impressed by the speed.
Sharing my improvements...
2012-06-07 23:25:58 +02:00
aparajita 7ccd6f842b Merge pull request #1557 from cacaodev/CPTableView-selectedColumn-typo
CPTableView -selectedColumn : missing return statement
2012-06-06 08:08:23 -07:00
cacaodev 299a664b9c CPTableView -selectedColumn : missing return statement 2012-06-06 14:24:28 +02:00
Alexander Ljungberg 0ed398310f Merge branch 'master' of github.com:cappuccino/cappuccino 2012-06-02 13:19:13 -07:00
Alexander Ljungberg 55709cb83a Test CPDate testInitWithString with a date prior to 1970.
This verifies that there are no problems with negative time intervals.
2012-06-02 13:18:58 -07:00
Alexander Ljungberg d0c7796e7c Match CPDate distantPast and distantFuture with Cocoa. 2012-06-02 13:17:34 -07:00
aparajita 544dff205d Merge pull request #1556 from cacaodev/CPDate-referenceDate
CPDateReferenceDate should be 'Jan 1 2001' instead of 'Feb 1 2001'
2012-06-02 12:41:46 -07:00
Alexander Ljungberg 25763962b2 Code formatting. 2012-06-02 11:53:04 -07:00
Alexander Ljungberg fc858933be Re #1556. Make CPDate testSince1970 agree with new reference date. 2012-06-02 11:32:19 -07:00
Alexander Ljungberg 6877aaaf61 Re #1556. Unit test CPDate dateWithTimeIntervalSinceReferenceDate:. 2012-06-02 11:27:19 -07:00
Alexander Ljungberg e4ab1256da Merge pull request #1556 from cacaodev/cappuccino
---

See <https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/Reference/Reference.html#//apple_ref/occ/clm/NSDate/dateWithTimeIntervalSinceReferenceDate:>
2012-06-02 11:23:22 -07:00
cacaodev f2dd6b5dce CPDateReferenceDate should be 'Jan 1 2001' instead of 'Feb 1 2001' 2012-06-02 19:38:34 +02:00
Blair Duncan eeceaa0c9b unlite if mouse is moved off and cursor up hilites last item if none 2012-06-01 20:17:09 -04:00
Alexander Ljungberg bc79d57712 Clean up. 2012-05-27 22:21:11 +01:00
aparajita 954ec26e80 Merge pull request #1551 from ggsato/subclassingDocController
fixed shared CPDocumentController instantiation and added its test
2012-05-26 12:44:18 -07:00
cacaodev 086c0e6ef0 Merge remote-tracking branch 'upstream/master' into CPTableView-content-binding 2012-05-26 08:03:56 +02:00
ggsato fabe1d8991 formatting and now subclassing is tested by Open a document 2012-05-26 11:08:57 +09:00
Antoine Mercadal 02b65e6dfb Fix a bug in Nib2Cib.j when configInfo is null 2012-05-25 18:06:05 -07:00
Alexander Ljungberg aa546374f3 Fixed: typo in aa4eff9. 2012-05-26 00:22:23 +01:00
Alexander Ljungberg 288ec78c3e Fixed: split view autosave.
The fix to prevent incorrect autosaving prevented correct autosaving as well.
2012-05-26 00:04:12 +01:00
Martin Carlberg 2f875615a2 Removed hardcoded width in disclosure button 2012-05-25 11:14:43 +02:00
Martin Carlberg 49adcd85fc Removed useless space after capp_lint warning 2012-05-25 10:54:10 +02:00
Martin Carlberg 8e785c2210 Removed set and get methods and blank line before if added. 2012-05-25 10:47:07 +02:00
ggsato 310422adb1 Added another way to subclass CPDocumentController 2012-05-25 17:09:31 +09:00
ggsato 0dbebf2f04 Added another way to subclass CPDocumentController 2012-05-25 16:54:10 +09:00
Alexander Ljungberg 46aabf0ea2 Code formatting. 2012-05-25 01:12:57 +01:00
Alexander Ljungberg 1a14ef2418 Fixed: capp_lint handling of string literals with escapes.
This could cause capp_lint to warn about what it perceived as code inside of string literals if the string literal ended with an escaped backslash.
2012-05-25 01:07:35 +01:00
Alexander Ljungberg aa4eff9f8d Format code, fix accidental global. 2012-05-25 00:04:46 +01:00
Alexander Ljungberg 9ffaf538e2 Remove unary + warning from capp_lint.
A statement like `x = +y;` actually does have an effect in JavaScript.
2012-05-24 23:58:01 +01:00
Alexander Ljungberg 2a21ce4a0c Support function argument types in capp_lint.
Syntax such as function(/*CPString*/anArgument) {} should not generate a warning, and in general inline /**/ comments should be ignored for linting purposes.
2012-05-24 23:52:30 +01:00
Alexander Ljungberg 09d5957c82 Code formatting. 2012-05-24 23:40:15 +01:00
Alexander Ljungberg 2b8b570dd4 Fixed: capp_lint exponential warnings.
capp_lint issued warnings over numerical literals like 2.1e+6 even that they were correctly formatted.
2012-05-24 23:22:24 +01:00
Alexander Ljungberg a7bee74fb0 Report the original line contents in capp_lint.
capp_lint does some preprocessing of lines to simplify the lint tests, but the user will expect the regular, non processed lines in the output.
2012-05-24 22:34:50 +01:00
Alexander Ljungberg 1f803f52d1 Add some illustrative capp_lint doctests. 2012-05-24 19:37:30 +01:00
Alexander Ljungberg 0d5b4d4958 Fixed: if linted text didn't end with a newline the last character would be ignored. 2012-05-24 19:26:05 +01:00
Alexander Ljungberg 24cce3ca8a Make LintChecker().lint_text('<code>') possible.
Made LintChecker()'s "view" and lint_text's "filename" arguments optional. Filename will default to <stdin> like Python does when you pipe to it. Also return found errors from lint_text as a convenience.
2012-05-24 19:24:50 +01:00
ggsato 2a0ee14130 wrapped window.status clear statement 2012-05-25 01:52:09 +09:00
Alexander Ljungberg e25394a322 Code formatting. 2012-05-24 17:10:46 +01:00
ggsato ab1dc15393 moved types declaration 2012-05-24 23:58:59 +09:00
ggsato 3a750591bb moved types declaration 2012-05-24 23:55:04 +09:00
ggsato 7da9877c5f fixed shared CPDocumentController instantiation and added its test 2012-05-24 23:12:07 +09:00
Alexander Ljungberg 66ff5dcb86 Merge pull request #1550 from ggsato/cappuccino
---

This is a tiny little minor fix of MainMenu.xib template. 

Before

https://www.dropbox.com/s/cqq8zhy8o2yof51/NibTemplate_Before.png

After

https://www.dropbox.com/s/78j95f1gl596vro/NibTemplate_After.png
2012-05-24 13:54:57 +01:00
ggsato f50a6ea7a3 fixed menu labels by removing numbers at Identity Label 2012-05-24 18:09:17 +09:00
Adam Radabaugh 253d7497ef Merge branch 'master' of git://github.com/cappuccino/cappuccino 2012-05-23 00:15:22 -06:00
Aparajita Fishman 1efc2e3c15 Fixed parsing in CGSizeFromString and CGPointFromString 2012-05-22 12:52:54 -07:00
Adam Radabaugh 909c6ed171 Fix style issue in CPControl 2012-05-19 16:56:57 -06:00
Aparajita Fishman b4f916351e Added capp_lint check for space inside parens and dependent statement on same line, cleaned up CPString.j 2012-05-19 14:20:07 -07:00
Adam Radabaugh a47a5b76eb Fix style issue in CPButton.j 2012-05-18 23:15:26 -06:00
Adam Radabaugh 919bfb7960 Fix style issue in CPControl 2012-05-18 17:11:04 -06:00
Antoine Mercadal bc09c99952 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2012-05-18 12:51:34 -07:00
Antoine Mercadal 28ccb27d4f Merge branch 'cpstring_append_path_component_cocoa_way' of https://github.com/mrcarlberg/cappuccino into PR_mrcarlberg_cpstring_append_path_component_cocoa_way 2012-05-18 12:47:41 -07:00
Jiva DeVoe d205c4eac7 updating to remove a comment and to fix a formatting issue 2012-05-18 10:25:06 -07:00
Jiva DeVoe 18662deec6 removed the if statement before the invalidate 2012-05-17 23:52:41 -07:00
Jiva DeVoe d955eceafa fixed an errant semicolon 2012-05-17 23:34:26 -07:00
Jiva DeVoe 995d529fb7 Added a very hacky workaround for the jittery resize bug in webkit. Ref: https://github.com/cappuccino/cappuccino/issues/1325 2012-05-17 23:10:04 -07:00
Aparajita Fishman d4e460dac5 When popover closes implicitly, popoverShouldClose delegate method should be called.
Added extra button popover to test -close method, which does not consult popoverShouldClose.
2012-05-17 17:02:45 -07:00
cacaodev 0314005e0e Added CPImage -data. If needed, generates data for canvas compatible browsers. Added a test in CPImageViewTest where an image is created from the data of another image 2012-05-17 23:02:49 +02:00
cacaodev 7831085a97 Merge remote-tracking branch 'upstream/master' into CPImageView-bindings
Conflicts:
	Tests/Manual/CPImageViewbindingsTest/Resources/MainMenu.cib
2012-05-17 14:01:20 +02:00
cacaodev db8f2fdf75 Added support for CPTableView content binding, generally used with view-based tables.
Grouped the 3 ways to set objectValue on a dataview (content binding, column value binding or regular delegate method) under one main method: _setObjectValueFortableColumn:row:ForView:
    Also fixed a bug where the dragging rows didn't have their bindings applied. Columns and row dragging are now using the previous method for setting data view objectValue.

    Updated TableBindings example: table with content binding vs. columns with value binding.
2012-05-16 15:57:26 +02:00
aparajita d18e77329f Merge pull request #1542 from BlairDuncan/controlDidFailToFormatStringFix
controlDidFailToFormatString should send a string not an HTML element
2012-05-15 21:39:14 -07:00
Blair Duncan 8f4acc98d4 controlDidFailToFormatString should send a string not an HTML element 2012-05-16 00:03:00 -04:00
Adam Radabaugh 95f7ba29cc Update latest nib2cib with demo of button types 2012-05-15 14:38:54 -06:00
Adam Radabaugh 7ab20145d1 Merge branch 'master' of git://github.com/cappuccino/cappuccino
Conflicts:
	Tests/Manual/CPButtonTest/Resources/MainMenu.cib
2012-05-15 14:15:03 -06:00
Blair Duncan 5f7d1e8dc3 controlDidFailToFormatString should send a string not an HTML element 2012-05-15 16:07:56 -04:00
Antoine Mercadal 6010288124 Merge pull request #1541 from cacaodev/CPPopover-setBehavior
CPPopover typo: setBehaviour: -> setBehavior:

Reviewed.
2012-05-15 12:49:59 -07:00
cacaodev 8a10105f48 CPPopover typo: setBehaviour: -> setBehavior: 2012-05-15 21:42:14 +02:00
Antoine Mercadal 478fb43d2a Fix all Manual tests showing empty UI. (re-run nib2cib on all of them) 2012-05-15 12:08:19 -07:00
Alexander Ljungberg 4b7cef637b Refs #1538. Reapply formatting. 2012-05-14 21:21:45 +01:00
Alexander Ljungberg 69c72d366e (Fix commit attribution) Merge pull request #1538 from mrcarlberg/cappuccino
---

Dont you hate when your logs of arrays and dictionaries display [Object object] when you have JavaScript objects in them. Now with this patch all JavaScript objects will be display with all attributes in a nice good looking way. Log CGRect, CGPoint and other JavaScript objects withour any hassle anymore. For example: console.log([myRect]);

Conflicts:
	Foundation/CPObject.j
	Tests/Foundation/CPMutableArrayTest.j
2012-05-14 21:20:41 +01:00
Alexander Ljungberg 5e7125e310 Refs #1538. Clean up, accidental global. 2012-05-14 21:12:31 +01:00
Alexander Ljungberg bc370a2a5a Merge pull request #1538 from mrcarlberg/cappuccino
---

Dont you hate when your logs of arrays and dictionaries display [Object object] when you have JavaScript objects in them. Now with this patch all JavaScript objects will be display with all attributes in a nice good looking way. Log CGRect, CGPoint and other JavaScript objects withour any hassle anymore. For example: console.log([myRect]);
2012-05-14 21:12:17 +01:00
Martin Carlberg 0abd9855c2 Moved new description functionallity from CFDictionary to CPDictionary.
Added testcase for both CPDictionary and CPArray. Fixed failing testcase.
Checked all new code with capp_lint for correct formatting.
2012-05-14 10:14:05 +02:00
Alexander Ljungberg 3525bd0183 Code formatting. 2012-05-13 14:26:19 +01:00
Darrell Walisser 098f72651c -correct documentation 2012-05-12 15:05:48 -04:00
Darrell Walisser 8c1d147319 -remove next sheet context hack
-order of notifications/didEndSelect are correct now
2012-05-12 14:22:54 -04:00
Martin Carlberg 327debe3a8 Some more clean-up 2012-05-11 23:39:41 +02:00
Martin Carlberg 4af27541d0 Clean-up 2012-05-11 23:33:37 +02:00
Martin Carlberg 70182a0ea2 Description methods in CPArray and CPDictionary will display JavaScript object attributes instead of displaying [Object object]
Don't you hate when your logs of arrays and dictionaries display [Object object] when you have JavaScript objects in them.
Now with this patch all JavaScript objects will be display with all attributes in a nice good looking way. Log CGRect, CGPoint
and other JavaScript objects withour any hassle anymore. For example: console.log([myRect]);
2012-05-11 17:40:11 +02:00
Martin Carlberg 183260d9e3 Added a themed attribute for round rect selection of rows.
Selections in the tableview can now have round corners. The default is a regular
rect, but if the selecction radius is changed. Nice good looking round rect
selections will appear.
2012-05-11 16:14:14 +02:00
Martin Carlberg df2cf923e1 MainBundle path has no '/' at the end when running in CommonJS.
This will make relative paths fail. For example if OBJJ_INCLUDE_PATHS has the path "../../MyLibrary".
MyLibrary will not be found when the path is joined with mainBundlePath without an ending '/'.
This is working when running in Browser.
2012-05-11 15:52:44 +02:00
Martin Carlberg c35ccde682 Added stringByAppendingPathComponent: and stringByAppendingPathExtension: to CPString. Also, changed CPString path behaviour to correspond to Cocoa behaviour. 2012-05-11 15:32:18 +02:00
Alexander Ljungberg afbfde0909 Code formatting. 2012-05-10 16:01:22 +01:00
Alexander Ljungberg e72093c91e Merge pull request #1531 from BlairDuncan/cappuccino
---
2012-05-10 15:50:10 +01:00
Blair Duncan 1ffdaf0f8b typo, LOG should be log 2012-05-10 09:01:03 -04:00
Blair Duncan 74431972d8 added missing LOG math global and replaced any math. with correspoinding global 2012-05-10 08:55:19 -04:00
Stefan Wallström 19804720af CPTableView: Don't update selection etc unless becoming first responder succeeds.
Fix for issue #1435
2012-05-10 13:42:37 +02:00
Alexander Ljungberg 1f8555ffd2 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-05-10 00:19:49 +01:00
Alexander Ljungberg 4218c49a7e Refs #1529. Verify that the actual issue error is gone. 2012-05-10 00:17:25 +01:00
Alexander Ljungberg 8aaf298466 Fixes #1529. Fixed: Incorrect CPDecimalNumber result for 220000/220.
And in general divisions where the quotient had fewer digits than the dividend when disregarding exponent would fail.

We want to stop dividing when we've gone over all the digits in the dividend and the remainder is 0.
2012-05-10 00:16:56 +01:00
Alexander Ljungberg 82e2c7a0e8 Refs #1529. Simpler test: 11/11. 2012-05-10 00:02:44 +01:00
Alexander Ljungberg 27fa01648f Code formatting, delete stray */. 2012-05-10 00:01:03 +01:00
Alexander Ljungberg ab25408429 Refs #1529. Unit test exposing division error. 2012-05-09 23:39:11 +01:00
Alexander Ljungberg d896baf38b Code formatting. 2012-05-09 19:09:35 +01:00
Darrell Walisser 53798c1545 -allow any window to become a sheet 2012-05-06 12:07:02 -04:00
Darrell Walisser 1e6f0090da -allow any window to become a sheet 2012-05-06 12:06:23 -04:00
aparajita 0dcca6d388 Merge pull request #1527 from BlairDuncan/reNib2cibTestFiles
ran nib2cib on all of current test files xib's
2012-05-04 18:04:55 -07:00
Blair Duncan 934691fffb nib2cib all of current test files xib's 2012-05-04 20:10:55 -04:00
Alexander Ljungberg 6bc26eb0cc Test app to verify CPProgressIndicator rendering, nib2cib and coding. 2012-05-03 20:42:41 +01:00
Alexander Ljungberg bdcc1539ac Use an ephemeral subview for the bar of a progress indicator.
This is clearer code and avoids encoding the 'pill view' automatically.
2012-05-03 20:40:50 +01:00
Alexander Ljungberg 6715fbbce2 nib2cib support for CPProgressIndicator size. Fixed: a regular size spinner in IB became twice as large in Cappuccino. 2012-05-03 20:27:05 +01:00
Alexander Ljungberg da055f83b3 Fixed: CPProgressIndicator encoder wasted space and caused errors.
The errors would cause exceptions such as "Not allowed to load local resource: file:///<some local path from the machine that ran nib2cib>" when loading cib driven app through a web server.
2012-05-03 19:45:12 +01:00
Alexander Ljungberg 1476efce90 Minor formatting. 2012-05-03 01:36:17 +01:00
Adam Radabaugh 2078d0e23b Restore copywrite info in headers. 2012-05-01 15:16:44 -06:00
Adam Radabaugh ea0107f67f Enable additional button types in CPButton with manual test. 2012-05-01 15:11:34 -06:00
Darrell Walisser c71f5baef2 -implement orderOut: to control sheet dismissal
-lots of comments and a few debug prints
2012-04-28 20:36:10 -04:00
Darrell Walisser 66f55df44a -use _endSheet to end sheets
-do not call orderFront: if the sheet is already visible
2012-04-28 20:32:13 -04:00
Darrell Walisser 8fd5f30b87 -call orderOut: to dismiss the alert sheet 2012-04-28 20:28:09 -04:00
Darrell Walisser 8bc4a287a6 -update docs for sheet notifications 2012-04-28 11:31:01 -04:00
cacaodev d1dd177bfd CPImageView: support for CPDataBinding. Test. 2012-04-28 17:12:22 +02:00
cacaodev 80b6788638 CPImage -initWithData: 2012-04-28 17:11:37 +02:00
Darrell Walisser ce6444c30e -implement CPWindow sheet notifications on delegate
-raise error when window already has a sheet, or attaching sheet to a sheet
2012-04-28 10:13:02 -04:00
Alexander Ljungberg c437537749 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-04-27 01:19:56 +01:00
Alexander Ljungberg c16c0309c8 Fixed: CPOutlineView setMenu: was not effective.
A CPOutlineView without a delegate `outlineView:menuForTableColumn:item` method, would not display its context menu as specified by `setMenu:` or in IB.
2012-04-27 01:19:47 +01:00
aparajita 1dcd380bb2 Merge pull request #1283 from cacaodev/CPRulePredicateEditor
CPRuleEditor & CPPredicateEditor fixes and enhancements
2012-04-26 12:02:07 -07:00
cacaodev 6fe3d53a13 Merge remote-tracking branch 'upstream/master' into CPRulePredicateEditor 2012-04-26 20:34:18 +02:00
cacaodev 92cdda1d22 capplinted CPRuleEditor/*.j 2012-04-26 20:34:09 +02:00
Aparajita Fishman 3eb4155489 Switched to /usr/bin/env bash for better cross-platform compatibility 2012-04-26 19:11:05 +02:00
Aparajita Fishman e657e7a684 Make capp_lint use a single code base for command line and SublimeLinter 2012-04-26 18:14:06 +02:00
Alexander Ljungberg 5446bedfcc Fixes #1519. Fixed: capp_lint __init__ takes at least 2 arguments error.
Some SublimeLinter specific bits appear to have made it into the standalone capp_lint.
2012-04-26 16:02:41 +01:00
Alexander Ljungberg be36803570 Fixed: CPPredicateEditor "Display value must be…" exception in recent revisions. 2012-04-26 15:35:55 +01:00
Alexander Ljungberg 998bdb550b Merge branch 'master' of github.com:cappuccino/cappuccino 2012-04-26 15:25:59 +01:00
Alexander Ljungberg a0c7305334 Fixed: collection views cleared their selection whenever the content was changed.
This was unlike Cocoa and prevented CPArrayController's selectsInsertedObjects from working.
2012-04-26 15:19:18 +01:00
cacaodev edb86ebeeb CPPredicateEditorValueBinder cleaning, conforms to recent CPBinder updates 2012-04-26 16:09:32 +02:00
cacaodev bfe53a1d54 Merge branch 'CPPredicateEditorRowNode-formatting' into CPRulePredicateEditor 2012-04-26 15:39:16 +02:00
cacaodev 3ab2ebf71f Merge remote-tracking branch 'upstream/master' into CPRulePredicateEditor
Conflicts:
	AppKit/CPRuleEditor/CPRuleEditor.j
2012-04-26 15:38:30 +02:00
Darrell Walisser 0f43cdee00 -sheet attached to modal window runs in modal context
-events in modal run loop get passed to sheet's parent window, so it can move and resize
2012-04-25 21:04:38 -04:00
Antoine Mercadal b04dbb647b Typo in method name + make some methods private 2012-04-25 12:41:22 -07:00
aparajita 72092732f3 Merge pull request #1516 from zittix/Xcodecapp_mising_help_fix
Add missing help file in XcodeCapp to avoid startup crash
2012-04-25 08:10:26 -07:00
zittix 7f0ff5fd0a Add missing help file in XcodeCapp 2012-04-25 16:25:58 +02:00
Antoine Mercadal 0318d23ab6 Fix stupid error in tooltips management when initializing from a coder 2012-04-24 18:10:33 -07:00
Antoine Mercadal 8fdf78cf67 Move the tooltip code into the CPView code (remove category). Fix problem with tooltips not working when using deploy 2012-04-24 17:57:05 -07:00
Darrell Walisser 06348bbe0b -keep parent window behind sheet when orderFront: on sheet or left mouse down on parent window 2012-04-24 20:54:09 -04:00
Antoine Mercadal 3ec4d3e374 Encode/Decode tooltip in CPView 2012-04-24 16:27:36 -07:00
Antoine Mercadal 9866bf19a4 Support for setting ToolTips right from IB 2012-04-24 16:13:37 -07:00
Aparajita Fishman 1e3c668c9b Added instructions for using pre-commit hook 2012-04-24 10:37:40 +02:00
Aparajita Fishman 36bfc7c675 Fixed decode methods to return the correct defaults, removed unnecessary containsValueForKey and || with defaults 2012-04-24 10:15:19 +02:00
Blair Duncan d6429e532b typo fix 2012-04-24 00:02:12 -04:00
Blair Duncan 864db16e33 Fix for issue 1491, don't scroll if active menu container is menubar 2012-04-23 23:54:13 -04:00
Blair Duncan 02ebb6e4f7 highlite menu item only if the active item was found 2012-04-23 23:06:31 -04:00
Alexander Ljungberg 44521a3c22 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-04-23 23:56:59 +01:00
Alexander Ljungberg c5afd3d39f Fixes #1512. Patch to improve rhino-narwhal platform support.
This rhino-narwhal patch can be applied to add JAVA_OPTS support when running Cappuccino utilities through rhino. This generally improves configurability for special cases, and specifically enables a work around for the "failed to map segment from shared object" error on some platforms.
2012-04-23 23:45:29 +01:00
Blair Duncan 5b5034da63 CPEvent - send a valid timestamp for periodic events 2012-04-23 18:19:37 -04:00
Aparajita Fishman 2fd67f6ba8 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-04-23 23:24:27 +02:00
Blair Duncan 5b6779a3a9 Fix for menu selection that was broken with the change to CPEvent timestamp 2012-04-23 16:51:10 -04:00
Alexander Ljungberg 74820a5040 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-04-23 19:16:05 +01:00
Alexander Ljungberg be76424513 Fixes #1460. Add an xcode-select warning to bootstrap.sh. 2012-04-23 19:15:37 +01:00
Alexander Ljungberg 2d4e544931 Don't mention a website which no longer exists. 2012-04-23 18:48:21 +01:00
Aparajita Fishman 1077294e9a Added missing -adjustSubviews method, code cleanup. 2012-04-23 12:08:12 +02:00
Aparajita Fishman bd691d5307 Hopefully finally fixed the problem with CPScrollView/CPScroller initialization. Fixes #1485. 2012-04-23 01:12:24 +02:00
Aparajita Fishman 48ef639408 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-04-22 23:14:18 +02:00
Aparajita Fishman 9830b2b115 Subviews may not be accessed during initWithCoder. Fixes #1485. 2012-04-22 23:13:58 +02:00
Alexander Ljungberg 40e07bbb45 Missing semicolons. 2012-04-22 15:22:00 +01:00
Alexander Ljungberg 7efc8230a2 Fixed: a collection view wouldn't become the first responder when its items were clicked. 2012-04-20 17:30:17 +01:00
Alexander Ljungberg 38dd03652a Merge branch 'master' of github.com:cappuccino/cappuccino 2012-04-20 15:14:37 +01:00
Alexander Ljungberg 21a34f88b2 Fixed: don't crash when removing objects from an array controller which has its arrangedObjects.@count observed. 2012-04-20 15:12:59 +01:00
Aparajita Fishman 092cb01bb3 Added capp_lint to Tools 2012-04-20 11:57:18 +02:00
Alexander Ljungberg d9640aa205 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-04-19 22:44:06 +01:00
Alexander Ljungberg 469414cb35 Fixed: a CPURLRequest created without using the designated initialiser wouldn't work.
Now `init` calls the designated initialiser like in Cocoa.
2012-04-19 22:43:45 +01:00
aparajita f96c113065 Merge pull request #1509 from cacaodev/CPData-bytes-base64
CFData: completed bytes(), base64() and adds CPData +dataWithBytes and +dataWithBase64:
2012-04-17 10:44:53 -07:00
cacaodev 7fe576163d CFData: Adds lazy getters bytes(), base64().
CPData: Adds +dataWithBytes and +dataWithBase64:
Tests.
2012-04-17 19:08:29 +02:00
Alexander Ljungberg 314be1ec11 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-04-17 15:28:11 +01:00
Alexander Ljungberg 0d810e64b7 Stub out CPDateFormatter and nib2cib support. 2012-04-17 15:27:47 +01:00
Aparajita Fishman 5763ebdf2b Fixed CPEvent -timestamp to return seconds since startup, as documented in Cocoa.
Miscellaneous cleanup of timestamp usage as well.
2012-04-15 11:30:27 -04:00
aparajita 3f58c4ea6f Merge pull request #1494 from cacaodev/CPImageView-bindings
CPImageView: support CPValueURLBinding and CPValuePathBinding.
2012-04-15 05:52:22 -07:00
cacaodev 22f75fa9cd Very minor UI changes 2012-04-15 09:52:57 +02:00
Randall Luecke 340b86e97f CPAlert shouldn't use 'alert' as a variable name 2012-04-13 10:59:30 -04:00
Aparajita Fishman 4fff92f3ee Ignore NS_*.j userland NS classes in XcodeCapp 2012-04-13 08:25:19 -04:00
cacaodev 0c8715dd8d Merge remote-tracking branch 'upstream/master' into CPImageView-bindings 2012-04-12 23:26:11 +02:00
cacaodev 487d38fd21 Merge remote-tracking branch 'upstream/master' into CPImageView-bindings 2012-04-12 23:12:09 +02:00
Aparajita Fishman c028c0ad26 Fixed infinite loop when finished editing a tableview cell. 2012-04-12 17:09:20 -04:00
cacaodev 925a922d90 Remove first row in the plist 2012-04-12 21:41:26 +02:00
Aparajita Fishman aeb2671fc0 CPImageView enhancements
- Changed from deprecated image scaling constants to new ones.
- Added support for CPImageScaleProportionallyUpOrDown (thanks BlairDuncan).
- Cleaned up image layout code.
2012-04-12 14:55:46 -04:00
Aparajita Fishman 502edbd152 nib2cib enhancements
- Added support for User Defined Runtime Attributes in IB.
- Added support for userland NS classes in IB.
- Added support for file-based nib2cib configuration.
- Converted nib2cib to Objective-J from straight Javascript.
- Updated man page for new features.
- Test app.
2012-04-12 12:09:24 -04:00
Aparajita Fishman 5fed81e1dc CFURL/CPURL fixes/enhancements
- Fixed bizarre bug where local variable path was being set as attribute of object in CPURL -pathComponents.
- Added CPURL -URLByDeletingLastPathComponent.
- Linted CFURL.js.
- CFURL constructor should copy when passed a CFURL.
- Added CFURL.createCopyDeletingLastPathComponent.
- Added test for URLByDeletingLastPathComponent.
2012-04-12 10:45:01 -04:00
Aparajita Fishman 6293380406 Let jake proceed if a man page cannot be copied 2012-04-10 22:42:46 -04:00
Antoine Mercadal 73641cb726 Merge remote-tracking branch 'upstream/master' 2012-04-10 16:10:14 -07:00
Antoine Mercadal 71cfeae5f1 fix typo preventing the highlighting color to be draw. 2012-04-10 16:08:17 -07:00
Aparajita Fishman c40aaa04f6 Merge branch 'master' of github.com:cappuccino/cappuccino into cappuccino 2012-04-10 18:42:43 -04:00
Aparajita Fishman f4f4554cde Fixed test of result of sudo() 2012-04-10 18:42:26 -04:00
aparajita 1b0fa21f28 Merge pull request #1498 from BlairDuncan/unnecessaryGlobals
Unnecessary globals
2012-04-10 14:57:40 -07:00
Aparajita Fishman 5c0e079873 CPBinder: In reverseSetValueFor:, suspend observation to avoid unwanted setValueFor:
isssue #1463
Manual test and ojtest.
2012-04-10 17:28:20 -04:00
Blair Duncan 6ede1ccb04 Unnecessary globals 2012-04-10 17:25:46 -04:00
aparajita 7173d3c866 Merge pull request #1496 from BlairDuncan/testBranch
Fix for issue 1425 CPOutlineView expand all items
2012-04-10 14:15:10 -07:00
cacaodev c989c30e00 Use new CPBinder methods from #1495 2012-04-10 22:57:20 +02:00
cacaodev d649fc2413 Merge remote-tracking branch 'upstream/master' into CPImageView-bindings 2012-04-10 22:26:23 +02:00
aparajita 8015106976 Merge pull request #1495 from cacaodev/CPBinder
CPBinder: consolidate setValueFor: with placeholders management
2012-04-10 13:22:23 -07:00
Blair Duncan 6b6c44c4d5 Fix for issue 1425 CPOutlineView expand all items when option key is pressed while clicking the disclosure triangle 2012-04-10 16:11:31 -04:00
cacaodev 742bfcb0e7 Fix non-applicable syntax 2012-04-10 22:06:50 +02:00
cacaodev f222d7bfe7 CPBinder: move placeholder handling to superclass, add 2 subclassable methods for appying the regular value or a placeholder value.
Update binder subclasses for CPTextField, CPCheckBox, CPColorWeel.
2012-04-10 21:48:09 +02:00
Aparajita Fishman f6bdf06e45 Fix _CPFormatLogMessage to do something intelligent if aLevel and/or aTitle is empty or not passed 2012-04-10 15:07:39 -04:00
Aparajita Fishman c04f188adc Fix for dump_theme failing without admin rights, common.jake linting 2012-04-10 14:26:00 -04:00
Antoine Mercadal 1e2964ad8f Fix a crash do to calling non-existing selector
That said, the popover is not moving correctly with the
attached view as it did. Patch in a following commit
2012-04-09 19:20:47 -07:00
Aparajita Fishman dd63174493 Merge branch 'master' of github.com:cappuccino/cappuccino into cappuccino 2012-04-09 15:53:53 -04:00
Aparajita Fishman 91642080d6 Eliminate flashing of insertion point when becoming first responder due to double setTimeout 2012-04-09 15:53:31 -04:00
cacaodev ccf18bb9cb CPPredicateEditorRowNode formatting 2012-04-09 19:54:00 +02:00
Antoine Mercadal 64a74d9ac6 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2012-04-09 10:28:02 -07:00
Aparajita Fishman bc8dc10ac3 Fix for #1433 2012-04-09 13:25:38 -04:00
Antoine Mercadal 324e75650d code style cleaning 2012-04-09 10:24:39 -07:00
Antoine Mercadal 8c205faf2d Merge https://github.com/rvanzon/cappuccino into rvanzon-xcc 2012-04-09 10:23:59 -07:00
Richard van Zon d56a15db83 Using fm instance and ignore errors 2012-04-09 08:06:53 +02:00
Aparajita Fishman 342bde7767 Started linting CPRuleEditor classes 2012-04-09 01:56:59 -04:00
Aparajita Fishman ec80a4c9e6 Add some missing imports 2012-04-09 00:59:57 -04:00
aparajita 2a1af53d79 Merge pull request #1456 from cacaodev/CPTabView
CPTabView: Do not track the segment when the delegate disallows item selection
2012-04-08 21:38:53 -07:00
Alexander Ljungberg c528563421 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-04-08 18:51:15 +02:00
Alexander Ljungberg a3a01c2419 Missing semicolons, whitespace. 2012-04-08 18:50:54 +02:00
Alexander Ljungberg 40d30459b8 Missing semicolons. 2012-04-08 18:10:54 +02:00
Alexander Ljungberg b746824933 Formatting. 2012-04-08 18:10:41 +02:00
cacaodev 1e9958c4c7 Handle CPValueBinding in the custom binder. Added a CPImageView with CPValueBinding to the test app.
Removed setBackgroundColor:gray for placeholders because it's a bad idea (non cocoa and need to restore bg when the value != placeholder).
2012-04-08 10:01:04 +02:00
aparajita 3230ea2519 Merge pull request #1492 from daboe01/master
fix for issue 1451
2012-04-07 13:25:39 -07:00
aparajita 22fc8337a3 Merge pull request #1257 from aparajita/_CPImageAndTextView-API
Add textFrame method to locate the text within the view
2012-04-07 10:51:10 -07:00
Aparajita Fishman 86d5818c0f Revert "Use /var/tmp, in Lion /tmp is not world writable"
This reverts commit e9d076adcd.
2012-04-07 10:42:27 -07:00
cacaodev b6a173cc0c CPImageView: support CPValueURLBinding and CPValuePathBinding. Readonly. With test. 2012-04-07 13:16:16 +02:00
daboe01 ec9c682052 Small progress indicator images fixed (http://www.preloaders.net/en/terms_of_use) 2012-04-06 13:56:06 +02:00
Aparajita Fishman e9d076adcd Use /var/tmp, in Lion /tmp is not world writable 2012-04-05 20:28:14 -07:00
Aparajita Fishman d59bc012b6 Added dump_theme tool 2012-04-05 20:25:14 -07:00
Aparajita Fishman eb292e6d87 Factored image creation code so -description can be added 2012-04-05 19:57:30 -07:00
Aparajita Fishman 129a8cb411 Added ability to specify bundle, which makes this usable with non-main bundle images. 2012-04-05 19:42:23 -07:00
Aparajita Fishman d76706b865 Cocoa always sends NSControlTextDidEndEditingNotification and the action when resigning, whether or not editing had begun. 2012-04-05 18:04:10 -07:00
aparajita 159c5c7342 Merge pull request #1253 from aparajita/better-theme-template
Improvements to the ThemeDescriptor capp template
2012-04-05 17:07:40 -07:00
Aparajita Fishman 4d50eea29b capp templates
- Small comment tweaks
2012-04-05 17:06:15 -07:00
daboe01 0ec10515cd Small progress indicator images 2012-04-05 20:45:19 +02:00
Aparajita Fishman c2f20c21e6 Added CGInsetUnion and CGInsetDifference 2012-04-04 23:17:24 -07:00
Aparajita Fishman e2ead56256 Collection KVC fixes, nextObject correctness
- Moved common CPArray/CPSet collection KVC operators to _CPCollectionKVCOperators.
- Implemented KVC operator dispatch using Objective-J.
- Fixed infinite loop with empty  collection in @min, @max and @sum operators.
- Correctly return valueForUndefinedKey when necessary.
- valueForUndefinedKey reason uses raw description for consistency, class' overridden description may not helpful at all.
- Don't create a forwarder for @ operators with property paths.
- Fixed CPSet -valueForKeyPath to correctly deal with nil/undefined/empty values.
- Added tests for collection  KVC operators.
- enumerator -nextObject should always compare against nil for clarity, correctness, and consistency.
2012-04-03 22:16:55 -07:00
Aparajita Fishman 029e45d027 Use === when possible, made it clearer where the ternary operator ends 2012-04-03 17:17:26 -07:00
Aparajita Fishman 93cc97002a Cocoa conformance and bug fixes
- showRelativeToRect:ofView:preferredEdge: must take provide a view, and if the rect is empty it defaults to the view's bounds.
- If If showRelativeToRect is called while a popover is closing, it is ignored.
- If showRelativeToRect is called when the popover is already open, it should just reposition the existing popover.
- close should NOT consult the delegate's popoverShouldClose. Only performClose should do that.
- If a window is closed, all of its popovers immediately order out.
- Updated demo app to cover more cases.
- Note that child popovers are currently not supported, as this requires support for child windows in CPWindow.
2012-03-31 18:40:47 -07:00
Aparajita Fishman 8fed89164f Add the appkit_tag_dom_elements flag to the NibApplication index-debug.html template 2012-03-30 11:19:40 -07:00
Aparajita Fishman 48b9f3198f Methods that return CGPoint should always copy! 2012-03-30 10:53:00 -07:00
Aparajita Fishman 5893b33962 Merge branch 'master' of github.com:cappuccino/cappuccino into cappuccino 2012-03-27 16:29:51 -07:00
Alexander Ljungberg d2f3ceaf67 Documentation. 2012-03-27 23:45:18 +01:00
Alexander Ljungberg 271b935ba2 + (BOOL)automaticallyNotifiesObserversOf<Key> support. 2012-03-27 23:42:17 +01:00
Aparajita Fishman 3ddab9e26a Added configurable list of source directories for framework Jakefile 2012-03-27 11:20:31 -07:00
Aparajita Fishman d68278e41f Use isMenuBar instead of testing class 2012-03-27 11:19:41 -07:00
Alexander Ljungberg 25676b4460 Fixed: reverse value transformations were not applied for table view bindings. 2012-03-27 13:56:25 +01:00
Alexander Ljungberg 56c7e1991e Fixed: check box binding value transformers were ignored. 2012-03-27 13:53:32 +01:00
Alexander Ljungberg ff68ccdeab Fix CPPopUpButtonTest. 2012-03-27 13:51:52 +01:00
Alexander Ljungberg 4acbfd5587 Formatters are a part of Foundation. 2012-03-27 10:37:15 +01:00
Alexander Ljungberg 8df2e608ab Merge branch 'master' of github.com:cappuccino/cappuccino 2012-03-27 10:02:52 +01:00
Alexander Ljungberg 38f8b1a931 Raise an exception if a view is added to itself as a subview.
This is better than a DOM node exception.
2012-03-27 10:02:27 +01:00
Alexander Ljungberg 099ee1e249 RC1 bootstrap. 2012-03-26 21:09:37 +01:00
Aparajita Fishman 9e8f659faf Stop generating useless XML from doxygen. 2012-03-26 12:47:05 -07:00
Aparajita Fishman cd148c36c9 Menu tracking fixes:
- Finally fixed #1457.
- Fixed case where mouse is dragged and then released over a submenu, which should release the menu.
- Fixed case where clicking without dragging, then clicking again on a menu title would not close the menu.
2012-03-26 12:38:50 -07:00
Alexander Ljungberg aba7fd5527 Make CPPopUpButton selectedTag private API to match Cocoa. 2012-03-26 19:55:50 +01:00
Alexander Ljungberg 68c794bf9d This will be Cappuccino 0.9.6. 2012-03-26 19:55:17 +01:00
Alexander Ljungberg ca9b3a7dbf Demonstrate that pop up button test is using tags. 2012-03-25 22:01:16 +01:00
Alexander Ljungberg 4eba585286 Fix manual pop up button test. 2012-03-25 21:40:52 +01:00
Alexander Ljungberg 4172ecfdf2 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-03-25 14:15:39 +01:00
Alexander Ljungberg da80176935 Minor optimisation. 2012-03-25 14:15:18 +01:00
Alexander Ljungberg f50802b85b Fixes #1164. Support CPOutlineView selectionShouldChangeInOutlineView: delegate method. 2012-03-25 13:58:41 +01:00
Alexander Ljungberg 5351bf7e12 Select outline view item parent with left key.
If there's a single item selected and it's not expanded, pressing the left arrow key on the keyboard now selects the item's parent unless the delegate vetoes.
2012-03-25 13:47:32 +01:00
Aparajita Fishman 96a038559e CPPopover fixes
- Removed animationStyle for now.
- Made sure that popoverDidClose is not called until animation is finished.
- Don't create a new attached window unless: there isn't one; the popover behavior has changed; the current attached window is still visible.
- Don't call popoverWillShow if there is not content view controller.
-  Removed unused _shown instance variable.
- Removed redundant !_attachedWindow checks followed by _attachedWindow message that returns a BOOL.
- Documentation tweaks.
- Fixed up some demo issues.
2012-03-24 20:56:31 -07:00
Aparajita Fishman c321084990 Whitespace 2012-03-24 17:57:13 -07:00
aparajita e13d070439 Merge pull request #1483 from cacaodev/CFPropertyList-XML-date-deserialization
CPDate deserialization from XML Property List, with test.
2012-03-24 17:49:37 -07:00
Aparajita Fishman 1a8fc7f07f CPPopover fixes/enhancements
- Lion-style popovers now zoom open just like their Lion counterparts (except for opacity, the browser couldn't handle that at the same time).
- Fixed a number of subtle drawing issues caused by not aligning path points correctly.
- The anchor arrow deals correctly with corner cases where the middle of the reference rect is not within the corners of the popover.
- Code cleanup: factored redundant code, removed unused code.
- Added corner cases to the demo app, changed demo app to reuse a single popover.
2012-03-23 19:53:46 -07:00
cacaodev 9ef95e1f68 Support for decoding date type in XML 1.0, with test. 2012-03-23 22:28:42 +01:00
aparajita 28ed2f9bd0 Merge pull request #1482 from cacaodev/CPViewController-bundle-fix
CPViewController The cib should be initialized with bundle information.
2012-03-23 09:30:23 -07:00
cacaodev 93f51eaa42 CPViewController The cib should be initialized with bundle information. 2012-03-23 10:09:48 +01:00
Aparajita Fishman 7c807dd887 Moved animationStyle to dedicated methods so they can be documented 2012-03-23 01:57:24 -07:00
Aparajita Fishman 429b42d3e0 Implement what is documented, that loadView without a cib name will create an empty view 2012-03-23 01:49:44 -07:00
Aparajita Fishman 08f013171e CPPopover tweaks:
- Added animationStyle (Lion/iOS) to CPPopover. iOS style does not zoom open, it just appears.
- Tweaked the Lion animation a bit to be a bit less rushed and match Mac OS X timing better.
- Fixed some typos.
2012-03-23 01:49:01 -07:00
Aparajita Fishman d620032d0d Switch from CPRect/Point to CGRect/Point functions 2012-03-22 18:58:41 -07:00
Alexander Ljungberg 3bc5605633 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-03-23 00:35:00 +00:00
Alexander Ljungberg 3a0068186a Implement stopping support for CPArray enumerateObjectsUsingBlock:. 2012-03-23 00:34:09 +00:00
Alexander Ljungberg e19a782954 Test CPArray enumerateObjectsUsingBlock:. 2012-03-23 00:26:05 +00:00
Aparajita Fishman 88783efa7b Needed an _isLazy flag to get correct behavior 2012-03-22 15:43:18 -07:00
Aparajita Fishman a249588f52 UIKit does NOT call viewDidLoad from setView, made this explicit in the docs
viewDidLoad is meant to deal with asynchronous *lazy* instantiation of a view via a cib or loadView. setView is neither asynchronous nor lazy.
2012-03-22 14:22:20 -07:00
Alexander Ljungberg 2951a83e73 CPArray enumerateObjectsWithOptions:usingBlock:. 2012-03-22 17:05:59 +00:00
Aparajita Fishman b99ece088d Prevent doxygen from parsing @implementation within comments 2012-03-21 12:48:12 -07:00
Aparajita Fishman ebd797d6d7 Documented need to use CPColorWithImages() instead of PatternColor() 2012-03-20 13:48:50 -07:00
aparajita fa7a68f3f8 Merge pull request #1479 from aparajita/DOM-class
Put view class in the DOM
2012-03-20 13:02:55 -07:00
Aparajita Fishman 8167c46cfc Added documentation for registerThemeValues methods 2012-03-20 12:51:30 -07:00
Aparajita Fishman 9456810c7e Add registerThemeValues methods in CPView, allows runtime registration of theme values using same format used in ThemeDescriptors.j 2012-03-20 12:21:05 -07:00
Alexander Ljungberg 79f2ec5d17 Refs #1480. Change NSSortDescriptors to CPSortDescriptors in docs. 2012-03-19 21:03:04 +00:00
Alexander Ljungberg 38a0a261c0 Merge pull request #1480 from Kentzo/cappuccino
---
2012-03-19 20:57:52 +00:00
Ilya Kulakov 91eb23ba87 Implement -sortedArrayUsingDescriptors: for CPSet. 2012-03-20 03:43:49 +07:00
Aparajita Fishman 706129bcbd Implement a mechanism to display a DOM element's CPView class 2012-03-18 16:19:01 -07:00
Aparajita Fishman 97b77e9b7b Changed to using data-cappuccino-view attribute 2012-03-18 15:33:19 -07:00
Alexander Ljungberg 3b85a67faf Fixed: table column divider lines were drawn on top of the header bottom line. 2012-03-18 18:01:24 +00:00
Alexander Ljungberg f2571e6536 Don't draw a table corner view if there is no vertical scrollbar.
This could either be due to autohiding or they usage of overlay scrollbars. Not showing it matches Cocoa and makes sense because it takes up space for no reason without the scrollbar.
2012-03-18 17:56:20 +00:00
Alexander Ljungberg bec8a4b1c6 Fixed: scroll views with a bezel border had two strange dots in the upper corners instead of a Lion-like bezel. 2012-03-18 16:56:04 +00:00
Alexander Ljungberg 028fb03ef1 Slightly optimise scroll view border drawing code. 2012-03-18 16:41:39 +00:00
Alexander Ljungberg 65aa08a9d9 Format code. 2012-03-18 16:38:51 +00:00
Alexander Ljungberg 22058a7a93 New corner view test which tests more cases and demonstrates the actual code rather than a category. 2012-03-18 16:30:46 +00:00
Alexander Ljungberg 90514bd3cb Test table view notifications for deselectAll. Verify absence of CPTableViewSelectionIsChangingNotification when changing programmatically. 2012-03-18 15:21:09 +00:00
Alexander Ljungberg bd7d258fcd Slightly less shiny outline view disclosure triangle. Subtle is more Cocoa like. 2012-03-18 14:15:40 +00:00
Alexander Ljungberg c21e40e819 Simplify. 2012-03-18 14:13:15 +00:00
Alexander Ljungberg e0c8ae6335 Minor outline view optimisation: don't apply a context rotation of 0 degrees. 2012-03-18 14:02:14 +00:00
Alexander Ljungberg e9d5d33cb2 Fixed: blurry outline view disclosure triangle.
The triangle centring was such that for a regular size disclosure control the right pointing triangle (collapsed state) was not drawn on integral coordinates.
2012-03-18 14:00:38 +00:00
Alexander Ljungberg 0d9b49df85 Optimise CPIndexSet. 2012-03-18 00:44:02 +00:00
Alexander Ljungberg db5e5d7da6 Test stopping CPIndexSet enumeration. 2012-03-18 00:39:07 +00:00
Alexander Ljungberg 44236795b5 CPIndexSet enumerateIndexesInRange:options:usingBlock:. 2012-03-17 18:18:08 +00:00
Alexander Ljungberg a26bca5dbe CPIndexSet enumerateIndexesWithOptions:usingBlock:. 2012-03-17 18:03:21 +00:00
Alexander Ljungberg 872b446695 CPIndexSet enumerateIndexesUsingBlock:. 2012-03-17 17:36:31 +00:00
Alexander Ljungberg 2b0ed8234c Format code. 2012-03-17 17:19:37 +00:00
Aparajita Fishman 39ec1cfd27 Put the view's class in the DOM for easier debugging 2012-03-16 13:25:13 -07:00
Alexander Ljungberg b7dcd24e11 Adjust size of spinner progress indicators properly in nib2cib. 2012-03-16 18:36:09 +00:00
Alexander Ljungberg 5097030143 Fixed: spinner style progress indicators were nib2cibbed to progress bars. 2012-03-16 18:23:47 +00:00
Alexander Ljungberg 516fac037f Merge branch 'master' of github.com:cappuccino/cappuccino 2012-03-15 00:14:39 +00:00
Alexander Ljungberg 1bf632a575 Rename shouldShowOutlineViewForItem to shouldShowOutlineDisclosureControlForItem.
ShouldShowOutlineView is not a great delegate method name for a control called an outline view. The original Cocoa name refers to an 'OutlineCell' which we don't have so that's not appropriate either.
2012-03-15 00:14:25 +00:00
Alexander Ljungberg 6137aa8637 Optimise shouldShowOutlineView. 2012-03-14 23:23:12 +00:00
Alexander Ljungberg 4be4506ffc Implement outline view outlineView:shouldShowOutlineViewForItem: delegate method (corresponding to shouldShowOutlineCellForItem in Cocoa). 2012-03-14 23:08:01 +00:00
aparajita d3c368ba92 Merge pull request #1477 from cacaodev/CFBundle-loadStatus-fix
CFBundle: isLoaded() should return a bool
2012-03-14 14:27:04 -07:00
cacaodev 9b0d03b024 CFBundle: isLoaded() should return a bool 2012-03-14 21:10:35 +01:00
Alexander Ljungberg c21d2fd017 Fixed: toolbar search fields created in IB were cut in half height-wise due to a too small max size. 2012-03-14 16:02:25 +00:00
Alexander Ljungberg 2940b5e787 Fixed: nib2cibbed search fields had the bottom pixel cut off. 2012-03-14 15:58:35 +00:00
Alexander Ljungberg cf18bcaaf9 Clean up. 2012-03-14 15:50:07 +00:00
Alexander Ljungberg c4eaf083b4 Code formatting. Don't shadow compressor function name. 2012-03-13 20:29:38 +00:00
Alexander Ljungberg df6b592d11 Refs #1474. Allow -T argument before -- in objjc and document it in help.
Seems like all options should be before -- really.
2012-03-13 20:27:20 +00:00
Alexander Ljungberg 109e8b1e33 Merge pull request #1474 from ternarylabs/cappuccino
---
2012-03-13 20:06:33 +00:00
Alexander Ljungberg 85c88d7c93 Whitespace. 2012-03-13 20:03:11 +00:00
Alexander Ljungberg d8e5fa3087 Merge pull request #1441 from cacaodev/cappuccino
---

With manual test.
See comments in the code about how to make bindings adoptions easier and avoid repeating code.
2012-03-13 19:58:29 +00:00
cacaodev 697a7b308a CPColorWell : Implements CPValueBinding (color), supports markers.
With manual test.
2012-03-13 20:35:31 +01:00
Alexander Ljungberg dcc031f23a Fixed: small size toolbars in bridge windows didn't show the bottom shadow line.
Switched to using a somewhat vertically resizable three part image. The centre image part is being compressed which normally would look poor but you can't tell since it's a gradient.
2012-03-13 14:45:33 +00:00
Alexander Ljungberg 061ea47953 Test N-part image layout. 2012-03-13 13:51:01 +00:00
Alexander Ljungberg f0e5161b7b Tile narrow vertical three part images horizontally, and short horizontal three part images vertically.
This allows you to use a 1px wide vertical three part image to stretch to any width.
2012-03-13 13:36:52 +00:00
Alexander Ljungberg eada36af26 More minor formatting. 2012-03-12 21:01:27 +00:00
Alexander Ljungberg a02c687df9 Fix missing semicolon. 2012-03-12 20:14:11 +00:00
Alexander Ljungberg e636087f4a Fixed decodeBytesForKey in theory.
There's no way to encode bytes today in the first place.
2012-03-12 20:06:23 +00:00
Alexander Ljungberg 4876f77914 Refs #1476. Format code. 2012-03-12 20:05:18 +00:00
Alexander Ljungberg ed6bed9bf7 Format code. 2012-03-12 19:43:28 +00:00
Alexander Ljungberg 87cb2eb19d Merge pull request #1476 from cacaodev/cappuccino
---

 In nib2cib, this typo was preventing from decoding base64 data included in nib files.
2012-03-12 19:20:01 +00:00
Alexander Ljungberg 53334251b8 Fix a typo in CPGradient comment and attempt to better explain what's going on. 2012-03-12 12:04:34 +00:00
Alexander Ljungberg a069f2945b Optimise. 2012-03-11 22:13:05 +00:00
Alexander Ljungberg 5a0e1d7bb3 Support any angle in CPGradient drawInRect:angle:. 2012-03-11 19:40:22 +00:00
Alexander Ljungberg ed1d77c86d Skeleton CPGraphicsContext isFlipped. 2012-03-11 19:39:25 +00:00
Alexander Ljungberg 74054442a2 CPGradient initWithColors:. 2012-03-11 19:38:02 +00:00
Alexander Ljungberg 59ef8329c0 Handle CPGradient colorSpace argument. 2012-03-11 15:37:45 +00:00
Alexander Ljungberg 20cffaa7fe Fix CPGradient angle. 2012-03-11 14:07:17 +00:00
Alexander Ljungberg ebeb1040e8 Simplify CPGrahicsTest slightly by connecting delegates in IB. 2012-03-11 14:06:31 +00:00
Alexander Ljungberg cdb919dea3 Add reference renderings to CPGraphicsTest. Add visual tests of CPGradient. 2012-03-11 13:13:50 +00:00
Alexander Ljungberg c509e6131a Fixed: CPGradient reversed its colours. 2012-03-11 13:12:17 +00:00
Alexander Ljungberg db6a4d7042 Stub out CPView inLiveResize.
CPWindow should send `viewWillStartLiveResize` and `viewWillEndLiveResize` to make this work.
2012-03-10 12:43:47 +00:00
Alexander Ljungberg a32b5ea72b nib2cib support for table view background colour. 2012-03-10 12:02:17 +00:00
Alexander Ljungberg 58a2fce110 Code formatting. 2012-03-10 12:01:40 +00:00
Alexander Ljungberg 3d9ae42dbf Starter CPGradient with drawInRect:angle:. 2012-03-10 11:55:13 +00:00
Alexander Ljungberg c4a16d10bc Starter CPColorSpace implementation. 2012-03-10 11:53:47 +00:00
Alexander Ljungberg eeca40c6f0 Implemented CPColor colorWithSRGBRed:green:blue:alpha:. 2012-03-10 11:52:49 +00:00
Alexander Ljungberg 2a031e82a4 Constrain CPColor components to [0.0, 1.0]. 2012-03-10 10:11:35 +00:00
cacaodev 0e6ce205ab CPPropertyListSerializationTest for CPPropertyListXMLFormat_v1_0 format 2012-03-09 20:52:08 +01:00
Alexander Ljungberg 9acbe0f2f8 Fix incorrect parameter type. 2012-03-09 19:49:58 +00:00
Alexander Ljungberg 3ee9c1a439 Fixed misplaced var, formatting. 2012-03-09 19:17:28 +00:00
Alexander Ljungberg 0eeff20af6 Code formatting. 2012-03-09 16:52:21 +00:00
Alexander Ljungberg a1cf9f1cd4 Table view cell layout test. 2012-03-09 15:36:21 +00:00
cacaodev 3897f422fe Use setter 2012-03-09 15:22:19 +01:00
cacaodev 9d785d1a3c CFPropertyList typo: CFData has _bytes, not bytes. In nib2cib, this typo was preventing from decoding base64 data included in nib files 2012-03-09 14:39:53 +01:00
Alexander Ljungberg 66f818872c Simplify shadow view code. 2012-03-09 12:50:52 +00:00
Alexander Ljungberg 342bacb25c Manual test for CPImageView with and without shadow. 2012-03-09 12:49:38 +00:00
Alexander Ljungberg 8e81be0319 Clean up. 2012-03-09 12:06:30 +00:00
Alexander Ljungberg 3acfa142bc Merge pull request #1475 from miLibris/cappuccino
---

Remove CPShadowView constants in CPImageView
2012-03-09 12:00:05 +00:00
Alexander Ljungberg 94a58c810e Calculate a default key view loop for windows loading from cibs even if autorecalculatesKeyViewLoop is NO. 2012-03-08 12:23:05 +00:00
Alexander Ljungberg 757a2bf400 nib2cib support for CPWindow autorecalculatesKeyViewLoop. 2012-03-08 12:05:12 +00:00
Luc Vauvillier b18fbd685b CPImageView : Remove shadow vars dependency 2012-03-08 12:49:31 +01:00
Alexander Ljungberg 56b5a9ec22 Make CPWindow autorecalculatesKeyViewLoop default to NO rather than null. 2012-03-08 11:39:59 +00:00
Georges Auberger 70432f0198 Added -T directive to enable ObjectiveJ.Preprocessor.Flags.IncludeTypeSignatures flag on preprocessor 2012-03-07 22:10:16 -08:00
Alexander Ljungberg 0736f86f32 Fixed: "[CPString count] unrecognized selector" error when binding an array controller's content array to a key of another AC's selection.
This change also avoids wrapping a selection proxy in a KVO array proxy, which isn't helpful and probably hurts performance.
2012-03-07 16:49:41 +00:00
Alexander Ljungberg 107d739489 Add support for checkbox placeholder bindings options. 2012-03-07 14:33:32 +00:00
Alexander Ljungberg 32a86a911f Allow custom binders to set default placeholders.
This makes it easier to write custom binders.
2012-03-07 14:31:53 +00:00
Alexander Ljungberg 9a32733f88 Fixed: incorrect bindings option in array controller test. 2012-03-07 13:04:20 +00:00
Alexander Ljungberg 0f655e3264 Fixed: sending CPWindow setAutorecalculatesKeyViewLoop:NO caused the window to recalculate the key view loop.
Although the intention might have been to do 'one final calculation run to provide a sensible default', the result is unintuitive and does not match Cocoa's behaviour.

If the key view loop has been manually set up and the user then calls `setAutorecalculatesKeyViewLoop:NO` they don't expect their work to be overwritten.
2012-03-01 20:35:20 +00:00
Alexander Ljungberg 55a4afa341 Merge pull request #1471 from tfc/cappuccino
---

...and fixed my last documentation commit for CPSplitView.
2012-03-01 18:15:53 +00:00
Jacek Galowicz 3b5aa1a2ab CPScrollView: Documented delegate methods 2012-03-01 18:44:51 +01:00
Jacek Galowicz 658e569251 Fix of last commit
My commit 1d8092e431 added some
documentation, but destroyed the order of the text.
2012-03-01 18:41:44 +01:00
Alexander Ljungberg 4eacfd83d6 Refs #1469. Formatting. 2012-03-01 10:48:07 +00:00
Alexander Ljungberg ad0fd0a34e Merge pull request #1469 from tfc/cappuccino
---

This regards CPSplitViews new delegate method
- (BOOL)splitView: (CPSplitView)aSplitView shouldAdjustSizeOfSubview: (CPView)aSubView
which was introduced in b27a3cdbe5 by Alexander Ljungberg.
2012-03-01 10:44:51 +00:00
Jacek Galowicz 1d8092e431 Added a documentation line for CPSplitView.
This regards CPSplitView's new delegate method
- (BOOL)splitView: (CPSplitView)aSplitView shouldAdjustSizeOfSubview: (CPView)aSubView
which was introduced in b27a3cdbe5 by Alexander Ljungberg.
2012-03-01 08:46:06 +01:00
Richard van Zon ee190d07c5 Added support for directory symbolic links 2012-02-29 13:13:31 +01:00
Alexander Ljungberg 87cc62d1d8 Fixed with nib2cib: CPBox title position 'none' was converted to 'on top'. 2012-02-24 20:53:02 +00:00
Alexander Ljungberg a16388b57d Allow toolbar size to be changed even after the toolbar has been created. 2012-02-24 20:38:05 +00:00
Alexander Ljungberg 98e54d2e09 Support for "small" size toolbars (CPToolbar sizeMode).
Support only in nib2cib and coding ATM. Calling setSizeMode: on an existing toolbar will not have an effect.
2012-02-24 20:10:36 +00:00
Alexander Ljungberg bd02ec057c Style fix. 2012-02-24 19:44:26 +00:00
Alexander Ljungberg 6ac804d37c CPWorkspace openFile and openURL. 2012-02-24 19:44:13 +00:00
Alexander Ljungberg 4b764dc8b4 Throw an exception when trying to set a null minimum item size for a collection view. 2012-02-17 16:25:16 +00:00
Alexander Ljungberg 3a8ad56d4b Fixed: don't crash when loading a collection view with no item prototype view from a cib. 2012-02-17 16:23:59 +00:00
Alexander Ljungberg f5bee48d98 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-02-17 14:26:56 +00:00
Alexander Ljungberg 24fbfbee60 Unit test for previous fix. 2012-02-17 14:26:28 +00:00
Alexander Ljungberg a1bc5ad4d3 Fixed: app would freeze on collection view setSelectionIndexes:nil. 2012-02-17 14:23:21 +00:00
Alexander Ljungberg 4aa3824a2a Minor collection view optimisation. 2012-02-17 14:05:03 +00:00
Aparajita Fishman 37d92c1182 Revert "Merge pull request #1438 from aradabaugh/master", it broke a few things
This reverts commit e081dbf127, reversing
changes made to 71e8f0201a.
2012-02-16 08:21:31 -08:00
cacaodev d581dec6cf CPTabView: Do not track the segment when the delegate disallows item selection. 2012-02-13 00:32:22 +01:00
Antoine Mercadal a0eadc6c4a Merge branch 'CPStepper-nib2cib' of https://github.com/cacaodev/cappuccino into stepper-nib2cib 2012-02-11 16:08:27 +01:00
Alexander Ljungberg fdf672cf0a Include a toolbar in NibAppRemixed as a (very minimal) example. 2012-02-10 19:57:50 +00:00
Alexander Ljungberg b8dacb1ffa Fixed with nib2cib: toolbars with default items such as NSToolbarShowColorsItem didn't convert right. 2012-02-10 19:57:00 +00:00
Alexander Ljungberg 81a99dd190 Merge pull request #1454 from cacaodev/cappuccino
---
2012-02-10 15:47:30 +00:00
cacaodev 6a42d601c5 CPTabView: remove duplicate code. 2012-02-10 16:31:45 +01:00
cacaodev 59ce74a3df CPTabView : _selectedIndex was undefined after decoding an empty tab view (no items).
A visible bug was that the first item added was not immediately selected. Updated CPTabViewNib example, shows the bug fixed.
2012-02-10 16:29:50 +01:00
Alexander Ljungberg eacee00fc8 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-02-08 15:58:00 +00:00
Alexander Ljungberg fe70a5541e Fixes #1450: a scroll view with non hiding legacy scrollbars would crash if the document view had a size of 0 pixels in either dimension. 2012-02-08 15:52:59 +00:00
Alexander Ljungberg c9d4089b9a Throw an exception when trying to set a scroller's knob proportion to NaN or Inifinity. 2012-02-08 14:54:50 +00:00
Alexander Ljungberg 8fdb872605 Clean up. 2012-02-08 13:48:43 +00:00
Antoine Mercadal 8b28041cf0 Merge pull request #1449 from cacaodev/CPControllerSelectionProxy-typos
CPControllerSelectionProxy: accidental globals.
2012-02-07 08:37:59 -08:00
cacaodev 4d3f8c3c8c CPStepper: nib2cib support, with test. 2012-02-07 16:38:48 +01:00
Antoine Mercadal f8cb4a15cb Merge pull request #1446 from cacaodev/CPArrayController-setSelectionIndexes-fix
CPArrayController : setAvoidsEmptySelection:YES should not apply when setting an empty selection explicitely. With tests.
2012-02-03 01:30:01 -08:00
Randall Luecke dd7d36da43 call layoutSubviews when the tableview lays out its subviews. 2012-02-02 19:34:11 -05:00
cacaodev 12201d38f3 CPArrayController : setAvoidsEmptySelection:YES should not apply when setting an empty selection explicitely. With tests. 2012-02-03 00:48:49 +01:00
Randall Luecke 3b4ad1d583 Remove 2nd call to setHeaderView: 2012-02-02 17:06:31 -05:00
cacaodev d44df8a9da CPControllerSelectionProxy: accidental globals. 2012-02-02 10:50:26 +01:00
Ross Boucher ab88f72827 Merge pull request #1445 from cacaodev/CPFont-cleaning
CPFont: fix typo in fontWithName:size: caching, rearrange constructor methods. With test.
2012-02-01 12:58:03 -08:00
cacaodev 75a00e8c4a CPFont: fix typo in fontWithName:size: caching, rearrange constructor methods. With test. 2012-02-01 14:05:37 +01:00
Randy Luecke 76c5500488 Merge pull request #1444 from lynnchin/patch-1
Update line 171 to remove "%s" to populate the result string.
2012-02-01 00:15:24 -08:00
lynnchin 8cb7c05c88 Update line 171 to remove "%s" to populate the result string. 2012-02-01 19:13:59 +11:00
Randy Luecke e081dbf127 Merge pull request #1438 from aradabaugh/master
Enable additional buttonTypes for CPButton
2012-01-31 22:23:42 -08:00
Ross Boucher 71e8f0201a Merge pull request #1443 from rafnocx/master
CPFont.j typo (line 180)
2012-01-31 20:04:28 -08:00
rafnocx c9ecb20b50 fix CPFont constructor (line 180) possible typo 2012-02-01 13:14:56 +11:00
Randall Luecke 7dc213995c Added CPObject's performSelector:withObject: and tests 2012-01-31 16:35:49 -05:00
aradabaugh bea34a9b35 Removes duplicate action for radioGroup. 2012-01-30 00:26:46 -07:00
aradabaugh 5ae405a89b Add visual test for CPButton buttonTypes. 2012-01-30 00:17:58 -07:00
Alexander Ljungberg 66fcbe7871 Visual CPSplitView test. 2012-01-27 20:58:54 +00:00
Alexander Ljungberg b27a3cdbe5 Rewritten split view resizing which plays well with a mix of fixed size and non-fixed size panes. 2012-01-27 20:44:38 +00:00
Alexander Ljungberg 9d7b822409 Add support for split view shouldAdjustSizeOfSubview: delegate method. 2012-01-27 17:04:04 +00:00
Alexander Ljungberg ab3f260757 Fixed: CPSplitView tried to auto save even without an auto save name. 2012-01-27 16:38:17 +00:00
Alexander Ljungberg b26b0a321b Reinstate defensive coding for numeric parameters in CPTableView. 2012-01-27 14:54:10 +00:00
Alexander Ljungberg 9536858599 Unit test CPSplitView. 2012-01-27 14:47:00 +00:00
Alexander Ljungberg c7d3ccb13a Add missing header to CPTabView. 2012-01-27 12:33:07 +00:00
Alexander Ljungberg a081f98fd1 Refs #1440. Whitespace cleanup. 2012-01-27 12:32:11 +00:00
Alexander Ljungberg 7096ea549e Merge pull request #1440 from cacaodev/cappuccino
---

- selectedTabViewItem should return nil when there are no items (i.e. _selectedIndex == CPNotFound).
Added an empty Tab View to CPTabViewNib test app.
Needs a jake sudo-install for changes to take effect.
2012-01-27 12:26:27 +00:00
Alexander Ljungberg 8e007985a1 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-01-27 12:20:17 +00:00
Alexander Ljungberg e03e774113 Format delegate signatures in collection view documentation. 2012-01-27 12:19:52 +00:00
cacaodev 7a41282912 CPTabView: Fix a bug where a CPTabView would not reflect immediately the replacement of the selected item's view.
Updated CPTabViewNib to show a setView: on the current item.

If the view changes on a non selected item, the tabView content will be
updated when this item is selected.
2012-01-26 14:45:42 +01:00
cacaodev c8f8c01d2f CPTabView : _setTabView: on newly decoded CPTabViewItems
A CPTabViewItem needs to know about its tabView.
2012-01-26 14:34:52 +01:00
cacaodev 7f6db7bf98 CPTabView: Fix a bug where -selectedTabViewItem was raising instead of returning nil when no tab items (i.e. _selectedItemIndex = -1) and causing nib2cib to fail.
Added An empty Tab View to CPTabViewNib test app.
Needs a jake sudo-install for changes to take effects.
2012-01-26 10:44:46 +01:00
aradabaugh e058efb622 Correcting minor whitespace styling. 2012-01-25 11:40:15 -07:00
aradabaugh c14643849f Minor style change. 2012-01-24 22:51:32 -07:00
aradabaugh edd09ef06a Enables additional buttonTypes for CPButton 2012-01-24 22:50:01 -07:00
Randy Luecke d06fccf157 Merge pull request #1436 from aradabaugh/master
Fixes CPShadowView shadowViewEnclosingView to use self instead of shadowView
2012-01-20 12:37:38 -08:00
aradabaugh 6bc3d49ba2 Correcting use of self in CPShadowView shadowViewEnclosingView: 2012-01-20 13:33:24 -07:00
aradabaugh a8d8736899 Fixes CPShadowView shadowViewEnclosingView to use self instead of shadowView. 2012-01-20 00:33:40 -07:00
Randall Luecke b1e4a43cd3 Fixed and finished the documentation for CPSet and CPMutableSet. 2012-01-19 01:19:20 -05:00
Antoine Mercadal eafbebcebb fix crash when setting title while to content view is set 2012-01-16 14:19:09 +01:00
Antoine Mercadal 0c72c52ba2 improve manual test of CPBox 2012-01-14 12:31:28 +01:00
Antoine Mercadal e8194d9c2e Fix some sizing problem with CPBox titles. close #1431 2012-01-14 12:31:12 +01:00
Antoine Mercadal f0e1b67197 Merge remote-tracking branch 'upstream/master' 2012-01-13 13:56:16 +01:00
Antoine Mercadal 7ba27cf617 Add manual test for CPBox title 2012-01-13 13:52:31 +01:00
Antoine Mercadal c9f765645c Support for CPBox title in nib2cib 2012-01-13 13:52:12 +01:00
Antoine Mercadal 5daa8cb289 Support for title in CPBox. close #1428 2012-01-13 13:51:50 +01:00
Aparajita Fishman 789d832808 Tab -> spaces 2012-01-12 18:44:19 +06:30
cacaodev 0908139218 Merge branch 'master' of git://github.com/cappuccino/cappuccino into CPRulePredicateEditor 2012-01-07 09:39:34 +01:00
cacaodev 926bcfb514 CPRuleEditor : Moved _CPRuleEditor*Button customization from class to controller and added initWithCoder methods. 2012-01-06 22:49:42 +01:00
Antoine Mercadal d7971322cb Merge pull request #1291 from miLibris/CPTheme-coding-fixes
_CPThemeAttribute fix : encode missing _defaultTheme value
2012-01-06 07:21:09 -08:00
Antoine Mercadal 6ddeb167b3 Merge pull request #1424 from anddam/master
Edit in press utility.
2012-01-06 07:20:30 -08:00
Andrea D'Amore c1be09c692 press: fixing basedir being added twice to png destination path 2012-01-06 15:25:54 +01:00
Aparajita Fishman 1c2a304ee5 Assignment of function is a statement and should be semicolon terminated. Some miscellaneous linting as well. 2012-01-05 17:51:37 -10:00
Antoine Mercadal 1a51acf2fc fix doc style under Windows. Thanks to @jakemarsh (fork removed). close #1401 2012-01-03 17:21:02 +01:00
Antoine Mercadal 47a5296f0b Merge pull request #1405 from applicaster/linux_rhino
Compilation problems on ubuntu
2012-01-03 07:47:32 -08:00
Antoine Mercadal 1189e8c849 Merge pull request #1422 from cacaodev/CPPredicate
CPCompoundPredicate -isEqual: typo.
2012-01-02 03:22:02 -08:00
cacaodev 8d59fc1334 CPPredicateEditor tests: updated xib to Xcode 4.2 and nib2cibed.
SmartFoldersDemo: disable the size-to-fit like feature in the controller because 1/ CPPredicateEditor should have its own sizeToFit and 2/ It was shadowing other resizing bugs.
2011-12-31 17:19:14 +01:00
cacaodev ce2316a8ee CPCompoundPredicate: Fixed typo in -isEqual:. With test. 2011-12-31 16:19:38 +01:00
cacaodev 0aae4f2627 Merge branch 'master' of git://github.com/cappuccino/cappuccino into CPRulePredicateEditor 2011-12-31 15:37:59 +01:00
Alexander Ljungberg ec9ddc0819 Merge pull request #1421 from cacaodev/cappuccino
---
2011-12-31 13:27:45 +01:00
cacaodev a5bd55dcac Rename CPExpression_* classes in NSExpression.j (nib2cib) 2011-12-31 09:33:12 +01:00
Alexander Ljungberg b0b1bd88a6 Fix clean up, clean up more. 2011-12-29 20:18:40 +01:00
Alexander Ljungberg 75d5619abd Clean up. 2011-12-29 20:12:11 +01:00
Alexander Ljungberg 522a641690 Merge pull request #1420 from cacaodev/cappuccino
---

Added isEqual:
Renamed CPExpression classes
Fixed -filteredArrayUsingPredicate: for proxy arrays.
2011-12-29 20:04:35 +01:00
cacaodev fe1bd1a978 Cleanup: removed log statements, some comments, css transition hack for fading the drop line separator. 2011-12-29 18:44:06 +01:00
cacaodev b39f509263 CPArray (CPPredicate): -filteredArrayUsingPredicate: and -filterUsingPredicate:
Use CPArray methods (not js array) because the receiver can be a CPArray subclass. With tests.

Fixes the bug reported here: https://groups.google.com/forum/?pli=1#!topic/objectivej/8q9hqbZZUv0
2011-12-29 17:16:53 +01:00
cacaodev 7a8173bf6f CPRuleEditor : Fixes a bug where a rule editor embedded in a scroll view was not updating its frameSize when rows where added/removed.
Reported here: https://groups.google.com/d/msg/objectivej/G2MFGGSHaOY/ojcQaoNSpcAJ
I also adjusted the plus button right padding to give enough space for the scroller.
Edited CPRuleEditorCibTest xib to unhide the vertical scroller.
2011-12-25 22:16:01 +01:00
cacaodev 1ea95bf6e0 CPExpression: renamed private classes to follow naming rules. 2011-12-17 16:10:06 +01:00
cacaodev 08d690b65d Completed isEqual: support for CPExpression & CPPredicate subclasses 2011-12-17 15:37:43 +01:00
cacaodev edf07a8fbc CPRuleEditor: In -initWithFrame: the _CPRuleEditorLocalizer was not initialized by default. 2011-12-17 15:28:41 +01:00
cacaodev fab7d41446 CPRuleEditor: renamed private class RowObject -> _CPRuleEditorRowObject 2011-12-13 10:32:34 +01:00
cacaodev f33a55f1d0 CPPredicateEditor: bindings compatibility. Send control action only after a UI interaction to prevent sending unwanted notifications to the binder.
Send action through the responder chain even if target or action is nil. CPControl relies on this to send updates to the binder.
2011-12-13 10:32:34 +01:00
cacaodev 96a3eef4e1 CPRuleEditor IE7/8/9 compatibility, closes #1279 2011-12-13 10:32:22 +01:00
cacaodev 93dc4d1bc9 CPRuleEditor: -bind:toObject:withKeyPath:options: removed a useless check that was causing an exception when keyPath was a compound key path.
CPPredicateEditor test app: bind textfield and editor to a CPObjectController.
2011-12-13 09:54:24 +01:00
cacaodev d973670026 CPPredicateEditor: - Templates merging. Means that from the same left item you can have different views on the right:
* date is (today, yesterday)
                      * date is less than [text field]

                    - CPPredicateEditorCibTest example: templates merging in the 'mixed' criterion.
                    - ojtest AppKit/CPPredicateEditorTest testing the merging feature.

                    - Cleaned and rearranged code related to the right control action method.
                    - re-enable tooltips.
2011-12-13 09:50:26 +01:00
cacaodev c327956537 CPRuleEditor: Since commit 2b52f7d, CPRuleEditor's delegate method -ruleEditor:displayValueForCriterion:inRow: is more restricive: you must return the same view object for a specific criterion in a given row.
In CPRuleEditorCibTest, the delegate has been updated to follow this rule, it also fixes a bug where the predicate was not correctly handling custom control values.
2011-12-13 09:49:35 +01:00
Randy Luecke 80f5ab09f3 Merge pull request #1410 from vhbit/master
Fixed a bug when changing selection in CPPopUpButton wasn't propagated back to bound object
2011-12-10 20:22:02 -08:00
Randy Luecke 5c8f201a92 Merge pull request #1406 from james-dessart-hb/master
Issue #1297 - fixing CPBrowser selection when using up/down arrow keys
2011-12-10 20:21:06 -08:00
Randy Luecke cf777d7f41 Merge pull request #1417 from BlairDuncan/master
Unnecessary globals
2011-12-10 20:20:22 -08:00
Blair Duncan bb7876759a unnecessary globals 2011-12-10 23:10:22 -05:00
Aparajita Fishman 800d6498d6 Added some missing semicolons 2011-12-10 10:48:54 -08:00
Aparajita Fishman 0648b4279f Added usage documentation for Framework.j 2011-12-10 09:48:08 -08:00
Antoine Mercadal 1a73abe7c3 Merge pull request #1267 from primalmotion/nib2cib-do-not-truncate-bold-labels
Do not truncate bold labels.

So this is a temp fix as @aparajita has a better way to handle this. As the patch is very straightforward, it will be easy to revert it when a more correct fix will come up. But while waiting, I think it's a good idea to have correct displaying of the bold labels.
2011-12-07 10:23:06 -08:00
Valerii Hiora cce4f7883c Merge branch 'master' of git://github.com/cappuccino/cappuccino 2011-12-07 09:58:36 +02:00
Alexander Ljungberg 3dff67e0b1 Faster CPNotificationCenter removeObserver.
Removing observers is now faster, significantly so when there are very many observers and one or more is removed while a notification is being posted.
2011-12-07 01:48:16 +00:00
Alexander Ljungberg 24326883ca More extensive Notification Center tests. 2011-12-07 01:38:41 +00:00
Alexander Ljungberg a5854f129d Fixes #1411. In IE, no table/outline view selection highlights would render for certain CIBs.
This fix also enables `setSelectionHighlightStyle: CPTableViewSelectionHighlightStyleSourceList` in Internet Explorer. Even that the gradient effect can't be rendered and the fallback regular rendering will be used, the proper field value might still be useful for subclasses or saving out to CIBs etc.
2011-12-06 23:29:57 +00:00
Alexander Ljungberg 052c07f3e3 Refs #1412, #1413. Manual test for the last two fixes. 2011-12-06 23:26:13 +00:00
Alexander Ljungberg 9367566e61 Fixes #1412. IE rendered clearColor shadows in black. 2011-12-06 23:01:26 +00:00
Alexander Ljungberg 107103bcbb Fixes #1413: Internet Explorer colorWithCSSString crash.
Syntax such as [[CPColor colorWithCSSString:@"rgba(0,0,0,0.5)"] cssString] lead to a CSS string incompatible with browsers without the CSS rgba feature.
2011-12-06 22:45:26 +00:00
Alexander Ljungberg 20ae47971c Missing semicolons. 2011-12-06 22:43:00 +00:00
Valerii Hiora d4ecb03d15 Fixed: On changing selection of CPPopUpButton value wasn't reverse
transformed to binded object
2011-12-06 22:41:30 +02:00
James Dessart f4eb47519d Issue #1297: Added tableViewSelectionDidChange: to the table view delegate in order to propagate keyboard-driven selection changes up to the browser 2011-12-02 15:46:07 -04:00
Alexander Ljungberg e37bfeeb09 Merge branch 'master' of github.com:cappuccino/cappuccino 2011-12-01 18:18:29 +00:00
Alexander Ljungberg bb0972ba49 Fixed: notifications were sent to removed observers.
If one observer of a notification centre notification removed another observer, that other observer would still be notified even that it was no longer observing.

Now the code agrees with its comments.
2011-12-01 18:18:15 +00:00
Antoine Mercadal ddc5994869 tooltips are now themable. 2011-11-28 12:05:43 +01:00
Darrell Walisser a2eb9e728c Various fixes for sheet bugs
-handle attempt to close sheet while it is animating in
-fixes Safari 5.1 animate out bug by using a timer to
initiate the in/out process
-allow window shadow to become 0 width/height for smoother animation
2011-11-24 19:28:04 -05:00
lowell 2169ba35ad [XcodeCapp] Silenced build warning: -[id<NSTableViewDelegate> tableView:heightOfRow:] expects an NSInteger for the second argument. 2011-11-24 13:59:39 -08:00
lowell 50b447b05d [XcodeCapp] App controller should conform to NSTableView data source and delegate protocols. Protocol methods don't need to be declared in the adopting class' interface because they will have already been declared in the protocol declaration. 2011-11-24 13:58:03 -08:00
Antoine Mercadal bc14ad6b9d small improvments in XcodeCapp, including handling quick remove/create existing files 2011-11-24 17:59:09 +01:00
Neer Friedman ffa33788c4 enquote ENVIRONMENTS environment variable 2011-11-24 18:04:26 +02:00
Neer Friedman 23c9c6bf44 concat command parts in Objective-j/Jakefile 2011-11-24 18:03:20 +02:00
dwalisser 604a49634d Merge remote-tracking branch 'upstream/master' 2011-11-24 09:43:10 -05:00
Alexander Ljungberg 476c02976b Code formatting. 2011-11-23 00:28:27 +00:00
Aparajita Fishman 6ac28e1a77 A few text tweaks to make the prompts more friendly. 2011-11-18 01:02:32 -08:00
Antoine Mercadal 4ec7cea6c4 update doxygen displayed Cappuccini version to 0.9.5 2011-11-16 15:12:22 +01:00
Alexander Ljungberg 0036f329f5 Fixed: in recent builds, WithBindingsTest failed with a "CPScroller does not contain theme attribute 'scroller-width'" error. 2011-11-16 12:57:01 +00:00
Alexander Ljungberg 15af54efda Fixed with CPTokenField: quickly entered tokens would be ignored.
If the autocomplete state had not been set yet, tokens could not be finished using the token separator, return or tab. Instead the user typed text remained in its 'non token' state.
2011-11-16 12:52:27 +00:00
Alexander Ljungberg 07966bb7fe Fixed with CPTokenField: crash if added to a window in a unit test. 2011-11-16 12:50:05 +00:00
Alexander Ljungberg e7d9b0503b Fixes #1398. Fixed with CPTokenField: deleting tokens in front of selected tokens would shift the selection to the right. 2011-11-16 12:04:03 +00:00
Alexander Ljungberg 072b43d178 Fixes #1397. Fixed with CPTokenField: make sure selection is initialised when loading from cib. 2011-11-16 11:55:38 +00:00
Alexander Ljungberg 281d2295ae Code formatting. 2011-11-15 23:47:56 +00:00
Darrell Walisser 3c7783f97c Revert "-fix uninitialized _selectedRange member when loading from cib",
putting in another branch

This reverts commit 2a82703e46.
2011-11-15 10:31:44 -05:00
Darrell Walisser 2a82703e46 -fix uninitialized _selectedRange member when loading from cib 2011-11-15 10:14:07 -05:00
Darrell Walisser 6eace4258f -initial stab at doc-modal sheets 2011-09-18 16:08:10 -04:00
Luc Vauvillier 6fe49fbf8d _CPThemeAttribute fix : encode missing _defaultTheme value 2011-06-01 17:02:01 +02:00
Antoine Mercadal 4a7c2a96db compense the y placement 2011-05-17 01:24:54 +02:00
Antoine Mercadal 0b09ada144 Do not truncate bold labels
When label with default size are bold, letter like p, g, q etc,
are truncated like in http://gyazo.com/d6c25af20574a96f9af0f288a7bd802a.png

This commit fix this.
2011-05-17 01:02:53 +02:00
Aparajita Fishman 329baa1719 Added license to header, SYS var 2011-05-11 11:39:18 -04:00
Aparajita Fishman 85080f5c58 Made colorPrint function local 2011-05-11 09:02:05 -04:00
Aparajita Fishman 910f02ea50 Removed duplicate productName 2011-05-10 12:20:26 -04:00
Aparajita Fishman bfd8eefa0e Added textFrame method to locate the text within the view 2011-05-09 21:15:12 -04:00
Aparajita Fishman 2d96fcf87f Improvements to the ThemeDescriptor capp template:
- New/improved jake tasks: debug, release, all, clean, clobber, test, test-release, help.
- help task shows comprehensive, formatted documentation for the available tasks.
- BlendKit is automatically symlinked into the Frameworks directory if necessary as part of the build process, so that the showcase will always work.
- User can easily change the build directory by changing one line.
- Fixed incorrect placeholders in main.j.
2011-05-07 13:12:12 -04:00
790 changed files with 73605 additions and 20103 deletions
+10 -2
View File
@@ -20,7 +20,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "_CPToolTip.j"
@import "CALayer.j"
@import "CGGeometry.j"
@import "CPAccordionView.j"
@import "CPAlert.j"
@import "CPAnimation.j"
@import "CPApplication.j"
@@ -35,16 +38,21 @@
@import "CPCibBindingConnector.j"
@import "CPCibConnector.j"
@import "CPCibControlConnector.j"
@import "CPCibHelpConnector.j"
@import "CPCibLoading.j"
@import "CPCibOutletConnector.j"
@import "CPCibRuntimeAttributesConnector.j"
@import "CPClipView.j"
@import "CPCollectionView.j"
@import "CPCollectionViewItem.j"
@import "CPColor.j"
@import "CPColorPanel.j"
@import "CPColorSpace.j"
@import "CPColorWell.j"
@import "CPComboBox.j"
@import "CPCompatibility.j"
@import "CPControl.j"
@import "CPController.j"
@import "CPCookie.j"
@import "CPCursor.j"
@import "CPDocument.j"
@@ -54,7 +62,7 @@
@import "CPFlashView.j"
@import "CPFont.j"
@import "CPFontManager.j"
@import "CPGeometry.j"
@import "CPGradient.j"
@import "CPGraphics.j"
@import "CPImage.j"
@import "CPImageView.j"
@@ -92,7 +100,6 @@
@import "CPTokenField.j"
@import "CPToolbar.j"
@import "CPToolbarItem.j"
@import "_CPToolTip.j"
@import "CPTreeNode.j"
@import "CPUserDefaultsController.j"
@import "CPView.j"
@@ -101,3 +108,4 @@
@import "CPWebView.j"
@import "CPWindow.j"
@import "CPWindowController.j"
@import "CPWorkspace.j"
+14 -11
View File
@@ -117,21 +117,21 @@ CPCriticalAlertStyle = 2;
*/
+ (CPAlert)alertWithMessageText:(CPString)aMessage defaultButton:(CPString)defaultButtonTitle alternateButton:(CPString)alternateButtonTitle otherButton:(CPString)otherButtonTitle informativeTextWithFormat:(CPString)informativeText
{
var alert = [[self alloc] init];
var newAlert = [[self alloc] init];
[alert setMessageText:aMessage];
[alert addButtonWithTitle:defaultButtonTitle];
[newAlert setMessageText:aMessage];
[newAlert addButtonWithTitle:defaultButtonTitle];
if (alternateButtonTitle)
[alert addButtonWithTitle:alternateButtonTitle];
[newAlert addButtonWithTitle:alternateButtonTitle];
if (otherButtonTitle)
[alert addButtonWithTitle:otherButtonTitle];
[newAlert addButtonWithTitle:otherButtonTitle];
if (informativeText)
[alert setInformativeText:informativeText];
[newAlert setInformativeText:informativeText];
return alert;
return newAlert;
}
/*!
@@ -142,12 +142,12 @@ CPCriticalAlertStyle = 2;
*/
+ (CPAlert)alertWithError:(CPString)anErrorMessage
{
var alert = [[self alloc] init];
var newAlert = [[self alloc] init];
[alert setMessageText:anErrorMessage];
[alert setAlertStyle:CPCriticalAlertStyle];
[newAlert setMessageText:anErrorMessage];
[newAlert setAlertStyle:CPCriticalAlertStyle];
return alert;
return newAlert;
}
/*!
@@ -631,7 +631,10 @@ CPCriticalAlertStyle = 2;
- (@action)_takeReturnCodeFrom:(id)aSender
{
if ([_window isSheet])
{
[CPApp endSheet:_window returnCode:[aSender tag]];
[_window orderOut:nil];
}
else
{
[CPApp abortModal];
+2 -1
View File
@@ -122,6 +122,7 @@ ACTUAL_FRAME_RATE = 0;
*/
- (void)setAnimationCurve:(CPAnimationCurve)anAnimationCurve
{
var timingFunctionName;
switch (anAnimationCurve)
{
case CPAnimationEaseInOut: timingFunctionName = kCAMediaTimingFunctionEaseInEaseOut;
@@ -306,7 +307,7 @@ ACTUAL_FRAME_RATE = 0;
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
return [_delegate animation:self valueForProgress:t];
if (_animationCurve == CPAnimationLinear)
return t;
+56 -23
View File
@@ -33,7 +33,8 @@
var CPMainCibFile = @"CPMainCibFile",
CPMainCibFileHumanFriendly = @"Main cib file base name";
CPMainCibFileHumanFriendly = @"Main cib file base name",
CPEventModifierFlags = 0;
CPApp = nil;
@@ -219,28 +220,22 @@ CPRunContinuesResponse = -1002;
// At this point we clear the window.status to eliminate Safari's "Cancelled" error message
// The message shouldn't be displayed, because only an XHR is cancelled, but it is a usability issue.
// We do it here so that applications can change it in willFinish or didFinishLaunching
#if PLATFORM(DOM)
window.status = " ";
#endif
// We also want to set the default cursor on the body, so that buttons and things don't have an iBeam
[[CPCursor arrowCursor] set];
var bundle = [CPBundle mainBundle],
types = [bundle objectForInfoDictionaryKey:@"CPBundleDocumentTypes"];
if ([types count] > 0)
_documentController = [CPDocumentController sharedDocumentController];
var delegateClassName = [bundle objectForInfoDictionaryKey:@"CPApplicationDelegateClass"];
delegateClassName = [bundle objectForInfoDictionaryKey:@"CPApplicationDelegateClass"];
if (delegateClassName)
{
var delegateClass = objj_getClass(delegateClassName);
if (delegateClass)
if ([_documentController class] == delegateClass)
[self setDelegate:_documentController];
else
[self setDelegate:[[delegateClass alloc] init]];
[self setDelegate:[[delegateClass alloc] init]];
}
var defaultCenter = [CPNotificationCenter defaultCenter];
@@ -249,13 +244,18 @@ CPRunContinuesResponse = -1002;
postNotificationName:CPApplicationWillFinishLaunchingNotification
object:self];
var types = [bundle objectForInfoDictionaryKey:@"CPBundleDocumentTypes"];
if ([types count] > 0)
_documentController = [CPDocumentController sharedDocumentController];
var needsUntitled = !!_documentController,
URLStrings = window.cpOpeningURLStrings && window.cpOpeningURLStrings(),
index = 0,
count = [URLStrings count];
for (; index < count; ++index)
needsUntitled = ![self _openURL:[CPURL URLWithString:URLStrings[index]]] || needsUntitled;
needsUntitled = ![self _openURL:[CPURL URLWithString:URLStrings[index]]] && needsUntitled;
if (needsUntitled && [_delegate respondsToSelector:@selector(applicationShouldOpenUntitledFile:)])
needsUntitled = [_delegate applicationShouldOpenUntitledFile:self];
@@ -374,7 +374,7 @@ CPRunContinuesResponse = -1002;
standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"];
// FIXME move this into the CIB eventually
[applicationLabel setFont:[CPFont boldSystemFontOfSize:14.0]];
[applicationLabel setFont:[CPFont boldSystemFontOfSize:[CPFont systemFontSize] + 2]];
[applicationLabel setAlignment:CPCenterTextAlignment];
[versionLabel setAlignment:CPCenterTextAlignment];
[copyrightLabel setAlignment:CPCenterTextAlignment];
@@ -576,28 +576,35 @@ CPRunContinuesResponse = -1002;
- (void)sendEvent:(CPEvent)anEvent
{
_currentEvent = anEvent;
CPEventModifierFlags = [anEvent modifierFlags];
#if PLATFORM(DOM)
var willPropagate = [[[anEvent window] platformWindow] _willPropagateCurrentDOMEvent];
// temporarily pretend we won't propagate the event. we'll restore the saved value later
// we do this outside the if so that changes user code might make in _handleKeyEquiv. are preserved
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
#endif
// Check if this is a candidate for key equivalent...
if ([anEvent _couldBeKeyEquivalent] && [self _handleKeyEquivalent:anEvent])
{
#if PLATFORM(DOM)
var characters = [anEvent characters],
modifierFlags = [anEvent modifierFlags];
// Unconditionally propagate on these keys to solve browser copy paste bugs
if ((characters == "c" || characters == "x" || characters == "v") && (modifierFlags & CPPlatformActionKeyMask))
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
#endif
return;
}
#if PLATFORM(DOM)
// if we make it this far, then restore the original willPropagate value
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:willPropagate];
#endif
if (_eventListeners.length)
{
@@ -926,15 +933,21 @@ CPRunContinuesResponse = -1002;
*/
- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
{
var styleMask = [aSheet styleMask];
if (!(styleMask & CPDocModalWindowMask))
if ([aWindow isSheet])
{
[CPException raise:CPInternalInconsistencyException reason:@"Currently only CPDocModalWindowMask style mask is supported for attached sheets"];
[CPException raise:CPInternalInconsistencyException reason:@"The target window of beginSheet: cannot be a sheet"];
return;
}
[aWindow orderFront:self];
[aSheet setPlatformWindow:[aWindow platformWindow]];
[aSheet._windowView _enableSheet:YES];
// -dw- if a sheet is already visible, we skip this since it serves no purpose and causes
// orderOut: to be called on the sheet, which is not what we want.
if (![aWindow isVisible])
{
[aWindow orderFront:self];
[aSheet setPlatformWindow:[aWindow platformWindow]];
}
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
}
@@ -963,7 +976,7 @@ CPRunContinuesResponse = -1002;
if (context != nil && context["sheet"] === sheet)
{
context["returnCode"] = returnCode;
[aWindow _detachSheetWindow];
[aWindow _endSheet];
return;
}
}
@@ -1166,12 +1179,12 @@ CPRunContinuesResponse = -1002;
var _CPModalSessionMake = function(aWindow, aStopCode)
{
return { _window:aWindow, _state:CPRunContinuesResponse , _previous:nil };
}
};
var _CPEventListenerMake = function(anEventMask, aCallback)
{
return { _mask:anEventMask, _callback:aCallback };
}
};
// Make this a global for use in CPPlatformWindow+DOM.j.
_CPRunModalLoop = function(anEvent)
@@ -1181,9 +1194,16 @@ _CPRunModalLoop = function(anEvent)
var theWindow = [anEvent window],
modalSession = CPApp._currentSession;
if (theWindow == modalSession._window || [theWindow worksWhenModal])
// The special case for popovers here is not clear. In Cocoa the popover window does not respond YES to worksWhenModal,
// yet it works when there is a modal window. Maybe it starts its own modal session, but interaction with the original
// modal window seems to continue working as well. Regardless of correctness, this solution beats popovers not working
// at all from sheets.
if (theWindow == modalSession._window ||
[theWindow worksWhenModal] ||
[theWindow attachedSheet] == modalSession._window || // -dw- allow modal parent of sheet to be repositioned
([theWindow isKindOfClass:_CPAttachedWindow] && [[theWindow targetView] window] === modalSession._window))
[theWindow sendEvent:anEvent];
}
};
/*!
Starts the GUI and Cappuccino frameworks. This function should be
@@ -1370,3 +1390,16 @@ var _CPAppBootstrapperActions = nil;
}
@end
@implementation CPEvent (CPApplicationModifierFlags)
/*!
Returns the currently pressed modifier flags.
*/
+ (unsigned)modifierFlags
{
return CPEventModifierFlags;
}
@end
+80 -33
View File
@@ -564,7 +564,7 @@
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
{
[self _selectionWillChange]
var r = [self __setSelectionIndexes:indexes];
var r = [self __setSelectionIndexes:indexes avoidEmpty:NO];
[self _selectionDidChange];
return r;
}
@@ -583,6 +583,11 @@
@ignore
*/
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes
{
return [self __setSelectionIndexes:indexes avoidEmpty:_avoidsEmptySelection];
}
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes avoidEmpty:(BOOL)avoidEmpty
{
var newIndexes = indexes;
@@ -591,7 +596,7 @@
if (![newIndexes count])
{
if (_avoidsEmptySelection && [[self arrangedObjects] count])
if (avoidEmpty && [[self arrangedObjects] count])
newIndexes = [CPIndexSet indexSetWithIndex:0];
}
else
@@ -606,7 +611,7 @@
// Remove out of bounds indexes.
[newIndexes removeIndexesInRange:CPMakeRange(objectsCount, [newIndexes lastIndex] + 1)];
// When avoiding empty selection and the deleted selection was at the bottom, select the last item.
if (![newIndexes count] && _avoidsEmptySelection && objectsCount)
if (![newIndexes count] && avoidEmpty && objectsCount)
newIndexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
}
@@ -647,7 +652,7 @@
[self willChangeValueForKey:@"selectionIndexes"];
[self _selectionWillChange];
var r = [self __setSelectedObjects:objects];
var r = [self __setSelectedObjects:objects avoidEmpty:NO];
[self didChangeValueForKey:@"selectionIndexes"];
[self _selectionDidChange];
@@ -659,6 +664,11 @@
@ignore
*/
- (BOOL)__setSelectedObjects:(CPArray)objects
{
[self __setSelectedObjects:objects avoidEmpty:_avoidsEmptySelection];
}
- (BOOL)__setSelectedObjects:(CPArray)objects avoidEmpty:(BOOL)avoidEmpty
{
var set = [CPIndexSet indexSet],
count = [objects count],
@@ -672,7 +682,7 @@
[set addIndex:index];
}
[self __setSelectionIndexes:set];
[self __setSelectionIndexes:set avoidEmpty:avoidEmpty];
return YES;
}
@@ -869,6 +879,9 @@
[_arrangedObjects removeObjectAtIndex:pos];
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:-1];
// This will automatically handle the avoidsEmptySelection case.
[self __setSelectionIndexes:_selectionIndexes];
}
[self didChangeValueForKey:@"content"];
@@ -910,6 +923,15 @@
[self removeObjectsAtArrangedObjectIndexes:_selectionIndexes];
}
/*!
Removes the object at the specified index in the controller's arranged objects from the content array.
@param int index - index of the object to remove.
*/
- (void)removeObjectAtArrangedObjectIndex:(int)index
{
[self removeObjectsAtArrangedObjectIndexes:[CPIndexSet indexSetWithIndex:index]];
}
/*!
Removes the objects at the specified indexes in the controller's arranged objects from the content array.
@param CPIndexSet indexes - indexes of the objects to remove.
@@ -924,36 +946,38 @@
_disableSetContent = YES;
var arrangedObjects = [self arrangedObjects],
index = [anIndexSet lastIndex],
position = CPNotFound,
newSelectionIndexes = [_selectionIndexes copy];
while (index !== CPNotFound)
{
var object = [arrangedObjects objectAtIndex:index];
// First try the simple case which should work if there are no sort descriptors.
if ([_contentObject objectAtIndex:index] === object)
[_contentObject removeObjectAtIndex:index];
else
[anIndexSet enumerateIndexesWithOptions:CPEnumerationReverse
usingBlock:function(anIndex)
{
// Since we don't have a reverse mapping between the sorted order and the
// unsorted one, we'll just simply have to remove an arbitrary pointer. It might
// be the 'wrong' one - as in not the one the user selected - but the wrong
// one is still just another pointer to the same object, so the user will not
// be able to see any difference.
contentIndex = [_contentObject indexOfObjectIdenticalTo:object];
[_contentObject removeObjectAtIndex:contentIndex];
}
[arrangedObjects removeObjectAtIndex:index];
var object = [arrangedObjects objectAtIndex:anIndex];
// Deselect this row if it was selected, and either way shift all selection indexes
// following it up by 1.
[newSelectionIndexes removeIndex:index];
[newSelectionIndexes shiftIndexesStartingAtIndex:index by:-1];
// First try the simple case which should work if there are no sort descriptors.
if ([_contentObject objectAtIndex:anIndex] === object)
[_contentObject removeObjectAtIndex:anIndex];
else
{
// Since we don't have a reverse mapping between the sorted order and the
// unsorted one, we'll just simply have to remove an arbitrary pointer. It might
// be the 'wrong' one - as in not the one the user selected - but the wrong
// one is still just another pointer to the same object, so the user will not
// be able to see any difference.
contentIndex = [_contentObject indexOfObjectIdenticalTo:object];
[_contentObject removeObjectAtIndex:contentIndex];
}
[arrangedObjects removeObjectAtIndex:anIndex];
if (!_avoidsEmptySelection || [newSelectionIndexes count] > 1)
{
[newSelectionIndexes removeIndex:anIndex];
[newSelectionIndexes shiftIndexesStartingAtIndex:anIndex by:-1];
}
else if ([newSelectionIndexes lastIndex] !== anIndex)
[newSelectionIndexes shiftIndexesStartingAtIndex:anIndex by:-1];
}];
index = [anIndexSet indexLessThanIndex:index];
}
// Allow handlesContentAsCompoundValue reverse sets to trigger.
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
_disableSetContent = NO;
@@ -1066,22 +1090,45 @@
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
isCompound = [self handlesContentAsCompoundValue];
isCompound = [self handlesContentAsCompoundValue],
dotIndex = keyPath.lastIndexOf("."),
firstPart = dotIndex !== CPNotFound ? keyPath.substring(0, dotIndex) : nil,
isSelectionProxy = firstPart && [[destination valueForKeyPath:firstPart] isKindOfClass:CPControllerSelectionProxy];
if (!isCompound)
if (!isCompound && !isSelectionProxy)
{
newValue = [destination mutableArrayValueForKeyPath:keyPath];
}
else
{
// handlesContentAsCompoundValue == YES so we cannot just set up a proxy.
// 1. If handlesContentAsCompoundValue we cannot just set up a proxy.
// Every read and every write must go through transformValue and
// reverseTransformValue, and the resulting object cannot be described by
// a key path.
// 2. If isSelectionProxy, we don't want to proxy a proxy - that's bad
// for performance and won't work with markers.
newValue = [destination valueForKeyPath:keyPath];
}
newValue = [self transformValue:newValue withOptions:options];
var isPlaceholder = CPIsControllerMarker(newValue);
if (isPlaceholder)
{
if (newValue === CPNotApplicableMarker && [options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
{
[CPException raise:CPGenericException
reason:@"can't transform non applicable key on: " + _source + " value: " + newValue];
}
newValue = [self _placeholderForMarker:newValue];
// This seems to be what Cocoa does.
if (!newValue)
newValue = [CPMutableArray array];
}
else
newValue = [self transformValue:newValue withOptions:options];
if (isCompound)
{
+1 -2
View File
@@ -20,7 +20,6 @@
* 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 <Foundation/CPObject.j>
@@ -276,7 +275,7 @@ var DefaultLineWidth = 1.0;
/*!
Append the contents of a CPBezierPath object.
*/
- (void)appendBezierPath:(NSBezierPath *)other
- (void)appendBezierPath:(CPBezierPath)other
{
CGPathAddPath(_path, nil, other._path);
}
+129 -7
View File
@@ -35,6 +35,16 @@ CPLineBorder = 1;
CPBezelBorder = 2;
CPGrooveBorder = 3;
// CPTitlePosition
CPNoTitle = 0;
CPAboveTop = 1;
CPAtTop = 2;
CPBelowTop = 3;
CPAboveBottom = 4;
CPAtBottom = 5;
CPBelowBottom = 6;
/*!
@ingroup appkit
@class CPBox
@@ -54,6 +64,10 @@ CPGrooveBorder = 3;
CPSize _contentMargin;
CPView _contentView;
CPString _title @accessors(getter=title);
int _titlePosition @accessors(getter=titlePosition);
CPTextField _titleView;
}
+ (id)boxEnclosingView:(CPView)aView
@@ -61,7 +75,7 @@ CPGrooveBorder = 3;
var box = [[self alloc] initWithFrame:CGRectMakeZero()],
enclosingView = [aView superview];
[box setAutoresizingMask:[aView autoresizingMask]];
[box setAutoresizingMask:[aView autoresizingMask]];
[box setFrameFromContentFrame:[aView frame]];
[enclosingView replaceSubview:aView with:box];
@@ -84,6 +98,9 @@ CPGrooveBorder = 3;
_borderWidth = 1.0;
_contentMargin = CGSizeMake(0.0, 0.0);
_titlePosition = CPNoTitle;
_titleView = [CPTextField labelWithTitle:@""];
_contentView = [[CPView alloc] initWithFrame:[self bounds]];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
@@ -278,18 +295,100 @@ CPGrooveBorder = 3;
- (void)setFrameFromContentFrame:(CPRect)aRect
{
[self setFrame:CGRectInset(aRect, -(_contentMargin.width + _borderWidth), -(_contentMargin.height + _borderWidth))];
var offset = [self _titleHeightOffset];
[self setFrame:CGRectInset(aRect, -(_contentMargin.width + _borderWidth), -(_contentMargin.height + offset[0] + _borderWidth))];
[self setNeedsDisplay:YES];
}
- (void)setTitle:(CPString)aTitle
{
if (aTitle == _title)
return;
_title = aTitle;
[self _manageTitlePositioning];
}
- (void)setTitlePosition:(int)aTitlePotisition
{
if (aTitlePotisition == _titlePosition)
return;
_titlePosition = aTitlePotisition;
[self _manageTitlePositioning];
}
- (void)_manageTitlePositioning
{
if (_titlePosition == CPNoTitle)
{
[_titleView removeFromSuperview];
[self setNeedsDisplay:YES];
return;
}
[_titleView setStringValue:_title];
[_titleView sizeToFit];
[self addSubview:_titleView];
switch (_titlePosition)
{
case CPAtTop:
case CPAboveTop:
case CPBelowTop:
[_titleView setFrameOrigin:CPPointMake(5.0, 0.0)];
[_titleView setAutoresizingMask:CPViewNotSizable];
break;
case CPAboveBottom:
case CPAtBottom:
case CPBelowBottom:
var h = [_titleView frameSize].height;
[_titleView setFrameOrigin:CPPointMake(5.0, [self frameSize].height - h)];
[_titleView setAutoresizingMask:CPViewMinYMargin];
break;
}
[self sizeToFit];
[self setNeedsDisplay:YES];
}
- (void)sizeToFit
{
var contentFrame = [_contentView frame];
var contentFrame = [_contentView frame],
offset = [self _titleHeightOffset];
if (!contentFrame)
return;
[_contentView setAutoresizingMask:CPViewNotSizable];
[self setFrameSize:CGSizeMake(contentFrame.size.width + _contentMargin.width * 2,
contentFrame.size.height + _contentMargin.height * 2)];
contentFrame.size.height + _contentMargin.height * 2 + offset[0])];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height)];
[_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height + offset[1])];
}
- (float)_titleHeightOffset
{
if (_titlePosition == CPNoTitle)
return [0.0, 0.0];
switch (_titlePosition)
{
case CPAtTop:
return [[_titleView frameSize].height, [_titleView frameSize].height];
case CPAtBottom:
return [[_titleView frameSize].height, 0.0];
default:
return [0.0, 0.0];
}
}
- (void)drawRect:(CPRect)rect
@@ -297,7 +396,7 @@ CPGrooveBorder = 3;
if (_borderType === CPNoBorder)
return;
var bounds = [self bounds];
var bounds = CGRectMakeCopy([self bounds]);
switch (_boxType)
{
@@ -312,6 +411,16 @@ CPGrooveBorder = 3;
break;
}
if (_titlePosition == CPAtTop)
{
bounds.origin.y += [_titleView frameSize].height;
bounds.size.height -= [_titleView frameSize].height;
}
if (_titlePosition == CPAtBottom)
{
bounds.size.height -= [_titleView frameSize].height;
}
switch (_borderType)
{
case CPBezelBorder:
@@ -386,7 +495,10 @@ var CPBoxTypeKey = @"CPBoxTypeKey",
CPBoxFillColorKey = @"CPBoxFillColorKey",
CPBoxCornerRadiusKey = @"CPBoxCornerRadiusKey",
CPBoxBorderWidthKey = @"CPBoxBorderWidthKey",
CPBoxContentMarginKey = @"CPBoxContentMarginKey";
CPBoxContentMarginKey = @"CPBoxContentMarginKey",
CPBoxTitle = @"CPBoxTitle",
CPBoxTitlePosition = @"CPBoxTitlePosition",
CPBoxTitleView = @"CPBoxTitleView";
@implementation CPBox (CPCoding)
@@ -407,10 +519,16 @@ var CPBoxTypeKey = @"CPBoxTypeKey",
_contentMargin = [aCoder decodeSizeForKey:CPBoxContentMarginKey];
_title = [aCoder decodeObjectForKey:CPBoxTitle];
_titlePosition = [aCoder decodeIntForKey:CPBoxTitlePosition];
_titleView = [aCoder decodeObjectForKey:CPBoxTitleView] || [CPTextField labelWithTitle:_title];
_contentView = [self subviews][0];
[self setAutoresizesSubviews:YES];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self _manageTitlePositioning];
}
return self;
@@ -429,6 +547,10 @@ var CPBoxTypeKey = @"CPBoxTypeKey",
[aCoder encodeFloat:_cornerRadius forKey:CPBoxCornerRadiusKey];
[aCoder encodeFloat:_borderWidth forKey:CPBoxBorderWidthKey];
[aCoder encodeObject:_title forKey:CPBoxTitle];
[aCoder encodeInt:_titlePosition forKey:CPBoxTitlePosition];
[aCoder encodeObject:_titleView forKey:CPBoxTitleView];
[aCoder encodeSize:_contentMargin forKey:CPBoxContentMarginKey];
}
+8 -2
View File
@@ -258,7 +258,7 @@
var column = [[CPTableColumn alloc] initWithIdentifier:@"Image"],
view = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
[view setImageScaling:CPScaleProportionally];
[view setImageScaling:CPImageScaleProportionallyDown];
[column setDataView:view];
[column setResizingMask:CPTableColumnNoResizing];
@@ -901,6 +901,12 @@ var _CPBrowserResizeControlBackgroundImage = nil;
[_browser _column:_index clickedRow:[selectedIndexes count] === 1 ? [selectedIndexes firstIndex] : -1];
}
- (void)tableViewSelectionDidChange:(CPNotification)aNotification
{
var selectedIndexes = [[aNotification object] selectedRowIndexes];
[_browser selectRowIndexes:selectedIndexes inColumn:_index];
}
- (id)childAtIndex:(unsigned)index
{
return [_delegate browser:_browser child:index ofItem:_item];
@@ -982,7 +988,7 @@ var _CPBrowserResizeControlBackgroundImage = nil;
isHighlighted = [self themeState] & CPThemeStateSelectedDataView;
[imageView setImage: _isLeaf ? (isHighlighted ? _highlightedBranchImage : _branchImage) : nil];
[imageView setImageScaling:CPScaleNone];
[imageView setImageScaling:CPImageScaleNone];
}
- (void)encodeWithCoder:(CPCoder)aCoder
+211 -79
View File
@@ -29,20 +29,21 @@
/* @group CPBezelStyle */
CPRoundedBezelStyle = 1;
CPRegularSquareBezelStyle = 2;
// IB style
CPRoundedBezelStyle = 1; // Push
CPRegularSquareBezelStyle = 2; // Bevel
CPThickSquareBezelStyle = 3;
CPThickerSquareBezelStyle = 4;
CPDisclosureBezelStyle = 5;
CPShadowlessSquareBezelStyle = 6;
CPCircularBezelStyle = 7;
CPTexturedSquareBezelStyle = 8;
CPHelpButtonBezelStyle = 9;
CPSmallSquareBezelStyle = 10;
CPTexturedRoundedBezelStyle = 11;
CPRoundRectBezelStyle = 12;
CPRecessedBezelStyle = 13;
CPRoundedDisclosureBezelStyle = 14;
CPDisclosureBezelStyle = 5; // Disclosure triangle
CPShadowlessSquareBezelStyle = 6; // Square
CPCircularBezelStyle = 7; // Round
CPTexturedSquareBezelStyle = 8; // Textured
CPHelpButtonBezelStyle = 9; // Help
CPSmallSquareBezelStyle = 10; // Gradient
CPTexturedRoundedBezelStyle = 11; // Round Textured
CPRoundRectBezelStyle = 12; // Round Rect
CPRecessedBezelStyle = 13; // Recessed
CPRoundedDisclosureBezelStyle = 14; // Disclosure
CPHUDBezelStyle = -1;
@@ -111,6 +112,8 @@ CPButtonImageOffset = 3.0;
CPTimer _continuousTimer;
float _periodicDelay;
float _periodicInterval;
BOOL _isTracking;
}
+ (id)buttonWithTitle:(CPString)aTitle
@@ -141,9 +144,9 @@ CPButtonImageOffset = 3.0;
}
/*!
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.
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
{
@@ -155,7 +158,7 @@ CPButtonImageOffset = 3.0;
[self setValue:CPCenterTextAlignment forThemeAttribute:@"alignment"];
[self setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
[self setValue:CPScaleNone forThemeAttribute:@"image-scaling"];
[self setValue:CPImageScaleNone forThemeAttribute:@"image-scaling"];
[self setBezelStyle:CPRoundRectBezelStyle];
[self setBordered:YES];
@@ -176,11 +179,13 @@ CPButtonImageOffset = 3.0;
// Continuous button defaults.
_periodicInterval = 0.05;
_periodicDelay = 0.5;
[self setButtonType:CPMomentaryPushInButton];
}
// Setting the state
/*!
Returns a Boolean value indicating whether the button allows a mixed state.
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
@@ -206,24 +211,20 @@ CPButtonImageOffset = 3.0;
}
/*!
Sets the value of the button using an Objective-J object.
@param anObjectValue The value of the button interpreted as an Objective-J object.
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))
anObjectValue = CPOffState;
else if (![anObjectValue isKindOfClass:[CPNumber class]])
anObjectValue = CPOnState;
else if (anObjectValue >= CPOnState)
anObjectValue = CPOnState
else if (anObjectValue < CPOffState)
if ([self allowsMixedState])
anObjectValue = CPMixedState;
else
anObjectValue = CPOnState;
@@ -231,24 +232,35 @@ CPButtonImageOffset = 3.0;
switch ([self objectValue])
{
case CPMixedState: [self unsetThemeState:CPThemeStateSelected];
[self setThemeState:CPButtonStateMixed];
break;
case CPMixedState:
[self unsetThemeState:CPThemeStateSelected];
[self setThemeState:CPButtonStateMixed];
if (_showsStateBy & (CPChangeGrayCellMask | CPChangeBackgroundCellMask))
[self setThemeState:CPThemeStateHighlighted];
else
[self unsetThemeState:CPThemeStateHighlighted];
break;
case CPOnState: [self unsetThemeState:CPButtonStateMixed];
[self setThemeState:CPThemeStateSelected];
break;
case CPOnState:
[self unsetThemeState:CPButtonStateMixed];
[self setThemeState:CPThemeStateSelected];
if (_showsStateBy & (CPChangeGrayCellMask | CPChangeBackgroundCellMask))
[self setThemeState:CPThemeStateHighlighted];
else
[self unsetThemeState:CPThemeStateHighlighted];
break;
case CPOffState: [self unsetThemeState:CPThemeStateSelected | CPButtonStateMixed];
case CPOffState:
[self unsetThemeState:CPThemeStateSelected | CPButtonStateMixed | CPThemeStateHighlighted];
}
}
/*!
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).
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
{
@@ -294,9 +306,9 @@ CPButtonImageOffset = 3.0;
}
/*!
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.
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
{
@@ -310,9 +322,9 @@ CPButtonImageOffset = 3.0;
}
/*!
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.
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
{
@@ -374,11 +386,19 @@ CPButtonImageOffset = 3.0;
- (void)setShowsStateBy:(CPInteger)aMask
{
// CPPushInCellMask cannot be set for showsStateBy.
aMask &= ~CPPushInCellMask;
if (_showsStateBy === aMask)
return;
_showsStateBy = aMask;
if (_showsStateBy & (CPChangeGrayCellMask | CPChangeBackgroundCellMask) && [self state] != CPOffState)
[self setThemeState:CPThemeStateHighlighted];
else
[self unsetThemeState:CPThemeStateHighlighted];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
@@ -402,15 +422,20 @@ CPButtonImageOffset = 3.0;
}
}
- (CPInteger)highlightsBy
{
return _highlightsBy;
}
- (void)setButtonType:(CPButtonType)aButtonType
{
switch (aButtonType)
{
case CPMomentaryLightButton: [self setHighlightsBy:CPChangeBackgroundCellMask];
case CPMomentaryLightButton: [self setHighlightsBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryPushInButton: [self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask];
case CPMomentaryPushInButton: [self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
@@ -418,12 +443,12 @@ CPButtonImageOffset = 3.0;
[self setShowsStateBy:CPNoCellMask];
break;
case CPPushOnPushOffButton: [self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask];
[self setShowsStateBy:CPChangeBackgroundCellMask];
case CPPushOnPushOffButton: [self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeBackgroundCellMask | CPChangeGrayCellMask];
break;
case CPOnOffButton: [self setHighlightsBy:CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeBackgroundCellMask];
case CPOnOffButton: [self setHighlightsBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
break;
case CPToggleButton: [self setHighlightsBy:CPPushInCellMask | CPContentsCellMask];
@@ -494,20 +519,43 @@ CPButtonImageOffset = 3.0;
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
[self highlight:YES];
_isTracking = YES;
return [super startTrackingAt:aPoint];
var startedTracking = [super startTrackingAt:aPoint];
if (_highlightsBy & (CPPushInCellMask | CPChangeGrayCellMask))
{
if (_showsStateBy & (CPChangeGrayCellMask | CPChangeBackgroundCellMask))
[self highlight:[self state] == CPOffState];
else
[self highlight:YES];
}
else
{
if (_showsStateBy & (CPChangeGrayCellMask | CPChangeBackgroundCellMask))
[self highlight:[self state] != CPOffState];
else
[self highlight:NO];
}
return startedTracking;
}
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
{
[self highlight:NO];
[self invalidateTimers];
[super stopTracking:lastPoint at:aPoint mouseIsUp:mouseIsUp];
_isTracking = NO;
if (mouseIsUp && CGRectContainsPoint([self bounds], aPoint))
[self setNextState];
else
{
if (_showsStateBy & (CPChangeGrayCellMask | CPChangeBackgroundCellMask))
[self highlight:[self state] != CPOffState];
else
[self highlight:NO];
}
[self setNeedsLayout];
[self setNeedsDisplay:YES];
[self invalidateTimers];
}
- (void)invalidateTimers
@@ -529,35 +577,18 @@ CPButtonImageOffset = 3.0;
{
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
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;
return _CGRectInsetByInset(bounds, contentInset);
}
- (CGRect)bezelRectForBounds:(CGRect)bounds
{
// Is this necessary? The theme itself can just change its inset to a zero inset when !CPThemeStateBordered.
if (![self isBordered])
return _CGRectMakeZero();
return bounds;
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
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;
bounds.size.height -= bezelInset.top + bezelInset.bottom;
return bounds;
return _CGRectInsetByInset(bounds, bezelInset);
}
- (CGSize)_minimumFrameSize
@@ -641,8 +672,51 @@ CPButtonImageOffset = 3.0;
if (contentView)
{
[contentView setText:([self hasThemeState:CPThemeStateHighlighted] && _alternateTitle) ? _alternateTitle : _title];
[contentView setImage:[self currentValueForThemeAttribute:@"image"]];
var title = nil,
image = nil;
if (_isTracking)
{
if (_highlightsBy & CPContentsCellMask)
{
if (_showsStateBy & CPContentsCellMask)
{
title = ([self state] == CPOffState && _alternateTitle) ? _alternateTitle : _title;
image = ([self state] == CPOffState && [self alternateImage]) ? [self alternateImage] : [self image];
}
else
{
title = [self alternateTitle];
image = [self alternateImage];
}
}
else if (_showsStateBy & CPContentsCellMask)
{
title = ([self state] != CPOffState && _alternateTitle) ? _alternateTitle : _title;
image = ([self state] != CPOffState && [self alternateImage]) ? [self alternateImage] : [self image];
}
else
{
title = _title;
image = [self image];
}
}
else
{
if (_showsStateBy & CPContentsCellMask)
{
title = ([self state] != CPOffState && _alternateTitle) ? _alternateTitle : _title;
image = ([self state] != CPOffState && [self alternateImage]) ? [self alternateImage] : [self image];
}
else
{
title = _title;
image = [self image];
}
}
[contentView setText:title];
[contentView setImage:image];
[contentView setImageOffset:[self currentValueForThemeAttribute:@"image-offset"]];
[contentView setFont:[self currentValueForThemeAttribute:@"font"]];
@@ -741,9 +815,51 @@ CPButtonImageOffset = 3.0;
return NO;
[self performClick:nil];
return YES;
}
/*!
Perform a click on the receiver.
@param sender - The sender object
*/
- (void)performClick:(id)sender
{
// This is slightly different from [super performClick:] in that the highlight behaviour is dependent on
// highlightsBy and showsStateBy.
if (![self isEnabled])
return;
[self setState:[self nextState]];
var shouldHighlight = NO;
if (_highlightsBy & (CPPushInCellMask | CPChangeGrayCellMask))
{
if (_showsStateBy & (CPChangeGrayCellMask | CPChangeBackgroundCellMask))
shouldHighlight = [self state] == CPOffState;
else
shouldHighlight = YES;
}
[self highlight:shouldHighlight];
try
{
[self sendAction:[self action] to:[self target]];
}
catch (e)
{
throw e;
}
finally
{
if (shouldHighlight)
[CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unhighlightButtonTimerDidFinish:) userInfo:nil repeats:NO];
}
}
@end
@implementation CPButton (NS)
@@ -784,7 +900,9 @@ var CPButtonImageKey = @"CPButtonImageKey",
CPButtonKeyEquivalentKey = @"CPButtonKeyEquivalentKey",
CPButtonKeyEquivalentMaskKey = @"CPButtonKeyEquivalentMaskKey",
CPButtonPeriodicDelayKey = @"CPButtonPeriodicDelayKey",
CPButtonPeriodicIntervalKey = @"CPButtonPeriodicIntervalKey";
CPButtonPeriodicIntervalKey = @"CPButtonPeriodicIntervalKey",
CPButtonHighlightsByKey = @"CPButtonHighlightsByKey",
CPButtonShowsStateByKey = @"CPButtonShowsStateByKey";
@implementation CPButton (CPCoding)
@@ -802,9 +920,20 @@ var CPButtonImageKey = @"CPButtonImageKey",
_title = [aCoder decodeObjectForKey:CPButtonTitleKey];
_alternateTitle = [aCoder decodeObjectForKey:CPButtonAlternateTitleKey];
_allowsMixedState = [aCoder decodeBoolForKey:CPButtonAllowsMixedStateKey];
if ([aCoder containsValueForKey:CPButtonAllowsMixedStateKey])
_allowsMixedState = [aCoder decodeBoolForKey:CPButtonAllowsMixedStateKey];
if ([aCoder containsValueForKey:CPButtonHighlightsByKey])
{
// If one exists, assume both do.
_highlightsBy = [aCoder decodeIntForKey:CPButtonHighlightsByKey];
_showsStateBy = [aCoder decodeIntForKey:CPButtonShowsStateByKey];
}
else
{
// Backwards compatibility: if this CPButton was encoded before coding of
// highlightsBy and showsStateBy were added, we should just use the
// default values from _init rather than overwriting with 0, 0.
}
[self setImageDimsWhenDisabled:[aCoder decodeObjectForKey:CPButtonImageDimsWhenDisabledKey]];
@@ -843,6 +972,9 @@ var CPButtonImageKey = @"CPButtonImageKey",
[aCoder encodeBool:_allowsMixedState forKey:CPButtonAllowsMixedStateKey];
[aCoder encodeInt:_highlightsBy forKey:CPButtonHighlightsByKey];
[aCoder encodeInt:_showsStateBy forKey:CPButtonShowsStateByKey];
[aCoder encodeBool:[self imageDimsWhenDisabled] forKey:CPButtonImageDimsWhenDisabledKey];
[aCoder encodeInt:[self imagePosition] forKey:CPButtonImagePositionKey];
+32 -38
View File
@@ -94,54 +94,48 @@ CPCheckBoxImageOffset = 4.0;
[self takeStateFromKeyPath:aKeyPath ofObjects:objects];
}
- (CPImage)image
{
return [self currentValueForThemeAttribute:@"image"];
}
- (CPImage)alternateImage
{
return [self currentValueForThemeAttribute:@"image"];
}
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
var startedTracking = [super startTrackingAt:aPoint];
[self highlight:YES];
return startedTracking;
}
@end
@implementation _CPCheckBoxValueBinder : CPBinder
{
}
- (void)setValueFor:(CPString)theBinding
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
[super _updatePlaceholdersWithOptions:options];
if (isPlaceholder)
{
switch (newValue)
{
case CPMultipleValuesMarker:
newValue = CPMixedState;
break;
[self _setPlaceholder:CPMixedState forMarker:CPMultipleValuesMarker isDefault:YES];
[self _setPlaceholder:CPOffState forMarker:CPNoSelectionMarker isDefault:YES];
[self _setPlaceholder:CPOffState forMarker:CPNotApplicableMarker isDefault:YES];
[self _setPlaceholder:CPOffState forMarker:CPNullMarker isDefault:YES];
}
case CPNoSelectionMarker:
newValue = CPOffState;
break;
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[_source setAllowsMixedState:(aValue === CPMixedState)];
[_source setState:aValue];
}
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];
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source setState:aValue];
}
@end
+42 -23
View File
@@ -40,23 +40,23 @@
@par Delegate Methods
@delegate -(void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
@delegate - (void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
Called when the selection in the collection view has changed.
@param collectionView the collection view who's selection changed
@delegate -(void)collectionView:(CPCollectionView)collectionView didDoubleClickOnItemAtIndex:(int)index;
@delegate - (void)collectionView:(CPCollectionView)collectionView didDoubleClickOnItemAtIndex:(int)index;
Called when the user double-clicks on an item in the collection view.
@param collectionView the collection view that received the double-click
@param index the index of the item that received the double-click
@delegate -(CPData)collectionView:(CPCollectionView)collectionView dataForItemsAtIndexes:(CPIndexSet)indices forType:(CPString)aType;
@delegate - (CPData)collectionView:(CPCollectionView)collectionView dataForItemsAtIndexes:(CPIndexSet)indices forType:(CPString)aType;
Invoked to obtain data for a set of indices.
@param collectionView the collection view to obtain data for
@param indices the indices to return data for
@param aType the data type
@return a data object containing the index items
@delegate -(CPArray)collectionView:(CPCollectionView)collectionView dragTypesForItemsAtIndexes:(CPIndexSet)indices;
@delegate - (CPArray)collectionView:(CPCollectionView)collectionView dragTypesForItemsAtIndexes:(CPIndexSet)indices;
Invoked to obtain the data types supported by the specified indices for placement on the pasteboard.
@param collectionView the collection view the items reside in
@param indices the indices to obtain drag types
@@ -242,13 +242,15 @@
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
If the new content array is smaller than the previous one, note that [receiver selectionIndexes] may
refer to out of range indices. \c selectionIndexes is not changed as a result of calling the
\c setContent: method.
@param anArray a content array
*/
- (void)setContent:(CPArray)anArray
{
// reset the _selectionIndexes
[self setSelectionIndexes:[CPIndexSet indexSet]];
_content = anArray;
[self reloadContent];
@@ -284,9 +286,11 @@
if (!_isSelectable)
{
var index = CPNotFound;
var index = CPNotFound,
itemCount = [_items count];
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
// Be wary of invalid selection ranges since setContent: does not clear selection indexes.
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound && index < itemCount)
[_items[index] setSelected:NO];
}
}
@@ -340,19 +344,23 @@
*/
- (void)setSelectionIndexes:(CPIndexSet)anIndexSet
{
if ([_selectionIndexes isEqual:anIndexSet] || !_isSelectable)
if (!anIndexSet)
anIndexSet = [CPIndexSet indexSet];
if (!_isSelectable || [_selectionIndexes isEqual:anIndexSet])
return;
var index = CPNotFound;
var index = CPNotFound,
itemCount = [_items count];
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
// Be wary of invalid selection ranges since setContent: does not clear selection indexes.
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) !== CPNotFound && index < itemCount)
[_items[index] setSelected:NO];
_selectionIndexes = anIndexSet;
var index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) !== CPNotFound)
[_items[index] setSelected:YES];
var binderClass = [[self class] _binderClassForBinding:@"selectionIndexes"];
@@ -401,7 +409,8 @@
}
index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
// Be wary of invalid selection ranges since setContent: does not clear selection indexes.
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound && index < count)
[_items[index] setSelected:YES];
[self tile];
@@ -473,7 +482,7 @@
}
var superview = [self superview],
proposedHeight = y + itemSize.height + _verticalMargin;
proposedHeight = y + itemSize.height + _verticalMargin;
if ([superview isKindOfClass:[CPClipView class]])
{
@@ -559,6 +568,8 @@
*/
- (void)setMinItemSize:(CGSize)aSize
{
if (aSize === nil || aSize === undefined)
[CPException raise:CPInvalidArgumentException reason:"Invalid value provided for minimum size"];
if (CGSizeEqualToSize(_minItemSize, aSize))
return;
@@ -665,6 +676,13 @@
indexes = [CPIndexSet indexSetWithIndex:index];
[self setSelectionIndexes:indexes];
// TODO Is it allowable for collection view items to become the first responder? In that case they
// may have become that at this point by virtue of CPWindow's sendEvent: mouse down handling, and
// the following line will rudely snatch it away from them. For most cases though, clicking on an
// item should naturally make the collection view the first responder so that keyboard navigation
// is enabled.
[[self window] makeFirstResponder:self];
}
else if (_allowsEmptySelection)
[self setSelectionIndexes:[CPIndexSet indexSet]];
@@ -965,14 +983,15 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
{
[super awakeFromCib];
if (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()) || CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
var prototypeView = [_itemPrototype view];
if (prototypeView && (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()) || CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero())))
{
var item = _itemPrototype;
if (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
_minItemSize = [[item view] frameSize];
_minItemSize = [prototypeView frameSize];
else if (CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
_maxItemSize = [[item view] frameSize];
_maxItemSize = [prototypeView frameSize];
}
}
@@ -989,11 +1008,11 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
_itemSize = CGSizeMakeZero();
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey] || CGSizeMakeZero();
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey] || CGSizeMakeZero();
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey];
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey];
_maxNumberOfRows = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfRowsKey] || 0;
_maxNumberOfColumns = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfColumnsKey] || 0;
_maxNumberOfRows = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfRowsKey];
_maxNumberOfColumns = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfColumnsKey];
_verticalMargin = [aCoder decodeFloatForKey:CPCollectionViewVerticalMarginKey];
+35 -17
View File
@@ -133,7 +133,7 @@ function CPColorWithImages()
}
/*!
Creates a color in the RGB color space, with an alpha value.
Creates a color in the RGB colorspace, 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.
@@ -147,13 +147,13 @@ function CPColorWithImages()
*/
+ (CPColor)colorWithRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
{
return [[CPColor alloc] _initWithRGBA:[red, green, blue, alpha]];
return [[CPColor alloc] _initWithRGBA:[MAX(0.0, MIN(1.0, red)), MAX(0.0, MIN(1.0, green)), MAX(0.0, MIN(1.0, blue)), MAX(0.0, MIN(1.0, alpha))]];
}
/*!
@deprecated in favor of colorWithRed:green:blue:alpha:
Creates a color in the RGB color space, with an alpha value.
Creates a color in the RGB colorspace, 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.
@@ -228,12 +228,12 @@ function CPColorWithImages()
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];
case 2: return [CPColor colorWithCalibratedRed: p green: b blue: t alpha: alpha];
case 3: return [CPColor colorWithCalibratedRed: p green: q blue: b alpha: alpha];
case 4: return [CPColor colorWithCalibratedRed: t green: p blue: b alpha: alpha];
case 5: return [CPColor colorWithCalibratedRed: b green: p blue: q alpha: alpha];
case 0: return [CPColor colorWithCalibratedRed:b green:t blue:p alpha:alpha];
case 1: return [CPColor colorWithCalibratedRed:q green:b blue:p alpha:alpha];
case 2: return [CPColor colorWithCalibratedRed:p green:b blue:t alpha:alpha];
case 3: return [CPColor colorWithCalibratedRed:p green:q blue:b alpha:alpha];
case 4: return [CPColor colorWithCalibratedRed:t green:p blue:b alpha:alpha];
case 5: return [CPColor colorWithCalibratedRed:b green:p blue:q alpha:alpha];
}
}
@@ -253,6 +253,17 @@ function CPColorWithImages()
return rgba ? [[CPColor alloc] _initWithRGBA: rgba] : null;
}
/*!
Creates a color in the sRGB colorspace with the given components and alpha values.
Values below 0.0 are treated as 0.0 and values above 1.0 are treated as 1.0.
*/
+ (CPColor)colorWithSRGBRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
{
// TODO If Cappuccino is ported to a colorspace aware platform, this color should be in
// sRGBColorSpace.
return [self colorWithRed:red green:green blue:blue alpha:alpha];
}
/*!
Returns a black color object. (RGBA=[0.0, 0.0, 0.0, 1.0])
*/
@@ -480,7 +491,9 @@ function CPColorWithImages()
parts[3] ? parseFloat(parts[3], 10) : 1.0
];
_cssString = aString;
// We can't reuse aString as _cssString because the browser might not support the `rgba` syntax, and aString might
// use it (issue #1413.)
[self _initCSSStringFromComponents];
return self;
}
@@ -494,18 +507,23 @@ function CPColorWithImages()
{
_components = components;
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]) : "") + ")";
[self _initCSSStringFromComponents];
}
return self;
}
- (void)_initCSSStringFromComponents
{
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]) : "") + ")";
}
/* @ignore */
- (id)_initWithPatternImage:(CPImage)anImage
{
+37 -36
View File
@@ -144,7 +144,7 @@ CPColorPickerViewHeight = 370;
- (void)setColor:(CPColor)aColor
{
_color = aColor;
[_previewView setBackgroundColor: _color];
[_previewView setBackgroundColor:_color];
[CPApp sendAction:@selector(changeColor:) to:nil from:self];
@@ -299,7 +299,7 @@ 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,
@@ -339,7 +339,7 @@ CPColorPickerViewHeight = 370;
[previewBox addSubview:_previewView];
var _previewLabel = [[CPTextField alloc] initWithFrame: CPRectMake(10, TOOLBAR_HEIGHT + 10, 60, 15)];
var _previewLabel = [[CPTextField alloc] initWithFrame:CGRectMake(10, TOOLBAR_HEIGHT + 10, 60, 15)];
[_previewLabel setStringValue:"Preview:"];
[_previewLabel setTextColor:[CPColor blackColor]];
[_previewLabel setAlignment:CPRightTextAlignment];
@@ -357,14 +357,14 @@ CPColorPickerViewHeight = 370;
[swatchBox addSubview:_swatchView];
var _swatchLabel = [[CPTextField alloc] initWithFrame: CPRectMake(10, TOOLBAR_HEIGHT + 8 + PREVIEW_HEIGHT + 6, 60, 15)];
[_swatchLabel setStringValue: "Swatches:"];
var _swatchLabel = [[CPTextField alloc] initWithFrame:CGRectMake(10, TOOLBAR_HEIGHT + 8 + PREVIEW_HEIGHT + 6, 60, 15)];
[_swatchLabel setStringValue:"Swatches:"];
[_swatchLabel setTextColor:[CPColor blackColor]];
[_swatchLabel setAlignment:CPRightTextAlignment];
var opacityLabel = [[CPTextField alloc] initWithFrame: CPRectMake(10, TOOLBAR_HEIGHT + PREVIEW_HEIGHT + 35, 60, 20)];
[opacityLabel setStringValue: "Opacity:"];
var opacityLabel = [[CPTextField alloc] initWithFrame:CGRectMake(10, TOOLBAR_HEIGHT + PREVIEW_HEIGHT + 35, 60, 20)];
[opacityLabel setStringValue:"Opacity:"];
[opacityLabel setTextColor:[CPColor blackColor]];
[opacityLabel setAlignment:CPRightTextAlignment];
@@ -389,7 +389,7 @@ CPColorPickerViewHeight = 370;
_action = nil;
_activePicker = nil;
[_previewView setBackgroundColor: _color];
[_previewView setBackgroundColor:_color];
if (buttonForLater)
[self _setPicker:buttonForLater];
@@ -407,12 +407,13 @@ CPColorPickerViewHeight = 370;
CPColorDragType = "CPColorDragType";
var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
/* @ignore */
@implementation _CPColorPanelSwatches : CPView
{
CPView[] _swatches;
CPArray _swatches;
CPColor _dragColor;
CPColorPanel _colorPanel;
CPCookie _swatchCookie;
@@ -422,13 +423,13 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
self = [super initWithFrame:aFrame];
[self setBackgroundColor: [CPColor grayColor]];
[self setBackgroundColor:[CPColor grayColor]];
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
var whiteColor = [CPColor whiteColor];
_swatchCookie = [[CPCookie alloc] initWithName: CPColorPanelSwatchesCookie];
_swatchCookie = [[CPCookie alloc] initWithName:CPColorPanelSwatchesCookie];
var colorList = [self startingColorList];
_swatches = [];
@@ -436,15 +437,15 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
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];
[fillView setBackgroundColor:(i < colorList.length) ? colorList[i] : whiteColor];
[view addSubview:fillView];
[self addSubview: view];
[self addSubview:view];
_swatches.push(view);
}
@@ -461,7 +462,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var cookieValue = [_swatchCookie value];
if (cookieValue == "")
if (!cookieValue)
{
return [
[CPColor blackColor],
@@ -480,7 +481,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
result = [];
for (var i = 0; i < cookieValue.length; i++)
result.push([CPColor colorWithHexString: cookieValue[i]]);
result.push([CPColor colorWithHexString:cookieValue[i]]);
return result;
}
@@ -495,7 +496,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
var future = new Date();
future.setYear(2019);
[_swatchCookie setValue: JSON.stringify(result) expires:future domain: nil];
[_swatchCookie setValue:JSON.stringify(result) expires:future domain:nil];
}
- (void)setColorPanel:(CPColorPanel)panel
@@ -528,7 +529,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
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];
[_colorPanel setColor:[self colorAtIndex:FLOOR(point.x / 13)] updatePicker:YES];
}
- (void)mouseDragged:(CPEvent)anEvent
@@ -545,10 +546,10 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
_dragColor = [[swatch subviews][0] backgroundColor];
var bounds = CPRectCreateCopy([swatch bounds]);
var bounds = CGRectMakeCopy([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]];
@@ -556,13 +557,13 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
[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)
event: anEvent
pasteboard: nil
source: self
slideBack: YES];
[self dragView:dragView
at:CGPointMake(point.x - bounds.size.width / 2.0, point.y - bounds.size.height / 2.0)
offset:CGPointMake(0.0, 0.0)
event:anEvent
pasteboard:nil
source:self
slideBack:YES];
}
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
@@ -580,7 +581,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
if (![pasteboard availableTypeFromArray:[CPColorDragType]] || location.x > [self bounds].size.width - 1 || location.x < 1)
return NO;
[self setColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] atIndex: FLOOR(location.x / 13)];
[self setColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] atIndex:FLOOR(location.x / 13)];
}
@end
@@ -635,7 +636,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
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]];
@@ -643,13 +644,13 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
[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)
event: anEvent
pasteboard: nil
source: self
slideBack: YES];
[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)
event:anEvent
pasteboard:nil
source:self
slideBack:YES];
}
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
+40 -36
View File
@@ -44,10 +44,11 @@
*/
- (id)initWithPickerMask:(int)aMask colorPanel:(CPColorPanel)aPanel
{
self = [super init];
_panel = aPanel;
_mask = aMask;
if (self = [super init])
{
_panel = aPanel;
_mask = aMask;
}
return self;
}
@@ -76,7 +77,6 @@
*/
- (void)setMode:(CPColorPanelMode)mode
{
return;
}
/*!
@@ -85,7 +85,6 @@
*/
- (void)setColor:(CPColor)aColor
{
return;
}
@end
@@ -110,12 +109,12 @@
- (id)initView
{
aFrame = CPRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
var aFrame = _CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
_pickerView = [[CPView alloc] initWithFrame:aFrame];
[_pickerView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
_brightnessSlider = [[CPSlider alloc] initWithFrame:_CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
[_brightnessSlider setValue:15.0 forThemeAttribute:@"track-width"];
[_brightnessSlider setValue:[CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPColorPicker class]] pathForResource:@"brightness_bar.png"]]] forThemeAttribute:@"track-color"];
@@ -128,9 +127,9 @@
[_brightnessSlider setAction:@selector(brightnessSliderDidChange:)];
[_brightnessSlider setAutoresizingMask:CPViewWidthSizable | CPViewMinYMargin];
_hueSaturationView = [[__CPColorWheel alloc] initWithFrame: CPRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)];
[_hueSaturationView setDelegate: self];
[_hueSaturationView setAutoresizingMask: (CPViewWidthSizable | CPViewHeightSizable)];
_hueSaturationView = [[__CPColorWheel alloc] initWithFrame:_CGRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)];
[_hueSaturationView setDelegate:self];
[_hueSaturationView setAutoresizingMask:(CPViewWidthSizable | CPViewHeightSizable)];
[_pickerView addSubview:_hueSaturationView];
[_pickerView addSubview:_brightnessSlider];
@@ -225,46 +224,49 @@
- (id)initWithFrame:(CPRect)aFrame
{
self = [super initWithFrame:aFrame];
var path = [[CPBundle bundleForClass:CPColorPicker] pathForResource:@"wheel.png"];
_wheelImage = new Image();
_wheelImage.src = path;
_wheelImage.style.position = "absolute";
path = [[CPBundle bundleForClass:CPColorPicker] pathForResource:@"wheel_black.png"];
_blackWheelImage = new Image();
_blackWheelImage.src = path;
_blackWheelImage.style.opacity = "0";
_blackWheelImage.style.filter = "alpha(opacity=0)"
_blackWheelImage.style.position = "absolute";
if (self = [super initWithFrame:aFrame])
{
#if PLATFORM(DOM)
_DOMElement.appendChild(_wheelImage);
_DOMElement.appendChild(_blackWheelImage);
var path = [[CPBundle bundleForClass:CPColorPicker] pathForResource:@"wheel.png"];
_wheelImage = new Image();
_wheelImage.src = path;
_wheelImage.style.position = "absolute";
path = [[CPBundle bundleForClass:CPColorPicker] pathForResource:@"wheel_black.png"];
_blackWheelImage = new Image();
_blackWheelImage.src = path;
_blackWheelImage.style.opacity = "0";
_blackWheelImage.style.filter = "alpha(opacity=0)"
_blackWheelImage.style.position = "absolute";
_DOMElement.appendChild(_wheelImage);
_DOMElement.appendChild(_blackWheelImage);
#endif
[self setWheelSize:aFrame.size];
[self setWheelSize:aFrame.size];
_crosshair = [[CPView alloc] initWithFrame:CPRectMake(_radius - 2, _radius - 2, 4, 4)];
[_crosshair setBackgroundColor:[CPColor blackColor]];
_crosshair = [[CPView alloc] initWithFrame:CGRectMake(_radius - 2, _radius - 2, 4, 4)];
[_crosshair setBackgroundColor:[CPColor blackColor]];
var view = [[CPView alloc] initWithFrame:CGRectInset([_crosshair bounds], 1.0, 1.0)];
[view setBackgroundColor:[CPColor whiteColor]];
var view = [[CPView alloc] initWithFrame:CGRectInset([_crosshair bounds], 1.0, 1.0)];
[view setBackgroundColor:[CPColor whiteColor]];
[_crosshair addSubview:view];
[_crosshair addSubview:view];
[self addSubview:_crosshair];
[self addSubview:_crosshair];
}
return self;
}
- (void)setWheelBrightness:(float)brightness
{
#if PLATFORM(DOM)
_blackWheelImage.style.opacity = 1.0 - brightness;
_blackWheelImage.style.filter = "alpha(opacity=" + (1.0 - brightness) * 100 + ")"
#endif
}
- (void)setFrameSize:(CPSize)aSize
@@ -277,6 +279,7 @@
{
var min = MIN(aSize.width, aSize.height);
#if PLATFORM(DOM)
_blackWheelImage.style.width = min;
_blackWheelImage.style.height = min;
_blackWheelImage.width = min;
@@ -290,6 +293,7 @@
_wheelImage.height = min;
_wheelImage.style.top = (aSize.height - min) / 2.0 + "px";
_wheelImage.style.left = (aSize.width - min) / 2.0 + "px";
#endif
_radius = min / 2.0;
+62
View File
@@ -0,0 +1,62 @@
/*
* CPColorSpace.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2012, SlevenBits Ltd.
*
* 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
*/
var sRGBColorSpace = nil;
/*!
Represent color spaces.
*/
@implementation CPColorSpace : CPObject
{
CGColorSpace _cgColorSpace;
}
/*!
Return an object representing the standard sRGB color space.
*/
+ (CPColorSpace)sRGBColorSpace
{
if (!sRGBColorSpace)
sRGBColorSpace = [[self alloc] initWithCGColorSpace:CGColorSpaceCreateDeviceRGB()];
return sRGBColorSpace;
}
- (id)initWithCGColorSpace:(CGColorSpace)cgColorSpace
{
if (self = [super init])
{
_cgColorSpace = cgColorSpace;
}
return self;
}
/*!
Return a Core Graphics color space representing the receiver.
*/
- (CGColorSpace)CGColorSpace
{
return _cgColorSpace;
}
@end
+155 -78
View File
@@ -43,7 +43,33 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
BOOL _bordered;
CPColor _color;
CPView _wellView;
}
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding == CPValueBinding)
return [CPColorWellValueBinder class];
return [super _binderClassForBinding:theBinding];
}
+ (CPString)defaultThemeClass
{
return @"colorwell";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), [CPNull null], _CGInsetMake(3.0, 3.0, 3.0, 3.0), _CGInsetMakeZero(), [CPNull null]]
forKeys:[@"bezel-inset", @"bezel-color", @"content-inset", @"content-border-inset", @"content-border-color"]];
}
- (void)_reverseSetBinding
{
var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
theBinding = [binderClass getBinding:CPValueBinding forObject:self];
[theBinding reverseSetValueFor:@"color"];
}
- (id)initWithFrame:(CGRect)aFrame
@@ -53,11 +79,8 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
if (self)
{
_active = NO;
_bordered = YES;
_color = [CPColor whiteColor];
[self drawBezelWithHighlight:NO];
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
[self setBordered:YES];
[self _registerForNotifications];
}
@@ -82,25 +105,23 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
object:[CPColorPanel sharedColorPanel]];
}
/*!
Sets whether the color well is bordered.
*/
- (void)setBordered:(BOOL)shouldBeBordered
{
if (shouldBeBordered)
[self setThemeState:CPThemeStateBordered];
else
[self unsetThemeState:CPThemeStateBordered];
}
/*!
Returns whether the color well is bordered
*/
- (BOOL)isBordered
{
return _bordered;
}
/*!
Sets the color well's current color.
*/
- (void)setBordered:(BOOL)bordered
{
if (_bordered == bordered)
return;
_bordered = bordered;
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
return [self hasThemeState:CPThemeStateBordered];
}
// Managing Color From Color Wells
@@ -123,7 +144,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
_color = aColor;
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
[self setNeedsLayout];
}
/*!
@@ -186,31 +207,6 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
return _active;
}
// Drawing a Color Well
- (void)drawBezelWithHighlight:(BOOL)shouldHighlight
{
}
/*!
Draws the colored area inside the color well without borders.
@param aRect the location at which to draw
*/
- (void)drawWellInside:(CGRect)aRect
{
if (!_wellView)
{
_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]];
@@ -229,27 +225,11 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
[self deactivate];
}
- (void)mouseDown:(CPEvent)anEvent
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
{
if (![self isEnabled])
return;
[self highlight:NO];
[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
{
[self drawBezelWithHighlight:NO];
if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]) || ![self isEnabled])
if (!mouseIsUp || !CGRectContainsPoint([self bounds], aPoint) || ![self isEnabled])
return;
[self activate:YES];
@@ -260,6 +240,115 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
[colorPanel orderFront:self];
}
- (CGRect)contentRectForBounds:(CGRect)bounds
{
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
return _CGRectInsetByInset(bounds, contentInset);
}
- (CGRect)bezelRectForBounds:(CGRect)bounds
{
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
return _CGRectInsetByInset(bounds, bezelInset);
}
- (CGRect)contentBorderRectForBounds:(CGRect)bounds
{
var contentBorderInset = [self currentValueForThemeAttribute:@"content-border-inset"];
return _CGRectInsetByInset(bounds, contentBorderInset);
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
{
switch (aName)
{
case "bezel-view":
return [self bezelRectForBounds:[self bounds]];
case "content-view":
return [self contentRectForBounds:[self bounds]];
case "content-border-view":
return [self contentBorderRectForBounds:[self bounds]];
}
return [super rectForEphemeralSubviewNamed:aName];
}
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
- (void)layoutSubviews
{
var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:@"content-view"];
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"bezel-view"];
[contentView setBackgroundColor:_color];
var contentBorderView = [self layoutEphemeralSubviewNamed:@"content-border-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"content-view"];
[contentBorderView setBackgroundColor:[self currentValueForThemeAttribute:@"content-border-color"]];
}
@end
@implementation CPColorWellValueBinder : CPBinder
{
}
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
var placeholderColor = [CPColor blueColor];
[self _setPlaceholder:placeholderColor forMarker:CPMultipleValuesMarker isDefault:YES];
[self _setPlaceholder:placeholderColor forMarker:CPNoSelectionMarker isDefault:YES];
[self _setPlaceholder:placeholderColor forMarker:CPNotApplicableMarker isDefault:YES];
[self _setPlaceholder:placeholderColor forMarker:CPNullMarker isDefault:YES];
}
- (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)
{
if (newValue === CPNotApplicableMarker && [options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
{
[CPException raise:CPGenericException
reason:@"can't transform non applicable key on: " + _source + " value: " + newValue];
}
newValue = [self _placeholderForMarker:newValue];
}
else
{
newValue = [self transformValue:newValue withOptions:options];
}
[_source setColor:newValue];
}
@end
var CPColorWellColorKey = "CPColorWellColorKey",
@@ -278,11 +367,8 @@ var CPColorWellColorKey = "CPColorWellColorKey",
if (self)
{
_active = NO;
_bordered = [aCoder decodeBoolForKey:CPColorWellBorderedKey];
_color = [aCoder decodeObjectForKey:CPColorWellColorKey];
[self drawBezelWithHighlight:NO];
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
[self setBordered:[aCoder decodeBoolForKey:CPColorWellBorderedKey]];
[self _registerForNotifications];
}
@@ -296,19 +382,10 @@ var CPColorWellColorKey = "CPColorWellColorKey",
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
// 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];
[aCoder encodeObject:[self isBordered] forKey:CPColorWellBorderedKey];
}
@end
+1192
View File
File diff suppressed because it is too large Load Diff
+28
View File
@@ -67,6 +67,13 @@ CPHTML5DragAndDropSourceYOffBy1 = 1 << 26;
CPSOPDisabledFromFileURLs = 1 << 27;
// element.style.font can be set for an element not in the DOM.
CPInputSetFontOutsideOfDOM = 1 << 28;
// Input elements have 1 px of extra padding on the left regardless of padding setting.
CPInput1PxLeftPadding = 1 << 29;
CPInputOnInputEventFeature = 1 << 30;
var USER_AGENT = "",
PLATFORM_ENGINE = CPUnknownBrowserEngine,
PLATFORM_FEATURES = 0;
@@ -74,6 +81,7 @@ var USER_AGENT = "",
// default these features to true
PLATFORM_FEATURES |= CPInputTypeCanBeChangedFeature;
PLATFORM_FEATURES |= CPInputSetFontOutsideOfDOM;
if (typeof window !== "undefined" && typeof window.navigator !== "undefined")
USER_AGENT = window.navigator.userAgent;
@@ -99,6 +107,9 @@ else if (typeof window !== "undefined" && window.attachEvent) // Must follow Ope
PLATFORM_FEATURES |= CPOpacityRequiresFilterFeature;
PLATFORM_FEATURES &= ~CPInputTypeCanBeChangedFeature;
// Tested in Internet Explore 8 and 9.
PLATFORM_FEATURES &= ~CPInputSetFontOutsideOfDOM;
}
// WebKit
@@ -135,6 +146,10 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
if (majorVersion < 532 || (majorVersion === 532 && minorVersion < 6))
PLATFORM_FEATURES |= CPHTML5DragAndDropSourceYOffBy1;
// This is supposedly fixed in webkit r123603. Seems to work in Chrome 21 but not Safari 6.0.
if (majorVersion < 537)
PLATFORM_FEATURES |= CPInput1PxLeftPadding;
if (USER_AGENT.indexOf("Chrome") === CPNotFound)
PLATFORM_FEATURES |= CPSOPDisabledFromFileURLs;
}
@@ -160,6 +175,9 @@ else if (USER_AGENT.indexOf("Gecko") !== -1) // Must follow KHTML check.
if (version < 3.0)
PLATFORM_FEATURES |= CPJavaScriptMouseWheelValues_8_15;
// Some day this might be fixed and should be version prefixed. No known fixed version yet.
PLATFORM_FEATURES |= CPInput1PxLeftPadding;
}
// Feature Specific Checks
@@ -185,6 +203,16 @@ if (typeof document != "undefined")
PLATFORM_FEATURES |= CPJavaScriptInnerTextFeature;
else if (DOMElement.textContent != undefined)
PLATFORM_FEATURES |= CPJavaScriptTextContentFeature;
var DOMInputElement = document.createElement("input");
if ("oninput" in DOMInputElement)
PLATFORM_FEATURES |= CPInputOnInputEventFeature;
else if (typeof DOMInputElement.setAttribute === "function")
{
DOMInputElement.setAttribute("oninput", "return;");
if (typeof DOMInputElement.oninput === "function")
PLATFORM_FEATURES |= CPInputOnInputEventFeature;
}
}
function CPFeatureIsCompatible(aFeature)
+72 -58
View File
@@ -28,42 +28,48 @@
@import "CPView.j"
@import "CPKeyValueBinding.j"
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
CPCenterTextAlignment = 2;
CPJustifiedTextAlignment = 3;
CPNaturalTextAlignment = 4;
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
CPCenterTextAlignment = 2;
CPJustifiedTextAlignment = 3;
CPNaturalTextAlignment = 4;
CPRegularControlSize = 0;
CPSmallControlSize = 1;
CPMiniControlSize = 2;
CPRegularControlSize = 0;
CPSmallControlSize = 1;
CPMiniControlSize = 2;
CPLineBreakByWordWrapping = 0;
CPLineBreakByCharWrapping = 1;
CPLineBreakByClipping = 2;
CPLineBreakByTruncatingHead = 3;
CPLineBreakByTruncatingTail = 4;
CPLineBreakByTruncatingMiddle = 5;
CPLineBreakByWordWrapping = 0;
CPLineBreakByCharWrapping = 1;
CPLineBreakByClipping = 2;
CPLineBreakByTruncatingHead = 3;
CPLineBreakByTruncatingTail = 4;
CPLineBreakByTruncatingMiddle = 5;
CPTopVerticalTextAlignment = 1;
CPCenterVerticalTextAlignment = 2;
CPBottomVerticalTextAlignment = 3;
CPTopVerticalTextAlignment = 1;
CPCenterVerticalTextAlignment = 2;
CPBottomVerticalTextAlignment = 3;
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
// Deprecated for use with images, use the CPImageScale constants
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
CPImageRight = 3;
CPImageBelow = 4;
CPImageAbove = 5;
CPImageOverlaps = 6;
CPImageScaleProportionallyDown = 0;
CPImageScaleAxesIndependently = 1;
CPImageScaleNone = 2;
CPImageScaleProportionallyUpOrDown = 3;
CPOnState = 1;
CPOffState = 0;
CPMixedState = -1;
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
CPImageRight = 3;
CPImageBelow = 4;
CPImageAbove = 5;
CPImageOverlaps = 6;
CPOnState = 1;
CPOffState = 0;
CPMixedState = -1;
CPControlNormalBackgroundColor = "CPControlNormalBackgroundColor";
CPControlSelectedBackgroundColor = "CPControlSelectedBackgroundColor";
@@ -106,7 +112,7 @@ var CPControlBlackColor = [CPColor blackColor];
CPTopVerticalTextAlignment,
CPLineBreakByClipping,
[CPColor blackColor],
[CPFont systemFontOfSize:12.0],
[CPFont systemFontOfSize:CPFontCurrentSystemSize],
[CPNull null],
_CGSizeMakeZero(),
CPImageLeft,
@@ -128,18 +134,18 @@ var CPControlBlackColor = [CPColor blackColor];
+ (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"];
if (self !== [CPControl class])
return;
[self exposeBinding:@"enabled"];
}
[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
@@ -385,7 +391,10 @@ var CPControlBlackColor = [CPColor blackColor];
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
{
[self highlight:NO];
if (mouseIsUp)
[self highlight:NO];
else
[self highlight:YES];
}
- (void)mouseDown:(CPEvent)anEvent
@@ -507,7 +516,7 @@ var CPControlBlackColor = [CPColor blackColor];
*/
- (CPString)stringValue
{
if (_formatter && _value !== undefined && _value !== nil)
if (_formatter && _value !== undefined)
{
var formattedValue = [self hasThemeState:CPThemeStateEditing] ? [_formatter editingStringForObjectValue:_value] : [_formatter stringForObjectValue:_value];
@@ -526,7 +535,7 @@ var CPControlBlackColor = [CPColor blackColor];
// Cocoa raises an invalid parameter assertion and returns if you pass nil.
if (aString === nil || aString === undefined)
{
CPLog.warn("nil sent to CPControl -setStringValue");
CPLog.warn("nil or undefined sent to CPControl -setStringValue");
return;
}
@@ -784,9 +793,10 @@ var CPControlBlackColor = [CPColor blackColor];
Sets the image scaling of the control.
<pre>
CPScaleProportionally
CPScaleToFit
CPScaleNone
CPImageScaleProportionallyDown
CPImageScaleAxesIndependently
CPImageScaleNone
CPImageScaleProportionallyUpOrDown
</pre>
*/
- (void)setImageScaling:(CPImageScaling)scaling
@@ -857,17 +867,16 @@ var CPControlBlackColor = [CPColor blackColor];
@end
var CPControlValueKey = "CPControlValueKey",
CPControlControlStateKey = @"CPControlControlStateKey",
CPControlIsEnabledKey = "CPControlIsEnabledKey",
var CPControlValueKey = @"CPControlValueKey",
CPControlControlStateKey = @"CPControlControlStateKey",
CPControlIsEnabledKey = @"CPControlIsEnabledKey",
CPControlTargetKey = @"CPControlTargetKey",
CPControlActionKey = @"CPControlActionKey",
CPControlSendActionOnKey = @"CPControlSendActionOnKey",
CPControlFormatterKey = @"CPControlFormatterKey",
CPControlSendsActionOnEndEditingKey = @"CPControlSendsActionOnEndEditingKey",
CPControlTargetKey = "CPControlTargetKey",
CPControlActionKey = "CPControlActionKey",
CPControlSendActionOnKey = "CPControlSendActionOnKey",
CPControlSendsActionOnEndEditingKey = "CPControlSendsActionOnEndEditingKey";
var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
__Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
@implementation CPControl (CPCoding)
@@ -890,6 +899,8 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
[self sendActionOn:[aCoder decodeIntForKey:CPControlSendActionOnKey]];
[self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
[self setFormatter:[aCoder decodeObjectForKey:CPControlFormatterKey]];
}
return self;
@@ -919,6 +930,9 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
[aCoder encodeObject:_action forKey:CPControlActionKey];
[aCoder encodeInt:_sendActionOn forKey:CPControlSendActionOnKey];
if (_formatter !== nil)
[aCoder encodeObject:_formatter forKey:CPControlFormatterKey];
}
@end
+6 -2
View File
@@ -111,8 +111,12 @@
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);
while (c.charAt(0) == ' ')
c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0)
return c.substring(nameEQ.length, c.length);
}
#endif
return "";
+2 -2
View File
@@ -922,9 +922,9 @@ var CPDocumentUntitledCount = 0;
var _CPReadSessionMake = function(aType, aDelegate, aDidReadSelector, aContextInfo)
{
return { fileType:aType, delegate:aDelegate, didReadSelector:aDidReadSelector, contextInfo:aContextInfo };
}
};
var _CPSaveSessionMake = function(anAbsoluteURL, aSaveOperation, aChangeCount, aDelegate, aDidSaveSelector, aContextInfo, aConnection)
{
return { absoluteURL:anAbsoluteURL, saveOperation:aSaveOperation, changeCount:aChangeCount, delegate:aDelegate, didSaveSelector:aDidSaveSelector, contextInfo:aContextInfo, connection:aConnection };
}
};
+47 -3
View File
@@ -179,7 +179,8 @@ CPDOMEventTouchCancel = "touchcancel";
var _CPEventPeriodicEventPeriod = 0,
_CPEventPeriodicEventTimer = nil,
_CPEventUpperCaseRegex = new RegExp("[A-Z]");
_CPEventUpperCaseRegex = new RegExp("[A-Z]"),
_CPEventStartupMilliseconds = new Date().getTime();
/*!
@ingroup appkit
@@ -203,12 +204,22 @@ var _CPEventPeriodicEventPeriod = 0,
BOOL _isARepeat;
unsigned _keyCode;
DOMEvent _DOMEvent;
int _data1;
int _data2;
float _deltaX;
float _deltaY;
float _deltaZ;
}
/*!
Returns the current time in fractional seconds since startup.
*/
+ (CPTimeInterval)currentTimestamp
{
return (new Date().getTime() - _CPEventStartupMilliseconds) / 1000;
}
/*!
Creates a new keyboard event.
@@ -389,7 +400,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns the time the event occurred.
Returns the time the event occurred in seconds since startup.
*/
- (CPTimeInterval)timestamp
{
@@ -508,6 +519,16 @@ var _CPEventPeriodicEventPeriod = 0,
return _DOMEvent;
}
- (int)data1
{
return _data1;
}
- (int)data2
{
return _data2;
}
// Getting Scroll Wheel Event Information
/*!
Returns the change in the x-axis for a mouse event.
@@ -621,11 +642,34 @@ var _CPEventPeriodicEventPeriod = 0,
_CPEventPeriodicEventTimer = nil;
}
- (CPString)description
{
switch (_type)
{
case CPKeyDown:
case CPKeyUp:
case CPFlagsChanged:
return [CPString stringWithFormat:@"CPEvent: type=%d loc=%@ time=%.1f flags=0x%X win=%@ winNum=%d ctxt=%@ chars=\"%@\" unmodchars=\"%@\" repeat=%d keyCode=%d", _type, CPStringFromPoint(_location), _timestamp, _modifierFlags, _window, _windowNumber, _context, _characters, _charactersIgnoringModifiers, _isARepeat, _keyCode];
case CPLeftMouseDown:
case CPLeftMouseUp:
case CPRightMouseDown:
case CPRightMouseUp:
case CPMouseMoved:
case CPLeftMouseDragged:
case CPRightMouseDragged:
case CPMouseEntered:
case CPMouseExited:
return [CPString stringWithFormat:@"CPEvent: type=%d loc=%@ time=%.1f flags=0x%X win=%@ winNum=%d ctxt=%@ evNum=%d click=%d buttonNumber=%d pressure=%f", _type, CPStringFromPoint(_location), _timestamp, _modifierFlags, _window, _windowNumber, _context, _eventNumber, _clickCount, [self buttonNumber], _pressure];
default:
return [CPString stringWithFormat:@"CPEvent: type=%d loc=%@ time=%.1f flags=0x%X win=%@ winNum=%d ctxt=%@ subtype=%d data1=%d data2=%d", _type, CPStringFromPoint(_location), _timestamp, _modifierFlags, _window, _windowNumber, _context, _subtype, _data1, _data2];
}
}
@end
function _CPEventFirePeriodEvent()
{
[CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:_CGPointMakeZero() modifierFlags:0 timestamp:0 windowNumber:0 context:nil subtype:0 data1:0 data2:0]];
[CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:_CGPointMakeZero() modifierFlags:0 timestamp:[CPEvent currentTimestamp] windowNumber:0 context:nil subtype:0 data1:0 data2:0]];
}
var CPEventClass = [CPEvent class];
+5 -5
View File
@@ -104,10 +104,10 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
- (void)setFlashVars:(CPDictionary)aDictionary
{
var varString = @"",
enumerator = [aDictionary keyEnumerator];
enumerator = [aDictionary keyEnumerator],
key;
var key;
while (key = [enumerator nextObject])
while ((key = [enumerator nextObject]) !== nil)
varString = [varString stringByAppendingFormat:@"&%@=%@", key, [aDictionary objectForKey:key]];
if (!_params)
@@ -146,7 +146,7 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
var enumerator = [_params keyEnumerator],
key;
while (_DOMObjectElement && (key = [enumerator nextObject]))
while (_DOMObjectElement && (key = [enumerator nextObject]) !== nil)
{
var param = document.createElement(@"param");
param.name = key;
@@ -178,7 +178,7 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
paramEnumerator = [_params keyEnumerator],
key;
while (key = [paramEnumerator nextObject])
while ((key = [paramEnumerator nextObject]) !== nil)
paramString = [paramString stringByAppendingFormat:@"<param name='%@' value='%@' />", key, [_params objectForKey:key]];
_DOMObjectElement = document.createElement(@"object");
+175 -72
View File
@@ -28,46 +28,85 @@
CPFontDefaultSystemFontFace = @"Arial, sans-serif";
CPFontDefaultSystemFontSize = 12;
var _CPFonts = {},
_CPFontSystemFontFace = CPFontDefaultSystemFontFace,
_CPFontSystemFontSize = 12,
_CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "),
_CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g");
/*!
To create a font of a size that will dynamically reflect the current
system font size, use this for the size argument.
*/
CPFontCurrentSystemSize = -1;
// For internal use only by this class and subclasses
_CPFontSystemFacePlaceholder = "_CPFontSystemFacePlaceholder";
var _CPFontCache = {},
_CPSystemFontCache = {},
_CPFontSystemFontFace = CPFontDefaultSystemFontFace,
_CPFontSystemFontSize = 12,
_CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "),
_CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g");
#define _CPRealFontSize(aSize) (aSize <= 0 ? _CPFontSystemFontSize : aSize)
#define _CPFontNormalizedNames(aName) _CPFontNormalizedNameArray(aName).join(", ")
#define _CPCachedFont(aName, aSize, isBold, isItalic) _CPFonts[_CPFontCreateCSSString(_CPFontNormalizedNames(aName), aSize, isBold, isItalic)]
#define _CPCachedFont(aName, aSize, isBold, isItalic) _CPFontCache[_CPFontCreateCSSString(_CPFontNormalizedNames(aName), aSize, isBold, isItalic)]
#define _CPUserFont(aName, aSize, isBold, isItalic) _CPCachedFont(aName, aSize, isBold, isItalic) || [[CPFont alloc] _initWithName:aName size:aSize bold:isBold italic:isItalic system:NO]
#define _CPSystemFontCacheKey(aSize, isBold) (String(aSize) + (isBold ? "b" : ""))
#define _CPCachedSystemFont(aSize, isBold) _CPSystemFontCache[_CPSystemFontCacheKey(aSize, isBold)]
#define _CPSystemFont(aSize, isBold) (_CPCachedSystemFont(aSize, isBold) || [[CPFont alloc] _initWithName:_CPFontSystemFacePlaceholder size:aSize bold:isBold italic:NO system:YES])
/*!
@ingroup appkit
@class CPFont
@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:
### System fonts
When you create a font using \c -systemFontOfSize: or \c -boldSystemFontOfSize:, a proxy font is
created that always refers to the current system font face and size. By default the system
font face/size is Arial 12px, with a fallback to sans-serif 12px. 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.
- By sending [CPFont setSystemFontFace:<face>] and/or [CPFont setSystemFontSize:<size>].
Note that if you change the system font face or size during runtime, the next time
any view using a system font is redrawn, it will show the new font.
- 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.
Note that in either case, you can specify a comma-delimited list of fonts as the font face.
Do not quote enclose font faces that contain spaces, that is done automatically when a CSS
representation of a font is requested.
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:
The browser will use the first available font in the list you supply. CPFont always ensures
that Arial and sans-serif are in the CSS representation of a font as a fallback, so there is
no need to add them to the end of your font list.
@code
### nib2cib conversion
Fonts are converted by nib2cib according to the following algorithm:
- If the font family is Lucida Grande, then a system font will be created.
- If the font is Lucida Grande 13 (plain), the "default" font will be used at runtime.
The default font is taken from the "font" theme attribute if one exists,
otherwise from the current system font face and size.
- Lucida Grande of any size other than 13 will retain its size.
- Fonts using any family other than Lucida Grande will be used as is, including the size.
### Using custom web fonts
The configurability of CPFont makes it easy to use a custom web font as the system font.
For example, if you want to use the google font Asap as the system font, you would do the
following:
- Add a <link> to the <head> of index-debug.html and index.html:
@code
<link href='http://fonts.googleapis.com/css?family=Asap:400,700' rel='stylesheet' type='text/css'>
@endcode
- Specify Asap as the system font in Info.plist by adding the following item:
@code
<key>CPSystemFontFace</key>
<string>Lucida Grande</string>
@endcode
<string>Asap</string>
@endcode
*/
@implementation CPFont : CPObject
{
@@ -78,19 +117,23 @@ var _CPFonts = {},
float _lineHeight;
BOOL _isBold @accessors(readonly, getter=isBold);
BOOL _isItalic @accessors(readonly, getter=isItalic);
BOOL _isSystem @accessors(readonly, getter=isSystem);
CPString _cssString;
}
+ (void)initialize
{
if (self !== [CPFont class])
return;
var systemFontFace = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPSystemFontFace"];
if (!systemFontFace)
systemFontFace = [[CPBundle bundleForClass:[CPView class]] objectForInfoDictionaryKey:@"CPSystemFontFace"];
if (systemFontFace)
[self setSystemFontFace:systemFontFace];
_CPFontSystemFontFace = _CPFontNormalizedNames(systemFontFace);
var systemFontSize = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPSystemFontSize"];
@@ -114,7 +157,13 @@ var _CPFonts = {},
*/
+ (CPString)setSystemFontFace:(CPString)aFace
{
_CPFontSystemFontFace = _CPFontNormalizedNames(aFace);
var normalizedFaces = _CPFontNormalizedNames(aFace);
if (normalizedFaces === _CPFontSystemFontFace)
return;
[self _invalidateSystemFontCache]
_CPFontSystemFontFace = aFace;
}
/*!
@@ -130,101 +179,136 @@ var _CPFonts = {},
*/
+ (float)setSystemFontSize:(float)size
{
if (size > 0)
if (size > 0 && size !== _CPFontSystemFontSize)
{
[self _invalidateSystemFontCache];
_CPFontSystemFontSize = size;
}
}
+ (void)_invalidateSystemFontCache
{
var systemSize = String(_CPFontSystemFontSize),
currentSize = String(CPFontCurrentSystemSize);
for (key in _CPSystemFontCache)
{
if (_CPSystemFontCache.hasOwnProperty(key) &&
(key.indexOf(systemSize) === 0 || key.indexOf(currentSize) === 0))
{
delete _CPSystemFontCache[key];
}
}
}
/*!
Returns a font with the specified name and size.
@param aName the name of the font
@param aSize the size of the font (in px)
@param aSize the size of the font (in px). 0 or negative will create a font
in the current system font size.
@return the requested font
*/
+ (CPFont)fontWithName:(CPString)aName size:(float)aSize
{
return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO italic:NO];
return _CPUserFont(aName, aSize <= 0 ? _CPFontSystemFontSize : aSize, NO, 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 aSize the size of the font (in px). 0 or negative will create a font
in the current system font size.
@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];
return _CPUserFont(aName, aSize <= 0 ? _CPFontSystemFontSize : aSize, NO, 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 px)
@param aSize the size of the font (in px). 0 or negative will create a font
in the current system font size.
@return the requested bold font
*/
+ (CPFont)boldFontWithName:(CPString)aName size:(float)aSize
{
return _CPCachedFont(aName, aSize, YES, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES italic:NO];
return _CPUserFont(aName, aSize <= 0 ? _CPFontSystemFontSize : aSize, YES, 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 aSize the size of the font (in px). 0 or negative will create a font
in the current system font size.
@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];
return _CPUserFont(aName, aSize <= 0 ? _CPFontSystemFontSize : aSize, YES, italic);
}
/*!
Internal font getter like fontWithName:size:italic: with a bold selector.
*/
+ (CPFont)_fontWithName:(CPString)aName size:(float)aSize bold:(BOOL)bold italic:(BOOL)italic
{
return _CPUserFont(aName, aSize <= 0 ? _CPFontSystemFontSize : aSize, bold, italic);
}
/*!
Returns the system font scaled to the specified size
@param aSize the size of the font (in px)
@param aSize the size of the font (in px). 0 creates a static font
in the current system font size. Negative creates a font
that dynamically tracks the current system font size.
@return the requested system font
*/
+ (CPFont)systemFontOfSize:(CPSize)aSize
{
return _CPCachedFont(_CPFontSystemFontFace, aSize, NO, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:NO italic:NO];
return _CPSystemFont(aSize === 0 ? _CPFontSystemFontSize : aSize, NO);
}
/*!
Returns the bold system font scaled to the specified size
@param aSize the size of the font (in px)
@param aSize the size of the font (in px). 0 creates a static font
in the current system font size. Negative creates a font
that dynamically tracks the current system font size.
@return the requested bold system font
*/
+ (CPFont)boldSystemFontOfSize:(CPSize)aSize
{
return _CPCachedFont(_CPFontSystemFontFace, aSize, YES, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:YES italic:NO];
return _CPSystemFont(aSize === 0 ? _CPFontSystemFontSize : aSize, YES);
}
/* 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
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold italic:(BOOL)isItalic system:(BOOL)isSystem
{
self = [super init];
if (self)
{
_name = _CPFontNormalizedNames(aName);
_size = aSize;
_ascender = 0;
_descender = 0;
_lineHeight = 0;
_isBold = isBold;
_isItalic = isItalic;
_isSystem = isSystem;
_cssString = _CPFontCreateCSSString(_name, _size, _isBold, _isItalic);
_CPFonts[_cssString] = self;
if (isSystem)
{
_name = aName;
_cssString = _CPFontCreateCSSString(_CPFontSystemFontFace, _size, _isBold, _isItalic);
_CPSystemFontCache[_CPSystemFontCacheKey(_size, _isBold)] = self;
}
else
{
_name = _CPFontNormalizedNames(aName);
_cssString = _CPFontCreateCSSString(_name, _size, _isBold, _isItalic);
_CPFontCache[_cssString] = self;
}
}
return self;
@@ -235,10 +319,12 @@ var _CPFonts = {},
*/
- (float)ascender
{
if (!_ascender)
[self _getMetrics];
var font = _isSystem ? _CPSystemFont(_size, _isBold) : self;
return _ascender;
if (!font._ascender)
[font _getMetrics];
return font._ascender;
}
/*!
@@ -247,10 +333,12 @@ var _CPFonts = {},
*/
- (float)descender
{
if (!_descender)
[self _getMetrics];
var font = _isSystem ? _CPSystemFont(_size, _isBold) : self;
return _descender;
if (!font._descender)
[font _getMetrics];
return font._descender;
}
/*!
@@ -260,10 +348,12 @@ var _CPFonts = {},
*/
- (float)defaultLineHeightForFont
{
if (!_lineHeight)
[self _getMetrics];
var font = _isSystem ? _CPSystemFont(_size, _isBold) : self;
return _lineHeight;
if (!font._lineHeight)
[font _getMetrics];
return font._lineHeight;
}
/*!
@@ -271,7 +361,7 @@ var _CPFonts = {},
*/
- (float)size
{
return _size;
return _CPRealFontSize(_size);
}
/*!
@@ -279,7 +369,9 @@ var _CPFonts = {},
*/
- (CPString)cssString
{
return _cssString;
var font = _isSystem ? _CPSystemFont(_size, _isBold) : self;
return font._cssString;
}
/*!
@@ -287,9 +379,17 @@ var _CPFonts = {},
*/
- (CPString)familyName
{
if (_isSystem)
return _CPFontSystemFontFace;
return _name;
}
- (BOOL)isSystemSize
{
return _size <= 0;
}
- (BOOL)isEqual:(id)anObject
{
return [anObject isKindOfClass:[CPFont class]] && [anObject cssString] === _cssString;
@@ -302,7 +402,7 @@ var _CPFonts = {},
- (id)copy
{
return [[CPFont alloc] _initWithName:_name size:_size bold:_isBold italic:_isItalic];
return [[CPFont alloc] _initWithName:_name size:_size bold:_isBold italic:_isItalic system:_isSystem];
}
- (void)_getMetrics
@@ -319,7 +419,8 @@ var _CPFonts = {},
var CPFontNameKey = @"CPFontNameKey",
CPFontSizeKey = @"CPFontSizeKey",
CPFontIsBoldKey = @"CPFontIsBoldKey",
CPFontIsItalicKey = @"CPFontIsItalicKey";
CPFontIsItalicKey = @"CPFontIsItalicKey",
CPFontIsSystemKey = @"CPFontIsSystemKey";
@implementation CPFont (CPCoding)
@@ -333,9 +434,10 @@ var CPFontNameKey = @"CPFontNameKey",
var fontName = [aCoder decodeObjectForKey:CPFontNameKey],
size = [aCoder decodeFloatForKey:CPFontSizeKey],
isBold = [aCoder decodeBoolForKey:CPFontIsBoldKey],
isItalic = [aCoder decodeBoolForKey:CPFontIsItalicKey];
isItalic = [aCoder decodeBoolForKey:CPFontIsItalicKey],
isSystem = [aCoder decodeBoolForKey:CPFontIsSystemKey];
return [self _initWithName:fontName size:size bold:isBold italic:isItalic];
return [self _initWithName:fontName size:size bold:isBold italic:isItalic system:isSystem];
}
/*!
@@ -348,6 +450,7 @@ var CPFontNameKey = @"CPFontNameKey",
[aCoder encodeFloat:_size forKey:CPFontSizeKey];
[aCoder encodeBool:_isBold forKey:CPFontIsBoldKey];
[aCoder encodeBool:_isItalic forKey:CPFontIsItalicKey];
[aCoder encodeBool:_isSystem forKey:CPFontIsSystemKey];
}
@end
@@ -356,7 +459,7 @@ var CPFontNameKey = @"CPFontNameKey",
// aName must be normalized
var _CPFontCreateCSSString = function(aName, aSize, isBold, isItalic)
{
var properties = (isItalic ? "italic " : "") + (isBold ? "bold " : "") + aSize + "px ";
var properties = (isItalic ? "italic " : "") + (isBold ? "bold " : "") + _CPRealFontSize(aSize) + "px ";
return properties + _CPFontConcatNameWithFallback(aName);
};
+148 -30
View File
@@ -24,6 +24,19 @@
@import "CPFont.j"
CPItalicFontMask = 1 << 0;
CPBoldFontMask = 1 << 1;
CPUnboldFontMask = 1 << 2;
CPNonStandardCharacterSetFontMask = 1 << 3;
CPNarrowFontMask = 1 << 4;
CPExpandedFontMask = 1 << 5;
CPCondensedFontMask = 1 << 6;
CPSmallCapsFontMask = 1 << 7;
CPPosterFontMask = 1 << 8;
CPCompressedFontMask = 1 << 9;
CPFixedPitchFontMask = 1 << 10;
CPUnitalicFontMask = 1 << 24;
var CPSharedFontManager = nil,
CPFontManagerFactory = Nil;
@@ -33,7 +46,17 @@ var CPSharedFontManager = nil,
*/
@implementation CPFontManager : CPObject
{
CPArray _availableFonts;
CPArray _availableFonts;
id _target @accessors(property=target);
SEL _action @accessors(property=action);
id _delegate @accessors(property=delegate);
CPFont _selectedFont;
BOOL _multiple @accessors;
CPDictionary _activeChange;
}
// Getting the Shared Font Manager
@@ -59,6 +82,16 @@ var CPSharedFontManager = nil,
CPFontManagerFactory = aClass;
}
- (id)init
{
if (self = [super init])
{
_action = @selector(changeFont:);
}
return self;
}
/*!
Returns an array of the available fonts
*/
@@ -97,43 +130,128 @@ var CPSharedFontManager = nil,
return _CPFontDetectFontAvailable(aFontName);
}
- (void)setSelectedFont:(CPFont)aFont isMultiple:(BOOL)aFlag
{
_selectedFont = aFont;
_isMultiple = aFlag;
// TODO Notify CPFontPanel when it exists.
}
- (CPFont)selectedFont
{
return _selectedFont;
}
- (BOOL)isMultiple
{
return _isMultiple;
}
- (int)weightOfFont:(CPFont)aFont
{
// TODO Weight 5 is a normal of book weight and 9 and above is bold, but it would be nice to be more
// precise than that.
return [aFont isBold] ? 9 : 5;
}
- (CPFontTraitMask)traitsOfFont:(CPFont)aFont
{
return ([aFont isBold] ? CPBoldFontMask : 0) | ([aFont isItalic] ? CPItalicFontMask : 0);
}
- (CPFont)convertFont:(CPFont)aFont
{
if (!_activeChange)
return aFont;
var addTraits = [_activeChange valueForKey:@"addTraits"];
if (addTraits)
aFont = [self convertFont:aFont toHaveTrait:addTraits];
return aFont;
}
- (CPFont)convertFont:(CPFont)aFont toHaveTrait:(CPFontTraitMask)addTraits
{
if (!aFont)
return nil;
var shouldBeBold = ([aFont isBold] || (addTraits & CPBoldFontMask)) && !(addTraits & CPUnboldFontMask),
shouldBeItalic = ([aFont isItalic] || (addTraits & CPItalicFontMask)) && !(addTraits & CPUnitalicFontMask),
shouldBeSize = [aFont size];
// XXX On the current platform there will always be a bold/italic version of each font, but still leave
// || aFont in here for future platforms.
aFont = [CPFont _fontWithName:[aFont familyName] size:shouldBeSize bold:shouldBeBold italic:shouldBeItalic] || aFont;
return aFont;
}
- (CPFont)convertFont:(CPFont)aFont toFace:(CPString)aTypeface
{
if (!aFont)
return nil;
var shouldBeBold = [aFont isBold],
shouldBeItalic = [aFont isItalic],
shouldBeSize = [aFont size];
aFont = [CPFont _fontWithName:aTypeface size:shouldBeSize bold:shouldBeBold italic:shouldBeItalic] || aFont;
return aFont;
}
- (@action)addFontTrait:(id)sender
{
_activeChange = [CPDictionary dictionaryWithObject:[sender tag] forKey:@"addTraits"];
[self sendAction];
}
- (BOOL)sendAction
{
return [CPApp sendAction:_action to:_target from:self];
}
@end
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",*/
/* "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",*/
"Big Caslon","Bitstream Vera Sans","Bitstream Vera Sans Mono","Bitstream Vera Serif",
/* "Blackadder ITC","Blackletter686 BT","Bodoni MT","Bodoni MT Black","Bodoni MT Condensed","Bodoni MT Poster Compressed","Book Antiqua","Bookman","Bookman Old Style","Bradley Hand ITC","Braggadocio","Britannic Bold","Broadway","Broadway BT",*/
/* "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",*/
"Big Caslon", "Bitstream Vera Sans", "Bitstream Vera Sans Mono", "Bitstream Vera Serif",
/* "Blackadder ITC", "Blackletter686 BT", "Bodoni MT", "Bodoni MT Black", "Bodoni MT Condensed", "Bodoni MT Poster Compressed", "Book Antiqua", "Bookman", "Bookman Old Style", "Bradley Hand ITC", "Braggadocio", "Britannic Bold", "Broadway", "Broadway BT",*/
"Brush Script MT",
/* "BudHand","CAMPBELL","Calibri","Californian FB","Calisto MT","Calligraph421 BT",*/
/* "BudHand", "CAMPBELL", "Calibri", "Californian FB", "Calisto MT", "Calligraph421 BT",*/
"Cambria",
/* "Candara","Capitals",*/
"Caslon","Castellar","Cataneo BT","Centaur","Century Gothic","Century Schoolbook","Century Schoolbook L",
/* "Champignon","Charcoal","Charter","Charter BT","Chicago","Chick","Chiller","ClearlyU","Colonna MT",*/
"Comic Sans", "Comic Sans MS","Consolas","Constantia","Cooper Black","Copperplate","Copperplate Gothic Bold","Copperplate Gothic Light","Corbel","Courier","Courier New",
/* "Croobie","Curlz MT","Desdemona","Didot","DomBold BT","Edwardian Script ITC","Engravers MT","Eras Bold ITC","Eras Demi ITC","Eras Light ITC","Eras Medium ITC","Eurostile","FIRSTHOME","Fat","Felix Titling","Fine Hand","Fixed","Footlight MT Light","Forte","Franklin Gothic Book","Franklin Gothic Demi","Franklin Gothic Demi Cond","Franklin Gothic Heavy","Franklin Gothic Medium","Franklin Gothic Medium Cond","Freestyle Script","French Script MT","Freshbot","Frosty",*/
/* "Candara", "Capitals",*/
"Caslon", "Castellar", "Cataneo BT", "Centaur", "Century Gothic", "Century Schoolbook", "Century Schoolbook L",
/* "Champignon", "Charcoal", "Charter", "Charter BT", "Chicago", "Chick", "Chiller", "ClearlyU", "Colonna MT",*/
"Comic Sans", "Comic Sans MS", "Consolas", "Constantia", "Cooper Black", "Copperplate", "Copperplate Gothic Bold", "Copperplate Gothic Light", "Corbel", "Courier", "Courier New",
/* "Croobie", "Curlz MT", "Desdemona", "Didot", "DomBold BT", "Edwardian Script ITC", "Engravers MT", "Eras Bold ITC", "Eras Demi ITC", "Eras Light ITC", "Eras Medium ITC", "Eurostile", "FIRSTHOME", "Fat", "Felix Titling", "Fine Hand", "Fixed", "Footlight MT Light", "Forte", "Franklin Gothic Book", "Franklin Gothic Demi", "Franklin Gothic Demi Cond", "Franklin Gothic Heavy", "Franklin Gothic Medium", "Franklin Gothic Medium Cond", "Freestyle Script", "French Script MT", "Freshbot", "Frosty",*/
"Futura",
/* "GENUINE","Gadget","Garamond",*/
"Geneva","Georgia","Georgia Ref", "Geeza Pro", "Gigi","Gill Sans","Gill Sans MT","Gill Sans MT Condensed","Gill Sans MT Ext Condensed Bold","Gill Sans Ultra Bold","Gill Sans Ultra Bold Condensed",
/* "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", */
/* "GENUINE", "Gadget", "Garamond",*/
"Geneva", "Georgia", "Georgia Ref", "Geeza Pro", "Gigi", "Gill Sans", "Gill Sans MT", "Gill Sans MT Condensed", "Gill Sans MT Ext Condensed Bold", "Gill Sans Ultra Bold", "Gill Sans Ultra Bold Condensed",
/* "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", */
"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",
/* "Niagara Engraved","Niagara Solid","Nimbus Mono L","Nimbus Roman No9 L","OCR A Extended","OCRB","Odessa LET","Old English Text MT","OldDreadfulNo7 BT","One Stroke Script LET","Onyx","Optima","Orange LET","Palace Script MT","Palatino","Palatino Linotype", */
/* "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",
/* "Niagara Engraved", "Niagara Solid", "Nimbus Mono L", "Nimbus Roman No9 L", "OCR A Extended", "OCRB", "Odessa LET", "Old English Text MT", "OldDreadfulNo7 BT", "One Stroke Script LET", "Onyx", "Optima", "Orange LET", "Palace Script MT", "Palatino", "Palatino Linotype", */
"Papyrus",
/* "ParkAvenue BT","Pepita MT","Perpetua","Perpetua Titling MT","Placard Condensed","Playbill","Poornut","Pristina","Pump Demi Bold LET","Pussycat","Quixley LET","Rage Italic","Rage Italic LET","Ravie","Rockwell","Rockwell Condensed","Rockwell Extra Bold","Ruach LET","Runic MT Condensed","Sand","Script MT Bold","Scruff LET","Segoe UI","Showcard Gothic","Skia","Smudger LET","Snap ITC","Square721 BT","Staccato222 BT","Stencil","Sylfaen", */
"Tahoma","Techno","Tempus Sans ITC","Terminal","Textile","Times","Times New Roman","Tiranti Solid LET","Trebuchet MS",
/* "Tw Cen MT","Tw Cen MT Condensed","Tw Cen MT Condensed Extra Bold","URW Antiqua T","URW Bookman L","URW Chancery L","URW Gothic L","URW Palladio L","Univers","University Roman LET","Utopia", */
"Verdana","Verdana Ref", /* "Victorian LET","Viner Hand ITC","Vivaldi","Vladimir Script","Vrinda","Weltron Urban","Westwood LET","Wide Latin","Zapf Chancery", */
/* "ParkAvenue BT", "Pepita MT", "Perpetua", "Perpetua Titling MT", "Placard Condensed", "Playbill", "Poornut", "Pristina", "Pump Demi Bold LET", "Pussycat", "Quixley LET", "Rage Italic", "Rage Italic LET", "Ravie", "Rockwell", "Rockwell Condensed", "Rockwell Extra Bold", "Ruach LET", "Runic MT Condensed", "Sand", "Script MT Bold", "Scruff LET", "Segoe UI", "Showcard Gothic", "Skia", "Smudger LET", "Snap ITC", "Square721 BT", "Staccato222 BT", "Stencil", "Sylfaen", */
"Tahoma", "Techno", "Tempus Sans ITC", "Terminal", "Textile", "Times", "Times New Roman", "Tiranti Solid LET", "Trebuchet MS",
/* "Tw Cen MT", "Tw Cen MT Condensed", "Tw Cen MT Condensed Extra Bold", "URW Antiqua T", "URW Bookman L", "URW Chancery L", "URW Gothic L", "URW Palladio L", "Univers", "University Roman LET", "Utopia", */
"Verdana", "Verdana Ref", /* "Victorian LET", "Viner Hand ITC", "Vivaldi", "Vladimir Script", "Vrinda", "Weltron Urban", "Westwood LET", "Wide Latin", "Zapf Chancery", */
"Zapfino"];
// Compare against the reference fonts. Return true if it produces a different size than at least one of them.
@@ -143,7 +261,7 @@ var _CPFontDetectFontAvailable = function(font)
if (_CPFontDetectCompareFonts(_CPFontDetectReferenceFonts[i], font))
return true;
return false;
}
};
var _CPFontDetectCache = {};
@@ -165,7 +283,7 @@ var _CPFontDetectCompareFonts = function(fontA, fontB)
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)
@@ -175,6 +293,6 @@ var _CPFontDetectPickTwoDifferentFonts = function(candidates)
if (_CPFontDetectCompareFonts(candidates[i], candidates[j]))
return [candidates[i], candidates[j]];
return [candidates[0]];
}
};
[CPFontManager setFontManagerFactory:[CPFontManager class]];
+123
View File
@@ -0,0 +1,123 @@
/*
* CPGradient.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2012, SlevenBits Ltd.
*
* 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
*/
CPGradientDrawsBeforeStartingLocation = kCGGradientDrawsBeforeStartLocation;
CPGradientDrawsAfterEndingLocation = kCGGradientDrawsAfterEndLocation;
/*!
A class for drawing linear and radial gradients with a convenient API.
*/
@implementation CPGradient : CPObject
{
CGGradient _gradient;
}
- (id)initWithColors:(CPArray)someColors
{
var count = [someColors count];
if (count < 2)
[CPException raise:CPInvalidArgumentException reason:@"at least 2 colors required"];
var distance = 1.0 / (count - 1),
locations = [CPMutableArray array],
location = 0.0;
for (var i = 0; i < count; i++)
{
[locations addObject:location];
location += distance;
}
return [self initWithColors:someColors atLocations:locations colorSpace:nil];
}
- (id)initWithColors:(CPArray)someColors atLocations:(CPArray)someLocations colorSpace:(CPColorSpace)aColorSpace
{
if (self = [super init])
{
var cgColors = [],
count = [someColors count],
colorSpace = [aColorSpace CGColorSpace] || CGColorSpaceCreateDeviceRGB;
for (var i = 0; i < count; i++)
cgColors.push(CGColorCreate(colorSpace, [someColors[i] components]));
_gradient = CGGradientCreateWithColors(colorSpace, cgColors, someLocations);
}
return self;
}
- (void)drawInRect:(CGRect)rect angle:(float)angle
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(ctx);
CGContextClipToRect(ctx, rect);
CGContextAddRect(ctx, rect);
var startPoint,
endPoint;
// Modulo of negative values doesn't work as expected in JS.
angle = ((angle % 360.0) + 360.0) % 360.0;
if (angle < 90.0)
startPoint = _CGPointMake(_CGRectGetMinX(rect), _CGRectGetMinY(rect));
else if (angle < 180.0)
startPoint = _CGPointMake(_CGRectGetMaxX(rect), _CGRectGetMinY(rect));
else if (angle < 270.0)
startPoint = _CGPointMake(_CGRectGetMaxX(rect), _CGRectGetMaxY(rect));
else
startPoint = _CGPointMake(_CGRectGetMinX(rect), _CGRectGetMaxY(rect));
// A line segment comes out of the starting point at the given angle, with the first colour
// at the starting point and the last at the end. To do what drawInRect: is supposed to do
// we want the opposite corner of the starting corner to just reach the final colour stop.
// So when the angle isn't a right angle, the segment has to extend beyond the edge of the
// rectangle just far enough. This is hard to describe without a picture but if we place
// another line through the opposite corner at -90 degrees, it'll help form some triangles
// from which we can derive this formula:
//
// length = cos(angle) * (rectWidth + rectHeight * tan(angle))
//
// This simplifies down to (in the first quadrant) rectWidth * cos(a) + rectHeight * sin(a).
var radians = PI * angle / 180.0,
length = ABS(_CGRectGetWidth(rect) * COS(radians)) + ABS(_CGRectGetHeight(rect) * SIN(radians));
endPoint = _CGPointMake(startPoint.x + length * COS(radians),
startPoint.y + length * SIN(radians));
[self drawFromPoint:startPoint toPoint:endPoint options:CPGradientDrawsBeforeStartingLocation | CPGradientDrawsAfterEndingLocation];
CGContextRestoreGState(ctx);
}
- (void)drawFromPoint:(NSPoint)startingPoint toPoint:(NSPoint)endingPoint options:(NSGradientDrawingOptions)options
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
// TODO kCGGradientDrawsBeforeStartLocation and kCGGradientDrawsAfterEndLocation are not actually supported
// by CGContextDrawLinearGradient yet.
CGContextDrawLinearGradient(ctx, _gradient, startingPoint, endingPoint, options);
}
@end
+5 -2
View File
@@ -70,7 +70,10 @@ function CPDrawColorTiledRects(
if (_CGRectIsEmpty(slice))
continue;
var minX, maxX, minY, maxY;
var minX,
maxX,
minY,
maxY;
if (side == CPMinXEdge || side == CPMaxXEdge)
{
@@ -105,4 +108,4 @@ function CPDrawColorTiledRects(
CGContextRestoreGState(context);
return resultRect;
}
}
+13
View File
@@ -86,4 +86,17 @@ var CPGraphicsContextCurrent = nil;
return _graphicsPort;
}
/*!
(Not implemented. Always returns Cappuccino's default, `YES`.)
Return `isFlipped` of the receiver's focused view, unless no view is focused in which case the receiver's
`flipped` flag, as set by `graphicsContextWithGraphicsPort:flipped:`, is returned.
Note: Cappuccino is flipped by default.
*/
- (BOOL)isFlipped
{
return YES;
}
@end
+49 -5
View File
@@ -21,13 +21,12 @@
*/
@import <Foundation/CPBundle.j>
@import <Foundation/CPGeometry.j>
@import <Foundation/CPNotificationCenter.j>
@import <Foundation/CPObject.j>
@import <Foundation/CPRunLoop.j>
@import <Foundation/CPString.j>
@import "CPGeometry.j"
CPImageLoadStatusInitialized = 0;
CPImageLoadStatusLoading = 1;
@@ -158,6 +157,20 @@ function CPAppKitImage(aFilename, aSize)
return self;
}
/*!
Initializes the receiver with the specified data. The method loads the data into memory.
@param someData the CPData object representing the image
@return the initialized image
*/
- (id)initWithData:(CPData)someData
{
var base64 = [someData base64],
type = [base64 hasPrefix:@"/9j/4AAQSkZJRgABAQEASABIAAD/"] ? @"jpg" : @"png",
dataURL = "data:image/" + type + ";base64," + base64;
return [self initWithContentsOfFile:dataURL];
}
/*!
Returns the path of the file associated with this image.
*/
@@ -166,6 +179,37 @@ function CPAppKitImage(aFilename, aSize)
return _filename;
}
/*!
Returns the data associated with this image.
@discussion Returns nil if the reciever was not initialized with -initWithData: and the browser does not support the canvas feature;
*/
- (CPData)data
{
#if PLATFORM(DOM)
var dataURL;
if ([_filename hasPrefix:@"data:image"])
dataURL = _filename;
else if (CPFeatureIsCompatible(CPHTMLCanvasFeature))
{
var canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d");
canvas.width = _image.width,
canvas.height = _image.height;
ctx.drawImage(_image, 0, 0);
dataURL = canvas.toDataURL("image/png");
}
else
return nil;
var base64 = dataURL.replace(/^data:image\/png;base64,/, "");
return [CPData dataWithBase64:base64];
#endif
}
/*!
Sets the size of the image.
@param the size of the image
@@ -281,7 +325,7 @@ function CPAppKitImage(aFilename, aSize)
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
[self _derefFromImage];
}
};
_image.onerror = function ()
{
@@ -293,7 +337,7 @@ function CPAppKitImage(aFilename, aSize)
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
[self _derefFromImage];
}
};
_image.onabort = function ()
{
@@ -305,7 +349,7 @@ function CPAppKitImage(aFilename, aSize)
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
[self _derefFromImage];
}
};
_image.src = _filename;
+80 -51
View File
@@ -26,11 +26,6 @@
@import "CPImage.j"
@import "CPShadowView.j"
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
CPImageAlignCenter = 0;
CPImageAlignTop = 1;
CPImageAlignTopLeft = 2;
@@ -41,15 +36,7 @@ CPImageAlignBottomLeft = 6;
CPImageAlignBottomRight = 7;
CPImageAlignRight = 8;
var CPImageViewShadowBackgroundColor = nil,
CPImageViewEmptyPlaceholderImage = nil;
var LEFT_SHADOW_INSET = 3.0,
RIGHT_SHADOW_INSET = 3.0,
TOP_SHADOW_INSET = 3.0,
BOTTOM_SHADOW_INSET = 5.0,
VERTICAL_SHADOW_INSET = TOP_SHADOW_INSET + BOTTOM_SHADOW_INSET,
HORIZONTAL_SHADOW_INSET = LEFT_SHADOW_INSET + RIGHT_SHADOW_INSET;
var CPImageViewEmptyPlaceholderImage = nil;
/*!
@ingroup appkit
@@ -72,11 +59,22 @@ var LEFT_SHADOW_INSET = 3.0,
+ (void)initialize
{
if (self !== [CPImageView class])
return;
var bundle = [CPBundle bundleForClass:[CPView class]];
CPImageViewEmptyPlaceholderImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"empty.png"]];
}
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding === CPValueBinding || theBinding === CPValueURLBinding || theBinding === CPValuePathBinding || theBinding === CPDataBinding)
return [CPImageViewValueBinder class];
return [super _binderClassForBinding:theBinding];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
@@ -240,7 +238,7 @@ var LEFT_SHADOW_INSET = 3.0,
[super setImageScaling:anImageScaling];
#if PLATFORM(DOM)
if ([self currentValueForThemeAttribute:@"image-scaling"] === CPScaleToFit)
if ([self currentValueForThemeAttribute:@"image-scaling"] === CPImageScaleAxesIndependently)
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, 0.0, 0.0);
}
@@ -297,19 +295,19 @@ var LEFT_SHADOW_INSET = 3.0,
imageScaling = [self currentValueForThemeAttribute:@"image-scaling"],
x = 0.0,
y = 0.0,
insetWidth = (_hasShadow ? HORIZONTAL_SHADOW_INSET : 0.0),
insetHeight = (_hasShadow ? VERTICAL_SHADOW_INSET : 0.0),
insetWidth = (_hasShadow ? [_shadowView horizontalInset] : 0.0),
insetHeight = (_hasShadow ? [_shadowView verticalInset] : 0.0),
boundsWidth = _CGRectGetWidth(bounds),
boundsHeight = _CGRectGetHeight(bounds),
width = boundsWidth - insetWidth,
height = boundsHeight - insetHeight;
if (imageScaling === CPScaleToFit)
if (imageScaling === CPImageScaleAxesIndependently)
{
#if PLATFORM(DOM)
_DOMImageElement.width = ROUND(width);
_DOMImageElement.height = ROUND(height);
#endif
#if PLATFORM(DOM)
_DOMImageElement.width = ROUND(width);
_DOMImageElement.height = ROUND(height);
#endif
}
else
{
@@ -318,17 +316,19 @@ var LEFT_SHADOW_INSET = 3.0,
if (size.width == -1 && size.height == -1)
return;
if (imageScaling === CPScaleProportionally)
switch (imageScaling)
{
// The max size it can be is size.width x size.height, so only
// only proportion otherwise.
if (width >= size.width && height >= size.height)
{
width = size.width;
height = size.height;
}
else
{
case CPImageScaleProportionallyDown:
if (width >= size.width && height >= size.height)
{
width = size.width;
height = size.height;
break;
}
// intentionally fall through to the next case
case CPImageScaleProportionallyUpOrDown:
var imageRatio = size.width / size.height,
viewRatio = width / height;
@@ -336,26 +336,19 @@ var LEFT_SHADOW_INSET = 3.0,
width = height * imageRatio;
else
height = width / imageRatio;
}
break;
#if PLATFORM(DOM)
case CPImageScaleAxesIndependently:
case CPImageScaleNone:
width = size.width;
height = size.height;
break;
}
#if PLATFORM(DOM)
_DOMImageElement.width = ROUND(width);
_DOMImageElement.height = ROUND(height);
#endif
}
else
{
width = size.width;
height = size.height;
}
if (imageScaling == CPScaleNone)
{
#if PLATFORM(DOM)
_DOMImageElement.width = ROUND(size.width);
_DOMImageElement.height = ROUND(size.height);
#endif
}
#endif
var x,
y;
@@ -406,7 +399,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)];
[_shadowView setFrame:_CGRectMake(x - [_shadowView leftInset], y - [_shadowView topInset], width + insetWidth, height + insetHeight)];
}
- (void)mouseDown:(CPEvent)anEvent
@@ -457,6 +450,39 @@ var LEFT_SHADOW_INSET = 3.0,
@end
@implementation CPImageViewValueBinder : CPBinder
{
}
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
[self _setPlaceholder:nil forMarker:CPMultipleValuesMarker isDefault:YES];
[self _setPlaceholder:nil forMarker:CPNoSelectionMarker isDefault:YES];
[self _setPlaceholder:nil forMarker:CPNotApplicableMarker isDefault:YES];
[self _setPlaceholder:nil forMarker:CPNullMarker isDefault:YES];
}
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[_source setImage:nil];
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
var image;
if (aBinding === CPDataBinding)
image = [[CPImage alloc] initWithData:aValue];
else if (aBinding === CPValueURLBinding || aBinding === CPValuePathBinding)
image = [[CPImage alloc] initWithContentsOfFile:aValue];
else if (aBinding === CPValueBinding)
image = aValue;
[_source setImage:image];
}
@end
var CPImageViewImageKey = @"CPImageViewImageKey",
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
CPImageViewImageAlignmentKey = @"CPImageViewImageAlignmentKey",
@@ -483,6 +509,9 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
if (typeof(appkit_tag_dom_elements) !== "undefined" && !!appkit_tag_dom_elements)
_DOMImageElement.setAttribute("data-cappuccino-view", [self className]);
#endif
self = [super initWithCoder:aCoder];
@@ -496,7 +525,7 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
[self setImageAlignment:[aCoder decodeIntForKey:CPImageViewImageAlignmentKey]];
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey] || NO)
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey])
[self setEditable:YES];
[self setNeedsLayout];
+2 -1
View File
@@ -28,6 +28,7 @@
CPStandardKeyBindings = {
@"@.": @"cancelOperation:",
@"@a": @"selectAll:",
@"^a": @"moveToBeginningOfParagraph:",
@"^$a": @"moveToBeginningOfParagraphAndModifySelection:",
@"^b": @"moveBackward:",
@@ -152,7 +153,7 @@ var CPKeyBindingCache = {};
+ (void)initialize
{
if ([self class] !== CPKeyBinding)
if (self !== [CPKeyBinding class])
return;
[self createKeyBindingsFromJSObject:CPStandardKeyBindings];
+117 -21
View File
@@ -41,6 +41,7 @@ var CPBindingOperationAnd = 0,
id _source;
JSObject _suppressedNotifications;
JSObject _placeholderForMarker;
}
+ (void)exposeBinding:(CPString)aBinding forClass:(Class)aClass
@@ -125,10 +126,13 @@ var CPBindingOperationAnd = 0,
_source = aSource;
_info = [CPDictionary dictionaryWithObjects:[aDestination, aKeyPath] forKeys:[CPObservedObjectKey, CPObservedKeyPathKey]];
_suppressedNotifications = {};
_placeholderForMarker = {};
if (options)
[_info setObject:options forKey:CPOptionsKey];
[self _updatePlaceholdersWithOptions:options];
[aDestination addObserver:self forKeyPath:aKeyPath options:CPKeyValueObservingOptionNew context:aBinding];
var bindings = [bindingsMap objectForKey:[_source UID]];
@@ -145,15 +149,40 @@ var CPBindingOperationAnd = 0,
return self;
}
- (void)setValueFor:(CPString)aBinding
- (void)setValueFor:(CPString)theBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath];
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
newValue = [self transformValue:newValue withOptions:options];
[_source setValue:newValue forKey:aBinding];
if (isPlaceholder)
{
if (newValue === CPNotApplicableMarker && [options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
{
[CPException raise:CPGenericException
reason:@"Cannot transform non-applicable key on: " + _source + " key path: " + keyPath + " value: " + newValue];
}
var value = [self _placeholderForMarker:newValue];
[self setPlaceholderValue:value withMarker:newValue forBinding:theBinding];
}
else
{
var value = [self transformValue:newValue withOptions:options];
[self setValue:value forBinding:theBinding];
}
}
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[_source setValue:aValue forKey:aBinding];
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source setValue:aValue forKey:aBinding];
}
- (void)reverseSetValueFor:(CPString)aBinding
@@ -161,10 +190,18 @@ var CPBindingOperationAnd = 0,
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [_source valueForKeyPath:aBinding];
newValue = [self valueForBinding:aBinding];
newValue = [self reverseTransformValue:newValue withOptions:options];
[self suppressSpecificNotificationFromObject:destination keyPath:keyPath];
[destination setValue:newValue forKeyPath:keyPath];
[self unsuppressSpecificNotificationFromObject:destination keyPath:keyPath];
}
- (id)valueForBinding:(CPString)aBinding
{
return [_source valueForKeyPath:aBinding];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
@@ -204,14 +241,13 @@ var CPBindingOperationAnd = 0,
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
- (id)reverseTransformValue:(id)aValue withOptions:(CPDictionary)options
{
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
@@ -271,6 +307,42 @@ var CPBindingOperationAnd = 0,
delete objectSuppressions[aKeyPath];
}
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
var count = [CPBinderPlaceholderMarkers count];
while (count--)
{
var marker = CPBinderPlaceholderMarkers[count],
optionName = CPBinderPlaceholderOptions[count],
isExplicit = [options containsKey:optionName],
placeholder = isExplicit ? [options objectForKey:optionName] : nil;
[self _setPlaceholder:placeholder forMarker:marker isDefault:!isExplicit];
}
}
- (void)_placeholderForMarker:aMarker
{
var placeholder = _placeholderForMarker[aMarker];
if (placeholder)
return placeholder['value'];
return nil;
}
- (void)_setPlaceholder:(id)aPlaceholder forMarker:(id)aMarker isDefault:(BOOL)isDefault
{
if (isDefault)
{
var existingPlaceholder = _placeholderForMarker[aMarker];
// Don't overwrite an explicitly set placeholder with a default.
if (existingPlaceholder && !existingPlaceholder['isDefault'])
return;
}
_placeholderForMarker[aMarker] = { 'isDefault': isDefault, 'value': aPlaceholder };
}
@end
@implementation CPObject (KeyValueBindingCreation)
@@ -404,7 +476,7 @@ var CPBindingOperationAnd = 0,
@end
var resolveMultipleValues = function resolveMultipleValues(/*CPString*/key, /*CPDictionary*/bindings, /*GSBindingOperationKind*/operation)
var resolveMultipleValues = function(/*CPString*/key, /*CPDictionary*/bindings, /*GSBindingOperationKind*/operation)
{
var bindingName = key,
theBinding,
@@ -426,9 +498,9 @@ var resolveMultipleValues = function resolveMultipleValues(/*CPString*/key, /*CP
}
return !operation;
}
};
var invokeAction = function invokeAction(/*CPString*/targetKey, /*CPString*/argumentKey, /*CPDictionary*/bindings)
var invokeAction = function(/*CPString*/targetKey, /*CPString*/argumentKey, /*CPDictionary*/bindings)
{
var theBinding = [bindings objectForKey:targetKey],
infoDictionary = theBinding._info,
@@ -463,7 +535,7 @@ var invokeAction = function invokeAction(/*CPString*/targetKey, /*CPString*/argu
}
[invocation invoke];
}
};
// Keys in options dictionary
@@ -479,15 +551,35 @@ 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";
CPAlignmentBinding = @"alignment";
CPContentArrayBinding = @"contentArray";
CPContentBinding = @"content";
CPContentObjectBinding = @"contentObject";
CPContentObjectsBinding = @"contentObjects";
CPContentValuesBinding = @"contentValues";
CPEditableBinding = @"editable";
CPEnabledBinding = @"enabled";
CPFontBinding = @"font";
CPFontNameBinding = @"fontName";
CPFontBoldBinding = @"fontBold";
CPHiddenBinding = @"hidden";
CPFilterPredicateBinding = @"filterPredicate";
CPPredicateBinding = @"predicate";
CPSelectedIndexBinding = @"selectedIndex";
CPSelectedLabelBinding = @"selectedLabel";
CPSelectedObjectBinding = @"selectedObject";
CPSelectedObjectsBinding = @"selectedObjects";
CPSelectedTagBinding = @"selectedTag";
CPSelectedValueBinding = @"selectedValue";
CPSelectedValuesBinding = @"selectedValues";
CPSelectionIndexesBinding = @"selectionIndexes";
CPTextColorBinding = @"textColor";
CPTitleBinding = @"title";
CPToolTipBinding = @"toolTip";
CPValueBinding = @"value";
CPValueURLBinding = @"valueURL";
CPValuePathBinding = @"valuePath";
CPDataBinding = @"data";
//Binding options constants
CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelection";
@@ -518,4 +610,8 @@ CPValueTransformerBindingOption = @"CPValueTransformer";
CPIsControllerMarker = function(/*id*/anObject)
{
return anObject === CPMultipleValuesMarker || anObject === CPNoSelectionMarker || anObject === CPNotApplicableMarker || anObject === CPNullMarker;
}
};
var CPBinderPlaceholderMarkers = [CPMultipleValuesMarker, CPNoSelectionMarker, CPNotApplicableMarker, CPNullMarker],
CPBinderPlaceholderOptions = [CPMultipleValuesPlaceholderBindingOption, CPNoSelectionPlaceholderBindingOption, CPNotApplicablePlaceholderBindingOption, CPNullPlaceholderBindingOption];
+4 -1
View File
@@ -64,6 +64,9 @@ var _CPLevelIndicatorBezelColor = nil,
+ (void)initialize
{
if (self !== [CPLevelIndicator class])
return;
var bundle = [CPBundle bundleForClass:CPLevelIndicator];
_CPLevelIndicatorBezelColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
@@ -253,7 +256,7 @@ var _CPLevelIndicatorBezelColor = nil,
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
bounds = [self bounds],
oldValue = [self doubleValue];
oldValue = [self doubleValue],
newValue = oldValue;
// Moving the mouse outside of the widget to the left sets it
+2 -2
View File
@@ -80,7 +80,7 @@ var _CPMenuBarVisible = NO,
+ (void)initialize
{
if (self !== CPMenu)
if (self !== [CPMenu class])
return;
[[self class] setMenuBarAttributes:[CPDictionary dictionary]];
@@ -806,7 +806,7 @@ var _CPMenuBarVisible = NO,
[aMenu _menuWillOpen];
if (!aFont)
aFont = [CPFont systemFontOfSize:12.0];
aFont = [CPFont systemFontOfSize:[CPFont systemFontSize]];
var theWindow = [aView window],
menuWindow = [_CPMenuWindow menuWindowWithMenu:aMenu font:aFont];
+5 -5
View File
@@ -34,12 +34,12 @@ var _CPMenuBarWindowBackgroundColor = nil,
+ (void)initialize
{
if (self != [_CPMenuBarWindow class])
if (self !== [_CPMenuBarWindow class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPMenuBarWindowFont = [CPFont boldSystemFontOfSize:12.0];
_CPMenuBarWindowFont = [CPFont boldSystemFontOfSize:[CPFont systemFontSize]];
}
+ (CPFont)font
@@ -74,7 +74,7 @@ var _CPMenuBarWindowBackgroundColor = nil,
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_titleField setFont:[CPFont boldSystemFontOfSize:13.0]];
[_titleField setFont:[CPFont boldSystemFontOfSize:[CPFont systemFontSize] + 1]];
[_titleField setAlignment:CPCenterTextAlignment];
[_titleField setTextShadowOffset:CGSizeMake(0, 1)];
@@ -257,7 +257,7 @@ var _CPMenuBarWindowBackgroundColor = nil,
items = [_menu itemArray],
count = items.length;
for (index = 0; index < count; ++index)
for (var index = 0; index < count; ++index)
{
var item = items[index],
menuItemView = [item _menuItemView];
@@ -335,7 +335,7 @@ var _CPMenuBarWindowBackgroundColor = nil,
- (CPFont)font
{
[CPFont systemFontOfSize:12.0];
[CPFont systemFontOfSize:[CPFont systemFontSize]];
}
- (void)tile
+58 -28
View File
@@ -5,13 +5,13 @@ _CPMenuManagerScrollingStateUp = -1;
_CPMenuManagerScrollingStateDown = 1;
_CPMenuManagerScrollingStateNone = 0;
var STICKY_TIME_INTERVAL = 500,
var STICKY_TIME_INTERVAL = 0.5,
SharedMenuManager = nil;
@implementation _CPMenuManager: CPObject
{
CPTimeInterval _startTime;
BOOL _hasMouseGoneUpAfterStartedTracking;
BOOL _mouseWasDragged;
int _scrollingState;
CGPoint _lastGlobalLocation;
@@ -66,7 +66,7 @@ var STICKY_TIME_INTERVAL = 500,
CPApp._activeMenu = menu;
_startTime = [anEvent timestamp];//new Date();
_startTime = [anEvent timestamp];
_scrollingState = _CPMenuManagerScrollingStateNone;
_constraintRect = aRect;
@@ -91,7 +91,7 @@ var STICKY_TIME_INTERVAL = 500,
return [self trackMenuBarButtonEvent:anEvent];
}
_hasMouseGoneUpAfterStartedTracking = NO;
_mouseWasDragged = NO;
[self trackEvent:anEvent];
}
@@ -127,7 +127,7 @@ var STICKY_TIME_INTERVAL = 500,
if (_keyBuffer)
{
if (([CPDate date] - _startTime) > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] / 2))
if (([anEvent timestamp] - _startTime) > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] / 2))
[self selectNextItemBeginningWith:_keyBuffer inMenu:menu clearBuffer:YES];
if (type === CPPeriodic)
@@ -137,10 +137,7 @@ var STICKY_TIME_INTERVAL = 500,
// 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)
if (!globalLocation)
return;
// Find which menu window the mouse is currently on top of
@@ -152,6 +149,14 @@ var STICKY_TIME_INTERVAL = 500,
activeItemIndex = activeMenuContainer ? [activeMenuContainer itemIndexAtPoint:menuLocation] : CPNotFound,
activeItem = activeItemIndex !== CPNotFound ? [activeMenu itemAtIndex:activeItemIndex] : nil;
// unhighlight when mouse is moved off the menu
if (_lastGlobalLocation && CGRectContainsPoint([activeMenuContainer globalFrame], _lastGlobalLocation)
&& !CGRectContainsPoint([activeMenuContainer globalFrame], globalLocation))
[activeMenu _highlightItemAtIndex:CPNotFound];
// Remember this for the next periodic event.
_lastGlobalLocation = globalLocation;
// If the item isn't enabled its as if we clicked on nothing.
if (![activeItem isEnabled] || [activeItem _isMenuBarButton])
{
@@ -161,7 +166,7 @@ var STICKY_TIME_INTERVAL = 500,
var mouseOverMenuView = [activeItem view];
if (type === CPScrollWheel)
if (type === CPScrollWheel && ![activeMenuContainer isMenuBar])
[activeMenuContainer scrollByDelta:[anEvent deltaY]];
if (type === CPPeriodic)
@@ -189,7 +194,7 @@ var STICKY_TIME_INTERVAL = 500,
var menuContainerWindow = activeMenuContainer;
if (![menuContainerWindow isKindOfClass:[CPWindow class]])
if (![menuContainerWindow isKindOfClass:CPWindow])
menuContainerWindow = [menuContainerWindow window];
[menuContainerWindow
@@ -211,10 +216,14 @@ var STICKY_TIME_INTERVAL = 500,
_lastMouseOverMenuView = nil;
}
[activeMenu _highlightItemAtIndex:activeItemIndex];
if (activeItemIndex != CPNotFound)
[activeMenu _highlightItemAtIndex:activeItemIndex];
if (type === CPMouseMoved || type === CPLeftMouseDragged || type === CPLeftMouseDown || type === CPPeriodic)
{
if (type === CPLeftMouseDragged)
_mouseWasDragged = YES;
var oldScrollingState = _scrollingState;
_scrollingState = [activeMenuContainer scrollingStateForPoint:globalLocation];
@@ -229,17 +238,35 @@ var STICKY_TIME_INTERVAL = 500,
}
else if (type === CPLeftMouseUp || type === CPRightMouseUp)
{
if (_hasMouseGoneUpAfterStartedTracking)
{
// Don't close the menu if the current item has a submenu
// and did not override it's default action
if ([activeItem action] === @selector(submenuAction:))
return;
/*
There are a few possibilites:
[trackingMenu cancelTracking];
1. The user clicks and releases without dragging within the sticky time.
This is considered a regular mouse click and not a drag. In this case
we allow the user to track the menu by moving the mouse. The next
mouse up will end tracking.
2. The user clicks and releases without dragging after the sticky time.
This is considered a drag and release and tracking ends.
3. The user clicks, drags and then releases. Tracking ends.
*/
if (_mouseWasDragged || ([anEvent timestamp] - _startTime > STICKY_TIME_INTERVAL))
{
/*
Close the menu if:
1. The mouse was dragged.
2. The mouse is released in the menubar.
3. The current item has a submenu with a custom action.
*/
if (_mouseWasDragged ||
[activeMenuContainer isMenuBar] ||
[activeItem action] !== @selector(submenuAction:))
{
[trackingMenu cancelTracking];
}
}
else
_hasMouseGoneUpAfterStartedTracking = YES;
}
}
@@ -252,7 +279,7 @@ var STICKY_TIME_INTERVAL = 500,
}
// If the item has a submenu, show it.
if ([activeItem hasSubmenu])// && [activeItem action] === @selector(submenuAction:))
if ([activeItem hasSubmenu]) // && [activeItem action] === @selector(submenuAction:))
{
var activeItemRect = [activeMenuContainer rectForItemAtIndex:activeItemIndex],
newMenuOrigin;
@@ -406,7 +433,7 @@ var STICKY_TIME_INTERVAL = 500,
break;
// If this menu is already being shown, unhighlight and return.
if (menu === newMenu)//&& [menu supermenu] === baseMenu)
if (menu === newMenu) //&& [menu supermenu] === baseMenu)
return [newMenu _highlightItemAtIndex:CPNotFound];
[menuContainer orderOut:self];
@@ -452,7 +479,7 @@ var STICKY_TIME_INTERVAL = 500,
var iter = [selectorNames objectEnumerator],
obj;
while (obj = [iter nextObject])
while ((obj = [iter nextObject]) !== nil)
{
var aSelector = CPSelectorFromString(obj);
@@ -464,7 +491,7 @@ var STICKY_TIME_INTERVAL = 500,
{
if (!_keyBuffer)
{
_startTime = [CPDate date];
_startTime = [anEvent timestamp];
_keyBuffer = character;
[CPEvent stopPeriodicEvents];
@@ -483,7 +510,7 @@ var STICKY_TIME_INTERVAL = 500,
var iter = [[menu itemArray] objectEnumerator],
obj;
while (obj = [iter nextObject])
while ((obj = [iter nextObject]) !== nil)
{
if ([obj isHidden] || ![obj isEnabled])
continue;
@@ -501,7 +528,7 @@ var STICKY_TIME_INTERVAL = 500,
_keyBuffer = Nil;
}
else
_startTime = [CPDate date];
_startTime = [CPEvent currentTimestamp];
}
- (void)scrollToBeginningOfDocument:(CPMenu)menu
@@ -645,8 +672,11 @@ var STICKY_TIME_INTERVAL = 500,
var index = menu._highlightedIndex - 1;
if (index < 0)
{
if (index != CPNotFound)
[menu _highlightItemAtIndex:[menu numberOfItems] - 1];
return;
}
[menu _highlightItemAtIndex:index];
var item = [menu highlightedItem];
+1 -3
View File
@@ -65,7 +65,7 @@ var STICKY_TIME_INTERVAL = 500,
+ (void)initialize
{
if (self != [_CPMenuWindow class])
if (self !== [_CPMenuWindow class])
return;
var bundle = [CPBundle bundleForClass:self];
@@ -110,8 +110,6 @@ var STICKY_TIME_INTERVAL = 500,
[_moreBelowView setFrameSize:[_CPMenuWindowMoreBelowImage size]];
[contentView addSubview:_moreBelowView];
[self setShadowStyle:CPWindowShadowStyleMenu];
}
return self;
+12 -13
View File
@@ -281,7 +281,7 @@ var CPMenuItemStringRepresentationDictionary = [CPDictionary dictionary];
*/
- (void)setFont:(CPFont)aFont
{
if (_font == aFont)
if ([_font isEqual:aFont])
return;
_font = aFont;
@@ -932,34 +932,33 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
_action = [aCoder decodeObjectForKey:CPMenuItemActionKey];
_isEnabled = DEFAULT_VALUE(CPMenuItemIsEnabledKey, YES);
_isHidden = DEFAULT_VALUE(CPMenuItemIsHiddenKey, NO);
_tag = DEFAULT_VALUE(CPMenuItemTagKey, 0);
_state = DEFAULT_VALUE(CPMenuItemStateKey, CPOffState);
_isHidden = [aCoder decodeBoolForKey:CPMenuItemIsHiddenKey];
_tag = [aCoder decodeIntForKey:CPMenuItemTagKey];
_state = [aCoder decodeIntForKey:CPMenuItemStateKey];
_image = DEFAULT_VALUE(CPMenuItemImageKey, nil);
_alternateImage = DEFAULT_VALUE(CPMenuItemAlternateImageKey, nil);
_image = [aCoder decodeObjectForKey:CPMenuItemImageKey];
_alternateImage = [aCoder decodeObjectForKey:CPMenuItemAlternateImageKey];
// CPImage _onStateImage;
// CPImage _offStateImage;
// CPImage _mixedStateImage;
// This order matters because setSubmenu: needs _menu to be around.
_menu = DEFAULT_VALUE(CPMenuItemMenuKey, nil);
[self setSubmenu:DEFAULT_VALUE(CPMenuItemSubmenuKey, nil)];
_menu = [aCoder decodeObjectForKey:CPMenuItemMenuKey];
[self setSubmenu:[aCoder decodeObjectForKey:CPMenuItemSubmenuKey]];
_keyEquivalent = [aCoder decodeObjectForKey:CPMenuItemKeyEquivalentKey] || @"";
_keyEquivalentModifierMask = [aCoder decodeObjectForKey:CPMenuItemKeyEquivalentModifierMaskKey] || 0;
_keyEquivalentModifierMask = [aCoder decodeIntForKey:CPMenuItemKeyEquivalentModifierMaskKey];
// int _mnemonicLocation;
// BOOL _isAlternate;
// Default is 0.
[self setIndentationLevel:[aCoder decodeIntForKey:CPMenuItemIndentationLevelKey] || 0];
[self setIndentationLevel:[aCoder decodeIntForKey:CPMenuItemIndentationLevelKey]];
// CPString _toolTip;
_representedObject = DEFAULT_VALUE(CPMenuItemRepresentedObjectKey, nil);
_view = DEFAULT_VALUE(CPMenuItemViewKey, nil);
_representedObject = [aCoder decodeObjectForKey:CPMenuItemRepresentedObjectKey];
_view = [aCoder decodeObjectForKey:CPMenuItemViewKey];
}
return self;
+1 -3
View File
@@ -148,10 +148,8 @@ var SelectionColor = nil,
[_submenuIndicatorView setFrame:submenuViewFrame];
}
_minSize = CGSizeMake(x + HORIZONTAL_MARGIN, height);
[self setAutoresizesSubviews:NO];
[self setFrameSize:_minSize];
[self setFrameSize:CGSizeMake(x + HORIZONTAL_MARGIN, height)];
[self setAutoresizesSubviews:YES];
}
+14 -14
View File
@@ -6,14 +6,14 @@ var LEFT_MARGIN = 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 = [];
@@ -43,9 +43,9 @@ var SUBMENU_INDICATOR_COLOR = nil,
_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;
@@ -74,7 +74,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
{
_stateView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
[_stateView setImageScaling:CPScaleNone];
[_stateView setImageScaling:CPImageScaleNone];
[self addSubview:_stateView];
@@ -175,7 +175,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
[_keyEquivalentView setTextShadowOffset:CGSizeMake(0, 1)];
[_keyEquivalentView setFrameOrigin:CGPointMake(x, VERTICAL_MARGIN)];
[_keyEquivalentView sizeToFit];
var keyEquivalentViewFrame = [_keyEquivalentView frame];
keyEquivalentViewFrame.origin.x = x;
@@ -215,7 +215,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
keyEquivalentViewFrame.origin.y = FLOOR((height - CGRectGetHeight(keyEquivalentViewFrame)) / 2.0);
[_keyEquivalentView setFrame:keyEquivalentViewFrame];
}
if (hasSubmenu)
{
submenuViewFrame.origin.y = FLOOR((height - CGRectGetHeight(submenuViewFrame)) / 2.0);
@@ -223,7 +223,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
}
_minSize = CGSizeMake(x + RIGHT_MARGIN, height);
[self setAutoresizesSubviews:NO];
[self setFrameSize:_minSize];
[self setAutoresizesSubviews:YES];
@@ -233,7 +233,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
{
// FIXME: This should probably be even throw.
if (![_menuItem isEnabled])
return;
return;
if (shouldHighlight)
{
@@ -259,7 +259,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_keyEquivalentView setTextShadowColor:[self textShadowColor]];
}
if ([[_menuItem menu] showsStateColumn])
{
if (shouldHighlight)
@@ -290,15 +290,15 @@ var SUBMENU_INDICATOR_COLOR = nil,
{
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);
}
+2 -2
View File
@@ -40,7 +40,7 @@ var _CPMenuItemSelectionColor = nil,
+ (void)initialize
{
if (self != [_CPMenuItemView class])
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];
@@ -176,7 +176,7 @@ var _CPMenuItemSelectionColor = nil,
- (void)setFont:(CPFont)aFont
{
if (_font === aFont)
if ([_font isEqual:aFont])
return;
_font = aFont;
+13 -8
View File
@@ -51,6 +51,9 @@
+ (id)initialize
{
if (self !== [CPObjectController class])
return;
[self exposeBinding:@"editable"];
[self exposeBinding:@"contentObject"];
}
@@ -371,7 +374,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
[self setObjectClass:objectClass || [CPMutableDictionary class]];
[self setEditable:[aCoder decodeBoolForKey:CPObjectControllerIsEditableKey]];
[self setAutomaticallyPreparesContent:[aCoder decodeBoolForKey:CPObjectControllerAutomaticallyPreparesContentKey] || NO];
[self setAutomaticallyPreparesContent:[aCoder decodeBoolForKey:CPObjectControllerAutomaticallyPreparesContentKey]];
[self setContent:[aCoder decodeObjectForKey:CPObjectControllerContentKey]];
_observedKeys = [[CPCountedSet alloc] init];
@@ -579,6 +582,8 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
- (void)removeObjectAtIndex:(unsigned)anIndex
{
var currentObject = [self objectAtIndex:anIndex];
for (var i = 0, count = [_observationProxies count]; i < count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
@@ -588,7 +593,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
if (operator)
[self willChangeValueForKey:keyPath];
[anObject removeObserver:proxy forKeyPath:keyPath];
[currentObject removeObserver:proxy forKeyPath:keyPath];
if (operator)
[self didChangeValueForKey:keyPath];
@@ -663,7 +668,8 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
- (id)_controllerMarkerForValues:(CPArray)theValues
{
var count = [theValues count];
var count = [theValues count],
value;
if (!count)
value = CPNoSelectionMarker;
@@ -677,7 +683,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
{
value = [theValues objectAtIndex:0];
for (var i = 0, count= [theValues count]; i < count && value != CPMultipleValuesMarker; i++)
for (var i = 0, count = [theValues count]; i < count && value != CPMultipleValuesMarker; i++)
{
if (![value isEqual:[theValues objectAtIndex:i]])
value = CPMultipleValuesMarker;
@@ -693,8 +699,8 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
- (id)valueForKeyPath:(CPString)theKeyPath
{
var values = [[_controller selectedObjects] valueForKeyPath:theKeyPath];
value = [self _controllerMarkerForValues:values];
var values = [[_controller selectedObjects] valueForKeyPath:theKeyPath],
value = [self _controllerMarkerForValues:values];
[_cachedValues setObject:value forKey:theKeyPath];
@@ -776,8 +782,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
[proxy setNotifyObject:YES];
[_observationProxies addObject:proxy];
// We keep are reference to the observed objects
// because the removeObserver: will be called after the selection changes
// We keep a reference to the observed objects because removeObserver: will be called after the selection changes.
var observedObjects = [_controller selectedObjects];
_observedObjectsByKeyPath[aKeyPath] = observedObjects;
[observedObjects addObserver:proxy forKeyPath:aKeyPath options:options context:context];
+90 -47
View File
@@ -62,7 +62,7 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_
CPOutlineViewDelegate_outlineView_shouldReorderColumn_toColumn_ = 1 << 12,
CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 13,
CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_ = 1 << 14,
CPOutlineViewDelegate_outlineView_shouldShowOutlineViewForItem_ = 1 << 15,
CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_ = 1 << 15,
CPOutlineViewDelegate_outlineView_shouldShowViewExpansionForTableColumn_item_ = 1 << 16,
CPOutlineViewDelegate_outlineView_shouldTrackView_forTableColumn_item_ = 1 << 17,
CPOutlineViewDelegate_outlineView_shouldTypeSelectForEvent_withCurrentSearchString_ = 1 << 18,
@@ -80,6 +80,10 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
CPOutlineViewCoalesceSelectionNotificationStateOn = 1,
CPOutlineViewCoalesceSelectionNotificationStateDid = 2;
#define SELECTION_SHOULD_CHANGE(anOutlineView) (!((anOutlineView)._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_selectionShouldChangeInOutlineView_) || [(anOutlineView)._outlineViewDelegate selectionShouldChangeInOutlineView:(anOutlineView)])
#define SHOULD_SELECT_ITEM(anOutlineView, anItem) (!((anOutlineView)._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_) || [(anOutlineView)._outlineViewDelegate outlineView:(anOutlineView) shouldSelectItem:(anItem)])
/*!
@ingroup appkit
@class CPOutlineView
@@ -136,7 +140,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
_selectionHighlightStyle = CPTableViewSelectionHighlightStyleSourceList;
// The root item has weight "0", thus represents the weight solely of its descendants.
_rootItemInfo = { isExpanded:YES, isExpandable:NO, level:-1, row:-1, children:[], weight:0 };
_rootItemInfo = { isExpanded:YES, isExpandable:NO, shouldShowOutlineDisclosureControl:NO, level:-1, row:-1, children:[], weight:0 };
_itemsForRows = [];
_itemInfosForItems = { };
@@ -147,7 +151,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
_retargedChildIndex = nil;
_shouldRetargetChildIndex = NO;
_startHoverTime = nil;
[self setIndentationPerLevel:16.0];
[self setIndentationMarkerFollowsDataView:YES];
@@ -294,6 +297,19 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
return itemInfo.isExpandable;
}
- (BOOL)_shouldShowOutlineDisclosureControlForItem:(id)anItem
{
if (!anItem)
return YES;
var itemInfo = _itemInfosForItems[[anItem UID]];
if (!itemInfo)
return YES;
return itemInfo.shouldShowOutlineDisclosureControl;
}
/*!
Used to find if an item is already expanded.
@@ -690,11 +706,13 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
*/
- (CGRect)frameOfOutlineDisclosureControlAtRow:(CPInteger)aRow
{
if (![self isExpandable:[self itemAtRow:aRow]])
var theItem = [self itemAtRow:aRow];
if (![self isExpandable:theItem] || ![self _shouldShowOutlineDisclosureControlForItem:theItem])
return _CGRectMakeZero();
var dataViewFrame = [self _frameOfOutlineDataViewAtRow:aRow],
frame = _CGRectMake(_CGRectGetMinX(dataViewFrame) - 10, _CGRectGetMinY(dataViewFrame), 10, _CGRectGetHeight(dataViewFrame));
disclosureWidth = _CGRectGetWidth([_disclosureControlPrototype frame]),
frame = _CGRectMake(_CGRectGetMinX(dataViewFrame) - disclosureWidth, _CGRectGetMinY(dataViewFrame), disclosureWidth, _CGRectGetHeight(dataViewFrame));
return frame;
}
@@ -822,29 +840,24 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
name:CPOutlineViewSelectionIsChangingNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemWillExpand:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewItemWillExpandNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemDidExpand:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewItemDidExpandNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemWillCollapse:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewItemWillCollapseNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemDidCollapse:)])
[defaultCenter
removeObserver:_outlineViewDelegate
@@ -870,7 +883,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
CPOutlineViewDelegate_outlineView_shouldReorderColumn_toColumn_ , @selector(outlineView:shouldReorderColumn:toColumn:),
CPOutlineViewDelegate_outlineView_shouldSelectItem_ , @selector(outlineView:shouldSelectItem:),
CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_ , @selector(outlineView:shouldSelectTableColumn:),
CPOutlineViewDelegate_outlineView_shouldShowOutlineViewForItem_ , @selector(outlineView:shouldShowOutlineViewForItem:),
CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_ , @selector(outlineView:shouldShowOutlineDisclosureControlForItem:),
CPOutlineViewDelegate_outlineView_shouldShowViewExpansionForTableColumn_item_ , @selector(outlineView:shouldShowViewExpansionForTableColumn:item:),
CPOutlineViewDelegate_outlineView_shouldTrackView_forTableColumn_item_ , @selector(outlineView:shouldTrackView:forTableColumn:item:),
CPOutlineViewDelegate_outlineView_shouldTypeSelectForEvent_withCurrentSearchString_ , @selector(outlineView:shouldTypeSelectForEvent:withCurrentSearchString:),
@@ -921,7 +934,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
name:CPOutlineViewSelectionIsChangingNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemWillExpand:)])
[defaultCenter
addObserver:_outlineViewDelegate
@@ -984,7 +996,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
_disclosureControlData = nil;
_disclosureControlQueue = [];
// fIXME: really?
// FIXME: really?
[self reloadData];
}
@@ -1120,13 +1132,14 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
if (_dragHoverTimer)
[_dragHoverTimer invalidate];
var autoExpandCallBack = function(){
var autoExpandCallBack = function()
{
if (_dropItem)
{
[_dropOperationFeedbackView blink];
[CPTimer scheduledTimerWithTimeInterval:.3 callback:objj_msgSend(self, "expandItem:", _dropItem) repeats:NO];
}
}
};
_dragHoverTimer = [CPTimer scheduledTimerWithTimeInterval:.8 callback:autoExpandCallBack repeats:NO];
}
@@ -1284,7 +1297,12 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
item = _itemsForRows[row],
isExpandable = [self isExpandable:item];
if (!isExpandable)
if (!isExpandable)
continue;
var disclosureControlFrame = [self frameOfOutlineDisclosureControlAtRow:row];
if (_CGRectIsEmpty(disclosureControlFrame))
continue;
var control = [self _dequeueDisclosureControl];
@@ -1294,7 +1312,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
[control setState:[self isItemExpanded:item] ? CPOnState : CPOffState];
var selector = [self isRowSelected:row] ? @"setThemeState:" : @"unsetThemeState:";
[control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
[control setFrame:[self frameOfOutlineDisclosureControlAtRow:row]];
[control setFrame:disclosureControlFrame];
[self addSubview:control];
}
@@ -1347,7 +1365,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
[self collapseItem:item];
else
[self expandItem:item];
[self expandItem:item expandChildren:([[CPApp currentEvent] modifierFlags] & CPAlternateKeyMask)];
}
/*!
@@ -1458,7 +1476,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
userInfo:[CPDictionary dictionaryWithObject:item forKey:"CPObject"]];
}
- (void)keyDown:(CPEvent)anEvent
{
var character = [anEvent charactersIgnoringModifiers],
@@ -1467,7 +1484,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
// Check for the key events manually, as opposed to waiting for CPWindow to sent the actual action message
// in _processKeyboardUIKey:, because we might not want to handle the arrow events.
if (character !== CPRightArrowFunctionKey && character !== CPLeftArrowFunctionKey)
if (character !== CPRightArrowFunctionKey && character !== CPLeftArrowFunctionKey)
return [super keyDown:anEvent];
var rows = [self selectedRowIndexes],
@@ -1481,7 +1498,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
for (; i < c; i++)
items.push([self itemAtRow:indexes[i]]);
if (character === CPRightArrowFunctionKey)
{
@@ -1490,12 +1506,32 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
}
else if (character === CPLeftArrowFunctionKey)
{
// When a single, collapsed item is selected and the left arrow key is pressed, the parent
// should be selected if possible.
if (c == 1)
{
var theItem = items[0];
if (![self isItemExpanded:theItem])
{
var parent = [self parentForItem:theItem],
shouldSelect = parent && SELECTION_SHOULD_CHANGE(self) && SHOULD_SELECT_ITEM(self, parent);
if (shouldSelect)
{
var rowIndex = [self rowForItem:parent];
[self selectRowIndexes:[CPIndexSet indexSetWithIndex:rowIndex] byExtendingSelection:NO];
[self scrollRowToVisible:rowIndex];
return;
}
}
}
for (var i = 0; i < c; i++)
[self collapseItem:items[i]];
[self collapseItem:items[i]];
}
[super keyDown:anEvent];
}
@end
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
@@ -1534,8 +1570,9 @@ var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem)
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem];
itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded;
itemInfo.shouldShowOutlineDisclosureControl = !(_implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_) || [_outlineViewDelegate outlineView:self shouldShowOutlineDisclosureControlForItem:newItem];
}
}
};
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate)
@@ -1559,6 +1596,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return [];
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem];
itemInfo.shouldShowOutlineDisclosureControl = !(_implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_) || [_outlineViewDelegate outlineView:self shouldShowOutlineDisclosureControlForItem:anItem];
// If we were previously expanded, but now no longer expandable, "de-expand".
// NOTE: we are *not* collapsing, thus no notification is posted.
@@ -1589,7 +1627,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
if (!childItemInfo)
{
childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 };
childItemInfo = { isExpanded:NO, isExpandable:NO, shouldShowOutlineDisclosureControl:YES, children:[], weight:1 };
itemInfosForItems[[childItem UID]] = childItemInfo;
}
@@ -1640,7 +1678,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
}
}//end of with
return descendants;
}
};
@implementation _CPOutlineViewTableViewDataSource : CPObject
{
@@ -1792,9 +1830,9 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
var dataView = nil;
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_))
dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
dataViewForTableColumn:theTableColumn
item:[_outlineView itemAtRow:theRow]];
dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
dataViewForTableColumn:theTableColumn
item:[_outlineView itemAtRow:theRow]];
if (!dataView)
dataView = [theTableColumn dataViewForRow:theRow];
@@ -1804,10 +1842,12 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
- (BOOL)tableView:(CPTableView)theTableView shouldSelectRow:(int)theRow
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_))
return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldSelectItem:[_outlineView itemAtRow:theRow]];
return SHOULD_SELECT_ITEM(_outlineView, [_outlineView itemAtRow:theRow]);
}
return YES;
- (BOOL)selectionShouldChangeInTableView:(CPTableView)theTableView
{
return SELECTION_SHOULD_CHANGE(_outlineView);
}
- (BOOL)tableView:(CPTableView)aTableView shouldEditTableColumn:(CPTableColumn)aColumn row:(int)aRow
@@ -1851,7 +1891,9 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return [_outlineView._outlineViewDelegate outlineView:_outlineView menuForTableColumn:aTableColumn item:item]
}
return nil;
// We reimplement CPView menuForEvent: because we can't call it directly. CPTableView implements menuForEvent:
// to call this delegate method.
return [_outlineView menu] || [[_outlineView class] defaultMenu];
}
@end
@@ -1885,16 +1927,22 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
- (void)drawRect:(CGRect)aRect
{
var bounds = [self bounds],
context = [[CPGraphicsContext currentContext] graphicsPort];
context = [[CPGraphicsContext currentContext] graphicsPort],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
CGContextBeginPath(context);
CGContextTranslateCTM(context, _CGRectGetWidth(bounds) / 2.0, _CGRectGetHeight(bounds) / 2.0);
CGContextRotateCTM(context, _angle);
CGContextTranslateCTM(context, -_CGRectGetWidth(bounds) / 2.0, -_CGRectGetHeight(bounds) / 2.0);
if (_angle)
{
var centre = _CGPointMake(FLOOR(width / 2.0), FLOOR(height / 2.0));
CGContextTranslateCTM(context, centre.x, centre.y);
CGContextRotateCTM(context, _angle);
CGContextTranslateCTM(context, -centre.x, -centre.y);
}
// Center, but crisp.
CGContextTranslateCTM(context, FLOOR((_CGRectGetWidth(bounds) - 9.0) / 2.0), FLOOR((_CGRectGetHeight(bounds) - 8.0) / 2.0));
CGContextTranslateCTM(context, FLOOR((width - 9.0) / 2.0), FLOOR((height - 8.0) / 2.0));
CGContextMoveToPoint(context, 0.0, 0.0);
CGContextAddLineToPoint(context, 9.0, 0.0);
@@ -1907,20 +1955,14 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
[self hasThemeState:CPThemeStateHighlighted]));
CGContextFillPath(context);
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0.0, 0.0);
CGContextAddLineToPoint(context, 4.5, 8.0);
if (_angle === 0.0)
{
CGContextAddLineToPoint(context, 4.5, 8.0);
CGContextAddLineToPoint(context, 9.0, 0.0);
}
else
CGContextAddLineToPoint(context, 4.5, 8.0);
CGContextSetStrokeColor(context, [CPColor colorWithCalibratedWhite:1.0 alpha: 0.8]);
CGContextSetStrokeColor(context, [CPColor colorWithCalibratedWhite:1.0 alpha: 0.7]);
CGContextStrokePath(context);
}
@@ -1984,7 +2026,8 @@ var CPOutlineViewIndentationPerLevelKey = @"CPOutlineViewIndentationPerLevelKey"
@end
var colorForDisclosureTriangle = function(isSelected, isHighlighted) {
var colorForDisclosureTriangle = function(isSelected, isHighlighted)
{
return isSelected
? (isHighlighted
? [CPColor colorWithCalibratedWhite:0.9 alpha: 1.0]
@@ -1992,4 +2035,4 @@ var colorForDisclosureTriangle = function(isSelected, isHighlighted) {
: (isHighlighted
? [CPColor colorWithCalibratedWhite:0.4 alpha: 1.0]
: [CPColor colorWithCalibratedWhite:0.5 alpha: 1.0]);
}
};
+1 -1
View File
@@ -73,7 +73,7 @@ var CPPasteboards = nil,
*/
+ (void)initialize
{
if (self != [CPPasteboard class])
if (self !== [CPPasteboard class])
return;
[self setVersion:1.0];
+295 -22
View File
@@ -20,12 +20,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPGeometry.j>
@import "CPButton.j"
@import "CPGeometry.j"
@import "CPKeyValueBinding.j"
@import "CPMenu.j"
@import "CPMenuItem.j"
var VISIBLE_MARGIN = 7.0;
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
@@ -246,22 +247,6 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
return _selectedIndex;
}
/*!
@ignore
*/
- (int)selectedTag
{
return [[self selectedItem] tag];
}
/*!
@ignore
*/
- (void)_setSelectedTag:(int)aTag
{
[self selectItemWithTag:aTag];
}
// Setting the Current Selection
/*!
Selects the specified menu item.
@@ -587,10 +572,18 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
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;
if (![self pullsDown] && [indexes containsIndex:indexOfSelectedItem])
{
// If the selected item is removed the first item becomes selected.
indexOfSelectedItem = 0;
}
else
{
// See whether the index has changed, despite the actual item not changing.
while ((index = [indexes indexGreaterThanIndex:index]) !== CPNotFound &&
index <= indexOfSelectedItem)
--indexOfSelectedItem;
}
[self selectItemAtIndex:indexOfSelectedItem];
}
@@ -776,6 +769,286 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
[[self selectedItem] setState:CPOffState];
}
- (void)_reverseSetBinding
{
[_CPPopUpButtonSelectionBinder reverseSetValueForObject:self];
[super _reverseSetBinding];
}
@end
@implementation CPPopUpButton (BindingSupport)
+ (Class)_binderClassForBinding:(CPString)aBinding
{
if (aBinding == CPSelectedIndexBinding ||
aBinding == CPSelectedObjectBinding ||
aBinding == CPSelectedTagBinding ||
aBinding == CPSelectedValueBinding ||
aBinding == CPContentBinding ||
aBinding == CPContentObjectsBinding ||
aBinding == CPContentValuesBinding)
{
var capitalizedBinding = aBinding.charAt(0).toUpperCase() + aBinding.substr(1);
return [CPClassFromString(@"_CPPopUpButton" + capitalizedBinding + "Binder") class];
}
return [super _binderClassForBinding:aBinding];
}
@end
@implementation _CPPopUpButtonContentBinder : CPBinder
{
}
- (CPInteger)_getInsertNullOffset
{
var options = [_info objectForKey:CPOptionsKey];
return [options objectForKey:CPInsertsNullPlaceholderBindingOption] ? 1 : 0;
}
- (CPString)_getNullPlaceholder
{
var options = [_info objectForKey:CPOptionsKey],
placeholder = [options objectForKey:CPNullPlaceholderBindingOption] || @"";
if (placeholder === [CPNull null])
placeholder = @"";
return placeholder;
}
- (id)transformValue:(CPArray)contentArray withOptions:(CPDictionary)options
{
// Desactivate the full array transformation forced by super because we don't want this. We want individual transformations (see below).
return contentArray;
}
- (void)setValue:(CPArray)contentArray forBinding:(CPString)aBinding
{
[self _setContent:contentArray];
[self _setContentValuesIfNeeded:contentArray];
}
- (void)valueForBinding:(CPString)aBinding
{
return [self _content];
}
- (void)_setContent:(CPArray)aValue
{
var count = [aValue count],
options = [_info objectForKey:CPOptionsKey],
offset = [self _getInsertNullOffset];
if (count + offset != [_source numberOfItems])
{
[_source removeAllItems];
if (offset)
[_source addItemWithTitle:[self _getNullPlaceholder]];
for (var i = 0; i < count; i++)
{
var item = [[CPMenuItem alloc] initWithTitle:@"" action:NULL keyEquivalent:nil];
[self _setValue:[aValue objectAtIndex:i] forItem:item withOptions:options];
[_source addItem:item];
}
}
else
{
for (var i = 0; i < count; i++)
{
[self _setValue:[aValue objectAtIndex:i] forItem:[_source itemAtIndex:i + offset] withOptions:options];
}
}
}
- (void)_setContentValuesIfNeeded:(CPArray)values
{
var offset = [self _getInsertNullOffset];
if (![_source infoForBinding:CPContentValuesBinding])
{
if (offset)
[[_source itemAtIndex:0] setTitle:[self _getNullPlaceholder]];
var count = [values count];
for (var i = 0; i < count; i++)
[[_source itemAtIndex:i + offset] setTitle:[[values objectAtIndex:i] description]];
}
}
- (void)_setValue:(id)aValue forItem:(CPMenuItem)aMenuItem withOptions:(CPDictionary)options
{
var value = [self _transformValue:aValue withOptions:options];
[aMenuItem setRepresentedObject:value];
}
- (id)_transformValue:(id)aValue withOptions:(CPDictionary)options
{
return [super transformValue:aValue withOptions:options];
}
- (CPArray)_content
{
return [_source valueForKeyPath:@"itemArray.representedObject"];
}
@end
@implementation _CPPopUpButtonContentValuesBinder : _CPPopUpButtonContentBinder
{
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[super _setContent:aValue];
}
- (void)_setValue:(id)aValue forItem:(CPMenuItem)aMenuItem withOptions:(CPDictionary)options
{
if (aValue === [CPNull null])
aValue = nil;
var value = [self _transformValue:aValue withOptions:options];
[aMenuItem setTitle:value];
}
- (CPArray)_content
{
return [_source valueForKeyPath:@"itemArray.title"];
}
@end
var binderForObject = {};
@implementation _CPPopUpButtonSelectionBinder : CPBinder
{
CPString _selectionBinding @accessors;
}
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
{
self = [super initWithBinding:aBinding name:aName to:aDestination keyPath:aKeyPath options:options from:aSource];
if (self)
{
binderForObject[[aSource UID]] = self;
_selectionBinding = aName;
}
return self;
}
+ (void)reverseSetValueForObject:(id)aSource
{
var binder = binderForObject[[aSource UID]];
[binder reverseSetValueFor:[binder _selectionBinding]];
}
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[self setValue:aValue forBinding:aBinding];
}
- (CPInteger)_getInsertNullOffset
{
var options = [[CPBinder infoForBinding:CPContentBinding forObject:_source] objectForKey:CPOptionsKey];
return [options objectForKey:CPInsertsNullPlaceholderBindingOption] ? 1 : 0;
}
@end
@implementation _CPPopUpButtonSelectedIndexBinder : _CPPopUpButtonSelectionBinder
{
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source selectItemAtIndex:aValue + [self _getInsertNullOffset]];
}
- (id)valueForBinding:(CPString)aBinding
{
return [_source indexOfSelectedItem] - [self _getInsertNullOffset];
}
@end
@implementation _CPPopUpButtonSelectedObjectBinder : _CPPopUpButtonSelectionBinder
{
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
var index = [_source indexOfItemWithRepresentedObject:aValue],
offset = [self _getInsertNullOffset];
// If the content binding has the option CPNullPlaceholderBindingOption and the object to select is nil, select the first item (i.e., the placeholder).
// Other cases to consider:
// 1. no binding:
// 1.1 there's no item with a represented object matching the object to select.
// 1.2 the object to select is nil/CPNull
// 2. there's a binding:
// 2.1 there's a CPNullPlaceholderBindingOption:
// 2.1.1 there's no item with a represented object matching the object to select?
// 2.1.2 the object to select is nil/CPNull
// 2.2 there's no CPNullPlaceholderBindingOption:
// 2.2.1 there's no item with a represented object matching the object to select?
// 2.2.2 the object to select is nil/CPNull
// More cases? Behaviour that depends on array controller settings?
if (offset === 1 && index === CPNotFound)
index = 0;
[_source selectItemAtIndex:index];
}
- (id)valueForBinding:(CPString)aBinding
{
return [[_source selectedItem] representedObject];
}
@end
@implementation _CPPopUpButtonSelectedTagBinder : _CPPopUpButtonSelectionBinder
{
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source selectItemWithTag:aValue];
}
- (id)valueForBinding:(CPString)aBinding
{
return [[_source selectedItem] tag];
}
@end
@implementation _CPPopUpButtonSelectedValueBinder : _CPPopUpButtonSelectionBinder
{
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source selectItemWithTitle:aValue];
}
- (id)valueForBinding:(CPString)aBinding
{
return [_source titleOfSelectedItem];
}
@end
var DEPRECATED_CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
+121 -68
View File
@@ -35,7 +35,6 @@ CPPopoverBehaviorApplicationDefined = 0;
CPPopoverBehaviorTransient = 1;
CPPopoverBehaviorSemitransient = 2;
var CPPopoverDelegate_popover_willShow_ = 1 << 0,
CPPopoverDelegate_popover_didShow_ = 1 << 1,
CPPopoverDelegate_popover_shouldClose_ = 1 << 2,
@@ -50,11 +49,14 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
view relative to another one.
Delegate can implement:
popoverShouldClose:(CPPopover)aPopOver
popoverWillShow:(CPPopover)aPopOver
popoverDidShow:(CPPopover)aPopOver
popoverWillClose:(CPPopover)aPopOver
popoverDidClose:(CPPopover)aPopOver
@code
popoverShouldClose:(CPPopover)aPopOver
popoverWillShow:(CPPopover)aPopOver
popoverDidShow:(CPPopover)aPopOver
popoverWillClose:(CPPopover)aPopOver
popoverDidClose:(CPPopover)aPopOver
@endcode
*/
@implementation CPPopover : CPResponder
{
@@ -62,11 +64,9 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
@outlet id _delegate @accessors(getter=delegate);
BOOL _animates @accessors(property=animates);
BOOL _shown @accessors(getter=shown);
int _appearance @accessors(property=appearance);
int _behavior @accessors(getter=behavior);
BOOL _needsCompute;
_CPAttachedWindow _attachedWindow;
int _implementedDelegateMethods;
}
@@ -78,17 +78,15 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Initialize the CPPopover witn default values
@returns anInitialized CPPopover
@returns an initialized CPPopover
*/
- (CPPopover)init
{
if (self = [super init])
{
_animates = YES;
_appearance = CPPopoverAppearanceMinimal;
_behavior = CPPopoverBehaviorApplicationDefined;
_needsCompute = YES;
_shown = NO;
_animates = YES;
_appearance = CPPopoverAppearanceMinimal;
_behavior = CPPopoverBehaviorApplicationDefined;
}
return self;
@@ -101,21 +99,21 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Returns the current rect of the popover
@return CPRect represeting the frame of the popover
@return CGRect representing the frame of the popover
*/
- (CPRect)positioningRect
- (CGRect)positioningRect
{
if (!_attachedWindow || ![_attachedWindow isVisible])
return nil;
if (![_attachedWindow isVisible])
return CGRectMakeZero();
return [_attachedWindow frame];
}
/*! Sets the frame of the popover
@param aRect the desired frame
*/
- (void)setPositioningRect:(CPRect)aRect
- (void)setPositioningRect:(CGRect)aRect
{
if (!_attachedWindow || ![_attachedWindow isVisible])
if (![_attachedWindow isVisible])
return;
[_attachedWindow setFrame:aRect];
}
@@ -123,12 +121,12 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Returns the size of the popover's view
@return CPSize represeting the size of the popover's view
@return CGSize representing the size of the popover's view
*/
- (CPRect)contentSize
- (CGSize)contentSize
{
if (!_attachedWindow || ![_attachedWindow isVisible])
return nil;
if (![_attachedWindow isVisible])
return CGRectMakeZero();
return [[_contentViewController view] frameSize];
}
@@ -145,32 +143,30 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Indicates if CPPopover is visible
@returns YES if visible
@returns \c YES if visible
*/
- (BOOL)shown
- (BOOL)isShown
{
if (!_attachedWindow)
return NO;
return [_attachedWindow isVisible];
}
/*!
Set the behaviour of the CPPopover. It can be
- CPPopoverBehaviorTransient: the popover will be close if another control outside the popover become the responder
- CPPopoverBehaviorApplicationDefined: (DEFAULT) the application is responsible for closing the popover
Set the behavior of the CPPopover. It can be:
@param aBehaviour the desired behaviour
- \c CPPopoverBehaviorTransient: the popover will close if another control outside the popover becomes the responder
- \c CPPopoverBehaviorApplicationDefined: (DEFAULT) the application is responsible for closing the popover
@param aBehavior the desired behavior
*/
- (void)setBehaviour:(int)aBehaviour
- (void)setBehavior:(int)aBehavior
{
if (_behavior == aBehaviour)
if (_behavior == aBehavior)
return;
_behavior = aBehaviour;
_needsCompute = YES;
_behavior = aBehavior;
[_attachedWindow setStyleMask:[self styleMaskForBehavior]];
}
- (void)setDelegate:(id)aDelegate
{
if (_delegate === aDelegate)
@@ -203,20 +199,31 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
@param positioningRect if set, the popover will be positionned to a random rect relative to the window
@param positioningView if set, the popover will be positioned relative to this view
@param preferredEdge: CPRectEdge representing the preferred positioning.
@param preferredEdge: \c CPRectEdge representing the preferred positioning.
*/
- (void)showRelativeToRect:(CPRect)positioningRect ofView:(CPView)positioningView preferredEdge:(CPRectEdge)preferredEdge
- (void)showRelativeToRect:(CGRect)positioningRect ofView:(CPView)positioningView preferredEdge:(CPRectEdge)preferredEdge
{
if (!positioningView)
[CPException raise:CPInvalidArgumentException reason:"positionView must not be nil"];
if (!_contentViewController)
[CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"];
// If the popover is currently closing, do nothing. That is what Cocoa does.
if ([_attachedWindow isClosing])
return;
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willShow_)
[_delegate popoverWillShow:self];
if (!_contentViewController)
[CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"];
if (_needsCompute || !_attachedWindow)
if (!_attachedWindow)
{
var styleMask = (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : nil;
_attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:styleMask];
_attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:[self styleMaskForBehavior]];
var parentWindow = [positioningView window];
if (![parentWindow isKindOfClass:_CPAttachedWindow])
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(parentWindowWillClose:) name:CPWindowWillCloseNotification object:parentWindow];
}
[_attachedWindow setAppearance:_appearance];
@@ -225,34 +232,40 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
[_attachedWindow setMovableByWindowBackground:NO];
[_attachedWindow setFrame:[_attachedWindow frameRectForContentRect:[[_contentViewController view] frame]]];
[_attachedWindow setContentView:[_contentViewController view]];
if (positioningRect)
[_attachedWindow positionRelativeToRect:positioningRect preferredEdge:preferredEdge];
else if (positioningView)
[_attachedWindow positionRelativeToView:positioningView preferredEdge:preferredEdge];
else
[CPException raise:CPInvalidArgumentException reason:@"a value must be passed for positioningRect or positioningView"];
[_attachedWindow positionRelativeToRect:positioningRect ofView:positioningView preferredEdge:preferredEdge];
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didShow_)
[_delegate popoverDidShow:self];
}
- (unsigned)styleMaskForBehavior
{
return (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : 0;
}
/*!
Closes the popover
*/
- (void)close
{
if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
if (![_delegate popoverShouldClose:self])
return;
[self _close];
}
/*!
Closes the popover
*/
- (void)_close
{
if ([_attachedWindow isClosing] || ![self isShown])
return;
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willClose_)
[_delegate popoverWillClose:self];
[_attachedWindow close];
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didClose_)
[_delegate popoverDidClose:self];
// popoverDidClose will be sent from attachedWindowDidClose, since
// the attached window will close asynchronously when animating.
}
@@ -262,11 +275,18 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Close the popover
@param aSender the sender of the action
@param sender the sender of the action
*/
- (IBAction)performClose:(id)aSender
- (IBAction)performClose:(id)sender
{
[self close];
if ([_attachedWindow isClosing])
return;
if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
if (![_delegate popoverShouldClose:self])
return;
[self _close];
}
@@ -276,16 +296,51 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*! @ignore */
- (BOOL)attachedWindowShouldClose:(_CPAttachedWindow)anAttachedWindow
{
[self close];
[self performClose:self];
// we return NO, because we want the CPPopover to compute
// if the attached can be close in order to send delegate messages
// We return NO, because we want the CPPopover to determine
// if the attached window can be closed and to give us a chance
// to send delegate messages.
return NO;
}
/*! @ignore */
- (void)attachedWindowDidClose:(_CPAttachedWindow)anAttachedWindow
{
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didClose_)
[_delegate popoverDidClose:self];
}
#pragma mark -
#pragma mark Notifications
/*!
@ignore
This method is called only when a non-popover parent window
is closing. In that case popovers should order out.
*/
- (void)parentWindowWillClose:(CPNotification)aNotification
{
[_attachedWindow orderOut:nil];
[self performClose:nil];
}
@end
var CPPopoverNeedsComputeKey = @"CPPopoverNeedsComputeKey",
@implementation CPPopover (Deprecated)
- (void)setBehaviour:(int)aBehavior
{
_CPReportLenientDeprecation(self, _cmd, @selector(setBehavior:));
[self setBehavior:aBehavior];
}
@end
var CPPopoverNeedsNewAttachedWindowKey = @"CPPopoverNeedsNewAttachedWindowKey",
CPPopoverAppearanceKey = @"CPPopoverAppearanceKey",
CPPopoverAnimatesKey = @"CPPopoverAnimatesKey",
CPPopoverContentViewControllerKey = @"CPPopoverContentViewControllerKey",
@@ -300,12 +355,11 @@ var CPPopoverNeedsComputeKey = @"CPPopoverNeedsComputeKey",
if (self)
{
_needsCompute = [aCoder decodeIntForKey:CPPopoverNeedsComputeKey];
_appearance = [aCoder decodeIntForKey:CPPopoverAppearanceKey];
_animates = [aCoder decodeBoolForKey:CPPopoverAnimatesKey];
_contentViewController = [aCoder decodeObjectForKey:CPPopoverContentViewControllerKey];
[self setDelegate:[aCoder decodeObjectForKey:CPPopoverDelegateKey]];
[self setBehaviour:[aCoder decodeIntForKey:CPPopoverBehaviorKey]];
[self setBehavior:[aCoder decodeIntForKey:CPPopoverBehaviorKey]];
}
return self;
}
@@ -314,9 +368,8 @@ var CPPopoverNeedsComputeKey = @"CPPopoverNeedsComputeKey",
{
[super encodeWithCoder:aCoder];
[aCoder encodeBool:_needsCompute forKey:CPPopoverNeedsComputeKey];
[aCoder encodeInt:_appearance forKey:CPPopoverAppearanceKey];
[aCoder encodeObject:_animates forKey:CPPopoverAnimatesKey];
[aCoder encodeBool:_animates forKey:CPPopoverAnimatesKey];
[aCoder encodeObject:_contentViewController forKey:CPPopoverContentViewControllerKey];
[aCoder encodeObject:_delegate forKey:CPPopoverDelegateKey];
[aCoder encodeInt:_behavior forKey:CPPopoverBehaviorKey];
+43 -26
View File
@@ -71,8 +71,6 @@ var CPProgressIndicatorSpinningStyleColors = nil,
BOOL _isDisplayedWhenStoppedSet;
BOOL _isDisplayedWhenStopped;
CPView _barView;
}
/*
@@ -80,7 +78,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
*/
+ (void)initialize
{
if (self != [CPProgressIndicator class])
if (self !== [CPProgressIndicator class])
return;
var bundle = [CPBundle bundleForClass:self];
@@ -88,9 +86,9 @@ var CPProgressIndicatorSpinningStyleColors = nil,
CPProgressIndicatorSpinningStyleColors = [];
CPProgressIndicatorSpinningStyleColors[CPMiniControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]];
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleMini.gif"] size:CGSizeMake(16.0, 16.0)]];
CPProgressIndicatorSpinningStyleColors[CPSmallControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]];
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleSmall.gif"] size:CGSizeMake(32.0, 32.0)]];
CPProgressIndicatorSpinningStyleColors[CPRegularControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]];
@@ -122,11 +120,11 @@ var CPProgressIndicatorSpinningStyleColors = nil,
// Bar Style
var prefixes = [
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle],
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle]
];
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle],
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle]
];
for (var i = 0, count = prefixes.length; i < count; i++)
{
@@ -410,27 +408,38 @@ var CPProgressIndicatorSpinningStyleColors = nil,
if (_style == CPProgressIndicatorSpinningStyle)
return;
if (!_barView)
{
_barView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 16.0)];
[self addSubview:_barView];
}
var barView = [self layoutEphemeralSubviewNamed:"bar-view"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[_barView setBackgroundColor:_CPControlThreePartImagePattern(
[barView setBackgroundColor:_CPControlThreePartImagePattern(
NO,
CPProgressIndicatorStyleSizes,
CPProgressIndicatorClassName,
@"Bar",
CPProgressIndicatorStyleIdentifiers[_style],
_CPControlIdentifierForControlSize(_controlSize))];
}
var width = CGRectGetWidth([self bounds]),
barWidth = width * ((_doubleValue - _minValue) / (_maxValue - _minValue));
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
}
if (barWidth > 0.0 && barWidth < 4.0)
barWidth = 4.0;
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
{
if (aViewName === @"bar-view" && _style !== CPProgressIndicatorSpinningStyle)
{
var width = CGRectGetWidth([self bounds]),
barWidth = width * ((_doubleValue - _minValue) / (_maxValue - _minValue));
[_barView setFrameSize:CGSizeMake(barWidth, 16.0)];
if (barWidth > 0.0 && barWidth < 4.0)
barWidth = 4.0;
return _CGRectMake(0, 0, barWidth, 16.0);
}
return nil;
}
/* @ignore */
@@ -440,9 +449,10 @@ var CPProgressIndicatorSpinningStyleColors = nil,
{
if (_style == CPProgressIndicatorSpinningStyle)
{
[_barView removeFromSuperview];
_barView = nil;
// This will cause the bar view to go away due to having a nil rect when _style == CPProgressIndicatorSpinningStyle.
[self layoutEphemeralSubviewNamed:"bar-view"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[self setBackgroundColor:CPProgressIndicatorSpinningStyleColors[_controlSize]];
}
@@ -477,10 +487,12 @@ var CPProgressIndicatorSpinningStyleColors = nil,
_doubleValue = [aCoder decodeObjectForKey:@"_doubleValue"];
_controlSize = [aCoder decodeObjectForKey:@"_controlSize"];
_isIndeterminate = [aCoder decodeObjectForKey:@"_isIndeterminate"];
_style = [aCoder decodeObjectForKey:@"_style"];
_style = [aCoder decodeIntForKey:@"_style"];
_isAnimating = [aCoder decodeObjectForKey:@"_isAnimating"];
_isDisplayedWhenStoppedSet = [aCoder decodeObjectForKey:@"_isDisplayedWhenStoppedSet"];
_isDisplayedWhenStopped = [aCoder decodeObjectForKey:@"_isDisplayedWhenStopped"];
[self updateBackgroundColor];
}
return self;
@@ -488,14 +500,19 @@ var CPProgressIndicatorSpinningStyleColors = nil,
- (void)encodeWithCoder:(CPCoder)aCoder
{
// Don't encode the background colour. It can be recreated based on the flags and if encoded causes hardcoded
// image paths in the cib while just wasting space.
var backgroundColor = [self backgroundColor];
[self setBackgroundColor:nil];
[super encodeWithCoder:aCoder];
[self setBackgroundColor:backgroundColor];
[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 encodeInt:_style forKey:@"_style"];
[aCoder encodeObject:_isAnimating forKey:@"_isAnimating"];
[aCoder encodeObject:_isDisplayedWhenStoppedSet forKey:@"_isDisplayedWhenStoppedSet"];
[aCoder encodeObject:_isDisplayedWhenStopped forKey:@"_isDisplayedWhenStopped"];
+17
View File
@@ -181,6 +181,23 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
[aCoder encodeObject:_radioGroup forKey:CPRadioRadioGroupKey];
}
- (CPImage)image
{
return [self currentValueForThemeAttribute:@"image"];
}
- (CPImage)alternateImage
{
return [self currentValueForThemeAttribute:@"image"];
}
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
var startedTracking = [super startTrackingAt:aPoint];
[self highlight:YES];
return startedTracking;
}
@end
@implementation CPRadioGroup : CPObject
+73 -24
View File
@@ -82,6 +82,22 @@
}
/*! @cond */
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding == CPValueBinding)
return [CPPredicateEditorValueBinder class];
return [super _binderClassForBinding:theBinding];
}
- (id)_replacementKeyPathForBinding:(CPString)aBinding
{
if (aBinding == CPValueBinding)
return @"predicate";
return [super _replacementKeyPathForBinding:aBinding];
}
- (void)_initRuleEditorShared
{
[super _initRuleEditorShared];
@@ -157,28 +173,40 @@
return trees;
}
- (id)_mergeTree:(id)tree
- (CPMutableArray)_mergeTree:(CPArray)aTree
{
var merged = [CPMutableArray array],
titles = [CPMutableArray array],
count = [tree count];
var mergedTree = [CPMutableArray array];
if (aTree == nil)
return mergedTree;
for (var i = 0; i < count; i++)
var icount = [aTree count];
for (var i = 0; i < icount; i++)
{
var t = tree[i],
title = [CPString stringWithString:[t title]];
var anode = [aTree objectAtIndex:i],
jcount = [mergedTree count],
merged = NO;
if ([titles containsObject:title])
for (var j = 0; j < jcount; j++)
{
CPLogConsole("CPPredicateEditor does not support templates merging yet. Ignoring duplicate template: " + [t description]);
continue;
var mergednode = [mergedTree objectAtIndex:j];
if ([[mergednode title] isEqualToString:[anode title]])
{
var children1 = [mergednode children],
children2 = [anode children],
children12 = [children1 arrayByAddingObjectsFromArray:children2],
mergedChildren = [self _mergeTree:children12];
[mergednode setChildren:mergedChildren];
merged = YES;
}
}
[merged addObject:t];
[titles addObject:title];
if (!merged)
[mergedTree addObject:anode];
}
return merged;
return mergedTree;
}
- (id)_constructTreeForTemplate:(CPPredicateEditorRowTemplate)aTemplate
@@ -227,14 +255,19 @@
- (void)setObjectValue:(id)objectValue
{
if (![[objectValue predicateFormat] isEqualToString:[[super predicate] predicateFormat]]) // ??
var ov = [self objectValue];
if ((ov == nil) != (objectValue == nil) || ![ov isEqual:objectValue])
{
[self _setPredicate:objectValue];
[self _reflectPredicate:objectValue];
}
}
- (void)_reflectPredicate:(id)predicate
{
var animation = _currentAnimation;
_currentAnimation = nil;
_sendAction = NO;
if (predicate != nil)
{
@@ -311,9 +344,9 @@
treeChild = [rootItems objectAtIndex:i];
var currentView = [templateViews objectAtIndex:[treeChild indexIntoTemplate]],
menuItemIndex = [treeChild menuItemIndex];
title = [treeChild title];
if (menuItemIndex == -1 || [[treeChild title] isEqual:[currentView titleOfSelectedItem]])
if (title == nil || [title isEqual:[currentView titleOfSelectedItem]])
{
var node = [_CPPredicateEditorRowNode rowNodeFromTree:treeChild];
[node applyTemplate:aTemplate withViews:templateViews forOriginalTemplate:originalTemplate];
@@ -336,16 +369,15 @@
- (void)_updatePredicate
{
[self willChangeValueForKey:@"objectValue"];
[self _updatePredicateFromRows];
[self didChangeValueForKey:@"objectValue"];
}
- (void)_updatePredicateFromRows
{
var rootRowsArray = [super _rootRowsArray],
subpredicates = [CPMutableArray array],
count = count2 = [rootRowsArray count],
count,
count2 = count = [rootRowsArray count],
predicate;
while (count--)
@@ -362,7 +394,7 @@
else
predicate = [[CPCompoundPredicate alloc] initWithType:[self _compoundPredicateTypeForRootRows] subpredicates:subpredicates];
[super _setPredicate:predicate];
[self _setPredicate:predicate];
}
- (id)_predicateFromRowItem:(id)rowItem
@@ -373,12 +405,13 @@
if (rowType == CPRuleEditorRowTypeCompound)
{
var subrows = [rowItem valueForKey:_subrowsArrayKeyPath],
count = [subrows count];
count = [subrows count];
for (var i = 0; i < count; i++)
{
var subrow = [subrows objectAtIndex:i];
var predicate = [self _predicateFromRowItem:subrow];
var subrow = [subrows objectAtIndex:i],
predicate = [self _predicateFromRowItem:subrow];
[subpredicates addObject:predicate];
}
}
@@ -414,7 +447,6 @@
- (void)_sendRuleAction
{
[self _updatePredicate];
[super _sendRuleAction];
}
@@ -483,9 +515,11 @@ var CPPredicateTemplatesKey = @"CPPredicateTemplates";
- (id)initWithCoder:(id)aCoder
{
self = [super initWithCoder:aCoder];
if (self != nil)
{
var nibTemplates = [aCoder decodeObjectForKey:CPPredicateTemplatesKey];
if (nibTemplates != nil)
[self setRowTemplates:nibTemplates];
}
@@ -501,4 +535,19 @@ var CPPredicateTemplatesKey = @"CPPredicateTemplates";
@end
@implementation CPPredicateEditorValueBinder : CPBinder
{
}
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[_source _reflectPredicate:nil];
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source _reflectPredicate:aValue];
}
@end
/*! @endcond */
@@ -185,7 +185,8 @@ CPTransformableAttributeType = 1800;
if (![[self operators] containsObject:[predicate predicateOperatorType]])
return 0;
if (!_rightIsWildcard && ![[self rightExpressions] containsObject:[predicate rightExpression]]) return 0;
if (!_rightIsWildcard && ![[self rightExpressions] containsObject:[predicate rightExpression]])
return 0;
return 1;
}
@@ -280,7 +281,7 @@ CPTransformableAttributeType = 1800;
*/
- (CPArray)leftExpressions
{
if (_templateType ==1 && !_leftIsWildcard)
if (_templateType == 1 && !_leftIsWildcard)
{
var view = [_views objectAtIndex:0];
return [[view itemArray] valueForKey:@"representedObject"];
@@ -685,6 +686,7 @@ CPTransformableAttributeType = 1800;
[textField setBordered:YES];
[textField setEditable:YES];
[textField setFont:[CPFont systemFontOfSize:10]];
[textField setSendsActionOnEndEditing:YES];
return textField;
}
File diff suppressed because it is too large Load Diff
+17 -20
View File
@@ -14,25 +14,21 @@
+ (id)rowNodeFromTree:(id)aTree
{
var mapTable = {};
return [_CPPredicateEditorRowNode _rowNodeFromTree:aTree withTemplateTable:mapTable];
return [_CPPredicateEditorRowNode _rowNodeFromTree:aTree withTemplateTable:{}];
}
+ (id)_rowNodeFromTree:(id)aTree withTemplateTable:(id)templateTable
{
var node,
views,
var views,
copiedContainer;
node = [[_CPPredicateEditorRowNode alloc] init];
node.tree = aTree;
var uuid = [[aTree template] UID],
cachedNode = templateTable[uuid],
node = [[_CPPredicateEditorRowNode alloc] init];
var template = [aTree template],
uuid = [template UID];
[node setTree:aTree];
var cachedNode = templateTable[uuid];
if (cachedNode == nil)
if (!cachedNode)
{
views = [CPMutableArray array];
copiedContainer = [CPMutableArray array];
@@ -44,8 +40,8 @@
copiedContainer = [cachedNode copiedTemplateContainer];
}
node.templateViews = views;
node.copiedTemplateContainer = copiedContainer;
[node setTemplateViews:views];
[node setCopiedTemplateContainer:copiedContainer];
var nodeChildren = [CPMutableArray array],
treeChildren = [aTree children],
@@ -66,7 +62,9 @@
- (BOOL)applyTemplate:(id)template withViews:(id)views forOriginalTemplate:(id)originalTemplate
{
var t = [tree template];
var t = [tree template],
count = [children count];
if (t !== template)
{
[templateViews setArray:views];
@@ -74,8 +72,7 @@
[copiedTemplateContainer addObject:template];
}
var count = [children count];
for (var i; i < count; i++)
for (var i = 0; i < count; i++)
[children[i] applyTemplate:template withViews:views forOriginalTemplate:originalTemplate];
}
@@ -89,9 +86,8 @@
- (void)copyTemplateIfNecessary
{
if ([copiedTemplateContainer count] == 0)
if ([copiedTemplateContainer count] === 0)
{
CPLogConsole("COPYING TEMPLATE");
var copy = [[tree template] copy];
[copiedTemplateContainer addObject:copy];
[templateViews addObjectsFromArray:[copy templateViews]];
@@ -118,7 +114,8 @@
- (id)displayValue
{
var title = [self title];
if (title != nil)
if (title !== nil)
return title;
return [self templateView];
@@ -129,4 +126,4 @@
return [CPString stringWithFormat:@"<%@ %@ %@ tree:%@ tviews:%@", [self className],[self UID], [self title], [tree UID], [templateViews description]];
}
@end
@end
+13 -9
View File
@@ -7,7 +7,7 @@
@import <Foundation/CPDictionary.j>
@import <Foundation/CPString.j>
var regex = new RegExp("\"(.+)\"\\s*=\\s*\"(.+)\"\\s*;\\s*(//.+)?");
var LocalizerStringsRegex = new RegExp("\"(.+)\"\\s*=\\s*\"(.+)\"\\s*;\\s*(//.+)?");
@implementation _CPRuleEditorLocalizer : CPObject
{
@@ -24,9 +24,10 @@ var regex = new RegExp("\"(.+)\"\\s*=\\s*\"(.+)\"\\s*;\\s*(//.+)?");
- (void)reloadIfNeeded
{
if (connection != nil) // Connection waiting
if (connection !== nil) // Connection waiting
{
connection = nil;
var data = [CPURLConnection sendSynchronousRequest:request returningResponse:NULL];
[self loadContent:[data rawString]];
}
@@ -34,7 +35,7 @@ var regex = new RegExp("\"(.+)\"\\s*=\\s*\"(.+)\"\\s*;\\s*(//.+)?");
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)rawString
{
if (connection != nil && rawString != nil)
if (connection !== nil && rawString !== nil)
[self loadContent:rawString];
connection = nil;
@@ -49,10 +50,12 @@ var regex = new RegExp("\"(.+)\"\\s*=\\s*\"(.+)\"\\s*;\\s*(//.+)?");
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)
var match = LocalizerStringsRegex.exec(line);
if (match && match.length >= 3)
[dict setObject:match[2] forKey:match[1]];
}
}
@@ -64,12 +67,13 @@ var regex = new RegExp("\"(.+)\"\\s*=\\s*\"(.+)\"\\s*;\\s*(//.+)?");
{
[self reloadIfNeeded];
if (_dictionary != nil && aString != nil)
if (_dictionary !== nil && aString !== nil)
{
var localized = [_dictionary objectForKey:aString];
if (localized != nil)
return localized;
if (localized !== nil)
return localized;
}
return aString;
}
}
+72 -53
View File
@@ -3,62 +3,80 @@
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
var GRADIENT_START_COLOR = "#fcfcfc",
GRADIENT_END_COLOR = "#dfdfdf",
BORDER_COLOR = "#BDBDBD";
var GRADIENT_NORMAL,
GRADIENT_HIGHLIGHTED,
IE_FILTER = "progid:DXImageTransform.Microsoft.gradient(startColorstr='#fcfcfc', endColorstr='#dfdfdf')";
GRADIENT_PROPERTY;
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
{
GRADIENT_NORMAL = "-webkit-gradient(linear, left top, left bottom, from(" + GRADIENT_START_COLOR + "), to(" + GRADIENT_END_COLOR + "))",
GRADIENT_HIGHLIGHTED = "-webkit-gradient(linear, left top, left bottom, from(" + GRADIENT_END_COLOR + "), to(" + GRADIENT_START_COLOR + "))";
GRADIENT_PROPERTY = "background";
}
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
{
GRADIENT_NORMAL = "-moz-linear-gradient(top, " + GRADIENT_START_COLOR + ", " + GRADIENT_END_COLOR + ")",
GRADIENT_HIGHLIGHTED = "-moz-linear-gradient(top, " + GRADIENT_END_COLOR + ", " + GRADIENT_START_COLOR + ")";
GRADIENT_PROPERTY = "background";
}
else if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
GRADIENT_NORMAL = "progid:DXImageTransform.Microsoft.gradient(startColorstr='" + GRADIENT_START_COLOR + "', endColorstr='" + GRADIENT_END_COLOR + "')";
GRADIENT_HIGHLIGHTED = "progid:DXImageTransform.Microsoft.gradient(startColorstr='" + GRADIENT_END_COLOR + "', endColorstr='" + GRADIENT_START_COLOR + "')";
GRADIENT_PROPERTY = "filter";
}else
{
GRADIENT_NORMAL = GRADIENT_START_COLOR;
GRADIENT_HIGHLIGHTED = GRADIENT_END_COLOR;
GRADIENT_PROPERTY = "background";
}
@implementation _CPRuleEditorPopUpButton : CPPopUpButton
{
CPInteger radius;
}
+ (void)initialize
- (void)_sharedInit
{
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))";
}
[self setBordered:NO];
var style = _DOMElement.style;
style.border = "1px solid " + BORDER_COLOR;
style[GRADIENT_PROPERTY] = GRADIENT_NORMAL;
}
- (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 _sharedInit];
[self setTextColor:[CPColor colorWithWhite:101 / 255 alpha:1]];
[self setBordered:NO];
}
return self;
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
[self _sharedInit];
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];
var superview = [self superview];
return ![superview isKindOfClass:[_CPRuleEditorViewSlice]] || [superview isEditable];
}
- (BOOL)trackMouse:(CPEvent)theEvent
@@ -80,13 +98,10 @@ var GRADIENT_NORMAL,
- (void)layoutSubviews
{
radius = FLOOR(CGRectGetHeight([self bounds])/2);
radius = FLOOR(CGRectGetHeight([self bounds]) / 2);
var style = _DOMElement.style,
radiusCSS = radius + "px";
//style.webkitBorderRadius = radiusCSS;
//style.mozBorderRadius = radiusCSS;
style.borderRadius = radiusCSS;
[super layoutSubviews];
@@ -94,20 +109,19 @@ var GRADIENT_NORMAL,
- (void)drawRect:(CGRect)aRect
{
var bounds = [self bounds],
context = [[CPGraphicsContext currentContext] graphicsPort];
var arrow_width = FLOOR(CGRectGetHeight(bounds)/3.5);
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds],
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 lineToPoint:CGPointMake(arrow_width / 2, arrow_width + 1)];
[arrowsPath closePath];
CGContextSetFillColor(context, [CPColor colorWithWhite:101/255 alpha:1]);
CGContextSetFillColor(context, [CPColor colorWithWhite:101 / 255 alpha:1]);
[arrowsPath fill];
CGContextScaleCTM(context, 1 , -1);
@@ -121,37 +135,42 @@ var GRADIENT_NORMAL,
CPInteger radius;
}
- (void)_sharedInit
{
[self setBordered:NO];
var style = _DOMElement.style;
style.border = "1px solid " + BORDER_COLOR;
style[GRADIENT_PROPERTY] = GRADIENT_NORMAL;
}
- (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;
}
if (self = [super initWithFrame:aFrame])
[self _sharedInit];
return self;
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
[self _sharedInit];
return self;
}
- (void)layoutSubviews
{
radius = FLOOR(CGRectGetHeight([self bounds])/2);
radius = FLOOR(CGRectGetHeight([self bounds]) / 2);
var style = _DOMElement.style,
radiusCSS = radius + "px";
style.borderRadius = radiusCSS;
style.backgroundImage = ([self isHighlighted]) ? GRADIENT_HIGHLIGHTED : GRADIENT_NORMAL;
style[GRADIENT_PROPERTY] = ([self isHighlighted]) ? GRADIENT_HIGHLIGHTED : GRADIENT_NORMAL;
[super layoutSubviews];
}
@end
+46 -33
View File
@@ -41,8 +41,8 @@ var CONTROL_HEIGHT = 16.,
_addButton = [self _createAddRowButton];
_subtractButton = [self _createDeleteRowButton];
//[_addButton setToolTip:[_ruleEditor _toolTipForAddSimpleRowButton]];
//[_subtractButton setToolTip:[_ruleEditor _toolTipForDeleteRowButton]];
[_addButton setToolTip:[_ruleEditor _toolTipForAddSimpleRowButton]];
[_subtractButton setToolTip:[_ruleEditor _toolTipForDeleteRowButton]];
[_addButton setHidden:!editable];
[_subtractButton setHidden:!editable];
[self addSubview:_addButton];
@@ -54,26 +54,36 @@ var CONTROL_HEIGHT = 16.,
[center addObserver:self selector:@selector(_textDidChange:) name:CPControlTextDidChangeNotification object:nil];
}
- (CPButton)_createAddRowButton
- (CPButton)_createRowButton
{
var button = [[_CPRuleEditorButton alloc] initWithFrame:CGRectMakeZero()];
[button setImage:[_ruleEditor _addImage]];
[button setFont:[CPFont boldFontWithName:@"Apple Symbol" size:12.0]];
[button setTextColor:[CPColor colorWithWhite:150 / 255 alpha:1]];
[button setAlignment:CPCenterTextAlignment];
[button setAutoresizingMask:CPViewMinXMargin];
[button setImagePosition:CPImageOnly];
return button;
}
- (CPButton)_createAddRowButton
{
var button = [self _createRowButton];
[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]];
var button = [self _createRowButton];
[button setImage:[_ruleEditor _removeImage]];
[button setAction:@selector(_deleteOption:)];
[button setTarget:self];
[button setAutoresizingMask:CPViewMinXMargin];
return button;
}
@@ -87,12 +97,14 @@ var CONTROL_HEIGHT = 16.,
- (CPPopUpButton)_createPopUpButtonWithItems:(CPArray)itemsArray selectedItemIndex:(int)index
{
var title = [[itemsArray objectAtIndex:index] title];
var font = [_ruleEditor font],
var title = [[itemsArray objectAtIndex:index] title],
font = [_ruleEditor font],
width = [title sizeWithFont:font].width + 20,
rect = CGRectMake(0, 0, (width - width % 40) + 80, CONTROL_HEIGHT);
rect = CGRectMake(0, 0, (width - width % 40) + 80, CONTROL_HEIGHT),
var popup = [[_CPRuleEditorPopUpButton alloc] initWithFrame:rect];
popup = [[_CPRuleEditorPopUpButton alloc] initWithFrame:rect];
[popup setTextColor:[CPColor colorWithWhite:101 / 255 alpha:1]];
[popup setValue:font forThemeAttribute:@"font"];
var count = [itemsArray count];
@@ -111,13 +123,14 @@ var CONTROL_HEIGHT = 16.,
- (_CPRuleEditorTextField)_createStaticTextFieldWithStringValue:(CPString )text
{
text = [[_ruleEditor standardLocalizer] localizedStringForString:text];
var textField = [[_CPRuleEditorTextField alloc] initWithFrame:CPMakeRect(0, 0, 200, CONTROL_HEIGHT)],
refont = [_ruleEditor font],
font = [CPFont fontWithName:[refont familyName] size:[refont size] + 2],
localizedText = [[_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 setStringValue:localizedText];
[textField sizeToFit];
return textField;
@@ -182,9 +195,10 @@ var CONTROL_HEIGHT = 16.,
parent,
numberOfCriteria,
numberOfChildren,
firstResponderIndex;
firstResponderIndex,
var ruleItems = [CPMutableArray array];
ruleItems = [CPMutableArray array],
responder = [[self window] firstResponder];
[self _emptyRulePartSubviews];
@@ -192,7 +206,6 @@ var CONTROL_HEIGHT = 16.,
numberOfCriteria = [criteria count];
firstResponderIndex = numberOfCriteria - 1;
var responder = [[self window] firstResponder];
if (responder)
firstResponderIndex = [_ruleOptionViews indexOfObjectIdenticalTo:responder];
@@ -213,16 +226,16 @@ var CONTROL_HEIGHT = 16.,
numberOfChildren = [childItems count];
if (numberOfChildren > 1)
{
var menuItems = [CPMutableArray arrayWithCapacity:numberOfChildren];
var menuItems = [CPMutableArray arrayWithCapacity:numberOfChildren],
selectedIndex = [childItems indexOfObject:criterion];
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];
var childItem = [childItems objectAtIndex:j],
childValue = [childValues objectAtIndex:j];
if ([childValue isKindOfClass:[CPMenuItem class]])
{
@@ -250,8 +263,8 @@ var CONTROL_HEIGHT = 16.,
}
else
{
var value = [childValues objectAtIndex:0];
var type = [value valueType];
var value = [childValues objectAtIndex:0],
type = [value valueType];
if (type === 0)
ruleView = [self _createStaticTextFieldWithStringValue:value];
@@ -308,7 +321,6 @@ var CONTROL_HEIGHT = 16.,
- (void)layoutSubviews
{
// CPLogConsole(_cmd);
[self _relayoutSubviewsWidthChanged:YES];
}
@@ -319,11 +331,11 @@ var CONTROL_HEIGHT = 16.,
leftButtonMinX,
rowHeight = [_ruleEditor rowHeight],
count = [_ruleOptionViews count],
sliceFrame = [self frame];
sliceFrame = [self frame],
buttonFrame = CGRectMake(CGRectGetWidth(sliceFrame) - BUTTON_HEIGHT - [self _rowButtonsRightHorizontalPadding], ([_ruleEditor rowHeight] - BUTTON_HEIGHT) / 2 - 2, BUTTON_HEIGHT, BUTTON_HEIGHT);
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];
@@ -339,7 +351,7 @@ var CONTROL_HEIGHT = 16.,
var ruleOptionView = _ruleOptionViews[i],
optionFrame = _ruleOptionFrames[i];
optionFrame.origin.y = (rowHeight - CGRectGetHeight(optionFrame))/2 - 2;
optionFrame.origin.y = (rowHeight - CGRectGetHeight(optionFrame)) / 2 - 2;
if (widthChanged)
{
optionFrame.origin.x = optionViewOriginX;
@@ -418,7 +430,7 @@ var CONTROL_HEIGHT = 16.,
- (float)_rowButtonsRightHorizontalPadding
{
return 10.;
return ([[_ruleEditor superview] isKindOfClass:[CPClipView class]]) ? 18. : 10.;
}
- (void)_setRowTypeToAddFromPlusButton:(int)type
@@ -473,13 +485,14 @@ var CONTROL_HEIGHT = 16.,
- (void)_sendRuleAction:(id)sender
{
[_ruleEditor _updatePredicate];
[_ruleEditor _sendRuleAction];
}
- (void)_textDidChange:(CPNotification)aNotif
{
if ([[aNotif object] superview] == self && [_ruleEditor _sendsActionOnIncompleteTextChange])
[_ruleEditor _sendRuleAction];
[self _sendRuleAction:nil];
}
@end
+124 -79
View File
@@ -30,40 +30,42 @@
@import "CPScroller.j"
@import "CPView.j"
#define SHOULD_SHOW_CORNER_VIEW() (_scrollerStyle === CPScrollerStyleLegacy && _verticalScroller && ![_verticalScroller isHidden])
/*! @ignore */
var _isSystemUsingOverlayScrollers = function()
{
#if PLATFORM(DOM)
var inner = document.createElement('p'),
outer = document.createElement('div');
var inner = document.createElement('p'),
outer = document.createElement('div');
inner.style.width = "100%";
inner.style.height = "200px";
inner.style.width = "100%";
inner.style.height = "200px";
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild (inner);
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild (inner);
document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2)
w2 = outer.clientWidth;
document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2)
w2 = outer.clientWidth;
document.body.removeChild (outer);
document.body.removeChild (outer);
return (w1 - w2 == 0);
return (w1 - w2 == 0);
#else
return NO;
return NO;
#endif
}
};
/*!
@ingroup appkit
@@ -123,6 +125,9 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
+ (void)initialize
{
if (self !== [CPScrollView class])
return;
var globalValue = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPScrollersGlobalStyle"];
if (globalValue == nil || globalValue == -1)
@@ -272,7 +277,19 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
}
/*!
Set the delegate of the scroll view
Sets the delegate of the scroll view.
Possible delegate methods to implement are listed below.
Notifies the delegate when the scroll view is about to scroll.
@code
- (void)scrollViewWillScroll:(CPScrollView)aScrollView
@endcode
Notifies the delegate when the scroll view has finished scrolling.
@code
- (void)scrollViewDidScroll:(CPScrollView)aScrollView
@endcode
*/
- (void)setDelegate:(id)aDelegate
{
@@ -737,35 +754,42 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
{
[_horizontalScroller setStyle:_scrollerStyle];
[_horizontalScroller unsetThemeState:CPThemeStateSelected];
switch (_scrollerKnobStyle)
{
case CPScrollerKnobStyleLight:
[_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
[_horizontalScroller setThemeState:CPThemeStateScrollerKnobLight];
break;
case CPScrollerKnobStyleDark:
[_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
[_horizontalScroller setThemeState:CPThemeStateScrollerKnobDark];
break;
default:
[_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
[_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
}
}
if (_hasVerticalScroller)
{
[_verticalScroller setStyle:_scrollerStyle];
[_verticalScroller unsetThemeState:CPThemeStateSelected];
switch (_scrollerKnobStyle)
{
case CPScrollerKnobStyleLight:
[_verticalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
[_verticalScroller setThemeState:CPThemeStateScrollerKnobLight];
break;
case CPScrollerKnobStyleDark:
[_verticalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
[_verticalScroller setThemeState:CPThemeStateScrollerKnobDark];
break;
default:
[_verticalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
[_verticalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
@@ -776,6 +800,7 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
{
if (_timerScrollersHide)
[_timerScrollersHide invalidate];
_timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
[[self bottomCornerView] setHidden:YES];
}
@@ -813,10 +838,15 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
_cornerView = documentCornerView;
if (_cornerView)
{
[_cornerView setHidden:!SHOULD_SHOW_CORNER_VIEW()];
[self addSubview:_cornerView];
}
}
[self reflectScrolledClipView:_contentView];
[documentHeaderView setNeedsLayout];
[documentHeaderView setNeedsDisplay:YES];
}
/* @ignore */
@@ -851,7 +881,9 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
var frame = [self _insetBounds];
frame.size.height = _CGRectGetHeight([headerView frame]);
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
if (SHOULD_SHOW_CORNER_VIEW())
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
return frame;
}
@@ -1138,8 +1170,9 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
if (_scrollerStyle === CPScrollerStyleOverlay && hasHorizontalScroll)
verticalScrollerHeight -= horizontalScrollerHeight;
var documentHeight = _CGRectGetHeight(documentFrame);
[_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height];
[_verticalScroller setKnobProportion:_CGRectGetHeight(contentFrame) / _CGRectGetHeight(documentFrame)];
[_verticalScroller setKnobProportion:documentHeight > 0 ? _CGRectGetHeight(contentFrame) / documentHeight : 1.0];
[_verticalScroller setFrame:_CGRectMake(_CGRectGetMaxX(contentFrame) - overlay, verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)];
}
else if (wasShowingVerticalScroller)
@@ -1155,8 +1188,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
if (_scrollerStyle === CPScrollerStyleOverlay && hasVerticalScroll)
horizontalScrollerWidth -= verticalScrollerWidth;
var documentWidth = _CGRectGetWidth(documentFrame);
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
[_horizontalScroller setKnobProportion:_CGRectGetWidth(contentFrame) / _CGRectGetWidth(documentFrame)];
[_horizontalScroller setKnobProportion:documentWidth > 0 ? _CGRectGetWidth(contentFrame) / documentWidth : 1.0];
[_horizontalScroller setFrame:_CGRectMake(_CGRectGetMinX(contentFrame), _CGRectGetMaxY(contentFrame) - overlay, horizontalScrollerWidth, horizontalScrollerHeight)];
}
else if (wasShowingHorizontalScroller)
@@ -1166,9 +1201,15 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
}
[_contentView setFrame:contentFrame];
[_headerClipView setFrame:headerClipViewFrame];
[_headerClipView setFrame:[self _headerClipViewFrame]];
[[_headerClipView documentView] setNeedsDisplay:YES];
[_cornerView setFrame:[self _cornerViewFrame]];
if (SHOULD_SHOW_CORNER_VIEW())
{
[_cornerView setFrame:[self _cornerViewFrame]];
[_cornerView setHidden:NO];
}
else
[_cornerView setHidden:YES];
if (_scrollerStyle === CPScrollerStyleLegacy)
{
@@ -1201,6 +1242,7 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
if (_timerScrollersHide)
[_timerScrollersHide invalidate]
_timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
}
@@ -1248,70 +1290,67 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
- (void)_drawGrayBezelInContext:(CGContext)context bounds:(CGRect)aRect
{
CGContextBeginPath(context);
var minX = _CGRectGetMinX(aRect),
maxX = _CGRectGetMaxX(aRect),
minY = _CGRectGetMinY(aRect),
maxY = _CGRectGetMaxY(aRect),
y = minY + 0.5;
// Slightly darker line on top.
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);
CGContextBeginPath(context);
CGContextMoveToPoint(context, minX, y);
CGContextAddLineToPoint(context, maxX, y);
CGContextStrokePath(context);
CGContextBeginPath(context);
// The rest of the border.
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);
var x = maxX - 0.5;
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);
CGContextMoveToPoint(context, x, minY + 1.0);
CGContextAddLineToPoint(context, x, maxY);
CGContextMoveToPoint(context, x - 0.5, maxY - 0.5);
CGContextAddLineToPoint(context, minX, maxY - 0.5);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:190.0 / 255.0 alpha:1.0]);
x = minX + 0.5;
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);
CGContextMoveToPoint(context, x, maxY);
CGContextAddLineToPoint(context, x, minY + 1.0);
CGContextStrokePath(context);
}
- (void)_drawGrooveInContext:(CGContext)context bounds:(CGRect)aRect
{
var minX = _CGRectGetMinX(aRect),
maxX = _CGRectGetMaxX(aRect),
minY = _CGRectGetMinY(aRect),
maxY = _CGRectGetMaxY(aRect);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:159.0 / 255.0 alpha:1.0]);
var y = _CGRectGetMinY(aRect) + 0.5;
var y = minY + 0.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect), y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect), y);
CGContextMoveToPoint(context, minX, y);
CGContextAddLineToPoint(context, maxX, y);
var x = _CGRectGetMaxX(aRect) - 1.5;
var x = maxX - 1.5;
CGContextMoveToPoint(context, x, _CGRectGetMinY(aRect) + 2.0);
CGContextAddLineToPoint(context, x, _CGRectGetMaxY(aRect) - 1.0);
CGContextMoveToPoint(context, x, minY + 2.0);
CGContextAddLineToPoint(context, x, maxY - 1.0);
y = _CGRectGetMaxY(aRect) - 1.5;
y = maxY - 1.5;
CGContextMoveToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y);
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 2.0, y);
CGContextMoveToPoint(context, maxX - 1.0, y);
CGContextAddLineToPoint(context, minX + 2.0, y);
x = _CGRectGetMinX(aRect) + 0.5;
x = minX + 0.5;
CGContextMoveToPoint(context, x, _CGRectGetMaxY(aRect));
CGContextAddLineToPoint(context, x, _CGRectGetMinY(aRect));
CGContextMoveToPoint(context, x, maxY);
CGContextAddLineToPoint(context, x, minY);
CGContextStrokePath(context);
@@ -1327,10 +1366,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
y = _CGRectGetMinY(aRect) + 2.5;
y = minY + 2.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 2.0, y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect) - 2.0, y);
CGContextMoveToPoint(context, minX + 2.0, y);
CGContextAddLineToPoint(context, maxX - 2.0, y);
CGContextStrokePath(context);
}
@@ -1470,21 +1509,27 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
_scrollTimer = nil;
_implementedDelegateMethods = 0;
// 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]];
[self setScrollerStyle:[aCoder decodeIntForKey:CPScrollViewScrollerStyleKey] || CPScrollerStyleGlobal];
[self setScrollerKnobStyle:[aCoder decodeIntForKey:CPScrollViewScrollerKnobStyleKey] || CPScrollerKnobStyleDefault];
_scrollerStyle = [aCoder decodeObjectForKey:CPScrollViewScrollerStyleKey] || CPScrollerStyleGlobal;
_scrollerKnobStyle = [aCoder decodeObjectForKey:CPScrollViewScrollerKnobStyleKey] || CPScrollerKnobStyleDefault;
[[CPNotificationCenter defaultCenter] addObserver:self
selector:@selector(_didReceiveDefaultStyleChange:)
name:CPScrollerStyleGlobalChangeNotification
object:nil];
selector:@selector(_didReceiveDefaultStyleChange:)
name:CPScrollerStyleGlobalChangeNotification
object:nil];
}
return self;
}
/*!
Do final init that can only be done when we are sure all subviews have been initialized.
*/
- (void)awakeFromCib
{
[self _updateScrollerStyle];
[self _updateCornerAndHeaderView];
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
+14 -3
View File
@@ -23,6 +23,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../Foundation/Foundation.h"
@import "CPControl.j"
// CPScroller Constants
@@ -260,6 +262,9 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
*/
- (void)setKnobProportion:(float)aProportion
{
if (!_IS_NUMERIC(aProportion))
[CPException raise:CPInvalidArgumentException reason:"aProportion must be numeric"];
_knobProportion = MIN(1.0, MAX(0.0001, aProportion));
[self setNeedsDisplay:YES];
@@ -521,7 +526,8 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
[self checkSpaceForParts];
var index = 0,
count = PARTS_ARRANGEMENT.length;
count = PARTS_ARRANGEMENT.length,
view;
for (; index < count; ++index)
{
@@ -765,6 +771,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
if (_timerFadeOut)
[_timerFadeOut invalidate];
_timerFadeOut = [CPTimer scheduledTimerWithTimeInterval:1.2 target:self selector:@selector(_performFadeOut:) userInfo:nil repeats:NO];
}
@@ -790,10 +797,12 @@ var CPScrollerControlSizeKey = @"CPScrollerControlSize",
if (self = [super initWithCoder:aCoder])
{
_controlSize = CPRegularControlSize;
if ([aCoder containsValueForKey:CPScrollerControlSizeKey])
_controlSize = [aCoder decodeIntForKey:CPScrollerControlSizeKey];
_knobProportion = 1.0;
if ([aCoder containsValueForKey:CPScrollerKnobProportionKey])
_knobProportion = [aCoder decodeFloatForKey:CPScrollerKnobProportionKey];
@@ -803,8 +812,10 @@ var CPScrollerControlSizeKey = @"CPScrollerControlSize",
_allowFadingOut = YES;
_isMouseOver = NO;
var paramAnimFadeOut = [CPDictionary dictionaryWithObjects:[self, CPViewAnimationFadeOutEffect]
forKeys:[CPViewAnimationTargetKey, CPViewAnimationEffectKey]];
var paramAnimFadeOut = [CPDictionary dictionaryWithObjects:[self, CPViewAnimationFadeOutEffect]
forKeys:[CPViewAnimationTargetKey, CPViewAnimationEffectKey]];
_animationScroller = [[CPViewAnimation alloc] initWithDuration:0.2 animationCurve:CPAnimationEaseInOut];
[_animationScroller setViewAnimations:[paramAnimFadeOut]];
[_animationScroller setDelegate:self];
+3 -3
View File
@@ -72,7 +72,7 @@ var RECENT_SEARCH_PREFIX = @" ";
+ (void)initialize
{
if (self != [CPSearchField class])
if (self !== [CPSearchField class])
return;
var bundle = [CPBundle bundleForClass:self];
@@ -173,7 +173,7 @@ var RECENT_SEARCH_PREFIX = @" ";
searchButtonImage = (_searchMenuTemplate === nil) ? CPSearchFieldSearchImage : CPSearchFieldFindImage;
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImageScaling:CPImageScaleAxesIndependently];
[button setImage:searchButtonImage];
[button setAutoresizingMask:CPViewMaxXMargin];
}
@@ -215,7 +215,7 @@ var RECENT_SEARCH_PREFIX = @" ";
{
var button = [self cancelButton];
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImageScaling:CPImageScaleAxesIndependently];
[button setImage:CPSearchFieldCancelImage];
[button setAlternateImage:CPSearchFieldCancelPressedImage];
[button setAutoresizingMask:CPViewMinXMargin];
+1 -1
View File
@@ -55,7 +55,7 @@ CPSegmentSwitchTrackingMomentary = 2;
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[CPCenterTextAlignment, CPCenterVerticalTextAlignment, CPImageLeft, CPScaleNone, _CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], [CPNull null], 1.0, 24.0]
return [CPDictionary dictionaryWithObjects:[CPCenterTextAlignment, CPCenterVerticalTextAlignment, CPImageLeft, CPImageScaleNone, _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"]];
}
+1 -1
View File
@@ -61,7 +61,7 @@
_blurRadius = aBlurRadius;
_color = aColor;
_cssString = [_color cssString] + " " + Math.round(anOffset.width) + @"px " + Math.round(anOffset.height) + @"px " + Math.round(_blurRadius) + @"px";
_cssString = [_color cssString] + " " + ROUND(anOffset.width) + @"px " + ROUND(anOffset.height) + @"px " + ROUND(_blurRadius) + @"px";
}
return self;
+39 -38
View File
@@ -47,7 +47,6 @@ var LIGHT_LEFT_INSET = 3.0,
/*!
@ingroup appkit
*/
@implementation CPShadowView : CPView
{
CPShadowWeight _weight;
@@ -55,40 +54,38 @@ var LIGHT_LEFT_INSET = 3.0,
+ (void)initialize
{
if (self != [CPShadowView class])
if (self !== [CPShadowView class])
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)],
CPShadowViewLightBackgroundColor = CPColorWithImages([
[@"CPShadowView/CPShadowViewLightTopLeft.png", 9.0, 9.0, bundle],
[@"CPShadowView/CPShadowViewLightTop.png", 1.0, 9.0, bundle],
[@"CPShadowView/CPShadowViewLightTopRight.png", 9.0, 9.0, bundle],
[[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)],
[@"CPShadowView/CPShadowViewLightLeft.png", 9.0, 1.0, bundle],
nil,
[@"CPShadowView/CPShadowViewLightRight.png", 9.0, 1.0, bundle],
[[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)]
]]];
[@"CPShadowView/CPShadowViewLightBottomLeft.png", 9.0, 9.0, bundle],
[@"CPShadowView/CPShadowViewLightBottom.png", 1.0, 9.0, bundle],
[@"CPShadowView/CPShadowViewLightBottomRight.png", 9.0, 9.0, bundle]
]);
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)],
CPShadowViewHeavyBackgroundColor = CPColorWithImages([
[@"CPShadowView/CPShadowViewHeavyTopLeft.png", 17.0, 17.0, bundle],
[@"CPShadowView/CPShadowViewHeavyTop.png", 1.0, 17.0, bundle],
[@"CPShadowView/CPShadowViewHeavyTopRight.png", 17.0, 17.0, bundle],
[[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)],
[@"CPShadowView/CPShadowViewHeavyLeft.png", 17.0, 1.0, bundle],
nil,
[@"CPShadowView/CPShadowViewHeavyRight.png", 17.0, 1.0, bundle],
[[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)]
]]];
[@"CPShadowView/CPShadowViewHeavyBottomLeft.png", 17.0, 17.0, bundle],
[@"CPShadowView/CPShadowViewHeavyBottom.png", 1.0, 17.0, bundle],
[@"CPShadowView/CPShadowViewHeavyBottomRight.png", 17.0, 17.0, bundle]
]);
}
+ (id)shadowViewEnclosingView:(CPView)aView
@@ -98,20 +95,24 @@ var LIGHT_LEFT_INSET = 3.0,
+ (id)shadowViewEnclosingView:(CPView)aView withWeight:(CPShadowWeight)aWeight
{
var shadowView = [[CPShadowView alloc] initWithFrame:[aView frame]];
[shadowView setWeight:aWeight];
var shadowView = [[self alloc] initWithFrame:[aView frame]];
var size = [shadowView frame].size,
width = size.width - [shadowView leftInset] - [shadowView rightInset],
height = size.height - [shadowView topInset] - [shadowView bottomInset],
enclosingView = [aView superview];
if (shadowView)
{
[shadowView setWeight:aWeight];
[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];
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;
}
+141 -141
View File
@@ -60,7 +60,7 @@
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
{
return [super initWithPickerMask:mask colorPanel: owningColorPanel];
return [super initWithPickerMask:mask colorPanel:owningColorPanel];
}
- (id)initView
@@ -70,156 +70,156 @@
_contentView = [[CPView alloc] initWithFrame:aFrame];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_rgbLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 10, 100, 20)];
[_rgbLabel setStringValue: "Red, Green, Blue"];
_rgbLabel = [[CPTextField alloc] initWithFrame:CGRectMake(0, 10, 100, 20)];
[_rgbLabel setStringValue:"Red, Green, Blue"];
[_rgbLabel setTextColor:[CPColor blackColor]];
_redLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 37, 15, 20)];
[_redLabel setStringValue: "R"];
_redLabel = [[CPTextField alloc] initWithFrame:CGRectMake(0, 37, 15, 20)];
[_redLabel setStringValue:"R"];
[_redLabel setTextColor:[CPColor blackColor]];
_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];
_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];
// 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];
_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];
_greenLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 63, 15, 20)];
[_greenLabel setStringValue: "G"];
_greenLabel = [[CPTextField alloc] initWithFrame:CGRectMake(0, 63, 15, 20)];
[_greenLabel setStringValue:"G"];
[_greenLabel setTextColor:[CPColor blackColor]];
_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];
_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
_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 = [[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];
_blueLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 90, 15, 20)];
[_blueLabel setStringValue: "B"];
_blueLabel = [[CPTextField alloc] initWithFrame:CGRectMake(0, 90, 15, 20)];
[_blueLabel setStringValue:"B"];
[_blueLabel setTextColor:[CPColor blackColor]];
_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];
_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
_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 = [[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];
_hsbLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 120, 190, 20)];
[_hsbLabel setStringValue: "Hue, Saturation, Brightness"];
_hsbLabel = [[CPTextField alloc] initWithFrame:CGRectMake(0, 120, 190, 20)];
[_hsbLabel setStringValue:"Hue, Saturation, Brightness"];
[_hsbLabel setTextColor:[CPColor blackColor]];
_hueLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 145, 15, 20)];
[_hueLabel setStringValue: "H"];
_hueLabel = [[CPTextField alloc] initWithFrame:CGRectMake(0, 145, 15, 20)];
[_hueLabel setStringValue:"H"];
[_hueLabel setTextColor:[CPColor blackColor]];
_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];
_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];
// 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 = [[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];
_saturationLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 170, 15, 20)];
[_saturationLabel setStringValue: "S"];
_saturationLabel = [[CPTextField alloc] initWithFrame:CGRectMake(0, 170, 15, 20)];
[_saturationLabel setStringValue:"S"];
[_saturationLabel setTextColor:[CPColor blackColor]];
_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];
_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];
// 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 = [[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];
_brightnessLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 196, 15, 20)];
[_brightnessLabel setStringValue: "B"];
_brightnessLabel = [[CPTextField alloc] initWithFrame:CGRectMake(0, 196, 15, 20)];
[_brightnessLabel setStringValue:"B"];
[_brightnessLabel setTextColor:[CPColor blackColor]];
_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];
_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];
// 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 = [[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];
_hexLabel = [[CPTextField alloc] initWithFrame: CGRectMake(0, 230, 30, 20)];
[_hexLabel setStringValue: "Hex"];
_hexLabel = [[CPTextField alloc] initWithFrame:CGRectMake(0, 230, 30, 20)];
[_hexLabel setStringValue:"Hex"];
[_hexLabel setTextColor:[CPColor blackColor]];
//hex input box
_hexValue = [[CPTextField alloc] initWithFrame: CGRectMake(32, 225, 80, 28)];
[_hexValue setEditable: YES];
[_hexValue setBezeled: YES];
[_hexValue setDelegate: self];
[_contentView addSubview: _hexValue];
_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];
[_contentView addSubview: _blueLabel];
[_contentView addSubview: _redSlider];
[_contentView addSubview: _greenSlider];
[_contentView addSubview: _blueSlider];
[_contentView addSubview:_rgbLabel];
[_contentView addSubview:_redLabel];
[_contentView addSubview:_greenLabel];
[_contentView addSubview:_blueLabel];
[_contentView addSubview:_redSlider];
[_contentView addSubview:_greenSlider];
[_contentView addSubview:_blueSlider];
[_contentView addSubview: _hsbLabel];
[_contentView addSubview: _hueLabel];
[_contentView addSubview: _saturationLabel];
[_contentView addSubview: _brightnessLabel];
[_contentView addSubview: _hueSlider];
[_contentView addSubview: _saturationSlider];
[_contentView addSubview: _brightnessSlider];
[_contentView addSubview:_hsbLabel];
[_contentView addSubview:_hueLabel];
[_contentView addSubview:_saturationLabel];
[_contentView addSubview:_brightnessLabel];
[_contentView addSubview:_hueSlider];
[_contentView addSubview:_saturationSlider];
[_contentView addSubview:_brightnessSlider];
[_contentView addSubview: _hexLabel];
[_contentView addSubview:_hexLabel];
}
- (CPView)provideNewView:(BOOL)initialRequest
@@ -250,35 +250,35 @@
{
case _hueSlider:
case _saturationSlider:
case _brightnessSlider: newColor = [CPColor colorWithHue: [_hueSlider floatValue]
saturation: [_saturationSlider floatValue]
brightness: [_brightnessSlider floatValue]
alpha: alpha];
case _brightnessSlider: newColor = [CPColor colorWithHue:[_hueSlider floatValue]
saturation:[_saturationSlider floatValue]
brightness:[_brightnessSlider floatValue]
alpha:alpha];
[self updateRGBSliders: newColor];
[self updateRGBSliders:newColor];
break;
case _redSlider:
case _greenSlider:
case _blueSlider: newColor = [CPColor colorWithCalibratedRed: [_redSlider floatValue]
green: [_greenSlider floatValue]
blue: [_blueSlider floatValue]
alpha: alpha];
case _blueSlider: newColor = [CPColor colorWithCalibratedRed:[_redSlider floatValue]
green:[_greenSlider floatValue]
blue:[_blueSlider floatValue]
alpha:alpha];
[self updateHSBSliders: newColor];
[self updateHSBSliders:newColor];
break;
}
[self updateLabels];
[self updateHex: newColor];
[colorPanel setColor: newColor];
[self updateHex:newColor];
[colorPanel setColor:newColor];
}
- (void)setColor:(CPColor)aColor
{
[self updateRGBSliders: aColor];
[self updateHSBSliders: aColor];
[self updateHex: aColor];
[self updateRGBSliders:aColor];
[self updateHSBSliders:aColor];
[self updateHex:aColor];
[self updateLabels];
}
@@ -307,13 +307,13 @@
- (void)updateLabels
{
[_hueValue setStringValue: ROUND([_hueSlider floatValue])];
[_saturationValue setStringValue: ROUND([_saturationSlider floatValue])];
[_brightnessValue setStringValue: ROUND([_brightnessSlider floatValue])];
[_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)];
[_redValue setStringValue:ROUND([_redSlider floatValue] * 255)];
[_greenValue setStringValue:ROUND([_greenSlider floatValue] * 255)];
[_blueValue setStringValue:ROUND([_blueSlider floatValue] * 255)];
}
- (CPImage)provideNewButtonImage
@@ -333,12 +333,12 @@
if (field === _hexValue)
{
var newColor = [CPColor colorWithHexString: value];
var newColor = [CPColor colorWithHexString:value];
if (newColor)
{
[self setColor: newColor];
[[self colorPanel] setColor: newColor];
[self setColor:newColor];
[[self colorPanel] setColor:newColor];
}
}
else
@@ -346,27 +346,27 @@
switch (field)
{
case _redValue: [_redSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _redSlider];
[self sliderChanged:_redSlider];
break;
case _greenValue: [_greenSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _greenSlider];
[self sliderChanged:_greenSlider];
break;
case _blueValue: [_blueSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _blueSlider];
[self sliderChanged:_blueSlider];
break;
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(value), 360), 0)];
[self sliderChanged: _hueSlider];
[self sliderChanged:_hueSlider];
break;
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
[self sliderChanged: _saturationSlider];
[self sliderChanged:_saturationSlider];
break;
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
[self sliderChanged: _brightnessSlider];
[self sliderChanged:_brightnessSlider];
break;
}
}
+217 -76
View File
@@ -89,7 +89,7 @@ var CPSplitViewHorizontalImage = nil,
CPString _autosaveName;
BOOL _shouldAutosave;
BOOL _needsRestoreFromAutosave;
CGSize _shouldRestoreFromAutosaveUnlessFrameSize;
BOOL _needsResizeSubviews;
int _suppressResizeNotificationsMask;
@@ -113,12 +113,13 @@ var CPSplitViewHorizontalImage = nil,
*/
+ (void)initialize
{
if (self != [CPSplitView class])
if (self !== [CPSplitView class])
return;
var bundle = [CPBundle bundleForClass:self];
CPSplitViewHorizontalImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSplitView/CPSplitViewHorizontal.png"] size:CPSizeMake(5.0, 10.0)];
CPSplitViewVerticalImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSplitView/CPSplitViewVertical.png"] size:CPSizeMake(10.0, 5.0)];
CPSplitViewHorizontalImage = CPImageInBundle("CPSplitView/CPSplitViewHorizontal.png", CGSizeMake(5.0, 10.0), bundle);
CPSplitViewVerticalImage = CPImageInBundle("CPSplitView/CPSplitViewVertical.png", CGSizeMake(10.0, 5.0), bundle);
}
- (id)initWithFrame:(CGRect)aFrame
@@ -178,14 +179,17 @@ var CPSplitViewHorizontalImage = nil,
count = _subviews.length;
if ([self isVertical])
{
for (; index < count; ++index)
[_subviews[index] setFrame:CGRectMake(ROUND((eachSize + dividerThickness) * index), 0, eachSize, frame.size.height)];
}
else
{
for (; index < count; ++index)
[_subviews[index] setFrame:CGRectMake(0, ROUND((eachSize + dividerThickness) * index), frame.size.width, eachSize)];
}
[self setNeedsDisplay:YES];
[self _postNotificationDidResize];
}
@@ -261,7 +265,6 @@ var CPSplitViewHorizontalImage = nil,
rect = CGRectMakeZero();
rect.size = [self frame].size;
rect.size[_sizeComponent] = [self dividerThickness];
rect.origin[_originComponent] = frame.origin[_originComponent] + frame.size[_sizeComponent];
@@ -370,28 +373,33 @@ var CPSplitViewHorizontalImage = nil,
_needsResizeSubviews = NO;
[self resizeSubviewsWithOldSize:[self _calculateSize]];
}
- (CGSize)_calculateSize
{
var subviews = [self subviews],
count = subviews.length,
oldSize = CGSizeMakeZero();
size = CGSizeMakeZero();
if ([self isVertical])
{
oldSize.width += [self dividerThickness] * (count - 1);
oldSize.height = CGRectGetHeight([self frame]);
size.width += [self dividerThickness] * (count - 1);
size.height = CGRectGetHeight([self frame]);
}
else
{
oldSize.width = CGRectGetWidth([self frame]);
oldSize.height += [self dividerThickness] * (count - 1);
size.width = CGRectGetWidth([self frame]);
size.height += [self dividerThickness] * (count - 1);
}
while (count--)
oldSize[_sizeComponent] += [subviews[count] frame].size[_sizeComponent];
size[_sizeComponent] += [subviews[count] frame].size[_sizeComponent];
[self resizeSubviewsWithOldSize:oldSize];
return size;
}
- (BOOL)cursorAtPoint:(CPPoint)aPoint hitDividerAtIndex:(int)anIndex
- (BOOL)cursorAtPoint:(CGPoint)aPoint hitDividerAtIndex:(int)anIndex
{
var frame = [_subviews[anIndex] frame],
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent],
@@ -444,9 +452,13 @@ var CPSplitViewHorizontalImage = nil,
if (type == CPLeftMouseUp)
{
// We disabled autosaving during tracking.
_shouldAutosave = YES;
if (_currentDivider != CPNotFound)
{
_currentDivider = CPNotFound;
[self _autosave];
[self _updateResizeCursor:anEvent];
}
@@ -455,10 +467,11 @@ var CPSplitViewHorizontalImage = nil,
if (type == CPLeftMouseDown)
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
count = [_subviews count] - 1;
_currentDivider = CPNotFound;
var count = [_subviews count] - 1;
for (var i = 0; i < count; i++)
{
var frame = [_subviews[i] frame],
@@ -472,19 +485,19 @@ var CPSplitViewHorizontalImage = nil,
{
var minPosition = [self minPossiblePositionOfDividerAtIndex:i],
maxPosition = [self maxPossiblePositionOfDividerAtIndex:i],
_preCollapsePosition = [_preCollapsePositions objectForKey:"" + i] || 0;
preCollapsePosition = [_preCollapsePositions objectForKey:"" + i] || 0;
if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
{
if ([self isSubviewCollapsed:_subviews[i]])
[self setPosition:_preCollapsePosition ? _preCollapsePosition : (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])
{
if ([self isSubviewCollapsed:_subviews[i + 1]])
[self setPosition:_preCollapsePosition ? _preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
else
[self setPosition:maxPosition ofDividerAtIndex:i];
}
@@ -494,6 +507,8 @@ var CPSplitViewHorizontalImage = nil,
_currentDivider = i;
_initialOffset = startPosition - point[_originComponent];
// Don't autosave during a resize. We'll wait until it's done.
_shouldAutosave = NO;
[self _postNotificationWillResize];
}
}
@@ -574,9 +589,11 @@ var CPSplitViewHorizontalImage = nil,
if (sizeA === 0)
canGrow = YES; // Subview is collapsed.
else if (!canShrink &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i]])
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i]])
{
canShrink = YES; // Subview is collapsible.
}
if (sizeB === 0)
{
@@ -586,9 +603,11 @@ var CPSplitViewHorizontalImage = nil,
canShrink = YES;
}
else if (!canGrow &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i + 1]])
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i + 1]])
{
canGrow = YES; // Right/lower subview is collapsible.
}
if (_isVertical && canShrink && canGrow)
cursor = [CPCursor resizeLeftRightCursor];
@@ -665,6 +684,7 @@ var CPSplitViewHorizontalImage = nil,
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
{
var proposedActualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
if (_IS_NUMERIC(proposedActualMin))
actualMin = proposedActualMin;
}
@@ -672,6 +692,7 @@ var CPSplitViewHorizontalImage = nil,
if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
{
var proposedActualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
if (_IS_NUMERIC(proposedActualMax))
actualMax = proposedActualMax;
}
@@ -685,6 +706,7 @@ var CPSplitViewHorizontalImage = nil,
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
if ([_delegate splitView:self canCollapseSubview:viewA])
realPosition = proposedMin;
// We can also collapse to the right.
if (position > proposedMax - (proposedMax - actualMax) / 2)
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
@@ -701,21 +723,26 @@ var CPSplitViewHorizontalImage = nil,
*/
- (void)setPosition:(float)position ofDividerAtIndex:(int)dividerIndex
{
// Any manual changes to the divider position should override anything we are restoring from
// autosave.
_shouldRestoreFromAutosaveUnlessFrameSize = nil;
SPLIT_VIEW_SUPPRESS_RESIZE_NOTIFICATIONS(YES);
[self _adjustSubviewsWithCalculatedSize];
var realPosition = [self _realPositionForPosition:position ofDividerAtIndex:dividerIndex];
var viewA = _subviews[dividerIndex],
var realPosition = [self _realPositionForPosition:position ofDividerAtIndex:dividerIndex],
viewA = _subviews[dividerIndex],
frameA = [viewA frame],
viewB = _subviews[dividerIndex + 1],
frameB = [viewB frame],
_preCollapsePosition = 0;
preCollapsePosition = 0,
preSize = frameA.size[_sizeComponent];
var preSize = frameA.size[_sizeComponent];
frameA.size[_sizeComponent] = realPosition - frameA.origin[_originComponent];
if (preSize !== 0 && frameA.size[_sizeComponent] === 0)
_preCollapsePosition = preSize;
preCollapsePosition = preSize;
if (preSize !== frameA.size[_sizeComponent])
{
SPLIT_VIEW_MAYBE_POST_WILL_RESIZE();
@@ -724,11 +751,15 @@ var CPSplitViewHorizontalImage = nil,
}
preSize = frameB.size[_sizeComponent];
var preOrigin = frameB.origin[_originComponent];
frameB.size[_sizeComponent] = frameB.origin[_originComponent] + frameB.size[_sizeComponent] - realPosition - [self dividerThickness];
if (preSize !== 0 && frameB.size[_sizeComponent] === 0)
_preCollapsePosition = frameB.origin[_originComponent];
preCollapsePosition = frameB.origin[_originComponent];
frameB.origin[_originComponent] = realPosition + [self dividerThickness];
if (preSize !== frameB.size[_sizeComponent] || preOrigin !== frameB.origin[_originComponent])
{
SPLIT_VIEW_MAYBE_POST_WILL_RESIZE();
@@ -736,31 +767,28 @@ var CPSplitViewHorizontalImage = nil,
SPLIT_VIEW_MAYBE_POST_DID_RESIZE();
}
if (_preCollapsePosition)
[_preCollapsePositions setObject:_preCollapsePosition forKey:"" + dividerIndex];
if (preCollapsePosition)
[_preCollapsePositions setObject:preCollapsePosition forKey:"" + dividerIndex];
[self setNeedsDisplay:YES];
if (SPLIT_VIEW_DID_SUPPRESS_RESIZE_NOTIFICATION())
[self _postNotificationDidResize];
SPLIT_VIEW_SUPPRESS_RESIZE_NOTIFICATIONS(NO);
}
- (void)setFrameSize:(CGSize)aSize
{
if (_needsRestoreFromAutosave)
if (_shouldRestoreFromAutosaveUnlessFrameSize)
_shouldAutosave = NO;
else
[self _adjustSubviewsWithCalculatedSize];
[super setFrameSize:aSize];
if (_needsRestoreFromAutosave)
{
_needsRestoreFromAutosave = NO;
[self _restoreFromAutosave];
if (_shouldRestoreFromAutosaveUnlessFrameSize)
_shouldAutosave = YES;
}
[self setNeedsDisplay:YES];
}
@@ -773,66 +801,101 @@ var CPSplitViewHorizontalImage = nil,
return;
}
[self adjustSubviews];
}
- (void)adjustSubviews
{
var count = [_subviews count];
if (!count)
return;
SPLIT_VIEW_MAYBE_POST_WILL_RESIZE();
[self _postNotificationWillResize];
var index = 0,
count = [_subviews count],
bounds = [self bounds],
boundsSize = bounds.size[_sizeComponent],
oldSize = [self _calculateSize],
dividerThickness = [self dividerThickness],
totalDividers = count - 1,
totalSizableSpace = 0,
nonSizableSpace = 0,
lastSizableIndex = -1,
oldFlexibleSpace = 0,
totalSizablePanes = 0,
isVertical = [self isVertical];
isSizableMap = {},
viewSizes = [],
delegateRespondsToShouldAdjust = [_delegate respondsToSelector:@selector(splitView:shouldAdjustSizeOfSubview:)];
// What we want to do is to preserve non resizable sizes first, and then to preserve the ratio of size to available
// non fixed space for every other subview. E.g. assume fixed space was 20 pixels initially, view 1 was 20 and
// view 2 was 30 pixels, for a total of 70 pixels. Then the new total size becomes 140 pixels. Now we want the fixed
// space to still be 20 pixels, view 1 to be 48 pixels and view 2 to be 72 pixels. This way the relative size of
// view 1 to view 2 remains the same - view 1 was 66% of view 2 initially and after the resize view 1 is still
// 66% of view 2's size.
//
// For this calculation, we can consider the dividers themselves to also be fixed size areas - they should remain
// the same size before and after.
// How much flexible size do we have in pre-resize pixels?
for (index = 0; index < count; ++index)
{
var view = _subviews[index],
isSizable = isVertical ? [view autoresizingMask] & CPViewWidthSizable : [view autoresizingMask] & CPViewHeightSizable;
isSizable = !delegateRespondsToShouldAdjust || [_delegate splitView:self shouldAdjustSizeOfSubview:view],
size = [view frame].size[_sizeComponent];
isSizableMap[index] = isSizable;
viewSizes.push(size);
if (isSizable)
{
totalSizableSpace += [view frame].size[_sizeComponent];
lastSizableIndex = index;
oldFlexibleSpace += size;
totalSizablePanes++;
}
}
if (totalSizablePanes === count)
totalSizableSpace = 0;
// nonSizableSpace is the number of fixed pixels in pre-resize terms and the desired number post-resize.
var nonSizableSpace = oldSize[_sizeComponent] - oldFlexibleSpace,
newFlexibleSpace = boundsSize - nonSizableSpace,
remainingFixedPixelsToRemove = 0;
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;
if (newFlexibleSpace < 0)
{
remainingFixedPixelsToRemove = -newFlexibleSpace;
newFlexibleSpace = 0;
}
var remainingFixedPanes = count - totalSizablePanes;
for (index = 0; index < count; ++index)
{
var view = _subviews[index],
viewFrame = CGRectMakeCopy(bounds),
isSizable = isVertical ? [view autoresizingMask] & CPViewWidthSizable : [view autoresizingMask] & CPViewHeightSizable;
isSizable = isSizableMap[index],
targetSize = 0;
// The last area must take up exactly the remaining space, fixed or not.
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)
targetSize = boundsSize - viewFrame.origin[_originComponent];
// Try to keep fixed size areas the same size.
else if (!isSizable)
{
viewFrame.size[_sizeComponent] = MAX(0, ROUND(ratio * [view frame].size[_sizeComponent]));
remainingFlexibleSpace -= (viewFrame.size[_sizeComponent] - [view frame].size[_sizeComponent]);
var removedFixedPixels = MIN(remainingFixedPixelsToRemove / remainingFixedPanes, viewSizes[index]);
targetSize = viewSizes[index] - removedFixedPixels;
remainingFixedPixelsToRemove -= removedFixedPixels;
remainingFixedPanes--;
}
// (new size / flexible size available) == (old size / old flexible size available)
else if (oldFlexibleSpace > 0)
targetSize = newFlexibleSpace * viewSizes[index] / oldFlexibleSpace;
// oldFlexibleSpace <= 0 so all flexible areas were crushed. When we get space, allocate it evenly.
// totalSizablePanes cannot be 0 since isSizable.
else
targetSize = newFlexibleSpace / totalSizablePanes;
else if (totalSizableSpace && !isSizable)
viewFrame.size[_sizeComponent] = [view frame].size[_sizeComponent];
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
targetSize = MAX(0, ROUND(targetSize));
viewFrame.size[_sizeComponent] = targetSize;
[view setFrame:viewFrame];
bounds.origin[_originComponent] += targetSize + dividerThickness;
}
SPLIT_VIEW_MAYBE_POST_DID_RESIZE();
@@ -852,6 +915,11 @@ Notifies the delegate when the subviews will be resized.
- (void)splitViewWillResizeSubviews:(CPNotification)aNotification;
@endcode
Allows the delegate to specify which of the CPSplitView's subviews should adjust if the window is resized.
@code
- (BOOL)splitView:(CPSplitView)aSplitView shouldAdjustSizeOfSubview:(CPView)aSubView
@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;
@@ -966,13 +1034,31 @@ The sum of the views and the sum of the dividers should be equal to the size of
- (void)_postNotificationWillResize
{
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewWillResizeSubviewsNotification object:self];
var userInfo = nil;
if (_currentDivider !== CPNotFound)
userInfo = [CPDictionary dictionaryWithObject:_currentDivider forKey:@"CPSplitViewDividerIndex"];
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewWillResizeSubviewsNotification
object:self
userInfo:userInfo];
}
- (void)_postNotificationDidResize
{
var userInfo = nil;
if (_currentDivider !== CPNotFound)
userInfo = [CPDictionary dictionaryWithObject:_currentDivider forKey:@"CPSplitViewDividerIndex"];
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewDidResizeSubviewsNotification
object:self
userInfo:userInfo];
// TODO Cocoa always autosaves on "viewDidEndLiveResize". If Cappuccino adds support for this we
// should do the same.
[self _autosave];
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewDidResizeSubviewsNotification object:self];
}
/*!
@@ -984,13 +1070,14 @@ The sum of the views and the sum of the dividers should be equal to the size of
{
if (_autosaveName == autosaveName)
return;
_autosaveName = autosaveName;
}
/*!
Get the name under which the split view divider position is automatically saved to CPUserDefaults.
@return the name to save under or nil if no auto save is active
@return the name to save under or nil if no autosave is active
*/
- (CPString)autosaveName
{
@@ -1002,7 +1089,7 @@ The sum of the views and the sum of the dividers should be equal to the size of
*/
- (void)_autosave
{
if (!_shouldAutosave)
if (_shouldRestoreFromAutosaveUnlessFrameSize || !_shouldAutosave || !_autosaveName)
return;
var userDefaults = [CPUserDefaults standardUserDefaults],
@@ -1023,6 +1110,22 @@ The sum of the views and the sum of the dividers should be equal to the size of
[userDefaults setObject:preCollapseArray forKey:autosavePrecollapseName];
}
/*!
This is called sometime later after a split view has been restored from a Cib.
See notes in initWithCoder.
@ignore
*/
- (void)_restoreFromAutosaveIfNeeded
{
if (_shouldRestoreFromAutosaveUnlessFrameSize && !_CGSizeEqualToSize([self frameSize], _shouldRestoreFromAutosaveUnlessFrameSize))
{
[self _restoreFromAutosave];
}
_shouldRestoreFromAutosaveUnlessFrameSize = nil;
}
/*!
@ignore
*/
@@ -1043,6 +1146,7 @@ The sum of the views and the sum of the dividers should be equal to the size of
position = 0;
_shouldAutosave = NO;
for (var i = 0, count = [frames count] - 1; i < count; i++)
{
var frame = CPRectFromString(frames[i]);
@@ -1052,12 +1156,14 @@ The sum of the views and the sum of the dividers should be equal to the size of
position += dividerThickness;
}
_shouldAutosave = YES;
}
if (preCollapseArray)
{
_preCollapsePositions = [CPMutableDictionary new];
for (var i = 0, count = [preCollapseArray count]; i < count; i++)
[_preCollapsePositions setObject:preCollapseArray[i] forKey:i + ""];
}
@@ -1068,6 +1174,9 @@ The sum of the views and the sum of the dividers should be equal to the size of
*/
- (CPString)_framesKeyForAutosaveName:(CPString)theAutosaveName
{
if (!theAutosaveName)
return nil;
return @"CPSplitView Subview Frames " + theAutosaveName;
}
@@ -1076,6 +1185,9 @@ The sum of the views and the sum of the dividers should be equal to the size of
*/
- (CPString)_precollapseKeyForAutosaveName:(CPString)theAutosaveName
{
if (!theAutosaveName)
return nil;
return @"CPSplitView Subview Precollapse Positions " + theAutosaveName;
}
@@ -1095,6 +1207,34 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
*/
- (id)initWithCoder:(CPCoder)aCoder
{
// We need to restore this property before calling super's initWithCoder:.
_autosaveName = [aCoder decodeObjectForKey:CPSplitViewAutosaveNameKey];
/*
It is common for the main window of a Cappuccino app window to be resized to match the browser
window size at the end of the UI being loaded from a cib. But at decoding time (now) whatever
window size was originally saved will be in place, so if we try to restore the autosaved divider
positions now they might be constrained to the wrong positions due to the difference in frame size,
and in addition they might move later when the window is resized.
The workaround is to restore the position once now (so it's approximately correct during loading),
and then once more in the next runloop cycle when any `setFullPlatformWindow` calls are done.
(However if the frame size doesn't change before the next cycle, we should not restore the position
again because that would overwrite any changes the app developer might have made in user code.)
The other consideration is that any parent split views need to be restored before any child
subviews, otherwise the parent restore will also change the positioning of the child.
*/
if (_autosaveName)
{
// Schedule /before/ [super initWithCoder:]. This way this instance's _restoreFromAutosaveIfNeeded
// will happen before that of any subviews loaded by [super initWithCoder:].
[[CPRunLoop currentRunLoop] performSelector:@selector(_restoreFromAutosaveIfNeeded) target:self argument:nil order:0 modes:[CPDefaultRunLoopMode]];
}
self = [super initWithCoder:aCoder];
if (self)
@@ -1114,12 +1254,13 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
_isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey];
[self _setVertical:[aCoder decodeBoolForKey:CPSplitViewIsVerticalKey]];
[self setAutosaveName:[aCoder decodeObjectForKey:CPSplitViewAutosaveNameKey]];
// We have to wait until we know our frame size before restoring, or the frame resize later will throw
// away the restored size.
if (_autosaveName)
_needsRestoreFromAutosave = YES;
{
[self _restoreFromAutosave];
// Remember the frame size we had at this point so that we can restore again if it changes
// before the next runloop cycle. See above notes.
_shouldRestoreFromAutosaveUnlessFrameSize = [self frameSize];
}
}
return self;
+59 -31
View File
@@ -34,6 +34,7 @@
@implementation CPStepper: CPControl
{
BOOL _valueWraps @accessors(property=valueWraps);
BOOL _autorepeat @accessors(getter=autorepeat);
int _increment @accessors(property=increment);
int _maxValue @accessors(property=maxValue);
int _minValue @accessors(property=minValue);
@@ -88,29 +89,38 @@
_minValue = 0.0;
_increment = 1.0;
_valueWraps = YES;
_autorepeat = YES;
[self setDoubleValue:0.0];
_buttonUp = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
[_buttonUp setContinuous:YES];
[_buttonUp setTarget:self];
[_buttonUp setAction:@selector(_buttonDidClick:)];
[_buttonUp setAutoresizingMask:CPViewNotSizable];
[self addSubview:_buttonUp];
_buttonDown = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
[_buttonDown setContinuous:YES];
[_buttonDown setTarget:self];
[_buttonDown setAction:@selector(_buttonDidClick:)];
[_buttonDown setAutoresizingMask:CPViewNotSizable];
[self addSubview:_buttonDown];
[self setNeedsLayout];
[self _init];
}
return self;
}
/*! @ignore */
- (void)_init
{
_buttonUp = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
[_buttonUp setContinuous:_autorepeat];
[_buttonUp setTarget:self];
[_buttonUp setAction:@selector(_buttonDidClick:)];
[_buttonUp setAutoresizingMask:CPViewNotSizable];
[self addSubview:_buttonUp];
_buttonDown = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
[_buttonDown setContinuous:_autorepeat];
[_buttonDown setTarget:self];
[_buttonDown setAction:@selector(_buttonDidClick:)];
[_buttonDown setAutoresizingMask:CPViewNotSizable];
[self setContinuous:_autorepeat];
[self addSubview:_buttonDown];
[self setNeedsLayout];
}
#pragma mark -
#pragma mark Superclass overrides
@@ -134,8 +144,8 @@
minSize = _CGSizeMake(upSize.width, upSize.height + downSize.height),
frame = _CGRectMakeCopy(aFrame);
frame.size.width = Math.max(minSize.width, frame.size.width);
frame.size.height = Math.max(minSize.height, frame.size.height);
frame.size.width = MAX(minSize.width, frame.size.width);
frame.size.height = MAX(minSize.height, frame.size.height);
[super setFrame:frame];
}
@@ -164,8 +174,13 @@
*/
- (void)setAutorepeat:(BOOL)shouldAutoRepeat
{
[_buttonUp setContinuous:shouldAutoRepeat];
[_buttonDown setContinuous:shouldAutoRepeat];
if (shouldAutoRepeat !== _autorepeat)
{
[_buttonUp setContinuous:shouldAutoRepeat];
[_buttonDown setContinuous:shouldAutoRepeat];
}
[self setContinuous:shouldAutoRepeat];
}
/*!
@@ -235,19 +250,27 @@
@end
var CPStepperMinValue = @"CPStepperMinValue",
CPStepperMaxValue = @"CPStepperMaxValue",
CPStepperValueWraps = @"CPStepperValueWraps",
CPStepperAutorepeat = @"CPStepperAutorepeat",
CPStepperIncrement = @"CPStepperIncrement";
@implementation CPStepper (CPCodingCompliance)
@implementation CPStepper (CPCoding)
- (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"];
_increment = [aCoder decodeIntForKey:CPStepperIncrement];
_minValue = [aCoder decodeIntForKey:CPStepperMinValue];
_maxValue = [aCoder decodeIntForKey:CPStepperMaxValue];
_valueWraps = [aCoder decodeBoolForKey:CPStepperValueWraps];
_autorepeat = [aCoder decodeBoolForKey:CPStepperAutorepeat];
[self _init];
}
return self;
}
@@ -255,11 +278,16 @@
{
[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"];
[aCoder encodeInt:_increment forKey:CPStepperIncrement];
if (_minValue)
[aCoder encodeInt:_minValue forKey:CPStepperMinValue];
if (_maxValue)
[aCoder encodeInt:_maxValue forKey:CPStepperMaxValue];
if (_valueWraps)
[aCoder encodeBool:_valueWraps forKey:CPStepperValueWraps];
if (_autorepeat)
[aCoder encodeBool:_autorepeat forKey:CPStepperAutorepeat];
}
@end
+45 -15
View File
@@ -1,3 +1,25 @@
/*
* CPTabView.j
* AppKit
*
* Created by Derek Hammer.
* Copyright 2010, Derek Hammer.
*
* 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 "CPBox.j"
@import "CPSegmentedControl.j"
@import "CPTabViewItem.j"
@@ -45,7 +67,6 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
if (self = [super initWithFrame:aFrame])
{
_items = [CPArray array];
_selectedIndex = CPNotFound;
[self _init];
[self setTabViewType:CPTopTabsBezelBorder];
@@ -56,6 +77,8 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
- (void)_init
{
_selectedIndex = CPNotFound;
_tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[_tabs setHitTests:NO];
@@ -250,17 +273,15 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
Selects the item at the specified index.
@param anIndex the index of the item to display.
*/
- (void)selectTabViewItemAtIndex:(unsigned)anIndex
- (BOOL)selectTabViewItemAtIndex:(unsigned)anIndex
{
var aTabViewItem = [_items objectAtIndex:anIndex];
if (anIndex === _selectedIndex)
return;
var aTabViewItem = [self tabViewItemAtIndex:anIndex];
if ((_delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![_delegate tabView:self shouldSelectTabViewItem:aTabViewItem])
return;
return NO;
if (_delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
[_delegate tabView:self willSelectTabViewItem:aTabViewItem];
@@ -270,6 +291,8 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
if (_delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
[_delegate tabView:self didSelectTabViewItem:aTabViewItem];
return YES;
}
/*!
@@ -278,7 +301,10 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (CPTabViewItem)selectedTabViewItem
{
return [_items objectAtIndex:_selectedIndex];
if (_selectedIndex != CPNotFound)
return [_items objectAtIndex:_selectedIndex];
return nil;
}
// Modifying the font
@@ -407,11 +433,8 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
{
var segmentIndex = [_tabs testSegment:[_tabs convertPoint:[anEvent locationInWindow] fromView:nil]];
if (segmentIndex != CPNotFound)
{
[self selectTabViewItemAtIndex:segmentIndex];
if (segmentIndex != CPNotFound && [self selectTabViewItemAtIndex:segmentIndex])
[_tabs trackSegment:anEvent];
}
}
- (void)_repositionTabs
@@ -428,8 +451,12 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
- (void)_setSelectedIndex:(CPNumber)index
{
_selectedIndex = index;
[self _setContentViewForItem:[_items objectAtIndex:_selectedIndex]];
}
[_box setContentView:[[_items objectAtIndex:_selectedIndex] view]];
- (void)_setContentViewForItem:(CPTabViewItem)anItem
{
[_box setContentView:[anItem view]];
}
- (void)_updateItems
@@ -469,17 +496,17 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
[_tabs setFont:_font];
_items = [aCoder decodeObjectForKey:CPTabViewItemsKey];
[_items makeObjectsPerformSelector:@selector(_setTabView:) withObject:self];
[self _updateItems];
[self _repositionTabs];
var selected = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
var selected = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
if (selected)
[self selectTabViewItem:selected];
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
[self setTabViewType:[aCoder decodeIntForKey:CPTabViewTypeKey]];
}
@@ -491,7 +518,10 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_items forKey:CPTabViewItemsKey];
[aCoder encodeObject:[self selectedTabViewItem] forKey:CPTabViewSelectedItemKey];
var selected = [self selectedTabViewItem];
if (selected)
[aCoder encodeObject:selected forKey:CPTabViewSelectedItemKey];
[aCoder encodeInt:_type forKey:CPTabViewTypeKey];
[aCoder encodeObject:_font forKey:CPTabViewFontKey];
+6
View File
@@ -132,7 +132,13 @@ CPPressedTab = 2;
*/
- (void)setView:(CPView)aView
{
if (_view == aView)
return;
_view = aView;
if ([_tabView selectedTabViewItem] == self)
[_tabView _setContentViewForItem:self];
}
/*!
+6 -8
View File
@@ -498,12 +498,13 @@ CPTableColumnUserResizingMask = 1 << 1;
}
/*!
If NO the tablecolumn will no longer be visible in the tableview
If YES the tablecolumn will be visible in the tableview.
If YES the tablecolumn will no longer be visible in the tableview.
If NO the tablecolumn will be visible in the tableview.
*/
- (void)setHidden:(BOOL)shouldBeHidden
{
shouldBeHidden = !!shouldBeHidden
if (_isHidden === shouldBeHidden)
return;
@@ -678,8 +679,11 @@ CPTableColumnUserResizingMask = 1 << 1;
bindingInfo = binding._info,
destination = [bindingInfo objectForKey:CPObservedObjectKey],
keyPath = [bindingInfo objectForKey:CPObservedKeyPathKey],
options = [bindingInfo objectForKey:CPOptionsKey],
dotIndex = keyPath.lastIndexOf(".");
newValue = [binding reverseTransformValue:newValue withOptions:options];
if (dotIndex === CPNotFound)
[[destination valueForKeyPath:keyPath] replaceObjectAtIndex:aRow withObject:newValue];
else
@@ -696,11 +700,6 @@ CPTableColumnUserResizingMask = 1 << 1;
}
}
//- (void)objectValue
//{
// return nil;
//}
@end
var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
@@ -734,7 +733,6 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
[self setIdentifier:[aCoder decodeObjectForKey:CPTableColumnIdentifierKey]];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
[self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
_resizingMask = [aCoder decodeIntForKey:CPTableColumnResizingMaskKey];
_isHidden = [aCoder decodeBoolForKey:CPTableColumnIsHiddenKey];
+4 -4
View File
@@ -40,7 +40,7 @@
+ (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"]];
forKeys:[@"background-color", @"text-alignment", @"text-inset", @"text-color", @"font", @"text-shadow-color", @"text-shadow-offset"]];
}
- (void)initWithFrame:(CGRect)frame
@@ -74,7 +74,7 @@
[_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 setFont:[self currentValueForThemeAttribute:@"font"]];
[_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
[_textField setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
[_textField setAlignment:[self currentValueForThemeAttribute:@"text-alignment"]];
@@ -102,7 +102,7 @@
- (void)setFont:(CPFont)aFont
{
[self setValue:aFont forThemeAttribute:"text-font"];
[self setValue:aFont forThemeAttribute:"font"];
}
- (void)_setIndicatorImage:(CPImage)anImage
@@ -643,7 +643,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
columnMaxX = _CGRectGetMaxX(columnToStroke);
CGContextMoveToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMinY(columnToStroke)));
CGContextAddLineToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMaxY(columnToStroke)));
CGContextAddLineToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMaxY(columnToStroke)) - 1.0);
}
CGContextClosePath(context);
CGContextStrokePath(context);
+162 -67
View File
@@ -87,9 +87,9 @@ CPTableViewSelectionHighlightStyleNone = -1;
CPTableViewSelectionHighlightStyleRegular = 0;
CPTableViewSelectionHighlightStyleSourceList = 1;
CPTableViewGridNone = 0;
CPTableViewSolidVerticalGridLineMask = 1 << 0;
CPTableViewSolidHorizontalGridLineMask = 1 << 1;
CPTableViewGridNone = 0;
CPTableViewSolidVerticalGridLineMask = 1 << 0;
CPTableViewSolidHorizontalGridLineMask = 1 << 1;
CPTableViewNoColumnAutoresizing = 0;
CPTableViewUniformColumnAutoresizingStyle = 1; // FIX ME: This is FUBAR
@@ -239,6 +239,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
BOOL _disableAutomaticResizing @accessors(property=disableAutomaticResizing);
BOOL _lastColumnShouldSnap;
BOOL _implementsCustomDrawRow;
BOOL _contentBindingExpicitelySet;
CPTableColumn _draggedColumn;
CPArray _differedColumnDataToRemove;
@@ -257,8 +258,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
*/
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPNull null], [CPNull null], [CPNull null], [CPNull null], [CPNull null], [CPNull null]]
forKeys:["alternating-row-colors", "grid-color", "highlighted-grid-color", "selection-color", "sourcelist-selection-color", "sort-image", "sort-image-reversed"]];
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPNull null], [CPNull null], [CPNull null], [CPNull null], [CPNull null], [CPNull null], [CPNull null]]
forKeys:["alternating-row-colors", "grid-color", "highlighted-grid-color", "selection-color", "sourcelist-selection-color", "sort-image", "sort-image-reversed", "selection-radius"]];
}
- (id)initWithFrame:(CGRect)aFrame
@@ -305,6 +306,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
_retargetedDropOperation = nil;
_dragOperationDefaultMask = nil;
_destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular;
_contentBindingExpicitelySet = NO;
[self setBackgroundColor:[CPColor whiteColor]];
[self _init];
@@ -321,7 +323,6 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
*/
- (void)_init
{
_tableViewFlags = 0;
_lastSelectedRow = -1;
_selectedColumnIndexes = [CPIndexSet indexSet];
@@ -335,19 +336,17 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
if (!_alternatingRowBackgroundColors)
_alternatingRowBackgroundColors = [[CPColor whiteColor], [CPColor colorWithHexString:@"e4e7ff"]];
_selectionHighlightColor = [CPColor colorWithHexString:@"5f83b9"];
_tableColumnRanges = [];
_dirtyTableColumnRangeIndex = 0;
_numberOfHiddenColumns = 0;
_objectValues = { };
_dataViewsForTableColumns = { };
_dataViews = [];
_numberOfRows = 0;
_exposedRows = [CPIndexSet indexSet];
_exposedColumns = [CPIndexSet indexSet];
_cachedDataViews = { };
_cachedRowHeights = [];
_groupRows = [CPIndexSet indexSet];
@@ -683,6 +682,7 @@ NOT YET IMPLEMENTED
*/
- (void)setRowHeight:(unsigned)aRowHeight
{
// Accept row heights such as "0".
aRowHeight = +aRowHeight;
if (_rowHeight === aRowHeight)
@@ -726,7 +726,7 @@ NOT YET IMPLEMENTED
- (void)setAlternatingRowBackgroundColors:(CPArray)alternatingRowBackgroundColors
{
[self setValue:alternatingRowBackgroundColors forThemeAttribute:"alternating-row-colors"];
[self setValue:alternatingRowBackgroundColors forThemeAttribute:@"alternating-row-colors"];
[self setNeedsDisplay:YES];
}
@@ -768,10 +768,6 @@ NOT YET IMPLEMENTED
*/
- (void)setSelectionHighlightStyle:(unsigned)aSelectionHighlightStyle
{
//early return for IE.
if (aSelectionHighlightStyle == CPTableViewSelectionHighlightStyleSourceList && !CPFeatureIsCompatible(CPHTMLCanvasFeature))
return;
_selectionHighlightStyle = aSelectionHighlightStyle;
[self setNeedsDisplay:YES];
@@ -788,7 +784,7 @@ NOT YET IMPLEMENTED
*/
- (void)setSelectionHighlightColor:(CPColor)aColor
{
[self setValue:aColor forThemeAttribute:"selection-color"];
[self setValue:aColor forThemeAttribute:@"selection-color"];
[self setNeedsDisplay:YES];
}
@@ -814,7 +810,7 @@ NOT YET IMPLEMENTED
*/
- (void)setSelectionGradientColors:(CPDictionary)aDictionary
{
[self setValue:aDictionary forThemeAttribute:"sourcelist-selection-color"];
[self setValue:aDictionary forThemeAttribute:@"sourcelist-selection-color"];
[self setNeedsDisplay:YES];
}
@@ -838,7 +834,7 @@ NOT YET IMPLEMENTED
*/
- (void)setGridColor:(CPColor)aColor
{
[self setValue:aColor forThemeAttribute:"grid-color"];
[self setValue:aColor forThemeAttribute:@"grid-color"];
[self setNeedsDisplay:YES];
}
@@ -958,6 +954,7 @@ NOT YET IMPLEMENTED
*/
- (void)_moveColumn:(unsigned)fromIndex toColumn:(unsigned)toIndex
{
// Convert parameters such as "0" to 0.
fromIndex = +fromIndex;
toIndex = +toIndex;
@@ -981,6 +978,13 @@ NOT YET IMPLEMENTED
columnIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(fromIndex, toIndex)];
[self reloadDataForRowIndexes:rowIndexes columnIndexes:columnIndexes];
// Notify even if programmatically moving a column as in Cocoa.
// TODO Only notify when a column drag operation ends, not each time a column reaches a new slot?
[[CPNotificationCenter defaultCenter] postNotificationName:CPTableViewColumnDidMoveNotification
object:self
userInfo:[CPDictionary dictionaryWithObjects:[fromIndex, toIndex]
forKeys:[@"CPOldColumn", @"CPNewColumn"]]];
}
/*!
@@ -1263,7 +1267,7 @@ NOT YET IMPLEMENTED
*/
- (int)selectedColumn
{
[_selectedColumnIndexes lastIndex];
return [_selectedColumnIndexes lastIndex];
}
/*!
@@ -1515,6 +1519,8 @@ NOT YET IMPLEMENTED
if ([scrollView isKindOfClass:[CPScrollView class]] && [scrollView documentView] === self)
[scrollView _updateCornerAndHeaderView];
[self setNeedsLayout];
}
// Complexity:
@@ -1566,6 +1572,7 @@ NOT YET IMPLEMENTED
*/
- (CGRect)rectOfColumn:(CPInteger)aColumnIndex
{
// Convert e.g. "0" to 0.
aColumnIndex = +aColumnIndex;
if (aColumnIndex < 0 || aColumnIndex >= NUMBER_OF_COLUMNS())
@@ -1795,7 +1802,7 @@ NOT YET IMPLEMENTED
{
if (_implementedDelegateMethods & CPTableViewDelegate_tableView_heightOfRow_)
{
return idx = [_cachedRowHeights indexOfObject:aPoint
return [_cachedRowHeights indexOfObject:aPoint
inSortedRange:nil
options:0
usingComparator:function(aPoint, rowCache)
@@ -2688,7 +2695,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
oldMainSortDescriptor = [[self sortDescriptors] objectAtIndex: 0];
// Remove every main descriptor equivalents (normally only one)
while ((descriptor = [e nextObject]) != nil)
while ((descriptor = [e nextObject]) !== nil)
{
if ([[descriptor key] isEqual: [newMainSortDescriptor key]])
[outdatedDescriptors addObject:descriptor];
@@ -2728,7 +2735,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
*/
- (CPImage)_tableHeaderSortImage
{
return [self currentValueForThemeAttribute:"sort-image"];
return [self currentValueForThemeAttribute:@"sort-image"];
}
/*!
@@ -2736,7 +2743,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
*/
- (CPImage)_tableHeaderReverseSortImage
{
return [self currentValueForThemeAttribute:"sort-image-reversed"];
return [self currentValueForThemeAttribute:@"sort-image-reversed"];
}
/*!
@@ -2826,11 +2833,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
var dataView = [self _newDataViewForRow:row tableColumn:tableColumn];
[dataView setFrame:[self frameOfDataViewAtColumn:columnIndex row:row]];
[dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]];
// If the column uses content bindings, allow them to override the objectValueForTableColumn.
[tableColumn _prepareDataView:dataView forRow:row];
[self _setObjectValueForTableColumn:tableColumn row:row forView:dataView];
[view addSubview:dataView];
row = [theDraggedRows indexGreaterThanIndex:row];
@@ -2871,7 +2875,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
dataViewFrame.origin.y = ( _CGRectGetMinY(dataViewFrame) - _CGRectGetMinY([self exposedRect]) ) + 23.0;
[dataView setFrame:dataViewFrame];
[dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]];
[self _setObjectValueForTableColumn:tableColumn row:row forView:dataView];
[dragView addSubview:dataView];
row = [_exposedRows indexGreaterThanIndex:row];
@@ -3049,7 +3053,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
return _sortDescriptors;
}
/*!
@ignore
*/
@@ -3271,11 +3274,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
isTextField = [dataView isKindOfClass:[CPTextField class]];
[dataView setFrame:[self frameOfDataViewAtColumn:column row:row]];
[dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]];
// This gives the table column an opportunity to apply its bindings.
// It will override the value set above if there is a binding.
[tableColumn _prepareDataView:dataView forRow:row];
[self _setObjectValueForTableColumn:tableColumn row:row forView:dataView];
if (isColumnSelected || [self isRowSelected:row])
[dataView setThemeState:CPThemeStateSelectedDataView];
@@ -3333,6 +3333,30 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
}
}
- (void)_setObjectValueForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRow forView:(CPView)aDataView
{
if (_implementedDataSourceMethods & CPTableViewDataSource_tableView_objectValueForTableColumn_row_)
[aDataView setObjectValue:[self _objectValueForTableColumn:aTableColumn row:aRow]];
// This gives the table column an opportunity to apply its bindings.
// It will override the value set above if there is a binding.
if (_contentBindingExpicitelySet)
[self _prepareContentBindedDataView:aDataView forRow:aRow];
else
// For both cell-based and view-based
[aTableColumn _prepareDataView:aDataView forRow:aRow];
}
- (void)_prepareContentBindedDataView:(CPView)dataView forRow:(CPInteger)aRow
{
var binder = [CPTableContentBinder getBinding:@"content" forObject:self],
content = [binder content],
rowContent = [content objectAtIndex:aRow];
[dataView setObjectValue:rowContent];
}
/*!
@ignore
*/
@@ -3373,6 +3397,14 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
*/
- (void)_commitDataViewObjectValue:(id)sender
{
/*
makeFirstResponder at the end of this method causes the dataview to resign.
If the dataview resigning triggers the action (as CPTextField does), we come right
back here and start an infinite loop. So we have to check this flag first.
*/
if ([sender respondsToSelector:@selector(sendsActionOnEndEditing)] && [sender sendsActionOnEndEditing] && _editingCellIndex === nil)
return;
_editingCellIndex = nil;
if (_implementedDataSourceMethods & CPTableViewDataSource_tableView_setObjectValue_forTableColumn_row_)
@@ -3430,7 +3462,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
[aTableColumn setDataView:dataView];
}
return [aTableColumn _newDataViewForRow:aRow];
}
@@ -3502,8 +3533,20 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
{
[super setNeedsDisplay:aFlag];
[_tableDrawView setNeedsDisplay:aFlag];
[[self headerView] setNeedsDisplay:YES];
}
/*!
@ignore
*/
- (void)setNeedsLayout
{
[super setNeedsLayout];
[[self headerView] setNeedsLayout];
}
/*!
@ignore
*/
@@ -3685,12 +3728,13 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
[_selectedColumnIndexes getIndexes:indexes maxCount:-1 inIndexRange:exposedRange];
}
var count = count2 = [indexes count];
var count,
count2 = count = [indexes count];
if (!count)
return;
var drawGradient = (_selectionHighlightStyle === CPTableViewSelectionHighlightStyleSourceList && [_selectedRowIndexes count] >= 1),
var drawGradient = (CPFeatureIsCompatible(CPHTMLCanvasFeature) && _selectionHighlightStyle === CPTableViewSelectionHighlightStyleSourceList && [_selectedRowIndexes count] >= 1),
deltaHeight = 0.5 * (_gridStyleMask & CPTableViewSolidHorizontalGridLineMask);
CGContextBeginPath(context);
@@ -3710,7 +3754,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
{
var topGroupLineColor = [CPColor colorWithCalibratedWhite:212.0 / 255.0 alpha:1.0],
bottomGroupLineColor = [CPColor colorWithCalibratedWhite:185.0 / 255.0 alpha:1.0],
gradientGroupColor = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [212.0 / 255.0, 212.0 / 255.0, 212.0 / 255.0,1.0, 197.0 / 255.0, 197.0 / 255.0, 197.0 / 255.0,1.0], [0,1], 2);
gradientGroupColor = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [212.0 / 255.0, 212.0 / 255.0, 212.0 / 255.0, 1.0, 197.0 / 255.0, 197.0 / 255.0, 197.0 / 255.0, 1.0], [0, 1], 2);
}
while (count--)
@@ -3757,7 +3801,25 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
CGContextStrokePath(context);
}
else
CGContextAddRect(context, rowRect);
{
var radius = [self currentValueForThemeAttribute:@"selection-radius"];
if (radius > 0)
{
var minX = CGRectGetMinX(rowRect),
maxX = CGRectGetMaxX(rowRect),
minY = CGRectGetMinY(rowRect),
maxY = CGRectGetMaxY(rowRect);
CGContextMoveToPoint(context, minX + radius, minY);
CGContextAddArcToPoint(context, maxX, minY, maxX, minY + radius, radius);
CGContextAddArcToPoint(context, maxX, maxY, maxX - radius, maxY, radius);
CGContextAddArcToPoint(context, minX, maxY, minX, maxY - radius, radius);
CGContextAddArcToPoint(context, minX, minY, minX + radius, minY, radius);
}
else
CGContextAddRect(context, rowRect);
}
}
CGContextClosePath(context);
@@ -3806,7 +3868,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
}
CGContextClosePath(context);
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:"highlighted-grid-color"]);
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"highlighted-grid-color"]);
CGContextStrokePath(context);
}
@@ -3817,7 +3879,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
*/
- (void)_drawGroupRowsForRects:(CPArray)rects
{
if (_selectionHighlightStyle === CPTableViewSelectionHighlightStyleSourceList || !rects.length)
if ((CPFeatureIsCompatible(CPHTMLCanvasFeature) && _selectionHighlightStyle === CPTableViewSelectionHighlightStyleSourceList) || !rects.length)
return;
var context = [[CPGraphicsContext currentContext] graphicsPort],
@@ -3828,8 +3890,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
var gradientCache = [self selectionGradientColors],
topLineColor = [CPColor colorWithHexString:"d3d3d3"],
bottomLineColor = [CPColor colorWithHexString:"bebebd"],
gradientColor = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [220.0 / 255.0, 220.0 / 255.0, 220.0 / 255.0,1.0,
199.0 / 255.0, 199.0 / 255.0, 199.0 / 255.0,1.0], [0,1], 2),
gradientColor = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [220.0 / 255.0, 220.0 / 255.0, 220.0 / 255.0, 1.0,
199.0 / 255.0, 199.0 / 255.0, 199.0 / 255.0, 1.0], [0, 1], 2),
drawGradient = YES;
while (i--)
@@ -3975,9 +4037,12 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
*/
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
// Try to become the first responder, but if we can't, that's okay.
[[self window] makeFirstResponder:self];
var row = [self rowAtPoint:aPoint];
//if the user clicks outside a row then deselect everything
// If the user clicks outside a row then deselect everything.
if (row < 0 && _allowsEmptySelection)
[self selectRowIndexes:[CPIndexSet indexSet] byExtendingSelection:NO];
@@ -4002,7 +4067,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if (row >= 0 && !(_implementedDataSourceMethods & CPTableViewDataSource_tableView_writeRowsWithIndexes_toPasteboard_))
[self _updateSelectionWithMouseAtRow:row];
[[self window] makeFirstResponder:self];
return YES;
}
@@ -4642,19 +4706,19 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
while (![_delegate tableView:self shouldSelectRow:i] && (i < [self numberOfRows] || i > 0))
shouldGoUpward ? i-- : i++; //check to see if the row can be selected if it can't be then see if the next row can be selected
//if the index still can be selected after the loop then just return
if (![_delegate tableView:self shouldSelectRow:i])
return;
// If the index still can be selected after the loop then just return.
if (![_delegate tableView:self shouldSelectRow:i])
return;
}
// if we go upward and see that this row is already selected we should deselect the row below
if ([selectedIndexes containsIndex:i] && extend)
// If we go upward and see that this row is already selected we should deselect the row below.
if (extend && [selectedIndexes containsIndex:i])
{
// the row we're on is the last to be selected
// The row we're on is the last to be selected.
var differedLastSelectedRow = i;
// no remove the one before/after it
shouldGoUpward ? i++ : i--;
shouldGoUpward ? i++ : i--;
[selectedIndexes removeIndex:i];
@@ -4666,7 +4730,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if ([selectedIndexes containsIndex:i])
{
i = shouldGoUpward ? [selectedIndexes firstIndex] -1 : [selectedIndexes lastIndex] + 1;
i = MIN(MAX(i,0), [self numberOfRows] - 1);
i = MIN(MAX(i, 0), [self numberOfRows] - 1);
}
[selectedIndexes addIndex:i];
@@ -4691,6 +4755,14 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
@implementation CPTableView (Bindings)
+ (id)_binderClassForBinding:(CPString)aBinding
{
if (aBinding == @"content")
return [CPTableContentBinder class];
return [super _binderClassForBinding:aBinding];
}
/*!
@ignore
*/
@@ -4708,7 +4780,10 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
- (void)_establishBindingsIfUnbound:(id)destination
{
if ([[self infoForBinding:@"content"] objectForKey:CPObservedObjectKey] !== destination)
[self bind:@"content" toObject:destination withKeyPath:@"arrangedObjects" options:nil];
{
[super bind:@"content" toObject:destination withKeyPath:@"arrangedObjects" options:nil];
_contentBindingExpicitelySet = NO;
}
if ([[self infoForBinding:@"selectionIndexes"] objectForKey:CPObservedObjectKey] !== destination)
[self bind:@"selectionIndexes" toObject:destination withKeyPath:@"selectionIndexes" options:nil];
@@ -4716,9 +4791,29 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
//[self bind:@"sortDescriptors" toObject:destination withKeyPath:@"sortDescriptors" options:nil];
}
- (void)setContent:(CPArray)content
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
{
[self reloadData];
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
if (aBinding == @"content")
_contentBindingExpicitelySet = YES;
}
@end
@implementation CPTableContentBinder : CPBinder
{
id _content @accessors(property=content);
}
- (void)setValueFor:(id)aBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey];
_content = [destination valueForKey:keyPath];
[_source reloadData];
}
@end
@@ -4766,15 +4861,14 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
_tableColumns = [aCoder decodeObjectForKey:CPTableViewTableColumnsKey] || [];
[_tableColumns makeObjectsPerformSelector:@selector(setTableView:) withObject:self];
if ([aCoder containsValueForKey:CPTableViewRowHeightKey])
_rowHeight = [aCoder decodeFloatForKey:CPTableViewRowHeightKey];
else
_rowHeight = 23.0;
_rowHeight = [aCoder decodeFloatForKey:CPTableViewRowHeightKey] || 23.0;
_intercellSpacing = [aCoder decodeSizeForKey:CPTableViewIntercellSpacingKey];
_intercellSpacing = [aCoder decodeSizeForKey:CPTableViewIntercellSpacingKey] || _CGSizeMake(3.0, 2.0);
if (_CGSizeEqualToSize(_intercellSpacing, _CGSizeMakeZero()))
_intercellSpacing = _CGSizeMake(3.0, 2.0);
[self setGridColor:[aCoder decodeObjectForKey:CPTableViewGridColorKey]];
_gridStyleMask = [aCoder decodeIntForKey:CPTableViewGridStyleMaskKey] || CPTableViewGridNone;
_gridStyleMask = [aCoder decodeIntForKey:CPTableViewGridStyleMaskKey];
_usesAlternatingRowBackgroundColors = [aCoder decodeObjectForKey:CPTableViewUsesAlternatingBackgroundKey];
[self setAlternatingRowBackgroundColors:[aCoder decodeObjectForKey:CPTableViewAlternatingRowColorsKey]];
@@ -4841,9 +4935,8 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
while (index != CPNotFound)
{
var indexSet = (switchFlag) ? otherSet : self;
otherIndex = [indexSet indexGreaterThanOrEqualToIndex:index];
var indexSet = (switchFlag) ? otherSet : self,
otherIndex = [indexSet indexGreaterThanOrEqualToIndex:index];
if (otherIndex == index)
{
@@ -4943,15 +5036,17 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
isBlinking = YES;
var showCallback = function() {
var showCallback = function()
{
objj_msgSend(self, "setHidden:", NO)
isBlinking = NO;
}
};
var hideCallback = function() {
var hideCallback = function()
{
objj_msgSend(self, "setHidden:", YES)
isBlinking = YES;
}
};
objj_msgSend(self, "setHidden:", YES);
[CPTimer scheduledTimerWithTimeInterval:0.1 callback:showCallback repeats:NO];
+144 -98
View File
@@ -46,7 +46,8 @@ var CPTextFieldDOMInputElement = nil,
CPTextFieldInputIsActive = NO,
CPTextFieldCachedSelectStartFunction = nil,
CPTextFieldCachedDragFunction = nil,
CPTextFieldBlurFunction = nil;
CPTextFieldBlurFunction = nil,
CPTextFieldInputFunction = nil;
#endif
@@ -202,13 +203,32 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
CPTextFieldInputDidBlur = YES;
return true;
}
};
CPTextFieldHandleBlur = function(anEvent)
{
CPTextFieldInputOwner = nil;
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
};
if (CPFeatureIsCompatible(CPInputOnInputEventFeature))
{
CPTextFieldInputFunction = function(anEvent)
{
if (!CPTextFieldInputOwner)
return;
var cappEvent = [CPEvent keyEventWithType:CPKeyUp location:_CGPointMakeZero() modifierFlags:0
timestamp:[CPEvent currentTimestamp] windowNumber:[[CPApp keyWindow] windowNumber] context:nil
characters:nil charactersIgnoringModifiers:nil isARepeat:NO keyCode:nil];
[CPTextFieldInputOwner keyUp:cappEvent];
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
CPTextFieldDOMInputElement.oninput = CPTextFieldInputFunction;
}
//FIXME make this not onblur
@@ -474,26 +494,43 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[[CPTextFieldInputOwner window] makeFirstResponder:nil];
#endif
// As long as we are the first responder we need to monitor the key status of our window.
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:) name:CPWindowDidResignKeyNotification object:[self window]];
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:) name:CPWindowDidBecomeKeyNotification object:[self window]];
_isEditing = NO;
if ([[self window] isKeyWindow])
[self _becomeFirstKeyResponder];
return YES;
}
/*!
A text field can be the first responder without necessarily being the focus of keyboard input. For example, it might be the first responder of window A but window B is the main and key window. It's important we don't put a focused input field into a text field in a non key window, even if that field is the first responder, because the key window might also have a first responder text field which the user will expect to receive keyboard input.
Since a first responder but non-key window text field can't receive input it should not even look like an active text field (Cocoa has a "slightly active" text field look it uses when another window is the key window, but Cappuccino doesn't today.)
*/
- (void)_becomeFirstKeyResponder
{
[self setThemeState:CPThemeStateEditing];
[self _updatePlaceholderState];
[self setNeedsLayout];
_isEditing = NO;
_stringValue = [self stringValue];
#if PLATFORM(DOM)
var element = [self _inputElement],
font = [self currentValueForThemeAttribute:@"font"];
// generate the font metric
[font _getMetrics];
font = [self currentValueForThemeAttribute:@"font"],
lineHeight = [font defaultLineHeightForFont];
element.value = _stringValue;
element.style.color = [[self currentValueForThemeAttribute:@"text-color"] cssString];
element.style.font = [font cssString];
if (CPFeatureIsCompatible(CPInputSetFontOutsideOfDOM))
element.style.font = [font cssString];
element.style.zIndex = 1000;
switch ([self alignment])
@@ -511,36 +548,46 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
switch (verticalAlign)
{
case CPTopVerticalTextAlignment:
var topPoint = (_CGRectGetMinY(contentRect) + 1) + "px"; // for the same reason we have a -1 for the left, we also have a + 1 here
var topPoint = _CGRectGetMinY(contentRect) + "px";
break;
case CPCenterVerticalTextAlignment:
var topPoint = (_CGRectGetMidY(contentRect) - (font._lineHeight / 2) + 1) + "px";
var topPoint = (_CGRectGetMidY(contentRect) - (lineHeight / 2)) + "px";
break;
case CPBottomVerticalTextAlignment:
var topPoint = (_CGRectGetMaxY(contentRect) - font._lineHeight) + "px";
var topPoint = (_CGRectGetMaxY(contentRect) - lineHeight) + "px";
break;
default:
var topPoint = (_CGRectGetMinY(contentRect) + 1) + "px";
var topPoint = _CGRectGetMinY(contentRect) + "px";
break;
}
element.style.top = topPoint;
element.style.left = (_CGRectGetMinX(contentRect) - 1) + "px"; // why -1?
var left = _CGRectGetMinX(contentRect);
// If the browser has a built in left padding, compensate for it. We need the input text to be exactly on top of the original text.
if (CPFeatureIsCompatible(CPInput1PxLeftPadding))
left -= 1;
element.style.left = left + "px";
element.style.width = _CGRectGetWidth(contentRect) + "px";
element.style.height = font._lineHeight + "px"; // private ivar for the line height of the DOM text at this particular size
element.style.height = ROUND(lineHeight) + "px";
element.style.lineHeight = ROUND(lineHeight) + "px";
element.style.verticalAlign = @"top";
_DOMElement.appendChild(element);
// The font change above doesn't work for some browsers if the element isn't already .appendChild'ed.
if (!CPFeatureIsCompatible(CPInputSetFontOutsideOfDOM))
element.style.font = [font cssString];
window.setTimeout(function()
{
element.focus();
// Select the text if the textfield became first responder through keyboard interaction
if (!_willBecomeFirstResponderByClick)
[self selectText:self];
[self _selectText:self immediately:YES];
_willBecomeFirstResponderByClick = NO;
@@ -561,14 +608,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[[self window] platformWindow]._DOMBodyElement.onselectstart = function () {};
}
#endif
return YES;
}
/* @ignore */
- (BOOL)resignFirstResponder
{
[self unsetThemeState:CPThemeStateEditing];
// When we are no longer the first responder we don't worry about the key status of our window anymore.
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidResignKeyNotification object:[self window]];
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidBecomeKeyNotification object:[self window]];
#if PLATFORM(DOM)
@@ -585,13 +632,29 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
// even if the value has not changed.
if ([self _valueIsValid:newValue] === NO)
{
[self setThemeState:CPThemeStateEditing];
element.focus();
return NO;
}
#endif
[self _resignFirstKeyResponder];
_isEditing = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
if ([self sendsActionOnEndEditing])
[self sendAction:[self action] to:[self target]];
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
return YES;
}
- (void)_resignFirstKeyResponder
{
[self unsetThemeState:CPThemeStateEditing];
// Cache the formatted string
_stringValue = [self stringValue];
@@ -603,6 +666,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
#if PLATFORM(DOM)
var element = [self _inputElement];
CPTextFieldInputResigning = YES;
if (CPTextFieldInputIsActive)
@@ -629,20 +694,18 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
#endif
}
// post CPControlTextDidEndEditingNotification
if (_isEditing)
{
_isEditing = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
- (void)_windowDidResignKey:(CPNotification)aNotification
{
if (![[self window] isKeyWindow])
[self _resignFirstKeyResponder];
}
if ([self sendsActionOnEndEditing])
[self sendAction:[self action] to:[self target]];
}
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
return YES;
- (void)_windowDidBecomeKey:(CPNotification)aNotification
{
if ([[self window] isKeyWindow] && [[self window] firstResponder] === self)
[self _becomeFirstKeyResponder];
}
- (BOOL)_valueIsValid:(CPString)aValue
@@ -656,7 +719,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
var acceptInvalidValue = NO;
if ([_delegate respondsToSelector:@selector(control:didFailToFormatString:errorDescription:)])
acceptInvalidValue = [_delegate control:self didFailToFormatString:[self _inputElement] errorDescription:error];
acceptInvalidValue = [_delegate control:self didFailToFormatString:aValue errorDescription:error];
if (acceptInvalidValue === NO)
return NO;
@@ -1048,8 +1111,16 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
textSize = [text sizeWithFont:font inWidth:textSize.width];
}
else
{
textSize = [text sizeWithFont:font];
// Account for possible fractional pixels at right edge
textSize.width += 1;
}
// Account for possible fractional pixels at bottom edge
textSize.height += 1;
frameSize.height = textSize.height + contentInset.top + contentInset.bottom;
if ([self isBezeled])
@@ -1075,24 +1146,36 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
*/
- (void)selectText:(id)sender
{
// FIXME Should this really make the text field the first responder?
[self _selectText:sender immediately:NO];
}
- (void)_selectText:(id)sender immediately:(BOOL)immediately
{
// Selecting the text in a field makes it the first responder
if (([self isEditable] || [self isSelectable]))
{
var wind = [self window];
#if PLATFORM(DOM)
var element = [self _inputElement];
if ([[self window] firstResponder] === self)
window.setTimeout(function() { element.select(); }, 0);
else if ([self window] !== nil && [[self window] makeFirstResponder:self])
window.setTimeout(function() {[self selectText:sender];}, 0);
if ([wind firstResponder] === self)
{
if (immediately)
element.select();
else
window.setTimeout(function() { element.select(); }, 0);
}
else if (wind !== nil && [wind makeFirstResponder:self])
[self _selectText:sender immediately:immediately];
#else
// Even if we can't actually select the text we need to preserve the first
// responder side effect.
if ([self window] !== nil && [[self window] firstResponder] !== self)
[[self window] makeFirstResponder:self];
if (wind !== nil && [wind firstResponder] !== self)
[wind makeFirstResponder:self];
#endif
}
}
- (void)copy:(id)sender
@@ -1119,7 +1202,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[self copy:sender];
[self deleteBackward:sender];
}
else
// If we don't have an oninput listener, we won't detect the change made by the cut and need to fake a key up "soon".
else if (!CPFeatureIsCompatible(CPInputOnInputEventFeature))
[CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(keyUp:) userInfo:nil repeats:NO];
}
@@ -1141,7 +1225,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[self setStringValue:newValue];
[self setSelectedRange:CPMakeRange(selectedRange.location + pasteString.length, 0)];
}
else
// If we don't have an oninput listener, we won't detect the change made by the cut and need to fake a key up "soon".
else if (!CPFeatureIsCompatible(CPInputOnInputEventFeature))
[CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(keyUp:) userInfo:nil repeats:NO];
}
@@ -1307,30 +1392,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
if (!contentInset)
return 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;
return _CGRectInsetByInset(bounds, contentInset);
}
- (CGRect)bezelRectForBounds:(CGRect)bounds
{
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
if (_CGInsetIsEmpty(bezelInset))
return bounds;
bounds.origin.x += bezelInset.left;
bounds.origin.y += bezelInset.top;
bounds.size.width -= bezelInset.left + bezelInset.right;
bounds.size.height -= bezelInset.top + bezelInset.bottom;
return bounds;
return _CGRectInsetByInset(bounds, bezelInset);
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
@@ -1357,7 +1426,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
else
{
var view = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
//[view setImagePosition:CPNoImage];
[view setHitTests:NO];
@@ -1433,7 +1501,7 @@ var secureStringForString = function(aString)
return "";
return Array(aString.length + 1).join(CPSecureTextFieldCharacter);
}
};
var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
@@ -1503,47 +1571,25 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
{
}
- (void)setValueFor:(CPString)theBinding
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
[super _updatePlaceholdersWithOptions:options];
if (isPlaceholder)
{
switch (newValue)
{
case CPMultipleValuesMarker:
newValue = [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || @"Multiple Values";
break;
[self _setPlaceholder:@"Multiple Values" forMarker:CPMultipleValuesMarker isDefault:YES];
[self _setPlaceholder:@"No Selection" forMarker:CPNoSelectionMarker isDefault:YES];
[self _setPlaceholder:@"Not Applicable" forMarker:CPNotApplicableMarker isDefault:YES];
[self _setPlaceholder:@"" forMarker:CPNullMarker isDefault:YES];
}
case CPNoSelectionMarker:
newValue = [options objectForKey:CPNoSelectionPlaceholderBindingOption] || @"No Selection";
break;
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[_source setPlaceholderString:aValue];
[_source setObjectValue:nil];
}
case CPNotApplicableMarker:
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
[CPException raise:CPGenericException
reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
newValue = [options objectForKey:CPNotApplicablePlaceholderBindingOption] || @"Not Applicable";
break;
case CPNullMarker:
newValue = [options objectForKey:CPNullPlaceholderBindingOption] || @"";
break;
}
[_source setPlaceholderString:newValue];
[_source setObjectValue:nil];
}
else
{
newValue = [self transformValue:newValue withOptions:options];
[_source setObjectValue:newValue];
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source setObjectValue:aValue];
}
@end
+7 -2
View File
@@ -255,7 +255,7 @@ var CPThemesByName = { },
attributeNames = [attributes keyEnumerator],
objectThemeClass = [anObject themeClass];
while (attributeName = [attributeNames nextObject])
while ((attributeName = [attributeNames nextObject]) !== nil)
[self _recordAttribute:[attributes objectForKey:attributeName] forClass:objectThemeClass];
}
@@ -418,6 +418,9 @@ CPThemeStateEditing = CPThemeState("editing");
CPThemeStateVertical = CPThemeState("vertical");
CPThemeStateDefault = CPThemeState("default");
CPThemeStateCircular = CPThemeState("circular");
CPThemeStateAutocompleting = CPThemeState("autocompleting");
CPThemeStateMainWindow = CPThemeState("mainWindow");
CPThemeStateKeyWindow = CPThemeState("keyWindow");
@implementation _CPThemeAttribute : CPObject
{
@@ -579,6 +582,7 @@ CPThemeStateCircular = CPThemeState("circular");
_cache = {};
_name = [aCoder decodeObjectForKey:@"name"];
_defaultValue = [aCoder decodeObjectForKey:@"defaultValue"];
_values = [CPDictionary dictionary];
if ([aCoder containsValueForKey:@"value"])
@@ -611,6 +615,7 @@ CPThemeStateCircular = CPThemeState("circular");
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_name forKey:@"name"];
[aCoder encodeObject:_defaultValue forKey:@"defaultValue"];
var keys = [_values allKeys],
count = keys.length;
@@ -666,7 +671,7 @@ var numberOfOnes = function(aNumber)
cachedNumberOfOnes[slot] = count;
return count;
}
};
numberOfOnes.displayName = "numberOfOnes";
+488 -455
View File
File diff suppressed because it is too large Load Diff
+148 -39
View File
@@ -50,6 +50,11 @@ CPToolbarDisplayModeIconOnly = 2;
*/
CPToolbarDisplayModeLabelOnly = 3;
CPToolbarSizeModeDefault = 0;
CPToolbarSizeModeRegular = 1;
CPToolbarSizeModeSmall = 2;
var CPToolbarsByIdentifier = nil,
CPToolbarConfigurationsByIdentifier = nil;
@@ -83,10 +88,12 @@ var CPToolbarsByIdentifier = nil,
@implementation CPToolbar : CPObject
{
CPString _identifier;
CPToolbarDisplayMode _displayMode;
CPToolbarDisplayMode _displayMode @accessors(property=displayMode);
BOOL _showsBaselineSeparator;
BOOL _allowsUserCustomization;
BOOL _isVisible;
int _sizeMode @accessors(property=sizeMode);
int _desiredHeight;
id _delegate;
@@ -107,7 +114,7 @@ var CPToolbarsByIdentifier = nil,
/* @ignore */
+ (void)initialize
{
if (self != [CPToolbar class])
if (self !== [CPToolbar class])
return;
CPToolbarsByIdentifier = [CPDictionary dictionary];
@@ -128,6 +135,19 @@ var CPToolbarsByIdentifier = nil,
[toolbarsSharingIdentifier addObject:toolbar];
}
/*
Temporary theme attributes until we've figured out which CPView these theme attributes should
belong to.
@ignore
*/
+ (id)_themeAttributes
{
// "regular-size-height" is used if no item has a non-zero min size and sizeMode == CPToolbarSizeModeRegular.
// "small-size-height" is used if no item has a non-zero min size and sizeMode == CPToolbarSizeModeSmall.
return [CPDictionary dictionaryWithObjects:[_CGInsetMake(4.0, 4.0, 4.0, TOOLBAR_ITEM_MARGIN), 59.0, 46.0]
forKeys:[@"content-inset", @"regular-size-height", @"small-size-height"]];
}
- (id)init
{
return [self initWithIdentifier:@""];
@@ -148,6 +168,8 @@ var CPToolbarsByIdentifier = nil,
_identifier = anIdentifier;
_isVisible = YES;
_sizeMode = CPToolbarSizeModeDefault;
_desiredHeight = 0;
[CPToolbar _addToolbar:self forIdentifier:_identifier];
}
@@ -202,6 +224,16 @@ var CPToolbarsByIdentifier = nil,
[_window _noteToolbarChanged];
}
- (void)setSizeMode:(CPToolbarSizeMode)aSize
{
if (aSize === _sizeMode)
return;
_sizeMode = aSize;
[[self _toolbarView] setFrame:[self _toolbarViewFrame]];
[_window _noteToolbarChanged];
}
- (CPWindow)_window
{
return _window;
@@ -209,7 +241,13 @@ var CPToolbarsByIdentifier = nil,
- (void)_setWindow:(CPWindow)aWindow
{
if (_window)
[[CPNotificationCenter defaultCenter] removeObserver:self object:_window];
_window = aWindow;
if (_window)
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_autovalidate) name:_CPWindowDidChangeFirstResponderNotification object:aWindow];
}
/*!
@@ -226,18 +264,43 @@ var CPToolbarsByIdentifier = nil,
[self _reloadToolbarItems];
}
- (void)setDisplayMode:(CPToolbarDisplayMode)aDisplayMode
{
if (_displayMode === aDisplayMode)
return;
_displayMode = aDisplayMode;
[self _reloadToolbarItems];
}
/* @ignore */
- (void)_loadConfiguration
{
}
- (CGRect)_toolbarViewFrame
{
var height = _desiredHeight || (_sizeMode != CPToolbarSizeModeSmall ? [self _valueForThemeAttribute:@"regular-size-height"] : [self _valueForThemeAttribute:@"small-size-height"]);
return CPRectMake(0.0, 0.0, 1200.0, height);
}
/*
Temporary theme attributes until we've figured out which CPView these theme attributes should
belong to.
@ignore
*/
- (id)_valueForThemeAttribute:(CPString)attributeName
{
return [[[self class] _themeAttributes] valueForKey:attributeName];
}
/* @ignore */
- (CPView)_toolbarView
{
if (!_toolbarView)
{
_toolbarView = [[_CPToolbarView alloc] initWithFrame:CPRectMake(0.0, 0.0, 1200.0, 59.0)];
_toolbarView = [[_CPToolbarView alloc] initWithFrame:[self _toolbarViewFrame]];
[_toolbarView setToolbar:self];
[_toolbarView setAutoresizingMask:CPViewWidthSizable];
@@ -257,13 +320,17 @@ var CPToolbarsByIdentifier = nil,
// _defaultItems may have been loaded from Cib
_itemIdentifiers = [_defaultItems valueForKey:@"itemIdentifier"] || [];
if (_delegate)
if ([_delegate respondsToSelector:@selector(toolbarDefaultItemIdentifiers:)])
{
var itemIdentifiersFromDelegate = [[_delegate toolbarDefaultItemIdentifiers:self] mutableCopy];
var itemIdentifiersFromDelegate = [_delegate toolbarDefaultItemIdentifiers:self];
// If we get items both from the Cib and from the delegate method, put the delegate items before the
// Cib ones.
if (itemIdentifiersFromDelegate)
_itemIdentifiers = [_itemIdentifiers arrayByAddingObjectsFromArray:itemIdentifiersFromDelegate];
_itemIdentifiers = [itemIdentifiersFromDelegate arrayByAddingObjectsFromArray:_itemIdentifiers];
}
// If we didn't load from a cib and the delegate hasn't been set yet, we'll just work with an empty list
// at this point.
var index = 0,
count = [_itemIdentifiers count];
@@ -340,6 +407,19 @@ var CPToolbarsByIdentifier = nil,
[toolbarItems[count] validate];
}
- (void)_autovalidate
{
var toolbarItems = [self visibleItems],
count = [toolbarItems count];
while (count--)
{
var item = [toolbarItems objectAtIndex:count];
if ([item autovalidates])
[item validate];
}
}
/* @ignore */
- (id)_itemForItemIdentifier:(CPString)identifier willBeInsertedIntoToolbar:(BOOL)toolbar
{
@@ -427,7 +507,8 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
CPToolbarIdentifiedItemsKey = @"CPToolbarIdentifiedItemsKey",
CPToolbarDefaultItemsKey = @"CPToolbarDefaultItemsKey",
CPToolbarAllowedItemsKey = @"CPToolbarAllowedItemsKey",
CPToolbarSelectableItemsKey = @"CPToolbarSelectableItemsKey";
CPToolbarSelectableItemsKey = @"CPToolbarSelectableItemsKey",
CPToolbarSizeModeKey = @"CPToolbarSizeModeKey";
@implementation CPToolbar (CPCoding)
@@ -446,6 +527,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
_showsBaselineSeparator = [aCoder decodeBoolForKey:CPToolbarShowsBaselineSeparatorKey];
_allowsUserCustomization = [aCoder decodeBoolForKey:CPToolbarAllowsUserCustomizationKey];
_isVisible = [aCoder decodeBoolForKey:CPToolbarIsVisibleKey];
_sizeMode = [aCoder decodeIntForKey:CPToolbarSizeModeKey];
_identifiedItems = [aCoder decodeObjectForKey:CPToolbarIdentifiedItemsKey];
_defaultItems = [aCoder decodeObjectForKey:CPToolbarDefaultItemsKey];
@@ -492,6 +574,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
[aCoder encodeBool:_showsBaselineSeparator forKey:CPToolbarShowsBaselineSeparatorKey];
[aCoder encodeBool:_allowsUserCustomization forKey:CPToolbarAllowsUserCustomizationKey];
[aCoder encodeBool:_isVisible forKey:CPToolbarIsVisibleKey];
[aCoder encodeInt:_sizeMode forKey:CPToolbarSizeModeKey]
[aCoder encodeObject:_identifiedItems forKey:CPToolbarIdentifiedItemsKey];
[aCoder encodeObject:_defaultItems forKey:CPToolbarDefaultItemsKey];
@@ -508,14 +591,13 @@ var _CPToolbarViewBackgroundColor = nil,
_CPToolbarViewExtraItemsImage = nil,
_CPToolbarViewExtraItemsAlternateImage = nil;
var TOOLBAR_TOP_MARGIN = 5.0,
TOOLBAR_ITEM_MARGIN = 10.0,
var TOOLBAR_ITEM_MARGIN = 10.0,
TOOLBAR_EXTRA_ITEMS_WIDTH = 20.0;
var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
{
return { index:anIndex, view:aView, label:aLabel, minWidth:aMinWidth };
}
};
/* @ignore */
@implementation _CPToolbarView : CPView
@@ -547,9 +629,9 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
var bundle = [CPBundle bundleForClass:self];
_CPToolbarViewExtraItemsImage = [[CPImage alloc] initWithContentsOfFile: [bundle pathForResource:"_CPToolbarView/_CPToolbarViewExtraItemsImage.png"] size: CPSizeMake(10.0, 15.0)];
_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)];
_CPToolbarViewExtraItemsAlternateImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:"_CPToolbarView/_CPToolbarViewExtraItemsAlternateImage.png"] size:_CGSizeMake(10.0, 15.0)];
}
- (id)initWithFrame:(CGRect)aFrame
@@ -563,7 +645,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
_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 = [[CPPopUpButton alloc] initWithFrame:_CGRectMake(0.0, 0.0, 10.0, 15.0) pullsDown:YES];
[_additionalItemsButton setBordered:NO];
[_additionalItemsButton setImagePosition:CPImageOnly];
@@ -615,7 +697,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
{
// We begin by recalculating the visible items.
var items = [_toolbar items],
itemsWidth = CGRectGetWidth([self bounds]),
itemsWidth = _CGRectGetWidth([self bounds]),
minWidth = _minWidth,
// FIXME: This should be a CPSet.
invisibleItemsSortedByPriority = [];
@@ -665,6 +747,24 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
height = minSize.height;
}
// We'll figure out the proper height for the toolbar depending on its items.
// If nothing has a minimum size we'll use the standard toolbar size for the
// sizeMode, indicated by a 0 _desiredHeight.
var contentInset = [_toolbar _valueForThemeAttribute:@"content-inset"],
newDesiredHeight = height ? height + contentInset.top + contentInset.bottom : 0;
if (newDesiredHeight != _toolbar._desiredHeight)
{
// FIXME Probably the toolbar view shouldn't be telling the toolbar which height it should be. Maybe refactor
// to just have the toolbar scan the toolbar items whenever the items change.
_toolbar._desiredHeight = newDesiredHeight;
[self setFrame:[_toolbar _toolbarViewFrame]];
[_toolbar._window _noteToolbarChanged];
// The above will cause tile to be called again.
return;
}
// Determine all the items that have flexible width.
// Also determine the height of the toolbar.
var count = _visibleItems.length,
@@ -684,7 +784,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
// static width (min==max). This handles the case where the user did setView:
// with a view of a different size than minSize/maxSize
else
[view setFrameSize:CGSizeMake(minSize.width, height)];
[view setFrameSize:_CGSizeMake(minSize.width, height)];
[view setHidden:NO];
}
@@ -719,21 +819,23 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
remainingSpace += proposedWidth - constrainedWidth;
}
[view setFrameSize:CGSizeMake(constrainedWidth, height)];
[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,
x = TOOLBAR_ITEM_MARGIN;
x = contentInset.left,
contentInset = [_toolbar _valueForThemeAttribute:@"content-inset"],
y = contentInset.top;
for (; index < count; ++index)
{
var view = [self viewForItem:_visibleItems[index]],
viewWidth = CGRectGetWidth([view frame]);
viewWidth = _CGRectGetWidth([view frame]);
[view setFrame:CGRectMake(x, 0.0, viewWidth, height)];
[view setFrame:_CGRectMake(x, y, viewWidth, height)];
x += viewWidth + TOOLBAR_ITEM_MARGIN;
}
@@ -767,7 +869,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
if (needsAdditionalItemsButton)
{
[_additionalItemsButton setFrameOrigin:CGPointMake(itemsWidth + 5.0, (CGRectGetHeight([self bounds]) - CGRectGetHeight([_additionalItemsButton frame])) / 2.0)];
[_additionalItemsButton setFrameOrigin:_CGPointMake(itemsWidth + 5.0, (_CGRectGetHeight([self bounds]) - _CGRectGetHeight([_additionalItemsButton frame])) / 2.0)];
[self addSubview:_additionalItemsButton];
@@ -876,10 +978,9 @@ var _CPToolbarItemVisibilityPriorityCompare = function(lhs, rhs)
return CPOrderedAscending;
return CPOrderedDescending;
}
};
var TOP_MARGIN = 5.0,
LABEL_MARGIN = 2.0;
var LABEL_MARGIN = 2.0;
@implementation _CPToolbarItemView : CPControl
{
@@ -906,12 +1007,12 @@ var TOP_MARGIN = 5.0,
{
_toolbarItem = aToolbarItem;
_labelField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
_labelField = [[CPTextField alloc] initWithFrame:_CGRectMakeZero()];
[_labelField setFont:[CPFont systemFontOfSize:11.0]];
[_labelField setTextColor:[self FIXME_labelColor]];
[_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
[_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_labelField setTextShadowOffset:_CGSizeMake(0.0, 1.0)];
[_labelField setAutoresizingMask:CPViewWidthSizable | CPViewMinXMargin];
[self addSubview:_labelField];
@@ -958,11 +1059,11 @@ var TOP_MARGIN = 5.0,
if (identifier === CPToolbarSeparatorItemIdentifier)
{
_view = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 2.0, 32.0)];
_view = [[CPView alloc] initWithFrame:_CGRectMake(0.0, 0.0, 2.0, 32.0)];
// FIXME: Get rid of this old API!!!
sizes = {};
sizes[@"CPToolbarItemSeparator"] = [CGSizeMake(2.0, 26.0), CGSizeMake(2.0, 1.0), CGSizeMake(2.0, 26.0)];
sizes[@"CPToolbarItemSeparator"] = [_CGSizeMake(2.0, 26.0), _CGSizeMake(2.0, 1.0), _CGSizeMake(2.0, 26.0)];
[_view setBackgroundColor:_CPControlThreePartImagePattern(YES, sizes, @"CPToolbarItem", @"Separator")];
[self addSubview:_view];
@@ -996,7 +1097,7 @@ var TOP_MARGIN = 5.0,
{
_imageView = [[CPImageView alloc] initWithFrame:[self bounds]];
[_imageView setImageScaling:CPScaleProportionally];
[_imageView setImageScaling:CPImageScaleProportionallyDown];
[self addSubview:_imageView];
}
@@ -1014,8 +1115,13 @@ var TOP_MARGIN = 5.0,
_labelSize = [_labelField frame].size;
_minSize = CGSizeMake(MAX(_labelSize.width, minSize.width), _labelSize.height + minSize.height + LABEL_MARGIN + TOP_MARGIN);
_maxSize = CGSizeMake(MAX(_labelSize.width, maxSize.width), 100000000.0);
var iconOnly = [[_toolbarItem toolbar] displayMode] === CPToolbarDisplayModeIconOnly,
labelOnly = [[_toolbarItem toolbar] displayMode] === CPToolbarDisplayModeLabelOnly;
[_labelField setHidden:iconOnly];
[_view setHidden:labelOnly];
_minSize = _CGSizeMake(MAX(_labelSize.width, minSize.width), (labelOnly ? 0 : minSize.height) + (iconOnly ? 0 : _labelSize.height + LABEL_MARGIN));
_maxSize = _CGSizeMake(MAX(_labelSize.width, maxSize.width), 100000000.0);
[_toolbar tile];
}
@@ -1032,20 +1138,23 @@ var TOP_MARGIN = 5.0,
width = _CGRectGetWidth(bounds);
if (identifier === CPToolbarSeparatorItemIdentifier)
return [_view setFrame:CGRectMake(ROUND((width - 2.0) / 2.0), 0.0, 2.0, _CGRectGetHeight(bounds))];
return [_view setFrame:_CGRectMake(ROUND((width - 2.0) / 2.0), 0.0, 2.0, _CGRectGetHeight(bounds))];
// The view is centred in the available space above the label.
var view = _view || _imageView,
itemMaxSize = [_toolbarItem maxSize],
height = _CGRectGetHeight(bounds) - _labelSize.height - LABEL_MARGIN - TOP_MARGIN,
iconOnly = [[_toolbarItem toolbar] displayMode] === CPToolbarDisplayModeIconOnly,
height = _CGRectGetHeight(bounds) - (iconOnly ? 0 : _labelSize.height),
viewWidth = MIN(itemMaxSize.width, width),
viewHeight = MIN(itemMaxSize.height, height);
[view setFrame:CGRectMake( ROUND((width - viewWidth) / 2.0),
TOP_MARGIN + ROUND((height - viewHeight) / 2.0),
viewWidth,
viewHeight)];
[view setFrame:_CGRectMake(ROUND((width - viewWidth) / 2.0),
ROUND((height - viewHeight) / 2.0),
viewWidth,
viewHeight)];
[_labelField setFrameOrigin:CGPointMake(ROUND((width - _labelSize.width) / 2.0), TOP_MARGIN + height + LABEL_MARGIN)];
// Label is always drawn at the bottom of the view. So if the view is really tall but the icon is tiny, the icon is centred above the label while the label remains on the bottom.
[_labelField setFrameOrigin:_CGPointMake(ROUND((width - _labelSize.width) / 2.0), _CGRectGetHeight(bounds) - _labelSize.height)];
}
- (void)mouseDown:(CPEvent)anEvent
@@ -1108,7 +1217,7 @@ var TOP_MARGIN = 5.0,
if (alternateImage)
[_imageView setImage:alternateImage];
[_labelField setTextShadowOffset:CGSizeMakeZero()];
[_labelField setTextShadowOffset:_CGSizeMakeZero()];
}
else
{
@@ -1117,7 +1226,7 @@ var TOP_MARGIN = 5.0,
if (image)
[_imageView setImage:image];
[_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_labelField setTextShadowOffset:_CGSizeMake(0.0, 1.0)];
}
[_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
+5 -5
View File
@@ -180,7 +180,7 @@ var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
var keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
while (keysCount--)
{
var key = keys[keysCount];
[self willChangeValueForKey:key];
@@ -194,7 +194,7 @@ var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
var keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
while (keysCount--)
{
var key = keys[keysCount];
[[_controller defaults] setObject:[_cachedValues objectForKey:key] forKey:key];
@@ -207,7 +207,7 @@ var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
while (keysCount--)
{
var key = keys[keysCount];
[self willChangeValueForKey:key];
@@ -229,7 +229,7 @@ var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
while (keysCount--)
{
var key = keys[keysCount],
value = [_cachedValues objectForKey:key],
@@ -250,7 +250,7 @@ var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
while (keysCount--)
{
var key = keys[keysCount],
value = [_cachedValues objectForKey:key],
+261 -18
View File
@@ -21,14 +21,14 @@
*/
@import <Foundation/CPArray.j>
@import <Foundation/CPGeometry.j>
@import <Foundation/CPObjJRuntime.j>
@import <Foundation/CPSet.j>
@import "CGAffineTransform.j"
@import "CGGeometry.j"
@import "CPColor.j"
@import "CPGeometry.j"
@import "CPGraphicsContext.j"
@import "CPResponder.j"
@import "CPTheme.j"
@@ -98,6 +98,10 @@ var CPViewFlags = { },
CPViewHasCustomDrawRect = 1 << 0,
CPViewHasCustomLayoutSubviews = 1 << 1;
var CPCurrentToolTip,
CPCurrentToolTipTimer,
CPToolTipDelay = 1.0;
/*!
@ingroup appkit
@class CPView
@@ -141,6 +145,7 @@ var CPViewFlags = { },
BOOL _postsFrameChangedNotifications;
BOOL _postsBoundsChangedNotifications;
BOOL _inhibitFrameAndBoundsChangedNotifications;
BOOL _inLiveResize;
#if PLATFORM(DOM)
DOMElement _DOMElement;
@@ -188,7 +193,10 @@ var CPViewFlags = { },
unsigned _viewClassFlags;
// ToolTips
CPString _toolTip @accessors(property=toolTip);
CPString _toolTip @accessors(getter=toolTip);
Function _toolTipFunctionIn;
Function _toolTipFunctionOut;
BOOL _toolTipInstalled;
}
/*
@@ -214,7 +222,7 @@ var CPViewFlags = { },
CachedNotificationCenter = [CPNotificationCenter defaultCenter];
}
- (void)setupViewFlags
- (void)_setupViewFlags
{
var theClass = [self class],
classUID = [theClass UID];
@@ -235,6 +243,13 @@ var CPViewFlags = { },
_viewClassFlags = CPViewFlags[classUID];
}
- (void)_setupToolTipHandlers
{
_toolTipInstalled = NO;
_toolTipFunctionIn = function(e) { [self _fireToolTip]; }
_toolTipFunctionOut = function(e) { [self _invalidateToolTip]; };
}
+ (CPSet)keyPathsForValuesAffectingFrame
{
return [CPSet setWithObjects:@"frameOrigin", @"frameSize"];
@@ -291,6 +306,9 @@ var CPViewFlags = { },
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(aFrame), _CGRectGetMinY(aFrame));
CPDOMDisplayServerSetStyleSize(_DOMElement, width, height);
if (typeof(appkit_tag_dom_elements) !== "undefined" && !!appkit_tag_dom_elements)
_DOMElement.setAttribute("data-cappuccino-view", [self className]);
_DOMImageParts = [];
_DOMImageSizes = [];
#endif
@@ -298,7 +316,8 @@ var CPViewFlags = { },
_theme = [CPTheme defaultTheme];
_themeState = CPThemeStateNormal;
[self setupViewFlags];
[self _setupToolTipHandlers];
[self _setupViewFlags];
[self _loadThemeAttributes];
}
@@ -306,6 +325,127 @@ var CPViewFlags = { },
return self;
}
/*!
Sets the tooltip for the receiver.
@param aToolTip the tooltip
*/
- (void)setToolTip:(CPString)aToolTip
{
if (_toolTip == aToolTip)
return;
_toolTip = aToolTip;
if (_toolTip)
[self _installToolTipEventHandlers];
else
[self _uninstallToolTipEventHandlers];
}
/*! @ignore
Install the handlers for the tooltip
*/
- (void)_installToolTipEventHandlers
{
if (_toolTipInstalled)
return;
#if PLATFORM(DOM)
if (_DOMElement.addEventListener)
{
_DOMElement.addEventListener("mouseover", _toolTipFunctionIn, NO);
_DOMElement.addEventListener("keypress", _toolTipFunctionOut, NO);
_DOMElement.addEventListener("mouseout", _toolTipFunctionOut, NO);
}
else if (_DOMElement.attachEvent)
{
_DOMElement.attachEvent("onmouseover", _toolTipFunctionIn);
_DOMElement.attachEvent("onkeypress", _toolTipFunctionOut);
_DOMElement.attachEvent("onmouseout", _toolTipFunctionOut);
}
#endif
_toolTipInstalled = YES;
}
/*! @ignore
Uninstall the handlers for the tooltip
*/
- (void)_uninstallToolTipEventHandlers
{
if (!_toolTipInstalled)
return;
#if PLATFORM(DOM)
if (_DOMElement.removeEventListener)
{
_DOMElement.removeEventListener("mouseover", _toolTipFunctionIn, NO);
_DOMElement.removeEventListener("keypress", _toolTipFunctionOut, NO);
_DOMElement.removeEventListener("mouseout", _toolTipFunctionOut, NO);
}
else if (_DOMElement.detachEvent)
{
_DOMElement.detachEvent("onmouseover", _toolTipFunctionIn);
_DOMElement.detachEvent("onkeypress", _toolTipFunctionOut);
_DOMElement.detachEvent("onmouseout", _toolTipFunctionOut);
}
#endif
_toolTipInstalled = NO;
}
/*! @ignore
Starts the tooltip timer.
*/
- (void)_fireToolTip
{
if (CPCurrentToolTipTimer)
{
[CPCurrentToolTipTimer invalidate];
if (CPCurrentToolTip)
[CPCurrentToolTip close];
CPCurrentToolTip = nil;
}
if (_toolTip)
CPCurrentToolTipTimer = [CPTimer scheduledTimerWithTimeInterval:CPToolTipDelay target:self selector:@selector(_showToolTip:) userInfo:nil repeats:NO];
}
/*! @ignore
Stop the tooltip timer if any
*/
- (void)_invalidateToolTip
{
if (CPCurrentToolTipTimer)
{
[CPCurrentToolTipTimer invalidate];
CPCurrentToolTipTimer = nil;
}
if (CPCurrentToolTip)
{
[CPCurrentToolTip close];
CPCurrentToolTip = nil;
}
}
/*! @ignore
Actually shows the tooltip if any
*/
- (void)_showToolTip:(CPTimer)aTimer
{
if (CPCurrentToolTip)
[CPCurrentToolTip close];
CPCurrentToolTip = [_CPToolTip toolTipWithString:_toolTip];
}
/*!
Returns the container view of the receiver
@return the receiver's containing view
@@ -365,6 +505,9 @@ var CPViewFlags = { },
/* @ignore */
- (void)_insertSubview:(CPView)aSubview atIndex:(int)anIndex
{
if (aSubview === self)
[CPException raise:CPInvalidArgumentException reason:"can't add a view as a subview of itself"];
// We will have to adjust the z-index of all views starting at this index.
var count = _subviews.length;
@@ -527,7 +670,7 @@ var CPViewFlags = { },
var addedSubview = nil,
addedSubviewEnumerator = [addedSubviews objectEnumerator];
while (addedSubview = [addedSubviewEnumerator nextObject])
while ((addedSubview = [addedSubviewEnumerator nextObject]) !== nil)
[self addSubview:addedSubview];
// If the order is fine, no need to reorder.
@@ -635,7 +778,7 @@ var CPViewFlags = { },
}
/*!
Called when the receiver is about to be remove one of its subviews.
Called when the receiver is about to remove one of its subviews.
@param aView the view that will be removed
*/
- (void)willRemoveSubview:(CPView)aView
@@ -706,7 +849,7 @@ var CPViewFlags = { },
/*!
Sets the frame size of the receiver to the dimensions and origin of the provided rectangle in the coordinate system
of the superview. The method also posts an CPViewFrameDidChangeNotification to the notification
of the superview. The method also posts a CPViewFrameDidChangeNotification to the notification
center if the receiver is configured to do so. If the frame is the same as the current frame, the method simply
returns (and no notification is posted).
@param aFrame the rectangle specifying the new origin and size of the receiver
@@ -759,7 +902,7 @@ var CPViewFlags = { },
}
/*!
Returns the center of the receiver's frame to the provided point. The point is defined in the superview's coordinate system.
Returns the center of the receiver's frame in the superview's coordinate system.
@return CGPoint the center point of the receiver's frame
*/
- (CGPoint)center
@@ -848,11 +991,17 @@ var CPViewFlags = { },
if (_backgroundType === BackgroundVerticalThreePartImage)
{
// Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], size.width, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width, size.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], size.width, _DOMImageSizes[2].height);
}
else if (_backgroundType === BackgroundHorizontalThreePartImage)
{
// Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], _DOMImageSizes[0].width, size.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, size.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], _DOMImageSizes[2].width, size.height);
}
else if (_backgroundType === BackgroundNinePartImage)
{
@@ -1539,7 +1688,10 @@ var CPViewFlags = { },
}
else if (_backgroundType == BackgroundVerticalThreePartImage)
{
// Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], frameSize.width, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], frameSize.width, frameSize.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], frameSize.width, _DOMImageSizes[2].height);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, 0.0, _DOMImageSizes[0].height);
@@ -1547,7 +1699,10 @@ var CPViewFlags = { },
}
else if (_backgroundType == BackgroundHorizontalThreePartImage)
{
// Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], _DOMImageSizes[0].width, frameSize.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], frameSize.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, frameSize.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], _DOMImageSizes[2].width, frameSize.height);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, _DOMImageSizes[0].width, 0.0);
@@ -2128,6 +2283,43 @@ setBoundsOrigin:
{
}
/*!
Return yes if the receiver is in a live-resize operation.
*/
- (BOOL)inLiveResize
{
return _inLiveResize;
}
/*!
Not implemented.
A view will be sent this message before a window begins a resize operation. The
receiver might choose to simplify its drawing operations during a live resize
for speed.
Subclasses should call super.
*/
- (void)viewWillStartLiveResize
{
_inLiveResize = YES;
}
/*!
Not implemented.
A view will be sent this message after a window finishes a resize operation. The
receiver which simplified its drawing operations in viewWillStartLiveResize might
stop doing so now. Note the view might no longer be in a window, so use
[self setNeedsDisplay:YES] if a final non-simplified redraw is required.
Subclasses should call super.
*/
- (void)viewDidEndLiveResize
{
_inLiveResize = NO;
}
@end
@implementation CPView (KeyView)
@@ -2543,6 +2735,50 @@ setBoundsOrigin:
return (_themeAttributes && _themeAttributes[aName] !== undefined);
}
/*!
Registers theme values encoded in an array at runtime. The format of the data in the array
is the same as that used by ThemeDescriptors.j, with the exception that you need to use
CPColorWithImages() in place of PatternColor(). For more information see the comments
at the top of ThemeDescriptors.j.
@param themeValues array of theme values
*/
- (void)registerThemeValues:(CPArray)themeValues
{
for (var i = 0; i < themeValues.length; ++i)
{
var attributeValueState = themeValues[i],
attribute = attributeValueState[0],
value = attributeValueState[1],
state = attributeValueState[2];
if (state)
[self setValue:value forThemeAttribute:attribute inState:state];
else
[self setValue:value forThemeAttribute:attribute];
}
}
/*!
Registers theme values encoded in an array at runtime. The format of the data in the array
is the same as that used by ThemeDescriptors.j, with the exception that you need to use
CPColorWithImages() in place of PatternColor(). The values in \c inheritedValues are
registered first, then those in \c themeValues override/augment the inherited values.
For more information see the comments at the top of ThemeDescriptors.j.
@param themeValues array of base theme values
@param inheritedValues array of overridden/additional theme values
*/
- (void)registerThemeValues:(CPArray)themeValues inherit:(CPArray)inheritedValues
{
// Register inherited values first, then override those with the subtheme values.
if (inheritedValues)
[self registerThemeValues:inheritedValues];
if (themeValues)
[self registerThemeValues:themeValues];
}
- (CPView)createEphemeralSubviewNamed:(CPString)aViewName
{
return nil;
@@ -2607,6 +2843,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
CPViewBoundsKey = @"CPViewBoundsKey",
CPViewFrameKey = @"CPViewFrameKey",
CPViewHitTestsKey = @"CPViewHitTestsKey",
CPViewToolTipKey = @"CPViewToolTipKey",
CPViewIsHiddenKey = @"CPViewIsHiddenKey",
CPViewOpacityKey = @"CPViewOpacityKey",
CPViewSubviewsKey = @"CPViewSubviewsKey",
@@ -2661,7 +2898,12 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
_autoresizesSubviews = ![aCoder containsValueForKey:CPViewAutoresizesSubviewsKey] || [aCoder decodeBoolForKey:CPViewAutoresizesSubviewsKey];
_hitTests = ![aCoder containsValueForKey:CPViewHitTestsKey] || [aCoder decodeObjectForKey:CPViewHitTestsKey];
_hitTests = ![aCoder containsValueForKey:CPViewHitTestsKey] || [aCoder decodeBoolForKey:CPViewHitTestsKey];
[self _setupToolTipHandlers];
_toolTip = [aCoder decodeObjectForKey:CPViewToolTipKey];
if (_toolTip)
[self _installToolTipEventHandlers];
// DOM SETUP
#if PLATFORM(DOM)
@@ -2681,10 +2923,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
}
#endif
if ([aCoder containsValueForKey:CPViewIsHiddenKey])
[self setHidden:[aCoder decodeBoolForKey:CPViewIsHiddenKey]];
else
_isHidden = NO;
[self setHidden:[aCoder decodeBoolForKey:CPViewIsHiddenKey]];
if ([aCoder containsValueForKey:CPViewOpacityKey])
[self setAlphaValue:[aCoder decodeIntForKey:CPViewOpacityKey]];
@@ -2692,8 +2931,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
_opacity = 1.0;
[self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]];
[self setupViewFlags];
[self _setupViewFlags];
_theme = [CPTheme defaultTheme];
_themeClass = [aCoder decodeObjectForKey:CPViewThemeClassKey];
@@ -2774,6 +3012,9 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
if (_isHidden)
[aCoder encodeBool:_isHidden forKey:CPViewIsHiddenKey];
if (_toolTip)
[aCoder encodeObject:_toolTip forKey:CPViewToolTipKey];
var nextKeyView = [self nextKeyView];
if (nextKeyView !== nil && ![nextKeyView isEqual:self])
@@ -2799,7 +3040,7 @@ var _CPViewFullScreenModeStateMake = function(aView)
var superview = aView._superview;
return { autoresizingMask:aView._autoresizingMask, frame:CGRectMakeCopy(aView._frame), index:(superview ? [superview._subviews indexOfObjectIdenticalTo:aView] : 0), superview:superview };
}
};
var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView)
{
@@ -2896,4 +3137,6 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView)
}*/
return transform;
}
};
+55 -24
View File
@@ -66,6 +66,8 @@ var CPViewControllerCachedCibs;
{
CPView _view @accessors(property=view);
BOOL _isLoading;
BOOL _isLazy;
BOOL _isViewLoaded @accessors(getter=isViewLoaded);
id _representedObject @accessors(property=representedObject);
CPString _title @accessors(property=title);
@@ -77,8 +79,10 @@ var CPViewControllerCachedCibs;
+ (void)initialize
{
if (self === CPViewController)
CPViewControllerCachedCibs = [CPDictionary dictionary];
if (self !== [CPViewController class])
return;
CPViewControllerCachedCibs = [CPDictionary dictionary];
}
/*!
@@ -124,6 +128,7 @@ var CPViewControllerCachedCibs;
_cibExternalNameTable = anExternalNameTable || [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
_isLoading = NO;
_isLazy = NO;
}
return self;
@@ -136,12 +141,12 @@ var CPViewControllerCachedCibs;
If you create your views manually, you must override this method and use
it to create your view and assign it to the view property. The default
implementation for programmatic views is to create a plain view. You can
invoke super to utilize this view.
implementation for programmatic views is to create a plain, zero width & height
view. You can invoke super to utilize this view.
If you use Interface Builder to create your views, you initialize the view
using the initWithCibName:bundle: method then you must not override this
method. The consequences risk shattering the space-time continuum.
If you use Interface Builder to create your views, and you initialize the
controller using the initWithCibName:bundle: methods, then you MUST NOT override
this method. The consequences risk shattering the space-time continuum.
Note: The cib loading system is currently synchronous.
*/
@@ -150,17 +155,22 @@ var CPViewControllerCachedCibs;
if (_view)
return;
// check if a cib is already cached for the current _cibName
var cib = [CPViewControllerCachedCibs objectForKey:_cibName];
if (!cib)
if (_cibName)
{
// if the cib isn't cached yet : fetch it and cache it
cib = [[CPCib alloc] initWithContentsOfURL:[_cibBundle pathForResource:_cibName + @".cib"]];
[CPViewControllerCachedCibs setObject:cib forKey:_cibName];
}
// check if a cib is already cached for the current _cibName
var cib = [CPViewControllerCachedCibs objectForKey:_cibName];
[cib instantiateCibWithExternalNameTable:_cibExternalNameTable];
if (!cib)
{
// if the cib isn't cached yet : fetch it and cache it
cib = [[CPCib alloc] initWithCibNamed:_cibName bundle:_cibBundle];
[CPViewControllerCachedCibs setObject:cib forKey:_cibName];
}
[cib instantiateCibWithExternalNameTable:_cibExternalNameTable];
}
else
_view = [CPView new];
}
/*!
@@ -197,20 +207,32 @@ var CPViewControllerCachedCibs;
[cibOwner viewControllerDidLoadCib:self];
_isLoading = NO;
[self viewDidLoad];
[self _viewDidLoad];
}
else if (_isLazy)
{
_isLazy = NO;
[self _viewDidLoad];
}
return _view;
}
- (void)_viewDidLoad
{
[self willChangeValueForKey:"isViewLoaded"];
[self viewDidLoad];
isViewLoaded = YES;
[self didChangeValueForKey:"isViewLoaded"];
}
/*!
This method is called after the view controller has loaded its associated views into memory.
This method is called regardless of whether the views were stored in a nib
file or created programmatically in the loadView method. This method is
most commonly used to perform additional initialization steps on views
that are loaded from cib files.
file or created programmatically in the loadView method, but NOT when setView
is invoked. This method is most commonly used to perform additional initialization
steps on views that are loaded from cib files.
*/
- (void)viewDidLoad
{
@@ -228,13 +250,21 @@ var CPViewControllerCachedCibs;
*/
- (void)setView:(CPView)aView
{
var viewWasLoaded = !_view;
var willChangeIsViewLoaded = (_isViewLoaded == NO && aView != nil) || (_isViewLoaded == YES && aView == nil);
if (willChangeIsViewLoaded)
[self willChangeValueForKey:"isViewLoaded"];
_view = aView;
_isViewLoaded = aView !== nil;
// Make sure the viewDidLoad method is called if the view is set directly
if (!_isLoading && viewWasLoaded)
[self viewDidLoad];
if (willChangeIsViewLoaded)
[self didChangeValueForKey:"isViewLoaded"];
}
- (BOOL)automaticallyNotifiesObserversOfIsViewLoaded
{
return NO;
}
@end
@@ -266,6 +296,7 @@ var CPViewControllerViewKey = @"CPViewControllerViewKey",
_cibBundle = bundlePath ? [CPBundle bundleWithPath:bundlePath] : [CPBundle mainBundle];
_cibExternalNameTable = [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
_isLazy = YES;
}
return self;
+2 -2
View File
@@ -199,7 +199,7 @@ CPWebViewAppKitScrollMaxPollCount = 3;
_ignoreLoadEnd = NO;
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
};
if (_iframe.addEventListener)
_iframe.addEventListener("load", _loadCallback, false);
@@ -830,7 +830,7 @@ CPWebViewAppKitScrollMaxPollCount = 3;
- (@action)reload:(id)sender
{
// If we're displaying pure HTML, redisplay it.
if(!_url && (_html !== nil))
if (!_url && (_html !== nil))
[self loadHTMLString:_html];
else
[self _loadMainFrameURL];
+372 -95
View File
@@ -167,18 +167,20 @@ CPWindowAbove = 1;
*/
CPWindowBelow = 2;
CPWindowWillCloseNotification = @"CPWindowWillCloseNotification";
CPWindowDidBecomeMainNotification = @"CPWindowDidBecomeMainNotification";
CPWindowDidResignMainNotification = @"CPWindowDidResignMainNotification";
CPWindowDidBecomeKeyNotification = @"CPWindowDidBecomeKeyNotification";
CPWindowDidResignKeyNotification = @"CPWindowDidResignKeyNotification";
CPWindowDidResizeNotification = @"CPWindowDidResizeNotification";
CPWindowDidMoveNotification = @"CPWindowDidMoveNotification";
CPWindowWillBeginSheetNotification = @"CPWindowWillBeginSheetNotification";
CPWindowDidEndSheetNotification = @"CPWindowDidEndSheetNotification";
CPWindowDidMiniaturizeNotification = @"CPWindowDidMiniaturizeNotification";
CPWindowWillMiniaturizeNotification = @"CPWindowWillMiniaturizeNotification";
CPWindowDidDeminiaturizeNotification = @"CPWindowDidDeminiaturizeNotification";
CPWindowWillCloseNotification = @"CPWindowWillCloseNotification";
CPWindowDidBecomeMainNotification = @"CPWindowDidBecomeMainNotification";
CPWindowDidResignMainNotification = @"CPWindowDidResignMainNotification";
CPWindowDidBecomeKeyNotification = @"CPWindowDidBecomeKeyNotification";
CPWindowDidResignKeyNotification = @"CPWindowDidResignKeyNotification";
CPWindowDidResizeNotification = @"CPWindowDidResizeNotification";
CPWindowDidMoveNotification = @"CPWindowDidMoveNotification";
CPWindowWillBeginSheetNotification = @"CPWindowWillBeginSheetNotification";
CPWindowDidEndSheetNotification = @"CPWindowDidEndSheetNotification";
CPWindowDidMiniaturizeNotification = @"CPWindowDidMiniaturizeNotification";
CPWindowWillMiniaturizeNotification = @"CPWindowWillMiniaturizeNotification";
CPWindowDidDeminiaturizeNotification = @"CPWindowDidDeminiaturizeNotification";
_CPWindowDidChangeFirstResponderNotification = @"_CPWindowDidChangeFirstResponderNotification";
CPWindowShadowStyleStandard = 0;
CPWindowShadowStyleMenu = 1;
@@ -257,6 +259,16 @@ var CPWindowActionMessageKeys = [
@param window the window to close
@return \c YES allows the window to close. \c NO
vetoes the close operation and leaves the window open.
@delegate -(BOOL)windowWillBeginSheet:(CPNotification)notification;
Sent from the notification center before sheet is visible on
the delegate's window.
@param notification contains information about the event
@delegate -(BOOL)windowDidEndSheet:(CPNotification)notification;
Sent from the notification center when an attached sheet on the
delegate's window has been animated out and is no longer visible.
@param notification contains information about the event
*/
@implementation CPWindow : CPResponder
{
@@ -333,7 +345,6 @@ var CPWindowActionMessageKeys = [
CPDictionary _sheetContext;
CPWindow _parentView;
BOOL _isSheet;
_CPWindowFrameAnimation _frameAnimation;
}
@@ -343,7 +354,7 @@ var CPWindowActionMessageKeys = [
*/
+ (void)initialize
{
if (self != [CPWindow class])
if (self !== [CPWindow class])
return;
var bundle = [CPBundle bundleForClass:[CPWindow class]];
@@ -403,10 +414,13 @@ CPTexturedBackgroundWindowMask
_isFullPlatformWindow = NO;
_registeredDraggedTypes = [CPSet set];
_registeredDraggedTypesArray = [];
_isSheet = NO;
_acceptsMouseMovedEvents = YES;
_isMovable = YES;
_isSheet = NO;
_sheetContext = nil;
_parentView = nil;
// Set up our window number.
_windowNumber = [CPApp._windows count];
CPApp._windows[_windowNumber] = self;
@@ -455,6 +469,7 @@ CPTexturedBackgroundWindowMask
if (aStyleMask & CPBorderlessBridgeWindowMask)
[self setFullPlatformWindow:YES];
_autorecalculatesKeyViewLoop = NO;
_defaultButtonEnabled = YES;
_keyViewLoopIsDirty = YES;
@@ -515,6 +530,11 @@ CPTexturedBackgroundWindowMask
- (void)awakeFromCib
{
_keyViewLoopIsDirty = ![self _hasKeyViewLoop];
// If no key view loop has been specified by hand, and we are not intending to auto recalculate,
// set up a default key view loop.
if (_keyViewLoopIsDirty && ![self autorecalculatesKeyViewLoop])
[self recalculateKeyViewLoop];
}
- (void)_setWindowView:(CPView)aWindowView
@@ -756,7 +776,21 @@ CPTexturedBackgroundWindowMask
[_windowView setFrameSize:size];
if (_hasShadow)
[_shadowView setFrameSize:_CGSizeMake(SHADOW_MARGIN_LEFT + size.width + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_BOTTOM + size.height + SHADOW_MARGIN_TOP + SHADOW_DISTANCE)];
{
// if the shadow would be taller/wider than the window height,
// make it the same as the window height. this allows views to
// become 0, 0 with no shadow on them and makes the sheet
// animation look nicer
var shadowSize = _CGSizeMake(size.width, size.height);
if (size.width >= (SHADOW_MARGIN_LEFT + SHADOW_MARGIN_RIGHT))
shadowSize.width += SHADOW_MARGIN_LEFT + SHADOW_MARGIN_RIGHT;
if (size.height >= (SHADOW_MARGIN_BOTTOM + SHADOW_MARGIN_TOP + SHADOW_DISTANCE))
shadowSize.height += SHADOW_MARGIN_BOTTOM + SHADOW_MARGIN_TOP + SHADOW_DISTANCE;
[_shadowView setFrameSize:shadowSize];
}
if (!_isAnimating)
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidResizeNotification object:self];
@@ -793,6 +827,10 @@ CPTexturedBackgroundWindowMask
- (void)setFrameOrigin:(CGPoint)anOrigin
{
[self _setClippedFrame:_CGRectMake(anOrigin.x, anOrigin.y, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)) display:YES animate:NO];
// reposition sheet
if ([self attachedSheet])
[self _setAttachedSheetFrameOrigin];
}
/*!
@@ -811,16 +849,20 @@ CPTexturedBackgroundWindowMask
- (void)orderFront:(id)aSender
{
#if PLATFORM(DOM)
// -dw- if a sheet is clicked, the parent window should come up too
if ([self isSheet])
[_parentView orderFront:self];
[_platformWindow orderFront:self];
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
#endif
if (_firstResponder === self || !_firstResponder)
[self makeFirstResponder:[self initialFirstResponder]];
if (!CPApp._keyWindow)
[self makeKeyWindow];
if ([self isKeyWindow] && (_firstResponder === self || !_firstResponder))
[self makeFirstResponder:_initialFirstResponder];
if (!CPApp._mainWindow)
[self makeMainWindow];
}
@@ -841,6 +883,13 @@ CPTexturedBackgroundWindowMask
*/
- (void)orderOut:(id)aSender
{
if ([self isSheet])
{
// -dw- as in Cocoa, orderOut: detaches the sheet and animates out
[self._parentView _detachSheetWindow];
return;
}
#if PLATFORM(DOM)
if ([self _sharesChromeWithPlatformWindow])
[_platformWindow orderOut:self];
@@ -956,7 +1005,7 @@ CPTexturedBackgroundWindowMask
// During init the initial first responder is set to the contentView
// if it hasn't changed in the mean time we need to update that reference
// to the new contentView
if ([self initialFirstResponder] === _contentView)
if (_initialFirstResponder === _contentView)
[self setInitialFirstResponder:aView];
_contentView = aView;
@@ -1201,6 +1250,8 @@ CPTexturedBackgroundWindowMask
[defaultCenter removeObserver:_delegate name:CPWindowDidResignMainNotification object:self];
[defaultCenter removeObserver:_delegate name:CPWindowDidMoveNotification object:self];
[defaultCenter removeObserver:_delegate name:CPWindowDidResizeNotification object:self];
[defaultCenter removeObserver:_delegate name:CPWindowWillBeginSheetNotification object:self];
[defaultCenter removeObserver:_delegate name:CPWindowDidEndSheetNotification object:self];
_delegate = aDelegate;
_delegateRespondsToWindowWillReturnUndoManagerSelector = [_delegate respondsToSelector:@selector(windowWillReturnUndoManager:)];
@@ -1246,6 +1297,20 @@ CPTexturedBackgroundWindowMask
selector:@selector(windowDidResize:)
name:CPWindowDidResizeNotification
object:self];
if ([_delegate respondsToSelector:@selector(windowWillBeginSheet:)])
[defaultCenter
addObserver:_delegate
selector:@selector(windowWillBeginSheet:)
name:CPWindowWillBeginSheetNotification
object:self];
if ([_delegate respondsToSelector:@selector(windowDidEndSheet:)])
[defaultCenter
addObserver:_delegate
selector:@selector(windowDidEndSheet:)
name:CPWindowDidEndSheetNotification
object:self];
}
/*!
@@ -1293,9 +1358,45 @@ CPTexturedBackgroundWindowMask
- (void)setInitialFirstResponder:(CPView)aView
{
// Before an initial first responder is set, be sure to calculate the key loop
[self _setupFirstResponder:aView];
_initialFirstResponder = aView;
}
- (void)_setupFirstResponder:(CPView)anInitialFirstResponder
{
/*
If:
- The key loop is dirty
- The key loop does not auto-recalculate
- No view within the window has become first responder
- No initial first responder has been set
Then calculate the key view loop and set the first responder
to the first view in the loop if no initial responder has been set, since we should
always have an initial first responder and a key loop by default.
*/
if (_keyViewLoopIsDirty &&
!_autorecalculatesKeyViewLoop &&
_firstResponder === self &&
_initialFirstResponder === [self contentView])
{
[self recalculateKeyViewLoop];
if (anInitialFirstResponder)
[self makeFirstResponder:anInitialFirstResponder];
else
{
// Make the first key view of the content view the first responder
var firstKeyView = [[self contentView] nextValidKeyView];
[self makeFirstResponder:firstKeyView];
}
}
}
/*!
Attempts to make the \c aResponder the first responder. Before trying
to make it the first responder, the receiver will ask the current first responder
@@ -1320,6 +1421,8 @@ CPTexturedBackgroundWindowMask
_firstResponder = aResponder;
[[CPNotificationCenter defaultCenter] postNotificationName:_CPWindowDidChangeFirstResponderNotification object:self];
return YES;
}
@@ -1488,6 +1591,30 @@ CPTexturedBackgroundWindowMask
var type = [anEvent type],
point = [anEvent locationInWindow];
// If a sheet is attached events get filtered here.
// It is not clear what events should be passed to the view, perhaps all?
// CPLeftMouseDown is needed for window moving and resizing to work.
// CPMouseMoved is needed for rollover effects on title bar buttons.
var sheet = [self attachedSheet];
if (sheet)
{
switch (type)
{
case CPLeftMouseDown:
[_windowView mouseDown:anEvent];
// -dw- if the window is clicked, the sheet should come to front, and become key,
// and the window should be immediately behind
[sheet makeKeyAndOrderFront:self];
break;
case CPMouseMoved:
[_windowView mouseMoved:anEvent];
break;
}
return;
}
switch (type)
{
case CPFlagsChanged: return [[self firstResponder] flagsChanged:anEvent];
@@ -1650,6 +1777,10 @@ CPTexturedBackgroundWindowMask
if (_firstResponder !== self && [_firstResponder respondsToSelector:@selector(becomeKeyWindow)])
[_firstResponder becomeKeyWindow];
[self _setupFirstResponder:nil];
[_windowView noteKeyWindowStateChanged];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPWindowDidBecomeKeyNotification
object:self];
@@ -1707,6 +1838,8 @@ CPTexturedBackgroundWindowMask
if (CPApp._keyWindow === self)
CPApp._keyWindow = nil;
[_windowView noteKeyWindowStateChanged];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPWindowDidResignKeyNotification
object:self];
@@ -2015,7 +2148,7 @@ CPTexturedBackgroundWindowMask
*/
- (BOOL)isMainWindow
{
return [CPApp mainWindow] == self;
return [CPApp mainWindow] === self;
}
/*!
@@ -2052,6 +2185,8 @@ CPTexturedBackgroundWindowMask
[self _synchronizeMenuBarTitleWithWindowTitle];
[self _synchronizeSaveMenuWithDocumentSaving];
[_windowView noteMainWindowStateChanged];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPWindowDidBecomeMainNotification
object:self];
@@ -2068,6 +2203,8 @@ CPTexturedBackgroundWindowMask
if (CPApp._mainWindow === self)
CPApp._mainWindow = nil;
[_windowView noteMainWindowStateChanged];
}
- (void)_updateMainAndKeyWindows
@@ -2236,62 +2373,124 @@ CPTexturedBackgroundWindowMask
[attachedSheet setFrame:sheetFrame display:YES animate:NO];
}
/* @ignore */
- (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
/* @ignore
Starting point for sheet session, called from CPApplication beginSheet:
*/
- (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate
didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
{
if (_sheetContext)
{
[CPException raise:CPInternalInconsistencyException
reason:@"The target window of beginSheet: already has a sheet, did you forget orderOut: ?"];
return;
}
var sheetFrame = [aSheet frame];
_sheetContext = {"sheet":aSheet, "modalDelegate":aModalDelegate, "endSelector":aDidEndSelector, "contextInfo":aContextInfo, "frame":CGRectMakeCopy(sheetFrame), "returnCode":-1, "opened": NO};
_sheetContext = {"sheet": aSheet, "modalDelegate": aModalDelegate, "endSelector": aDidEndSelector,
"contextInfo": aContextInfo, "frame": _CGRectMakeCopy(sheetFrame), "returnCode": -1,
"opened": NO};
[self _attachSheetWindow:aSheet];
[self _attachSheetWindow];
}
/* @ignore */
- (void)_attachSheetWindow:(CPWindow)aSheet
/* @ignore
Called to animate the sheet in. The timer seems to solve a bug where sheets would
be partially animated under certain conditions.
*/
- (void)_attachSheetWindow
{
var sheetFrame = [aSheet frame],
frame = [self frame],
sheetContent = [aSheet contentView];
_sheetContext["isAttached"] = YES;
[self _setUpMasksForView:sheetContent];
aSheet._isSheet = YES;
aSheet._parentView = self;
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2),
originy = frame.origin.y + [[self contentView] frame].origin.y,
startFrame = CGRectMake(originx, originy, sheetFrame.size.width, 0),
endFrame = CGRectMake(originx, originy, sheetFrame.size.width, sheetFrame.size.height);
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
[CPApp runModalForWindow:aSheet];
[aSheet orderFront:self];
[aSheet setFrame:startFrame display:YES animate:NO];
_sheetContext["opened"] = YES;
[aSheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseOut];
// Should run the main loop here until _isAnimating = FALSE
[aSheet becomeKeyWindow];
// it would be ideal to block here and spin an event loop, until attach is complete
[CPTimer scheduledTimerWithTimeInterval:0.0
target:self
selector:@selector(_sheetShouldAnimateIn:)
userInfo:nil
repeats:NO];
}
/* @ignore */
/* @ignore
Called to end the sheet. Note that orderOut: is needed to animate the sheet out, as in Cocoa.
The sheet isn't completely gone until _cleanupSheetWindow gets called.
*/
- (void)_endSheet
{
var delegate = _sheetContext["modalDelegate"],
endSelector = _sheetContext["endSelector"];
// If the sheet has been ordered out, defer didEndSelector until after sheet animates out.
// This must be done since we cannot block and wait for the animation to complete.
if (delegate && endSelector)
{
if (_sheetContext["isAttached"])
objj_msgSend(delegate, endSelector, _sheetContext["sheet"], _sheetContext["returnCode"],
_sheetContext["contextInfo"]);
else
_sheetContext["deferDidEndSelector"] = YES;
}
}
/* @ignore
Called to animate the sheet out. If called while animating in, schedules an animate
out at completion
*/
- (void)_detachSheetWindow
{
var sheet = [self attachedSheet],
startFrame = [sheet frame],
endFrame = CGRectMakeCopy(startFrame);
_sheetContext["isAttached"] = NO;
endFrame.size.height = 0;
// it would be ideal to block here and spin the event loop, until attach is complete
[CPTimer scheduledTimerWithTimeInterval:0.0
target:self
selector:@selector(_sheetShouldAnimateOut:)
userInfo:nil
repeats:NO];
}
_sheetContext["frame"] = startFrame;
/* @ignore
Called to cleanup sheet, when we are definitely done with it
*/
- (void)_cleanupSheetWindow
{
var sheet = _sheetContext["sheet"],
lastFrame = _sheetContext["frame"],
deferDidEnd = _sheetContext["deferDidEndSelector"];
var sheetContent = [sheet contentView];
[self _setUpMasksForView:sheetContent];
[sheet setFrame:lastFrame];
[self _restoreMasksForView:[sheet contentView]];
_sheetContext["opened"] = NO;
[sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseIn];
// if the parent window is modal, the sheet started its own modal session
if (sheet._isModal)
[CPApp stopModal];
// restore the state of window before it was sheetified
[sheet._windowView _enableSheet:NO];
// close it
sheet._isSheet = NO;
[sheet orderOut:self];
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
if (deferDidEnd)
{
var delegate = _sheetContext["modalDelegate"],
selector = _sheetContext["endSelector"],
returnCode = _sheetContext["returnCode"],
contextInfo = _sheetContext["contextInfo"];
// context must be destroyed, since didEnd might want to attach another sheet
_sheetContext = nil;
sheet._parentView = nil;
objj_msgSend(delegate, selector, sheet, returnCode, contextInfo);
}
else
{
_sheetContext = nil;
sheet._parentView = nil;
}
}
/* @ignore */
@@ -2301,34 +2500,117 @@ CPTexturedBackgroundWindowMask
if (anim._window != sheet)
return;
var sheetContent = [sheet contentView];
[CPTimer scheduledTimerWithTimeInterval:0.0
target:self
selector:@selector(_sheetAnimationDidEnd:)
userInfo:nil
repeats:NO];
}
if (_sheetContext["opened"] === YES)
/* @ignore */
- (void)_sheetShouldAnimateIn:(CPTimer)timer
{
// can't open sheet while opening or closing animation is going on
if (_sheetContext["isOpening"] ||
_sheetContext["isClosing"])
return;
var sheet = _sheetContext["sheet"],
sheetFrame = [sheet frame],
frame = [self frame];
[self _setUpMasksForView:[sheet contentView]];
sheet._isSheet = YES;
sheet._parentView = self;
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2),
originy = frame.origin.y + [[self contentView] frame].origin.y,
startFrame = CGRectMake(originx, originy, sheetFrame.size.width, 0),
endFrame = CGRectMake(originx, originy, sheetFrame.size.width, sheetFrame.size.height);
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
// if sheet is attached to a modal window, the sheet runs
// as if itself and the parent window are modal
sheet._isModal = NO;
if ([CPApp modalWindow] === self)
{
[self _restoreMasksForView:sheetContent];
[CPApp runModalForWindow:sheet];
sheet._isModal = YES;
}
[sheet orderFront:self];
[sheet setFrame:startFrame display:YES animate:NO];
_sheetContext["opened"] = YES;
_sheetContext["shouldClose"] = NO;
_sheetContext["isOpening"] = YES;
[sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseOut];
// NOTE: cocoa doesn't make window key until animation is done, but a
// keypress while animating eventually gets to the window. Therefore,
// there must be a runloop specifically designed for sheets?
[sheet makeKeyWindow];
}
/* @ignore */
- (void)_sheetShouldAnimateOut:(CPTimer)timer
{
var sheet = _sheetContext["sheet"],
startFrame = [sheet frame],
endFrame = CGRectMakeCopy(startFrame);
if (_sheetContext["isOpening"])
{
// allow sheet to be closed while opening, it will close when animate in completes
_sheetContext["shouldClose"] = YES;
return;
}
[CPApp stopModal];
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
if (_sheetContext["isClosing"])
return;
[sheet orderOut:self];
_sheetContext["opened"] = NO;
_sheetContext["frame"] = startFrame;
_sheetContext["isClosing"] = YES;
var lastFrame = _sheetContext["frame"];
[sheet setFrame:lastFrame];
// the parent window can be orderedOut to disable the sheet animate out, as in Cocoa
if ([self isVisible])
{
endFrame.size.height = 0;
[self _setUpMasksForView:[sheet contentView]];
[sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseIn];
}
else
{
[self _sheetAnimationDidEnd:nil];
}
}
[self _restoreMasksForView:sheetContent];
/* @ignore */
- (void)_sheetAnimationDidEnd:(CPTimer)timer
{
var sheet = _sheetContext["sheet"];
var delegate = _sheetContext["modalDelegate"],
endSelector = _sheetContext["endSelector"],
returnCode = _sheetContext["returnCode"],
contextInfo = _sheetContext["contextInfo"];
_sheetContext["isOpening"] = NO;
_sheetContext["isClosing"] = NO;
_sheetContext = nil;
sheet._parentView = nil;
if (_sheetContext["opened"] === YES)
{
// sheet is open and completely visible
[self _restoreMasksForView:[sheet contentView]];
if (delegate != nil && endSelector != nil)
objj_msgSend(delegate, endSelector, sheet, returnCode, contextInfo);
// we wanted to close the sheet while it animated in, do that now
if (_sheetContext["shouldClose"] === YES)
[self _detachSheetWindow];
}
else
{
// sheet is closed and not visible
[self _cleanupSheetWindow];
}
}
- (void)_setUpMasksForView:(CPView)aView
@@ -2484,10 +2766,7 @@ CPTexturedBackgroundWindowMask
[views sortUsingFunction:keyViewComparator context:nil];
var index = 0,
count = [views count];
for (; index < count; ++index)
for (var index = 0, count = [views count]; index < count; ++index)
[views[index] setNextKeyView:views[(index + 1) % count]];
_keyViewLoopIsDirty = NO;
@@ -2500,9 +2779,7 @@ CPTexturedBackgroundWindowMask
_autorecalculatesKeyViewLoop = shouldRecalculate;
if (_keyViewLoopIsDirty)
[self recalculateKeyViewLoop];
else if (_autorecalculatesKeyViewLoop)
if (_autorecalculatesKeyViewLoop)
[self _dirtyKeyViewLoop];
}
@@ -2523,7 +2800,7 @@ CPTexturedBackgroundWindowMask
if (!nextValidKeyView)
{
var initialFirstResponder = [self initialFirstResponder];
var initialFirstResponder = _initialFirstResponder;
if ([initialFirstResponder acceptsFirstResponder])
nextValidKeyView = initialFirstResponder;
@@ -2546,7 +2823,7 @@ CPTexturedBackgroundWindowMask
if (!previousValidKeyView)
{
var initialFirstResponder = [self initialFirstResponder];
var initialFirstResponder = _initialFirstResponder;
if ([initialFirstResponder acceptsFirstResponder])
previousValidKeyView = initialFirstResponder;
@@ -2668,12 +2945,12 @@ var allViews = function(aWindow)
[views addObjectsFromArray:[[aWindow contentView] subviews]];
var index = 0;
for (; index < views.length; ++index)
// Start from index 1 because index 0 is the contentView and its subviews have already been added
for (var index = 1; index < views.length; ++index)
views = views.concat([views[index] subviews]);
return views;
}
};
var keyViewComparator = function(lhs, rhs, context)
{
@@ -2704,7 +2981,7 @@ var keyViewComparator = function(lhs, rhs, context)
return CPOrderedSame;
return CPOrderedDescending;
}
};
@implementation CPWindow (MenuBar)
@@ -2790,7 +3067,7 @@ var keyViewComparator = function(lhs, rhs, context)
- (CGPoint)convertBaseToPlatformWindow:(CGPoint)aPoint
{
if ([self _sharesChromeWithPlatformWindow])
return aPoint;
return _CGPointMakeCopy(aPoint);
var origin = [self frame].origin;
@@ -2798,12 +3075,12 @@ var keyViewComparator = function(lhs, rhs, context)
}
/*!
Converts aPoint from the parent platform window coordinate system to the windows coordinate system.
Converts aPoint from the parent platform window coordinate system to the window's coordinate system.
*/
- (CGPoint)convertPlatformWindowToBase:(CGPoint)aPoint
{
if ([self _sharesChromeWithPlatformWindow])
return aPoint;
return _CGPointMakeCopy(aPoint);
var origin = [self frame].origin;
@@ -2928,7 +3205,7 @@ var keyViewComparator = function(lhs, rhs, context)
var interpolate = function(fromValue, toValue, progress)
{
return fromValue + (toValue - fromValue) * progress;
}
};
/* @ignore */
@implementation _CPWindowFrameAnimation : CPAnimation
+215 -128
View File
@@ -22,21 +22,28 @@
@import "_CPWindowView.j"
#define ALIGN_STROKE(point) (FLOOR(point) === (point) ? (point) + halfStrokeWidth : (point))
#define ALIGN_COORD(point) (FLOOR(point))
var _CPAttachedWindowViewDefaultCursorSize = CGSizeMake(16, 10),
_CPAttachedWindowViewRadius = 5.0,
_CPAttachedWindowViewStrokeWidth = 1.0,
_CPAttachedWindowViewShadowSize = CGSizeMake(0, 6),
_CPAttachedWindowViewShadowBlur = 15.0;
/*!
@ignore
A custom CPWindowView that manage border and cursor
A custom CPWindowView that manages a border and cursor
*/
@implementation _CPAttachedWindowView : _CPWindowView
{
BOOL _mouseDownPressed @accessors(getter=isMouseDownPressed, setter=setMouseDownPressed:);
float _arrowOffsetX @accessors(property=arrowOffsetX);
float _arrowOffsetY @accessors(property=arrowOffsetY);
int _appearance @accessors(property=appearance);
unsigned _preferredEdge @accessors(property=preferredEdge);
float _arrowOffsetX @accessors(property=arrowOffsetX);
float _arrowOffsetY @accessors(property=arrowOffsetY);
int _appearance @accessors(property=appearance);
unsigned _preferredEdge @accessors(property=preferredEdge);
CPSize _cursorSize;
CGSize _cursorSize;
}
/*!
@@ -81,18 +88,14 @@
/*!
Initialize the _CPWindowView
*/
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
- (id)initWithFrame:(CGRect)aFrame styleMask:(unsigned)aStyleMask
{
if (self = [super initWithFrame:aFrame styleMask:aStyleMask])
{
var bundle = [CPBundle bundleForClass:[self class]];
_arrowOffsetX = 0.0;
_arrowOffsetY = 0.0;
// @TODO: make this themable
_useGlowingEffect = YES;
_appearance = CPPopoverAppearanceMinimal;
_cursorSize = CPSizeMake(15, 10);
_cursorSize = CGSizeMakeCopy(_CPAttachedWindowViewDefaultCursorSize);
}
return self;
@@ -103,7 +106,7 @@
*/
- (void)hideCursor
{
_cursorSize = CPSizeMakeZero();
_cursorSize = CGSizeMakeZero();
[self setNeedsDisplay:YES];
}
@@ -112,9 +115,8 @@
*/
- (void)showCursor
{
_cursorSize = CPSizeMake(15, 10);
_cursorSize = CGSizeMakeCopy(_CPAttachedWindowViewDefaultCursorSize);
[self setNeedsDisplay:YES];
_mouseDownPressed = NO;
}
/*!
@@ -125,176 +127,261 @@
[super drawRect:aRect];
var context = [[CPGraphicsContext currentContext] graphicsPort],
radius = 5,
radius = _CPAttachedWindowViewRadius,
arrowWidth = _cursorSize.width,
arrowHeight = _cursorSize.height,
strokeWidth = 1,
strokeWidth = _CPAttachedWindowViewStrokeWidth,
halfStrokeWidth = strokeWidth / 2.0,
strokeColor,
shadowColor = [[CPColor blackColor] colorWithAlphaComponent:.2],
shadowSize = CGSizeMake(0, 7),
shadowBlur = 15,
gradient;
shadowSize = _CPAttachedWindowViewShadowSize,
shadowBlur = _CPAttachedWindowViewShadowBlur,
gradient,
frame = [self bounds];
if (_appearance == CPPopoverAppearanceMinimal)
{
gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [(254.0 / 255), (254.0 / 255), (254.0 / 255), 0.93,
(231.0 / 255), (231.0 / 255), (231.0 / 255), 0.93], [0,1], 2);
gradient = CGGradientCreateWithColorComponents(
CGColorSpaceCreateDeviceRGB(),
[
(254.0 / 255), (254.0 / 255), (254.0 / 255), 0.93,
(231.0 / 255), (231.0 / 255), (231.0 / 255), 0.93
],
[0, 1],
2
);
strokeColor = [CPColor colorWithHexString:@"B8B8B8"];
}
else
{
gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [(38.0 / 255), (38.0 / 255), (38.0 / 255), 0.93,
(18.0 / 255), (18.0 / 255), (18.0 / 255), 0.93], [0,1], 2);
gradient = CGGradientCreateWithColorComponents(
CGColorSpaceCreateDeviceRGB(),
[
(38.0 / 255), (38.0 / 255), (38.0 / 255), 0.93,
(18.0 / 255), (18.0 / 255), (18.0 / 255), 0.93
],
[0, 1],
2);
strokeColor = [CPColor colorWithHexString:@"222222"];
}
// fix rect to take care of stroke and shadow
aRect.origin.x += strokeWidth + shadowBlur;
aRect.origin.y += strokeWidth + (shadowBlur + shadowSize.height / 2);
aRect.size.width -= (strokeWidth * 2) + (shadowBlur * 2);
aRect.size.height -= (strokeWidth * 2) + (shadowBlur * 2 + shadowSize.height);
frame.origin.x += halfStrokeWidth + shadowBlur;
frame.origin.y += halfStrokeWidth + (shadowBlur + shadowSize.height / 2);
frame.size.width -= strokeWidth + (shadowBlur * 2);
frame.size.height -= strokeWidth + (shadowBlur * 2 + shadowSize.height);
CGContextSetStrokeColor(context, strokeColor);
CGContextSetLineWidth(context, strokeWidth);
CGContextBeginPath(context);
CGContextSetShadowWithColor(context, shadowSize, shadowBlur, shadowColor);
CGContextDrawLinearGradient(context, gradient, CGPointMake(CPRectGetMidX(aRect), 0.0), CGPointMake(CPRectGetMidX(aRect), aRect.size.height), 0);
CGContextDrawLinearGradient(context, gradient, CGPointMake(CGRectGetMidX(frame), 0.0), CGPointMake(CGRectGetMidX(frame), frame.size.height), 0);
var xMin = _CGRectGetMinX(aRect),
xMax = _CGRectGetMaxX(aRect),
yMin = _CGRectGetMinY(aRect),
yMax = _CGRectGetMaxY(aRect);
var xMin = _CGRectGetMinX(frame),
xMax = _CGRectGetMaxX(frame),
yMin = _CGRectGetMinY(frame),
yMax = _CGRectGetMaxY(frame),
arrowMinX = ALIGN_COORD(xMin + radius + strokeWidth),
arrowMaxX = ALIGN_COORD(xMax - radius - strokeWidth),
arrowMinY = ALIGN_COORD(yMin + radius + strokeWidth),
arrowMaxY = ALIGN_COORD(yMax - radius + strokeWidth),
arrowAnchor = CGPointMakeZero(),
arrowStart = CGPointMakeZero(),
pt = CGPointMakeZero();
// draw!
switch (_preferredEdge)
{
case CPMinXEdge:
// origin ne
CGContextMoveToPoint(context, xMin + radius, yMin);
// ne
CGContextAddLineToPoint(context, xMax - radius, yMin);
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
// arrow CPMinXEdge
CGContextAddLineToPoint(context, xMax, (aRect.size.height / 2) + aRect.origin.y + _arrowOffsetY - (arrowHeight - 2));
CGContextAddLineToPoint(context, aRect.size.width + arrowHeight + aRect.origin.x + _arrowOffsetX, (aRect.size.height / 2) + aRect.origin.y + _arrowOffsetY);
CGContextAddLineToPoint(context, aRect.size.width + aRect.origin.x + _arrowOffsetX, (aRect.size.height / 2 + (arrowWidth / 2)) + aRect.origin.y + _arrowOffsetY);
// se
CGContextAddLineToPoint(context, xMax, yMax - radius);
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
// sw
CGContextAddLineToPoint(context, xMin + radius, yMax);
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
// nw
CGContextAddLineToPoint(context, xMin, yMin + radius);
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
break;
case CPMaxXEdge:
// origin ne
CGContextMoveToPoint(context, xMin + radius, yMin);
// origin nw
pt.x = ALIGN_COORD(xMin + radius);
pt.y = yMin;
CGContextMoveToPoint(context, pt.x, pt.y);
// ne
CGContextAddLineToPoint(context, xMax - radius, yMin);
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
pt.x = ALIGN_COORD(xMax - radius);
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, xMax, yMin, xMax, ALIGN_COORD(yMin + radius));
if (_preferredEdge === CPMinXEdge)
{
// arrow CPMinXEdge
arrowAnchor.x = ALIGN_STROKE(xMax);
arrowAnchor.y = ALIGN_COORD((frame.size.height / 2) + yMin + _arrowOffsetY);
// to top edge
pt.y = ALIGN_COORD(arrowAnchor.y - (arrowWidth / 2));
// adjust starting point to not go beyond the corner
if (pt.y <= arrowMinY)
pt.y = arrowMinY;
else if ((pt.y + arrowWidth) > arrowMaxY)
pt.y = arrowMaxY - arrowWidth;
pt.x = arrowAnchor.x;
arrowStart = CGPointMakeCopy(pt);
CGContextAddLineToPoint(context, pt.x, pt.y);
// top edge -> point
pt.x = ALIGN_STROKE(arrowAnchor.x + arrowHeight);
pt.y = arrowAnchor.y;
CGContextAddLineToPoint(context, pt.x, pt.y);
// point -> bottom edge
pt.x = arrowAnchor.x;
pt.y = ALIGN_COORD(arrowStart.y + arrowWidth);
CGContextAddLineToPoint(context, pt.x, pt.y);
}
// se
CGContextAddLineToPoint(context, xMax, yMax - radius);
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
pt.x = xMax;
pt.y = ALIGN_COORD(yMax - radius);
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, pt.x, yMax, ALIGN_COORD(xMax - radius), yMax);
// sw
CGContextAddLineToPoint(context, xMin + radius, yMax);
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
pt.x = ALIGN_COORD(xMin + radius);
pt.y = yMax;
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, xMin, pt.y, xMin, ALIGN_COORD(yMax - radius));
// arrow CPMaxXEdge
CGContextAddLineToPoint(context, xMin, (aRect.size.height / 2 + (arrowWidth / 2) + aRect.origin.y + _arrowOffsetY));
CGContextAddLineToPoint(context, aRect.origin.x - arrowHeight + _arrowOffsetX, (aRect.size.height / 2) + aRect.origin.y + _arrowOffsetY);
CGContextAddLineToPoint(context, aRect.origin.x + _arrowOffsetX, (aRect.size.height / 2 - (arrowWidth / 2) + aRect.origin.y + _arrowOffsetY));
if (_preferredEdge === CPMaxXEdge)
{
// arrow CPMaxXEdge
arrowAnchor.x = ALIGN_STROKE(xMin);
arrowAnchor.y = ALIGN_COORD((frame.size.height / 2) + yMin + _arrowOffsetY);
// to bottom edge
pt.y = ALIGN_COORD(arrowAnchor.y + (arrowWidth / 2));
// adjust starting point to not go beyond the corner
if ((pt.y - arrowWidth) < arrowMinY)
pt.y = arrowMinY + arrowWidth;
else if (pt.y > arrowMaxY)
pt.y = arrowMaxY;
pt.x = arrowAnchor.x;
arrowStart = CGPointMakeCopy(pt);
CGContextAddLineToPoint(context, pt.x, pt.y);
// bottom edge -> point
pt.x = ALIGN_STROKE(arrowAnchor.x - arrowHeight);
pt.y = arrowAnchor.y;
CGContextAddLineToPoint(context, pt.x, pt.y);
// point -> top edge
pt.x = arrowAnchor.x;
pt.y = ALIGN_COORD(arrowStart.y - arrowWidth);
CGContextAddLineToPoint(context, pt.x, pt.y);
}
// nw
CGContextAddLineToPoint(context, xMin, yMin + radius);
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
pt.x = xMin;
pt.y = ALIGN_COORD(yMin + radius);
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, pt.x, yMin, ALIGN_COORD(xMin + radius), yMin);
break;
case CPMaxYEdge:
// origin nw
CGContextMoveToPoint(context, xMin, yMin + yMin);
// nw
CGContextAddLineToPoint(context, xMin, yMin + radius);
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
// arrow CPMaxYEdge
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x + _arrowOffsetX - (arrowWidth / 2), yMin);
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x + _arrowOffsetX, aRect.origin.y - arrowHeight + _arrowOffsetY);
CGContextAddLineToPoint(context, (aRect.size.width / 2) + (arrowWidth / 2) + aRect.origin.x + _arrowOffsetX, aRect.origin.y + _arrowOffsetY);
// ne
CGContextAddLineToPoint(context, xMax - radius, yMin);
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
// se
CGContextAddLineToPoint(context, xMax, yMax - radius);
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
// sw
CGContextAddLineToPoint(context, xMin + radius, yMax);
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
break;
case CPMinYEdge:
// origin nw
CGContextMoveToPoint(context, xMin, yMin + yMin);
// origin sw
pt.x = xMin;
pt.y = ALIGN_COORD(yMax - radius);
CGContextMoveToPoint(context, pt.x, pt.y);
// nw
CGContextAddLineToPoint(context, xMin, yMin + radius);
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
pt.y = ALIGN_COORD(yMin + radius);
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, pt.x, yMin, ALIGN_COORD(xMin + radius), yMin);
if (_preferredEdge === CPMaxYEdge)
{
// arrow CPMaxYEdge
arrowAnchor.x = ALIGN_COORD((frame.size.width / 2) + xMin + _arrowOffsetX);
arrowAnchor.y = ALIGN_STROKE(yMin + _arrowOffsetY);
// to left edge
pt.x = ALIGN_COORD(arrowAnchor.x - (arrowWidth / 2));
// adjust starting point to not go beyond the corner
if (pt.x < arrowMinX)
pt.x = arrowMinX;
else if ((pt.x + arrowWidth) > arrowMaxX)
pt.x = arrowMaxX - arrowWidth;
pt.y = arrowAnchor.y;
arrowStart = CGPointMakeCopy(pt);
CGContextAddLineToPoint(context, pt.x, pt.y);
// left edge -> point
pt.x = arrowAnchor.x;
pt.y = ALIGN_STROKE(arrowAnchor.y - arrowHeight);
CGContextAddLineToPoint(context, pt.x, pt.y);
// point -> right edge
pt.x = ALIGN_COORD(arrowStart.x + arrowWidth);
pt.y = arrowAnchor.y;
CGContextAddLineToPoint(context, pt.x, pt.y);
}
// ne
CGContextAddLineToPoint(context, xMax - radius, yMin);
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
pt.x = ALIGN_COORD(xMax - radius);
pt.y = yMin;
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, xMax, pt.y, xMax, ALIGN_COORD(yMin + radius));
// se
CGContextAddLineToPoint(context, xMax, yMax - radius);
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
pt.x = xMax;
pt.y = ALIGN_COORD(yMax - radius);
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, pt.x, yMax, ALIGN_COORD(xMax - radius), yMax);
// arrow CPMinYEdge
CGContextAddLineToPoint(context, (aRect.size.width / 2) + (arrowWidth / 2) + aRect.origin.x + _arrowOffsetX , yMax);
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x + _arrowOffsetX, aRect.size.height + aRect.origin.y + arrowHeight + _arrowOffsetY);
CGContextAddLineToPoint(context, (aRect.size.width / 2) - (arrowWidth / 2) + aRect.origin.x + _arrowOffsetX, aRect.size.height + aRect.origin.y + _arrowOffsetY);
if (_preferredEdge === CPMinYEdge)
{
// arrow CPMinYEdge
arrowAnchor.x = ALIGN_COORD((frame.size.width / 2) + xMin + _arrowOffsetX);
arrowAnchor.y = ALIGN_STROKE(yMax + _arrowOffsetY);
// to right edge
pt.x = ALIGN_COORD(arrowAnchor.x + (arrowWidth / 2));
// adjust starting point to not go beyond the corner
if ((pt.x - arrowWidth) < arrowMinX)
pt.x = arrowMinX + arrowWidth;
else if (pt.x > arrowMaxX)
pt.x = arrowMaxX;
pt.y = arrowAnchor.y;
arrowStart = CGPointMakeCopy(pt);
CGContextAddLineToPoint(context, pt.x, pt.y);
// right edge -> point
pt.x = arrowAnchor.x;
pt.y = ALIGN_STROKE(arrowAnchor.y + arrowHeight);
CGContextAddLineToPoint(context, pt.x, pt.y);
// point -> left edge
pt.x = ALIGN_COORD(arrowStart.x - arrowWidth);
pt.y = arrowAnchor.y;
CGContextAddLineToPoint(context, pt.x, pt.y);
}
// sw
CGContextAddLineToPoint(context, xMin + radius, yMax);
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
pt.x = ALIGN_COORD(xMin + radius);
pt.y = yMax;
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, xMin, pt.y, xMin, ALIGN_COORD(yMax - radius));
break;
default:
// no computed edge means standard rounded rect
CGContextAddPath(context, CGPathWithRoundedRectangleInRect(aRect, radius, radius, YES, YES, YES, YES));
CGContextAddPath(context, CGPathWithRoundedRectangleInRect(frame, radius, radius, YES, YES, YES, YES));
}
CGContextClosePath(context);
//Draw it
CGContextStrokePath(context);
CGContextFillPath(context);
}
- (void)mouseDown:(CPEvent)anEvent
{
_mouseDownPressed = YES;
[super mouseDown:anEvent];
}
- (void)mouseUp:(CPEvent)anEvent
{
_mouseDownPressed = NO;
[super mouseUp:anEvent];
}
@end
@@ -33,7 +33,14 @@ var _CPToolbarViewBackgroundColor = nil;
+ (CPColor)toolbarBackgroundColor
{
if (!_CPToolbarViewBackgroundColor)
_CPToolbarViewBackgroundColor = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[_CPBorderlessBridgeWindowView class]] pathForResource:@"_CPToolbarView/_CPToolbarViewBackground.png"] size:CGSizeMake(1.0, 59.0)]];
{
var bundle = [CPBundle bundleForClass:[_CPBorderlessBridgeWindowView class]];
_CPToolbarViewBackgroundColor = CPColorWithImages([
["_CPToolbarView/toolbar-background-top.png", 1, 1, bundle],
["_CPToolbarView/toolbar-background-center.png", 1, 57.0, bundle],
["_CPToolbarView/toolbar-background-bottom.png", 1, 1, bundle]
], CPColorPatternIsVertical);
}
return _CPToolbarViewBackgroundColor;
}
+8 -2
View File
@@ -24,7 +24,7 @@ var _CPStandardWindowViewBodyBackgroundColor = nil;
if (self)
{
var theClass = [self class],
bounds = [self bounds];
bounds = [self bounds];
_bodyView = [[CPView alloc] initWithFrame:_CGRectMake(0.0, 0.0, _CGRectGetWidth(bounds), _CGRectGetHeight(bounds))];
@@ -54,4 +54,10 @@ var _CPStandardWindowViewBodyBackgroundColor = nil;
return aContentRect;
}
@end
- (void)_enableSheet:(BOOL)enable
{
// do nothing, already a sheet
}
@end
+60 -58
View File
@@ -21,24 +21,24 @@
*/
@import "CPTextField.j"
@import "_CPTitleableWindowView.j"
var _CPHUDWindowViewBackgroundColor = nil,
_CPHUDWindowViewThemeValues = nil,
CPHUDCloseButtonImage = nil;
var HUD_TITLEBAR_HEIGHT = 26.0;
@implementation _CPHUDWindowView : _CPWindowView
@implementation _CPHUDWindowView : _CPTitleableWindowView
{
CPView _toolbarView;
CPTextField _titleField;
CPButton _closeButton;
}
+ (void)initialize
{
if (self != [_CPHUDWindowView class])
if (self !== [_CPHUDWindowView class])
return;
var bundle = [CPBundle bundleForClass:self];
@@ -60,28 +60,23 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
_CPHUDWindowViewCloseImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowClose.png"] size:CPSizeMake(18.0, 18.0)];
_CPHUDWindowViewCloseActiveImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowCloseActive.png"] size:CPSizeMake(18.0, 18.0)];
_CPHUDWindowViewThemeValues = [
[@"title-font", [CPFont systemFontOfSize:[CPFont systemFontSize] - 1]],
[@"title-text-color", [CPColor colorWithWhite:255.0 / 255.0 alpha:0.75]],
[@"title-text-color", [CPColor colorWithWhite:255.0 / 255.0 alpha:1], CPThemeStateKeyWindow],
[@"title-text-shadow-color", [CPColor blackColor]],
[@"title-text-shadow-offset", CGSizeMake(0.0, 1.0)],
[@"title-alignment", CPCenterTextAlignment],
// FIXME: Make this to CPLineBreakByTruncatingMiddle once it's implemented.
[@"title-line-break-mode", CPLineBreakByTruncatingTail],
[@"title-vertical-alignment", CPCenterVerticalTextAlignment]
];
}
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
+ (int)titleBarHeight
{
var contentRect = CGRectMakeCopy(aFrameRect),
titleBarHeight = HUD_TITLEBAR_HEIGHT;
contentRect.origin.y += titleBarHeight;
contentRect.size.height -= titleBarHeight;
return contentRect;
}
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
{
var frameRect = CGRectMakeCopy(aContentRect),
titleBarHeight = HUD_TITLEBAR_HEIGHT;
frameRect.origin.y -= titleBarHeight;
frameRect.size.height += titleBarHeight;
return frameRect;
return HUD_TITLEBAR_HEIGHT;
}
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
@@ -90,7 +85,7 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
if ([[[self window] toolbar] isVisible])
{
toolbarHeight = CGRectGetHeight([[self toolbarView] frame]);
var toolbarHeight = CGRectGetHeight([[self toolbarView] frame]);
contentRect.origin.y += toolbarHeight;
contentRect.size.height -= toolbarHeight;
@@ -105,7 +100,7 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
if ([[[self window] toolbar] isVisible])
{
toolbarHeight = CGRectGetHeight([[self toolbarView] frame]);
var toolbarHeight = CGRectGetHeight([[self toolbarView] frame]);
frameRect.origin.y -= toolbarHeight;
frameRect.size.height += toolbarHeight;
@@ -120,37 +115,18 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
if (self)
{
// Until windows become properly themable, just set these values here in the subclass.
[self registerThemeValues:_CPHUDWindowViewThemeValues];
var bounds = [self bounds];
[self setBackgroundColor:_CPHUDWindowViewBackgroundColor];
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_titleField setHitTests:NO];
[_titleField setFont:[CPFont systemFontOfSize:11.0]];
[_titleField setTextColor:[CPColor whiteColor]];
[_titleField setTextShadowColor:[CPColor blackColor]];
[_titleField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_titleField setAutoresizingMask:CPViewWidthSizable];
// FIXME: Make this to CPLineBreakByTruncatingMiddle once it's implemented.
[_titleField setLineBreakMode:CPLineBreakByTruncatingTail];
[_titleField setAlignment:CPCenterTextAlignment];
[_titleField setStringValue:@"Untitled"];
[_titleField sizeToFit];
[_titleField setAutoresizingMask:CPViewWidthSizable];
[_titleField setStringValue:@""];
[_titleField setFrame:CGRectMake(20.0, 3.0, CGRectGetWidth([self bounds]) - 40.0, CGRectGetHeight([_titleField frame]))];
[self addSubview:_titleField];
if (_styleMask & CPClosableWindowMask)
{
var closeSize = [_CPHUDWindowViewCloseImage size];
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 5.0, closeSize.width, closeSize.height)];
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 4.0, closeSize.width, closeSize.height)];
[_closeButton setBordered:NO];
@@ -161,6 +137,8 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
}
[self setResizeIndicatorOffset:CGSizeMake(5.0, 5.0)];
[self tile];
}
return self;
@@ -172,11 +150,6 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
[_closeButton setAction:@selector(performClose:)];
}
- (void)setTitle:(CPString)aTitle
{
[_titleField setStringValue:aTitle];
}
- (_CPToolbarView)toolbarView
{
return _toolbarView;
@@ -194,7 +167,7 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
- (CGSize)toolbarOffset
{
return CGSizeMake(0.0, HUD_TITLEBAR_HEIGHT);
return _CGSizeMake(0.0, [[self class] titleBarHeight]);
}
- (void)tile
@@ -203,14 +176,43 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
var theWindow = [self window],
bounds = [self bounds],
width = CGRectGetWidth(bounds);
width = _CGRectGetWidth(bounds);
[_titleField setFrame:CGRectMake(20.0, 3.0, width - 40.0, CGRectGetHeight([_titleField frame]))];
[_titleField setFrame:_CGRectMake(20.0, 0, width - 40.0, [self toolbarOffset].height)];
var maxY = [self toolbarMaxY];
if ([_titleField isHidden])
maxY -= ([self toolbarOffset]).height;
[[theWindow contentView] setFrameOrigin:CGPointMake(0.0, maxY, width, CGRectGetHeight(bounds) - maxY)];
var contentRect = _CGRectMake(0.0, maxY, width, _CGRectGetHeight(bounds) - maxY);
[[theWindow contentView] setFrame:contentRect];
}
- (void)_enableSheet:(BOOL)enable
{
[super _enableSheet:enable];
[_closeButton setHidden:enable];
[_titleField setHidden:enable];
// resize the window
var theWindow = [self window],
frame = [theWindow frame],
dy = ([self toolbarOffset]).height;
if (enable)
dy = -dy;
var newHeight = _CGRectGetMaxY(frame) + dy,
newWidth = _CGRectGetMaxX(frame);
frame.size.height += dy;
[self setFrameSize:_CGSizeMake(newWidth, newHeight)];
[self tile];
[theWindow setFrame:frame display:NO animate:NO];
[theWindow setMovableByWindowBackground:!enable];
}
@end
+79 -78
View File
@@ -21,7 +21,7 @@
*/
@import "CPTextField.j"
@import "_CPWindowView.j"
@import "_CPTitleableWindowView.j"
var GRADIENT_HEIGHT = 41.0;
@@ -98,31 +98,44 @@ var _CPTexturedWindowHeadGradientColor = nil,
var _CPStandardWindowViewBodyBackgroundColor = nil,
_CPStandardWindowViewDividerBackgroundColor = nil,
_CPStandardWindowViewTitleBackgroundColor = nil,
_CPStandardWindowViewCloseButtonImage = nil,
_CPStandardWindowViewCloseButtonHighlightedImage = nil,
_CPStandardWindowViewCloseButtonUnsavedImage = nil,
_CPStandardWindowViewCloseButtonUnsavedHighlightedImage = nil,
_CPStandardWindowViewMinimizeButtonImage = nil,
_CPStandardWindowViewMinimizeButtonHighlightedImage = nil;
_CPStandardWindowViewMinimizeButtonHighlightedImage = nil,
_CPStandardWindowViewThemeValues = nil;
var STANDARD_GRADIENT_HEIGHT = 41.0,
STANDARD_TITLEBAR_HEIGHT = 25.0;
var STANDARD_GRADIENT_HEIGHT = 41.0;
@implementation _CPStandardWindowView : _CPWindowView
@implementation _CPStandardWindowView : _CPTitleableWindowView
{
_CPTexturedWindowHeadView _headView;
CPView _dividerView;
CPView _bodyView;
CPView _toolbarView;
CPTextField _titleField;
CPButton _closeButton;
CPButton _minimizeButton;
BOOL _isDocumentEdited;
}
+ (void)initialize
{
_CPStandardWindowViewThemeValues = [
[@"title-font", [CPFont boldSystemFontOfSize:CPFontCurrentSystemSize]],
[@"title-text-color", [CPColor colorWithWhite:22.0 / 255.0 alpha:0.75]],
[@"title-text-color", [CPColor colorWithWhite:22.0 / 255.0 alpha:1], CPThemeStateKeyWindow],
[@"title-text-shadow-color", [CPColor whiteColor]],
[@"title-text-shadow-offset", CGSizeMake(0.0, 1.0)],
[@"title-alignment", CPCenterTextAlignment],
// FIXME: Make this to CPLineBreakByTruncatingMiddle once it's implemented.
[@"title-line-break-mode", CPLineBreakByTruncatingTail],
[@"title-vertical-alignment", CPCenterVerticalTextAlignment]
];
}
+ (CPColor)bodyBackgroundColor
{
if (!_CPStandardWindowViewBodyBackgroundColor)
@@ -139,41 +152,6 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
return _CPStandardWindowViewDividerBackgroundColor;
}
+ (CPColor)titleColor
{
if (!_CPStandardWindowViewTitleBackgroundColor)
_CPStandardWindowViewTitleBackgroundColor = [CPColor colorWithCalibratedRed:44.0 / 255.0 green:44.0 / 255.0 blue:44.0 / 255.0 alpha:1.0];
return _CPStandardWindowViewTitleBackgroundColor;
}
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
var contentRect = CGRectMakeCopy(aFrameRect),
titleBarHeight = [self titleBarHeight] + 1.0;
contentRect.origin.y += titleBarHeight;
contentRect.size.height -= titleBarHeight;
return contentRect;
}
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
{
var frameRect = CGRectMakeCopy(aContentRect),
titleBarHeight = [self titleBarHeight] + 1.0;
frameRect.origin.y -= titleBarHeight;
frameRect.size.height += titleBarHeight;
return frameRect;
}
+ (float)titleBarHeight
{
return STANDARD_TITLEBAR_HEIGHT;
}
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
var contentRect = [[self class] contentRectForFrameRect:aFrameRect],
@@ -181,7 +159,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
if ([theToolbar isVisible])
{
toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]);
var toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]);
contentRect.origin.y += toolbarHeight;
contentRect.size.height -= toolbarHeight;
@@ -197,7 +175,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
if ([theToolbar isVisible])
{
toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]);
var toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]);
frameRect.origin.y -= toolbarHeight;
frameRect.size.height += toolbarHeight;
@@ -212,6 +190,9 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
if (self)
{
// Until windows become properly themable, just set these values here in the subclass.
[self registerThemeValues:_CPStandardWindowViewThemeValues];
var theClass = [self class],
bounds = [self bounds];
@@ -220,7 +201,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
[_headView setAutoresizingMask:CPViewWidthSizable];;
[_headView setHitTests:NO];
[self addSubview:_headView];
[self addSubview:_headView positioned:CPWindowBelow relativeTo:_titleField];
_dividerView = [[CPView alloc] initWithFrame:CGRectMake(0.0, CGRectGetMaxY([_headView frame]), CGRectGetWidth(bounds), 1.0)];
@@ -242,24 +223,6 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
[self setResizeIndicatorOffset:CGSizeMake(2.0, 2.0)];
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_titleField setFont:[CPFont boldSystemFontOfSize:12.0]];
[_titleField setAutoresizingMask:CPViewWidthSizable];
// FIXME: Make this to CPLineBreakByTruncatingMiddle once it's implemented.
[_titleField setLineBreakMode:CPLineBreakByTruncatingTail];
[_titleField setAlignment:CPCenterTextAlignment];
[_titleField setTextShadowColor:[CPColor whiteColor]];
[_titleField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_titleField setStringValue:@"Untitled"];
[_titleField sizeToFit];
[_titleField setAutoresizingMask:CPViewWidthSizable];
[_titleField setStringValue:@""];
[self addSubview:_titleField];
if (_styleMask & CPClosableWindowMask)
{
if (!_CPStandardWindowViewCloseButtonImage)
@@ -272,7 +235,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
_CPStandardWindowViewCloseButtonUnsavedHighlightedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardCloseButtonUnsavedHighlighted.png"] size:CGSizeMake(16.0, 16.0)];
}
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 7.0, 16.0, 16.0)];
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 6.0, 16.0, 16.0)];
[_closeButton setBordered:NO];
[self _updateCloseButton];
@@ -326,14 +289,20 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
var theWindow = [self window],
bounds = [self bounds],
width = CGRectGetWidth(bounds);
width = _CGRectGetWidth(bounds);
[_headView setFrameSize:CGSizeMake(width, [self toolbarMaxY])];
[_dividerView setFrame:CGRectMake(0.0, CGRectGetMaxY([_headView frame]), width, 1.0)];
[_headView setFrameSize:_CGSizeMake(width, [self toolbarMaxY])];
[_dividerView setFrame:_CGRectMake(0.0, _CGRectGetMaxY([_headView frame]), width, 1.0)];
var dividerMaxY = CGRectGetMaxY([_dividerView frame]);
var dividerMaxY = 0,
dividerMinY = 0;
if (![_dividerView isHidden])
{
dividerMinY = _CGRectGetMinY([_dividerView frame]);
dividerMaxY = _CGRectGetMaxY([_dividerView frame]);
}
[_bodyView setFrame:CGRectMake(0.0, dividerMaxY, width, CGRectGetHeight(bounds) - dividerMaxY)];
[_bodyView setFrame:_CGRectMake(0.0, dividerMaxY, width, _CGRectGetHeight(bounds) - dividerMaxY)];
var leftOffset = 8;
@@ -342,10 +311,13 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
if (_minimizeButton)
leftOffset += 19.0;
[_titleField setFrame:CGRectMake(leftOffset, 5.0, width - leftOffset * 2.0, CGRectGetHeight([_titleField frame]))];
[_titleField setFrame:_CGRectMake(leftOffset, 0, width - leftOffset * 2.0, [[self class] titleBarHeight])];
[[theWindow contentView] setFrameOrigin:CGPointMake(0.0, CGRectGetMaxY([_dividerView frame]))];
var contentRect = _CGRectMake(0.0, dividerMaxY, width, _CGRectGetHeight([_bodyView frame]));
[[theWindow contentView] setFrame:contentRect];
}
/*
- (void)setAnimatingToolbar:(BOOL)isAnimatingToolbar
{
@@ -394,17 +366,46 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
[self _updateCloseButton];
}
- (void)setTitle:(CPString)aTitle
{
[_titleField setStringValue:aTitle];
}
- (void)mouseDown:(CPEvent)anEvent
{
if (CGRectContainsPoint([_headView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]))
return [self trackMoveWithEvent:anEvent];
if (![_headView isHidden])
if (CGRectContainsPoint([_headView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]))
return [self trackMoveWithEvent:anEvent];
[super mouseDown:anEvent];
}
- (void)_enableSheet:(BOOL)enable
{
[super _enableSheet:enable];
[_headView setHidden:enable];
[_dividerView setHidden:enable];
[_closeButton setHidden:enable];
[_minimizeButton setHidden:enable];
[_titleField setHidden:enable];
if (enable)
[_bodyView setBackgroundColor:[_CPDocModalWindowView bodyBackgroundColor]];
else
[_bodyView setBackgroundColor:[[self class] bodyBackgroundColor]];
// resize the window
var theWindow = [self window],
frame = [theWindow frame];
var dy = _CGRectGetHeight([_headView frame]) + _CGRectGetHeight([_dividerView frame]);
if (enable)
dy = -dy;
var newHeight = _CGRectGetMaxY(frame) + dy,
newWidth = _CGRectGetMaxX(frame);
frame.size.height += dy;
[self setFrameSize:_CGSizeMake(newWidth, newHeight)];
[self tile];
[theWindow setFrame:frame display:NO animate:NO];
}
@end
+114
View File
@@ -0,0 +1,114 @@
/*
* _CPTitleableWindowView.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2012, SlevenBits Ltd.
*
* 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 "_CPWindowView.j"
var STANDARD_TITLEBAR_HEIGHT = 25.0;
@implementation _CPTitleableWindowView : _CPWindowView
{
CPTextField _titleField;
}
+ (int)titleBarHeight
{
return STANDARD_TITLEBAR_HEIGHT;
}
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
var contentRect = CGRectMakeCopy(aFrameRect),
titleBarHeight = [[self class] titleBarHeight];
contentRect.origin.y += titleBarHeight;
contentRect.size.height -= titleBarHeight;
return contentRect;
}
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
{
var frameRect = CGRectMakeCopy(aContentRect),
titleBarHeight = [[self class] titleBarHeight];
frameRect.origin.y -= titleBarHeight;
frameRect.size.height += titleBarHeight;
return frameRect;
}
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
{
self = [super initWithFrame:aFrame styleMask:aStyleMask];
if (self)
{
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_titleField setHitTests:NO];
[_titleField setStringValue:@"Untitled"];
[_titleField sizeToFit];
[_titleField setAutoresizingMask:CPViewWidthSizable];
[_titleField setStringValue:@""];
[_titleField setFrame:CGRectMake(20.0, 3.0, CGRectGetWidth([self bounds]) - 40.0, CGRectGetHeight([_titleField frame]))];
[self addSubview:_titleField];
[self setNeedsLayout];
}
return self;
}
- (void)setTitle:(CPString)aTitle
{
[_titleField setStringValue:aTitle];
}
- (void)tile
{
[super tile];
var theWindow = [self window],
bounds = [self bounds],
width = CGRectGetWidth(bounds);
// The vertical alignment of the title is set by the theme, so just give it all available space. By default
// the title will vertically centre within.
[_titleField setFrame:_CGRectMake(20.0, 0, width - 40.0, [[self class] titleBarHeight])];
}
- (void)layoutSubviews
{
[super layoutSubviews];
[_titleField setTextColor:[self currentValueForThemeAttribute:@"title-text-color"]];
[_titleField setFont:[self currentValueForThemeAttribute:@"title-font"]];
[_titleField setAlignment:[self currentValueForThemeAttribute:@"title-alignment"]];
[_titleField setVerticalAlignment:[self currentValueForThemeAttribute:@"title-vertical-alignment"]];
[_titleField setLineBreakMode:[self currentValueForThemeAttribute:@"title-line-break-mode"]];
[_titleField setTextShadowColor:[self currentValueForThemeAttribute:@"title-text-shadow-color"]];
[_titleField setTextShadowOffset:[self currentValueForThemeAttribute:@"title-text-shadow-offset"]];
}
@end
+25 -22
View File
@@ -27,15 +27,31 @@
{
BOOL _mouseDownPressed @accessors(getter=isMouseDownPressed, setter=setMouseDownPressed:);
unsigned _gravity @accessors(property=gravity);
CPColor _backgroundColor;
CPColor _strokeColor;
}
#pragma mark -
#pragma mark Class methods
+ (CPString)defaultThemeClass
{
return @"tooltip";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPColor colorWithHexString:@"E3E3E3"],
[CPColor colorWithHexString:@"FFFFCA"],
2.0,
1.0,
[CPColor blackColor]]
forKeys:[@"stroke-color",
@"background-color",
@"border-radius",
@"stroke-width",
@"color"]];
}
/*! compute the contentView frame from a given window frame
@param aFrameRect the window frame
*/
@@ -67,21 +83,6 @@
}
#pragma mark -
#pragma mark Initialization
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
{
if (self = [super initWithFrame:aFrame styleMask:aStyleMask])
{
_strokeColor = [CPColor colorWithHexString:@"E3E3E3"];
_backgroundColor = [CPColor colorWithHexString:@"FFFFCA"];
}
return self;
}
#pragma mark -
#pragma mark drawing
@@ -90,11 +91,13 @@
[super drawRect:aRect];
var context = [[CPGraphicsContext currentContext] graphicsPort],
radius = 2,
strokeWidth = 1;
radius = [self currentValueForThemeAttribute:@"border-radius"],
strokeWidth = [self currentValueForThemeAttribute:@"stroke-width"],
strokeColor = [self currentValueForThemeAttribute:@"stroke-color"],
bgColor = [self currentValueForThemeAttribute:@"background-color"];
CGContextSetStrokeColor(context, _strokeColor);
CGContextSetFillColor(context, _backgroundColor);
CGContextSetStrokeColor(context, strokeColor);
CGContextSetFillColor(context, bgColor);
CGContextSetLineWidth(context, strokeWidth);
CGContextBeginPath(context);
+60 -6
View File
@@ -41,11 +41,13 @@ var _CPWindowViewResizeIndicatorImage = nil;
CGPoint _mouseDraggedPoint;
CGRect _cachedScreenFrame;
CPView _sheetShadowView;
}
+ (void)initialize
{
if (self != [_CPWindowView class])
if (self !== [_CPWindowView class])
return;
_CPWindowViewResizeIndicatorImage = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPWindow class]] pathForResource:@"_CPWindowView/_CPWindowViewResizeIndicator.png"] size:CGSizeMake(12.0, 12.0)];
@@ -61,6 +63,17 @@ var _CPWindowViewResizeIndicatorImage = nil;
return CGRectMakeCopy(aContentRect);
}
+ (CPString)defaultThemeClass
{
return "window";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPColor blackColor], [CPFont systemFontOfSize:CPFontCurrentSystemSize], [CPNull null], _CGSizeMakeZero(), CPCenterTextAlignment, CPLineBreakByTruncatingTail, CPTopVerticalTextAlignment]
forKeys:[@"title-text-color", @"title-font", @"title-text-shadow-color", @"title-text-shadow-offset", @"title-alignment", @"title-line-break-mode", @"title-vertical-alignment"]];
}
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
return [[self class] contentRectForFrameRect:aFrameRect];
@@ -113,7 +126,6 @@ var _CPWindowViewResizeIndicatorImage = nil;
if ([theWindow isMovable] && [theWindow isMovableByWindowBackground])
[self trackMoveWithEvent:anEvent];
else
[super mouseDown:anEvent];
}
@@ -140,7 +152,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
var newSize = CGSizeMake(CGRectGetWidth(_resizeFrame) + location.x - CGRectGetMinX(_resizeFrame), CGRectGetHeight(_resizeFrame) + location.y - CGRectGetMinY(_resizeFrame));
if (theWindow._isSheet && theWindow._parentView && (theWindow._frame.size.width !== newSize.width))
[theWindow._parentView _setAttachedSheetFrameOrigin];
[theWindow._parentView _setAttachedSheetFrameOrigin];
[theWindow setFrameSize:newSize];
}
@@ -184,13 +196,11 @@ var _CPWindowViewResizeIndicatorImage = nil;
_cachedScreenFrame = nil;
return;
}
else if (type === CPLeftMouseDown)
{
_mouseDraggedPoint = [[self window] convertBaseToGlobal:[anEvent locationInWindow]];
_cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
}
else if (type === CPLeftMouseDragged)
{
var theWindow = [self window],
@@ -198,7 +208,6 @@ var _CPWindowViewResizeIndicatorImage = nil;
location = [theWindow convertBaseToGlobal:[anEvent locationInWindow]],
origin = [self _pointWithinScreenFrame:CGPointMake(_CGRectGetMinX(frame) + (location.x - _mouseDraggedPoint.x),
_CGRectGetMinY(frame) + (location.y - _mouseDraggedPoint.y))];
[theWindow setFrameOrigin:origin];
_mouseDraggedPoint = [self _pointWithinScreenFrame:location];
@@ -207,6 +216,17 @@ var _CPWindowViewResizeIndicatorImage = nil;
[CPApp setTarget:self selector:@selector(trackMoveWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (void)setFrameSize:(CGSize)newSize
{
[super setFrameSize:newSize];
// reposition sheet if the parent window resizes or moves
var theWindow = [self window];
if ([theWindow attachedSheet])
[theWindow _setAttachedSheetFrameOrigin];
}
- (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator
{
if (shouldShowResizeIndicator)
@@ -350,6 +370,23 @@ var _CPWindowViewResizeIndicatorImage = nil;
[self tile];
}
- (void)noteKeyWindowStateChanged
{
if ([[self window] isKeyWindow])
[self setThemeState:CPThemeStateKeyWindow];
else
[self unsetThemeState:CPThemeStateKeyWindow];
}
- (void)noteMainWindowStateChanged
{
if ([[self window] isMainWindow])
[self setThemeState:CPThemeStateMainWindow];
else
[self unsetThemeState:CPThemeStateMainWindow];
}
/*
- (void)setAnimatingToolbar:(BOOL)isAnimatingToolbar
{
@@ -370,4 +407,21 @@ var _CPWindowViewResizeIndicatorImage = nil;
[self addSubview:_resizeIndicator];
}
- (void)_enableSheet:(BOOL)enable
{
if (enable)
{
var bundle = [CPBundle bundleForClass:[CPWindow class]];
_sheetShadowView = [[CPView alloc] initWithFrame:_CGRectMake(0, 0, _CGRectGetWidth([self bounds]), 8)];
[_sheetShadowView setAutoresizingMask:CPViewWidthSizable];
[_sheetShadowView setBackgroundColor:[CPColor colorWithPatternImage:[[CPImage alloc]
initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowAttachedSheetShadow.png"] size:_CGSizeMake(9, 8)]]];
[self addSubview:_sheetShadowView];
}
else
{
[_sheetShadowView removeFromSuperview];
}
}
@end
+75 -15
View File
@@ -33,7 +33,7 @@
@class CPWindowController
An instance of a CPWindowController manages a CPWindow. Windows are typically loaded via a cib,
but they can also manage windows created in code. A CPWindowController can manage a window by
but they can also manage windows created in code. A CPWindowController can manage a window by
itself or work with AppKits's document-based architecture.
In a Document based app, a CPWindowController instance is created and managed by a CPDocument subclass.
@@ -181,8 +181,7 @@
if (!_window)
{
var reason = [CPString stringWithFormat:@"Window for %@ could not be loaded from Cib or no window specified. \
Override loadWindow to load the window manually.", self];
var reason = [CPString stringWithFormat:@"Window for %@ could not be loaded from Cib or no window specified. Override loadWindow to load the window manually.", self];
[CPException raise:CPInternalInconsistencyException reason:reason];
}
@@ -333,6 +332,41 @@
- (void)setViewControllerContainerView:(CPView)aView
{
if (!_viewControllerContainerView && !aView)
return;
var viewController = [self viewController],
viewControllerView = [viewController isViewLoaded] ? [viewController view] : nil,
contentView = [[self window] contentView];
if (aView)
{
[aView setFrame:[contentView frame]];
[aView setAutoresizingMask:[contentView autoresizingMask]];
if (viewControllerView)
{
[viewControllerView removeFromSuperview];
[aView addSubview:viewControllerView];
}
[[self window] setContentView:aView];
}
else if (viewControllerView)
{
[viewControllerView removeFromSuperview];
[viewControllerView setFrame:[contentView frame]];
[viewControllerView setAutoresizingMask:[contentView autoresizingMask]]
[[self window] setContentView:viewControllerView];
}
else
{
var view = [[CPView alloc] init];
[view setFrame:[contentView frame]];
[view setAutoresizingMask:[contentView autoresizingMask]];
[[self window] setContentView:view]
}
_viewControllerContainerView = aView;
}
@@ -343,21 +377,47 @@
- (void)setViewController:(CPViewController)aViewController
{
var containerView = [self viewControllerContainerView] || [[self window] contentView],
view = [_viewController view],
frame = view ? [view frame] : [containerView bounds];
if (!_viewController && !aViewController)
return;
[view removeFromSuperview];
var containerView = [self viewControllerContainerView],
newView = [aViewController isViewLoaded] ? [aViewController view] : nil;
if (containerView)
{
var oldView = [_viewController isViewLoaded] ? [_viewController view] : nil;
if (oldView)
{
[newView setFrame:[oldView frame]];
[newView setAutoresizingMask:[oldView autoresizingMask]];
}
if (oldView && newView)
[containerView replaceSubview:oldView with:newView];
else if (oldView)
[oldView removeFromSuperview];
else if (newView)
[containerView addSubview:newView];
}
else if (newView)
{
var contentView = [[self window] contentView];
[newView setFrame:[contentView frame]];
[newView setAutoresizingMask:[contentView autoresizingMask]];
[[self window] setContentView:newView];
}
else
{
var view = [[CPView alloc] init],
contentView = [[self window] contentView];
[view setFrame:[contentView frame]];
[view setAutoresizingMask:[contentView autoresizingMask]];
[[self window] setContentView:view]
}
_viewController = aViewController;
view = [_viewController view];
if (view)
{
[view setFrame:frame];
[containerView addSubview:view];
}
}
- (CPViewController)viewController
+56
View File
@@ -0,0 +1,56 @@
/*
* CPWorkspace.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2012, SlevenBits Ltd.
*
* 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/CPString.j>
var SharedWorkspace = nil;
@implementation CPWorkspace : CPObject
{
}
+ (CPWorkspace)sharedWorkspace
{
if (!SharedWorkspace)
SharedWorkspace = [CPWorkspace new];
return SharedWorkspace;
}
- (BOOL)openFile:(CPString)fullPath
{
var url = [CPURL URLWithString:fullPath];
return [self openURL:url];
}
- (BOOL)openURL:(CPURL)url
{
if (!url || ![url absoluteURL])
return NO;
window.open([url absoluteURL]);
return YES;
}
@end
+6 -2
View File
@@ -61,6 +61,10 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
if (self)
{
_data = [CPURLConnection sendSynchronousRequest:[CPURLRequest requestWithURL:aURL] returningResponse:nil];
if (!_data)
return nil;
_awakenCustomResources = YES;
}
@@ -137,7 +141,7 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
var key = nil,
keyEnumerator = [replacementClasses keyEnumerator];
while (key = [keyEnumerator nextObject])
while ((key = [keyEnumerator nextObject]) !== nil)
[unarchiver setClass:[replacementClasses objectForKey:key] forClassName:key];
}
@@ -162,7 +166,7 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
- (BOOL)instantiateCibWithOwner:(id)anOwner topLevelObjects:(CPArray)topLevelObjects
{
return [self instantiateCibWithExternalNameTable:[CPDictionary dictionaryWithObjectsAndKeys:anOwner, CPCibOwner, topLevelObjects, CPCibTopLevelObjects]];
return [self instantiateCibWithExternalNameTable:[CPDictionary dictionaryWithObjects:[anOwner, topLevelObjects] forKeys:[CPCibOwner, CPCibTopLevelObjects]]];
}
@end
+59
View File
@@ -0,0 +1,59 @@
/*
* CPCibHelpConnector.j
* AppKit
*
* Created by Antoine Mercadal.
* Copyright 2012, The Cappuccino Project.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPCibConnector.j"
@implementation CPCibHelpConnector : CPCibConnector
{
id _destination;
id _file;
id _marker;
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_destination = [aCoder decodeObjectForKey:@"_destination"];
_file = [aCoder decodeObjectForKey:@"_file"];
_marker = [aCoder decodeObjectForKey:@"_marker"];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_destination forKey:@"_destination"];
[aCoder encodeObject:_file forKey:@"_file"];
[aCoder encodeObject:_marker forKey:@"_marker"];
}
- (void)establishConnection
{
[_destination setToolTip:_marker];
}
@end
@@ -0,0 +1,64 @@
/*
* CPCibRuntimeAttributesConnector.j
* AppKit
*
* Created by Aparajita Fishman.
* Copyright 2012, The Cappuccino Project.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPCibConnector.j"
var CPCibRuntimeAttributesConnectorObjectKey = @"CPCibRuntimeAttributesConnectorObjectKey",
CPCibRuntimeAttributesConnectorKeyPathsKey = @"CPCibRuntimeAttributesConnectorKeyPathsKey",
CPCibRuntimeAttributesConnectorValuesKey = @"CPCibRuntimeAttributesConnectorValuesKey";
@implementation CPCibRuntimeAttributesConnector : CPCibConnector
{
id _keyPaths;
id _values;
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_source = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorObjectKey];
_keyPaths = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorKeyPathsKey];
_values = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorValuesKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_source forKey:CPCibRuntimeAttributesConnectorObjectKey];
[aCoder encodeObject:_keyPaths forKey:CPCibRuntimeAttributesConnectorKeyPathsKey];
[aCoder encodeObject:_values forKey:CPCibRuntimeAttributesConnectorValuesKey];
}
- (void)establishConnection
{
var count = [_keyPaths count];
while (count--)
[_source setValue:_values[count] forKeyPath:_keyPaths[count]];
}
@end
+2 -2
View File
@@ -61,14 +61,14 @@ var _CPCibClassSwapperClassNameKey = @"_CPCibClassSwapperClassNameKey",
if (!object)
{
CPLog.error("Unable to find class " + theClassName + " in cib file.");
CPLog.error("Unable to find class " + theClassName + " referenced in cib file.");
object = [self allocObjectWithCoder:aCoder className:[aCoder decodeObjectForKey:_CPCibClassSwapperOriginalClassNameKey]];
}
}
if (!object)
[CPException raise:CPInvalidArgumentException reason:@"Unable to find class " + theClassName + " in cib file."];
[CPException raise:CPInvalidArgumentException reason:@"Unable to find class " + theClassName + " referenced in cib file."];
return object;
}
+33 -1
View File
@@ -43,6 +43,11 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
return [[self alloc] initWithClassName:@"CPImage" resourceName:aResourceName properties:[CPDictionary dictionaryWithObject:aSize forKey:@"size"]];
}
+ (id)imageResourceWithName:(CPString)aResourceName size:(CGSize)aSize bundleClass:(CPString)aBundleClass
{
return [[self alloc] initWithClassName:@"CPImage" resourceName:aResourceName properties:[CPDictionary dictionaryWithObjects:[aSize, aBundleClass] forKeys:[@"size", @"bundleClass"]]];
}
- (id)initWithClassName:(CPString)aClassName resourceName:(CPString)aResourceName properties:(CPDictionary)properties
{
self = [super init];
@@ -89,12 +94,32 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
else if (_resourceName == "CPRemoveTemplate")
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"minus_button.png"] size:CGSizeMake(11, 4)];
return [[CPImage alloc] initWithContentsOfFile:[[aCoder bundle] pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
return [self imageFromBundle:[aCoder bundle]];
}
return self;
}
- (CPImage)imageFromBundle:(CPBundle)aBundle
{
if (!aBundle)
{
var bundleClass = _properties.valueForKey(@"bundleClass");
if (bundleClass)
{
bundleClass = CPClassFromString(bundleClass);
if (bundleClass)
aBundle = [CPBundle bundleForClass:bundleClass];
}
else
aBundle = [CPBundle mainBundle];
}
return [[CPImage alloc] initWithContentsOfFile:[aBundle pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
}
@end
@implementation _CPCibCustomResource (CPImage)
@@ -129,4 +154,11 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
return nil;
}
- (CPString)description
{
var image = [self imageFromBundle:nil];
return [image description];
}
@end
+26 -6
View File
@@ -29,6 +29,8 @@
@import "CPCibControlConnector.j"
@import "CPCibOutletConnector.j"
@import "CPCibBindingConnector.j"
@import "CPCibRuntimeAttributesConnector.j"
@import "CPCibHelpConnector.j"
@implementation _CPCibObjectData : CPObject
@@ -106,7 +108,7 @@
var object = nil,
objectEnumerator = [_visibleWindows objectEnumerator];
while (object = [objectEnumerator nextObject])
while ((object = [objectEnumerator nextObject]) !== nil)
[_replacementObjects[[object UID]] makeKeyAndOrderFront:self];
}
@@ -232,15 +234,15 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
{
_replacementObjects[[object UID]] = instantiatedObject;
if ([instantiatedObject isKindOfClass:[CPView class]])
if ([instantiatedObject isKindOfClass:CPView])
{
var clipView = [instantiatedObject superview];
if ([clipView isKindOfClass:[CPClipView class]])
if ([clipView isKindOfClass:CPClipView])
{
var scrollView = [clipView superview];
if ([scrollView isKindOfClass:[CPScrollView class]])
if ([scrollView isKindOfClass:CPScrollView])
[scrollView setDocumentView:instantiatedObject];
}
}
@@ -257,11 +259,29 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
_replacementObjects[[_fileOwner UID]] = anOwner;
var index = 0,
count = _connections.length;
count = _connections.length,
runtimeAttributeConnectors = [],
connection = nil;
for (; index < count; ++index)
{
var connection = _connections[index];
connection = _connections[index];
if ([connection isKindOfClass:CPCibRuntimeAttributesConnector])
// Defer runtime attribute connections until after all other connections are made
runtimeAttributeConnectors.push(connection);
else
{
[connection replaceObjects:_replacementObjects];
[connection establishConnection];
}
}
count = runtimeAttributeConnectors.length;
for (index = 0; index < count; ++index)
{
connection = runtimeAttributeConnectors[index];
[connection replaceObjects:_replacementObjects];
[connection establishConnection];
+4 -5
View File
@@ -77,8 +77,8 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemp
_windowTitle = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowTitleKey];
_windowView = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowViewKey];
_windowAutorecalculatesKeyViewLoop = !![aCoder decodeObjectForKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
_windowIsFullPlatformWindow = !![aCoder decodeObjectForKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
_windowAutorecalculatesKeyViewLoop = [aCoder decodeBoolForKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
_windowIsFullPlatformWindow = [aCoder decodeBoolForKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
}
return self;
@@ -125,14 +125,13 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemp
- (id)_cibInstantiate
{
var windowClass = CPClassFromString([self windowClass]);
var windowClass = CPClassFromString([self windowClass]),
theWindow = [[windowClass alloc] initWithContentRect:_windowRect styleMask:_windowStyleMask];
/* if (!windowClass)
[NSException raise:NSInvalidArgumentException format:@"Unable to locate NSWindow class %@, using NSWindow",_windowClass];
class=[NSWindow class];*/
var theWindow = [[windowClass alloc] initWithContentRect:_windowRect styleMask:_windowStyleMask];
if (_minSize)
[theWindow setMinSize:_minSize];
if (_maxSize)
+7 -6
View File
@@ -29,7 +29,7 @@
function CABackingStoreGetContext(aBackingStore)
{
return aBackingStore.context;
}
};
if (CPFeatureIsCompatible(CPHTMLCanvasFeature))
{
@@ -42,7 +42,7 @@ CABackingStoreCreate = function()
// FIXME: Consolidate drawImage to support this.
return { context:DOMElement.getContext("2d"), buffer:DOMElement, _image:DOMElement };
}
};
CABackingStoreSetSize = function(aBackingStore, aSize)
{
@@ -52,7 +52,8 @@ CABackingStoreSetSize = function(aBackingStore, aSize)
buffer.height = aSize.height;
buffer.style.width = PIXEL(aSize.width);
buffer.style.height = PIXEL(aSize.height);
}
};
}
else
{
@@ -64,10 +65,10 @@ CABackingStoreCreate = function()
context.buffer = "";
return { context:context };
}
};
CABackingStoreSetSize = function(aBackingStore, aSize)
{
}
};
}
}
+1 -1
View File
@@ -20,7 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "CGGeometry.h"
#include "../../Foundation/_CGGeometry.h"
#define _CGAffineTransformMake(a_, b_, c_, d_, tx_, ty_) { a:a_, b:b_, c:c_, d:d_, tx:tx_, ty:ty_ }
#define _CGAffineTransformMakeIdentity() _CGAffineTransformMake(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)
+4 -3
View File
@@ -108,7 +108,7 @@ function CGColorCreateCopy(aColor)
*/
function CGColorCreateGenericGray(gray, alpha)
{
return CGColorCreate(CGColorSpaceCreateDeviceRGB(), [gray,gray,gray, alpha]);
return CGColorCreate(CGColorSpaceCreateDeviceRGB(), [gray, gray, gray, alpha]);
}
/*!
@@ -137,7 +137,7 @@ function CGColorCreateGenericRGB(red, green, blue, alpha)
*/
function CGColorCreateGenericCMYK(cyan, magenta, yellow, black, alpha)
{
return CGColorCreate(CGColorSpaceCreateDeviceCMYK(),
return CGColorCreate(CGColorSpaceCreateDeviceCMYK(),
[cyan, magenta, yellow, black, alpha]);
}
@@ -150,7 +150,8 @@ function CGColorCreateGenericCMYK(cyan, magenta, yellow, black, alpha)
*/
function CGColorCreateCopyWithAlpha(aColor, anAlpha)
{
if ( !aColor ) return aColor; // Avoid error null pointer in next line
if (!aColor)
return aColor; // Avoid error null pointer in next line
var components = aColor.components.slice();
+1 -1
View File
@@ -193,7 +193,7 @@ function CGColorSpaceRetain(aColorSpace)
}
// FIXME: We should refer to some default values.
#define STANDARDIZE(components, index, minimum, maximum, multiplier) \
#define STANDARDIZE(components, index, minimum, maximum, multiplier) \
{ \
if (index > components.length) \
{ \
+3 -3
View File
@@ -323,7 +323,7 @@ function CGContextTranslateCTM(aContext, tx, ty)
#define rotate_scale(a, b, c, d) \
var sign = (a * d < 0.0 || b * c > 0.0) ? -1.0 : 1.0;\
a1 = (Math.atan2(sign * b, sign * a) + Math.atan2(-c, d)) / 2.0,\
a1 = (ATAN2(sign * b, sign * a) + ATAN2(-c, d)) / 2.0,\
cos = COS(a1),\
sin = SIN(a1);\
\
@@ -358,7 +358,7 @@ if (CPFeatureIsCompatible(CPJavaScriptCanvasTransformFeature))
CGContextConcatCTM = function(aContext, anAffineTransform)
{
aContext.transform(anAffineTransform.a, anAffineTransform.b, anAffineTransform.c, anAffineTransform.d, anAffineTransform.tx, anAffineTransform.ty);
}
};
}
else
@@ -428,7 +428,7 @@ CGContextConcatCTM = function(aContext, anAffineTransform)
CGContextScaleCTM(aContext, sx, sy);
if (a2 != 0.0)
CGContextRotateCTM(aContext, a2);
}
};
}

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