Compare commits

..
2532 Commits
Author SHA1 Message Date
Francisco Ryan Tolmasky I 80097ea2a2 Merge branch 'master' into @each 2010-11-03 21:28:10 -07:00
Ross Boucher b85e9d83b8 Fix for the fix for extensionless IB resource names. 2010-11-03 11:18:37 -07:00
Francisco Ryan Tolmasky I 2e9684e9a7 Fix for bottom corner view of CPScrollView being broken in CPCoding circumstances (normal coding, nib2cibing, Atlas, etc.).
Reviewed by me.
2010-11-03 10:37:51 -07:00
Klaas Pieter Annema a80a0d0a13 Complete the style fix started in previous commit 2010-11-03 14:13:55 +01:00
Francisco Ryan Tolmasky I 885eff1f9b Style fix.
Reviewed by me.
2010-11-03 01:34:54 -07:00
Francisco Ryan Tolmasky I 706e80362d Slight change to last commit, change == to ===.
Reviewed by me.
2010-11-03 01:25:08 -07:00
Brian DonovanandFrancisco Ryan Tolmasky I 7bf2297125 -[CPArrayController setContent:] would interpret nil as [nil].
When initializing a CPArrayController with a value that is not an array setContent: would make it an array by replacing value with [value]. This is consistent with how Cocoa does it, but it should first check to make sure that the content is not nil. If it is, the sensible thing to do (and what Cocoa does) is to replace it with an empty array.

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

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

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

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

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

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

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

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

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

Removing unnecessary constants

Borrowing initialization from my old implementation.

Refactoring the initialization method and adding setBackgroundColor: override.

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

Implement the bulk of the new CPTabView

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

Adding delegate

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

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

Cleaning up the test.

Resolving delegate issues (thanks Saikat!).

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

Conflicts:

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

- List of themes is available via CPApplication -themes.

- CPThemeBlend adds the following methods:

themes
themeNames

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

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

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

- Theme browser application that demonstrates the API.

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

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

- Bezel drawing uses CPDrawTiledRects, obeys border width.

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

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

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

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

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

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

- Moved colorization of log level to _CPFormatLogMessage.

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

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

- Added inline collapsible class hierarchy diagrams within each class.

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

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

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

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

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

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

Conflicts:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Conflicts:

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

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

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

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

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

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

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

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

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

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

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

Conflicts:

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

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

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

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

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

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

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

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

Conflicts:

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

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

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

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

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

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

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

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

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

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

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

Reviewed by me.
2009-12-04 12:39:49 -08:00
Francisco Ryan Tolmasky I 629737cda3 Apply positioning heuristics to +[CPMenu popUpMenu...] as well.
Reviewed by me.
2009-12-04 12:12:53 -08:00
Francisco Ryan Tolmasky I ec41411675 Fix for disabled menu item shadows, and slighlty better positioning for pop up menus.
Reviewed by me.
2009-12-04 11:55:01 -08:00
Francisco Ryan Tolmasky I becdf2bfeb Fix for menus not having the proper font.
Reviewed by me.
2009-12-04 11:35:40 -08:00
Ross Boucher 1e723945f8 Should have removed rather than commented out these lines 2009-12-04 11:25:20 -08:00
Ross Boucher dfb7599bb6 Remove the cursor hack from CPImageAndTextView, set the cursor globally to the default in CPApplication 2009-12-04 11:22:57 -08:00
Ross Boucher e1d3363ad9 A couple fixes to the CPCursor stuff 2009-12-04 11:12:13 -08:00
cacaodevandRoss Boucher c36c750c5d CPCursor implementation tested in WebKit/FF/IE/Opera. See comments in the file for more details. 2009-12-04 11:02:57 -08:00
Francisco Ryan Tolmasky I c7581c0847 Merge branch 'jake' into menus
Conflicts:
	AppKit/CPMenu.j
2009-12-03 22:50:13 -08:00
Ross Boucher 936d65291f Temporary fix until Francisco merges in the menu branch. 2009-12-03 19:31:52 -08:00
Francisco Ryan Tolmasky I a64030ad93 Merge branch 'jake' into menus 2009-12-03 19:25:38 -08:00
cacaodevandRoss Boucher 01d60ad4e9 CPSearchField changes from issue #194 2009-12-03 19:24:43 -08:00
Francisco Ryan Tolmasky I 06b64c6a87 Fix for a few edge cases, and added showsStateColumn support to nib2cib.
Reviewed by me.
2009-12-03 19:24:03 -08:00
Francisco Ryan Tolmasky I 0eff4e2bc0 Fix for moving to a base menu resetting the child menu.
Reviewed by me.
2009-12-03 17:58:49 -08:00
Ross Boucher 44d6139db2 Fix for some resizing issues in CPWebView. 2009-12-03 17:39:44 -08:00
Francisco Ryan Tolmasky I 506e3004b7 Merge branch 'jake' into menus 2009-12-03 17:02:02 -08:00
Francisco Ryan Tolmasky I 9ce4c7a468 Don't highlight items while scrolling.
Reviewed by me.
2009-12-03 16:59:10 -08:00
Ross Boucher 2fc724e469 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-03 16:29:46 -08:00
Ross Boucher afb69a7f03 Set the created window to not be at 0,0. We need real cascading support. 2009-12-03 16:29:08 -08:00
Ross Boucher cd2dd9f12d Remove dead variables 2009-12-03 16:28:56 -08:00
Francisco Ryan Tolmasky I 29963f74d6 Made menu positioning smarter.
Reviewed by me.
2009-12-03 16:24:35 -08:00
Francisco Ryan Tolmasky I 565a017ebd Merge branch 'jake' into menus 2009-12-03 11:21:35 -08:00
Derek HammerandFrancisco Ryan Tolmasky I 0b85847524 Adding reset to CPAppBootstrapper so that application can be restarted programmatically 2009-12-03 11:20:44 -08:00
Francisco Ryan Tolmasky I cfc46edfb8 Fix for properly positioning pop up button menus.
Reviewed by me.
2009-12-03 01:27:53 -08:00
Francisco Ryan Tolmasky I f250373673 Fix for actions not being sent in submenus.
Reviewed by me.
2009-12-03 00:42:13 -08:00
Francisco Ryan Tolmasky I b0acc13da7 Fix for exceptions when not on a menu item.
Reviewed by me.
2009-12-02 23:08:33 -08:00
Francisco Ryan Tolmasky I d705af8965 Added support for indentation levels in menu items.
Reviewed by me.
2009-12-02 20:41:52 -08:00
Francisco Ryan Tolmasky I a401dfddff Merge branch 'jake' into menus 2009-12-02 20:19:14 -08:00
Francisco Ryan Tolmasky I f579fd925e Fixed state columns not showing up.
Reviewed by me.
2009-12-02 20:18:25 -08:00
Ross Boucher e6d86eaa9b Throw an exception for -1 indexes in CPArray objectAtIndex: 2009-12-02 19:19:18 -08:00
Francisco Ryan Tolmasky I 348e45a5cd Some cleanup and a fix for custom views in menus.
Reviewed by me.
2009-12-02 18:40:47 -08:00
Ross Boucher 2120e9cf2a Potential fix for a drawing issue in IE. 2009-12-02 18:27:18 -08:00
Ross Boucher 3002acc895 Change for the way in which we detect full bridge window close 2009-12-02 18:26:55 -08:00
Francisco Ryan Tolmasky I 0b3c313280 Fix for highlight look in menu bars.
Reviewed by me.
2009-12-02 18:12:50 -08:00
Francisco Ryan Tolmasky I 982ab4b4fa Merge branch 'jake' into menus 2009-12-02 17:18:11 -08:00
Ross Boucher a0ee2f384b Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-02 17:15:17 -08:00
Ross Boucher 56a739655f A whole bunch of textfield and key event fixes. 2009-12-02 17:14:47 -08:00
Francisco Ryan Tolmasky I 150ee44da0 Added background highlight to menu bar and fixed highligh turning off after stopping tracking in menu bar.
Reviewed by me.
2009-12-02 16:39:38 -08:00
Francisco Ryan Tolmasky I 78795e3167 Preliminary menu bar support.
Reviewed by me.
2009-12-02 15:57:52 -08:00
tlrobinson b0dd3cd818 Fix nib2cib. 2009-12-01 20:02:55 -08:00
Francisco Ryan Tolmasky I ef12ec54d7 Added new view for menu bar items.
Reviewed by me.
2009-12-01 19:19:24 -08:00
Francisco Ryan Tolmasky I 495b774965 A bit of cleanup.
Reviewed by me.
2009-12-01 17:49:15 -08:00
Ross Boucher 1381bb5c54 Prevent CPViewController from loading the same cibs lots of times. I think the solution should be made generic and put into CPCib though. Closes #348. 2009-12-01 09:25:49 -08:00
Ross Boucher f1d4794dd1 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-12-01 09:14:45 -08:00
Thomas BalthazarandRoss Boucher d58473c270 Fix for GHissue #348 : CPViewController should cache the cib 2009-12-01 09:14:30 -08:00
Francisco Ryan Tolmasky I 7adf32f36e Changed menu bar background image.
Reviewed by me.
2009-11-30 23:41:16 -08:00
Francisco Ryan Tolmasky I 5c3beb4160 Fix for _minimumWidth not being defined in the CPMenu class, resulting in minimum widths being applied globally, and menus appearing in strange places in desktop mode.
Reviewed by me.
2009-11-30 23:20:56 -08:00
Francisco Ryan Tolmasky I b82c307007 Added -setMinimumWidth/minimumWidth to CPMenu.
Reviewed by me.
2009-11-30 23:08:05 -08:00
Francisco Ryan Tolmasky I a7010e7598 Accidentally broke normal menu items.
Reviewed by me.
2009-11-30 22:43:36 -08:00
Francisco Ryan Tolmasky I f850cbf780 Better handling of submenu actions.
Reviewed by me.
2009-11-30 22:30:41 -08:00
Tom Robinson 4581fe4f22 Cleanup command line tool args (change objj to include command at args[0]) 2009-11-30 21:45:01 -08:00
Francisco Ryan Tolmasky I 35df54ae99 Merge branch 'jake' into menus 2009-11-30 21:29:27 -08:00
Francisco Ryan Tolmasky I f8a5f91687 Fix for nib2cib leaving cells as targets for menu items.
Reviewed by me.
2009-11-30 21:28:42 -08:00
Francisco Ryan Tolmasky I 4b71557584 Added -popUpMenuPositioningItem:atLocation:inView:callback: and began porting existing uses to it.
Reviewed by me.
2009-11-30 20:54:53 -08:00
Tom Robinson feda903f2f Remove unused junk 2009-11-30 18:45:40 -08:00
Tom Robinson 150e264f0d Remove bake. 2009-11-30 17:21:16 -08:00
Tom Robinson b592f6ae92 Remove submodules 2009-11-30 17:15:37 -08:00
Francisco Ryan Tolmasky I 37ba8fb57d Merge branch 'jake' into menus 2009-11-30 02:02:48 -08:00
Francisco Ryan Tolmasky I 72f80cdbed Cleaned up menu constraints.
Reviewed by me.
2009-11-30 02:01:44 -08:00
Francisco Ryan Tolmasky I c070f20669 Better constraint support, and better support for moving out of submenus.
Reviewed by me.
2009-11-29 19:54:15 -08:00
Ross Boucher a4d5165a3d Fix for style issues. 2009-11-26 19:53:36 -05:00
Abhinav GuptaandRoss Boucher 4fdddfb585 Fixed CPString's commonPrefixWithString to be faster. 2009-11-26 19:49:41 -05:00
Abhinav GuptaandRoss Boucher 0575e96b60 Added commonPrefixWithString method to CPString and tests for it. 2009-11-26 18:13:01 -05:00
Ross Boucher d0a8749986 Fix a type in CPOutlineView. Closes #265. 2009-11-25 00:09:55 -05:00
Ross Boucher 44fbf8afe2 Add support for encoding dates, courtesy of luddep. 2009-11-24 23:02:38 -05:00
Ross Boucher 1eb9202233 A few style guideline changes. 2009-11-24 22:56:18 -05:00
Alexander LjungbergandRoss Boucher b7da92d225 CPDate initWithString: now takes proper international format strings like NSDate. Similarly CPDate description generates such strings. 2009-11-24 22:42:02 -05:00
Ross Boucher e4f6d0db1f Fixes an issue with HUD style alert panels. Closes #343. 2009-11-24 22:13:20 -05:00
Ross Boucher 0a8bd9f687 Remove the "Cancelled" message that Safari shows when an XHR is cancelled during startup. Closes #344. 2009-11-24 18:38:25 -05:00
Ross Boucher f2608998f9 Fixes a typo in CPRectContainsRect by simply calling out to CGRectContainsRect. We should explore simply removing this method entirely. Includes test cases. Closes #345. 2009-11-24 18:30:31 -05:00
Ross Boucher ffb08d32ce Fix an issue with storing 0 in a CPSet. Includes test cases. Closes #337. 2009-11-24 16:06:32 -05:00
Francisco Ryan Tolmasky I 119e776ddc Make scrolling work in submenus.
Reviewed by me.
2009-11-23 23:35:58 -08:00
Francisco Ryan Tolmasky I 652930d5aa Merge branch 'jake' into menus 2009-11-22 16:43:43 -08:00
Francisco Ryan Tolmasky I e3babe97e4 Update to fix menu item sizes breaking on second open.
Reviewed by me.
2009-11-20 23:34:21 -08:00
Ross Boucher 72d01865ae Add about panel 2009-11-20 18:06:16 -08:00
Ross Boucher b9664681a3 Better error reporting for narwhal-jsc 2009-11-19 15:29:20 -08:00
Ross Boucher fd5c545189 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-19 14:54:51 -08:00
Ross Boucher 0639f4b00f Exit from subjake if the subjake returns non zero status code. Don't exit in the compiler (required for building in Atlas to not kill the process) 2009-11-19 14:48:18 -08:00
Tom Robinson ab49986238 Add --clone option to bootstrap, and prompt for location 2009-11-19 14:18:49 -08:00
Francisco Ryan Tolmasky I a4fdc50d1d Move these back into their own folders.
Reviewed by me.
2009-11-19 14:04:16 -08:00
Francisco Ryan Tolmasky I ed228b6183 Merge branch 'jake' into menus 2009-11-19 14:02:34 -08:00
Francisco Ryan Tolmasky I e0e675531a Temporarily move these out into the main folder.
Reviewed by me.
2009-11-19 14:02:16 -08:00
Francisco Ryan Tolmasky I 44e0879224 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-19 13:26:36 -08:00
Francisco Ryan Tolmasky I 1e6fa93ea2 Fix for NSScrollView breaking nib2cib.
Reviewed by me.
2009-11-19 13:26:02 -08:00
Tom Robinson 2aaed6bffd Replace outdated objj-executable with Narwhal magic. 2009-11-19 00:17:12 -08:00
Francisco Ryan Tolmasky I 2d367a8b47 Fix for not being able to drag window from spaces in toolbar.
Reviewed by me.
2009-11-18 22:08:57 -08:00
Francisco Ryan Tolmasky I 52c18abc5e Fix for class_addMethod with a root class.
Reviewed by me.
2009-11-18 21:56:10 -08:00
Ross Boucher 595c70ed56 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-18 14:28:33 -08:00
Alexander LjungbergandRoss Boucher 9faec8decd Fixed: calling setIsPaneSplitter: on a CPTableView would change the divider width but the subviews would not change size to match. 2009-11-18 14:22:58 -08:00
Tom Robinson 90dc1f6cf8 Reorder shell config file checks. 2009-11-18 01:34:01 -08:00
Francisco Ryan Tolmasky I ba01976151 Added target and action to radio groups.
Reviewed by me.
2009-11-17 19:52:20 -08:00
Francisco Ryan Tolmasky I 4d7f5a8a09 Fix for fixing state after turning setAllowsMixedState to NO.
Reviewed by me.
2009-11-17 19:17:58 -08:00
Ross Boucher 2d01fa6f94 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-17 17:04:12 -08:00
Ross Boucher 970f848b84 Make CPAlert slightly (but only slightly) more externally hackable 2009-11-17 17:03:42 -08:00
Tom Robinson 31feec0465 Flush stdin after writing file to ShrinkSafe process (fixes building in Rhino) 2009-11-17 17:02:07 -08:00
Francisco Ryan Tolmasky I 2466c14300 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-17 14:49:30 -08:00
Francisco Ryan Tolmasky I 49927fcfb7 Fix for building projects where source files are in nested subfolders.
Reviewed by me.
2009-11-17 14:46:54 -08:00
Ross Boucher f612683dfb Taking this out for now. 2009-11-17 10:26:58 -08:00
Ross Boucher 11e6ad2153 Adding a simple way to set a function for the target/action 2009-11-17 09:28:44 -08:00
Klaas Pieter AnnemaandRoss Boucher d041c69e0d Added a check if the window is loaded in CPWindowController 2009-11-17 09:19:05 -08:00
Randall LueckeandRoss Boucher b394052145 fixed tableview typo 2009-11-17 09:16:30 -08:00
Francisco Ryan Tolmasky I bce83e45b5 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-16 18:28:04 -08:00
Francisco Ryan Tolmasky I 77bd8d3a76 Add hide: and hideOthers support.
Reviewed by me.
2009-11-16 18:27:38 -08:00
Tom Robinson 118ece9f1c Implement "which" for bootstrap and switch to 280north repos. 2009-11-16 17:11:05 -08:00
Francisco Ryan Tolmasky I 971956a6ba Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-16 15:09:51 -08:00
Francisco Ryan Tolmasky I 48cd362015 Fix for using unicode characters with capp config.
Reviewed by me.
2009-11-16 15:09:22 -08:00
Tom Robinson b12b1bf662 Incorrect case in require("os") 2009-11-16 14:12:53 -08:00
Francisco Ryan Tolmasky I 6829d502d7 Better support for opening files.
Reviewed by me.
2009-11-16 11:47:06 -08:00
Francisco Ryan Tolmasky I aa8689a4f0 Fix for compiling with spaces in path name and misidentifying IE.
Reviewed by me.
2009-11-15 19:13:13 -08:00
Francisco Ryan Tolmasky I 44cbcc60fa Check for gcc.
Reviewed by me.
2009-11-15 15:07:58 -08:00
Francisco Ryan Tolmasky I d4edb28837 Merge branch 'jake' of git@github.com:280north/cappuccino into jake 2009-11-15 14:46:59 -08:00
Francisco Ryan Tolmasky I 3245f38788 nib2cib fix for pull down menus.
Reviewed by me.
2009-11-15 14:45:46 -08:00
Ross Boucher 392cca1b2a Look for uppercase charactrs OR shift keys for determining shift key mask status on menu items 2009-11-15 12:51:48 -08:00
Francisco Ryan Tolmasky I ad901ed4b0 Added convinience method to applicationtask for grabbing the built index file.
Reviewed by me.
2009-11-15 07:38:28 -08:00
Francisco Ryan Tolmasky I 8f1e56e398 Implemented manual validation for toolbar items and fixed a number of toolbar bugs.
Closes #43.
Closes #48.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Conflicts:

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

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

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

Reviewed by me.
2009-05-24 14:20:18 -07:00
Ross Boucher c56e552d6e Merge branch 'master' of git@github.com:280north/cappuccino 2009-05-24 13:43:44 -07:00
Ross Boucher 5a3f1c81a0 Add open panel beginnings 2009-05-24 13:43:23 -07:00
Francisco Ryan Tolmasky I 25c145e490 Fix Info.plist name for Aristo blend.
Reviewed by me.
2009-05-24 12:49:25 -07:00
Francisco Ryan Tolmasky I 44dc4f6595 Fix for scroll wheel not working in Firefox 3 and up.
Closes #102.

Reviewed by me.
2009-05-24 12:45:51 -07:00
Ross Boucher d3938f3031 Merge branch 'master' of git@github.com:280north/cappuccino 2009-05-23 17:28:55 -07:00
Ross Boucher cfa21b0c96 Add a randomColor method. Useful for debugging. 2009-05-23 17:28:21 -07:00
Francisco Ryan Tolmasky I 83bceaa867 Fix for HUD button misrendered in Aristo theme gallery until pressed for first time.
Closes #141.

Reviewed by me.
2009-05-23 13:04:29 -07:00
Francisco Ryan Tolmasky I f6a731ff91 Updated loading page and removed some unused resources from Aristo blend.
Reviewed by me.
2009-05-23 12:55:20 -07:00
Francisco Ryan Tolmasky I 354fddf6b2 Updated template theme project to use new theme gallery.
Reviewed by me.
2009-05-23 12:43:35 -07:00
Francisco Ryan Tolmasky I aebbdbe0a3 Fixed a few graphics bugs and made the automatically generated theme gallery nicer.
Reviewed by me.
2009-05-23 12:33:24 -07:00
Francisco Ryan Tolmasky I 15bff97388 Fix for MainMenu.cib not displaying images.
Closes #140.

Reviewed by me.
2009-05-22 03:23:08 -07:00
Ross Boucher 18cf198592 Beginnings of a simple array controller test app. 2009-02-19 01:36:40 -08:00
Ross Boucher 9bbe51fa64 CPArrayController works simply with bindings and arrangedObjects 2009-02-19 01:29:39 -08:00
Ross Boucher 4de3a34a3e CPObjectController now works, as do bindings and CPControls. 2009-02-16 00:37:50 -08:00
Ross Boucher c028425f14 More bindings fixes. 2009-02-09 17:35:25 -08:00
Ross Boucher 7d03d8a58f Some test apps for bindings. 2009-02-07 13:00:27 -07:00
Ross Boucher db0e88d8a7 Various fixes. 2009-02-07 12:59:50 -07:00
Ross Boucher 1b8aca26a3 In progress work on bindings. 2009-02-07 12:55:15 -07:00
Ross Boucher b239053810 First take at CPController, CPObjectController. 2009-02-07 12:55:05 -07:00
Ross Boucher 1acb130be1 Add preliminary support for Key Value Bindings to Cappuccino. 2009-02-07 12:54:59 -07:00
1060 changed files with 90624 additions and 25365 deletions
+4
View File
@@ -1,3 +1,7 @@
.DS_Store
Frameworks
Build
Demos
./Aristo
WebSite
.push-package
-12
View File
@@ -1,12 +0,0 @@
[submodule "External/narwhal"]
path = External/narwhal
url = git://github.com/tlrobinson/narwhal.git
[submodule "External/jack"]
path = External/jack
url = git://github.com/tlrobinson/jack.git
[submodule "External/browserjs"]
path = External/browserjs
url = git://github.com/tlrobinson/browserjs.git
[submodule "External/ojunit"]
path = External/ojunit
url = git://github.com/280north/ojunit.git
+20 -2
View File
@@ -25,19 +25,26 @@
@import "CPAnimation.j"
@import "CPApplication.j"
@import "CPBezierPath.j"
@import "CPBox.j"
@import "CPBrowser.j"
@import "CPButton.j"
@import "CPButtonBar.j"
@import "CPCheckBox.j"
@import "CPCib.j"
@import "CPCibConnector.j"
@import "CPCibControlConnector.j"
@import "CPCibLoading.j"
@import "CPCibOutletConnector.j"
@import "CPClipView.j"
@import "CPCollectionView.j"
@import "CPCollectionViewItem.j"
@import "CPColor.j"
@import "CPColorPanel.j"
@import "CPColorWell.j"
@import "CPCompatibility.j"
@import "CPControl.j"
@import "CPCookie.j"
@import "CPCursor.j"
@import "CPDocument.j"
@import "CPDocumentController.j"
@import "CPEvent.j"
@@ -46,30 +53,41 @@
@import "CPFont.j"
@import "CPFontManager.j"
@import "CPGeometry.j"
@import "CPGraphics.j"
@import "CPImage.j"
@import "CPImageView.j"
@import "CPKeyBinding.j"
@import "CPMenu.j"
@import "CPMenuItem.j"
@import "CPOpenPanel.j"
@import "CPOutlineView.j"
@import "CPPanel.j"
@import "CPPasteboard.j"
@import "CPPopUpButton.j"
@import "CPProgressIndicator.j"
@import "CPRadio.j"
@import "CPResponder.j"
@import "CPScrollView.j"
@import "CPScroller.j"
@import "CPScrollView.j"
@import "CPSearchField.j"
@import "CPSecureTextField.j"
@import "CPSegmentedControl.j"
@import "CPShadow.j"
@import "CPSlider.j"
@import "CPSplitView.j"
@import "CPTabView.j"
@import "CPTableColumn.j"
@import "CPTableView.j"
@import "CPTabView.j"
@import "CPText.j"
@import "CPTextField.j"
@import "CPToolbar.j"
@import "CPToolbarItem.j"
@import "CPTokenField.j"
@import "CPTreeNode.j"
@import "CPView.j"
@import "CPViewAnimation.j"
@import "CPViewController.j"
@import "CPWebView.j"
@import "CPWindow.j"
@import "CPWindowController.j"
@import "CPArrayController.j"
+416
View File
@@ -0,0 +1,416 @@
/*
* CPAccordionView.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPArray.j>
@import <Foundation/CPObject.j>
@import <Foundation/CPKeyValueObserving.j>
@import <Foundation/CPIndexSet.j>
@import <Foundation/CPString.j>
@import "CPView.j"
@import "CPButton.j"
/*!
@ingroup appkit
@class CPAccordionViewItem
<p>A CPAccordionViewItem represents a single section of a CPAccordionView.</p>
*/
@implementation CPAccordionViewItem : CPObject
{
CPString _identifier @accessors(property=identifier);
CPView _view @accessors(property=view);
CPString _label @accessors(property=label);
}
- (id)init
{
return [self initWithIdentifier:@""];
}
/*!
Initializes a new CPAccordionViewItem with the specified identifier. This identifier may
then be used in subsequent methods to provide abstract introspection of the CPAccordionView.
*/
- (id)initWithIdentifier:(CPString)anIdentifier
{
self = [super init];
if (self)
[self setIdentifier:anIdentifier];
return self;
}
@end
/*!
@ingroup appkit
@class CPAccordionView
<p>CPAccordionView provides a container for CPAccordionViewItem objects and manages layout state
for all sublayout items.</p>
<strong>Example</strong><br />
<pre>
var myAccordionView = [[CPAccordionView alloc] initWithFrame:CGRectMakeZero()];
var firstItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"firstSection"]];
[firstItem setView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection"]];
[secondItem setView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
[myAccordionView addItem:firstItem];
[myAccordionView addItem:secondItem];
[myAccordionView setAutoresizingMask: CPViewWidthSizable | CPViewHeightSizable];
</pre>
*/
@implementation CPAccordionView : CPView
{
CPInteger _dirtyItemIndex;
CPView _itemHeaderPrototype;
CPMutableArray _items;
CPMutableArray _itemViews;
CPIndexSet _expandedItemIndexes;
}
/*!
Initializes the receiver for usage with the specified bounding rectangle
@return the initialized view
*/
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_items = [];
_itemViews = [];
_expandedItemIndexes = [CPIndexSet indexSet];
[self setItemHeaderPrototype:[[CPButton alloc] initWithFrame:_CGRectMake(0.0, 0.0, 100.0, 24.0)]];
}
return self;
}
- (void)setItemHeaderPrototype:(CPView)aView
{
_itemHeaderPrototype = aView;
}
- (CPView)itemHeaderPrototype
{
return _itemHeaderPrototype;
}
- (CPArray)items
{
return _items;
}
/*!
Append a CPAccordionViewItem to the receiver. Note that the CPAccordionViewItem must contain
a valid CPView derived component or a TypeError will be generated when the contents of the
ViewItem are disclosed.
*/
- (void)addItem:(CPAccordionViewItem)anItem
{
[self insertItem:anItem atIndex:_items.length];
}
- (void)insertItem:(CPAccordionViewItem)anItem atIndex:(CPInteger)anIndex
{
// FIXME: SHIFT ITEMS RIGHT
[_expandedItemIndexes addIndex:anIndex];
var itemView = [[_CPAccordionItemView alloc] initWithAccordionView:self];
[itemView setIndex:anIndex];
[itemView setLabel:[anItem label]];
[itemView setContentView:[anItem view]];
[self addSubview:itemView];
[_items insertObject:anItem atIndex:anIndex];
[_itemViews insertObject:itemView atIndex:anIndex];
[self _invalidateItemsStartingAtIndex:anIndex];
[self setNeedsLayout];
}
- (void)removeItem:(CPAccordionViewItem)anItem
{
[self removeItemAtIndex:[_items indexOfObjectIdenticalTo:anItem]];
}
- (void)removeItemAtIndex:(CPInteger)anIndex
{
// SHIFT ITEMS LEFT
[_expandedItemIndexes removeIndex:anIndex];
[_itemViews[anIndex] removeFromSuperview];
[_items removeObjectAtIndex:anIndex];
[_itemViews removeObjectAtIndex:anIndex];
[self _invalidateItemsStartingAtIndex:anIndex];
[self setNeedsLayout];
}
- (void)removeAllItems
{
var count = _items.length;
while (count--)
[self removeItemAtIndex:count];
}
- (void)expandItemAtIndex:(CPInteger)anIndex
{
if (![_itemViews[anIndex] isCollapsed])
return;
[_expandedItemIndexes addIndex:anIndex];
[_itemViews[anIndex] setCollapsed:NO];
[self _invalidateItemsStartingAtIndex:anIndex];
}
- (void)collapseItemAtIndex:(CPInteger)anIndex
{
if ([_itemViews[anIndex] isCollapsed])
return;
[_expandedItemIndexes removeIndex:anIndex];
[_itemViews[anIndex] setCollapsed:YES];
[self _invalidateItemsStartingAtIndex:anIndex];
}
- (void)toggleItemAtIndex:(CPInteger)anIndex
{
var itemView = _itemViews[anIndex];
if ([itemView isCollapsed])
[self expandItemAtIndex:anIndex];
else
[self collapseItemAtIndex:anIndex];
}
- (CPIndexSet)expandedItemIndexes
{
return _expandedItemIndexes;
}
- (CPIndexSet)collapsedItemIndexes
{
var indexSet = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, _items.length)];
[indexSet removeIndexes:_expandedIndexes];
return indexSet;
}
- (void)setEnabled:(BOOL)isEnabled forItemAtIndex:(CPInteger)anIndex
{
var itemView = _itemViews[anIndex];
if (!itemView)
return;
if (!isEnabled)
[self collapseItemAtIndex:anIndex];
else
[self expandItemAtIndex:anIndex];
[itemView setEnabled:isEnabled];
}
- (void)_invalidateItemsStartingAtIndex:(CPInteger)anIndex
{
if (_dirtyItemIndex === CPNotFound)
_dirtyItemIndex = anIndex;
_dirtyItemIndex = MIN(_dirtyItemIndex, anIndex);
[self setNeedsLayout];
}
- (void)setFrameSize:(CGSize)aSize
{
var width = _CGRectGetWidth([self frame]);
[super setFrameSize:aSize];
if (width !== _CGRectGetWidth([self frame]))
[self _invalidateItemsStartingAtIndex:0];
}
- (void)layoutSubviews
{
if (_items.length <= 0)
return [self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), 0.0)];
if (_dirtyItemIndex === CPNotFound)
return;
_dirtyItemIndex = MIN(_dirtyItemIndex, _items.length - 1);
var index = _dirtyItemIndex,
count = _itemViews.length,
width = _CGRectGetWidth([self bounds]),
y = index > 0 ? CGRectGetMaxY([_itemViews[index - 1] frame]) : 0.0;
// Do this now (instead of after looping), so that if we are made dirty again in the middle we don't blow this value away.
_dirtyItemIndex = CPNotFound;
for (; index < count; ++index)
{
var itemView = _itemViews[index];
[itemView setFrameY:y width:width];
y = CGRectGetMaxY([itemView frame]);
}
[self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), y)];
}
@end
@implementation _CPAccordionItemView : CPView
{
CPAccordionView _accordionView;
BOOL _isCollapsed @accessors(getter=isCollapsed, setter=setCollapsed:);
CPInteger _index @accessors(property=index);
CPView _headerView;
CPView _contentView;
}
- (id)initWithAccordionView:(CPAccordionView)anAccordionView
{
self = [super initWithFrame:_CGRectMakeZero()];
if (self)
{
_accordionView = anAccordionView;
_isCollapsed = NO;
var bounds = [self bounds];
_headerView = [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:[_accordionView itemHeaderPrototype]]];
if ([_headerView respondsToSelector:@selector(setTarget:)] && [_headerView respondsToSelector:@selector(setAction:)])
{
[_headerView setTarget:self];
[_headerView setAction:@selector(toggle:)];
}
[self addSubview:_headerView];
}
return self;
}
- (void)toggle:(id)aSender
{
[_accordionView toggleItemAtIndex:[self index]];
}
- (void)setLabel:(CPString)aLabel
{
if ([_headerView respondsToSelector:@selector(setTitle:)])
[_headerView setTitle:aLabel];
else if ([_headerView respondsToSelector:@selector(setLabel:)])
[_headerView setLabel:aLabel];
else if ([_headerView respondsToSelector:@selector(setStringValue:)])
[_headerView setStringValue:aLabel];
}
- (void)setEnabled:(BOOL)isEnabled
{
if ([_headerView respondsToSelector:@selector(setEnabled:)])
[_headerView setEnabled:isEnabled];
}
- (void)setContentView:(CPView)aView
{
if (_contentView === aView)
return;
[_contentView removeObserver:self forKeyPath:@"frame"];
[_contentView removeFromSuperview];
_contentView = aView;
[_contentView addObserver:self forKeyPath:@"frame" options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:NULL];
[self addSubview:_contentView];
[_accordionView _invalidateItemsStartingAtIndex:[self index]];
}
- (void)setFrameY:(float)aY width:(float)aWidth
{
var headerHeight = _CGRectGetHeight([_headerView frame]);
// Size to fit or something?
[_headerView setFrameSize:_CGSizeMake(aWidth, headerHeight)];
[_contentView setFrameOrigin:_CGPointMake(0.0, headerHeight)];
if ([self isCollapsed])
[self setFrame:_CGRectMake(0.0, aY, aWidth, headerHeight)];
else
{
var contentHeight = _CGRectGetHeight([_contentView frame]);
[_contentView setFrameSize:_CGSizeMake(aWidth, contentHeight)];
[self setFrame:_CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)];
}
}
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
{
}
- (void)observeValueForKeyPath:(CPString)aKeyPath
ofObject:(id)anObject
change:(CPDictionary)aChange
context:(id)aContext
{
if (aKeyPath === "frame" && !CGRectEqualToRect([aChange objectForKey:CPKeyValueChangeOldKey], [aChange objectForKey:CPKeyValueChangeNewKey]))
[_accordionView _invalidateItemsStartingAtIndex:[self index]];
/*
else if (aKeyPath === "itemHeaderPrototype")
{
}
*/
}
@end
+274 -112
View File
@@ -26,144 +26,153 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@import <AppKit/CPApplication.j>
@import <AppKit/CPButton.j>
@import <AppKit/CPColor.j>
@import <AppKit/CPFont.j>
@import <AppKit/CPImage.j>
@import <AppKit/CPImageView.j>
@import <AppKit/CPPanel.j>
@import <AppKit/CPTextField.j>
@import "CPApplication.j"
@import "CPButton.j"
@import "CPColor.j"
@import "CPFont.j"
@import "CPImage.j"
@import "CPImageView.j"
@import "CPPanel.j"
@import "CPTextField.j"
/*
@global
@group CPAlertStyle
*/
CPWarningAlertStyle = 0;
CPWarningAlertStyle = 0;
/*
@global
@group CPAlertStyle
*/
CPInformationalAlertStyle = 1;
CPInformationalAlertStyle = 1;
/*
@global
@group CPAlertStyle
*/
CPCriticalAlertStyle = 2;
var CPAlertWarningImage,
CPAlertInformationImage,
CPAlertErrorImage;
CPCriticalAlertStyle = 2;
/*!
@ingroup appkit
CPAlert is an alert panel that can be displayed modally to present the
user with a message and one or more options.
It can be used to display an information message (<pre>CPInformationalAlertStyle</pre>),
a warning message (<pre>CPWarningAlertStyle</pre> - which is the default), or a critical
alert (<pre>CPCriticalAlertStyle</pre>). In each case the user can be presented with one
or more options by adding buttons using the <pre>addButtonWithTitle:</pre> method.
It can be used to display an information message \c CPInformationalAlertStyle,
a warning message \c CPWarningAlertStyle (the default), or a critical
alert \c CPCriticalAlertStyle. In each case the user can be presented with one
or more options by adding buttons using the \c -addButtonWithTitle: method.
The panel is displayed modally by calling <pre>runModal</pre> and once the user has
The panel is displayed modally by calling \c -runModal and once the user has
dismissed the panel, a message will be sent to the panel's delegate (if set), informing
it which button was clicked (see delegate methods).
@delegate -(void)alertDidEnd:(CPAlert)theAlert returnCode:(int)returnCode;
Called when the user dismisses the alert by clicking one of the buttons.
@param theAlert the alert panel that the user dismissed
@param returnCode the index of the button that the user clicked (starting from 0,
@param returnCode the index of the button that the user clicked (starting from 0,
representing the first button added to the alert which appears on the
right, 1 representing the next button to the left and so on)
*/
@implementation CPAlert : CPObject
@implementation CPAlert : CPView
{
CPPanel _alertPanel;
CPTextField _messageLabel;
CPTextField _informativeLabel;
CPImageView _alertImageView;
CPAlertStyle _alertStyle;
CPString _windowTitle;
int _windowStyle;
int _buttonCount;
CPArray _buttons;
id _delegate;
SEL _didEndSelector;
id _modalDelegate;
}
+ (void)initialize
+ (CPString)defaultThemeClass
{
if (self != CPAlert)
return;
return @"alert";
}
var bundle = [CPBundle bundleForClass:[self class]];
CPAlertWarningImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-warning.png"]
size:CGSizeMake(32.0, 32.0)];
CPAlertInformationImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-information.png"]
size:CGSizeMake(32.0, 32.0)];
CPAlertErrorImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-error.png"]
size:CGSizeMake(32.0, 32.0)];
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[CGSizeMake(400.0, 110.0), CGInsetMake(15, 15, 15, 50), 6, 10,
CPJustifiedTextAlignment, [CPColor blackColor], [CPFont boldSystemFontOfSize:13.0], [CPNull null], CGSizeMakeZero(),
CPJustifiedTextAlignment, [CPColor blackColor], [CPFont systemFontOfSize:12.0], [CPNull null], CGSizeMakeZero(),
CGPointMake(15, 12),
[CPNull null],
[CPNull null],
[CPNull null]
]
forKeys:[@"size", @"content-inset", @"informative-offset", @"button-offset",
@"message-text-alignment", @"message-text-color", @"message-text-font", @"message-text-shadow-color", @"message-text-shadow-offset",
@"informative-text-alignment", @"informative-text-color", @"informative-text-font", @"informative-text-shadow-color", @"informative-text-shadow-offset",
@"image-offset",
@"information-image",
@"warning-image",
@"error-image"
]];
}
/*!
Initializes a <pre>CPAlert</pre> panel with the default alert style (<pre>CPWarningAlertStyle</pre>).
Initializes a \c CPAlert panel with the default alert style \c CPWarningAlertStyle.
*/
- (id)init
{
self = [super init];
if (self)
if (self = [super init])
{
_buttonCount = 0;
_buttons = [CPArray array];
_alertStyle = CPWarningAlertStyle;
_messageLabel = [[CPTextField alloc] initWithFrame:CGRectMake(57.0, 10.0, 220.0, 80.0)];
[_messageLabel setFont:[CPFont systemFontOfSize:12.0]];
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
[_messageLabel setAlignment:CPJustifiedTextAlignment];
_alertImageView = [[CPImageView alloc] initWithFrame:CGRectMake(15.0, 12.0, 32.0, 32.0)];
[self setWindowStyle:nil];
_alertPanel = nil;
_windowStyle = nil;
_didEndSelector = nil;
_messageLabel = [CPTextField labelWithTitle:@"Alert"];
_alertImageView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
_informativeLabel = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
}
return self;
}
/*!
Sets the window appearance.
Sets the window appearance. If CPHUDBackgroundWindowMask is set, the default HUD theme
will be activated.
@param styleMask - Either CPHUDBackgroundWindowMask or nil for standard.
*/
- (void)setWindowStyle:(int)styleMask
{
_windowStyle = styleMask;
_alertPanel = [[CPPanel alloc] initWithContentRect:CGRectMake(0.0, 0.0, 300.0, 130.0) styleMask:styleMask ? styleMask | CPTitledWindowMask : CPTitledWindowMask];
[_alertPanel setFloatingPanel:YES];
[_alertPanel center];
[_messageLabel setTextColor:(styleMask == CPHUDBackgroundWindowMask) ? [CPColor whiteColor] : [CPColor blackColor]];
var count = [_buttons count];
for(var i=0; i < count; i++)
[self setTheme:(_windowStyle & CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]];
// We'll need to recreate the panel to get the new window style.
_alertPanel = nil;
}
- (void)_createPanel
{
var frame = CGRectMakeZero();
frame.size = [self currentValueForThemeAttribute:@"size"];
_alertPanel = [[CPPanel alloc] initWithContentRect:frame styleMask:_windowStyle ? _windowStyle | CPTitledWindowMask : CPTitledWindowMask];
var contentView = [_alertPanel contentView],
count = [_buttons count];
if (count)
{
var button = _buttons[i];
[button setFrameSize:CGSizeMake([button frame].size.width, (styleMask == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
[button setBezelStyle:(styleMask == CPHUDBackgroundWindowMask) ? CPHUDBezelStyle : CPRoundedBezelStyle];
[[_alertPanel contentView] addSubview:button];
while (count--)
[contentView addSubview:_buttons[count]];
}
[[_alertPanel contentView] addSubview:_messageLabel];
[[_alertPanel contentView] addSubview:_alertImageView];
else
[self addButtonWithTitle:@"OK"];
[contentView addSubview:_messageLabel];
[contentView addSubview:_alertImageView];
[contentView addSubview:_informativeLabel];
}
/*!
@@ -226,7 +235,7 @@ var CPAlertWarningImage,
}
/*!
Sets the receivers message text, or title, to a given text.
Sets the receivers message text, or title, to a given text.
@param messageText - Message text for the alert.
*/
- (void)setMessageText:(CPString)messageText
@@ -234,75 +243,228 @@ var CPAlertWarningImage,
[_messageLabel setStringValue:messageText];
}
/*!
Return's the receiver's message text body.
/*!
Returns the receiver's message text body.
*/
- (CPString)messageText
{
return [_messageLabel stringValue];
}
/*!
Sets the receiver's informative text, shown below the message text.
@param informativeText - The informative text.
*/
- (void)setInformativeText:(CPString)informativeText
{
[_informativeLabel setStringValue:informativeText];
}
/*!
Returns the receiver's informative text.
*/
- (CPString)informativeText
{
return [_informativeLabel stringValue];
}
/*!
Adds a button with a given title to the receiver.
Buttons will be added starting from the right hand side of the <pre>CPAlert</pre> panel.
Buttons will be added starting from the right hand side of the \c CPAlert panel.
The first button will have the index 0, the second button 1 and so on.
The first button will automatically be given a key equivalent of Return,
and any button titled "Cancel" will be given a key equivalent of Escape.
You really shouldn't need more than 3 buttons.
*/
- (void)addButtonWithTitle:(CPString)title
{
var button = [[CPButton alloc] initWithFrame:CGRectMake(200.0 - (_buttonCount * 90.0), 98.0, 80.0, (_windowStyle == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
var bounds = [[_alertPanel contentView] bounds],
button = [[CPButton alloc] initWithFrame:CGRectMakeZero()],
_buttonCount = [_buttons count];
[button setTitle:title];
[button setTarget:self];
[button setTag:_buttonCount];
[button setAction:@selector(_notifyDelegate:)];
[button setBezelStyle:(_windowStyle == CPHUDBackgroundWindowMask) ? CPHUDBezelStyle : CPRoundRectBezelStyle];
[[_alertPanel contentView] addSubview:button];
if (_buttonCount == 0)
[_alertPanel setDefaultButton:button];
[button setAction:@selector(_dismissAlert:)];
_buttonCount++;
[_buttons addObject:button];
[[_alertPanel contentView] addSubview:button];
if (_buttonCount == 0)
[button setKeyEquivalent:CPCarriageReturnCharacter];
else if ([title lowercaseString] === "cancel")
[button setKeyEquivalent:CPEscapeFunctionKey];
else
[button setKeyEquivalent:nil];
[_buttons insertObject:button atIndex:0];
}
- (void)layoutPanel
{
if (!_alertPanel)
[self _createPanel];
var inset = [self currentValueForThemeAttribute:@"content-inset"],
iconOffset = [self currentValueForThemeAttribute:@"image-offset"],
theTitle,
theImage;
switch (_alertStyle)
{
case CPWarningAlertStyle: theImage = [self currentValueForThemeAttribute:@"warning-image"];
theTitle = @"Warning";
break;
case CPInformationalAlertStyle: theImage = [self currentValueForThemeAttribute:@"information-image"];
theTitle = @"Information";
break;
case CPCriticalAlertStyle: theImage = [self currentValueForThemeAttribute:@"error-image"];
theTitle = @"Error";
break;
}
[_alertImageView setImage:theImage];
var imageSize = theImage ? [theImage size] : CGSizeMakeZero();
[_alertImageView setFrame:CGRectMake(iconOffset.x, iconOffset.y, imageSize.width, imageSize.height)];
[_alertPanel setTitle:_windowTitle ? _windowTitle : theTitle];
[_alertPanel setFloatingPanel:YES];
[_alertPanel center];
[_messageLabel setTextColor:[self currentValueForThemeAttribute:@"message-text-color"]];
[_messageLabel setFont:[self currentValueForThemeAttribute:@"message-text-font"]];
[_messageLabel setTextShadowColor:[self currentValueForThemeAttribute:@"message-text-shadow-color"]];
[_messageLabel setTextShadowOffset:[self currentValueForThemeAttribute:@"message-text-shadow-offset"]];
[_messageLabel setAlignment:[self currentValueForThemeAttribute:@"message-text-alignment"]];
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
[_informativeLabel setTextColor:[self currentValueForThemeAttribute:@"informative-text-color"]];
[_informativeLabel setFont:[self currentValueForThemeAttribute:@"informative-text-font"]];
[_informativeLabel setTextShadowColor:[self currentValueForThemeAttribute:@"informative-text-shadow-color"]];
[_informativeLabel setTextShadowOffset:[self currentValueForThemeAttribute:@"informative-text-shadow-offset"]];
[_informativeLabel setLineBreakMode:CPLineBreakByWordWrapping];
// FIXME sizeWithFontCorrection shouldn't be needed.
var bounds = [[_alertPanel contentView] bounds],
offsetX = CGRectGetWidth(bounds) - inset.right,
informativeOffset = [self currentValueForThemeAttribute:@"informative-offset"],
buttonOffset = [self currentValueForThemeAttribute:@"button-offset"],
textWidth = offsetX - inset.left,
messageSize = [([_messageLabel stringValue] || " ") sizeWithFont:[_messageLabel font] inWidth:textWidth],
informationString = [_informativeLabel stringValue],
informativeSize = [(informationString || " ") sizeWithFont:[_informativeLabel font] inWidth:textWidth],
sizeWithFontCorrection = 6.0;
[_messageLabel setFrame:CGRectMake(inset.left, inset.top, textWidth, messageSize.height + sizeWithFontCorrection)];
[_informativeLabel setFrame:CGRectMake(inset.left, CGRectGetMaxY([_messageLabel frame]) + informativeOffset, textWidth, informativeSize.height + sizeWithFontCorrection)];
// Don't let an empty informative label partially cover the buttons.
[_informativeLabel setHidden:!informationString];
var aRepresentativeButton = _buttons[0],
buttonY = MAX(CGRectGetMaxY([_alertImageView frame]), CGRectGetMaxY(informationString ? [_informativeLabel frame] : [_messageLabel frame])) + buttonOffset; // the lower of the bottom of the text and the bottom of the icon.
[aRepresentativeButton setTheme:[self theme]];
[aRepresentativeButton sizeToFit];
// Make the window just tall enough to fit everything. Bit of a hack really.
var minimumSize = [self currentValueForThemeAttribute:@"size"],
desiredHeight = MAX(minimumSize.height, buttonY + CGRectGetHeight([aRepresentativeButton bounds]) + inset.bottom),
deltaY = desiredHeight - CGRectGetHeight(bounds),
frameSize = CGSizeMakeCopy([_alertPanel frame].size);
frameSize.height += deltaY;
[_alertPanel setFrameSize:frameSize];
var count = [_buttons count];
while (count--)
{
var button = _buttons[count];
[button setTheme:[self theme]];
[button sizeToFit];
var buttonBounds = [button bounds],
width = MAX(80.0, CGRectGetWidth(buttonBounds)),
height = CGRectGetHeight(buttonBounds);
offsetX -= width;
[button setFrame:CGRectMake(offsetX, buttonY, width, height)];
offsetX -= 10;
}
}
/*!
Displays the <pre>CPAlert</pre> panel as a modal dialog. The user will not be
Displays the \c CPAlert panel as a modal dialog. The user will not be
able to interact with any other controls until s/he has dismissed the alert
by clicking on one of the buttons.
*/
- (void)runModal
{
var theTitle;
switch (_alertStyle)
{
case CPWarningAlertStyle: [_alertImageView setImage:CPAlertWarningImage];
theTitle = @"Warning";
break;
case CPInformationalAlertStyle: [_alertImageView setImage:CPAlertInformationImage];
theTitle = @"Information";
break;
case CPCriticalAlertStyle: [_alertImageView setImage:CPAlertErrorImage];
theTitle = @"Error";
break;
}
[_alertPanel setTitle:_windowTitle ? _windowTitle : theTitle];
[self layoutPanel];
[CPApp runModalForWindow:_alertPanel];
}
/* @ignore */
- (void)_notifyDelegate:(id)button
{
if (_delegate && [_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:[button tag]];
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
[CPApp abortModal];
[_alertPanel close];
@param window The parent window for the sheet.
@param modalDelegate The delegate for the modal-dialog session.
@param alertDidEndSelector Message the alert sends to modalDelegate after the sheet is dismissed.
@param contextInfo Contextual data passed to modalDelegate in didEndSelector message.
*/
- (void)beginSheetModalForWindow:(CPWindow)window modalDelegate:(id)modalDelegate didEndSelector:(SEL)alertDidEndSelector contextInfo:(void)contextInfo
{
if (!(_windowStyle & CPDocModalWindowMask))
[self setWindowStyle:CPDocModalWindowMask];
[self layoutPanel];
_didEndSelector = alertDidEndSelector;
_modalDelegate = modalDelegate;
[CPApp beginSheet:_alertPanel modalForWindow:window modalDelegate:self didEndSelector:@selector(_alertDidEnd:returnCode:contextInfo:) contextInfo:contextInfo];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
@param window The parent window for the sheet.
*/
- (void)beginSheetModalForWindow:(CPWindow)window
{
if (!(_windowStyle & CPDocModalWindowMask))
[self setWindowStyle:CPDocModalWindowMask];
[self layoutPanel];
[CPApp beginSheet:_alertPanel modalForWindow:window modalDelegate:self didEndSelector:@selector(_alertDidEnd:returnCode:contextInfo:) contextInfo:nil];
}
- (void)_alertDidEnd:(CPWindow)aSheet returnCode:(CPInteger)returnCode contextInfo:(id)contextInfo
{
if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:returnCode];
if (_didEndSelector)
objj_msgSend(_modalDelegate, _didEndSelector, self, returnCode, contextInfo);
_didEndSelector = nil;
_modalDelegate = nil;
}
/* @ignore */
- (void)_dismissAlert:(CPButton)button
{
if ([_alertPanel isSheet])
[CPApp endSheet:_alertPanel returnCode:[button tag]];
else
{
[CPApp abortModal];
[_alertPanel close];
[self _alertDidEnd:nil returnCode:[button tag] contextInfo:nil];
}
}
@end
+74 -39
View File
@@ -48,19 +48,19 @@ CPAnimationLinear = 3;
ACTUAL_FRAME_RATE = 0;
/*!
/*!
@ingroup appkit
@class CPAnimation
Manages an animation. Contains timing and progress information.
@par Delegate Methods
@delegate -(BOOL)animationShouldStart:(CPAnimation)animation;
Called at the beginning of <code>startAnimation</code>.
Called at the beginning of \c -startAnimation.
@param animation the animation that will start
@return <code>YES</code> allows the animation to start.
<code>NO</code> stops the animation.
@return \c YES allows the animation to start.
\c NO stops the animation.
@delegate -(void)animationDidEnd:(CPAnimation)animation;
Called when an animation has completed.
@@ -72,7 +72,7 @@ ACTUAL_FRAME_RATE = 0;
@delegate - (float)animation:(CPAnimation)animation valueForProgress:(float)progress;
The value from this method will be returned when CPAnimation's
<code>currentValue</code> method is called.
\c currentValue method is called.
@param animation the animation to obtain the curve value for
@param progress the current animation progress
@return the curve value
@@ -81,13 +81,13 @@ ACTUAL_FRAME_RATE = 0;
{
CPTimeInterval _lastTime;
CPTimeInterval _duration;
CPAnimationCurve _animationCurve;
CAMediaTimingFunction _timingFunction;
float _frameRate;
float _progress;
id _delegate;
CPTimer _timer;
}
@@ -101,36 +101,37 @@ ACTUAL_FRAME_RATE = 0;
- (id)initWithDuration:(float)aDuration animationCurve:(CPAnimationCurve)anAnimationCurve
{
self = [super init];
if (self)
{
_progress = 0.0;
_duration = MAX(0.0, aDuration);
_animationCurve = anAnimationCurve;
_frameRate = 60.0;
[self setAnimationCurve:anAnimationCurve];
}
return self;
}
/*!
Sets the animation's pace.
@param anAnimationCurve the animation's pace
@throws CPInvalidArgumentException if an invalid animation curve is specified
@throws CPInvalidArgumentException if an invalid animation curve is specified
*/
- (void)setAnimationCurve:(CPAnimationCurve)anAnimationCurve
{
switch (_animationCurve)
switch (anAnimationCurve)
{
case CPAnimationEaseInOut: timingFunctionName = kCAMediaTimingFunctionEaseInEaseOut;
break;
case CPAnimationEaseIn: timingFunctionName = kCAMediaTimingFunctionEaseIn;
break;
case CPAnimationEaseOut: timingFunctionName = kCAMediaTimingFunctionEaseOut;
break;
case CPAnimationLinear: timingFunctionName = kCAMediaTimingFunctionLinear;
break;
@@ -138,7 +139,7 @@ ACTUAL_FRAME_RATE = 0;
reason:"Invalid value provided for animation curve"];
break;
}
_animationCurve = anAnimationCurve;
_timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName];
}
@@ -154,13 +155,13 @@ ACTUAL_FRAME_RATE = 0;
/*!
Sets the animation's length.
@param aDuration the new animation length
@throws CPInvalidArgumentException if <code>aDuration</code> is negative
@throws CPInvalidArgumentException if \c aDuration is negative
*/
- (void)setDuration:(CPTimeInterval)aDuration
{
if (aDuration < 0)
[CPException raise:CPInvalidArgumentException reason:"aDuration can't be negative"];
_duration = aDuration;
}
@@ -175,13 +176,13 @@ ACTUAL_FRAME_RATE = 0;
/*!
Sets the animation frame rate. This is not a guaranteed frame rate. 0 means to go as fast as possible.
@param frameRate the new desired frame rate
@throws CPInvalidArgumentException if <code>frameRate</code> is negative
@throws CPInvalidArgumentException if \c frameRate is negative
*/
- (void)setFrameRate:(float)frameRate
{
if (frameRate < 0)
[CPException raise:CPInvalidArgumentException reason:"frameRate can't be negative"];
_frameRate = frameRate;
}
@@ -211,22 +212,22 @@ ACTUAL_FRAME_RATE = 0;
}
/*!
Starts the animation. The method calls <code>animationShouldStart:</code>
Starts the animation. The method calls \c -animationShouldStart:
on the delegate (if it implements it) to see if the animation
should begin.
*/
- (void)startAnimation
{
// If we're already animating, or our delegate stops us, animate.
if (_timer || _delegate && [_delegate respondsToSelector:@selector(animationShouldStart)] && ![_delegate animationShouldStart:self])
if (_timer || _delegate && [_delegate respondsToSelector:@selector(animationShouldStart:)] && ![_delegate animationShouldStart:self])
return;
if (_progress === 1.0)
_progress = 0.0;
ACTUAL_FRAME_RATE = 0;
_lastTime = new Date();
_timer = [CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(animationTimerDidFire:) userInfo:nil repeats:YES];
}
@@ -241,14 +242,14 @@ ACTUAL_FRAME_RATE = 0;
_lastTime = currentTime;
++ACTUAL_FRAME_RATE;
[self setCurrentProgress:progress];
if (progress === 1.0)
{
[_timer invalidate];
_timer = nil;
if ([_delegate respondsToSelector:@selector(animationDidEnd:)])
[_delegate animationDidEnd:self];
}
@@ -261,16 +262,16 @@ ACTUAL_FRAME_RATE = 0;
{
if (!_timer)
return;
[_timer invalidate];
_timer = nil;
if ([_delegate respondsToSelector:@selector(animationDidStop:)])
[_delegate animationDidStop:self];
}
/*!
Returns <code>YES</code> if the animation
Returns \c YES if the animation
is running.
*/
- (BOOL)isAnimating
@@ -300,13 +301,47 @@ ACTUAL_FRAME_RATE = 0;
*/
- (float)currentValue
{
var t = [self currentProgress];
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
return [_delegate animation:self valueForProgress:_progress];
if (_animationCurve == CPAnimationLinear)
return _progress;
alert("IMPLEMENT ANIMATION CURVES!!!");
return [_delegate animation:self valueForProgress:t];
var c1 = [],
c2 = [];
[_timingFunction getControlPointAtIndex:1 values:c1];
[_timingFunction getControlPointAtIndex:2 values:c2];
return CubicBezierAtTime(t,c1[0],c1[1],c2[0],c2[1],_duration);
}
@end
// currently used function to determine time
// 1:1 conversion to js from webkit source files
// UnitBezier.h, WebCore_animation_AnimationBase.cpp
var CubicBezierAtTime = function CubicBezierAtTime(t,p1x,p1y,p2x,p2y,duration)
{
var ax=0,bx=0,cx=0,ay=0,by=0,cy=0;
// `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
function sampleCurveX(t) {return ((ax*t+bx)*t+cx)*t;};
function sampleCurveY(t) {return ((ay*t+by)*t+cy)*t;};
function sampleCurveDerivativeX(t) {return (3.0*ax*t+2.0*bx)*t+cx;};
// The epsilon value to pass given that the animation is going to run over |duration| seconds. The longer the animation, the more precision is needed in the timing function result to avoid ugly discontinuities.
function solveEpsilon(duration) {return 1.0/(200.0*duration);};
function solve(x,epsilon) {return sampleCurveY(solveCurveX(x,epsilon));};
// Given an x value, find a parametric value it came from.
function solveCurveX(x,epsilon) {var t0,t1,t2,x2,d2,i;
function fabs(n) {if(n>=0) {return n;}else {return 0-n;}};
// First try a few iterations of Newton's method -- normally very fast.
for(t2=x, i=0; i<8; i++) {x2=sampleCurveX(t2)-x; if(fabs(x2)<epsilon) {return t2;} d2=sampleCurveDerivativeX(t2); if(fabs(d2)<1e-6) {break;} t2=t2-x2/d2;}
// Fall back to the bisection method for reliability.
t0=0.0; t1=1.0; t2=x; if(t2<t0) {return t0;} if(t2>t1) {return t1;}
while(t0<t1) {x2=sampleCurveX(t2); if(fabs(x2-x)<epsilon) {return t2;} if(x>x2) {t0=t2;}else {t1=t2;} t2=(t1-t0)*.5+t0;}
return t2; // Failure.
};
// Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
cx=3.0*p1x; bx=3.0*(p2x-p1x)-cx; ax=1.0-cx-bx; cy=3.0*p1y; by=3.0*(p2y-p1y)-cy; ay=1.0-cy-by;
// Convert from input time to parametric value in curve, then from that to output time.
return solve(t, solveEpsilon(duration));
};
+603 -227
View File
File diff suppressed because it is too large Load Diff
+675
View File
@@ -0,0 +1,675 @@
/*
* CPArrayController.j
* AppKit
*
* Adapted from Cocotron, by Johannes Fortmann
*
* Created by Ross Boucher.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPIndexSet.j>
@import "CPObjectController.j"
@import "CPKeyValueBinding.j"
@implementation CPArrayController : CPObjectController
{
BOOL _avoidsEmptySelection;
BOOL _clearsFilterPredicateOnInsertion;
BOOL _filterRestrictsInsertion;
BOOL _preservesSelection;
BOOL _selectsInsertedObjects;
BOOL _alwaysUsesMultipleValuesMarker;
id _selectionIndexes;
id _sortDescriptors;
id _filterPredicate;
id _arrangedObjects;
}
+ (void)initialize
{
if (self !== [CPArrayController class])
return;
[self exposeBinding:@"contentArray"];
[self exposeBinding:@"contentSet"];
}
+ (CPSet)keyPathsForValuesAffectingContentArray
{
return [CPSet setWithObjects:"content"];
}
+ (CPSet)keyPathsForValuesAffectingArrangedObjects
{
return [CPSet setWithObjects:"content", "filterPredicate", "sortDescriptors"];
}
+ (CPSet)keyPathsForValuesAffectingSelection
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingSelectionIndex
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingSelectionIndexes
{
// When the arranged objects change, selection preservation may cause the indexes
// to change.
return [CPSet setWithObjects:"arrangedObjects"];
}
+ (CPSet)keyPathsForValuesAffectingSelectedObjects
{
// Don't need to depend on arrangedObjects here because selectionIndexes already does.
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanRemove
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanSelectNext
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanSelectPrevious
{
return [CPSet setWithObjects:"selectionIndexes"];
}
- (id)init
{
self = [super init];
if (self)
{
_selectionIndexes = [CPIndexSet indexSet];
}
return self;
}
- (void)prepareContent
{
[self _setContentArray:[[self newObject]]];
}
- (BOOL)preservesSelection
{
return _preservesSelection;
}
- (void)setPreservesSelection:(BOOL)value
{
_preservesSelection = value;
}
- (BOOL)selectsInsertedObjects
{
return _selectsInsertedObjects;
}
- (void)setSelectsInsertedObjects:(BOOL)value
{
_selectsInsertedObjects = value;
}
- (BOOL)avoidsEmptySelection
{
return _avoidsEmptySelection;
}
- (void)setAvoidsEmptySelection:(BOOL)value
{
_avoidsEmptySelection = value;
}
- (void)setContent:(id)value
{
if (value === nil)
value = [];
if (![value isKindOfClass:[CPArray class]])
value = [value];
var oldSelectedObjects = nil,
oldSelectionIndexes = nil;
if ([self preservesSelection])
oldSelectedObjects = [self selectedObjects];
else
oldSelectionIndexes = [self selectionIndexes];
/*
When the contents are changed, the selected indexes may no longer refer to the
same items. This would cause problems when setSelectedObjects is called below.
Any KVO observation would try to retrieve the 'before' value which could be
wrong or even throw an exception for no longer existing indexes.
To avoid that, use the internal __setSelectedObjects which fires no notifications.
The selectionIndexes notifications will fire later since they depend on the
content key. This pattern is also applied for many other methods throughout this
class.
*/
if (_clearsFilterPredicateOnInsertion)
[self willChangeValueForKey:@"filterPredicate"];
// Don't use [super setContent:] as that would fire the contentObject change.
// We need to be in control of when notifications fire.
_contentObject = value;
if (_clearsFilterPredicateOnInsertion)
[self __setFilterPredicate:nil]; // Causes a _rearrangeObjects.
else
[self _rearrangeObjects];
if ([self preservesSelection])
[self __setSelectedObjects:oldSelectedObjects];
else
[self __setSelectionIndexes:oldSelectionIndexes];
if (_clearsFilterPredicateOnInsertion)
[self didChangeValueForKey:@"filterPredicate"];
}
- (void)_setContentArray:(id)anArray
{
[self setContent:anArray];
}
- (void)_setContentSet:(id)aSet
{
[self setContent:aSet];
}
- (id)contentArray
{
return [self content];
}
- (id)contentSet
{
return [self content];
}
- (CPArray)arrangeObjects:(CPArray)objects
{
var filterPredicate = [self filterPredicate],
sortDescriptors = [self sortDescriptors];
if (filterPredicate && sortDescriptors)
{
var sortedObjects = [objects filteredArrayUsingPredicate:filterPredicate];
[sortedObjects sortUsingDescriptors:sortDescriptors];
return sortedObjects;
}
else if (filterPredicate)
return [objects filteredArrayUsingPredicate:filterPredicate];
else if (sortDescriptors)
return [objects sortedArrayUsingDescriptors:sortDescriptors];
return [objects copy];
}
- (void)rearrangeObjects
{
[self willChangeValueForKey:@"arrangedObjects"];
[self _rearrangeObjects];
[self didChangeValueForKey:@"arrangedObjects"];
}
/*
Like rearrangeObjects but don't fire any change notifications.
@ignore
*/
- (void)_rearrangeObjects
{
/*
Rearranging reapplies the selection criteria and may cause objects to disappear,
so take care of the selection.
*/
var oldSelectedObjects = nil,
oldSelectionIndexes = nil;
if ([self preservesSelection])
oldSelectedObjects = [self selectedObjects];
else
oldSelectionIndexes = [self selectionIndexes];
[self __setArrangedObjects:[self arrangeObjects:[self contentArray]]];
if ([self preservesSelection])
[self __setSelectedObjects:oldSelectedObjects];
else
[self __setSelectionIndexes:oldSelectionIndexes];
}
- (void)__setArrangedObjects:(id)value
{
if (_arrangedObjects === value)
return;
_arrangedObjects = [[_CPObservableArray alloc] initWithArray:value];
}
- (id)arrangedObjects
{
return _arrangedObjects;
}
- (CPArray)sortDescriptors
{
return _sortDescriptors;
}
- (void)setSortDescriptors:(CPArray)value
{
if (_sortDescriptors === value)
return;
_sortDescriptors = [value copy];
// Use the non-notification version since arrangedObjects already depends
// on sortDescriptors.
[self _rearrangeObjects];
}
- (CPPredicate)filterPredicate
{
return _filterPredicate;
}
- (void)setFilterPredicate:(CPPredicate)value
{
[self __setFilterPredicate:value];
}
/*
Like setFilterPredicate but don't fire any change notifications.
@ignore
*/
- (void)__setFilterPredicate:(CPPredicate)value
{
if (_filterPredicate === value)
return;
_filterPredicate = value;
// Use the non-notification version since arrangedObjects already depends
// on filterPredicate.
[self _rearrangeObjects];
}
- (BOOL)alwaysUsesMultipleValuesMarker
{
return _alwaysUsesMultipleValuesMarker;
}
//Selection
- (unsigned)selectionIndex
{
return [_selectionIndexes firstIndex];
}
- (BOOL)setSelectionIndex:(unsigned)index
{
return [self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
- (CPIndexSet)selectionIndexes
{
return _selectionIndexes;
}
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
{
[self _selectionWillChange]
[self __setSelectionIndexes:indexes];
[self _selectionDidChange];
}
/*
Like setSelectionIndex but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectionIndex:(int)theIndex
{
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:theIndex]];
}
/*
Like setSelectionIndexes but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes
{
if (!indexes)
indexes = [CPIndexSet indexSet];
if (![indexes count])
{
if (_avoidsEmptySelection && [[self arrangedObjects] count])
indexes = [CPIndexSet indexSetWithIndex:0];
}
else
{
var objectsCount = [[self arrangedObjects] count];
// Remove out of bounds indexes.
[indexes removeIndexesInRange:CPMakeRange(objectsCount, [indexes lastIndex] + 1)];
// When avoiding empty selection and the deleted selection was at the bottom, select the last item.
if (![indexes count] && _avoidsEmptySelection && objectsCount)
indexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
}
if ([_selectionIndexes isEqualToIndexSet:indexes])
return NO;
_selectionIndexes = [indexes copy];
// Push back the new selection to the model for selectionIndexes if we have one.
// There won't be an infinite loop because of the equality check above.
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
return YES;
}
- (CPArray)selectedObjects
{
var objects = [[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]];
return [_CPObservableArray arrayWithArray:(objects || [])];
}
- (BOOL)setSelectedObjects:(CPArray)objects
{
[self willChangeValueForKey:@"selectionIndexes"];
[self _selectionWillChange];
[self __setSelectedObjects:objects];
[self didChangeValueForKey:@"selectionIndexes"];
[self _selectionDidChange];
}
/*
Like setSelectedObjects but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectedObjects:(CPArray)objects
{
var set = [CPIndexSet indexSet],
count = [objects count],
arrangedObjects = [self arrangedObjects];
for (var i = 0; i < count; i++)
{
var index = [arrangedObjects indexOfObject:[objects objectAtIndex:i]];
if (index !== CPNotFound)
[set addIndex:index];
}
[self __setSelectionIndexes:set];
return YES;
}
//Moving selection
- (BOOL)canSelectPrevious
{
return [[self selectionIndexes] firstIndex] > 0
}
- (void)selectPrevious:(id)sender
{
var index = [[self selectionIndexes] firstIndex] - 1;
if (index >= 0)
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
- (BOOL)canSelectNext
{
return [[self selectionIndexes] firstIndex] < [[self arrangedObjects] count] - 1;
}
- (void)selectNext:(id)sender
{
var index = [[self selectionIndexes] firstIndex] + 1;
if (index < [[self arrangedObjects] count])
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
//Add/Remove
- (void)addObject:(id)object
{
if (![self canAdd])
return;
if (_clearsFilterPredicateOnInsertion)
[self willChangeValueForKey:@"filterPredicate"];
[self willChangeValueForKey:@"content"];
[_contentObject addObject:object];
if (_clearsFilterPredicateOnInsertion)
[self __setFilterPredicate:nil];
if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
{
var pos = [_arrangedObjects insertObject:object inArraySortedByDescriptors:_sortDescriptors];
// selectionIndexes change notification will be fired as a result of the
// content change. Don't fire manually.
if (_selectsInsertedObjects)
[self __setSelectionIndex:pos];
else
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:1];
}
else
[self _rearrangeObjects];
[self didChangeValueForKey:@"content"];
if (_clearsFilterPredicateOnInsertion)
[self didChangeValueForKey:@"filterPredicate"];
}
- (void)insertObject:(id)anObject atArrangedObjectIndex:(int)anIndex
{
if (![self canAdd])
return;
if (_clearsFilterPredicateOnInsertion)
[self willChangeValueForKey:@"filterPredicate"];
[self willChangeValueForKey:@"content"];
[_contentObject insertObject:anObject atIndex:anIndex];
if (_clearsFilterPredicateOnInsertion)
[self __setFilterPredicate:nil];
[[self arrangedObjects] insertObject:anObject atIndex:anIndex];
// selectionIndexes change notification will be fired as a result of the
// content change. Don't fire manually.
if ([self selectsInsertedObjects])
[self __setSelectionIndex:anIndex];
else
[[self selectionIndexes] shiftIndexesStartingAtIndex:anIndex by:1];
if ([self avoidsEmptySelection] && [[self selectionIndexes] count] <= 0 && [_contentObject count] > 0)
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:0]];
[self didChangeValueForKey:@"content"];
if (_clearsFilterPredicateOnInsertion)
[self didChangeValueForKey:@"filterPredicate"];
}
- (void)removeObject:(id)object
{
if (![self canRemove])
return;
[self willChangeValueForKey:@"content"];
[_contentObject removeObject:object];
if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
{
// selectionIndexes change notification will be fired as a result of the
// content change. Don't fire manually.
var pos = [_arrangedObjects indexOfObject:object];
[_arrangedObjects removeObjectAtIndex:pos];
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:-1];
}
[self didChangeValueForKey:@"content"];
}
- (void)add:(id)sender
{
if (![self canAdd])
return;
[self insert:sender];
}
- (void)insert:(id)sender
{
if (![self canInsert])
return;
var newObject = [self automaticallyPreparesContent] ? [self newObject] : [self _defaultNewObject];
[self addObject:newObject];
}
- (void)remove:(id)sender
{
[self removeObjects:[[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]]];
}
- (void)removeObjectsAtArrangedObjectIndexes:(CPIndexSet)indexes
{
[self _removeObjects:[[self arrangedObjects] objectsAtIndexes:indexes]];
}
- (void)addObjects:(CPArray)objects
{
if (![self canAdd])
return;
var contentArray = [self contentArray],
count = [objects count];
for (var i = 0; i < count; i++)
[contentArray addObject:[objects objectAtIndex:i]];
[self setContent:contentArray];
}
- (void)removeObjects:(CPArray)objects
{
if (![self canRemove])
return;
[self _removeObjects:objects];
}
- (void)_removeObjects:(CPArray)objects
{
[self willChangeValueForKey:@"content"];
[_contentObject removeObjectsInArray:objects];
var arrangedObjects = [self arrangedObjects],
position = [arrangedObjects indexOfObject:[objects objectAtIndex:0]];
[arrangedObjects removeObjectsInArray:objects];
var objectsCount = [arrangedObjects count],
selectionIndexes = [CPIndexSet indexSet];
if ([self preservesSelection] || [self avoidsEmptySelection])
{
selectionIndexes = [CPIndexSet indexSetWithIndex:position];
// Remove the selection if there are no objects
if (objectsCount <= 0)
selectionIndexes = [CPIndexSet indexSet];
// Shift selection to last object if position is out of bounds
else if (position >= objectsCount)
selectionIndexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
}
_selectionIndexes = selectionIndexes;
[self didChangeValueForKey:@"content"];
}
- (BOOL)canInsert
{
return [self isEditable];
}
@end
@implementation CPArrayController (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:coder];
if (self)
{
_avoidsEmptySelection = [coder decodeBoolForKey:@"CPArrayControllerAvoidsEmptySelection"];
_clearsFilterPredicateOnInsertion = [coder decodeBoolForKey:@"CPClearsFilterPredicateOnInsertion"];
_filterRestrictsInsertion = [coder decodeBoolForKey:@"CPArrayControllerFilterRestrictsInsertion"];
_preservesSelection = [coder decodeBoolForKey:@"CPArrayControllerPreservesSelection"];
_selectsInsertedObjects = [coder decodeBoolForKey:@"CPArrayControllerSelectsInsertedObjects"];
_alwaysUsesMultipleValuesMarker = [coder decodeBoolForKey:@"CPArrayControllerAlwaysUsesMultipleValuesMarker"];
if ([self automaticallyPreparesContent])
[self prepareContent];
else
[self _setContentArray:[]];
}
return self;
}
- (void)awakeFromCib
{
[self _selectionWillChange];
[self _selectionDidChange];
}
@end
+97 -19
View File
@@ -4,7 +4,7 @@
* Created by Ross Boucher.
* Copyright 2009, 280 North, Inc.
*
* Adapted from Kevin Wojniak, portions Copyright 2009 Kevin Wojniak.
* Adapted from Kevin Wojniak, portions Copyright 2009 Kevin Wojniak.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,26 +20,27 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright 2009 280 North, Inc.
*/
@import <AppKit/CPGraphicsContext.j>
@import <Foundation/CPObject.j>
@import "CPGraphicsContext.j"
// Class defaults
var DefaultLineWidth = 1.0;
/*!
/*!
@ingroup appkit
@class CPBezierPath
A CPBezierPath allows you to create paths for drawing to the screen using a simpler API than CoreGraphics.
Paths can form any shape, including regular polgyons like squares and triangles; circles, arcs; or complex
line segments.
line segments.
A path can be stroked and filled using the relevant method. The currently active fill and stroke color will
be used, which can be set by calling setFill: and setStroke: on any CPColor object (or set: for both).
*/
@@ -50,52 +51,76 @@ var DefaultLineWidth = 1.0;
float _lineWidth;
}
/*!
Create a new CPBezierPath object.
*/
+ (CPBezierPath)bezierPath
{
return [[[self class] alloc] init];
return [[self alloc] init];
}
/*!
Create a new CPBezierPath object initialized with an oval path drawn within a rectangular path.
*/
+ (CPBezierPath)bezierPathWithOvalInRect:(CGRect)rect
{
var path = [[self class] bezierPath];
var path = [self bezierPath];
[path appendBezierPathWithOvalInRect:rect];
return path;
}
/*!
Create a new CPBezierPath object initialized with a rectangular path.
*/
+ (CPBezierPath)bezierPathWithRect:(CGRect)rect
{
var path = [[self class] bezierPath];
var path = [self bezierPath];
[path appendBezierPathWithRect:rect];
return path;
}
/*!
Get default line width.
*/
+ (float)defaultLineWidth
{
return DefaultLineWidth;
}
/*!
Set default line width.
*/
+ (void)setDefaultLineWidth:(float)width
{
DefaultLineWidth = width;
}
+ (void)fillRect:(CGRect)rect
/*!
Fill rectangular path with current fill color.
*/
+ (void)fillRect:(CGRect)aRect
{
[[[self class] bezierPathWithRect:rect] fill];
[[self bezierPathWithRect:aRect] fill];
}
+ (void)strokeRect:(CGRect)rect
/*!
Using the current stroke color and default drawing attributes, strokes a counterclockwise path beginning at the rectangle's origin.
*/
+ (void)strokeRect:(CGRect)aRect
{
[[[self class] bezierPathWithRect:rect] stroke];
[[self bezierPathWithRect:aRect] stroke];
}
/*!
Using the current stroke color and default drawing attributes, strokes a line between two points.
*/
+ (void)strokeLineFromPoint:(CGPoint)point1 toPoint:(CGPoint)point2
{
var path = [[self class] bezierPath];
var path = [self bezierPath];
[path moveToPoint:point1];
[path lineToPoint:point2];
@@ -103,6 +128,9 @@ var DefaultLineWidth = 1.0;
[path stroke];
}
/*!
Create a new CPBezierPath object using the default line width.
*/
- (id)init
{
if (self = [super init])
@@ -114,26 +142,41 @@ var DefaultLineWidth = 1.0;
return self;
}
/*!
Moves the current point to another location.
*/
- (void)moveToPoint:(CGPoint)point
{
CGPathMoveToPoint(_path, nil, point.x, point.y);
}
/*!
Append a straight line to the path.
*/
- (void)lineToPoint:(CGPoint)point
{
CGPathAddLineToPoint(_path, nil, point.x, point.y);
}
/*!
Add a cubic Bezier curve to the path.
*/
- (void)curveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
{
CGPathAddCurveToPoint(_path, nil, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y);
}
/*!
Create a line segment between the first and last points in the subpath, closing it.
*/
- (void)closePath
{
CGPathCloseSubpath(_path);
}
/*!
Draw a line along the path with the current stroke color and default drawing attributes.
*/
- (void)stroke
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
@@ -145,6 +188,9 @@ var DefaultLineWidth = 1.0;
CGContextStrokePath(ctx);
}
/*!
Fill the path with the current fill color.
*/
- (void)fill
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
@@ -156,56 +202,88 @@ var DefaultLineWidth = 1.0;
CGContextFillPath(ctx);
}
/*!
Get the line width.
*/
- (float)lineWidth
{
return _lineWidth;
}
/*!
Set the line width.
*/
- (void)setLineWidth:(float)lineWidth
{
_lineWidth = lineWidth;
}
/*!
Get the total number of elements.
*/
- (unsigned)elementCount
{
return _path.count;
}
/*!
Check if receiver is empty, returns appropriate Boolean value.
*/
- (BOOL)isEmpty
{
return CGPathIsEmpty(_path);
}
/*!
Get the current point.
*/
- (CGPoint)currentPoint
{
return CGPathGetCurrentPoint(_path);
}
/*!
Append a series of line segments.
*/
- (void)appendBezierPathWithPoints:(CPArray)points count:(unsigned)count
{
CGPathAddLines(_path, nil, points, count);
}
/*!
Append a rectangular path.
*/
- (void)appendBezierPathWithRect:(CGRect)rect
{
CGPathAddRect(_path, nil, rect);
}
/*!
Append an oval path; oval is drawn within the rectangular path.
*/
- (void)appendBezierPathWithOvalInRect:(CGRect)rect
{
CGPathAddPath(_path, nil, CGPathWithEllipseInRect(rect));
}
/*!
Append a rounded rectangular path.
*/
- (void)appendBezierPathWithRoundedRect:(CGRect)rect xRadius:(float)xRadius yRadius:(float)yRadius
{
CGPathAddPath(_path, nil, CGPathWithRoundedRectangleInRect(rect, xRadius, yRadius, YES, YES, YES, YES));
}
/*!
Append the contents of a CPBezierPath object.
*/
- (void)appendBezierPath:(NSBezierPath *)other
{
CGPathAddPath(_path, nil, other._path);
}
/*!
Remove all path elements; clears path.
*/
- (void)removeAllPoints
{
_path = CGPathCreateMutable();
+368
View File
@@ -0,0 +1,368 @@
/*
* CPBox.j
* AppKit
*
* Created by Ross Boucher.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPView.j"
// CPBoxType
CPBoxPrimary = 0;
CPBoxSecondary = 1;
CPBoxSeperator = 2;
CPBoxOldStyle = 3;
CPBoxCustom = 4;
// CPBorderType
CPNoBorder = 0;
CPLineBorder = 1;
CPBezelBorder = 2;
CPGrooveBorder = 3;
@implementation CPBox : CPView
{
CPBoxType _boxType;
CPBorderType _borderType;
CPColor _borderColor;
CPColor _fillColor;
float _cornerRadius;
float _borderWidth;
CPSize _contentMargin;
CPView _contentView;
}
+ (id)boxEnclosingView:(CPView)aView
{
var box = [[self alloc] initWithFrame:CGRectMakeZero()],
enclosingView = [aView superview];
[box setFrameFromContentFrame:[aView frame]];
[enclosingView replaceSubview:aView with:box];
[box setContentView:aView];
return box;
}
- (id)initWithFrame:(CPRect)frameRect
{
self = [super initWithFrame:frameRect];
if (self)
{
_borderType = CPBezelBorder;
_fillColor = [CPColor clearColor];
_borderColor = [CPColor blackColor];
_borderWidth = 1.0;
_contentMargin = CGSizeMake(0.0, 0.0);
_contentView = [[CPView alloc] initWithFrame:[self bounds]];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self setAutoresizesSubviews:YES];
[self addSubview:_contentView];
}
return self;
}
// Configuring Boxes
- (CPRect)borderRect
{
return [self bounds];
}
- (CPBorderType)borderType
{
return _borderType;
}
- (void)setBorderType:(CPBorderType)aBorderType
{
if (_borderType === aBorderType)
return;
_borderType = aBorderType;
[self setNeedsDisplay:YES];
}
- (CPBoxType)boxType
{
return _boxType;
}
- (void)setBoxType:(CPBoxType)aBoxType
{
if (_boxType === aBoxType)
return;
_boxType = aBoxType;
[self setNeedsDisplay:YES];
}
- (CPColor)borderColor
{
return _borderColor;
}
- (void)setBorderColor:(CPColor)color
{
if ([color isEqual:_borderColor])
return;
_borderColor = color;
[self setNeedsDisplay:YES];
}
- (float)borderWidth
{
return _borderWidth;
}
- (void)setBorderWidth:(float)width
{
if (width === _borderWidth)
return;
_borderWidth = width;
[self setNeedsDisplay:YES];
}
- (float)cornerRadius
{
return _cornerRadius;
}
- (void)setCornerRadius:(float)radius
{
if (radius === _cornerRadius)
return;
_cornerRadius = radius;
[self setNeedsDisplay:YES];
}
- (CPColor)fillColor
{
return _fillColor;
}
- (void)setFillColor:(CPColor)color
{
if ([color isEqual:_fillColor])
return;
_fillColor = color;
[self setNeedsDisplay:YES];
}
- (CPView)contentView
{
return _contentView;
}
- (void)setContentView:(CPView)aView
{
if (aView === _contentView)
return;
[aView setFrame:CGRectInset([self bounds], _contentMargin.width + _borderWidth, _contentMargin.height + _borderWidth)];
[aView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self replaceSubview:_contentView with:aView];
_contentView = aView;
}
- (CPSize)contentViewMargins
{
return _contentMargin;
}
- (void)setContentViewMargins:(CPSize)size
{
if (size.width < 0 || size.height < 0)
[CPException raise:CPGenericException reason:@"Margins must be positive"];
_contentMargin = CGSizeMakeCopy(size);
[self setNeedsDisplay:YES];
}
- (void)setFrameFromContentFrame:(CPRect)aRect
{
[self setFrame:CGRectInset(aRect, -(_contentMargin.width + _borderWidth), -(_contentMargin.height + _borderWidth))];
[self setNeedsDisplay:YES];
}
- (void)sizeToFit
{
var contentFrame = [_contentView frame];
[self setFrameSize:CGSizeMake(contentFrame.size.width + _contentMargin.width * 2,
contentFrame.size.height + _contentMargin.height * 2)];
[_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height)];
}
- (void)drawRect:(CPRect)rect
{
if (_borderType === CPNoBorder)
return;
var bounds = [self bounds];
switch (_boxType)
{
case CPBoxSeperator:
// NSBox does not include a horitontal flag for the seperator type. We have to determine
// the type of seperator to draw by the width and height of the frame.
if (CGRectGetWidth(bounds) === 5.0)
return [self _drawVerticalSeperatorInRect:bounds];
else if (CGRectGetHeight(bounds) === 5.0)
return [self _drawHorizontalSeperatorInRect:bounds];
break;
}
switch (_borderType)
{
case CPBezelBorder:
[self _drawBezelBorderInRect:bounds];
break;
default:
case CPLineBorder:
[self _drawLineBorderInRect:bounds];
break;
}
}
- (void)_drawHorizontalSeperatorInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, CGRectGetWidth(aRect), CGRectGetMinY(aRect));
CGContextStrokePath(context);
}
- (void)_drawVerticalSeperatorInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, CGRectGetMinX(aRect), CGRectGetHeight(aRect));
CGContextStrokePath(context);
}
- (void)_drawBezelBorderInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
sides = [CPMinYEdge, CPMaxXEdge, CPMaxYEdge, CPMinXEdge],
sideGray = 190.0 / 255.0,
grays = [142.0 / 255.0, sideGray, sideGray, sideGray],
borderWidth = _borderWidth;
while (borderWidth--)
aRect = CPDrawTiledRects(aRect, aRect, sides, grays);
CGContextSetFillColor(context, [self fillColor]);
CGContextFillRect(context, aRect);
}
- (void)_drawLineBorderInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
aRect = CGRectInset(aRect, _borderWidth / 2.0, _borderWidth / 2.0);
CGContextSetFillColor(context, [self fillColor]);
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, _borderWidth);
CGContextFillRoundedRectangleInRect(context, aRect, _cornerRadius, YES, YES, YES, YES);
CGContextStrokeRoundedRectangleInRect(context, aRect, _cornerRadius, YES, YES, YES, YES);
}
@end
var CPBoxTypeKey = @"CPBoxTypeKey",
CPBoxBorderTypeKey = @"CPBoxBorderTypeKey",
CPBoxBorderColorKey = @"CPBoxBorderColorKey",
CPBoxFillColorKey = @"CPBoxFillColorKey",
CPBoxCornerRadiusKey = @"CPBoxCornerRadiusKey",
CPBoxBorderWidthKey = @"CPBoxBorderWidthKey",
CPBoxContentMarginKey = @"CPBoxContentMarginKey";
@implementation CPBox (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_boxType = [aCoder decodeIntForKey:CPBoxTypeKey];
_borderType = [aCoder decodeIntForKey:CPBoxBorderTypeKey];
_borderColor = [aCoder decodeObjectForKey:CPBoxBorderColorKey];
_fillColor = [aCoder decodeObjectForKey:CPBoxFillColorKey];
_cornerRadius = [aCoder decodeFloatForKey:CPBoxCornerRadiusKey];
_borderWidth = [aCoder decodeFloatForKey:CPBoxBorderWidthKey];
_contentMargin = [aCoder decodeSizeForKey:CPBoxContentMarginKey];
_contentView = [self subviews][0];
[self setAutoresizesSubviews:YES];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeInt:_boxType forKey:CPBoxTypeKey];
[aCoder encodeInt:_borderType forKey:CPBoxBorderTypeKey];
[aCoder encodeObject:_borderColor forKey:CPBoxBorderColorKey];
[aCoder encodeObject:_fillColor forKey:CPBoxFillColorKey];
[aCoder encodeFloat:_cornerRadius forKey:CPBoxCornerRadiusKey];
[aCoder encodeFloat:_borderWidth forKey:CPBoxBorderWidthKey];
[aCoder encodeSize:_contentMargin forKey:CPBoxContentMarginKey];
}
@end
+955
View File
@@ -0,0 +1,955 @@
/*
* CPBrowser.j
* AppKit
*
* Created by Ross Boucher.
* Copyright 2010, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPIndexSet.j>
@import "CPControl.j"
@import "CPImage.j"
@import "CPTableView.j"
@import "CPTextField.j"
@import "CPScrollView.j"
/*!
@ingroup appkit
@class CPBrowser
*/
@implementation CPBrowser : CPControl
{
id _delegate;
CPString _pathSeparator;
CPView _contentView;
CPScrollView _horizontalScrollView;
CPView _prototypeView;
CPArray _tableViews;
CPArray _tableDelegates;
id _rootItem;
BOOL _delegateSupportsImages;
SEL _doubleAction @accessors(property=doubleAction);
BOOL _allowsMultipleSelection;
BOOL _allowsEmptySelection;
Class _tableViewClass @accessors(property=tableViewClass);
float _rowHeight;
float _imageWidth;
float _leafWidth;
float _minColumnWidth;
float _defaultColumnWidth @accessors(property=defaultColumnWidth);
CPArray _columnWidths;
}
+ (CPImage)branchImage
{
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPBrowser class]]
pathForResource:"browser-leaf.png"]
size:CGSizeMake(9,9)];
}
+ (CPImage)highlightedBranchImage
{
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPBrowser class]]
pathForResource:"browser-leaf-highlighted.png"]
size:CGSizeMake(9,9)];
}
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
_rowHeight = 23.0;
_defaultColumnWidth = 140.0;
_minColumnWidth = 80.0;
_imageWidth = 23.0;
_leafWidth = 13.0;
_columnWidths = [];
_pathSeparator = "/";
_tableViews = [];
_tableDelegates = [];
_allowsMultipleSelection = YES;
_allowsEmptySelection = YES;
_tableViewClass = [_CPBrowserTableView class];
_prototypeView = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_prototypeView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_prototypeView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateSelectedDataView];
[_prototypeView setLineBreakMode:CPLineBreakByTruncatingTail];
_horizontalScrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
[_horizontalScrollView setHasVerticalScroller:NO];
[_horizontalScrollView setAutohidesScrollers:YES];
[_horizontalScrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_contentView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 0, CGRectGetHeight([self bounds]))];
[_contentView setAutoresizingMask:CPViewHeightSizable];
[_horizontalScrollView setDocumentView:_contentView];
[self addSubview:_horizontalScrollView];
}
return self;
}
- (void)setPrototypeView:(CPView)aPrototypeView
{
_prototypeView = [CPKeyedUnarchiver unarchiveObjectWithData:
[CPKeyedArchiver archivedDataWithRootObject:aPrototypeView]];
}
- (CPView)prototypeView
{
return [CPKeyedUnarchiver unarchiveObjectWithData:
[CPKeyedArchiver archivedDataWithRootObject:_prototypeView]];
}
- (void)setDelegate:(id)anObject
{
_delegate = anObject;
_delegateSupportsImages = [_delegate respondsToSelector:@selector(browser:imageValueForItem:)];
[self loadColumnZero];
}
- (id)delegate
{
return _delegate;
}
- (CPTableView)tableViewInColumn:(unsigned)index
{
return _tableViews[index];
}
- (unsigned)columnOfTableView:(CPTableView)aTableView
{
return [_tableViews indexOfObject:aTableView];
}
- (void)loadColumnZero
{
if ([_delegate respondsToSelector:@selector(rootItemForBrowser:)])
_rootItem = [_delegate rootItemForBrowser:self];
else
_rootItem = nil;
[self setLastColumn:-1];
[self addColumn];
}
- (void)setLastColumn:(int)columnIndex
{
if (columnIndex >= _tableViews.length)
return;
var oldValue = _tableViews.length - 1,
indexPlusOne = columnIndex + 1; // unloads all later columns.
[[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
_tableViews = _tableViews.slice(0, indexPlusOne);
_tableDelegates = _tableDelegates.slice(0, indexPlusOne);
if ([_delegate respondsToSelector:@selector(browser:didChangeLastColumn:toColumn:)])
[_delegate browser:self didChangeLastColumn:oldValue toColumn:columnIndex];
[self tile];
}
- (int)lastColumn
{
return _tableViews.length - 1;
}
- (void)addColumn
{
var lastIndex = [self lastColumn],
lastColumn = _tableViews[lastIndex],
selectionIndexes = [lastColumn selectedRowIndexes];
if (lastIndex >= 0 && [selectionIndexes count] > 1)
[CPException raise:CPInvalidArgumentException
reason:"Can't add column, column "+lastIndex+" has invalid selection."];
var index = lastIndex + 1,
item = index === 0 ? _rootItem : [_tableDelegates[lastIndex] childAtIndex:[selectionIndexes firstIndex]];
if (index > 0 && item && [self isLeafItem:item])
return;
var table = [[_tableViewClass alloc] initWithFrame:CGRectMakeZero() browser:self];
[table setHeaderView:nil];
[table setCornerView:nil];
[table setAllowsMultipleSelection:_allowsMultipleSelection];
[table setAllowsEmptySelection:_allowsEmptySelection];
[table registerForDraggedTypes:[self registeredDraggedTypes]];
[self _addTableColumnsToTableView:table forColumnIndex:index];
var delegate = [[_CPBrowserTableDelegate alloc] init];
[delegate _setDelegate:_delegate];
[delegate _setBrowser:self];
[delegate _setIndex:index];
[delegate _setItem:item];
_tableViews[index] = table;
_tableDelegates[index] = delegate;
[table setDelegate:delegate];
[table setDataSource:delegate];
[table setTarget:delegate];
[table setAction:@selector(_tableViewClicked:)];
[table setDoubleAction:@selector(_tableViewDoubleClicked:)];
[table setDraggingDestinationFeedbackStyle:CPTableViewDraggingDestinationFeedbackStyleRegular];
var scrollView = [[_CPBrowserScrollView alloc] initWithFrame:CGRectMakeZero()];
[scrollView _setBrowser:self];
[scrollView setDocumentView:table];
[scrollView setHasHorizontalScroller:NO];
[scrollView setAutoresizingMask:CPViewHeightSizable];
[_contentView addSubview:scrollView];
[self tile];
[self scrollColumnToVisible:index];
}
- (void)_addTableColumnsToTableView:(CPTableView)aTableView forColumnIndex:(unsigned)index
{
if (_delegateSupportsImages)
{
var column = [[CPTableColumn alloc] initWithIdentifier:@"Image"],
view = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
[view setImageScaling:CPScaleProportionally];
[column setDataView:view];
[column setResizingMask:CPTableColumnNoResizing];
[aTableView addTableColumn:column];
}
var column = [[CPTableColumn alloc] initWithIdentifier:@"Content"];
[column setDataView:_prototypeView];
[column setResizingMask:CPTableColumnNoResizing];
[aTableView addTableColumn:column];
var column = [[CPTableColumn alloc] initWithIdentifier:@"Leaf"],
view = [[_CPBrowserLeafView alloc] initWithFrame:CGRectMakeZero()];
[view setBranchImage:[[self class] branchImage]];
[view setHighlightedBranchImage:[[self class] highlightedBranchImage]];
[column setDataView:view];
[column setResizingMask:CPTableColumnNoResizing];
[aTableView addTableColumn:column];
}
- (void)reloadColumn:(int)column
{
[[self tableViewInColumn:column] reloadData];
}
- (void)tile
{
var xOrigin = 0,
scrollerWidth = [CPScroller scrollerWidth],
height = CGRectGetHeight([_contentView bounds]);
for (var i = 0, count = _tableViews.length; i < count; i++)
{
var tableView = _tableViews[i],
scrollView = [tableView enclosingScrollView],
width = [self widthOfColumn:i],
tableHeight = CGRectGetHeight([tableView bounds]);
[[tableView tableColumnWithIdentifier:"Image"] setWidth:_imageWidth];
[[tableView tableColumnWithIdentifier:"Content"] setWidth:width - (_leafWidth + _delegateSupportsImages ? _imageWidth : 0) - scrollerWidth - scrollerWidth];
[[tableView tableColumnWithIdentifier:"Leaf"] setWidth:_leafWidth];
[tableView setRowHeight:_rowHeight];
[tableView setFrameSize:CGSizeMake(width - scrollerWidth, tableHeight)];
[scrollView setFrameOrigin:CGPointMake(xOrigin, 0)];
[scrollView setFrameSize:CGSizeMake(width, height)];
xOrigin += width;
}
[_contentView setFrameSize:CGSizeMake(xOrigin, height)];
}
- (unsigned)rowAtPoint:(CGPoint)aPoint
{
var column = [self columnAtPoint:aPoint];
if (column === -1)
return -1;
var tableView = _tableViews[column];
return [tableView rowAtPoint:[tableView convertPoint:aPoint fromView:self]];
}
- (unsigned)columnAtPoint:(CGPoint)aPoint
{
var adjustedPoint = [_contentView convertPoint:aPoint fromView:self];
for (var i = 0, count = _tableViews.length; i < count; i++)
{
var frame = [[_tableViews[i] enclosingScrollView] frame];
if (CGRectContainsPoint(frame, adjustedPoint))
return i;
}
return -1;
}
- (CGRect)rectOfRow:(unsigned)aRow inColumn:(unsigned)aColumn
{
var tableView = _tableViews[aColumn],
rect = [tableView rectOfRow:aRow];
rect.origin = [self convertPoint:rect.origin fromView:tableView];
return rect;
}
// ITEMS
- (id)itemAtRow:(int)row inColumn:(int)column
{
return [_tableDelegates[column] childAtIndex:row];
}
- (BOOL)isLeafItem:(id)item
{
return [_delegate respondsToSelector:@selector(browser:isLeafItem:)] && [_delegate browser:self isLeafItem:item];
}
- (id)parentForItemsInColumn:(int)column
{
return [_tableDelegates[column] _item];
}
- (CPSet)selectedItems
{
var selectedColumn = [self selectedColumn],
selectedIndexes = [self selectedRowIndexesInColumn:selectedColumn],
set = [CPSet set],
index = [selectedIndexes firstIndex];
while (index !== CPNotFound)
{
[set addObject:[self itemAtRow:index inColumn:selectedColumn]];
index = [selectedIndexes indexGreaterThanIndex:index];
}
return set;
}
- (id)selectedItem
{
var selectedColumn = [self selectedColumn],
selectedRow = [self selectedRowInColumn:selectedColumn];
return [self itemAtRow:selectedRow inColumn:selectedColumn];
}
// CLICK EVENTS
- (void)trackMouse:(CPEvent)anEvent
{
}
- (void)_column:(unsigned)columnIndex clickedRow:(unsigned)rowIndex
{
[self setLastColumn:columnIndex];
if (rowIndex >= 0)
[self addColumn];
[self doClick:self];
}
- (void)sendAction
{
[self sendAction:_action to:_target];
}
- (void)doClick:(id)sender
{
[self sendAction:_action to:_target];
}
- (void)doDoubleClick:(id)sender
{
[self sendAction:_doubleAction to:_target];
}
- (void)keyDown:(CPEvent)anEvent
{
var column = [self selectedColumn];
if (column === -1)
return;
[_tableViews[column] keyDown:anEvent];
}
// SIZING
- (float)columnContentWidthForColumnWidth:(float)aWidth
{
return aWidth - (_leafWidth + _delegateSupportsImages ? _imageWidth : 0) - [CPScroller scrollerWidth];
}
- (float)columnWidthForColumnContentWidth:(float)aWidth
{
return aWidth + (_leafWidth + _delegateSupportsImages ? _imageWidth : 0) + [CPScroller scrollerWidth];
}
- (void)setImageWidth:(float)aWidth
{
_imageWidth = aWidth;
[self tile];
}
- (float)imageWidth
{
return _imageWidth;
}
- (void)setMinColumnWidth:(float)minWidth
{
_minColumnWidth = minWidth;
[self tile];
}
- (float)minColumnWidth
{
return _minColumnWidth;
}
- (void)setWidth:(float)aWidth ofColumn:(unsigned)column
{
_columnWidths[column] = aWidth;
if ([_delegate respondsToSelector:@selector(browser:didResizeColumn:)])
[_delegate browser:self didResizeColumn:column];
[self tile];
}
- (float)widthOfColumn:(unsigned)column
{
var width = _columnWidths[column];
if (width == null)
width = _defaultColumnWidth;
return MAX([CPScroller scrollerWidth], MAX(_minColumnWidth, width));
}
- (void)setRowHeight:(float)aHeight
{
_rowHeight = aHeight;
}
- (float)rowHeight
{
return _rowHeight;
}
// SCROLLERS
- (void)scrollColumnToVisible:(unsigned)columnIndex
{
[_contentView scrollRectToVisible:[[[self tableViewInColumn:columnIndex] enclosingScrollView] frame]];
}
- (void)scrollRowToVisible:(unsigned)rowIndex inColumn:(unsigned)columnIndex
{
[self scrollColumnToVisible:columnIndex];
[[self tableViewInColumn:columnIndex] scrollRowToVisible:rowIndex];
}
- (BOOL)autohidesScroller
{
return [_horizontalScrollView autohidesScrollers];
}
- (void)setAutohidesScroller:(BOOL)shouldHide
{
[_horizontalScrollView setAutohidesScrollers:shouldHide];
}
// SELECTION
- (unsigned)selectedRowInColumn:(unsigned)columnIndex
{
if (columnIndex > [self lastColumn] || columnIndex < 0)
return -1;
return [_tableViews[columnIndex] selectedRow];
}
- (unsigned)selectedColumn
{
var column = [self lastColumn],
row = [self selectedRowInColumn:column];
if (row >= 0)
return column;
else
return column - 1;
}
- (void)selectRow:(unsigned)row inColumn:(unsigned)column
{
var selectedIndexes = row === -1 ? [CPIndexSet indexSet] : [CPIndexSet indexSetWithIndex:row];
[self selectRowIndexes:selectedIndexes inColumn:column];
}
- (BOOL)allowsMultipleSelection
{
return _allowsMultipleSelection;
}
- (void)setAllowsMultipleSelection:(BOOL)shouldAllow
{
if (_allowsMultipleSelection === shouldAllow)
return;
_allowsMultipleSelection = shouldAllow;
[_tableViews makeObjectsPerformSelector:@selector(setAllowsMultipleSelection:) withObject:shouldAllow];
}
- (BOOL)allowsEmptySelection
{
return _allowsEmptySelection;
}
- (void)setAllowsEmptySelection:(BOOL)shouldAllow
{
if (_allowsEmptySelection === shouldAllow)
return;
_allowsEmptySelection = shouldAllow;
[_tableViews makeObjectsPerformSelector:@selector(setAllowsEmptySelection:) withObject:shouldAllow];
}
- (CPIndexSet)selectedRowIndexesInColumn:(unsigned)column
{
if (column < 0 || column > [self lastColumn] +1)
return [CPIndexSet indexSet];
return [[self tableViewInColumn:column] selectedRowIndexes];
}
- (void)selectRowIndexes:(CPIndexSet)indexSet inColumn:(unsigned)column
{
if (column < 0 || column > [self lastColumn] + 1)
return;
if ([_delegate respondsToSelector:@selector(browser:selectionIndexesForProposedSelection:inColumn:)])
indexSet = [_delegate browser:self selectionIndexesForProposedSelection:indexSet inColumn:column];
if ([_delegate respondsToSelector:@selector(browser:shouldSelectRowIndexes:inColumn:)] &&
![_delegate browser:self shouldSelectRowIndexes:indexSet inColumn:column])
return;
if ([_delegate respondsToSelector:@selector(browserSelectionIsChanging:)])
[_delegate browserSelectionIsChanging:self];
if (column > [self lastColumn])
[self addColumn];
[self setLastColumn:column];
[[self tableViewInColumn:column] selectRowIndexes:indexSet byExtendingSelection:NO];
[self scrollColumnToVisible:column];
if ([_delegate respondsToSelector:@selector(browserSelectionDidChange:)])
[_delegate browserSelectionDidChange:self];
}
- (void)setBackgroundColor:(CPColor)aColor
{
[super setBackgroundColor:aColor];
[_contentView setBackgroundColor:aColor];
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
// DRAG AND DROP
- (void)registerForDraggedTypes:(CPArray)types
{
[super registerForDraggedTypes:types];
[_tableViews makeObjectsPerformSelector:@selector(registerForDraggedTypes:) withObject:types];
}
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent
{
if ([_delegate respondsToSelector:@selector(browser:canDragRowsWithIndexes:inColumn:withEvent:)])
return [_delegate browser:self canDragRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent];
return YES;
}
- (CPImage)draggingImageForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
{
if ([_delegate respondsToSelector:@selector(browser:draggingImageForRowsWithIndexes:inColumn:withEvent:offset:)])
return [_delegate browser:self draggingImageForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
return nil;
}
- (CPView)draggingViewForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
{
if ([_delegate respondsToSelector:@selector(browser:draggingViewForRowsWithIndexes:inColumn:withEvent:offset:)])
return [_delegate browser:self draggingViewForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
return nil;
}
@end
var _CPBrowserResizeControlBackgroundImage = nil;
@implementation _CPBrowserResizeControl : CPView
{
CGPoint _mouseDownX;
CPBrowser _browser;
unsigned _index;
unsigned _width;
}
+ (CPImage)backgroundImage
{
if (!_CPBrowserResizeControlBackgroundImage)
{
var path = [[CPBundle bundleForClass:[self class]] pathForResource:"browser-resize-control.png"];
_CPBrowserResizeControlBackgroundImage = [[CPImage alloc] initWithContentsOfFile:path
size:CGSizeMake(15, 14)];
}
return _CPBrowserResizeControlBackgroundImage;
}
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
[self setBackgroundColor:[CPColor colorWithPatternImage:[[self class] backgroundImage]]];
return self;
}
- (void)mouseDown:(CPEvent)anEvent
{
_mouseDownX = [anEvent locationInWindow].x;
_browser = [[self superview] _browser];
_index = [_browser columnOfTableView:[[self superview] documentView]];
_width = [_browser widthOfColumn:_index];
}
- (void)mouseDragged:(CPEvent)anEvent
{
var deltaX = [anEvent locationInWindow].x - _mouseDownX;
[_browser setWidth:_width + deltaX ofColumn:_index];
}
- (void)mouseUp:(CPEvent)anEvent
{
}
@end
@implementation _CPBrowserScrollView : CPScrollView
{
_CPBrowserResizeControl _resizeControl;
CPBrowser _browser @accessors;
}
- (void)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
_resizeControl = [[_CPBrowserResizeControl alloc] initWithFrame:CGRectMakeZero()];
[self addSubview:_resizeControl];
}
return self;
}
- (void)reflectScrolledClipView:(CPClipView)aClipView
{
[super reflectScrolledClipView:aClipView];
var frame = [_verticalScroller frame];
frame.size.height = CGRectGetHeight([self bounds]) - 14.0 - frame.origin.y;
[_verticalScroller setFrameSize:frame.size];
var resizeFrame = CGRectMake(CGRectGetMinX(frame), CGRectGetMaxY(frame), [CPScroller scrollerWidth], 14.0);
[_resizeControl setFrame:resizeFrame];
}
@end
@implementation _CPBrowserTableView : CPTableView
{
CPBrowser _browser;
}
- (id)initWithFrame:(CGRect)aFrame browser:(CPBrowser)aBrowser
{
if (self = [super initWithFrame:aFrame])
_browser = aBrowser;
return self;
}
- (BOOL)acceptsFirstResponder
{
return NO;
}
- (void)mouseDown:(CPEvent)anEvent
{
[super mouseDown:anEvent];
[[self window] makeFirstResponder:_browser];
}
- (CPView)browserView
{
return _browser;
}
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes atPoint:(CGPoint)mouseDownPoint
{
return [_browser canDragRowsWithIndexes:rowIndexes inColumn:[_browser columnOfTableView:self] withEvent:[CPApp currentEvent]];
}
- (CPImage)dragImageForRowsWithIndexes:(CPIndexSet)dragRows tableColumns:(CPArray)theTableColumns event:(CPEvent)dragEvent offset:(CPPointPointer)dragImageOffset
{
return [_browser draggingImageForRowsWithIndexes:dragRows inColumn:[_browser columnOfTableView:self] withEvent:dragEvent offset:dragImageOffset] ||
[super dragImageForRowsWithIndexes:dragRows tableColumns:theTableColumns event:dragEvent offset:dragImageOffset];
}
- (CPView)dragViewForRowsWithIndexes:(CPIndexSet)dragRows tableColumns:(CPArray)theTableColumns event:(CPEvent)dragEvent offset:(CPPoint)dragViewOffset
{
var count = theTableColumns.length;
while (count--)
{
if ([theTableColumns[count] identifier] === "Leaf")
[theTableColumns removeObject:theTableColumns[count]];
}
return [_browser draggingViewForRowsWithIndexes:dragRows inColumn:[_browser columnOfTableView:self] withEvent:dragEvent offset:dragViewOffset] ||
[super dragViewForRowsWithIndexes:dragRows tableColumns:theTableColumns event:dragEvent offset:dragViewOffset];
}
- (void)moveUp:(id)sender
{
[super moveUp:sender];
[_browser selectRow:[self selectedRow] inColumn:[_browser selectedColumn]];
}
- (void)moveDown:(id)sender
{
[super moveDown:sender];
[_browser selectRow:[self selectedRow] inColumn:[_browser selectedColumn]];
}
- (void)moveLeft:(id)sender
{
var previousColumn = [_browser selectedColumn] - 1,
selectedRow = [_browser selectedRowInColumn:previousColumn];
[_browser selectRow:selectedRow inColumn:previousColumn];
}
- (void)moveRight:(id)sender
{
[_browser selectRow:0 inColumn:[_browser selectedColumn] + 1];
}
@end
@import <Foundation/CPObject.j>
@implementation _CPBrowserTableDelegate : CPObject
{
CPBrowser _browser @accessors;
unsigned _index @accessors;
id _delegate @accessors;
id _item @accessors;
}
- (unsigned)numberOfRowsInTableView:(CPTableView)aTableView
{
return [_delegate browser:_browser numberOfChildrenOfItem:_item];
}
- (void)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)column row:(unsigned)row
{
if ([column identifier] === "Image")
return [_delegate browser:_browser imageValueForItem:[self childAtIndex:row]];
else if ([column identifier] === "Leaf")
return ![_browser isLeafItem:[self childAtIndex:row]];
else
return [_delegate browser:_browser objectValueForItem:[self childAtIndex:row]];
}
- (void)_tableViewDoubleClicked:(CPTableView)aTableView
{
[_browser doDoubleClick:self];
}
- (void)_tableViewClicked:(CPTableView)aTableView
{
var selectedIndexes = [aTableView selectedRowIndexes];
[_browser _column:_index clickedRow:[selectedIndexes count] === 1 ? [selectedIndexes firstIndex] : -1];
}
- (id)childAtIndex:(unsigned)index
{
return [_delegate browser:_browser child:index ofItem:_item];
}
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id)info row:(int)row dropOperation:(CPTableViewDropOperation)operation
{
if ([_delegate respondsToSelector:@selector(browser:acceptDrop:atRow:column:dropOperation:)])
return [_delegate browser:_browser acceptDrop:info atRow:row column:_index dropOperation:operation];
else
return NO;
}
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(int)row proposedDropOperation:(CPTableViewDropOperation)operation
{
if ([_delegate respondsToSelector:@selector(browser:validateDrop:proposedRow:column:dropOperation:)])
return [_delegate browser:_browser validateDrop:info proposedRow:row column:_index dropOperation:operation];
else
return CPDragOperationNone;
}
- (BOOL)tableView:(CPTableView)aTableView writeRowsWithIndexes:(CPIndexSet)rowIndexes toPasteboard:(CPPasteboard)pboard
{
if ([_delegate respondsToSelector:@selector(browser:writeRowsWithIndexes:inColumn:toPasteboard:)])
return [_delegate browser:_browser writeRowsWithIndexes:rowIndexes inColumn:_index toPasteboard:pboard];
else
return NO;
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
if (aSelector === @selector(browser:writeRowsWithIndexes:inColumn:toPasteboard:))
return [_delegate respondsToSelector:@selector(browser:writeRowsWithIndexes:inColumn:toPasteboard:)];
else
return [super respondsToSelector:aSelector];
}
@end
@implementation _CPBrowserLeafView : CPView
{
BOOL _isLeaf @accessors(readonly, property=isLeaf);
CPImage _branchImage @accessors(property=branchImage);
CPImage _highlightedBranchImage @accessors(property=highlightedBranchImage);
}
- (BOOL)objectValue
{
return _isLeaf;
}
- (void)setObjectValue:(id)aValue
{
_isLeaf = !!aValue;
[self setNeedsLayout];
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
{
if (aName === "image-view")
return CGRectInset([self bounds], 1, 1);
return [super rectForEphemeralSubviewNamed:aName];
}
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
if (aName === "image-view")
return [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
return [super createEphemeralSubviewNamed:aName];
}
- (void)layoutSubviews
{
var imageView = [self layoutEphemeralSubviewNamed:@"image-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:nil],
isHighlighted = [self themeState] & CPThemeStateSelectedDataView;
[imageView setImage: _isLeaf ? (isHighlighted ? _highlightedBranchImage : _branchImage) : nil];
[imageView setImageScaling:CPScaleNone];
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeBool:_isLeaf forKey:"_CPBrowserLeafViewIsLeafKey"];
[aCoder encodeObject:_branchImage forKey:"_CPBrowserLeafViewBranchImageKey"];
[aCoder encodeObject:_highlightedBranchImage forKey:"_CPBrowserLeafViewHighlightedBranchImageKey"];
}
- (void)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_isLeaf = [aCoder decodeBoolForKey:"_CPBrowserLeafViewIsLeafKey"];
_branchImage = [aCoder decodeObjectForKey:"_CPBrowserLeafViewBranchImageKey"];
_highlightedBranchImage = [aCoder decodeObjectForKey:"_CPBrowserLeafViewHighlightedBranchImageKey"];
}
return self;
}
@end
+186 -105
View File
@@ -24,31 +24,8 @@
@import "CGGeometry.j"
@import "CPControl.j"
@import "CPStringDrawing.j"
#include "CoreGraphics/CGGeometry.h"
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
/* @group CPCellImagePosition */
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
CPImageRight = 3;
CPImageBelow = 4;
CPImageAbove = 5;
CPImageOverlaps = 6;
/* @group CPButtonState */
CPOnState = 1;
CPOffState = 0;
CPMixedState = -1;
/* @group CPBezelStyle */
@@ -95,7 +72,10 @@ CPChangeBackgroundCellMask = CPBackgroundButtonMask;
CPButtonStateMixed = CPThemeState("mixed");
/*!
CPButtonDefaultHeight = 24.0;
CPButtonImageOffset = 3.0;
/*!
@ingroup appkit
@class CPButton
@@ -106,12 +86,9 @@ CPButtonStateMixed = CPThemeState("mixed");
@implementation CPButton : CPControl
{
BOOL _allowsMixedState;
CPString _title;
CPString _alternateTitle;
CPImage _image;
CPImage _alternateImage;
CPInteger _showsStateBy;
CPInteger _highlightsBy;
@@ -120,6 +97,9 @@ CPButtonStateMixed = CPThemeState("mixed");
// NS-style Display Properties
CPBezelStyle _bezelStyle;
CPControlSize _controlSize;
CPString _keyEquivalent;
unsigned _keyEquivalentModifierMask;
}
+ (id)buttonWithTitle:(CPString)aTitle
@@ -138,21 +118,21 @@ CPButtonStateMixed = CPThemeState("mixed");
return button;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return @"button";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMakeZero(), nil]
forKeys:[@"bezel-inset", @"content-inset", @"bezel-color"]];
return [CPDictionary dictionaryWithObjects:[[CPNull null], 0.0, _CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null]]
forKeys:[@"image", @"image-offset", @"bezel-inset", @"content-inset", @"bezel-color"]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
// Should we instead override the defaults?
@@ -160,19 +140,22 @@ CPButtonStateMixed = CPThemeState("mixed");
[self setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
[self setValue:CPScaleNone forThemeAttribute:@"image-scaling"];
_controlSize = CPRegularControlSize;
_keyEquivalent = @"";
_keyEquivalentModifierMask = 0;
// [self setBezelStyle:CPRoundRectBezelStyle];
[self setBordered:YES];
}
return self;
}
// Setting the state
/*!
Returns <code>YES</code> if the button has a 'mixed' state in addition to on and off.
Returns \c YES if the button has a 'mixed' state in addition to on and off.
*/
- (BOOL)allowsMixedState
{
@@ -192,8 +175,8 @@ CPButtonStateMixed = CPThemeState("mixed");
_allowsMixedState = aFlag;
if (!_allowsMixedState)
[self unsetThemeState:CPButtonStateMixed];
if (!_allowsMixedState && [self state] === CPMixedState)
[self setState:CPOnState];
}
- (void)setObjectValue:(id)anObjectValue
@@ -248,9 +231,9 @@ CPButtonStateMixed = CPThemeState("mixed");
}
/*!
Sets the button's state to <code>aState</code>.
Sets the button's state to \c aState.
@param aState Possible states are any of the CPButton globals:
<code>CPOffState, CPOnState, CPMixedState</code>
\c CPOffState, \c CPOnState, \c CPMixedState
*/
- (void)setState:(CPInteger)aState
{
@@ -269,9 +252,9 @@ CPButtonStateMixed = CPThemeState("mixed");
{
if (_title === aTitle)
return;
_title = aTitle;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -285,7 +268,7 @@ CPButtonStateMixed = CPThemeState("mixed");
{
if (_alternateTitle === aTitle)
return;
_alternateTitle = aTitle;
[self setNeedsLayout];
@@ -299,18 +282,12 @@ CPButtonStateMixed = CPThemeState("mixed");
- (void)setImage:(CPImage)anImage
{
if (_image === anImage)
return;
_image = anImage;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
[self setValue:anImage forThemeAttribute:@"image"];
}
- (CPImage)image
{
return _image;
return [self valueForThemeAttribute:@"image" inState:CPThemeStateNormal];
}
/*!
@@ -319,13 +296,7 @@ CPButtonStateMixed = CPThemeState("mixed");
*/
- (void)setAlternateImage:(CPImage)anImage
{
if (_alternateImage === anImage)
return;
_alternateImage = anImage;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
[self setValue:anImage forThemeAttribute:@"image" inState:CPThemeStateHighlighted];
}
/*!
@@ -333,7 +304,17 @@ CPButtonStateMixed = CPThemeState("mixed");
*/
- (CPImage)alternateImage
{
return _alternateImage;
return [self valueForThemeAttribute:@"image" inState:CPThemeStateHighlighted];
}
- (void)setImageOffset:(float)theImageOffset
{
[self setValue:theImageOffset forThemeAttribute:@"image-offset"];
}
- (float)imageOffset
{
return [self valueForThemeAttribute:@"image-offset"];
}
- (void)setShowsStateBy:(CPInteger)aMask
@@ -368,7 +349,7 @@ CPButtonStateMixed = CPThemeState("mixed");
- (void)setButtonType:(CPButtonType)aButtonType
{
switch (buttonType)
switch (aButtonType)
{
case CPMomentaryLightButton: [self setHighlightsBy:CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
@@ -390,17 +371,17 @@ CPButtonStateMixed = CPThemeState("mixed");
[self setShowsStateBy:CPChangeBackgroundCellMask];
break;
case CPToggleButton: [self setHighlightsBy:CPPushInCellMask | NSContentsCellMask];
case CPToggleButton: [self setHighlightsBy:CPPushInCellMask | CPContentsCellMask];
[self setShowsStateBy:CPContentsCellMask];
break;
case CPSwitchButton: [CPException raise:CPInvalidArgumentException
case CPSwitchButton: [CPException raise:CPInvalidArgumentException
reason:"The CPSwitchButton type is not supported in Cappuccino, use the CPCheckBox class instead."];
case CPRadioButton: [CPException raise:CPInvalidArgumentException
case CPRadioButton: [CPException raise:CPInvalidArgumentException
reason:"The CPRadioButton type is not supported in Cappuccino, use the CPRadio class instead."];
default: [CPException raise:CPInvalidArgumentException
default: [CPException raise:CPInvalidArgumentException
reason:"Unknown button type."];
}
@@ -416,7 +397,7 @@ CPButtonStateMixed = CPThemeState("mixed");
_imageDimsWhenDisabled = imageShouldDimWhenDisabled;
if (_imageDimsWhenDisabled)
if ([self hasThemeState:CPThemeStateDisabled])
{
[self setNeedsDisplay:YES];
[self setNeedsLayout];
@@ -431,7 +412,7 @@ CPButtonStateMixed = CPThemeState("mixed");
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
[self highlight:YES];
return [super startTrackingAt:aPoint];
}
@@ -452,15 +433,16 @@ CPButtonStateMixed = CPThemeState("mixed");
if (_CGInsetIsEmpty(contentInset))
return bounds;
bounds = _CGRectMakeCopy(bounds);
bounds.origin.x += contentInset.left;
bounds.origin.y += contentInset.top;
bounds.size.width -= contentInset.left + contentInset.right;
bounds.size.height -= contentInset.top + contentInset.bottom;
return bounds;
}
- (CGRect)bezelRectForBounds:(CFRect)bounds
- (CGRect)bezelRectForBounds:(CGRect)bounds
{
if (![self isBordered])
return _CGRectMakeZero();
@@ -470,6 +452,7 @@ CPButtonStateMixed = CPThemeState("mixed");
if (_CGInsetIsEmpty(bezelInset))
return bounds;
bounds = _CGRectMakeCopy(bounds);
bounds.origin.x += bezelInset.left;
bounds.origin.y += bezelInset.top;
bounds.size.width -= bezelInset.left + bezelInset.right;
@@ -483,8 +466,20 @@ CPButtonStateMixed = CPThemeState("mixed");
*/
- (void)sizeToFit
{
var size = [([self title] || " ") sizeWithFont:[self currentValueForThemeAttribute:@"font"]],
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
[self layoutSubviews];
var size,
contentView = [self ephemeralSubviewNamed:@"content-view"];
if (contentView)
{
[contentView sizeToFit];
size = [contentView frameSize];
}
else
size = [([self title] || " ") sizeWithFont:[self currentValueForThemeAttribute:@"font"]];
var contentInset = [self currentValueForThemeAttribute:@"content-inset"],
minSize = [self currentValueForThemeAttribute:@"min-size"],
maxSize = [self currentValueForThemeAttribute:@"max-size"];
@@ -504,10 +499,10 @@ CPButtonStateMixed = CPThemeState("mixed");
{
if (aName === "bezel-view")
return [self bezelRectForBounds:[self bounds]];
else if (aName === "content-view")
return [self contentRectForBounds:[self bounds]];
return [super rectForEphemeralSubviewNamed:aName];
}
@@ -518,13 +513,11 @@ CPButtonStateMixed = CPThemeState("mixed");
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
else
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
return [super createEphemeralSubviewNamed:aName];
}
- (void)layoutSubviews
@@ -532,9 +525,8 @@ CPButtonStateMixed = CPThemeState("mixed");
var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:@"content-view"];
if (bezelView)
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
positioned:CPWindowAbove
@@ -543,7 +535,8 @@ CPButtonStateMixed = CPThemeState("mixed");
if (contentView)
{
[contentView setText:([self hasThemeState:CPThemeStateHighlighted] && _alternateTitle) ? _alternateTitle : _title];
[contentView setImage:([self hasThemeState:CPThemeStateHighlighted] && _alternateImage) ? _alternateImage : _image];
[contentView setImage:[self currentValueForThemeAttribute:@"image"]];
[contentView setImageOffset:[self currentValueForThemeAttribute:@"image-offset"]];
[contentView setFont:[self currentValueForThemeAttribute:@"font"]];
[contentView setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
@@ -554,17 +547,10 @@ CPButtonStateMixed = CPThemeState("mixed");
[contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
[contentView setImagePosition:[self currentValueForThemeAttribute:@"image-position"]];
[contentView setImageScaling:[self currentValueForThemeAttribute:@"image-scaling"]];
[contentView setDimsImage:[self hasThemeState:CPThemeStateDisabled] && _imageDimsWhenDisabled];
}
}
- (void)setDefaultButton:(BOOL)shouldBeDefaultButton
{
if (shouldBeDefaultButton)
[self setThemeState:CPThemeStateDefault];
else
[self unsetThemeState:CPThemeStateDefault];
}
- (void)setBordered:(BOOL)shouldBeBordered
{
if (shouldBeBordered)
@@ -578,6 +564,79 @@ CPButtonStateMixed = CPThemeState("mixed");
return [self hasThemeState:CPThemeStateBordered];
}
/*!
Sets the keyboard shortcut for this button. For special keys see
CPEvent.j CP...FunctionKey and CPText.j CP...Character.
@param aString the keyboard shortcut as a string
*/
- (void)setKeyEquivalent:(CPString)aString
{
_keyEquivalent = aString || @"";
// Check if the key equivalent is the enter key
// Treat \r and \n as the same key equivalent. See issue #710.
if (aString === CPNewlineCharacter || aString === CPCarriageReturnCharacter)
[self setThemeState:CPThemeStateDefault];
else
[self unsetThemeState:CPThemeStateDefault];
}
- (void)viewWillMoveToWindow:(CPWindow)aWindow
{
var selfWindow = [self window];
if (selfWindow === aWindow || aWindow === nil)
return;
if ([selfWindow defaultButton] === self)
[selfWindow setDefaultButton:nil];
if ([self keyEquivalent] === CPNewlineCharacter || [self keyEquivalent] === CPCarriageReturnCharacter)
[aWindow setDefaultButton:self];
}
/*!
Returns the keyboard shortcut for this button.
*/
- (CPString)keyEquivalent
{
return _keyEquivalent;
}
/*!
Returns the mask used with this button's key equivalent.
*/
- (void)setKeyEquivalentModifierMask:(unsigned)aMask
{
_keyEquivalentModifierMask = aMask;
}
/*!
Sets the mask to be used with this button's key equivalent.
*/
- (unsigned)keyEquivalentModifierMask
{
return _keyEquivalentModifierMask;
}
/*!
Checks the button's key equivalent against that in the event, and if they
match simulates a button click.
*/
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
{
// Don't handle the key equivalent for the default window because the window will handle it for us
if ([[self window] defaultButton] === self)
return NO;
if (![anEvent _triggersKeyEquivalent:[self keyEquivalent] withModifierMask:[self keyEquivalentModifierMask]])
return NO;
[self performClick:nil];
return YES;
}
@end
@implementation CPButton (NS)
@@ -593,36 +652,51 @@ CPButtonStateMixed = CPThemeState("mixed");
@end
var CPButtonImageKey = @"CPButtonImageKey",
CPButtonAlternateImageKey = @"CPButtonAlternateImageKey",
CPButtonTitleKey = @"CPButtonTitleKey",
CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey",
CPButtonIsBorderedKey = @"CPButtonIsBorderedKey";
var CPButtonImageKey = @"CPButtonImageKey",
CPButtonAlternateImageKey = @"CPButtonAlternateImageKey",
CPButtonTitleKey = @"CPButtonTitleKey",
CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey",
CPButtonIsBorderedKey = @"CPButtonIsBorderedKey",
CPButtonAllowsMixedStateKey = @"CPButtonAllowsMixedStateKey",
CPButtonImageDimsWhenDisabledKey = @"CPButtonImageDimsWhenDisabledKey",
CPButtonImagePositionKey = @"CPButtonImagePositionKey",
CPButtonKeyEquivalentKey = @"CPButtonKeyEquivalentKey",
CPButtonKeyEquivalentMaskKey = @"CPButtonKeyEquivalentMaskKey";
@implementation CPButton (CPCoding)
/*!
Initializes the button by unarchiving data from <code>aCoder</code>.
Initializes the button by unarchiving data from \c aCoder.
@param aCoder the coder containing the archived CPButton.
*/
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_controlSize = CPRegularControlSize;
[self setImage:[aCoder decodeObjectForKey:CPButtonImageKey]];
[self setAlternateImage:[aCoder decodeObjectForKey:CPButtonAlternateImageKey]];
[self setTitle:[aCoder decodeObjectForKey:CPButtonTitleKey]];
[self setAlternateTitle:[aCoder decodeObjectForKey:CPButtonAlternateTitleKey]];
_title = [aCoder decodeObjectForKey:CPButtonTitleKey];
_alternateTitle = [aCoder decodeObjectForKey:CPButtonAlternateTitleKey];
if ([aCoder containsValueForKey:CPButtonAllowsMixedStateKey])
_allowsMixedState = [aCoder decodeBoolForKey:CPButtonAllowsMixedStateKey];
[self setImageDimsWhenDisabled:[aCoder decodeObjectForKey:CPButtonImageDimsWhenDisabledKey]];
if ([aCoder containsValueForKey:CPButtonImagePositionKey])
[self setImagePosition:[aCoder decodeIntForKey:CPButtonImagePositionKey]];
if ([aCoder containsValueForKey:CPButtonKeyEquivalentKey])
[self setKeyEquivalent:CFData.decodeBase64ToUtf16String([aCoder decodeObjectForKey:CPButtonKeyEquivalentKey])];
_keyEquivalentModifierMask = [aCoder decodeIntForKey:CPButtonKeyEquivalentMaskKey];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
return self;
}
@@ -634,11 +708,18 @@ var CPButtonImageKey = @"CPButtonImageKey",
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_image forKey:CPButtonImageKey];
[aCoder encodeObject:_alternateImage forKey:CPButtonAlternateImageKey];
[aCoder encodeObject:_title forKey:CPButtonTitleKey];
[aCoder encodeObject:_alternateTitle forKey:CPButtonAlternateTitleKey];
[aCoder encodeBool:_allowsMixedState forKey:CPButtonAllowsMixedStateKey];
[aCoder encodeBool:[self imageDimsWhenDisabled] forKey:CPButtonImageDimsWhenDisabledKey];
[aCoder encodeInt:[self imagePosition] forKey:CPButtonImagePositionKey];
if (_keyEquivalent)
[aCoder encodeObject:CFData.encodeBase64Utf16String(_keyEquivalent) forKey:CPButtonKeyEquivalentKey];
[aCoder encodeInt:_keyEquivalentModifierMask forKey:CPButtonKeyEquivalentMaskKey];
}
@end
+244 -28
View File
@@ -1,61 +1,277 @@
@import <AppKit/CPView.j>
#include "CoreGraphics/CGGeometry.h"
@import "CPView.j"
@implementation CPButtonBar : CPControl
@implementation CPButtonBar : CPView
{
BOOL _hasResizeControl;
BOOL _resizeControlIsLeftAligned;
CPArray _buttons;
}
+ (CPString)themeClass
+ (id)plusButton
{
var button = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"plus_button.png"] size:CGSizeMake(11, 12)];
[button setBordered:NO];
[button setImage:image];
[button setImagePosition:CPImageOnly];
return button;
}
+ (id)minusButton
{
var button = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"minus_button.png"] size:CGSizeMake(11, 4)];
[button setBordered:NO];
[button setImage:image];
[button setImagePosition:CPImageOnly];
return button;
}
+ (id)actionPopupButton
{
var button = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"action_button.png"] size:CGSizeMake(22, 14)];
[button addItemWithTitle:nil];
[[button lastItem] setImage:image];
[button setImagePosition:CPImageOnly];
[button setValue:CGInsetMake(0, 0, 0, 0) forThemeAttribute:"content-inset"];
[button setPullsDown:YES];
return button;
}
+ (CPString)defaultThemeClass
{
return @"button-bar";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[nil]
forKeys:[@"bezel-color"]];
return [CPDictionary dictionaryWithObjects:[CGInsetMake(0.0, 0.0, 0.0, 0.0), CGSizeMakeZero(), [CPNull null], [CPNull null], [CPNull null], [CPNull null]]
forKeys:[@"resize-control-inset", @"resize-control-size", @"resize-control-color", @"bezel-color", @"button-bezel-color", @"button-text-color"]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_buttons = [];
[self setNeedsLayout];
}
return self;
}
- (void)awakeFromCib
{
var view = [self superview],
subview = self;
while (view)
{
if ([view isKindOfClass:[CPSplitView class]])
{
var viewIndex = [[view subviews] indexOfObject:subview];
[view setButtonBar:self forDividerAtIndex:viewIndex];
break;
}
subview = view;
view = [view superview];
}
}
- (void)setButtons:(CPArray)buttons
{
_buttons = [CPArray arrayWithArray:buttons];
for (var i = 0, count = [_buttons count]; i < count; i++)
[_buttons[i] setBordered:YES];
[self setNeedsLayout];
}
- (CPArray)buttons
{
return [CPArray arrayWithArray:_buttons];
}
- (void)setHasResizeControl:(BOOL)shouldHaveResizeControl
{
if (_hasResizeControl === shouldHaveResizeControl)
return;
_hasResizeControl = !!shouldHaveResizeControl;
[self setNeedsLayout];
}
- (BOOL)hasResizeControl
{
return _hasResizeControl;
}
- (void)setResizeControlIsLeftAligned:(BOOL)shouldBeLeftAligned
{
if (_resizeControlIsLeftAligned === shouldBeLeftAligned)
return;
_resizeControlIsLeftAligned = !!shouldBeLeftAligned;
[self setNeedsLayout];
}
- (BOOL)resizeControlIsLeftAligned
{
return _resizeControlIsLeftAligned;
}
- (CGRect)resizeControlFrame
{
var inset = [self currentValueForThemeAttribute:@"resize-control-inset"],
size = [self currentValueForThemeAttribute:@"resize-control-size"],
currentSize = [self bounds],
leftOrigin = _resizeControlIsLeftAligned ? 0 : currentSize.size.width - size.width - inset.right - inset.left;
return CGRectMake(leftOrigin, 0, size.width + inset.left + inset.right, size.height + inset.top + inset.bottom);
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
{
if (aName === "bezel-view")
return [self bounds];
if (aName === "resize-control-view")
{
var inset = [self currentValueForThemeAttribute:@"resize-control-inset"],
size = [self currentValueForThemeAttribute:@"resize-control-size"],
currentSize = [self bounds];
if (_resizeControlIsLeftAligned)
return CGRectMake(inset.left, inset.top, size.width, size.height);
else
return CGRectMake(currentSize.size.width - size.width - inset.right, inset.top, size.width, size.height);
}
return [super rectForEphemeralSubviewNamed:aName];
}
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
if (aName === "bezel-view")
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
if (aName === "resize-control-view")
return [[CPView alloc] initWithFrame:CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
return [super createEphemeralSubviewNamed:aName];
}
- (void)layoutSubviews
{
var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:@""];
if (bezelView)
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
[self setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
var normalColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateNormal],
highlightedColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateHighlighted],
disabledColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateDisabled],
textColor = [self valueForThemeAttribute:@"button-text-color" inState:CPThemeStateNormal];
var buttonsNotHidden = [CPArray arrayWithArray:_buttons],
count = [buttonsNotHidden count];
while (count--)
if ([buttonsNotHidden[count] isHidden])
[buttonsNotHidden removeObject:buttonsNotHidden[count]];
var currentButtonOffset = _resizeControlIsLeftAligned ? CGRectGetMaxX([self bounds]) + 1 : -1,
bounds = [self bounds],
height = CGRectGetHeight(bounds) - 1,
frameWidth = CGRectGetWidth(bounds),
resizeRect = _hasResizeControl ? [self rectForEphemeralSubviewNamed:"resize-control-view"] : CGRectMakeZero(),
resizeWidth = CGRectGetWidth(resizeRect),
availableWidth = frameWidth - resizeWidth - 1;
for (var i = 0, count = [buttonsNotHidden count]; i < count; i++)
{
var button = buttonsNotHidden[i],
width = CGRectGetWidth([button frame]);
if (availableWidth > width)
availableWidth -= width;
else
break;
if (_resizeControlIsLeftAligned)
{
[button setFrame:CGRectMake(currentButtonOffset - width, 1, width, height)];
currentButtonOffset -= width - 1;
}
else
{
[button setFrame:CGRectMake(currentButtonOffset, 1, width, height)];
currentButtonOffset += width - 1;
}
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal | CPThemeStateBordered];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted | CPThemeStateBordered];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled | CPThemeStateBordered];
[button setValue:textColor forThemeAttribute:@"text-color" inState:CPThemeStateBordered];
// FIXME shouldn't need this
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[self addSubview:button];
}
if (_hasResizeControl)
{
var resizeControlView = [self layoutEphemeralSubviewNamed:@"resize-control-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:nil];
[resizeControlView setAutoresizingMask: _resizeControlIsLeftAligned ? CPViewMaxXMargin : CPViewMinXMargin];
[resizeControlView setBackgroundColor:[self currentValueForThemeAttribute:@"resize-control-color"]];
}
}
- (void)addSubview:(CPView)aSubview
- (void)setFrameSize:(CGSize)aSize
{
[super addSubview:aSubview];
[aSubview setAutoresizingMask:CPViewMinXMargin];
[super setFrameSize:aSize];
[self setNeedsLayout];
}
@end
var CPButtonBarHasResizeControlKey = @"CPButtonBarHasResizeControlKey",
CPButtonBarResizeControlIsLeftAlignedKey = @"CPButtonBarResizeControlIsLeftAlignedKey",
CPButtonBarButtonsKey = @"CPButtonBarButtonsKey";
@implementation CPButtonBar (CPCoding)
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeBool:_hasResizeControl forKey:CPButtonBarHasResizeControlKey];
[aCoder encodeBool:_resizeControlIsLeftAligned forKey:CPButtonBarResizeControlIsLeftAlignedKey];
[aCoder encodeObject:_buttons forKey:CPButtonBarButtonsKey];
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_buttons = [aCoder decodeObjectForKey:CPButtonBarButtonsKey] || [];
_hasResizeControl = [aCoder decodeBoolForKey:CPButtonBarHasResizeControlKey];
_resizeControlIsLeftAligned = [aCoder decodeBoolForKey:CPButtonBarResizeControlIsLeftAlignedKey];
}
return self;
}
@end
+27 -2
View File
@@ -23,6 +23,8 @@
@import "CPButton.j"
CPCheckBoxImageOffset = 4.0;
@implementation CPCheckBox : CPButton
{
}
@@ -37,7 +39,7 @@
return [self buttonWithTitle:aTitle];
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return @"check-box";
}
@@ -55,10 +57,33 @@
[self setImagePosition:CPImageLeft];
[self setAlignment:CPLeftTextAlignment];
[self setBordered:YES];
[self setBordered:NO];
}
return self;
}
- (void)takeStateFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
{
var count = objects.length,
value = [objects[0] valueForKeyPath:aKeyPath] ? CPOnState : CPOffState;
[self setAllowsMixedState:NO];
[self setState:value];
while (count-- > 1)
{
if (value !== ([objects[count] valueForKeyPath:aKeyPath] ? CPOnState : CPOffState))
{
[self setAllowsMixedState:YES];
[self setState:CPMixedState];
}
}
}
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
{
[self takeStateFromKeyPath:aKeyPath ofObjects:objects];
}
@end
+68 -40
View File
@@ -22,14 +22,12 @@
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
/*!
/*!
@ingroup appkit
@class CPClipView
CPClipView allows you to define a clip rect and display only that portion of its containing view.
CPClipView allows you to define a clip rect and display only that portion of its containing view.
It is used to hold the document view in a CPScrollView.
*/
@implementation CPClipView : CPView
@@ -38,8 +36,8 @@
}
/*!
Sets the document view to be <code>aView</code>.
@param aView the new document view. It's frame origin will be changed to <code>(0,0)</code> after calling this method.
Sets the document view to be \c aView.
@param aView the new document view. It's frame origin will be changed to \c (0,0) after calling this method.
*/
- (void)setDocumentView:(CPView)aView
{
@@ -47,7 +45,7 @@
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_documentView)
{
[defaultCenter
@@ -59,29 +57,29 @@
removeObserver:self
name:CPViewBoundsDidChangeNotification
object:_documentView];
[_documentView removeFromSuperview];
}
_documentView = aView;
if (_documentView)
{
[self addSubview:_documentView];
[_documentView setPostsFrameChangedNotifications:YES];
[_documentView setPostsBoundsChangedNotifications:YES];
[defaultCenter
[_documentView setPostsFrameChangedNotifications:YES];
[_documentView setPostsBoundsChangedNotifications:YES];
[defaultCenter
addObserver:self
selector:@selector(viewFrameChanged:)
name:CPViewFrameDidChangeNotification
name:CPViewFrameDidChangeNotification
object:_documentView];
[defaultCenter
[defaultCenter
addObserver:self
selector:@selector(viewBoundsChanged:)
name:CPViewBoundsDidChangeNotification
name:CPViewBoundsDidChangeNotification
object:_documentView];
}
}
@@ -95,7 +93,7 @@
}
/*!
Returns a new point that may be adjusted from <code>aPoint</code>
Returns a new point that may be adjusted from \c aPoint
to make sure it lies within the document view.
@param aPoint
@return the adjusted point
@@ -106,7 +104,7 @@
return _CGPointMakeZero();
var documentFrame = [_documentView frame];
aPoint.x = MAX(0.0, MIN(aPoint.x, MAX(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(_bounds), 0.0)));
aPoint.y = MAX(0.0, MIN(aPoint.y, MAX(_CGRectGetHeight(documentFrame) - _CGRectGetHeight(_bounds), 0.0)));
@@ -117,18 +115,22 @@
{
if (_CGPointEqualToPoint(_bounds.origin, aPoint))
return;
[super setBoundsOrigin:aPoint];
var superview = [self superview];
if([superview isKindOfClass:[CPScrollView class]])
var superview = [self superview],
// This is hack to avoid having to import CPScrollView.
// FIXME: Should CPScrollView be finding out about this on its own somehow?
scrollViewClass = objj_getClass("CPScrollView");
if ([superview isKindOfClass:scrollViewClass])
[superview reflectScrolledClipView:self];
}
/*!
Scrolls the clip view to the specified point. The method
sets its bounds origin to <code>aPoint</code>.
sets its bounds origin to \c aPoint.
*/
- (void)scrollToPoint:(CGPoint)aPoint
{
@@ -162,37 +164,63 @@
- (void)_constrainScrollPoint
{
var oldScrollPoint = [self bounds].origin;
// Call scrollToPoint: because the current scroll point may no longer make
// Call scrollToPoint: because the current scroll point may no longer make
// sense given the new frame of the document view.
[self scrollToPoint:oldScrollPoint];
// scrollToPoint: takes care of reflectScrollClipView: for us, so bail if
// scrollToPoint: takes care of reflectScrollClipView: for us, so bail if
// the scroll points are not equal (meaning scrollToPoint: didn't early bail).
if (!CGPointEqualToPoint(oldScrollPoint, [self bounds].origin))
return;
// ... and we're in a scroll view of course.
var superview = [self superview];
if ([superview isKindOfClass:[CPScrollView class]])
var superview = [self superview],
// This is hack to avoid having to import CPScrollView.
// FIXME: Should CPScrollView be finding out about this on its own somehow?
scrollViewClass = objj_getClass("CPScrollView");
if ([superview isKindOfClass:scrollViewClass])
[superview reflectScrolledClipView:self];
}
- (BOOL)autoscroll:(CPEvent)anEvent
- (BOOL)autoscroll:(CPEvent)anEvent
{
var bounds = [self bounds],
eventLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil];
eventLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
superview = [self superview],
deltaX = 0,
deltaY = 0;
if (CPRectContainsPoint(bounds, eventLocation))
if (CGRectContainsPoint(bounds, eventLocation))
return NO;
var newRect = CGRectMakeZero();
if (![superview isKindOfClass:[CPScrollView class]] || [superview hasVerticalScroller])
{
if (eventLocation.y < CGRectGetMinY(bounds))
deltaY = CGRectGetMinY(bounds) - eventLocation.y;
else if (eventLocation.y > CGRectGetMaxY(bounds))
deltaY = CGRectGetMaxY(bounds) - eventLocation.y;
if (deltaY < -bounds.size.height)
deltaY = -bounds.size.height;
if (deltaY > bounds.size.height)
deltaY = bounds.size.height;
}
newRect.origin = eventLocation;
newRect.size = CPSizeMake(10, 10);
if (![superview isKindOfClass:[CPScrollView class]] || [superview hasHorizontalScroller])
{
if (eventLocation.x < CGRectGetMinX(bounds))
deltaX = CGRectGetMinX(bounds) - eventLocation.x;
else if (eventLocation.x > CGRectGetMaxX(bounds))
deltaX = CGRectGetMaxX(bounds) - eventLocation.x;
if (deltaX < -bounds.size.width)
deltaX = -bounds.size.width;
if (deltaX > bounds.size.width)
deltaX = bounds.size.width;
}
return [_documentView scrollRectToVisible:newRect];
return [self scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
}
@end
@@ -206,14 +234,14 @@ var CPClipViewDocumentViewKey = @"CPScrollViewDocumentView";
{
if (self = [super initWithCoder:aCoder])
[self setDocumentView:[aCoder decodeObjectForKey:CPClipViewDocumentViewKey]];
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_documentView forKey:CPClipViewDocumentViewKey];
}
+389 -236
View File
@@ -26,19 +26,20 @@
@import <Foundation/CPKeyedArchiver.j>
@import <Foundation/CPKeyedUnarchiver.j>
@import <AppKit/CPView.j>
@import "CPView.j"
@import "CPCollectionViewItem.j"
/*!
/*!
@ingroup appkit
@class CPCollectionView
This class displays an array as a grid of objects, where each object is represented by a view.
The view is controlled by creating a CPCollectionViewItem and specifying its view, then
This class displays an array as a grid of objects, where each object is represented by a view.
The view is controlled by creating a CPCollectionViewItem and specifying its view, then
setting that item as the collection view prototype.
@par Delegate Methods
@delegate -(void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
Called when the selection in the collection view has changed.
@param collectionView the collection view who's selection changed
@@ -61,76 +62,84 @@
@param indices the indices to obtain drag types
@return an array of drag types (CPString)
*/
@implementation CPCollectionView : CPView
{
CPArray _content;
CPArray _items;
CPData _itemData;
CPCollectionViewItem _itemPrototype;
CPCollectionViewItem _itemForDragging;
CPMutableArray _cachedItems;
unsigned _maxNumberOfRows;
unsigned _maxNumberOfColumns;
CGSize _minItemSize;
CGSize _maxItemSize;
CPArray _backgroundColors;
float _tileWidth;
BOOL _isSelectable;
BOOL _allowsMultipleSelection;
BOOL _allowsEmptySelection;
CPIndexSet _selectionIndexes;
CGSize _itemSize;
float _horizontalMargin;
float _verticalMargin;
unsigned _numberOfRows;
unsigned _numberOfColumns;
id _delegate;
CPEvent _mouseDownEvent;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_items = [];
_content = [];
_cachedItems = [];
_itemSize = CGSizeMakeZero();
_minItemSize = CGSizeMakeZero();
_maxItemSize = CGSizeMakeZero();
[self setBackgroundColors:nil];
_verticalMargin = 5.0;
_tileWidth = -1.0;
_selectionIndexes = [CPIndexSet indexSet];
_allowsEmptySelection = YES;
_isSelectable = YES;
}
return self;
}
/*!
Sets the item prototype to <code>anItem</code>
Sets the item prototype to \c anItem
@param anItem the new item prototype
*/
- (void)setItemPrototype:(CPCollectionViewItem)anItem
{
_itemData = [CPKeyedArchiver archivedDataWithRootObject:anItem];
_itemForDragging = anItem//[CPKeyedUnarchiver unarchiveObjectWithData:_itemData];
_cachedItems = [];
_itemData = nil;
_itemForDragging = nil;
_itemPrototype = anItem;
[self reloadContent];
}
@@ -143,17 +152,24 @@
}
/*!
Returns a collection view item for <code>anObject</code>.
Returns a collection view item for \c anObject.
@param anObject the object to be represented.
*/
- (CPCollectionViewItem)newItemForRepresentedObject:(id)anObject
{
var item = nil;
if (_cachedItems.length)
item = _cachedItems.pop();
else
{
if (!_itemData)
if (_itemPrototype)
_itemData = [CPKeyedArchiver archivedDataWithRootObject:_itemPrototype];
item = [CPKeyedUnarchiver unarchiveObjectWithData:_itemData];
}
[item setRepresentedObject:anObject];
[[item view] setFrameSize:_itemSize];
@@ -163,7 +179,7 @@
// Working with the Responder Chain
/*!
Returns <code>YES</code> by default.
Returns \c YES by default.
*/
- (BOOL)acceptsFirstResponder
{
@@ -175,13 +191,13 @@
*/
- (BOOL)isFirstResponder
{
return [[self window] firstResponder] == self;
return [[self window] firstResponder] === self;
}
// Setting the Content
/*!
Sets the content of the collection view to the content in <code>anArray</code>.
This array can be of any type, and each element will be passed to the <code>setRepresentedObject:</code> method.
Sets the content of the collection view to the content in \c anArray.
This array can be of any type, and each element will be passed to the \c -setRepresentedObject: method.
It's the responsibility of your custom collection view item to interpret the object.
@param anArray the content array
*/
@@ -189,9 +205,9 @@
{
if (_content == anArray)
return;
_content = anArray;
[self reloadContent];
}
@@ -214,36 +230,36 @@
// Setting the Selection Mode
/*!
Sets whether the user is allowed to select items
@param isSelectable <code>YES</code> allows the user to select items.
@param isSelectable \c YES allows the user to select items.
*/
- (void)setSelectable:(BOOL)isSelectable
{
if (_isSelectable == isSelectable)
return;
_isSelectable = isSelectable;
if (!_isSelectable)
{
var index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
[_items[index] setSelected:NO];
}
}
/*!
Returns <code>YES</code> if the collection view is
selected, and <code>NO</code> otherwise.
Returns \c YES if the collection view is
selectable, and \c NO otherwise.
*/
- (BOOL)isSelected
- (BOOL)isSelectable
{
return _isSelected;
return _isSelectable;
}
/*!
Sets whether the user may have no items selected. If YES, mouse clicks not on any item will empty the current selection. The first item will also start off as selected.
@param shouldAllowMultipleSelection <code>YES</code> allows the user to select multiple items
@param shouldAllowMultipleSelection \c YES allows the user to select multiple items
*/
- (void)setAllowsEmptySelection:(BOOL)shouldAllowEmptySelection
{
@@ -251,7 +267,7 @@
}
/*!
Returns <code>YES</code> if the user can select no items, <code>NO</code> otherwise.
Returns \c YES if the user can select no items, \c NO otherwise.
*/
- (BOOL)allowsEmptySelection
{
@@ -260,7 +276,7 @@
/*!
Sets whether the user can select multiple items.
@param shouldAllowMultipleSelection <code>YES</code> allows the user to select multiple items
@param shouldAllowMultipleSelection \c YES allows the user to select multiple items
*/
- (void)setAllowsMultipleSelection:(BOOL)shouldAllowMultipleSelection
{
@@ -268,7 +284,7 @@
}
/*!
Returns <code>YES</code> if the user can select multiple items, <code>NO</code> otherwise.
Returns \c YES if the user can select multiple items, \c NO otherwise.
*/
- (BOOL)allowsMultipleSelection
{
@@ -281,23 +297,25 @@
*/
- (void)setSelectionIndexes:(CPIndexSet)anIndexSet
{
if (_selectionIndexes == anIndexSet || !_isSelectable)
if ([_selectionIndexes isEqual:anIndexSet] || !_isSelectable)
return;
var index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
[_items[index] setSelected:NO];
_selectionIndexes = anIndexSet;
var index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
[_items[index] setSelected:YES];
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
[_delegate collectionViewDidChangeSelection:self]
[_delegate collectionViewDidChangeSelection:self];
}
/*!
@@ -305,37 +323,43 @@
*/
- (CPIndexSet)selectionIndexes
{
return _selectionIndexes;
return [_selectionIndexes copy];
}
/* @ignore */
- (void)reloadContent
{
{
// Remove current views
var count = _items.length;
while (count--)
{
[[_items[count] view] removeFromSuperview];
[_items[count] setSelected:NO];
_cachedItems.push(_items[count]);
}
_items = [];
if (!_itemData || !_content)
if (!_itemPrototype || !_content)
return;
var index = 0;
count = _content.length;
for (; index < count; ++index)
{
_items.push([self newItemForRepresentedObject:_content[index]]);
[self addSubview:[_items[index] view]];
}
index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
[_items[index] setSelected:YES];
[self tile];
}
@@ -343,49 +367,49 @@
- (void)tile
{
var width = CGRectGetWidth([self bounds]);
if (![_content count] || width == _tileWidth)
return;
// We try to fit as many views per row as possible. Any remaining space is then
// We try to fit as many views per row as possible. Any remaining space is then
// either proportioned out to the views (if their minSize != maxSize) or used as
// margin
var itemSize = CGSizeMakeCopy(_minItemSize);
_numberOfColumns = MAX(1.0, FLOOR(width / itemSize.width));
if (_maxNumberOfColumns > 0)
_numberOfColumns = MIN(_maxNumberOfColumns, _numberOfColumns);
var remaining = width - _numberOfColumns * itemSize.width,
itemsNeedSizeUpdate = NO;
if (remaining > 0 && itemSize.width < _maxItemSize.width)
itemSize.width = MIN(_maxItemSize.width, itemSize.width + FLOOR(remaining / _numberOfColumns));
// When we ONE column and a non-integral width, the FLOORing above can cause the item width to be smaller than the total width.
if (_maxNumberOfColumns == 1 && itemSize.width < _maxItemSize.width && itemSize.width < width)
itemSize.width = MIN(_maxItemSize.width, width);
if (!CGSizeEqualToSize(_itemSize, itemSize))
{
_itemSize = itemSize;
itemsNeedSizeUpdate = YES;
}
var index = 0,
count = _items.length;
if (_maxNumberOfColumns > 0 && _maxNumberOfRows > 0)
count = MIN(count, _maxNumberOfColumns * _maxNumberOfRows);
_numberOfRows = CEIL(count / _numberOfColumns);
_horizontalMargin = FLOOR((width - _numberOfColumns * itemSize.width) / (_numberOfColumns + 1));
var x = _horizontalMargin,
y = -itemSize.height;
for (; index < count; ++index)
{
if (index % _numberOfColumns == 0)
@@ -393,19 +417,28 @@
x = _horizontalMargin;
y += _verticalMargin + itemSize.height;
}
var view = [_items[index] view];
[view setFrameOrigin:CGPointMake(x, y)];
if (itemsNeedSizeUpdate)
[view setFrameSize:_itemSize];
x += itemSize.width + _horizontalMargin;
}
var superview = [self superview],
proposedHeight = y + itemSize.height + _verticalMargin;
if ([superview isKindOfClass:[CPClipView class]])
{
var superviewSize = [superview bounds].size;
proposedHeight = MAX(superviewSize.height, proposedHeight);
}
_tileWidth = width;
[self setFrameSize:CGSizeMake(width, y + itemSize.height + _verticalMargin)];
[self setFrameSize:CGSizeMake(width, proposedHeight)];
_tileWidth = -1.0;
}
@@ -423,9 +456,9 @@
{
if (_maxNumberOfRows == aMaxNumberOfRows)
return;
_maxNumberOfRows = aMaxNumberOfRows;
[self tile];
}
@@ -445,9 +478,9 @@
{
if (_maxNumberOfColumns == aMaxNumberOfColumns)
return;
_maxNumberOfColumns = aMaxNumberOfColumns;
[self tile];
}
@@ -484,9 +517,9 @@
{
if (CGSizeEqualToSize(_minItemSize, aSize))
return;
_minItemSize = CGSizeMakeCopy(aSize);
[self tile];
}
@@ -506,9 +539,9 @@
{
if (CGSizeEqualToSize(_maxItemSize, aSize))
return;
_maxItemSize = CGSizeMakeCopy(aSize);
[self tile];
}
@@ -520,6 +553,30 @@
return _maxItemSize;
}
- (void)setBackgroundColors:(CPArray)backgroundColors
{
if (_backgroundColors === backgroundColors)
return;
_backgroundColors = backgroundColors;
if (!_backgroundColors)
_backgroundColors = [CPColor whiteColor];
if ([_backgroundColors count] === 1)
[self setBackgroundColor:_backgroundColors[0]];
else
[self setBackgroundColor:nil];
[self setNeedsDisplay:YES];
}
- (CPArray)backgroundColors
{
return _backgroundColors;
}
- (void)mouseUp:(CPEvent)anEvent
{
if ([_selectionIndexes count] && [anEvent clickCount] == 2 && [_delegate respondsToSelector:@selector(collectionView:didDoubleClickOnItemAtIndex:)])
@@ -528,45 +585,89 @@
- (void)mouseDown:(CPEvent)anEvent
{
_mouseDownEvent = anEvent;
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
row = FLOOR(location.y / (_itemSize.height + _verticalMargin)),
column = FLOOR(location.x / (_itemSize.width + _horizontalMargin)),
index = row * _numberOfColumns + column;
if (index >= 0 && index < _items.length)
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
{
if (_allowsMultipleSelection && ([anEvent modifierFlags] & CPCommandKeyMask || [anEvent modifierFlags] & CPShiftKeyMask))
{
if ([anEvent modifierFlags] & CPCommandKeyMask)
{
var indexes = [_selectionIndexes copy];
if ([indexes containsIndex:index])
[indexes removeIndex:index];
else
[indexes addIndex:index];
}
else if ([anEvent modifierFlags] & CPShiftKeyMask)
{
var firstSelectedIndex = [[self selectionIndexes] firstIndex],
newSelectedRange = nil;
if (index < firstSelectedIndex)
newSelectedRange = CPMakeRange(index, (firstSelectedIndex - index) + 1);
else
newSelectedRange = CPMakeRange(firstSelectedIndex, (index - firstSelectedIndex) + 1);
indexes = [[self selectionIndexes] copy];
[indexes addIndexesInRange:newSelectedRange];
}
}
else
indexes = [CPIndexSet indexSetWithIndex:index];
[self setSelectionIndexes:indexes];
}
else if (_allowsEmptySelection)
[self setSelectionIndexes:[CPIndexSet indexSet]];
}
- (void)mouseDragged:(CPEvent)anEvent
{
var locationInWindow = [anEvent locationInWindow],
mouseDownLocationInWindow = [_mouseDownEvent locationInWindow];
// FIXME: This is because Safari's drag hysteresis is 3px x 3px
if ((ABS(locationInWindow.x - mouseDownLocationInWindow.x) < 3) &&
(ABS(locationInWindow.y - mouseDownLocationInWindow.y) < 3))
return;
if (![_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)])
return;
// If we don't have any selected items, we've clicked away, and thus the drag is meaningless.
if (![_selectionIndexes count])
return;
if ([_delegate respondsToSelector:@selector(collectionView:canDragItemsAtIndexes:withEvent:)] &&
![_delegate collectionView:self canDragItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent])
return;
// Set up the pasteboard
var dragTypes = [_delegate collectionView:self dragTypesForItemsAtIndexes:_selectionIndexes];
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self];
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
[_itemForDragging setRepresentedObject:_content[[_selectionIndexes firstIndex]]];
if (!_itemForDragging)
_itemForDragging = [self newItemForRepresentedObject:_content[[_selectionIndexes firstIndex]]];
else
[_itemForDragging setRepresentedObject:_content[[_selectionIndexes firstIndex]]];
var view = [_itemForDragging view];
var view = [_itemForDragging view],
frame = [view frame];
[view setFrameSize:_itemSize];
[view setAlphaValue:0.7];
[self dragView:view
at:[[_items[[_selectionIndexes firstIndex]] view] frame].origin
offset:CGPointMakeZero()
event:anEvent
offset:CGSizeMakeZero()
event:_mouseDownEvent
pasteboard:nil
source:self
slideBack:YES];
@@ -593,9 +694,9 @@
{
if (_verticalMargin == aVerticalMargin)
return;
_verticalMargin = aVerticalMargin;
[self tile];
}
@@ -625,100 +726,173 @@
return _delegate;
}
@end
/*!
Represents an object inside a CPCollectionView.
*/
@implementation CPCollectionViewItem : CPObject
- (CPCollectionViewItem)itemAtIndex:(unsigned)anIndex
{
id _representedObject;
CPView _view;
BOOL _isSelected;
return [_items objectAtIndex:anIndex];
}
// Setting the Represented Object
/*!
Sets the object to be represented by this item.
@param anObject the object to be represented
*/
- (void)setRepresentedObject:(id)anObject
- (CGRect)frameForItemAtIndex:(unsigned)anIndex
{
if (_representedObject == anObject)
return;
_representedObject = anObject;
// FIXME: This should be set up by bindings
[_view setRepresentedObject:anObject];
return [[[self itemAtIndex:anIndex] view] frame];
}
/*!
Returns the object represented by this view item
*/
- (id)representedObject
- (CGRect)frameForItemsAtIndexes:(CPIndexSet)anIndexSet
{
return _representedObject;
}
var indexArray = [],
frame = CGRectNull;
// Modifying the View
/*!
Sets the view that is used represent this object.
@param aView the view used to represent this object
*/
- (void)setView:(CPView)aView
{
_view = aView;
}
[anIndexSet getIndexes:indexArray maxCount:-1 inIndexRange:nil];
/*!
Returns the view that represents this object.
*/
- (CPView)view
{
return _view;
}
var index = 0,
count = [indexArray count];
// Modifying the Selection
/*!
Sets whether this view item should be selected.
@param shouldBeSelected <code>YES</code> makes the item selected. <code>NO</code> deselects it.
*/
- (void)setSelected:(BOOL)shouldBeSelected
{
if (_isSelected == shouldBeSelected)
return;
_isSelected = shouldBeSelected;
// FIXME: This should be set up by bindings
[_view setSelected:_isSelected];
}
for (; index < count; ++index)
frame = CGRectUnion(frame, [self frameForItemAtIndex:indexArray[index]]);
/*!
Returns <code>YES</code> if the item is currently selected. <code>NO</code> if the item is not selected.
*/
- (BOOL)isSelected
{
return _isSelected;
}
// Parent Collection View
/*!
Returns the collection view of which this item is a part.
*/
- (CPCollectionView)collectionView
{
return [_view superview];
return frame;
}
@end
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey";
@implementation CPCollectionView (KeyboardInteraction)
- (void)_modifySelectionWithNewIndex:(int)anIndex direction:(int)aDirection expand:(BOOL)shouldExpand
{
anIndex = MIN(MAX(anIndex, 0), [[self items] count] - 1);
if (_allowsMultipleSelection && shouldExpand)
{
var indexes = [_selectionIndexes copy],
bottomAnchor = [indexes firstIndex],
topAnchor = [indexes lastIndex];
// if the direction is backward (-1) check with the bottom anchor
if (aDirection === -1)
[indexes addIndexesInRange:CPMakeRange(anIndex, bottomAnchor - anIndex + 1)];
else
[indexes addIndexesInRange:CPMakeRange(topAnchor, anIndex - topAnchor + 1)];
}
else
indexes = [CPIndexSet indexSetWithIndex:anIndex];
[self setSelectionIndexes:indexes];
[self _scrollToSelection];
}
- (void)_scrollToSelection
{
var frame = [self frameForItemsAtIndexes:[self selectionIndexes]];
if (!CGRectIsNull(frame))
[self scrollRectToVisible:frame];
}
- (void)moveLeft:(id)sender
{
var index = [[self selectionIndexes] firstIndex];
if (index === CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - 1 direction:-1 expand:NO];
}
- (void)moveLeftAndModifySelection:(id)sender
{
var index = [[self selectionIndexes] firstIndex];
if (index === CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - 1 direction:-1 expand:YES];
}
- (void)moveRight:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + 1 direction:1 expand:NO];
}
- (void)moveRightAndModifySelection:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + 1 direction:1 expand:YES];
}
- (void)moveDown:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + [self numberOfColumns] direction:1 expand:NO];
}
- (void)moveDownAndModifySelection:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + [self numberOfColumns] direction:1 expand:YES];
}
- (void)moveUp:(id)sender
{
var index = [[self selectionIndexes] firstIndex];
if (index == CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - [self numberOfColumns] direction:-1 expand:NO];
}
- (void)moveUpAndModifySelection:(id)sender
{
var index = [[self selectionIndexes] firstIndex];
if (index == CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - [self numberOfColumns] direction:-1 expand:YES];
}
- (void)deleteBackward:(id)sender
{
if ([[self delegate] respondsToSelector:@selector(collectionView:shouldDeleteItemsAtIndexes:)])
{
[[self delegate] collectionView:self shouldDeleteItemsAtIndexes:[self selectionIndexes]];
var index = [[self selectionIndexes] firstIndex];
if (index > [[self content] count] - 1)
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:[[self content] count] - 1]];
[self _scrollToSelection];
[self setNeedsDisplay:YES];
}
}
- (void)keyDown:(CPEvent)anEvent
{
[self interpretKeyEvents:[anEvent]];
}
@end
@implementation CPCollectionView (Deprecated)
- (CGRect)rectForItemAtIndex:(int)anIndex
{
_CPReportLenientDeprecation([self class], _cmd, @selector(frameForItemAtIndex:));
// Don't re-compute anything just grab the current frame
// This allows subclasses to override tile without messing this up.
return [self frameForItemAtIndex:anIndex];
}
- (CGRect)rectForItemsAtIndexes:(CPIndexSet)anIndexSet
{
_CPReportLenientDeprecation([self class], _cmd, @selector(frameForItemsAtIndexes:));
return [self frameForItemsAtIndexes:anIndexSet];
}
@end
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
CPCollectionViewMaxNumberOfRowsKey = @"CPCollectionViewMaxNumberOfRowsKey",
CPCollectionViewMaxNumberOfColumnsKey = @"CPCollectionViewMaxNumberOfColumnsKey",
CPCollectionViewSelectableKey = @"CPCollectionViewSelectableKey",
CPCollectionViewAllowsMultipleSelectionKey = @"CPCollectionViewAllowsMultipleSelectionKey",
CPCollectionViewBackgroundColorsKey = @"CPCollectionViewBackgroundColorsKey";
@implementation CPCollectionView (CPCoding)
@@ -735,13 +909,25 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
_cachedItems = [];
_itemSize = CGSizeMakeZero();
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey];
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey];
_verticalMargin = [aCoder decodeSizeForKey:CPCollectionViewVerticalMarginKey];
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey] || CGSizeMakeZero();
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey] || CGSizeMakeZero();
_maxNumberOfRows = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfRowsKey] || 0;
_maxNumberOfColumns = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfColumnsKey] || 0;
_verticalMargin = [aCoder decodeFloatForKey:CPCollectionViewVerticalMarginKey];
_isSelectable = [aCoder decodeBoolForKey:CPCollectionViewSelectableKey];
_allowsMultipleSelection = [aCoder decodeBoolForKey:CPCollectionViewAllowsMultipleSelectionKey];
[self setBackgroundColors:[aCoder decodeObjectForKey:CPCollectionViewBackgroundColorsKey]];
_tileWidth = -1.0;
_selectionIndexes = [CPIndexSet indexSet];
_allowsEmptySelection = YES;
}
return self;
@@ -751,54 +937,21 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
{
[super encodeWithCoder:aCoder];
[aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey];
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
if (!CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
[aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey];
[aCoder encodeSize:_verticalMargin forKey:CPCollectionViewVerticalMarginKey];
if (!CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
[aCoder encodeInt:_maxNumberOfRows forKey:CPCollectionViewMaxNumberOfRowsKey];
[aCoder encodeInt:_maxNumberOfColumns forKey:CPCollectionViewMaxNumberOfColumnsKey];
[aCoder encodeBool:_isSelectable forKey:CPCollectionViewSelectableKey];
[aCoder encodeBool:_allowsMultipleSelection forKey:CPCollectionViewAllowsMultipleSelectionKey];
[aCoder encodeFloat:_verticalMargin forKey:CPCollectionViewVerticalMarginKey];
[aCoder encodeObject:_backgroundColors forKey:CPCollectionViewBackgroundColorsKey];
}
@end
var CPCollectionViewItemViewKey = @"CPCollectionViewItemViewKey";
@implementation CPCollectionViewItem (CPCoding)
/*
FIXME Not yet implemented
*/
- (id)copy
{
}
@end
var CPCollectionViewItemViewKey = @"CPCollectionViewItemViewKey";
@implementation CPCollectionViewItem (CPCoding)
/*!
Initializes the view item by unarchiving data from a coder.
@param aCoder the coder from which the data will be unarchived
@return the initialized collection view item
*/
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
_view = [aCoder decodeObjectForKey:CPCollectionViewItemViewKey];
return self;
}
/*!
Archives the colletion view item to the provided coder.
@param aCoder the coder to which the view item should be archived
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_view forKey:CPCollectionViewItemViewKey];
}
@end
+86
View File
@@ -0,0 +1,86 @@
/*
* CPCollectionViewItem.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPViewController.j"
/*!
Represents an object inside a CPCollectionView.
*/
@implementation CPCollectionViewItem : CPViewController
{
BOOL _isSelected;
}
// Setting the Represented Object
/*!
Sets the object to be represented by this item.
@param anObject the object to be represented
*/
- (void)setRepresentedObject:(id)anObject
{
[super setRepresentedObject:anObject];
var view = [self view];
if ([view respondsToSelector:@selector(setRepresentedObject:)])
[view setRepresentedObject:[self representedObject]];
}
// Modifying the Selection
/*!
Sets whether this view item should be selected.
@param shouldBeSelected \c YES makes the item selected. \c NO deselects it.
*/
- (void)setSelected:(BOOL)shouldBeSelected
{
shouldBeSelected = !!shouldBeSelected;
if (_isSelected === shouldBeSelected)
return;
_isSelected = shouldBeSelected;
var view = [self view];
if ([view respondsToSelector:@selector(setSelected:)])
[view setSelected:[self isSelected]];
}
/*!
Returns \c YES if the item is currently selected. \c NO if the item is not selected.
*/
- (BOOL)isSelected
{
return _isSelected;
}
// Parent Collection View
/*!
Returns the collection view of which this item is a part.
*/
- (CPCollectionView)collectionView
{
return [_view superview];
}
@end
+181 -149
View File
@@ -32,7 +32,7 @@ var _redComponent = 0,
_greenComponent = 1,
_blueComponent = 2,
_alphaCompnent = 3;
var _hueComponent = 0,
_saturationComponent = 1,
_brightnessComponent = 2;
@@ -46,30 +46,29 @@ var cachedBlackColor,
cachedLightGrayColor,
cachedDarkGrayColor,
cachedWhiteColor,
cachedBrownColor,
cachedCyanColor,
cachedMagentaColor,
cachedOrangeColor,
cachedPurpleColor,
cachedShadowColor,
cachedClearColor;
/*!
/*!
@ingroup appkit
@code CPColor
<code>CPColor</code> can be used to represent color
\c CPColor can be used to represent color
in an RGB or HSB model with an optional transparency value.</p>
<p>It also provides some class helper methods that
returns instances of commonly used colors.</p>
<p>The class does not have a <code>set:</code> method
like NextStep based frameworks to change the color of
the current context. To change the color of the current
context, use CGContextSetFillColor().
*/
@implementation CPColor : CPObject
{
CPArray _components;
CPImage _patternImage;
CPString _cssString;
CPString _cssString;
}
/*!
@@ -77,12 +76,12 @@ var cachedBlackColor,
Each component should be between the range of 0.0 to 1.0. For
the alpha component, a value of 1.0 is opaque, and 0.0 means
completely transparent.
@param red the red component of the color
@param green the green component of the color
@param blue the blue component of the color
@param alpha the alpha component
@return a color initialized to the values specified
*/
+ (CPColor)colorWithRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
@@ -92,17 +91,17 @@ var cachedBlackColor,
/*!
@deprecated in favor of colorWithRed:green:blue:alpha:
Creates a color in the RGB color space, with an alpha value.
Each component should be between the range of 0.0 to 1.0. For
the alpha component, a value of 1.0 is opaque, and 0.0 means
completely transparent.
@param red the red component of the color
@param green the green component of the color
@param blue the blue component of the color
@param alpha the alpha component
@return a color initialized to the values specified
*/
+ (CPColor)colorWithCalibratedRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
@@ -112,12 +111,12 @@ var cachedBlackColor,
/*!
Creates a new color object with <code>white</code> for the RGB components.
Creates a new color object with \c white for the RGB components.
For the alpha component, a value of 1.0 is opaque, and 0.0 means completely transparent.
@param white a float between 0.0 and 1.0
@param alpha the alpha component between 0.0 and 1.0
@return a color initialized to the values specified
*/
+ (CPColor)colorWithWhite:(float)white alpha:(float)alpha
@@ -127,13 +126,13 @@ var cachedBlackColor,
/*!
@deprecated in favor of colorWithWhite:apha:
Creates a new color object with <code>white</code> for the RGB components.
Creates a new color object with \c white for the RGB components.
For the alpha component, a value of 1.0 is opaque, and 0.0 means completely transparent.
@param white a float between 0.0 and 1.0
@param alpha the alpha component between 0.0 and 1.0
@return a color initialized to the values specified
*/
+ (CPColor)colorWithCalibratedWhite:(float)white alpha:(float)alpha
@@ -143,11 +142,11 @@ var cachedBlackColor,
/*!
Creates a new color in HSB space.
@param hue the hue value
@param saturation the saturation value
@param brightness the brightness value
@return the initialized color
*/
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness
@@ -157,16 +156,16 @@ var cachedBlackColor,
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness alpha:(float)alpha
{
if(saturation === 0.0)
if (saturation === 0.0)
return [CPColor colorWithCalibratedWhite:brightness / 100.0 alpha:alpha];
var f = hue % 60,
p = (brightness * (100 - saturation)) / 10000,
q = (brightness * (6000 - saturation * f)) / 600000,
t = (brightness * (6000 - saturation * (60 -f))) / 600000,
b = brightness / 100.0;
switch(FLOOR(hue / 60))
switch (FLOOR(hue / 60))
{
case 0: return [CPColor colorWithCalibratedRed: b green: t blue: p alpha: alpha];
case 1: return [CPColor colorWithCalibratedRed: q green: b blue: p alpha: alpha];
@@ -181,7 +180,7 @@ var cachedBlackColor,
Creates an RGB color from a hexadecimal string. For example,
the a string of "FFFFFF" would return a white CPColor.
"FF0000" would return a pure red, "00FF00" would return a
pure blue, and "0000FF" would return a pure green.
pure blue, and "0000FF" would return a pure green.
@param hex a 6 character long string of hex
@@ -189,7 +188,8 @@ var cachedBlackColor,
*/
+ (CPColor)colorWithHexString:(string)hex
{
return [[CPColor alloc] _initWithRGBA: hexToRGB(hex)];
var rgba = hexToRGB(hex);
return rgba ? [[CPColor alloc] _initWithRGBA: rgba] : null;
}
/*!
@@ -291,6 +291,61 @@ var cachedBlackColor,
return cachedYellowColor;
}
/*!
Returns a brown color object (RGBA=[0.6, 0.4, 0.2, 1.0])
*/
+ (CPColor)brownColor
{
if (!cachedBrownColor)
cachedBrownColor = [[CPColor alloc] _initWithRGBA:[0.6, 0.4, 0.2, 1.0]];
return cachedBrownColor;
}
/*!
Returns a cyan color object (RGBA=[0.0, 1.0, 1.0, 1.0])
*/
+ (CPColor)cyanColor
{
if (!cachedCyanColor)
cachedCyanColor = [[CPColor alloc] _initWithRGBA:[0.0, 1.0, 1.0, 1.0]];
return cachedCyanColor;
}
/*!
Returns a magenta color object (RGBA=[1.0, 0.0, 1.0, 1.0])
*/
+ (CPColor)magentaColor
{
if (!cachedMagentaColor)
cachedMagentaColor = [[CPColor alloc] _initWithRGBA:[1.0, 0.0, 1.0, 1.0]];
return cachedMagentaColor;
}
/*!
Returns a orange color object (RGBA=[1.0, 0.5, 0.0, 1.0])
*/
+ (CPColor)orangeColor
{
if (!cachedOrangeColor)
cachedOrangeColor = [[CPColor alloc] _initWithRGBA:[1.0, 0.5, 0.0, 1.0]];
return cachedOrangeColor;
}
/*!
Returns a purple color object (RGBA=[0.5, 0.0, 0.5, 1.0])
*/
+ (CPColor)purpleColor
{
if (!cachedPurpleColor)
cachedPurpleColor = [[CPColor alloc] _initWithRGBA:[0.5, 0.0, 0.5, 1.0]];
return cachedPurpleColor;
}
/*!
Returns a shadow looking color (RGBA=[0.0, 0.0, 0.0, 0.33])
*/
@@ -315,8 +370,18 @@ var cachedBlackColor,
return cachedClearColor;
}
+ (CPColor)alternateSelectedControlColor
{
return [[CPColor alloc] _initWithRGBA:[0.22, 0.46, 0.84, 1.0]];
}
+ (CPColor)secondarySelectedControlColor
{
return [[CPColor alloc] _initWithRGBA:[0.83, 0.83, 0.83, 1.0]];
}
/*!
Creates a color using a tile pattern with <code>anImage</code>
Creates a color using a tile pattern with \c anImage
@param the image to tile
@return a tiled image color object
*/
@@ -327,7 +392,7 @@ var cachedBlackColor,
/*!
Creates a CPColor from a valid CSS RGB string. Example, "rgb(32,64,129)".
@param aString a CSS color string
@return a color initialized to the value in the css string
*/
@@ -339,23 +404,23 @@ var cachedBlackColor,
/* @ignore */
- (id)_initWithCSSString:(CPString)aString
{
if(aString.indexOf("rgb") == CPNotFound)
if (aString.indexOf("rgb") == CPNotFound)
return nil;
self = [super init];
var startingIndex = aString.indexOf("(");
var parts = aString.substring(startingIndex+1).split(',');
var startingIndex = aString.indexOf("("),
parts = aString.substring(startingIndex + 1).split(',');
_components = [
parseInt(parts[0], 10) / 255.0,
parseInt(parts[1], 10) / 255.0,
parseInt(parts[2], 10) / 255.0,
parts[3] ? parseInt(parts[3], 10) / 255.0 : 1.0
]
parts[3] ? parseInt(parts[3], 10) / 255.0 : 1.0
];
_cssString = aString;
return self;
}
@@ -363,55 +428,20 @@ var cachedBlackColor,
- (id)_initWithRGBA:(CPArray)components
{
self = [super init];
if (self)
{
_components = components;
if (!CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0 && window.Base64 && window.CRC32)
{
var bytes = [0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,0x8,0x3,0x0,0x0,0x0,0x28,0xcb,0x34,0xbb,0x0,0x0,0x3,0x0,0x50,0x4c,0x54,0x45,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x17,0x89,0x99,0x55,0x0,0x0,0x0,0x1,0x74,0x52,0x4e,0x53,0x0,0x40,0xe6,0xd8,0x66,0x0,0x0,0x0,0x10,0x49,0x44,0x41,0x54,0x78,0xda,0x62,0x60,0x0,0x0,0x0,0x0,0xff,0xff,0x3,0x0,0x0,0x2,0x0,0x1,0x24,0x7f,0x24,0xf1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82,0xff];
var r_off = 41;
var g_off = 42;
var b_off = 43;
var a_off = 821;
var plte_crc_off = 809;
var trns_crc_off = 822;
var plte_type_off = 37;
var trns_type_off = 817;
bytes[r_off] = Math.round(_components[0]*255);
bytes[g_off] = Math.round(_components[1]*255);
bytes[b_off] = Math.round(_components[2]*255);
bytes[a_off] = Math.round(_components[3]*255);
// calculate new CRCs
var new_plte_crc = integerToBytes(CRC32.getCRC(bytes, plte_type_off, 4+768), 4);
var new_trns_crc = integerToBytes(CRC32.getCRC(bytes, trns_type_off, 4+1), 4);
// overwrite old CRCs with new ones
for (var i = 0; i < 4; i++)
{
bytes[plte_crc_off+i] = new_plte_crc[i];
bytes[trns_crc_off+i] = new_trns_crc[i];
}
// Base64 encode, strip whitespace and build data URL
var base64image = Base64.encode(bytes); //.replace(/[\s]/g, "");
_cssString = "url(\"data:image/png;base64," + base64image + "\")";
}
else
{
var hasAlpha = CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0;
_cssString = (hasAlpha ? "rgba(" : "rgb(") +
parseInt(_components[0] * 255.0) + ", " +
parseInt(_components[1] * 255.0) + ", " +
parseInt(_components[2] * 255.0) +
(hasAlpha ? (", " + _components[3]) : "") + ")";
}
var hasAlpha = CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0;
_cssString = (hasAlpha ? "rgba(" : "rgb(") +
parseInt(_components[0] * 255.0) + ", " +
parseInt(_components[1] * 255.0) + ", " +
parseInt(_components[2] * 255.0) +
(hasAlpha ? (", " + _components[3]) : "") + ")";
}
return self;
}
@@ -419,13 +449,14 @@ var cachedBlackColor,
- (id)_initWithPatternImage:(CPImage)anImage
{
self = [super init];
if (self)
{
_patternImage = anImage;
_cssString = "url(\"" + [_patternImage filename] + "\")";
_components = [0.0, 0.0, 0.0, 1.0];
}
return self;
}
@@ -487,17 +518,17 @@ var cachedBlackColor,
/*!
Returns a new color with the same RGB as the receiver but a new alpha component.
@param anAlphaComponent the alpha component for the new color
@return a new color object
*/
- (CPColor)colorWithAlphaComponent:(float)anAlphaComponent
{
var components = _components.slice();
components[components.length - 1] = anAlphaComponent;
return [[[self class] alloc] _initWithRGBA:components];
}
@@ -516,37 +547,40 @@ var cachedBlackColor,
var red = ROUND(_components[_redComponent] * 255.0),
green = ROUND(_components[_greenComponent] * 255.0),
blue = ROUND(_components[_blueComponent] * 255.0);
var max = MAX(red, green, blue),
min = MIN(red, green, blue),
delta = max - min;
var brightness = max / 255.0,
saturation = (max != 0) ? delta / max : 0;
var hue;
if(saturation == 0)
if (saturation == 0)
{
hue = 0;
}
else
{
var rr = (max - red) / delta;
var gr = (max - green) / delta;
var br = (max - blue) / delta;
if (red == max)
var rr = (max - red) / delta,
gr = (max - green) / delta,
br = (max - blue) / delta;
if (red == max)
hue = br - gr;
else if (green == max)
else if (green == max)
hue = 2 + rr - br;
else
else
hue = 4 + gr - rr;
hue /= 6;
if (hue < 0)
if (hue < 0)
hue++;
}
return [
ROUND(hue * 360.0),
ROUND(hue * 360.0),
ROUND(saturation * 100.0),
ROUND(brightness * 100.0)
];
@@ -594,7 +628,7 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
@implementation CPColor (CoreGraphicsExtensions)
/*!
/*!
Set's the receiver to be the fill and stroke color in the current graphics context
*/
- (void)set
@@ -603,16 +637,16 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
[self setStroke];
}
/*!
/*!
Set's the receiver to be the fill color in the current graphics context
*/
- (void)setFill
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetFillColor(ctx, self);
CGContextSetFillColor(ctx, self);
}
/*!
/*!
Set's the receiver to be the stroke color in the current graphics context
*/
- (void)setStroke
@@ -623,6 +657,15 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
@end
@implementation CPColor (Debugging)
+ (CPColor)randomColor
{
return [CPColor colorWithRed:RAND() green:RAND() blue:RAND() alpha:1.0];
}
@end
var CPColorComponentsKey = @"CPColorComponentsKey",
CPColorPatternImageKey = @"CPColorPatternImageKey";
@@ -636,7 +679,7 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
{
if ([aCoder containsValueForKey:CPColorPatternImageKey])
return [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
return [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
}
@@ -654,59 +697,48 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
@end
var hexCharacters = "0123456789ABCDEF";
/*!
Used for the CPColor <code>colorWithHexString:</code> implementation
Used for the CPColor \c +colorWithHexString: implementation
@ignore
@class CPColor
@return an array of rgb components
*/
function hexToRGB(hex)
var hexToRGB = function(hex)
{
if ( hex.length == 3 )
if (hex.length == 3)
hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
if(hex.length != 6)
if (hex.length != 6)
return null;
hex = hex.toUpperCase();
for(var i=0; i<hex.length; i++)
if(hexCharacters.indexOf(hex.charAt(i)) == -1)
for (var i = 0; i < hex.length; i++)
if (hexCharacters.indexOf(hex.charAt(i)) == -1)
return null;
var red = (hexCharacters.indexOf(hex.charAt(0)) * 16 + hexCharacters.indexOf(hex.charAt(1))) / 255.0;
var green = (hexCharacters.indexOf(hex.charAt(2)) * 16 + hexCharacters.indexOf(hex.charAt(3))) / 255.0;
var blue = (hexCharacters.indexOf(hex.charAt(4)) * 16 + hexCharacters.indexOf(hex.charAt(5))) / 255.0;
var red = (hexCharacters.indexOf(hex.charAt(0)) * 16 + hexCharacters.indexOf(hex.charAt(1))) / 255.0,
green = (hexCharacters.indexOf(hex.charAt(2)) * 16 + hexCharacters.indexOf(hex.charAt(3))) / 255.0,
blue = (hexCharacters.indexOf(hex.charAt(4)) * 16 + hexCharacters.indexOf(hex.charAt(5))) / 255.0;
return [red, green, blue, 1.0];
}
};
function integerToBytes(integer, length) {
if (!length)
length = (integer == 0) ? 1 : Math.round((Math.log(integer)/Math.log(2))/8+0.5);
var bytes = new Array(length);
for (var i = length-1; i >= 0; i--) {
bytes[i] = integer & 255;
integer = integer >> 8
}
return bytes;
}
function rgbToHex(r,g,b) {
var rgbToHex = function(r,g,b)
{
return byteToHex(r) + byteToHex(g) + byteToHex(b);
}
};
function byteToHex(n) {
if (!n || isNaN(n)) return "00";
n = ROUND(MIN(255,MAX(0,256*n)));
return hexCharacters.charAt((n - n % 16) / 16) +
hexCharacters.charAt(n % 16);
}
var byteToHex = function(n)
{
if (!n || isNaN(n))
return "00";
// Toll-Free bridge CPColor to CGColor.
//CGColor.prototype.isa = CPColor;
//[CPColor initialize];
n = FLOOR(MIN(255, MAX(0, 256 * n)));
//http://dev.mootools.net/browser/trunk/Source/Utilities/Color.js?rev=1184
return hexCharacters.charAt((n - n % 16) / 16) +
hexCharacters.charAt(n % 16);
};
+95 -91
View File
@@ -20,11 +20,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPApplication.j"
@import "CPButton.j"
@import "CPCookie.j"
@import "CPPanel.j"
@import "CPView.j"
CPColorPanelColorDidChangeNotification = @"CPColorPanelColorDidChangeNotification";
var PREVIEW_HEIGHT = 20.0,
@@ -35,7 +37,7 @@ var PREVIEW_HEIGHT = 20.0,
var SharedColorPanel = nil,
ColorPickerClasses = [];
/*
A color wheel
@global
@@ -52,16 +54,16 @@ CPSliderColorPickerMode = 2;
CPColorPickerViewWidth = 265,
CPColorPickerViewHeight = 370;
/*!
/*!
@ingroup appkit
@class CPColorPanel
CPColorPanel provides a reusable panel that can be used
displayed on screen to prompt the user for a color selection. To
obtain the panel, call the <code>sharedColorPanel</code> method.
obtain the panel, call the \c +sharedColorPanel method.
*/
@implementation CPColorPanel : CPPanel
{
{
_CPColorPanelToolbar _toolbar;
_CPColorPanelSwatches _swatchView;
_CPColorPanelPreview _previewView;
@@ -80,8 +82,8 @@ CPColorPickerViewHeight = 370;
int _mode;
}
/*!
A list of color pickers is collected here, and any color panel created will contain
/*!
A list of color pickers is collected here, and any color panel created will contain
any picker in this list up to this point. In other words, call before creating a color panel.
*/
+ (void)provideColorPickerClass:(Class)aColorPickerSubclass
@@ -96,7 +98,7 @@ CPColorPickerViewHeight = 370;
{
if (!SharedColorPanel)
SharedColorPanel = [[CPColorPanel alloc] init];
return SharedColorPanel;
}
@@ -107,16 +109,16 @@ CPColorPickerViewHeight = 370;
+ (void)setPickerMode:(CPColorPanelMode)mode
{
var panel = [CPColorPanel sharedColorPanel];
[panel setMode: mode];
[panel setMode:mode];
}
/*
To obtain the color panel, use <code>sharedColorPanel</code>.
To obtain the color panel, use \c +sharedColorPanel.
@ignore
*/
- (id)init
{
self = [super initWithContentRect:CGRectMake(500.0, 50.0, 219.0, 370.0)
self = [super initWithContentRect:CGRectMake(500.0, 50.0, 219.0, 370.0)
styleMask:(CPTitledWindowMask | CPClosableWindowMask | CPResizableWindowMask)];
if (self)
@@ -125,30 +127,30 @@ CPColorPickerViewHeight = 370;
[self setTitle:@"Color Panel"];
[self setLevel:CPFloatingWindowLevel];
[self setFloatingPanel:YES];
[self setBecomesKeyOnlyIfNeeded:YES];
[self setMinSize:CGSizeMake(219.0, 342.0)];
[self setMaxSize:CGSizeMake(323.0, 537.0)];
}
return self;
}
/*!
Sets the color of the panel, and updates the picker. Also posts a <code>CPColorPanelDidChangeNotification</code>.
Sets the color of the panel, and updates the picker. Also posts a \c CPColorPanelDidChangeNotification.
*/
- (void)setColor:(CPColor)aColor
{
{
_color = aColor;
[_previewView setBackgroundColor: _color];
[CPApp sendAction:@selector(changeColor:) to:nil from:self];
if (_target && _action)
[CPApp sendAction:_action to:_target from:self];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPColorPanelColorDidChangeNotification
object:self];
@@ -165,7 +167,7 @@ CPColorPickerViewHeight = 370;
- (void)setColor:(CPColor)aColor updatePicker:(BOOL)bool
{
[self setColor:aColor];
if (bool)
[_activePicker setColor:_color];
}
@@ -232,30 +234,30 @@ CPColorPickerViewHeight = 370;
{
var picker = _colorPickers[[sender tag]],
view = [picker provideNewView:NO];
if (!view)
view = [picker provideNewView:YES];
if (view == _currentView)
return;
if (_currentView)
[view setFrame:[_currentView frame]];
else
{
var height = (TOOLBAR_HEIGHT+10+PREVIEW_HEIGHT+5+SWATCH_HEIGHT+32),
var height = (TOOLBAR_HEIGHT + 10 + PREVIEW_HEIGHT + 5 + SWATCH_HEIGHT + 32),
bounds = [[self contentView] bounds];
[view setFrameSize: CPSizeMake(bounds.size.width - 10, bounds.size.height - height)];
[view setFrameOrigin: CPPointMake(5, height)];
[view setFrameSize:CPSizeMake(bounds.size.width - 10, bounds.size.height - height)];
[view setFrameOrigin:CPPointMake(5, height)];
}
[_currentView removeFromSuperview];
[[self contentView] addSubview:view];
_currentView = view;
_activePicker = picker;
[picker setColor:[self color]];
}
@@ -285,7 +287,7 @@ CPColorPickerViewHeight = 370;
_colorPickers = [];
var count = [ColorPickerClasses count];
for (var i=0; i<count; i++)
for (var i = 0; i < count; i++)
{
var currentPickerClass = ColorPickerClasses[i],
currentPicker = [[currentPickerClass alloc] initWithPickerMask:0 colorPanel:self];
@@ -297,29 +299,29 @@ CPColorPickerViewHeight = 370;
bounds = [contentView bounds];
_toolbar = [[CPView alloc] initWithFrame:CGRectMake(0, 6, CGRectGetWidth(bounds), TOOLBAR_HEIGHT)];
[_toolbar setAutoresizingMask: CPViewWidthSizable];
[_toolbar setAutoresizingMask: CPViewWidthSizable];
var totalToolbarWidth = count * ICON_WIDTH + (count - 1) * ICON_PADDING,
leftOffset = (CGRectGetWidth(bounds) - totalToolbarWidth) / 2.0,
buttonForLater = nil;
for (var i=0; i<count; i++)
for (var i = 0; i < count; i++)
{
var image = [_colorPickers[i] provideNewButtonImage],
highlightImage = [_colorPickers[i] provideNewAlternateButtonImage],
button = [[CPButton alloc] initWithFrame:CGRectMake(leftOffset + i*(ICON_WIDTH+ICON_PADDING), 0, ICON_WIDTH, ICON_WIDTH)];
button = [[CPButton alloc] initWithFrame:CGRectMake(leftOffset + i * (ICON_WIDTH + ICON_PADDING), 0, ICON_WIDTH, ICON_WIDTH)];
[button setTag:i];
[button setTarget:self];
[button setAction:@selector(_setPicker:)];
[button setBordered:NO];
[button setAutoresizingMask:CPViewMinXMargin|CPViewMaxXMargin];
[button setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin];
[button setImage:image];
[button setAlternateImage:highlightImage];
[_toolbar addSubview:button];
if (!buttonForLater)
buttonForLater = button;
}
@@ -330,7 +332,7 @@ CPColorPickerViewHeight = 370;
_previewView = [[_CPColorPanelPreview alloc] initWithFrame:CGRectInset([previewBox bounds], 2.0, 2.0)];
[_previewView setColorPanel:self];
[_previewView setAutoresizingMask:CPViewWidthSizable];
[_previewView setAutoresizingMask:CPViewWidthSizable];
[previewBox setBackgroundColor:[CPColor colorWithWhite:0.8 alpha:1.0]];
[previewBox setAutoresizingMask:CPViewWidthSizable];
@@ -338,7 +340,7 @@ CPColorPickerViewHeight = 370;
[previewBox addSubview:_previewView];
var _previewLabel = [[CPTextField alloc] initWithFrame: CPRectMake(10, TOOLBAR_HEIGHT + 10, 60, 15)];
[_previewLabel setStringValue: "Preview:"];
[_previewLabel setStringValue:"Preview:"];
[_previewLabel setTextColor:[CPColor blackColor]];
[_previewLabel setAlignment:CPRightTextAlignment];
@@ -350,8 +352,8 @@ CPColorPickerViewHeight = 370;
_swatchView = [[_CPColorPanelSwatches alloc] initWithFrame:CGRectInset([swatchBox bounds], 1.0, 1.0)];
[_swatchView setColorPanel: self];
[_swatchView setAutoresizingMask: CPViewWidthSizable];
[_swatchView setColorPanel:self];
[_swatchView setAutoresizingMask:CPViewWidthSizable];
[swatchBox addSubview:_swatchView];
@@ -367,7 +369,7 @@ CPColorPickerViewHeight = 370;
[opacityLabel setAlignment:CPRightTextAlignment];
_opacitySlider = [[CPSlider alloc] initWithFrame:CGRectMake(76, TOOLBAR_HEIGHT + PREVIEW_HEIGHT + 34, CGRectGetWidth(bounds) - 86, 20.0)];
[_opacitySlider setMinValue:0.0];
[_opacitySlider setMaxValue:1.0];
@@ -415,37 +417,37 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
CPCookie _swatchCookie;
}
-(id)initWithFrame:(CPRect)aFrame
- (id)initWithFrame:(CPRect)aFrame
{
self = [super initWithFrame:aFrame];
[self setBackgroundColor: [CPColor grayColor]];
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
var whiteColor = [CPColor whiteColor];
_swatchCookie = [[CPCookie alloc] initWithName: CPColorPanelSwatchesCookie];
var colorList = [self startingColorList];
_swatches = [];
for(var i=0; i < 50; i++)
for (var i = 0; i < 50; i++)
{
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
var view = [[CPView alloc] initWithFrame: CPRectMake(13*i+1, 1, 12, 12)],
var view = [[CPView alloc] initWithFrame: CPRectMake(13 * i + 1, 1, 12, 12)],
fillView = [[CPView alloc] initWithFrame:CGRectInset([view bounds], 1.0, 1.0)];
[view setBackgroundColor:whiteColor];
[fillView setBackgroundColor: (i < colorList.length) ? colorList[i] : whiteColor];
[view addSubview:fillView];
[self addSubview: view];
_swatches.push(view);
}
return self;
}
@@ -457,7 +459,8 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (CPArray)startingColorList
{
var cookieValue = [_swatchCookie value];
if(cookieValue == "")
if (cookieValue == "")
{
return [
[CPColor blackColor],
@@ -471,11 +474,11 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
[CPColor yellowColor]
];
}
var cookieValue = eval(cookieValue);
var result = [];
for(var i=0; i<cookieValue.length; i++)
var cookieValue = eval(cookieValue),
result = [];
for (var i = 0; i < cookieValue.length; i++)
result.push([CPColor colorWithHexString: cookieValue[i]]);
return result;
@@ -485,13 +488,13 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var result = [];
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
for(var i=0; i<_swatches.length; i++)
for (var i = 0; i < _swatches.length; i++)
result.push([[[_swatches[i] subviews][0] backgroundColor] hexString]);
var future = new Date();
future.setYear(2019);
[_swatchCookie setValue: CPJSObjectCreateJSON(result) expires:future domain: nil];
[_swatchCookie setValue: JSON.stringify(result) expires:future domain: nil];
}
- (void)setColorPanel:(CPColorPanel)panel
@@ -518,9 +521,10 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (void)mouseUp:(CPEvent)anEvent
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if(point.x > [self bounds].size.width - 1 || point.x < 1)
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
bounds = [self bounds];
if (!CGRectContainsPoint(bounds, point) || point.x > [self bounds].size.width - 1 || point.x < 1)
return NO;
[_colorPanel setColor: [self colorAtIndex:FLOOR(point.x / 13)] updatePicker: YES];
@@ -534,21 +538,21 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
return NO;
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPArray arrayWithObject:CPColorDragType] owner:self];
var swatch = _swatches[FLOOR(point.x / 13)];
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
_dragColor = [[swatch subviews][0] backgroundColor];
var bounds = CPRectCreateCopy([swatch bounds]);
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
var dragView = [[CPView alloc] initWithFrame: bounds];
var dragView = [[CPView alloc] initWithFrame: bounds],
dragFillView = [[CPView alloc] initWithFrame:CGRectInset(bounds, 1.0, 1.0)];
[dragView setBackgroundColor:[CPColor blackColor]];
[dragFillView setBackgroundColor:_dragColor];
[dragView addSubview:dragFillView];
[self dragView: dragView
@@ -562,20 +566,20 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
{
if(aType == CPColorDragType)
[aPasteboard setData:_dragColor forType:aType];
if (aType == CPColorDragType)
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:_dragColor] forType:aType];
}
- (void)performDragOperation:(id <CPDraggingInfo>)aSender
{
{
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
pasteboard = [aSender draggingPasteboard],
swatch = nil;
if(![pasteboard availableTypeFromArray:[CPColorDragType]] || location.x > [self bounds].size.width - 1 || location.x < 1)
if (![pasteboard availableTypeFromArray:[CPColorDragType]] || location.x > [self bounds].size.width - 1 || location.x < 1)
return NO;
[self setColor:[pasteboard dataForType:CPColorDragType] atIndex: FLOOR(location.x / 13)];
[self setColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] atIndex: FLOOR(location.x / 13)];
}
@end
@@ -589,9 +593,9 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (id)initWithFrame:(CPRect)aFrame
{
self = [super initWithFrame:aFrame];
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
return self;
}
@@ -609,11 +613,11 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var pasteboard = [aSender draggingPasteboard];
if(![pasteboard availableTypeFromArray:[CPColorDragType]])
if (![pasteboard availableTypeFromArray:[CPColorDragType]])
return NO;
var color = [pasteboard dataForType:CPColorDragType];
[_colorPanel setColor: color updatePicker: YES];
var color = [CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]];
[_colorPanel setColor:color updatePicker:YES];
}
- (BOOL)isOpaque
@@ -625,19 +629,19 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPArray arrayWithObject:CPColorDragType] owner:self];
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPColorDragType] owner:self];
var bounds = CPRectMake(0, 0, 15, 15);
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
var dragView = [[CPView alloc] initWithFrame: bounds];
var dragView = [[CPView alloc] initWithFrame: bounds],
dragFillView = [[CPView alloc] initWithFrame:CGRectInset(bounds, 1.0, 1.0)];
[dragView setBackgroundColor:[CPColor blackColor]];
[dragFillView setBackgroundColor:[self backgroundColor]];
[dragView addSubview:dragFillView];
[self dragView: dragView
at: CPPointMake(point.x - bounds.size.width / 2.0, point.y - bounds.size.height / 2.0)
offset: CPPointMake(0.0, 0.0)
@@ -649,8 +653,8 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
{
if(aType == CPColorDragType)
[aPasteboard setData:[self backgroundColor] forType:aType];
if (aType == CPColorDragType)
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:[self backgroundColor]] forType:aType];
}
@end
+41 -40
View File
@@ -21,13 +21,15 @@
*/
@import <Foundation/CPObject.j>
@import "CPColorPanel.j"
/*!
@import "CPView.j"
/*!
@ingroup appkit
@class CPColorPicker
CPColorPicker is an abstract superclass for all color picker subclasses. If you want a particular color picker, use CPColorPanel's <code>setPickerMode:</code> method. The simplest way to implement your own color picker is to create a subclass of CPColorPicker.
CPColorPicker is an abstract superclass for all color picker subclasses. If you want a particular color picker, use CPColorPanel's \c +setPickerMode: method. The simplest way to implement your own color picker is to create a subclass of CPColorPicker.
*/
@implementation CPColorPicker : CPObject
{
@@ -60,7 +62,7 @@
/*
FIXME Not implemented.
@return <code>nil</code>
@return \c nil
@ignore
*/
- (CPImage)provideNewButtonImage
@@ -100,18 +102,18 @@
CPColor _cachedColor;
}
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
{
return [super initWithPickerMask:mask colorPanel: owningColorPanel];
}
-(id)initView
- (id)initView
{
aFrame = CPRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
_pickerView = [[CPView alloc] initWithFrame:aFrame];
[_pickerView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
[_pickerView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
@@ -134,17 +136,17 @@
[_pickerView addSubview:_brightnessSlider];
}
-(void)brightnessSliderDidChange:(id)sender
- (void)brightnessSliderDidChange:(id)sender
{
[self updateColor];
}
-(void)colorWheelDidChange:(id)sender
- (void)colorWheelDidChange:(id)sender
{
[self updateColor];
}
-(void)updateColor
- (void)updateColor
{
var hue = [_hueSaturationView angle],
saturation = [_hueSaturationView distance],
@@ -221,7 +223,7 @@
float _radius;
}
-(id)initWithFrame:(CPRect)aFrame
- (id)initWithFrame:(CPRect)aFrame
{
self = [super initWithFrame:aFrame];
@@ -239,8 +241,10 @@
_blackWheelImage.style.filter = "alpha(opacity=0)"
_blackWheelImage.style.position = "absolute";
#if PLATFORM(DOM)
_DOMElement.appendChild(_wheelImage);
_DOMElement.appendChild(_blackWheelImage);
#endif
[self setWheelSize:aFrame.size];
@@ -257,19 +261,19 @@
return self;
}
-(void)setWheelBrightness:(float)brightness
- (void)setWheelBrightness:(float)brightness
{
_blackWheelImage.style.opacity = 1.0 - brightness;
_blackWheelImage.style.filter = "alpha(opacity=" + (1.0 - brightness)*100 + ")"
_blackWheelImage.style.filter = "alpha(opacity=" + (1.0 - brightness) * 100 + ")"
}
-(void)setFrameSize:(CPSize)aSize
- (void)setFrameSize:(CPSize)aSize
{
[super setFrameSize:aSize];
[self setWheelSize:aSize];
}
-(void)setWheelSize:(CPSize)aSize
- (void)setWheelSize:(CPSize)aSize
{
var min = MIN(aSize.width, aSize.height);
@@ -292,57 +296,55 @@
[self setAngle:[self degreesToRadians:_angle] distance:(_distance / 100.0) * _radius];
}
-(void)setDelegate:(id)aDelegate
- (void)setDelegate:(id)aDelegate
{
_delegate = aDelegate;
}
-(id)delegate
- (id)delegate
{
return _delegate;
}
-(float)angle
- (float)angle
{
return _angle;
}
-(float)distance
- (float)distance
{
return _distance;
}
-(void)mouseDown:(CPEvent)anEvent
- (void)mouseDown:(CPEvent)anEvent
{
[self reposition:anEvent];
}
-(void)mouseDragged:(CPEvent)anEvent
- (void)mouseDragged:(CPEvent)anEvent
{
[self reposition:anEvent];
}
-(void)reposition:(CPEvent)anEvent
- (void)reposition:(CPEvent)anEvent
{
var bounds = [self bounds],
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
var midX = CGRectGetMidX(bounds);
var midY = CGRectGetMidY(bounds);
var distance = MIN(SQRT((location.x - midX)*(location.x - midX) + (location.y - midY)*(location.y - midY)), _radius);
var angle = ATAN2(location.y - midY, location.x - midX);
location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
midX = CGRectGetMidX(bounds),
midY = CGRectGetMidY(bounds),
distance = MIN(SQRT((location.x - midX) * (location.x - midX) + (location.y - midY) * (location.y - midY)), _radius),
angle = ATAN2(location.y - midY, location.x - midX);
[self setAngle:angle distance:distance];
[_delegate colorWheelDidChange:self];
}
-(void)setAngle:(int)angle distance:(float)distance
- (void)setAngle:(int)angle distance:(float)distance
{
var bounds = [self bounds];
var midX = CGRectGetMidX(bounds);
var midY = CGRectGetMidY(bounds);
var bounds = [self bounds],
midX = CGRectGetMidX(bounds),
midY = CGRectGetMidY(bounds);
_angle = [self radiansToDegrees:angle];
_distance = (distance / _radius) * 100.0;
@@ -350,23 +352,22 @@
[_crosshair setFrameOrigin:CPPointMake(COS(angle) * distance + midX - 2.0, SIN(angle) * distance + midY - 2.0)];
}
-(void)setPositionToColor:(CPColor)aColor
- (void)setPositionToColor:(CPColor)aColor
{
var hsb = [aColor hsbComponents],
bounds = [self bounds];
var angle = [self degreesToRadians:hsb[0]],
bounds = [self bounds],
angle = [self degreesToRadians:hsb[0]],
distance = (hsb[1] / 100.0) * _radius;
[self setAngle:angle distance:distance];
}
-(int)radiansToDegrees:(float)radians
- (int)radiansToDegrees:(float)radians
{
return ((-radians / PI) * 180 + 360) % 360;
}
-(float)degreesToRadians:(float)degrees
- (float)degreesToRadians:(float)degrees
{
return -(((degrees - 360) / 180) * PI);
}
+41 -35
View File
@@ -29,19 +29,19 @@
var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiveNotification";
/*!
/*!
@ingroup appkit
@class CPColorWell
CPColorWell is a CPControl for selecting and displaying a single color value. An example of a CPColorWell object (or simply color well) is found in CPColorPanel, which uses a color well to display the current color selection.</p>
<p>An application can have one or more active CPColorWells. You can activate multiple CPColorWells by invoking the <code>activate:</code> method with <code>NO</code> as its argument. When a mouse-down event occurs on an CPColorWell's border, it becomes the only active color well. When a color well becomes active, it brings up the color panel also.
<p>An application can have one or more active CPColorWells. You can activate multiple CPColorWells by invoking the \c -activate: method with \c NO as its argument. When a mouse-down event occurs on an CPColorWell's border, it becomes the only active color well. When a color well becomes active, it brings up the color panel also.
*/
@implementation CPColorWell : CPControl
{
BOOL _active;
BOOL _bordered;
CPColor _color;
CPView _wellView;
}
@@ -49,19 +49,19 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_active = NO;
_bordered = YES;
_color = [CPColor whiteColor];
[self drawBezelWithHighlight:NO];
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
[self _registerForNotifications];
}
return self;
}
@@ -97,9 +97,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
if (_bordered == bordered)
return;
_bordered = bordered;
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
}
@@ -120,14 +120,14 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
if (_color == aColor)
return;
_color = aColor;
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
}
/*!
Changes the color of the well to that of <code>aSender</code>.
Changes the color of the well to that of \c aSender.
@param aSender the object from which to retrieve the color
*/
- (void)takeColorFrom:(id)aSender
@@ -137,8 +137,8 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
// Activating and Deactivating Color Wells
/*!
Activates the color well, displays the color panel, and makes the panel's current color the same as its own.
If exclusive is <code>YES</code>, deactivates any other CPColorWells. <code>NO</code>, keeps them active.
Activates the color well, displays the color panel, and makes the panel's current color the same as its own.
If exclusive is \c YES, deactivates any other CPColorWells. \c NO, keeps them active.
@param shouldBeExclusive whether other color wells should be deactivated.
*/
- (void)activate:(BOOL)shouldBeExclusive
@@ -152,9 +152,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
if ([self isActive])
return;
_active = YES;
[[CPNotificationCenter defaultCenter]
addObserver:self
selector:@selector(colorPanelDidChangeColor:)
@@ -169,9 +169,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
if (![self isActive])
return;
_active = NO;
[[CPNotificationCenter defaultCenter]
removeObserver:self
name:CPColorPanelColorDidChangeNotification
@@ -179,7 +179,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
}
/*!
Returns <code>YES</code> if the color well is active.
Returns \c YES if the color well is active.
*/
- (BOOL)isActive
{
@@ -202,19 +202,19 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
_wellView = [[CPView alloc] initWithFrame:aRect];
[_wellView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self addSubview:_wellView];
}
else
[_wellView setFrame:aRect];
[_wellView setBackgroundColor:_color];
}
- (void)colorPanelDidChangeColor:(CPNotification)aNotification
{
[self takeColorFrom:[aNotification object]];
[self sendAction:[self action] to:[self target]];
}
@@ -231,25 +231,31 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
- (void)mouseDown:(CPEvent)anEvent
{
if (![self isEnabled])
return;
[self drawBezelWithHighlight:YES];
}
- (void)mouseDragged:(CPEvent)anEvent
{
if (![self isEnabled])
return;
[self drawBezelWithHighlight:CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])];
}
-(void)mouseUp:(CPEvent)anEvent
- (void)mouseUp:(CPEvent)anEvent
{
[self drawBezelWithHighlight:NO];
if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]))
if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]) || ![self isEnabled])
return;
[self activate:YES];
var colorPanel = [CPColorPanel sharedColorPanel];
[colorPanel setColor:_color];
[colorPanel orderFront:self];
}
@@ -262,17 +268,17 @@ var CPColorWellColorKey = "CPColorWellColorKey",
@implementation CPColorWell (CPCoding)
/*!
Initializes the color well by unarchiving data from <code>aCoder</code>.
Initializes the color well by unarchiving data from \c aCoder.
@param aCoder the coder containing the archived CPColorWell.
*/
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_active = NO;
_bordered = [aCoder decodeObjectForKey:CPColorWellBorderedKey];
_bordered = [aCoder decodeBoolForKey:CPColorWellBorderedKey];
_color = [aCoder decodeObjectForKey:CPColorWellColorKey];
[self drawBezelWithHighlight:NO];
@@ -280,7 +286,7 @@ var CPColorWellColorKey = "CPColorWellColorKey",
[self _registerForNotifications];
}
return self;
}
@@ -290,17 +296,17 @@ var CPColorWellColorKey = "CPColorWellColorKey",
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
// We do this in order to avoid encoding the _wellView, which
// We do this in order to avoid encoding the _wellView, which
// should just automatically be created programmatically as needed.
var actualSubviews = _subviews;
_subviews = [_subviews copy];
[_subviews removeObjectIdenticalTo:_wellView];
[super encodeWithCoder:aCoder];
_subviews = actualSubviews;
[aCoder encodeObject:_color forKey:CPColorWellColorKey];
[aCoder encodeObject:_bordered forKey:CPColorWellBorderedKey];
}
+74 -42
View File
@@ -21,6 +21,8 @@
*/
@import "CPEvent.j"
@import "CPPlatform.j"
// Browser Engines
CPUnknownBrowserEngine = 0;
@@ -30,22 +32,28 @@ CPKHTMLBrowserEngine = 3;
CPOperaBrowserEngine = 4;
CPWebKitBrowserEngine = 5;
// Operating Systems
CPMacOperatingSystem = 0;
CPWindowsOperatingSystem = 1;
CPOtherOperatingSystem = 2;
// Features
CPCSSRGBAFeature = 1 << 5;
CPHTMLCanvasFeature = 1 << 6;
CPHTMLContentEditableFeature = 1 << 7;
CPHTMLDragAndDropFeature = 1 << 8;
CPJavascriptInnerTextFeature = 1 << 8;
CPJavascriptTextContentFeature = 1 << 9;
CPJavascriptClipboardEventsFeature = 1 << 10;
CPJavascriptClipboardAccessFeature = 1 << 11;
CPJavaScriptCanvasDrawFeature = 1 << 12;
CPJavaScriptCanvasTransformFeature = 1 << 13;
CPJavascriptInnerTextFeature = 1 << 9;
CPJavascriptTextContentFeature = 1 << 10;
CPJavascriptClipboardEventsFeature = 1 << 11;
CPJavascriptClipboardAccessFeature = 1 << 12;
CPJavaScriptCanvasDrawFeature = 1 << 13;
CPJavaScriptCanvasTransformFeature = 1 << 14;
CPVMLFeature = 1 << 14;
CPVMLFeature = 1 << 15;
CPJavascriptRemedialKeySupport = 1 << 15;
CPJavascriptRemedialKeySupport = 1 << 16;
CPJavaScriptShadowFeature = 1 << 20;
CPJavaScriptNegativeMouseWheelValues = 1 << 22;
@@ -54,8 +62,8 @@ CPJavaScriptMouseWheelValues_8_15 = 1 << 23
CPOpacityRequiresFilterFeature = 1 << 24;
//Internet explorer does not allow dynamically changing the type of an input element
CPInputTypeCanBeChangedFeature = 1 << 25;
CPInputTypeCanBeChangedFeature = 1 << 25;
CPHTML5DragAndDropSourceYOffBy1 = 1 << 26;
var USER_AGENT = "",
@@ -66,27 +74,27 @@ var USER_AGENT = "",
PLATFORM_FEATURES |= CPInputTypeCanBeChangedFeature;
if (typeof window != "undfined" && typeof window.navigator != "undefined")
if (typeof window !== "undefined" && typeof window.navigator !== "undefined")
USER_AGENT = window.navigator.userAgent;
// Opera
if (window.opera)
if (typeof window !== "undefined" && window.opera)
{
PLATFORM_ENGINE = CPOperaBrowserEngine;
PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature;
}
// Internet Explorer
else if (window.attachEvent) // Must follow Opera check.
else if (typeof window !== "undefined" && window.attachEvent) // Must follow Opera check.
{
PLATFORM_ENGINE = CPInternetExplorerBrowserEngine;
// Features we can only be sure of with IE (no known independent tests)
PLATFORM_FEATURES |= CPVMLFeature;
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
PLATFORM_FEATURES |= CPOpacityRequiresFilterFeature;
PLATFORM_FEATURES &= ~CPInputTypeCanBeChangedFeature;
@@ -96,20 +104,35 @@ else if (window.attachEvent) // Must follow Opera check.
else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
{
PLATFORM_ENGINE = CPWebKitBrowserEngine;
// Features we can only be sure of with WebKit (no known independent tests)
PLATFORM_FEATURES |= CPCSSRGBAFeature;
PLATFORM_FEATURES |= CPHTMLContentEditableFeature;
if (USER_AGENT.indexOf("Chrome") === -1)
PLATFORM_FEATURES |= CPHTMLDragAndDropFeature;
PLATFORM_FEATURES |= CPJavascriptClipboardEventsFeature;
PLATFORM_FEATURES |= CPJavascriptClipboardAccessFeature;
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
var versionStart = USER_AGENT.indexOf("AppleWebKit/") + "AppleWebKit/".length,
versionEnd = USER_AGENT.indexOf(" ", versionStart),
version = parseFloat(USER_AGENT.substring(versionStart, versionEnd), 10);
versionString = USER_AGENT.substring(versionStart, versionEnd),
versionDivision = versionString.indexOf('.'),
majorVersion = parseInt(versionString.substring(0, versionDivision)),
minorVersion = parseInt(versionString.substr(versionDivision + 1));
if(USER_AGENT.indexOf("Plainview") == -1 && version >= 525.14 || USER_AGENT.indexOf("Chrome") != -1)
if ((USER_AGENT.indexOf("Safari") !== CPNotFound && (majorVersion > 525 || (majorVersion === 525 && minorVersion > 14))) || USER_AGENT.indexOf("Chrome") !== CPNotFound)
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
// FIXME this is a terrible hack to get around this bug:
// https://bugs.webkit.org/show_bug.cgi?id=21548
if (![CPPlatform isBrowser])
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
if (majorVersion < 532 || (majorVersion === 532 && minorVersion < 6))
PLATFORM_FEATURES |= CPHTML5DragAndDropSourceYOffBy1;
}
// KHTML
@@ -119,22 +142,19 @@ else if (USER_AGENT.indexOf("KHTML") != -1) // Must follow WebKit check.
}
// Gecko
else if (USER_AGENT.indexOf("Gecko") != -1) // Must follow KHTML check.
else if (USER_AGENT.indexOf("Gecko") !== -1) // Must follow KHTML check.
{
PLATFORM_ENGINE = CPGeckoBrowserEngine;
PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature;
var index = USER_AGENT.indexOf("Firefox"),
version = (index == -1) ? 2.0 : parseFloat(USER_AGENT.substring(index + "Firefox".length + 1));
version = (index === -1) ? 2.0 : parseFloat(USER_AGENT.substring(index + "Firefox".length + 1));
if (version >= 3.0)
PLATFORM_FEATURES |= CPCSSRGBAFeature;
var geckoIndex = USER_AGENT.indexOf("Gecko"),
geckoVersion = (geckoIndex === -1) ? 0.0 : parseFloat(USER_AGENT.substring(geckoIndex + "Gecko".length + 1, USER_AGENT.indexOf(' ', geckoIndex)));
if (version < 20061028)
if (version < 3.0)
PLATFORM_FEATURES |= CPJavaScriptMouseWheelValues_8_15;
}
@@ -146,16 +166,16 @@ if (typeof document != "undefined")
if (canvasElement && canvasElement.getContext)
{
PLATFORM_FEATURES |= CPHTMLCanvasFeature;
// Detect Canvas setTransform/transform support
var context = document.createElement("canvas").getContext("2d");
if (context && context.setTransform && context.transform)
PLATFORM_FEATURES |= CPJavaScriptCanvasTransformFeature;
}
var DOMElement = document.createElement("div");
// Detect whether we have innerText or textContent (or neither)
if (DOMElement.innerText != undefined)
PLATFORM_FEATURES |= CPJavascriptInnerTextFeature;
@@ -170,26 +190,38 @@ function CPFeatureIsCompatible(aFeature)
function CPBrowserIsEngine(anEngine)
{
return PLATFORM_ENGINE == anEngine;
return PLATFORM_ENGINE === anEngine;
}
if (USER_AGENT.indexOf("Mac") != -1)
function CPBrowserIsOperatingSystem(anOperatingSystem)
{
return OPERATING_SYSTEM === anOperatingSystem;
}
OPERATING_SYSTEM = CPOtherOperatingSystem;
if (USER_AGENT.indexOf("Mac") !== -1)
{
OPERATING_SYSTEM = CPMacOperatingSystem;
CPPlatformActionKeyMask = CPCommandKeyMask;
CPUndoKeyEquivalent = @"Z";
CPUndoKeyEquivalent = @"z";
CPRedoKeyEquivalent = @"Z";
CPUndoKeyEquivalentModifierMask = CPCommandKeyMask;
CPRedoKeyEquivalentModifierMask = CPCommandKeyMask | CPShiftKeyMask;
CPRedoKeyEquivalentModifierMask = CPCommandKeyMask;
}
else
{
if (USER_AGENT.indexOf("Windows") !== -1)
OPERATING_SYSTEM = CPWindowsOperatingSystem;
CPPlatformActionKeyMask = CPControlKeyMask;
CPUndoKeyEquivalent = @"Z";
CPRedoKeyEquivalent = @"Y";
CPUndoKeyEquivalent = @"z";
CPRedoKeyEquivalent = @"y";
CPUndoKeyEquivalentModifierMask = CPControlKeyMask;
CPRedoKeyEquivalentModifierMask = CPControlKeyMask;
}
+234 -170
View File
@@ -23,51 +23,45 @@
@import "CPFont.j"
@import "CPShadow.j"
@import "CPView.j"
@import "CPKeyValueBinding.j"
#include "CoreGraphics/CGGeometry.h"
#include "Platform/Platform.h"
/*
@global
@group CPTextAlignment
*/
CPLeftTextAlignment = 0;
/*
@global
@group CPTextAlignment
*/
CPRightTextAlignment = 1;
/*
@global
@group CPTextAlignment
*/
CPCenterTextAlignment = 2;
/*
@global
@group CPTextAlignment
*/
CPJustifiedTextAlignment = 3;
/*
@global
@group CPTextAlignment
*/
CPNaturalTextAlignment = 4;
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
CPCenterTextAlignment = 2;
CPJustifiedTextAlignment = 3;
CPNaturalTextAlignment = 4;
/*
@global
@group CPControlSize
*/
CPRegularControlSize = 0;
/*
@global
@group CPControlSize
*/
CPSmallControlSize = 1;
/*
@global
@group CPControlSize
*/
CPMiniControlSize = 2;
CPRegularControlSize = 0;
CPSmallControlSize = 1;
CPMiniControlSize = 2;
CPLineBreakByWordWrapping = 0;
CPLineBreakByCharWrapping = 1;
CPLineBreakByClipping = 2;
CPLineBreakByTruncatingHead = 3;
CPLineBreakByTruncatingTail = 4;
CPLineBreakByTruncatingMiddle = 5;
CPTopVerticalTextAlignment = 1,
CPCenterVerticalTextAlignment = 2,
CPBottomVerticalTextAlignment = 3;
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
CPImageRight = 3;
CPImageBelow = 4;
CPImageAbove = 5;
CPImageOverlaps = 6;
CPOnState = 1;
CPOffState = 0;
CPMixedState = -1;
CPControlNormalBackgroundColor = "CPControlNormalBackgroundColor";
CPControlSelectedBackgroundColor = "CPControlSelectedBackgroundColor";
@@ -80,7 +74,7 @@ CPControlTextDidEndEditingNotification = "CPControlTextDidEndEditingNotific
var CPControlBlackColor = [CPColor blackColor];
/*!
/*!
@ingroup appkit
@class CPControl
@@ -89,20 +83,18 @@ var CPControlBlackColor = [CPColor blackColor];
@implementation CPControl : CPView
{
id _value;
// Target-Action Support
id _target;
SEL _action;
int _sendActionOn;
BOOL _sendsActionOnEndEditing @accessors(property=sendsActionOnEndEditing);
// Mouse Tracking Support
BOOL _continuousTracking;
BOOL _trackingWasWithinFrame;
unsigned _trackingMouseDownFlags;
CGPoint _previousTrackingLocation;
JSObject _ephemeralSubviewsForNames;
CPSet _ephereralSubviews;
CPString _toolTip;
}
@@ -114,7 +106,7 @@ var CPControlBlackColor = [CPColor blackColor];
CPLineBreakByClipping,
[CPColor blackColor],
[CPFont systemFontOfSize:12.0],
nil,
[CPNull null],
_CGSizeMakeZero(),
CPImageLeft,
CPScaleToFit,
@@ -133,16 +125,46 @@ var CPControlBlackColor = [CPColor blackColor];
@"max-size"]];
}
+ (void)initialize
{
if (self === [CPControl class])
{
[self exposeBinding:@"value"];
[self exposeBinding:@"objectValue"];
[self exposeBinding:@"stringValue"];
[self exposeBinding:@"integerValue"];
[self exposeBinding:@"intValue"];
[self exposeBinding:@"doubleValue"];
[self exposeBinding:@"floatValue"];
[self exposeBinding:@"enabled"];
}
}
- (void)_reverseSetBinding
{
var theBinding = [CPKeyValueBinding getBinding:CPValueBinding forObject:self];
[theBinding reverseSetValueFor:@"objectValue"];
}
- (void)_replacementKeyPathForBinding:(CPString)aBinding
{
if (aBinding === @"value")
return @"objectValue";
return [super _replacementKeyPathForBinding:aBinding];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_sendActionOn = CPLeftMouseUpMask;
_trackingMouseDownFlags = 0;
}
return self;
}
@@ -181,21 +203,22 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Causes <code>anAction</code> to be sent to <code>anObject</code>.
Causes \c anAction to be sent to \c anObject.
@param anAction the action to send
@param anObject the object to which the action will be sent
*/
- (void)sendAction:(SEL)anAction to:(id)anObject
{
[self _reverseSetBinding];
[CPApp sendAction:anAction to:anObject from:self];
}
- (int)sendActionOn:(int)mask
{
var previousMask = _sendActionOn;
_sendActionOn = mask;
return previousMask;
}
@@ -208,7 +231,7 @@ var CPControlBlackColor = [CPColor blackColor];
{
if (_toolTip == aToolTip)
return;
_toolTip = aToolTip;
#if PLATFORM(DOM)
@@ -243,7 +266,7 @@ var CPControlBlackColor = [CPColor blackColor];
// Some subclasses should redefine this with CPLeftMouseDraggedMask
if (flag)
_sendActionOn |= CPPeriodicMask;
else
else
_sendActionOn &= ~CPPeriodicMask;
}
@@ -255,16 +278,15 @@ var CPControlBlackColor = [CPColor blackColor];
- (void)trackMouse:(CPEvent)anEvent
{
var type = [anEvent type],
currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil];
currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
isWithinFrame = [self tracksMouseOutsideOfFrame] || CGRectContainsPoint([self bounds], currentLocation);
if (type === CPLeftMouseUp)
{
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:YES];
_trackingMouseDownFlags = 0;
}
else
{
if (type === CPLeftMouseDown)
@@ -278,29 +300,57 @@ var CPControlBlackColor = [CPColor blackColor];
{
if (!_trackingWasWithinFrame)
_continuousTracking = [self startTrackingAt:currentLocation];
else if (_continuousTracking)
_continuousTracking = [self continueTracking:_previousTrackingLocation at:currentLocation];
}
else
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:NO];
}
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
if ((_sendActionOn & (1 << type)) && isWithinFrame)
[self sendAction:_action to:_target];
_trackingWasWithinFrame = isWithinFrame;
_previousTrackingLocation = currentLocation;
}
- (void)performClick:(id)sender
- (void)setState:(int)state
{
}
- (int)nextState
{
return 0;
}
- (void)performClick:(id)sender
{
if (![self isEnabled])
return;
[self highlight:YES];
[self setState:[self nextState]];
[self sendAction:[self action] to:[self target]];
try
{
[self sendAction:[self action] to:[self target]];
}
catch (e)
{
throw e;
}
finally
{
[CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unhighlightButtonTimerDidFinish:) userInfo:nil repeats:NO];
}
}
- (void)unhighlightButtonTimerDidFinish:(id)sender
{
[self highlight:NO];
}
@@ -312,7 +362,7 @@ var CPControlBlackColor = [CPColor blackColor];
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
[self highlight:YES];
return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
}
@@ -330,7 +380,7 @@ var CPControlBlackColor = [CPColor blackColor];
{
if (![self isEnabled])
return;
[self trackMouse:anEvent];
}
@@ -348,7 +398,7 @@ var CPControlBlackColor = [CPColor blackColor];
- (void)setObjectValue:(id)anObject
{
_value = anObject;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -422,7 +472,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's int value
Returns the receiver's string value
*/
- (CPString)stringValue
{
@@ -430,7 +480,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's int value
Set's the receiver's string value
*/
- (void)setStringValue:(CPString)anObject
{
@@ -477,52 +527,124 @@ var CPControlBlackColor = [CPColor blackColor];
[self setStringValue:[sender stringValue]];
}
- (void)textDidBeginEditing:(CPNotification)note
- (void)textDidBeginEditing:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if([note object] != self)
if ([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
}
- (void)textDidChange:(CPNotification)note
- (void)textDidChange:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if([note object] != self)
if ([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
}
- (void)textDidEndEditing:(CPNotification)note
- (void)textDidEndEditing:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if([note object] != self)
if ([note object] != self)
return;
[self _reverseSetBinding];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
}
#define BRIDGE(UPPERCASE, LOWERCASE, ATTRIBUTENAME) \
- (void)set##UPPERCASE:(id)aValue\
{\
[self setValue:aValue forThemeAttribute:ATTRIBUTENAME];\
}\
- (id)LOWERCASE\
{\
return [self valueForThemeAttribute:ATTRIBUTENAME];\
- (void)setAlignment:(CPTextAlignment)alignment
{
[self setValue:alignment forThemeAttribute:@"alignment"];
}
BRIDGE(Alignment, alignment, "alignment")
BRIDGE(VerticalAlignment, verticalAlignment, "vertical-alignment")
BRIDGE(LineBreakMode, lineBreakMode, "line-break-mode")
BRIDGE(TextColor, textColor, "text-color")
BRIDGE(Font, font, "font")
BRIDGE(TextShadowColor, textShadowColor, "text-shadow-color")
BRIDGE(TextShadowOffset, textShadowOffset, "text-shadow-offset")
BRIDGE(ImagePosition, imagePosition, "image-position")
BRIDGE(ImageScaling, imageScaling, "image-scaling")
- (CPTextAlignment)alignment
{
return [self valueForThemeAttribute:@"alignment"];
}
- (void)setVerticalAlignment:(CPTextVerticalAlignment)alignment
{
[self setValue:alignment forThemeAttribute:@"vertical-alignment"];
}
- (CPTextVerticalAlignment)verticalAlignment
{
return [self valueForThemeAttribute:@"vertical-alignment"];
}
- (void)setLineBreakMode:(CPLineBreakMode)mode
{
[self setValue:mode forThemeAttribute:@"line-break-mode"];
}
- (CPLineBreakMode)lineBreakMode
{
return [self valueForThemeAttribute:@"line-break-mode"];
}
- (void)setTextColor:(CPColor)aColor
{
[self setValue:aColor forThemeAttribute:@"text-color"];
}
- (CPColor)textColor
{
return [self valueForThemeAttribute:@"text-color"];
}
- (void)setTextShadowColor:(CPColor)aColor
{
[self setValue:aColor forThemeAttribute:@"text-shadow-color"];
}
- (CPColor)textShadowColor
{
return [self valueForThemeAttribute:@"text-shadow-color"];
}
- (void)setTextShadowOffset:(float)offset
{
[self setValue:offset forThemeAttribute:@"text-shadow-offset"];
}
- (float)textShadowOffset
{
return [self valueForThemeAttribute:@"text-shadow-offset"];
}
- (void)setFont:(CPFont)aFont
{
[self setValue:aFont forThemeAttribute:@"font"];
}
- (CPFont)font
{
return [self valueForThemeAttribute:@"font"];
}
- (void)setImagePosition:(CPCellImagePosition)position
{
[self setValue:position forThemeAttribute:@"image-position"];
}
- (CPCellImagePosition)imagePosition
{
return [self valueForThemeAttribute:@"image-position"];
}
- (void)setImageScaling:(CPImageScaling)scaling
{
[self setValue:scaling forThemeAttribute:@"image-scaling"];
}
- (CPImageScaling)imageScaling
{
return [self valueForThemeAttribute:@"image-scaling"];
}
- (void)setEnabled:(BOOL)isEnabled
{
@@ -555,63 +677,17 @@ BRIDGE(ImageScaling, imageScaling, "image-scaling")
return [self hasThemeState:CPThemeStateHighlighted];
}
- (CPView)createEphemeralSubviewNamed:(CPString)aViewName
{
return nil;
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
{
return _CGRectMakeZero();
}
- (CPView)layoutEphemeralSubviewNamed:(CPString)aViewName
positioned:(CPWindowOrderingMode)anOrderingMode
relativeToEphemeralSubviewNamed:(CPString)relativeToViewName
{
if (!_ephemeralSubviewsForNames)
{
_ephemeralSubviewsForNames = {};
_ephemeralSubviews = [CPSet set];
}
var frame = [self rectForEphemeralSubviewNamed:aViewName];
if (frame && !_CGRectIsEmpty(frame))
{
if (!_ephemeralSubviewsForNames[aViewName])
{
_ephemeralSubviewsForNames[aViewName] = [self createEphemeralSubviewNamed:aViewName];
[_ephemeralSubviews addObject:_ephemeralSubviewsForNames[aViewName]];
if (_ephemeralSubviewsForNames[aViewName])
[self addSubview:_ephemeralSubviewsForNames[aViewName] positioned:anOrderingMode relativeTo:_ephemeralSubviewsForNames[relativeToViewName]];
}
if (_ephemeralSubviewsForNames[aViewName])
[_ephemeralSubviewsForNames[aViewName] setFrame:frame];
}
else if (_ephemeralSubviewsForNames[aViewName])
{
[_ephemeralSubviewsForNames[aViewName] removeFromSuperview];
[_ephemeralSubviews removeObject:_ephemeralSubviewsForNames[aViewName]];
delete _ephemeralSubviewsForNames[aViewName];
}
return _ephemeralSubviewsForNames[aViewName];
}
@end
var CPControlValueKey = "CPControlValueKey",
CPControlControlStateKey = @"CPControlControlStateKey",
CPControlIsEnabledKey = "CPControlIsEnabledKey",
CPControlTargetKey = "CPControlTargetKey",
CPControlActionKey = "CPControlActionKey",
CPControlSendActionOnKey = "CPControlSendActionOnKey";
CPControlSendActionOnKey = "CPControlSendActionOnKey",
CPControlSendsActionOnEndEditingKey = "CPControlSendsActionOnEndEditingKey";
var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
@@ -634,8 +710,9 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
[self setAction:[aCoder decodeObjectForKey:CPControlActionKey]];
[self sendActionOn:[aCoder decodeIntForKey:CPControlSendActionOnKey]];
[self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
}
return self;
}
@@ -645,23 +722,10 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
var count = [_subviews count],
ephemeral
subviews = nil;
if (count > 0 && [_ephemeralSubviews count] > 0)
{
subviews = [_subviews.slice(0) copy];
while (count--)
if ([_ephemeralSubviews containsObject:_subviews[count]])
_subviews.splice(count, 1);
}
[super encodeWithCoder:aCoder];
if (subviews)
_subviews = subviews;
if (_sendsActionOnEndEditing)
[aCoder encodeBool:_sendsActionOnEndEditing forKey:CPControlSendsActionOnEndEditingKey];
if (_value !== nil)
[aCoder encodeObject:_value forKey:CPControlValueKey];
@@ -684,7 +748,7 @@ var _CPControlSizeIdentifiers = [],
_CPControlSizeIdentifiers[CPRegularControlSize] = "Regular";
_CPControlSizeIdentifiers[CPSmallControlSize] = "Small";
_CPControlSizeIdentifiers[CPMiniControlSize] = "Mini";
function _CPControlIdentifierForControlSize(aControlSize)
{
return _CPControlSizeIdentifiers[aControlSize];
@@ -695,21 +759,21 @@ function _CPControlColorWithPatternImage(sizes, aClassName)
var index = 1,
count = arguments.length,
identifier = "";
for (; index < count; ++index)
identifier += arguments[index];
var color = _CPControlCachedColorWithPatternImages[identifier];
if (!color)
{
var bundle = [CPBundle bundleForClass:[CPControl class]];
color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:aClassName + "/" + identifier + ".png"] size:sizes[identifier]]];
_CPControlCachedColorWithPatternImages[identifier] = color;
}
return color;
}
@@ -718,17 +782,17 @@ function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
var index = 2,
count = arguments.length,
identifier = "";
for (; index < count; ++index)
identifier += arguments[index];
var color = _CPControlCachedThreePartImagePattern[identifier];
if (!color)
{
var bundle = [CPBundle bundleForClass:[CPControl class]],
path = aClassName + "/" + identifier;
sizes = sizes[identifier];
color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:[
@@ -736,9 +800,9 @@ function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "1.png"] size:sizes[1]],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "2.png"] size:sizes[2]]
] isVertical:isVertical]];
_CPControlCachedThreePartImagePattern[identifier] = color;
}
return color;
}
+88
View File
@@ -0,0 +1,88 @@
//
// CPController.j
// AppKit
//
// Created by Ross Boucher 1/15/09
// Copyright 280 North
//
// Adapted from GNUStep
// Copyright (C) 2007 Free Software Foundation, Inc
// Released under the LGPL.
//
@import <Foundation/CPObject.j>
var CPControllerDeclaredKeysKey = @"CPControllerDeclaredKeysKey";
@implementation CPController : CPObject
{
CPArray _editors;
CPArray _declaredKeys;
}
- (id)init
{
self = [super init];
if (self)
{
_editors = [];
_declaredKeys = [];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
if ([_declaredKeys count] > 0)
[aCoder encodeObject:_declaredKeys forKey:CPControllerDeclaredKeysKey];
}
- (id)initWithCoder:(CPCoder)aDecoder
{
self = [super init];
if (self)
{
_editors = [];
_declaredKeys = [aDecoder decodeObjectForKey:CPControllerDeclaredKeysKey] || [];
}
return nil;
}
- (BOOL)isEditing
{
return [_editors count] > 0;
}
- (BOOL)commitEditing
{
var index = 0,
count = _editors.length;
for (; index < count; ++index)
if (![[_editors objectAtIndex:i] commitEditing])
return NO;
return YES;
}
- (void)discardEditing
{
[_editors makeObjectsPerformSelector:@selector(discardEditing)];
}
- (void)objectDidBeginEditing:(id)anEditor
{
[_editors addObject:anEditor];
}
- (void)objectDidEndEditing:(id)anEditor
{
[_editors removeObject:anEditor];
}
@end
+30 -21
View File
@@ -24,7 +24,7 @@
@import <Foundation/CPString.j>
/*!
/*!
@ingroup appkit
@class CPCookie
CPCookie is the Cappuccino interface to a web browser cookie. You can set the name
@@ -33,18 +33,18 @@
{
CPString _cookieName;
CPString _cookieValue;
CPString _expires;
}
/*!
Initializes a cookie with a given name <code>aName</code>.
Initializes a cookie with a given name \c aName.
@param the name for the cookie
*/
- (id)initWithName:(CPString)aName
{
self = [super init];
_cookieName = aName;
_cookieValue = [self _readCookieValue];
@@ -83,30 +83,39 @@
*/
- (void)setValue:(CPString)value expires:(CPDate)date domain:(CPString)domain
{
if(date)
var expires = "; expires="+date.toGMTString();
else
if (date)
var expires = "; expires=" + date.toGMTString();
else
var expires = "";
if(domain)
domain = "; domain="+domain;
else
if (domain)
domain = "; domain=" + domain;
else
domain = "";
document.cookie = _cookieName+"="+value+expires+"; path=/"+domain;
#if PLATFORM(DOM)
document.cookie = _cookieName+"="+value+expires+"; path=/"+domain;
#else
_cookieValue = value;
_expires = expires;
#endif
}
/* @ignore */
- (CPString)_readCookieValue
{
var nameEQ = _cookieName + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return "";
#if PLATFORM(DOM)
var nameEQ = _cookieName + "=",
ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++)
{
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
#endif
return "";
}
@end
+277
View File
@@ -0,0 +1,277 @@
/*
Testing browsers:
WebKit r50235 (Safari 4.0.3+)
FireFox 3.5
Opera 10.0.0
Implemented class methods:
Webkit : All
IE : All
FireFox Win : All
FireFox Mac : All except closedHandCursor disappearingItemCursor // Firefox mac does not support url cursors
Opera : All except resizeLeftRightCursor resizeUpDownCursor operationNotAllowedCursor dragCopyCursor dragLinkCursor contextualMenuCursor openHandCursor closedHandCursor disappearingItemCursor // Opera does not support url cursors so these won't work with images
*/
@import <Foundation/CPObject.j>
var currentCursor = nil,
cursorStack = [],
cursors = {},
cursorURLFormat = nil;
@implementation CPCursor : CPObject
{
CPString _cssString;
BOOL _isSetOnMouseEntered @accessors(readwrite, getter=isSetOnMouseEntered, setter=setOnMouseEntered:);
BOOL _isSetOnMouseExited @accessors(readwrite, getter=isSetOnMouseExited, setter=setOnMouseExited:);
}
+ (CPCursor)currentCursor
{
return currentCursor;
}
- (id)initWithCSSString:(CPString)aString
{
if (self = [super init])
_cssString = aString;
return self;
}
+ (CPCursor)cursorWithCSSString:(CPString)cssString
{
var cursor = cursors[cssString];
if (typeof cursor == 'undefined')
{
cursor = [[CPCursor alloc] initWithCSSString:cssString];
cursors[cssString] = cursor;
}
return cursor;
}
+ (CPCursor)cursorWithImageNamed:(CPString)imageName
{
if (!cursorURLFormat)
{
cursorURLFormat = @"url(" + [[CPBundle bundleForClass:self] resourcePath] + @"/CPCursor/%@.cur)";
if (CPBrowserIsEngine(CPGeckoBrowserEngine))
cursorURLFormat += ", default";
}
var url = [CPString stringWithFormat:cursorURLFormat, imageName];
return [[CPCursor alloc] initWithCSSString:url];
}
- (CPString)_cssString
{
return _cssString;
}
+ (CPCursor)arrowCursor
{
return [CPCursor cursorWithCSSString:@"default"]; // WebKit | FF | opera | IE
}
+ (CPCursor)crosshairCursor
{
return [CPCursor cursorWithCSSString:@"crosshair"]; // WebKit | FF | opera | IE
}
+ (CPCursor)IBeamCursor
{
return [CPCursor cursorWithCSSString:@"text"]; // WebKit | FF | opera | IE
}
+ (CPCursor)pointingHandCursor
{
return [CPCursor cursorWithCSSString:@"pointer"]; // WebKit | FF | opera | IE
}
+ (CPCursor)resizeDownCursor
{
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)];
return [CPCursor cursorWithCSSString:"s-resize"]; // WebKit | FF | opera
}
+ (CPCursor)resizeUpCursor
{
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)];
return [CPCursor cursorWithCSSString:@"n-resize"]; // WebKit | FF | opera
}
+ (CPCursor)resizeLeftCursor
{
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)];
return [CPCursor cursorWithCSSString:@"w-resize"]; // WebKit | FF | opera
}
+ (CPCursor)resizeRightCursor
{
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)];
return [CPCursor cursorWithCSSString:@"e-resize"]; // WebKit | FF | opera
}
+ (CPCursor)resizeLeftRightCursor
{
return [CPCursor cursorWithCSSString:@"col-resize"]; // WebKit | FF | IE
}
+ (CPCursor)resizeUpDownCursor
{
return [CPCursor cursorWithCSSString:@"row-resize"]; // WebKit | FF | IE
}
+ (CPCursor)operationNotAllowedCursor
{
return [CPCursor cursorWithCSSString:@"not-allowed"]; // WebKit | FF | IE
}
+ (CPCursor)dragCopyCursor
{
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)];
return [CPCursor cursorWithCSSString:@"copy"]; // WebKit | FF
}
+ (CPCursor)dragLinkCursor
{
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)];
return [CPCursor cursorWithCSSString:@"alias"]; // WebKit | FF
}
+ (CPCursor)contextualMenuCursor
{
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)];
return [CPCursor cursorWithCSSString:@"context-menu"]; // WebKit | FF Mac . Not impl FF Win.
}
+ (CPCursor)openHandCursor
{
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
return [CPCursor cursorWithCSSString:@"-webkit-grab"];
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
return [CPCursor cursorWithCSSString:@"-moz-grab"];
else if (CPBrowserIsEngine(CPOperaBrowserEngine))
return [CPCursor cursorWithCSSString:@"move"];
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)]; // WebKit only. move in FFMac|Opera
}
+ (CPCursor)closedHandCursor
{
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
return [CPCursor cursorWithCSSString:@"-webkit-grabbing"];
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
return [CPCursor cursorWithCSSString:@"-moz-grabbing"];
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)]; // WebKit || FF
}
+ (CPCursor)disappearingItemCursor
{
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)]; // None
}
+ (void)hide
{
[self _setCursorCSS:"none"]; // Not supported in IE
}
+ (void)unhide
{
[self _setCursorCSS:[currentCursor _cssString]];
}
+ (void)setHiddenUntilMouseMoves:(BOOL)flag
{
if (flag)
[CPCursor hide];
else
[CPCursor unhide];
}
- (id)initWithImage:(CPImage)image hotSpot:(CPPoint)hotSpot
{
return [self initWithCSSString:"url(" + [image filename] + "), auto"];
}
- (void)mouseEntered:(CPEvent)event
{
}
- (void)mouseExited:(CPEvent)event
{
}
- (void)set
{
currentCursor = self;
#if PLATFORM(DOM)
[[self class] _setCursorCSS:_cssString];
#endif
}
+ (void)_setCursorCSS:(CPString)aString
{
#if PLATFORM(DOM)
var platformWindows = [[CPPlatformWindow visiblePlatformWindows] allObjects];
for (var i = 0, count = [platformWindows count]; i < count; i++)
platformWindows[i]._DOMBodyElement.style.cursor = aString;
#endif
}
- (void)push
{
currentCursor = cursorStack.push(self);
}
- (void)pop
{
[CPCursor pop];
}
+ (void)pop
{
if (cursorStack.length > 1)
{
cursorStack.pop();
currentCursor = cursorStack[cursorStack.length - 1];
}
}
- (id)initWithCoder:(CPCoder)coder
{
if (self = [super init])
_cssString = [coder decodeObjectForKey:@"CPCursorNameKey"];
return self;
}
- (void)encodeWithCoder:(CPCoder)coder
{
[coder encodeObject:_cssString forKey:@"CPCursorNameKey"];
}
@end
+303 -103
View File
@@ -23,7 +23,10 @@
@import <Foundation/CPString.j>
@import <Foundation/CPArray.j>
@import "CPApplication.j"
@import "CPResponder.j"
@import "CPSavePanel.j"
@import "CPViewController.j"
@import "CPWindowController.j"
@@ -80,7 +83,7 @@ CPDocumentDidFailToSaveNotification = @"CPDocumentDidFailToSaveNotification";
var CPDocumentUntitledCount = 0;
/*!
/*!
@ingroup appkit
@class CPDocument
@@ -90,19 +93,25 @@ var CPDocumentUntitledCount = 0;
CPDocuments should be used to represent this.
*/
@implementation CPDocument : CPResponder
{
CPURL _fileURL;
CPString _fileType;
CPArray _windowControllers;
unsigned _untitledDocumentIndex;
{
CPWindow _window; // For outlet purposes.
CPView _view; // For outlet purposes
CPDictionary _viewControllersForWindowControllers;
BOOL _hasUndoManager;
CPUndoManager _undoManager;
int _changeCount;
CPURLConnection _readConnection;
CPURLRequest _writeRequest;
CPURL _fileURL;
CPString _fileType;
CPArray _windowControllers;
unsigned _untitledDocumentIndex;
BOOL _hasUndoManager;
CPUndoManager _undoManager;
int _changeCount;
CPURLConnection _readConnection;
CPURLRequest _writeRequest;
CPAlert _canCloseAlert;
}
/*!
@@ -112,17 +121,18 @@ var CPDocumentUntitledCount = 0;
- (id)init
{
self = [super init];
if (self)
{
_windowControllers = [];
_viewControllersForWindowControllers = [CPDictionary dictionary];
_hasUndoManager = YES;
_changeCount = 0;
[self setNextResponder:CPApp];
}
return self;
}
@@ -135,10 +145,10 @@ var CPDocumentUntitledCount = 0;
- (id)initWithType:(CPString)aType error:({CPError})anError
{
self = [self init];
if (self)
[self setFileType:aType];
return self;
}
@@ -156,15 +166,15 @@ var CPDocumentUntitledCount = 0;
- (id)initWithContentsOfURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo
{
self = [self init];
if (self)
{
[self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
[self setFileURL:anAbsoluteURL];
[self setFileType:aType];
[self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
}
return self;
}
@@ -174,22 +184,22 @@ var CPDocumentUntitledCount = 0;
@param absoluteContentsURL the location of the document's contents
@param aType the type of the contents
@param aDelegate this object will receive a callback after the document's contents are loaded
@param aDidReadSelector the message selector that will be sent to <code>aDelegate</code>
@param aContextInfo passed as the argument to the message sent to the <code>aDelegate</code>
@param aDidReadSelector the message selector that will be sent to \c aDelegate
@param aContextInfo passed as the argument to the message sent to the \c aDelegate
@return the initialized document
*/
- (id)initForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo
{
self = [self init];
if (self)
{
[self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
[self setFileURL:anAbsoluteURL];
[self setFileType:aType];
[self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
}
return self;
}
@@ -222,15 +232,73 @@ var CPDocumentUntitledCount = 0;
reason:"readFromData:ofType: must be overridden by the document subclass."];
}
- (void)viewControllerWillLoadCib:(CPViewController)aViewController
{
}
- (void)viewControllerDidLoadCib:(CPViewController)aViewController
{
}
- (CPWindowController)firstEligibleExistingWindowController
{
return nil;
}
// Creating and managing window controllers
/*!
Creates the window controller for this document.
*/
- (void)makeWindowControllers
{
var controller = [[CPWindowController alloc] initWithWindowCibName:nil];
[self addWindowController:controller];
[self makeViewAndWindowControllers];
}
- (void)makeViewAndWindowControllers
{
var viewCibName = [self viewCibName],
viewController = nil,
windowController = nil;
// Create our view controller if we have a cib for it.
if ([viewCibName length])
viewController = [[CPViewController alloc] initWithCibName:viewCibName bundle:nil owner:self];
// If we have a view controller, check if we have a free window for it.
if (viewController)
windowController = [self firstEligibleExistingWindowController];
// If not, create one.
if (!windowController)
{
var windowCibName = [self windowCibName];
// From a cib if we have one.
if ([windowCibName length])
windowController = [[CPWindowController alloc] initWithWindowCibName:windowCibName owner:self];
// If not you get a standard window capable of displaying multiple documents and view
else if (viewController)
{
var view = [viewController view],
viewFrame = [view frame];
viewFrame.origin = CGPointMake(50, 50);
var theWindow = [[CPWindow alloc] initWithContentRect:viewFrame styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
windowController = [[CPWindowController alloc] initWithWindow:theWindow];
}
}
if (windowController && viewController)
[windowController setSupportsMultipleDocuments:YES];
if (windowController)
[self addWindowController:windowController];
if (viewController)
[self addViewController:viewController forWindowController:windowController];
}
/*!
@@ -249,12 +317,52 @@ var CPDocumentUntitledCount = 0;
- (void)addWindowController:(CPWindowController)aWindowController
{
[_windowControllers addObject:aWindowController];
if ([aWindowController document] != self)
{
[aWindowController setNextResponder:self];
if ([aWindowController document] !== self)
[aWindowController setDocument:self];
}
}
/*!
Remove a controller to the document's list of controllers. This should
be called after closing the controller's window.
@param aWindowController the controller to remove
*/
- (void)removeWindowController:(CPWindowController)aWindowController
{
if (aWindowController)
[_windowControllers removeObject:aWindowController];
if ([aWindowController document] === self)
[aWindowController setDocument:nil];
}
- (CPView)view
{
return _view;
}
- (CPArray)viewControllers
{
return [_viewControllersForWindowControllers allValues];
}
- (void)addViewController:(CPViewController)aViewController forWindowController:(CPWindowController)aWindowController
{
// FIXME: exception if we don't own the window controller?
[_viewControllersForWindowControllers setObject:aViewController forKey:[aWindowController UID]];
if ([aWindowController document] === self)
[aWindowController setViewController:aViewController];
}
- (void)removeViewController:(CPViewController)aViewController
{
[_viewControllersForWindowControllers removeObject:aViewController];
}
- (CPViewController)viewControllerForWindowController:(CPWindowController)aWindowController
{
return [_viewControllersForWindowControllers objectForKey:[aWindowController UID]];
}
// Managing Document Windows
@@ -263,6 +371,7 @@ var CPDocumentUntitledCount = 0;
*/
- (void)showWindows
{
[_windowControllers makeObjectsPerformSelector:@selector(setDocument:) withObject:self];
[_windowControllers makeObjectsPerformSelector:@selector(showWindow:) withObject:self];
}
@@ -273,14 +382,19 @@ var CPDocumentUntitledCount = 0;
{
if (_fileURL)
return [_fileURL lastPathComponent];
if (!_untitledDocumentIndex)
_untitledDocumentIndex = ++CPDocumentUntitledCount;
if (_untitledDocumentIndex == 1)
return @"Untitled";
return @"Untitled " + _untitledDocumentIndex;
if (_untitledDocumentIndex == 1)
return @"Untitled";
return @"Untitled " + _untitledDocumentIndex;
}
- (CPString)viewCibName
{
return nil;
}
/*!
@@ -292,18 +406,18 @@ var CPDocumentUntitledCount = 0;
}
/*!
Called after <code>aWindowController<code> loads the document's Nib file.
Called after \c aWindowController loads the document's Nib file.
@param aWindowController the controller that loaded the Nib file
*/
- (void)windowControllerDidLoadNib:(CPWindowController)aWindowController
- (void)windowControllerDidLoadCib:(CPWindowController)aWindowController
{
}
/*!
Called before <code>aWindowController</code> will load the document's Nib file.
Called before \c aWindowController will load the document's Nib file.
@param aWindowController the controller that will load the Nib file
*/
- (void)windowControllerWillLoadNib:(CPWindowController)aWindowController
- (void)windowControllerWillLoadCib:(CPWindowController)aWindowController
{
}
@@ -322,7 +436,7 @@ var CPDocumentUntitledCount = 0;
// FIXME: Oh man is this every looking for trouble, we need to handle login at the Cappuccino level, with HTTP Errors.
_readConnection = [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:anAbsoluteURL] delegate:self];
_readConnection.session = _CPReadSessionMake(aType, aDelegate, aDidReadSelector, aContextInfo);
}
@@ -340,11 +454,11 @@ var CPDocumentUntitledCount = 0;
*/
- (void)setFileURL:(CPURL)aFileURL
{
if (_fileURL == aFileURL)
if (_fileURL === aFileURL)
return;
_fileURL = aFileURL;
[_windowControllers makeObjectsPerformSelector:@selector(synchronizeWindowTitleWithDocumentName)];
}
@@ -365,17 +479,22 @@ var CPDocumentUntitledCount = 0;
_writeRequest = [CPURLRequest requestWithURL:anAbsoluteURL];
[_writeRequest setHTTPMethod:@"POST"];
[_writeRequest setHTTPBody:[data string]];
// FIXME: THIS IS WRONG! We need a way to decide
if ([CPPlatform isBrowser])
[_writeRequest setHTTPMethod:@"POST"];
else
[_writeRequest setHTTPMethod:@"PUT"];
[_writeRequest setHTTPBody:[data rawString]];
[_writeRequest setValue:@"close" forHTTPHeaderField:@"Connection"];
if (aSaveOperation == CPSaveOperation)
if (aSaveOperation === CPSaveOperation)
[_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
if (aSaveOperation != CPSaveToOperation)
if (aSaveOperation !== CPSaveToOperation)
[self updateChangeCount:CPChangeCleared];
// FIXME: Oh man is this every looking for trouble, we need to handle login at the Cappuccino level, with HTTP Errors.
var connection = [CPURLConnection connectionWithRequest:_writeRequest delegate:self];
@@ -391,21 +510,21 @@ var CPDocumentUntitledCount = 0;
// If we got this far and it wasn't an HTTP request, then everything is fine.
if (![aResponse isKindOfClass:[CPHTTPURLResponse class]])
return;
var statusCode = [aResponse statusCode];
// Nothing to do if everything is hunky dory.
if (statusCode === 200)
return;
var session = aConnection.session;
if (aConnection == _readConnection)
{
[aConnection cancel];
alert("There was an error retrieving the document.");
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
}
else
@@ -414,24 +533,25 @@ var CPDocumentUntitledCount = 0;
if (statusCode == 409)
{
[aConnection cancel];
if (confirm("There already exists a file with that name, would you like to overwrite it?"))
{
[_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
[aConnection start];
}
else
else
{
if (session.saveOperation != CPSaveToOperation)
{
_changeCount += session.changeCount;
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
}
_writeRequest = nil;
objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo);
[self _sendDocumentSavedNotification:NO];
}
}
}
@@ -444,11 +564,11 @@ var CPDocumentUntitledCount = 0;
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)aData
{
var session = aConnection.session;
// READ
if (aConnection == _readConnection)
{
[self readFromData:[CPData dataWithString:aData] ofType:session.fileType error:nil];
[self readFromData:[CPData dataWithRawString:aData] ofType:session.fileType error:nil];
objj_msgSend(session.delegate, session.didReadSelector, self, YES, session.contextInfo);
}
@@ -456,10 +576,11 @@ var CPDocumentUntitledCount = 0;
{
if (session.saveOperation != CPSaveToOperation)
[self setFileURL:session.absoluteURL];
_writeRequest = nil;
objj_msgSend(session.delegate, session.didSaveSelector, self, YES, session.contextInfo);
[self _sendDocumentSavedNotification:YES];
}
}
@@ -470,23 +591,24 @@ var CPDocumentUntitledCount = 0;
- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
{
var session = aConnection.session;
if (_readConnection == aConnection)
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
else
{
{
if (session.saveOperation != CPSaveToOperation)
{
_changeCount += session.changeCount;
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
}
}
_writeRequest = nil;
alert("There was an error saving the document.");
objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo);
[self _sendDocumentSavedNotification:NO];
}
}
@@ -502,7 +624,7 @@ var CPDocumentUntitledCount = 0;
// Managing Document Status
/*!
Returns <code>YES</code> if there are any unsaved changes.
Returns \c YES if there are any unsaved changes.
*/
- (BOOL)isDocumentEdited
{
@@ -522,9 +644,9 @@ var CPDocumentUntitledCount = 0;
else if (aChangeType == CPChangeCleared)
_changeCount = 0;
/*else if (aChangeType == CPCHangeReadOtherContents)
else if (aChangeType == CPChangeAutosaved)*/
else if (aChangeType == CPChangeAutosaved)*/
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
}
@@ -548,7 +670,7 @@ var CPDocumentUntitledCount = 0;
// Working with Undo Manager
/*!
Returns <code>YES</code> if the document has a
Returns \c YES if the document has a
CPUndoManager.
*/
- (BOOL)hasUndoManager
@@ -558,15 +680,15 @@ var CPDocumentUntitledCount = 0;
/*!
Sets whether the document should have a CPUndoManager.
@param aFlag <code>YES</code> makes the document have an undo manager
@param aFlag \c YES makes the document have an undo manager
*/
- (void)setHasUndoManager:(BOOL)aFlag
{
if (_hasUndoManager == aFlag)
return;
_hasUndoManager = aFlag;
if (!_hasUndoManager)
[self setUndoManager:nil];
}
@@ -575,7 +697,7 @@ var CPDocumentUntitledCount = 0;
- (void)_undoManagerWillCloseGroup:(CPNotification)aNotification
{
var undoManager = [aNotification object];
if ([undoManager isUndoing] || [undoManager isRedoing])
return;
@@ -602,13 +724,13 @@ var CPDocumentUntitledCount = 0;
- (void)setUndoManager:(CPUndoManager)anUndoManager
{
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_undoManager)
{
[defaultCenter removeObserver:self
name:CPUndoManagerDidUndoChangeNotification
object:_undoManager];
[defaultCenter removeObserver:self
name:CPUndoManagerDidRedoChangeNotification
object:_undoManager];
@@ -617,17 +739,17 @@ var CPDocumentUntitledCount = 0;
name:CPUndoManagerWillCloseUndoGroupNotification
object:_undoManager];
}
_undoManager = anUndoManager;
if (_undoManager)
{
[defaultCenter addObserver:self
selector:@selector(_undoManagerDidUndoChange:)
name:CPUndoManagerDidUndoChangeNotification
object:_undoManager];
[defaultCenter addObserver:self
selector:@selector(_undoManagerDidRedoChange:)
name:CPUndoManagerDidRedoChangeNotification
@@ -642,7 +764,7 @@ var CPDocumentUntitledCount = 0;
/*!
Returns the document's undo manager. If the document
should have one, but the manager is <code>nil</code>, it
should have one, but the manager is \c nil, it
will be created and then returned.
@return the document's undo manager
*/
@@ -653,7 +775,7 @@ var CPDocumentUntitledCount = 0;
return _undoManager;
}
/*
Implemented as a delegate of a CPWindow
@ignore
@@ -666,22 +788,27 @@ var CPDocumentUntitledCount = 0;
// Handling User Actions
/*!
Saves the document. If the document does not
have a file path to save to (<code>fileURL</code>)
then <code>saveDocumentAs:</code> will be called.
have a file path to save to (\c fileURL)
then \c -saveDocumentAs: will be called.
@param aSender the object requesting the save
*/
- (void)saveDocument:(id)aSender
{
[self saveDocumentWithDelegate:nil didSaveSelector:nil contextInfo:nil];
}
- (void)saveDocumentWithDelegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(Object)contextInfo
{
if (_fileURL)
{
[[CPNotificationCenter defaultCenter]
postNotificationName:CPDocumentWillSaveNotification
object:self];
[self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:self didSaveSelector:@selector(document:didSave:contextInfo:) contextInfo:NULL];
[self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
}
else
[self saveDocumentAs:self];
[self _saveDocumentAsWithDelegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
}
/*!
@@ -690,22 +817,30 @@ var CPDocumentUntitledCount = 0;
*/
- (void)saveDocumentAs:(id)aSender
{
_documentName = window.prompt("Document Name:");
[self _saveDocumentAsWithDelegate:nil didSaveSelector:nil contextInfo:nil];
}
if (!_documentName)
- (void)_saveDocumentAsWithDelegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(Object)contextInfo
{
var savePanel = [CPSavePanel savePanel],
response = [savePanel runModal];
if (!response)
return;
var saveURL = [savePanel URL];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPDocumentWillSaveNotification
object:self];
[self saveToURL:[self proposedFileURL] ofType:[self fileType] forSaveOperation:CPSaveAsOperation delegate:self didSaveSelector:@selector(document:didSave:contextInfo:) contextInfo:NULL];
[self saveToURL:saveURL ofType:[self fileType] forSaveOperation:CPSaveAsOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
}
/*
@ignore
*/
- (void)document:(id)aDocument didSave:(BOOL)didSave contextInfo:(id)aContextInfo
- (void)_sendDocumentSavedNotification:(BOOL)didSave
{
if (didSave)
[[CPNotificationCenter defaultCenter]
@@ -719,6 +854,71 @@ var CPDocumentUntitledCount = 0;
@end
@implementation CPDocument (ClosingDocuments)
- (void)close
{
[_windowControllers makeObjectsPerformSelector:@selector(removeDocumentAndCloseIfNecessary:) withObject:self];
[[CPDocumentController sharedDocumentController] removeDocument:self];
}
- (void)shouldCloseWindowController:(CPWindowController)controller delegate:(id)delegate shouldCloseSelector:(SEL)selector contextInfo:(Object)info
{
if ([controller shouldCloseDocument] || ([_windowControllers count] < 2 && [_windowControllers indexOfObject:controller] !== CPNotFound))
[self canCloseDocumentWithDelegate:self shouldCloseSelector:@selector(_document:shouldClose:context:) contextInfo:{delegate:delegate, selector:selector, context:info}];
else if ([delegate respondsToSelector:selector])
objj_msgSend(delegate, selector, self, YES, info);
}
- (void)_document:(CPDocument)aDocument shouldClose:(BOOL)shouldClose context:(Object)context
{
if (aDocument === self && shouldClose)
[self close];
objj_msgSend(context.delegate, context.selector, aDocument, shouldClose, context.context);
}
- (void)canCloseDocumentWithDelegate:(id)aDelegate shouldCloseSelector:(SEL)aSelector contextInfo:(Object)context
{
if (![self isDocumentEdited])
return [aDelegate respondsToSelector:aSelector] && objj_msgSend(aDelegate, aSelector, self, YES, context);
_canCloseAlert = [[CPAlert alloc] init];
[_canCloseAlert setDelegate:self];
[_canCloseAlert setAlertStyle:CPWarningAlertStyle];
[_canCloseAlert setTitle:@"Unsaved Document"];
[_canCloseAlert setMessageText:@"Do you want to save the changes you've made to the document \"" + ([self displayName] || [self fileName]) + "\"?"];
[_canCloseAlert addButtonWithTitle:@"Save"];
[_canCloseAlert addButtonWithTitle:@"Cancel"];
[_canCloseAlert addButtonWithTitle:@"Don't Save"];
_canCloseAlert._context = {delegate:aDelegate, selector:aSelector, context:context};
[_canCloseAlert runModal];
}
- (void)alertDidEnd:(CPAlert)alert returnCode:(int)returnCode
{
if (alert !== _canCloseAlert)
return;
var delegate = alert._context.delegate,
selector = alert._context.selector,
context = alert._context.context;
if (returnCode === 0)
[self saveDocumentWithDelegate:delegate didSaveSelector:selector contextInfo:context];
else
objj_msgSend(delegate, selector, self, returnCode === 2, context);
_canCloseAlert = nil;
}
@end
var _CPReadSessionMake = function(aType, aDelegate, aDidReadSelector, aContextInfo)
{
return { fileType:aType, delegate:aDelegate, didReadSelector:aDidReadSelector, contextInfo:aContextInfo };
+183 -36
View File
@@ -24,11 +24,12 @@
@import <Foundation/CPBundle.j>
@import "CPDocument.j"
@import "CPOpenPanel.j";
var CPSharedDocumentController = nil;
/*!
/*!
@ingroup appkit
@class CPDocumentController
This class is responsible for managing an application's open documents.
@@ -40,7 +41,7 @@ var CPSharedDocumentController = nil;
}
/*!
Returns the singleton instance of the application's document controller. If it has not
Returns the singleton instance of the application's document controller. If it has not
been created yet, it will be created then returned.
@return a CPDocumentController
*/
@@ -48,7 +49,7 @@ var CPSharedDocumentController = nil;
{
if (!CPSharedDocumentController)
[[self alloc] init];
return CPSharedDocumentController;
}
@@ -58,11 +59,11 @@ var CPSharedDocumentController = nil;
- (id)init
{
self = [super init];
if (self)
{
_documents = [[CPArray alloc] init];
if (!CPSharedDocumentController)
CPSharedDocumentController = self;
@@ -78,22 +79,22 @@ var CPSharedDocumentController = nil;
method searches documents already open. It does not
open the document at the URL if it is not already open.
@param aURL the url of the document
@return the document, or <code>nil</code> if such a document is not open
@return the document, or \c nil if such a document is not open
*/
- (CPDocument)documentForURL:(CPURL)aURL
{
var index = 0,
count = [_documents count];
for (; index < count; ++index)
for (; index < count; ++index)
{
var theDocument = _documents[index];
if ([[theDocument fileURL] isEqual:aURL])
return theDocument;
if ([[theDocument fileURL] isEqual:aURL])
return theDocument;
}
return nil;
return nil;
}
/*!
@@ -104,16 +105,16 @@ var CPSharedDocumentController = nil;
- (void)openUntitledDocumentOfType:(CPString)aType display:(BOOL)shouldDisplay
{
var theDocument = [self makeUntitledDocumentOfType:aType error:nil];
if (theDocument)
[self addDocument:theDocument];
if (shouldDisplay)
{
[theDocument makeWindowControllers];
[theDocument showWindows];
}
return theDocument;
}
@@ -138,16 +139,21 @@ var CPSharedDocumentController = nil;
- (CPDocument)openDocumentWithContentsOfURL:(CPURL)anAbsoluteURL display:(BOOL)shouldDisplay error:(CPError)anError
{
var result = [self documentForURL:anAbsoluteURL];
if (!result)
{
var type = [self typeForContentsOfURL:anAbsoluteURL error:anError];
result = [self makeDocumentWithContentsOfURL:anAbsoluteURL ofType:type delegate:self didReadSelector:@selector(document:didRead:contextInfo:) contextInfo:[CPDictionary dictionaryWithObject:shouldDisplay forKey:@"shouldDisplay"]];
[self addDocument:result];
if (result)
[self noteNewRecentDocument:result];
}
else if (shouldDisplay)
[result showWindows];
return result;
}
@@ -157,7 +163,7 @@ var CPSharedDocumentController = nil;
@param anAbsoluteURL the document URL
@param absoluteContentsURL the location of the document's contents
@param anError not used
@return the loaded document or <code>nil</code> if there was an error
@return the loaded document or \c nil if there was an error
*/
- (CPDocument)reopenDocumentForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL error:(CPError)anError
{
@@ -187,7 +193,7 @@ var CPSharedDocumentController = nil;
@param aDelegate receives a callback after the load has completed
@param aSelector the selector to invoke for the callback
@param aContextInfo an object passed as an argument for the callback
@return a new document or <code>nil</code> if there was an error
@return a new document or \c nil if there was an error
*/
- (CPDocument)makeDocumentForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aSelector contextInfo:(id)aContextInfo
{
@@ -203,9 +209,8 @@ var CPSharedDocumentController = nil;
if (!didRead)
return;
[self addDocument:aDocument];
[aDocument makeWindowControllers];
if ([aContextInfo objectForKey:@"shouldDisplay"])
[aDocument showWindows];
}
@@ -219,6 +224,20 @@ var CPSharedDocumentController = nil;
[self openUntitledDocumentOfType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] display:YES];
}
- (void)openDocument:(id)aSender
{
var openPanel = [CPOpenPanel openPanel];
[openPanel runModal];
var URLs = [openPanel URLs],
index = 0,
count = [URLs count];
for (; index < count; ++index)
[self openDocumentWithContentsOfURL:[CPURL URLWithString:URLs[index]] display:YES error:nil];
}
// Managing Documents
/*!
@@ -231,7 +250,7 @@ var CPSharedDocumentController = nil;
}
/*!
Adds <code>aDocument</code> under the control of the receiver.
Adds \c aDocument under the control of the receiver.
@param aDocument the document to add
*/
- (void)addDocument:(CPDocument)aDocument
@@ -240,7 +259,7 @@ var CPSharedDocumentController = nil;
}
/*!
Removes <code>aDocument</code> from the control of the receiver.
Removes \c aDocument from the control of the receiver.
@param aDocument the document to remove
*/
- (void)removeDocument:(CPDocument)aDocument
@@ -257,23 +276,29 @@ var CPSharedDocumentController = nil;
{
var index = 0,
count = _documentTypes.length,
extension = [[anAbsoluteURL pathExtension] lowercaseString];
extension = [[anAbsoluteURL pathExtension] lowercaseString],
starType = nil;
for (; index < count; ++index)
{
var documentType = _documentTypes[index],
extensions = [documentType objectForKey:@"CFBundleTypeExtensions"],
extensionIndex = 0,
extensionCount = extensions.length;
for (; extensionIndex < extensionCount; ++extensionIndex)
if ([extensions[extensionIndex] lowercaseString] == extension)
{
var thisExtension = [extensions[extensionIndex] lowercaseString];
if (thisExtension === extension)
return [documentType objectForKey:@"CPBundleTypeName"];
if (thisExtension === "****")
starType = [documentType objectForKey:@"CPBundleTypeName"];
}
}
// FIXME?
return [self defaultType];//nil;
return starType || [self defaultType];
}
// Managing Document Types
@@ -287,18 +312,18 @@ var CPSharedDocumentController = nil;
for (;i < count; ++i)
{
var documentType = _documentTypes[i];
if ([documentType objectForKey:@"CPBundleTypeName"] == aType)
return documentType;
}
return nil;
}
/*!
Returns the CPDocument subclass associated with <code>aType</code>.
Returns the CPDocument subclass associated with \c aType.
@param aType the type of document
@return a Cappuccino Class object, or <code>nil</code> if no match was found
@return a Cappuccino Class object, or \c nil if no match was found
*/
- (Class)documentClassForType:(CPString)aType
{
@@ -308,3 +333,125 @@ var CPSharedDocumentController = nil;
}
@end
@implementation CPDocumentController (Closing)
- (void)closeAllDocumentsWithDelegate:(id)aDelegate didCloseAllSelector:(SEL)didCloseSelector contextInfo:(Object)info
{
var context = {
delegate: aDelegate,
selector: didCloseSelector,
context: info
};
[self _closeDocumentsStartingWith:nil shouldClose:YES context:context];
}
// Recursive callback method. Start it by passing in a document of nil.
- (void)_closeDocumentsStartingWith:(CPDocument)aDocument shouldClose:(BOOL)shouldClose context:(Object)context
{
if (shouldClose)
{
[aDocument close];
if ([[self documents] count] > 0)
{
[[[self documents] lastObject] canCloseDocumentWithDelegate:self
shouldCloseSelector:@selector(_closeDocumentsStartingWith:shouldClose:context:)
contextInfo:context];
return;
}
}
if ([context.delegate respondsToSelector:context.selector])
objj_msgSend(context.delegate, context.selector, self, [[self documents] count] === 0, context.context);
}
@end
@implementation CPDocumentController (Recents)
- (CPArray)recentDocumentURLs
{
// FIXME move this to CP land
if (typeof window["cpRecentDocumentURLs"] === 'function')
return window.cpRecentDocumentURLs();
return [];
}
- (void)clearRecentDocuments:(id)sender
{
if (typeof window["cpClearRecentDocuments"] === 'function')
window.cpClearRecentDocuments();
[self _updateRecentDocumentsMenu];
}
- (void)noteNewRecentDocument:(CPDocument)aDocument
{
[self noteNewRecentDocumentURL:[[aDocument fileURL] absoluteString]];
}
- (void)noteNewRecentDocumentURL:(CPString)aURL
{
if (typeof window["cpNoteNewRecentDocumentPath"] === 'function')
window.cpNoteNewRecentDocumentPath(aURL);
[self _updateRecentDocumentsMenu];
}
- (void)_removeAllRecentDocumentsFromMenu:(CPMenu)aMenu
{
var items = [aMenu itemArray],
count = [items count];
while (count--)
{
var item = items[count];
if ([item action] === @selector(_openRecentDocument:))
[aMenu removeItemAtIndex:count];
}
}
- (void)_updateRecentDocumentsMenu
{
var menu = [[CPApp mainMenu] _menuWithName:@"_CPRecentDocumentsMenu"],
recentDocuments = [self recentDocumentURLs],
menuItems = [menu itemArray],
documentCount = [recentDocuments count],
menuItemCount = [menuItems count];
[self _removeAllRecentDocumentsFromMenu:menu];
if (menuItemCount)
{
if (!documentCount)
{
if ([menuItems[0] isSeparatorItem])
[menu removeItemAtIndex:0];
}
else
{
if (![menuItems[0] isSeparatorItem])
[menu insertItem:[CPMenuItem separatorItem] atIndex:0];
}
}
while (documentCount--)
{
var path = recentDocuments[documentCount],
item = [[CPMenuItem alloc] initWithTitle:[path lastPathComponent] action:@selector(_openRecentDocument:) keyEquivalent:nil];
[item setTag:path];
[menu insertItem:item atIndex:0];
}
}
- (void)_openRecentDocument:(id)sender
{
[self openDocumentWithContentsOfURL:[sender tag] display:YES error:nil];
}
@end
+344 -174
View File
@@ -20,124 +20,32 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CPView.j>
@import <AppKit/CPEvent.j>
@import <AppKit/CPPasteboard.j>
@import <AppKit/CPImageView.j>
@import "CPApplication.j"
@import "CPEvent.j"
@import "CPImageView.j"
@import "CPPasteboard.j"
@import "CPView.j"
@import "CPWindow.j"
#import "CoreGraphics/CGGeometry.h"
CPDragOperationNone = 0,
CPDragOperationCopy = 1 << 1,
CPDragOperationLink = 1 << 1,
CPDragOperationGeneric = 1 << 2,
CPDragOperationPrivate = 1 << 3,
CPDragOperationMove = 1 << 4,
CPDragOperationDelete = 1 << 5,
CPDragOperationEvery = -1;
#define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window])
var CPSharedDragServer = nil;
var CPDragServerView = nil,
CPDragServerSource = nil,
CPDragServerWindow = nil,
CPDragServerOffset = nil,
CPDragServerLocation = nil,
CPDragServerPasteboard = nil,
CPDragServerDestination = nil,
CPDragServerDraggingInfo = nil,
CPDragServerPreviousEvent = nil,
CPDragServerAutoscrollInterval = nil;
var CPDragServerPreviousEvent = nil,
CPDragServerPeriodicUpdateInterval = 0.05;
var CPDragServerIsDraggingImage = NO,
var CPSharedDragServer = nil;
CPDragServerShouldSendDraggedViewMovedTo = NO,
CPDragServerShouldSendDraggedImageMovedTo = NO,
CPDragServerShouldSendDraggedViewEndedAtOperation = NO,
CPDragServerShouldSendDraggedImageEndedAtOperation = NO;
var CPDragServerAutoscroll = function()
{
[CPDragServerSource autoscroll:CPDragServerPreviousEvent];
}
var CPDragServerStartDragging = function(anEvent)
{
CPDragServerUpdateDragging(anEvent);
}
var CPDragServerUpdateDragging = function(anEvent)
{
// If this is a mouse up, then complete the drag.
if([anEvent type] == CPLeftMouseUp)
{
if (CPDragServerAutoscrollInterval !== nil)
clearInterval(CPDragServerAutoscrollInterval);
CPDragServerAutoscrollInterval = nil;
CPDragServerLocation = [DRAGGING_WINDOW(CPDragServerDestination) convertBridgeToBase:[[anEvent window] convertBaseToBridge:[anEvent locationInWindow]]];
[CPDragServerView removeFromSuperview];
[CPSharedDragServer._dragWindow orderOut:nil];
if (CPDragServerDestination &&
(![CPDragServerDestination respondsToSelector:@selector(prepareForDragOperation:)] || [CPDragServerDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
(![CPDragServerDestination respondsToSelector:@selector(performDragOperation:)] || [CPDragServerDestination performDragOperation:CPDragServerDraggingInfo]) &&
[CPDragServerDestination respondsToSelector:@selector(concludeDragOperation:)])
[CPDragServerDestination concludeDragOperation:CPDragServerDraggingInfo];
if (CPDragServerShouldSendDraggedImageEndedAtOperation)
[CPDragServerSource draggedImage:[CPDragServerView image] endedAt:CPDragServerLocation operation:NO];
else if (CPDragServerShouldSendDraggedViewEndedAtOperation)
[CPDragServerSource draggedView:CPDragServerView endedAt:CPDragServerLocation operation:NO];
CPDragServerIsDraggingImage = NO;
CPDragServerDestination = nil;
return;
}
if (CPDragServerAutoscrollInterval === nil)
{
if ([CPDragServerSource respondsToSelector:@selector(autoscroll:)])
CPDragServerAutoscrollInterval = setInterval(CPDragServerAutoscroll, 100);
}
CPDragServerPreviousEvent = anEvent;
// If we're not a mouse up, then we're going to want to grab the next event.
[CPApp setCallback:CPDragServerUpdateDragging
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask
untilDate:nil inMode:0 dequeue:NO];
var location = [anEvent locationInWindow],
operation =
bridgeLocation = [[anEvent window] convertBaseToBridge:location];
// We have to convert base to bridge since the drag event comes from the source window, not the drag window.
var draggingDestination = [[CPDOMWindowBridge sharedDOMWindowBridge] _dragHitTest:bridgeLocation pasteboard:CPDragServerPasteboard];
CPDragServerLocation = [DRAGGING_WINDOW(draggingDestination) convertBridgeToBase:bridgeLocation];
if(draggingDestination != CPDragServerDestination)
{
if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingExited:)])
[CPDragServerDestination draggingExited:CPDragServerDraggingInfo];
CPDragServerDestination = draggingDestination;
if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingEntered:)])
[CPDragServerDestination draggingEntered:CPDragServerDraggingInfo];
}
else if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingUpdated:)])
[CPDragServerDestination draggingUpdated:CPDragServerDraggingInfo];
location.x -= CPDragServerOffset.x;
location.y -= CPDragServerOffset.y;
[CPDragServerView setFrameOrigin:location];
if (CPDragServerShouldSendDraggedImageMovedTo)
[CPDragServerSource draggedImage:[CPDragServerView image] movedTo:location];
else if (CPDragServerShouldSendDraggedViewMovedTo)
[CPDragServerSource draggedView:CPDragServerView movedTo:location];
}
var CPDragServerSource = nil;
var CPDragServerDraggingInfo = nil;
/*
CPDraggingInfo is a container of information about a specific dragging session.
@@ -147,24 +55,36 @@ var CPDragServerUpdateDragging = function(anEvent)
{
}
- (CPPasteboard)draggingPasteboard
{
if ([CPPlatform supportsDragAndDrop])
return [_CPDOMDataTransferPasteboard DOMDataTransferPasteboard];
return [[CPDragServer sharedDragServer] draggingPasteboard];
}
- (id)draggingSource
{
return CPDragServerSource;
return [[CPDragServer sharedDragServer] draggingSource];
}
/*
- (unsigned)draggingSourceOperationMask
*/
- (CPPoint)draggingLocation
{
return CPDragServerLocation;
return [[CPDragServer sharedDragServer] draggingLocation];
}
- (CPPasteboard)draggingPasteboard
- (CPWindow)draggingDestinationWindow
{
return CPDragServerPasteboard;
return DRAGGING_WINDOW([[CPDragServer sharedDragServer] draggingDestination]);
}
- (CPImage)draggedImage
{
return [CPDragServerView image];
return [[self draggedView] image];
}
- (CGPoint)draggedImageLocation
@@ -172,22 +92,51 @@ var CPDragServerUpdateDragging = function(anEvent)
return [self draggedViewLocation];
}
- (CGPoint)draggedViewLocation
{
return [DRAGGING_WINDOW(CPDragServerDestination) convertBridgeToBase:[CPDragServerView frame].origin];
}
- (CPView)draggedView
{
return CPDragServerView;
return [[CPDragServer sharedDragServer] draggedView];
}
- (CGPoint)draggedViewLocation
{
var dragServer = [CPDragServer sharedDragServer];
return [DRAGGING_WINDOW([dragServer draggingDestination]) convertPlatformWindowToBase:[[dragServer draggedView] frame].origin];
}
@end
var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
CPDraggingSource_draggedImage_endedAt_operation_ = 1 << 1,
CPDraggingSource_draggedView_movedTo_ = 1 << 2,
CPDraggingSource_draggedView_endedAt_operation_ = 1 << 3;
@implementation CPDragServer : CPObject
{
CPWindow _dragWindow;
CPImageView _imageView;
BOOL _isDragging @accessors(readonly, getter=isDragging);
CPWindow _draggedWindow @accessors(readonly, getter=draggedWindow);
CPView _draggedView @accessors(readonly, getter=draggedView);
CPImageView _imageView;
BOOL _isDraggingImage;
CGSize _draggingOffset @accessors(readonly, getter=draggingOffset);
CPPasteboard _draggingPasteboard @accessors(readonly, getter=draggingPasteboard);
id _draggingSource @accessors(readonly, getter=draggingSource);
unsigned _implementedDraggingSourceMethods;
CGPoint _draggingLocation;
id _draggingDestination;
BOOL _draggingDestinationWantsPeriodicUpdates;
CGPoint _startDragLocation;
BOOL _shouldSlideBack;
unsigned _dragOperation;
CPTimer _draggingUpdateTimer;
}
/*
@@ -196,9 +145,9 @@ var CPDragServerUpdateDragging = function(anEvent)
*/
+ (void)initialize
{
if (self != [CPDragServer class])
if (self !== [CPDragServer class])
return;
CPDragServerDraggingInfo = [[CPDraggingInfo alloc] init];
}
@@ -206,7 +155,7 @@ var CPDragServerUpdateDragging = function(anEvent)
{
if (!CPSharedDragServer)
CPSharedDragServer = [[CPDragServer alloc] init];
return CPSharedDragServer;
}
@@ -216,16 +165,175 @@ var CPDragServerUpdateDragging = function(anEvent)
- (id)init
{
self = [super init];
if (self)
{
_dragWindow = [[CPWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:CPBorderlessWindowMask];
[_dragWindow setLevel:CPDraggingWindowLevel];
_draggedWindow = [[CPWindow alloc] initWithContentRect:_CGRectMakeZero() styleMask:CPBorderlessWindowMask];
[_draggedWindow setLevel:CPDraggingWindowLevel];
}
return self;
}
- (id)draggingDestination
{
return _draggingDestination;
}
- (CGPoint)draggingLocation
{
return _draggingLocation
}
- (void)draggingStartedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation
{
if (_isDraggingImage)
{
if ([_draggingSource respondsToSelector:@selector(draggedImage:beganAt:)])
[_draggingSource draggedImage:[_draggedView image] beganAt:aLocation];
}
else
{
if ([_draggingSource respondsToSelector:@selector(draggedView:beganAt:)])
[_draggingSource draggedView:_draggedView beganAt:aLocation];
}
if (![CPPlatform supportsDragAndDrop])
[_draggedWindow orderFront:self];
}
- (void)draggingSourceUpdatedWithGlobalLocation:(CGPoint)aGlobalLocation
{
if (![CPPlatform supportsDragAndDrop])
[_draggedWindow setFrameOrigin:_CGPointMake(aGlobalLocation.x - _draggingOffset.width, aGlobalLocation.y - _draggingOffset.height)];
if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_movedTo_)
[_draggingSource draggedImage:[_draggedView image] movedTo:aGlobalLocation];
else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_movedTo_)
[_draggingSource draggedView:_draggedView movedTo:aGlobalLocation];
}
- (CPDragOperation)draggingUpdatedInPlatformWindow:(CPPlatformWindow)aPlatformWindow location:(CGPoint)aLocation
{
[_draggingUpdateTimer invalidate];
_draggingUpdateTimer = nil;
var dragOperation = CPDragOperationCopy;
// We have to convert base to bridge since the drag event comes from the source window, not the drag window.
var draggingDestination = [aPlatformWindow _dragHitTest:aLocation pasteboard:[CPDragServerDraggingInfo draggingPasteboard]];
if (draggingDestination)
_draggingLocation = [DRAGGING_WINDOW(draggingDestination) convertPlatformWindowToBase:aLocation];
if(draggingDestination !== _draggingDestination)
{
if ([_draggingDestination respondsToSelector:@selector(draggingExited:)])
[_draggingDestination draggingExited:CPDragServerDraggingInfo];
_draggingDestination = draggingDestination;
if ([_draggingDestination respondsToSelector:@selector(wantsPeriodicDraggingUpdates)])
_draggingDestinationWantsPeriodicUpdates = [_draggingDestination wantsPeriodicDraggingUpdates];
else
_draggingDestinationWantsPeriodicUpdates = YES;
if ([_draggingDestination respondsToSelector:@selector(draggingEntered:)])
dragOperation = [_draggingDestination draggingEntered:CPDragServerDraggingInfo];
}
else if ([_draggingDestination respondsToSelector:@selector(draggingUpdated:)])
dragOperation = [_draggingDestination draggingUpdated:CPDragServerDraggingInfo];
if (!_draggingDestination)
dragOperation = CPDragOperationNone;
else
{
if (_draggingDestinationWantsPeriodicUpdates)
_draggingUpdateTimer = [CPTimer scheduledTimerWithTimeInterval:CPDragServerPeriodicUpdateInterval
target:self
selector:@selector(_sendPeriodicDraggingUpdate:)
userInfo:[CPDictionary dictionaryWithJSObject:{platformWindow:aPlatformWindow, location:aLocation}]
repeats:NO];
var scrollView = [_draggingDestination isKindOfClass:[CPView class]] ? [_draggingDestination enclosingScrollView] : nil;
if (scrollView)
{
var contentView = [scrollView contentView],
bounds = [contentView bounds],
insetBounds = CGRectInset(bounds, 10, 10),
eventLocation = [contentView convertPoint:_draggingLocation fromView:nil],
deltaX = 0,
deltaY = 0;
if (!CGRectContainsPoint(insetBounds, eventLocation))
{
if ([scrollView hasVerticalScroller])
{
if (eventLocation.y < CGRectGetMinY(insetBounds))
deltaY = CGRectGetMinY(insetBounds) - eventLocation.y;
else if (eventLocation.y > CGRectGetMaxY(insetBounds))
deltaY = CGRectGetMaxY(insetBounds) - eventLocation.y;
if (deltaY < -insetBounds.size.height)
deltaY = -insetBounds.size.height;
if (deltaY > insetBounds.size.height)
deltaY = insetBounds.size.height;
}
if ([scrollView hasHorizontalScroller])
{
if (eventLocation.x < CGRectGetMinX(insetBounds))
deltaX = CGRectGetMinX(insetBounds) - eventLocation.x;
else if (eventLocation.x > CGRectGetMaxX(insetBounds))
deltaX = CGRectGetMaxX(insetBounds) - eventLocation.x;
if (deltaX < -insetBounds.size.width)
deltaX = -insetBounds.size.width;
if (deltaX > insetBounds.size.width)
deltaX = insetBounds.size.width;
}
[contentView scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
}
}
}
return dragOperation;
}
- (void)_sendPeriodicDraggingUpdate:(CPTimer)aTimer
{
var userInfo = [aTimer userInfo];
_dragOperation = [self draggingUpdatedInPlatformWindow:[userInfo objectForKey:@"platformWindow"]
location:[userInfo objectForKey:@"location"]];
}
- (void)draggingEndedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation operation:(CPDragOperation)anOperation
{
[_draggingUpdateTimer invalidate];
_draggingUpdateTimer = nil;
[_draggedView removeFromSuperview];
if (![CPPlatform supportsDragAndDrop])
[_draggedWindow orderOut:self];
if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_endedAt_operation_)
[_draggingSource draggedImage:[_draggedView image] endedAt:aLocation operation:anOperation];
else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_endedAt_operation_)
[_draggingSource draggedView:_draggedView endedAt:aLocation operation:anOperation];
_isDragging = NO;
}
- (void)performDragOperationInPlatformWindow:(CPPlatformWindow)aPlatformWindow
{
if (_draggingDestination &&
(![_draggingDestination respondsToSelector:@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
(![_draggingDestination respondsToSelector:@selector(performDragOperation:)] || [_draggingDestination performDragOperation:CPDragServerDraggingInfo]) &&
[_draggingDestination respondsToSelector:@selector(concludeDragOperation:)])
[_draggingDestination concludeDragOperation:CPDragServerDraggingInfo];
}
/*!
Initiates a drag session.
@param aView the view being dragged
@@ -235,50 +343,72 @@ var CPDragServerUpdateDragging = function(anEvent)
@param anEvent
@param aPasteboard the pasteboard that contains the drag data
@param aSourceObject the object where the drag started
@param slideBack if <code>YES</code>, <code>aView</code> slides back to
@param slideBack if \c YES, \c aView slides back to
its origin on a failed drop
*/
- (void)dragView:(CPView)aView fromWindow:(CPWindow)aWindow at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
- (void)dragView:(CPView)aView fromWindow:(CPWindow)aWindow at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)mouseDownEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
{
var eventLocation = [anEvent locationInWindow];
CPDragServerView = aView;
CPDragServerSource = aSourceObject;
CPDragServerWindow = aWindow;
CPDragServerOffset = CPPointMake(eventLocation.x - viewLocation.x, eventLocation.y - viewLocation.y);
CPDragServerPasteboard = [CPPasteboard pasteboardWithName:CPDragPboard];//aPasteboard;
_isDragging = YES;
[_dragWindow setFrameSize:CGSizeMakeCopy([[CPDOMWindowBridge sharedDOMWindowBridge] frame].size)];
[_dragWindow orderFront:self];
_draggedView = aView;
_draggingPasteboard = aPasteboard || [CPPasteboard pasteboardWithName:CPDragPboard];
_draggingSource = aSourceObject;
_draggingDestination = nil;
_shouldSlideBack = slideBack;
[aView setFrameOrigin:viewLocation];
[[_dragWindow contentView] addSubview:aView];
// The offset is based on the distance from where we want the view to be initially from where the mouse is initially
// Hence the use of mouseDownEvent's location and view's location in global coordinates.
var mouseDownWindow = [mouseDownEvent window],
mouseDownEventLocation = [mouseDownEvent locationInWindow];
if (CPDragServerIsDraggingImage)
if (mouseDownEventLocation)
{
if ([CPDragServerSource respondsToSelector:@selector(draggedImage:beganAt:)])
[CPDragServerSource draggedImage:[aView image] beganAt:viewLocation];
CPDragServerShouldSendDraggedImageMovedTo = [CPDragServerSource respondsToSelector:@selector(draggedImage:movedTo:)];
CPDragServerShouldSendDraggedImageEndedAtOperation = [CPDragServerSource respondsToSelector:@selector(draggedImage:endAt:operation:)];
CPDragServerShouldSendDraggedViewMovedTo = NO;
CPDragServerShouldSendDraggedViewEndedAtOperation = NO;
if (mouseDownWindow)
mouseDownEventLocation = [mouseDownWindow convertBaseToGlobal:mouseDownEventLocation];
_draggingOffset = _CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y);
}
else
_draggingOffset = _CGSizeMakeZero();
if ([CPPlatform isBrowser])
[_draggedWindow setPlatformWindow:[aWindow platformWindow]];
[aView setFrameOrigin:_CGPointMakeZero()];
var mouseLocation = [CPEvent mouseLocation];
// Place it where the mouse pointer is.
_startDragLocation = _CGPointMake(mouseLocation.x - _draggingOffset.width, mouseLocation.y - _draggingOffset.height);
[_draggedWindow setFrameOrigin:_startDragLocation];
[_draggedWindow setFrameSize:[aView frame].size];
[[_draggedWindow contentView] addSubview:aView];
_implementedDraggingSourceMethods = 0;
if (_draggedView === _imageView)
{
if ([_draggingSource respondsToSelector:@selector(draggedImage:movedTo:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_movedTo_;
if ([_draggingSource respondsToSelector:@selector(draggedImage:endedAt:operation:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_endedAt_operation_;
}
else
{
if ([CPDragServerSource respondsToSelector:@selector(draggedView:beganAt:)])
[CPDragServerSource draggedView:aView beganAt:viewLocation];
CPDragServerShouldSendDraggedViewMovedTo = [CPDragServerSource respondsToSelector:@selector(draggedView:movedTo:)];
CPDragServerShouldSendDraggedViewEndedAtOperation = [CPDragServerSource respondsToSelector:@selector(draggedView:endedAt:operation:)];
if ([_draggingSource respondsToSelector:@selector(draggedView:movedTo:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedView_movedTo_;
CPDragServerShouldSendDraggedImageMovedTo = NO;
CPDragServerShouldSendDraggedImageEndedAtOperation = NO;
if ([_draggingSource respondsToSelector:@selector(draggedView:endedAt:operation:)])
_implementedDraggingSourceMethods |= CPDraggingSource_draggedView_endedAt_operation_;
}
CPDragServerStartDragging(anEvent);
if (![CPPlatform supportsDragAndDrop])
{
[self draggingStartedInPlatformWindow:[aWindow platformWindow] globalLocation:mouseLocation];
[self trackDragging:mouseDownEvent];
}
}
/*!
@@ -290,22 +420,62 @@ var CPDragServerUpdateDragging = function(anEvent)
@param anEvent
@param aPasteboard the pasteboard where the drag data is located
@param aSourceObject the object where the drag started
@param slideBack if <code>YES</code>, <code>aView</code> slides back to
@param slideBack if \c YES, \c aView slides back to
its origin on a failed drop
*/
- (void)dragImage:(CPImage)anImage fromWindow:(CPWindow)aWindow at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
{
CPDragServerIsDraggingImage = YES;
_isDraggingImage = YES;
var imageSize = [anImage size];
if (!_imageView)
_imageView = [[CPImageView alloc] initWithFrame:CPRectMakeZero()];
_imageView = [[CPImageView alloc] initWithFrame:_CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)];
[_imageView setImage:anImage];
[_imageView setFrameSize:CGSizeMakeCopy([anImage size])];
[self dragView:_imageView fromWindow:aWindow at:imageLocation offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
}
- (void)trackDragging:(CPEvent)anEvent
{
var type = [anEvent type],
platformWindow = [_draggedWindow platformWindow],
platformWindowLocation = [[anEvent window] convertBaseToPlatformWindow:[anEvent locationInWindow]];
if (type === CPLeftMouseUp)
{
// Make sure we do not finalize (cancel) the drag if the last drag update was disallowed
if (_dragOperation !== CPDragOperationNone)
[self performDragOperationInPlatformWindow:platformWindow];
[self draggingEndedInPlatformWindow:platformWindow globalLocation:platformWindowLocation operation:_dragOperation];
// Stop tracking events.
return;
}
else if (type === CPKeyDown)
{
var keyCode = [anEvent keyCode];
if (keyCode === CPEscapeKeyCode)
{
_dragOperation = CPDragOperationNone;
[self draggingEndedInPlatformWindow:platformWindow globalLocation:CGPointMakeZero() operation:_dragOperation];
return;
}
}
else
{
[self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation];
_dragOperation = [self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation];
}
// If we're not a mouse up, then we're going to want to grab the next event.
[CPApp setTarget:self selector:@selector(trackDragging:)
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPKeyDownMask
untilDate:nil inMode:0 dequeue:NO];
}
@end
@implementation CPWindow (CPDraggingAdditions)
@@ -318,23 +488,23 @@ var CPDragServerUpdateDragging = function(anEvent)
return nil;
// We don't need to do this because the only place this gets called
// -_dragHitTest: in CPDOMWindowBridge does this already. Perhaps to
// -_dragHitTest: in CPPlatformWindow does this already. Perhaps to
// be safe?
// if (![self containsPoint:aPoint])
// return nil;
var adjustedPoint = _CGPointMake(aPoint.x - _CGRectGetMinX(_frame), aPoint.y - _CGRectGetMinY(_frame)),
var adjustedPoint = [self convertPlatformWindowToBase:aPoint],
hitView = [_windowView hitTest:adjustedPoint];
while (hitView && ![aPasteboard availableTypeFromArray:[hitView registeredDraggedTypes]])
hitView = [hitView superview];
if (hitView)
return hitView;
if ([aPasteboard availableTypeFromArray:[self registeredDraggedTypes]])
return self;
return nil;
}
+233 -132
View File
@@ -21,114 +21,29 @@
*/
@import <Foundation/CPObject.j>
#include "CoreGraphics/CGGeometry.h"
@import "CPText.j"
/*
@global
@group CPEventType
*/
CPLeftMouseDown = 1;
/*
@global
@group CPEventType
*/
CPLeftMouseUp = 2;
/*
@global
@group CPEventType
*/
CPRightMouseDown = 3;
/*
@global
@group CPEventType
*/
CPRightMouseUp = 4;
/*
@global
@group CPEventType
*/
CPMouseMoved = 5;
/*
@global
@group CPEventType
*/
CPLeftMouseDragged = 6;
/*
@global
@group CPEventType
*/
CPRightMouseDragged = 7;
/*
@global
@group CPEventType
*/
CPMouseEntered = 8;
/*
@global
@group CPEventType
*/
CPMouseExited = 9;
/*
@global
@group CPEventType
*/
CPKeyDown = 10;
/*
@global
@group CPEventType
*/
CPKeyUp = 11;
/*
@global
@group CPEventType
*/
CPFlagsChanged = 12;
/*
@global
@group CPEventType
*/
CPAppKitDefined = 13;
/*
@global
@group CPEventType
*/
CPSystemDefined = 14;
/*
@global
@group CPEventType
*/
CPApplicationDefined = 15;
/*
@global
@group CPEventType
*/
CPPeriodic = 16;
/*
@global
@group CPEventType
*/
CPCursorUpdate = 17;
/*
@global
@group CPEventType
*/
CPCursorUpdate = 17;
CPScrollWheel = 22;
/*
@global
@group CPEventType
*/
CPOtherMouseDown = 25;
/*
@global
@group CPEventType
*/
CPOtherMouseUp = 26;
/*
@global
@group CPEventType
*/
CPOtherMouseDragged = 27;
// iPhone Event Types
@@ -136,8 +51,7 @@ CPTouchStart = 28;
CPTouchMove = 29;
CPTouchEnd = 30;
CPTouchCancel = 31;
CPAlphaShiftKeyMask = 1 << 16;
CPShiftKeyMask = 1 << 17;
CPControlKeyMask = 1 << 18;
@@ -171,26 +85,102 @@ CPPeriodicMask = 1 << CPPeriodic;
CPScrollWheelMask = 1 << CPScrollWheel;
CPAnyEventMask = 0xffffffff;
CPDOMEventDoubleClick = "dblclick",
CPDOMEventMouseDown = "mousedown",
CPDOMEventMouseUp = "mouseup",
CPDOMEventMouseMoved = "mousemove",
CPDOMEventMouseDragged = "mousedrag",
CPDOMEventKeyUp = "keyup",
CPDOMEventKeyDown = "keydown",
CPDOMEventKeyPress = "keypress";
CPDOMEventCopy = "copy";
CPDOMEventPaste = "paste";
CPDOMEventScrollWheel = "mousewheel";
CPDOMEventTouchStart = "touchstart";
CPDOMEventTouchMove = "touchmove";
CPDOMEventTouchEnd = "touchend";
CPDOMEventTouchCancel = "touchcancel";
CPUpArrowFunctionKey = "\uF700";
CPDownArrowFunctionKey = "\uF701";
CPLeftArrowFunctionKey = "\uF702";
CPRightArrowFunctionKey = "\uF703";
CPF1FunctionKey = "\uF704";
CPF2FunctionKey = "\uF705";
CPF3FunctionKey = "\uF706";
CPF4FunctionKey = "\uF707";
CPF5FunctionKey = "\uF708";
CPF6FunctionKey = "\uF709";
CPF7FunctionKey = "\uF70A";
CPF8FunctionKey = "\uF70B";
CPF9FunctionKey = "\uF70C";
CPF10FunctionKey = "\uF70D";
CPF11FunctionKey = "\uF70E";
CPF12FunctionKey = "\uF70F";
CPF13FunctionKey = "\uF710";
CPF14FunctionKey = "\uF711";
CPF15FunctionKey = "\uF712";
CPF16FunctionKey = "\uF713";
CPF17FunctionKey = "\uF714";
CPF18FunctionKey = "\uF715";
CPF19FunctionKey = "\uF716";
CPF20FunctionKey = "\uF717";
CPF21FunctionKey = "\uF718";
CPF22FunctionKey = "\uF719";
CPF23FunctionKey = "\uF71A";
CPF24FunctionKey = "\uF71B";
CPF25FunctionKey = "\uF71C";
CPF26FunctionKey = "\uF71D";
CPF27FunctionKey = "\uF71E";
CPF28FunctionKey = "\uF71F";
CPF29FunctionKey = "\uF720";
CPF30FunctionKey = "\uF721";
CPF31FunctionKey = "\uF722";
CPF32FunctionKey = "\uF723";
CPF33FunctionKey = "\uF724";
CPF34FunctionKey = "\uF725";
CPF35FunctionKey = "\uF726";
CPInsertFunctionKey = "\uF727";
CPDeleteFunctionKey = "\uF728";
CPHomeFunctionKey = "\uF729";
CPBeginFunctionKey = "\uF72A";
CPEndFunctionKey = "\uF72B";
CPPageUpFunctionKey = "\uF72C";
CPPageDownFunctionKey = "\uF72D";
CPPrintScreenFunctionKey = "\uF72E";
CPScrollLockFunctionKey = "\uF72F";
CPPauseFunctionKey = "\uF730";
CPSysReqFunctionKey = "\uF731";
CPBreakFunctionKey = "\uF732";
CPResetFunctionKey = "\uF733";
CPStopFunctionKey = "\uF734";
CPMenuFunctionKey = "\uF735";
CPUserFunctionKey = "\uF736";
CPSystemFunctionKey = "\uF737";
CPPrintFunctionKey = "\uF738";
CPClearLineFunctionKey = "\uF739";
CPClearDisplayFunctionKey = "\uF73A";
CPInsertLineFunctionKey = "\uF73B";
CPDeleteLineFunctionKey = "\uF73C";
CPInsertCharFunctionKey = "\uF73D";
CPDeleteCharFunctionKey = "\uF73E";
CPPrevFunctionKey = "\uF73F";
CPNextFunctionKey = "\uF740";
CPSelectFunctionKey = "\uF741";
CPExecuteFunctionKey = "\uF742";
CPUndoFunctionKey = "\uF743";
CPRedoFunctionKey = "\uF744";
CPFindFunctionKey = "\uF745";
CPHelpFunctionKey = "\uF746";
CPModeSwitchFunctionKey = "\uF747";
CPEscapeFunctionKey = "\u001B";
CPDOMEventDoubleClick = "dblclick",
CPDOMEventMouseDown = "mousedown",
CPDOMEventMouseUp = "mouseup",
CPDOMEventMouseMoved = "mousemove",
CPDOMEventMouseDragged = "mousedrag",
CPDOMEventKeyUp = "keyup",
CPDOMEventKeyDown = "keydown",
CPDOMEventKeyPress = "keypress";
CPDOMEventCopy = "copy";
CPDOMEventPaste = "paste";
CPDOMEventScrollWheel = "mousewheel";
CPDOMEventTouchStart = "touchstart";
CPDOMEventTouchMove = "touchmove";
CPDOMEventTouchEnd = "touchend";
CPDOMEventTouchCancel = "touchcancel";
var _CPEventPeriodicEventPeriod = 0,
_CPEventPeriodicEventTimer = nil;
_CPEventPeriodicEventTimer = nil,
_CPEventUpperCaseRegex = new RegExp("[A-Z]");
/*!
/*!
@ingroup appkit
@class CPEvent
CPEvent encapsulates the details of a Cappuccino keyboard or mouse event.
@@ -206,12 +196,13 @@ var _CPEventPeriodicEventPeriod = 0,
unsigned _clickCount;
float _pressure;
CPWindow _window;
Number _windowNumber;
CPString _characters;
CPString _charactersIgnoringModifiers
BOOL _isARepeat;
unsigned _keyCode;
DOMEvent _DOMEvent;
float _deltaX;
float _deltaY;
float _deltaZ;
@@ -220,16 +211,16 @@ var _CPEventPeriodicEventPeriod = 0,
/*!
Creates a new keyboard event.
@param anEventType the event type. Must be one of CPKeyDown, CPKeyUp or CPFlagsChanged
@param aPoint the location of the cursor in the window specified by <code>aWindowNumber</code>
@param aPoint the location of the cursor in the window specified by \c aWindowNumber
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
@param aTimestamp the time the event occurred
@param aWindowNumber the number of the CPWindow where the event occurred
@param aGraphicsContext the graphics context where the event occurred
@param characters the characters associated with the event
@param unmodCharacters the string of keys pressed without the presence of any modifiers other than Shift
@param repeatKey <code>YES</code> if this is caused by the system repeat as opposed to the user pressing the key again
@param repeatKey \c YES if this is caused by the system repeat as opposed to the user pressing the key again
@param code a number associated with the keyboard key of this event
@throws CPInternalInconsistencyException if <code>anEventType</code> is not a CPKeyDown,
@throws CPInternalInconsistencyException if \c anEventType is not a CPKeyDown,
CPKeyUp or CPFlagsChanged
@return the keyboard event
*/
@@ -238,14 +229,14 @@ var _CPEventPeriodicEventPeriod = 0,
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)repeatKey keyCode:(unsigned short)code
{
return [[self alloc] _initKeyEventWithType:anEventType location:aPoint modifierFlags:modifierFlags
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext
characters:characters charactersIgnoringModifiers:unmodCharacters isARepeat:repeatKey keyCode:code];
}
/*!
Creates a new mouse event
@param anEventType the event type
@param aPoint the location of the cursor in the window specified by <code>aWindowNumber</code>
@param aPoint the location of the cursor in the window specified by \c aWindowNumber
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
@param aTimestamp the time the event occurred
@param aWindowNumber the number of the CPWindow where the event occurred
@@ -256,7 +247,7 @@ var _CPEventPeriodicEventPeriod = 0,
@throws CPInternalInconsistencyException if an invalid event type is provided
@return the new mouse event
*/
+ (id)mouseEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
+ (id)mouseEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
{
@@ -267,7 +258,7 @@ var _CPEventPeriodicEventPeriod = 0,
/*!
Creates a new custom event
@param anEventType the event type. Must be one of CPAppKitDefined, CPSystemDefined, CPApplicationDefined or CPPeriodic
@param aLocation the location of the cursor in the window specified by <code>aWindowNumber</code>
@param aLocation the location of the cursor in the window specified by \c aWindowNumber
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
@param aTimestamp the time the event occurred
@param aWindowNumber the number of the CPWindow where the event occurred
@@ -287,12 +278,12 @@ var _CPEventPeriodicEventPeriod = 0,
}
/* @ignore */
- (id)_initMouseEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned)modifierFlags
- (id)_initMouseEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
{
self = [super init];
if (self)
{
_type = anEventType;
@@ -305,7 +296,7 @@ var _CPEventPeriodicEventPeriod = 0,
_pressure = aPressure;
_window = [CPApp windowWithWindowNumber:aWindowNumber];
}
return self;
}
@@ -315,7 +306,7 @@ var _CPEventPeriodicEventPeriod = 0,
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)isARepeat keyCode:(unsigned short)code
{
self = [super init];
if (self)
{
_type = anEventType;
@@ -327,9 +318,9 @@ var _CPEventPeriodicEventPeriod = 0,
_charactersIgnoringModifiers = unmodCharacters;
_isARepeat = isARepeat;
_keyCode = code;
_window = [CPApp windowWithWindowNumber:aWindowNumber];
_windowNumber = aWindowNumber;
}
return self;
}
@@ -339,7 +330,7 @@ var _CPEventPeriodicEventPeriod = 0,
subtype:(short)aSubtype data1:(int)aData1 data2:(int)aData2
{
self = [super init];
if (self)
{
_type = anEventType;
@@ -350,22 +341,33 @@ var _CPEventPeriodicEventPeriod = 0,
_subtype = aSubtype;
_data1 = aData1;
_data2 = aData2;
}
}
return self;
}
/*!
Returns the location of the mouse (for mouse events).
If this is not a mouse event, it returns <code>nil</code>.
If <code>window</code> returns <code>nil</code>, then
If this is not a mouse event, it returns \c nil.
If \c window returns \c nil, then
the mouse coordinates will be based on the screen coordinates.
Otherwise, the coordinates are relative to the window's coordinates.
@return the location of the mouse, or <code>nil</code> for non-mouse events.
@return the location of the mouse, or \c nil for non-mouse events.
*/
- (CGPoint)locationInWindow
{
return _location;
return _CGPointMakeCopy(_location);
}
- (CGPoint)globalLocation
{
var theWindow = [self window],
location = [self locationInWindow];
if (theWindow)
return [theWindow convertBaseToGlobal:location];
return location;
}
/*!
@@ -397,6 +399,9 @@ var _CPEventPeriodicEventPeriod = 0,
*/
- (CPWindow)window
{
if (!_window)
_window = [CPApp windowWithWindowNumber:_windowNumber];
return _window;
}
@@ -414,7 +419,10 @@ var _CPEventPeriodicEventPeriod = 0,
*/
- (int)buttonNumber
{
return _buttonNumber;
if (_type === CPRightMouseDown || _type === CPRightMouseUp || _type === CPRightMouseDragged)
return 1;
return 0;
}
/*!
@@ -444,7 +452,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns <code>YES</code> if the keyboard event was caused by the key being held down.
Returns \c YES if the keyboard event was caused by the key being held down.
@throws CPInternalInconsistencyException if this method is called on a non-key event
*/
- (BOOL)isARepeat
@@ -461,6 +469,18 @@ var _CPEventPeriodicEventPeriod = 0,
return _keyCode;
}
+ (CGPoint)mouseLocation
{
// FIXME: this is incorrect, we shouldn't depend on the current event.
var event = [CPApp currentEvent],
eventWindow = [event window];
if (eventWindow)
return [eventWindow convertBaseToGlobal:[event locationInWindow]];
return [event locationInWindow];
}
- (float)pressure
{
return _pressure;
@@ -499,15 +519,76 @@ var _CPEventPeriodicEventPeriod = 0,
return _deltaZ;
}
- (BOOL)_triggersKeyEquivalent:(CPString)aKeyEquivalent withModifierMask:aKeyEquivalentModifierMask
{
if (!aKeyEquivalent)
return NO;
if (_CPEventUpperCaseRegex.test(aKeyEquivalent))
aKeyEquivalentModifierMask |= CPShiftKeyMask;
if (CPBrowserIsOperatingSystem(CPWindowsOperatingSystem) && (aKeyEquivalentModifierMask & CPCommandKeyMask))
{
aKeyEquivalentModifierMask |= CPControlKeyMask;
aKeyEquivalentModifierMask &= ~CPCommandKeyMask;
}
if ((_modifierFlags & (CPShiftKeyMask | CPAlternateKeyMask | CPCommandKeyMask | CPControlKeyMask)) !== aKeyEquivalentModifierMask)
return NO;
// Treat \r and \n as the same key equivalent. See issue #710.
if (_characters === CPNewlineCharacter || _characters === CPCarriageReturnCharacter)
return CPNewlineCharacter === aKeyEquivalent || CPCarriageReturnCharacter === aKeyEquivalent;
return [_characters caseInsensitiveCompare:aKeyEquivalent] === CPOrderedSame;
}
- (BOOL)_couldBeKeyEquivalent
{
if (_type !== CPKeyDown)
return NO;
var characterCount = _characters.length;
if (!characterCount)
return NO;
if (_modifierFlags & (CPCommandKeyMask | CPControlKeyMask))
return YES;
for(var i=0; i<characterCount; i++)
{
switch(_characters.charAt(i))
{
case CPBackspaceCharacter:
case CPDeleteCharacter:
case CPDeleteFunctionKey:
case CPTabCharacter:
case CPCarriageReturnCharacter:
case CPNewlineCharacter:
case CPEscapeFunctionKey:
case CPPageUpFunctionKey:
case CPPageDownFunctionKey:
case CPLeftArrowFunctionKey:
case CPUpArrowFunctionKey:
case CPRightArrowFunctionKey:
case CPDownArrowFunctionKey:
return YES;
}
}
// FIXME: More cases? Space?
return NO;
}
/*!
Generates periodic events every <code>aPeriod</code> seconds.
Gene rates periodic events every \c aPeriod seconds.
@param aDelay the number of seconds before the first event
@param aPeriod the length of time in seconds between successive events
*/
+ (void)startPeriodicEventsAfterDelay:(CPTimeInterval)aDelay withPeriod:(CPTimeInterval)aPeriod
{
_CPEventPeriodicEventPeriod = aPeriod;
// FIXME: OH TIMERS!!!
_CPEventPeriodicEventTimer = window.setTimeout(function() { _CPEventPeriodicEventTimer = window.setInterval(_CPEventFirePeriodEvent, aPeriod * 1000.0); }, aDelay * 1000.0);
}
@@ -519,9 +600,9 @@ var _CPEventPeriodicEventPeriod = 0,
{
if (_CPEventPeriodicEventTimer === nil)
return;
window.clearTimeout(_CPEventPeriodicEventTimer);
_CPEventPeriodicEventTimer = nil;
}
@@ -532,3 +613,23 @@ function _CPEventFirePeriodEvent()
[CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:_CGPointMakeZero() modifierFlags:0 timestamp:0 windowNumber:0 context:nil subtype:0 data1:0 data2:0]];
}
var CPEventClass = [CPEvent class];
function _CPEventFromNativeMouseEvent(aNativeEvent, anEventType, aPoint, modifierFlags, aTimestamp, aWindowNumber, aGraphicsContext, anEventNumber, aClickCount, aPressure)
{
aNativeEvent.isa = CPEventClass;
aNativeEvent._type = anEventType;
aNativeEvent._location = aPoint;
aNativeEvent._modifierFlags = modifierFlags;
aNativeEvent._timestamp = aTimestamp;
aNativeEvent._windowNumber = aWindowNumber;
aNativeEvent._window = nil;
aNativeEvent._context = aGraphicsContext;
aNativeEvent._eventNumber = anEventNumber;
aNativeEvent._clickCount = aClickCount;
aNativeEvent._pressure = aPressure;
return aNativeEvent;
}
+30 -6
View File
@@ -22,6 +22,7 @@
@import <Foundation/CPObject.j>
/*!
@ingroup appkit
@class CPFlashMovie
@@ -30,17 +31,17 @@
*/
@implementation CPFlashMovie : CPObject
{
CPString _fileName;
CPString _filename;
}
/*!
Creates a new Flash movie with the swf at <code>aFileName</code>.
Creates a new Flash movie with the swf at \c aFileName.
@param aFilename the swf to load
@return the initialized CPFlashMovie
*/
+ (id)flashMovieWithFile:(CPString)aFileName
+ (id)flashMovieWithFile:(CPString)aFilename
{
return [[self alloc] initWithFile:aFileName];
return [[self alloc] initWithFile:aFilename];
}
/*!
@@ -48,14 +49,37 @@
@param aFilename the swf to load
@return the initialized CPFlashMovie
*/
- (id)initWithFile:(CPString)aFileName
- (id)initWithFile:(CPString)aFilename
{
self = [super init];
if (self)
_fileName = aFileName;
_filename = aFilename;
return self;
}
- (CPString)filename
{
return _filename;
}
@end
var CPFlashMovieFilenameKey = "CPFlashMovieFilenameKey";
@implementation CPFlashMovie (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
_filename = [aCoder decodeObjectForKey:CPFlashMovieFilenameKey];
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_filename forKey:CPFlashMovieFilenameKey];
}
@end
+131 -40
View File
@@ -20,10 +20,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPDOMWindowBridge.j"
@import "CPFlashMovie.j"
@import "CPView.j"
var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
/*!
@ingroup appkit
*/
@@ -31,9 +33,13 @@
{
CPFlashMovie _flashMovie;
DOMElement _DOMEmbedElement;
DOMElement _DOMMParamElement;
CPDictionary _params;
CPDictionary _paramElements;
#if PLATFORM(DOM)
DOMElement _DOMParamElement;
DOMElement _DOMObjectElement;
DOMElement _DOMInnerObjectElement;
#endif
}
- (id)initWithFrame:(CGRect)aFrame
@@ -42,35 +48,32 @@
if (self)
{
_DOMObjectElement = document.createElement("object");
_DOMObjectElement.width = "100%";
_DOMObjectElement.height = "100%";
_DOMObjectElement.style.top = "0px";
_DOMObjectElement.style.left = "0px";
_DOMParamElement = document.createElement("param");
_DOMParamElement.name = "movie";
_DOMObjectElement.appendChild(_DOMParamElement);
var param = document.createElement("param");
param.name = "wmode";
param.value = "transparent";
_DOMObjectElement.appendChild(param);
_DOMEmbedElement = document.createElement("embed");
_DOMEmbedElement.type = "application/x-shockwave-flash";
_DOMEmbedElement.setAttribute("wmode", "transparent");
_DOMEmbedElement.width = "100%";
_DOMEmbedElement.height = "100%";
// IE requires this thing to be in the _DOMElement and not the _DOMObjectElement.
_DOMElement.appendChild(_DOMEmbedElement);
_DOMElement.appendChild(_DOMObjectElement);
#if PLATFORM(DOM)
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
_DOMObjectElement = document.createElement(@"object");
_DOMObjectElement.width = @"100%";
_DOMObjectElement.height = @"100%";
_DOMObjectElement.style.top = @"0px";
_DOMObjectElement.style.left = @"0px";
_DOMObjectElement.type = @"application/x-shockwave-flash";
_DOMObjectElement.setAttribute(@"classid", IEFlashCLSID);
_DOMParamElement = document.createElement(@"param");
_DOMParamElement.name = @"movie";
_DOMInnerObjectElement = document.createElement(@"object");
_DOMInnerObjectElement.width = @"100%";
_DOMInnerObjectElement.height = @"100%";
_DOMObjectElement.appendChild(_DOMParamElement);
_DOMObjectElement.appendChild(_DOMInnerObjectElement);
_DOMElement.appendChild(_DOMObjectElement);
}
else
[self _rebuildIEObjects];
#endif
}
return self;
@@ -82,11 +85,15 @@
return;
_flashMovie = aFlashMovie;
_DOMParamElement.value = aFlashMovie._fileName;
if (_DOMEmbedElement)
_DOMEmbedElement.src = aFlashMovie._fileName;
#if PLATFORM(DOM)
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
_DOMParamElement.value = [aFlashMovie filename];
_DOMInnerObjectElement.data = [aFlashMovie filename];
}
else
[self _rebuildIEObjects];
#endif
}
- (CPFlashMovie)flashMovie
@@ -94,19 +101,103 @@
return _flashMovie;
}
- (void)setFlashVars:(CPDictionary)aDictionary
{
var varString = @"",
enumerator = [aDictionary keyEnumerator];
var key;
while (key = [enumerator nextObject])
varString = [varString stringByAppendingFormat:@"&%@=%@", key, [aDictionary objectForKey:key]];
if (!_params)
_params = [CPDictionary dictionary];
[_params setObject:varString forKey:@"flashvars"];
[self setParameters:_params];
}
- (CPDictionary)flashVars
{
return [_params objectForKey:@"flashvars"];
}
- (void)setParameters:(CPDictionary)aDictionary
{
#if PLATFORM(DOM)
if (_paramElements && !CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
var elements = [_paramElements allValues],
count = [elements count];
for (var i = 0; i < count; i++)
_DOMObjectElement.removeChild([elements objectAtIndex:i]);
}
#endif
_params = aDictionary;
#if PLATFORM(DOM)
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
_paramElements = [CPDictionary dictionary];
var enumerator = [_params keyEnumerator],
key;
while (key = [enumerator nextObject] && _DOMObjectElement)
{
var param = document.createElement(@"param");
param.name = key;
param.value = [_params objectForKey:key];
_DOMObjectElement.appendChild(param);
[_paramElements setObject:param forKey:key];
}
}
else
[self _rebuildIEObjects];
#endif
}
- (CPDictionary)parameters
{
return _params;
}
#if PLATFORM(DOM)
- (void)_rebuildIEObjects
{
_DOMElement.innerHTML = @"";
if (![_flashMovie filename])
return;
var paramString = [CPString stringWithFormat:@"<param name='movie' value='%@' />", [_flashMovie filename]],
paramEnumerator = [_params keyEnumerator],
key;
while (key = [paramEnumerator nextObject])
paramString = [paramString stringByAppendingFormat:@"<param name='%@' value='%@' />", key, [_params objectForKey:key]];
_DOMObjectElement = document.createElement(@"object");
_DOMElement.appendChild(_DOMObjectElement);
_DOMObjectElement.outerHTML = [CPString stringWithFormat:@"<object classid=%@ width=%@ height=%@>%@</object>", IEFlashCLSID, CGRectGetWidth([self bounds]), CGRectGetHeight([self bounds]), paramString];
}
#endif
- (void)mouseDragged:(CPEvent)anEvent
{
[[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES];
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
- (void)mouseDown:(CPEvent)anEvent
{
[[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES];
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
- (void)mouseUp:(CPEvent)anEvent
{
[[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES];
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
@end
+90 -12
View File
@@ -20,12 +20,21 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
var _CPFonts = {};
_CPFontSystemFontFace = @"Arial";
@import <Foundation/CPObject.j>
@import <Foundation/CPBundle.j>
#define _CPCachedFont(aName, aSize, isBold) _CPFonts[(isBold ? @"bold " : @"") + ROUND(aSize) + @"px '" + aName + @"'"]
@import "CPView.j"
/*!
var _CPFonts = {},
_CPFontSystemFontFace = @"Arial, sans-serif",
_CPWrapRegExp = new RegExp("\\s*,\\s*", "g");
#define _CPCreateCSSString(aName, aSize, isBold) (isBold ? @"bold " : @"") + ROUND(aSize) + @"px " + ((aName === _CPFontSystemFontFace) ? aName : (@"\"" + aName.replace(_CPWrapRegExp, '", "') + @"\", " + _CPFontSystemFontFace))
#define _CPCachedFont(aName, aSize, isBold) _CPFonts[_CPCreateCSSString(aName, aSize, isBold)]
/*!
@ingroup appkit
@class CPFont
@@ -35,11 +44,22 @@ var _CPFonts = {};
{
CPString _name;
float _size;
float _ascender;
float _descender;
float _lineHeight;
BOOL _isBold;
CPString _cssString;
}
+ (void)initialize
{
var systemFont = [[CPBundle bundleForClass:[CPView class]] objectForInfoDictionaryKey:"CPSystemFontFace"];
if (systemFont)
_CPFontSystemFontFace = systemFont;
}
/*!
Returns a font with the specified name and size.
@param aName the name of the font
@@ -86,25 +106,64 @@ var _CPFonts = {};
@ignore
*/
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold
{
{
self = [super init];
if (self)
{
_name = aName;
_size = aSize;
_ascender = 0;
_descender = 0;
_lineHeight = 0;
_isBold = isBold;
_cssString = (_isBold ? @"bold " : @"") + ROUND(aSize) + @"px '" + aName + @"'";
_cssString = _CPCreateCSSString(_name, _size, _isBold);
_CPFonts[_cssString] = self;
}
return self;
}
/*!
Returns the font size (in points)
Returns the distance of the longest ascender's top y-coordinate from the baseline (in CSS px)
*/
- (float)ascender
{
if (!_ascender)
[self _getMetrics];
return _ascender;
}
/*!
Returns the bottom y coordinate (in CSS px), offset from the baseline, of the receiver's longest descender.
Thus, if the longest descender extends 2 points below the baseline, descender will return 2.
*/
- (float)descender
{
if (!_descender)
[self _getMetrics];
return _descender;
}
/*!
Returns the default line height.
NOTE: This was moved from NSFont to NSLayoutManager in Cocoa, but since there is no CPLayoutManager, it has been kept here.
*/
- (float)defaultLineHeightForFont
{
if (!_lineHeight)
[self _getMetrics];
return _lineHeight;
}
/*!
Returns the font size (in CSS px)
*/
- (float)size
{
@@ -127,6 +186,25 @@ var _CPFonts = {};
return _name;
}
- (BOOL)isEqual:(id)anObject
{
return [anObject isKindOfClass:[CPFont class]] && [anObject cssString] === [self cssString];
}
- (CPString)description
{
return [CPString stringWithFormat:@"%@ %@ %f pt.", [super description], [self familyName], [self size]];
}
- (void)_getMetrics
{
var metrics = [CPString metricsOfFont:self];
_ascender = [metrics objectForKey:@"ascender"];
_descender = [metrics objectForKey:@"descender"];
_lineHeight = [metrics objectForKey:@"lineHeight"];
}
@end
var CPFontNameKey = @"CPFontNameKey",
+2 -2
View File
@@ -22,7 +22,7 @@
@import <Foundation/CPObject.j>
@import <AppKit/CPFont.j>
@import "CPFont.j"
var CPSharedFontManager = nil,
@@ -51,7 +51,7 @@ var CPSharedFontManager = nil,
// Changing the Default Font Conversion Classes
/*!
Sets the class that will be used to create the applcation's
Sets the class that will be used to create the application's
font manager.
*/
+ (void)setFontManagerFactory:(Class)aClass
+59 -45
View File
@@ -62,15 +62,15 @@ function CPPointMake(x, y)
}
/*!
Makes a CGRect with an origin and size equal to <code>aRect</code> less the <code>dX/dY</code> insets specified.
Makes a CGRect with an origin and size equal to \c aRect less the \c dX/dY insets specified.
@param dX the size of the inset in the x-axis
@param dY the size of the inset in the y-axis
@group CGRect
@return CGRect a rectangle like <code>aRect</code> with an inset
@return CGRect a rectangle like \c aRect with an inset
*/
function CPRectInset(aRect, dX, dY)
{
return CPRectMake( aRect.origin.x + dX, aRect.origin.y + dY,
return CPRectMake( aRect.origin.x + dX, aRect.origin.y + dY,
aRect.size.width - 2 * dX, aRect.size.height - 2*dY);
}
@@ -96,13 +96,13 @@ function CPRectIntegral(aRect)
function CPRectIntersection(lhsRect, rhsRect)
{
var intersection = CPRectMake(
Math.max(CPRectGetMinX(lhsRect), CPRectGetMinX(rhsRect)),
Math.max(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
Math.max(CPRectGetMinX(lhsRect), CPRectGetMinX(rhsRect)),
Math.max(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
0, 0);
intersection.size.width = Math.min(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)) - CPRectGetMinX(intersection);
intersection.size.height = Math.min(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect)) - CPRectGetMinY(intersection);
return CPRectIsEmpty(intersection) ? CPRectMakeZero() : intersection;
}
@@ -132,7 +132,7 @@ function CPRectMake(x, y, width, height)
}
/*!
Creates a new rectangle with its origin offset by <code>dX</code> and <code>dY</code>.
Creates a new rectangle with its origin offset by \c dX and \c dY.
@group CGRect
@param aRect the rectangle to copy the origin and size from
@param dX the amount added to the x-size of the new rectangle
@@ -160,18 +160,18 @@ function CPRectStandardize(aRect)
standardized.origin.x += width;
standardized.size.width = -width;
}
if (height < 0.0)
{
standardized.origin.y += height;
standardized.size.height = -height;
}
return standardized;
}
/*!
Returns the smallest rectangle that can contain the two argument <code>CGRect</code>s.
Returns the smallest rectangle that can contain the two argument \c CGRects.
@group CGRect
@param lhsRect the first CGRect to use for the union calculation
@param rhsRect the second CGRect to use for the union calculation
@@ -183,7 +183,7 @@ function CPRectUnion(lhsRect, rhsRect)
minY = Math.min(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
maxX = Math.max(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)),
maxY = Math.max(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect));
return CPRectMake(minX, minY, maxX - minX, maxY - minY);
}
@@ -211,41 +211,41 @@ function CPSizeMake(width, height)
}
/*!
Returns <code>YES</code> if the CGRect, <code>aRect</code>, contains
the CGPoint, <code>aPoint</code>.
Returns \c YES if the CGRect, \c aRect, contains
the CGPoint, \c aPoint.
@param aRect the rectangle to test with
@param aPoint the point to test with
@group CGRect
@return BOOL <code>YES</code> if the rectangle contains the point, <code>NO</code> otherwise.
@return BOOL \c YES if the rectangle contains the point, \c NO otherwise.
*/
function CPRectContainsPoint(aRect, aPoint)
{
return aPoint.x >= CPRectGetMinX(aRect) &&
aPoint.y >= CPRectGetMinY(aRect) &&
aPoint.x < CPRectGetMaxX(aRect) &&
aPoint.y < CPRectGetMaxY(aRect);
aPoint.x < CPRectGetMaxX(aRect) &&
aPoint.y < CPRectGetMaxY(aRect);
}
/*!
Returns a <code>BOOL</code> indicating whether CGRect <code>possibleOuter</code>
contains CGRect <code>possibleInner</code>.
Returns a \c BOOL indicating whether CGRect \c possibleOuter
contains CGRect \c possibleInner.
@group CGRect
@param possibleOuter the CGRect to test if <code>possibleInner</code> is inside of
@param possibleInner the CGRect to test if it fits inside <code>possibleOuter</code>.
@return BOOL <code>YES</code> if <code>possibleInner</code> fits inside <code>possibleOuter</code>.
@param possibleOuter the CGRect to test if \c possibleInner is inside of
@param possibleInner the CGRect to test if it fits inside \c possibleOuter.
@return BOOL \c YES if \c possibleInner fits inside \c possibleOuter.
*/
function CPRectContainsRect(lhsRect, rhsRect)
function CPRectContainsRect(possibleOuter, possibleInner)
{
return CPRectEqualToRect(CPUnionRect(lhsRect, rhsRect), rhsRect);
return CGRectContainsRect(possibleOuter, possibleInner);
}
/*!
Tests whether the two CGPoints are equal to each other by comparing their
<code>x</code> and <code>y</code> members.
\c x and \c y members.
@group @CGPoint
@param lhsPoint the first CGPoint to check
@param rhsPoint the second CGPoint to check
@return BOOL <code>YES</code> if the two points have the same x's, and the same y's.
@return BOOL \c YES if the two points have the same x's, and the same y's.
*/
function CPPointEqualToPoint(lhsPoint, rhsPoint)
{
@@ -257,11 +257,11 @@ function CPPointEqualToPoint(lhsPoint, rhsPoint)
@group CGRect
@param lhsRect the first CGRect to compare
@param rhsRect the second CGRect to compare
@return BOOL <code>YES</code> if the two rectangles have the same origin and size. <code>NO</code>, otherwise.
@return BOOL \c YES if the two rectangles have the same origin and size. \c NO, otherwise.
*/
function CPRectEqualToRect(lhsRect, rhsRect)
{
return CPPointEqualToPoint(lhsRect.origin, rhsRect.origin) &&
return CPPointEqualToPoint(lhsRect.origin, rhsRect.origin) &&
CPSizeEqualToSize(lhsRect.size, rhsRect.size);
}
@@ -346,11 +346,11 @@ function CPRectGetWidth(aRect)
}
/*!
Returns <code>YES</code> if the two rectangles intersect
Returns \c YES if the two rectangles intersect
@group CGRect
@param lhsRect the first CGRect
@param rhsRect the second CGRect
@return BOOL <code>YES</code> if the two rectangles have any common spaces, and <code>NO</code>, otherwise.
@return BOOL \c YES if the two rectangles have any common spaces, and \c NO, otherwise.
*/
function CPRectIntersectsRect(lhsRect, rhsRect)
{
@@ -358,11 +358,11 @@ function CPRectIntersectsRect(lhsRect, rhsRect)
}
/*!
Returns <code>YES</code> if the CGRect has no area.
Returns \c YES if the CGRect has no area.
The test is performed by checking if the width and height are both zero.
@group CGRect
@param aRect the CGRect to test
@return BOOL <code>YES</code> if the CGRect has no area, and <code>NO</code>, otherwise.
@return BOOL \c YES if the CGRect has no area, and \c NO, otherwise.
*/
function CPRectIsEmpty(aRect)
{
@@ -370,10 +370,10 @@ function CPRectIsEmpty(aRect)
}
/*!
Returns <code>YES</code> if the CGRect has no area.
Returns \c YES if the CGRect has no area.
The test is performed by checking if the width and height are both zero.
@group CGRect
@return BOOL <code>YES</code> if the CGRect has no area, and <code>NO</code>, otherwise.
@return BOOL \c YES if the CGRect has no area, and \c NO, otherwise.
*/
function CPRectIsNull(aRect)
{
@@ -381,11 +381,25 @@ function CPRectIsNull(aRect)
}
/*!
Returns <code>YES</code> if the two CGSizes are identical.
Creates two rectangles -- slice and rem -- from inRect, by dividing inRect
with a line that's parallel to the side of inRect specified by edge.
The size of slice is determined by amount, which specifies the distance from edge.
slice and rem must not be NULL.
@group CGRect
*/
function CPDivideRect(inRect, slice, rem, amount, edge)
{
CGRectDivide(inRect, slice, rem, amount, edge);
}
/*!
Returns \c YES if the two CGSizes are identical.
@group CGSize
@param lhsSize the first CGSize to compare
@param rhsSize the second CGSize to compare
@return BOOL <code>YES</code> if the two sizes are identical. <code>NO</code>, otherwise.
@return BOOL \c YES if the two sizes are identical. \c NO, otherwise.
*/
function CPSizeEqualToSize(lhsSize, rhsSize)
{
@@ -434,7 +448,7 @@ function CPStringFromRect(aRect)
function CPPointFromString(aString)
{
var comma = aString.indexOf(',');
return { x:parseFloat(aString.substr(1, comma - 1), 10), y:parseFloat(aString.substring(comma + 1, aString.length), 10) };
}
@@ -447,20 +461,20 @@ function CPPointFromString(aString)
function CPSizeFromString(aString)
{
var comma = aString.indexOf(',');
return { width:parseFloat(aString.substr(1, comma - 1), 10), height:parseFloat(aString.substring(comma + 1, aString.length), 10) };
}
/*!
Returns a CGRect created from a string.
@group CGRect
@param aString a string in the form generated by <code>CPStringFromRect</code>
@param aString a string in the form generated by \c CPStringFromRect
@return CGRect the rectangle created from the string
*/
function CPRectFromString(aString)
{
var comma = aString.indexOf(',', aString.indexOf(',') + 1);
return { origin:CPPointFromString(aString.substr(1, comma - 1)), size:CPSizeFromString(aString.substring(comma + 2, aString.length)) };
}
@@ -477,7 +491,7 @@ function CPPointFromEvent(anEvent)
/*!
Returns a zero sized CGSize.
@group CGSize
@return CGSize a size object with zeros for <code>width</code> and <code>height</code>
@return CGSize a size object with zeros for \c width and \c height
*/
function CPSizeMakeZero()
{
@@ -485,7 +499,7 @@ function CPSizeMakeZero()
}
/*!
Returns a rectangle at origin <code>(0,0)</code> and size of <code>(0,0)</code>.
Returns a rectangle at origin \c (0,0) and size of \c (0,0).
@group CGRect
@return CGRect a zeroed out CGRect
*/
@@ -495,15 +509,15 @@ function CPRectMakeZero()
}
/*!
Returns a point located at <code>(0, 0)</code>.
Returns a point located at \c (0, 0).
@group CGPoint
@return CGPoint a point located at <code>(0, 0)</code>
@return CGPoint a point located at \c (0, 0)
*/
function CPPointMakeZero()
{
return CPPointMake(0, 0, 0);
}
/*!
/*!
@}
*/
+108
View File
@@ -0,0 +1,108 @@
/*
* CPGraphics.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2010, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPColor.j"
@import "CPGraphicsContext.j"
function CPDrawTiledRects(
/* CGRect */ boundsRect,
/* CGRect */ clipRect,
/* CPRectEdge[] */ sides,
/* float[] */ grays)
{
if (sides.length != grays.length)
[CPException raise:CPInvalidArgumentException reason:@"sides (length: " + sides.length + ") and grays (length: " + grays.length + ") must have the same length."];
var colors = [];
for (var i = 0; i < grays.length; ++i)
colors.push([CPColor colorWithCalibratedWhite:grays[i] alpha:1.0]);
return CPDrawColorTiledRects(boundsRect, clipRect, sides, colors);
}
function CPDrawColorTiledRects(
/* CGRect */ boundsRect,
/* CGRect */ clipRect,
/* CPRectEdge[] */ sides,
/* CPColor[] */ colors)
{
if (sides.length != colors.length)
[CPException raise:CPInvalidArgumentException reason:@"sides (length: " + sides.length + ") and colors (length: " + colors.length + ") must have the same length."];
var resultRect = _CGRectMakeCopy(boundsRect),
slice = _CGRectMakeZero(),
remainder = _CGRectMakeZero(),
context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(context);
CGContextSetLineWidth(context, 1.0);
for (var sideIndex = 0; sideIndex < sides.length; ++sideIndex)
{
var side = sides[sideIndex];
CGRectDivide(resultRect, slice, remainder, 1.0, side);
resultRect = remainder;
slice = CGRectIntersection(slice, clipRect);
// Cocoa docs say that only slices that are within the clipRect are actually drawn
if (_CGRectIsEmpty(slice))
continue;
var minX, maxX, minY, maxY;
if (side == CPMinXEdge || side == CPMaxXEdge)
{
// Make sure we have at least 1 pixel to draw a line
if (_CGRectGetWidth(slice) < 1.0)
continue;
minX = _CGRectGetMinX(slice) + 0.5;
maxX = minX;
minY = _CGRectGetMinY(slice);
maxY = _CGRectGetMaxY(slice);
}
else // CPMinYEdge || CPMaxYEdge
{
// Make sure we have at least 1 pixel to draw a line
if (_CGRectGetHeight(slice) < 1.0)
continue;
minX = _CGRectGetMinX(slice);
maxX = _CGRectGetMaxX(slice);
minY = _CGRectGetMinY(slice) + 0.5;
maxY = minY;
}
CGContextBeginPath(context);
CGContextMoveToPoint(context, minX, minY);
CGContextAddLineToPoint(context, maxX, maxY);
CGContextSetStrokeColor(context, colors[sideIndex]);
CGContextStrokePath(context);
}
CGContextRestoreGState(context);
return resultRect;
}
+5
View File
@@ -20,6 +20,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import "CGContext.j"
var CPGraphicsContextCurrent = nil;
/*!
+101 -40
View File
@@ -19,7 +19,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPBundle.j>
@import <Foundation/CPNotificationCenter.j>
@import <Foundation/CPObject.j>
@@ -28,6 +28,7 @@
@import "CPGeometry.j"
CPImageLoadStatusInitialized = 0;
CPImageLoadStatusLoading = 1;
CPImageLoadStatusCompleted = 2;
@@ -38,26 +39,32 @@ CPImageLoadStatusReadError = 6;
CPImageDidLoadNotification = @"CPImageDidLoadNotification";
// Image Names
CPImageNameColorPanel = @"CPImageNameColorPanel";
CPImageNameColorPanelHighlighted = @"CPImageNameColorPanelHighlighted";
var imagesForNames = { },
AppKitImageForNames = { };
AppKitImageForNames[CPImageNameColorPanel] = CGSizeMake(26.0, 29.0);
AppKitImageForNames[CPImageNameColorPanelHighlighted] = CGSizeMake(26.0, 29.0);
function CPImageInBundle(aFilename, aSize, aBundle)
{
if (!aBundle)
aBundle = [CPBundle mainBundle];
if (aSize)
return [[CPImage alloc] initWithContentsOfFile:[aBundle pathForResource:aFilename] size:aSize];
return [[CPImage alloc] initWithContentsOfFile:[aBundle pathForResource:aFilename]];
}
@implementation CPBundle (CPImageAdditions)
- (CPString)pathForResource:(CPString)aFilename
function CPAppKitImage(aFilename, aSize)
{
return [self resourcePath] + '/' + aFilename;
return CPImageInBundle(aFilename, aSize, [CPBundle bundleForClass:[CPView class]]);
}
@end
/*!
@ingroup appkit
@class CPImage
@@ -83,32 +90,38 @@ function CPImageInBundle(aFilename, aSize, aBundle)
{
CGSize _size;
CPString _filename;
CPString _name;
id _delegate;
unsigned _loadStatus;
Image _image;
}
- (id)init
{
return [self initByReferencingFile:@"" size:CGSizeMake(-1, -1)];
}
/*!
Initializes the image, by associating it with a filename. The image
denoted in <code>aFilename</code> is not actually loaded. It will
denoted in \c aFilename is not actually loaded. It will
be loaded once needed.
@param aFilename the file containing the image
@param aSize the image's size
@return the initialized image
*/
- (CPImage)initByReferencingFile:(CPString)aFilename size:(CGSize)aSize
- (id)initByReferencingFile:(CPString)aFilename size:(CGSize)aSize
{
self = [super init];
if (self)
{
_size = CPSizeCreateCopy(aSize);
_filename = aFilename;
_loadStatus = CPImageLoadStatusInitialized;
}
return self;
}
@@ -118,13 +131,13 @@ function CPImageInBundle(aFilename, aSize, aBundle)
@param aSize the size of the image
@return the initialized image.
*/
- (CPImage)initWithContentsOfFile:(CPString)aFilename size:(CGSize)aSize
- (id)initWithContentsOfFile:(CPString)aFilename size:(CGSize)aSize
{
self = [self initByReferencingFile:aFilename size:aSize];
if (self)
[self load];
return self;
}
@@ -134,13 +147,13 @@ function CPImageInBundle(aFilename, aSize, aBundle)
@param aFilename the file name of the image
@return the initialized image
*/
- (CPImage)initWithContentsOfFile:(CPString)aFilename
- (id)initWithContentsOfFile:(CPString)aFilename
{
self = [self initByReferencingFile:aFilename size: CGSizeMake(-1, -1)];
self = [self initByReferencingFile:aFilename size:CGSizeMake(-1, -1)];
if (self)
[self load];
return self;
}
@@ -169,6 +182,50 @@ function CPImageInBundle(aFilename, aSize, aBundle)
return _size;
}
+ (id)imageNamed:(CPString)aName
{
var image = imagesForNames[aName];
if (image)
return image;
var imageOrSize = AppKitImageForNames[aName];
if (!imageOrSize)
return nil;
if (!imageOrSize.isa)
{
imageOrSize = CPAppKitImage("CPImage/" + aName + ".png", imageOrSize);
[imageOrSize setName:aName];
AppKitImageForNames[aName] = imageOrSize;
}
return imageOrSize;
}
- (BOOL)setName:(CPString)aName
{
if (_name === aName)
return YES;
if (imagesForNames[aName])
return NO;
_name = aName;
imagesForNames[aName] = self;
return YES;
}
- (CPString)name
{
return _name;
}
/*!
Sets the receiver's delegate.
@param the delegate
@@ -187,9 +244,9 @@ function CPImageInBundle(aFilename, aSize, aBundle)
}
/*!
Returns <code>YES</code> if the image data has already been loaded.
Returns the load status, which will be CPImageLoadStatusCompleted if the image data has already been loaded.
*/
- (BOOL)loadStatus
- (unsigned)loadStatus
{
return _loadStatus;
}
@@ -204,9 +261,10 @@ function CPImageInBundle(aFilename, aSize, aBundle)
{
if (_loadStatus == CPImageLoadStatusLoading || _loadStatus == CPImageLoadStatusCompleted)
return;
_loadStatus = CPImageLoadStatusLoading;
#if PLATFORM(DOM)
_image = new Image();
var isSynchronous = YES;
@@ -223,7 +281,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
}
[self _derefFromImage];
}
_image.onerror = function ()
{
if (isSynchronous)
@@ -235,7 +293,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
}
[self _derefFromImage];
}
_image.onabort = function ()
{
if (isSynchronous)
@@ -247,10 +305,13 @@ function CPImageInBundle(aFilename, aSize, aBundle)
}
[self _derefFromImage];
}
_image.src = _filename;
isSynchronous = NO;
// onload and friends may fire after this point but BEFORE the end of the run loop,
// crazy, I know. So don't set isSynchronous here, rather wait a bit longer.
window.setTimeout(function() { isSynchronous = NO; }, 0);
#endif
}
- (BOOL)isThreePartImage
@@ -283,7 +344,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
[[CPNotificationCenter defaultCenter]
postNotificationName:CPImageDidLoadNotification
object:self];
if ([_delegate respondsToSelector:@selector(imageDidLoad:)])
[_delegate imageDidLoad:self];
}
@@ -292,7 +353,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
- (void)_imageDidError
{
_loadStatus = CPImageLoadStatusReadError;
if ([_delegate respondsToSelector:@selector(imageDidError:)])
[_delegate imageDidError:self];
}
@@ -301,7 +362,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
- (void)_imageDidAbort
{
_loadStatus = CPImageLoadStatusCancelled;
if ([_delegate respondsToSelector:@selector(imageDidAbort:)])
[_delegate imageDidAbort:self];
}
@@ -341,7 +402,7 @@ function CPImageInBundle(aFilename, aSize, aBundle)
- (id)initWithImageSlices:(CPArray)imageSlices isVertical:(BOOL)isVertical
{
self = [super init];
if (self)
{
_imageSlices = imageSlices;
@@ -386,13 +447,13 @@ var CPThreePartImageImageSlicesKey = @"CPThreePartImageImageSlicesKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_imageSlices = [aCoder decodeObjectForKey:CPThreePartImageImageSlicesKey];
_isVertical = [aCoder decodeBoolForKey:CPThreePartImageIsVerticalKey];
}
return self;
}
@@ -413,10 +474,10 @@ var CPThreePartImageImageSlicesKey = @"CPThreePartImageImageSlicesKey",
- (id)initWithImageSlices:(CPArray)imageSlices
{
self = [super init];
if (self)
_imageSlices = imageSlices;
return self;
}
@@ -449,10 +510,10 @@ var CPNinePartImageImageSlicesKey = @"CPNinePartImageImageSlicesKey";
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
_imageSlices = [aCoder decodeObjectForKey:CPNinePartImageImageSlicesKey];
return self;
}
+161 -31
View File
@@ -26,30 +26,23 @@
@import "CPImage.j"
@import "CPShadowView.j"
#include "Platform/Platform.h"
#include "Platform/DOM/CPDOMDisplayServer.h"
#include "CoreGraphics/CGGeometry.h"
/*
@global
@group CPImageScaling
*/
CPScaleProportionally = 0;
/*
@global
@group CPImageScaling
*/
CPScaleToFit = 1;
/*
@global
@group CPImageScaling
*/
CPScaleNone = 2;
CPImageAlignCenter = 0;
CPImageAlignTop = 1;
CPImageAlignTopLeft = 2;
CPImageAlignTopRight = 3;
CPImageAlignLeft = 4;
CPImageAlignBottom = 5;
CPImageAlignBottomLeft = 6;
CPImageAlignBottomRight = 7;
CPImageAlignRight = 8;
var CPImageViewShadowBackgroundColor = nil;
var CPImageViewShadowBackgroundColor = nil,
CPImageViewEmptyPlaceholderImage = nil;
var LEFT_SHADOW_INSET = 3.0,
RIGHT_SHADOW_INSET = 3.0,
@@ -66,12 +59,22 @@ var LEFT_SHADOW_INSET = 3.0,
*/
@implementation CPImageView : CPControl
{
DOMElement _DOMImageElement;
DOMElement _DOMImageElement;
BOOL _hasShadow;
CPView _shadowView;
BOOL _hasShadow;
CPView _shadowView;
BOOL _isEditable;
CGRect _imageRect;
CPImageAlignment _imageAlignment;
}
+ (void)initialize
{
var bundle = [CPBundle bundleForClass:[CPView class]];
CGRect _imageRect;
CPImageViewEmptyPlaceholderImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"empty.png"]];
}
- (id)initWithFrame:(CGRect)aFrame
@@ -85,7 +88,13 @@ var LEFT_SHADOW_INSET = 3.0,
_DOMImageElement.style.position = "absolute";
_DOMImageElement.style.left = "0px";
_DOMImageElement.style.top = "0px";
if ([CPPlatform supportsDragAndDrop])
{
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement);
_DOMImageElement.style.visibility = "hidden";
@@ -126,7 +135,7 @@ var LEFT_SHADOW_INSET = 3.0,
var newImage = [self objectValue];
#if PLATFORM(DOM)
_DOMImageElement.src = newImage ? [newImage filename] : "";
_DOMImageElement.src = newImage ? [newImage filename] : [CPImageViewEmptyPlaceholderImage filename];
#endif
var size = [newImage size];
@@ -159,8 +168,8 @@ var LEFT_SHADOW_INSET = 3.0,
}
/*!
Returns <code>YES</code> if the image view draws with
a drop shadow. The default is <code>NO</code>.
Returns \c YES if the image view draws with
a drop shadow. The default is \c NO.
*/
- (BOOL)hasShadow
{
@@ -197,6 +206,30 @@ var LEFT_SHADOW_INSET = 3.0,
[self hideOrDisplayContents];
}
/*!
Sets the type of image alignment that should be used to
render the image.
@param anImageAlignment the type of scaling to use
*/
- (void)setImageAlignment:(CPImageAlignment)anImageAlignment
{
if (_imageAlignment == anImageAlignment)
return;
_imageAlignment = anImageAlignment;
if (![self image])
return;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
- (unsigned)imageAlignment
{
return _imageAlignment;
}
/*!
Sets the type of image scaling that should be used to
render the image.
@@ -217,6 +250,11 @@ var LEFT_SHADOW_INSET = 3.0,
[self setNeedsDisplay:YES];
}
- (unsigned)imageScaling
{
return [self currentValueForThemeAttribute:@"image-scaling"];
}
/*!
Toggles the display of the image view.
*/
@@ -319,8 +357,45 @@ var LEFT_SHADOW_INSET = 3.0,
#endif
}
var x = (boundsWidth - width) / 2.0,
y = (boundsHeight - height) / 2.0;
var x, y;
switch (_imageAlignment)
{
case CPImageAlignLeft:
case CPImageAlignTopLeft:
case CPImageAlignBottomLeft:
x = 0.0;
break;
case CPImageAlignRight:
case CPImageAlignTopRight:
case CPImageAlignBottomRight:
x = boundsWidth - width;
break;
default:
x = (boundsWidth - width) / 2.0;
break;
}
switch (_imageAlignment)
{
case CPImageAlignTop:
case CPImageAlignTopLeft:
case CPImageAlignTopRight:
y = 0.0;
break;
case CPImageAlignBottom:
case CPImageAlignBottomLeft:
case CPImageAlignBottomRight:
y = boundsHeight - height;
break;
default:
y = (boundsHeight - height) / 2.0;
break;
}
#if PLATFORM(DOM)
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, x, y);
@@ -339,11 +414,53 @@ var LEFT_SHADOW_INSET = 3.0,
[[self nextResponder] mouseDown:anEvent];
}
- (void)setEditable:(BOOL)shouldBeEditable
{
if (_isEditable === shouldBeEditable)
return;
_isEditable = shouldBeEditable;
if (_isEditable)
[self registerForDraggedTypes:[CPImagesPboardType]];
else
{
var draggedTypes = [self registeredDraggedTypes];
[self unregisterDraggedTypes];
[draggedTypes removeObjectIdenticalTo:CPImagesPboardType];
[self registerForDraggedTypes:draggedTypes];
}
}
- (BOOL)isEditable
{
return _isEditable;
}
- (BOOL)performDragOperation:(CPDraggingInfo)aSender
{
var images = [CPKeyedUnarchiver unarchiveObjectWithData:[[aSender draggingPasteboard] dataForType:CPImagesPboardType]];
if ([images count])
{
[self setImage:images[0]];
[self sendAction:[self action] to:[self target]];
}
return YES;
}
@end
var CPImageViewImageKey = @"CPImageViewImageKey",
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey";
var CPImageViewImageKey = @"CPImageViewImageKey",
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
CPImageViewImageAlignmentKey = @"CPImageViewImageAlignmentKey",
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
@implementation CPImageView (CPCoding)
@@ -360,6 +477,11 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
_DOMImageElement.style.left = "0px";
_DOMImageElement.style.top = "0px";
_DOMImageElement.style.visibility = "hidden";
if ([CPPlatform supportsDragAndDrop])
{
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
#endif
self = [super initWithCoder:aCoder];
@@ -371,7 +493,11 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
#endif
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
[self setImageAlignment:[aCoder decodeIntForKey:CPImageViewImageAlignmentKey]];
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey] || NO)
[self setEditable:YES];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -402,6 +528,10 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
_subviews = actualSubviews;
[aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
[aCoder encodeInt:_imageAlignment forKey:CPImageViewImageAlignmentKey];
if (_isEditable)
[aCoder encodeBool:_isEditable forKey:CPImageViewIsEditableKey];
}
@end
+263
View File
@@ -0,0 +1,263 @@
/*
* CPKeyBinding.j
* AppKit
*
* Created by Nicholas Small.
* Copyright 2010, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import "CPEvent.j"
CPStandardKeyBindings = {
@"@.": @"cancelOperation:",
@"^a": @"moveToBeginningOfParagraph:",
@"^$a": @"moveToBeginningOfParagraphAndModifySelection:",
@"^b": @"moveBackward:",
@"^$b": @"moveBackwardAndModifySelection:",
@"^~b": @"moveWordBackward:",
@"^~$b": @"moveWordBackwardAndModifySelection:",
@"^d": @"deleteForward:",
@"^e": @"moveToEndOfParagraph:",
@"^$e": @"moveToEndOfParagraphAndModifySelection:",
@"^f": @"moveForward:",
@"^$f": @"moveForwardAndModifySelection:",
@"^~f": @"moveWordForward:",
@"^~$f": @"moveWordForwardAndModifySelection:",
@"^h": @"deleteBackward:",
@"^k": @"deleteToEndOfParagraph:",
@"^l": @"centerSelectionInVisibleArea:",
@"^n": @"moveDown:",
@"^$n": @"moveDownAndModifySelection:",
@"^o": [@"insertNewlineIgnoringFieldEditor:", @"moveBackward:"],
@"^p": @"moveUp:",
@"^$p": @"moveUpAndModifySelection:",
@"^t": @"transpose:",
@"^v": @"pageDown:",
@"^$v": @"pageDownAndModifySelection:",
@"^y": @"yank:"
};
CPStandardKeyBindings[CPNewlineCharacter] = @"insertNewline:";
CPStandardKeyBindings[CPCarriageReturnCharacter] = @"insertNewline:";
CPStandardKeyBindings[CPEnterCharacter] = @"insertNewline:";
CPStandardKeyBindings[@"~" + CPNewlineCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"~" + CPCarriageReturnCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"~" + CPEnterCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"^" + CPNewlineCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[@"^" + CPCarriageReturnCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[@"^" + CPEnterCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[CPBackspaceCharacter] = @"deleteBackward:";
CPStandardKeyBindings[@"~" + CPBackspaceCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[CPDeleteCharacter] = @"deleteBackward:";
CPStandardKeyBindings[@"@" + CPDeleteCharacter] = @"deleteToBeginningOfLine:";
CPStandardKeyBindings[@"~" + CPDeleteCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[@"^" + CPDeleteCharacter] = @"deleteBackwardByDecomposingPreviousCharacter:";
CPStandardKeyBindings[@"^~" + CPDeleteCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[CPDeleteFunctionKey] = @"deleteForward:";
CPStandardKeyBindings[@"~" + CPDeleteFunctionKey] = @"deleteWordForward:";
CPStandardKeyBindings[CPTabCharacter] = @"insertTab:";
CPStandardKeyBindings[@"~" + CPTabCharacter] = @"insertTabIgnoringFieldEditor:";
CPStandardKeyBindings[@"^" + CPTabCharacter] = @"selectNextKeyView:";
CPStandardKeyBindings[CPBackTabCharacter] = @"insertBacktab:";
CPStandardKeyBindings[@"^" + CPBackTabCharacter] = @"selectPreviousKeyView:";
CPStandardKeyBindings[CPEscapeFunctionKey] = @"cancelOperation:";
CPStandardKeyBindings[@"~" + CPEscapeFunctionKey] = @"complete:";
CPStandardKeyBindings[CPF5FunctionKey] = @"complete:";
CPStandardKeyBindings[CPLeftArrowFunctionKey] = @"moveLeft:";
CPStandardKeyBindings[@"~" + CPLeftArrowFunctionKey] = @"moveWordLeft:";
CPStandardKeyBindings[@"^" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLine:";
CPStandardKeyBindings[@"@" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLine:";
CPStandardKeyBindings[@"$" + CPLeftArrowFunctionKey] = @"moveLeftAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPLeftArrowFunctionKey] = @"moveWordLeftAndModifySelection:";
CPStandardKeyBindings[@"$^" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPLeftArrowFunctionKey] = @"makeBaseWritingDirectionRightToLeft:";
CPStandardKeyBindings[@"@^~" + CPLeftArrowFunctionKey] = @"makeTextWritingDirectionRightToLeft:";
CPStandardKeyBindings[CPRightArrowFunctionKey] = @"moveRight:";
CPStandardKeyBindings[@"~" + CPRightArrowFunctionKey] = @"moveWordRight:";
CPStandardKeyBindings[@"^" + CPRightArrowFunctionKey] = @"moveToRightEndOfLine:";
CPStandardKeyBindings[@"@" + CPRightArrowFunctionKey] = @"moveToRightEndOfLine:";
CPStandardKeyBindings[@"$" + CPRightArrowFunctionKey] = @"moveRightAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPRightArrowFunctionKey] = @"moveWordRightAndModifySelection:";
CPStandardKeyBindings[@"$^" + CPRightArrowFunctionKey] = @"moveToRightEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPRightArrowFunctionKey] = @"moveToRightEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPRightArrowFunctionKey] = @"makeBaseWritingDirectionLeftToRight:";
CPStandardKeyBindings[@"@^~" + CPRightArrowFunctionKey] = @"makeTextWritingDirectionLeftToRight:";
CPStandardKeyBindings[CPUpArrowFunctionKey] = @"moveUp:";
CPStandardKeyBindings[@"~" + CPUpArrowFunctionKey] = [@"moveBackward:", @"moveToBeginningOfParagraph:"];
CPStandardKeyBindings[@"^" + CPUpArrowFunctionKey] = @"scrollPageUp:";
CPStandardKeyBindings[@"@" + CPUpArrowFunctionKey] = @"moveToBeginningOfDocument:";
CPStandardKeyBindings[@"$" + CPUpArrowFunctionKey] = @"moveUpAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPUpArrowFunctionKey] = @"moveParagraphBackwardAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPUpArrowFunctionKey] = @"moveToBeginningOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPDownArrowFunctionKey] = @"moveDown:";
CPStandardKeyBindings[@"~" + CPDownArrowFunctionKey] = [@"moveForward:", @"moveToEndOfParagraph:"];
CPStandardKeyBindings[@"^" + CPDownArrowFunctionKey] = @"scrollPageDown:";
CPStandardKeyBindings[@"@" + CPDownArrowFunctionKey] = @"moveToEndOfDocument:";
CPStandardKeyBindings[@"$" + CPDownArrowFunctionKey] = @"moveDownAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPDownArrowFunctionKey] = @"moveParagraphForwardAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPDownArrowFunctionKey] = @"moveToEndOfDocumentAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPDownArrowFunctionKey] = @"makeBaseWritingDirectionNatural:";
CPStandardKeyBindings[@"@^~" + CPDownArrowFunctionKey] = @"makeTextWritingDirectionNatural:";
CPStandardKeyBindings[CPHomeFunctionKey] = @"scrollToBeginningOfDocument:";
CPStandardKeyBindings[@"$" + CPHomeFunctionKey] = @"moveToBeginningOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPEndFunctionKey] = @"scrollToEndOfDocument:";
CPStandardKeyBindings[@"$" + CPEndFunctionKey] = @"moveToEndOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPPageUpFunctionKey] = @"scrollPageUp:";
CPStandardKeyBindings[@"~" + CPPageUpFunctionKey] = @"pageUp:";
CPStandardKeyBindings[@"$" + CPPageUpFunctionKey] = @"pageUpAndModifySelection:";
CPStandardKeyBindings[CPPageDownFunctionKey] = @"scrollPageDown:";
CPStandardKeyBindings[@"~" + CPPageDownFunctionKey] = @"pageDown:";
CPStandardKeyBindings[@"$" + CPPageDownFunctionKey] = @"pageDownAndModifySelection:";
var CPKeyBindingCache = {};
@implementation CPKeyBinding : CPObject
{
CPString _key;
unsigned _modifierFlags;
CPArray _selectors;
CPString _cacheName;
}
+ (void)initialize
{
if ([self class] !== CPKeyBinding)
return;
[self createKeyBindingsFromJSObject:CPStandardKeyBindings];
}
+ (void)createKeyBindingsFromJSObject:(JSObject)anObject
{
var binding;
for (binding in anObject)
[self cacheKeyBinding:[[CPKeyBinding alloc] initWithPhysicalKeyString:binding selectors:anObject[binding]]];
}
+ (void)cacheKeyBinding:(CPKeyBinding)aBinding
{
if (!aBinding)
return;
CPKeyBindingCache[[aBinding _cacheName]] = aBinding;
}
+ (CPKeyBinding)keyBindingForKey:(CPString)aKey modifierFlags:(unsigned)aFlag
{
var tempBinding = [[self alloc] initWithKey:aKey modifierFlags:aFlag selectors:nil];
return CPKeyBindingCache[[tempBinding _cacheName]];
}
+ (CPArray)selectorsForKey:(CPString)aKey modifierFlags:(unsigned)aFlag
{
return [[self keyBindingForKey:aKey modifierFlags:aFlag] selectors];
}
- (id)initWithPhysicalKeyString:(CPString)binding selectors:(CPArray)selectors
{
var components = binding.split(@""),
modifierFlags = ([components containsObject:@"$"] ? CPShiftKeyMask : 0) |
([components containsObject:@"^"] ? CPControlKeyMask : 0) |
([components containsObject:@"~"] ? CPAlternateKeyMask : 0) |
([components containsObject:@"@"] ? CPCommandKeyMask : 0);
if (![selectors isKindOfClass:CPArray])
selectors = [selectors];
return [self initWithKey:[components lastObject] modifierFlags:modifierFlags selectors:selectors];
}
- (id)initWithKey:(CPString)aKey modifierFlags:(unsigned)aFlag selectors:(CPArray)selectors
{
self = [super init];
if (self)
{
_key = aKey;
_modifierFlags = aFlag;
_selectors = selectors;
// We normalize our key binding string in order to properly cache it.
// We want to ensure the modifiers are always in the same order.
var cacheName = [];
if (_modifierFlags & CPCommandKeyMask)
cacheName.push(@"@");
if (_modifierFlags & CPControlKeyMask)
cacheName.push(@"^");
if (_modifierFlags & CPAlternateKeyMask)
cacheName.push(@"~");
if (_modifierFlags & CPShiftKeyMask)
cacheName.push(@"$");
cacheName.push(_key);
_cacheName = cacheName.join(@"");
}
return self;
}
- (CPString)key
{
return _key;
}
- (unsigned)modifierFlags
{
return _modifierFlags;
}
- (CPArray)selectors
{
return _selectors;
}
- (CPString)_cacheName
{
return _cacheName;
}
- (BOOL)isEqual:(CPKeyBinding)rhs
{
return _key === [rhs key] && _modifierFlags === [rhs modifierFlags];
}
- (CPString)description
{
return [CPString stringWithFormat:@"<KeyBinding string: '%@' modifierFlags: 0x%lx selectors: %@>", _key, _modifierFlags, _selectors];
}
@end
+472
View File
@@ -0,0 +1,472 @@
/*
* CPKeyValueBinding.j
* AppKit
*
* Created by Ross Boucher 1/13/09
* Copyright 280 North, Inc.
*
* Adapted from GNUStep
* Released under the LGPL.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPArray.j>
@import <Foundation/CPDictionary.j>
@import <Foundation/CPValueTransformer.j>
var exposedBindingsMap = [CPDictionary new],
bindingsMap = [CPDictionary new];
var CPBindingOperationAnd = 0,
CPBindingOperationOr = 1;
@implementation CPKeyValueBinding : CPObject
{
CPDictionary _info;
id _source;
}
+ (void)exposeBinding:(CPString)aBinding forClass:(Class)aClass
{
var bindings = [exposedBindingsMap objectForKey:[aClass hash]];
if (!bindings)
{
bindings = [];
[exposedBindingsMap setObject:bindings forKey:[aClass hash]];
}
bindings.push(aBinding);
}
+ (CPArray)exposedBindingsForClass:(Class)aClass
{
return [[exposedBindingsMap objectForKey:[aClass hash]] copy];
}
+ (CPKeyValueBinding)getBinding:(CPString)aBinding forObject:(id)anObject
{
return [[bindingsMap objectForKey:[anObject hash]] objectForKey:aBinding];
}
+ (CPDictionary)infoForBinding:(CPString)aBinding forObject:(id)anObject
{
var theBinding = [self getBinding:aBinding forObject:anObject];
if (theBinding)
return theBinding._info;
return nil;
}
+ (CPDictionary)allBindingsForObject:(id)anObject
{
return [bindingsMap objectForKey:[anObject hash]];
}
+ (void)unbind:(CPString)aBinding forObject:(id)anObject
{
var bindings = [bindingsMap objectForKey:[anObject hash]];
if (!bindings)
return;
var theBinding = [bindings objectForKey:aBinding];
if (!theBinding)
return;
var infoDictionary = theBinding._info,
observedObject = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey];
[observedObject removeObserver:theBinding forKeyPath:keyPath];
[bindings removeObjectForKey:aBinding];
}
+ (void)unbindAllForObject:(id)anObject
{
var bindings = [bindingsMap objectForKey:[anObject hash]];
if (!bindings)
return;
var allKeys = [bindings allKeys],
count = allKeys.length;
while (count--)
[anObject unbind:[bindings objectForKey:allKeys[count]]];
[bindingsMap removeObjectForKey:[anObject hash]];
}
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
{
self = [super init];
if (self)
{
_source = aSource;
_info = [CPDictionary dictionaryWithObjects:[aDestination, aKeyPath] forKeys:[CPObservedObjectKey, CPObservedKeyPathKey]];
if (options)
[_info setObject:options forKey:CPOptionsKey];
[aDestination addObserver:self forKeyPath:aKeyPath options:CPKeyValueObservingOptionNew context:aBinding];
var bindings = [bindingsMap objectForKey:[_source hash]];
if (!bindings)
{
bindings = [CPDictionary new];
[bindingsMap setObject:bindings forKey:[_source hash]];
}
[bindings setObject:self forKey:aName];
[self setValueFor:aBinding];
}
return self;
}
- (void)setValueFor:(CPString)aBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
if (isPlaceholder)
{
switch (newValue)
{
case CPMultipleValuesMarker:
newValue = [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || @"Multiple Values";
break;
case CPNoSelectionMarker:
newValue = [options objectForKey:CPNoSelectionPlaceholderBindingOption] || @"No Selection";
break;
case CPNotApplicableMarker:
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
[CPException raise:CPGenericException reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
newValue = [options objectForKey:CPNotApplicablePlaceholderBindingOption] || @"Not Applicable";
break;
}
}
else
{
// Only transform the value if the current value is not a placeholder
newValue = [self transformValue:newValue withOptions:options];
}
[_source setValue:newValue forKey:aBinding];
if ([_source respondsToSelector:@selector(_setCurrentValueIsPlaceholder:)])
[_source _setCurrentValueIsPlaceholder:isPlaceholder];
}
- (void)reverseSetValueFor:(CPString)aBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [_source valueForKeyPath:aBinding];
newValue = [self reverseTransformValue:newValue withOptions:options];
[destination setValue:newValue forKeyPath:keyPath];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
{
if (!changes)
return;
[self setValueFor:context];
}
- (id)transformValue:(id)aValue withOptions:(CPDictionary)options
{
var valueTransformerName,
valueTransformer,
placeholder;
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
if (valueTransformerName)
{
valueTransformer = [CPValueTransformer valueTransformerForName:valueTransformerName];
if (!valueTransformer)
{
var valueTransformerClass = CPClassFromString(valueTransformerName);
if (valueTransformerClass)
{
valueTransformer = [[valueTransformerClass alloc] init];
[valueTransformerClass setValueTransformer:valueTransformer forName:valueTransformerName];
}
}
}
else
valueTransformer = [options objectForKey:CPValueTransformerBindingOption];
if (valueTransformer)
aValue = [valueTransformer transformedValue:aValue];
if (aValue === undefined || aValue === nil)
aValue = [options objectForKey:CPNullPlaceholderBindingOption] || nil;
return aValue;
}
- (id)reverseTransformValue:(id)aValue withOptions: (CPDictionary)options
{
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
if (valueTransformerName)
valueTransformer = [CPValueTransformer valueTransformerForName:valueTransformerName];
else
valueTransformer = [options objectForKey:CPValueTransformerBindingOption];
if (valueTransformer && [[valueTransformer class] allowsReverseTransformation])
aValue = [valueTransformer reverseTransformedValue:aValue];
return aValue;
}
@end
@implementation CPObject (KeyValueBindingCreation)
+ (void)exposeBinding:(CPString)aBinding
{
[CPKeyValueBinding exposeBinding:aBinding forClass:[self class]];
}
- (CPArray)exposedBindings
{
var exposedBindings = [],
theClass = [self class];
while (theClass)
{
var temp = [CPKeyValueBinding exposedBindingsForClass:theClass];
if (temp)
[exposedBindings addObjectsFromArray:temp];
theClass = [theClass superclass];
}
return exposedBindings;
}
- (Class)valueClassForBinding:(CPString)binding
{
return [CPString class];
}
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
{
if (!anObject || !aKeyPath)
return CPLog.error("Invalid object or path on "+self+" for "+aBinding);
//if (![[self exposedBindings] containsObject:aBinding])
// CPLog.warn("No binding exposed on "+self+" for "+aBinding);
[self unbind:aBinding];
[[CPKeyValueBinding alloc] initWithBinding:[self _replacementKeyPathForBinding:aBinding] name:aBinding to:anObject keyPath:aKeyPath options:options from:self];
}
- (CPDictionary)infoForBinding:(CPString)aBinding
{
return [CPKeyValueBinding infoForBinding:aBinding forObject:self];
}
- (void)unbind:(CPString)aBinding
{
[CPKeyValueBinding unbind:aBinding forObject:self];
}
- (id)_replacementKeyPathForBinding:(CPString)binding
{
return binding;
}
@end
@implementation _CPKeyValueOrBinding : CPKeyValueBinding
{
}
- (void)setValueFor:(CPString)aBinding
{
var bindings = [bindingsMap valueForKey:[_source hash]];
if (!bindings)
return;
[_source setValue:resolveMultipleValues(aBinding, bindings, CPBindingOperationOr) forKey:aBinding];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
{
[self setValueFor:context];
}
@end
@implementation _CPKeyValueAndBinding : CPKeyValueBinding
{
}
- (void)setValueFor:(CPString)aBinding
{
var bindings = [bindingsMap objectForKey:[_source hash]];
if (!bindings)
return;
[_source setValue:resolveMultipleValues(aBinding, bindings, CPBindingOperationAnd) forKey:aBinding];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObejct change:(CPDictionary)changes context:(id)context
{
[self setValueFor:context];
}
@end
var resolveMultipleValues = function resolveMultipleValues(/*CPString*/key, /*CPDictionary*/bindings, /*GSBindingOperationKind*/operation)
{
var bindingName = key,
theBinding,
count = 1;
while (theBinding = [bindings objectForKey:bindingName])
{
var infoDictionary = theBinding._info,
object = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey],
options = [infoDictionary objectForKey:CPOptionsKey];
var value = [theBinding transformValue:[object valueForKeyPath:keyPath] withOptions:options];
if (value == operation)
return operation;
bindingName = [CPString stringWithFormat:@"%@%i", key, ++count];
}
return !operation;
}
var invokeAction = function invokeAction(/*CPString*/targetKey, /*CPString*/argumentKey, /*CPDictionary*/bindings)
{
var theBinding = [bindings objectForKey:targetKey],
infoDictionary = theBinding._info,
object = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey],
options = [infoDictionary objectForKey:CPOptionsKey],
target = [object valueForKeyPath:keyPath],
selector = [options objectForKey:CPSelectorNameBindingOption];
if (!target || !selector)
return;
var invocation = [CPInvocation invocationWithMethodSignature:[target methodSignatureForSelector:selector]];
[invocation setSelector:selector];
var bindingName = argumentKey,
count = 1;
while (theBinding = [bindings objectForKey:bindingName])
{
infoDictionary = theBinding._info;
keyPath = [infoDictionary objectForKey:CPObserverKeyPathKey];
object = [[infoDictionary objectForKey:CPObservedObjectKey] valueForKeyPath:keyPath];
if (object)
[invocation setArgument:object atIndex:++count];
bindingName = [CPString stringWithFormat:@"%@%i", argumentKey, count];
}
[invocation invoke];
}
// Keys in options dictionary
// Keys in dictionary returned by infoForBinding
CPObservedObjectKey = @"CPObservedObjectKey";
CPObservedKeyPathKey = @"CPObservedKeyPathKey";
CPOptionsKey = @"CPOptionsKey";
// special markers
CPMultipleValuesMarker = @"CPMultipleValuesMarker";
CPNoSelectionMarker = @"CPNoSelectionMarker";
CPNotApplicableMarker = @"CPNotApplicableMarker";
// Binding name constants
CPAlignmentBinding = @"CPAlignmentBinding";
CPEditableBinding = @"CPEditableBinding";
CPEnabledBinding = @"CPEnabledBinding";
CPFontBinding = @"CPFontBinding";
CPHiddenBinding = @"CPHiddenBinding";
CPSelectedIndexBinding = @"CPSelectedIndexBinding";
CPTextColorBinding = @"CPTextColorBinding";
CPToolTipBinding = @"CPToolTipBinding";
CPValueBinding = @"value";
//Binding options constants
CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelectionBindingOption";
CPAllowsNullArgumentBindingOption = @"CPAllowsNullArgumentBindingOption";
CPConditionallySetsEditableBindingOption = @"CPConditionallySetsEditableBindingOption";
CPConditionallySetsEnabledBindingOption = @"CPConditionallySetsEnabledBindingOption";
CPConditionallySetsHiddenBindingOption = @"CPConditionallySetsHiddenBindingOption";
CPContinuouslyUpdatesValueBindingOption = @"CPContinuouslyUpdatesValueBindingOption";
CPCreatesSortDescriptorBindingOption = @"CPCreatesSortDescriptorBindingOption";
CPDeletesObjectsOnRemoveBindingsOption = @"CPDeletesObjectsOnRemoveBindingsOption";
CPDisplayNameBindingOption = @"CPDisplayNameBindingOption";
CPDisplayPatternBindingOption = @"CPDisplayPatternBindingOption";
CPHandlesContentAsCompoundValueBindingOption = @"CPHandlesContentAsCompoundValueBindingOption";
CPInsertsNullPlaceholderBindingOption = @"CPInsertsNullPlaceholderBindingOption";
CPInvokesSeparatelyWithArrayObjectsBindingOption = @"CPInvokesSeparatelyWithArrayObjectsBindingOption";
CPMultipleValuesPlaceholderBindingOption = @"CPMultipleValuesPlaceholderBindingOption";
CPNoSelectionPlaceholderBindingOption = @"CPNoSelectionPlaceholderBindingOption";
CPNotApplicablePlaceholderBindingOption = @"CPNotApplicablePlaceholderBindingOption";
CPNullPlaceholderBindingOption = @"CPNullPlaceholderBindingOption";
CPPredicateFormatBindingOption = @"CPPredicateFormatBindingOption";
CPRaisesForNotApplicableKeysBindingOption = @"CPRaisesForNotApplicableKeysBindingOption";
CPSelectorNameBindingOption = @"CPSelectorNameBindingOption";
CPSelectsAllWhenSettingContentBindingOption = @"CPSelectsAllWhenSettingContentBindingOption";
CPValidatesImmediatelyBindingOption = @"CPValidatesImmediatelyBindingOption";
CPValueTransformerNameBindingOption = @"CPValueTransformerNameBindingOption";
CPValueTransformerBindingOption = @"CPValueTransformerBindingOption";
CPIsControllerMarker = function(/*id*/anObject)
{
return anObject === CPMultipleValuesMarker || anObject === CPNoSelectionMarker || anObject === CPNotApplicableMarker;
}
-1937
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+553
View File
@@ -0,0 +1,553 @@
@import "CPPanel.j"
@import "_CPMenuWindow.j"
var MENUBAR_HEIGHT = 28.0,
MENUBAR_MARGIN = 10.0,
MENUBAR_LEFT_MARGIN = 10.0,
MENUBAR_RIGHT_MARGIN = 10.0;
var _CPMenuBarWindowBackgroundColor = nil,
_CPMenuBarWindowFont = nil;
@implementation _CPMenuBarWindow : CPPanel
{
CPMenu _menu;
CPView _highlightView;
CPArray _menuItemViews;
CPMenuItem _trackingMenuItem;
CPImageView _iconImageView;
CPTextField _titleField;
CPColor _textColor;
CPColor _titleColor;
CPColor _textShadowColor;
CPColor _titleShadowColor;
CPColor _highlightColor;
CPColor _highlightTextColor;
CPColor _highlightTextShadowColor;
}
+ (void)initialize
{
if (self != [_CPMenuBarWindow class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPMenuBarWindowFont = [CPFont boldSystemFontOfSize:12.0];
}
+ (CPFont)font
{
return _CPMenuBarWindowFont;
}
- (id)init
{
// This only shows up in browser land, so don't bother calculating metrics in desktop.
var contentRect = [[CPPlatformWindow primaryPlatformWindow] contentBounds];
contentRect.size.height = MENUBAR_HEIGHT;
self = [super initWithContentRect:contentRect styleMask:CPBorderlessWindowMask];
if (self)
{
[self setLevel:CPMainMenuWindowLevel];
[self setAutoresizingMask:CPWindowWidthSizable];
var contentView = [self contentView];
[contentView setAutoresizesSubviews:NO];
[self setBecomesKeyOnlyIfNeeded:YES];
//
_iconImageView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 16.0, 16.0)];
[contentView addSubview:_iconImageView];
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_titleField setFont:[CPFont boldSystemFontOfSize:13.0]];
[_titleField setAlignment:CPCenterTextAlignment];
[_titleField setTextShadowOffset:CGSizeMake(0, 1)];
[contentView addSubview:_titleField];
}
return self;
}
- (void)setTitle:(CPString)aTitle
{
#if PLATFORM(DOM)
var bundleName = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPBundleName"];
if (![bundleName length])
document.title = aTitle;
else if ([aTitle length])
document.title = aTitle + @" - " + bundleName;
else
document.title = bundleName;
#endif
[_titleField setStringValue:aTitle];
[_titleField sizeToFit];
[self tile];
}
- (void)setIconImage:(CPImage)anImage
{
[_iconImageView setImage:anImage];
[_iconImageView setHidden:anImage == nil];
[self tile];
}
- (void)setIconImageAlphaValue:(float)anAlphaValue
{
[_iconImageView setAlphaValue:anAlphaValue];
}
- (void)setColor:(CPColor)aColor
{
if (!aColor)
{
if (!_CPMenuBarWindowBackgroundColor)
_CPMenuBarWindowBackgroundColor = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[_CPMenuBarWindow class]] pathForResource:@"_CPMenuBarWindow/_CPMenuBarWindowBackground.png"] size:CGSizeMake(1.0, 28.0)]];
[[self contentView] setBackgroundColor:_CPMenuBarWindowBackgroundColor];
}
else
[[self contentView] setBackgroundColor:aColor];
}
- (void)setTextColor:(CPColor)aColor
{
if (_textColor == aColor)
return;
_textColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setTextColor:) withObject:_textColor];
}
- (void)setTitleColor:(CPColor)aColor
{
if (_titleColor == aColor)
return;
_titleColor = aColor;
[_titleField setTextColor:aColor ? aColor : [CPColor blackColor]];
}
- (void)setTextShadowColor:(CPColor)aColor
{
if (_textShadowColor == aColor)
return;
_textShadowColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setTextShadowColor:) withObject:_textShadowColor];
}
- (void)setTitleShadowColor:(CPColor)aColor
{
if (_titleShadowColor == aColor)
return;
_titleShadowColor = aColor;
[_titleField setTextShadowColor:aColor ? aColor : [CPColor whiteColor]];
}
- (void)setHighlightColor:(CPColor)aColor
{
if (_highlightColor == aColor)
return;
_highlightColor = aColor;
}
- (void)setHighlightTextColor:(CPColor)aColor
{
if (_highlightTextColor == aColor)
return;
_highlightTextColor = aColor;
// [_menuItemViews makeObjectsPerformSelector:@selector(setActivateColor:) withObject:_highlightTextColor];
}
- (void)setHighlightTextShadowColor:(CPColor)aColor
{
if (_highlightTextShadowColor == aColor)
return;
_highlightTextShadowColor = aColor;
// [_menuItemViews makeObjectsPerformSelector:@selector(setActivateShadowColor:) withObject:_highlightTextShadowColor];
}
- (void)setMenu:(CPMenu)aMenu
{
if (_menu == aMenu)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_menu)
{
[defaultCenter
removeObserver:self
name:CPMenuDidAddItemNotification
object:_menu];
[defaultCenter
removeObserver:self
name:CPMenuDidChangeItemNotification
object:_menu];
[defaultCenter
removeObserver:self
name:CPMenuDidRemoveItemNotification
object:_menu];
var items = [_menu itemArray],
count = items.length;
while (count--)
[[items[count] _menuItemView] removeFromSuperview];
}
_menu = aMenu;
if (_menu)
{
[defaultCenter
addObserver:self
selector:@selector(menuDidAddItem:)
name:CPMenuDidAddItemNotification
object:_menu];
[defaultCenter
addObserver:self
selector:@selector(menuDidChangeItem:)
name:CPMenuDidChangeItemNotification
object:_menu];
[defaultCenter
addObserver:self
selector:@selector(menuDidRemoveItem:)
name:CPMenuDidRemoveItemNotification
object:_menu];
}
_menuItemViews = [];
var contentView = [self contentView],
items = [_menu itemArray],
count = items.length;
for (index = 0; index < count; ++index)
{
var item = items[index],
menuItemView = [item _menuItemView];
_menuItemViews.push(menuItemView);
[menuItemView setTextColor:_textColor];
[menuItemView setHidden:[item isHidden]];
[menuItemView synchronizeWithMenuItem];
[contentView addSubview:menuItemView];
}
[self tile];
}
- (void)menuDidChangeItem:(CPNotification)aNotification
{
var menuItem = [_menu itemAtIndex:[[aNotification userInfo] objectForKey:@"CPMenuItemIndex"]],
menuItemView = [menuItem _menuItemView];
[menuItemView setHidden:[menuItem isHidden]];
[menuItemView synchronizeWithMenuItem];
[self tile];
}
- (void)menuDidAddItem:(CPNotification)aNotification
{
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"],
menuItem = [_menu itemAtIndex:index],
menuItemView = [menuItem _menuItemView];
[_menuItemViews insertObject:menuItemView atIndex:index];
[menuItemView setTextColor:_textColor];
[menuItemView setHidden:[menuItem isHidden]];
[menuItemView synchronizeWithMenuItem];
[[self contentView] addSubview:menuItemView];
[self tile];
}
- (void)menuDidRemoveItem:(CPNotification)aNotification
{
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"],
menuItemView = [_menuItemViews objectAtIndex:index];
[_menuItemViews removeObjectAtIndex:index];
[menuItemView removeFromSuperview];
[self tile];
}
- (void)mouseDown:(CPEvent)anEvent
{
var constraintRect = CGRectInset([[self platformWindow] visibleFrame], 5.0, 0.0);
constraintRect.size.height -= 5.0;
[[_CPMenuManager sharedMenuManager]
beginTracking:anEvent
menuContainer:self
constraintRect:constraintRect
callback:function(aMenuContainer, aMenu)
{
[aMenu _performActionOfHighlightedItemChain];
[aMenu _highlightItemAtIndex:CPNotFound];
}];
}
- (CPFont)font
{
[CPFont systemFontOfSize:12.0];
}
- (void)tile
{
var items = [_menu itemArray],
index = 0,
count = items.length,
x = MENUBAR_LEFT_MARGIN,
y = 0.0,
isLeftAligned = YES;
for (; index < count; ++index)
{
var item = items[index];
if ([item isSeparatorItem])
{
x = CGRectGetWidth([self frame]) - MENUBAR_RIGHT_MARGIN;
isLeftAligned = NO;
continue;
}
if ([item isHidden])
continue;
var menuItemView = [item _menuItemView],
frame = [menuItemView frame];
if (isLeftAligned)
{
[menuItemView setFrame:CGRectMake(x, 0.0, CGRectGetWidth(frame), MENUBAR_HEIGHT)];
x += CGRectGetWidth([menuItemView frame]);
}
else
{
[menuItemView setFrame:CGRectMake(x - CGRectGetWidth(frame), 0.0, CGRectGetWidth(frame), MENUBAR_HEIGHT)];
x = CGRectGetMinX([menuItemView frame]);
}
}
var bounds = [[self contentView] bounds],
titleFrame = [_titleField frame];
if ([_iconImageView isHidden])
[_titleField setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(titleFrame)) / 2.0, (CGRectGetHeight(bounds) - CGRectGetHeight(titleFrame)) / 2.0)];
else
{
var iconFrame = [_iconImageView frame],
iconWidth = CGRectGetWidth(iconFrame),
totalWidth = iconWidth + CGRectGetWidth(titleFrame);
[_iconImageView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - totalWidth) / 2.0, (CGRectGetHeight(bounds) - CGRectGetHeight(iconFrame)) / 2.0)];
[_titleField setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - totalWidth) / 2.0 + iconWidth, (CGRectGetHeight(bounds) - CGRectGetHeight(titleFrame)) / 2.0)];
}
}
- (void)setFrame:(CGRect)aRect display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
{
var size = [self frame].size;
[super setFrame:aRect display:shouldDisplay animate:shouldAnimate];
if (!_CGSizeEqualToSize(size, aRect.size))
[self tile];
}
@end
@implementation _CPMenuBarWindow (CPMenuContainer)
- (BOOL)isMenuBar
{
return YES;
}
- (CGRect)globalFrame
{
return [self frame];
}
- (_CPManagerScrollingState)scrollingStateForPoint:(CGPoint)aGlobalLocation
{
return _CPMenuManagerScrollingStateNone;
}
- (CPInteger)itemIndexAtPoint:(CGPoint)aPoint
{
var items = [_menu itemArray],
index = items.length;
while (index--)
{
var item = items[index];
if ([item isHidden] || [item isSeparatorItem])
continue;
if (CGRectContainsPoint([self rectForItemAtIndex:index], aPoint))
return index;
}
return CPNotFound;
}
- (CGRect)rectForItemAtIndex:(CPInteger)anIndex
{
var menuItem = [_menu itemAtIndex:anIndex === CPNotFound ? 0 : anIndex];
return [[menuItem _menuItemView] frame];
}
@end
@implementation _CPMenuBarView : _CPMenuView
{
}
- (CGRect)rectForItemAtIndex:(int)anIndex
{
return [_menuItemViews[anIndex === CPNotFound ? 0 : anIndex] frame];
}
- (int)itemIndexAtPoint:(CGPoint)aPoint
{
var bounds = [self bounds];
if (!CGRectContainsPoint(bounds, aPoint))
return CPNotFound;
var x = aPoint.x,
low = 0,
high = _visibleMenuItemInfos.length - 1;
while (low <= high)
{
var middle = FLOOR(low + (high - low) / 2),
info = _visibleMenuItemInfos[middle],
frame = [info.view frame];
if (x < CGRectGetMinX(frame))
high = middle - 1;
else if (x > CGRectGetMaxX(frame))
low = middle + 1;
else
return info.index;
}
return CPNotFound;
}
- (void)tile
{
var items = [_menu itemArray],
index = 0,
count = items.length,
x = MENUBAR_LEFT_MARGIN,
y = 0.0,
isLeftAligned = YES;
for (; index < count; ++index)
{
var item = items[index];
if ([item isSeparatorItem])
{
x = CGRectGetWidth([self frame]) - MENUBAR_RIGHT_MARGIN;
isLeftAligned = NO;
continue;
}
if ([item isHidden])
continue;
var menuItemView = [item _menuItemView],
frame = [menuItemView frame];
if (isLeftAligned)
{
[menuItemView setFrameOrigin:CGPointMake(x, (MENUBAR_HEIGHT - 1.0 - CGRectGetHeight(frame)) / 2.0)];
x += CGRectGetWidth([menuItemView frame]) + MENUBAR_MARGIN;
}
else
{
[menuItemView setFrameOrigin:CGPointMake(x - CGRectGetWidth(frame), (MENUBAR_HEIGHT - 1.0 - CGRectGetHeight(frame)) / 2.0)];
x = CGRectGetMinX([menuItemView frame]) - MENUBAR_MARGIN;
}
}
var bounds = [[self contentView] bounds],
titleFrame = [_titleField frame];
if ([_iconImageView isHidden])
[_titleField setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(titleFrame)) / 2.0, (CGRectGetHeight(bounds) - CGRectGetHeight(titleFrame)) / 2.0)];
else
{
var iconFrame = [_iconImageView frame],
iconWidth = CGRectGetWidth(iconFrame),
totalWidth = iconWidth + CGRectGetWidth(titleFrame);
[_iconImageView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - totalWidth) / 2.0, (CGRectGetHeight(bounds) - CGRectGetHeight(iconFrame)) / 2.0)];
[_titleField setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - totalWidth) / 2.0 + iconWidth, (CGRectGetHeight(bounds) - CGRectGetHeight(titleFrame)) / 2.0)];
}
}
@end
+367
View File
@@ -0,0 +1,367 @@
@import <Foundation/CPObject.j>
_CPMenuManagerScrollingStateUp = -1,
_CPMenuManagerScrollingStateDown = 1,
_CPMenuManagerScrollingStateNone = 0;
var STICKY_TIME_INTERVAL = 500;
var SharedMenuManager = nil;
@implementation _CPMenuManager: CPObject
{
CPTimeInterval _startTime;
int _scrollingState;
CGPoint _lastGlobalLocation;
CPView _lastMouseOverMenuView;
CGRect _constraintRect;
CPMutableArray _menuContainerStack;
Function _trackingCallback;
}
+ (_CPMenuManager)sharedMenuManager
{
if (!SharedMenuManager)
SharedMenuManager = [[_CPMenuManager alloc] init];
return SharedMenuManager;
}
- (id)init
{
if (SharedMenuManager)
return SharedMenuManager;
return [super init];
}
- (id)trackingMenuContainer
{
return _menuContainerStack[0];
}
- (CPMenu)trackingMenu
{
return [[self trackingMenuContainer] menu];
}
- (void)beginTracking:(CPEvent)anEvent
menuContainer:(id)aMenuContainer
constraintRect:(CGRect)aRect
callback:(Function)aCallback
{
var menu = [aMenuContainer menu];
CPApp._activeMenu = menu;
_startTime = [anEvent timestamp];//new Date();
_scrollingState = _CPMenuManagerScrollingStateNone;
_constraintRect = aRect;
_menuContainerStack = [aMenuContainer];
_trackingCallback = aCallback;
if (menu === [CPApp mainMenu])
{
var globalLocation = [anEvent globalLocation];
// Find which menu window the mouse is currently on top of
var menuLocation = [aMenuContainer convertGlobalToBase:globalLocation];
// Find out the item the mouse is currently on top of
var activeItemIndex = [aMenuContainer itemIndexAtPoint:menuLocation],
activeItem = activeItemIndex !== CPNotFound ? [menu itemAtIndex:activeItemIndex] : nil;
_menuBarButtonItemIndex = activeItemIndex;
_menuBarButtonMenuContainer = aMenuContainer;
if ([activeItem _isMenuBarButton])
return [self trackMenuBarButtonEvent:anEvent];
}
[self trackEvent:anEvent];
}
- (void)trackEvent:(CPEvent)anEvent
{
var type = [anEvent type],
trackingMenu = [self trackingMenu];
// Close Menu Event.
if (type === CPAppKitDefined)
return [self completeTracking];
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPAppKitDefinedMask untilDate:nil inMode:nil dequeue:YES];
// Periodic events don't have a valid location.
var globalLocation = type === CPPeriodic ? _lastGlobalLocation : [anEvent globalLocation];
// Remember this for the next periodic event.
_lastGlobalLocation = globalLocation;
// Find which menu window the mouse is currently on top of
var activeMenuContainer = [self menuContainerForPoint:globalLocation],
activeMenu = [activeMenuContainer menu],
menuLocation = [activeMenuContainer convertGlobalToBase:globalLocation];
// Find out the item the mouse is currently on top of
var activeItemIndex = activeMenuContainer ? [activeMenuContainer itemIndexAtPoint:menuLocation] : CPNotFound,
activeItem = activeItemIndex !== CPNotFound ? [activeMenu itemAtIndex:activeItemIndex] : nil;
// If the item isn't enabled its as if we clicked on nothing.
if (![activeItem isEnabled] || [activeItem _isMenuBarButton])
{
activeItemIndex = CPNotFound;
activeItem = nil;
}
var mouseOverMenuView = [activeItem view];
if (type === CPPeriodic)
{
if (_scrollingState === _CPMenuManagerScrollingStateUp)
[activeMenuContainer scrollUp];
else if (_scrollingState === _CPMenuManagerScrollingStateDown)
[activeMenuContainer scrollDown];
}
// If we're over a custom menu view...
if (mouseOverMenuView)
{
if (!_lastMouseOverMenuView)
[activeMenu _highlightItemAtIndex:CPNotFound];
if (_lastMouseOverMenuView != mouseOverMenuView)
{
[mouseOverMenuView mouseExited:anEvent];
// FIXME: Possibly multiple of these?
[_lastMouseOverMenuView mouseEntered:anEvent];
_lastMouseOverMenuView = mouseOverMenuView;
}
var menuContainerWindow = activeMenuContainer;
if (![menuContainerWindow isKindOfClass:[CPWindow class]])
menuContainerWindow = [menuContainerWindow window];
[menuContainerWindow
sendEvent:[CPEvent mouseEventWithType:type location:menuLocation modifierFlags:[anEvent modifierFlags]
timestamp:[anEvent timestamp]
windowNumber:menuContainerWindow
context:nil
eventNumber:0
clickCount:[anEvent clickCount]
pressure:[anEvent pressure]]];
}
else
{
if (_lastMouseOverMenuView)
{
[_lastMouseOverMenuView mouseExited:anEvent];
_lastMouseOverMenuView = nil;
}
[activeMenu _highlightItemAtIndex:activeItemIndex];
if (type === CPMouseMoved || type === CPLeftMouseDragged || type === CPLeftMouseDown)
{
var oldScrollingState = _scrollingState;
_scrollingState = [activeMenuContainer scrollingStateForPoint:globalLocation];
if (_scrollingState !== oldScrollingState)
{
if (_scrollingState === _CPMenuManagerScrollingStateNone)
[CPEvent stopPeriodicEvents];
else if (oldScrollingState === _CPMenuManagerScrollingStateNone)
[CPEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.04];
}
}
else if (type === CPLeftMouseUp && ([anEvent timestamp] - _startTime > STICKY_TIME_INTERVAL))
[trackingMenu cancelTracking];
}
// If the item has a submenu, show it.
if ([activeItem hasSubmenu])// && [activeItem action] === @selector(submenuAction:))
{
var activeItemRect = [activeMenuContainer rectForItemAtIndex:activeItemIndex];
if ([activeMenuContainer isMenuBar])
var newMenuOrigin = CGPointMake(CGRectGetMinX(activeItemRect), CGRectGetMaxY(activeItemRect));
else
var newMenuOrigin = CGPointMake(CGRectGetMaxX(activeItemRect), CGRectGetMinY(activeItemRect));
newMenuOrigin = [activeMenuContainer convertBaseToGlobal:newMenuOrigin];
[self showMenu:[activeItem submenu] fromMenu:[activeItem menu] atPoint:newMenuOrigin];
}
// This handles both the case where we've moved away from the menu, and where
// we've moved to an item without a submenu.
else
[self showMenu:nil fromMenu:activeMenu atPoint:CGPointMakeZero()];
}
- (void)trackMenuBarButtonEvent:(CPEvent)anEvent
{
var type = [anEvent type];
if (type === CPAppKitDefined)
return [self completeTracking];
var globalLocation = [anEvent globalLocation];
// Find which menu window the mouse is currently on top of
var menu = [self trackingMenu],
trackingMenuContainer = [self trackingMenuContainer],
menuLocation = [trackingMenuContainer convertGlobalToBase:globalLocation];
if ([trackingMenuContainer itemIndexAtPoint:menuLocation] === _menuBarButtonItemIndex)
[menu _highlightItemAtIndex:_menuBarButtonItemIndex];
else
[menu _highlightItemAtIndex:CPNotFound];
[CPApp setTarget:self selector:@selector(trackMenuBarButtonEvent:) forNextEventMatchingMask:CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPAppKitDefinedMask untilDate:nil inMode:nil dequeue:YES];
if (type === CPLeftMouseUp)
[menu cancelTracking];
}
- (void)completeTracking
{
var trackingMenu = [self trackingMenu];
// Stop all periodic events at this point.
[CPEvent stopPeriodicEvents];
// Get the highlighted item from the original menu.
var highlightedItem = [trackingMenu highlightedItem];
// Hide all submenus.
[self showMenu:nil fromMenu:trackingMenu atPoint:nil];
var delegate = [trackingMenu delegate];
if ([delegate respondsToSelector:@selector(menuDidClose:)])
[delegate menuDidClose:trackingMenu];
if (_trackingCallback)
_trackingCallback([self trackingMenuContainer], trackingMenu);
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidEndTrackingNotification
object:trackingMenu];
CPApp._activeMenu = nil;
}
- (id)menuContainerForPoint:(float)aGlobalLocation
{
var count = [_menuContainerStack count],
firstMenuContainer = _menuContainerStack[0];
// Trivial case.
if (count === 1)
return firstMenuContainer;
var firstMenuWindowIndex = 0,
lastMenuWindowIndex = count - 1;
// If the first menu container is a bar, then it has to fall strictly within its bounds.
if ([firstMenuContainer isMenuBar])
{
if (CGRectContainsPoint([firstMenuContainer globalFrame], aGlobalLocation))
return firstMenuContainer;
firstMenuWindowIndex = 1;
}
var index = count,
x = aGlobalLocation.x,
closerDeltaX = Infinity,
closerMenuContainer = nil;
while (index-- > firstMenuWindowIndex)
{
var menuContainer = _menuContainerStack[index],
menuContainerFrame = [menuContainer globalFrame],
menuContainerMinX = _CGRectGetMinX(menuContainerFrame),
menuContainerMaxX = _CGRectGetMaxX(menuContainerFrame);
// If within the x bounds of this menu container, return it.
if (x < menuContainerMaxX && x >= menuContainerMinX)
return menuContainer;
// If this is either the first or last menu *window*, check to see how close we are to it.
if (index === firstMenuWindowIndex || index === lastMenuWindowIndex)
{
var deltaX = ABS(x < menuContainerMinX ? menuContainerMinX - x : menuContainerMaxX - x);
if (deltaX < closerDeltaX)
{
closerMenuContainer = menuContainer;
closerDeltaX = deltaX;
}
}
}
return closerMenuContainer;
}
- (void)showMenu:(CPMenu)newMenu fromMenu:(CPMenu)baseMenu atPoint:(CGPoint)aGlobalLocation
{
var count = _menuContainerStack.length,
index = count;
// Hide all menus up to the base menu...
while (index--)
{
var menuContainer = _menuContainerStack[index],
menu = [menuContainer menu];
// If we reach the base menu, or this menu is already being shown, break.
if (menu === baseMenu)
break;
// If this menu is already being shown, unhighlight and return.
if (menu === newMenu)//&& [menu supermenu] === baseMenu)
return [newMenu _highlightItemAtIndex:CPNotFound];
[menuContainer orderOut:self];
[menuContainer setMenu:nil];
[_CPMenuWindow poolMenuWindow:menuContainer];
[_menuContainerStack removeObjectAtIndex:index];
}
if (!newMenu)
return;
// Unhighlight any previously highlighted item.
[newMenu _highlightItemAtIndex:CPNotFound];
var menuWindow = [_CPMenuWindow menuWindowWithMenu:newMenu font:[_menuContainerStack[0] font]];
[_menuContainerStack addObject:menuWindow];
[menuWindow setConstraintRect:_constraintRect];
// If our parent menu is a menu bar...
if (baseMenu === [self trackingMenu] && [[self trackingMenuContainer] isMenuBar])
[menuWindow setBackgroundStyle:_CPMenuWindowMenuBarBackgroundStyle];
else
[menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle];
[menuWindow setFrameOrigin:aGlobalLocation];
[menuWindow orderFront:self];
}
@end
+547
View File
@@ -0,0 +1,547 @@
@import "CPWindow.j"
var _CPMenuWindowPool = [],
_CPMenuWindowPoolCapacity = 5,
_CPMenuWindowBackgroundColors = [];
_CPMenuWindowMenuBarBackgroundStyle = 0;
_CPMenuWindowPopUpBackgroundStyle = 1;
_CPMenuWindowAttachedMenuBackgroundStyle = 2;
var STICKY_TIME_INTERVAL = 500,
TOP_MARGIN = 5.0,
LEFT_MARGIN = 1.0,
RIGHT_MARGIN = 1.0,
BOTTOM_MARGIN = 5.0,
SCROLL_INDICATOR_HEIGHT = 16.0;
/*
@ignore
*/
@implementation _CPMenuWindow : CPWindow
{
_CPMenuView _menuView;
CPClipView _menuClipView;
CPImageView _moreAboveView;
CPImageView _moreBelowView;
CGRect _unconstrainedFrame;
CGRect _constraintRect;
}
+ (id)menuWindowWithMenu:(CPMenu)aMenu font:(CPFont)aFont
{
var menuWindow = nil;
if (_CPMenuWindowPool.length)
{
menuWindow = _CPMenuWindowPool.pop();
// Do this so that coordinates will be accurate.
[menuWindow setFrameOrigin:CGPointMakeZero()];
}
else
menuWindow = [[_CPMenuWindow alloc] init];
[menuWindow setFont:aFont];
[menuWindow setMenu:aMenu];
[menuWindow setMinWidth:[aMenu minimumWidth]];
return menuWindow;
}
+ (void)poolMenuWindow:(_CPMenuWindow)aMenuWindow
{
if (!aMenuWindow || _CPMenuWindowPool.length >= _CPMenuWindowPoolCapacity)
return;
_CPMenuWindowPool.push(aMenuWindow);
}
+ (void)initialize
{
if (self != [_CPMenuWindow class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPMenuWindowMoreAboveImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowMoreAbove.png"] size:CGSizeMake(38.0, 18.0)];
_CPMenuWindowMoreBelowImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowMoreBelow.png"] size:CGSizeMake(38.0, 18.0)];
}
- (id)initWithContentRect:(CGRect)aRect styleMask:(unsigned)aStyleMask
{
_constraintRect = _CGRectMakeZero();
_unconstrainedFrame = _CGRectMakeZero();
self = [super initWithContentRect:aRect styleMask:CPBorderlessWindowMask];
if (self)
{
[self setLevel:CPPopUpMenuWindowLevel];
[self setHasShadow:YES];
[self setShadowStyle:CPMenuWindowShadowStyle];
[self setAcceptsMouseMovedEvents:YES];
var contentView = [self contentView];
_menuView = [[_CPMenuView alloc] initWithFrame:CGRectMakeZero()];
_menuClipView = [[CPClipView alloc] initWithFrame:CGRectMake(LEFT_MARGIN, TOP_MARGIN, 0.0, 0.0)];
[_menuClipView setDocumentView:_menuView];
[contentView addSubview:_menuClipView];
_moreAboveView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
[_moreAboveView setImage:_CPMenuWindowMoreAboveImage];
[_moreAboveView setFrameSize:[_CPMenuWindowMoreAboveImage size]];
[contentView addSubview:_moreAboveView];
_moreBelowView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
[_moreBelowView setImage:_CPMenuWindowMoreBelowImage];
[_moreBelowView setFrameSize:[_CPMenuWindowMoreBelowImage size]];
[contentView addSubview:_moreBelowView];
[self setShadowStyle:CPWindowShadowStyleMenu];
}
return self;
}
+ (float)_standardLeftMargin
{
return LEFT_MARGIN;
}
- (void)setFont:(CPFont)aFont
{
[_menuView setFont:aFont];
}
- (CPFont)font
{
return [_menuView font];
}
+ (CPColor)backgroundColorForBackgroundStyle:(_CPMenuWindowBackgroundStyle)aBackgroundStyle
{
var color = _CPMenuWindowBackgroundColors[aBackgroundStyle];
if (!color)
{
var bundle = [CPBundle bundleForClass:[self class]];
if (aBackgroundStyle == _CPMenuWindowPopUpBackgroundStyle)
color = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded0.png"] size:CGSizeMake(4.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow1.png"] size:CGSizeMake(1.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded2.png"] size:CGSizeMake(4.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow3.png"] size:CGSizeMake(4.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow4.png"] size:CGSizeMake(1.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow5.png"] size:CGSizeMake(4.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded6.png"] size:CGSizeMake(4.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow7.png"] size:CGSizeMake(1.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded8.png"] size:CGSizeMake(4.0, 4.0)]
]]];
else if (aBackgroundStyle == _CPMenuWindowMenuBarBackgroundStyle)
color = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow3.png"] size:CGSizeMake(4.0, 0.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow4.png"] size:CGSizeMake(1.0, 0.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow5.png"] size:CGSizeMake(4.0, 0.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow3.png"] size:CGSizeMake(4.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow4.png"] size:CGSizeMake(1.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow5.png"] size:CGSizeMake(4.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded6.png"] size:CGSizeMake(4.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow7.png"] size:CGSizeMake(1.0, 4.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded8.png"] size:CGSizeMake(4.0, 4.0)]
]]];
_CPMenuWindowBackgroundColors[aBackgroundStyle] = color;
}
return color;
}
- (void)setBackgroundStyle:(_CPMenuWindowBackgroundStyle)aBackgroundStyle
{
[self setBackgroundColor:[[self class] backgroundColorForBackgroundStyle:aBackgroundStyle]];
}
- (void)setMenu:(CPMenu)aMenu
{
[aMenu _setMenuWindow:self];
[_menuView setMenu:aMenu];
var menuViewSize = [_menuView frame].size;
[self setFrameSize:CGSizeMake(LEFT_MARGIN + menuViewSize.width + RIGHT_MARGIN, TOP_MARGIN + menuViewSize.height + BOTTOM_MARGIN)];
[_menuView scrollPoint:CGPointMake(0.0, 0.0)];
[_menuClipView setFrame:CGRectMake(LEFT_MARGIN, TOP_MARGIN, menuViewSize.width, menuViewSize.height)];
}
- (void)setMinWidth:(float)aWidth
{
var size = [self unconstrainedFrame].size;
[self setFrameSize:CGSizeMake(MAX(size.width, aWidth), size.height)];
}
- (CPMenu)menu
{
return [_menuView menu];
}
- (void)orderFront:(id)aSender
{
[self setFrame:_unconstrainedFrame];
[super orderFront:aSender];
}
- (void)setConstraintRect:(CGRect)aRect
{
_constraintRect = aRect;
[self setFrame:_unconstrainedFrame];
}
- (CGRect)unconstrainedFrame
{
return _CGRectMakeCopy(_unconstrainedFrame);
}
// We need this because if not this will call setFrame: with -frame instead of -unconstrainedFrame, turning
// the constrained frame into the unconstrained frame.
- (void)setFrameOrigin:(CGPoint)aPoint
{
[super setFrame:_CGRectMake(aPoint.x, aPoint.y, _CGRectGetWidth(_unconstrainedFrame), _CGRectGetHeight(_unconstrainedFrame))];
}
- (void)setFrameSize:(CGSize)aSize
{
[super setFrame:_CGRectMake(_CGRectGetMinX(_unconstrainedFrame), _CGRectGetMinY(_unconstrainedFrame), aSize.width, aSize.height)];
}
- (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
{
// FIXME: There are integral window issues with platform windows.
// FIXME: This gets called far too often.
_unconstrainedFrame = _CGRectMakeCopy(aFrame);
var constrainedFrame = CGRectIntersection(_unconstrainedFrame, _constraintRect);
// We don't want to simply intersect the visible frame and the unconstrained frame.
// We should be allowing as much of the width to fit as possible (pushing back and forward).
constrainedFrame.origin.x = CGRectGetMinX(_unconstrainedFrame);
constrainedFrame.size.width = CGRectGetWidth(_unconstrainedFrame);
if (CGRectGetWidth(constrainedFrame) > CGRectGetWidth(_constraintRect))
constrainedFrame.size.width = CGRectGetWidth(_constraintRect);
if (CGRectGetMaxX(constrainedFrame) > CGRectGetMaxX(_constraintRect))
constrainedFrame.origin.x -= CGRectGetMaxX(constrainedFrame) - CGRectGetMaxX(_constraintRect);
if (CGRectGetMinX(constrainedFrame) < CGRectGetMinX(_constraintRect))
constrainedFrame.origin.x = CGRectGetMinX(_constraintRect);
[super setFrame:constrainedFrame display:shouldDisplay animate:shouldAnimate];
// This needs to happen before changing the frame.
var menuViewOrigin = CGPointMake(CGRectGetMinX(aFrame) + LEFT_MARGIN, CGRectGetMinY(aFrame) + TOP_MARGIN),
moreAbove = menuViewOrigin.y < CGRectGetMinY(constrainedFrame) + TOP_MARGIN,
moreBelow = menuViewOrigin.y + CGRectGetHeight([_menuView frame]) > CGRectGetMaxY(constrainedFrame) - BOTTOM_MARGIN,
topMargin = TOP_MARGIN,
bottomMargin = BOTTOM_MARGIN,
contentView = [self contentView],
bounds = [contentView bounds];
if (moreAbove)
{
topMargin += SCROLL_INDICATOR_HEIGHT;
var frame = [_moreAboveView frame];
[_moreAboveView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(frame)) / 2.0, (TOP_MARGIN + SCROLL_INDICATOR_HEIGHT - CGRectGetHeight(frame)) / 2.0)];
}
[_moreAboveView setHidden:!moreAbove];
if (moreBelow)
{
bottomMargin += SCROLL_INDICATOR_HEIGHT;
[_moreBelowView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth([_moreBelowView frame])) / 2.0, CGRectGetHeight(bounds) - SCROLL_INDICATOR_HEIGHT - BOTTOM_MARGIN)];
}
[_moreBelowView setHidden:!moreBelow];
var clipFrame = CGRectMake(LEFT_MARGIN, topMargin, CGRectGetWidth(constrainedFrame) - LEFT_MARGIN - RIGHT_MARGIN, CGRectGetHeight(constrainedFrame) - topMargin - bottomMargin)
[_menuClipView setFrame:clipFrame];
[_menuView setFrameSize:CGSizeMake(CGRectGetWidth(clipFrame), CGRectGetHeight([_menuView frame]))];
[_menuView scrollPoint:CGPointMake(0.0, [self convertBaseToGlobal:clipFrame.origin].y - menuViewOrigin.y)];
}
- (BOOL)hasMinimumNumberOfVisibleItems
{
var visibleRect = [_menuView visibleRect];
// Clearly if the entire view isn't visible the minimum won't be visible.
if (CGRectIsEmpty(visibleRect))
return NO;
var numberOfUnhiddenItems = [_menuView numberOfUnhiddenItems],
minimumNumberOfVisibleItems = MIN(numberOfUnhiddenItems, 3),
count = 0,
index = [_menuView itemIndexAtPoint:[_menuView convertPoint:[_menuClipView frame].origin fromView:nil]];
for (; index < numberOfUnhiddenItems && count < minimumNumberOfVisibleItems; ++index)
{
var itemRect = [_menuView rectForUnhiddenItemAtIndex:index],
visibleItemRect = CGRectIntersection(visibleRect, itemRect);
// As soon as we get to the first unhidden item that is no longer visible, stop.
if (CGRectIsEmpty(visibleItemRect))
break;
// If the item is *completely* visible, count it.
if (CGRectEqualToRect(visibleItemRect, itemRect))
++count;
}
return count >= minimumNumberOfVisibleItems;
}
- (BOOL)canScrollUp
{
return ![_moreAboveView isHidden];
}
- (BOOL)canScrollDown
{
return ![_moreBelowView isHidden];
}
- (BOOL)canScroll
{
return [self canScrollUp] || [self canScrollDown];
}
- (void)scrollUp
{
if (CGRectGetMinY(_unconstrainedFrame) >= CGRectGetMinY(_constraintRect))
return;
_unconstrainedFrame.origin.y += 10;
[self setFrame:_unconstrainedFrame];
}
- (void)scrollDown
{
if (CGRectGetMaxY(_unconstrainedFrame) <= CGRectGetHeight(_constraintRect))
return;
_unconstrainedFrame.origin.y -= 10;
[self setFrame:_unconstrainedFrame];
}
@end
@implementation _CPMenuWindow (CPMenuContainer)
- (CGRect)globalFrame
{
return [self frame];
}
- (BOOL)isMenuBar
{
return NO;
}
- (_CPManagerScrollingState)scrollingStateForPoint:(CGPoint)aGlobalLocation
{
var frame = [self frame];
if (![self canScroll])
return _CPMenuManagerScrollingStateNone;
// If we're at or above of the top scroll indicator...
if (aGlobalLocation.y < CGRectGetMinY(frame) + TOP_MARGIN + SCROLL_INDICATOR_HEIGHT)
return _CPMenuManagerScrollingStateUp;
// If we're at or below the bottom scroll indicator...
if (aGlobalLocation.y > CGRectGetMaxY(frame) - BOTTOM_MARGIN - SCROLL_INDICATOR_HEIGHT)
return _CPMenuManagerScrollingStateDown;
return _CPMenuManagerScrollingStateNone;
}
- (float)deltaYForItemAtIndex:(int)anIndex
{
return TOP_MARGIN + CGRectGetMinY([_menuView rectForItemAtIndex:anIndex]);
}
- (CGPoint)rectForItemAtIndex:(int)anIndex
{
return [_menuView convertRect:[_menuView rectForItemAtIndex:anIndex] toView:nil];
}
- (int)itemIndexAtPoint:(CGPoint)aPoint
{
// Don't return indexes of items that aren't visible.
if (!CGRectContainsPoint([_menuClipView bounds], [_menuClipView convertPoint:aPoint fromView:nil]))
return NO;
return [_menuView itemIndexAtPoint:[_menuView convertPoint:aPoint fromView:nil]];
}
@end
/*
@ignore
*/
@implementation _CPMenuView : CPView
{
CPArray _menuItemViews;
CPArray _visibleMenuItemInfos;
CPFont _font @accessors(property=font);
}
- (unsigned)numberOfUnhiddenItems
{
return _visibleMenuItemInfos.length;
}
- (CGRect)rectForUnhiddenItemAtIndex:(int)anIndex
{
return [self rectForItemAtIndex:_visibleMenuItemInfos[anIndex].index];
}
- (CGRect)rectForItemAtIndex:(int)anIndex
{
return [_menuItemViews[anIndex === CPNotFound ? 0 : anIndex] frame];
}
- (int)itemIndexAtPoint:(CGPoint)aPoint
{
var x = aPoint.x,
bounds = [self bounds];
if (x < CGRectGetMinX(bounds) || x > CGRectGetMaxX(bounds))
return CPNotFound;
var y = aPoint.y,
low = 0,
high = _visibleMenuItemInfos.length - 1;
while (low <= high)
{
var middle = FLOOR(low + (high - low) / 2),
info = _visibleMenuItemInfos[middle]
frame = [info.view frame];
if (y < CGRectGetMinY(frame))
high = middle - 1;
else if (y > CGRectGetMaxY(frame))
low = middle + 1;
else
return info.index;
}
return CPNotFound;
}
- (void)tile
{
[_menuItemViews makeObjectsPerformSelector:@selector(removeFromSuperview)];
_menuItemViews = [];
_visibleMenuItemInfos = [];
var menu = [self menu];
if (!menu)
return;
var items = [menu itemArray],
index = 0,
count = [items count],
maxWidth = 0,
y = 0,
showsStateColumn = [menu showsStateColumn];
for (; index < count; ++index)
{
var item = items[index],
view = [item _menuItemView];
_menuItemViews.push(view);
if ([item isHidden])
continue;
_visibleMenuItemInfos.push({ view:view, index:index });
[view setFont:_font];
[view setShowsStateColumn:showsStateColumn];
[view synchronizeWithMenuItem];
[view setFrameOrigin:CGPointMake(0.0, y)];
[self addSubview:view];
var size = [view minSize],
width = size.width;
if (maxWidth < width)
maxWidth = width;
y += size.height;
}
for (index = 0; index < count; ++index)
{
var view = _menuItemViews[index];
[view setFrameSize:CGSizeMake(maxWidth, CGRectGetHeight([view frame]))];
}
[self setAutoresizesSubviews:NO];
[self setFrameSize:CGSizeMake(maxWidth, y)];
[self setAutoresizesSubviews:YES];
}
- (void)setMenu:(CPMenu)aMenu
{
[super setMenu:aMenu];
[self tile];
}
@end
File diff suppressed because it is too large Load Diff
+239
View File
@@ -0,0 +1,239 @@
@import "CPView.j"
var HORIZONTAL_MARGIN = 8.0,
SUBMENU_INDICATOR_MARGIN = 3.0,
VERTICAL_MARGIN = 4.0;
var SelectionColor = nil,
SUBMENU_INDICATOR_COLOR = nil,
_CPMenuItemSelectionColor = nil,
_CPMenuItemTextShadowColor = nil,
_CPMenuItemDefaultStateImages = [],
_CPMenuItemDefaultStateHighlightedImages = [];
@implementation _CPMenuItemMenuBarView : CPView
{
CPMenuItem _menuItem @accessors(property=menuItem);
CPFont _font;
CPColor _textColor;
CPColor _textShadowColor;
BOOL _isDirty;
_CPImageAndTextView _imageAndTextView;
CPView _submenuIndicatorView;
}
+ (void)initialize
{
if (self !== [_CPMenuItemMenuBarView class])
return;
var bundle = [CPBundle bundleForClass:self];
SelectionColor = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuBarWindow/_CPMenuBarWindowBackgroundSelected.png"] size:CGSizeMake(1.0, 28.0)]];
SUBMENU_INDICATOR_COLOR = [CPColor grayColor];
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
_CPMenuItemDefaultStateImages[CPOffState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil;
_CPMenuItemDefaultStateImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnState.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateHighlightedImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnStateHighlighted.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateImages[CPMixedState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPMixedState] = nil;
}
+ (id)view
{
return [[self alloc] init];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_imageAndTextView = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(HORIZONTAL_MARGIN, 0.0, 0.0, 0.0)];
[_imageAndTextView setImagePosition:CPImageLeft];
[_imageAndTextView setImageOffset:3.0];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_imageAndTextView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin];
[self addSubview:_imageAndTextView];
_submenuIndicatorView = [[_CPMenuItemMenuBarSubmenuIndicatorView alloc] initWithFrame:CGRectMake(0.0, 0.0, 9.0, 6.0)];
[_submenuIndicatorView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin];
[self addSubview:_submenuIndicatorView];
[self setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
}
return self;
}
- (CPColor)textColor
{
if (![_menuItem isEnabled])
return [CPColor lightGrayColor];
return _textColor || [CPColor colorWithCalibratedRed:70.0 / 255.0 green:69.0 / 255.0 blue:69.0 / 255.0 alpha:1.0];
}
- (CPColor)textShadowColor
{
if (![_menuItem isEnabled])
return [CPColor colorWithWhite:0.8 alpha:0.8];
return _textShadowColor || [CPColor colorWithWhite:1.0 alpha:0.8];
}
- (void)update
{
var x = HORIZONTAL_MARGIN,
height = 0.0;
[_imageAndTextView setFont:[_menuItem font] || [_CPMenuBarWindow font]];
[_imageAndTextView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_imageAndTextView setImage:[_menuItem image]];
[_imageAndTextView setText:[_menuItem title]];
[_imageAndTextView setTextColor:[self textColor]];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_imageAndTextView sizeToFit];
var imageAndTextViewFrame = [_imageAndTextView frame];
imageAndTextViewFrame.origin.x = x;
x += CGRectGetWidth(imageAndTextViewFrame);
height = MAX(height, CGRectGetHeight(imageAndTextViewFrame));
var hasSubmenuIndicator = [_menuItem hasSubmenu] && [_menuItem action];
if (hasSubmenuIndicator)
{
[_submenuIndicatorView setHidden:NO];
[_submenuIndicatorView setColor:[self textColor]];
[_submenuIndicatorView setShadowColor:[self textShadowColor]];
var submenuViewFrame = [_submenuIndicatorView frame];
submenuViewFrame.origin.x = x + SUBMENU_INDICATOR_MARGIN;
x = CGRectGetMaxX(submenuViewFrame);
height = MAX(height, CGRectGetHeight(submenuViewFrame));
}
else
[_submenuIndicatorView setHidden:YES];
height += 2.0 * VERTICAL_MARGIN;
imageAndTextViewFrame.origin.y = FLOOR((height - CGRectGetHeight(imageAndTextViewFrame)) / 2.0);
[_imageAndTextView setFrame:imageAndTextViewFrame];
if (hasSubmenuIndicator)
{
submenuViewFrame.origin.y = FLOOR((height - CGRectGetHeight(submenuViewFrame)) / 2.0) + 1.0;
[_submenuIndicatorView setFrame:submenuViewFrame];
}
_minSize = CGSizeMake(x + HORIZONTAL_MARGIN, height);
[self setAutoresizesSubviews:NO];
[self setFrameSize:_minSize];
[self setAutoresizesSubviews:YES];
}
- (void)highlight:(BOOL)shouldHighlight
{
// FIXME: This should probably be even throw.
if (![_menuItem isEnabled])
shouldHighlight = NO;
if (shouldHighlight)
{
if (![_menuItem _isMenuBarButton])
[self setBackgroundColor:SelectionColor];
[_imageAndTextView setImage:[_menuItem alternateImage] || [_menuItem image]];
[_imageAndTextView setTextColor:[CPColor whiteColor]];
[_imageAndTextView setTextShadowColor:_CPMenuItemTextShadowColor];
[_submenuIndicatorView setColor:[CPColor whiteColor]];
[_submenuIndicatorView setShadowColor:[CPColor colorWithWhite:0.1 alpha:0.7]];
}
else
{
[self setBackgroundColor:nil];
[_imageAndTextView setImage:[_menuItem image]];
[_imageAndTextView setTextColor:[self textColor]];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_submenuIndicatorView setColor:[self textColor]];
[_submenuIndicatorView setShadowColor:[self textShadowColor]];
}
}
@end
@implementation _CPMenuItemMenuBarSubmenuIndicatorView : CPView
{
CPColor _color;
CPColor _shadowColor;
}
- (void)setColor:(CPColor)aColor
{
if (_color === aColor)
return;
_color = aColor;
[self setNeedsDisplay:YES];
}
- (void)setShadowColor:(CPColor)aColor
{
if (_shadowColor === aColor)
return;
_shadowColor = aColor;
[self setNeedsDisplay:YES];
}
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds];
bounds.size.height -= 1.0;
bounds.size.width -= 2.0;
bounds.origin.x += 1.0;
CGContextBeginPath(context);
CGContextMoveToPoint(context, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
CGContextAddLineToPoint(context, CGRectGetMidX(bounds), CGRectGetMaxY(bounds));
CGContextClosePath(context);
CGContextSetShadowWithColor(context, CGSizeMake(0.0, 1.0), 1.1, _shadowColor || [CPColor whiteColor]);
CGContextSetFillColor(context, _color || [CPColor blackColor]);
CGContextFillPath(context);
}
@end
@@ -0,0 +1,38 @@
@import "CPView.j"
@implementation _CPMenuItemSeparatorView : CPView
{
}
+ (id)view
{
return [[self alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 10.0)];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
[self setAutoresizingMask:CPViewWidthSizable];
return self;
}
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds];
CGContextBeginPath(context);
CGContextMoveToPoint(context, CGRectGetMinX(bounds), FLOOR(CGRectGetMidY(bounds)) - 0.5);
CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), FLOOR(CGRectGetMidY(bounds)) - 0.5);
CGContextSetStrokeColor(context, [CPColor lightGrayColor]);
CGContextStrokePath(context);
}
@end
+306
View File
@@ -0,0 +1,306 @@
@import "CPControl.j"
var LEFT_MARGIN = 3.0,
RIGHT_MARGIN = 14.0 + 3.0,
STATE_COLUMN_WIDTH = 14.0,
INDENTATION_WIDTH = 17.0,
VERTICAL_MARGIN = 4.0,
RIGHT_COLUMNS_MARGIN = 30.0,
KEY_EQUIVALENT_MARGIN = 10.0;
var SUBMENU_INDICATOR_COLOR = nil,
_CPMenuItemSelectionColor = nil,
_CPMenuItemTextShadowColor = nil,
_CPMenuItemDefaultStateImages = [],
_CPMenuItemDefaultStateHighlightedImages = [];
@implementation _CPMenuItemStandardView : CPView
{
CPMenuItem _menuItem @accessors(property=menuItem);
CPFont _font;
CPColor _textColor;
CPColor _textShadowColor;
CGSize _minSize @accessors(readonly, property=minSize);
BOOL _isDirty;
CPImageView _stateView;
_CPImageAndTextView _imageAndTextView;
_CPImageAndTextView _keyEquivalentView;
CPView _submenuIndicatorView;
}
+ (void)initialize
{
if (self !== [_CPMenuItemStandardView class])
return;
SUBMENU_INDICATOR_COLOR = [CPColor grayColor];
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
var bundle = [CPBundle bundleForClass:self];
_CPMenuItemDefaultStateImages[CPOffState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil;
_CPMenuItemDefaultStateImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnState.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateHighlightedImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnStateHighlighted.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateImages[CPMixedState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPMixedState] = nil;
}
+ (id)view
{
return [[self alloc] init];
}
+ (float)_standardLeftMargin
{
return LEFT_MARGIN + STATE_COLUMN_WIDTH;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_stateView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
[_stateView setImageScaling:CPScaleNone];
[self addSubview:_stateView];
_imageAndTextView = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
[_imageAndTextView setImagePosition:CPImageLeft];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[self addSubview:_imageAndTextView];
_keyEquivalentView = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
[_keyEquivalentView setImagePosition:CPNoImage];
[_keyEquivalentView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_keyEquivalentView setAutoresizingMask:CPViewMinXMargin];
[self addSubview:_keyEquivalentView];
_submenuIndicatorView = [[_CPMenuItemSubmenuIndicatorView alloc] initWithFrame:CGRectMake(0.0, 0.0, 8.0, 10.0)];
[_submenuIndicatorView setColor:SUBMENU_INDICATOR_COLOR];
[_submenuIndicatorView setAutoresizingMask:CPViewMinXMargin];
[self addSubview:_submenuIndicatorView];
[self setAutoresizingMask:CPViewWidthSizable];
}
return self;
}
- (CPColor)textColor
{
if (![_menuItem isEnabled])
return [CPColor lightGrayColor];
return _textColor || [CPColor colorWithCalibratedRed:70.0 / 255.0 green:69.0 / 255.0 blue:69.0 / 255.0 alpha:1.0];
}
- (CPColor)textShadowColor
{
if (![_menuItem isEnabled])
return nil;
return _textShadowColor || [CPColor colorWithWhite:1.0 alpha:0.8];
}
- (void)setFont:(CPFont)aFont
{
_font = aFont;
}
- (void)update
{
var x = LEFT_MARGIN + [_menuItem indentationLevel] * INDENTATION_WIDTH,
height = 0.0,
hasStateColumn = [[_menuItem menu] showsStateColumn];
if (hasStateColumn)
{
[_stateView setHidden:NO];
[_stateView setImage:_CPMenuItemDefaultStateImages[[_menuItem state]] || nil];
x += STATE_COLUMN_WIDTH;
}
else
[_stateView setHidden:YES];
[_imageAndTextView setFont:[_menuItem font] || _font];
[_imageAndTextView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_imageAndTextView setImage:[_menuItem image]];
[_imageAndTextView setText:[_menuItem title]];
[_imageAndTextView setTextColor:[self textColor]];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_imageAndTextView sizeToFit];
var imageAndTextViewFrame = [_imageAndTextView frame];
imageAndTextViewFrame.origin.x = x;
x += CGRectGetWidth(imageAndTextViewFrame);
height = MAX(height, CGRectGetHeight(imageAndTextViewFrame));
var hasKeyEquivalent = !![_menuItem keyEquivalent],
hasSubmenu = [_menuItem hasSubmenu];
if (hasKeyEquivalent || hasSubmenu)
x += RIGHT_COLUMNS_MARGIN;
if (hasKeyEquivalent)
{
[_keyEquivalentView setFont:[_menuItem font] || _font];
[_keyEquivalentView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_keyEquivalentView setImage:[_menuItem image]];
[_keyEquivalentView setText:[_menuItem keyEquivalentStringRepresentation]];
[_keyEquivalentView setTextColor:[self textColor]];
[_keyEquivalentView setTextShadowColor:[self textShadowColor]];
[_keyEquivalentView setTextShadowOffset:CGSizeMake(0, 1)];
[_keyEquivalentView setFrameOrigin:CGPointMake(x, VERTICAL_MARGIN)];
[_keyEquivalentView sizeToFit];
var keyEquivalentViewFrame = [_keyEquivalentView frame];
keyEquivalentViewFrame.origin.x = x;
x += CGRectGetWidth(keyEquivalentViewFrame);
height = MAX(height, CGRectGetHeight(keyEquivalentViewFrame));
if (hasSubmenu)
x += RIGHT_COLUMNS_MARGIN;
}
else
[_keyEquivalentView setHidden:YES];
if (hasSubmenu)
{
[_submenuIndicatorView setHidden:NO];
var submenuViewFrame = [_submenuIndicatorView frame];
submenuViewFrame.origin.x = x;
x += CGRectGetWidth(submenuViewFrame);
height = MAX(height, CGRectGetHeight(submenuViewFrame));
}
else
[_submenuIndicatorView setHidden:YES];
height += 2.0 * VERTICAL_MARGIN;
imageAndTextViewFrame.origin.y = FLOOR((height - CGRectGetHeight(imageAndTextViewFrame)) / 2.0);
[_imageAndTextView setFrame:imageAndTextViewFrame];
if (hasStateColumn)
[_stateView setFrameSize:CGSizeMake(STATE_COLUMN_WIDTH, height)];
if (hasKeyEquivalent)
{
keyEquivalentViewFrame.origin.y = FLOOR((height - CGRectGetHeight(keyEquivalentViewFrame)) / 2.0);
[_keyEquivalentView setFrame:keyEquivalentViewFrame];
}
if (hasSubmenu)
{
submenuViewFrame.origin.y = FLOOR((height - CGRectGetHeight(submenuViewFrame)) / 2.0);
[_submenuIndicatorView setFrame:submenuViewFrame];
}
_minSize = CGSizeMake(x + RIGHT_MARGIN, height);
[self setAutoresizesSubviews:NO];
[self setFrameSize:_minSize];
[self setAutoresizesSubviews:YES];
}
- (void)highlight:(BOOL)shouldHighlight
{
// FIXME: This should probably be even throw.
if (![_menuItem isEnabled])
return;
if (shouldHighlight)
{
[self setBackgroundColor:_CPMenuItemSelectionColor];
[_imageAndTextView setImage:[_menuItem alternateImage] || [_menuItem image]];
[_imageAndTextView setTextColor:[CPColor whiteColor]];
[_keyEquivalentView setTextColor:[CPColor whiteColor]];
[_submenuIndicatorView setColor:[CPColor whiteColor]];
[_imageAndTextView setTextShadowColor:_CPMenuItemTextShadowColor];
[_keyEquivalentView setTextShadowColor:_CPMenuItemTextShadowColor];
}
else
{
[self setBackgroundColor:nil];
[_imageAndTextView setImage:[_menuItem image]];
[_imageAndTextView setTextColor:[self textColor]];
[_keyEquivalentView setTextColor:[self textColor]];
[_submenuIndicatorView setColor:SUBMENU_INDICATOR_COLOR];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_keyEquivalentView setTextShadowColor:[self textShadowColor]];
}
if ([[_menuItem menu] showsStateColumn])
{
if (shouldHighlight)
[_stateView setImage:_CPMenuItemDefaultStateHighlightedImages[[_menuItem state]] || nil];
else
[_stateView setImage:_CPMenuItemDefaultStateImages[[_menuItem state]] || nil];
}
}
@end
@implementation _CPMenuItemSubmenuIndicatorView : CPView
{
CPColor _color;
}
- (void)setColor:(CPColor)aColor
{
if (_color === aColor)
return;
_color = aColor;
[self setNeedsDisplay:YES];
}
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds];
CGContextBeginPath(context);
CGContextMoveToPoint(context, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), CGRectGetMidY(bounds));
CGContextAddLineToPoint(context, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
CGContextClosePath(context);
CGContextSetFillColor(context, _color);
CGContextFillPath(context);
}
@end
+257
View File
@@ -0,0 +1,257 @@
@import <AppKit/CPControl.j>
@import "_CPMenuItemSeparatorView.j"
@import "_CPMenuItemStandardView.j"
@import "_CPMenuItemMenuBarView.j"
var LEFT_MARGIN = 3.0,
RIGHT_MARGIN = 16.0,
STATE_COLUMN_WIDTH = 14.0,
INDENTATION_WIDTH = 17.0,
VERTICAL_MARGIN = 4.0;
var _CPMenuItemSelectionColor = nil,
_CPMenuItemTextShadowColor = nil,
_CPMenuItemDefaultStateImages = [],
_CPMenuItemDefaultStateHighlightedImages = [];
/*
@ignore
*/
@implementation _CPMenuItemView : CPView
{
CPMenuItem _menuItem;
CPView _view;
CPFont _font;
CPColor _textColor;
CPColor _textShadowColor;
CGSize _minSize;
BOOL _isDirty;
BOOL _showsStateColumn;
CPImageView _stateView;
_CPImageAndTextView _imageAndTextView;
CPView _submenuView;
}
+ (void)initialize
{
if (self != [_CPMenuItemView class])
return;
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
var bundle = [CPBundle bundleForClass:self];
_CPMenuItemDefaultStateImages[CPOffState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil;
_CPMenuItemDefaultStateImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnState.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateHighlightedImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnStateHighlighted.png"] size:CGSizeMake(14.0, 14.0)];
_CPMenuItemDefaultStateImages[CPMixedState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPMixedState] = nil;
}
+ (float)leftMargin
{
return LEFT_MARGIN + STATE_COLUMN_WIDTH;
}
- (id)initWithFrame:(CGRect)aFrame forMenuItem:(CPMenuItem)aMenuItem
{
self = [super initWithFrame:aFrame];
if (self)
{
_menuItem = aMenuItem;
_showsStateColumn = YES;
_isDirty = YES;
[self setAutoresizingMask:CPViewWidthSizable];
[self synchronizeWithMenuItem];
}
return self;
}
- (CGSize)minSize
{
return _minSize;
}
- (void)setDirty
{
_isDirty = YES;
}
- (void)synchronizeWithMenuItem
{
var menuItemView = [_menuItem view];
if ([_menuItem isSeparatorItem])
{
if (![_view isKindOfClass:[_CPMenuItemSeparatorView class]])
{
[_view removeFromSuperview];
_view = [_CPMenuItemSeparatorView view];
}
}
else if (menuItemView)
{
if (_view !== menuItemView)
{
[_view removeFromSuperview];
_view = menuItemView;
}
}
else if ([_menuItem menu] == [CPApp mainMenu])
{
if (![_view isKindOfClass:[_CPMenuItemMenuBarView class]])
{
[_view removeFromSuperview];
_view = [_CPMenuItemMenuBarView view];
}
[_view setMenuItem:_menuItem];
}
else
{
if (![_view isKindOfClass:[_CPMenuItemStandardView class]])
{
[_view removeFromSuperview];
_view = [_CPMenuItemStandardView view];
}
[_view setMenuItem:_menuItem];
}
if ([_view superview] !== self)
[self addSubview:_view];
if ([_view respondsToSelector:@selector(update)])
[_view update];
_minSize = [_view frame].size;
[self setAutoresizesSubviews:NO];
[self setFrameSize:_minSize];
[self setAutoresizesSubviews:YES];
}
- (void)setShowsStateColumn:(BOOL)shouldShowStateColumn
{
_showsStateColumn = shouldShowStateColumn;
}
- (void)highlight:(BOOL)shouldHighlight
{
if ([_view respondsToSelector:@selector(highlight:)])
[_view highlight:shouldHighlight];
}
- (BOOL)eventOnSubmenu:(CPEvent)anEvent
{
if (![_menuItem hasSubmenu])
return NO;
return CGRectContainsPoint([_submenuView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]);
}
- (BOOL)isHidden
{
return [_menuItem isHidden];
}
- (CPMenuItem)menuItem
{
return _menuItem;
}
- (void)setFont:(CPFont)aFont
{
if (_font === aFont)
return;
_font = aFont;
if ([_view respondsToSelector:@selector(setFont:)])
[_view setFont:aFont];
[self setDirty];
}
- (void)setTextColor:(CPColor)aColor
{
if (_textColor == aColor)
return;
_textColor = aColor;
[_imageAndTextView setTextColor:[self textColor]];
[_submenuView setColor:[self textColor]];
}
- (CPColor)textColor
{
return nil;
}
- (void)setTextShadowColor:(CPColor)aColor
{
if (_textShadowColor == aColor)
return;
_textShadowColor = aColor;
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
//[_submenuView setColor:[self textColor]];
}
- (CPColor)textShadowColor
{
return [_menuItem isEnabled] ? (_textShadowColor ? _textShadowColor : [CPColor colorWithWhite:1.0 alpha:0.8]) : [CPColor colorWithWhite:0.8 alpha:0.8];
}
@end
@implementation _CPMenuItemArrowView : CPView
{
CPColor _color;
}
- (void)setColor:(CPColor)aColor
{
if (_color == aColor)
return;
_color = aColor;
[self setNeedsDisplay:YES];
}
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextBeginPath(context);
CGContextMoveToPoint(context, 1.0, 4.0);
CGContextAddLineToPoint(context, 9.0, 4.0);
CGContextAddLineToPoint(context, 5.0, 8.0);
CGContextAddLineToPoint(context, 1.0, 4.0);
CGContextClosePath(context);
CGContextSetFillColor(context, _color);
CGContextFillPath(context);
}
@end
+625
View File
@@ -0,0 +1,625 @@
@import <Foundation/CPDictionary.j>
@import <Foundation/CPCountedSet.j>
@import "CPController.j"
@implementation CPObjectController : CPController
{
id _contentObject;
id _selection;
Class _objectClass;
BOOL _isEditable;
BOOL _automaticallyPreparesContent;
CPCountedSet _observedKeys;
}
+ (id)initialize
{
[self exposeBinding:@"editable"];
[self exposeBinding:@"contentObject"];
}
+ (CPSet)keyPathsForValuesAffectingContentObject
{
return [CPSet setWithObjects:"content"];
}
+ (BOOL)automaticallyNotifiesObserversForKey:(CPString)aKey
{
if (aKey === @"contentObject")
return NO;
return YES;
}
+ (CPSet)keyPathsForValuesAffectingCanAdd
{
return [CPSet setWithObject:"editable"];
}
+ (CPSet)keyPathsForValuesAffectingCanInsert
{
return [CPSet setWithObject:"editable"];
}
+ (CPSet)keyPathsForValuesAffectingCanRemove
{
return [CPSet setWithObjects:"editable", "selection"];
}
- (id)init
{
return [self initWithContent:nil];
}
- (id)initWithContent:(id)aContent
{
if (self = [super init])
{
[self setContent:aContent];
[self setEditable:YES];
[self setObjectClass:[CPMutableDictionary class]];
_observedKeys = [[CPCountedSet alloc] init];
}
return self;
}
- (id)content
{
return _contentObject;
}
- (void)setContent:(id)aContent
{
[self willChangeValueForKey:@"contentObject"];
[self _selectionWillChange];
_contentObject = aContent;
[self didChangeValueForKey:@"contentObject"];
[self _selectionDidChange];
}
- (void)_setContentObject:(id)aContent
{
[self setContent:aContent];
}
- (id)_contentObject
{
return [self content];
}
- (void)setAutomaticallyPreparesContent:(BOOL)shouldAutomaticallyPrepareContent
{
_automaticallyPreparesContent = shouldAutomaticallyPrepareContent;
}
- (BOOL)automaticallyPreparesContent
{
return _automaticallyPreparesContent;
}
- (void)prepareContent
{
[self setContent:[self newObject]];
}
- (void)setObjectClass:(Class)aClass
{
_objectClass = aClass;
}
- (Class)objectClass
{
return _objectClass;
}
- (id)newObject
{
return [[[self objectClass] alloc] init];
}
- (void)addObject:(id)anObject
{
[self setContent:anObject];
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
}
- (void)removeObject:(id)anObject
{
if ([self content] === anObject)
[self setContent:nil];
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
}
- (void)add:(id)aSender
{
// FIXME: This should happen on the next run loop?
[self addObject:[self newObject]];
}
- (BOOL)canAdd
{
return [self isEditable];
}
- (void)remove:(id)aSender
{
// FIXME: This should happen on the next run loop?
[self removeObject:[self content]];
}
- (BOOL)canRemove
{
return [self isEditable] && [[self selectedObjects] count];
}
- (void)setEditable:(BOOL)shouldBeEditable
{
_isEditable = shouldBeEditable;
}
- (BOOL)isEditable
{
return _isEditable;
}
- (CPArray)selectedObjects
{
return [[_CPObservableArray alloc] initWithObjects:[_contentObject] count:1];
}
- (id)selection
{
return _selection;
}
- (void)_selectionWillChange
{
[_selection controllerWillChange];
[self willChangeValueForKey:@"selection"];
}
- (void)_selectionDidChange
{
if (_selection === undefined || _selection === nil)
_selection = [[CPControllerSelectionProxy alloc] initWithController:self];
[_selection controllerDidChange];
[self didChangeValueForKey:@"selection"];
}
- (id)observedKeys
{
return _observedKeys;
}
- (void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
[_observedKeys addObject:aKeyPath];
[super addObserver:anObserver forKeyPath:aKeyPath options:options context:context];
}
- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath
{
[_observedKeys removeObject:aKeyPath];
[super removeObserver:anObserver forKeyPath:aKeyPath];
}
@end
var CPObjectControllerObjectClassNameKey = @"CPObjectControllerObjectClassNameKey",
CPObjectControllerIsEditableKey = @"CPObjectControllerIsEditableKey",
CPObjectControllerAutomaticallyPreparesContentKey = @"CPObjectControllerAutomaticallyPreparesContentKey";
@implementation CPObjectController (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
var objectClassName = [aCoder decodeObjectForKey:CPObjectControllerObjectClassNameKey],
objectClass = CPClassFromString(objectClassName);
// FIXME: Error if objectClass === nil
[self setObjectClass:objectClass];
[self setEditable:[aCoder decodeBoolForKey:CPObjectControllerIsEditableKey]];
[self setAutomaticallyPreparesContent:[aCoder decodeBoolForKey:CPObjectControllerAutomaticallyPreparesContentKey] || NO];
_observedKeys = [[CPCountedSet alloc] init];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:CPStringFromClass(objectClass) forKey:CPObjectControllerObjectClassNameKey];
[aCoder encodeObject:[self isEditable] forKey:CPObjectControllerIsEditableKey];
if (![self automaticallyPreparesContent])
[aCoder encodeBOOL:YES forKey:CPObjectControllerAutomaticallyPreparesContentKey];
}
@end
@implementation _CPObservationProxy : CPObject
{
id _keyPath;
id _observer;
id _object;
BOOL _notifyObject;
id _context;
int _options;
}
- (id)initWithKeyPath:(id)aKeyPath observer:(id)anObserver object:(id)anObject
{
if (self=[super init])
{
_keyPath = aKeyPath;
_observer = anObserver;
_object = anObject;
}
return self;
}
- (id)observer
{
return _observer;
}
- (id)keyPath
{
return _keyPath;
}
- (id)context
{
return _context;
}
- (int)options
{
return _options;
}
- (void)setNotifyObject:(BOOL)notify
{
_notifyObject = notify;
}
- (BOOL)isEqual:(id)anObject
{
if ([anObject class] === [self class])
{
if (anObject._observer === _observer && [anObject._keyPath isEqual:_keyPath] && [anObject._object isEqual:_object])
return YES;
}
return NO;
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
{
if (_notifyObject)
[_object observeValueForKeyPath:_keyPath ofObject:_object change:change context:context];
[_observer observeValueForKeyPath:_keyPath ofObject:_object change:change context:context];
}
- (CPString)description
{
return [super description] + [CPString stringWithFormat:@"observation proxy for %@ on key path %@", _observer, _keyPath];
}
@end
@implementation _CPObservableArray : CPMutableArray
{
CPArray _observationProxies;
}
+ (id)alloc
{
var a = [];
a.isa = self;
var ivars = class_copyIvarList(self),
count = ivars.length;
while (count--)
a[ivar_getName(ivars[count])] = nil;
return a;
}
- (CPString)description
{
return "<_CPObservableArray: "+[super description]+" >";
}
- (id)initWithArray:(CPArray)anArray
{
if (self = [super initWithArray:anArray])
{
_observationProxies = [];
}
return self;
}
- (id)initWithObjects:(CPArray)objects count:(unsigned)count
{
if (self = [super initWithObjects:objects count:count])
{
_observationProxies = [];
}
return self;
}
-(void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
if (aKeyPath.indexOf("@") === 0)
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self];
proxy._options = options;
proxy._context = context;
[_observationProxies addObject:proxy];
var dotIndex = aKeyPath.indexOf("."),
remaining = aKeyPath.substring(dotIndex+1),
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self addObserver:proxy toObjectsAtIndexes:indexes forKeyPath:remaining options:options context:context];
}
else
{
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self addObserver:anObserver toObjectsAtIndexes:indexes forKeyPath:aKeyPath options:options context:context];
}
}
- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath
{
if (aKeyPath.indexOf("@") === 0)
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self],
index = [_observationProxies indexOfObject:proxy];
proxy = [_observationProxies objectAtIndex:index];
var dotIndex = aKeyPath.indexOf("."),
remaining = aKeyPath.substring(dotIndex+1),
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self removeObserver:proxy fromObjectsAtIndexes:indexes forKeyPath:remaining];
}
else
{
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self removeObserver:anObserver fromObjectsAtIndexes:indexes forKeyPath:aKeyPath];
}
}
- (void)insertObject:(id)anObject atIndex:(unsigned)anIndex
{
for (var i=0, count=[_observationProxies count]; i<count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super insertObject:anObject atIndex:anIndex];
}
- (void)removeObjectAtIndex:(unsigned)anIndex
{
for (var i=0, count=[_observationProxies count]; i<count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[anObject removeObserver:proxy forKeyPath:keyPath];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super removeObjectAtIndex:anIndex];
}
- (_CPObservableArray)objectsAtIndexes:(CPIndexSet)theIndexes
{
return [_CPObservableArray arrayWithArray:[super objectsAtIndexes:theIndexes]];
}
- (void)addObject:(id)anObject
{
[self insertObject:anObject atIndex:[self count]];
}
- (void)removeLastObject
{
[self removeObjectAtIndex:[self count]];
}
- (void)replaceObjectAtIndex:(unsigned)anIndex withObject:(id)anObject
{
var currentObject = [self objectAtIndex:anIndex];
for (var i=0, count=[_observationProxies count]; i<count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[currentObject removeObserver:proxy forKeyPath:keyPath];
[anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super replaceObjectAtIndex:anIndex withObject:anObject];
}
@end
@implementation CPControllerSelectionProxy : CPObject
{
id _controller;
id _keys;
CPDictionary _cachedValues;
CPArray _observationProxies;
}
- (id)initWithController:(id)aController
{
if (self = [super init])
{
_cachedValues = [CPDictionary dictionary];
_observationProxies = [CPArray array];
_controller = aController;
}
return self;
}
- (id)valueForKey:(CPString)aKey
{
var value = [_cachedValues objectForKey:aKey];
if (value !== undefined && value !== nil)
return value;
var allValues = [[_controller selectedObjects] valueForKeyPath:aKey],
count = [allValues count];
if (!count)
value = CPNoSelectionMarker;
else if (count === 1)
value = [allValues objectAtIndex:0];
else
{
if ([_controller alwaysUsesMultipleValuesMarker])
value = CPMultipleValuesMarker;
else
{
value = [allValues objectAtIndex:0];
for (var i=0, count=[allValues count]; i<count && value!=CPMultipleValuesMarker; i++)
{
if (![value isEqual:[allValues objectAtIndex:i]])
value = CPMultipleValuesMarker;
}
}
}
[_cachedValues setValue:value forKey:aKey];
return value;
}
- (unsigned)count
{
return [_cachedValues count];
}
- (id)keyEnumerator
{
return [_cachedValues keyEnumerator];
}
- (void)setValue:(id)aValue forKey:(CPString)aKey
{
[[_controller selectedObjects] setValue:aValue forKey:aKey];
}
-(void)controllerWillChange
{
_keys = [_cachedValues allKeys];
if (!_keys)
return;
for (var i=0, count=_keys.length; i<count; i++)
[self willChangeValueForKey:_keys[i]];
[_cachedValues removeAllObjects];
}
-(void)controllerDidChange
{
[_cachedValues removeAllObjects];
if (!_keys)
return;
for (var i=0, count=_keys.length; i<count; i++)
[self didChangeValueForKey:_keys[i]];
_keys = nil;
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
{
[_cachedValues removeObjectForKey:aKeyPath];
}
- (void)addObserver:(id)anObject forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self];
[proxy setNotifyObject:YES];
[_observationProxies addObject:proxy];
[[_controller selectedObjects] addObserver:proxy forKeyPath:aKeyPath options:options context:context];
}
- (void)removeObserver:(id)anObject forKeyPath:(CPString)aKeyPath
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self],
index = [_observationProxies indexOfObject:proxy];
[[_controller selectedObjects] removeObserver:[_observationProxies objectAtIndex:index] forKeyPath:aKeyPath];
[_observationProxies removeObjectAtIndex:index];
}
@end
+46
View File
@@ -0,0 +1,46 @@
@import "CPPanel.j"
@implementation CPOpenPanel : CPPanel
{
BOOL _canChooseFiles @accessors(property=canChooseFiles);
BOOL _canChooseDirectories @accessors(property=canChooseDirectories);
BOOL _allowsMultipleSelection @accessors(property=allowsMultipleSelection);
CPURL _directoryURL @accessors(property=directoryURL);
CPArray _URLs;
}
+ (id)openPanel
{
return [[CPOpenPanel alloc] init];
}
- (CPInteger)runModal
{
if (typeof window["cpOpenPanel"] === "function")
{
// FIXME: Is this correct???
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
var options = { directoryURL: [self directoryURL],
canChooseFiles: [self canChooseFiles],
canChooseDirectories: [self canChooseDirectories],
allowsMultipleSelection: [self allowsMultipleSelection] };
var result = window.cpOpenPanel(options);
_URLs = result.URLs;
return result.button;
}
throw "-runModal is unimplemented.";
}
- (CPArray)URLs
{
return _URLs;
}
@end
+1279 -57
View File
File diff suppressed because it is too large Load Diff
+13 -6
View File
@@ -46,6 +46,13 @@ CPCancelButton = 0;
<li>A panel can be made to work even when there's an attention panel on-screen. This permits actions within the panel to affect the attention panel.</li>
</ul>
*/
/*
@global
@class CPWindow
*/
CPDocModalWindowMask = 1 << 6;
@implementation CPPanel : CPWindow
{
BOOL _becomesKeyOnlyIfNeeded;
@@ -53,7 +60,7 @@ CPCancelButton = 0;
}
/*!
Returns <code>YES</code> if the receiver is a floating panel (like a palette).
Returns \c YES if the receiver is a floating panel (like a palette).
*/
- (BOOL)isFloatingPanel
{
@@ -61,8 +68,8 @@ CPCancelButton = 0;
}
/*!
Sets the receiver to be a floating panel. <code>YES</code>
makes the window a floating panel. <code>NO</code> makes it a normal window.
Sets the receiver to be a floating panel. \c YES
makes the window a floating panel. \c NO makes it a normal window.
@param isFloatingPanel specifies whether to make it floating
*/
- (void)setFloatingPanel:(BOOL)isFloatingPanel
@@ -71,8 +78,8 @@ CPCancelButton = 0;
}
/*!
Returns <code>YES</code> if the window only becomes key
if needed. <code>NO</code> means it behaves just like other windows.
Returns \c YES if the window only becomes key
if needed. \c NO means it behaves just like other windows.
*/
- (BOOL)becomesKeyOnlyIfNeeded
{
@@ -81,7 +88,7 @@ CPCancelButton = 0;
/*!
Sets whether the the window becomes key only if needed.
@param shouldBecomeKeyOnlyIfNeeded <code>YES</code> makes the window become key only if needed
@param shouldBecomeKeyOnlyIfNeeded \c YES makes the window become key only if needed
*/
- (void)setBecomesKeyOnlyIfNeeded:(BOOL)shouldBecomeKeyOnlyIfNeeded
{
+164 -20
View File
@@ -38,9 +38,17 @@ CPFontPboardType = @"CPFontPboardType";
CPHTMLPboardType = @"CPHTMLPboardType";
CPStringPboardType = @"CPStringPboardType";
CPURLPboardType = @"CPURLPboardType";
CPImagesPboardType = @"CPImagesPboardType";
CPVideosPboardType = @"CPVideosPboardType";
UTF8PboardType = @"public.utf8-plain-text";
// Deprecated
CPImagePboardType = @"CPImagePboardType";
var CPPasteboards = nil;
var CPPasteboards = nil,
supportsNativePasteboard = NO;
/*!
@ingroup appkit
@@ -56,6 +64,8 @@ var CPPasteboards = nil;
unsigned _changeCount;
CPString _stateUID;
WebScriptObject _nativePasteboard;
}
/*
@@ -69,6 +79,9 @@ var CPPasteboards = nil;
[self setVersion:1.0];
CPPasteboards = [CPDictionary dictionary];
if (typeof window.cpPasteboardWithName !== "undefined")
supportsNativePasteboard = YES;
}
/*!
@@ -87,7 +100,7 @@ var CPPasteboards = nil;
+ (id)pasteboardWithName:(CPString)aName
{
var pasteboard = [CPPasteboards objectForKey:aName];
if (pasteboard)
return pasteboard;
@@ -111,6 +124,12 @@ var CPPasteboards = nil;
_provided = [CPDictionary dictionary];
_changeCount = 0;
if (supportsNativePasteboard)
{
_nativePasteboard = window.cpPasteboardWithName(aName);
[self _synchronizePasteboard];
}
}
return self;
@@ -139,7 +158,16 @@ var CPPasteboards = nil;
[_owners setObject:anOwner forKey:type];
}
if (_nativePasteboard)
{
var nativeTypes = [types copy];
if ([types containsObject:CPStringPboardType])
nativeTypes.push(UTF8PboardType);
_nativePasteboard.addTypes_(nativeTypes);
}
return ++_changeCount;
}
@@ -150,6 +178,12 @@ var CPPasteboards = nil;
@return the pasteboard's change count
*/
- (unsigned)declareTypes:(CPArray)types owner:(id)anOwner
{
[self _declareTypes:types owner:anOwner updateNativePasteboard:YES];
}
/*! @ignore */
- (unsigned)_declareTypes:(CPArray)types owner:(id)anOwner updateNativePasteboard:(BOOL)shouldUpdate
{
[_types setArray:types];
@@ -160,7 +194,16 @@ var CPPasteboards = nil;
while (count--)
[_owners setObject:anOwner forKey:_types[count]];
if (_nativePasteboard && shouldUpdate)
{
var nativeTypes = [types copy];
if ([types containsObject:CPStringPboardType])
nativeTypes.push(UTF8PboardType);
_nativePasteboard.declareTypes_(nativeTypes);
_changeCount = _nativePasteboard.changeCount();
}
return ++_changeCount;
}
@@ -168,12 +211,15 @@ var CPPasteboards = nil;
Sets the pasteboard data for the specified type
@param aData the data
@param aType the data type being set
@return <code>YES</code> if the data was successfully written to the pasteboard
@return \c YES if the data was successfully written to the pasteboard
*/
- (BOOL)setData:(CPData)aData forType:(CPString)aType
{
[_provided setObject:aData forKey:aType];
if (aType === CPStringPboardType)
[self setData:aData forType:UTF8PboardType];
return YES;
}
@@ -181,22 +227,22 @@ var CPPasteboards = nil;
Writes the specified property list as data for the specified type
@param aPropertyList the property list to write
@param aType the data type
@return <code>YES</code> if the property list was successfully written to the pasteboard
@return \c YES if the property list was successfully written to the pasteboard
*/
- (BOOL)setPropertyList:(id)aPropertyList forType:(CPString)aType
{
return [self setData:[CPPropertyListSerialization dataFromPropertyList:aPropertyList format:CPPropertyListXMLFormat_v1_0 errorDescription:nil] forType:aType];
return [self setData:[CPPropertyListSerialization dataFromPropertyList:aPropertyList format:CPPropertyList280NorthFormat_v1_0] forType:aType];
}
/*!
Sets the specified string as data for the specified type
@param aString the string to write
@param aType the data type
@return <code>YES</code> if the string was successfully written to the pasteboard
@return \c YES if the string was successfully written to the pasteboard
*/
- (void)setString:(CPString)aString forType:(CPString)aType
{
return [self setPropertyList:aString forType:aType];
[self setPropertyList:aString forType:aType];
}
// Determining Types
@@ -204,11 +250,11 @@ var CPPasteboards = nil;
Checks the pasteboard's types for a match with the types listen in the specified array. The array should
be ordered by the requestor's most preferred data type first.
@param anArray an array of requested types ordered by preference
@return the highest match with the pasteboard's supported types or <code>nil</code> if no match was found
@return the highest match with the pasteboard's supported types or \c nil if no match was found
*/
- (CPString)availableTypeFromArray:(CPArray)anArray
{
return [_types firstObjectCommonWithArray:anArray];
return [[self types] firstObjectCommonWithArray:anArray];
}
/*!
@@ -216,6 +262,7 @@ var CPPasteboards = nil;
*/
- (CPArray)types
{
[self _synchronizePasteboard];
return _types;
}
@@ -231,7 +278,7 @@ var CPPasteboards = nil;
/*!
Returns the pasteboard data for the specified data type
@param aType the requested data type
@return the requested data or <code>nil</code> if the data doesn't exist
@return the requested data or \c nil if the data doesn't exist
*/
- (CPData)dataForType:(CPString)aType
{
@@ -244,27 +291,57 @@ var CPPasteboards = nil;
if (owner)
{
[owner pasteboard:self provideDataForType:aType];
++_changeCount;
[owner pasteboard:self provideDataForType:aType];
return [_provided objectForKey:aType];
}
if (aType === CPStringPboardType)
return [self dataForType:UTF8PboardType];
return nil;
}
- (void)_synchronizePasteboard
{
if (_nativePasteboard && _nativePasteboard.changeCount() > _changeCount)
{
var nativeTypes = [_nativePasteboard.types() copy];
if ([nativeTypes containsObject:UTF8PboardType])
nativeTypes.push(CPStringPboardType);
[self _declareTypes:nativeTypes owner:self updateNativePasteboard:NO];
_changeCount = _nativePasteboard.changeCount();
}
}
/*! @ignore
method provided for integration with native pasteboard
*/
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
{
if (aType === CPStringPboardType)
{
var string = _nativePasteboard.stringForType_(UTF8PboardType);
[self setString:string forType:CPStringPboardType];
[self setString:string forType:UTF8PboardType];
}
else
[self setString:_nativePasteboard.stringForType_(aType) forType:aType];
}
/*!
Returns the property list for the specified data type
@param aType the requested data type
@return the property list or <code>nil</code> if the list was not found
@return the property list or \c nil if the list was not found
*/
- (id)propertyListForType:(CPString)aType
{
var data = [self dataForType:aType];
if (data)
return [CPPropertyListSerialization propertyListFromData:data format:CPPropertyListXMLFormat_v1_0 errorDescription:nil];
return [CPPropertyListSerialization propertyListFromData:data format:CPPropertyList280NorthFormat_v1_0];
return nil;
}
@@ -272,7 +349,7 @@ var CPPasteboards = nil;
/*!
Returns the string for the specified data type
@param aType the requested data type
@return the string or <code>nil</code> if the string was not found
@return the string or \c nil if the string was not found
*/
- (CPString)stringForType:(CPString)aType
{
@@ -299,3 +376,70 @@ var CPPasteboards = nil;
}
@end
#if PLATFORM(DOM)
var DOMDataTransferPasteboard = nil;
@implementation _CPDOMDataTransferPasteboard : CPPasteboard
{
DataTransfer _dataTransfer;
}
+ (_CPDOMDataTransferPasteboard)DOMDataTransferPasteboard
{
if (!DOMDataTransferPasteboard)
DOMDataTransferPasteboard = [[_CPDOMDataTransferPasteboard alloc] init];
return DOMDataTransferPasteboard;
}
- (void)_setDataTransfer:(DataTransfer)aDataTransfer
{
_dataTransfer = aDataTransfer;
}
- (void)_setPasteboard:(CPPasteboard)aPasteboard
{
_dataTransfer.clearData();
var types = [aPasteboard types],
count = types.length;
while (count--)
{
var type = types[count];
if (type === CPStringPboardType)
_dataTransfer.setData(type, [aPasteboard stringForType:type]);
else
_dataTransfer.setData(type, [[aPasteboard dataForType:type] rawString]);
}
}
- (CPArray)types
{
return Array.prototype.slice.apply(_dataTransfer.types);
}
- (CPData)dataForType:(CPString)aType
{
var dataString = _dataTransfer.getData(aType);
if (aType === CPStringPboardType)
return [CPData dataFromPropertyList:dataString format:kCFPropertyList280NorthFormat_v1_0];
return [CPData dataWithRawString:dataString];
}
- (id)propertyListForType:(CPString)aType
{
if (aType === CPStringPboardType)
return _dataTransfer.getData(aType);
return [CPPropertyListSerialization propertyListFromData:[self dataForType:aType] format:CPPropertyListUnknownFormat];
}
@end
#endif
+119 -94
View File
@@ -25,14 +25,12 @@
@import "CPMenu.j"
@import "CPMenuItem.j"
#include "CoreGraphics/CGGeometry.h"
var VISIBLE_MARGIN = 7.0;
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
/*!
@ingroup appkit
@class CPPopUpButton
@@ -42,11 +40,11 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
int _selectedIndex;
CPRectEdge _preferredEdge;
CPMenu _menu;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return "popup-button";
}
@@ -54,27 +52,27 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
Initializes the pop-up button to the specified size.
@param aFrame the size for the button
@param shouldPullDown <code>YES</code> makes this a pull-down menu, <code>NO</code> makes it a pop-up menu.
@param shouldPullDown \c YES makes this a pull-down menu, \c NO makes it a pop-up menu.
@return the initialized pop-up button
*/
- (id)initWithFrame:(CGRect)aFrame pullsDown:(BOOL)shouldPullDown
{
self = [super initWithFrame:aFrame];
if (self)
{
_selectedIndex = CPNotFound;
_preferredEdge = CPMaxYEdge;
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
[self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"];
[self setValue:CPLineBreakByTruncatingTail forThemeAttribute:@"line-break-mode"];
[self setMenu:[[CPMenu alloc] initWithTitle:@""]];
[self setPullsDown:shouldPullDown];
}
return self;
}
@@ -87,8 +85,8 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
Specifies whether the object is a pull-down or a pop-up menu.
@param shouldPullDown <code>YES</code> makes the pop-up button
a pull-down menu. <code>NO</code> makes it a pop-up menu.
@param shouldPullDown \c YES makes the pop-up button
a pull-down menu. \c NO makes it a pop-up menu.
*/
- (void)setPullsDown:(BOOL)shouldPullDown
{
@@ -111,7 +109,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
}
/*!
Returns <code>YES</code> if the button is a pull-down menu. <code>NO</code> if the button is a pop-up menu.
Returns \c YES if the button is a pull-down menu. \c NO if the button is a pop-up menu.
*/
- (BOOL)pullsDown
{
@@ -145,7 +143,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
var index = 0,
count = [titles count];
for (; index < count; ++index)
[self addItemWithTitle:titles[index]];
}
@@ -159,11 +157,11 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
var items = [self itemArray],
count = [items count];
while (count--)
if ([items[count] title] == aTitle)
[self removeItemAtIndex:count];
[_menu insertItemWithTitle:aTitle action:NULL keyEquivalent:nil atIndex:anIndex];
}
@@ -173,7 +171,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
- (void)removeAllItems
{
var count = [_menu numberOfItems];
while (count--)
[_menu removeItemAtIndex:0];
}
@@ -200,18 +198,18 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
// Getting the User's Selection
/*!
Returns the selected item or <code>nil</code> if no item is selected.
Returns the selected item or \c nil if no item is selected.
*/
- (CPMenuItem)selectedItem
{
if (_selectedIndex < 0)
if (_selectedIndex < 0 || _selectedIndex > [self numberOfItems] - 1)
return nil;
return [_menu itemAtIndex:_selectedIndex];
}
/*!
Returns the title of the selected item or <code>nil</code> if no item is selected.
Returns the title of the selected item or \c nil if no item is selected.
*/
- (CPString)titleOfSelectedItem
{
@@ -253,15 +251,15 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
if (_selectedIndex == anIndex)
return;
if (_selectedIndex >= 0 && ![self pullsDown])
[[self selectedItem] setState:CPOffState];
_selectedIndex = anIndex;
if (_selectedIndex >= 0 && ![self pullsDown])
[[self selectedItem] setState:CPOnState];
[self synchronizeTitleAndSelectedItem];
}
@@ -310,7 +308,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_menu)
{
[defaultCenter
@@ -330,7 +328,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
}
_menu = aMenu;
if (_menu)
{
[defaultCenter
@@ -338,20 +336,20 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
selector:@selector(menuDidAddItem:)
name:CPMenuDidAddItemNotification
object:_menu];
[defaultCenter
addObserver:self
selector:@selector(menuDidChangeItem:)
name:CPMenuDidChangeItemNotification
object:_menu];
[defaultCenter
addObserver:self
selector:@selector(menuDidRemoveItem:)
name:CPMenuDidRemoveItemNotification
object:_menu];
}
[self synchronizeTitleAndSelectedItem];
}
@@ -372,7 +370,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
}
/*!
Returns the item at the specified index or <code>nil</code> if the item does not exist.
Returns the item at the specified index or \c nil if the item does not exist.
@param anIndex the index of the item to obtain
*/
- (CPMenuItem)itemAtIndex:(unsigned)anIndex
@@ -381,7 +379,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
}
/*!
Returns the title of the item at the specified index or <code>nil</code> if no item exists.
Returns the title of the item at the specified index or \c nil if no item exists.
@param anIndex the index of the item
*/
- (CPString)itemTitleAtIndex:(unsigned)anIndex
@@ -396,12 +394,13 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
var titles = [],
items = [self itemArray],
index = 0,
count = [items count];
for (; index < count; ++index)
items.push([items[index] title]);
titles.push([items[index] title]);
return titles;
}
/*!
@@ -502,7 +501,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
if ([self title] === aTitle)
return;
if ([self pullsDown])
{
var items = [_menu itemArray];
@@ -519,14 +518,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
else
{
var index = [self indexOfItemWithTitle:aTitle];
if (index < 0)
{
[self addItemWithTitle:aTitle];
index = [self numberOfItems] - 1;
}
[self selectItemAtIndex:index];
}
}
@@ -554,7 +553,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if ([self pullsDown])
{
var items = [_menu itemArray];
if ([items count] > 0)
item = items[0];
}
@@ -573,22 +572,22 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
- (void)menuDidAddItem:(CPNotification)aNotification
{
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"];
if (_selectedIndex < 0)
[self selectItemAtIndex:0];
else if (index == _selectedIndex)
[self synchronizeTitleAndSelectedItem];
else if (index < _selectedIndex)
++_selectedIndex;
if (index == 0 && [self pullsDown])
{
var items = [_menu itemArray];
[items[0] setHidden:YES];
if (items.length > 0)
[items[1] setHidden:NO];
}
@@ -613,10 +612,10 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if ([self pullsDown] && index != 0)
return;
if (![self pullsDown] && index != _selectedIndex)
return;
[self synchronizeTitleAndSelectedItem];
}
@@ -627,30 +626,63 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
- (void)menuDidRemoveItem:(CPNotification)aNotification
{
var numberOfItems = [self numberOfItems];
if (numberOfItems <= _selectedIndex)
if (numberOfItems <= _selectedIndex && numberOfItems > 0)
[self selectItemAtIndex:numberOfItems - 1];
else
[self synchronizeTitleAndSelectedItem];
}
- (void)mouseDown:(CPEvent)anEvent
{
if (![self isEnabled])
if (![self isEnabled] || ![self numberOfItems])
return;
[self highlight:YES];
var menu = [self menu],
theWindow = [self window],
menuWindow = [_CPMenuWindow menuWindowWithMenu:menu font:[self font]];
[menuWindow setDelegate:self];
[menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle];
// Pull Down Menus show up directly below their buttons.
bounds = [self bounds],
minimumWidth = CGRectGetWidth(bounds);
// FIXME: setFont: should set the font on the menu.
[menu setFont:[self font]];
if ([self pullsDown])
var menuOrigin = [theWindow convertBaseToBridge:[self convertPoint:CGPointMake(0.0, CGRectGetMaxY([self bounds])) toView:nil]];
// Pop Up Menus attempt to show up "on top" of the selected item.
{
var positionedItem = nil,
location = CGPointMake(0.0, CGRectGetMaxY(bounds));
}
else
{
var contentRect = [self contentRectForBounds:bounds],
positionedItem = [self selectedItem],
standardLeftMargin = [_CPMenuWindow _standardLeftMargin] + [_CPMenuItemStandardView _standardLeftMargin],
location = CGPointMake(CGRectGetMinX(contentRect) - standardLeftMargin, 0.0);
minimumWidth += standardLeftMargin;
// To ensure the selected item is highlighted correctly, unset the highlighted item
[menu _highlightItemAtIndex:CPNotFound];
}
[menu setMinimumWidth:minimumWidth];
[menu
_popUpMenuPositioningItem:positionedItem
atLocation:location
topY:CGRectGetMinY(bounds)
bottomY:CGRectGetMaxY(bounds)
inView:self
callback:function(aMenu)
{
[self highlight:NO];
var highlightedItem = [aMenu highlightedItem];
if ([highlightedItem _isSelectable])
[self selectItem:highlightedItem];
}];
/*
else
{
// This is confusing, I KNOW, so let me explain it to you.
@@ -658,43 +690,19 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
// 1. So calculate where our content is, then calculate where the menu item is.
// 2. Move LEFT by whatever indentation we have (offsetWidths, aka, window margin, item margin, etc).
// 3. MOVE UP by the difference in sizes of the content and menu item, this will only work if the content is vertically centered.
var contentRect = [self convertRect:[self contentRectForBounds:[self bounds]] toView:nil],
menuOrigin = [theWindow convertBaseToBridge:contentRect.origin],
var contentRect = [self convertRect:[self contentRectForBounds:bounds] toView:nil],
menuOrigin = [theWindow convertBaseToGlobal:contentRect.origin],
menuItemRect = [menuWindow rectForItemAtIndex:_selectedIndex];
menuOrigin.x -= CGRectGetMinX(menuItemRect) + [menuWindow overlapOffsetWidth] + [[[menu itemAtIndex:_selectedIndex] _menuItemView] overlapOffsetWidth];
menuOrigin.y -= CGRectGetMinY(menuItemRect) + (CGRectGetHeight(menuItemRect) - CGRectGetHeight(contentRect)) / 2.0;
}
[menuWindow setFrameOrigin:menuOrigin];
var menuMaxX = CGRectGetMaxX([menuWindow frame]),
buttonMaxX = [theWindow convertBaseToBridge:CGPointMake(CGRectGetMaxX([self convertRect:[self bounds] toView:nil]), 0.0)].x;
if (menuMaxX < buttonMaxX)
[menuWindow setMinWidth:CGRectGetWidth([menuWindow frame]) + buttonMaxX - menuMaxX - ([self pullsDown] ? 0.0 : VISIBLE_MARGIN)];
[menuWindow orderFront:self];
[menuWindow beginTrackingWithEvent:anEvent sessionDelegate:self didEndSelector:@selector(menuWindowDidFinishTracking:highlightedItem:)];
*/
}
/*
@ignore
*/
- (void)menuWindowDidFinishTracking:(_CPMenuWindow)aMenuWindow highlightedItem:(CPMenuItem)aMenuItem
- (void)rightMouseDown:(CPEvent)anEvent
{
[_CPMenuWindow poolMenuWindow:aMenuWindow];
[self highlight:NO];
var index = [_menu indexOfItem:aMenuItem];
if (index == CPNotFound)
return;
[self selectItemAtIndex:index];
[CPApp sendAction:[aMenuItem action] to:[aMenuItem target] from:aMenuItem];
// Disable standard CPView behaviour which incorrectly displays the menu as a 'context menu'.
}
- (void)_popUpItemAction:(id)aSender
@@ -702,6 +710,23 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
[self sendAction:[self action] to:[self target]];
}
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
{
var count = objects.length,
value = [objects[0] valueForKeyPath:aKeyPath];
[self selectItemWithTag:value];
[self setEnabled:YES];
while (count-- > 1)
{
if (value !== [objects[count] valueForKeyPath:aKeyPath])
{
[[self selectedItem] setState:CPOffState];
}
}
}
@end
var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
@@ -719,7 +744,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
// Nothing is currently selected
@@ -728,7 +753,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
[self setMenu:[aCoder decodeObjectForKey:CPPopUpButtonMenuKey]];
[self selectItemAtIndex:[aCoder decodeObjectForKey:CPPopUpButtonSelectedIndexKey]];
}
return self;
}
@@ -740,7 +765,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_menu forKey:CPPopUpButtonMenuKey];
[aCoder encodeInt:_selectedIndex forKey:CPPopUpButtonSelectedIndexKey];
}
+35 -46
View File
@@ -20,11 +20,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CGGeometry.j>
@import <AppKit/CPImageView.j>
@import <AppKit/CPView.j>
#include "CoreGraphics/CGGeometry.h"
@import "CGGeometry.j"
@import "CPImageView.j"
@import "CPView.j"
/*
@@ -104,17 +102,14 @@ var CPProgressIndicatorSpinningStyleColors = nil,
for (; start <= end; ++start)
{
CPProgressIndicatorBezelBorderViewPool[start] = [];
CPProgressIndicatorBezelBorderViewPool[start][CPMiniControlSize] = [];
CPProgressIndicatorBezelBorderViewPool[start][CPSmallControlSize] = [];
CPProgressIndicatorBezelBorderViewPool[start][CPRegularControlSize] = [];
}
CPProgressIndicatorClassName = [self className];
CPProgressIndicatorStyleIdentifiers = [];
CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle] = @"Bar";
CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorSpinningStyle] = @"Spinny";
CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle] = @"HUDBar";
@@ -126,30 +121,20 @@ var CPProgressIndicatorSpinningStyleColors = nil,
CPProgressIndicatorStyleSizes = [];
// Bar Sttyle
var prefix = CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle];
var prefixes = [
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle],
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle]
];
CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
prefix = CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle];
CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = _CGSizeMake(1.0, 9.0);
CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = _CGSizeMake(1.0, 9.0);
CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = _CGSizeMake(1.0, 9.0);
// HUD Bar Style
prefix = CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle];
CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)];
prefix = CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle];
CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = _CGSizeMake(1.0, 9.0);
CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = _CGSizeMake(1.0, 9.0);
CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = _CGSizeMake(1.0, 9.0);
for (var i = 0, count = prefixes.length; i<count; i++)
{
var prefix = prefixes[i];
CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(3.0, 16.0), _CGSizeMake(1.0, 16.0), _CGSizeMake(3.0, 16.0)];
CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = [_CGSizeMake(3.0, 16.0), _CGSizeMake(1.0, 16.0), _CGSizeMake(3.0, 16.0)];
CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = [_CGSizeMake(3.0, 16.0), _CGSizeMake(1.0, 16.0), _CGSizeMake(3.0, 16.0)];
}
}
- (id)initWithFrame:(CGRect)aFrame
@@ -205,7 +190,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
/*!
Always returns <code>NO</code>. Cappuccino does not have multiple threads.
Always returns \c NO. Cappuccino does not have multiple threads.
*/
- (BOOL)usesThreadedAnimation
{
@@ -329,7 +314,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
/*!
Specifies whether this progress indicator should be indeterminate or display progress based on it's max and min.
@param isDeterminate <code>YES</code> makes the indicator indeterminate
@param isDeterminate \c YES makes the indicator indeterminate
*/
- (void)setIndeterminate:(BOOL)isIndeterminate
{
@@ -342,7 +327,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
/*!
Returns <code>YES</code> if the progress bar is indeterminate.
Returns \c YES if the progress bar is indeterminate.
*/
- (BOOL)isIndeterminate
{
@@ -377,9 +362,9 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
/*!
Sets whether the indicator should be displayed when it isn't animating. By default this is <code>YES</code> if the style
is CPProgressIndicatorBarStyle, and <code>NO</code> if it's CPProgressIndicatorSpinningStyle.
@param isDisplayedWhenStopped <code>YES</code> means the indicator will be displayed when it's not animating.
Sets whether the indicator should be displayed when it isn't animating. By default this is \c YES if the style
is CPProgressIndicatorBarStyle, and \c NO if it's CPProgressIndicatorSpinningStyle.
@param isDisplayedWhenStopped \c YES means the indicator will be displayed when it's not animating.
*/
- (void)setDisplayedWhenStopped:(BOOL)isDisplayedWhenStopped
{
@@ -394,7 +379,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
}
/*!
Returns <code>YES</code> if the progress bar is displayed when not animating.
Returns \c YES if the progress bar is displayed when not animating.
*/
- (BOOL)isDisplayedWhenStopped
{
@@ -428,21 +413,25 @@ var CPProgressIndicatorSpinningStyleColors = nil,
if (!_barView)
{
_barView = [[CPView alloc] initWithFrame:CGRectMake(2.0, 2.0, 0.0, 9.0)];
[_barView setBackgroundColor:[CPColor redColor]];
_barView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 16.0)];
[self addSubview:_barView];
}
[_barView setBackgroundColor:_CPControlColorWithPatternImage(
[_barView setBackgroundColor:_CPControlThreePartImagePattern(
NO,
CPProgressIndicatorStyleSizes,
CPProgressIndicatorClassName,
@"Bar",
CPProgressIndicatorStyleIdentifiers[_style],
_CPControlIdentifierForControlSize(_controlSize))];
[_barView setFrameSize:CGSizeMake(CGRectGetWidth([self bounds]) * (_doubleValue - _minValue) / (_maxValue - _minValue) - 4.0, 9.0)];
var width = CGRectGetWidth([self bounds]),
barWidth = width * ((_doubleValue - _minValue) / (_maxValue - _minValue));
if (barWidth > 0.0 && barWidth < 4.0)
barWidth = 4.0;
[_barView setFrameSize:CGSizeMake(barWidth, 16.0)];
}
/* @ignore */
+26 -17
View File
@@ -25,28 +25,29 @@
@import "CPButton.j"
/*!
@ingroup appkit
from this mailing list thread:
http://groups.google.com/group/objectivej/browse_thread/thread/7c41cbd9cbee9ea3
http://groups.google.com/group/objectivej/browse_thread/thread/7c41cbd9cbee9ea3
-----------------------------------
Creating a checkbox is easy enough:
checkbox = [[CPCheckBox alloc] initWithFrame:aFrame];
That's basically all there is to it. Radio buttons are very similar,
the key difference is the introduction of a new class CPRadioGroup,
which defines which radio buttons are part of the same group:
[myRadioButton setRadioGroup:aRadioGroup];
Every radio button receives a unique radio group by default (so if you
do nothing further, they will all behave independently), but you can
use an existing radio button's group with other buttons as so:
button1 = [[CPRadio alloc] initWithFrame:aFrame];
...
button2 = [[CPRadio alloc] initWithFrame:aFrame radioGroup:[button1
@@ -55,13 +56,16 @@
button3 = [[CPRadio alloc] initWithFrame:aFrame radioGroup:[button1
radioGroup]];
...etc...
Here, all the radio buttons will act "together". [[button1 radioGroup]
allRadios] returns every button that's part of this group, and
[[button1 radioGroup] selectedRadio] returns the currently selected
option.
*/
CPRadioImageOffset = 4.0;
@implementation CPRadio : CPButton
{
CPRadioGroup _radioGroup;
@@ -86,7 +90,7 @@
return button;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return @"radio";
}
@@ -95,10 +99,10 @@
- (id)initWithFrame:(CGRect)aFrame radioGroup:(CPRadioGroup)aRadioGroup
{
self = [super initWithFrame:aFrame];
if (self)
{
[self setRadioGroup:aRadioGroup || [CPRadioGroup new]];
[self setRadioGroup:aRadioGroup];
[self setHighlightsBy:CPContentsCellMask];
[self setShowsStateBy:CPContentsCellMask];
@@ -109,13 +113,13 @@
[self setBordered:YES];
}
return self;
return self;
}
- (id)initWithFrame:(CGRect)aFrame
{
return [self initWithFrame:aFrame radioGroup:nil];
return [self initWithFrame:aFrame radioGroup:[CPRadioGroup new]];
}
- (CPInteger)nextState
@@ -141,7 +145,7 @@
- (void)setObjectValue:(id)aValue
{
[super setObjectValue:aValue];
if ([self state] === CPOnState)
[_radioGroup _setSelectedRadio:self];
}
@@ -175,6 +179,9 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
{
CPSet _radios;
CPRadio _selectedRadio;
id _target @accessors(property=target);
SEL _action @accessors(property=action);
}
- (id)init
@@ -213,6 +220,8 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
[_selectedRadio setState:CPOffState];
_selectedRadio = aRadio;
[CPApp sendAction:_action to:_target from:self];
}
- (CPRadio)selectedRadio
+80 -67
View File
@@ -23,19 +23,23 @@
@import <Foundation/CPObject.j>
CPDeleteKeyCode = 8;
CPTabKeyCode = 9;
CPReturnKeyCode = 13;
CPEscapeKeyCode = 27;
CPLeftArrowKeyCode = 37;
CPUpArrowKeyCode = 38;
CPRightArrowKeyCode = 39;
CPDownArrowKeyCode = 40;
CPDeleteKeyCode = 8;
CPTabKeyCode = 9;
CPReturnKeyCode = 13;
CPEscapeKeyCode = 27;
CPSpaceKeyCode = 32;
CPPageUpKeyCode = 33;
CPPageDownKeyCode = 34;
CPLeftArrowKeyCode = 37;
CPUpArrowKeyCode = 38;
CPRightArrowKeyCode = 39;
CPDownArrowKeyCode = 40;
CPDeleteForwardKeyCode = 46;
/*!
@ingroup appkit
@class CPResponder
Subclasses of CPResonder can be part of the responder chain.
*/
@implementation CPResponder : CPObject
@@ -46,7 +50,7 @@ CPDownArrowKeyCode = 40;
// Changing the first responder
/*!
Returns <code>YES</code> if the receiver is able to become the first responder. <code>NO</code> otherwise.
Returns \c YES if the receiver is able to become the first responder. \c NO otherwise.
*/
- (BOOL)acceptsFirstResponder
{
@@ -55,8 +59,8 @@ CPDownArrowKeyCode = 40;
/*!
Notifies the receiver that it will become the first responder. The receiver can reject first
responder if it returns <code>NO</code>. The default implementation always returns <code>YES</code>.
@return <code>YES</code> if the receiver accepts first responder status.
responder if it returns \c NO. The default implementation always returns \c YES.
@return \c YES if the receiver accepts first responder status.
*/
- (BOOL)becomeFirstResponder
{
@@ -65,7 +69,7 @@ CPDownArrowKeyCode = 40;
/*!
Notifies the receiver that it has been asked to give up first responder status.
@return <code>YES</code> if the receiver is willing to give up first responder status.
@return \c YES if the receiver is willing to give up first responder status.
*/
- (BOOL)resignFirstResponder
{
@@ -96,41 +100,29 @@ CPDownArrowKeyCode = 40;
*/
- (void)interpretKeyEvents:(CPArray)events
{
var event,
index = 0;
while(event = events[index++])
var index = 0,
count = [events count];
for (; index < count; ++index)
{
switch([event keyCode])
var event = events[index],
modifierFlags = [event modifierFlags],
character = [event charactersIgnoringModifiers],
selectorNames = [CPKeyBinding selectorsForKey:character modifierFlags:modifierFlags];
if (selectorNames)
{
case CPLeftArrowKeyCode: [self moveBackward:self];
break;
case CPRightArrowKeyCode: [self moveForward:self];
break;
case CPUpArrowKeyCode: [self moveUp:self];
break;
case CPDownArrowKeyCode: [self moveDown:self];
break;
case CPDeleteKeyCode: [self deleteBackward:self];
break;
case CPReturnKeyCode:
case 3: [self insertLineBreak:self];
break;
case CPEscapeKeyCode: [self cancel:self];
break;
for (var s = 0, scount = selectorNames.length; s < scount; s++)
{
var selector = selectorNames[s];
if (!selector)
continue;
case CPTabKeyCode: var shift = [event modifierFlags] & CPShiftKeyMask;
if (!shift)
[self insertTab:self];
else
[self insertBackTab:self];
break;
default: [self insertText:[event characters]];
[self doCommandBySelector:CPSelectorFromString(selector)];
}
}
else if (!(modifierFlags & (CPCommandKeyMask | CPControlKeyMask)) && [self respondsToSelector:@selector(insertText:)])
[self insertText:[event characters]];
}
}
@@ -143,6 +135,15 @@ CPDownArrowKeyCode = 40;
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the user has clicked the right mouse down in its area.
@param anEvent contains information about the right click
*/
- (void)rightMouseDown:(CPEvent)anEvent
{
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the user has initiated a drag
over it. A drag is a mouse movement while the left button is down.
@@ -162,6 +163,15 @@ CPDownArrowKeyCode = 40;
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the user has released the right mouse button.
@param anEvent contains information about the release
*/
- (void)rightMouseUp:(CPEvent)anEvent
{
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the user has moved the mouse (with no buttons down).
@param anEvent contains information about the movement
@@ -212,11 +222,20 @@ CPDownArrowKeyCode = 40;
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the user has pressed or released a modifier key (Shift, Control, and so on).
@param anEvent information about the key press
*/
- (void)flagsChanged:(CPEvent)anEvent
{
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*
FIXME This description is bad.
Based on <code>anEvent</code>, the receiver should simulate the event.
Based on \c anEvent, the receiver should simulate the event.
@param anEvent the event to simulate
@return <code>YES</code> if the event receiver simulated the event
@return \c YES if the event receiver simulated the event
*/
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
{
@@ -224,14 +243,6 @@ CPDownArrowKeyCode = 40;
}
// Action Methods
/*!
Deletes one character backward, or the selection if anything is selected.
@param aSender the object requesting this
*/
- (void)deleteBackward:(id)aSender
{
}
/*!
Insert a line break at the caret position or selection.
@param aSender the object requesting this
@@ -247,11 +258,7 @@ CPDownArrowKeyCode = 40;
*/
- (void)insertNewline:(id)aSender
{
[self insertNewline:aSender];
}
- (void)cancel:(id)sender
{
[[self nextResponder] insertNewline:aSender];
}
- (void)insertTab:(id)sender
@@ -273,12 +280,12 @@ CPDownArrowKeyCode = 40;
// Dispatch methods
/*!
The receiver will attempt to perform the command,
if it responds to it. If not, the <code>nextResponder</code> will be called to do it.
if it responds to it. If not, the \c -nextResponder will be called to do it.
@param aSelector the command to attempt
*/
- (void)doCommandBySelector:(SEL)aSelector
{
if([self respondsToSelector:aSelector])
if ([self respondsToSelector:aSelector])
[self performSelector:aSelector];
else
[_nextResponder doCommandBySelector:aSelector];
@@ -288,15 +295,15 @@ CPDownArrowKeyCode = 40;
The receiver will attempt to perform the command, or pass it on to the next responder if it doesn't respond to it.
@param aSelector the command to perform
@param anObject the argument to the method
@return <code>YES</code> if the receiver was able to perform the command, or a responder down the chain was
@return \c YES if the receiver was able to perform the command, or a responder down the chain was
able to perform the command.
*/
- (BOOL)tryToPerform:(SEL)aSelector with:(id)anObject
{
if([self respondsToSelector:aSelector])
if ([self respondsToSelector:aSelector])
{
[self performSelector:aSelector withObject:anObject];
return YES;
}
@@ -335,7 +342,8 @@ CPDownArrowKeyCode = 40;
@end
var CPResponderNextResponderKey = @"CPResponderNextResponderKey";
var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
CPResponderMenuKey = @"CPResponderMenuKey";
@implementation CPResponder (CPCoding)
@@ -347,10 +355,13 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey";
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_nextResponder = [aCoder decodeObjectForKey:CPResponderNextResponderKey];
_menu = [aCoder decodeObjectForKey:CPResponderMenuKey];
}
return self;
}
@@ -363,6 +374,8 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey";
// This will come out nil on the other side with decodeObjectForKey:
if (_nextResponder !== nil)
[aCoder encodeConditionalObject:_nextResponder forKey:CPResponderNextResponderKey];
[aCoder encodeObject:_menu forKey:CPResponderMenuKey];
}
@end
+67
View File
@@ -0,0 +1,67 @@
@import "CPPanel.j"
@implementation CPSavePanel : CPPanel
{
CPURL _URL;
BOOL _isExtensionHidden @accessors(getter=isExtensionHidden, setter=setExtensionHidden:);
BOOL _canSelectHiddenExtension @accessors(property=canSelectHiddenExtension);
BOOL _allowsOtherFileTypes @accessors(property=allowsOtherFileTypes);
BOOL _canCreateDirectories @accessors(property=canCreateDirectories);
CPArray _allowedFileTypes @accessors(property=allowedFileTypes);
}
+ (id)savePanel
{
return [[CPSavePanel alloc] init];
}
- (id)init
{
if (self = [super init])
{
_canCreateDirectories = YES;
}
return self;
}
- (CPInteger)runModal
{
// FIXME: Is this correct???
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
if (typeof window["cpSavePanel"] === "function")
{
var resultObject = window.cpSavePanel({
isExtensionHidden: _isExtensionHidden,
canSelectHiddenExtension: _canSelectHiddenExtension,
allowsOtherFileTypes: _allowsOtherFileTypes,
canCreateDirectories: _canCreateDirectories,
allowedFileTypes: _allowedFileTypes
}),
result = resultObject.button;
_URL = result ? [CPURL URLWithString:resultObject.URL] : nil;
}
else
{
// FIXME: This is not the best way to do this.
var documentName = window.prompt("Document Name:"),
result = documentName !== null;
_URL = result ? [[self class] proposedFileURLWithDocumentName:documentName] : nil;
}
return result;
}
- (CPURL)URL
{
return _URL;
}
@end
+18
View File
@@ -0,0 +1,18 @@
@import <Foundation/CPObject.j>
@implementation CPScreen : CPObject
{
}
- (CGRect)visibleFrame
{
#if PLATFORM(DOM)
return _CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight);
#else
return _CGRectMakeZero();
#endif
}
@end
+591 -192
View File
File diff suppressed because it is too large Load Diff
+144 -112
View File
@@ -22,8 +22,6 @@
@import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
// CPScroller Constants
CPScrollerNoPart = 0;
@@ -41,9 +39,9 @@ CPNoScrollerParts = 0;
CPOnlyScrollerArrows = 1;
CPAllScrollerParts = 2;
/*!
/*!
@ingroup appkit
@class CPScroller
@class CPScroller
*/
var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScrollerIncrementLine, CPScrollerKnob],
@@ -64,32 +62,33 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
BOOL _isVertical @accessors(readonly, getter=isVertical);
float _knobProportion;
CPScrollerPart _hitPart;
CPScrollerPart _trackingPart;
float _trackingFloatValue;
CGPoint _trackingStartPoint;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return "scroller";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[ nil, nil, nil, nil,
_CGSizeMakeZero(), _CGSizeMakeZero(), _CGInsetMakeZero(), _CGInsetMakeZero(), _CGSizeMakeZero()]
forKeys:[ @"knob-slot-color",
@"decrement-line-color",
@"increment-line-color",
@"knob-color",
@"decrement-line-size",
@"increment-line-size",
@"track-inset",
@"knob-inset",
@"minimum-knob-length"]];
return [CPDictionary dictionaryWithJSObject:{
@"scroller-width": 15.0,
@"knob-slot-color": [CPColor lightGrayColor],
@"decrement-line-color": [CPNull null],
@"increment-line-color": [CPNull null],
@"knob-color": [CPColor grayColor],
@"decrement-line-size":_CGSizeMakeZero(),
@"increment-line-size":_CGSizeMakeZero(),
@"track-inset":_CGInsetMakeZero(),
@"knob-inset": _CGInsetMakeZero(),
@"minimum-knob-length":21.0
}]
}
@@ -98,17 +97,18 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_controlSize = CPRegularControlSize;
_partRects = [];
[self setFloatValue:0.0 knobProportion:1.0];
[self setFloatValue:0.0];
[self setKnobProportion:1.0];
_hitPart = CPScrollerNoPart;
[self _recalculateIsVertical];
[self _calculateIsVertical];
}
return self;
@@ -120,7 +120,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
*/
+ (float)scrollerWidth
{
return 17.0;//[self scrollerWidthForControlSize:CPRegularControlSize];
return [[[CPScroller alloc] init] currentValueForThemeAttribute:@"scroller-width"];
}
/*!
@@ -129,7 +129,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
*/
+ (float)scrollerWidthForControlSize:(CPControlSize)aControlSize
{
return 17.0;//_CPScrollerWidths[aControlSize];
return [self scrollerWidth];
}
/*!
@@ -155,28 +155,17 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
return _controlSize;
}
// Setting the Knob Position
/*!
Sets the scroller's knob position (ranges from 0.0 to 1.0).
@param aValue the knob position (ranges from 0.0 to 1.0)
*/
- (void)setFloatValue:(float)aValue
- (void)setObjectValue:(id)aValue
{
[super setFloatValue:MIN(1.0, MAX(0.0, aValue))];
[self setNeedsLayout];
[super setObjectValue:MIN(1.0, MAX(0.0, +aValue))];
}
/*!
Sets the position and proportion of the knob.
@param aValue the knob position (ranges from 0.0 to 1.0)
@param aProportion the knob's proportion (ranges from 0.0 to 1.0)
*/
- (void)setFloatValue:(float)aValue knobProportion:(float)aProportion
- (void)setKnobProportion:(float)aProportion
{
_knobProportion = MIN(1.0, MAX(0.0001, aProportion));
[self setFloatValue:aValue];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
/*!
@@ -190,10 +179,10 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (id)currentValueForThemeAttribute:(CPString)anAttributeName
{
var themeState = _themeState;
if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName)
themeState &= ~CPThemeStateHighlighted;
return [self valueForThemeAttribute:anAttributeName inState:themeState];
}
@@ -208,32 +197,32 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
}
/*!
Returns the part of the scroller that would be hit by <code>aPoint</code>.
Returns the part of the scroller that would be hit by \c aPoint.
@param aPoint the simulated point hit
@return the part of the scroller that intersects the point
*/
- (CPScrollerPart)testPart:(CGPoint)aPoint
{
aPoint = [self convertPoint:aPoint fromView:nil];
// The ordering of these tests is important. We check the knob and
// The ordering of these tests is important. We check the knob and
// page rects first since they may overlap with the arrows.
if (CGRectContainsPoint([self rectForPart:CPScrollerKnob], aPoint))
return CPScrollerKnob;
if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementPage], aPoint))
return CPScrollerDecrementPage;
if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementPage], aPoint))
return CPScrollerIncrementPage;
if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementLine], aPoint))
return CPScrollerDecrementLine;
if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementLine], aPoint))
return CPScrollerIncrementLine;
if (CGRectContainsPoint([self rectForPart:CPScrollerKnobSlot], aPoint))
return CPScrollerKnobSlot;
@@ -251,16 +240,16 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
if (_knobProportion === 1.0)
{
_usableParts = CPNoScrollerParts;
_partRects[CPScrollerDecrementPage] = _CGRectMakeZero();
_partRects[CPScrollerKnob] = _CGRectMakeZero();
_partRects[CPScrollerIncrementPage] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementPage] = CGRectMakeZero();
_partRects[CPScrollerKnob] = CGRectMakeZero();
_partRects[CPScrollerIncrementPage] = CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = CGRectMakeZero();
_partRects[CPScrollerIncrementLine] = CGRectMakeZero();
// In this case, the slot is the entirety of the scroller.
_partRects[CPScrollerKnobSlot] = _CGRectMakeCopy(bounds);
_partRects[CPScrollerKnobSlot] = CGRectMakeCopy(bounds);
return;
}
@@ -270,8 +259,8 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
var knobInset = [self currentValueForThemeAttribute:@"knob-inset"],
trackInset = [self currentValueForThemeAttribute:@"track-inset"],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
height = _CGRectGetHeight(bounds);
if ([self isVertical])
{
var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
@@ -289,15 +278,24 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
_partRects[CPScrollerIncrementPage] = _CGRectMake(0.0, knobLocation + knobHeight, width, height - (knobLocation + knobHeight) - effectiveIncrementLineHeight);
_partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotHeight);
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height);
}
_partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height);
if (height < knobHeight + decrementLineSize.height + incrementLineSize.height + trackInset.top + trackInset.bottom)
_partRects[CPScrollerKnob] = _CGRectMakeZero();
if (height < decrementLineSize.height + incrementLineSize.height - 2)
{
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, 0, width - trackInset.left - trackInset.right, height);
}
}
else
{
var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
incrementLineSize = [self currentValueForThemeAttribute:"increment-line-size"],
effectiveDecrementLineWidth = decrementLineSize.width + trackInset.left,
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right;
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right,
slotWidth = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth,
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
knobWidth = MAX(minimumKnobLength, (slotWidth * _knobProportion)),
@@ -310,6 +308,16 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
_partRects[CPScrollerKnobSlot] = _CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotWidth, height - trackInset.top - trackInset.bottom);
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = _CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height);
if (width < knobWidth + decrementLineSize.width + incrementLineSize.width + trackInset.left + trackInset.right)
_partRects[CPScrollerKnob] = _CGRectMakeZero();
if (width < decrementLineSize.width + incrementLineSize.width - 2)
{
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = _CGRectMake(0.0, 0.0, width, slotHeight);
}
}
}
@@ -349,9 +357,9 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (CPView)createViewForPart:(CPScrollerPart)aPart
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
@@ -365,7 +373,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
@@ -379,12 +387,12 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
for (; index < count; ++index)
{
var part = PARTS_ARRANGEMENT[index];
if (index === 0)
view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowBelow relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index + 1]];
else
view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowAbove relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index - 1]];
if (view)
[view setBackgroundColor:[self currentValueForThemeAttribute:NAMES_FOR_PARTS[part] + "-color"]];
}
@@ -394,7 +402,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
Caches images for the scroll arrow and knob.
*/
- (void)drawParts
{
{
[self drawKnobSlot];
[self drawKnob];
[self drawArrow:CPScrollerDecrementArrow highlight:NO];
@@ -417,37 +425,37 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (void)trackKnob:(CPEvent)anEvent
{
var type = [anEvent type];
if (type === CPLeftMouseUp)
{
_hitPart = CPScrollerNoPart;
return;
}
if (type === CPLeftMouseDown)
{
_trackingFloatValue = [self floatValue];
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
}
else if (type === CPLeftMouseDragged)
{
var knobRect = [self rectForPart:CPScrollerKnob],
knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
remainder = ![self isVertical] ? (_CGRectGetWidth(knobSlotRect) - _CGRectGetWidth(knobRect)) : (_CGRectGetHeight(knobSlotRect) - _CGRectGetHeight(knobRect));
if (remainder <= 0)
[self setFloatValue:0.0];
else
{
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
delta = ![self isVertical] ? location.x - _trackingStartPoint.x : location.y - _trackingStartPoint.y;
[self setFloatValue:_trackingFloatValue + delta / remainder];
}
}
[CPApp setTarget:self selector:@selector(trackKnob:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
[self sendAction:[self action] to:[self target]];
@@ -465,26 +473,26 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
{
[self highlight:NO];
[CPEvent stopPeriodicEvents];
_hitPart = CPScrollerNoPart;
return;
}
if (type === CPLeftMouseDown)
{
_trackingPart = [self hitPart];
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if ([anEvent modifierFlags] & CPAlternateKeyMask)
{
if (_trackingPart == CPScrollerDecrementLine)
_hitPart = CPScrollerDecrementPage;
else if (_trackingPart == CPScrollerIncrementLine)
_hitPart = CPScrollerIncrementPage;
else if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage)
{
var knobRect = [self rectForPart:CPScrollerKnob],
@@ -493,55 +501,55 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
remainder = (![self isVertical] ? _CGRectGetWidth(knobSlotRect) : _CGRectGetHeight(knobSlotRect)) - knobWidth;
[self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - _CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - _CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder];
_hitPart = CPScrollerKnob;
[self sendAction:[self action] to:[self target]];
[self sendAction:[self action] to:[self target]];
// Now just track the knob.
return [self trackKnob:anEvent];
}
}
[self highlight:YES];
[self sendAction:[self action] to:[self target]];
[CPEvent startPeriodicEventsAfterDelay:0.5 withPeriod:0.04];
}
else if (type === CPLeftMouseDragged)
{
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage)
{
var hitPart = [self testPart:[anEvent locationInWindow]];
if (hitPart == CPScrollerDecrementPage || hitPart == CPScrollerIncrementPage)
{
_trackingPart = hitPart;
_hitPart = hitPart;
}
}
[self highlight:CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint)];
}
else if (type == CPPeriodic && CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint))
[self sendAction:[self action] to:[self target]];
[CPApp setTarget:self selector:@selector(trackScrollButtons:) forNextEventMatchingMask:CPPeriodicMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (void)_recalculateIsVertical
- (void)_calculateIsVertical
{
// Recalculate isVertical.
var bounds = [self bounds],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
_isVertical = width < height ? 1 : (width > height ? 0 : -1);
if (_isVertical === 1)
[self setThemeState:CPThemeStateVertical];
else if (_isVertical === 0)
@@ -552,8 +560,6 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
{
[super setFrameSize:aSize];
[self _recalculateIsVertical];
[self checkSpaceForParts];
[self setNeedsLayout];
}
@@ -562,15 +568,15 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
{
if (![self isEnabled])
return;
_hitPart = [self testPart:[anEvent locationInWindow]];
switch (_hitPart)
{
case CPScrollerKnob: return [self trackKnob:anEvent];
case CPScrollerDecrementLine:
case CPScrollerIncrementLine:
case CPScrollerDecrementLine:
case CPScrollerIncrementLine:
case CPScrollerDecrementPage:
case CPScrollerIncrementPage: return [self trackScrollButtons:anEvent];
}
@@ -590,29 +596,55 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize",
_controlSize = CPRegularControlSize;
if ([aCoder containsValueForKey:CPScrollerControlSizeKey])
_controlSize = [aCoder decodeIntForKey:CPScrollerControlSizeKey];
_knobProportion = 1.0;
if ([aCoder containsValueForKey:CPScrollerKnobProportionKey])
_knobProportion = [aCoder decodeFloatForKey:CPScrollerKnobProportionKey];
_partRects = [];
_hitPart = CPScrollerNoPart;
[self _recalculateIsVertical];
// [self checkSpaceForParts];
// [self setNeedsLayout];
[self _calculateIsVertical];
// Adjust the size of the scroller if the size from cib
// isn't equal to the scrollerWidth
var frame = [self frame],
scrollerWidth = [CPScroller scrollerWidth];
if ([self isVertical] && CGRectGetWidth(frame) !== scrollerWidth)
frame.size.width = scrollerWidth;
if (![self isVertical] && CGRectGetHeight(frame) !== scrollerWidth)
frame.size.height = scrollerWidth;
[self setFrame:frame];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeInt:_controlSize forKey:CPScrollerControlSizeKey];
[aCoder encodeFloat:_knobProportion forKey:CPScrollerKnobProportionKey];
}
@end
@implementation CPScroller (Deprecated)
/*!
Sets the position and proportion of the knob.
@param aValue the knob position (ranges from 0.0 to 1.0)
@param aProportion the knob's proportion (ranges from 0.0 to 1.0)
*/
- (void)setFloatValue:(float)aValue knobProportion:(float)aProportion
{
[self setFloatValue:aValue];
[self setKnobProportion:aProportion];
}
@end
+821
View File
@@ -0,0 +1,821 @@
/*
* CPSearchField.j
* AppKit
*
* Created by cacaodev.
* Copyright 2009.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPButton.j"
@import "CPTextField.j"
CPSearchFieldRecentsTitleMenuItemTag = 1000;
CPSearchFieldRecentsMenuItemTag = 1001;
CPSearchFieldClearRecentsMenuItemTag = 1002;
CPSearchFieldNoRecentsMenuItemTag = 1003;
CPSearchFieldSeparatorMenuItemTag = 1004;
var CPSearchFieldSearchImage = nil,
CPSearchFieldFindImage = nil,
CPSearchFieldCancelImage = nil,
CPSearchFieldCancelPressedImage = nil;
var SEARCH_BUTTON_DEFAULT_WIDTH = 25.0,
CANCEL_BUTTON_DEFAULT_WIDTH = 22.0,
BUTTON_DEFAULT_HEIGHT = 22.0;
var RECENT_SEARCH_PREFIX = @" ";
/*!
@ingroup appkit
@class CPSearchField
The CPSearchField class defines the programmatic interface for text fields that are optimized for text-based searches. A CPSearchField object directly inherits from the CPTextField class. The search field implemented by these classes presents a standard user interface for searches, including a search button, a cancel button, and a pop-up icon menu for listing recent search strings and custom search categories.
When the user types and then pauses, the text field's action message is sent to its target. You can query the text field's string value for the current text to search for. Do not rely on the sender of the action to be an CPMenu object because the menu may change. If you need to change the menu, modify the search menu template and call the setSearchMenuTemplate: method to update.
*/
@implementation CPSearchField : CPTextField
{
CPButton _searchButton;
CPButton _cancelButton;
CPMenu _searchMenuTemplate;
CPMenu _searchMenu;
CPString _recentsAutosaveName;
CPArray _recentSearches;
int _maximumRecents;
BOOL _sendsWholeSearchString;
BOOL _sendsSearchStringImmediately;
BOOL _canResignFirstResponder;
CPTimer _partialStringTimer;
}
+ (CPString)defaultThemeClass
{
return @"searchfield"
}
+ (void)initialize
{
if (self != [CPSearchField class])
return;
var bundle = [CPBundle bundleForClass:self];
CPSearchFieldSearchImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldSearch.png"] size:_CGSizeMake(SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
CPSearchFieldFindImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldFind.png"] size:_CGSizeMake(SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"] size:_CGSizeMake(CANCEL_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"] size:_CGSizeMake(CANCEL_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
}
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
_maximumRecents = 10;
_sendsWholeSearchString = NO;
_sendsSearchStringImmediately = NO;
_recentsAutosaveName = nil;
[self _init];
#if PLATFORM(DOM)
_cancelButton._DOMElement.style.cursor = "default";
_searchButton._DOMElement.style.cursor = "default";
#endif
}
return self;
}
- (void)_init
{
_recentSearches = [CPArray array];
[self setBezeled:YES];
[self setBezelStyle:CPTextFieldRoundedBezel];
[self setBordered:YES];
[self setEditable:YES];
[self setDelegate:self];
[self setContinuous:YES];
var bounds = [self bounds],
cancelButton = [[CPButton alloc] initWithFrame:[self cancelButtonRectForBounds:bounds]],
searchButton = [[CPButton alloc] initWithFrame:[self searchButtonRectForBounds:bounds]];
[self setCancelButton:cancelButton];
[self resetCancelButton];
[self setSearchButton:searchButton];
[self resetSearchButton];
_canResignFirstResponder = YES;
}
// Managing Buttons
/*!
Sets the button used to display the search-button image
@param button The search button.
*/
- (void)setSearchButton:(CPButton)button
{
if (button != _searchButton)
{
[_searchButton removeFromSuperview];
_searchButton = button;
[_searchButton setFrame:[self searchButtonRectForBounds:[self bounds]]];
[_searchButton setAutoresizingMask:CPViewMaxXMargin];
[self addSubview:_searchButton];
}
}
/*!
Returns the button used to display the search-button image.
@return The search button.
*/
- (CPButton)searchButton
{
return _searchButton;
}
/*!
Resets the search button to its default attributes.
This method resets the target, action, regular image, and pressed image. By default, when users click the search button or press the Return key, the action defined for the receiver is sent to its designated target. This method gives you a way to customize the search button for specific situations and then reset the button defaults without having to undo changes individually.
*/
- (void)resetSearchButton
{
var button = [self searchButton],
searchButtonImage = (_searchMenuTemplate === nil) ? CPSearchFieldSearchImage : CPSearchFieldFindImage;
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImage:searchButtonImage];
[button setAutoresizingMask:CPViewMaxXMargin];
}
/*!
Sets the button object used to display the cancel-button image.
@param button The cancel button.
*/
- (void)setCancelButton:(CPButton)button
{
if (button != _cancelButton)
{
[_cancelButton removeFromSuperview];
_cancelButton = button;
[_cancelButton setFrame:[self cancelButtonRectForBounds:[self bounds]]];
[_cancelButton setAutoresizingMask:CPViewMinXMargin];
[_cancelButton setTarget:self];
[_cancelButton setAction:@selector(_searchFieldCancel:)];
[self _updateCancelButtonVisibility];
[self addSubview:_cancelButton];
}
}
/*!
Returns the button object used to display the cancel-button image.
@return The cancel button.
*/
- (CPButton)cancelButton
{
return _cancelButton;
}
/*!
Resets the cancel button to its default attributes.
This method resets the target, action, regular image, and pressed image. By default, when users click the cancel button, the delete: action message is sent up the responder chain. This method gives you a way to customize the cancel button for specific situations and then reset the button defaults without having to undo changes individually.
*/
- (void)resetCancelButton
{
var button = [self cancelButton];
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImage:CPSearchFieldCancelImage];
[button setAlternateImage:CPSearchFieldCancelPressedImage];
[button setAutoresizingMask:CPViewMinXMargin];
[button setTarget:self];
[button setAction:@selector(_searchFieldCancel:)];
}
// Custom Layout
/*!
Modifies the bounding rectangle for the search-text field.
@param rect The current bounding rectangle for the search text field.
@return The updated bounding rectangle to use for the search text field. The default value is the value passed into the rect parameter.
Subclasses can override this method to return a new bounding rectangle for the text-field object. You might use this method to provide a custom layout for the search field control.
*/
- (CGRect)searchTextRectForBounds:(CGRect)rect
{
var leftOffset = 0,
width = _CGRectGetWidth(rect),
bounds = [self bounds];
if (_searchButton)
{
var searchBounds = [self searchButtonRectForBounds:bounds];
leftOffset = _CGRectGetMaxX(searchBounds) + 2;
}
if (_cancelButton)
{
var cancelRect = [self cancelButtonRectForBounds:bounds];
width = _CGRectGetMinX(cancelRect) - leftOffset;
}
return _CGRectMake(leftOffset, _CGRectGetMinY(rect), width, _CGRectGetHeight(rect));
}
/*!
Modifies the bounding rectangle for the search button.
@param rect The current bounding rectangle for the search button.
Subclasses can override this method to return a new bounding rectangle for the search button. You might use this method to provide a custom layout for the search field control.
*/
- (CGRect)searchButtonRectForBounds:(CGRect)rect
{
return _CGRectMake(5, (_CGRectGetHeight(rect) - BUTTON_DEFAULT_HEIGHT) / 2, SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT);
}
/*!
Modifies the bounding rectangle for the cancel button.
@param rect The updated bounding rectangle to use for the cancel button. The default value is the value passed into the rect parameter.
Subclasses can override this method to return a new bounding rectangle for the cancel button. You might use this method to provide a custom layout for the search field control.
*/
- (CGRect)cancelButtonRectForBounds:(CGRect)rect
{
return _CGRectMake(_CGRectGetWidth(rect) - CANCEL_BUTTON_DEFAULT_WIDTH - 5, (_CGRectGetHeight(rect) - CANCEL_BUTTON_DEFAULT_WIDTH) / 2, BUTTON_DEFAULT_HEIGHT, BUTTON_DEFAULT_HEIGHT);
}
// Managing Menu Templates
/*!
Returns the menu template object used to dynamically construct the search pop-up icon menu.
@return The current menu template.
*/
- (CPMenu)searchMenuTemplate
{
return _searchMenuTemplate;
}
/*!
Sets the menu template object used to dynamically construct the receiver's pop-up icon menu.
@param menu The menu template to use.
The receiver looks for the tag constants described in ŇMenu tagsÓ to determine how to populate the menu with items related to recent searches. See ŇConfiguring a Search MenuÓ for a sample of how you might set up the search menu template.
*/
- (void)setSearchMenuTemplate:(CPMenu)aMenu
{
_searchMenuTemplate = aMenu;
[self resetSearchButton];
[self _loadRecentSearchList];
[self _updateSearchMenu];
}
// Managing Search Modes
/*!
Returns a Boolean value indicating whether the receiver sends the search action message when the user clicks the search button (or presses return) or after each keystroke.
@return \c YES if the action message is sent all at once when the user clicks the search button or presses return; otherwise, NO if the search string is sent after each keystroke. The default value is NO.
*/
- (BOOL)sendsWholeSearchString
{
return _sendsWholeSearchString;
}
/*!
Sets whether the receiver sends the search action message when the user clicks the search button (or presses return) or after each keystroke.
@param flag \c YES to send the action message all at once when the user clicks the search button or presses return; otherwise, NO to send the search string after each keystroke.
*/
- (void)setSendsWholeSearchString:(BOOL)flag
{
_sendsWholeSearchString = flag;
}
/*!
Returns a Boolean value indicating whether the receiver sends its action immediately upon being notified of changes to the search field text or after a brief pause.
@return \c YES if the text field sends its action immediately upon notification of any changes to the search field; otherwise, NO.
*/
- (BOOL)sendsSearchStringImmediately
{
return _sendsSearchStringImmediately;
}
/*!
Sets whether the text field sends its action message to the target immediately upon notification of any changes to the search field text or after a brief pause.
@param flag \c YES to send the text field's action immediately upon notification of any changes to the search field; otherwise, NO if you want the text field to pause briefly before sending its action message. Pausing gives the user the opportunity to type more text into the search field before initiating the search.
*/
- (void)setSendsSearchStringImmediately:(BOOL)flag
{
_sendsSearchStringImmediately = flag;
}
// Managing Recent Search Strings
/*!
Returns the maximum number of recent search strings to display in the custom search menu.
@return The maximum number of search strings that can appear in the menu. This value is between 0 and 254.
*/
- (int)maximumRecents
{
return _maximumRecents;
}
/*!
Sets the maximum number of search strings that can appear in the search menu.
@param maxRecents The maximum number of search strings that can appear in the menu. This value can be between 0 and 254. Specifying a value less than 0 sets the value to the default, which is 10. Specifying a value greater than 254 sets the maximum to 254.
*/
- (void)setMaximumRecents:(int)max
{
if (max > 254)
max = 254;
else if (max < 0)
max = 10;
_maximumRecents = max;
}
/*!
Returns the list of recent search strings for the control.
@return An array of \c CPString objects, each of which contains a search string either displayed in the search menu or from a recent autosave archive. If there have been no recent searches and no prior searches saved under an autosave name, this array may be empty.
*/
- (CPArray)recentSearches
{
return _recentSearches;
}
/*!
Sets the list of recent search strings to list in the pop-up icon menu of the receiver.
@param searches An array of CPString objects containing the search strings.
You might use this method to set the recent list of searches from an archived copy.
*/
- (void)setRecentSearches:(CPArray)searches
{
var max = MIN([self maximumRecents], [searches count]),
searches = [searches subarrayWithRange:CPMakeRange(0, max)];
_recentSearches = searches;
[self _autosaveRecentSearchList];
}
/*!
Returns the key under which the prior list of recent search strings has been archived.
@return The autosave name, which is used as a key in the standard user defaults to save the recent searches. The default value is nil, which causes searches not to be autosaved.
*/
- (CPString)recentsAutosaveName
{
return _recentsAutosaveName;
}
/*!
Sets the autosave name under which the receiver automatically archives the list of recent search strings.
@param name The autosave name, which is used as a key in the standard user defaults to save the recent searches. If you specify nil or an empty string for this parameter, no autosave name is set and searches are not autosaved.
*/
- (void)setRecentsAutosaveName:(CPString)name
{
if (_recentsAutosaveName != nil)
[self _deregisterForAutosaveNotification];
_recentsAutosaveName = name;
if (_recentsAutosaveName != nil)
[self _registerForAutosaveNotification];
}
// Private methods and subclassing
- (CGRect)contentRectForBounds:(CGRect)bounds
{
var superbounds = [super contentRectForBounds:bounds];
return [self searchTextRectForBounds:superbounds];
}
+ (double)_keyboardDelayForPartialSearchString:(CPString)string
{
return (6 - MIN([string length],4))/10;
}
- (CPMenu)menu
{
return _searchMenu;
}
- (BOOL)isOpaque
{
return [super isOpaque] && [_cancelButton isOpaque] && [_searchButton isOpaque];
}
- (void)_updateCancelButtonVisibility
{
[_cancelButton setHidden:([[self stringValue] length] === 0)];
}
- (void)controlTextDidChange:(CPNotification)aNotification
{
if (![self sendsWholeSearchString])
{
if ([self sendsSearchStringImmediately])
[self _sendPartialString];
else
{
[_partialStringTimer invalidate];
var timeInterval = [CPSearchField _keyboardDelayForPartialSearchString:[self stringValue]];
_partialStringTimer = [CPTimer scheduledTimerWithTimeInterval:timeInterval
target:self
selector:@selector(_sendPartialString)
userInfo:nil
repeats:NO];
}
}
[self _updateCancelButtonVisibility];
}
- (void)_sendAction:(id)sender
{
[self sendAction:[self action] to:[self target]];
}
- (void)sendAction:(SEL)anAction to:(id)anObject
{
[super sendAction:anAction to:anObject];
[_partialStringTimer invalidate];
[self _addStringToRecentSearches:[self stringValue]];
[self _updateCancelButtonVisibility];
}
- (void)_addStringToRecentSearches:(CPString)string
{
if (string === nil || string === @"" || [_recentSearches containsObject:string])
return;
var searches = [CPMutableArray arrayWithArray:_recentSearches];
[searches addObject:string];
[self setRecentSearches:searches];
[self _updateSearchMenu];
}
- (CPView)hitTest:(CGPoint)aPoint
{
// Make sure a hit anywhere within the search field returns the search field itself
if (_CGRectContainsPoint([self frame], aPoint))
return self;
else
return nil;
}
- (BOOL)resignFirstResponder
{
return _canResignFirstResponder && [super resignFirstResponder];
}
- (void)mouseDown:(CPEvent)anEvent
{
var location = [anEvent locationInWindow],
point = [self convertPoint:location fromView:nil];
if (_CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point))
{
if (_searchMenuTemplate == nil)
[self _sendAction:self];
else
[self _showMenu];
}
else if (_CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point))
[_cancelButton mouseDown:anEvent];
else
[super mouseDown:anEvent];
}
/*!
Provides the common case items for a recent searches menu. If there are not recent searches,
displays a single disabled item:
No Recent Searches
If there are 1 more recent searches, it displays:
Recent Searches
recent search 1
recent search 2
etc.
---------------------
Clear Recent Searches
If you wish to add items before or after the template, you can. If you put items
before, a separator will automatically be placed before the default template item.
If you add items after the default template, it is your responsibility to add a separator.
To add a custom item:
item = [[CPMenuItem alloc] initWithTitle:@"google"
action:@selector(google:)
keyEquivalent:@""];
[item setTag:700];
[item setTarget:self];
[template addItem:item];
Be sure that your custom items do not use tags in the range 1000-1004 inclusive.
If you wish to maintain state in custom menu items that you add, you will need to maintain
the item state yourself, then in the action method of the custom items, modify the items
in the search menu template and send [searchField setSearchMenuTemplate:template] to update the menu.
*/
- (CPMenu)defaultSearchMenuTemplate
{
var template = [[CPMenu alloc] init],
item;
item = [[CPMenuItem alloc] initWithTitle:@"Recent Searches"
action:nil
keyEquivalent:@""];
[item setTag:CPSearchFieldRecentsTitleMenuItemTag];
[item setEnabled:NO];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"Recent search item"
action:@selector(_searchFieldSearch:)
keyEquivalent:@""];
[item setTag:CPSearchFieldRecentsMenuItemTag];
[item setTarget:self];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"Clear Recent Searches"
action:@selector(_searchFieldClearRecents:)
keyEquivalent:@""];
[item setTag:CPSearchFieldClearRecentsMenuItemTag];
[item setTarget:self];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"No Recent Searches"
action:nil
keyEquivalent:@""];
[item setTag:CPSearchFieldNoRecentsMenuItemTag];
[item setEnabled:NO];
[template addItem:item];
return template;
}
- (void)_updateSearchMenu
{
if (_searchMenuTemplate === nil)
return;
var menu = [[CPMenu alloc] init],
countOfRecents = [_recentSearches count],
numberOfItems = [_searchMenuTemplate numberOfItems];
for (var i = 0; i < numberOfItems; i++)
{
var item = [[_searchMenuTemplate itemAtIndex:i] copy];
switch ([item tag])
{
case CPSearchFieldRecentsTitleMenuItemTag:
if (countOfRecents === 0)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
break;
case CPSearchFieldRecentsMenuItemTag:
{
var itemAction = @selector(_searchFieldSearch:);
for (var recentIndex = 0; recentIndex < countOfRecents; ++recentIndex)
{
// RECENT_SEARCH_PREFIX is a hack until CPMenuItem -setIndentationLevel works
var recentItem = [[CPMenuItem alloc] initWithTitle:RECENT_SEARCH_PREFIX + [_recentSearches objectAtIndex:recentIndex]
action:itemAction
keyEquivalent:[item keyEquivalent]];
[item setTarget:self];
[menu addItem:recentItem];
}
continue;
}
case CPSearchFieldClearRecentsMenuItemTag:
if (countOfRecents === 0)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
[item setAction:@selector(_searchFieldClearRecents:)];
[item setTarget:self];
break;
case CPSearchFieldNoRecentsMenuItemTag:
if (countOfRecents !== 0)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
break;
case CPSearchFieldSeparatorMenuItemTag:
item = [CPMenuItem separatorItem];
[item setEnabled:NO];
[menu addItem:item];
continue;
}
[item setEnabled:([item isEnabled] && [item action] != nil && [item target] != nil)];
[menu addItem:item];
}
[menu setDelegate:self];
_searchMenu = menu;
}
- (void)_addSeparatorToMenu:(CPMenu)aMenu
{
var separator = [CPMenuItem separatorItem];
[separator setEnabled:NO];
[aMenu addItem:separator];
}
- (void)menuWillOpen:(CPMenu)menu
{
_canResignFirstResponder = NO;
}
- (void)menuDidClose:(CPMenu)menu
{
_canResignFirstResponder = YES;
[self becomeFirstResponder];
}
- (void)_showMenu
{
if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled])
return;
var aFrame = [[self superview] convertRect:[self frame] toView:nil],
location = CPMakePoint(aFrame.origin.x + 10, aFrame.origin.y + aFrame.size.height - 4);
var anEvent = [CPEvent mouseEventWithType:CPRightMouseDown location:location modifierFlags:0 timestamp:[[CPApp currentEvent] timestamp] windowNumber:[[self window] windowNumber] context:nil eventNumber:1 clickCount:1 pressure:0];
[self selectAll:nil];
[CPMenu popUpContextMenu:_searchMenu withEvent:anEvent forView:self];
}
- (void)_sendPartialString
{
[super sendAction:[self action] to:[self target]];
[_partialStringTimer invalidate];
}
- (void)_searchFieldCancel:(id)sender
{
[self setObjectValue:@""];
[self _sendPartialString];
[self _updateCancelButtonVisibility];
}
- (void)_searchFieldSearch:(id)sender
{
var searchString = [[sender title] substringFromIndex:[RECENT_SEARCH_PREFIX length]];
if ([sender tag] != CPSearchFieldRecentsMenuItemTag)
[self _addStringToRecentSearches:searchString];
[self setObjectValue:searchString];
[self _sendPartialString];
[self selectAll:nil];
[self _updateCancelButtonVisibility];
}
- (void)_searchFieldClearRecents:(id)sender
{
[self setRecentSearches:[CPArray array]];
[self _updateSearchMenu];
[self setStringValue:@""];
[self _updateCancelButtonVisibility];
}
- (void)_registerForAutosaveNotification
{
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_updateAutosavedRecents:) name:@"CPAutosavedRecentsChangedNotification" object:nil];
}
- (void)_deregisterForAutosaveNotification
{
[[CPNotificationCenter defaultCenter] removeObserver:self name:@"CPAutosavedRecentsChangedNotification" object:nil];
}
- (void)_autosaveRecentSearchList
{
if (_recentsAutosaveName != nil)
[[CPNotificationCenter defaultCenter] postNotificationName:@"CPAutosavedRecentsChangedNotification" object:_recentsAutosaveName];
}
- (void)_updateAutosavedRecents:(id)notification
{
var list = [self recentSearches],
name = [notification object],
bundle_name = [[[CPBundle mainBundle] infoDictionary] objectForKey:"CPBundleName"],
cookie_name = [bundle_name lowercaseString] + "." + [notification object],
cookie = [[CPCookie alloc] initWithName:cookie_name],
cookie_value = [list componentsJoinedByString:@","];
[cookie setValue:cookie_value
expires:[[CPDate alloc] initWithTimeIntervalSinceNow:3600*24*365]
domain:(window.location.href.hostname)];
}
- (void)_loadRecentSearchList
{
var list,
name = [self recentsAutosaveName];
if (name === nil)
return;
var bundle_name = [[[CPBundle mainBundle] infoDictionary] objectForKey:"CPBundleName"],
cookie_name = [bundle_name lowercaseString] + "." + name,
cookie = [[CPCookie alloc] initWithName:cookie_name];
if (cookie != nil)
{
var cookie_value = [cookie value];
list = (cookie_value != @"") ? [cookie_value componentsSeparatedByString:@","] : [CPArray array];
_recentSearches = list;
}
}
@end
var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey",
CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey",
CPMaximumRecentsKey = @"CPMaximumRecentsKey",
CPSearchMenuTemplateKey = @"CPSearchMenuTemplateKey";
@implementation CPSearchField (CPCoding)
- (void)encodeWithCoder:(CPCoder)coder
{
[_searchButton removeFromSuperview];
[_cancelButton removeFromSuperview];
[super encodeWithCoder:coder];
if (_searchButton)
[self addSubview:_searchButton];
if (_cancelButton)
[self addSubview:_cancelButton];
[coder encodeBool:_sendsWholeSearchString forKey:CPSendsWholeSearchStringKey];
[coder encodeBool:_sendsSearchStringImmediately forKey:CPSendsSearchStringImmediatelyKey];
[coder encodeInt:_maximumRecents forKey:CPMaximumRecentsKey];
if (_recentsAutosaveName)
[coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey];
if (_searchMenuTemplate)
[coder encodeObject:_searchMenuTemplate forKey:CPSearchMenuTemplateKey];
}
- (id)initWithCoder:(CPCoder)coder
{
if (self = [super initWithCoder:coder])
{
_recentsAutosaveName = [coder decodeObjectForKey:CPRecentsAutosaveNameKey];
_sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey];
_sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey];
_maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey];
var template = [coder decodeObjectForKey:CPSearchMenuTemplateKey];
if (template)
[self setSearchMenuTemplate:template];
[self _init];
}
return self;
}
@end
+1
View File
@@ -1,6 +1,7 @@
@import "CPTextField.j"
/*!
@ingroup appkit
*/
+211 -186
View File
@@ -24,25 +24,12 @@
@import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
/*
@global
@group CPSegmentSwitchTracking
*/
CPSegmentSwitchTrackingSelectOne = 0;
/*
@global
@group CPSegmentSwitchTracking
*/
CPSegmentSwitchTrackingSelectAny = 1;
/*
@global
@group CPSegmentSwitchTracking
*/
CPSegmentSwitchTrackingMomentary = 2;
/*!
/*!
@ingroup appkit
@class CPSegmentedControl
@@ -61,14 +48,14 @@ CPSegmentSwitchTrackingMomentary = 2;
BOOL _trackingHighlighted;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return "segmented-control";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[CPCenterTextAlignment, CPCenterVerticalTextAlignment, CPImageLeft, CPScaleNone, _CGInsetMakeZero(), _CGInsetMakeZero(), nil, nil, nil, nil, 1.0, 24.0]
return [CPDictionary dictionaryWithObjects:[CPCenterTextAlignment, CPCenterVerticalTextAlignment, CPImageLeft, CPScaleNone, _CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], [CPNull null], 1.0, 24.0]
forKeys:[@"alignment", @"vertical-alignment", @"image-position", @"image-scaling", @"bezel-inset", @"content-inset", @"left-segment-bezel-color", @"right-segment-bezel-color", @"center-segment-bezel-color", @"divider-bezel-color", @"divider-thickness", @"default-height"]];
}
@@ -76,16 +63,16 @@ CPSegmentSwitchTrackingMomentary = 2;
{
_segments = [];
_themeStates = [];
self = [super initWithFrame:aRect];
if (self)
{
_selectedSegment = -1;
_trackingMode = CPSegmentSwitchTrackingSelectOne;
}
return self;
}
@@ -94,7 +81,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (int)selectedTag
{
return _segments[_selectedSegment].tag;
return [_segments[_selectedSegment] tag];
}
// Specifying the number of segments
@@ -106,11 +93,11 @@ CPSegmentSwitchTrackingMomentary = 2;
{
if (_segments.length == aCount)
return;
var height = CGRectGetHeight([self bounds]);
if (_segments.length < aCount)
{
{
for (var index = _segments.length; index < aCount; ++index)
{
_segments[index] = [[_CPSegmentItem alloc] init];
@@ -119,13 +106,13 @@ CPSegmentSwitchTrackingMomentary = 2;
}
else if (aCount < _segments.length)
{
for (var index = aCount; index < _segments.length; ++index)
_segments[index] = nil;
_segments.length = aCount;
_themeStates.length = aCount;
}
if (_selectedSegment < _segments.length)
if (_selectedSegment >= _segments.length)
_selectedSegment = -1;
[self tileWithChangedSegment:0];
}
@@ -141,7 +128,7 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Selects a segment.
@param aSegment the segment to select
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setSelectedSegment:(unsigned)aSegment
{
@@ -163,15 +150,15 @@ CPSegmentSwitchTrackingMomentary = 2;
- (BOOL)selectSegmentWithTag:(int)aTag
{
var index = 0;
for (; index < _segments.length; ++index)
if (_segments[index].tag == aTag)
{
[self setSelectedSegment:index];
return YES;
}
return NO;
}
@@ -186,28 +173,28 @@ CPSegmentSwitchTrackingMomentary = 2;
{
if (_trackingMode == aTrackingMode)
return;
_trackingMode = aTrackingMode;
if (_trackingMode == CPSegmentSwitchTrackingSelectOne)
{
var index = 0,
selected = NO;
for (; index < _segments.length; ++index)
if (_segments[index].selected)
if ([_segments[index] selected])
if (selected)
[self setSelected:NO forSegment:index];
else
selected = YES;
}
else if (_trackingMode == CPSegmentSwitchTrackingMomentary)
{
var index = 0;
for (; index < _segments.length; ++index)
if (_segments[index].selected)
if ([_segments[index] selected])
[self setSelected:NO forSegment:index];
}
}
@@ -225,36 +212,34 @@ CPSegmentSwitchTrackingMomentary = 2;
Sets the width of the specified segment.
@param aWidth the new width for the segment
@param aSegment the segment to set the width for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setWidth:(float)aWidth forSegment:(unsigned)aSegment
{
_segments[aSegment].width = aWidth;
[_segments[aSegment] setWidth:aWidth];
[self tileWithChangedSegment:aSegment];
}
/*!
Returns the width for the specified segment.
@param aSegment the segment to get the width for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (float)widthForSegment:(unsigned)aSegment
{
return _segments[aSegment].width;
return [_segments[aSegment] width];
}
/*!
Sets the image for the specified segment.
@param anImage the image for the segment
@param aSegment the segment to set the image on
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setImage:(CPImage)anImage forSegment:(unsigned)aSegment
{
var segment = _segments[aSegment];
segment.image = anImage;
[_segments[aSegment] setImage:anImage];
[self tileWithChangedSegment:aSegment];
}
@@ -262,75 +247,73 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Returns the image for the specified segment
@param aSegment the segment to obtain the image for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (CPImage)imageForSegment:(unsigned)aSegment
{
return _segments[aSegment].image;
return [_segments[aSegment] image];
}
/*!
Sets the label for the specified segment
@param aLabel the label for the segment
@param aSegment the segment to label
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setLabel:(CPString)aLabel forSegment:(unsigned)aSegment
{
var segment = _segments[aSegment];
_segments[aSegment].label = aLabel;
[_segments[aSegment] setLabel:aLabel];
[self tileWithChangedSegment:aSegment];
}
/*!
Returns the label for the specified segment
@param the segment to obtain the label for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (CPString)labelForSegment:(unsigned)aSegment
{
return _segments[aSegment].label;
return [_segments[aSegment] label];
}
/*!
Sets the menu for the specified segment
@param aMenu the menu to set
@param aSegment the segment to set the menu on
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setMenu:(CPMenu)aMenu forSegment:(unsigned)aSegment
{
_segments[aSegment].menu = aMenu;
[_segments[aSegment] setMenu:aMenu];
}
/*!
Returns the menu for the specified segment.
@param aSegment the segment to obtain the menu for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (CPMenu)menuForSegment:(unsigned)aSegment
{
return _segments[aSegment].menu;
return [_segments[aSegment] menu];
}
/*!
Sets the selection for the specified segment. If only one segment
can be selected at a time, any other segment will be deselected.
@param isSelected <code>YES</code> selects the segment. <code>NO</code> deselects it.
@param isSelected \c YES selects the segment. \c NO deselects it.
@param aSegment the segment to set the selection for
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setSelected:(BOOL)isSelected forSegment:(unsigned)aSegment
{
var segment = _segments[aSegment];
// If we're already in this state, bail.
if (segment.selected == isSelected)
if ([segment selected] == isSelected)
return;
segment.selected = isSelected;
[segment setSelected:isSelected];
_themeStates[aSegment] = isSelected ? CPThemeStateSelected : CPThemeStateNormal;
@@ -338,18 +321,18 @@ CPSegmentSwitchTrackingMomentary = 2;
if (isSelected)
{
var oldSelectedSegment = _selectedSegment;
_selectedSegment = aSegment;
if (_trackingMode == CPSegmentSwitchTrackingSelectOne && oldSelectedSegment != aSegment && oldSelectedSegment != -1)
{
_segments[oldSelectedSegment].selected = NO;
[_segments[oldSelectedSegment] setSelected:NO];
_themeStates[oldSelectedSegment] = CPThemeStateNormal;
[self drawSegmentBezel:oldSelectedSegment highlight:NO];
}
}
if (_trackingMode != CPSegmentSwitchTrackingMomentary)
[self drawSegmentBezel:aSegment highlight:NO];
@@ -358,37 +341,42 @@ CPSegmentSwitchTrackingMomentary = 2;
}
/*!
Returns <code>YES</code> if the specified segment is selected.
Returns \c YES if the specified segment is selected.
@param aSegment the segment to check for selection
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (BOOL)isSelectedForSegment:(unsigned)aSegment
{
return _segments[aSegment].selected;
return [_segments[aSegment] selected];
}
/*!
Enables/diables the specified segment.
@param isEnabled <code>YES</code> enables the segment
@param isEnabled \c YES enables the segment
@param aSegment the segment to enable/disble
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setEnabled:(BOOL)isEnabled forSegment:(unsigned)aSegment
{
_segments[aSegment].enabled = isEnabled;
[_segments[aSegment] setEnabled:isEnabled];
if (isEnabled)
_themeStates[aSegment] &= ~CPThemeStateDisabled;
else
_themeStates[aSegment] |= CPThemeStateDisabled;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
/*!
Returns <code>YES</code> if the specified segment is enabled.
Returns \c YES if the specified segment is enabled.
@param aSegment the segment to check
@throws CPRangeException if <code>aSegment</code> is out of bounds
@throws CPRangeException if \c aSegment is out of bounds
*/
- (BOOL)isEnabledForSegment:(unsigned)aSegment
{
return _segments[aSegment].enabled;
return [_segments[aSegment] enabled];
}
/*!
@@ -398,7 +386,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setTag:(int)aTag forSegment:(unsigned)aSegment
{
_segments[aSegment].tag = aTag;
[_segments[aSegment] setTag:aTag];
}
/*!
@@ -407,14 +395,14 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (int)tagForSegment:(unsigned)aSegment
{
return _segments[aSegment].tag;
return [_segments[aSegment] tag];
}
// Drawings
/*!
Draws the specified segment bezel
@param aSegment the segment to draw the bezel for
@param shouldHighlight <code>YES</code> highlights the bezel
@param shouldHighlight \c YES highlights the bezel
*/
- (void)drawSegmentBezel:(int)aSegment highlight:(BOOL)shouldHighlight
{
@@ -439,6 +427,16 @@ CPSegmentSwitchTrackingMomentary = 2;
return [self _leftOffsetForSegment:segment - 1] + [self widthForSegment:segment - 1] + thickness;
}
- (unsigned)_indexOfLastSegment
{
var lastSegmentIndex = [_segments count] - 1;
if (lastSegmentIndex < 0)
lastSegmentIndex = 0;
return lastSegmentIndex;
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
{
var height = [self currentValueForThemeAttribute:@"default-height"],
@@ -452,25 +450,28 @@ CPSegmentSwitchTrackingMomentary = 2;
}
else if (aName === "right-segment-bezel")
{
return CGRectMake(CGRectGetMaxX(bounds) - contentInset.right - bezelInset.right, bezelInset.top, contentInset.right, height);
return CPRectMake(CGRectGetWidth([self bounds]) - contentInset.right,
bezelInset.top,
contentInset.right,
height);
}
else if (aName.substring(0, "segment-bezel".length) == "segment-bezel")
else if (aName.indexOf("segment-bezel") === 0)
{
var segment = parseInt(aName.substring("segment-bezel-".length), 10),
frame = CGRectCreateCopy(_segments[segment].frame);
frame = CGRectCreateCopy([_segments[segment] frame]);
if (segment == 0)
if (segment === 0)
{
frame.origin.x += contentInset.left;
frame.size.width -= contentInset.left;
}
if (segment == _segments.length - 1)
frame.size.width -= contentInset.right;
if (segment === _segments.length - 1)
frame.size.width = CGRectGetWidth([self bounds]) - contentInset.right - frame.origin.x;
return frame;
}
else if (aName.substring(0, "divider-bezel".length) == "divider-bezel")
else if (aName.indexOf("divider-bezel") === 0)
{
var segment = parseInt(aName.substring("divider-bezel-".length), 10),
width = [self widthForSegment:segment],
@@ -479,7 +480,7 @@ CPSegmentSwitchTrackingMomentary = 2;
return CGRectMake(left + width, bezelInset.top, thickness, height);
}
else if (aName.substring(0, "segment-content".length) == "segment-content")
else if (aName.indexOf("segment-content") === 0)
{
var segment = parseInt(aName.substring("segment-content-".length), 10);
@@ -491,7 +492,7 @@ CPSegmentSwitchTrackingMomentary = 2;
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
if (aName.substring(0, "segment-content".length) == "segment-content")
if ([aName hasPrefix:@"segment-content"])
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
@@ -499,50 +500,59 @@ CPSegmentSwitchTrackingMomentary = 2;
- (void)layoutSubviews
{
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
inState:_themeStates[0]];
if (_segments.length <= 0)
return;
var leftBezelView = [self layoutEphemeralSubviewNamed:@"left-segment-bezel"
var themeState = _themeStates[0];
themeState |= _themeState & CPThemeStateDisabled;
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
inState:themeState],
leftBezelView = [self layoutEphemeralSubviewNamed:@"left-segment-bezel"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[leftBezelView setBackgroundColor:leftCapColor];
var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color"
inState:_themeStates[_themeStates.length - 1]];
var themeState = _themeStates[_themeStates.length - 1];
var rightBezelView = [self layoutEphemeralSubviewNamed:@"right-segment-bezel"
themeState |= _themeState & CPThemeStateDisabled;
var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color"
inState:themeState],
rightBezelView = [self layoutEphemeralSubviewNamed:@"right-segment-bezel"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[rightBezelView setBackgroundColor:rightCapColor];
for (var i=0, count = _themeStates.length; i<count; i++)
for (var i = 0, count = _themeStates.length; i < count; i++)
{
var themeState = _themeStates[i];
themeState |= _themeState & CPThemeStateDisabled;
var bezelColor = [self valueForThemeAttribute:@"center-segment-bezel-color"
inState:themeState];
var bezelColor = [self valueForThemeAttribute:@"center-segment-bezel-color"
inState:themeState],
var bezelView = [self layoutEphemeralSubviewNamed:"segment-bezel-"+i
positioned:CPWindowBelow
bezelView = [self layoutEphemeralSubviewNamed:"segment-bezel-" + i
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[bezelView setBackgroundColor:bezelColor];
//layout image/title views
var segment = _segments[i];
var contentView = [self layoutEphemeralSubviewNamed:@"segment-content-"+i
// layout image/title views
var segment = _segments[i],
contentView = [self layoutEphemeralSubviewNamed:@"segment-content-" + i
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"segment-bezel-"+i];
relativeToEphemeralSubviewNamed:@"segment-bezel-" + i];
[contentView setText:segment.label];
[contentView setImage:segment.image];
[contentView setText:[segment label]];
[contentView setImage:[segment image]];
[contentView setFont:[self valueForThemeAttribute:@"font" inState:themeState]];
[contentView setTextColor:[self valueForThemeAttribute:@"text-color" inState:themeState]];
@@ -551,27 +561,27 @@ CPSegmentSwitchTrackingMomentary = 2;
[contentView setLineBreakMode:[self valueForThemeAttribute:@"line-break-mode" inState:themeState]];
[contentView setTextShadowColor:[self valueForThemeAttribute:@"text-shadow-color" inState:themeState]];
[contentView setTextShadowOffset:[self valueForThemeAttribute:@"text-shadow-offset" inState:themeState]];
[contentView setImageScaling:[self valueForThemeAttribute:@"image-scaling" inState:themeState]];
if (segment.image && segment.label)
[contentView setImageScaling:[self valueForThemeAttribute:@"image-scaling" inState:themeState]];
if ([segment image] && [segment label])
[contentView setImagePosition:[self valueForThemeAttribute:@"image-position" inState:themeState]];
else if (segment.image)
else if ([segment image])
[contentView setImagePosition:CPImageOnly];
if (i == count - 1)
continue;
var borderState = _themeStates[i] | _themeStates[i+1];
var borderState = _themeStates[i] | _themeStates[i + 1];
borderState = (borderState & CPThemeStateSelected & ~CPThemeStateHighlighted) ? CPThemeStateSelected : CPThemeStateNormal;
borderState |= _themeState & CPThemeStateDisabled;
var borderColor = [self valueForThemeAttribute:@"divider-bezel-color"
inState:borderState];
inState:borderState],
var borderView = [self layoutEphemeralSubviewNamed:"divider-bezel-"+i
positioned:CPWindowBelow
borderView = [self layoutEphemeralSubviewNamed:"divider-bezel-" + i
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[borderView setBackgroundColor:borderColor];
@@ -582,7 +592,7 @@ CPSegmentSwitchTrackingMomentary = 2;
/*!
Draws the specified segment
@param aSegment the segment to draw
@param shouldHighlight <code>YES</code> highlights the bezel
@param shouldHighlight \c YES highlights the bezel
*/
- (void)drawSegment:(int)aSegment highlight:(BOOL)shouldHighlight
{
@@ -594,48 +604,53 @@ CPSegmentSwitchTrackingMomentary = 2;
return;
var segment = _segments[aSegment],
segmentWidth = segment.width,
segmentWidth = [segment width],
themeState = _themeStates[aSegment] | (_themeState & CPThemeStateDisabled),
contentInset = [self valueForThemeAttribute:@"content-inset" inState:themeState],
font = [self valueForThemeAttribute:@"font" inState:themeState];
if (!segmentWidth)
{
if (segment.image && segment.label)
segmentWidth = [segment.label sizeWithFont:font].width + [segment.image size].width + contentInset.left + contentInset.right;
if ([segment image] && [segment label])
segmentWidth = [[segment label] sizeWithFont:font].width + [[segment image] size].width + contentInset.left + contentInset.right;
else if (segment.image)
segmentWidth = [segment.image size].width + contentInset.left + contentInset.right;
segmentWidth = [[segment image] size].width + contentInset.left + contentInset.right;
else if (segment.label)
segmentWidth = [segment.label sizeWithFont:font].width + contentInset.left + contentInset.right;
segmentWidth = [[segment label] sizeWithFont:font].width + contentInset.left + contentInset.right;
else
segmentWidth = 0.0;
}
var delta = segmentWidth - CGRectGetWidth(segment.frame);
var delta = segmentWidth - CGRectGetWidth([segment frame]);
if (!delta)
return;
{
[self setNeedsLayout];
[self setNeedsDisplay:YES];
// Update Contorl Size
return;
}
// Update control size
var frame = [self frame];
[self setFrameSize:CGSizeMake(CGRectGetWidth(frame) + delta, CGRectGetHeight(frame))];
// Update Segment Width
segment.width = segmentWidth;
segment.frame = [self frameForSegment:aSegment];;
// Update segment width
[segment setWidth:segmentWidth];
[segment setFrame:[self frameForSegment:aSegment]];
// Update Following Segments Widths
// Update following segments widths
var index = aSegment + 1;
for (; index < _segments.length; ++index)
{
_segments[index].frame.origin.x += delta;
[_segments[index] frame].origin.x += delta;
[self drawSegmentBezel:index highlight:NO];
[self drawSegment:index highlight:NO];
}
[self drawSegmentBezel:aSegment highlight:NO];
[self drawSegment:aSegment highlight:NO];
@@ -681,11 +696,20 @@ CPSegmentSwitchTrackingMomentary = 2;
{
var location = [self convertPoint:aPoint fromView:nil],
count = _segments.length;
while (count--)
if (CGRectContainsPoint(_segments[count].frame, aPoint))
if (CGRectContainsPoint([_segments[count] frame], aPoint))
return count;
if (_segments.length)
{
var adjustedLastFrame = CGRectCreateCopy([_segments[_segments.length - 1] frame]);
adjustedLastFrame.size.width = CGRectGetWidth([self bounds]) - adjustedLastFrame.origin.x;
if (CGRectContainsPoint(adjustedLastFrame, aPoint))
return _segments.length - 1;
}
return -1;
}
@@ -693,7 +717,7 @@ CPSegmentSwitchTrackingMomentary = 2;
{
if (![self isEnabled])
return;
[self trackSegment:anEvent];
}
@@ -707,74 +731,76 @@ CPSegmentSwitchTrackingMomentary = 2;
@param anEvent the event to handle
*/
- (void)trackSegment:(CPEvent)anEvent
{
{
var type = [anEvent type],
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if (type == CPLeftMouseUp)
{
if (_trackingSegment == -1)
return;
if (CGRectContainsPoint(_segments[_trackingSegment].frame, location))
if (_trackingSegment === [self testSegment:location])
{
if (_trackingMode == CPSegmentSwitchTrackingSelectAny)
{
[self setSelected:![self isSelectedForSegment:_trackingSegment] forSegment:_trackingSegment];
// With ANY, _selectedSegment means last pressed.
_selectedSegment = _trackingSegment;
}
else
[self setSelected:YES forSegment:_trackingSegment];
[self sendAction:[self action] to:[self target]];
if (_trackingMode == CPSegmentSwitchTrackingMomentary)
{
[self setSelected:NO forSegment:_trackingSegment];
_selectedSegment = -1;
}
}
[self drawSegmentBezel:_trackingSegment highlight:NO];
_trackingSegment = -1;
return;
}
if (type == CPLeftMouseDown)
{
_trackingHighlighted = YES;
_trackingSegment = [self testSegment:location];
[self drawSegmentBezel:_trackingSegment highlight:YES];
var trackingSegment = [self testSegment:location];
if (trackingSegment > -1 && [self isEnabledForSegment:trackingSegment])
{
_trackingHighlighted = YES;
_trackingSegment = trackingSegment;
[self drawSegmentBezel:_trackingSegment highlight:YES];
}
}
else if (type == CPLeftMouseDragged)
{
if (_trackingSegment == -1)
return;
var highlighted = CGRectContainsPoint(_segments[_trackingSegment].frame, location);
var highlighted = [self testSegment:location] === _trackingSegment;
if (highlighted != _trackingHighlighted)
{
_trackingHighlighted = highlighted;
[self drawSegmentBezel:_trackingSegment highlight:_trackingHighlighted];
}
}
[CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (void)setFont:(CPFont)aFont
{
[super setFont:aFont];
[self tileWithChangedSegment:0];
}
@@ -790,12 +816,12 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
var frame = [self frame],
originalWidth = frame.size.width;
frame.size.width = 0;
[self setFrame:frame];
@@ -806,38 +832,38 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
if ([aCoder containsValueForKey:CPSegmentedControlSelectedKey])
_selectedSegment = [aCoder decodeIntForKey:CPSegmentedControlSelectedKey];
else
else
_selectedSegment = -1;
if ([aCoder containsValueForKey:CPSegmentedControlTrackingModeKey])
_trackingMode = [aCoder decodeIntForKey:CPSegmentedControlTrackingModeKey];
else
_trackingMode = CPSegmentSwitchTrackingSelectOne;
// HACK
for (var i = 0; i < _segments.length; i++)
{
_themeStates[i] = _segments[i].selected ? CPThemeStateSelected : CPThemeStateNormal;
_themeStates[i] = [_segments[i] selected] ? CPThemeStateSelected : CPThemeStateNormal;
[self tileWithChangedSegment:i];
}
var difference = MAX(originalWidth - [self frame].size.width, 0.0),
remainingWidth = FLOOR(difference / _segments.length);
for (var i=0; i < _segments.length; i++)
[self setWidth:_segments[i].width + remainingWidth forSegment:i];
for (var i = 0; i < _segments.length; i++)
[self setWidth:[_segments[i] width] + remainingWidth forSegment:i];
[self tileWithChangedSegment:0];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_segments forKey:CPSegmentedControlSegmentsKey];
[aCoder encodeInt:_selectedSegment forKey:CPSegmentedControlSelectedKey];
[aCoder encodeInt:_segmentStyle forKey:CPSegmentedControlSegmentStyleKey];
@@ -849,15 +875,15 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
@implementation _CPSegmentItem : CPObject
{
CPImage image;
CPString label;
CPMenu menu;
BOOL selected;
BOOL enabled;
int tag;
int width;
CPImage image @accessors;
CPString label @accessors;
CPMenu menu @accessors;
BOOL selected @accessors;
BOOL enabled @accessors;
int tag @accessors;
int width @accessors;
CGRect frame;
CGRect frame @accessors;
}
- (id)init
@@ -868,8 +894,8 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
label = @"";
menu = nil;
selected = NO;
enabled = NO;
tag = 0;
enabled = YES;
tag = -1;
width = 0;
frame = CGRectMakeZero();
@@ -892,7 +918,7 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
image = [aCoder decodeObjectForKey:CPSegmentItemImageKey];
@@ -905,7 +931,7 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
frame = CGRectMakeZero();
}
return self;
}
@@ -921,4 +947,3 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
}
@end
+41 -18
View File
@@ -28,19 +28,17 @@
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
CPLightShadow = 0;
CPHeavyShadow = 1;
var CPShadowViewLightBackgroundColor = nil,
CPShadowViewHeavyBackgroundColor = nil;
var LIGHT_LEFT_INSET = 3.0,
LIGHT_RIGHT_INSET = 3.0,
LIGHT_TOP_INSET = 3.0,
LIGHT_BOTTOM_INSET = 5.0,
HEAVY_LEFT_INSET = 7.0,
HEAVY_RIGHT_INSET = 7.0,
HEAVY_TOP_INSET = 5.0,
@@ -61,51 +59,76 @@ var LIGHT_LEFT_INSET = 3.0,
return;
var bundle = [CPBundle bundleForClass:[self class]];
CPShadowViewLightBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTopLeft.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTop.png"] size:CGSizeMake(1.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTopRight.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightLeft.png"] size:CGSizeMake(9.0, 1.0)],
nil,
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightRight.png"] size:CGSizeMake(9.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomLeft.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottom.png"] size:CGSizeMake(1.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomRight.png"] size:CGSizeMake(9.0, 9.0)]
]]];
CPShadowViewHeavyBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTopLeft.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTop.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTopRight.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyLeft.png"] size:CGSizeMake(17.0, 1.0)],
nil,
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyRight.png"] size:CGSizeMake(17.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomLeft.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottom.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomRight.png"] size:CGSizeMake(17.0, 17.0)]
]]];
}
+ (id)shadowViewEnclosingView:(CPView)aView
{
return [self shadowViewEnclosingView:aView withWeight:CPLightShadow];
}
+ (id)shadowViewEnclosingView:(CPView)aView withWeight:(CPShadowWeight)aWeight
{
var shadowView = [[CPShadowView alloc] initWithFrame:[aView frame]];
[shadowView setWeight:aWeight];
var size = [shadowView frame].size,
width = size.width - [shadowView leftInset] - [shadowView rightInset],
height = size.height - [shadowView topInset] - [shadowView bottomInset],
enclosingView = [aView superview];
[shadowView setHitTests:[aView hitTests]];
[shadowView setAutoresizingMask:[aView autoresizingMask]];
[aView removeFromSuperview];
[shadowView addSubview:aView];
[aView setFrame:CGRectMake([shadowView leftInset], [shadowView topInset], width, height)]
[enclosingView addSubview:shadowView];
return shadowView;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_weight = CPLightShadow;
[self setBackgroundColor:CPShadowViewLightBackgroundColor];
[self setHitTests:NO];
}
return self;
}
@@ -113,9 +136,9 @@ var LIGHT_LEFT_INSET = 3.0,
{
if (_weight == aWeight)
return;
_weight = aWeight;
if (_weight == CPLightShadow)
[self setBackgroundColor:CPShadowViewLightBackgroundColor];
@@ -147,7 +170,7 @@ var LIGHT_LEFT_INSET = 3.0,
{
if (_weight == CPLightShadow)
return LIGHT_LEFT_INSET + LIGHT_RIGHT_INSET;
return HEAVY_LEFT_INSET + HEAVY_RIGHT_INSET;
}
@@ -155,7 +178,7 @@ var LIGHT_LEFT_INSET = 3.0,
{
if (_weight == CPLightShadow)
return LIGHT_TOP_INSET + LIGHT_BOTTOM_INSET;
return HEAVY_TOP_INSET + HEAVY_BOTTOM_INSET;
}
+59 -41
View File
@@ -22,7 +22,6 @@
@import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
/*! SLIDER STATES */
@@ -42,14 +41,14 @@ CPCircularSlider = 1;
BOOL _isVertical;
}
+ (CPString)themeClass
+ (CPString)defaultThemeClass
{
return "slider";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[nil, _CGSizeMakeZero(), 0.0, nil]
return [CPDictionary dictionaryWithObjects:[[CPNull null], _CGSizeMakeZero(), 0.0, [CPNull null]]
forKeys:[@"knob-color", @"knob-size", @"track-width", @"track-color"]];
}
@@ -61,14 +60,14 @@ CPCircularSlider = 1;
{
_minValue = 0.0;
_maxValue = 100.0;
[self setObjectValue:50.0];
[self setContinuous:YES];
[self _recalculateIsVertical];
}
return self;
}
@@ -76,13 +75,17 @@ CPCircularSlider = 1;
{
if (_minValue === aMinimumValue)
return;
_minValue = aMinimumValue;
var doubleValue = [self doubleValue];
if (doubleValue < _minValue)
[self setDoubleValue:_minValue];
// The relative position may have (did) change.
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
- (float)minValue
@@ -94,13 +97,17 @@ CPCircularSlider = 1;
{
if (_maxValue === aMaximumValue)
return;
_maxValue = aMaximumValue;
var doubleValue = [self doubleValue];
if (doubleValue > _maxValue)
[self setDoubleValue:_maxValue];
// The relative position may have (did) change.
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
- (float)maxValue
@@ -161,27 +168,27 @@ CPCircularSlider = 1;
bounds.size.height = trackWidth;
}
}
return bounds;
}
- (CGRect)knobRectForBounds:(CGRect)bounds
{
var knobSize = [self currentValueForThemeAttribute:@"knob-size"];
if (knobSize.width <= 0 || knobSize.height <= 0)
return _CGRectMakeZero();
var knobRect = _CGRectMake(0.0, 0.0, knobSize.width, knobSize.height),
trackRect = [self trackRectForBounds:bounds];
// No track, do our best to approximate a place for this thing.
if (!trackRect || _CGRectIsEmpty(trackRect))
trackRect = bounds;
if ([self hasThemeState:CPThemeStateCircular])
{
var angle = 3*PI_2 - (1.0 - [self doubleValue] - _minValue) / (_maxValue - _minValue) * PI2,
var angle = 3 * PI_2 - (1.0 - [self doubleValue] - _minValue) / (_maxValue - _minValue) * PI2,
radius = CGRectGetWidth(trackRect) / 2.0 - 8.0;
knobRect.origin.x = radius * COS(angle) + CGRectGetMidX(trackRect) - 3.0;
@@ -190,7 +197,7 @@ CPCircularSlider = 1;
else if ([self isVertical])
{
knobRect.origin.x = _CGRectGetMidX(trackRect) - knobSize.width / 2.0;
knobRect.origin.y = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height);
knobRect.origin.y = ((_maxValue - [self doubleValue]) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height);
}
else
{
@@ -205,10 +212,10 @@ CPCircularSlider = 1;
{
if (aName === "track-view")
return [self trackRectForBounds:[self bounds]];
else if (aName === "knob-view")
return [self knobRectForBounds:[self bounds]];
return [super rectForEphemeralSubviewNamed:aName];
}
@@ -217,12 +224,12 @@ CPCircularSlider = 1;
if (aName === "track-view" || aName === "knob-view")
{
var view = [[CPView alloc] init];
[view setHitTests:NO];
return view;
}
return [super createEphemeralSubviewNamed:aName];
}
@@ -248,7 +255,7 @@ CPCircularSlider = 1;
var bounds = [self bounds],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
_isVertical = width < height ? 1 : (width > height ? 0 : -1);
if (_isVertical === 1)
@@ -274,7 +281,7 @@ CPCircularSlider = 1;
var knobView = [self layoutEphemeralSubviewNamed:@"knob-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"track-view"];
if (knobView)
[knobView setBackgroundColor:[self currentValueForThemeAttribute:"knob-color"]];
}
@@ -312,7 +319,7 @@ CPCircularSlider = 1;
var minValue = [self minValue];
return MAX(0.0, MIN(1.0, (aPoint.y - _CGRectGetMinY(trackRect)) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue;
return MAX(0.0, MIN(1.0, (_CGRectGetMaxY(trackRect) - aPoint.y) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue;
}
else
{
@@ -331,44 +338,43 @@ CPCircularSlider = 1;
{
var bounds = [self bounds],
knobRect = [self knobRectForBounds:_CGRectMakeCopy(bounds)];
if (_CGRectContainsPoint(knobRect, aPoint))
_dragOffset = _CGSizeMake(_CGRectGetMidX(knobRect) - aPoint.x, _CGRectGetMidY(knobRect) - aPoint.y);
else
else
{
var trackRect = [self trackRectForBounds:bounds];
if (trackRect && _CGRectContainsPoint(trackRect, aPoint))
{
_dragOffset = _CGSizeMakeZero();
[self setObjectValue:[self _valueAtPoint:aPoint]];
}
else
return NO;
}
[self setHighlighted:YES];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
return YES;
return YES;
}
- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
{
[self setObjectValue:[self _valueAtPoint:_CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
return YES;
}
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
{
[self setHighlighted:NO];
if ([_target respondsToSelector:@selector(sliderDidFinish:)])
[_target sliderDidFinish:self];
@@ -384,10 +390,22 @@ CPCircularSlider = 1;
{
if (flag)
_sendActionOn |= CPLeftMouseDraggedMask;
else
else
_sendActionOn &= ~CPLeftMouseDraggedMask;
}
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
{
var count = objects.length,
value = [objects[0] valueForKeyPath:aKeyPath];
[self setObjectValue:value];
while (count-- > 1)
if (value !== ([objects[count] valueForKeyPath:aKeyPath]))
return [self setFloatValue:1.0];
}
@end
var CPSliderMinValueKey = "CPSliderMinValueKey",
@@ -434,14 +452,14 @@ var CPSliderMinValueKey = "CPSliderMinValueKey",
- (id)value
{
CPLog.warn("[CPSlider value] is deprecated, use doubleValue or objectValue instead.");
return [self doubleValue];
return [self doubleValue];
}
- (void)setValue:(id)aValue
{
CPLog.warn("[CPSlider setValue:] is deprecated, use setDoubleValue: or setObjectValue: instead.");
[self setObjectValue:aValue];
}
+106 -154
View File
@@ -20,8 +20,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPView.j"
@import "CPColorPicker.j"
/*
@ignore
*/
@@ -45,14 +47,15 @@
CPTextField _saturationLabel;
CPTextField _brightnessLabel;
CPTextField _hexLabel;
DOMElement _redValue;
DOMElement _greenValue;
DOMElement _blueValue;
DOMElement _hueValue;
DOMElement _saturationValue;
DOMElement _brightnessValue;
DOMElement _hexValue;
CPTextField _hexValue;
CPTextField _hexValue;
CPTextField _redValue;
CPTextField _greenValue;
CPTextField _blueValue;
CPTextField _hueValue;
CPTextField _saturationValue;
CPTextField _brightnessValue;
}
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
@@ -81,72 +84,14 @@
[_redSlider setTarget: self];
[_redSlider setAction: @selector(sliderChanged:)];
[_redSlider setAutoresizingMask: CPViewWidthSizable];
var updateFunction = function(aDOMEvent)
{
if(isNaN(this.value))
return;
switch(this)
{
case _redValue: [_redSlider setFloatValue:MAX(MIN(ROUND(this.value), 255) / 255.0, 0)];
//[self sliderChanged: _redSlider];
break;
case _greenValue: [_greenSlider setFloatValue:MAX(MIN(ROUND(this.value), 255) / 255.0, 0)];
//[self sliderChanged: _greenSlider];
break;
case _blueValue: [_blueSlider setFloatValue:MAX(MIN(ROUND(this.value), 255) / 255.0, 0)];
//[self sliderChanged: _blueSlider];
break;
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(this.value), 360), 0)];
//[self sliderChanged: _hueSlider];
break;
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(this.value), 100), 0)];
//[self sliderChanged: _saturationSlider];
break;
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(this.value), 100), 0)];
//[self sliderChanged: _brightnessSlider];
break;
}
this.blur();
};
var keypressFunction = function(aDOMEvent)
{
aDOMEvent = aDOMEvent || window.event;
if (aDOMEvent.keyCode == 13)
{
updateFunction(aDOMEvent);
if(aDOMEvent.preventDefault)
aDOMEvent.preventDefault();
else if(aDOMEvent.stopPropagation)
aDOMEvent.stopPropagation();
}
}
//red value input box
var redValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 35, 45, 20)];
[redValue setAutoresizingMask: CPViewMinXMargin];
_redValue = document.createElement("input");
_redValue.style.width = "40px";
_redValue.style.backgroundColor = "transparent";
_redValue.style.border = "1px solid black";
_redValue.style.color = "black";
_redValue.style.position = "absolute";
_redValue.style.top = "0px";
_redValue.style.left = "0px";
_redValue.onchange = updateFunction;
redValue._DOMElement.appendChild(_redValue);
[_contentView addSubview: redValue];
// red value input box
_redValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 30, 45, 29)];
[_redValue setAutoresizingMask: CPViewMinXMargin];
[_redValue setEditable: YES];
[_redValue setBezeled: YES];
[_redValue setDelegate: self];
[_contentView addSubview: _redValue];
_greenLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 58, 15, 20)];
[_greenLabel setStringValue: "G"];
@@ -159,15 +104,13 @@
[_greenSlider setAction: @selector(sliderChanged:)];
[_greenSlider setAutoresizingMask: CPViewWidthSizable];
//green value input box
var greenValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 58, 45, 20)];
[greenValue setAutoresizingMask: CPViewMinXMargin];
_greenValue = _redValue.cloneNode(false);
_greenValue.onchange = updateFunction;
greenValue._DOMElement.appendChild(_greenValue);
[_contentView addSubview: greenValue];
// green value input box
_greenValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 53, 45, 29)];
[_greenValue setAutoresizingMask: CPViewMinXMargin];
[_greenValue setEditable: YES];
[_greenValue setBezeled: YES];
[_greenValue setDelegate: self];
[_contentView addSubview: _greenValue];
_blueLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 81, 15, 20)];
[_blueLabel setStringValue: "B"];
@@ -180,15 +123,13 @@
[_blueSlider setAction: @selector(sliderChanged:)];
[_blueSlider setAutoresizingMask: CPViewWidthSizable];
//blue value input box
var blueValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 81, 45, 20)];
[blueValue setAutoresizingMask: CPViewMinXMargin];
_blueValue = _redValue.cloneNode(false);
_blueValue.onchange = updateFunction;
blueValue._DOMElement.appendChild(_blueValue);
[_contentView addSubview: blueValue];
// blue value input box
_blueValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 76, 45, 29)];
[_blueValue setAutoresizingMask: CPViewMinXMargin];
[_blueValue setEditable: YES];
[_blueValue setBezeled: YES];
[_blueValue setDelegate: self];
[_contentView addSubview: _blueValue];
_hsbLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 120, 190, 20)];
[_hsbLabel setStringValue: "Hue, Saturation, Brightness"];
@@ -205,16 +146,14 @@
[_hueSlider setAction: @selector(sliderChanged:)];
[_hueSlider setAutoresizingMask: CPViewWidthSizable];
//red value input box
var hueValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 145, 45, 20)];
[hueValue setAutoresizingMask: CPViewMinXMargin];
// hue value input box
_hueValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 140, 45, 29)];
[_hueValue setAutoresizingMask: CPViewMinXMargin];
[_hueValue setEditable: YES];
[_hueValue setBezeled: YES];
[_hueValue setDelegate: self];
[_contentView addSubview: _hueValue];
_hueValue = _redValue.cloneNode(false);
_hueValue.onchange = updateFunction;
hueValue._DOMElement.appendChild(_hueValue);
[_contentView addSubview: hueValue];
_saturationLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 168, 15, 20)];
[_saturationLabel setStringValue: "S"];
[_saturationLabel setTextColor:[CPColor blackColor]];
@@ -226,15 +165,13 @@
[_saturationSlider setAction: @selector(sliderChanged:)];
[_saturationSlider setAutoresizingMask: CPViewWidthSizable];
//green value input box
var saturationValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 168, 45, 20)];
[saturationValue setAutoresizingMask: CPViewMinXMargin];
_saturationValue = _redValue.cloneNode(false);
_saturationValue.onchange = updateFunction;
saturationValue._DOMElement.appendChild(_saturationValue);
[_contentView addSubview: saturationValue];
// saturation value input box
_saturationValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 163, 45, 29)];
[_saturationValue setAutoresizingMask: CPViewMinXMargin];
[_saturationValue setEditable: YES];
[_saturationValue setBezeled: YES];
[_saturationValue setDelegate: self];
[_contentView addSubview: _saturationValue];
_brightnessLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 191, 15, 20)];
[_brightnessLabel setStringValue: "B"];
@@ -247,49 +184,25 @@
[_brightnessSlider setAction: @selector(sliderChanged:)];
[_brightnessSlider setAutoresizingMask: CPViewWidthSizable];
//blue value input box
var brightnessValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 191, 45, 20)];
[brightnessValue setAutoresizingMask: CPViewMinXMargin];
_brightnessValue = _redValue.cloneNode(false);
_brightnessValue.onchange = updateFunction;
brightnessValue._DOMElement.appendChild(_brightnessValue);
[_contentView addSubview: brightnessValue];
// brightness value input box
_brightnessValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 186, 45, 29)];
[_brightnessValue setAutoresizingMask: CPViewMinXMargin];
[_brightnessValue setEditable: YES];
[_brightnessValue setBezeled: YES];
[_brightnessValue setDelegate: self];
[_contentView addSubview: _brightnessValue];
_hexLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 230, 30, 20)];
[_hexLabel setStringValue: "Hex"];
[_hexLabel setTextColor:[CPColor blackColor]];
//hex input box
_hexValue = _redValue.cloneNode(false);
_hexValue.style.top = "228px";
_hexValue.style.width = "80px";
_hexValue.style.left = "35px";
_hexValue.onkeypress = function(aDOMEvent)
{
aDOMEvent = aDOMEvent || window.event;
if (aDOMEvent.keyCode == 13)
{
var newColor = [CPColor colorWithHexString: this.value];
if(newColor)
{
[self setColor: newColor];
[[self colorPanel] setColor: newColor];
}
if(aDOMEvent.preventDefault)
aDOMEvent.preventDefault();
else if(aDOMEvent.stopPropagation)
aDOMEvent.stopPropagation();
this.blur();
}
};
_contentView._DOMElement.appendChild(_hexValue);
//hex input box
_hexValue = [[CPTextField alloc] initWithFrame: CGRectMake(32, 225, 80, 29)];
[_hexValue setEditable: YES];
[_hexValue setBezeled: YES];
[_hexValue setDelegate: self];
[_contentView addSubview: _hexValue];
[_contentView addSubview: _rgbLabel];
[_contentView addSubview: _redLabel];
[_contentView addSubview: _greenLabel];
@@ -380,7 +293,7 @@
- (void)updateHex:(CPColor)aColor
{
_hexValue.value = [aColor hexString];
[_hexValue setStringValue:[aColor hexString]];
}
- (void)updateRGBSliders:(CPColor)aColor
@@ -394,13 +307,13 @@
- (void)updateLabels
{
_hueValue.value = ROUND([_hueSlider floatValue]);
_saturationValue.value = ROUND([_saturationSlider floatValue]);
_brightnessValue.value = ROUND([_brightnessSlider floatValue]);
[_hueValue setStringValue: ROUND([_hueSlider floatValue])];
[_saturationValue setStringValue: ROUND([_saturationSlider floatValue])];
[_brightnessValue setStringValue: ROUND([_brightnessSlider floatValue])];
_redValue.value = ROUND([_redSlider floatValue] * 255);
_greenValue.value = ROUND([_greenSlider floatValue] * 255);
_blueValue.value = ROUND([_blueSlider floatValue] * 255);
[_redValue setStringValue: ROUND([_redSlider floatValue] * 255)];
[_greenValue setStringValue: ROUND([_greenSlider floatValue] * 255)];
[_blueValue setStringValue: ROUND([_blueSlider floatValue] * 255)];
}
- (CPImage)provideNewButtonImage
@@ -413,4 +326,43 @@
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:CPColorPicker] pathForResource:"slider_button_h.png"] size:CGSizeMake(32, 32)];
}
- (void)controlTextDidEndEditing:(CPNotification)aNotification
{
var field = [aNotification object],
value = [[field stringValue] stringByTrimmingWhitespace];
if (field === _hexValue) {
var newColor = [CPColor colorWithHexString: value];
if (newColor) {
[self setColor: newColor];
[[self colorPanel] setColor: newColor];
}
} else {
switch(field) {
case _redValue: [_redSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _redSlider];
break;
case _greenValue: [_greenSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _greenSlider];
break;
case _blueValue: [_blueSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _blueSlider];
break;
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(value), 360), 0)];
[self sliderChanged: _hueSlider];
break;
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
[self sliderChanged: _saturationSlider];
break;
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
[self sliderChanged: _brightnessSlider];
break;
}
}
}
@end
+284 -115
View File
@@ -20,13 +20,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPButtonBar.j"
@import "CPImage.j"
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
#include "Platform/Platform.h"
#include "Platform/DOM/CPDOMDisplayServer.h"
CPSplitViewDidResizeSubviewsNotification = @"CPSplitViewDidResizeSubviewsNotification";
CPSplitViewWillResizeSubviewsNotification = @"CPSplitViewWillResizeSubviewsNotification";
@@ -43,18 +40,32 @@ var CPSplitViewHorizontalImage = nil,
id _delegate;
BOOL _isVertical;
BOOL _isPaneSplitter;
int _currentDivider;
float _initialOffset;
float _preCollapsePosition;
CPString _originComponent;
CPString _sizeComponent;
CPArray _DOMDividerElements;
CPString _dividerImagePath;
int _drawingDivider;
BOOL _needsResizeSubviews;
CPArray _buttonBars;
}
+ (CPString)defaultThemeClass
{
return @"splitview";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[10.0, 1.0, [CPColor grayColor]]
forKeys:[@"divider-thickness", @"pane-divider-thickness", @"pane-divider-color"]];
}
/*
@@ -75,18 +86,19 @@ var CPSplitViewHorizontalImage = nil,
if (self = [super initWithFrame:aFrame])
{
_currentDivider = CPNotFound;
_DOMDividerElements = [];
_buttonBars = [];
[self _setVertical:YES];
}
return self;
}
- (float)dividerThickness
{
return _isPaneSplitter ? 1.0 : 10.0;
return [self currentValueForThemeAttribute:[self isPaneSplitter] ? @"pane-divider-thickness" : @"divider-thickness"];
}
- (BOOL)isVertical
@@ -98,13 +110,13 @@ var CPSplitViewHorizontalImage = nil,
{
if (![self _setVertical:shouldBeVertical])
return;
// Just re-adjust evenly.
var frame = [self frame],
dividerThickness = [self dividerThickness];
[self _postNotificationWillResize];
var eachSize = ROUND((frame.size[_sizeComponent] - dividerThickness * (_subviews.length - 1)) / _subviews.length),
index = 0,
count = _subviews.length;
@@ -115,9 +127,9 @@ var CPSplitViewHorizontalImage = nil,
else
for (; index < count; ++index)
[_subviews[index] setFrame:CGRectMake(0, ROUND((eachSize + dividerThickness) * index), frame.size.width, eachSize)];
[self setNeedsDisplay:YES];
[self _postNotificationDidResize];
}
@@ -125,13 +137,13 @@ var CPSplitViewHorizontalImage = nil,
- (BOOL)_setVertical:(BOOL)shouldBeVertical
{
var changed = (_isVertical != shouldBeVertical);
_isVertical = shouldBeVertical;
_originComponent = [self isVertical] ? "x" : "y";
_sizeComponent = [self isVertical] ? "width" : "height";
_dividerImagePath = [self isVertical] ? [CPSplitViewVerticalImage filename] : [CPSplitViewHorizontalImage filename];
return changed;
}
@@ -144,20 +156,21 @@ var CPSplitViewHorizontalImage = nil,
{
if (_isPaneSplitter == shouldBePaneSplitter)
return;
_isPaneSplitter = shouldBePaneSplitter;
#if PLATFORM(DOM)
_DOMDividerElements = [];
#endif
if (_DOMDividerElements[_drawingDivider])
[self _setupDOMDivider];
// The divider changes size when pane splitter mode is toggled, so the
// subviews need to change size too.
_needsResizeSubviews = YES;
[self setNeedsDisplay:YES];
}
- (void)didAddSubview:(CPView)aSubview
{
_needsResizeSubviews = YES;
// [self adjustSubviews];
}
- (BOOL)isSubviewCollapsed:(CPView)subview
@@ -169,9 +182,9 @@ var CPSplitViewHorizontalImage = nil,
{
var frame = [_subviews[aDivider] frame],
rect = CGRectMakeZero();
rect.size = [self frame].size;
rect.size[_sizeComponent] = [self dividerThickness];
rect.origin[_originComponent] = frame.origin[_originComponent] + frame.size[_sizeComponent];
@@ -180,20 +193,19 @@ var CPSplitViewHorizontalImage = nil,
- (CGRect)effectiveRectOfDividerAtIndex:(int)aDivider
{
var realRect = [self rectOfDividerAtIndex:aDivider];
var padding = 2;
var realRect = [self rectOfDividerAtIndex:aDivider],
padding = 2;
realRect.size[_sizeComponent] += padding * 2;
realRect.origin[_originComponent] -= padding;
return realRect;
}
- (void)drawRect:(CGRect)rect
{
var count = [_subviews count] - 1;
while ((count--) > 0)
{
_drawingDivider = count;
@@ -207,29 +219,33 @@ var CPSplitViewHorizontalImage = nil,
if (!_DOMDividerElements[_drawingDivider])
{
_DOMDividerElements[_drawingDivider] = document.createElement("div");
_DOMDividerElements[_drawingDivider].style.cursor = "move";
_DOMDividerElements[_drawingDivider].style.position = "absolute";
_DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat";
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
if (_isPaneSplitter)
{
_DOMDividerElements[_drawingDivider].style.backgroundColor = "#A5A5A5";
_DOMDividerElements[_drawingDivider].style.backgroundImage = "";
}
else
{
_DOMDividerElements[_drawingDivider].style.backgroundColor = "";
_DOMDividerElements[_drawingDivider].style.backgroundImage = "url('"+_dividerImagePath+"')";
}
}
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
}
[self _setupDOMDivider];
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect));
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect));
#endif
}
- (void)_setupDOMDivider
{
if (_isPaneSplitter)
{
_DOMDividerElements[_drawingDivider].style.backgroundColor = [[self currentValueForThemeAttribute:@"pane-divider-color"] cssString];
_DOMDividerElements[_drawingDivider].style.backgroundImage = "";
}
else
{
_DOMDividerElements[_drawingDivider].style.backgroundColor = "";
_DOMDividerElements[_drawingDivider].style.backgroundImage = "url('"+_dividerImagePath+"')";
}
}
- (void)viewWillDraw
{
[self _adjustSubviewsWithCalculatedSize];
@@ -239,13 +255,13 @@ var CPSplitViewHorizontalImage = nil,
{
if (!_needsResizeSubviews)
return;
_needsResizeSubviews = NO;
var subviews = [self subviews],
count = subviews.length,
oldSize = CGSizeMakeZero();
if ([self isVertical])
{
oldSize.width += [self dividerThickness] * (count - 1);
@@ -256,10 +272,10 @@ var CPSplitViewHorizontalImage = nil,
oldSize.width = CGRectGetWidth([self frame]);
oldSize.height += [self dividerThickness] * (count - 1);
}
while (count--)
oldSize[_sizeComponent] += [subviews[count] frame].size[_sizeComponent];
[self resizeSubviewsWithOldSize:oldSize];
}
@@ -268,31 +284,41 @@ var CPSplitViewHorizontalImage = nil,
var frame = [_subviews[anIndex] frame],
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent],
effectiveRect = [self effectiveRectOfDividerAtIndex:anIndex],
buttonBar = _buttonBars[anIndex],
buttonBarRect = null,
additionalRect = null;
if (buttonBar != null)
{
buttonBarRect = [buttonBar resizeControlFrame];
buttonBarRect.origin = [self convertPoint:buttonBarRect.origin fromView:buttonBar];
}
if ([_delegate respondsToSelector:@selector(splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:)])
effectiveRect = [_delegate splitView:self effectiveRect:effectiveRect forDrawnRect:effectiveRect ofDividerAtIndex:anIndex];
if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
additionalRect = [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex];
return CGRectContainsPoint(effectiveRect, aPoint) || (additionalRect && CGRectContainsPoint(additionalRect, aPoint));
return CGRectContainsPoint(effectiveRect, aPoint) ||
(additionalRect && CGRectContainsPoint(additionalRect, aPoint)) ||
(buttonBarRect && CGRectContainsPoint(buttonBarRect, aPoint));
}
- (CPView)hitTest:(CGPoint)aPoint
{
if ([self isHidden] || ![self hitTests] || !CGRectContainsPoint([self frame], aPoint))
return nil;
var point = [self convertPoint:aPoint fromView:[self superview]];
var count = [_subviews count] - 1;
var point = [self convertPoint:aPoint fromView:[self superview]],
count = [_subviews count] - 1;
for (var i = 0; i < count; i++)
{
if ([self cursorAtPoint:point hitDividerAtIndex:i])
return self;
}
return [super hitTest:aPoint];
}
@@ -303,18 +329,19 @@ var CPSplitViewHorizontalImage = nil,
- (void)trackDivider:(CPEvent)anEvent
{
var type = [anEvent type];
if (type == CPLeftMouseUp)
{
if (_currentDivider != CPNotFound)
{
_currentDivider = CPNotFound;
[self _updateResizeCursor:anEvent];
[self _postNotificationDidResize];
}
return;
}
if (type == CPLeftMouseDown)
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
@@ -331,21 +358,21 @@ var CPSplitViewHorizontalImage = nil,
if ([anEvent clickCount] == 2 &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)])
{
{
var minPosition = [self minPossiblePositionOfDividerAtIndex:i],
maxPosition = [self maxPossiblePositionOfDividerAtIndex:i];
if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
{
if ([self isSubviewCollapsed:_subviews[i]])
[self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
[self setPosition:_preCollapsePosition ? _preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
else
[self setPosition:minPosition ofDividerAtIndex:i];
}
else if ([_delegate splitView:self canCollapseSubview:_subviews[i+1]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i+1] forDoubleClickOnDividerAtIndex:i])
else if ([_delegate splitView:self canCollapseSubview:_subviews[i + 1]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i + 1] forDoubleClickOnDividerAtIndex:i])
{
if ([self isSubviewCollapsed:_subviews[i+1]])
[self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
if ([self isSubviewCollapsed:_subviews[i + 1]])
[self setPosition:_preCollapsePosition ? _preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
else
[self setPosition:maxPosition ofDividerAtIndex:i];
}
@@ -359,15 +386,20 @@ var CPSplitViewHorizontalImage = nil,
}
}
}
if (_currentDivider === CPNotFound)
return;
}
else if (type == CPLeftMouseDragged && _currentDivider != CPNotFound)
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
[self setPosition:(point[_originComponent] + _initialOffset) ofDividerAtIndex:_currentDivider];
// Cursor might change if we reach a resize limit.
[self _updateResizeCursor:anEvent];
}
[CPApp setTarget:self selector:@selector(trackDivider:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
@@ -377,13 +409,89 @@ var CPSplitViewHorizontalImage = nil,
[self trackDivider:anEvent];
}
- (void)viewDidMoveToWindow
{
// Enable split view resize cursors. Commented out pending CPTrackingArea implementation.
//[[self window] setAcceptsMouseMovedEvents:YES];
}
- (void)mouseEntered:(CPEvent)anEvent
{
// Tracking code handles cursor by itself.
if (_currentDivider == CPNotFound)
[self _updateResizeCursor:anEvent];
}
- (void)mouseMoved:(CPEvent)anEvent
{
if (_currentDivider == CPNotFound)
[self _updateResizeCursor:anEvent];
}
- (void)mouseExited:(CPEvent)anEvent
{
if (_currentDivider == CPNotFound)
// FIXME: we should use CPCursor push/pop (if previous currentCursor != arrow).
[[CPCursor arrowCursor] set];
}
- (void)_updateResizeCursor:(CPEvent)anEvent
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if ([anEvent type] === CPLeftMouseUp && ![[self window] acceptsMouseMovedEvents])
{
[[CPCursor arrowCursor] set];
return;
}
for (var i = 0, count = [_subviews count] - 1; i < count; i++)
{
// If we are currently tracking, keep the resize cursor active even outside of hit areas.
if (_currentDivider === i || (_currentDivider == CPNotFound && [self cursorAtPoint:point hitDividerAtIndex:i]))
{
var frame = [_subviews[i] frame],
size = frame.size[_sizeComponent],
startPosition = frame.origin[_originComponent] + size,
canShrink = [self _realPositionForPosition:startPosition - 1 ofDividerAtIndex:i] < startPosition,
canGrow = [self _realPositionForPosition:startPosition + 1 ofDividerAtIndex:i] > startPosition,
cursor = [CPCursor arrowCursor];
if (size === 0)
canGrow = YES; // Subview is collapsed.
else if (!canShrink &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i]])
canShrink = YES; // Subview is collapsible.
if (_isVertical && canShrink && canGrow)
cursor = [CPCursor resizeLeftRightCursor];
else if (_isVertical && canShrink)
cursor = [CPCursor resizeLeftCursor];
else if (_isVertical && canGrow)
cursor = [CPCursor resizeRightCursor];
else if (canShrink && canGrow)
cursor = [CPCursor resizeUpDownCursor];
else if (canShrink)
cursor = [CPCursor resizeUpCursor];
else if (canGrow)
cursor = [CPCursor resizeDownCursor];
[cursor set];
return;
}
}
[[CPCursor arrowCursor] set];
}
- (float)maxPossiblePositionOfDividerAtIndex:(int)dividerIndex
{
var frame = [_subviews[dividerIndex + 1] frame];
if (dividerIndex + 1 < [_subviews count] - 1)
return frame.origin[_originComponent] + frame.size[_sizeComponent] - [self dividerThickness];
else
else
return [self frame].size[_sizeComponent] - [self dividerThickness];
}
@@ -392,17 +500,15 @@ var CPSplitViewHorizontalImage = nil,
if (dividerIndex > 0)
{
var frame = [_subviews[dividerIndex - 1] frame];
return frame.origin[_originComponent] + frame.size[_sizeComponent] + [self dividerThickness];
}
else
else
return 0;
}
- (void)setPosition:(float)position ofDividerAtIndex:(int)dividerIndex
- (int)_realPositionForPosition:(float)position ofDividerAtIndex:(int)dividerIndex
{
[self _adjustSubviewsWithCalculatedSize];
// not sure where this should override other positions?
if ([_delegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)])
position = [_delegate splitView:self constrainSplitPosition:position ofSubviewAt:dividerIndex];
@@ -411,47 +517,64 @@ var CPSplitViewHorizontalImage = nil,
proposedMin = [self minPossiblePositionOfDividerAtIndex:dividerIndex],
actualMax = proposedMax,
actualMin = proposedMin;
if([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
actualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
if([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
actualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
var frame = [self frame],
viewA = _subviews[dividerIndex],
frameA = [viewA frame],
viewB = _subviews[dividerIndex + 1],
frameB = [viewB frame];
var realPosition = MAX(MIN(position, actualMax), actualMin);
var viewA = _subviews[dividerIndex],
realPosition = MAX(MIN(position, actualMax), actualMin);
if (position < proposedMin + (actualMin - proposedMin) / 2)
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
if ([_delegate splitView:self canCollapseSubview:viewA])
realPosition = proposedMin;
return realPosition;
}
- (void)setPosition:(float)position ofDividerAtIndex:(int)dividerIndex
{
[self _adjustSubviewsWithCalculatedSize];
var realPosition = [self _realPositionForPosition:position ofDividerAtIndex:dividerIndex];
var viewA = _subviews[dividerIndex],
frameA = [viewA frame],
viewB = _subviews[dividerIndex + 1],
frameB = [viewB frame];
_preCollapsePosition = 0;
var preSize = frameA.size[_sizeComponent];
frameA.size[_sizeComponent] = realPosition - frameA.origin[_originComponent];
if (preSize !== 0 && frameA.size[_sizeComponent] === 0)
_preCollapsePosition = preSize;
[_subviews[dividerIndex] setFrame:frameA];
preSize = frameB.size[_sizeComponent];
frameB.size[_sizeComponent] = frameB.origin[_originComponent] + frameB.size[_sizeComponent] - realPosition - [self dividerThickness];
if (preSize !== 0 && frameB.size[_sizeComponent] === 0)
_preCollapsePosition = preSize;
frameB.origin[_originComponent] = realPosition + [self dividerThickness];
[_subviews[dividerIndex + 1] setFrame:frameB];
[self setNeedsDisplay:YES];
}
- (void)setFrameSize:(CGSize)aSize
{
[self _adjustSubviewsWithCalculatedSize];
[super setFrameSize:aSize];
[self setNeedsDisplay:YES];
}
- (void)resizeSubviewsWithOldSize:(CPSize)oldSize
{
{
if ([_delegate respondsToSelector:@selector(splitView:resizeSubviewsWithOldSize:)])
{
[_delegate splitView:self resizeSubviewsWithOldSize:oldSize];
@@ -459,7 +582,7 @@ var CPSplitViewHorizontalImage = nil,
}
[self _postNotificationWillResize];
var index = 0,
count = [_subviews count],
bounds = [self bounds],
@@ -488,8 +611,9 @@ var CPSplitViewHorizontalImage = nil,
totalSizableSpace = 0;
var nonSizableSpace = totalSizableSpace ? bounds.size[_sizeComponent] - totalSizableSpace : 0,
ratio = (bounds.size[_sizeComponent] - totalDividers*dividerThickness - nonSizableSpace) / (oldSize[_sizeComponent]- totalDividers*dividerThickness - nonSizableSpace),
remainingFlexibleSpace = bounds.size[_sizeComponent] - oldSize[_sizeComponent];
remainingFlexibleSpace = bounds.size[_sizeComponent] - oldSize[_sizeComponent],
oldDimension = (oldSize[_sizeComponent] - totalDividers * dividerThickness - nonSizableSpace),
ratio = oldDimension <= 0 ? 0 : (bounds.size[_sizeComponent] - totalDividers * dividerThickness - nonSizableSpace) / oldDimension;
for (index = 0; index < count; ++index)
{
@@ -508,10 +632,8 @@ var CPSplitViewHorizontalImage = nil,
}
else if (totalSizableSpace && !isSizable)
viewFrame.size[_sizeComponent] = [view frame].size[_sizeComponent];
else
alert("SHOULD NEVER GET HERE");
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
[view setFrame:viewFrame];
}
@@ -525,7 +647,7 @@ var CPSplitViewHorizontalImage = nil,
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewDidResizeSubviewsNotification object:self];
if ([_delegate respondsToSelector:@selector(splitViewWillResizeSubviews:)])
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewWillResizeSubviewsNotification object:self];
_delegate = delegate;
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
@@ -540,6 +662,47 @@ var CPSplitViewHorizontalImage = nil,
object:self];
}
/*!
Set the button bar who's resize control should act as a control for this splitview.
Each divider can have at most one button bar assigned to it, and that button bar must be
a subview of one of the split view's subviews.
Calling this method with nil as the button bar will remove any currently assigned button bar
for the divider at that index. Indexes will not be adjusted as new subviews are added, so you
should usually call this method after adding all the desired subviews to the split view.
This method will automatically configure the hasResizeControl and resizeControlIsLeftAligned
parameters of the button bar, and will override any currently set values.
*/
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex
{
if (!aButtonBar)
{
_buttonBars[dividerIndex] = nil;
return;
}
var view = [aButtonBar superview],
subview = aButtonBar;
while (view && view !== self)
{
subview = view;
view = [view superview];
}
if (view !== self)
[CPException raise:CPInvalidArgumentException
reason:@"CPSplitView button bar must be a subview of the split view."];
var viewIndex = [[self subviews] indexOfObject:subview];
[aButtonBar setHasResizeControl:YES];
[aButtonBar setResizeControlIsLeftAligned:dividerIndex < viewIndex];
_buttonBars[dividerIndex] = aButtonBar;
}
- (void)_postNotificationWillResize
{
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewWillResizeSubviewsNotification object:self];
@@ -554,30 +717,33 @@ var CPSplitViewHorizontalImage = nil,
var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
CPSplitViewIsVerticalKey = "CPSplitViewIsVerticalKey",
CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey";
CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey",
CPSplitViewButtonBarsKey = "CPSplitViewButtonBarsKey";
@implementation CPSplitView (CPCoding)
/*
Initializes the split view by unarchiving data from <code>aCoder</code>.
Initializes the split view by unarchiving data from \c aCoder.
@param aCoder the coder containing the archived CPSplitView.
*/
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_currentDivider = CPNotFound;
_DOMDividerElements = [];
_delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];;
_buttonBars = [aCoder decodeObjectForKey:CPSplitViewButtonBarsKey] || [];
_delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];
_isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey];
[self _setVertical:[aCoder decodeBoolForKey:CPSplitViewIsVerticalKey]];
}
return self;
}
@@ -588,9 +754,12 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
//FIXME how should we handle this?
//[aCoder encodeObject:_buttonBars forKey:CPSplitViewButtonBarsKey];
[aCoder encodeConditionalObject:_delegate forKey:CPSplitViewDelegateKey];
[aCoder encodeBool:_isVertical forKey:CPSplitViewIsVerticalKey];
[aCoder encodeBool:_isPaneSplitter forKey:CPSplitViewIsPaneSplitterKey];
}
+22 -70
View File
@@ -22,15 +22,23 @@
@import <Foundation/CPString.j>
#include "CoreGraphics/CGGeometry.h"
#include "Platform/Platform.h"
@import "CPPlatformString.j"
var CPStringReferenceElement = nil,
CPStringDefaultFont = nil;
var CPStringSizeWithFontInWidthCache = {};
CPStringSizeCachingEnabled = YES;
@implementation CPString (CPStringDrawing)
/*!
Returns a dictionary with the items "ascender", "descender", "lineHeight"
*/
+ (CPDictionary)metricsOfFont:(CPFont)aFont
{
return [CPPlatformString metricsOfFont:aFont];
}
/*!
Returns the string
*/
@@ -46,75 +54,19 @@ var CPStringReferenceElement = nil,
- (CGSize)sizeWithFont:(CPFont)aFont inWidth:(float)aWidth
{
#if PLATFORM(DOM)
if (!CPStringReferenceElement)
if (!CPStringSizeCachingEnabled)
return [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth];
var cacheKey = self + [aFont cssString] + aWidth,
size = CPStringSizeWithFontInWidthCache[cacheKey];
if (size === undefined)
{
CPStringReferenceElement = document.createElement("span");
var style = CPStringReferenceElement.style;
style.position = "absolute";
style.whiteSpace = "pre";
style.visibility = "visible";
style.padding = "0px";
style.margin = "0px";
style.left = "-100000px";
style.top = "-100000px";
style.zIndex = "10000";
style.background = "red";
document.getElementsByTagName("body")[0].appendChild(CPStringReferenceElement);
size = [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth];
CPStringSizeWithFontInWidthCache[cacheKey] = size;
}
if (!aFont)
{
if (!CPStringDefaultFont)
CPStringDefaultFont = [CPFont systemFontOfSize:12.0];
aFont = CPStringDefaultFont;
}
var style = CPStringReferenceElement.style;
if (aWidth === NULL)
{
style.width = "";
style.whiteSpace = "pre";
}
else
{
style.width = ROUND(aWidth) + "px";
if (document.attachEvent)
style.wordWrap = "break-word";
else
{
style.whiteSpace = "-o-pre-wrap";
style.whiteSpace = "-pre-wrap";
style.whiteSpace = "-moz-pre-wrap";
style.whiteSpace = "pre-wrap";
}
}
style.font = [aFont cssString];
if (CPFeatureIsCompatible(CPJavascriptInnerTextFeature))
CPStringReferenceElement.innerText = self;
else if (CPFeatureIsCompatible(CPJavascriptTextContentFeature))
CPStringReferenceElement.textContent = self;
return _CGSizeMake(CPStringReferenceElement.clientWidth, CPStringReferenceElement.clientHeight);
#endif
return _CGSizeMakeZero();
}
+ (void)_resetSize
{
CPStringReferenceElement = nil;
return CGSizeMakeCopy(size);
}
@end
+204 -542
View File
@@ -1,32 +1,8 @@
/*
* CPTabView.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPImageView.j"
@import "CPBox.j"
@import "CPSegmentedControl.j"
@import "CPTabViewItem.j"
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
/*
Places tabs on top with a bezeled border.
@global
@@ -34,7 +10,7 @@
*/
CPTopTabsBezelBorder = 0;
//CPLeftTabsBezelBorder = 1;
//CPBottomTabsBezelBorder = 2;
CPBottomTabsBezelBorder = 2;
//CPRightTabsBezelBorder = 3;
/*
Displays no tabs and has a bezeled border.
@@ -55,173 +31,55 @@ CPNoTabsLineBorder = 5;
*/
CPNoTabsNoBorder = 6;
var CPTabViewBezelBorderLeftImage = nil,
CPTabViewBackgroundCenterImage = nil,
CPTabViewBezelBorderRightImage = nil,
CPTabViewBezelBorderColor = nil,
CPTabViewBezelBorderBackgroundColor = nil;
var LEFT_INSET = 7.0,
RIGHT_INSET = 7.0;
var CPTabViewDidSelectTabViewItemSelector = 1,
CPTabViewShouldSelectTabViewItemSelector = 2,
CPTabViewWillSelectTabViewItemSelector = 4,
CPTabViewDidChangeNumberOfTabViewItemsSelector = 8;
/*!
@ingroup appkit
@class CPTabView
var HEIGHT_OF_SEGMENTED_CONTROL = 24;
This class represents a view that has multiple subviews (CPTabViewItem) presented as individual tabs.
Only one CPTabViewItem is shown at a time, and other CPTabViewItems can be made visible
(one at a time) by clicking on the CPTabViewItem's tab at the top of the tab view.
THe currently selected CPTabViewItem is the view that is displayed.
*/
@implementation CPTabView : CPView
{
CPView _labelsView;
CPView _backgroundView;
CPView _separatorView;
CPView _auxiliaryView;
CPView _contentView;
CPArray _tabViewItems;
CPTabViewItem _selectedTabViewItem;
CPArray items;
CPTabViewType _tabViewType;
id _delegate;
unsigned _delegateSelectors;
}
CPSegmentedControl tabs;
CPBox box;
/*
@ignore
*/
+ (void)initialize
{
if (self != CPTabView)
return;
var bundle = [CPBundle bundleForClass:self],
emptyImage = [[CPImage alloc] initByReferencingFile:@"" size:CGSizeMake(7.0, 0.0)],
backgroundImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBackgroundCenter.png"] size:CGSizeMake(1.0, 1.0)],
bezelBorderLeftImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBorderLeft.png"] size:CGSizeMake(7.0, 1.0)],
bezerBorderImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBorder.png"] size:CGSizeMake(1.0, 1.0)],
bezelBorderRightImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBorderRight.png"] size:CGSizeMake(7.0, 1.0)];
CPTabViewBezelBorderBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
emptyImage,
emptyImage,
emptyImage,
CPNumber selectedIndex;
bezelBorderLeftImage,
backgroundImage,
bezelBorderRightImage,
CPTabViewType type;
bezelBorderLeftImage,
bezerBorderImage,
bezelBorderRightImage
]]];
CPTabViewBezelBorderColor = [CPColor colorWithPatternImage:bezerBorderImage];
}
/*
@ignore
*/
+ (CPColor)bezelBorderColor
{
return CPTabViewBezelBorderColor;
id delegate;
unsigned delegateSelectors;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_tabViewType = CPTopTabsBezelBorder;
_tabViewItems = [];
items = [CPArray array];
tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, HEIGHT_OF_SEGMENTED_CONTROL)];
[tabs setHitTests:NO];
box = [[CPBox alloc] initWithFrame:CGRectMake(0, HEIGHT_OF_SEGMENTED_CONTROL / 2, CGRectGetWidth(aFrame),
CGRectGetHeight(aFrame) - HEIGHT_OF_SEGMENTED_CONTROL)];
selectedIndex = CPNotFound;
[self setTabViewType:CPTopTabsBezelBorder];
[self setBackgroundColor:[CPColor colorWithCalibratedWhite:0.95 alpha:1.0]];
[self addSubview:box];
[self addSubview:tabs];
[box setAutoresizingMask:CPViewWidthSizable];
[tabs setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin];
}
return self;
}
- (void)viewDidMoveToWindow
{
if (_tabViewType != CPTopTabsBezelBorder || _labelsView)
return;
[self _createBezelBorder];
[self layoutSubviews];
}
/* @ignore */
- (void)_createBezelBorder
{
var bounds = [self bounds];
_labelsView = [[_CPTabLabelsView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), 0.0)];
[_labelsView setTabView:self];
[_labelsView setAutoresizingMask:CPViewWidthSizable];
[self addSubview:_labelsView];
_backgroundView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[_backgroundView setBackgroundColor:CPTabViewBezelBorderBackgroundColor];
[_backgroundView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self addSubview:_backgroundView];
_separatorView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[_separatorView setBackgroundColor:[[self class] bezelBorderColor]];
[_separatorView setAutoresizingMask:CPViewWidthSizable | CPViewMaxYMargin];
[self addSubview:_separatorView];
}
/*
Lays out the subviews
@ignore
*/
- (void)layoutSubviews
{
if (_tabViewType == CPTopTabsBezelBorder)
{
var backgroundRect = [self bounds],
labelsViewHeight = [_CPTabLabelsView height];
backgroundRect.origin.y += labelsViewHeight;
backgroundRect.size.height -= labelsViewHeight;
[_backgroundView setFrame:backgroundRect];
var auxiliaryViewHeight = 5.0;
if (_auxiliaryView)
{
auxiliaryViewHeight = CGRectGetHeight([_auxiliaryView frame]);
[_auxiliaryView setFrame:CGRectMake(LEFT_INSET, labelsViewHeight, CGRectGetWidth(backgroundRect) - LEFT_INSET - RIGHT_INSET, auxiliaryViewHeight)];
}
[_separatorView setFrame:CGRectMake(LEFT_INSET, labelsViewHeight + auxiliaryViewHeight, CGRectGetWidth(backgroundRect) - LEFT_INSET - RIGHT_INSET, 1.0)];
}
// CPNoTabsNoBorder
[_contentView setFrame:[self contentRect]];
}
// Adding and Removing Tabs
/*!
Adds a CPTabViewItem to the tab view.
@@ -229,7 +87,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)addTabViewItem:(CPTabViewItem)aTabViewItem
{
[self insertTabViewItem:aTabViewItem atIndex:[_tabViewItems count]];
[self insertTabViewItem:aTabViewItem atIndex:[items count]];
}
/*!
@@ -240,18 +98,13 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)insertTabViewItem:(CPTabViewItem)aTabViewItem atIndex:(unsigned)anIndex
{
if (!_labelsView && _tabViewType == CPTopTabsBezelBorder)
[self _createBezelBorder];
[_tabViewItems insertObject:aTabViewItem atIndex:anIndex];
[_labelsView tabView:self didAddTabViewItem:aTabViewItem];
if ([_tabViewItems count] == 1)
[self selectFirstTabViewItem:self];
[items insertObject:aTabViewItem atIndex:anIndex];
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
[self _updateItems];
[self _repositionTabs];
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[delegate tabViewDidChangeNumberOfTabViewItems:self];
}
/*!
@@ -260,12 +113,19 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)removeTabViewItem:(CPTabViewItem)aTabViewItem
{
[_tabViewItems removeObjectIdenticalTo:aTabViewItem];
for (var i = 0; i < [items count]; i++)
{
if ([items objectAtIndex:i] === aTabViewItem)
{
[items removeObjectAtIndex:i];
}
}
[_labelsView tabView:self didRemoveTabViewItem:aTabViewItem];
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
[self _updateItems];
[self _repositionTabs];
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[delegate tabViewDidChangeNumberOfTabViewItems:self];
}
// Accessing Tabs
@@ -275,7 +135,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (int)indexOfTabViewItem:(CPTabViewItem)aTabViewItem
{
return [_tabViewItems indexOfObjectIdenticalTo:aTabViewItem];
return [items indexOfObjectIdenticalTo:aTabViewItem];
}
/*!
@@ -284,14 +144,11 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (int)indexOfTabViewItemWithIdentifier:(CPString)anIdentifier
{
var index = 0,
count = [_tabViewItems count];
for (; index < count; ++index)
if ([[_tabViewItems[index] identifier] isEqual:anIdentifier])
for (var index = [items count]; index >= 0; index--)
if ([[items[index] identifier] isEqual:anIdentifier])
return index;
return index;
return CPNotFound;
}
/*!
@@ -299,7 +156,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (unsigned)numberOfTabViewItems
{
return [_tabViewItems count];
return [items count];
}
/*!
@@ -307,7 +164,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (CPTabViewItem)tabViewItemAtIndex:(unsigned)anIndex
{
return _tabViewItems[anIndex];
return [items objectAtIndex:anIndex];
}
/*!
@@ -315,7 +172,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (CPArray)tabViewItems
{
return _tabViewItems;
return [items copy]; // Copy?
}
// Selecting a Tab
@@ -325,10 +182,10 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)selectFirstTabViewItem:(id)aSender
{
var count = [_tabViewItems count];
if (count)
[self selectTabViewItemAtIndex:0];
if ([items count] === 0)
return; // throw?
[self selectTabViewItemAtIndex:0];
}
/*!
@@ -337,10 +194,10 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)selectLastTabViewItem:(id)aSender
{
var count = [_tabViewItems count];
if (count)
[self selectTabViewItemAtIndex:count - 1];
if ([items count] === 0)
return; // throw?
[self selectTabViewItemAtIndex:[items count] - 1];
}
/*!
@@ -349,13 +206,16 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)selectNextTabViewItem:(id)aSender
{
if (!_selectedTabViewItem)
if (selectedIndex === CPNotFound)
return;
var index = [self indexOfTabViewItem:_selectedTabViewItem],
count = [_tabViewItems count];
[self selectTabViewItemAtIndex:index + 1 % count];
var nextIndex = selectedIndex + 1;
if (nextIndex === [items count])
// does nothing. According to spec at (http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/ApplicationKit/Classes/NSTabView_Class/Reference/Reference.html#//apple_ref/occ/instm/NSTabView/selectNextTabViewItem:)
return;
[self selectTabViewItemAtIndex:nextIndex];
}
/*!
@@ -364,13 +224,15 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)selectPreviousTabViewItem:(id)aSender
{
if (!_selectedTabViewItem)
if (selectedIndex === CPNotFound)
return;
var index = [self indexOfTabViewItem:_selectedTabViewItem],
count = [_tabViewItems count];
[self selectTabViewItemAtIndex:index == 0 ? count : index - 1];
var previousIndex = selectedIndex - 1;
if (previousIndex < 0)
return; // does nothing. See above.
[self selectTabViewItemAtIndex:previousIndex];
}
/*!
@@ -379,41 +241,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)selectTabViewItem:(CPTabViewItem)aTabViewItem
{
if ((_delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![_delegate tabView:self shouldSelectTabViewItem:aTabViewItem])
return;
if (_delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
[_delegate tabView:self willSelectTabViewItem:aTabViewItem];
if (_selectedTabViewItem)
{
_selectedTabViewItem._tabState = CPBackgroundTab;
[_labelsView tabView:self didChangeStateOfTabViewItem:_selectedTabViewItem];
[_contentView removeFromSuperview];
[_auxiliaryView removeFromSuperview];
}
_selectedTabViewItem = aTabViewItem;
_selectedTabViewItem._tabState = CPSelectedTab;
_contentView = [_selectedTabViewItem view];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_auxiliaryView = [_selectedTabViewItem auxiliaryView];
[_auxiliaryView setAutoresizingMask:CPViewWidthSizable];
[self addSubview:_contentView];
if (_auxiliaryView)
[self addSubview:_auxiliaryView];
[_labelsView tabView:self didChangeStateOfTabViewItem:_selectedTabViewItem];
[self layoutSubviews];
if (_delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
[_delegate tabView:self didSelectTabViewItem:aTabViewItem];
[self selectTabViewItemAtIndex:[self indexOfTabViewItem:aTabViewItem]];
}
/*!
@@ -422,7 +250,24 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)selectTabViewItemAtIndex:(unsigned)anIndex
{
[self selectTabViewItem:_tabViewItems[anIndex]];
var aTabViewItem = [items objectAtIndex:anIndex];
if (anIndex === selectedIndex)
return;
var aTabViewItem = [self tabViewItemAtIndex:anIndex];
if ((delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![delegate tabView:self shouldSelectTabViewItem:aTabViewItem])
return;
if (delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
[delegate tabView:self willSelectTabViewItem:aTabViewItem];
[tabs selectSegmentWithTag:anIndex];
[self _setSelectedIndex:anIndex];
if (delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
[delegate tabView:self didSelectTabViewItem:aTabViewItem];
}
/*!
@@ -430,32 +275,43 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (CPTabViewItem)selectedTabViewItem
{
return _selectedTabViewItem;
return [items objectAtIndex:selectedIndex];
}
//
//
/*!
Sets the tab view type.
@param aTabViewType the view type
*/
- (void)setTabViewType:(CPTabViewType)aTabViewType
{
if (_tabViewType == aTabViewType)
if (type === aTabViewType)
return;
_tabViewType = aTabViewType;
if (_tabViewType == CPNoTabsBezelBorder || _tabViewType == CPNoTabsLineBorder || _tabViewType == CPNoTabsNoBorder)
[_labelsView removeFromSuperview];
else if (![_labelsView superview])
[self addSubview:_labelsView];
if (_tabViewType == CPNoTabsLineBorder || _tabViewType == CPNoTabsNoBorder)
[_backgroundView removeFromSuperview];
else if (![_backgroundView superview])
[self addSubview:_backgroundView];
[self layoutSubviews];
if ((type === CPTopTabsBezelBorder || type === CPBottomTabsBezelBorder)
&& (aTabViewType !== CPTopTabsBezelBorder && aTabViewType !== CPBottomTabsBezelBorder))
[tabs removeFromSuperview];
if ((type === CPNoTabsBezelBorder || type === CPNoTabsLineBorder || type === CPNoTabsNoBorder)
&& (aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsNoBorder))
[self addSubview:tabs];
type = aTabViewType;
switch (type)
{
case CPTopTabsBezelBorder:
case CPBottomTabsBezelBorder:
case CPNoTabsBezelBorder:
[box setBorderType:CPBezelBorder];
break;
case CPNoTabsLineBorder:
[box setBorderType:CPLineBorder];
break;
case CPNoTabsNoBorder:
[box setBorderType:CPNoBorder];
break;
}
}
/*!
@@ -463,31 +319,15 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (CPTabViewType)tabViewType
{
return _tabViewType;
return type;
}
// Determining the Size
/*!
Returns the content rectangle.
Returns the receiver's delegate.
*/
- (CGRect)contentRect
- (id)delegate
{
var contentRect = CGRectMakeCopy([self bounds]);
if (_tabViewType == CPTopTabsBezelBorder)
{
var labelsViewHeight = [_CPTabLabelsView height],
auxiliaryViewHeight = _auxiliaryView ? CGRectGetHeight([_auxiliaryView frame]) : 5.0,
separatorViewHeight = 1.0;
contentRect.origin.y += labelsViewHeight + auxiliaryViewHeight + separatorViewHeight;
contentRect.size.height -= labelsViewHeight + auxiliaryViewHeight + separatorViewHeight * 2.0; // 2 for the bottom border as well.
contentRect.origin.x += LEFT_INSET;
contentRect.size.width -= LEFT_INSET + RIGHT_INSET;
}
return contentRect;
return delegate;
}
/*!
@@ -496,35 +336,74 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (void)setDelegate:(id)aDelegate
{
if (_delegate == aDelegate)
if (delegate == aDelegate)
return;
_delegate = aDelegate;
_delegateSelectors = 0;
if ([_delegate respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)])
_delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector;
delegate = aDelegate;
if ([_delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)])
_delegateSelectors |= CPTabViewWillSelectTabViewItemSelector;
delegateSelectors = 0;
if ([_delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)])
_delegateSelectors |= CPTabViewDidSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)])
delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector;
if ([_delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)])
_delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector;
if ([delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)])
delegateSelectors |= CPTabViewWillSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)])
delegateSelectors |= CPTabViewDidSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)])
delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector;
}
//
- (void)setBackgroundColor:(CPColor)aColor
{
[box setBackgroundColor:aColor];
}
- (void)mouseDown:(CPEvent)anEvent
{
var location = [_labelsView convertPoint:[anEvent locationInWindow] fromView:nil],
tabViewItem = [_labelsView representedTabViewItemAtPoint:location];
if (tabViewItem)
[self selectTabViewItem:tabViewItem];
var segmentIndex = [tabs testSegment:[tabs convertPoint:[anEvent locationInWindow] fromView:nil]];
if (segmentIndex != CPNotFound)
{
[self selectTabViewItemAtIndex:segmentIndex];
[tabs trackSegment:anEvent];
}
}
- (void)_repositionTabs
{
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
verticalCenterOfTabs = CGRectGetHeight([tabs bounds]) / 2;
if (type === CPBottomTabsBezelBorder)
[tabs setCenter:CGPointMake(horizontalCenterOfSelf, CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
else
[tabs setCenter:CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
}
- (void)_setSelectedIndex:(CPNumber)index
{
selectedIndex = index;
[box setContentView:[[items objectAtIndex:selectedIndex] view]];
}
- (void)_updateItems
{
[tabs setSegmentCount:[items count]];
for (var i = 0; i < [items count]; i++)
{
[tabs setLabel:[[items objectAtIndex:i] label] forSegment:i];
[tabs setTag:i forSegment:i];
}
if (selectedIndex === CPNotFound)
{
[self selectFirstTabViewItem:self];
}
}
@end
@@ -540,20 +419,17 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
{
if (self = [super initWithCoder:aCoder])
{
_tabViewType = [aCoder decodeIntForKey:CPTabViewTypeKey];
_tabViewItems = [];
// FIXME: this is somewhat hacky
[self _createBezelBorder];
var items = [aCoder decodeObjectForKey:CPTabViewItemsKey];
for (var i = 0; items && i < items.length; i++)
[self insertTabViewItem:items[i] atIndex:i];
type = [aCoder decodeIntForKey:CPTabViewTypeKey];
items = [];
var encodedItems = [aCoder decodeObjectForKey:CPTabViewItemsKey];
for (var i = 0; encodedItems && i < encodedItems.length; i++)
[self insertTabViewItem:encodedItems[i] atIndex:i];
var selected = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
if (selected)
[self selectTabViewItem:selected];
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
}
@@ -562,228 +438,14 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
var actualSubviews = _subviews;
_subviews = [];
[super encodeWithCoder:aCoder];
_subviews = actualSubviews;
[aCoder encodeObject:_tabViewItems forKey:CPTabViewItemsKey];;
[aCoder encodeObject:_selectedTabViewItem forKey:CPTabViewSelectedItemKey];
[aCoder encodeInt:_tabViewType forKey:CPTabViewTypeKey];
[aCoder encodeConditionalObject:_delegate forKey:CPTabViewDelegateKey];
}
@end
var _CPTabLabelsViewBackgroundColor = nil,
_CPTabLabelsViewInsideMargin = 10.0,
_CPTabLabelsViewOutsideMargin = 15.0;
/* @ignore */
@implementation _CPTabLabelsView : CPView
{
CPTabView _tabView;
CPDictionary _tabLabels;
}
+ (void)initialize
{
if (self != [_CPTabLabelsView class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPTabLabelsViewBackgroundColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelsViewLeft.png"] size:CGSizeMake(12.0, 26.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelsViewCenter.png"] size:CGSizeMake(1.0, 26.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelsViewRight.png"] size:CGSizeMake(12.0, 26.0)]
] isVertical:NO]];
}
+ (float)height
{
return 26.0;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_tabLabels = [];
[self setBackgroundColor:_CPTabLabelsViewBackgroundColor];
[self setFrameSize:CGSizeMake(CGRectGetWidth(aFrame), 26.0)];
}
return self;
}
- (void)setTabView:(CPTabView)aTabView
{
_tabView = aTabView;
}
- (CPTabView)tabView
{
return _tabView;
}
- (void)tabView:(CPTabView)aTabView didAddTabViewItem:(CPTabViewItem)aTabViewItem
{
var label = [[_CPTabLabel alloc] initWithFrame:CGRectMakeZero()];
[label setTabViewItem:aTabViewItem];
_tabLabels.push(label);
[self addSubview:label];
[self layoutSubviews];
}
- (void)tabView:(CPTabView)aTabView didRemoveTabViewItem:(CPTabViewItem)aTabViewItem
{
var index = [aTabView indexOfTabViewItem:aTabViewItem],
label = _tabLabels[index];
[_tabLabels removeObjectAtIndex:index];
[label removeFromSuperview];
[self layoutSubviews];
}
-(void)tabView:(CPTabView)aTabView didChangeStateOfTabViewItem:(CPTabViewItem)aTabViewItem
{
[_tabLabels[[aTabView indexOfTabViewItem:aTabViewItem]] setTabState:[aTabViewItem tabState]];
}
- (CPTabViewItem)representedTabViewItemAtPoint:(CGPoint)aPoint
{
var index = 0,
count = _tabLabels.length;
for (; index < count; ++index)
{
var label = _tabLabels[index];
if (CGRectContainsPoint([label frame], aPoint))
return [label tabViewItem];
}
return nil;
}
- (void)layoutSubviews
{
var index = 0,
count = _tabLabels.length,
width = (_CGRectGetWidth([self bounds]) - (count - 1) * _CPTabLabelsViewInsideMargin - 2 * _CPTabLabelsViewOutsideMargin) / count,
x = _CPTabLabelsViewOutsideMargin;
for (; index < count; ++index)
{
var label = _tabLabels[index],
frame = _CGRectMake(x, 8.0, width, 18.0);
[label setFrame:frame];
x = _CGRectGetMaxX(frame) + _CPTabLabelsViewInsideMargin;
}
}
- (void)setFrameSize:(CGSize)aSize
{
if (CGSizeEqualToSize([self frame].size, aSize))
return;
[super setFrameSize:aSize];
[self layoutSubviews];
}
@end
var _CPTabLabelBackgroundColor = nil,
_CPTabLabelSelectedBackgroundColor = nil;
/* @ignore */
@implementation _CPTabLabel : CPView
{
CPTabViewItem _tabViewItem;
CPTextField _labelField;
}
+ (void)initialize
{
if (self != [_CPTabLabel class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPTabLabelBackgroundColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelBackgroundLeft.png"] size:CGSizeMake(6.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelBackgroundCenter.png"] size:CGSizeMake(1.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelBackgroundRight.png"] size:CGSizeMake(6.0, 18.0)]
] isVertical:NO]];
_CPTabLabelSelectedBackgroundColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelSelectedLeft.png"] size:CGSizeMake(3.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelSelectedCenter.png"] size:CGSizeMake(1.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelSelectedRight.png"] size:CGSizeMake(3.0, 18.0)]
] isVertical:NO]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_labelField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_labelField setAlignment:CPCenterTextAlignment];
[_labelField setFrame:CGRectMake(5.0, 0.0, CGRectGetWidth(aFrame) - 10.0, 20.0)];
[_labelField setAutoresizingMask:CPViewWidthSizable];
[_labelField setFont:[CPFont boldSystemFontOfSize:11.0]];
[self addSubview:_labelField];
[self setTabState:CPBackgroundTab];
}
return self;
}
- (void)setTabState:(CPTabState)aTabState
{
[self setBackgroundColor:aTabState == CPSelectedTab ? _CPTabLabelSelectedBackgroundColor : _CPTabLabelBackgroundColor];
}
- (void)setTabViewItem:(CPTabViewItem)aTabViewItem
{
_tabViewItem = aTabViewItem;
[self update];
}
- (CPTabViewItem)tabViewItem
{
return _tabViewItem;
}
- (void)update
{
[_labelField setStringValue:[_tabViewItem label]];
[aCoder encodeObject:items forKey:CPTabViewItemsKey];;
[aCoder encodeObject:[self selectedTabViewItem] forKey:CPTabViewSelectedItemKey];
[aCoder encodeInt:type forKey:CPTabViewTypeKey];
[aCoder encodeConditionalObject:delegate forKey:CPTabViewDelegateKey];
}
@end
+16 -1
View File
@@ -22,7 +22,7 @@
@import <Foundation/CPObject.j>
@import <AppKit/CPView.j>
@import "CPView.j"
/*
@@ -58,6 +58,13 @@ CPPressedTab = 2;
CPView _view;
CPView _auxiliaryView;
CPTabView _tabView;
}
- (id)init
{
return [self initWithIdentifier:@""];
}
/*!
@@ -163,6 +170,14 @@ CPPressedTab = 2;
return _tabView;
}
/*!
@ignore
*/
- (void)_setTabView:(CPTabView)aView
{
_tabView = aView;
}
@end
var CPTabViewItemIdentifierKey = "CPTabViewItemIdentifierKey",
+396 -317
View File
@@ -3,7 +3,7 @@
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,411 +20,440 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/Foundation.j>
@import <Foundation/CPDictionary.j>
@import <Foundation/CPObject.j>
@import <Foundation/CPIndexSet.j>
@import <Foundation/CPSortDescriptor.j>
@import <Foundation/CPString.j>
@import "CPTableHeaderView.j"
/*
@ignore
*/
/*
@global
@class CPTableColumn
*/
CPTableColumnNoResizing = 0;
/*
@global
@class CPTableColumn
*/
CPTableColumnAutoresizingMask = 1;
/*
@global
@class CPTableColumn
*/
CPTableColumnUserResizingMask = 2;
CPTableColumnAutoresizingMask = 1 << 0;
CPTableColumnUserResizingMask = 1 << 1;
#define PurgableInfoMake(aView, aRow) { view:(aView), row:(aRow) }
#define PurgableInfoView(anInfo) ((anInfo).view)
#define PurgableInfoRow(anInfo) ((anInfo).row)
/*!
@ingroup appkit
@class CPTableColumn
An CPTableColumn object mainly keeps information about the width of the column, its minimum and maximum width; whether the column can be edited or resized; and the cells used to draw the column header and the data in the column. You can change all these attributes of the column by calling the appropriate methods. Please note that the table column does not hold nor has access to the data to be displayed in the column; this data is maintained in the table view's data source.</p>
<p>Each CPTableColumn object is identified by a CPString, called the column identifier. The reason is that, after a column has been added to a table view, the user might move the columns around, so there is a need to identify the columns regardless of its position in the table.
@ignore
*/
@implementation CPTableColumn : CPObject
{
CPString _identifier;
CPView _headerView;
CPTableView _tableView;
float _width;
float _minWidth;
float _maxWidth;
unsigned _resizingMask;
CPTableView _tableView;
CPView _headerView;
CPView _dataView;
Object _dataViewData;
CPView _dataView; // default data view for this column
float _width;
float _minWidth;
float _maxWidth;
unsigned _resizingMask;
Object _dataViewData; // cache of data view archives (key=data view hash, value=data view archive)
Object _dataViewForView; // mapping from view instances back to their data view prototype (key=view instance hash, value=data view)
Object _purgableInfosForDataView; // (key=data view hash, value=)
id _identifier;
BOOL _isEditable;
CPSortDescriptor _sortDescriptorPrototype;
BOOL _isHidden;
CPString _headerToolTip;
BOOL _disableResizingPosting @accessors(property=disableResizingPosting);
}
/*!
Initializes the table column with the specified identifier.
@param anIdentifier the identifier
@return the initialized table column
*/
- (id)initWithIdentifier:(CPString)anIdentifier
- (id)init
{
return [self initWithIdentifier:@""];
}
- (id)initWithIdentifier:(id)anIdentifier
{
self = [super init];
if (self)
{
[self _init];
_identifier = anIdentifier;
_width = 40.0;
_minWidth = 8.0;
_maxWidth = 1000.0;
var dataView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()];
[dataView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateHighlighted];
[self setDataView:dataView];
_headerView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()];
[_headerView setBackgroundColor:[CPColor greenColor]];
_dataViewData = { };
_width = 100.0;
_minWidth = 10.0;
_maxWidth = 1000000.0;
_resizingMask = CPTableColumnAutoresizingMask | CPTableColumnUserResizingMask;
_disableResizingPosting = NO;
[self setIdentifier:anIdentifier];
var header = [[_CPTableColumnHeaderView alloc] initWithFrame:CGRectMakeZero()];
[self setHeaderView:header];
[self setDataView:[CPTextField new]];
}
return self;
}
- (void)_init
{
_dataViewData = {};
_dataViewForView = {};
_purgableInfosForDataView = {};
}
/*!
Sets the table column's identifier
@param anIdentifier the new identifier
*/
- (void)setIdentifier:(CPString)anIdentifier
{
_identifier = anIdentifier;
}
/*!
Returns the table column's identifier
*/
- (CPString)identifier
{
return _identifier;
}
// Setting the CPTableView
/*!
Sets the table's view. This is called automatically by Cappuccino.
@param aTableView the new table view
*/
- (void)setTableView:(CPTableView)aTableView
{
_tableView = aTableView;
}
/*!
Returns the column's table view.
*/
- (CPTableView)tableView
{
return _tableView;
}
// Controlling size
/*!
Sets the column's width.
@param aWidth the new column width
*/
- (void)setWidth:(float)aWidth
{
_width = aWidth;
aWidth = +aWidth;
if (_width === aWidth)
return;
var newWidth = MIN(MAX(aWidth, [self minWidth]), [self maxWidth]);
if (_width === newWidth)
return;
var oldWidth = _width;
_width = newWidth;
var tableView = [self tableView];
if (tableView)
{
var index = [[tableView tableColumns] indexOfObjectIdenticalTo:self],
dirtyTableColumnRangeIndex = tableView._dirtyTableColumnRangeIndex;
if (dirtyTableColumnRangeIndex < 0)
tableView._dirtyTableColumnRangeIndex = index;
else
tableView._dirtyTableColumnRangeIndex = MIN(index, tableView._dirtyTableColumnRangeIndex);
var rows = tableView._exposedRows,
columns = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(index, [tableView._exposedColumns lastIndex] - index + 1)];
// FIXME: Would be faster with some sort of -setNeedsDisplayInColumns: that updates a dirtyTableColumnForDisplay cache; then marked columns would relayout their data views at display time.
[tableView _layoutDataViewsInRows:rows columns:columns];
[tableView tile];
if (!_disableResizingPosting)
[self _postDidResizeNotificationWithOldWidth:oldWidth];
}
}
/*!
Returns the column's width
*/
- (float)width
{
return _width;
}
/*!
Sets column's minimum width.
@param aWidth the new minimum column width
*/
- (void)setMinWidth:(float)aWidth
- (void)setMinWidth:(float)aMinWidth
{
if (_width < (_minWidth = aWidth))
[self setWidth:_minWidth];
aMinWidth = +aMinWidth;
if (_minWidth === aMinWidth)
return;
_minWidth = aMinWidth;
var width = [self width],
newWidth = MAX(width, [self minWidth]);
if (width !== newWidth)
[self setWidth:newWidth];
}
/*!
The column's minimum width
*/
- (float)minWidth
{
return _minWidth;
}
/*!
Sets the column's maximum width.
@param aWidth the new maximum width
*/
- (void)setMaxWidth:(float)aWidth
- (void)setMaxWidth:(float)aMaxWidth
{
if (_width > (_maxmimumWidth = aWidth))
[self setWidth:_maxWidth];
aMaxWidth = +aMaxWidth;
if (_maxWidth === aMaxWidth)
return;
_maxWidth = aMaxWidth;
var width = [self width],
newWidth = MIN(width, [self maxWidth]);
if (width !== newWidth)
[self setWidth:newWidth];
}
/*!
Sets the resizing mask. The mask is one of:
<pre>
CPTableColumnNoResizing;
CPTableColumnAutoresizingMask;
CPTableColumnUserResizingMask;
</pre>
@param aMask the new resizing mask
*/
- (void)setResizingMask:(unsigned)aMask
- (float)maxWidth
{
_resizingMask = aMask;
return _maxWidth;
}
- (void)setResizingMask:(unsigned)aResizingMask
{
_resizingMask = aResizingMask;
}
/*!
Returns the column's resizing mask. One of:
<pre>
CPTableColumnNoResizing;
CPTableColumnAutoresizingMask;
CPTableColumnUserResizingMask;
</pre>
*/
- (unsigned)resizingMask
{
return _resizingMask;
}
/*!
Resizes the column according to the min, max and set width.
*/
- (void)sizeToFit
{
var width = CPRectGetWidth([_headerView frame]);
if (width < _minWidth)
var width = _CGRectGetWidth([_headerView frame]);
if (width < [self minWidth])
[self setMinWidth:width];
else if (width > _maxWidth)
else if (width > [self maxWidth])
[self setMaxWidth:width]
if (_width != width)
if (_width !== width)
[self setWidth:width];
}
/*!
Sets whether the column in this data is editable.
@param aFlag <code>YES</code> means the column data is editable
*/
- (void)setEditable:(BOOL)aFlag
{
_isEditable = aFlag;
}
/*!
Returns <code>YES</code> if the column data is editable.
*/
- (BOOL)isEditable
{
return _isEditable;
}
//Setting the column header view
/*!
Sets the view that draws the column's header.
@param aHeaderView the view that will draws the column header
*/
//Setting Component Cells
- (void)setHeaderView:(CPView)aView
{
if (!aView)
[CPException raise:CPInvalidArgumentException reason:@"Attempt to set nil header view on " + [self description]];
_headerView = aView;
var tableHeaderView = [_tableView headerView];
[tableHeaderView setNeedsLayout];
[tableHeaderView setNeedsDisplay:YES];
}
/*!
Return the view that draws the column's header
*/
- (CPView)headerView
{
return _headerView;
}
/*!
Sets the data cell that draws rows in this column.
*/
- (void)setDataCell:(CPView <CPCoding>)aView
{
[self setDataView:aView];
}
This method set's the "prototype" view which will be used to create all table cells in this column.
/*
Sets the data view that draws rows in this column.
It creates a snapshot of aView, using keyed archiving, which is then copied over and over for each
individual cell that is shown. As a result, changes made after calling this method won't be reflected.
Example:
[tableColumn setDataView:someView]; // snapshot taken
[[tableColumn dataView] setSomething:x]; //won't work
This doesn't work because the snapshot is taken before the new property is applied. Instead, do:
[someView setSomething:x];
[tableColumn setDataView:someView];
*/
- (void)setDataView:(CPView <CPCoding>)aView
- (void)setDataView:(CPView)aView
{
if (_dataView)
_dataViewData[[_dataView hash]] = nil;
_dataViewData[[_dataView UID]] = nil;
[aView setThemeState:CPThemeStateTableDataView];
_dataView = aView;
_dataViewData[[aView hash]] = [CPKeyedArchiver archivedDataWithRootObject:aView];
_dataViewData[[aView UID]] = [CPKeyedArchiver archivedDataWithRootObject:aView];
}
/*!
Returns the data cell that draws rows in this column
*/
- (CPCell)dataCell
- (CPView)dataView
{
return _dataView;
}
/*
Returns the data view that draws rows in this column
*/
- (CPView)dataView
{
return [self dataCell];
}
Returns the CPView object used by the CPTableView to draw values for the receiver.
/*!
By default returns the value from <code>dataCell</code>. This can
be overridden by a subclass to return different cells for different
rows.
@param aRowIndex the index of the row to obtain the cell for
By default, this method just calls dataView. Subclassers can override if they need to
potentially use different cells for different rows. Subclasses should expect this method
to be invoked with row equal to -1 in cases where no actual row is involved but the table
view needs to get some generic cell info.
*/
- (CPCell)dataCellForRow:(int)aRowIndex
- (id)dataViewForRow:(int)aRowIndex
{
return [self dataView];
}
- (CPView)dataViewForRow:(int)aRowIndex
- (id)_newDataViewForRow:(int)aRowIndex
{
return [self dataCellForRow:aRowIndex];
}
/*
- (void)_markViewAsPurgable:(CPView)aView
{
var viewHash = [aView hash],
dataViewHash = [_dataViewForView[viewHash] hash];
if (!_purgableInfosForDataView[dataViewHash])
_purgableInfosForDataView[dataViewHash] = [CPDictionary dictionary];
[_purgableInfosForDataView[dataViewHash] setObject:aView forKey:viewHash];
}
*/
- (void)_markView:(CPView)aView inRow:(unsigned)aRow asPurgable:(BOOL)isPurgable
{
var viewHash = [aView hash],
dataViewHash = [_dataViewForView[viewHash] hash];
if (!_purgableInfosForDataView[dataViewHash])
{
if (!isPurgable)
return;
_purgableInfosForDataView[dataViewHash] = {};
}
if (!isPurgable) {
if (_purgableInfosForDataView[dataViewHash][viewHash])
CPLog.warn("removing unpurgable " + _purgableInfosForDataView[dataViewHash][viewHash]);
delete _purgableInfosForDataView[dataViewHash][viewHash];
}
else
_purgableInfosForDataView[dataViewHash][viewHash] = PurgableInfoMake(aView, aRow);
}
var dataView = [self dataViewForRow:aRowIndex],
dataViewUID = [dataView UID];
var x = [self tableView]._cachedDataViews[dataViewUID];
if (x && x.length)
return x.pop();
- (CPView)_newDataViewForRow:(int)aRowIndex avoidingRows:(CPRange)rows
{
var view = [self dataViewForRow:aRowIndex],
viewHash = [view hash],
purgableInfos = _purgableInfosForDataView[viewHash];
if (purgableInfos)
{
for (var key in purgableInfos)
{
var info = purgableInfos[key];
//if (!CPLocationInRange(PurgableInfoRow(info), rows))
//{
//CPLog.debug("yes, a purged view is usable, its called: " + PurgableInfoView(info));
delete purgableInfos[key];
return PurgableInfoView(info);
//}
//else
// CPLog.warn("avoiding");
}
}
// if we haven't cached an archive of the data view, do it now
if (!_dataViewData[viewHash])
_dataViewData[viewHash] = [CPKeyedArchiver archivedDataWithRootObject:view];
if (!_dataViewData[dataViewUID])
_dataViewData[dataViewUID] = [CPKeyedArchiver archivedDataWithRootObject:dataView];
// unarchive the data view cache
var newView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[viewHash]];
// map the new view's hash to it's data view prototype
_dataViewForView[[newView hash]] = view;
CPLog.warn("creating cell: %s", newView);
return newView;
var newDataView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[dataViewUID]];
newDataView.identifier = dataViewUID;
// make sure only we have control over the size and placement
[newDataView setAutoresizingMask:CPViewNotSizable];
return newDataView;
}
- (void)_purge
{
for (var viewHash in _purgableInfosForDataView)
{
var purgableInfos = _purgableInfosForDataView[viewHash];
//Setting the Identifier
for (var key in purgableInfos)
{
var view = PurgableInfoView(purgableInfos[key]);
if (!view)
CPLog.info("key="+key+" view=" + view + " purgableInfos[key]="+purgableInfos[key])
else if (view._superview) {
//CPLog.error("PURGING: (removing)" + view);
//[view removeFromSuperview];
[view setHidden:YES];
}
//else
// CPLog.warn("PURGING: (already removed)" + view);
//delete purgableInfos[key];
}
}
/*
Sets the receiver identifier to anIdentifier.
*/
- (void)setIdentifier:(id)anIdentifier
{
_identifier = anIdentifier;
}
/*
Returns the object used by the data source to identify the attribute corresponding to the receiver.
*/
- (id)identifier
{
return _identifier;
}
//Controlling Editability
/*
Controls whether the user can edit cells in the receiver by double-clicking them.
*/
- (void)setEditable:(BOOL)shouldBeEditable
{
_isEditable = shouldBeEditable;
}
/*
Returns YES if the user can edit cells associated with the receiver by double-clicking the
column in the NSTableView, NO otherwise.
*/
- (BOOL)isEditable
{
return _isEditable;
}
//Sorting
- (void)setSortDescriptorPrototype:(CPSortDescriptor)aSortDescriptor
{
_sortDescriptorPrototype = aSortDescriptor;
}
- (CPSortDescriptor)sortDescriptorPrototype
{
return _sortDescriptorPrototype;
}
//Setting Column Visibility
- (void)setHidden:(BOOL)shouldBeHidden
{
shouldBeHidden = !!shouldBeHidden
if (_isHidden === shouldBeHidden)
return;
_isHidden = shouldBeHidden;
[[self headerView] setHidden:shouldBeHidden];
[[self tableView] _tableColumnVisibilityDidChange:self];
}
- (BOOL)isHidden
{
return _isHidden;
}
//Setting Tool Tips
/*
Sets the tooltip string that is displayed when the cursor pauses over the
header cell of the receiver.
*/
- (void)setHeaderToolTip:(CPString)aToolTip
{
_headerToolTip = aToolTip;
}
- (CPString)headerToolTip
{
return _headerToolTip;
}
- (void)_postDidResizeNotificationWithOldWidth:(float)oldWidth
{
[[CPNotificationCenter defaultCenter]
postNotificationName:CPTableViewColumnDidResizeNotification
object:[self tableView]
userInfo:[CPDictionary dictionaryWithObjects:[self, oldWidth] forKeys:[@"CPTableColumn", "CPOldWidth"]]];
}
@end
@implementation CPTableColumn (Bindings)
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
{
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
if (![aBinding isEqual:@"someListOfExceptedBindings(notAcceptedBindings)"])
[[self tableView] _establishBindingsIfUnbound:anObject];
}
- (void)prepareDataView:(CPView)aDataView forRow:(unsigned)aRow
{
var bindingsDictionary = [CPKeyValueBinding allBindingsForObject:self],
keys = [bindingsDictionary allKeys];
for (var i = 0, count = [keys count]; i < count; i++)
{
var bindingName = keys[i],
bindingPath = [aDataView _replacementKeyPathForBinding:bindingName],
binding = [bindingsDictionary objectForKey:bindingName],
bindingInfo = binding._info,
destination = [bindingInfo objectForKey:CPObservedObjectKey],
keyPath = [bindingInfo objectForKey:CPObservedKeyPathKey],
dotIndex = keyPath.lastIndexOf("."),
value;
if (dotIndex === CPNotFound)
value = [[destination valueForKeyPath:keyPath] objectAtIndex:aRow];
else
{
/*
Optimize the prototypical use case where the key path describes a value
in an array. Without this optimization, we call CPArray's valueForKey
which generates as many values as objects in the array, of which we then
pick one and throw away the rest.
The optimization is to get the array and access the value directly. This
turns the operation into a single access regardless of how long the model
array is.
*/
var firstPart = keyPath.substring(0, dotIndex),
secondPart = keyPath.substring(dotIndex + 1),
firstValue = [destination valueForKeyPath:firstPart];
if ([firstValue isKindOfClass:CPArray])
value = [[firstValue objectAtIndex:aRow] valueForKeyPath:secondPart];
else
value = [[firstValue valueForKeyPath:secondPart] objectAtIndex:aRow];
}
value = [binding transformValue:value withOptions:[bindingInfo objectForKey:CPOptionsKey]];
// console.log(bindingName+" : "+keyPath+" : "+aRow+" : "+[[destination valueForKeyPath:keyPath] objectAtIndex:aRow]);
[aDataView setValue:value forKey:bindingPath];
}
}
//- (void)objectValue
//{
// return nil;
//}
- (void)setValue:(CPArray)content
{
[[self tableView] reloadData];
}
@end
var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
CPTableColumnHeaderViewKey = @"CPTableColumnHeaderViewKey",
@@ -432,24 +461,36 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
CPTableColumnWidthKey = @"CPTableColumnWidthKey",
CPTableColumnMinWidthKey = @"CPTableColumnMinWidthKey",
CPTableColumnMaxWidthKey = @"CPTableColumnMaxWidthKey",
CPTableColumnResizingMaskKey = @"CPTableColumnResizingMaskKey";
CPTableColumnResizingMaskKey = @"CPTableColumnResizingMaskKey",
CPTableColumnIsHiddenKey = @"CPTableColumnIsHiddenKey",
CPSortDescriptorPrototypeKey = @"CPSortDescriptorPrototypeKey",
CPTableColumnIsEditableKey = @"CPTableColumnIsEditableKey";
@implementation CPTableColumn (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
[self _init];
_identifier = [aCoder decodeObjectForKey:CPTableColumnIdentifierKey];
self = [super init];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
[self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
_width = [aCoder decodeFloatForKey:CPTableColumnWidthKey];
_minWidth = [aCoder decodeFloatForKey:CPTableColumnMinWidthKey];
_maxWidth = [aCoder decodeFloatForKey:CPTableColumnMaxWidthKey];
_resizingMask = [aCoder decodeBoolForKey:CPTableColumnResizingMaskKey];
if (self)
{
_dataViewData = { };
_width = [aCoder decodeFloatForKey:CPTableColumnWidthKey];
_minWidth = [aCoder decodeFloatForKey:CPTableColumnMinWidthKey];
_maxWidth = [aCoder decodeFloatForKey:CPTableColumnMaxWidthKey];
[self setIdentifier:[aCoder decodeObjectForKey:CPTableColumnIdentifierKey]];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
[self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
_resizingMask = [aCoder decodeIntForKey:CPTableColumnResizingMaskKey];
_isHidden = [aCoder decodeBoolForKey:CPTableColumnIsHiddenKey];
_isEditable = [aCoder decodeBoolForKey:CPTableColumnIsEditableKey];
_sortDescriptorPrototype = [aCoder decodeObjectForKey:CPSortDescriptorPrototypeKey];
}
return self;
}
@@ -457,15 +498,53 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_identifier forKey:CPTableColumnIdentifierKey];
[aCoder encodeObject:_headerView forKey:CPTableColumnHeaderViewKey];
[aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
[aCoder encodeObject:_width forKey:CPTableColumnWidthKey];
[aCoder encodeObject:_minWidth forKey:CPTableColumnMinWidthKey];
[aCoder encodeObject:_maxWidth forKey:CPTableColumnMaxWidthKey];
[aCoder encodeObject:_headerView forKey:CPTableColumnHeaderViewKey];
[aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
[aCoder encodeObject:_resizingMask forKey:CPTableColumnResizingMaskKey];
[aCoder encodeBool:_isHidden forKey:CPTableColumnIsHiddenKey];
[aCoder encodeBool:_isEditable forKey:CPTableColumnIsEditableKey];
[aCoder encodeObject:_sortDescriptorPrototype forKey:CPSortDescriptorPrototypeKey];
}
@end
@implementation CPTableColumn (NSInCompatibility)
- (void)setHeaderCell:(CPView)aView
{
[CPException raise:CPUnsupportedMethodException
reason:@"setHeaderCell: is not supported. -setHeaderCell:aView instead."];
}
- (CPView)headerCell
{
[CPException raise:CPUnsupportedMethodException
reason:@"headCell is not supported. -headerView instead."];
}
- (void)setDataCell:(CPView)aView
{
[CPException raise:CPUnsupportedMethodException
reason:@"setDataCell: is not supported. Use -setHeaderCell:aView instead."];
}
- (CPView)dataCell
{
[CPException raise:CPUnsupportedMethodException
reason:@"dataCell is not supported. Use -dataCell instead."];
}
- (id)dataCellForRow:(int)row
{
[CPException raise:CPUnsupportedMethodException
reason:@"dataCellForRow: is not supported. Use -dataViewForRow:row instead."];
}
@end
+685
View File
@@ -0,0 +1,685 @@
/*
* CPTableHeaderView.j
* AppKit
*
* Created by Ross Boucher.
* Copyright 2009 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPIndexSet.j>
@import "CPTableColumn.j"
@import "CPTableView.j"
@import "CPView.j"
@implementation _CPTableColumnHeaderView : CPView
{
_CPImageAndTextView _textField;
}
+ (CPString)defaultThemeClass
{
return @"columnHeader";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPNull null], CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], CGSizeMakeZero()]
forKeys:[@"background-color", @"text-alignment", @"text-inset", @"text-color", @"text-font", @"text-shadow-color", @"text-shadow-offset"]];
}
- (void)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
[self _init];
return self;
}
- (void)_init
{
_textField = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
[_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
[_textField setLineBreakMode:CPLineBreakByTruncatingTail];
[_textField setAlignment:CPLeftTextAlignment];
[_textField setVerticalAlignment:CPCenterVerticalTextAlignment];
[self addSubview:_textField];
}
- (void)layoutSubviews
{
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
var inset = [self currentValueForThemeAttribute:@"text-inset"],
bounds = [self bounds];
[_textField setFrame:_CGRectMake(inset.right, inset.top, bounds.size.width - inset.right - inset.left, bounds.size.height - inset.top - inset.bottom)];
[_textField setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
[_textField setFont:[self currentValueForThemeAttribute:@"text-font"]];
[_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
[_textField setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
[_textField setAlignment:[self currentValueForThemeAttribute:@"text-alignment"]];
}
- (void)setStringValue:(CPString)string
{
[_textField setText:string];
}
- (CPString)stringValue
{
return [_textField text];
}
- (void)textField
{
return _textField;
}
- (void)sizeToFit
{
[_textField sizeToFit];
}
- (void)setFont:(CPFont)aFont
{
[_textField setFont:aFont];
}
- (void)_setIndicatorImage:(CPImage)anImage
{
if (anImage)
{
[_textField setImage:anImage];
[_textField setImagePosition:CPImageRight];
}
else
{
[_textField setImagePosition:CPNoImage];
}
}
@end
var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringValueKey",
_CPTableColumnHeaderViewFontKey = @"_CPTableColumnHeaderViewFontKey",
_CPTableColumnHeaderViewImageKey = @"_CPTableColumnHeaderViewImageKey";
@implementation _CPTableColumnHeaderView (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
[self _init];
[self _setIndicatorImage:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewImageKey]];
[self setStringValue:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewStringValueKey]];
[self setFont:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewFontKey]];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:[_textField text] forKey:_CPTableColumnHeaderViewStringValueKey];
[aCoder encodeObject:[_textField image] forKey:_CPTableColumnHeaderViewImageKey];
[aCoder encodeObject:[_textField font] forKey:_CPTableColumnHeaderViewFontKey];
}
@end
@implementation CPTableHeaderView : CPView
{
CGPoint _mouseDownLocation;
CGPoint _previousTrackingLocation;
int _activeColumn;
int _pressedColumn;
BOOL _isResizing;
BOOL _isDragging;
BOOL _isTrackingColumn;
BOOL _drawsColumnLines;
float _columnOldWidth;
CPTableView _tableView @accessors(property=tableView);
}
+ (CPString)defaultThemeClass
{
return @"tableHeaderRow";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPColor grayColor]]
forKeys:[@"background-color", @"divider-color"]];
}
- (void)_init
{
_mouseDownLocation = _CGPointMakeZero();
_previousTrackingLocation = _CGPointMakeZero();
_activeColumn = -1;
_pressedColumn = -1;
_isResizing = NO;
_isDragging = NO;
_isTrackingColumn = NO;
_drawsColumnLines = YES;
_columnOldWidth = 0.0;
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
[self _init];
return self;
}
- (int)columnAtPoint:(CGPoint)aPoint
{
return [_tableView columnAtPoint:CGPointMake(aPoint.x, aPoint.y)];
}
- (CGRect)headerRectOfColumn:(int)aColumnIndex
{
var headerRect = [self bounds],
columnRect = [_tableView rectOfColumn:aColumnIndex];
headerRect.origin.x = _CGRectGetMinX(columnRect);
headerRect.size.width = _CGRectGetWidth(columnRect);
return headerRect;
}
- (void)setDrawsColumnLines:(BOOL)aFlag
{
_drawsColumnLines = aFlag;
}
- (BOOL)drawsColumnLines
{
return _drawsColumnLines;
}
- (CGRect)_cursorRectForColumn:(int)column
{
if (column == -1 || !([_tableView._tableColumns[column] resizingMask] & CPTableColumnUserResizingMask))
return _CGRectMakeZero();
var rect = [self headerRectOfColumn:column];
rect.origin.x = _CGRectGetMaxX(rect) - 5;
rect.size.width = 20;
return rect;
}
- (void)_setPressedColumn:(CPInteger)column
{
if (_pressedColumn != -1)
{
var headerView = [_tableView._tableColumns[_pressedColumn] headerView];
[headerView unsetThemeState:CPThemeStateHighlighted];
}
if (column != -1)
{
var headerView = [_tableView._tableColumns[column] headerView];
[headerView setThemeState:CPThemeStateHighlighted];
}
_pressedColumn = column;
}
- (void)mouseDown:(CPEvent)theEvent
{
[self trackMouse:theEvent];
}
- (void)trackMouse:(CPEvent)theEvent
{
var type = [theEvent type],
currentLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil];
// Take the right columns resize tracking area into account
currentLocation.x -= 5.0;
var columnIndex = [self columnAtPoint:currentLocation],
shouldResize = [self shouldResizeTableColumn:columnIndex at:_CGPointMake(currentLocation.x + 5.0, currentLocation.y)];
if (type === CPLeftMouseUp)
{
if (shouldResize)
[self stopResizingTableColumn:_activeColumn at:currentLocation];
else if ([self _shouldStopTrackingTableColumn:columnIndex at:currentLocation])
{
[_tableView _didClickTableColumn:columnIndex modifierFlags:[theEvent modifierFlags]];
[self stopTrackingTableColumn:columnIndex at:currentLocation];
_isTrackingColumn = NO;
}
[self _updateResizeCursor:[CPApp currentEvent]];
_activeColumn = CPNotFound;
return;
}
if (type === CPLeftMouseDown)
{
if (columnIndex === -1)
return;
_mouseDownLocation = currentLocation;
_activeColumn = columnIndex;
[_tableView _sendDelegateDidMouseDownInHeader:columnIndex];
if (shouldResize)
[self startResizingTableColumn:columnIndex at:currentLocation];
else
{
[self startTrackingTableColumn:columnIndex at:currentLocation];
_isTrackingColumn = YES;
}
}
else if (type === CPLeftMouseDragged)
{
if (shouldResize)
[self continueResizingTableColumn:_activeColumn at:currentLocation];
else
{
if (_activeColumn === columnIndex && _CGRectContainsPoint([self headerRectOfColumn:columnIndex], currentLocation))
{
if (_isTrackingColumn && _pressedColumn !== -1)
{
if (![self continueTrackingTableColumn:columnIndex at:currentLocation])
return; // Stop tracking the column, because it's being dragged
} else
[self startTrackingTableColumn:columnIndex at:currentLocation];
} else if (_isTrackingColumn && _pressedColumn !== -1)
[self stopTrackingTableColumn:_activeColumn at:currentLocation];
}
}
_previousTrackingLocation = currentLocation;
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (void)startTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
[self _setPressedColumn:aColumnIndex];
}
- (BOOL)continueTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
if ([self _shouldDragTableColumn:aColumnIndex at:aPoint])
{
var columnRect = [self headerRectOfColumn:aColumnIndex],
offset = _CGPointMakeZero(),
view = [_tableView _dragViewForColumn:aColumnIndex event:[CPApp currentEvent] offset:offset],
viewLocation = _CGPointMakeZero();
viewLocation.x = ( _CGRectGetMinX(columnRect) + offset.x ) + ( aPoint.x - _mouseDownLocation.x );
viewLocation.y = _CGRectGetMinY(columnRect) + offset.y;
[self dragView:view at:viewLocation offset:_CGSizeMakeZero() event:[CPApp currentEvent]
pasteboard:[CPPasteboard pasteboardWithName:CPDragPboard] source:self slideBack:YES];
return NO;
}
return YES;
}
- (BOOL)_shouldStopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
return _isTrackingColumn && _activeColumn === aColumnIndex &&
_CGRectContainsPoint([self headerRectOfColumn:aColumnIndex], aPoint);
}
- (void)stopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
[self _setPressedColumn:CPNotFound];
[self _updateResizeCursor:[CPApp currentEvent]];
}
- (BOOL)_shouldDragTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
return [_tableView allowsColumnReordering] && ABS(aPoint.x - _mouseDownLocation.x) >= 10.0;
}
- (CGRect)_headerRectOfLastVisibleColumn
{
var tableColumns = [_tableView tableColumns],
columnIndex = [tableColumns count];
while (columnIndex--)
{
var tableColumn = [tableColumns objectAtIndex:columnIndex];
if (![tableColumn isHidden])
return [self headerRectOfColumn:columnIndex];
}
return nil;
}
- (void)_constrainDragView:(CPView)theDragView at:(CGPoint)aPoint
{
var tableColumns = [_tableView tableColumns],
lastColumnRect = [self _headerRectOfLastVisibleColumn],
activeColumnRect = [self headerRectOfColumn:_activeColumn],
dragWindow = [theDragView window],
frame = [dragWindow frame];
// Convert the frame origin from the global coordinate system to the windows' coordinate system
frame.origin = [[self window] convertGlobalToBase:frame.origin];
// the from the window to the view
frame.origin = [self convertPoint:frame.origin fromView:nil];
// This effectively clamps the value between the minimum and maximum
frame.origin.x = MAX(0.0, MIN(_CGRectGetMinX(frame), _CGRectGetMaxX(lastColumnRect) - _CGRectGetWidth(activeColumnRect)));
// Make sure the column cannot move vertically
frame.origin.y = _CGRectGetMinY(lastColumnRect);
// Convert the calculated origin back to the window coordinate system
frame.origin = [self convertPoint:frame.origin toView:nil];
// Then back to the global coordinate system
frame.origin = [[self window] convertBaseToGlobal:frame.origin];
[dragWindow setFrame:frame];
}
- (void)_moveColumn:(int)aFromIndex toColumn:(int)aToIndex
{
[_tableView moveColumn:aFromIndex toColumn:aToIndex];
_activeColumn = aToIndex;
_pressedColumn = _activeColumn;
}
- (void)draggedView:(CPView)aView beganAt:(CGPoint)aPoint
{
_isDragging = YES;
var column = [[_tableView tableColumns] objectAtIndex:_activeColumn];
[[column headerView] setHidden:YES];
[_tableView _setDraggedColumn:column];
[self setNeedsDisplay:YES];
}
- (void)draggedView:(CPView)aView movedTo:(CGPoint)aPoint
{
[self _constrainDragView:aView at:aPoint];
var dragWindow = [aView window],
dragWindowFrame = [dragWindow frame];
var hoverPoint = CGPointCreateCopy(aPoint);
if (aPoint.x < _previousTrackingLocation.x)
hoverPoint = _CGPointMake(_CGRectGetMinX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
else if (aPoint.x > _previousTrackingLocation.x)
hoverPoint = _CGPointMake(_CGRectGetMaxX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
// Convert the hover point from the global coordinate system to windows' coordinate system
hoverPoint = [[self window] convertGlobalToBase:hoverPoint];
// then to the view
hoverPoint = [self convertPoint:hoverPoint fromView:nil];
var hoveredColumn = [self columnAtPoint:hoverPoint];
if (hoveredColumn !== -1)
{
var columnRect = [self headerRectOfColumn:hoveredColumn],
columnCenterPoint = [self convertPoint:CGPointMake(_CGRectGetMidX(columnRect), _CGRectGetMidY(columnRect)) fromView:self];
if (hoveredColumn < _activeColumn && hoverPoint.x < columnCenterPoint.x)
[self _moveColumn:_activeColumn toColumn:hoveredColumn];
else if (hoveredColumn > _activeColumn && hoverPoint.x > columnCenterPoint.x)
[self _moveColumn:_activeColumn toColumn:hoveredColumn];
}
_previousTrackingLocation = aPoint;
}
- (void)draggedView:(CPImage)aView endedAt:(CGPoint)aLocation operation:(CPDragOperation)anOperation
{
_isDragging = NO;
_isTrackingColumn = NO; // We need to do this explicitly because the mouse up section of trackMouse is never reached
[_tableView _setDraggedColumn:nil];
[[[[_tableView tableColumns] objectAtIndex:_activeColumn] headerView] setHidden:NO];
[self stopTrackingTableColumn:_activeColumn at:aLocation];
[self setNeedsDisplay:YES];
}
- (BOOL)shouldResizeTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
if (_isResizing)
return YES;
if (_isTrackingColumn)
return NO;
return [_tableView allowsColumnResizing] && _CGRectContainsPoint([self _cursorRectForColumn:aColumnIndex], aPoint);
}
- (void)startResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
_isResizing = YES;
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
[tableColumn setDisableResizingPosting:YES];
[_tableView setDisableAutomaticResizing:YES];
}
- (void)continueResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex],
newWidth = [tableColumn width] + aPoint.x - _previousTrackingLocation.x;
if (newWidth < [tableColumn minWidth])
[[CPCursor resizeRightCursor] set];
else if (newWidth > [tableColumn maxWidth])
[[CPCursor resizeLeftCursor] set];
else
{
_tableView._lastColumnShouldSnap = NO;
[tableColumn setWidth:newWidth];
[[CPCursor resizeLeftRightCursor] set];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
}
- (void)stopResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
[tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
[tableColumn setDisableResizingPosting:NO];
[_tableView setDisableAutomaticResizing:NO];
_isResizing = NO;
}
- (void)_updateResizeCursor:(CPEvent)theEvent
{
// never get stuck in resize cursor mode (FIXME take out when we turn on tracking rects)
if (![_tableView allowsColumnResizing] || ([theEvent type] === CPLeftMouseUp && ![[self window] acceptsMouseMovedEvents]))
{
[[CPCursor arrowCursor] set];
return;
}
var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
mouseOverLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
overColumn = [self columnAtPoint:mouseOverLocation];
if (overColumn >= 0 && _CGRectContainsPoint([self _cursorRectForColumn:overColumn], mouseLocation))
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn],
width = [tableColumn width];
if (width == [tableColumn minWidth])
[[CPCursor resizeRightCursor] set];
else if (width == [tableColumn maxWidth])
[[CPCursor resizeLeftCursor] set];
else
[[CPCursor resizeLeftRightCursor] set];
}
else
[[CPCursor arrowCursor] set];
}
- (void)mouseEntered:(CPEvent)theEvent
{
[self _updateResizeCursor:theEvent];
}
- (void)mouseMoved:(CPEvent)theEvent
{
[self _updateResizeCursor:theEvent];
}
- (void)mouseExited:(CPEvent)theEvent
{
// FIXME: we should use CPCursor push/pop (if previous currentCursor != arrow).
[[CPCursor arrowCursor] set];
}
- (void)layoutSubviews
{
var tableColumns = [_tableView tableColumns],
count = [tableColumns count];
for (var i = 0; i < count; i++)
{
var column = [tableColumns objectAtIndex:i],
headerView = [column headerView];
var frame = [self headerRectOfColumn:i];
frame.size.height -= 0.5;
if (i > 0)
{
frame.origin.x += 0.5;
frame.size.width -= 1;
}
[headerView setFrame:frame];
if([headerView superview] != self)
[self addSubview:headerView];
}
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
}
- (void)drawRect:(CGRect)aRect
{
if (!_tableView || ![self drawsColumnLines])
return;
var context = [[CPGraphicsContext currentContext] graphicsPort],
exposedColumnIndexes = [_tableView columnIndexesInRect:aRect],
columnsArray = [],
tableColumns = [_tableView tableColumns],
exposedTableColumns = _tableView._exposedColumns,
firstIndex = [exposedTableColumns firstIndex],
exposedRange = CPMakeRange(firstIndex, [exposedTableColumns lastIndex] - firstIndex + 1);
CGContextSetLineWidth(context, 1);
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"divider-color"]);
[exposedColumnIndexes getIndexes:columnsArray maxCount:-1 inIndexRange:exposedRange];
var columnArrayIndex = 0,
columnArrayCount = columnsArray.length,
columnMaxX;
CGContextBeginPath(context);
for(; columnArrayIndex < columnArrayCount; columnArrayIndex++)
{
// grab each column rect and add vertical lines
var columnIndex = columnsArray[columnArrayIndex],
columnToStroke = [self headerRectOfColumn:columnIndex];
columnMaxX = _CGRectGetMaxX(columnToStroke);
CGContextMoveToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(_CGRectGetMinY(columnToStroke)));
CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(_CGRectGetMaxY(columnToStroke)));
}
CGContextClosePath(context);
CGContextStrokePath(context);
/*if (_isDragging)
{
CGContextSetFillColor(context, [CPColor grayColor]);
CGContextFillRect(context, [self headerRectOfColumn:_activeColumn])
}*/
}
@end
var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey",
CPTableHeaderViewDrawsColumnLines = @"CPTableHeaderViewDrawsColumnLines";
@implementation CPTableHeaderView (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
[self _init];
_tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
_drawsColumnLines = [aCoder decodeBoolForKey:CPTableHeaderViewDrawsColumnLines];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_tableView forKey:CPTableHeaderViewTableViewKey];
[aCoder encodeBool:_drawsColumnLines forKey:CPTableHeaderViewDrawsColumnLines];
}
@end
+3697 -1095
View File
File diff suppressed because it is too large Load Diff
+30
View File
@@ -0,0 +1,30 @@
/*
* CPText.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2010, WireLoad, LLC.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
CPEnterCharacter = "\u0003";
CPBackspaceCharacter = "\u0008";
CPTabCharacter = "\u0009";
CPNewlineCharacter = "\u000a";
CPFormFeedCharacter = "\u000c";
CPCarriageReturnCharacter = "\u000d";
CPBackTabCharacter = "\u0019";
CPDeleteCharacter = "\u007f";
+552 -240
View File
File diff suppressed because it is too large Load Diff
+219 -20
View File
@@ -22,10 +22,12 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@import <Foundation/CPKeyedUnarchiver.j>
var CPThemesByName = { },
CPThemeDefaultTheme = nil;
var CPThemesByName = { },
CPThemeDefaultTheme = nil,
CPThemeDefaultHudTheme = nil;
/*!
@@ -48,6 +50,27 @@ var CPThemesByName = { },
return CPThemeDefaultTheme;
}
/*!
Set the default HUD theme. If set to nil, the default described in defaultHudTheme
will be used.
*/
+ (void)setDefaultHudTheme:(CPTheme)aTheme
{
CPThemeDefaultHudTheme = aTheme;
}
/*!
The default HUD theme is (sometimes) used for windows with the CPHUDBackgroundWindowMask
style mask. The default is theme with the name of the default theme with -HUD appended
at the end.
*/
+ (CPTheme)defaultHudTheme
{
if (!CPThemeDefaultHudTheme)
CPThemeDefaultHudTheme = [CPTheme themeNamed:[[self defaultTheme] name] + "-HUD"];
return CPThemeDefaultHudTheme;
}
+ (CPTheme)themeNamed:(CPString)aName
{
return CPThemesByName[aName];
@@ -73,9 +96,110 @@ var CPThemesByName = { },
return _name;
}
- (_CPThemeAttribute)_attributeWithName:(CPString)aName forClass:(CPString)aClass
/*!
Returns an array of names of themed classes defined in this theme, as found in its
ThemeDescriptors.j file.
NOTE: The names are not class names (such as "CPButton"), but the names returned
by the class' +defaultThemeClass method. For example, the name for CPCheckBox is "check-box",
as defined in CPCheckBox::themeClass.
*/
- (CPArray)classNames
{
var attributes = [_attributes objectForKey:aClass];
return [_attributes allKeys];
}
/*!
Returns a dictionary of all theme attributes defined for the given class, as found in the
theme's ThemeDescriptors.j file. The keys of the dictionary are attribute names, and the values
are instances of _CPThemeAttribute.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aClass The themed class whose attributes you want to retrieve
@return A dictionary of attributes or nil
*/
- (CPDictionary)attributesForClass:(id)aClass
{
if (!aClass)
return nil;
var className = nil;
if ([aClass isKindOfClass:[CPString class]])
{
// See if it is a class name
var theClass = CPClassFromString(aClass);
if (theClass)
aClass = theClass;
else
className = aClass;
}
if (!className)
{
if ([aClass isKindOfClass:[CPView class]])
{
if ([aClass respondsToSelector:@selector(defaultThemeClass)])
className = [aClass defaultThemeClass];
else if ([aClass respondsToSelector:@selector(themeClass)])
{
CPLog.warn(@"%@ themeClass is deprecated in favor of defaultThemeClass",CPStringFromClass([anObject class]));
className = [aClass themeClass];
}
else
return nil;
}
else
[CPException raise:CPInvalidArgumentException reason:@"aClass must be a class object or a string."];
}
return [_attributes objectForKey:className];
}
/*!
Returns an array of names of all theme attributes defined for the given class, as found in the
theme's ThemeDescriptors.j file.
The \c aClass parameter can be one of the following:
- A class instance, for example the result of [CPCheckBox class]. The class must be a subclass
of CPView.
- A class name, for example "CPCheckBox".
- A themed class name, for example "check-box".
If \c aClass does not refer to a themed class in this theme, nil is returned.
@param aClass The themed class whose attributes you want to retrieve
@return An array of attribute names or nil
*/
- (CPDictionary)attributeNamesForClass:(id)aClass
{
var attributes = [self attributesForClass:aClass];
if (attributes)
return [attributes allKeys];
else
return [CPArray array];
}
/*!
Returns a theme attribute defined for the given class, as found in the
theme's ThemeDescriptors.j file.
\c aName should be the attribute name as you would pass to the method
CPView::valueForThemeAttribute:.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aName The name of the attribute you want to retrieve
@param aClass The themed class in which to look for the attribute
@return An instance of _CPThemeAttribute or nil
*/
- (_CPThemeAttribute)attributeWithName:(CPString)aName forClass:(id)aClass
{
var attributes = [self attributesForClass:aClass];
if (!attributes)
return nil;
@@ -83,12 +207,53 @@ var CPThemesByName = { },
return [attributes objectForKey:aName];
}
/*!
Returns the value for a theme attribute in its normal state, as defined for the given class
in the theme's ThemeDescriptors.j file.
\c aName should be the attribute name as you would pass to the method
CPView::valueForThemeAttribute:.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aName The name of the attribute whose value you want to retrieve
@param aClass The themed class in which to look for the attribute
@return A value or nil
*/
- (id)valueForAttributeWithName:(CPString)aName forClass:(id)aClass
{
return [self valueForAttributeWithName:aName inState:CPThemeStateNormal forClass:aClass];
}
/*!
Returns the value for a theme attribute in a given state, as defined for the given class
in the theme's ThemeDescriptors.j file. This is the equivalent of the method
CPView::valueForThemeAttribute:inState:, but retrieves the value from the theme definition as
opposed to a single view's current theme state.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aName The name of the attribute whose value you want to retrieve
@param aState The state qualifier for the attribute
@param aClass The themed class in which to look for the attribute
@return A value or nil
*/
- (id)valueForAttributeWithName:(CPString)aName inState:(CPThemeState)aState forClass:(id)aClass
{
var attribute = [self attributeWithName:aName forClass:aClass];
if (!attribute)
return nil;
return [attribute valueForState:aState];
}
- (void)takeThemeFromObject:(id)anObject
{
var attributes = [anObject _themeAttributeDictionary],
attributeName = nil,
attributeNames = [attributes keyEnumerator],
objectThemeClass = [[anObject class] themeClass];
objectThemeClass = [anObject themeClass];
while (attributeName = [attributeNames nextObject])
[self _recordAttribute:[attributes objectForKey:attributeName] forClass:objectThemeClass];
@@ -242,6 +407,9 @@ CPThemeStateNormal = CPThemeStates["normal"] = 0;
CPThemeStateDisabled = CPThemeState("disabled");
CPThemeStateHighlighted = CPThemeState("highlighted");
CPThemeStateSelected = CPThemeState("selected");
CPThemeStateTableDataView = CPThemeState("tableDataView");
CPThemeStateSelectedDataView = CPThemeStateSelectedTableDataView = CPThemeState("selectedTableDataView");
CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
CPThemeStateBezeled = CPThemeState("bezeled");
CPThemeStateBordered = CPThemeState("bordered");
CPThemeStateEditable = CPThemeState("editable");
@@ -254,10 +422,10 @@ CPThemeStateCircular = CPThemeState("circular");
{
CPString _name;
id _defaultValue;
CPDictionary _values;
CPDictionary _values @accessors(readonly, getter=values);
JSObject _cache;
CPThemeAttribute _parentAttribute;
_CPThemeAttribute _parentAttribute;
}
- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue
@@ -378,7 +546,7 @@ CPThemeStateCircular = CPThemeState("circular");
return value;
}
- (void)setParentAttribute:(CPThemeAttribute)anAttribute
- (void)setParentAttribute:(_CPThemeAttribute)anAttribute
{
if (_parentAttribute === anAttribute)
return;
@@ -387,7 +555,7 @@ CPThemeStateCircular = CPThemeState("circular");
_parentAttribute = anAttribute;
}
- (CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
- (_CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
{
var mergedAttribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue];
@@ -472,15 +640,15 @@ CPThemeStateCircular = CPThemeState("circular");
@end
var cachedNumberOfOnes = [ 0 /*000000*/, 1 /*000001*/, 1 /*000010*/, 2 /*000011*/, 1 /*000100*/, 2 /*000101*/, 2 /*000110*/,
3 /*000111*/, 1 /*001000*/, 2 /*001001*/, 2 /*001010*/, 3 /*001011*/, 2 /*001100*/, 3 /*001101*/,
3 /*001110*/, 4 /*001111*/, 1 /*010000*/, 2 /*010001*/, 2 /*010010*/, 3 /*010011*/, 2 /*010100*/,
3 /*010101*/, 3 /*010110*/, 4 /*010111*/, 2 /*011000*/, 3 /*011001*/, 3 /*011010*/, 4 /*011011*/,
3 /*011100*/, 4 /*011101*/, 4 /*011110*/, 5 /*011111*/, 1 /*100000*/, 2 /*100001*/, 2 /*100010*/,
3 /*100011*/, 2 /*100100*/, 3 /*100101*/, 3 /*100110*/, 4 /*100111*/, 2 /*101000*/, 3 /*101001*/,
3 /*101010*/, 4 /*101011*/, 3 /*101100*/, 4 /*101101*/, 4 /*101110*/, 5 /*101111*/, 2 /*110000*/,
3 /*110001*/, 3 /*110010*/, 4 /*110011*/, 3 /*110100*/, 4 /*110101*/, 4 /*110110*/, 5 /*110111*/,
3 /*111000*/, 4 /*111001*/, 4 /*111010*/, 5 /*111011*/, 4 /*111100*/, 5 /*111101*/, 5 /*111110*/,
var cachedNumberOfOnes = [ 0 /*000000*/, 1 /*000001*/, 1 /*000010*/, 2 /*000011*/, 1 /*000100*/, 2 /*000101*/, 2 /*000110*/,
3 /*000111*/, 1 /*001000*/, 2 /*001001*/, 2 /*001010*/, 3 /*001011*/, 2 /*001100*/, 3 /*001101*/,
3 /*001110*/, 4 /*001111*/, 1 /*010000*/, 2 /*010001*/, 2 /*010010*/, 3 /*010011*/, 2 /*010100*/,
3 /*010101*/, 3 /*010110*/, 4 /*010111*/, 2 /*011000*/, 3 /*011001*/, 3 /*011010*/, 4 /*011011*/,
3 /*011100*/, 4 /*011101*/, 4 /*011110*/, 5 /*011111*/, 1 /*100000*/, 2 /*100001*/, 2 /*100010*/,
3 /*100011*/, 2 /*100100*/, 3 /*100101*/, 3 /*100110*/, 4 /*100111*/, 2 /*101000*/, 3 /*101001*/,
3 /*101010*/, 4 /*101011*/, 3 /*101100*/, 4 /*101101*/, 4 /*101110*/, 5 /*101111*/, 2 /*110000*/,
3 /*110001*/, 3 /*110010*/, 4 /*110011*/, 3 /*110100*/, 4 /*110101*/, 4 /*110110*/, 5 /*110111*/,
3 /*111000*/, 4 /*111001*/, 4 /*111010*/, 5 /*111011*/, 4 /*111100*/, 5 /*111101*/, 5 /*111110*/,
6 /*111111*/ ];
var numberOfOnes = function(aNumber)
@@ -531,7 +699,7 @@ function CPThemeAttributeEncode(aCoder, aThemeAttribute)
function CPThemeAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme, aClass)
{
var key = "$a" + anAttributeName;
var key = "$a" + anAttributeName;
if (![aCoder containsValueForKey:key])
var attribute = [[_CPThemeAttribute alloc] initWithName:anAttributeName defaultValue:aDefaultValue];
@@ -551,7 +719,38 @@ function CPThemeAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme,
}
if (aTheme && aClass)
[attribute setParentAttribute:[aTheme _attributeWithName:anAttributeName forClass:aClass]];
[attribute setParentAttribute:[aTheme attributeWithName:anAttributeName forClass:aClass]];
return attribute;
}
/* TO AUTO CREATE THESE:
function bit_count(bits)
{
var count = 0;
while (bits)
{
++count;
bits &= (bits - 1);
}
return count ;
}
zeros = "000000000";
function pad(string, digits)
{
return zeros.substr(0, digits - string.length) + string;
}
var str = ""
str += '[';
for (i = 0;i < Math.pow(2,6);++i)
{
str += bit_count(i) + " /*" + pad(i.toString(2),6) + "*" + "/, ";
}
print(str+']');
*/
+42 -24
View File
@@ -22,9 +22,10 @@
@import <Foundation/CPObject.j>
@import <AppKit/CPTheme.j>
@import <AppKit/_CPCibCustomResource.j>
@import <AppKit/_CPCibKeyedUnarchiver.j>
@import "CPTheme.j"
@import "_CPCibCustomResource.j"
@import "_CPCibKeyedUnarchiver.j"
/*!
@ingroup appkit
@@ -33,52 +34,69 @@
@implementation CPThemeBlend : CPObject
{
CPBundle _bundle;
CPArray _themes @accessors(readonly, getter=themes);
CPArray _themes;
id _loadDelegate;
}
- (id)initWithContentsOfURL:(CPURL)aURL
{
self = [super init];
if (self)
{
_bundle = [[CPBundle alloc] initWithPath:aURL + "/Info.plist"];
_bundle = [[CPBundle alloc] initWithPath:aURL];
}
return self;
}
/*!
Returns an array of names of the keyed theme archives that make up this blend.
Each item in the array will have the extension ".keyedtheme".
*/
- (CPArray)themes
{
return _themes;
}
/*!
Returns an array of names of the themes that make up this blend.
*/
- (CPArray)themeNames
{
var names = [];
for (var i = 0; i < _themes.length; ++i)
names.push(_themes[i].substring(0, _themes[i].indexOf(".keyedtheme")));
return names;
}
- (void)loadWithDelegate:(id)aDelegate
{
_loadDelegate = aDelegate;
[_bundle loadWithDelegate:self];
}
- (void)bundleDidFinishLoading:(CPBundle)aBundle
{
var paths = [_bundle objectForInfoDictionaryKey:@"CPBundleReplacedFiles"],
index = 0,
count = paths.length,
bundlePath = [_bundle bundlePath];
_themes = [_bundle objectForInfoDictionaryKey:@"CPKeyedThemes"];
var count = _themes.length;
while (count--)
{
var path = paths[count];
if ([path pathExtension] === "keyedtheme")
{
var unarchiver = [[_CPThemeKeyedUnarchiver alloc]
initForReadingWithData:[CPData dataWithString:objj_files[bundlePath + '/' + path].contents]
bundle:_bundle];
var path = [aBundle pathForResource:_themes[count]],
unarchiver = [[_CPThemeKeyedUnarchiver alloc]
initForReadingWithData:[[CPURL URLWithString:path] staticResourceData]
bundle:_bundle];
[unarchiver decodeObjectForKey:@"root"];
[unarchiver decodeObjectForKey:@"root"];
[unarchiver finishDecoding];
}
[unarchiver finishDecoding];
}
[_loadDelegate blendDidFinishLoading:self];
}
+1250
View File
File diff suppressed because it is too large Load Diff
+610 -322
View File
File diff suppressed because it is too large Load Diff
+180 -90
View File
@@ -23,38 +23,22 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@import <AppKit/CPImage.j>
@import <AppKit/CPView.j>
@import "CPImage.j"
@import "CPView.j"
/*
@global
@class CPToolbarItem
*/
CPToolbarItemVisibilityPriorityStandard = 0;
/*
@global
@class CPToolbarItem
*/
CPToolbarItemVisibilityPriorityLow = -1000;
/*
@global
@class CPToolbarItem
*/
CPToolbarItemVisibilityPriorityHigh = 1000;
/*
@global
@class CPToolbarItem
*/
CPToolbarItemVisibilityPriorityUser = 2000;
CPToolbarSeparatorItemIdentifier = @"CPToolbarSeparatorItemIdentifier";
CPToolbarSpaceItemIdentifier = @"CPToolbarSpaceItemIdentifier";
CPToolbarFlexibleSpaceItemIdentifier = @"CPToolbarFlexibleSpaceItemIdentifier";
CPToolbarShowColorsItemIdentifier = @"CPToolbarShowColorsItemIdentifier";
CPToolbarShowFontsItemIdentifier = @"CPToolbarShowFontsItemIdentifier";
CPToolbarCustomizeToolbarItemIdentifier = @"CPToolbarCustomizeToolbarItemIdentifier";
CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
CPToolbarSeparatorItemIdentifier = @"CPToolbarSeparatorItem";
CPToolbarSpaceItemIdentifier = @"CPToolbarSpaceItem";
CPToolbarFlexibleSpaceItemIdentifier = @"CPToolbarFlexibleSpaceItem";
CPToolbarShowColorsItemIdentifier = @"CPToolbarShowColorsItem";
CPToolbarShowFontsItemIdentifier = @"CPToolbarShowFontsItem";
CPToolbarCustomizeToolbarItemIdentifier = @"CPToolbarCustomizeToolbarItem";
CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
/*!
@ingroup appkit
@@ -84,6 +68,13 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
CGSize _maxSize;
int _visibilityPriority;
BOOL _autovalidates;
}
- (id)init
{
return [self initWithItemIdentifier:@""];
}
// Creating a Toolbar Item
@@ -107,6 +98,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
_maxSize = CGSizeMakeZero();
_visibilityPriority = CPToolbarItemVisibilityPriorityStandard;
_autovalidates = YES;
}
return self;
@@ -129,6 +121,12 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
return _toolbar;
}
/* @ignore */
- (void)_setToolbar:(CPToolbar)aToolbar
{
_toolbar = aToolbar;
}
/*!
Returns the item's label
*/
@@ -183,7 +181,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
- (void)setToolTip:(CPString)aToolTip
{
if ([_view respondsToSelector:@selector(setToolTip:)])
[view setToolTip:aToolTip];
[_view setToolTip:aToolTip];
_toolTip = aToolTip;
}
@@ -223,7 +221,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
}
/*!
Sets the target of the action that is triggered when the user clicks this item. <code>nil</code> will cause
Sets the target of the action that is triggered when the user clicks this item. \c nil will cause
the action to be passed on to the first responder.
@param aTarget the new target
*/
@@ -261,7 +259,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
}
/*!
Returns <code>YES</code> if the item is enabled.
Returns \c YES if the item is enabled.
*/
- (BOOL)isEnabled
{
@@ -273,7 +271,7 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
/*!
Sets whether the item is enabled.
@param aFlag <code>YES</code> enables the item
@param aFlag \c YES enables the item
*/
- (void)setEnabled:(BOOL)shouldBeEnabled
{
@@ -308,8 +306,8 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
if (!_image)
return;
if (_minSize.width == 0 && _minSize.height == 0 &&
_maxSize.width == 0 && _maxSize.height == 0)
if (_minSize.width === 0 && _minSize.height === 0 &&
_maxSize.width === 0 && _maxSize.height === 0)
{
var imageSize = [_image size];
@@ -388,6 +386,9 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
*/
- (void)setMinSize:(CGSize)aMinSize
{
if(!aMinSize.height || !aMinSize.width)
return;
_minSize = CGSizeMakeCopy(aMinSize);
// Try to provide some sanity: Make maxSize >= minSize
@@ -408,6 +409,9 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier";
*/
- (void)setMaxSize:(CGSize)aMaxSize
{
if(!aMaxSize.height || !aMaxSize.width)
return;
_maxSize = CGSizeMakeCopy(aMaxSize);
// Try to provide some sanity: Make minSize <= maxSize
@@ -444,6 +448,127 @@ CPToolbarItemVisibilityPriorityUser
_visibilityPriority = aVisibilityPriority;
}
- (void)validate
{
var action = [self action],
target = [self target];
// View items do not do any target-action analysis.
if (_view)
{
if ([target respondsToSelector:@selector(validateToolbarItem:)])
[self setEnabled:[target validateToolbarItem:self]];
return;
}
if (!action)
return [self setEnabled:NO];
if (target && ![target respondsToSelector:action])
return [self setEnabled:NO];
target = [CPApp targetForAction:action to:target from:self];
if (!target)
return [self setEnabled:NO];
if ([target respondsToSelector:@selector(validateToolbarItem:)])
[self setEnabled:[target validateToolbarItem:self]];
else
[self setEnabled:YES];
}
- (BOOL)autovalidates
{
return _autovalidates;
}
- (void)setAutovalidates:(BOOL)shouldAutovalidate
{
_autovalidates = !!shouldAutovalidate;
}
@end
var CPToolbarItemItemIdentifierKey = @"CPToolbarItemItemIdentifierKey",
CPToolbarItemLabelKey = @"CPToolbarItemLabelKey",
CPToolbarItemPaletteLabelKey = @"CPToolbarItemPaletteLabelKey",
CPToolbarItemToolTipKey = @"CPToolbarItemToolTipKey",
CPToolbarItemTagKey = @"CPToolbarItemTagKey",
CPToolbarItemTargetKey = @"CPToolbarItemTargetKey",
CPToolbarItemActionKey = @"CPToolbarItemActionKey",
CPToolbarItemEnabledKey = @"CPToolbarItemEnabledKey",
CPToolbarItemImageKey = @"CPToolbarItemImageKey",
CPToolbarItemAlternateImageKey = @"CPToolbarItemAlternateImageKey",
CPToolbarItemViewKey = @"CPToolbarItemViewKey",
CPToolbarItemMinSizeKey = @"CPToolbarItemMinSizeKey",
CPToolbarItemMaxSizeKey = @"CPToolbarItemMaxSizeKey",
CPToolbarItemVisibilityPriorityKey = @"CPToolbarItemVisibilityPriorityKey",
CPToolbarItemAutovalidatesKey = @"CPToolbarItemAutovalidatesKey";
@implementation CPToolbarItem (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_itemIdentifier = [aCoder decodeObjectForKey:CPToolbarItemItemIdentifierKey];
_minSize = [aCoder decodeSizeForKey:CPToolbarItemMinSizeKey];
_maxSize = [aCoder decodeSizeForKey:CPToolbarItemMaxSizeKey];
[self setLabel:[aCoder decodeObjectForKey:CPToolbarItemLabelKey]];
[self setPaletteLabel:[aCoder decodeObjectForKey:CPToolbarItemPaletteLabelKey]];
[self setToolTip:[aCoder decodeObjectForKey:CPToolbarItemToolTipKey]];
[self setTag:[aCoder decodeObjectForKey:CPToolbarItemTagKey]];
[self setTarget:[aCoder decodeObjectForKey:CPToolbarItemTargetKey]];
[self setAction:CPSelectorFromString([aCoder decodeObjectForKey:CPToolbarItemActionKey])];
[self setEnabled:[aCoder decodeBoolForKey:CPToolbarItemEnabledKey]];
[self setImage:[aCoder decodeObjectForKey:CPToolbarItemImageKey]];
[self setAlternateImage:[aCoder decodeObjectForKey:CPToolbarItemAlternateImageKey]];
[self setView:[aCoder decodeObjectForKey:CPToolbarItemViewKey]];
[self setVisibilityPriority:[aCoder decodeIntForKey:CPToolbarItemVisibilityPriorityKey]];
[self setAutovalidates:[aCoder decodeBoolForKey:CPToolbarItemAutovalidatesKey]];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_itemIdentifier forKey:CPToolbarItemItemIdentifierKey];
[aCoder encodeObject:[self label] forKey:CPToolbarItemLabelKey];
[aCoder encodeObject:[self paletteLabel] forKey:CPToolbarItemPaletteLabelKey];
[aCoder encodeObject:[self toolTip] forKey:CPToolbarItemToolTipKey];
[aCoder encodeObject:[self tag] forKey:CPToolbarItemTagKey];
[aCoder encodeObject:[self target] forKey:CPToolbarItemTargetKey];
[aCoder encodeObject:[self action] forKey:CPToolbarItemActionKey];
[aCoder encodeObject:[self isEnabled] forKey:CPToolbarItemEnabledKey];
[aCoder encodeObject:[self image] forKey:CPToolbarItemImageKey];
[aCoder encodeObject:[self alternateImage] forKey:CPToolbarItemAlternateImageKey];
[aCoder encodeObject:[self view] forKey:CPToolbarItemViewKey];
[aCoder encodeSize:[self minSize] forKey:CPToolbarItemMinSizeKey];
[aCoder encodeSize:[self maxSize] forKey:CPToolbarItemMaxSizeKey];
[aCoder encodeObject:[self visibilityPriority] forKey:CPToolbarItemVisibilityPriorityKey];
[aCoder encodeBool:[self autovalidates] forKey:CPToolbarItemAutovalidatesKey];
}
@end
@implementation CPToolbarItem (CPCopying)
@@ -451,27 +576,31 @@ CPToolbarItemVisibilityPriorityUser
- (id)copy
{
var copy = [[[self class] alloc] initWithItemIdentifier:_itemIdentifier];
if (_view)
[copy setView:[CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:_view]]];
[copy _setToolbar:_toolbar];
[copy setLabel:_label];
[copy setPaletteLabel:_paletteLabel];
[copy setToolTip:[self toolTip]];
[copy setTag:[self tag]];
[copy setTarget:[self target]];
[copy setAction:[self action]];
[copy setEnabled:[self isEnabled]];
[copy setImage:_image];
[copy setAlternateImage:_alternateImage];
[copy setImage:[self image]];
[copy setAlternateImage:[self alternateImage]];
[copy setMinSize:_minSize];
[copy setMaxSize:_maxSize];
[copy setVisibilityPriority:_visibilityPriority];
[copy setVisibilityPriority:[self visibilityPriority]];
[copy setAutovalidates:[self autovalidates]];
return copy;
}
@@ -479,62 +608,17 @@ CPToolbarItemVisibilityPriorityUser
// Standard toolbar identifiers
var _CPToolbarSeparatorItemView = nil,
_CPToolbarSpaceItemView = nil;
@implementation CPToolbarItem (Standard)
+ (CPView)_separatorItemView
{
if (!_CPToolbarSeparatorItemView)
{
_CPToolbarSeparatorItemView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 2.0, 32.0)];
sizes = {};
sizes[@"CPToolbarItemSeparator"] = [CGSizeMake(2.0, 26.0), CGSizeMake(2.0, 1.0), CGSizeMake(2.0, 26.0)];
[_CPToolbarSeparatorItemView setBackgroundColor:_CPControlThreePartImagePattern(YES, sizes, @"CPToolbarItem", @"Separator")];
}
return _CPToolbarSeparatorItemView;
}
+ (CPView)_spaceItemView
{
if (!_CPToolbarSpaceItemView)
_CPToolbarSpaceItemView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
return _CPToolbarSpaceItemView;
}
/* @ignore */
+ (CPToolbarItem)_standardItemWithItemIdentifier:(CPString)anItemIdentifier
{
var item = [[CPToolbarItem alloc] initWithItemIdentifier:anItemIdentifier];
switch (anItemIdentifier)
{
case CPToolbarSeparatorItemIdentifier: [item setView:[self _separatorItemView]];
[item setMinSize:CGSizeMake(2.0, 0.0)];
[item setMaxSize:CGSizeMake(2.0, 100000.0)];
return item;
case CPToolbarSpaceItemIdentifier: [item setView:[self _spaceItemView]];
[item setMinSize:CGSizeMake(32.0, 32.0)];
[item setMaxSize:CGSizeMake(32.0, 32.0)];
return item;
case CPToolbarFlexibleSpaceItemIdentifier: [item setView:[self _spaceItemView]];
[item setMinSize:CGSizeMake(32.0, 32.0)];
[item setMaxSize:CGSizeMake(10000.0, 32.0)];
return item;
case CPToolbarShowColorsItemIdentifier: return nil;
case CPToolbarSeparatorItemIdentifier: return [_CPToolbarSeparatorItem new];
case CPToolbarSpaceItemIdentifier: return [_CPToolbarSpaceItem new];
case CPToolbarFlexibleSpaceItemIdentifier: return [_CPToolbarFlexibleSpaceItem new];
case CPToolbarShowColorsItemIdentifier: return [_CPToolbarShowColorsItem new];
case CPToolbarShowFontsItemIdentifier: return nil;
case CPToolbarCustomizeToolbarItemIdentifier: return nil;
case CPToolbarPrintItemIdentifier: return nil;
@@ -544,3 +628,9 @@ var _CPToolbarSeparatorItemView = nil,
}
@end
@import "_CPToolbarFlexibleSpaceItem.j"
@import "_CPToolbarShowColorsItem.j"
@import "_CPToolbarSeparatorItem.j"
@import "_CPToolbarSpaceItem.j"
+316
View File
@@ -0,0 +1,316 @@
@import <Foundation/CPObject.j>
@implementation CPTreeNode : CPObject
{
id _representedObject @accessors(readonly, property=representedObject);
CPTreeNode _parentNode @accessors(readonly, property=parentNode);
CPMutableArray _childNodes;
}
+ (id)treeNodeWithRepresentedObject:(id)anObject
{
return [[self alloc] initWithRepresentedObject:anObject];
}
- (id)initWithRepresentedObject:(id)anObject
{
self = [super init];
if (self)
{
_representedObject = anObject;
_childNodes = [];
}
return self;
}
- (BOOL)isLeaf
{
return [_childNodes count] <= 0;
}
- (CPArray)childNodes
{
return [_childNodes copy];
}
- (CPMutableArray)mutableChildNodes
{
return [self mutableArrayValueForKey:@"childNodes"];
}
- (void)insertObject:(id)aTreeNode inChildNodesAtIndex:(CPInteger)anIndex
{
[[aTreeNode._parentNode mutableChildNodes] removeObjectIdenticalTo:aTreeNode];
aTreeNode._parentNode = self;
[_childNodes insertObject:aTreeNode atIndex:anIndex];
}
- (void)removeObjectFromChildNodesAtIndex:(CPInteger)anIndex
{
[_childNodes objectAtIndex:anIndex]._parentNode = nil;
[_childNodes removeObjectAtIndex:anIndex];
}
- (void)replaceObjectFromChildNodesAtIndex:(CPInteger)anIndex withObject:(id)aTreeNode
{
var oldTreeNode = [_childNodes objectAtIndex:anIndex];
oldTreeNode._parentNode = nil;
aTreeNode._parentNode = self;
[_childNodes replaceObjectAtIndex:anIndex withObject:aTreeNode];
}
- (id)objectInChildNodesAtIndex:(CPInteger)anIndex
{
return _childNodes[anIndex];
}
- (void)sortWithSortDescriptors:(CPArray)sortDescriptors recursively:(BOOL)shouldSortRecursively
{
[_childNodes sortUsingDescriptors:sortDescriptors];
if (!shouldSortRecursively)
return;
var count = [_childNodes count];
while (count--)
[_childNodes[count] sortWithSortDescriptors:sortDescriptors recursively:YES];
}
- (CPEnumerator)preOrder
{
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorPreOrder];
}
- (CPEnumerator)inOrder
{
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorInOrder];
}
- (CPEnumerator)postOrder
{
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorPostOrder];
}
- (CPEnumerator)levelOrder
{
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorLevelOrder];
}
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
{
if (aState.state !== 0)
return 0;
// FIXME: Change this to inorder when implemented?
var count = [[self preOrder] countByEnumeratingWithState:aState objects:objects count:aCount];
// Dangerous?
aState.state = YES;
return count;
}
@end
var CPTreeNodeRepresentedObjectKey = @"CPTreeNodeRepresentedObjectKey",
CPTreeNodeParentNodeKey = @"CPTreeNodeParentNodeKey",
CPTreeNodeChildNodesKey = @"CPTreeNodeChildNodesKey";
@implementation CPTreeNode (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_representedObject = [aCoder decodeObjectForKey:CPTreeNodeRepresentedObjectKey];
_parentNode = [aCoder decodeObjectForKey:CPTreeNodeParentNodeKey];
_childNodes = [aCoder decodeObjectForKey:CPTreeNodeChildNodesKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_representedObject forKey:CPTreeNodeRepresentedObjectKey];
[aCoder encodeConditionalObject:_parentNode forKey:CPTreeNodeParentNodeKey];
[aCoder encodeObject:_childNodes forKey:CPTreeNodeChildNodesKey];
}
@end
var _CPTreeNodeEnumeratorPreOrder = 0,
_CPTreeNodeEnumeratorInOrder = 1,
_CPTreeNodeEnumeratorPostOrder = 2,
_CPTreeNodeEnumeratorLevelOrder = 3;
@implementation _CPTreeNodeEnumerator : CPEnumerator
{
int _order;
Object _state;
CPTreeNode _treeNode;
}
+ (_CPTreeNodeEnumerator)enumeratorWithTreeNode:(CPTreeNode)aTreeNode order:(int)anOrder
{
return [[self alloc] initWithTreeNode:aTreeNode order:anOrder];
}
- (id)initWithTreeNode:(CPTreeNode)aTreeNode order:(int)anOrder
{
self = [super init];
if (self)
{
_order = anOrder
_state = [self _newState];
_treeNode = aTreeNode;
}
return self;
}
- (id)_newState
{
return { stack:[_treeNode], visited:[CPSet set] };
}
- (id)_preOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
{
var stack = state.stack;
if (stack.length <= 0)
return nil;
if (shouldReturnAllObjects)
var allObjects = [];
while (stack.length)
{
var currentNode = stack.pop(),
childNodes = currentNode._childNodes,
count = childNodes.length;
while (count--)
stack.push(childNodes[count]);
if (shouldReturnAllObjects)
allObjects.push(currentNode);
else
return currentNode;
}
return allObjects;
}
- (id)_inOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
{
// Implement.
}
- (id)_postOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
{
var stack = state.stack;
if (stack.length <= 0)
return nil;
var visited = state.visited;
if (shouldReturnAllObjects)
var allObjects = [];
while (stack.length)
{
var currentNode = [stack lastObject],
childNodes = currentNode._childNodes,
originalCount = stack.length,
count = childNodes.length;
while (count--)
{
var treeNode = childNodes[count];
if ([visited containsObject:treeNode])
continue;
else
stack.push(treeNode);
}
if (originalCount === stack.length)
{
[visited addObject:currentNode];
if (shouldReturnAllObjects)
allObjects.push(stack.pop());
else
return stack.pop();
}
}
return allObjects;
}
- (id)_levelOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
{
// Implement.
}
- (id)nextObject
{
if (_order === _CPTreeNodeEnumeratorPreOrder)
return [self _preOrderFromState:[self _newState] allObjects:NO];
else if (_order === _CPTreeNodeEnumeratorInOrder)
return [self _inOrderFromState:[self _newState] allObjects:NO];
else if (_order === _CPTreeNodeEnumeratorPostOrder)
return [self _postOrderFromState:[self _newState] allObjects:NO];
//else if (_order === _CPTreeNodeEnumeratorLevelOrder)
return [self _levelOrderFromState:[self _newState] allObjects:NO];
}
- (CPArray)allObjects
{
if (_order === _CPTreeNodeEnumeratorPreOrder)
return [self _preOrderFromState:[self _newState] allObjects:YES];
else if (_order === _CPTreeNodeEnumeratorInOrder)
return [self _inOrderFromState:[self _newState] allObjects:YES];
else if (_order === _CPTreeNodeEnumeratorPostOrder)
return [self _postOrderFromState:[self _newState] allObjects:YES];
//else if (_order === _CPTreeNodeEnumeratorLevelOrder)
return [self _levelOrderFromState:[self _newState] allObjects:NO];
}
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
{
if (aState.state !== 0)
return 0;
var count = [[self allObjects] countByEnumeratingWithState:aState objects:objects count:aCount];
// Dangerous?
aState.state = YES;
return count;
}
@end
+703 -359
View File
File diff suppressed because it is too large Load Diff
+180
View File
@@ -0,0 +1,180 @@
/*
* CPViewAnimation.j
* AppKit
*
* Created by Klaas Pieter Annema on September 3, 2009.
* Copyright 2009, Sofa BV
*
* 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 "CPAnimation.j"
CPViewAnimationTargetKey = @"CPViewAnimationTarget";
CPViewAnimationStartFrameKey = @"CPViewAnimationStartFrame";
CPViewAnimationEndFrameKey = @"CPViewAnimationEndFrame";
CPViewAnimationEffectKey = @"CPViewAnimationEffect";
CPViewAnimationFadeInEffect = @"CPViewAnimationFadeIn";
CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
@implementation CPViewAnimation : CPAnimation
{
CPArray _viewAnimations;
}
- (id)initWithViewAnimations:(CPArray)viewAnimations
{
if (self = [super initWithDuration:0.5 animationCurve:CPAnimationLinear])
{
[self setViewAnimations:viewAnimations];
}
return self;
}
- (void)startAnimation
{
var animationIndex = [_viewAnimations count];
while (animationIndex--)
{
var dictionary = [_viewAnimations objectAtIndex:animationIndex],
view = [self _targetView:dictionary],
startFrame = [self _startFrame:dictionary];
[view setFrame:startFrame];
var effect = [self _effect:dictionary];
if (effect === CPViewAnimationFadeInEffect)
{
[view setAlphaValue:0.0];
[view setHidden:NO];
}
else if (effect === CPViewAnimationFadeOutEffect)
[view setAlphaValue:1.0];
}
[super startAnimation];
}
- (void)setCurrentProgress:(CPAnimationProgress)progress
{
[super setCurrentProgress:progress];
var animationIndex = [_viewAnimations count];
while (animationIndex--)
{
var dictionary = [_viewAnimations objectAtIndex:animationIndex],
view = [self _targetView:dictionary],
startFrame = [self _startFrame:dictionary],
endFrame = [self _endFrame:dictionary],
differenceFrame = _CGRectMakeZero();
differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x;
differenceFrame.origin.y = endFrame.origin.y - startFrame.origin.y;
differenceFrame.size.width = endFrame.size.width - startFrame.size.width;
differenceFrame.size.height = endFrame.size.height - startFrame.size.height;
var intermediateFrame = _CGRectMakeZero();
intermediateFrame.origin.x = startFrame.origin.x + differenceFrame.origin.x * progress;
intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * progress;
intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * progress;
intermediateFrame.size.height = startFrame.size.height + differenceFrame.size.height * progress;
[view setFrame:intermediateFrame];
// Update the view's alpha value
var effect = [self _effect:dictionary];
if (effect === CPViewAnimationFadeInEffect)
[view setAlphaValue:1.0 * progress];
else if (effect === CPViewAnimationFadeOutEffect)
[view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * progress];
if (progress === 1.0)
[view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
}
}
- (void)stopAnimation
{
var animationIndex = [_viewAnimations count];
while (animationIndex--)
{
var dictionary = [_viewAnimations objectAtIndex:animationIndex],
view = [self _targetView:dictionary],
endFrame = [self _endFrame:dictionary];
[view setFrame:endFrame];
var effect = [self _effect:dictionary];
if (effect === CPViewAnimationFadeInEffect)
[view setAlphaValue:1.0];
else if (effect === CPViewAnimationFadeOutEffect)
[view setAlphaValue:0.0];
[view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
}
[super stopAnimation];
}
- (id)_targetView:(CPDictionary)dictionary
{
var targetView = [dictionary valueForKey:CPViewAnimationTargetKey];
if (!targetView)
[CPException raise:CPInternalInconsistencyException reason:[CPString stringWithFormat:@"view animation: %@ does not have a target view", [dictionary description]]];
return targetView;
}
- (CGRect)_startFrame:(CPDictionary)dictionary
{
var startFrame = [dictionary valueForKey:CPViewAnimationStartFrameKey];
if (!startFrame)
return [[self _targetView:dictionary] frame];
return startFrame;
}
- (CGRect)_endFrame:(CPDictionary)dictionary
{
var endFrame = [dictionary valueForKey:CPViewAnimationEndFrameKey];
if (!endFrame)
return [[self _targetView:dictionary] frame];
return endFrame;
}
- (CPString)_effect:(CPDictionary)dictionary
{
return [dictionary valueForKey:CPViewAnimationEffectKey];
}
- (CPArray)viewAnimations
{
return _viewAnimations;
}
- (void)setViewAnimations:(CPArray)viewAnimations
{
if (viewAnimations != _viewAnimations)
{
[self stopAnimation];
_viewAnimations = [viewAnimations copy];
}
}
@end
+260
View File
@@ -0,0 +1,260 @@
/*
* CPViewController.j
* AppKit
*
* Created by Nicholas Small and Francisco Tolmasky.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPArray.j>
@import "CPApplication.j"
@import "CPCib.j"
@import "CPResponder.j"
var CPViewControllerCachedCibs;
/*! @class CPViewController
The CPViewController class provides the fundamental view-management controller for Cappuccino applications.
The basic view controller class supports the presentation of an associated view in addition to basic support
for managing modal views and, in the future, animations. Subclasses such as CPNavigationController and
CPTabBarController provide additional behavior for managing complex hierarchies of view controllers and views.
You use each instance of CPViewController to manage a single view (and hierarchy). For a simple view controller,
this entails managing the view hierarchy responsible for presenting your application content.
A typical view hierarchy consists of a root viewŃa reference to which is available in the view property of this classŃ
and one or more subviews presenting the actual content. In the case of navigation and tab bar controllers, the view
controller manages not only the high-level view hierarchy (which provides the navigation controls) but also one
or more additional view controllers that handle the presentation of the application content.
Unlike UIViewController in Cocoa Touch, a CPViewController does not represent an entire screen of content. You
will add your root view to an existing view or window's content view. You can manage many view controllers
on screen at once. CPViewController is also the preferred way of working with Cibs.
Subclasses can override -loadView to create their custom view hierarchy, or specify a cib name to be loaded automatically.
It has methods that are called when a view appears or disappears.
This class is also a good place for delegate & datasource methods, and other controller stuff.
*/
@implementation CPViewController : CPResponder
{
CPView _view @accessors(property=view);
BOOL _isLoading;
id _representedObject @accessors(property=representedObject);
CPString _title @accessors(property=title);
CPString _cibName @accessors(property=cibName, readonly);
CPBundle _cibBundle @accessors(property=cibBundle, readonly);
CPDictionary _cibExternalNameTable @accessors(property=cibExternalNameTable, readonly);
}
+ (void)initialize
{
if (self === CPViewController)
CPViewControllerCachedCibs = [CPDictionary dictionary];
}
/*!
Convenience initializer calls -initWithCibName:bundle: with nil for both parameters.
*/
- (id)init
{
return [self initWithCibName:nil bundle:nil];
}
- (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil
{
return [self initWithCibName:aCibNameOrNil bundle:aCibBundleOrNil externalNameTable:nil];
}
- (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil owner:(id)anOwner
{
return [self initWithCibName:aCibNameOrNil bundle:aCibBundleOrNil externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]];
}
/*!
The designated initializer. If you subclass CPViewController, you must call the super implementation of this method, even if you aren't using a Cib.
In the specified Cib, the File's Owner proxy should have its class set to your view controller subclass, with the view outlet connected to the main view.
If you pass in a nil Cib name, then you must either call -setView: before -view is invoked, or override -loadView to set up your views.
@param cibNameOrNil The path to the cib to load for the root view or nil to programmatically create views.
@param cibBundleOrNil The bundle that the cib is located in or nil for the main bundle.
*/
- (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil externalNameTable:(CPDictionary)anExternalNameTable
{
self = [super init];
if (self)
{
// Don't load the cib until someone actually requests the view. The user may just be intending to use setView:.
_cibName = aCibNameOrNil;
_cibBundle = aCibBundleOrNil || [CPBundle mainBundle];
_cibExternalNameTable = anExternalNameTable || [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
_isLoading = NO;
}
return self;
}
/*!
Programmatically creates the view that the controller manages.
You should never call this method directly. The view controller calls this method when the view property is requested but is nil.
If you create your views manually, you must override this method and use it to create your view and assign it to the view property.
The default implementation for programmatic views is to create a plain view. You can invoke super to utilize this view.
If you use Interface Builder to create your views, you initialize the view using the
initWithCibName:bundle: method then you must not override this method. The consequences risk shattering the space-time continuum.
Note: The cib loading system is currently synchronous.
*/
- (void)loadView
{
if (_view)
return;
// check if a cib is already cached for the current _cibName
var cib = [CPViewControllerCachedCibs objectForKey:_cibName];
if (!cib)
{
// 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];
}
[cib instantiateCibWithExternalNameTable:_cibExternalNameTable];
}
/*!
Returns the view that the controller manages.
If this property is nil, the controller sends loadView to itself to create the view that it manages.
Subclasses should override the loadView method to create any custom views. The default value is nil.
*/
- (CPView)view
{
if (!_view)
{
_isLoading = YES;
var cibOwner = [_cibExternalNameTable objectForKey:CPCibOwner];
if ([cibOwner respondsToSelector:@selector(viewControllerWillLoadCib:)])
[cibOwner viewControllerWillLoadCib:self];
[self loadView];
if (_view === nil && [cibOwner isKindOfClass:[CPDocument class]])
[self setView:[cibOwner valueForKey:@"view"]];
if (!_view)
{
var reason = [CPString stringWithFormat:@"View for %@ could not be loaded from Cib or no view specified. Override loadView to load the view manually.", self];
[CPException raise:CPInternalInconsistencyException reason:reason];
}
if ([cibOwner respondsToSelector:@selector(viewControllerDidLoadCib:)])
[cibOwner viewControllerDidLoadCib:self];
_isLoading = NO;
[self viewDidLoad];
}
return _view;
}
/*!
This method is called after the view controller has loaded its associated views into memory.
This method is called regardless of whether the views were stored in a nib file or created programmatically in the loadView method.
This method is most commonly used to perform additional initialization steps on views that are loaded from cib files.
*/
- (void)viewDidLoad
{
}
/*!
Manually sets the view that the controller manages.
Setting to nil will cause -loadView to be called on all subsequent calls of -view.
@param aView The view this controller should represent.
*/
- (void)setView:(CPView)aView
{
var viewWasLoaded = !_view;
_view = aView;
// Make sure the viewDidLoad method is called if the view is set directly
if (!_isLoading && viewWasLoaded)
[self viewDidLoad];
}
@end
var CPViewControllerViewKey = @"CPViewControllerViewKey",
CPViewControllerTitleKey = @"CPViewControllerTitleKey",
CPViewControllerCibNameKey = @"CPViewControllerCibNameKey",
CPViewControllerBundleKey = @"CPViewControllerBundleKey";
@implementation CPViewController (CPCoding)
/*!
Initializes the view controller by unarchiving data from a coder.
@param aCoder the coder from which the data will be unarchived
@return the initialized view controller
*/
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_view = [aCoder decodeObjectForKey:CPViewControllerViewKey];
_title = [aCoder decodeObjectForKey:CPViewControllerTitleKey];
_cibName = [aCoder decodeObjectForKey:CPViewControllerCibNameKey];
var bundlePath = [aCoder decodeObjectForKey:CPViewControllerBundleKey];
_cibBundle = bundlePath ? [CPBundle bundleWithPath:bundlePath] : [CPBundle mainBundle];
_cibExternalNameTable = [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
}
return self;
}
/*!
Archives the view controller to the provided coder.
@param aCoder the coder to which the view controller should be archived
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_view forKey:CPViewControllerViewKey];
[aCoder encodeObject:_title forKey:CPViewControllerTitleKey];
[aCoder encodeObject:_cibName forKey:CPViewControllerCibNameKey];
[aCoder encodeObject:[_cibBundle bundlePath] forKey:CPViewControllerBundleKey];
}
@end
+102 -57
View File
@@ -20,9 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CPView.j>
#include "Platform/Platform.h"
@import "CPView.j"
@import "CPScrollView.j"
// FIXME: implement these where possible:
@@ -50,30 +49,32 @@ CPWebViewScrollNative = 2;
{
CPScrollView _scrollView;
CPView _frameView;
IFrame _iframe;
CPString _mainFrameURL;
CPArray _backwardStack;
CPArray _forwardStack;
BOOL _ignoreLoadStart;
BOOL _ignoreLoadEnd;
id _downloadDelegate;
id _frameLoadDelegate;
id _policyDelegate;
id _resourceLoadDelegate;
id _UIDelegate;
CPWebScriptObject _wso;
CPString _url;
CPString _html;
Function _loadCallback;
int _scrollMode;
CGSize _scrollSize;
int _loadHTMLStringTimer;
}
- (id)initWithFrame:(CPRect)frameRect frameName:(CPString)frameName groupName:(CPString)groupName
@@ -93,10 +94,10 @@ CPWebViewScrollNative = 2;
_backwardStack = [];
_forwardStack = [];
_scrollMode = CPWebViewScrollNative;
[self _initDOMWithFrame:aFrame];
}
return self;
}
@@ -104,59 +105,62 @@ CPWebViewScrollNative = 2;
{
_ignoreLoadStart = YES;
_ignoreLoadEnd = YES;
_iframe = document.createElement("iframe");
_iframe.name = "iframe_" + Math.floor(Math.random()*10000);
_iframe.style.width = "100%";
_iframe.style.height = "100%";
_iframe.style.borderWidth = "0px";
_iframe.frameBorder = "0";
[self setDrawsBackground:YES];
_loadCallback = function() {
// HACK: this block handles the case where we don't know about loads initiated by the user clicking a link
if (!_ignoreLoadStart)
{
// post the start load notification
[self _startedLoading];
if (_mainFrameURL)
[_backwardStack addObject:_mainFrameURL];
// FIXME: this doesn't actually get the right URL for different domains. Not possible due to browser security restrictions.
_mainFrameURL = _iframe.src;
_mainFrameURL = _iframe.src;
// clear the forward
[_forwardStack removeAllObjects];
}
else
_ignoreLoadStart = NO;
if (!_ignoreLoadEnd)
{
[self _finishedLoading];
}
else
_ignoreLoadEnd = NO;
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
if (_iframe.addEventListener)
_iframe.addEventListener("load", _loadCallback, false);
else if (_iframe.attachEvent)
_iframe.attachEvent("onload", _loadCallback);
_frameView = [[CPView alloc] initWithFrame:[self bounds]];
[_frameView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
_scrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
[_scrollView setAutohidesScrollers:YES];
[_scrollView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
[_scrollView setDocumentView:_frameView];
_frameView._DOMElement.appendChild(_iframe);
[self _setScrollMode:_scrollMode];
[self addSubview:_scrollView];
@@ -164,13 +168,37 @@ CPWebViewScrollNative = 2;
- (void)setFrameSize:(CPSize)aSize
{
{
[super setFrameSize:aSize];
[self _resizeWebFrame];
}
- (BOOL)_resizeWebFrame
- (void)_attachScrollEventIfNecessary
{
if (_scrollMode !== CPWebViewScrollAppKit)
return;
var win = null;
try { win = [self DOMWindow]; } catch (e) {}
if (win && win.addEventListener)
{
var scrollEventHandler = function(anEvent)
{
var frameBounds = [self bounds],
frameCenter = CGPointMake(CGRectGetMidX(frameBounds), CGRectGetMidY(frameBounds)),
windowOrigin = [self convertPoint:frameCenter toView:nil],
globalOrigin = [[self window] convertBaseToBridge:windowOrigin];
anEvent._overrideLocation = globalOrigin;
[[[self window] platformWindow] scrollEvent:anEvent];
};
win.addEventListener("DOMMouseScroll", scrollEventHandler, false);
}
}
- (void)_resizeWebFrame
{
if (_scrollMode === CPWebViewScrollAppKit)
{
@@ -180,13 +208,14 @@ CPWebViewScrollNative = 2;
}
else
{
[_frameView setFrameSize:[_scrollView bounds].size];
var visibleRect = [_frameView visibleRect];
[_frameView setFrameSize:CGSizeMake(CGRectGetMaxX(visibleRect), CGRectGetMaxY(visibleRect))];
// try to get the document size so we can correctly set the frame
var win = null;
try { win = [self DOMWindow]; } catch (e) {}
if (win && win.document)
if (win && win.document && win.document.body)
{
var width = win.document.body.scrollWidth,
height = win.document.body.scrollHeight;
@@ -199,9 +228,11 @@ CPWebViewScrollNative = 2;
else
{
CPLog.warn("using default size 800*1600");
[_frameView setFrameSize:CGSizeMake(800, 1600)];
}
[_frameView scrollRectToVisible:visibleRect];
}
}
}
@@ -210,14 +241,17 @@ CPWebViewScrollNative = 2;
{
if (_scrollMode == aScrollMode)
return;
[self _setScrollMode:aScrollMode];
}
- (void)_setScrollMode:(int)aScrollMode
{
_scrollMode = aScrollMode;
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
_scrollMode = CPWebViewScrollNative;
else
_scrollMode = aScrollMode;
_ignoreLoadStart = YES;
_ignoreLoadEnd = YES;
@@ -228,16 +262,16 @@ CPWebViewScrollNative = 2;
{
[_scrollView setHasHorizontalScroller:YES];
[_scrollView setHasVerticalScroller:YES];
_iframe.setAttribute("scrolling", "no");
}
else
{
[_scrollView setHasHorizontalScroller:NO];
[_scrollView setHasVerticalScroller:NO];
_iframe.setAttribute("scrolling", "auto");
[_frameView setFrameSize:[_scrollView bounds].size];
}
@@ -255,14 +289,16 @@ CPWebViewScrollNative = 2;
[self _setScrollMode:CPWebViewScrollAppKit];
[_frameView setFrameSize:[_scrollView contentSize]];
[self _startedLoading];
_ignoreLoadStart = YES;
_ignoreLoadEnd = NO;
_url = null;
_html = aString;
[self _load];
}
@@ -271,13 +307,13 @@ CPWebViewScrollNative = 2;
[self _setScrollMode:CPWebViewScrollNative];
[self _startedLoading];
_ignoreLoadStart = YES;
_ignoreLoadEnd = NO;
_url = _mainFrameURL;
_html = null;
[self _load];
}
@@ -292,11 +328,19 @@ CPWebViewScrollNative = 2;
// clear the iframe
_iframe.src = "";
// need to give the browser a chance to reset iframe, otherwise we'll be document.write()-ing the previous document
window.setTimeout(function() {
if (_loadHTMLStringTimer !== nil)
{
window.clearTimeout(_loadHTMLStringTimer);
_loadHTMLStringTimer = nil;
}
// need to give the browser a chance to reset iframe, otherwise we'll be document.write()-ing the previous document
_loadHTMLStringTimer = window.setTimeout(function()
{
var win = [self DOMWindow];
win.document.write(_html);
if (win)
win.document.write(_html);
window.setTimeout(_loadCallback, 1);
}, 0);
@@ -314,7 +358,8 @@ CPWebViewScrollNative = 2;
- (void)_finishedLoading
{
[self _resizeWebFrame];
[self _attachScrollEventIfNecessary];
[[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressFinishedNotification object:self];
if ([_frameLoadDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)])
@@ -327,7 +372,7 @@ CPWebViewScrollNative = 2;
}
- (void)setMainFrameURL:(CPString)URLString
{
{
if (_mainFrameURL)
[_backwardStack addObject:_mainFrameURL];
_mainFrameURL = URLString;
@@ -344,9 +389,9 @@ CPWebViewScrollNative = 2;
[_forwardStack addObject:_mainFrameURL];
_mainFrameURL = [_backwardStack lastObject];
[_backwardStack removeLastObject];
[self _loadMainFrameURL];
return YES;
}
return NO;
@@ -360,9 +405,9 @@ CPWebViewScrollNative = 2;
[_backwardStack addObject:_mainFrameURL];
_mainFrameURL = [_forwardStack lastObject];
[_forwardStack removeLastObject];
[self _loadMainFrameURL];
return YES;
}
return NO;
@@ -585,7 +630,7 @@ CPWebViewScrollNative = 2;
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
// FIXME: encode/decode these?
@@ -593,14 +638,14 @@ CPWebViewScrollNative = 2;
_backwardStack = [];
_forwardStack = [];
_scrollMode = CPWebViewScrollNative;
#if PLATFORM(DOM)
[self _initDOMWithFrame:[self frame]];
#endif
[self setBackgroundColor:[CPColor whiteColor]];
}
return self;
}
+1197 -454
View File
File diff suppressed because it is too large Load Diff
@@ -38,6 +38,11 @@ var _CPToolbarViewBackgroundColor = nil;
return _CPToolbarViewBackgroundColor;
}
- (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator
{
// We don't ever want to show the resize indicator.
}
- (void)tile
{
[super tile];
@@ -66,11 +71,12 @@ var _CPToolbarViewBackgroundColor = nil;
[self addSubview:_toolbarBackgroundView positioned:CPWindowBelow relativeTo:nil];
}
var frame = CGRectMakeZero();
frame.origin = CGPointMakeCopy([self toolbarOffset]);
var frame = CGRectMakeZero(),
toolbarOffset = [self toolbarOffset];
frame.origin = CGPointMake(toolbarOffset.width, toolbarOffset.height);
frame.size = [_toolbarView frame].size;
[_toolbarBackgroundView setFrame:frame];
}
+50
View File
@@ -0,0 +1,50 @@
@import "_CPWindowView.j"
var _CPStandardWindowViewBodyBackgroundColor = nil;
@implementation _CPDocModalWindowView : _CPWindowView
{
CPView _bodyView;
}
+ (CPColor)bodyBackgroundColor
{
if (!_CPStandardWindowViewBodyBackgroundColor)
_CPStandardWindowViewBodyBackgroundColor = [CPColor colorWithWhite:0.96 alpha:0.9];
return _CPStandardWindowViewBodyBackgroundColor;
}
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
{
self = [super initWithFrame:aFrame styleMask:aStyleMask];
if (self)
{
var theClass = [self class],
bounds = [self bounds];
_bodyView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), CGRectGetHeight(bounds))];
[_bodyView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_bodyView setBackgroundColor:[theClass bodyBackgroundColor]];
[_bodyView setHitTests:NO];
[self addSubview:_bodyView];
}
return self;
}
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
return aFrameRect;
}
- (CGRect)frameRectForContentRect:(CGRect)aContentRect
{
return aContentRect;
}
@end
+12 -12
View File
@@ -43,21 +43,21 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
_CPHUDWindowViewBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground0.png"] size:CPSizeMake(6.0, 78.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground1.png"] size:CPSizeMake(1.0, 78.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground2.png"] size:CPSizeMake(6.0, 78.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground0.png"] size:CPSizeMake(7.0, 37.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground1.png"] size:CPSizeMake(1.0, 37.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground2.png"] size:CPSizeMake(7.0, 37.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground3.png"] size:CPSizeMake(6.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground4.png"] size:CPSizeMake(1.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground5.png"] size:CPSizeMake(6.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground3.png"] size:CPSizeMake(7.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground4.png"] size:CPSizeMake(2.0, 2.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground5.png"] size:CPSizeMake(7.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground6.png"] size:CPSizeMake(6.0, 6.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground7.png"] size:CPSizeMake(6.0, 6.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground8.png"] size:CPSizeMake(6.0, 6.0)]
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground6.png"] size:CPSizeMake(7.0, 3.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground7.png"] size:CPSizeMake(1.0, 3.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground8.png"] size:CPSizeMake(7.0, 3.0)]
]]];
_CPHUDWindowViewCloseImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowClose.png"] size:CPSizeMake(20.0, 20.0)];
_CPHUDWindowViewCloseActiveImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowCloseActive.png"] size:CPSizeMake(20.0, 20.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)];
}
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
@@ -148,7 +148,7 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
{
var closeSize = [_CPHUDWindowViewCloseImage size];
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(4.0, 4.0, closeSize.width, closeSize.height)];
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 5.0, closeSize.width, closeSize.height)];
[_closeButton setBordered:NO];
+76 -17
View File
@@ -22,6 +22,7 @@
@import "_CPWindowView.j"
var GRADIENT_HEIGHT = 41.0;
var _CPTexturedWindowHeadGradientColor = nil,
@@ -56,7 +57,7 @@ var _CPTexturedWindowHeadGradientColor = nil,
+ (CPColor)solidColor
{
if (!_CPTexturedWindowHeadSolidColor)
_CPTexturedWindowHeadSolidColor = [CPColor colorWithCalibratedRed:182.0 / 255.0 green:182.0 / 255.0 blue:182.0 / 255.0 alpha:1.0];
_CPTexturedWindowHeadSolidColor = [CPColor colorWithCalibratedRed:195.0 / 255.0 green:195.0 / 255.0 blue:195.0 / 255.0 alpha:1.0];
return _CPTexturedWindowHeadSolidColor;
}
@@ -94,11 +95,15 @@ var _CPTexturedWindowHeadGradientColor = nil,
@end
var _CPStandardWindowViewBodyBackgroundColor = nil,
_CPStandardWindowViewDividerBackgroundColor = nil,
_CPStandardWindowViewTitleBackgroundColor = nil,
_CPStandardWindowViewCloseButtonImage = nil,
_CPStandardWindowViewCloseButtonHighlightedImage = nil;
var _CPStandardWindowViewBodyBackgroundColor = nil,
_CPStandardWindowViewDividerBackgroundColor = nil,
_CPStandardWindowViewTitleBackgroundColor = nil,
_CPStandardWindowViewCloseButtonImage = nil,
_CPStandardWindowViewCloseButtonHighlightedImage = nil,
_CPStandardWindowViewCloseButtonUnsavedImage = nil,
_CPStandardWindowViewCloseButtonUnsavedHighlightedImage = nil,
_CPStandardWindowViewMinimizeButtonImage = nil,
_CPStandardWindowViewMinimizeButtonHighlightedImage = nil;
var STANDARD_GRADIENT_HEIGHT = 41.0;
STANDARD_TITLEBAR_HEIGHT = 25.0;
@@ -112,6 +117,9 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
CPTextField _titleField;
CPButton _closeButton;
CPButton _minimizeButton;
BOOL _isDocumentEdited;
}
+ (CPColor)bodyBackgroundColor
@@ -230,7 +238,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
[_bodyView setHitTests:NO];
[self addSubview:_bodyView];
[self setResizeIndicatorOffset:CGSizeMake(2.0, 2.0)];
_titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
@@ -256,24 +264,44 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
if (!_CPStandardWindowViewCloseButtonImage)
{
var bundle = [CPBundle bundleForClass:[CPWindow class]];
_CPStandardWindowViewCloseButtonImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardCloseButton.png"] size:CGSizeMake(16.0, 16.0)];
_CPStandardWindowViewCloseButtonHighlightedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardCloseButtonHighlighted.png"] size:CGSizeMake(16.0, 16.0)];
_CPStandardWindowViewCloseButtonUnsavedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardCloseButtonUnsaved.png"] size:CGSizeMake(16.0, 16.0)];
_CPStandardWindowViewCloseButtonUnsavedHighlightedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardCloseButtonUnsavedHighlighted.png"] size:CGSizeMake(16.0, 16.0)];
}
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 7.0, 16.0, 16.0)];
[_closeButton setBordered:NO];
[_closeButton setImage:_CPStandardWindowViewCloseButtonImage];
[_closeButton setAlternateImage:_CPStandardWindowViewCloseButtonHighlightedImage];
[self _updateCloseButton];
[self addSubview:_closeButton];
}
if (_styleMask & CPMiniaturizableWindowMask && ![CPPlatform isBrowser])
{
if (!_CPStandardWindowViewMinimizeButtonImage)
{
var bundle = [CPBundle bundleForClass:[CPWindow class]];
_CPStandardWindowViewMinimizeButtonImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardMinimizeButton.png"] size:CGSizeMake(16.0, 16.0)];
_CPStandardWindowViewMinimizeButtonHighlightedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/Standard/CPWindowStandardMinimizeButtonHighlighted.png"] size:CGSizeMake(16.0, 16.0)];
}
_minimizeButton = [[CPButton alloc] initWithFrame:CGRectMake(27.0, 7.0, 16.0, 16.0)];
[_minimizeButton setBordered:NO];
[_minimizeButton setImage:_CPStandardWindowViewMinimizeButtonImage];
[_minimizeButton setAlternateImage:_CPStandardWindowViewMinimizeButtonHighlightedImage];
[self addSubview:_minimizeButton];
}
[self tile];
}
return self;
}
@@ -281,6 +309,9 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
{
[_closeButton setTarget:[self window]];
[_closeButton setAction:@selector(performClose:)];
[_minimizeButton setTarget:[self window]];
[_minimizeButton setAction:@selector(performMiniaturize:)];
}
- (CGSize)toolbarOffset
@@ -303,7 +334,14 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
[_bodyView setFrame:CGRectMake(0.0, dividerMaxY, width, CGRectGetHeight(bounds) - dividerMaxY)];
[_titleField setFrame:CGRectMake(10.0, 3.0, width - 20.0, CGRectGetHeight([_titleField frame]))];
var leftOffset = 8;
if (_closeButton)
leftOffset += 19.0;
if (_minimizeButton)
leftOffset += 19.0;
[_titleField setFrame:CGRectMake(leftOffset, 5.0, width - leftOffset*2.0, CGRectGetHeight([_titleField frame]))];
[[theWindow contentView] setFrameOrigin:CGPointMake(0.0, CGRectGetMaxY([_dividerView frame]))];
}
@@ -334,6 +372,27 @@ var STANDARD_GRADIENT_HEIGHT = 41.0;
}
}
*/
- (void)_updateCloseButton
{
if (_isDocumentEdited)
{
[_closeButton setImage:_CPStandardWindowViewCloseButtonUnsavedImage];
[_closeButton setAlternateImage:_CPStandardWindowViewCloseButtonUnsavedHighlightedImage];
}
else
{
[_closeButton setImage:_CPStandardWindowViewCloseButtonImage];
[_closeButton setAlternateImage:_CPStandardWindowViewCloseButtonHighlightedImage];
}
}
- (void)setDocumentEdited:(BOOL)isEdited
{
_isDocumentEdited = isEdited;
[self _updateCloseButton];
}
- (void)setTitle:(CPString)aTitle
{
[_titleField setStringValue:aTitle];
+42 -25
View File
@@ -20,10 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPView.j"
@import "CPImageView.j"
#include "../CoreGraphics/CGGeometry.h"
@import "CPView.j"
var _CPWindowViewResizeIndicatorImage = nil;
@@ -36,7 +34,9 @@ var _CPWindowViewResizeIndicatorImage = nil;
CGSize _resizeIndicatorOffset;
CPView _toolbarView;
CGSize _toolbarOffset;
// BOOL _isAnimatingToolbar;
CGRect _resizeFrame;
CGPoint _mouseDraggedPoint;
@@ -79,15 +79,17 @@ var _CPWindowViewResizeIndicatorImage = nil;
if (self)
{
_styleMask = aStyleMask;
_resizeIndicatorOffset = CGSizeMake(0.0, 0.0);
_toolbarOffset = CGSizeMake(0.0, 0.0);
[self setShowsResizeIndicator:!(_styleMask & CPBorderlessBridgeWindowMask) && (_styleMask & CPResizableWindowMask)];
_resizeIndicatorOffset = CGSizeMakeZero();
_toolbarOffset = CGSizeMakeZero();
}
return self;
}
- (void)setDocumentEdited:(BOOL)isEdited
{
}
- (void)setTitle:(CPString)aTitle
{
}
@@ -100,7 +102,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
- (void)mouseDown:(CPEvent)anEvent
{
var theWindow = [self window];
if ((_styleMask & CPResizableWindowMask) && _resizeIndicator)
{
// FIXME: This should be better
@@ -135,22 +137,38 @@ var _CPWindowViewResizeIndicatorImage = nil;
}
else if (type === CPLeftMouseDragged)
[theWindow setFrameSize:CGSizeMake(CGRectGetWidth(_resizeFrame) + location.x - CGRectGetMinX(_resizeFrame), CGRectGetHeight(_resizeFrame) + location.y - CGRectGetMinY(_resizeFrame))];
{
var newSize = CGSizeMake(CGRectGetWidth(_resizeFrame) + location.x - CGRectGetMinX(_resizeFrame), CGRectGetHeight(_resizeFrame) + location.y - CGRectGetMinY(_resizeFrame));
if (theWindow._isSheet && theWindow._parentView && (theWindow._frame.size.width !== newSize.width))
[theWindow._parentView _setAttachedSheetFrameOrigin];
[theWindow setFrameSize:newSize];
}
[CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (CGPoint)_pointWithinScreenFrame:(CGPoint)aPoint
{
// FIXME: this is WRONG, all of this is WRONG
if (![CPPlatform isBrowser])
return aPoint;
var visibleFrame = _cachedScreenFrame;
if (!visibleFrame)
visibleFrame = [[CPDOMWindowBridge sharedDOMWindowBridge] visibleFrame];
visibleFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
var minPointY = 0;
if([CPMenu menuBarVisible])
minPointY = [[CPApp mainMenu] menuBarHeight];
var restrictedPoint = CGPointMake(0, 0);
restrictedPoint.x = MIN(MAX(aPoint.x, -_frame.size.width + 4.0), CGRectGetMaxX(visibleFrame) - 4.0);
restrictedPoint.y = MIN(MAX(aPoint.y, 0.0), CGRectGetMaxY(visibleFrame) - 8.0);
restrictedPoint.y = MIN(MAX(aPoint.y, minPointY), CGRectGetMaxY(visibleFrame) - 8.0);
return restrictedPoint;
}
@@ -158,22 +176,24 @@ var _CPWindowViewResizeIndicatorImage = nil;
- (void)trackMoveWithEvent:(CPEvent)anEvent
{
var type = [anEvent type];
if (type === CPLeftMouseUp)
{
_cachedScreenFrame = nil;
return;
}
else if (type === CPLeftMouseDown)
{
_mouseDraggedPoint = [[self window] convertBaseToBridge:[anEvent locationInWindow]];
_cachedScreenFrame = [[CPDOMWindowBridge sharedDOMWindowBridge] visibleFrame];
_mouseDraggedPoint = [[self window] convertBaseToGlobal:[anEvent locationInWindow]];
_cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
}
else if (type === CPLeftMouseDragged)
{
var theWindow = [self window],
frame = [theWindow frame],
location = [theWindow convertBaseToBridge:[anEvent locationInWindow]],
location = [theWindow convertBaseToGlobal:[anEvent locationInWindow]],
origin = [self _pointWithinScreenFrame:CGPointMake(_CGRectGetMinX(frame) + (location.x - _mouseDraggedPoint.x),
_CGRectGetMinY(frame) + (location.y - _mouseDraggedPoint.y))];
@@ -196,18 +216,18 @@ var _CPWindowViewResizeIndicatorImage = nil;
[_resizeIndicator setImage:_CPWindowViewResizeIndicatorImage];
[_resizeIndicator setAutoresizingMask:CPViewMinXMargin | CPViewMinYMargin];
[self addSubview:_resizeIndicator];
}
else
{
[_resizeIndicator removeFromSuperview];
_resizeIndicator = nil;
}
}
- (CPImage)showsResizeIndicator
- (BOOL)showsResizeIndicator
{
return _resizeIndicator !== nil;
}
@@ -248,7 +268,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
- (CGSize)toolbarOffset
{
return CGSizeMakeZero();
return _toolbarOffset;
}
- (CPColor)toolbarLabelColor
@@ -305,11 +325,8 @@ var _CPWindowViewResizeIndicatorImage = nil;
if (toolbarView)
{
[toolbarView removeFromSuperview];
[toolbarView setLabelColor:[self toolbarLabelColor]];
if ([self respondsToSelector:@selector(toolbarLabelShadowColor)])
[toolbarView setLabelShadowColor:[self toolbarLabelShadowColor]];
[toolbarView FIXME_setIsHUD:_styleMask & CPHUDBackgroundWindowMask];
[self addSubview:toolbarView];
}
@@ -322,7 +339,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
{
var contentRect = [self convertRect:[[theWindow contentView] frame] toView:nil];
contentRect.origin = [theWindow convertBaseToBridge:contentRect.origin];
contentRect.origin = [theWindow convertBaseToGlobal:contentRect.origin];
[self setAutoresizesSubviews:NO];
[theWindow setFrame:[theWindow frameRectForContentRect:contentRect]];
+208 -42
View File
@@ -27,8 +27,6 @@
@import "CPWindow.j"
@import "CPDocument.j"
#include "Platform/Platform.h"
/*!
@ingroup appkit
@@ -41,10 +39,24 @@
*/
@implementation CPWindowController : CPResponder
{
id _owner;
CPWindow _window;
CPDocument _document;
CPString _windowCibName;
CPWindow _window;
CPArray _documents;
CPDocument _document;
BOOL _shouldCloseDocument;
BOOL _supportsMultipleDocuments;
id _cibOwner;
CPString _windowCibName;
CPString _windowCibPath;
CPViewController _viewController;
CPView _viewControllerContainerView;
}
- (id)init
{
return [self initWithWindow:nil];
}
/*!
@@ -55,14 +67,17 @@
- (id)initWithWindow:(CPWindow)aWindow
{
self = [super init];
if (self)
{
[self setWindow:aWindow];
[self setShouldCloseDocument:NO];
[self setNextResponder:CPApp];
_documents = [];
}
return self;
}
@@ -84,16 +99,27 @@
*/
- (id)initWithWindowCibName:(CPString)aWindowCibName owner:(id)anOwner
{
self = [super init];
self = [self initWithWindow:nil];
if (self)
{
_owner = anOwner;
_cibOwner = anOwner;
_windowCibName = aWindowCibName;
[self setNextResponder:CPApp];
}
return self;
}
- (id)initWithWindowCibPath:(CPString)aWindowCibPath owner:(id)anOwner
{
self = [self initWithWindow:nil];
if (self)
{
_cibOwner = anOwner;
_windowCibPath = aWindowCibPath;
}
return self;
}
@@ -102,34 +128,33 @@
*/
- (void)loadWindow
{
[self windowWillLoad];
//FIXME: ACTUALLY LOAD WINDOW!!!
[self setWindow:CPApp._keyWindow = [[CPWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:CPBorderlessBridgeWindowMask|CPTitledWindowMask|CPClosableWindowMask|CPResizableWindowMask]];
[self windowDidLoad];
if (_window)
return;
[[CPBundle mainBundle] loadCibFile:[self windowCibPath] externalNameTable:[CPDictionary dictionaryWithObject:_cibOwner forKey:CPCibOwner]];
}
/*!
Shows the window.
@param aSender the object requesting the show
*/
- (CFAction)showWindow:(id)aSender
- (@action)showWindow:(id)aSender
{
var theWindow = [self window];
if ([theWindow respondsToSelector:@selector(becomesKeyOnlyIfNeeded)] && [theWindow becomesKeyOnlyIfNeeded])
if ([theWindow respondsToSelector:@selector(becomesKeyOnlyIfNeeded)] && [theWindow becomesKeyOnlyIfNeeded])
[theWindow orderFront:aSender];
else
[theWindow makeKeyAndOrderFront:aSender];
}
/*!
Returns <code>YES</code> if the window has been loaded. Specifically,
Returns \c YES if the window has been loaded. Specifically,
if loadWindow has been called.
*/
- (BOOL)isWindowLoaded
{
return _window;
return _window !== nil;
}
/*!
@@ -138,7 +163,28 @@
- (CPWindow)window
{
if (!_window)
[self loadWindow];
{
[self windowWillLoad];
[_document windowControllerWillLoadCib:self];
[self loadWindow];
if (_window === nil && [_cibOwner isKindOfClass:[CPDocument class]])
[self setWindow:[_cibOwner valueForKey:@"window"]];
if (!_window)
{
var reason = [CPString stringWithFormat:@"Window for %@ could not be loaded from Cib or no window specified. \
Override loadWindow to load the window manually.", self];
[CPException raise:CPInternalInconsistencyException reason:reason];
}
[self windowDidLoad];
[_document windowControllerDidLoadCib:self];
[self synchronizeWindowTitleWithDocumentName];
}
return _window;
}
@@ -149,8 +195,10 @@
*/
- (void)setWindow:(CPWindow)aWindow
{
[_window setWindowController:nil];
_window = aWindow;
[_window setWindowController:self];
[_window setNextResponder:self];
}
@@ -160,9 +208,6 @@
*/
- (void)windowDidLoad
{
[_document windowControllerDidLoadNib:self];
[self synchronizeWindowTitleWithDocumentName];
}
/*!
@@ -170,7 +215,6 @@
*/
- (void)windowWillLoad
{
[_document windowControllerWillLoadNib:self];
}
/*!
@@ -179,17 +223,20 @@
*/
- (void)setDocument:(CPDocument)aDocument
{
if (_document == aDocument)
if (_document === aDocument)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_document)
{
if (![self supportsMultipleDocuments])
[self removeDocument:_document];
[defaultCenter removeObserver:self
name:CPDocumentWillSaveNotification
object:_document];
[defaultCenter removeObserver:self
name:CPDocumentDidSaveNotification
object:_document];
@@ -198,16 +245,18 @@
name:CPDocumentDidFailToSaveNotification
object:_document];
}
_document = aDocument;
if (_document)
{
[self addDocument:_document];
[defaultCenter addObserver:self
selector:@selector(_documentWillSave:)
name:CPDocumentWillSaveNotification
object:_document];
[defaultCenter addObserver:self
selector:@selector(_documentDidSave:)
name:CPDocumentDidSaveNotification
@@ -217,13 +266,94 @@
selector:@selector(_documentDidFailToSave:)
name:CPDocumentDidFailToSaveNotification
object:_document];
[self setDocumentEdited:[_document isDocumentEdited]];
}
}
var viewController = [_document viewControllerForWindowController:self];
if (viewController)
[self setViewController:viewController];
[self synchronizeWindowTitleWithDocumentName];
}
- (void)setSupportsMultipleDocuments:(BOOL)shouldSupportMultipleDocuments
{
_supportsMultipleDocuments = shouldSupportMultipleDocuments;
}
- (BOOL)supportsMultipleDocuments
{
return _supportsMultipleDocuments;
}
- (void)addDocument:(CPDocument)aDocument
{
if (aDocument && ![_documents containsObject:aDocument])
[_documents addObject:aDocument];
}
- (void)removeDocument:(CPDocument)aDocument
{
var index = [_documents indexOfObjectIdenticalTo:aDocument];
if (index === CPNotFound)
return;
[_documents removeObjectAtIndex:index];
if (_document === aDocument && [_documents count])
[self setDocument:[_documents objectAtIndex:MIN(index, [_documents count] - 1)]];
}
- (void)removeDocumentAndCloseIfNecessary:(CPDocument)aDocument
{
[self removeDocument:aDocument];
if (![_documents count])
[self close];
}
- (CPArray)documents
{
return _documents;
}
- (void)setViewControllerContainerView:(CPView)aView
{
_viewControllerContainerView = aView;
}
- (void)viewControllerContainerView
{
return _viewControllerContainerView;
}
- (void)setViewController:(CPViewController)aViewController
{
var containerView = [self viewControllerContainerView] || [[self window] contentView],
view = [_viewController view],
frame = view ? [view frame] : [containerView bounds];
[view removeFromSuperview];
_viewController = aViewController;
view = [_viewController view];
if (view)
{
[view setFrame:frame];
[containerView addSubview:view];
}
}
- (CPViewController)viewController
{
return _viewController;
}
/* @ignore */
- (void)_documentWillSave:(CPNotification)aNotification
{
@@ -252,13 +382,49 @@
/*!
Sets whether the document has unsaved changes. The window can use this as a hint to
@param isEdited <code>YES</code> means the document has unsaved changes.
@param isEdited \c YES means the document has unsaved changes.
*/
- (void)setDocumentEdited:(BOOL)isEdited
{
[[self window] setDocumentEdited:isEdited];
}
- (void)close
{
[[self window] close];
}
- (void)setShouldCloseDocument:(BOOL)shouldCloseDocument
{
_shouldCloseDocument = shouldCloseDocument;
}
- (BOOL)shouldCloseDocument
{
return _shouldCloseDocument;
}
- (id)owner
{
return _cibOwner;
}
- (CPString)windowCibName
{
if (_windowCibName)
return _windowCibName;
return [[_windowCibPath lastPathComponent] stringByDeletingPathExtension];
}
- (CPString)windowCibPath
{
if (_windowCibPath)
return _windowCibPath;
return [[CPBundle mainBundle] pathForResource:_windowCibName + @".cib"];
}
// Setting and Getting Window Attributes
/*!
@@ -268,7 +434,7 @@
{
if (!_document || !_window)
return;
// [_window setRepresentedFilename:];
[_window setTitle:[self windowTitleForDocumentDisplayName:[_document displayName]]];
}
+30 -14
View File
@@ -24,17 +24,20 @@
@import <Foundation/CPURLConnection.j>
@import <Foundation/CPURLRequest.j>
@import "_CPCibClassSwapper.j"
@import "_CPCibCustomObject.j"
@import "_CPCibCustomResource.j"
@import "_CPCibCustomView.j"
@import "_CPCibKeyedUnarchiver.j"
@import "_CPCibObjectData.j"
@import "_CPCibProxyObject.j"
@import "_CPCibWindowTemplate.j"
CPCibOwner = @"CPCibOwner",
CPCibTopLevelObjects = @"CPCibTopLevelObjects",
CPCibReplacementClasses = @"CPCibReplacementClasses";
CPCibReplacementClasses = @"CPCibReplacementClasses",
CPCibExternalObjects = @"CPCibExternalObjects";
var CPCibObjectDataKey = @"CPCibObjectDataKey";
@@ -57,7 +60,7 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
if (self)
{
_data = [CPURLConnection sendSynchronousRequest:[CPURLRequest requestWithURL:aURL] returningResponse:nil error:nil];
_data = [CPURLConnection sendSynchronousRequest:[CPURLRequest requestWithURL:aURL] returningResponse:nil];
_awakenCustomResources = YES;
}
@@ -80,11 +83,25 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
return self;
}
- (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle loadDelegate:(id)aLoadDelegate
- (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle
{
if (![aName hasSuffix:@".cib"])
aName = [aName stringByAppendingString:@".cib"];
// If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later.
self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName]];
if (self)
_bundle = aBundle;
return self;
}
- (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle loadDelegate:(id)aLoadDelegate
{
if (![aName hasSuffix:@".cib"])
aName = [aName stringByAppendingString:@".cib"];
// If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later.
self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName] loadDelegate:aLoadDelegate];
@@ -124,6 +141,8 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
[unarchiver setClass:[replacementClasses objectForKey:key] forClassName:key];
}
[unarchiver setExternalObjectsForProxyIdentifiers:[anExternalNameTable objectForKey:CPCibExternalObjects]];
var objectData = [unarchiver decodeObjectForKey:CPCibObjectDataKey];
if (!objectData || ![objectData isKindOfClass:[_CPCibObjectData class]])
@@ -131,18 +150,10 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
var topLevelObjects = [anExternalNameTable objectForKey:CPCibTopLevelObjects];
[objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects]
[objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects];
[objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects];
[objectData awakeWithOwner:owner topLevelObjects:topLevelObjects];
var menu;
if ((menu = [objectData mainMenu]) != nil)
{
[CPApp setMainMenu:menu];
[CPMenu setMenuBarVisible:YES];
}
// Display Visible Windows.
[objectData displayVisibleWindows];
@@ -160,12 +171,17 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)data
{
_data = [CPData dataWithString:data];
// FIXME: Why aren't we getting connection:didFailWithError:
if (!data)
return [self connection:aConnection didFailWithError:nil];
_data = [CPData dataWithRawString:data];
}
- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
{
alert("cib: connection failed.");
if ([_loadDelegate respondsToSelector:@selector(cibDidFailToLoad:)])
[_loadDelegate cibDidFailToLoad:self];
_loadDelegate = nil;
}
+88
View File
@@ -0,0 +1,88 @@
/*
* CPCibConnector.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPKeyValueCoding.j>
var _CPCibConnectorSourceKey = @"_CPCibConnectorSourceKey",
_CPCibConnectorDestinationKey = @"_CPCibConnectorDestinationKey",
_CPCibConnectorLabelKey = @"_CPCibConnectorLabelKey";
@implementation CPCibConnector : CPObject
{
id _source @accessors(property=source);
id _destination @accessors(property=destination);
CPString _label @accessors(property=label);
}
- (void)replaceObject:(id)anObject withObject:(id)anotherObject
{
if (_source === anObject)
_source = anotherObject;
if (_destination === anObject)
_destination = anotherObject;
}
- (void)replaceObjects:(Object)replacementObjects
{
var replacement = replacementObjects[[_source UID]];
if (replacement !== undefined)
_source = replacement;
replacement = replacementObjects[[_destination UID]];
if (replacement !== undefined)
_destination = replacement;
}
@end
@implementation CPCibConnector (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_source = [aCoder decodeObjectForKey:_CPCibConnectorSourceKey];
_destination = [aCoder decodeObjectForKey:_CPCibConnectorDestinationKey];
_label = [aCoder decodeObjectForKey:_CPCibConnectorLabelKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_source forKey:_CPCibConnectorSourceKey];
[aCoder encodeObject:_destination forKey:_CPCibConnectorDestinationKey];
[aCoder encodeObject:_label forKey:_CPCibConnectorLabelKey];
}
@end
// For backwards compatibility.
@implementation _CPCibConnector : CPCibConnector { } @end
+82
View File
@@ -0,0 +1,82 @@
/*
* CPCibControlConnector.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPCibConnector.j"
@implementation CPCibControlConnector : CPCibConnector
{
}
- (void)establishConnection
{
var selectorName = _label,
selectorNameLength = [selectorName length];
if (selectorNameLength && selectorName.charAt(selectorNameLength - 1) !== ':')
selectorName += ':';
var selector = CPSelectorFromString(selectorName);
// Not having a selector is a fatal error.
if (!selector)
{
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] selector " + selectorName + @" does not exist."];
}
// If the destination doesn't respond to this selector, warn but don't die.
if (_destination && ![_destination respondsToSelector:selector])
{
CPLog.warn(@"Could not connect the action " + selector + @" to target of class " + [_destination className]);
return;
}
// Not being able to set the action is a fatal error.
if ([_source respondsToSelector:@selector(setAction:)])
objj_msgSend(_source, @selector(setAction:), selector);
else
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] " + [_source description] + @" does not respond to setAction:"];
// Not being able to set the target is a fatal error.
if ([_source respondsToSelector:@selector(setTarget:)])
objj_msgSend(_source, @selector(setTarget:), _destination);
else
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] " + [_source description] + @" does not respond to setTarget:"];
}
@end
@implementation _CPCibControlConnector : CPCibControlConnector
{
}
@end
+74 -24
View File
@@ -27,8 +27,6 @@
var CPCibOwner = @"CPCibOwner";
var LoadInfoForCib = {};
@implementation CPObject (CPCibLoading)
- (void)awakeFromCib
@@ -39,38 +37,90 @@ var LoadInfoForCib = {};
@implementation CPBundle (CPCibLoading)
+ (void)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable loadDelegate:aDelegate
+ (CPCib)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable
{
var cib = [[CPCib alloc] initWithContentsOfURL:anAbsolutePath loadDelegate:self];
LoadInfoForCib[[cib hash]] = { loadDelegate:aDelegate, externalNameTable:aNameTable };
return [[[CPCib alloc] initWithContentsOfURL:anAbsolutePath] instantiateCibWithExternalNameTable:aNameTable];
}
+ (void)loadCibNamed:(CPString)aName owner:(id)anOwner loadDelegate:(id)aDelegate
+ (CPCib)loadCibNamed:(CPString)aName owner:(id)anOwner
{
// Path is based solely on anOwner:
if (![aName hasSuffix:@".cib"])
aName = [aName stringByAppendingString:@".cib"];
// Path is based solely on anOwner:
var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle],
path = [bundle pathForResource:aName];
return [self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]];
}
- (CPCib)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable
{
return [[[CPCib alloc] initWithContentsOfURL:aFileName] instantiateCibWithExternalNameTable:aNameTable];
}
+ (CPCib)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable loadDelegate:aDelegate
{
return ([[CPCib alloc]
initWithContentsOfURL:anAbsolutePath
loadDelegate:[[_CPCibLoadDelegate alloc]
initWithLoadDelegate:aDelegate
externalNameTable:aNameTable]]);
}
+ (CPCib)loadCibNamed:(CPString)aName owner:(id)anOwner loadDelegate:(id)aDelegate
{
if (![aName hasSuffix:@".cib"])
aName = [aName stringByAppendingString:@".cib"];
// Path is based solely on anOwner:
var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle],
path = [bundle pathForResource:aName];
[self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner] loadDelegate:aDelegate];
return [self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner] loadDelegate:aDelegate];
}
- (void)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable loadDelegate:(id)aDelegate
- (CPCib)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable loadDelegate:(id)aDelegate
{
var cib = [[CPCib alloc] initWithCibNamed:aFileName bundle:self loadDelegate:[self class]];
LoadInfoForCib[[cib hash]] = { loadDelegate:aDelegate, externalNameTable:aNameTable };
}
+ (void)cibDidFinishLoading:(CPCib)aCib
{
var loadInfo = LoadInfoForCib[[aCib hash]];
delete LoadInfoForCib[[aCib hash]];
[aCib instantiateCibWithExternalNameTable:loadInfo.externalNameTable];
[loadInfo.loadDelegate cibDidFinishLoading:aCib];
return ([[CPCib alloc]
initWithCibNamed:aFileName
bundle:self
loadDelegate:[[_CPCibLoadDelegate alloc]
initWithLoadDelegate:aDelegate
externalNameTable:aNameTable]]);
}
@end
@implementation _CPCibLoadDelegate : CPObject
{
id _loadDelegate;
CPDictionary _externalNameTable;
}
- (id)initWithLoadDelegate:(id)aLoadDelegate externalNameTable:(id)anExternalNameTable
{
self = [self init];
if (self)
{
_loadDelegate = aLoadDelegate;
_externalNameTable = anExternalNameTable;
}
return self;
}
- (void)cibDidFinishLoading:(CPCib)aCib
{
[aCib instantiateCibWithExternalNameTable:_externalNameTable];
[_loadDelegate cibDidFinishLoading:aCib];
}
- (void)cibDidFailToLoad:(CPCib)aCib
{
[_loadDelegate cibDidFailToLoad:aCib];
}
@end

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