Compare commits

...
Author SHA1 Message Date
Alexander Ljungberg 7662f89193 Update some more version numbers. 2013-11-28 19:51:15 +00:00
Alexander Ljungberg dbb59f57ea This will be Cappuccino 0.9.7. 2013-11-28 19:48:29 +00:00
Alexander Ljungberg c1f538ece5 Formatting: whitespace.
Refs #1974.
2013-11-28 18:39:01 +00:00
Alexander Ljungberg b4cabc97d1 Merge pull request #1974 from mrcarlberg/protocol
Protocol support for Objective-J
2013-11-28 17:18:16 +00:00
Antoine Mercadal cf2e66d7fe Merge pull request #2021 from Dogild/sheetDoubleClickBug
Fixed: when doubleClicking to open/close a sheet, issues with the parentWindow and the frameOrigin of the sheet
2013-11-25 15:49:08 -08:00
Martin Carlberg e511638962 Fixed: Cleaned up return and parameter types on methods. 2013-11-24 22:21:56 +01:00
Martin Carlberg 8419001810 Merge branch 'master' of https://github.com/cappuccino/cappuccino into protocol 2013-11-22 14:23:52 +01:00
Alexandre Wilhelm e058d2e143 Fixed: when doubleClicking to open/close a sheet, issues with the parentWindow and the frameOrigin of the sheet
When opening a sheet, with a double click the frame origin of the sheet changed and the parent disappeared.
This PR fix this issue.

Test app in Tests/Manual/AttachedSheet/AppController.j
2013-11-21 17:42:43 -08:00
Antoine Mercadal 616f0c61ef Fixed: Typo introduced in previous PR merge 2013-11-18 16:26:50 -08:00
Antoine Mercadal d0ef8a2885 Merge pull request #2005 from adamsowinski/master
Fixes a bug with CPCursor push method.
2013-11-18 16:22:43 -08:00
Antoine Mercadal 985db21ed9 Merge pull request #1990 from spebbe/cpanimation_frame_rate
CPAnimation frame rate fixes.
2013-11-18 16:20:29 -08:00
Antoine Mercadal d0460ad202 Merge pull request #2017 from daboe01/fix-scrollview-sorting-while-editing
Fixed: _editingCellIndex is currently not considered when table columns are pressed
2013-11-18 16:08:57 -08:00
Antoine Mercadal 8ca7227185 Merge pull request #1970 from mrcarlberg/table_header_divider_thickness
New: Added themable attribute for divider thickness in table header view
2013-11-18 16:06:49 -08:00
Antoine Mercadal 6c8a21c1cc Merge pull request #1971 from mrcarlberg/table_view_grid_line_thickness
New: Added themable attribute for grid line thickness in table view
2013-11-18 16:06:01 -08:00
Antoine Mercadal 4a82dbc34d FIXED: Previous commit was actually missing to fill the drop view with the background color.
This patch restore the correct behavior and display corectly colors set as dropview-*-on-background-color
2013-11-15 17:59:41 -08:00
Antoine Mercadal 1cec1b0637 NEW: CPTableView drop view now supports theming
Previously, the style of the blueish view that shows up on CPTableView when user is about to drop something on it was hard coded.
This patch adds the following theme attributes in CPTableView

    // theme of the drop view for CPDragOperationOn on a non selected row
    dropview-on-background-color
    dropview-on-border-color
    dropview-on-border-width
    dropview-on-border-radius

    // theme of the drop view for CPDragOperationOn on a selected row
    dropview-on-selected-background-color
    dropview-on-selected-border-color
    dropview-on-selected-border-width
    dropview-on-selected-border-radius

    // theme of the drop view for CPDragOperationAbove on a non selected row
    dropview-above-border-color
    dropview-above-border-width

    // theme of the drop view for CPDragOperationAbove on a selected row
    dropview-above-selected-border-color
    dropview-above-selected-border-width

Aristo and Aristo2 have been updated, and use the same old hardcoded values.
2013-11-15 17:48:57 -08:00
Antoine Mercadal abd9506d40 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2013-11-15 10:40:10 -08:00
Antoine Mercadal 8f7a32141b FIXED: CPTextField was sometimes returning YES even if disabled
Preiviously, CPTextField's acceptsFirstResponder was returning YES even if the textfield was disabled.
This patch restore the correct Cocoa behavior.
2013-11-15 10:38:31 -08:00
daboe01 ff067374bc fix first responder assignment when pressing a header column 2013-11-15 10:55:05 +01:00
Alexander Ljungberg 6cbfa30652 Fixed: view coordinate conversion broken by previous commit.
Without this fix, -CPView convertPoint:fromView was broken due to the changes made in #1998. In particular, the transform for the fromView would be calculated and then just thrown away if the views were in the same window. This happened to work in some specific cases and the lack of unit tests concealed the error.

This fix properly applies the transforms when two views are in the same window without one of them necessarily being inside the other.

Refs #1998.
2013-11-04 00:03:31 +00:00
Adam Sowinski f5a1a6725d Simplified currentCursor assignment. 2013-10-29 23:35:04 +00:00
Antoine Mercadal 2508fa7a97 Merge pull request #1998 from Dogild/scaling-support
New: Added support for scaling in CPView
2013-10-29 12:54:12 -07:00
Antoine Mercadal 0b351ac2d7 Merge pull request #2011 from Dogild/CPTextMovements
New: Added Movement Codes for CPTextDidEndEditingNotification
2013-10-29 11:27:17 -07:00
Antoine Mercadal 24b44c2acf Merge pull request #2010 from daboe01/fix-textFields-on-different-windows-can-clobber-each-others-contents
Fixed: editing textFields on different windows can clobber each others contents
2013-10-29 11:23:00 -07:00
Alexandre Wilhelm 8f70cebefc Typo 2013-10-29 11:22:55 -07:00
Antoine Mercadal 6e7fc5c887 Merge pull request #2008 from Dogild/souldSelectTableColumnFix
Fixed: shouldSelectTableColumn isn't called in CPTableView and CPOutlineView
2013-10-29 11:22:01 -07:00
Alexandre Wilhelm 7f53d15e75 Fixed: the userInfo of the notification from textDidEndEditing is wrong
Previously, when overriding the method textDidEndEditing, the userInfo notification didn't contain the information about CPTextMovement
2013-10-29 11:13:48 -07:00
Alexander Ljungberg d3ab2a0f3d New: "//site.com/x" style URL support in CPURL and CFURL.
With this feature, CFURL and CPURL can now correctly transform a relative scheme URL starting with a double-slash.

For example, + CPURL URLWithString:@"//a.se/a" relativeToURL:@"ftp://b.se/c" would represent an absolute URL of "ftp://a.se/a".
2013-10-29 15:03:37 +00:00
Alexander Ljungberg af26523e36 New: text underline support for private _CPImageAndTextView.
This features presents a less hack-y way to underline text for those not afraid to use private, internal APIs.
2013-10-29 11:40:25 +00:00
Alexandre Wilhelm ebc1025fd9 New: Added Movement Codes for CPTextDidEndEditingNotification
This PR adds a new feature for CPControl. Now when leaving the control, the userInfo of the notification CPTextDidEndEditingNotification contains the last movements of the control as in COCOA

Test app in Tests/Manual/CPTextFieldMovementsTest
2013-10-29 01:20:00 -07:00
Adam Sowinski a96242324a Merge branch 'master' of https://github.com/cappuccino/cappuccino 2013-10-28 17:00:42 +00:00
daboe01 d1406e1b8f Fixed: editing textFields on different windows can clobber each others contents
Was be caused by resignFirstResponder not checking that the input owner is self.

Fixes #1983
2013-10-27 13:46:00 +01:00
Alexandre Wilhelm c22f489ee9 Fixed: shouldSelectTableColumn isn't called in CPTableView and CPOutlineView
Previously shouldSelectTableColumn wasn't called in CPTableView and CPOutlineView.
This PR resolves this issue, shouldSelectTableColumn is now called between selectionShouldChangeInTableView and tableViewSelectionIsChanging as in COCOA.

Test app Tests/Manual/TableTest/DelegateSelectionTest/
2013-10-24 22:13:35 -07:00
Antoine Mercadal 0ac74fe16e Merge pull request #2007 from krodelin/fix-CPNumber-numberWithBool
Fixed: Return a Number from CPNumber>>numberWithBool:
2013-10-24 10:37:05 -07:00
Udo Schneider df2be926a5 Fixed: Return a Number from CPNumber>>numberWithBool:
The Cocoa signature for this method
	+ (NSNumber *)numberWithBool:(BOOL)value
implies that a number is being returned. In Cappuccino a Boolean is returned.

This leads to some problems e.g. in
addObserver:forKeyPath:options:context: with CPKeyValueObservingOptionPrior
and observeValueForKeyPath:ofObject:change:context: with CPKeyValueObservingOptionPrior.

Setting CPKeyValueObservingOptionPrior leads to CPKeyValueChangeNotificationIsPriorKey being set to 1 (which should be equal to [NSNumber numberWithBool:YES] as documented in https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html. The actual value though is true as [CPNumber numberWithBool:YES] does not return a number but a boolean. This commit fixes this issue.
2013-10-24 19:20:45 +02:00
Adam Sowinski 71ed0d6cfc Merge branch 'master' of https://github.com/cappuccino/cappuccino 2013-10-22 11:19:21 +01:00
Antoine Mercadal 2d96875574 Merge pull request #2004 from Dogild/comboBox-trapMouse
Fixed: CPComboBox don't close when clicking on the scroll
2013-10-21 14:25:20 -07:00
Antoine Mercadal 949c618ff1 Merge pull request #2006 from Dogild/outlineView-selectItem
Fixed: The delegate method shouldSelectItem doesn't work in CPOutlineView
2013-10-21 14:24:35 -07:00
Alexandre Wilhelm 8909576a0b Changed comment 2013-10-20 21:01:10 -07:00
Alexandre Wilhelm 0afc903138 Fixed: The delegate method shouldSelectItem doesn't work in CPOutlineView
Previously the delegate method shouldSelectItem didn't work in CPOutlineView.
It didn't work because the checking method _delegateRespondsToSelectionIndexesForProposedSelection and _delegateRespondsToShouldSelectRow didn't check if the real delegate of the outlineView implemented the methods
2013-10-20 20:57:42 -07:00
Adam Sowinski 8971972a28 Fixed a bug where currentCursor variable was assigned a CPNumber instance instead of CPCursor instance. 2013-10-21 00:26:27 +01:00
Alexandre Wilhelm 2df13b7ffc Fixed: CPComboBox don't close when clicking on the scroll
Previously CPComboBox don't close when clicking on the scroll, now it does

Fixed #1991
2013-10-19 00:40:19 -07:00
Antoine Mercadal bb6b5c1232 Merge pull request #2003 from Dogild/refactor-tableView
Fixed: shouldSelectRow was called with selectionIndexesForProposedSelect...
2013-10-18 13:03:49 -07:00
Alexandre Wilhelm ab1c689e4e Optimization with menu. Fixed issue with unsigned bit and delegate Fixed #1994 2013-10-18 12:01:33 -07:00
Alexandre Wilhelm 7bdedca350 Delegate WillDisplayView is called before setNeedsDisplay now 2013-10-18 11:55:40 -07:00
Alexandre Wilhelm e1eac245a7 Changed naming of the private delegate call. Fixed small bugs 2013-10-18 11:47:46 -07:00
Alexandre Wilhelm cf19aef382 Added method selectionIndexesForProposedSelection in CPOutlineView 2013-10-17 15:54:40 -07:00
Alexandre Wilhelm d6e40332c4 Removed comments 2013-10-17 14:32:34 -07:00
Alexandre Wilhelm 4b8a6ee674 Fixed: shouldSelectRow was called with selectionIndexesForProposedSelection
Previously the method shouldSelectRow was called even it's the method selectionIndexesForProposedSelection was implemented by the delegate. Now it works as in Cocoa.
The method selectionIndexesForProposedSelection is called when it has to be called, like in Cocoa.
This PR adds new methods to check and call the delegate/datasource methods more easily

Test app in Tests/Manual/TableTest/DelegateSelectionTest/
2013-10-17 14:26:19 -07:00
Antoine Mercadal 406a049380 Fixed: Previous commit was preventing to select in the void if selectionShouldChangeInTableView: was not implemented
This patch restore the correct behavior
2013-10-16 16:48:50 -07:00
Antoine Mercadal b2dc9c225c Merge pull request #1999 from Dogild/delegate-CPTableView-Methods
Fixed: Delegate method of CPTableView aren't call in the good order
2013-10-16 16:28:48 -07:00
Antoine Mercadal 86e94178e3 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2013-10-16 16:10:11 -07:00
Antoine Mercadal f75955bb04 Fixed: CPNumberFormatter minimum and maximum wrong encoding when set to nil
Previously, a decoded CPNumberFormatter was converting the minimum and maximum values to 0 if they were set to nil. This was causing unexpected behavior when creating a CPNumberFormatter from a xib. This patch actually decodes _minimum and _maximum values as objects to preserve nil.

Test added in Foundation/CPNumberFormatter.j
2013-10-16 16:07:00 -07:00
Alexandre Wilhelm f0a9696634 Fixed typo 2013-10-16 15:03:35 -07:00
Alexandre Wilhelm 016c267e69 Fixed: Delegate method of CPTableView aren't call in the good order
Previously the call of the delegate method of a CPTableView weren't call in the good order, specially the selecting method.
Now it works as in Cocoa.
Fixed typos

Test app in Tests/Manual/TableTest/DelegateSelectionTest
2013-10-16 15:01:28 -07:00
Antoine Mercadal f6028455b7 Merge pull request #1969 from Dogild/xCodeCappCreateProject
New: Added menu Create Project... in xCodeCapp
2013-10-15 14:05:12 -07:00
Antoine Mercadal ed99833894 Merge pull request #1996 from rgv151/master
PATCH: Implement shouldExpand/Collapse delegate for CPOutlineView
2013-10-15 14:04:46 -07:00
Alexandre Wilhelm ef5f26fd81 New: Added support for scaling in CPView
This PR adds the support of scaling in CPView.
There are two new public methods in CPView : -(void)scaleUnitSquareToSize: and -(void)setScaleSize:
-(void)scaleUnitSquareToSize: works exactly as in COCOA, it means if you set a first scale to 0.5 and then 0.5 again, the scaleSize of the view will be 0.25
-(void)setScaleSize: works with the value given. If you set 0.5 after you just seted 0.5 the scaleSize will be 0.5. This method is definitly better in using, specially when using the scaleSize binding with a slider.

Test app in Tests/Manual/ScalingTest
2013-10-15 14:03:26 -07:00
Antoine Mercadal 2f18218ce5 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2013-10-15 12:41:20 -07:00
Antoine Mercadal 0b5a98d3fe FIXED: lineBreakMode set to CPLineBreakByTruncating* was trimming consecutive white spaces
Previously, using a truncating line break mode on a CPTextField and setting the string value to "test      test" was displaying "test test". This patch changes the css white-space property from "nowrap" to "pre" which preserves the white spaces.
2013-10-15 12:39:03 -07:00
Bruce Doan 918543d617 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2013-10-12 23:00:12 +07:00
Bruce Doan 6f8d6a5b25 Some minor fixes to pass the capp_lint checks 2013-10-09 00:09:30 +07:00
aparajita 95082c3263 Merge pull request #1982 from Dogild/MenuFix
Fixed: Menu disappears when opening a submenu
2013-10-07 04:29:20 -07:00
Bruce Doan 8503081a6f PATCH: Implement shouldExpand/Collapse delegate for CPOutlineView 2013-10-06 23:47:25 +07:00
Alexander Ljungberg 6efefbedcd Test: disabling a highlighted menu item should deselect it.
Refs #1762.
2013-09-23 11:24:54 +01:00
Alexander Ljungberg eef91c0240 Merge pull request #1976 from Dogild/HighlightedDisabledMenu
Fixed: a disabled CPMenuItem could still have a selected background
2013-09-23 11:22:27 +01:00
Björn Sperber 5cefce1cf0 Respect frameRate when scheduling timer in CPAnimation. Treat a frameRate of 0 as "really fast" instead of CPTimer default (10 fps). 2013-09-19 13:52:49 +02:00
Martin Carlberg f0e2daf6c7 Fixed: Add get and set instance methods to class definition when ivar has accessors.
This caused 'Method is not implemented' warnings when a class implemented protocol declared set and get methods as 'accessors' on an ivar.
2013-09-12 21:54:57 +02:00
Martin Carlberg 9f0d8c54e4 Fixed: Uses current protocolDefs when compiling accessors
This caused 'null is not an object' type error when class declaration with 'accessors' declared ivars was in the same file as the protocol it was conforming to.
2013-09-12 21:47:15 +02:00
Alexander Ljungberg b20d711922 Merge pull request #1984 from mrcarlberg/if-empty-statement
Fixed: Compiler now generates correct empty statement after 'if (a);'
2013-09-09 15:53:21 +01:00
Martin Carlberg 23fb618596 Fixed: Compiler now generates correct empty statement after 'if (a);'
Earlier the compiler generated the 'if' without the last ';' when a empty statement is used, with sometimes devastating result. The same if an empty statement was after the 'else'.

I have also added a test case for some different empty statement senarios.
2013-09-09 16:38:38 +02:00
Aparajita Fishman 2dff348cca Fixed: text fields in full platform windows could not be selected. 2013-09-02 22:14:16 -04:00
Martin Carlberg ba0604320e Fixed: Should be 'objj_allocateProtocol' and 'objj_registerProtocol' not 'objc_allocateProtocol' and 'objc_registerProtocol' 2013-08-31 15:33:32 +02:00
Martin Carlberg c979a69e6b Fixed: Compiler can now handle only @action/IBAction declared return type when checking for 'Conflicting return type' method declaration.
Also made the warning message point to correct return type token when type is not declared.
2013-08-28 11:23:55 +02:00
Aparajita Fishman 40e06a634e Fixed: background-color was rendering subviews invisible. 2013-08-26 13:50:42 -04:00
Aparajita Fishman 30441b109f Fixed: windows that were autoresized and not constrainable would obey the global CPWindowConstrainToScreen flag.
Previously, if a window had an autoresizingMask and was marked as not being constrained (for example _CPMenuBarWindow), and the CPWindowConstrainToScreen was set to NO, resizing the platform window would not autoresize the window.

This commit ensures that windows that autoresize but don't care about constraining will resize with the platform window no matter what.

Fixes #1981.
2013-08-23 18:28:40 -04:00
Alexandre Wilhelm f17fd6a448 Fixed: Menu disappears when opening a submenu
Previously when opening a submenu from a menu, the main menu disappears because a issue with the poolMenuWindow.
This PR fixes this bug.
It also handle more properly the case when an user is making several right clicks on a responder (origin problem with the ghost menu).

Fixed #1887
2013-08-23 13:59:11 -07:00
Martin Carlberg 0e4ad998d8 Fixed: Remove all protocols in objj_resetRegisterClasses 2013-08-22 16:54:19 +02:00
Martin Carlberg 9eebb0a64b Fixed: Pass correct node to error message when finding duplicated protocol 2013-08-22 16:53:22 +02:00
Martin Carlberg 9f7d0578e5 New: Added the basic protocols CPObject and CPCoding 2013-08-22 14:31:15 +02:00
Martin Carlberg 0afe21dd29 Fixed: Copy method descriptions to an array instead of JSObject 2013-08-22 12:37:29 +02:00
Martin Carlberg cfc682c165 Fixed: Protocol methods is now registered in the correct place 2013-08-22 12:36:29 +02:00
Martin Carlberg c326168e83 Fixed: Protocol definition in compiler was not created correct from protocol definition in the runtime 2013-08-22 12:35:16 +02:00
Martin Carlberg b8b96a17d7 Fixed: Check if global function exists in correct way 2013-08-22 12:34:14 +02:00
Martin Carlberg 48d98f7ebd Fixed: Added theme attribute 'divider-thickness' to wrong class when doing manual merge. 2013-08-20 11:22:39 +02:00
Martin Carlberg 7044c1cda4 Merge branch 'master' of https://github.com/cappuccino/cappuccino into table_header_divider_thickness 2013-08-20 09:44:17 +02:00
Alexander Ljungberg 594ea6e5cb Simplify. 2013-08-19 22:31:21 +01:00
Alexander Ljungberg 957a572bcd Fixed: missing imports. 2013-08-19 22:31:21 +01:00
Alexander Ljungberg 08eff6ec22 New: grey out Edit menu non applicable items for text fields.
Copy, cut and delete are now disabled if there's no selection in the active text field. Cut, paste and delete are greyed out if the text field is not editable (a label).

Refs #1964.
2013-08-19 22:31:21 +01:00
Alexander Ljungberg 3fb12f6382 Clean up. 2013-08-19 22:31:21 +01:00
Alexander Ljungberg 5958220bdd New: CPTextField deleteForward:.
This enables delete forward to be activated through action connections to text fields (or the first responder).
2013-08-19 22:31:21 +01:00
Alexander Ljungberg 648dc6e86c New: Edit > Delete menu item support for text fields.
This menu item deletes the current selection if there is one.

Refs #1964.
2013-08-19 22:31:21 +01:00
Alexander Ljungberg 9d43a559fe Fixed: - CPTextField deleteBackward: required selection.
According to the spec, deleteBackward: should remove the element before the insertion point if there is no selection (e.g. actually delete backwards).
2013-08-19 22:31:21 +01:00
Alexander Ljungberg 168738fb93 Return false for mouse handler if propagation is stopped.
Refs #1964.
2013-08-19 22:31:20 +01:00
Alexander Ljungberg 376b3a496e Fixed: copy and paste by Cappuccino Edit menu not working.
When the Edit menu is used to cut or to paste, Cappuccino needs to do all the work of making it happen. But the current code relied on the browser doing part of the work.

This fix adds new state so CPTextField can know if it should expect the browser to do some of the work or not.

Refs #1964.
2013-08-19 22:31:20 +01:00
Alexander Ljungberg 58d5d7d731 Fixed: selectable text deselected when a menu was clicked.
This made it impossible to select some (non-editable) text, and then to click a Cappuccino menu option like Edit > Copy. Upon the click of Edit, the just selected text would be lost.

This was caused by some very mysterious code focusing and blurring an input every time propagation was stopped. Since it wasn't documented, the snippet was just removed for now. If it turns out it was useful we'll need to add it back and make sure it's not called in this scenario (while documenting it properly).

Refs #1964.
2013-08-19 22:31:20 +01:00
Antoine Mercadal f637931ba7 FIXED: Bug introduced with my previous commit, preventing popover to open in some cases.
Previously, addChildWindow:ordered: was setting the platform window of the child window.
This patch restore the correct behaviour, and fix a bug with _CPAutocompleteMenu. Now the autocomplete menu is opened as a child of its textfield window using the correct platform window.
2013-08-15 19:40:40 -07:00
Alexandre Wilhelm ec4b348369 Fixed: a disabled CPMenuItem could still have a selected background
Previously it was possible to have a highlighted CPMenuItem for a disabled CPMenuItem. (To get that, select an item, close the menu, disabled the item manually and then open the menu again).
Now it is not possible to get this behavior.
2013-08-15 17:15:51 -07:00
Alexandre Wilhelm 879ede5d70 Changed the format of the xib to 4.6 2013-08-15 16:37:07 -07:00
Antoine Mercadal 1e7dd0dc59 FIXED: Bug that could open a child window in the wrong platform window
Previously, addChildWindow:ordered: did not set not the child window's platform window. This could result to open them in the wrong browser window. This patch makes sure to set the parent's platform window as the child window's platform window.
2013-08-15 13:33:50 -07:00
Aparajita Fishman f1077719fb Fixed: main div in index.html had wrong id.
The div's id was changed to cappuccino, and it was supposed to be cappuccino-body, which broke code that relied on the DOM remaining stable during startup.
2013-08-15 10:40:18 -04:00
Aparajita Fishman c9dae8ced4 Revert "Fixed: nib2cib used a temp file for plutil output instead of using stdout."
This reverts commit 4e4fc389d2. It wasn't working reliably.
2013-08-15 10:35:25 -04:00
Aparajita Fishman 4e4fc389d2 Fixed: nib2cib used a temp file for plutil output instead of using stdout.
Previously, nib2cib sent the output of plutil to a temp file, then read that file. plutil supports writing to stdout, which avoids the temp file completely, so that is what we do now.
2013-08-15 10:21:45 -04:00
Aparajita Fishman fa86c54fff Fixed: missing semicolon. 2013-08-15 10:21:45 -04:00
Alexander Ljungberg 2065c7fbc8 Fixed: CPTextField deleteBackward: leaving 1 character.
Previously if - CPTextField `deleteBackward:` was invoked without it being a browser backspace key event for an actively edited text field, the first character in the current selection would not be deleted.

This fix makes it so that `deleteBackward:` works properly from any caller. The fix also undoes a mistake in a recent previous commit which prevented the text field from visually updating after deletion.
2013-08-14 16:23:57 +01:00
Alexander Ljungberg 100efc6450 Formatting. 2013-08-13 11:00:48 +01:00
Aparajita Fishman 987d2a2d73 Formatting 2013-08-12 23:31:34 -04:00
Martin Carlberg 63dac5553e Fixed: Updated test case to include '@required' and '@optional' keywords 2013-08-12 22:46:26 +02:00
Martin Carlberg 0b75876283 Fixed: Moved incorrect positioned parenthesis to handle '@required' token 2013-08-12 22:44:35 +02:00
Martin Carlberg beec0c5293 Fixed: Handle '@required' before any method declarations 2013-08-12 22:43:03 +02:00
Martin Carlberg 672ed6ed0c Fixed: Handle protocol declaration with no method declarations 2013-08-12 22:41:36 +02:00
Aparajita Fishman d6f1c2bc57 Fixed: attempting to use an unsupported built in image in IB would generate an error, but not explain why.
Previously, attempting to use an unsupported built in image such as NSActionTemplate would generate an error message that said, "The image “NSActionTemplate” cannot be found." This would lead the user to think that there was something wrong with nib2cib, instead of understanding that only certain built in images are supported (currently NSAddTemplate and NSRemoveTemplate).

With this commit, an attempt to use an unsupported built in image (where built in is assumed to be any name that matches /^NS[A-Z][A-Za-z]+$/) results in the error message "The built in image “<name>” is not supported."
2013-08-12 15:18:07 -04:00
Martin Carlberg 3b8aedf5aa Merge branch 'master' of https://github.com/cappuccino/cappuccino into protocol 2013-08-12 18:25:00 +02:00
Alexander Ljungberg d40449c469 Ignore XCC .xcodeproj files in tests. 2013-08-12 17:03:31 +01:00
Alexander Ljungberg 8bdbb5d333 Fixed: _CPImageAndTextView unguarded platform access.
This could cause issues during jake deploy or unit testing.
2013-08-12 16:57:50 +01:00
Alexander Ljungberg 638d8de472 New: triple click selectable text field to select all.
This matches Cocoa behaviour. Cocoa also supports double click to select the current word but we currently don't know what word is being clicked. In some browsers (e.g. Safari) this will work natively. Chrome on the other hand selects something random after double click on a non editable div.
2013-08-12 16:57:07 +01:00
Alexander Ljungberg 03acecdec9 New: selectable textfield Select All (Cmd-A, Ctrl-A) support.
Like in Cocoa, a non-editable but selectable text can now be clicked and all text can be selected with the Edit > Select All option or the associated keyboard equivalent. Just like in Cocoa this works on selectable text labels as well (text fields without a bezel).
2013-08-12 16:44:46 +01:00
Martin Carlberg f74312dc42 Fixed: Allow type on return or parameter type to be a class if superclass or protocol declared it as 'id' 2013-08-12 16:55:35 +02:00
Martin Carlberg 2e216d7e9a Fixed: Make default return type to 'void' for '@action' or 'IBAction' marked method. 2013-08-12 16:53:19 +02:00
Alexander Ljungberg 0e7b592786 Fixed: certain editing actions allowed for disabled text fields. 2013-08-12 15:52:36 +01:00
Martin Carlberg 29d7833fcb Fixed: Renamed local variable that used reserved variable name ('arguments') 2013-08-12 16:52:07 +02:00
Martin Carlberg 4eba639c73 Fixed: Allow some tokens to be identifiers 2013-08-12 16:50:34 +02:00
Martin Carlberg 361f421816 Fixed: Added 'id' as a token and enforce that protocol can only follow 'id' as a Objective-J type 2013-08-12 16:49:39 +02:00
Martin Carlberg bb58a206a8 Fixed: Removed all warnings of conflicting return and parameter types caused by the new compiler 2013-08-12 16:46:14 +02:00
Alexander Ljungberg 4775b594f5 Test: extended copy and paste manual test.
This change adds selectable text fields and labels to the potential copy sources.

Refs #1972.
2013-08-12 15:44:22 +01:00
Alexander Ljungberg a90180a92f Fixed: CPTextField copy: only worked for editable text fields.
A non-editable text field does not use an input field, and so does not track what is selected within it. We will use a workaround for now but in a CoreText based text field in the future we'd be likely to always have a correct selectedRange and be able to remove this hack.

Fixes #1972.
2013-08-12 15:43:24 +01:00
Alexander Ljungberg 377618dcd4 New: non-editable but selectable text fields can become the first responder.
Without this change, text fields with setEditable:NO but setSelectable:YES could not become the first responder, and so would not listen for copy: events.

This change allows selectable fields to become the first responder, taking advantage of the distinction between first responder and first key responder maintained internally in CPTextField - a merely selectable field does not become the first key responder.

Refs #1972.
2013-08-12 15:41:10 +01:00
Martin Carlberg 1cfc8139b9 Fixed: Removed double declared ivar 2013-08-12 16:39:54 +02:00
Alexander Ljungberg 4b4ac5d8b7 Fixed: certain actions would edit a non-editable text field. 2013-08-12 15:36:16 +01:00
Martin Carlberg 7c2c2a3114 Fixed: Allow protocols in interface declaration 2013-08-12 09:40:20 +02:00
Alexandre Wilhelm c0dce226bf Changed capp_buid to cap_build.... 2013-08-11 23:24:38 -07:00
Alexandre Wilhelm 2fcf1f4ac4 Added: Creating project with symlinks
Previously it wasn't possible to create project with symlink.
Now you can set in the preferences of xCodeCapp if you want to create your project with symlink or not with a radioButton.
When launching xCodeCapp, the system will check if $CAPP_BUILD is defined or not. If not, the button in the preference will be disabled and a toolTip will advice how to create a $CAPP_BUILD variable.
2013-08-11 14:04:50 -07:00
Aparajita Fishman 8d47b3f048 Fixed: CGContextAddArc would fail if the path was empty.
Previously, CGContextAddArc would not work with an empty path. In Cocoa, CGContextAddArc implicitly starts a path, so it does not require a non-empty path.

This commit allows CGContextAddArc to be used with an empty path.
2013-08-10 17:51:20 -04:00
Aparajita Fishman 06e392ee22 Fixed: CPApplicationDidChangeScreenParametersNotification was sent once for each window.
Should be sent only once per resize.
2013-08-09 15:01:30 -04:00
Martin Carlberg d38125db13 New: Added Objective-J protocol support
The Objective-J parser and compiler now handles protocol syntax. The Objective-J runtime has new functions to handle protocols. The method 'conformsToProtocol:' has been added to CPObject as an instance and a class method.
2013-08-09 19:02:45 +02:00
Aparajita Fishman 3beb753c63 Fixed: when constraining a window resize, the horizontal margin was fixed (and too large).
Previously a fixed margin of 40px was maintained at the left/right of a window when resizing it, which was excessive.

Now the minimum size allowed during a resize is the same as the minimum margin allowed when moving a window, which is determined based on the type of window.
2013-08-09 09:16:43 -04:00
Aparajita Fishman d751fea510 Fixed: constraining window's to the screen did not respect a window's minSize.
Previously, when the platform window was resized, windows were moved/resized to stay within the virtual screen, but if the window had a minimum size, it was not respected.

This commit ensures that if a window has a minimum size, it will always be respected.
2013-08-09 09:12:07 -04:00
Aparajita Fishman 42ad40d10d New: sort the keys in CPDictionary -description.
This makes it easier to find an item in a large dictionary.
2013-08-09 08:28:37 -04:00
Aparajita Fishman 86e5c15e3c Formatting, optimizations. 2013-08-09 08:28:37 -04:00
Aparajita Fishman 6bec4064b5 Fixed: window width was not constrained when platform window was resized.
Previously window heights were constrained to the usable screen when the platform window (virtual screen) resized, but widths were not. The code was there to constrain the width, but it wasn't being used.

This commit ensures the width constraining code is executed.
2013-08-09 08:28:36 -04:00
Aparajita Fishman fc931902d7 New: notify when the platform window resizes.
The platform window is the virtual screen for Cappuccino windows. Per Cocoa, when the screen (platform window) resizes, CPApplicationDidChangeScreenParametersNotification is sent and the CPApplication delegate method applicationDidChangeScreenParameters: is called.
2013-08-09 08:28:36 -04:00
Aparajita Fishman d336c30ab6 New: moved application constants to a separate file. 2013-08-09 08:28:36 -04:00
Aparajita Fishman 9fb966d0ca Docs 2013-08-09 08:28:36 -04:00
Aparajita Fishman 3c2a2f39fc Fixed: resizing a window did not attempt to maintain a minimum margin on screen.
Previously, window moves were constrained such that a minimum margin of the window was visible on screen, but window resizes were not constrained, allowing the user to effectively move the window off screen.

Now resizes are constrained such that a minimum margin of the window is always visible on screen so that the window does not get "lost".
2013-08-09 08:28:36 -04:00
Aparajita Fishman 2183c6d383 New: added methods to globally turn off window constraining when resizing the platform window.
Previously, whenever the platform window (virtual screen) resized, windows were moved or resized to keep them on screen. This could not be easily overridden by the user.

Two class methods have been added:

CPWindow +setConstrainWindowsToUsableScreen:
CPWindow +constrainWindowsToUsableScreen

If +setConstrainWindowsToUsableScreen:NO is called, then resizing the platform window will not move or resize user windows.
2013-08-09 08:28:36 -04:00
Antoine Mercadal e61b6783b3 FIXED: Crash when the autocomplete menu of a Token Field is visible while one of the superviews is removed
Previously, _CPAutocompleteMenu was trying to relayout itself using its related textfield's window frame. This was
causing a crash if one of the CPTokenField's superview has been removed. This fix ensures to stop layouting if the related text field has no window anymore.
2013-08-06 16:04:39 -07:00
Martin Carlberg 7f089972bd New: Added themable attribute for divider thickness in table header view 2013-08-06 11:54:13 +02:00
Martin Carlberg 5a7c2e5617 New: Added themable attribute for grid line thickness in table view 2013-08-06 11:53:13 +02:00
Alexandre Wilhelm ceb22a47c5 New: Added menu Create Project... in xCodeCapp
Previously it wasn't possible to create a capp project from xCodeCapp.
Now you can create one from the menu item Create Project, xCodeCapp will load the project as the same time is no error occurs.
When choosing an existing project, xCodeCapp removes the old one (this is asked to the user, would you like to replace the files...).
In case of errors, the errors panel appears.
2013-08-06 00:41:38 -07:00
Aparajita Fishman 3c9435ed21 Fixed: FileRequest was broken under CommonJS.
The progress event was being used even under CommonJS, which broke file loading and thus jake deploy.
2013-08-02 19:05:57 -04:00
Aparajita Fishman 9e7346f1e8 New: new index.html with loading progress by default.
Previously, the index[-debug].html in the default capp templates did not include a loading progress function. We just had the plain spinner, which gave no visible sign of progress.

Now the capp templates include a progress function and a nice iOS7-ish progress thermometer	is displayed during loading (except when run directly from source). 'jake debug' and 'jake release' will now generate the application/image sizes needed to display loading progress. The old spinner.gif has been removed.

In addition, the message displayed when JavaScript is unavailable has been simplified and shows a link to www.enable-javascript.com instead of the missing link to our old site.
2013-08-02 17:49:45 -04:00
Aparajita Fishman 4221acf3fd New: added support for continuous load progress notification.
Previously, Cappuccino only called OBJJ_PROGRESS_CALLBACK when an executable or image sprite file was finished loading. Only a slow connection, this would result in long periods with no visible progress.

Now OBJJ_PROGRESS_CALLBACK is called continuously during download via the XHR progress event. All supported browsers except IE 9 support this event.
2013-08-02 17:33:59 -04:00
Aparajita Fishman b49a872806 Fixed: IE would scroll entire app to the left, leaving white space on the right.
Previously, in IE you could scroll the entire browser window to the right a very long way, leaving white space to the right of the Cappuccino app. This was caused by a 100,000px wide measurement span that was supposed to be positioned at left:-100,000 but was mistakenly at left:-10,000, which left 90,000px on screen.

This commit fixes the left position of that span, eliminating the ability to scroll the app.

Fixes #1725
2013-08-01 16:20:47 -04:00
Aparajita Fishman 655bc0348b Formatting 2013-07-30 09:40:18 -04:00
Aparajita Fishman 2b23374ec7 New: CPAlert supports custom didEnd selector or block.
Previously, unless you were using a sheet alert, there was no way to set a custom dismissal handler for an alert. In Cocoa alerts are synchronous, in Cappuccino they are asynchronous, which meant that a single dismissal handler had to handle all possible non-sheet alerts.

This commit adds several methods which add two ways to specify a custom dismissal handler: via delegate/selector, and via a block (function). The new methods are:

setDidEndSelector:
runModalWithDidEndBlock:
beginSheetModalForWindow:didEndBlock:

Note that didEnd blocks are transient and take precedence over didEnd selectors.

The CPAlertTest demo was updated to fix some bugs and added the ability to run the tests using blocks.
2013-07-29 13:06:57 -04:00
Aparajita Fishman 1df1c1e9ab Merge branch 'refs/heads/contentViewResizeFix' 2013-07-27 13:42:05 -04:00
Aparajita Fishman 084bc84160 Fixed: removed redundant code. 2013-07-27 13:41:35 -04:00
Aparajita Fishman d8281a6e22 Fixed: simplified the overlay scroller test, documented the technique.
Previously the inner element's offsetWidth was tested before and after setting the overflow to scroll. This is unnecessary, we can just set the overflow to scroll and test the outer element's clientWidth vs. offsetWidth. By definition, clientWidth does not include scrollbars, whereas offsetWidth does. So if they are equal then overlay scrollers must be in use.

Note that FireFox (as of version 22) does not support overlay scrollers, so even if the system does, Cappuccino will not on FireFox unless the programmer forces overlay scrollers.
2013-07-27 09:27:58 -04:00
Aparajita Fishman bdd29936d7 Fixed: test for fixed scrollbars was broken by a previous commit. 2013-07-26 23:38:20 -04:00
Aparajita Fishman f3f1f72ae2 Fixed: variable move in previous commit broke selection notifications. 2013-07-26 12:17:52 -04:00
Aparajita Fishman 2da6c88fad Fixed: constant name was misleading.
Previously CPTimerMinTimeInterval was used as a constant for the *default* time interval used when a timer was initialized with an interval <= 0. It isn't the minimum, it is possible to create a timer with an interval less than that constant's value.

The name has been changed to CPTimerDefaultTimeInterval to make it clearer what it's purpose is. It has also been changed to a #define, that will result in smaller generated code.
2013-07-26 02:08:14 -04:00
aparajita b03e354dbf Merge pull request #1965 from Dogild/Timer
Fixed: CPTimer didn't allow a timeInterval < 0.1
2013-07-25 23:01:14 -07:00
Aparajita Fishman 5b62773a39 Fixed: off-by-one in row calculation caused drawing problems with variable-height rows in CPTableView.
Previously, if the last row's height was increased, empty rows below would not be pushed down. This was due to an off-by-one in -_unboundedRowsInRect (now _exposedRowsInRect) which caused the incorrect rect of the last row to be retrieved.

This commit fixes that bug and also makes the following changes:

- Added FULL_ROW_HEIGHT(), ROW_BOTTOM() and HAS_VARIABLE_ROW_HEIGHTS() macros to make the code clearer.
- Documentation cleanup.
- Eliminated some intermediate variables.
- Rewrote -_rectOfRow to reduce redundant code and fixed some logic errors.
- Renamed some variables to make their intention clearer (to me at least).
- Added an out of bounds check in -rowAtPoint: before doing the relatively expensive binary search.
- In -noteHeightOfRowsWithIndexesChanged:, the first valid index is used instead of the first index (which might be invalid).
- Fixed a bug in -noteHeightOfRowsWithIndexesChanged: where row height was not set correctly if a row was not in the index set.
- Fixed incorrect use of CEIL in -_unboundedRowsInRect, it was wrapped around the divisor instead of the entire expression.
- Fixed drawBackgroundInClipRect: drawing one too many rows.
- Fixed -rowAtPoint not checking for x in bounds.

BREAKING CHANGE:
Previously, CPTableView -rowAtPoint would incorrectly return a valid row index when the x value was outside of the table's bounds. Now an out of bounds x value will return -1, which is consistent with Cocoa (and the intent of the method).
2013-07-25 10:48:11 -04:00
Aparajita Fishman 5c211b350e Docs 2013-07-24 19:21:56 -04:00
Aparajita Fishman 2c6ab1714f Fixed: stray theme slice. 2013-07-24 11:10:35 -04:00
Aparajita Fishman 17fe9b0f60 Formatting 2013-07-23 18:03:17 -04:00
Aparajita Fishman 639670e47d Formatting 2013-07-23 10:15:49 -04:00
Aparajita Fishman 27165db513 Fixed: menu items would not obey enabled bindings for auto-enabling menus.
Previously, the auto-enabling logic for CPMenu would not check to see if a menu item had enabled bindings, and would ignore the state determined by those bindings.

Now, if a menu is auto-enabling and an item has an enabled binding, the binding is used to set the enabled state of the item.
2013-07-22 22:20:40 -04:00
Aparajita Fishman 650bc77b2c Fixed: number formatter was called twice for every setObjectValue.
Previously setObjectValue checked for a formatted value, and then called [self stringValue], which ended up formatting the value again.

Now all of the cases (no formatter, formatter succeeds, formatter fails) are handled explicitly in setObjectValue, eliminating the extra call to the formatter.
2013-07-22 21:26:18 -04:00
Aparajita Fishman a5e62ed132 Fixed: NSMenu autoEnablesItems was not supported by nib2cib. 2013-07-22 21:13:15 -04:00
Alexandre Wilhelm 56963d65f3 Fixed: CPTimer don't allow to put timeInterval below 0.1
Previously it wasn't possible to set the timeInterval below 0.1.
Now you can do it and the timeInterval will set to 0.1 if the timeInterval is less or equal to 0 as in cocoa.

Cocoa specs here:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/Reference/NSTimer.html
2013-07-22 15:20:10 -07:00
Aparajita Fishman 771370e64b Docs: typos 2013-07-21 22:30:20 -04:00
Aparajita Fishman 0bd670b2a3 Fixed: extraneous colon in https scheme test.
And whitespace formatting.
2013-07-20 13:23:05 -04:00
Aparajita Fishman e0af5d0573 Fixed: changed magic number to constant, add missing space after comma. 2013-07-20 12:05:53 -04:00
aparajita 23d2a71649 Merge pull request #1962 from BlairDuncan/CPTimerMinimumInterval
Fixed: CPTimer number of seconds interval set to 0.1 if less than or equal to 0.0
2013-07-20 09:02:13 -07:00
Blair Duncan 3419f6fbb4 Fixed: CPTimer number of seconds interval set to 0.1 if less than or equal to 0.0
Cocoa specs here:
 https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/Reference/NSTimer.html
...
"Parameters
seconds
The number of seconds between firings of the timer. If seconds is less than or equal to 0.0, this method chooses the nonnegative value of 0.1 milliseconds instead."
2013-07-18 09:33:12 -04:00
Aparajita Fishman 2ca020f3a9 Fixed: it seems setHidden must be called in CPView -initWithCoder.
Reverts change made in 64f962e29a.
2013-07-17 13:45:32 -04:00
Aparajita Fishman 778843593b Fixed: CPTextField would not become/resign key responder when first responder and unhidden/hidden.
Previously, no attempt was made to become/resign first key responder when a CPTextField was unhidden/hidden. This could lead to a case where a hidden CPTextField was made first responder, then unhidden (and have a focus ring), but would not receive key input.
2013-07-17 13:28:17 -04:00
Aparajita Fishman 64f962e29a Fixed: viewDidHide and viewDidUnhide were not called when being added to/removed from hidden ancestor.
Cocoa specifies that viewDidHide will be called when an unhidden view is added to a view hierarchy with a hidden ancestor view, and viewDidUnhide is called when an unhidden view is removed from a view hierarchy with a hidden ancestor view. This was not the case in Cappuccino.

This commit adds that functionality, and also removes a spurious viewDidHide/viewDidUnhide call that was generated as a side effect in initWithCoder.
2013-07-17 13:28:17 -04:00
Aparajita Fishman 90fe91d63e Formatting: @ignore requires /*! comment, whitespace cleanup 2013-07-17 13:28:17 -04:00
Alexander Ljungberg d404d027c2 Test: - CPImage initWithContentsOfFile:nil. 2013-07-15 10:48:58 +01:00
Alexander Ljungberg b0babdb7bb Formatting.
Refs #1959.
2013-07-15 10:48:14 +01:00
Alexander Ljungberg 0f53ceda30 Fixed: comparing a CPNumber vs nil or CPNull didn't throw an exception.
In Objective-C, both `[@34 compare:nil]` and `[@34 compare:[CPNull null]]` throw invalid argument exceptions.

This fix makes the same true in Objective-J.

Refs #1959.
2013-07-15 10:47:38 +01:00
Alexander Ljungberg 315e3fccf3 Formatting.
Refs #1959.
2013-07-15 10:36:48 +01:00
Alexander Ljungberg 2973743a0d Merge pull request #1959 from mrcarlberg/compare_sort_with_null
CPString 'compare:' method and sort using descriptors handles nil and CPNull in correct way
2013-07-15 10:28:43 +01:00
Aparajita Fishman 083310c44f Fixed: nib2cib did not allow xibs or images to be in subdirectories of Resources.
Previously, nib2cib would not correctly calculate the app/resource directories if the xib was in a subdirectory of Resources. Also, image resources in subdirectories did not have the subdirectory encoded with the image name.

Now xibs and images may be anywhere under Resources.

Fixes #1960.
2013-07-14 18:11:31 -04:00
Aparajita Fishman 54d13c8fc9 Fixed: CPImageView's _DOMImageElement was not created during initWithCoder.
Previously, _createDOMImageElement was not called until after [super initWithCoder] was called. But that call would end up in CPImageView -setObjectValue, which would attempt to access _DOMImageElement before it had been created.

Now _DOMImageElement is checked before being accessed or created.
2013-07-14 17:46:22 -04:00
Aparajita Fishman fbc869ad29 Fixed: in certain degenerate cases, CPTextField may not have a window within _isWithinUsablePlatformRect
Previously, a case could arise where a text field was set as the initial first responder but during cib loading was not yet assigned to a window. In this case _isWithinUsablePlatformRect would fail.

Now _isWithinUsablePlatformRect checks to make sure the text field has a window.
2013-07-14 15:59:23 -04:00
Martin Carlberg f52f11899a New: Sort using descriptors handles nil and CPNull in correct way
This is the same way as Cocoa works.
Also added test case.
2013-07-09 13:38:13 +02:00
Martin Carlberg fc403d679c New: CPString 'compare:' method handles nil and CPNull in correct way
This is the same way as Cocoa works.
Also added test case.
2013-07-09 13:37:12 +02:00
Alexander Ljungberg e8b2f2e39f Fixed: previous CPImageView revision not compiling with Rhino. 2013-07-08 17:28:48 +01:00
Alexander Ljungberg b258b1a164 New: appkit_tag_dom_elements now tags with UIDs too.
Tagging with UIDs can make it much easier to debug encoding/decoding related bugs where it's not clear that the right view ended up in the right spot.

The new data attribute is called "data-cappuccino-uid".

Also collect and simplify appkit_tag_dom_elements code a little.
2013-07-08 17:05:22 +01:00
Alexander Ljungberg 0badf30763 Simplify CPImageView code. 2013-07-08 17:02:41 +01:00
Alexander Ljungberg c68b174be5 Fixed: appkit_tag_dom_elements support by CPImageView.
Without this fix, the `appkit_tag_dom_elements` flag would only affect CPImageViews unarchived from a coder (e.g. in a collection view, from a cib). It would have no effect on a CPImageView created in code.

This change refactors the _DOMImageElement code to a shared method, reducing redundancy while fixing the bug.
2013-07-08 14:31:06 +01:00
Alexander Ljungberg d61d4ebbe7 Fixed: -CPImage initWithContentsOfFile:nil created broken image.
Without this fix, code like `[[[CPImage alloc] initWithContentsOfFile:nil] description]` would cause a crash.

This fix makes `[[CPImage alloc] initWithContentsOfFile:nil]` behave like its equivalent in Cocoa: it returns nil without warning or error.
2013-07-08 12:45:23 +01:00
Alexander Ljungberg e7ecd92cbc Fixed: custom CPWindow subclasses breaking flatten.
If a cib file had a custom CPWindow subclass, that cib file would not be properly processed by flatten as it'd fail to find the relevant class (the fact that the class can't be found is an issue in itself). This would cause an exception.

This fix makes CPCibWindowTemplate act similar to CPCibCustomView when the referenced class can't be found: it instantiates a regular CPWindow. This is sufficient for flatten's purposes.
2013-07-02 17:16:55 +01:00
Antoine Mercadal 93c27625b9 NEW: Added some themable attributes for CPPopover
The following theme attributes has been added
 - border-radius
 - stroke-width
 - shadow-size
 - shadow-blur
2013-06-28 17:48:32 -07:00
Alexander Ljungberg 6ef776e488 Fixed: - CPView nextValidKeyView infinite loop.
Previously, certain situations could easily lead to an infinite loop in - CPView nextValidKeyView. For instance, opening a sheet view with no responder returning YES for canBecomeKeyView would freeze Cappuccino.

This was caused by the cycle detection in nextValidKeyView not being able to pick up on cycles where the nextKeyView of the original receiver did not participate. Since content views often have a next key view inside of them, and the views inside rarely have a next key view back "up" to the content view, the content view would never be seen again even if there was a cycle.

This fix detects cycles at any level by remembering all previous visited responders.
2013-06-25 18:05:46 +01:00
Alexander Ljungberg d9e3542c34 Merge branch 'refs/heads/slevenbits-native-clipboard' 2013-06-17 00:54:41 +01:00
Alexander Ljungberg 093ac8cf54 Merge branch 'refs/heads/slevenbits-nsvalue-nib2cib' 2013-06-17 00:54:05 +01:00
Alexander Ljungberg 757c79d15c Refactor, restructure and simplify copy and paste handling.
This change brings nearly all copy and paste related into a single, self-contained class. This new class is still somewhat coupled to CPPlatformWindow+DOM.j in the sense that it's highly specific and meant to be called in a very specialised way. Despite this, it's still a significant decoupling and the new code is more readable and easier to follow.
2013-06-17 00:17:00 +01:00
Alexander Ljungberg 8dd252eee1 Cleanup: TableTest/Editing. 2013-06-16 13:23:22 +01:00
Alexander Ljungberg f318759a4a Fixed: menu items becoming permanently disabled, breaking e.g. Select All.
Without this fix, if a menu item was disabled it could only be automatically re-enabled if the menu item had a `validateMenuItem:` or `validateUserInterfaceItem:` enabled target.

This meant that for example if the Edit > Select All menu item was validated when the first responder was something like a collection view, it'd become disabled. If then the first responder was changed to a text field and revalidation occurred, the menu item would not become enabled and Select All would not be possible in the text field neither through the Edit menu nor the Cmd-A/Ctrl-A keyboard equivalent.

This fix ensures that menu item validation does not only take negative action (disabling enabled items which should be disabled), but also positive action (enabling disabled items which should be enabled), even when there's no `validateMenuItem:` or `validateUserInterfaceItem:`.
2013-06-16 13:22:44 +01:00
Alexander Ljungberg 85985add3c Fixed: objects without a superclass. 2013-06-15 17:53:54 +01:00
Alexander Ljungberg 9d435e0f8a Test: include an image in Copy and Paste test.
Image copy and paste to and from the system clipboard is not available in Cappuccino today. However, the image in the collection view can be used to test internal Cappuccino copy and paste (using Edit > Copy, Edit > Paste from the Cappuccino menu).
2013-06-15 17:53:17 +01:00
Alexander Ljungberg 2b0754c6a0 Simplify copy and paste code path.
This change begins to clean up the control flow of copy and paste. Before, copy and paste was dealt with partly in CPPlatformWindow, partly in CPApp and partly in CPTextField.

Now, CPApplication has been removed from the path, simplifying it down to the two more expected actors.
2013-06-15 17:08:11 +01:00
Alexander Ljungberg 0ead233cba Fixed: Safari "can't paste" code triggered even for a content editable target.
These targets might be rare but could occur in some Cappuccino text editor widget, in which case our standard native paste handling from Safari should work fine.
2013-06-15 14:42:15 +01:00
Alexander Ljungberg 5d07eb7316 Fixed: paste in Firefox.
The paste into input field hack requires that we don't stop the Cmd-V/Ctrl-V keydown propagation.
2013-06-15 13:23:01 +01:00
Alexander Ljungberg 198857e0ad Fixed: copying from a CPTextField would not actually but the string value in the Cappuccino pasteboard.
Without this fix, when text was copied from a CPTextField, the value would be copied into the system clipboard (if possible), but not into the Cappuccino pasteboard. This meant that the text could not be pasted back in Cappuccino using e.g. Edit > Paste from the Cappuccino menu.

This fix ensures the appropriate text is copied both into Cappuccino's pasteboard and the system clipboard (when possible).
2013-06-14 14:31:00 +01:00
Alexander Ljungberg a4aed913d7 Test: new copy and paste manual test.
This test makes it easy to test copy and paste both inside a Cappuccino app, and externally to and from other Cappuccino instances in other browser, or other applications, when using a text field or a collection view as the source/destination.
2013-06-14 14:27:40 +01:00
Alexander Ljungberg 613a20a639 New: native copy and paste support extended with copy and cut.
This fix switches to full native copy and paste in browsers which support it. This allows copy from anywhere - a collection view, a table view and so on - without the browser greying out the copy menu or beeping.

In the future this can easily be extended to copy and paste images as well.

This change also improves Safari paste support. In recent versions of Safari, pasting from the system clipboard into Cappuccino has been impossible. This remains impossible due to the lack of beforepaste events, but now the code cleanly switches to a Cappuccino-only paste at least.
2013-06-14 14:05:36 +01:00
Alexander Ljungberg e59389b0dd Fixed: crash in - CPArray/CPDictionary description containing self referential JS object.
Without this fix, certain JS contents could cause `- CPDictionary description` and `- CPArray description` to crash.

This change limits how deeply the description code will recurse before returning a default "…" description.
2013-06-13 20:14:22 +01:00
Alexander Ljungberg 22905745f1 Fixed: crash on -CPArray/CPDictionary description if a value was the window object.
Without this fix, code like `[@{ "a": window } description]` would crash with a "Maximum call stack size exceeded" exception.

Now`CPDescriptionOfObject()` function simply describes the window object as `window` rather than trying to serialise it into a huge description string.
2013-06-13 19:19:22 +01:00
Alexander Ljungberg d3a44cbc63 New: objj_getClassList().
This function obtains the list of registered classes at the time its called.
2013-06-13 18:18:13 +01:00
Alexander Ljungberg a9a0b1c7d9 New: JavaScript clipboard API support for pasting.
Without this feature, attempts to paste data into a Cappuccino app (outside of a text field) are handled by redirecting the paste into a hidden text field. Then a paste event is generated from whatever is captured in this field after a 0 timeout. This method is prone to timing related bugs where the paste event actually has an empty clipboard.

With this new feature we read the paste data directly from the browser's native paste event when the browser supports it (Chrome 10+, Safari 5+, Firefox 22+). This is much more dependable and may in the future also enable us to read other types of paste data such as images.
2013-06-13 13:26:16 +01:00
Alexander Ljungberg 72169e54d8 New: nib2cib support for runtime attributes of point, size, rect and range types.
This change adds nib2cib support for `NSValue` when the value represents a NSPoint, NSSize, NSRect or an NSRange, which enables user defined runtime attributes of these types to be set in Xcode and then properly decoded in a Cappuccino app.
2013-06-13 13:24:36 +01:00
Alexander Ljungberg bf94dd3a6e New: KVC setValue:forKey: now automatically unwraps CPValue.
This corresponds to the same KVC behaviour in Cocoa and is key when decoding cibs with certain properties set to struct values (such as NSSize).
2013-06-13 13:20:22 +01:00
Alexander Ljungberg fe79628034 Fixed: CGRectFromString made bad CGSizeFromString call.
Without this fix, CGRectFromString would call CGSizeFromString with a value like "{1, 2}}" (not the extra trailing "}"). Although CGSizeFromString didn't complain, it wasn't correct either.
2013-06-13 12:46:08 +01:00
Alexander Ljungberg 563300a16f Test: CGGeometry "string from" for point, size and rect. 2013-06-13 12:43:48 +01:00
Antoine Mercadal 29c336f7b8 Fixed: Wrong initial values for _lineDashesPhase and _lineDashes in CPBezierPath
Firefox is not accepting the initial values for these two attributes, making it crash with an ILLEGAL VALUE error in any application using CPBezierPath (especially ones with CPPredicateEditor that is using bezier path to draw the selection arrows.)
2013-06-12 13:21:46 -07:00
Alexander Ljungberg b0b0452647 Merge pull request #1943 from Dogild/EmptyTableView
Fixed: selection in a tableView without column
2013-06-12 13:07:40 +01:00
Alexander Ljungberg abd382d9c2 Merge pull request #1940 from krodelin/udos-Resources-Directory-in-Framework-Template
New: Added "Resources" directory to capp Framework template
2013-06-12 13:06:26 +01:00
Alexander Ljungberg 36c2672064 Merge pull request #1939 from Dogild/RemovedColumn
Fixed: removeTableColumn does not removes column from tableColumns array
2013-06-12 13:01:47 +01:00
Alexander Ljungberg 5bab2e1469 Merge pull request #1938 from ahankinson/fix-collectionview-shiftselect
Fixed: CPCollectionView range bounds exception if shift key was held for...
2013-06-12 12:55:10 +01:00
Alexander Ljungberg df7a6930c2 Test: expose a problem with - CPTabView insertTabViewItem:atIndex.
Refs #1920, #1921.
2013-06-12 12:31:30 +01:00
Alexander Ljungberg 45c75235a5 Merge pull request #1898 from ahankinson/fix-issue1396
Fixed: CPTokenField sends focus and blur notifications
2013-06-12 12:07:02 +01:00
Alexander Ljungberg 0d283231a2 New: automatically fix ulimit when possible.
Without this fix, trying to build Cappuccino or run a jake script with a too low `ulimit -n` would cause a fatal error.

This change will automatically increase the ulimit when possible and only error out when it's not. The automatic change does not permanently affect the terminal session as it only targets the soft limit.
2013-06-12 11:16:39 +01:00
Alexander Ljungberg 4652db7246 Formatting: semicolons. 2013-06-12 11:07:03 +01:00
Alexander Ljungberg 22dcacd8ce Fixed: remove non-standard CPDocument API "firstEligibleExistingWindowController".
This method did not actually do anything, and was not part of the expected CPDocument API.

Refs #1870.
2013-06-12 10:28:41 +01:00
Alexander Ljungberg e2339ee1c6 Formatting: whitespace.
Refs #1870.
2013-06-12 10:27:28 +01:00
Alexander Ljungberg 6ab650346b Merge pull request #1870 from BlairDuncan/documentControllerCurrentDocument
Fixed CPDocumentController missing method currentDocument
2013-06-12 10:20:25 +01:00
Blair Duncan 2cbc4d93bd Fixed: CPWindows contentView Autoresizes Subviews set in Cib is now honoured
Currently when a window is decoded from a cib, the contentView is set to always auto resize its subviews regardless of the setting in IB.
2013-06-07 07:05:44 -04:00
Alexandre Wilhelm 8bf2118b6e Fixed: selection in a tableView without column
Previously it was possible to select rows in a CPTableView even if there wasn't columns. It was also possible to make a drag/drop.
This PR fixes theses both problems.
2013-06-03 15:36:59 -07:00
Alexandre Wilhelm 566521f854 capp_lint 2013-06-03 11:32:05 -07:00
Alexandre Wilhelm c7c3bdd543 Fixed: CPTableView Drag and drop in void causes a crash
Previously the drag and drop and multiple selection from a void cells caused an exception.
With this fix, you can start a drag/drop and a multiple selection from a empty row.

Fixes #1857
2013-06-03 11:27:10 -07:00
Aparajita Fishman 50d3bfd456 Fixed: Frameworks/Source directory was being copied to Build 2013-06-01 15:48:02 -04:00
Udo Schneider 6a516873b7 New: Added "Resources" directory to cap Framework template
Added a new folder "Resources" in Tools/capp/Resources/Templates/Framework/. As the folder is empty be default for frameworks it contains a .gitignore file to be able to add it to git.

Motivation is to prevent (spelling) mistakes when manually creating a Resource folder for Frameworks (e.g. "Ressources").
2013-06-01 13:13:05 +02:00
Alexandre Wilhelm 827b9c4c57 Fixed small bugs with _reloadAllRows 2013-05-31 16:21:56 -07:00
Alexandre Wilhelm 3b48aafe66 Fixed: removeTableColumn does not removes column from tableColumns array
Previously the tableView didn't correctly remove a given tableColumn. It was removed in the method load (who is called by the layoutSubviews).
Now the tableColumns is removed before the layoutSubviews (as in cocoa).
It fixed also another problem, before this fixe it wasn't possible to remove all of the columns of a tableView (the last column was always displayed). This is fixed also

Fixes #1913

You can test that with the app of t00f
2013-05-31 16:11:11 -07:00
Andrew Hankinson 8d7e2f9ec6 Fixed: CPCollectionView range bounds exception if shift key was held for first selection
Previously, if you held down the shift key while making the first selection in a CPCollectionView it would raise an exception claiming {-1, XXX} was out of range. This was because `firstIndex` returns CPNotFound (-1) if nothing is selected.

In Cocoa, holding down the shift key while making the initial selection behaves as if you made an initial selection.

This commit catches a CPNotFound and sets the first index to the index of the item under the mouse pointer.
2013-05-31 17:19:09 -04:00
Alexander Ljungberg 295443f2e3 Merge pull request #1937 from mrcarlberg/colon_selector
Fixed: When selector is only a ':' in a send message statement the new compiler crashed.
2013-05-30 13:46:28 +01:00
Martin Carlberg 595736b8c6 Fixed: When selector is only a ':' in a send message statement the new compiler crashed.
The program below crashed on the last line with a 'null is not an object' error message. Also added a test case.

@implementation MyObject {
- (int):(int)a {
  return a;
}
@end
var a = [[MyObject alloc] init];
var b = [a:3];
2013-05-30 14:39:58 +02:00
Antoine Mercadal 8f17f904f2 Merge pull request #1935 from Dogild/CGPath
Fixed: CGPath is wrong when creating an arc
2013-05-29 10:11:39 -07:00
Aparajita Fishman 668eb1f8c4 Fixed: in some cases nib2cib would write to stdout, which wasn't captured by XcodeCapp.
Previously, only stderr was checked for response text. In some edge cases it would write an error message to stdout. In addition, the default error message provided when the return status was non-zero and the output was empty was implemented incorrectly.

Now all output from nib2cib is correctly captured.

Also updated help to indicate how to enable debug logging.
2013-05-25 19:23:10 -04:00
Aparajita Fishman 3159021d27 CPDatePicker fixes, optimizations, tweaks...
- CPImageInBundle() can't be used from a ThemeDescriptor. Replaced with PatternImage().
- DRY! Put clock image sizes in variables so they can be maintained in one place.
- When displayed from the theme showcase, the hand images in HandLayer -setImage: were still _CPCibCustomResources, not sure why. This condition is now explicitly handled by converting to the referenced image.
- Fixed a bug in _CPDatePickerClock -setEnabled where the sublayers would not update unless the event loop was pumped.
- Check for unchanged value in setters.
- Various code optimizations.
- Removed unnecessary method comments.
- Fixed typo in demo app.
2013-05-25 19:11:27 -04:00
Alexandre Wilhelm fc4413d56b Changed clockWise to isClockWise 2013-05-24 14:15:54 -07:00
Alexandre Wilhelm 8b7eb1815d Removed unused code 2013-05-24 13:40:46 -07:00
Alexandre Wilhelm cb187c3e8f Added tests 2013-05-24 11:53:47 -07:00
Alexandre Wilhelm 25f54c83ed Added method CGPathContainsPoint 2013-05-24 11:53:33 -07:00
Alexandre Wilhelm a79ac2e9e4 Removed unused code 2013-05-23 14:11:03 -07:00
Alexandre Wilhelm b5df5f730b Fixed: CGPath is wrong when creating an arc
Previously when creating a CGPath with an arc, the path was wrong. It added a line when it wasn't necessary and when it was necessary it added a line to a wrong point.
Now CGPath works like in cocoa (If the specified path already contains a subpath, Quartz implicitly adds a line connecting the subpath’s current point to the beginning of the arc. If the path is empty, Quartz creates a new subpath with a starting point set to the starting point of the arc.)

Test app in Tests/Manual/CGPath/AppController.j
2013-05-23 14:07:04 -07:00
Martin Carlberg a2257dab8f New: Empty loop test cases for compiler generator 2013-05-22 11:41:17 +02:00
Martin Carlberg ee4112b7f1 Fixed: Removed double spaces before '@ref' and '@selector' generated output from compiler.
'@ref' is generated to ' function(__input…' with the starting space if, for example, the code is 'return(@ref(a))'. This will create a space between 'return' and 'function(__input…'. When the compiler is generate the code this is not necessary.
2013-05-22 10:34:46 +02:00
Martin Carlberg 1d896c6ac9 Fixed: Code generator didn't generate ';' for empty loops
The line 'while (count--);' was generated to 'while (count--)'. The same with 'for(;;);' and 'for (a in []);'
2013-05-22 10:27:01 +02:00
Antoine Mercadal 42bc87d9ca Merge pull request #1934 from Dogild/showcase
Fixed: Aristo showcase is broken because CPDatePicker
2013-05-21 15:30:15 -07:00
Alexandre Wilhelm 85e71017d9 capp_lint and code style 2013-05-21 15:28:33 -07:00
Antoine Mercadal d8c8694c0d nib2cib the xib 2013-05-21 15:27:45 -07:00
Antoine Mercadal 305fbb8ce2 Merge branch 'RadialGradient' of https://github.com/Dogild/cappuccino into pr-1933 2013-05-21 15:18:25 -07:00
Alexandre Wilhelm 0c613f1dde Fixed bugs with showcase 2013-05-21 14:10:05 -07:00
Alexandre Wilhelm 14ab582a53 Fixed : Aristo showcase is broken because CPDatePicker
Previously the showcase of Aristo and Aristo2 didn't work because several bugs in the class CPDatePicker.

This PR fixes these problems :
- The first problem was when displaying a textual datePicker, the class tried to calculate different things for the calendar (good optimization as well).
- The second problem was about the calendar and the hands. It wasn't possible to display a PatternColor made with an image in a layer, now we use a PatternImage and the method CGContextDrawImage to draw the hands.
2013-05-21 13:53:16 -07:00
aparajita 6c2062c1f0 Merge pull request #1882 from ahankinson/fix-theme-disabled-controls
Theming fixes for disabled controls in Aristo2
2013-05-21 06:51:21 -07:00
Aparajita Fishman 7385f04d7f Fixed: theme showcase was failing due to various bugs. 2013-05-21 09:50:46 -04:00
Alexandre Wilhelm 9d76ab70fe Changed image for lineal gradient 2013-05-20 21:54:04 -07:00
Alexandre Wilhelm ce22cebf07 Removed the reverse colors (it was a bad idea) 2013-05-20 21:53:35 -07:00
Alexandre Wilhelm 22d66438fb Added test for linear/radial gradient 2013-05-20 19:08:44 -07:00
Alexandre Wilhelm de4e28b5cc Fixed bug with linear gradient when drawing it without CPGradient 2013-05-20 19:07:39 -07:00
Alexandre Wilhelm 5e0793c2ac Fixed small init bug in CPBezierPath 2013-05-20 19:06:48 -07:00
Alexandre Wilhelm 54dd027c15 Removes previous test 2013-05-20 19:06:08 -07:00
Alexandre Wilhelm ad33411ec6 New: CGContextDrawRadialGradient support
Canvas supports CGContextDrawRadialGradient as in cocoa. The CGGradientDrawingOptions is not actually supported.

Test app in Tests/Manual/CGCanvasContext
2013-05-20 15:08:46 -07:00
Aparajita Fishman 6bac934d0c Fixed: changed indentation of generated code to Cappuccino standard of 4 spaces. 2013-05-18 18:42:26 -04:00
Alexander Ljungberg 8c5015a0bc Test: verify compiler output for return statement without space.
Refs #1830.
2013-05-18 01:00:49 +01:00
Alexander Ljungberg 302138c257 Fixed: OutputTest reversed expectation and test value in error messages.
The message would read "expected x but was y", where y would actually be the correct expected value and x the wrong one.
2013-05-18 00:59:20 +01:00
Alexander Ljungberg 501310c058 Formatting: OldBrowserCompatibility.js.
Refs #1929.
2013-05-16 15:24:24 -07:00
Alexander Ljungberg cb2ba64a73 Merge branch 'master' of github.com:cappuccino/cappuccino 2013-05-16 14:18:46 -07:00
Alexander Ljungberg de1d6aad9c Test: check compiler output for selectors with keywords in them.
Refs #1929.
2013-05-16 14:17:31 -07:00
Aparajita Fishman 391ff7279d Fixed: capp_lint errors. 2013-05-16 15:02:45 -04:00
Alexander Ljungberg 1d1016f08e Test: reactivate the regex-simple-char-classes test.
This test failed with the old preprocessor but works fine now with the new compiler.

Refs #1929.
2013-05-16 11:15:03 -07:00
Alexander Ljungberg d040e60f60 Merge pull request #1929 from mrcarlberg/preprocess
Many compiler fixes
2013-05-16 10:03:38 -07:00
Martin Carlberg 3808427f24 Fixed: Accidental global variable 2013-05-16 16:15:29 +02:00
Martin Carlberg b3e6eb74b2 Fixed: Reset all the macros when compiling a new file in the default implementation of the macro store. 2013-05-16 12:07:44 +02:00
Martin Carlberg 392aafb360 Revert "Revert "New: Added test cases for some preprocess directives in OutputTest.j""
This reverts commit 5e6c89ca8b.

Conflicts:
	Tests/Objective-J/Preprocessor/OutputTests/OutputTest.j
2013-05-16 12:05:57 +02:00
Martin Carlberg 6556ccef80 Fixed: Removed use of global variable 2013-05-16 11:26:01 +02:00
Martin Carlberg f96e934cf8 Fixed: Removed use of in some cases undefined global variables 2013-05-16 11:25:42 +02:00
Alexander Ljungberg 44a872659a New: type check - CPPasteBoard setString:forType:.
When this method is given e,g, an array or CPData, it now crashes early instead of the pasteboard exhibiting strange behaviour.
2013-05-15 08:47:43 -07:00
Martin Carlberg 256c5b83da Fixed: Typo, changed comma to semicolon 2013-05-15 15:35:03 +02:00
Martin Carlberg 5e6c89ca8b Revert "New: Added test cases for some preprocess directives in OutputTest.j"
This reverts commit 9b709b85a9.
2013-05-15 15:21:49 +02:00
Martin Carlberg bf4a5b2c9a Merge branch 'master' of https://github.com/cappuccino/cappuccino into preprocess 2013-05-15 09:08:26 +02:00
Alexander Ljungberg 6701117945 Fixed: [pasteboard declareTypes:… owner:nil]; would emit a warning.
Without this fix, declaring a type with a nil owner would cause a "DEPRECATED: object cannot be nil" warning to be issued.

This fix now allows a nil owner without warning.
2013-05-14 14:44:00 -07:00
Alexander Ljungberg f2d9ef7720 Test: - CPPasteboard setString:forType: and stringForType:. 2013-05-14 14:40:41 -07:00
Alexander Ljungberg 3fb0dd725a Fixed: CPLocale for English, United Kingdom had the wrong identifier. 2013-05-14 13:06:53 -07:00
Alexander Ljungberg a324cb3306 Fixed: CPLocale detection didn't work.
Previously, if the browser provided a language string such as "en-US", CPLocale would try to look up the locale for "en_EN", which wouldn't exist so it'd always select the default language.

This fix uses the browser provided language string fully to select the appropriate locale.
2013-05-14 13:03:31 -07:00
Alexander Ljungberg 2a9f3deb0e Merge pull request #1930 from mrcarlberg/cplocal_cant_handle_unknown_country_codes
Fixed: CPLocal can't handle unknown language codes
2013-05-14 12:00:39 -07:00
Alexander Ljungberg 89e81e97d1 Merge branch 'master' of github.com:cappuccino/cappuccino 2013-05-14 11:59:29 -07:00
Alexander Ljungberg b4fb4ba941 Formatting: CPLocale.
Tabs to spaces and other whitespace changes.
2013-05-14 11:59:17 -07:00
Aparajita Fishman eb859d42a4 Fixed: framework image names without @framework would cause nib2cib to fail.
I wasn't properly handling the case where _resourcePathForName would be called with a nil framework.
2013-05-14 07:54:08 -04:00
Martin Carlberg 9d86391bdb Fixed: CPLocal can't handle unknown language codes
When the language code is not known it still sets the current language code
to the unknown code instead of the defualt 'en_US' code.
This makes the test cases for CPDateFormatter fail when run on a foreign system.
2013-05-14 13:30:30 +02:00
Martin Carlberg 9b709b85a9 New: Added test cases for some preprocess directives in OutputTest.j
Also fixed so OutputTest.j now uses the new compiler instead of the old.
2013-05-14 10:31:29 +02:00
Alexander Ljungberg 9bde63923c Formatting: CPPredicateTest.
Refs #1914.
2013-05-13 22:27:39 -07:00
Alexander Ljungberg d7c676893d Merge pull request #1914 from mrcarlberg/predicate_expression_equals_nil
CPExpression and CPPredicate can't handle nil as argument in method isEqual:
2013-05-13 22:21:05 -07:00
Alexander Ljungberg 8bc8ae4e3b Merge pull request #1928 from mrcarlberg/ie_negative_width_height_crash
Fixed: IE8/9 (maybe 10 too) can't handle negative width or height.
2013-05-13 22:17:18 -07:00
Alexander Ljungberg 35b4e8f653 Merge pull request #1915 from Dogild/PopUpListComboBox
Fixed: CPComboBox popupList should close if mouse is clicked outside
2013-05-13 21:56:28 -07:00
Martin Carlberg 7837277cbe Merge branch 'master' of https://github.com/cappuccino/cappuccino into preprocess 2013-05-13 16:38:39 +02:00
Martin Carlberg 8145df9613 Fixed: Removed all uses of preprocess macros in the compiler 2013-05-13 16:23:12 +02:00
Martin Carlberg 9ffa184056 Fixed: IE8/9 can't handle negative style width or height.
Functions are used everywhere to set width or height in the DOM except in the method lockFocus. This will cause IE8/9 to report error if the width or height is negative in this method.
2013-05-13 15:12:59 +02:00
Aparajita Fishman e047212f5f New: xcc --reset resets the Xcode support before opening the project.
This will help in cases where the project is way out of sync and crashes XCC.
2013-05-12 16:18:41 -04:00
Aparajita Fishman 574672f15f Fixed: some error handling needed improving.
- Added ~/narwhal/bin to executable paths.
- Hopefully clearer error message when an executable is missing.
- Log PATH when executable is missing.
- Catch parse exceptions when parsing parser.j errors, log the returned text.
2013-05-11 09:34:23 -04:00
Aparajita Fishman 9b3676fa4f New: missing image/framework in xib is reported as an error.
Previously, if an image or framework in image@framework was missing, it was just a warning, and conversion would continue.

Now an exception is raised and conversion stops.
2013-05-10 09:27:47 -04:00
Alexander Ljungberg 57d5dac72a Merge branch 'master' of github.com:cappuccino/cappuccino 2013-05-09 14:06:39 -07:00
Alexander Ljungberg 626e1e770e Fixed: in the last few revisions, table rows could be selected despite delegate shouldSelectRow: returning NO.
This error was caused by 3612565e3a dropping the return statement.

Refs #1905.
2013-05-09 14:05:53 -07:00
Aparajita Fishman 75b3bf22e6 New: added xcc executable to open a project in XcodeCapp from command line.
Usage: xcc [directory]

Updated help accordingly.
2013-05-09 16:48:37 -04:00
Alexander Ljungberg 48be680fde Test: clean up and fix minor errors. 2013-05-09 11:32:09 -07:00
Alexander Ljungberg e95856dadd Merge pull request #1905 from ahankinson/fix-cptableview-shouldselectrow-delegate
Fixed: Delegate method fires twice when using keyboard to select rows in...
2013-05-09 11:25:44 -07:00
Aparajita Fishman 86d7ec4180 New: added "Show in Finder" item to XcodeCapp.
Shows the Cappuccino project folder. If Path Finder is installed, it says "Show in Path Finder" and that is used.

Reorganized the menu a bit and updated the help.
2013-05-09 09:26:44 -04:00
Aparajita Fishman a63bb155c2 New: nib2cib gives a more helpful message when unsupported classes are encountered.
Previously users saw the generic "-[CPKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (NSFoo)" message, which was not particularly instructive.

Now the message is: "NSFoo objects are not supported by nib2cib."

Closes #1923
2013-05-09 07:35:27 -04:00
Aparajita Fishman 01291591b7 Fixed: missing self. in call to _delegate.
Small formatting and code tweaks as well.
2013-05-09 07:31:11 -04:00
Aparajita Fishman e7ad1a1f7a New: bumped XcodeCapp version. 2013-05-09 07:02:53 -04:00
Aparajita Fishman 2e0b204b8d Fixed: Xcode project was being saved when no modifications were made.
Saving the project requires the xib to be selected again if it was being edited, which is not so nice.

Now we check the project's modified flag before saving and lazy-create the groups.
2013-05-08 22:28:07 -04:00
Aparajita Fishman 77f8136e79 New: give a download link for XcodeCapp 3. 2013-05-08 11:01:21 -04:00
Aparajita Fishman e45c05b08e Merge branch 'refs/heads/XcodeCapp3' 2013-05-08 10:24:21 -04:00
Aparajita Fishman 14eff74652 Docs: updated XCC help. 2013-05-08 10:19:46 -04:00
Aparajita Fishman 14fec1a608 Fixed: deleted xib or cib files were not processed correctly.
Now, deleting a xib file will delete its corresponding cib. Deleting the cib will mark its corresponding xib for updating.
2013-05-08 10:19:25 -04:00
Aparajita Fishman 7034635b8e Fixed: converting xib with Autolayout gave confusing error message.
Previously, attempting to nib2cib a xib with autolayout would give an error message that there was no class to archive NSLayoutConstraint, which was meaningless to most people.

Now an error message that says exactly why it failed and how to fix it is given.
2013-05-08 09:57:00 -04:00
Aparajita Fishman 19aee142de Fixed: headers were incorrect or missing. 2013-05-08 09:54:13 -04:00
Aparajita Fishman 218eed7e97 Fixed: Frameworks/Source was being ignored during directory scans.
Formatting tweaks also.
2013-05-07 19:00:55 -04:00
Antoine Mercadal ec3fb2bd33 Merge branch 'WindowSheet' of https://github.com/Dogild/cappuccino into pr-1918 2013-05-07 11:20:49 -07:00
Antoine Mercadal b4a2ba4fc6 Merge branch 'outlineViewDisclosureSelectedThemestate' of https://github.com/BlairDuncan/cappuccino into outlineViewDisclosureSelectedThemestate
Conflicts:
	AppKit/CPOutlineView.j
2013-05-07 11:13:35 -07:00
Aparajita Fishman 1e828b2e8d New: changed terminology from "Reset Project" to "Synchronize Project". 2013-05-07 12:39:59 -04:00
Aparajita Fishman 4c94691b6f Fixed: merge with master added spurious files. 2013-05-07 12:39:31 -04:00
Aparajita Fishman 2b273b1e12 Fixed: capp templates were missing configuration for new features.
- The new compiler requires the OBJJ_INCLUDE_PATHS environment variable to be set.
- The new XcodeCapp 3 support for Frameworks/Source requires that directory to be excluded from builds.
2013-05-07 12:38:58 -04:00
Blair Duncan f8faf5199d linting 2013-05-06 23:57:58 -04:00
Blair Duncan eb312d5f66 updated to take into account trailiing rows beyond the last disclosure control 2013-05-06 23:51:41 -04:00
Antoine Mercadal 7fc7632971 Fixed: Crash after deployment when importing CPDatePicker
Previously, CPStepper was delcared using a @class. If CPStepper was not manually imported anywhere else in the app, it caused a crash.
This patch explicitely import CPStepper.j in _CPDatePickerTextField.j
2013-05-06 15:37:25 -07:00
Alexandre Wilhelm e22d6e0217 Removed on pixel at the top of a sheet window 2013-05-06 15:28:49 -07:00
Antoine Mercadal a11de15e33 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2013-05-06 15:11:18 -07:00
Antoine Mercadal eb04174e68 Revert "Merge branch 'outlineViewDisclosureSelectedThemestate' of https://github.com/BlairDuncan/cappuccino into pr-1917"
This reverts commit 345a54e8c9, reversing
changes made to 21301cae21.

This commit is reverted because it causes a non obvious crash when selecting the latest row of a CPOutlineView.

The crash is visible in Tests/Manual/CPOutlineViewTest
2013-05-06 15:07:26 -07:00
Aparajita Fishman 97f93a031f Merge branch 'refs/heads/master' into XcodeCapp3 2013-05-06 17:45:48 -04:00
Aparajita Fishman 1f280b3985 New: CPNumberFormatter -localizedStringFromNumber:numberStyle:
Added unit test as well.
2013-05-06 17:45:16 -04:00
Antoine Mercadal e0d33a8e3f Merge branch 'SheetToolBar' of https://github.com/Dogild/cappuccino into pr-1919 2013-05-06 13:29:09 -07:00
Antoine Mercadal 345a54e8c9 Merge branch 'outlineViewDisclosureSelectedThemestate' of https://github.com/BlairDuncan/cappuccino into pr-1917 2013-05-06 13:15:41 -07:00
Antoine Mercadal 21301cae21 Merge pull request #1912 from Dogild/CornerView
Fixed: CornerView in TableViews from cibs are not sized well
2013-05-06 13:13:31 -07:00
Antoine Mercadal f8513eae26 Merge pull request #1903 from Dogild/CPDateFormatterSupport
New: Added support for CPTimeZone and CPDateFormatter
2013-05-06 13:11:36 -07:00
Martin Carlberg ee9b04944a Merge branch 'master' of https://github.com/cappuccino/cappuccino into preprocess 2013-05-06 16:24:54 +02:00
Martin Carlberg e9ca7c7395 Fixed: IE8 Browser support.
The compiler can now run in IE8. Also found the use of the function .indexOf on Arrays in CPView.j.
It is not supported in IE8.

Added a new file (OldBrowserCompatibility.js) in the Objective-J framework that will add functions if they are not supported in the javascript runtime.
2013-05-06 16:17:09 +02:00
Aparajita Fishman 2abe573bfe Fixed: XcodeCapp would attempt to build on non-Mac OS X platforms. 2013-05-05 22:18:50 -04:00
Aparajita Fishman 0aad32ba86 Fixed: building on 10.6 failed.
There are features of Objective-C 2.0 used in XcodeCapp that cannot be compiled with Xcode 4.2, which is the maximum version that runs on OS X 10.6. Users on 10.6 would see compile errors.

Now a check for OS X 10.7+ is done, and on any version earlier than that, the user is presented with a message telling them to download XcodeCapp from the web site.
2013-05-05 16:13:43 -04:00
Aparajita Fishman a24aacdb3e Fixed: pbxprojModifier was not working on OS X 10.6.
It turns out it never worked on 10.6. I had to modify mod_pbxproj.py to make it work. In the process I was able to make it faster by skipping conversion to JSON.

Also, a backup of the pbxproj file is made before saving, just in case.
2013-05-05 10:37:52 -04:00
Aparajita Fishman d2b1968dec Fixed: About window icon was small in OS X 10.6
Previously I was using the app icns file for the image. Now I have a separate retina-ready image for the About window.
2013-05-03 12:14:48 -04:00
Aparajita Fishman 9ee7535039 Tweaked the parser error messages 2013-05-03 12:12:46 -04:00
Aparajita Fishman d723c7306a Fixed: XCC was crashing on startup in OS X 10.6
The Lumberjack logging library was using a function not present in 10.6.

This commit reverts to an earlier release that works with 10.6.
2013-05-03 12:12:15 -04:00
Aparajita Fishman 9dd642395f Merge branch 'refs/heads/master' into XcodeCapp3 2013-05-02 17:53:06 -04:00
Aparajita Fishman 2b5cf1a56d Fixed: renamed jsc to narwhal-jsc.
Also put the list of mandatory executables in Info.plist.
2013-05-02 17:52:21 -04:00
Aparajita Fishman 1f4b49c461 Fixed: missing help.pdf. 2013-05-02 17:38:25 -04:00
Aparajita Fishman e20f2b75f0 Fixed: Lumberjack files were missing. 2013-05-02 17:24:29 -04:00
Aparajita Fishman 550401dffe New: XcodeCapp 3 total overhaul part 2.
Whew, a complete overhaul of my previous complete overhaul. Changes in no particular order:

- Redesigned the About box.
- Converted tabs to spaces.
- Using Lumberjack for (much better) logging. When debugging, copious logging goes only to Xcode's console, not to the system log. In the release build, only basic info and errors goes to the system log.
- Reformatted the help using Pages, it's a PDF now (so I can use better fonts).
- Massive optimization across the board. All time-consuming operations are done with NSOperation, which uses Grand Central Dispatch, and can be interrupted. So the XCC menu remains fully responsive during source processing.
- Updates to the Xcode project are coalesced so only one read/update/write operation is done.
- Instead of launching a shell and reading the .profile, the target executable is directly launched, but it must reside somewhere in the default binary path + /usr/local/bin:/usr/local/narwhal/bin:~/bin. If jsc, python, objj and nib2cib cannot be found in that path, the user is alerted and XCC quits.
- Added a preference (true by default) to automatically load the Xcode project when a project is opened.
- Added a preference to turn off per-file processing notifications.
- Added a hidden preference to set the log level. Useful for debugging a user's release build.
- Redesigned the Preferences window.
- Renamed some methods/properties, eliminated some unused properties.
- All of the windows remember their position.
- Moved the fsevent_callback into XcodeCapp.m.
- Fixed a bug in mod_pbxproj.py not setting the type of PBXFileReferences which are directories to "folder".
- Added support for categories in parser.j. Woo-hoo!
- Rewrote pbxprojModifier.py to use a class.
- Renamed the Xcode project group names to "Cocoa Classes" and "Cappuccino Source". Within "Cappuccino Source", framework code is kept in a "Frameworks" group.
- Shadow filenames are all project-relative now, thus *much* shorter.
- pbxprojModifier.py keeps the groups and files in the project in sorted order: Resource folders are at the top, followed by Cocoa Classes, followed by Cappuccino Source. Within Cocoa Classes, non-framework files come first, followed by framework files, followed by xcc_general_include.h.
- If either .XcodeSupport or the .xcodeproj is missing, the other is regenerated to ensure they stay in sync.
- A compatibility version for .XcodeSupport is stored inside it in Info.plist. If that version < the app's compatibility version, the project is reset. This ensures that format changes in the future will not result in projects in an unknown state.
- If the Xcode project cannot be opened, the user is alerted and given the option of regenerating the project.
- Resetting the project deletes all .cibs to force the .xibs to be regenerated.
- All possible FSEvents are dealt with individually now, and in a way that (hopefully) maintains sync between Cappuccino and XCC.
- A file descriptor to the Xcode project is kept open so that If the project path changes it can be relocated. If it does move, the user is alerted ad given the option of reloading the project or quitting.
- If one of the watched paths changes, the project is reloaded.
- Xcode creates temporary files, they are properly filtered out now when handling FSEvents.
- NSRegularExpression was being used before, but that is OS X 10.7 only. NSPredicate is used instead now.
-
2013-05-02 17:04:46 -04:00
Antoine Mercadal f9dad2c1b3 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2013-05-01 15:29:11 -07:00
Antoine Mercadal eacc527c5f Fixed: Tooltips for a view in another view with tooltip was not shown
Previously, tooltip system was using bubbling event. This was actually making impossible to see a view's tooltip if the parent view also has a tooltip. This patch changes the capturing mode from bubbling to capture.
2013-05-01 15:25:59 -07:00
Alexandre Wilhelm 30e9389a92 Updated test 2013-04-30 15:25:23 -07:00
Alexandre Wilhelm e5fc452063 Added theme for Arsito1 2013-04-30 14:43:47 -07:00
Alexandre Wilhelm 7477294648 Added test for toolbar sheet 2013-04-30 14:39:31 -07:00
Alexandre Wilhelm 16b2334274 Refactor code 2013-04-30 14:35:01 -07:00
Alexandre Wilhelm 7b59ec93df Fixed: Windows with toolbars do not display correctly as sheets
Previously it wasn't possible to display a toolbar in a sheet window.
Now, a toobar is displayed well in a window. This PR allows every sheet window to have a toolbar, with the PR #1918 just the CPTitleWindow/HUD sheet could have a toolbar as in cocoa.

Fixes #1863
2013-04-30 14:11:45 -07:00
Blair Duncan 23ef587f68 added don't attempt to setthemestates if there are no disclosure controls
previous commit was failed the travis build test when there were no controls
2013-04-30 12:05:12 -04:00
Alexander Ljungberg 72455f43d4 Test: expose child window level crash bug if present.
This manual test exposes the bug addressed by issue #1911.
2013-04-30 00:57:42 +01:00
Alexander Ljungberg e8828fe0bc Merge branch 'slevenbits-child-windows-order-fix' of git://github.com/slevenbits/cappuccino into slevenbits-slevenbits-child-windows-order-fix 2013-04-30 00:44:56 +01:00
Alexander Ljungberg 3430684c22 Merge branch 'master' of github.com:cappuccino/cappuccino 2013-04-30 00:40:49 +01:00
Alexandre Wilhelm 3357162660 Added CPBorderlessBridgeWindowMask for the ToolBar 2013-04-29 16:21:56 -07:00
Alexandre Wilhelm 2e93e4abf7 Fixed: Sheet window under the toolbar
Previously when using a sheet window in a fullPlatform window, the sheet window started the animation under (the layout) the toolbar.
Now, the sheet animation starts below the toolbar as in cocoa.
It also fixed that only a CPBordelessWindow/CPTitleWindow/HUD can have a toolbar.
2013-04-29 16:16:29 -07:00
Blair Duncan 3e268a88b3 Fixed: OutlineView disclosure button selected themestate when selected
Previously, when a row with a disclosure control (triangle) was selected, the row was selected
but the control remained in the unselected themestate. Disclosure control themestate was only being
changed when the control itself was clicked on. This fix changes the controls themestate whenever
the row selection changes.
2013-04-29 11:29:57 -04:00
Aparajita Fishman 6de967345c Removed unused constant 2013-04-27 09:04:36 -04:00
Antoine Mercadal a38d6c11b4 Fixed: Tooltips always showing in primary platform window
Previously, the tooltip of a control was always shown on the primary platform window. This fixes sets the tooltip window's platform view to [[targetView window] platformWindow].
2013-04-26 14:56:20 -07:00
Antoine Mercadal 807387463f Merge pull request #1916 from Dogild/DatePickerHidden
Fixed: CPDatePicker freeze when hidden

Reviewed
2013-04-26 13:31:06 -07:00
Aparajita Fishman 52a53fb8d1 Fixed: if .xcodeproj was missing, it was not created.
Now if either .XcodeSupport or the .xcodeproj is missing, both are recreated to ensure they are in sync.

Also, when trying to open the Xcode project, if it is missing or cannot be opened, an alert is displayed and the user is given the option of regenerating the project.

Some code cleanup as well.
2013-04-26 14:27:47 -04:00
Antoine Mercadal 6bd9a08460 Fixed: CPAlert always shows on main platform window
Previously, a CPAlert was always shown on the main platform window. This behavior could result in a feeling that the application was hanging because of the modal nature of the alert when users are looking to another platform window. This fix ensure to set the CPAlert window's platformWindow to the current key window using [[CPApp keyWindow] platformWindow].
2013-04-26 10:34:48 -07:00
Antoine Mercadal 81a61c1412 Fixed: Trying to open a CPPopover in a secondary platform window opened in the main window
Previously, when opening a popover on a view from another platform window, the popover
was actually opened in the main window. This fix ensure to set the correct platform window
to the _CPPopoverWindow by setting it to the [[positioningView window] platformWindow];
2013-04-26 10:25:52 -07:00
Aparajita Fishman 811c7444df New: added documentation for using framework images.
This documentation is also in the nib2cib man page, but who will read that?
2013-04-26 11:41:42 -04:00
Aparajita Fishman a5a9bbf1a7 Fixed: XcodeCapp would attempt to open a path that did not exist or was not a directory.
The first defense against this is to validate the recent menu items to ensure they exist and are directories. If not, the item is disabled.

The next time a project is opened, the missing project is pruned from the recent menu.

The second defense is a check when an attempt is made to open a project.
2013-04-26 11:30:12 -04:00
Aparajita Fishman 12cf674595 Fixed: warning notification said "Error parsing…" instead of "Warning parsing…"
I was missing the variable in a test.
2013-04-26 11:07:37 -04:00
Ilya Kulakov 7ccf7c731c Consistent approach to handle child windows.
When added, level of child window is reset to level of the parent.
A user may change it aftewards to the level that may even break
specified relative position.

E.g. if a child window is added below the parent (Normal)
and its level is set to Floating it will be ordered above.

Whenever you change level of the parent window, levels of the child
windows are reset as well ignoring all your changes.

According to the example, if you set level of the parent to Normal+1,
child window' level will also be set to Normal+1 and its relative
order to the parent (below) will be restored.
2013-04-26 19:46:38 +07:00
Ilya Kulakov d3a4ce4608 Revert "Fix child windows may reside on other layers than parent."
This reverts commit 8e4f1fdd10.
2013-04-26 17:57:18 +07:00
Ilya Kulakov 920204fc63 Revert "It's important to order out child windows before parent window relationship is broken."
This reverts commit c6553016d3.
2013-04-26 17:57:00 +07:00
Aparajita Fishman 2d8d68dc5e Fixed: Jakefile for XcodeCapp did not install symlink correctly.
FILE.exists was being used to test for the existence of the symlink in /Applications, but that doesn't work.

The correct way is to use ln -sfh. Note that the -h was missing before, which prevents an existing target symlink from being followed, which is why the symlink would end up inside XcodeCapp.app.
2013-04-25 23:22:37 -04:00
Alexandre Wilhelm 736dffa334 capp_lint 2013-04-25 17:06:52 -07:00
Alexandre Wilhelm bd2a7b2b7b Fixed: CPDatePicker freeze when hidden
Previously the CPDatePicker freezed when trying to hide it when it was the firstResponder.
There was an intern problem in the CPDatePickerTextField about the nextKeyView. That's why there was a boundless loop and the freeze.
This PR also fixed a big about the previous and next textField in the CPDatePicker.
It also fixed a bug about the CPDatePicker when it becomes firstResponder.

Fixes #1909
2013-04-25 16:56:10 -07:00
Aparajita Fishman fc8ca14743 Updated XcodeCapp 3 help to reflect new features. 2013-04-25 19:27:18 -04:00
Aparajita Fishman 15cf818b1e Fixed: not enough space around status icon. 2013-04-25 19:03:10 -04:00
Aparajita Fishman cf9b630401 Fixed: Xcode created temporary files which were being processed.
When saving a xib, Xcode creates a temporary file with the name <filename>~.xib. The file event listener would sometimes pick this up and XcodeCapp would attempt to process it, but by the time nib2cib was launched it would be gone, generating an error.

Now .xib files whose filenames end with ~ are ignored.
2013-04-25 19:02:46 -04:00
Aparajita Fishman 3cc6b8dfbe New: better icons for XcodeCapp 3 2013-04-25 19:00:20 -04:00
Aparajita Fishman bf6ce64209 New: XcodeCapp 3 tweaks...
- Renamed XcodeSupport to .XcodeSupport.
- Added "Reset Project" to menu, it closes the project in Xcode if necessary, removes .XcodeSupport and .xcodeproj, then reloads.
- Added separate preferences for showing errors panel on warnings/errors. You may not want to see the panel if there are category warnings.
- New status icons (again).
- If an error occurs, the status icon turns red when all processing is done.
- Reworked notifications. Objective-J parsing is notified when done. Xib conversion notifies at beginning and end, because it typically takes a few seconds. Individual file notifications are suppressed if a project is being loaded.
2013-04-25 13:11:22 -04:00
Alexandre Wilhelm afdad97aad Added CPComboBox Aristo2 style 2013-04-24 17:47:30 -07:00
Alexandre Wilhelm 7e27de8a1e Updated slices 2013-04-24 17:46:53 -07:00
Aparajita Fishman 949af39041 New: the highest first launch version is saved.
The effect is that each minor point release (3.1 -> 3.2) will cause the help to display the first time it is launched, so that the user is encouraged to find out what is new.
2013-04-24 18:41:26 -04:00
Aparajita Fishman 2104c838bd Fixed: Resources directories in Frameworks/Source/<framework> were not picked up by XcodeCapp.
XcodeCapp would add a folder reference in the project for user framework Resources directories in Frameworks/Debug, but it didn't add references for framework Resources directories in Frameworks/Source.
2013-04-24 18:11:53 -04:00
Aparajita Fishman ee1c7a5f01 New: updated nib2cib man page to cover new features.
Framework image support and --no-colors option.
2013-04-24 18:09:48 -04:00
Aparajita Fishman 6d77faa7dd Fixed: order of framework image arguments was backwards.
Previously the order was <framework>@<image>, which seems backwards.

Now the order is <image>@<framework>.
2013-04-24 18:09:02 -04:00
Aparajita Fishman f4dc139675 Tweaked the About panel. 2013-04-24 17:26:34 -04:00
Aparajita Fishman 73d62029ba Various fixes...
- Accidentally deleted the Jakefile. It has been restored, and fixed the case where it would put a symlink to XcodeCapp.app within XcodeCapp.app.
- Minor changes to remove compiler warnings.
2013-04-24 16:01:55 -04:00
Aparajita Fishman b38f845643 New: high resolution status icons.
Also a help text tweak.
2013-04-24 15:39:23 -04:00
Aparajita Fishman cdef68034d New: 2x status icons. 2013-04-24 15:08:16 -04:00
Aparajita Fishman 467036bf34 Fixed: any .xcodecapp-ignore file was parsed.
Previously any .xcodecapp-ignore file within the monitored directories would be parsed. This commit ensures that only the project's root .xcodecapp-ignore file is parsed.
2013-04-24 15:07:59 -04:00
Aparajita Fishman 934dedecd2 Changed terminology to "Open" from "Listen" 2013-04-24 15:06:30 -04:00
Aparajita Fishman bd96d1b5e2 Updated help 2013-04-24 15:05:45 -04:00
Aparajita Fishman 01920e674d Fixed: Notification Center was suppressing notifications.
By default, Notification Center may suppress notifications if the application is frontmost. This commit ensures that all notifications are displayed.
2013-04-24 11:39:57 -04:00
Aparajita Fishman 0ec218a599 New: XcodeCapp preference to set maximum recent projects.
Previously the number of recent projects was unbounded, which made the recent menu unwieldy.

Now the recent projects list is pruned to the maximum set in the preferences, which defaults to 20.
2013-04-24 11:38:57 -04:00
Aparajita Fishman db21168a93 New: ignore XcodeSupport directories. 2013-04-24 10:58:52 -04:00
Aparajita Fishman 606205b58d New: XcodeCapp 3, a major overhaul.
- Updated project to Xcode 4.
- Reorganized files into preferred Xcode 4 hierarchy.
- Updated code to use properties.
- Eliminated unused/redundant code.
- Significantly optimized project scans.
- Added support for outlets, actions and resources in user frameworks.
- Now using bindings throughout.
- New application icon, Retina ready.
- New status menu icons.
- Reorganized menu.
- Added Preferences… menu item.
- Parsing errors and nib2cib errors are actually logged to the errors panel now.
- When an error occurs, the errors panel automatically opens, unless the "Automatically open Errors & Warnings panel" preference is off.
- Double-clicking an error or selecting an error and clicking Open opens the error in the preferred editor for .j files (or Xcode for .xibs). The cursor jumps to the offending line in the following editors: Sublime Text, TextWrangler, BBEdit, TextMate, Chocolate, MacVim.
- The Errors panel now remembers its position/size.
- When a project is loaded, the errors panel is cleared.
- When a file is modified, any pre-existing errors for that file are removed.
- Updated to Growl framework 2.0.1.
- If Notification Center is available (OS X 10.8+), that is used instead of Growl.
- .xcodecapp-ignore now supports ignoring a directory by suffixing the name with "/".
- .xcodecapp-ignore now supports include expressions prefixed with "!".
- Significantly optimized filename matching against ignored paths.
- .XcodeSupport has been renamed XcodeSupport to make it visible, so that trashing it is easier if things get out of sync.
- The template Xcode project now contains no frameworks or targets, so Xcode does not show any warnings or errors, and the user cannot accidentally try to build.
- Removing a file now removes the file from the Xcode project.
- Shadow files replace forward slash with U+2215 (DIVISION SLASH), which looks like forward slash but is a character that is extremely unlikely to be in a filename.
2013-04-24 10:57:59 -04:00
Alexander Ljungberg 1aa0956b4d Merge pull request #1915 from Dogild/PopUpListComboBox
Fixed: CPComboBox popupList should close if mouse is clicked outside
2013-04-24 13:51:10 +01:00
Martin Carlberg 14ee789df4 Fixed: Mark correct column position in 'Expected a Semicolon' errors in the parser. 2013-04-24 10:12:42 +02:00
Alexandre Wilhelm d400617c1b Added optimization 2013-04-24 00:41:06 -07:00
Alexandre Wilhelm 056a00e54e Fixed: CPComboBox popupList should close if mouse is clicked outside of the control
Previously the list of the CPComboBox didn't close when clicking outside of the control
Now the list has the same behavior as Cocoa

Fixes #1859
2013-04-24 00:33:56 -07:00
Aparajita Fishman 0b7e92aa53 New: better logging of image bundle info in nib2cib.
If an image comes from a framework, the framework's bundle identifier is logged if it is available.
2013-04-23 23:36:28 -04:00
Aparajita Fishman 9cb2c758c7 New: --no-colors option for nib2cib.
Previously error messages would always be colorized, which doesn't work well if you are piping the output.

Passing --no-colors turns off all colors in the output.
2013-04-23 23:34:55 -04:00
Martin Carlberg b6fd6a15f0 Fixed: Removed extra spaces in code generation between 'else' and 'if' in 'else if' statements 2013-04-23 17:07:26 +02:00
Martin Carlberg e35bfaf96c Fixed: Better looking code generation with correct indentation for 'if' - 'else if' statements 2013-04-23 15:48:25 +02:00
Martin Carlberg ffdee8c3d7 Fixed: Method isEqual: can handle nil as an argument for CPExpression and CPPredicate including sub classes. 2013-04-23 12:58:07 +02:00
Martin Carlberg 8a94c33a64 New: Added test cases checking that a CPObject, CPExpression and CPPredicate is not equal nil.
CPExpression and CPPredicate can't handle nil as an argument to method isEqual:. These test cases checks that this is working.
2013-04-23 12:54:26 +02:00
Alexandre Wilhelm 9d69ec739f Fixed: CornerView in TableViews from cibs sized
Previously the size of the cornerView was wrong in a TableView from cib.

Now the nib2cib of _CPCornerView set the good value.

Fixes #1865
2013-04-22 15:38:31 -07:00
Ilya Kulakov c6553016d3 It's important to order out child windows before parent window relationship is broken. 2013-04-23 01:32:08 +07:00
Alexander Ljungberg 6048814635 Merge branch 'refs/heads/slevenbits-cpcolor-hsb-fix' 2013-04-21 15:03:53 +01:00
Alexander Ljungberg fe26e6cfe0 New: + CPException raise:format:.
This method allows the exception reason to be a formatted string with parameter replacement.
2013-04-21 14:56:57 +01:00
Alexander Ljungberg 3e35e3d8a8 Fixed: CPColorPicker not working with fixed CPColor colorWithHue: implementation. 2013-04-21 14:32:10 +01:00
Alexander Ljungberg 70b5105daa Fixed: CPColor colorWithHue:saturation:brightness: returning undefined.
A hue of 1.0 would cause the CPColor colorWithHue:saturation:brightness: method to return `undefined` instead of a CPColor instance.
2013-04-21 14:22:34 +01:00
Alexander Ljungberg d00846aae7 Fixed: CPColor colorWithHue:saturation:brightness: parameters not clamped.
Previously, the parameters to CPColor colorWithHue:saturation:brightness: could be specified below 0 or above 1.0.

Now the values are clamped so that values below 0 are taken as 0 and values above 1.0 and taken as 1.0.
2013-04-21 14:21:47 +01:00
Aparajita Fishman 7ec660c509 New: record the source filename in SyntaxError. 2013-04-20 13:24:50 -04:00
Ilya Kulakov 8e4f1fdd10 Fix child windows may reside on other layers than parent.
Child windows should reside on the same layer as parent.
2013-04-20 21:08:32 +07:00
Alexander Ljungberg 0c2abf3629 Test: new CPColor HSB tests. 2013-04-20 13:56:49 +01:00
Alexander Ljungberg 95d4bef3ea New: - CPColor hueComponent, saturationComponent and brightnessComponent. 2013-04-20 13:42:05 +01:00
Alexander Ljungberg 4e1a1415f6 Fixed: - CPColor hsbComponents range.
Previously, - CPColor hsbComponents returned degrees and percents. With the latest change to - CPColor colorWithHue:saturation:brightness: this was inconsistent.

Now - CPColor hsbComponents returns its components as factors in the 0-1.0 range.
2013-04-20 13:41:16 +01:00
Alexander Ljungberg 40579b5d56 Fixed: parameter range of CPColor colorWithHue:saturation:brightness:.
Previously, + CPColor colorWithHue:saturation:brightness: took its parameters as degrees and percent (e.g. hue between 0º and 360º, saturation and brightness between 0% and 100%). However, in Cocoa the components are given as factors (0.0-1.0) like other colour methods.

This fix makes + CPColor colorWithHue:saturation:brightness: work like in Cocoa.
2013-04-20 12:41:13 +01:00
Antoine Mercadal 60f79bdf63 Merge pull request #1910 from Dogild/MenuColor
Fixed: CPMenu bar selected background color
2013-04-19 14:59:36 -07:00
Alexandre Wilhelm 96a772d4dc Fixed: CPMenu bar selected background color
- Previously the selected background color didn't have the right color.
2013-04-19 14:54:37 -07:00
Andrew Hankinson 2974bdc1d7 Fix formatting and enumerator problems 2013-04-19 16:45:40 -04:00
aparajita c7f4517490 Merge pull request #1881 from kerusan/cpruleeditor_post_row_change
Fixed: 'RowCountChanged' notification generates nil warning when dragging a row
2013-04-18 13:26:20 -07:00
aparajita 8f6efdaae0 Merge pull request #1902 from ahankinson/fix-issue1899
Fixed: Removing an item from a menu also removes its highlight state
2013-04-18 13:17:24 -07:00
aparajita e760ee39e5 Merge pull request #1906 from ahankinson/fix-cptableview-variabletypo
Fixed: Misspelled variable in CPTableView
2013-04-18 13:02:32 -07:00
aparajita 0bc95c069d Merge pull request #1818 from t00f/master
New: tableView:shouldReorderColumn:toColumn: CPTableView delegate method
2013-04-18 12:58:38 -07:00
Aparajita Fishman f883b6a182 Fixed: _CPPopoverWindow.j was not imported in CPApplication.j
This caused the isKindOfClass: test in _CPRunModalLoop to generate an error in a deployment.

Importing that file fixed the error.
2013-04-18 13:31:27 -04:00
Christophe Serafin 88a247c107 merged sources and show shouldReorderColumn usage in TableCibTest example 2013-04-17 01:57:07 +02:00
Alexandre Wilhelm de5fbd921e Fixed bug when changing timeZone of the CPDatePicker 2013-04-16 15:22:16 -07:00
Alexandre Wilhelm a8aeb8addb Added CPTimeZone test 2013-04-16 15:21:30 -07:00
Alexandre Wilhelm 13211b489d Added support for timeZone in CPDatePicker calendar 2013-04-16 14:20:18 -07:00
Alexandre Wilhelm 9f5e977bcd Added support for timeZone in CPDatePicker textual 2013-04-16 14:10:52 -07:00
Alexandre Wilhelm 28357bd57f Corrected bad test 2013-04-16 02:26:17 +02:00
Alexandre Wilhelm f39e224c48 Updated manual example 2013-04-15 16:33:00 -07:00
Alexandre Wilhelm 9b9b041263 Removed double action in CPDatePicker 2013-04-15 16:22:54 -07:00
Alexandre Wilhelm 98a59c4700 Fixed small bus about timeZone 2013-04-15 16:20:02 -07:00
Alexandre Wilhelm 3497e36f23 Fixed bunch of bugs in CPDateFormatter with TimeZone 2013-04-15 14:25:30 -07:00
Andrew Hankinson 3612565e3a Fix delegate selection to check the index first
In the previous patch the shouldSelectRow delegate was being stored and only called once. This changes its behaviour again to first fire the delegate to see if the row in question can be selected. If not, it will look for the next row (up or down) that may be selected and choose that one.
2013-04-15 16:38:37 -04:00
Andrew Hankinson c24a7712cd Fixed: Misspelled variable in CPTableView
This commit fixes a typo in CPTableView. `_contentBindingExpicitelySet` should be `_contentBindingExplicitlySet`. The misspelling was consistent, so this should have no functional change.
2013-04-15 11:58:13 -04:00
Alexander Ljungberg 83677dae83 Merge pull request #1904 from ahankinson/docs-fix-tableview-typo
Docs: Fix small but potentially confusing typo in CPTableView
2013-04-15 16:48:27 +01:00
Andrew Hankinson 6e2dcd5dcb Fixed: Delegate method fires twice when using keyboard to select rows in table view
Previously, navigating through the rows of a tableview with the arrow keys would cause the delegate method `- (BOOL)tableView:(CPTableView)aTableView shouldSelectRow:(int)rowIndex` to fire twice. This was due to the delegate method being called twice in checking whether the row could be selected.

This commit changes it so that the delegate method is called just once and the result stored.
2013-04-15 11:46:58 -04:00
Andrew Hankinson 5eea9c301c Docs: Fix small but potentially confusing typo in CPTableView
This commit fixes the delegate documentation for `- (void)tableViewSelectionIsChanging:(CPNotification)aNotification`, removing reference to "selection chaining." (should be "selection changing")
2013-04-15 11:21:29 -04:00
Andrew Hankinson efa2918ce9 Change how menu items are highlighted
This replaces the previous solution with one proposed by @BlairDuncan. It uses the _highlightItemAtIndex: method to maintain the highlight state, rather than setting the _highlightIndex variable directly.
2013-04-14 15:40:35 -04:00
Alexandre Wilhelm 0bbaec0829 New: Added support for CPTimeZone and CPDateFormatter
- Added support for CPDateFormatter in Foundation
- Added support for CPTimeZone in Foundation
- Added support fo CPDateFormatter in nib2cib

Test app in Tests/Manual/CPDateFormatter
UnitTest in Tests/Foundation/CPTimeZoneTest.j
UnitTest in Tests/Foundation/CPDateFormatterTest.j
2013-04-12 11:15:10 -07:00
Martin Carlberg 689ab09555 New: Now supports 'defined' operator, which lets you check whether macros are defined in the middle of an ‘#if’.
Also the evaluation of expressions are now lazy.
2013-04-11 09:37:40 +02:00
Martin Carlberg 30ee1ad8cd New: Handles line continue token '\' on lines starting with '#'
We now support lines like this:
#define StopButtonTitle() \
        CPLocalizedString(@"Stop", @"Stop button title")
2013-04-11 09:32:41 +02:00
Andrew Hankinson cc9ff15142 Fixed: Removing an item from a menu also removes its highlight state
Previously when a menu item was instantiated outside of the context of the menu itself, its highlight state was maintained even after it was removed from the menu. If the menu was dismissed with the item highlighted, and then the item was used in another menu (e.g., re-added to a context menu for a table row) it would appear highlighted, even though the menu highlight index was not set.

This commit ensures that when removing items from a menu that the highlight state of the underlying view is set to NO as well.

Tests for this behaviour are included as well.

Fixes #1899
2013-04-10 00:04:53 -04:00
Alexander Ljungberg 4c756c7cbf Merge pull request #1900 from ahankinson/fix-aboutpanel-cib
Fixed: AboutPanel is now constructed in code, rather than in a CIB
2013-04-09 00:26:16 +01:00
Andrew Hankinson 100f1b0b41 Fixed: AboutPanel is now constructed in code, rather than in a CIB
Previously the default About panel was constructed in a CIB. Additionally, an Xcode-based XIB/CIB file was constructed to replace it.

This commit creates the default About panel in code and removes the additional CIB/XIB files in the AppKit/Resources panel.
2013-04-08 19:20:37 -04:00
Aparajita Fishman d9117bd9a0 Fixed: Converter was copying too much state from Nib2Cib, framework resources could not be referenced in Xcode.
* State *
Previously the Converter class needlessly copied a whole bunch of state from the Nib2Cib class, which was not only poor factoring, but made for easy omissions of state when instantiating a new Converter, such as was done in NSNib.j.

This commit pushes all state not specific to Converter up to Nib2Cib. This allowed removal of redundant code in NSNib -NS_initWithCoder.

* Resources *
Previously it was not possible to use custom images that were located in a framework, because only the app's Resources directory was searched.

This commit automatically searches all frameworks for Resources directories. When a custom image is specified in Xcode, first the app's Resources directory is searched, then all framework Resource directories. Alternately, the specific framework to use can be specified in Xcode by using the form framework@image.

At runtime, the framework is loaded by its identifier (as specified in Info.plist), and if there is no identifier, by searching next to the current AppKit framework.

All of this renders the nib2cib -R option completely obsolete, so it was removed from the NibApplication/Jakefile template.
2013-04-08 15:48:45 -04:00
Andrew Hankinson 6ef5b46dd6 Fixed: CPTokenField sends focus and blur notifications
This commit adds notifications for focus and blur on CPTokenField.

Attached is a modified Manual CPTokenFieldTest that observes these notifications.

Fixes #1396
2013-04-07 20:50:50 -04:00
Alexander Ljungberg b3c60e56a6 Merge pull request #1897 from ahankinson/fix-info-plist-templates
Fixed: Additional keys in default Info.plist templates
2013-04-08 00:35:42 +01:00
Alexander Ljungberg 8d345701da Merge pull request #1896 from ahankinson/fix-about-panel-xib
Fixed: New AboutPanel.xib replaces older CIB file
2013-04-07 23:18:48 +01:00
Alexander Ljungberg 016ed4f6ee Merge branch 'master' of github.com:cappuccino/cappuccino 2013-04-07 23:16:45 +01:00
Andrew Hankinson 3da7e45244 Fixed: Additional keys in default Info.plist templates
This fix adds two keys to the default Info.plist in the capp gen template for NibApplication, "CPBundleVersion" and "CPHumanReadableCopyright". These are introduced primarily to fill out the fields in the default "About" panel. (see #1896)
2013-04-07 17:02:54 -04:00
Andrew Hankinson b1229bce1d Fixed: New AboutPanel.xib replaces older CIB file
With the death of Atlas CIB files can no longer be edited directly. This commit replaces a CIB-only version of "AppKit/Resources/AboutPanel.cib" with a XIB-derived one that can be edited in Xcode.

This commit also moves some of the formatting of the about panel into the IB file (c.f. the FIXME note).
2013-04-07 16:54:15 -04:00
Aparajita Fishman fea6b37379 New: capp framework template provides a default CPPrincipalClass.
Previously no default principal class was declared in Info.plist for a framework.

This commit declares the principal class to be the same as the main framework class created with capp gen -t Framework.
2013-04-06 16:21:47 -04:00
Aparajita Fishman d64ea284fb Fixed: CPBundle -bundleWithIdentifier did not create CPBundle when necessary.
Previously, if a CFBundle with the given identifier had been loaded, but no CPBundle had yet been created with the given identifier, -bundleWithIdentifier would return nil instead of a newly constructed CPBundle with the CFBundle's URL.

This commit correctly returns a newly constructed CPBundle when a CFBundle is found.
2013-04-06 16:20:21 -04:00
Aparajita Fishman cc2503ac0f Fixed: CFBundle.prototype.bundleURL() did not return an absolute URL.
CFBundle internally stores its URL in relative form, and returned that relative URL in the bundleURL() function. However, in Cocoa an absolute URL is returned. It is reasonable to assume an absolute URL would be expected by some asking for the bundle's URL. Even within CFBundle, most times bundleURL() is called it is followed with absoluteURL().

This commit returns an absolute URL from bundleURL().
2013-04-06 15:51:09 -04:00
Aparajita Fishman 486bff44df Fixed: wrong display name for CFBundle.bundleContainingURL. 2013-04-06 15:48:41 -04:00
Aparajita Fishman 04d6b34bfe Fixed: tests broke because of change in CGRect/CGSize/CGPoint description. 2013-04-06 08:49:33 -04:00
Aparajita Fishman 0193632673 New: use a more compact representation of CGSize/CGPoint/CGRect in description. 2013-04-05 23:18:56 -04:00
Aparajita Fishman a3730812bc New: CFBundle.identifier, CFBundle.bundleWithIdentifier, CPBundle -bundleWithIdentifier.
Finding a bundle by identifier is theoretically better than using a class.
2013-04-05 23:16:05 -04:00
Antoine Mercadal 90e11039a1 Merge branch 'CPDatePickerTarget' of https://github.com/Dogild/cappuccino into pr-1895 2013-04-05 11:40:27 -07:00
Antoine Mercadal 80d928eff2 Merge branch 'menuKeyboardNavigationFix' of https://github.com/BlairDuncan/cappuccino into pr-1894 2013-04-05 11:37:21 -07:00
Antoine Mercadal 838041ef59 Merge pull request #1872 from ahankinson/fix-tableview-method-documentation
Docs: Out of date documentation for CPTableView
2013-04-05 11:31:23 -07:00
Antoine Mercadal 732f94a284 Merge pull request #1883 from ahankinson/fix-textfield-ib-enabled
Fixed: Allow Interface Builder to set CPTextField enabled state
2013-04-05 11:30:54 -07:00
Antoine Mercadal 70081e1118 Merge pull request #1873 from ahankinson/fix-issue1866
Fixed: XCodeCapp adding duplicate files to Xcode project
2013-04-05 11:30:17 -07:00
Antoine Mercadal 35c15c90e4 Merge pull request #1890 from Dogild/MenuItemColor
Fixed: CPMenuBar theming
2013-04-05 11:28:57 -07:00
Alexandre Wilhelm 812cd463db Fixed: CPDatePicker works with action and target
Previously the CPDatePicker didn't work with the action and target. Now each time the dateValue changed, the given action is sent to the target.
This commit fix also a bug with moving with tab and the arrows. Before, the left arrow worked liked a tab when the firstElementTextField was selected in a textual CPDatePicker.

Test app in Tests/Manual/CPDatePicker.
2013-04-05 11:28:41 -07:00
Alexandre Wilhelm 090d097a53 Added action and target 2013-04-05 11:19:20 -07:00
Alexandre Wilhelm 36b337e784 Fixed bug about left moving 2013-04-05 11:13:28 -07:00
Blair Duncan 7d0d1056c0 Fixed – Menus no longer respond to keyboard navigation
When a menu is active, menu selection should change as characters are typed.
This can be seen in the manual CPMenuTest.

It used to work in the past but with all of the changes in the last few months to the compiler I
was not able to track down the exact commit that broke it. The code responsible for
clearing the _keybuffer after a brief delay in typing, was not being called,
resulting in a build up of characters.

This commit moves the check for delay to the interpretKeyEvent and takes care of
clearing the _keybuffer itself and removes that responsibility from the selection method.
2013-04-04 12:44:15 -04:00
Aparajita Fishman 21146ff49f Fixed: scrolling CPTextField to visible would cause unexpected behavior
Previously, when a text field became the key responder, first it was scrolled to visible, then a check was made to see if the text field was completely within the platform window bounds. The scrolling to visible would unfortunately cause problems because of the interaction between the blur handler in text fields and controls that can be clicked without becoming first responder.

This commit completely forbids text fields from becoming first responder if they are not completely within the platform window. That eliminates any possibility of unwanted browser scrolling of the text field.
2013-04-02 12:06:32 -04:00
Antoine Mercadal b76eedfc0e Merge pull request #1884 from Dogild/CPDatePickerSupport
New: CPDatePicker Support
2013-04-01 18:01:42 -07:00
Alexandre Wilhelm c547117223 Removed comments 2013-04-01 14:37:53 -07:00
Antoine Mercadal fc2132485d Merge branch 'CPMenuGhost' of https://github.com/Dogild/cappuccino into pr-1891 2013-04-01 14:26:47 -07:00
Alexandre Wilhelm 71cc825038 Fixed: CPMenu ghost his fixed #1887
Fixed the bug about ghost menu after several right click
2013-04-01 13:28:30 -07:00
Antoine Mercadal 59d1da77c2 Fixed: setting CPNullPlaceholderBindingOption in binding was setting the value
This commit fix a bug where declaring the binding option CPNullPlaceholderBindingOption was actually setting the
actual value of a text field instead of just its placeholder. This commit adds a test to determine if the binding source
implements setPlaceholderString:. In that case, we let the value to be nil.
2013-04-01 12:47:00 -07:00
Alexandre Wilhelm c6a59d7c59 Fixed: CPMenuBar theming
Previously it wasn't possible to theme the main menu of the app. With this fix the user can either theme the main menu with the theming system or with the method +setMenuBarAttributes from CPMenu.
2013-03-31 23:31:02 -07:00
Alexander Ljungberg 84559fae9c Merge pull request #1889 from saikat/master
Fix a memory leak in _CPImageAndTextView.  This closes #1888.
2013-03-31 09:56:14 +01:00
Saikat Chakrabarti aa0602dcbb Fix a memory leak in _CPImageAndTextView.j 2013-03-30 21:52:17 -07:00
Antoine Mercadal 6d0caacdeb Fixed: setAnimates: for CPPopover doesn't get forwarded to _CPPopoverWindow.
Without this fix, using setAnimates: on a popover would only be applied after closing/reopening of the popover.
2013-03-28 15:18:46 -07:00
Martin Carlberg 84df301f3e New: #if macro statement works for simple literals but not for macro identifiers and defined keyword 2013-03-28 22:43:26 +01:00
Andrew Hankinson 792a72af74 Fixed: Themed text values set via a single variable
Previously, the themed text values for controls were set directly on the control, which made modifying the theme values for text consistently across the controls difficult.

This commit introduces several file-scoped variables that are used to set the text colour, the disabled text colour for both regular and default controls, as well as a consistent text shadow colour for each of these as well.
2013-03-28 13:35:09 -04:00
Andrew Hankinson 8fee6578c2 Fixed: Minor typo in CPWindow comment 2013-03-28 10:36:46 -04:00
Andrew Hankinson 6d843e6aab Fixed: Removed duplicated method in CPToolbar
CPToolbar setDisplayMode has been implemented (L246). This commit removes a duplicate empty method that says it has not been implemented.
2013-03-28 10:19:08 -04:00
Alexandre Wilhelm 27bb85bb00 Fixed bug about firstResponder. Fixed bug about current date when changing the month (to pass from the 31 to 30) 2013-03-27 11:23:20 -07:00
Martin Carlberg 2751f4fea9 New: Added missed #ifdef derective 2013-03-27 14:52:05 +01:00
Martin Carlberg c21cfeb28e New: Added #ifdef, #ifndef, #else, #endif and #undef macro derectives 2013-03-27 14:50:55 +01:00
Martin Carlberg 8707247008 New: Always generate code when compiling 2013-03-27 14:45:25 +01:00
Andrew Hankinson 3d0bde6763 Stepper disabled graphics update 2013-03-27 00:20:20 -04:00
Andrew Hankinson 11f509933e Typos 2013-03-26 23:40:19 -04:00
Andrew Hankinson 7078dd92dd Restoring the segmented control theme descriptor settings 2013-03-26 23:23:35 -04:00
Andrew Hankinson f5e0addbcc Restoring circular slider disabled graphics 2013-03-26 23:22:34 -04:00
Andrew Hankinson fd88ac509f Slight tweak to the disabled slider knob graphic
The stroke opacity is reduced from 35% to 20% to bring it in line with the stroke opacity of other disabled controls
2013-03-26 23:22:02 -04:00
Andrew Hankinson d267ddcafa Reverse earlier commits that removed some images
The segmented control disabled state is not applied via CSS opacity, so the segmented control images must be present.
2013-03-26 23:20:40 -04:00
Andrew Hankinson 9084e9ed18 Fixed: Text shadow offset on enabled controls
Previously, the text shadow offset on a control that was active (e.g., a button that was set to default, or the active segment of a segmented control) would have a text shadow applied to it if the button was also disabled.

This commit negates the text-shadow offset so that the text appears correctly.
2013-03-26 23:17:23 -04:00
Andrew Hankinson bf29a4faa9 Defined file-level variables for text colors
This commit defines file-level variables for the disabled text colour, the disabled text shadow colour, and the placeholder text colour. It also adds or replaces these values in the controls where appropriate.
2013-03-26 23:14:57 -04:00
Andrew Hankinson 615380a70c Standardizing disabled text theming for popup and pulldown buttons 2013-03-26 22:46:49 -04:00
Antoine Mercadal d268013bf0 Fixed: Make build under rhino to work
Previously, rhino build was failing
2013-03-26 18:03:38 -07:00
Antoine Mercadal 835367e1bf Merge branch 'master' into CPDatePickerSupport 2013-03-26 18:02:27 -07:00
Antoine Mercadal 054421c978 Fixed: Crash with rhino in fontinfo due to missing import
fontinfo's Jakefile needed to import SYSTEM to call SYSTEM.env
2013-03-26 17:57:02 -07:00
Andrew Hankinson 20a2b2d330 Fixed: circular slider disabled image uses CSS opacity 2013-03-26 20:23:38 -04:00
Alexandre Wilhelm 1649ea64cc New: CPDatePicker Support
- Added CPDatePicker
- Added CPLocale
- nib2cib for CPDatePicker

Test app in Tests/Manual/CPDatePickerTest
2013-03-26 16:52:46 -07:00
Andrew Hankinson d50439161a Fixed: Combo box disabled state dims text
Previously, setting a CPComboBox to disabled would not dim the text. This commit fixes the theme state to include a setting for the text colour and text shadow colour.
2013-03-26 19:19:03 -04:00
Andrew Hankinson 7d6cdf1b7b Updated pulldown button disabled images
These updated images have an outer stroke opacity of 20%, compared to 35% for the active images
2013-03-26 19:01:08 -04:00
Andrew Hankinson abcb60ed4c Updated popup button disabled images
These updated images have an outer stroke opacity of 20%, compared to 35% for the active images
2013-03-26 19:00:52 -04:00
Andrew Hankinson 443b6ff4f9 Updated combo box disabled images
These updated images have an outer stroke opacity of 20%, compared to 35% for the active images
2013-03-26 19:00:14 -04:00
Andrew Hankinson de89eadcf2 Formatting and whitespace 2013-03-26 18:40:22 -04:00
Andrew Hankinson 4956218b10 Fixed: Change default disabled opacity
Previously some disabled controls would be set with an opacity of 0.35, which resulted in controls that were visually too light.

This commit changes the default disabled opacity to 0.5.

Refs #1788
2013-03-26 17:44:57 -04:00
Andrew Hankinson bcfaf3a37e Fix Pulldown Button disabled images
The new images are set at full opacity with the blue highlight colour removed
2013-03-26 17:43:02 -04:00
Andrew Hankinson b1c45e579a Fix CPPopupButton disabled images
The new images are set at full opacity with the blue highlight colour removed
2013-03-26 17:42:41 -04:00
Andrew Hankinson e627f60b16 Fix CPComboBox disabled images
The new images are set at full opacity with the blue highlight colour removed
2013-03-26 17:42:05 -04:00
Andrew Hankinson 7154252dff Fixed: Allow Interface Builder to set CPTextField enabled state
Previously, the enabled/disabled control for NSTextField in Interface Builder was ignored by nib2cib.

This change allows the enabled/disabled state on CPTextField to be set in interface builder.
2013-03-26 14:54:53 -04:00
Andrew Hankinson a368fe5825 Fix disabled theme for Aristo2 segmented controls
Disabled state is now set via CSS opacity alone
2013-03-26 13:39:46 -04:00
Andrew Hankinson 895a128ff7 Fix disabled theme for Aristo2 radio buttons
Disabled state is now set via CSS opacity alone
2013-03-26 13:33:55 -04:00
Andrew Hankinson 792a4dda7f Merge branch 'fix-theme-disabled-controls' of github.com:ahankinson/cappuccino into fix-theme-disabled-controls 2013-03-26 13:29:56 -04:00
Andrew Hankinson 4d828a01aa Fix disabled theme for Aristo2 checkboxes
Previously the Aristo2 checkboxes used dedicated images for disabled controls.

This commit removes the disabled controls and allows the disabled state to be set via CSS opacity on the "regular" checkbox controls.
2013-03-26 13:29:48 -04:00
Andrew Hankinson 195ee3ee2c Fix disabled theme for Aristo2 checkboxes
Previously the Aristo2 checkboxes used dedicated images for disabled controls.

This commit removes the disabled controls and allows the disabled state to be set via CSS opacity on the "regular" checkbox controls.
2013-03-26 13:23:11 -04:00
Kjell Nilsson d9e7912162 Fixed: constructing a 'RowCountChanged' notification generates a nil warning when dragging a row
Previously, when

- Dragging a row in the rule editor

would eventually try to generate a dictionary with key 'indexes' and a
nil value in the method __postRowCountChangedNotificationOfType:indexes:.
Generating an empty dictionary instead when there is no indexes solves
this issue.
2013-03-26 11:19:44 +01:00
Aparajita Fishman 2a580c675a Fixed: shared singleton Converter was being overwritten by incompletely constructed instance.
Previously, NSNib would create a Converter instance for converting table cell views. Unfortunately Converter did not expect to be instantiated more than once, and the singleton SharedConverter was unconditionally being set in the initializer. This might not have caused problems, except that NSNib did not copy all of the shared Converter's state to the copy, especially the resource path, which caused custom images in table cell views to fail.

This commit correctly ensures that the shared Converter instance is set only once, and also copies all of the shared Converter state to the instance that is used for converting the table cell view.
2013-03-25 16:07:58 -04:00
Aparajita Fishman 9f66de8422 Fixed: removed deprecated check for no resource path.
Long ago it was required to use the -R option with nib2cib if custom images were used. nib2cib now infers the resource path, so there will always be at least a default resource path. Thus the check for no resource path was unnecessary.

This commit removes that check.
2013-03-25 16:02:52 -04:00
Aparajita Fishman b26542136e Formatting 2013-03-25 15:59:10 -04:00
Christophe Serafin c135905e64 removed blank line and console messages 2013-03-25 13:37:49 +01:00
Christophe Serafin b7b7d33597 avoid to call the delegate when moving before the first column and after the last column 2013-03-25 13:22:43 +01:00
Aparajita Fishman 097d8e9b97 Fixed: adding object to CPArrayController generated warning.
Previously, if properties were bound to table columns in a cell-based table, and an object was added/inserted using CPArrayController, a warning was generated about a missing observer.

This commit is a temporary fix, the real fix is to implement more granular notifications during didChangeValueForKey:, which will eliminate the source of this problem.

Fixes #1781.
2013-03-24 20:12:22 -04:00
Aparajita Fishman 8c811ba9ca Fixed: instantiating a cib with no owner would generate nil warning
Previously, when a view-based table:

- Had no delegate.
- Used bindings for its data source, thus obviating the need for makeViewWithIdentifier:owner:.

it would eventually call CPCib -instantiateCibWithOwner:topLevelObjects: with a nil owner (the nil table delegate). This method would try to construct a dictionary with the nil owner, which would generate a deprecation warning, and will in the future fail altogether.

In Cocoa, this is exactly what happens, the owner is nil. And the documentation for -instantiateNibWithOwner:topLevelObjects: clearly states that the owner may be nil.

This commit only adds the owner to the name table dictionary if the owner is non-nil. Since objectForKey: with a non-existent key returns nil, this is the same as storing nil for that key.
2013-03-24 19:46:53 -04:00
Alexander Ljungberg b6cf557483 Merge pull request #1879 from cacaodev/CPDragServer-fixed-constrained-inside-bounds
Fixed: A dragged view was constrained inside a plaform window bounds.
2013-03-24 22:20:42 +00:00
Alexander Ljungberg 3562aed899 Merge pull request #1878 from ahankinson/fix-cpimage
Fixed: Typo in CPImageView Category
2013-03-24 22:17:16 +00:00
cacaodev 07222e92c2 Fixed: A dragged view was constrained inside a plaform window bounds.
For example, in CPTableView before this change, dragged rows could not move up if the table view was near the top of the platform window.

Fixes #1877
Test TableTest/ViewBasedCib/ and drag up the third row.
2013-03-24 22:08:15 +01:00
Andrew Hankinson 011c3c9c5b Fixed: Typo in CPImageView Category
The category name for CPImage (CachedImage) was spelled wrong. This commit fixes the typo.
2013-03-24 16:15:50 -04:00
Alexander Ljungberg 28b77fa02b Merge pull request #1876 from cacaodev/CPTableView-viewForRow-infinite-loop
Fixed: a view outside a CPTableView causing an infinite loop when becomes FR.
2013-03-24 20:00:02 +00:00
cacaodev a9ec90713e The FR can be a window, don't check if it's inside a table. 2013-03-24 20:33:22 +01:00
cacaodev 8663b7b3fa Merge remote-tracking branch 'upstream/master' into CPTableView-viewForRow-infinite-loop 2013-03-24 18:50:41 +01:00
cacaodev 3ef5cfe846 Fixed: Infinite loop when a first responder has a nil superview
This bug appears only if a table view have been added to the window.

CPTableView observes first responder changes and moves up in the view
hierarchy to determine the edited data view. If for some reason, a
superview in the hierarchy was nil, we entered an infinite loop.

This commit adds guards to the recursive method that searches the data
view. Also added an early return when the fr changes to a view outside
the table.

Fixes #1875
2013-03-24 18:37:12 +01:00
Aparajita Fishman 05fa505bb6 Fixed: CPArray did not allow binding to @count.
Previously, CPArray did not allow binding to the collection operator @count. In Cocoa this is allowed.

This commit allow the key path @count to be observed, so that @count can be bound to.

Formatting fixes as well.
2013-03-23 15:21:50 -04:00
Andrew Hankinson 5c3adfda29 Fixed: XCodeCapp adding duplicate files to Xcode project
Previously, XCC would indiscriminately add files to the Xcode project via the pbxprojModifier.py script. This resulted in duplicate references to a file.

This fix adds a check to see if the file is already included in the project's sourceGroup folder, and will return None if it is.

Fixes #1866
2013-03-22 09:44:02 -04:00
Andrew Hankinson 0013375eea Docs: Out of date documentation for CPTableView
A small documentation change to reflect the updated viewForTableColumn:row:
2013-03-21 16:24:55 -04:00
Blair Duncan 5868a4cefb added missing methods to CPDocumentController
documentForWindow
hasEditedDocuments

both are in cocoa
2013-03-21 11:15:25 -04:00
Blair Duncan 3178f0b57d Fixed CPDocumentController missing method currentDocument
In this commit I've added the currentDocument method to the document controller

Also removed the firstEligibleExistingWindowController method from CPDocument
It did nothing but add confusion as it was not used anywhere else in the frameworks.
And it is not in cocoa.
2013-03-21 10:38:06 -04:00
Alexander Ljungberg 31c06771f3 Fixed: CPBezierPath getLineDash:phase: typo. 2013-03-21 14:37:37 +00:00
Alexander Ljungberg 6f57b8a2de Merge pull request #1869 from sherab/stringByTrimmingCharactersInSet-fix
Fixed: stringByTrimmingCharactersInSet not removing characters at end
2013-03-21 13:52:55 +00:00
Tim Lewis bd6d2e71e7 Fixed: stringByTrimmingCharactersInSet not removing characters at end
If a string had characters from the set at both the start and end,
the end trim was one character less than required.
2013-03-21 13:44:00 +00:00
Martin Carlberg 89457845f9 Fixed: Made some smaller code generation changes to get better formatted compiled code 2013-03-21 14:32:21 +01:00
Martin Carlberg 53e98521f3 Merge branch 'master' of https://github.com/cappuccino/cappuccino into preprocess 2013-03-21 12:25:47 +01:00
Martin Carlberg 1842d7127a New: The generated code will now have correct indentation. 2013-03-21 11:33:13 +01:00
Martin Carlberg ecc1e774b9 New: Added macro/identifier concatenation with the '##' operator
Example:
#define first Martin
#define second Carlberg
var first##second = 13;

Compiles to:
var MartinCarlberg = 13;

Example 2:
#define _function(inline) function inline { return _##inline; }
#define _CGPointMake(x_, y_) { x:x_, y:y_ }
_function(CGPointMake(x, y))

Compiles to:
function CGPointMake (x, y) {
  return {x: x, y: y};
}
2013-03-20 21:00:36 +01:00
Martin Carlberg fa18095538 Fixed: Does not add extra parentheses for expression operators with the same precedence 2013-03-20 20:47:27 +01:00
Alexander Ljungberg da9333e884 Fixed: CPBezierPath getLineDash: nil arguments, setLineDash:count:phase: argument style.
Previously, passing nil to the first or last argument of getLineDash:count:phase: would cause a crash.

With this change, these references are simply not written to if nil.

Previously, setLineDash:count:phase: took references for its arguments to match getLineDash:count:phase:. This was however wrong and is not what is done in Cocoa.

This fix makes the setLineDash:count:phase: calling convention the same as in Cocoa.
2013-03-20 16:02:27 +00:00
Alexander Ljungberg af11431b09 Fixed: Firefox dashed stroke phase support (theoretically).
This fix should in theory make the phase argument work in Firefox, although in Firefox 19.0.2 it doesn't seem to work. Hopefully it'll kick in in a future version of Firefox.
2013-03-20 15:42:22 +00:00
Alexander Ljungberg 16134aa0de Test: dashed and phased CG strokes. 2013-03-20 15:27:48 +00:00
Alexander Ljungberg ffbd9815d5 New: CPBezierPath setLineDash: and getLineDash:.
Also includes Cocoa compatible methods for completeness.
2013-03-20 15:26:51 +00:00
Alexander Ljungberg ab692bb15d New: CGContextSetLineDash. 2013-03-20 14:06:01 +00:00
Alexander Ljungberg 085654e751 Fixed: nib2cib of combo box parsed enabled state twice.
It's sufficient to read the _enabled state in the superclass NSCell, no need to read it again in the subclass.

Refs #1868.
2013-03-19 23:17:35 +00:00
Alexander Ljungberg 5b3386af2f Merge pull request #1868 from ahankinson/fix-cpcombobox-ib-disable
Fixed: Allow Interface Builder to set CPComboBox enabled state
2013-03-19 23:05:59 +00:00
Andrew Hankinson d6545627aa Fixed: Allow Interface Builder to set CPComboBox enabled state
Previously, the enabled state of a CPComboBox could not be set in Interface Builder.

This commit allows Interface Builder to set the enabled state of a CPComboBox.

A modified test in Manual/CPComboBoxTest is included. This test simply adds a new disabled combo box to an existing window, and then checks to see if it is disabled, printing a descriptive message to the Javascript console.
2013-03-19 19:01:56 -04:00
Andrew Hankinson cb63013197 New: Higher Contrast XCodeCapp menubar icons
This commit changes the current XCodeCapp menubar icon to use higher contrast colours, making it easier to see when XCC is working or idle.

Previously, the colours were black and dark green. With this change, the colours are black and orange (taken from the Cappuccino logo).

This commit includes the original PSD artwork as well as rendered versions of the icons in PNG format.
2013-03-18 09:56:43 -04:00
Aparajita Fishman 5d2e4bf7cc Fixed: theme build failed
Previously CPTableView -_init was trying to reference a theme value, but that doesn't work because the theme creates a CPTableView and during that _init the theme value is not yet defined.

This commit uses lazy instantiation to avoid this problem.

Also, column selection was added to the CPDictionaryControllerTest to better visualize unfocused selection highlight colors.
2013-03-18 08:21:02 -04:00
Aparajita Fishman a4fb2deece Fixed: unfocused selection highlight colors were hard coded
Previously, the colors used for unfocused selection highlighting were hard coded. In Cocoa, they seem to be desaturations of the focused selection highlight colors.

This commit calculates the unfocused highlight colors from the focused colors.

It also removes some dangling commas.
2013-03-17 18:29:47 -04:00
Martin Carlberg 92ac8569b3 New: Full support for generate code instead of copy
The new compiler can now generate code. The old way of copy and alter the source
code is still supported.
2013-03-17 21:00:24 +01:00
Martin Carlberg 0c982b0999 Fixed: An ExpressionStatement with a Send message expression can be parsed wrongly
When a statement ends without a semicolon and a Send message expression is on the next line it was wrongly parsed as a single Send message expression. It should be an ExpressionStatement with a Send message expression inside.
2013-03-17 20:52:21 +01:00
Martin Carlberg bef0ca18c6 New: New option to generate code for the objjc tool
A new option flag '-G' can be added to let the compiler generate the code instead of copy and alter it from the source code
2013-03-17 20:45:34 +01:00
Aparajita Fishman afc2c17b5a Fixed: highlighted table cells with CPTableViewSelectionHighlightStyleNone had white text.
Previously, CPTableView was unconditionally setting the selected theme state for selected data views. When the selection highlight style is CPTableViewSelectionHighlightStyleNone, there is no row selection highlighting done. Since the default theme specifies white text for selected data views, we ended up with white text on a non-highlighted background, which was invisible on non-alternate rows and almost invisible on alternate rows.

This commit unsets the selected theme state flag for any redrawn data views when the selection highlight style is CPTableViewSelectionHighlightStyleNone, thus the text color does change at all when selected.

Fixes #1847
2013-03-16 15:41:24 -04:00
Blair DuncanandAparajita Fishman efdf0a6b84 Fixed: When editing a table cell, the row lost focus.
Previously, when a table cell was edited, the table thought it had lost focus and displayed the cell's row highlight in an unfocused state.

This fix updates the _isFocused test to include tests for cell editing in both cell-based and view-based tables.
2013-03-16 09:33:53 -04:00
Aparajita Fishman b36f8d794c Fixed: unfocused selection highlight in table upside down.
Previously the gradient in an unfocused selection highlight in CPTableViewSelectionHighlightStyleSourceList style was darker at the top and brighter at the bottom, which is the opposite direction of the gradient when focused.

This commit makes all of the unfocused highlight colors a strict 5% desaturation of the focused colors.

Refs #1839
2013-03-15 19:57:20 -04:00
Aparajita Fishman 5c022f86ea Fixed: table selection highlight gradient top/bottom too dark.
In CPTableViewSelectionHighlightStyleSourceList selection style, a table view draws the highlight on each row with a top line, linear gradient, and bottom line. Previously, the top and bottom lines were quite dark in relation to the gradient.

This commit makes the top and bottom line brighter, to make the transition to the gradient more subtle.

Refs #1839
2013-03-15 19:57:19 -04:00
Blair DuncanandAparajita Fishman fd20a8045e Fixed: table view selection color did not change when losing focus.
CPTableView has no focus ring, and currently gives no visual feedback of its firstResponder status. In Cocoa when the table view resigns firstResponder or its window loses key status, the selection color turns gray.

This commit sets the selection color to gray when a table view resign firstResponder or its window loses key status. A second window and a couple of textfields were added to the CPDictionaryControllerTest to demonstrate the changes.

Fixes #1839
2013-03-15 19:56:47 -04:00
Aparajita Fishman 9482d14160 Fixed: table view highlight update loop had high overhead
Previously the selection highlight update loop created two selectors and called an extra method for every row being updated.

The selectors are now calculated beforehand, and the method call has been eliminated.
2013-03-15 16:37:15 -04:00
Aparajita Fishman 61783021cc Fixed: default horizontal margin wasn't changed along with theme value 2013-03-15 13:30:26 -04:00
Andrew HankinsonandAparajita Fishman 64b5299c0d Fixed: menus were too far apart.
Previously the main menus were farther apart than the Aristo 2 PSD indicated, and too far apart visually.

This commit reduces the horizontal margin between menu items that have originated from Interface Builder. A value of 9.0 for horizontal margin (down from 12.0) reduces the margin on both sides of the menu by 3px, reducing the inter-menu spacing by a total of 6px.

Fixes #1809
2013-03-15 12:55:03 -04:00
Blair DuncanandAparajita Fishman 8d2077fc5d Fixed: views from other windows could be set as next/previous key view.
Previously, no check was done to ensure a next/previous key view belonged to the same window as the view to which it was being chained. This could lead to an infinite loop.

This commit will only set the next/previous key view if the proposed's views window is either nil or is the same as the receiver's window.

Closes pull request #1851
2013-03-15 12:39:08 -04:00
Alexander Ljungberg 720b61f4f6 New: close pull down menu on second click on its button.
Previously, if a pull down menu was brought down from a pop up button in pull down mode, clicking the button again would close and reopen the menu.

With this fix the behaviour becomes like in Cocoa, and clicking the button a second time simply closes the menu.
2013-03-15 14:47:16 +00:00
Alexander Ljungberg 9fa8867495 Fixed: infinite loop clicking on a pull down menu button.
This was caused by the menu opening up below the button. When the menu manager examined this event it saw a click outside of the menu and immediately closed the just opened menu. Then it put the opening event back on the event queue, causing the pop up button to try to open its menu again.

The fix ignores the opening event for purposes of detecting clicks which should close the menu.

Refs #1833.
2013-03-15 14:47:16 +00:00
Aparajita Fishman b198fee11a Fixed: default class theme value could be CPNull.
The class method +themeAttributes returns a dictionary, so CPNull has to be used instead of nil. Previously, if the class theme attribute was used, there was no attempt to convert CPNull to nil, which could have unintended consequences.
2013-03-15 10:02:31 -04:00
Aparajita Fishman 2f71b8d5c9 Fixed: improved handling of custom styled table text cells.
Previously more work was done than necessary to initialize custom table text cells.

Now the theme state is set before initializing table cells, which allows fonts and colors to be set correctly. The selected colors still have to be set explicitly.

BREAKING CHANGE:

Because this operates within nib2cib, all xibs should be re-converted.
2013-03-15 10:00:12 -04:00
cacaodevandAparajita Fishman 33858cfc3b Fixed: incorrect table column highlighting and row selection after column sort.
Previously in CPTableView, after clicking a sortable column, data views of the sorted column ended up in a selected state and a row was selected instead of the sorted column. As a result, the text of the rows would turn white as if they were selected, but there was no highlight, so the text was basically invisible.

This commit fixes that by reversing the order of operations when clicking a column. First the sort is done, then the selection.

Fixes #1337, #1688, #1779.
2013-03-15 08:26:37 -04:00
cacaodevandAparajita Fishman 7225e7e038 New: deprecate -tableView:dataViewForTableColumn:row: and -outlineView:dataViewForTableColumn:item:
-tableView:dataViewForTableColumn:row: and -outlineView:dataViewForTableColumn:item: are deprecated in favor of ...viewForTableColumn:...

Using the previous delegate API and not caching the view with an identifier was degrading performance. With this change, developers are encouraged to use the new caching system and the CPTableView method -makeViewWithIdentifier:owner: to get the view.

Also fixed a condition where a view-based outline view was not always asking for the view from its delegate. In some circumstances, an outline view could be considered as view-based instead of cell-based.

Test for deprecated delegate methods in CPOutlineViewViewBasedCib and TableTest/ViewBased examples.

Fixes #1823
2013-03-15 08:16:02 -04:00
Aparajita Fishman d25ff21030 Fixed: _CPThemeAttribute _parentAttribute had confusing name
Previously _CPThemeAttribute had an ivar called _parentAttribute, which represented the attribute from the theme descriptor, as opposed to the attribute for a particular instance of a view.

This commit renames that ivar to _themeDefaultAttribute, so it is clearer where it gets its values.
2013-03-14 23:57:39 -04:00
Aparajita Fishman 8055808235 Fixed: table view cells with custom font/color did not change properly when selected
Previously, if a cell-based table had a custom font or color in a table cell, when the cell was selected it would not change color. Also, edited cells did not maintain the original font/color.

This commit ensures that table cells uses the theme setting for selected text color, while maintaining all font and color attributes when selected or being edited.

BREAKING CHANGE:

Because this fix operates at the level of nib2cib, xibs that use customized cell-based table text cells should be reconverted.
2013-03-14 23:51:59 -04:00
Aparajita Fishman 9827f19c63 Fixed: selected table used bold font, text was fixed size
It used to be part of the theme to make the text in selected table rows bold. I never quite understood that, it really isn't necessary visually. Cocoa doesn't do it, I don't know of any toolkit that does.

Also, fixed sizes were used for text field theme fonts, which did not allow them to track runtime changes to the system font size.

This commit makes selected table row text plain, so selecting a row does not change the metrics of the text, just changes the color, which is much more pleasing visually.

Also, the special CPFontCurrentSystemSize constant, which tracks the actual font size at runtime, is used for text field font sizes.
2013-03-14 23:51:54 -04:00
Aparajita Fishman edb1a68952 Formatting 2013-03-14 23:49:14 -04:00
Aparajita Fishman 6dc9aa815a Fixed: eliminated duplicate CPThemeStateSelectedTableDataView state
CPThemeStateSelectedTableDataView and CPThemeStateSelectedDataView were the same, and were not used in any consistent or meaningful way.

This commit eliminates CPThemeStateSelectedTableDataView, only CPThemeStateSelectedDataView is used now.
2013-03-14 17:06:23 -04:00
Aparajita Fishman bf36c40f88 Fixed: optimized selector creation
Use @selector, that happens at compile time, instead of CPSelectorFromString, which happens at runtime.
2013-03-14 17:06:23 -04:00
Antoine Mercadal 099da1b071 Merge branch 'pr-1858' 2013-03-14 13:54:12 -07:00
Alexander LjungbergandAntoine Mercadal cd620b0c5a Fixed: more precise array controller insert index test.
Refs #1856.
2013-03-14 13:49:42 -07:00
Blair DuncanandAntoine Mercadal 21de08506c added in the xib that I modified for testing. 2013-03-14 13:49:42 -07:00
Blair DuncanandAntoine Mercadal 009ae1e14c Fixed ArrayController failed to recognize row 0 as the insert location
The logic is wrong in the test for last selection since it can be 0
and if there is no selection, [_selectionIndexes lastIndex] returns -1

Fixes #1723
2013-03-14 13:49:42 -07:00
cacaodev c8b812bbb5 FIXED: A data view edited in a table view was duplicated after a reload.
Previously in CPTableTView, a view being edited was not cached when unloaded, for example when made invisible after scrolling or when calling -reloadData.
This situation was causing a duplicated view to be added at the same place when the data view was loaded again.
After this commit, edited data views are cached and resign their first responder status just before they are added to the queue because they can be reused at another place.

Test: Added a "reload data" button in ViewBasedCib example.
2013-03-14 19:28:45 +01:00
Alexander Ljungberg be2234113b Fixed: more precise array controller insert index test.
Refs #1856.
2013-03-14 17:32:08 +00:00
Alexander Ljungberg 4dd4d17ef9 Merge pull request #1856 from BlairDuncan/arrayControllerFixFor1723
Fixed ArrayController failed to recognize row 0 as the insert location
2013-03-14 17:25:07 +00:00
Blair Duncan cac0555c43 added in the xib that I modified for testing. 2013-03-14 12:43:50 -04:00
Blair Duncan 35dd35d821 Fixed ArrayController failed to recognize row 0 as the insert location
The logic is wrong in the test for last selection since it can be 0
and if there is no selection, [_selectionIndexes lastIndex] returns -1

Fixes #1723
2013-03-14 12:33:17 -04:00
Aparajita Fishman 03b663463d Fixed: couldn't set the first responder of a sheet
Previously the sheet was made key at the beginning of the animation. It turns out events would not reliably make it to the sheet during animation. The other problem is that if a text field was the first responder, at the beginning of the animation it is offscreen, which means it refuses first responder and sets the first responder to nil.

Now we no longer try to make the sheet key before the animation ends, avoiding the text field problem.
2013-03-14 00:30:37 -04:00
Aparajita Fishman 9a28beb6b5 Fixed: makeFirstResponder didn't work for token fields
A change had been made to CPTextField _becomeFirstKeyResponder that wasn't propagated to CPTokenField.
2013-03-13 19:46:43 -04:00
Aparajita Fishman dc96b3862b Fixed: popovers were not constrained to the usable content frame
Previously, popovers did not properly stay below the menu bar.

This commit ensures they stay within whatever is the usable content frame for the platform window.
2013-03-13 17:00:54 -04:00
Aparajita Fishman facd97c09d Fixed: if orderOut: was not called for a popover, it would not detach from its parent
When a transient popover was closed by clicking, in some cases it would not detach from its parent, leaving it in the window list. This caused problems later on.

This commit ensures the popover is detached from its parent when it is ordered out.
2013-03-13 16:39:14 -04:00
Aparajita Fishman 3696986a5c Fixed: removed stray #import.
Build was failing on Linux because of it.
2013-03-13 15:36:41 -04:00
Aparajita Fishman 1e98c66b3c Fixed: under some circumstances, blur function could be called with no CPTextFieldInputOwner set
This would cause a crash because the blur function was trying to access the DOM element.

Now we check if the owner is null.
2013-03-13 15:32:54 -04:00
Aparajita Fishman 7df34cc709 Fixed: windows with sheets were filtering mouse move events.
Previously, if a window had a sheet, a mouse move event was passed to the sheet and then filtered. This disabled resize cursors for the parent window of a sheet.

This commit allows mouse move events to continue to the parent window so that resize cursors will work on the parent window as well.
2013-03-13 15:09:02 -04:00
Aparajita Fishman 3301754af2 Fixed: a sheet's parent window did not become main
Sheets are like child windows, they can never become main. Previously, when an attempt was made to make a sheet the main window, its parent window did not become main as it should have. Thus the title bar would remain dimmed, even though the sheet was the key window.

With this commit, when a sheet is made main, it defers to the parent window.
2013-03-13 15:04:34 -04:00
Aparajita Fishman 25d5441444 Fixed: sheet opening animation was not cleaned up when sheet immediately closed
Previously, if an event occurred during the sheet opening animation that would close the sheet, the animation was not properly cleaned up and the subsequent closing animation would die horribly.

The animation is always cleaned up with this commit.
2013-03-13 14:52:45 -04:00
Aparajita Fishman 07d35d606c Fixed: resize masks for a few views in AttachedSheet2 demo were not set
Previously they floated, now they are anchored.
2013-03-13 14:50:07 -04:00
Aparajita Fishman 2dd7ba6e28 Fixed: sheet top shadow would not adjust when parent window was resized
It is possible to resize the parent window of a sheet while it is open. Previously, the sheet's top shadow was not adjusted when the parent window was resized, which could lead to it being out of synch.

Now the sheet shadow is adjusted whenever the parent window's size changes.
2013-03-13 12:47:14 -04:00
Aparajita Fishman 92fb9eade5 Fixed: if a sheet's parent window frame was changed, the sheet did not reposition
Previously, sheets were only repositioned if the parent window's setFrameOrigin: method was called. This did not cover all possible cases for parent window repositioning.

Now the sheet is repositioned any time the parent window's origin changes.
2013-03-13 12:37:46 -04:00
Aparajita Fishman 2f4b0f8563 Formatting 2013-03-13 12:36:04 -04:00
Aparajita Fishman afd5925499 Fixed: _CG and _CP macros were confusing and could degrade performance
Previously, Cappuccino was using preprocessor macros internally for the CGPoint/Size/Rect/Inset/Affine functions, as well as for CPRange. These macros had the same name as the corresponding function, but began with _. The functions were actually defined using the macros.

The motivation behind using macros was to increase performance by reducing function calls. However, there were a number of problems with this approach:

- There was an artificial dichotomy between _CG macros and the corresponding CG functions. We never completely replaced CG function calls with _CG macros. In fact, they were often mixed up in the same file. There was an extra burden on the programmer to remember to use the macro instead of the function.
- If a method call was passed as an argument to a macro, performance could actually be significantly *worse* than a function call. For example, _CGGetRectMakeCopy([view frame]) would expand to `{ origin:{ x:[view frame].origin.x, y:[view frame].origin.y }, size:{ width:[view frame].size.width, height:[view frame].size.height } }`. So instead of a single objj_msgSend and a single simple function call, we ended up with 4 objj_msgSend calls, which are way more expensive than simple function calls.
- Because of this expansion problem, to use macros efficiently required us to remember to use variables for all macro parameters. This didn't happen, and shouldn't have to happen.
- Finally, with modern Javascript engines, function call overhead is so small that it really isn't worth using the macros.

This commit eliminates the _CGGeometry, CGAffineTransformation and CPRange macros and replaces them with function calls.

BREAKING CHANGE:
The macros are no longer available. They could only be used with compiled code, but if there is any user code that used them, they will have to be replaced with the corresponding functions.
2013-03-13 12:22:10 -04:00
Aparajita Fishman 10b588a19c Fixed: CPGraphicsTest window wouldn't fit in 15" screen
I'm happy for those who have 27" screens, but on my poor MPB 15" screen, the CPGraphicsTest window was too tall to see everything.

I split the window into two windows so everything can be seen.
2013-03-13 12:05:54 -04:00
Aparajita Fishman 843e5016e5 Fixed: modal sheet would appear briefly before animation
The AttachedSheet2 demo was calling runModalForWindow:, which caused the sheet to appear briefly as an application modal.

That call was removed, beginSheet: does everything.

Also:

- Wrapped _attachSheetWindow method into _attachSheet:modalDelegate: method.
- Just to be safe, in CPWindow -_sheetShouldAnimateIn:, the sheet is moved offscreen before being ordered front.
2013-03-13 11:51:27 -04:00
Alexander Ljungberg 8d54c0123b Fixed: menus not closing on left click.
Previously, clicking outside a menu on a control would not close the menu. Also clicking on the menu header again would open a second menu.

This error was caused by the control receiving the click and starting its own tracking, depriving the menu of the mouse up event it was awaiting.

The behaviour to wait for the mouse up was wrong to begin with. Menus should close on mouse down.

This fix closes the menu on left mouse down anywhere but the menu, while still allowing the click to pass through to any control underneath the cursor.

Fixes #1833.
2013-03-13 14:01:08 +00:00
Alexander Ljungberg 677124da49 Fixed: another tab view decoding error.
Without this fix, CPTabView would still make view hierarchy changes in `initWithCoder:` despite the fix in f805b6b. Making view hierarchy changes before a cib is fully decoded can easily result in a corrupted hierarchy.

In this case, the decoding of a tab view item view, A, lead to the decoder to try to decode A's next responder, which was the tab view, B. B then tried to set the selected tab, which involved adding A as a subview. But since A wasn't done decoding, A._superview would change later in the process, corrupting this change.

This fix delays `_updateItems` to `awakeFromCib` at which time changing the view hierarchy is safe.

Refs #1409.
2013-03-13 12:41:47 +00:00
Aparajita Fishman 50ca0d4b34 Fixed: menubar title was set to document title.
Currently, if a window controller has a document, its title is put in menubar. I cannot remember any Cocoa application that ever did this.

This commit removes the synchronizing of the document title with the menubar title.
2013-03-13 00:27:39 -04:00
Aparajita Fishman 54bc851159 Fixed: missing theme image, window sizing/moving was broken.
After bbfaac5, all kinds of strange behavior occurred with window sizing and moving due to overzealous constraining.

Cocoa does not constrain the frame of hidden windows. When a hidden window is ordered in, it is constrained to the usable screen content rect. A visible window has its height constrained when its frame is set. Its origin is constrained such that a minimum margin at the left, right and top is visible, and the top is constrained to be below the menu bar.

This commit fixes a number of problems related to window moving and resizing that were introduced by bbfaac5:

- Sheets are not constrained at all.
- Moving a window does not constrain its size.

In addition, when a window is moved, tracking is relative to the initial click point, which provides proper behavior when the movement is constrained and the mouse keeps moving.
2013-03-12 21:49:15 -04:00
Aparajita Fishman 481f7c61b8 Fixed: browser would scroll text fields into view when they focused.
Previously, there were two instances in which a browser would forcibly scroll a text field into view, out of Cappuccino's control:

- A text field is first responder in the key window, is partially or fully offscreen, and you click somewhere else within the same window. If the target of the click does not accept first responder, the text field is refocused.

- A text field is first responder in a non-key window, is partially or fully offscreen, and you make its window the key window. In that case the text field is made first responder and is focused.

In both cases, focusing the text field causes the browser to scroll the viewport out of Cappuccino's control such that the text field is completely onscreen.

With this commit, before a text field is focused, it is checked to ensure it is completely within the usable content rect of the platform window. If not, it refuses first responder. If the window is becoming key, the first responder is set to nil.
2013-03-12 21:19:09 -04:00
Aparajita Fishman 69bda9427a Fixed: some window subclasses should not be constrained to the usable screen content
Previously, all window subclasses were constrained to the usable screen content. Unfortunately that included the menu bar window, which ended up appearing below itself!

This commit introduces an ivar that indicates whether instances of the window subclass should be constrained or not.
2013-03-12 15:00:26 -04:00
Aparajita Fishman bbfaac5468 Fixed: windows were allowed to extend beyond the usable screen content.
Previously, no bounds were placed on the placement or sizing of windows, which allowed them to extend beyond the usable screen content (the area bounded by the menu bar at the top and the platform window on the other sides).

Cocoa enforces the following restrictions:

- When a window is ordered in, it is forced within the usable screen content (below the menu bar) and its size and width are clipped to the usable screen content as well.

- If a window is already visible, any methods that move or resize the window will ensure the top and bottom of the window are within the usable screen content. The width is unchanged.

This commit implements Cocoa's restrictions in CPWindow.

Fixes #1690
2013-03-12 13:49:42 -04:00
Alexander Ljungberg d15550cacb Merge branch 'refs/heads/slevenbits-platform-resize-fix' 2013-03-12 17:03:33 +00:00
Alexander Ljungberg 784eed9b1a Merge branch 'refs/heads/slevenbits-autocomplete-modal-fix' 2013-03-12 17:03:24 +00:00
Alexander Ljungberg 7b11411b61 Merge branch 'refs/heads/slevenbits-popover-override-modality-fix' 2013-03-12 17:03:13 +00:00
Alexander Ljungberg 921b30a892 Merge branch 'refs/heads/slevenbits-popover-child-window-close-fix' 2013-03-12 17:02:57 +00:00
Alexander Ljungberg baa75a8b64 Merge branch 'master' of github.com:cappuccino/cappuccino 2013-03-12 16:56:23 +00:00
aparajita fd49bd2f2d Update CONTRIBUTING.md
Updated commit message section.
2013-03-12 13:40:18 -03:00
Aparajita Fishman 445045565b Fixed: frame/bounds change notification was sent unconditionally.
Previously, calling setPostsFrameChangedNotifications:YES or setPostsBoundsChangedNotifications:YES would immediately result in the notification being sent. Cocoa will only send in this context if:

- setPosts[Frame/Bounds]ChangedNotifications:NO was called.
- The frame/bounds changed between that call and the call to setPosts[Frame/Bounds]ChangedNotifications:YES.

We are currently not tracking pending changes, so this commit removes the sending of the notification completely in those methods.

Fixes #1076
2013-03-12 12:20:58 -04:00
Andrew HankinsonandAparajita Fishman 6c80d1f883 Fixed: resizeWithOldSuperviewSize did not maintain size ratio
Previously, Cappuccino would resize in such a way that a view's size ratio to its superview would not be maintained.

This commit ensures that size ratios are maintained during resizing.

Patch contributed by @davidkhess

Fixes #357
2013-03-12 11:38:09 -04:00
Aparajita Fishman 3af2314a70 Fixed: sheet resizing displayed incorrectly
Previously, when a sheet was resized, there were a number of problems:

- Sheets in Cocoa resize their width symmetrically, such that they always remain centered. This was not happening in Cappuccino.

- When a sheet is resized wider than its parent window, the shadow at the top of the sheet was growing wider than the bounds of the parent window's title bar, which makes no sense since the shadow is supposed to be cast by the title bar.

- Sheets had no top border, so when they were resized wider than the parent window, the top edge looked like it was cut off. In Cocoa, sheets have a top border that sits under the title bar of the parent window, and which is visible when the sheet is resized wider than the parent window.

This commit addresses these problems as follows:

- Sheet width is now resized symmetrically.

- Sheet resizing is pinned to the screen bounds.

- The top sheet shadow is pinned to the width of the parent window's content view.

- Sheets now have a top border.

In addition to these changes, a redundant sheet top shadow was eliminated from one of the _CPWindowView subclasses.

Fixes #1846
2013-03-12 10:20:14 -04:00
Aparajita Fishman 17f9304adc Fixed: sheet animation was resizing the sheet to zero, causing problems
Previously sheet animation was performed by sizing the sheet from zero to full height when animating in, and then back to zero height when animating out. This caused problems with the resize algorithms, which are not designed to deal with sizing from zero.

Analyzing Cocoa behavior revealed that sheets slide in and out with no resizing.

With this commit, a general purpose mechanism for clipping a window to a rect was added to CPDOMWindowLayer. Clipping was put in CPDOMWindowLayer because that is the class that deals with windows at the global level. CPWindow uses the clipping mechanism to slide the sheet in and out, thus avoiding all resizing problems.

Fixes #1840
2013-03-12 10:20:13 -04:00
Aparajita Fishman f208ff52fd Fixed: attached sheet shadow had extra width, was too dark
Previously the attached sheet shadow (that appears below the title bar of the window a sheet is attached to) was 9x8, and it was quite dark.

With this commit the width has been reduced to 1 (to reduce the image size) and it has been lightened up.

Also changed "height-shadow" theme attribute to "shadow-height".
2013-03-12 10:20:13 -04:00
Aparajita Fishman 2dca00c4a0 Fixed: sheets should not be resizable from the top
Previously, sheets could be resized from the top, which would destroy the illusion of being attached to the top of the parent window.

With this commit, sheets are prevented from being resized by the user from the top edge.
2013-03-12 10:20:13 -04:00
aparajita 1443fff315 Merge pull request #1811 from stewa/fix-menu-custom-views-reverse-mouse-event
Fixed: mouseEntered and mouseExited mixed up for custom views in menu

Previously, when clicking and dragging inside a menu, mouseEntered and mouseExited were sent to the wrong views.

This commit correctly sends mouseExited to the previous hovered view, then mouseEntered to the new hovered view.
2013-03-12 07:16:02 -07:00
aparajita 96605826ba Merge pull request #1842 from stewa/empty-collectionview-keyboard-navigation-problem
Fixed: using keyboard navigation in empty CPCollectionView threw exception

Previously, if an empty CPCollectionView was first responder and keyboard navigation was used, a CPInvalidArgumentException (Range {-1, 1} is out of bounds) was thrown.

This commit checks for an empty collection, eliminating the exception.
2013-03-12 07:01:53 -07:00
Martin Carlberg 22cdbd7ec7 Merge branch 'master' of https://github.com/cappuccino/cappuccino into preprocess
Conflicts:
	Objective-J/ObjJAcornCompiler.js
	Objective-J/acorn.js
2013-03-12 11:20:56 +01:00
Martin Carlberg 362f3b890e Added first try for compiler to generate code 2013-03-12 09:22:26 +01:00
aparajita da69a6e339 Merge pull request #1845 from cacaodev/CPCollectionView-doc
Docs: CPCollectionView-setItemPrototype: method documentation
2013-03-11 21:20:14 -07:00
Stefan Wallström a549c191da lint 2013-03-11 21:09:22 +01:00
Antoine Mercadal 26213491a3 Revert "don't allow views from another window to be next/previouskeyViews"
This reverts commit 7fab8d9782.

This breaks the repsonder chain if it is defined in a view that has no window yet.
Details and reduction here: https://github.com/cappuccino/cappuccino/commit/7fab8d9782d4604c4441e48701f9207e4a2b4229#commitcomment-2781849
2013-03-11 13:01:22 -07:00
cacaodev 0d168a4518 Remove //@class CPClipView 2013-03-11 17:52:21 +01:00
cacaodev 0e4f5e9203 Uncomment import 2013-03-11 17:14:00 +01:00
aparajita bbc7d2f29e Merge pull request #1848 from ahankinson/cptableview-documentation-formatting
Formatting: various CPTableView fixes
2013-03-11 09:08:46 -07:00
cacaodev a98def4326 Added doc for -setItemPrototype: explaining how to setup the item prototype when you want to use bindings for the view. 2013-03-11 16:49:19 +01:00
Andrew Hankinson b274c63395 CPTableView formatting
Formatting, whitespace and typo correction.
2013-03-11 10:01:46 -04:00
Stefan Wallström 2bf2442096 Fixed: Using keyboard navigation in empty CPCollectionView threw exception. 2013-03-10 17:38:08 +01:00
Christophe Serafin ef4ba78ab7 removed extra blank and added a blank line above if condition 2013-03-10 17:05:53 +01:00
Christophe Serafin 85cb1b7a76 removed an extra blank and changed _shouldReorderColumn format 2013-03-10 17:04:45 +01:00
Christophe Serafin fe260a85f5 added _lastDragDestinationColumnIndex to call delegate method only once 2013-03-10 16:41:37 +01:00
Christophe Serafin 159941696d changed condition order for optimization 2013-03-08 19:35:10 +01:00
Christophe Serafin 152fd66bbe fixed reordering column with a restriction on a targeted column 2013-03-08 18:11:27 +01:00
Christophe Serafin ae4c77a6d4 Merge branch 'master' of https://github.com/cappuccino/cappuccino 2013-03-08 16:53:07 +01:00
Christophe Serafin 77d2ebbda0 adds shouldReorderColumn to CPTableView delegate methods 2013-03-01 11:57:24 +01:00
Stefan Wallström b7ff643a34 Fixed: when clicking and dragging inside a menu, mouseEntered and mouseExited was mixed up for custom views. 2013-02-27 22:26:52 +01:00
Martin Carlberg c17053f71a Removed test line 2013-02-26 08:53:12 +01:00
Martin Carlberg e8e87b3b83 Added recursive token transformer and preprocessor tokenizer 2013-02-24 22:26:27 +01:00
Martin Carlberg 340f1e3258 Made the acorn parser able to run outside of the Cappuccino world 2013-02-24 22:25:00 +01:00
Martin Carlberg 529e703ddd Merge branch 'master' of https://github.com/cappuccino/cappuccino into objj_compiler2 2013-02-24 15:45:56 +01:00
Martin Carlberg 699ef14b4e Merge with latest acorn compiler 2013-02-21 12:57:19 +01:00
Martin Carlberg 8c68854d1d Fixed local variable that is declared as a global 2013-02-19 20:25:57 +01:00
Martin Carlberg 64a38a2aef Refactored how maybe warnings is handled and prepared for new "local variable hides global variable" warning. The warning is disabled because there are to many warning in the Cappuccino frameworks right now. 2013-02-19 20:22:42 +01:00
Martin Carlberg cccfe7268b Fixed better comment 2013-02-19 17:48:16 +01:00
Martin Carlberg c03697c0a6 Fixed support for IE8 2013-02-19 17:47:34 +01:00
Martin Carlberg 32bf87c0c3 Fixed typo 2013-02-19 17:46:24 +01:00
642 changed files with 50370 additions and 13191 deletions
+2
View File
@@ -11,5 +11,7 @@ xcuserdata/
!*.xcodeproj/project.pbxproj
*.xCodeSupport/
*.XcodeSupport/
*XcodeSupport/
Tests/Manual/**/*.xcodeproj
*.sublime-project
*.sublime-workspace
+1
View File
@@ -55,6 +55,7 @@
@import "CPController.j"
@import "CPCookie.j"
@import "CPCursor.j"
@import "CPDatePicker.j"
@import "CPDocument.j"
@import "CPDocumentController.j"
@import "CPEvent.j"
+14 -14
View File
@@ -106,7 +106,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
_itemViews = [];
_expandedItemIndexes = [CPIndexSet indexSet];
[self setItemHeaderPrototype:[[CPButton alloc] initWithFrame:_CGRectMake(0.0, 0.0, 100.0, 24.0)]];
[self setItemHeaderPrototype:[[CPButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 24.0)]];
}
return self;
@@ -258,18 +258,18 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
- (void)setFrameSize:(CGSize)aSize
{
var width = _CGRectGetWidth([self frame]);
var width = CGRectGetWidth([self frame]);
[super setFrameSize:aSize];
if (width !== _CGRectGetWidth([self frame]))
if (width !== CGRectGetWidth([self frame]))
[self _invalidateItemsStartingAtIndex:0];
}
- (void)layoutSubviews
{
if (_items.length <= 0)
return [self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), 0.0)];
return [self setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), 0.0)];
if (_dirtyItemIndex === CPNotFound)
return;
@@ -278,7 +278,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
var index = _dirtyItemIndex,
count = _itemViews.length,
width = _CGRectGetWidth([self bounds]),
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.
@@ -293,7 +293,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
y = CGRectGetMaxY([itemView frame]);
}
[self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), y)];
[self setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), y)];
}
@end
@@ -310,7 +310,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
- (id)initWithAccordionView:(CPAccordionView)anAccordionView
{
self = [super initWithFrame:_CGRectMakeZero()];
self = [super initWithFrame:CGRectMakeZero()];
if (self)
{
@@ -376,21 +376,21 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
- (void)setFrameY:(float)aY width:(float)aWidth
{
var headerHeight = _CGRectGetHeight([_headerView frame]);
var headerHeight = CGRectGetHeight([_headerView frame]);
// Size to fit or something?
[_headerView setFrameSize:_CGSizeMake(aWidth, headerHeight)];
[_contentView setFrameOrigin:_CGPointMake(0.0, headerHeight)];
[_headerView setFrameSize:CGSizeMake(aWidth, headerHeight)];
[_contentView setFrameOrigin:CGPointMake(0.0, headerHeight)];
if ([self isCollapsed])
[self setFrame:_CGRectMake(0.0, aY, aWidth, headerHeight)];
[self setFrame:CGRectMake(0.0, aY, aWidth, headerHeight)];
else
{
var contentHeight = _CGRectGetHeight([_contentView frame]);
var contentHeight = CGRectGetHeight([_contentView frame]);
[_contentView setFrameSize:_CGSizeMake(aWidth, contentHeight)];
[self setFrame:_CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)];
[_contentView setFrameSize:CGSizeMake(aWidth, contentHeight)];
[self setFrame:CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)];
}
}
+66 -24
View File
@@ -96,7 +96,8 @@ var bottomHeight = 71;
id _delegate @accessors(property=delegate);
id _modalDelegate;
SEL _didEndSelector;
SEL _didEndSelector @accessors(property=didEndSelector);
Function _didEndBlock;
_CPAlertThemeView _themeView @accessors(property=themeView, readonly);
CPWindow _window @accessors(property=window, readonly);
@@ -224,16 +225,15 @@ var bottomHeight = 71;
}
/*! @deprecated
*/
- (void)setWindowStyle:(int)aStyle
/*! @deprecated */
- (void)setWindowStyle:(int)style
{
CPLog.warn("DEPRECATED: setWindowStyle: is deprecated. use setTheme: instead");
[self setTheme:(aStyle === CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]];
[self setTheme:(style === CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]];
}
/*! @deprecated
*/
/*! @deprecated */
- (int)windowStyle
{
CPLog.warn("DEPRECATED: windowStyle: is deprecated. use theme instead");
@@ -242,18 +242,19 @@ var bottomHeight = 71;
/*!
set the text of the alert's message
Set the text of the alert's message.
@param aText CPString containing the text
*/
- (void)setMessageText:(CPString)aText
- (void)setMessageText:(CPString)text
{
[_messageLabel setStringValue:aText];
[_messageLabel setStringValue:text];
_needsLayout = YES;
}
/*!
return the content of the message text
Return the content of the message text.
@return CPString containing the message text
*/
- (CPString)messageText
@@ -262,13 +263,13 @@ var bottomHeight = 71;
}
/*!
set the text of the alert's informative text
Set the text of the alert's informative text.
@param aText CPString containing the informative text
*/
- (void)setInformativeText:(CPString)aText
- (void)setInformativeText:(CPString)text
{
[_informativeLabel setStringValue:aText];
[_informativeLabel setStringValue:text];
_needsLayout = YES;
}
@@ -285,6 +286,7 @@ var bottomHeight = 71;
/*!
Sets the title of the alert window.
This API is not present in Cocoa.
@param aTitle CPString containing the window title
*/
- (void)setTitle:(CPString)aTitle
@@ -294,7 +296,7 @@ var bottomHeight = 71;
}
/*!
set the accessory view
Set the accessory view.
@param aView the accessory view
*/
@@ -305,7 +307,7 @@ var bottomHeight = 71;
}
/*!
set if alert shows the suppression button
Set if the alert shows the suppression button.
@param shouldShowSuppressionButton YES or NO
*/
@@ -596,6 +598,17 @@ var bottomHeight = 71;
[CPApp runModalForWindow:_window];
}
/*!
The same as \c runModal, but executes the code in \c block when the
alert is dismissed.
*/
- (void)runModalWithDidEndBlock:(Function /*(CPAlert alert, int returnCode)*/)block
{
_didEndBlock = block;
[self runModal];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
@@ -630,6 +643,20 @@ var bottomHeight = 71;
[self beginSheetModalForWindow:aWindow modalDelegate:nil didEndSelector:nil contextInfo:nil];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
Executes the code in \c block when the alert is dismissed.
@param window The parent window for the sheet.
@param block Code block to execute on dismissal
*/
- (void)beginSheetModalForWindow:(CPWindow)aWindow didEndBlock:(Function /*(CPAlert alert, int returnCode)*/)block
{
_didEndBlock = block;
[self beginSheetModalForWindow:aWindow modalDelegate:nil didEndSelector:nil contextInfo:nil];
}
#pragma mark Private
/*!
@@ -642,6 +669,7 @@ var bottomHeight = 71;
_window = [[CPPanel alloc] initWithContentRect:frame styleMask:forceStyle || _defaultWindowStyle];
[_window setLevel:CPStatusWindowLevel];
[_window setPlatformWindow:[[CPApp keyWindow] platformWindow]];
if (_title)
[_window setTitle:_title];
@@ -696,14 +724,28 @@ var bottomHeight = 71;
*/
- (void)_alertDidEnd:(CPWindow)aWindow returnCode:(int)returnCode contextInfo:(id)contextInfo
{
if (_didEndSelector)
objj_msgSend(_modalDelegate, _didEndSelector, self, returnCode, contextInfo);
if (_didEndBlock)
{
if (typeof(_didEndBlock) === "function")
_didEndBlock(self, returnCode);
else
CPLog.warn("%s: didEnd block is not a function", [self description]);
_modalDelegate = nil;
_didEndSelector = nil;
if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:returnCode];
// didEnd blocks are transient
_didEndBlock = nil;
}
else if (_modalDelegate)
{
if (_didEndSelector)
objj_msgSend(_modalDelegate, _didEndSelector, self, returnCode, contextInfo);
}
else if (_delegate)
{
if (_didEndSelector)
objj_msgSend(_delegate, _didEndSelector, self, returnCode);
else if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:returnCode];
}
}
@end
@@ -715,7 +757,7 @@ var bottomHeight = 71;
return @"alert";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"size": CGSizeMake(400.0, 110.0),
+3 -1
View File
@@ -236,7 +236,9 @@ ACTUAL_FRAME_RATE = 0;
ACTUAL_FRAME_RATE = 0;
_lastTime = new Date();
_timer = [CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(animationTimerDidFire:) userInfo:nil repeats:YES];
var timerInterval = _frameRate <= 0.0 ? 0.0001 : 1.0/_frameRate;
_timer = [CPTimer scheduledTimerWithTimeInterval:timerInterval target:self selector:@selector(animationTimerDidFire:) userInfo:nil repeats:YES];
}
/*
+44 -82
View File
@@ -20,10 +20,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "../Foundation/CPRange.h"
@import <Foundation/CPBundle.j>
@import "CPApplication_Constants.j"
@import "CPCompatibility.j"
@import "CPColorPanel.j"
@import "CPCursor.j"
@@ -36,29 +35,12 @@
@import "CPPanel.j"
@import "CPPlatform.j"
@import "CPWindowController.j"
@import "_CPPopoverWindow.j"
var CPMainCibFile = @"CPMainCibFile",
CPMainCibFileHumanFriendly = @"Main cib file base name",
CPEventModifierFlags = 0;
CPApp = nil;
CPApplicationWillFinishLaunchingNotification = @"CPApplicationWillFinishLaunchingNotification";
CPApplicationDidFinishLaunchingNotification = @"CPApplicationDidFinishLaunchingNotification";
CPApplicationWillTerminateNotification = @"CPApplicationWillTerminateNotification";
CPApplicationWillBecomeActiveNotification = @"CPApplicationWillBecomeActiveNotification";
CPApplicationDidBecomeActiveNotification = @"CPApplicationDidBecomeActiveNotification";
CPApplicationWillResignActiveNotification = @"CPApplicationWillResignActiveNotification";
CPApplicationDidResignActiveNotification = @"CPApplicationDidResignActiveNotification";
CPTerminateNow = YES;
CPTerminateCancel = NO;
CPTerminateLater = -1; // not currently supported
CPRunStoppedResponse = -1000;
CPRunAbortedResponse = -1001;
CPRunContinuesResponse = -1002;
/*!
@ingroup appkit
@class CPApplication
@@ -175,7 +157,8 @@ CPRunContinuesResponse = -1002;
CPApplicationDidBecomeActiveNotification, @selector(applicationDidBecomeActive:),
CPApplicationWillResignActiveNotification, @selector(applicationWillResignActive:),
CPApplicationDidResignActiveNotification, @selector(applicationDidResignActive:),
CPApplicationWillTerminateNotification, @selector(applicationWillTerminate:)
CPApplicationWillTerminateNotification, @selector(applicationWillTerminate:),
CPApplicationDidChangeScreenParametersNotification, @selector(applicationDidChangeScreenParameters:)
],
count = [delegateNotifications count];
@@ -373,22 +356,32 @@ CPRunContinuesResponse = -1002;
applicationVersion = [options objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"],
copyright = [options objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"];
var aboutPanelPath = [[CPBundle bundleForClass:[CPWindowController class]] pathForResource:@"AboutPanel.cib"],
aboutPanelController = [CPWindowController alloc],
aboutPanelController = [aboutPanelController initWithWindowCibPath:aboutPanelPath owner:aboutPanelController],
aboutPanel = [aboutPanelController window],
contentView = [aboutPanel contentView],
imageView = [contentView viewWithTag:1],
applicationLabel = [contentView viewWithTag:2],
versionLabel = [contentView viewWithTag:3],
copyrightLabel = [contentView viewWithTag:4],
standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"];
var windowWidth = 275,
windowHeight = 223,
imgWidth = 100,
imgHeight = 100,
interField = 8,
aboutPanel = [[CPWindow alloc] initWithContentRect:CGRectMake(0, 0, windowWidth, windowHeight) styleMask:CPClosableWindowMask],
imageView = [[CPImageView alloc] initWithFrame:CGRectMake((windowWidth / 2) - (imgWidth / 2), interField, imgWidth, imgHeight)],
applicationLabel = [[CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 16, windowWidth - 34, 24)],
versionLabel = [[CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 48, windowWidth - 34, 16)],
copyrightLabel = [[CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 72, windowWidth - 34, 32)],
contentView = [aboutPanel contentView];
// FIXME move this into the CIB eventually
[applicationLabel setFont:[CPFont boldSystemFontOfSize:[CPFont systemFontSize] + 2]];
[applicationLabel setAlignment:CPCenterTextAlignment];
[versionLabel setFont:[CPFont systemFontOfSize:[CPFont systemFontSize] - 1]];
[versionLabel setAlignment:CPCenterTextAlignment];
[copyrightLabel setFont:[CPFont systemFontOfSize:[CPFont systemFontSize] - 1]];
[copyrightLabel setAlignment:CPCenterTextAlignment];
[copyrightLabel setLineBreakMode:CPLineBreakByWordWrapping];
[contentView addSubview:imageView];
[contentView addSubview:applicationLabel];
[contentView addSubview:versionLabel];
[contentView addSubview:copyrightLabel];
var standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"];
[imageView setImage:applicationIcon || [[CPImage alloc] initWithContentsOfFile:standardPath
size:CGSizeMake(256, 256)]];
@@ -402,7 +395,7 @@ CPRunContinuesResponse = -1002;
else
[versionLabel setStringValue:@""];
[copyrightLabel setStringValue:copyright || ""];
[copyrightLabel setStringValue:copyright || @""];
[aboutPanel center];
_aboutPanel = aboutPanel;
@@ -578,8 +571,8 @@ CPRunContinuesResponse = -1002;
/* @ignore */
- (BOOL)_handleKeyEquivalent:(CPEvent)anEvent
{
return [[self keyWindow] performKeyEquivalent:anEvent] ||
[[self mainMenu] performKeyEquivalent:anEvent];
return [[self keyWindow] performKeyEquivalent:anEvent] ||
[[self mainMenu] performKeyEquivalent:anEvent];
}
/*!
@@ -593,33 +586,10 @@ CPRunContinuesResponse = -1002;
var theWindow = [anEvent window];
#if PLATFORM(DOM)
var willPropagate = [[theWindow platformWindow] _willPropagateCurrentDOMEvent];
// temporarily pretend we won't propagate the event. we'll restore the saved value later
// we do this outside the if so that changes user code might make in _handleKeyEquiv. are preserved
[[theWindow platformWindow] _propagateCurrentDOMEvent:NO];
#endif
// Check if this is a candidate for key equivalent...
if ([anEvent _couldBeKeyEquivalent] && [self _handleKeyEquivalent:anEvent])
{
#if PLATFORM(DOM)
var characters = [anEvent characters],
modifierFlags = [anEvent modifierFlags];
// Unconditionally propagate on these keys to solve browser copy paste bugs
if ((characters == "c" || characters == "x" || characters == "v") && (modifierFlags & CPPlatformActionKeyMask))
[[theWindow platformWindow] _propagateCurrentDOMEvent:YES];
#endif
// The key equivalent was handled.
return;
}
#if PLATFORM(DOM)
// if we make it this far, then restore the original willPropagate value
[[theWindow platformWindow] _propagateCurrentDOMEvent:willPropagate];
#endif
if ([anEvent type] == CPMouseMoved)
{
@@ -630,10 +600,10 @@ CPRunContinuesResponse = -1002;
}
/*
Event listeners are processed from back to front so that newer event listeners normally take
precedence. If during the execution of a callback a new event listener is added, it should
be inserted after the current callback but before any higher priority callbacks. This makes
repeating event listeners (those that reinsert themselves) stable relative to each other.
Event listeners are processed from back to front so that newer event listeners normally take
precedence. If during the execution of a callback a new event listener is added, it should
be inserted after the current callback but before any higher priority callbacks. This makes
repeating event listeners (those that reinsert themselves) stable relative to each other.
*/
for (var i = _eventListeners.length - 1; i >= 0; i--)
{
@@ -654,6 +624,7 @@ CPRunContinuesResponse = -1002;
}
}
}
_eventListenerInsertionIndex = _eventListeners.length;
if (theWindow)
@@ -706,7 +677,7 @@ CPRunContinuesResponse = -1002;
- (CPArray)windows
{
// Return all windows, but not the CPNull placeholder in _windows[0].
return [_windows subarrayWithRange:_CPMakeRange(1, [_windows count] - 1)];
return [_windows subarrayWithRange:CPMakeRange(1, [_windows count] - 1)];
}
/*!
@@ -989,10 +960,10 @@ CPRunContinuesResponse = -1002;
@param aSheet the window to display as a sheet
@param aWindow the window that will hold the sheet as a child
@param aModalDelegate
@param aDidEndSelector
@param aContextInfo
@param didEndSelector
@param contextInfo
*/
- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)didEndSelector contextInfo:(id)contextInfo
{
if ([aWindow isSheet])
{
@@ -1000,17 +971,8 @@ CPRunContinuesResponse = -1002;
return;
}
[aSheet._windowView _enableSheet:YES];
// -dw- if a sheet is already visible, we skip this since it serves no purpose and causes
// orderOut: to be called on the sheet, which is not what we want.
if (![aWindow isVisible])
{
[aWindow orderFront:self];
[aSheet setPlatformWindow:[aWindow platformWindow]];
}
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
[aSheet._windowView _enableSheet:YES inWindow:aWindow];
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:didEndSelector contextInfo:contextInfo];
}
/*!
@@ -1035,7 +997,7 @@ CPRunContinuesResponse = -1002;
var aWindow = [_windows objectAtIndex:count],
context = aWindow._sheetContext;
if (context != nil && context["sheet"] === sheet)
if (context && context["sheet"] === sheet)
{
context["returnCode"] = returnCode;
[aWindow _endSheet];
@@ -1380,8 +1342,8 @@ var _CPAppBootstrapperActions = nil;
if (mainCibFile)
{
[mainBundle loadCibFile:mainCibFile
externalNameTable:@{ CPCibOwner: CPApp }
loadDelegate:self];
externalNameTable:@{ CPCibOwner: CPApp }
loadDelegate:self];
return YES;
}
@@ -1458,7 +1420,7 @@ var _CPAppBootstrapperActions = nil;
+ (void)cibDidFailToLoad:(CPCib)aCib
{
throw new Error("Could not load main cib file (Did you forget to nib2cib it?).");
throw new Error("Could not load main cib file. Did you forget to nib2cib it?");
}
+ (void)reset
+40
View File
@@ -0,0 +1,40 @@
/*
* CPApplication_Constants.j
* AppKit
*
* Created by Aparajita Fishman.
* Copyright 2013 The Cappuccino Project
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
CPApp = nil;
CPApplicationWillFinishLaunchingNotification = @"CPApplicationWillFinishLaunchingNotification";
CPApplicationDidFinishLaunchingNotification = @"CPApplicationDidFinishLaunchingNotification";
CPApplicationWillTerminateNotification = @"CPApplicationWillTerminateNotification";
CPApplicationWillBecomeActiveNotification = @"CPApplicationWillBecomeActiveNotification";
CPApplicationDidBecomeActiveNotification = @"CPApplicationDidBecomeActiveNotification";
CPApplicationWillResignActiveNotification = @"CPApplicationWillResignActiveNotification";
CPApplicationDidResignActiveNotification = @"CPApplicationDidResignActiveNotification";
CPApplicationDidChangeScreenParametersNotification = @"CPApplicationDidChangeScreenParametersNotification";
CPTerminateNow = YES;
CPTerminateCancel = NO;
CPTerminateLater = -1; // not currently supported
CPRunStoppedResponse = -1000;
CPRunAbortedResponse = -1001;
CPRunContinuesResponse = -1002;
+27 -12
View File
@@ -65,51 +65,51 @@
+ (CPSet)keyPathsForValuesAffectingContentArray
{
return [CPSet setWithObjects:"content"];
return [CPSet setWithObjects:@"content"];
}
+ (CPSet)keyPathsForValuesAffectingArrangedObjects
{
// Also depends on "filterPredicate" but we'll handle that manually.
return [CPSet setWithObjects:"content", "sortDescriptors"];
return [CPSet setWithObjects:@"content", @"sortDescriptors"];
}
+ (CPSet)keyPathsForValuesAffectingSelection
{
return [CPSet setWithObjects:"selectionIndexes"];
return [CPSet setWithObjects:@"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingSelectionIndex
{
return [CPSet setWithObjects:"selectionIndexes"];
return [CPSet setWithObjects:@"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingSelectionIndexes
{
// When the arranged objects change, selection preservation may cause the indexes
// to change.
return [CPSet setWithObjects:"arrangedObjects"];
return [CPSet setWithObjects:@"arrangedObjects"];
}
+ (CPSet)keyPathsForValuesAffectingSelectedObjects
{
// Don't need to depend on arrangedObjects here because selectionIndexes already does.
return [CPSet setWithObjects:"selectionIndexes"];
return [CPSet setWithObjects:@"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanRemove
{
return [CPSet setWithObjects:"selectionIndexes"];
return [CPSet setWithObjects:@"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanSelectNext
{
return [CPSet setWithObjects:"selectionIndexes"];
return [CPSet setWithObjects:@"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanSelectPrevious
{
return [CPSet setWithObjects:"selectionIndexes"];
return [CPSet setWithObjects:@"selectionIndexes"];
}
@@ -744,6 +744,7 @@
return;
var willClearPredicate = NO;
if (_clearsFilterPredicateOnInsertion && _filterPredicate)
{
[self willChangeValueForKey:@"filterPredicate"];
@@ -792,10 +793,18 @@
// not appear in arrangedObjects and we do not have to update at all.
*/
// This will also send notificaitons for arrangedObjects.
// TODO: Remove these lines when granular notifications are implemented
var proxy = [_CPKVOProxy proxyForObject:self];
[proxy setAdding:YES];
// This will also send notifications for arrangedObjects.
[self didChangeValueForKey:@"content"];
if (willClearPredicate)
[self didChangeValueForKey:@"filterPredicate"];
// TODO: Remove this line when granular notifications are implemented
[proxy setAdding:NO];
}
/*!
@@ -811,6 +820,7 @@
return;
var willClearPredicate = NO;
if (_clearsFilterPredicateOnInsertion && _filterPredicate)
{
[self willChangeValueForKey:@"filterPredicate"];
@@ -848,9 +858,15 @@
if ([self avoidsEmptySelection] && [[self selectionIndexes] count] <= 0 && [_contentObject count] > 0)
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:0]];
var proxy = [_CPKVOProxy proxyForObject:self];
[proxy setAdding:YES];
[self didChangeValueForKey:@"content"];
if (willClearPredicate)
[self didChangeValueForKey:@"filterPredicate"];
[proxy setAdding:NO];
}
/*!
@@ -914,11 +930,10 @@
var newObject = [self automaticallyPreparesContent] ? [self newObject] : [self _defaultNewObject],
lastSelectedIndex = [_selectionIndexes lastIndex];
if (lastSelectedIndex)
if (lastSelectedIndex !== CPNotFound)
[self insertObject:newObject atArrangedObjectIndex:lastSelectedIndex];
else
[self addObject:newObject];
}
/*!
+45
View File
@@ -48,6 +48,8 @@ var DefaultLineWidth = 1.0;
{
CGPath _path;
float _lineWidth;
CPArray _lineDashes;
float _lineDashesPhase;
}
/*!
@@ -145,6 +147,8 @@ var DefaultLineWidth = 1.0;
{
_path = CGPathCreateMutable();
_lineWidth = [[self class] defaultLineWidth];
_lineDashesPhase = 0;
_lineDashes = [];
}
return self;
@@ -205,6 +209,7 @@ var DefaultLineWidth = 1.0;
CGContextBeginPath(ctx);
CGContextAddPath(ctx, _path);
CGContextSetLineWidth(ctx, [self lineWidth]);
CGContextSetLineDash(ctx, _lineDashesPhase, _lineDashes);
CGContextStrokePath(ctx);
}
@@ -218,10 +223,50 @@ var DefaultLineWidth = 1.0;
CGContextBeginPath(ctx);
CGContextAddPath(ctx, _path);
CGContextSetLineWidth(ctx, [self lineWidth]);
CGContextSetLineDash(ctx, _lineDashesPhase, _lineDashes);
CGContextClosePath(ctx);
CGContextFillPath(ctx);
}
/*!
Cocoa compatibility.
*/
- (void)getLineDash:(CPArrayRef)patternRef count:(NSInteger)count phase:(CGFloatRef)phaseRef
{
return [self getLineDash:patternRef phase:phaseRef];
}
/*!
Retrieve the line dash pattern and phase and write them into the provided references.
*/
- (void)getLineDash:(CPArrayRef)patternRef phase:(CGFloatRef)phaseRef
{
if (patternRef)
@deref(patternRef) = [_lineDashes copy];
if (phaseRef)
@deref(phaseRef) = _lineDashesPhase;
}
/*!
Cocoa compatibility.
*/
- (void)setLineDash:(CPArray)aPattern count:(NSInteger)count phase:(CGFloat)aPhase
{
[self setLineDash:aPattern phase:aPhase];
}
/*!
Set stroke line dash pattern.
@param aPattern an array of stroke-skip lengths such as [2, 2, 4, 4]
@param aPhase amount of shift for the starting position of the first stroke
*/
- (void)setLineDash:(CPArray)aPattern phase:(CGFloat)aPhase
{
_lineDashes = aPattern;
_lineDashesPhase = aPhase;
}
/*!
Get the line width.
*/
+7 -7
View File
@@ -76,7 +76,7 @@ CPBelowBottom = 6;
return @"box";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"background-color": [CPNull null],
@@ -444,9 +444,9 @@ CPBelowBottom = 6;
case CPBoxSeparator:
// NSBox does not include a horizontal flag for the separator type. We have to determine
// the type of separator to draw by the width and height of the frame.
if (_CGRectGetWidth(bounds) === 5.0)
if (CGRectGetWidth(bounds) === 5.0)
return [self _drawVerticalSeparatorInRect:bounds];
else if (_CGRectGetHeight(bounds) === 5.0)
else if (CGRectGetHeight(bounds) === 5.0)
return [self _drawHorizontalSeparatorInRect:bounds];
break;
@@ -493,8 +493,8 @@ CPBelowBottom = 6;
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, _CGRectGetMinX(aRect), _CGRectGetMidY(aRect));
CGContextAddLineToPoint(context, _CGRectGetWidth(aRect), _CGRectGetMidY(aRect));
CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMidY(aRect));
CGContextAddLineToPoint(context, CGRectGetWidth(aRect), CGRectGetMidY(aRect));
CGContextStrokePath(context);
}
@@ -505,8 +505,8 @@ CPBelowBottom = 6;
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, _CGRectGetMidX(aRect), _CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, _CGRectGetMidX(aRect), _CGRectGetHeight(aRect));
CGContextMoveToPoint(context, CGRectGetMidX(aRect), CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, CGRectGetMidX(aRect), CGRectGetHeight(aRect));
CGContextStrokePath(context);
}
+26 -13
View File
@@ -71,7 +71,7 @@
return "browser";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"image-control-resize": [CPNull null],
@@ -171,7 +171,7 @@
[self addColumn];
}
- (void)setLastColumn:(int)columnIndex
- (void)setLastColumn:(CPInteger)columnIndex
{
if (columnIndex >= _tableViews.length)
return;
@@ -179,6 +179,11 @@
var oldValue = _tableViews.length - 1,
indexPlusOne = columnIndex + 1; // unloads all later columns.
if (columnIndex > 0)
[_tableViews[columnIndex - 1] setNeedsDisplay:YES];
[_tableViews[columnIndex] setNeedsDisplay:YES];
[[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
@@ -286,7 +291,7 @@
[aTableView addTableColumn:column];
}
- (void)reloadColumn:(int)column
- (void)reloadColumn:(CPInteger)column
{
[[self tableViewInColumn:column] reloadData];
}
@@ -354,7 +359,7 @@
// ITEMS
- (id)itemAtRow:(int)row inColumn:(int)column
- (id)itemAtRow:(CPInteger)row inColumn:(CPInteger)column
{
return [_tableDelegates[column] childAtIndex:row];
}
@@ -364,7 +369,7 @@
return [_delegate respondsToSelector:@selector(browser:isLeafItem:)] && [_delegate browser:self isLeafItem:item];
}
- (id)parentForItemsInColumn:(int)column
- (id)parentForItemsInColumn:(CPInteger)column
{
return [_tableDelegates[column] _item];
}
@@ -647,7 +652,7 @@
[_tableViews makeObjectsPerformSelector:@selector(registerForDraggedTypes:) withObject:types];
}
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)columnIndex withEvent:(CPEvent)dragEvent
{
if ([_delegate respondsToSelector:@selector(browser:canDragRowsWithIndexes:inColumn:withEvent:)])
return [_delegate browser:self canDragRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent];
@@ -655,7 +660,7 @@
return YES;
}
- (CPImage)draggingImageForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
- (CPImage)draggingImageForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)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];
@@ -663,7 +668,7 @@
return nil;
}
- (CPView)draggingViewForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
- (CPView)draggingViewForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)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];
@@ -766,7 +771,7 @@
CPBrowser _browser @accessors;
}
- (void)initWithFrame:(CGRect)aFrame
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
@@ -820,6 +825,14 @@
return _browser;
}
/*!
@ignore
*/
- (BOOL)_isFocused
{
return ([super _isFocused] || [_browser tableViewInColumn:[_browser selectedColumn]] === self);
}
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes atPoint:(CGPoint)mouseDownPoint
{
return [_browser canDragRowsWithIndexes:rowIndexes inColumn:[_browser columnOfTableView:self] withEvent:[CPApp currentEvent]];
@@ -889,12 +902,12 @@
[_browser selectRowIndexes:selectedIndexes inColumn:_index];
}
- (id)childAtIndex:(unsigned)index
- (id)childAtIndex:(CPUInteger)index
{
return [_delegate browser:_browser child:index ofItem:_item];
}
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id)info row:(int)row dropOperation:(CPTableViewDropOperation)operation
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id)info row:(CPInteger)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];
@@ -902,7 +915,7 @@
return NO;
}
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(int)row proposedDropOperation:(CPTableViewDropOperation)operation
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(CPInteger)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];
@@ -982,7 +995,7 @@
[aCoder encodeObject:_highlightedBranchImage forKey:"_CPBrowserLeafViewHighlightedBranchImageKey"];
}
- (void)initWithCoder:(CPCoder)aCoder
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
+41 -32
View File
@@ -149,13 +149,13 @@ CPButtonImageOffset = 3.0;
return @"button";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"image": [CPNull null],
@"image-offset": 0.0,
@"bezel-inset": _CGInsetMakeZero(),
@"content-inset": _CGInsetMakeZero(),
@"bezel-inset": CGInsetMakeZero(),
@"content-inset": CGInsetMakeZero(),
@"bezel-color": [CPNull null],
};
}
@@ -292,7 +292,7 @@ CPButtonImageOffset = 3.0;
}
/*!
Sets the button's next state to \c aState.
Sets the button's state to the next available state.
@param aState Possible states are any of the CPButton globals:
\c CPOffState, \c CPOnState, \c CPMixedState
*/
@@ -448,38 +448,47 @@ CPButtonImageOffset = 3.0;
{
switch (aButtonType)
{
case CPMomentaryLightButton: [self setHighlightsBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryLightButton:
[self setHighlightsBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryPushInButton: [self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryPushInButton:
[self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryChangeButton: [self setHighlightsBy:CPContentsCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryChangeButton:
[self setHighlightsBy:CPContentsCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPPushOnPushOffButton: [self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeBackgroundCellMask | CPChangeGrayCellMask];
break;
case CPPushOnPushOffButton:
[self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeBackgroundCellMask | CPChangeGrayCellMask];
break;
case CPOnOffButton: [self setHighlightsBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
break;
case CPOnOffButton:
[self setHighlightsBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
break;
case CPToggleButton: [self setHighlightsBy:CPPushInCellMask | CPContentsCellMask];
[self setShowsStateBy:CPContentsCellMask];
break;
case CPToggleButton:
[self setHighlightsBy:CPPushInCellMask | CPContentsCellMask];
[self setShowsStateBy:CPContentsCellMask];
break;
case CPSwitchButton: [CPException raise:CPInvalidArgumentException
reason:"The CPSwitchButton type is not supported in Cappuccino, use the CPCheckBox class instead."];
case CPSwitchButton:
[CPException raise:CPInvalidArgumentException
reason:"The CPSwitchButton type is not supported in Cappuccino, use the CPCheckBox class instead."];
case CPRadioButton: [CPException raise:CPInvalidArgumentException
reason:"The CPRadioButton type is not supported in Cappuccino, use the CPRadio class instead."];
case CPRadioButton:
[CPException raise:CPInvalidArgumentException
reason:"The CPRadioButton type is not supported in Cappuccino, use the CPRadio class instead."];
default: [CPException raise:CPInvalidArgumentException
reason:"Unknown button type."];
default:
[CPException raise:CPInvalidArgumentException
reason:"Unknown button type."];
}
[self setImageDimsWhenDisabled:YES];
@@ -596,7 +605,7 @@ CPButtonImageOffset = 3.0;
{
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
return _CGRectInsetByInset(bounds, contentInset);
return CGRectInsetByInset(bounds, contentInset);
}
- (CGRect)bezelRectForBounds:(CGRect)bounds
@@ -607,7 +616,7 @@ CPButtonImageOffset = 3.0;
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
return _CGRectInsetByInset(bounds, bezelInset);
return CGRectInsetByInset(bounds, bezelInset);
}
- (CGSize)_minimumFrameSize
@@ -667,14 +676,14 @@ CPButtonImageOffset = 3.0;
{
if (aName === "bezel-view")
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
else
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
return [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()];
}
- (void)layoutSubviews
+1 -1
View File
@@ -79,7 +79,7 @@
return @"button-bar";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"resize-control-inset": CGInsetMake(0.0, 0.0, 0.0, 0.0),
+4 -4
View File
@@ -108,19 +108,19 @@
- (CGPoint)constrainScrollPoint:(CGPoint)aPoint
{
if (!_documentView)
return _CGPointMakeZero();
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)));
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)));
return aPoint;
}
- (void)setBoundsOrigin:(CGPoint)aPoint
{
if (_CGPointEqualToPoint(_bounds.origin, aPoint))
if (CGPointEqualToPoint(_bounds.origin, aPoint))
return;
[super setBoundsOrigin:aPoint];
+82 -81
View File
@@ -20,8 +20,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "../Foundation/CPRange.h"
@import <Foundation/CPArray.j>
@import <Foundation/CPData.j>
@import <Foundation/CPIndexSet.j>
@@ -34,9 +32,6 @@
@import "CPPasteboard.j"
@import "CPView.j"
@class CPClipView
/*!
@ingroup appkit
@class CPCollectionView
@@ -130,8 +125,8 @@ var HORIZONTAL_MARGIN = 2;
_maxNumberOfRows = 0;
_maxNumberOfColumns = 0;
_minItemSize = _CGSizeMakeZero();
_maxItemSize = _CGSizeMakeZero();
_minItemSize = CGSizeMakeZero();
_maxItemSize = CGSizeMakeZero();
[self setBackgroundColors:nil];
@@ -155,11 +150,11 @@ var HORIZONTAL_MARGIN = 2;
_numberOfColumns = CPNotFound;
_numberOfRows = CPNotFound;
_itemSize = _CGSizeMakeZero();
_itemSize = CGSizeMakeZero();
_selectionIndexes = [CPIndexSet indexSet];
_storedFrameSize = _CGSizeMakeZero();
_storedFrameSize = CGSizeMakeZero();
_needsMinMaxItemSizeUpdate = YES;
_uniformSubviewsResizing = NO;
@@ -175,50 +170,47 @@ var HORIZONTAL_MARGIN = 2;
/*!
Sets the item prototype to \c anItem
@param anItem the new item prototype.
The item prototype should implement the CPCoding protocol
because the item is copied by archiving and unarchiving the
prototypal view.
@note
- If anItem is located in an external cib file, representedObject, outlets, and bindings will be automatically restored when an item is created.
- If anItem and its view belong to the same cib as the collection view, the item prototype should implement the CPCoding protocol because the item is copied by archiving and unarchiving the prototypal view.
@note
Bindings won't be restored through archiving, instead you need to subclass the -representedObject: method and update the view there.
Example:
@par Example:
<pre>
@implement MyCustomView : CPCollectionViewItem
{
CPArray items @accessors;
}
@code
@implementation MyCustomPrototypeItem: CPCollectionViewItem
{
@outlet CPTextField textField;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
items = [];
}
return self;
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
items = [aCoder decodeObjectForKey:@"KEY"];
return self;
}
textField = [aCoder decodeObjectForKey:@"TextField"];
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:items forKey:@"KEY"];
[super encodeWithCoder:aCoder];
}
return self;
}
@end
</pre>
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeConditionalObject:textField forKey:@"TextField"];
}
This will allow the collection view to create multiple 'clean' copies
of the item prototype which will maintain the original values for item
and all of the properties archived by the super class.
- (void)setRepresentedObject:(id)anObject
{
[super setRepresentedObject:anObject];
[textField setStringValue:[anObject objectForKey:@"value"]];
[[self view] setColor:[anObject objectForKey:@"color"]];
}
@end
@endcode
@param anItem the new item prototype
*/
- (void)setItemPrototype:(CPCollectionViewItem)anItem
{
@@ -463,12 +455,12 @@ var HORIZONTAL_MARGIN = 2;
[self tileIfNeeded:NO];
}
- (void)resizeSubviewsWithOldSize:(CPSize)oldBoundsSize
- (void)resizeSubviewsWithOldSize:(CGSize)oldBoundsSize
{
// Desactivate subviews autoresizing
}
- (void)resizeWithOldSuperviewSize:(CPSize)oldBoundsSize
- (void)resizeWithOldSuperviewSize:(CGSize)oldBoundsSize
{
if (_lockResizing)
return;
@@ -510,7 +502,7 @@ var HORIZONTAL_MARGIN = 2;
if (!lazyFlag ||
_numberOfColumns !== oldNumberOfColumns ||
_numberOfRows !== oldNumberOfRows ||
!_CGSizeEqualToSize(_itemSize, oldItemSize))
!CGSizeEqualToSize(_itemSize, oldItemSize))
[self displayItems:_items frameSize:_storedFrameSize itemSize:_itemSize columns:_numberOfColumns rows:_numberOfRows count:count];
}
@@ -519,7 +511,7 @@ var HORIZONTAL_MARGIN = 2;
{
var width = aSuperviewSize.width,
height = aSuperviewSize.height,
itemSize = _CGSizeMakeCopy(_minItemSize),
itemSize = CGSizeMakeCopy(_minItemSize),
maxItemSizeWidth = _maxItemSize.width,
maxItemSizeHeight = _maxItemSize.height,
itemsCount = [_items count],
@@ -558,8 +550,8 @@ var HORIZONTAL_MARGIN = 2;
if (maxItemSizeHeight > 0)
itemSizeHeight = MIN(itemSizeHeight, maxItemSizeHeight);
_itemSize = _CGSizeMake(MAX(_minItemSize.width, itemSize.width), MAX(_minItemSize.height, itemSizeHeight));
_storedFrameSize = _CGSizeMake(MAX(width, _minItemSize.width), height);
_itemSize = CGSizeMake(MAX(_minItemSize.width, itemSize.width), MAX(_minItemSize.height, itemSizeHeight));
_storedFrameSize = CGSizeMake(MAX(width, _minItemSize.width), height);
_numberOfColumns = numberOfColumns;
_numberOfRows = numberOfRows;
countRef(MIN(itemsCount, numberOfColumns * numberOfRows));
@@ -580,7 +572,7 @@ var HORIZONTAL_MARGIN = 2;
if (idx >= displayCount)
{
[view setFrameOrigin:_CGPointMake(-anItemSize.width, -anItemSize.height)];
[view setFrameOrigin:CGPointMake(-anItemSize.width, -anItemSize.height)];
return;
}
@@ -590,7 +582,7 @@ var HORIZONTAL_MARGIN = 2;
y += _verticalMargin + anItemSize.height;
}
[view setFrameOrigin:_CGPointMake(x, y)];
[view setFrameOrigin:CGPointMake(x, y)];
[view setFrameSize:anItemSize];
x += anItemSize.width + _horizontalMargin;
@@ -693,12 +685,12 @@ var HORIZONTAL_MARGIN = 2;
if (aSize === nil || aSize === undefined)
[CPException raise:CPInvalidArgumentException reason:"Invalid value provided for minimum size"];
if (_CGSizeEqualToSize(_minItemSize, aSize))
if (CGSizeEqualToSize(_minItemSize, aSize))
return;
_minItemSize = _CGSizeMakeCopy(aSize);
_minItemSize = CGSizeMakeCopy(aSize);
if (_CGSizeEqualToSize(_minItemSize, _CGSizeMakeZero()))
if (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
_needsMinMaxItemSizeUpdate = YES;
[self tile];
@@ -718,10 +710,10 @@ var HORIZONTAL_MARGIN = 2;
*/
- (void)setMaxItemSize:(CGSize)aSize
{
if (_CGSizeEqualToSize(_maxItemSize, aSize))
if (CGSizeEqualToSize(_maxItemSize, aSize))
return;
_maxItemSize = _CGSizeMakeCopy(aSize);
_maxItemSize = CGSizeMakeCopy(aSize);
// if (_maxItemSize.width == 0 || _maxItemSize.height == 0)
// _needsMinMaxItemSizeUpdate = YES;
@@ -792,10 +784,14 @@ var HORIZONTAL_MARGIN = 2;
var firstSelectedIndex = [[self selectionIndexes] firstIndex],
newSelectedRange = nil;
// This catches the case where the shift key is held down for the first selection.
if (firstSelectedIndex === CPNotFound)
firstSelectedIndex = index;
if (index < firstSelectedIndex)
newSelectedRange = _CPMakeRange(index, (firstSelectedIndex - index) + 1);
newSelectedRange = CPMakeRange(index, (firstSelectedIndex - index) + 1);
else
newSelectedRange = _CPMakeRange(firstSelectedIndex, (index - firstSelectedIndex) + 1);
newSelectedRange = CPMakeRange(firstSelectedIndex, (index - firstSelectedIndex) + 1);
indexes = [[self selectionIndexes] copy];
[indexes addIndexesInRange:newSelectedRange];
@@ -834,7 +830,7 @@ var HORIZONTAL_MARGIN = 2;
[self tile];
}
- (void)setUniformSubviewsResizing:(float)flag
- (void)setUniformSubviewsResizing:(BOOL)flag
{
_uniformSubviewsResizing = flag;
[self tileIfNeeded:NO];
@@ -896,12 +892,12 @@ var HORIZONTAL_MARGIN = 2;
return CPNotFound;
}
- (CPCollectionViewItem)itemAtIndex:(unsigned)anIndex
- (CPCollectionViewItem)itemAtIndex:(CPUInteger)anIndex
{
return [_items objectAtIndex:anIndex];
}
- (CGRect)frameForItemAtIndex:(unsigned)anIndex
- (CGRect)frameForItemAtIndex:(CPUInteger)anIndex
{
return [[[self itemAtIndex:anIndex] view] frame];
}
@@ -944,9 +940,9 @@ var HORIZONTAL_MARGIN = 2;
// Create and position the drop indicator view.
if (!_dropView)
_dropView = [[_CPCollectionViewDropIndicator alloc] initWithFrame:_CGRectMake(-8, -8, 0, 0)];
_dropView = [[_CPCollectionViewDropIndicator alloc] initWithFrame:CGRectMake(-8, -8, 0, 0)];
[_dropView setFrameSize:_CGSizeMake(10, _itemSize.height + _verticalMargin)];
[_dropView setFrameSize:CGSizeMake(10, _itemSize.height + _verticalMargin)];
[self addSubview:_dropView];
}
@@ -982,14 +978,14 @@ var HORIZONTAL_MARGIN = 2;
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self];
var dragImageOffset = _CGSizeMakeZero(),
var dragImageOffset = CGSizeMakeZero(),
view = [self _draggingViewForItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent offset:dragImageOffset];
[view setFrameSize:_itemSize];
[view setAlphaValue:0.7];
var dragLocation = [self convertPoint:locationInWindow fromView:nil],
dragPoint = _CGPointMake(dragLocation.x - _itemSize.width / 2 , dragLocation.y - _itemSize.height / 2);
dragPoint = CGPointMake(dragLocation.x - _itemSize.width / 2 , dragLocation.y - _itemSize.height / 2);
[self dragView:view
at:dragPoint
@@ -1121,12 +1117,12 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
_currentDragOperation = dragOperation;
var frameOrigin,
dropviewFrameWidth = _CGRectGetWidth([_dropView frame]);
dropviewFrameWidth = CGRectGetWidth([_dropView frame]);
if (_currentDropIndex == -1 || _currentDragOperation == CPDragOperationNone)
frameOrigin = _CGPointMake(-dropviewFrameWidth, 0);
frameOrigin = CGPointMake(-dropviewFrameWidth, 0);
else if (_currentDropIndex == 0)
frameOrigin = _CGPointMake(0, 0);
frameOrigin = CGPointMake(0, 0);
else
{
var offset;
@@ -1143,7 +1139,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
var rect = [self frameForItemAtIndex:dropIndex];
frameOrigin = _CGPointMake(_CGRectGetMaxX(rect) + offset, rect.origin.y - _verticalMargin);
frameOrigin = CGPointMake(CGRectGetMaxX(rect) + offset, rect.origin.y - _verticalMargin);
}
[_dropView setFrameOrigin:frameOrigin];
@@ -1190,8 +1186,8 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
width = _CGRectGetWidth(aRect),
circleRect = _CGRectMake(1, 1, width - 2, width - 2);
width = CGRectGetWidth(aRect),
circleRect = CGRectMake(1, 1, width - 2, width - 2);
CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]);
CGContextSetFillColor(context, [CPColor whiteColor]);
@@ -1205,8 +1201,8 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
//then draw the line
CGContextBeginPath(context);
CGContextMoveToPoint(context, FLOOR(width / 2), _CGRectGetMinY(aRect) + width);
CGContextAddLineToPoint(context, FLOOR(width / 2), _CGRectGetHeight(aRect));
CGContextMoveToPoint(context, FLOOR(width / 2), CGRectGetMinY(aRect) + width);
CGContextAddLineToPoint(context, FLOOR(width / 2), CGRectGetHeight(aRect));
CGContextStrokePath(context);
}
@@ -1216,7 +1212,12 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
- (void)_modifySelectionWithNewIndex:(int)anIndex direction:(int)aDirection expand:(BOOL)shouldExpand
{
anIndex = MIN(MAX(anIndex, 0), [[self items] count] - 1);
var count = [[self items] count];
if (count === 0)
return;
anIndex = MIN(MAX(anIndex, 0), count - 1);
if (_allowsMultipleSelection && shouldExpand)
{
@@ -1226,9 +1227,9 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
// if the direction is backward (-1) check with the bottom anchor
if (aDirection === -1)
[indexes addIndexesInRange:_CPMakeRange(anIndex, bottomAnchor - anIndex + 1)];
[indexes addIndexesInRange:CPMakeRange(anIndex, bottomAnchor - anIndex + 1)];
else
[indexes addIndexesInRange:_CPMakeRange(topAnchor, anIndex - topAnchor + 1)];
[indexes addIndexesInRange:CPMakeRange(topAnchor, anIndex - topAnchor + 1)];
}
else
indexes = [CPIndexSet indexSetWithIndex:anIndex];
@@ -1241,7 +1242,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
{
var frame = [self frameForItemsAtIndexes:[self selectionIndexes]];
if (!_CGRectIsNull(frame))
if (!CGRectIsEmpty(frame))
[self scrollRectToVisible:frame];
}
@@ -1321,7 +1322,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
[self interpretKeyEvents:[anEvent]];
}
- (void)setAutoresizingMask:(int)aMask
- (void)setAutoresizingMask:(unsigned)aMask
{
[super setAutoresizingMask:0];
}
@@ -1389,10 +1390,10 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
{
[super encodeWithCoder:aCoder];
if (!_CGSizeEqualToSize(_minItemSize, _CGSizeMakeZero()))
if (!CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
[aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey];
if (!_CGSizeEqualToSize(_maxItemSize, _CGSizeMakeZero()))
if (!CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
[aCoder encodeInt:_maxNumberOfRows forKey:CPCollectionViewMaxNumberOfRowsKey];
+87 -20
View File
@@ -156,11 +156,15 @@ var cachedBlackColor,
}
/*!
Creates a new color in HSB space.
Creates a new color based on the given HSB components.
@param hue the hue value
@param saturation the saturation value
@param brightness the brightness value
Note: earlier versions of this method took a hue component as degrees between 0-360,
and saturation and brightness components as percent between 0-100. This method has
now been corrected to take all components in the 0-1 range as in Cocoa.
@param hue the hue component (0.0-1.0)
@param saturation the saturation component (0.0-1.0)
@param brightness the brightness component (0.0-1.0)
@return the initialized color
*/
@@ -169,25 +173,61 @@ var cachedBlackColor,
return [self colorWithHue:hue saturation:saturation brightness:brightness alpha:1.0];
}
/*!
Calibrated colors are not supported in Cappuccino.
This method has the same result as [CPColor colorWithHue:saturation:brightness:alpha:].
*/
+ (CPColor)colorWithCalibratedHue:(float)hue saturation:(float)saturation brightness:(float)brightness alpha:(float)alpha
{
return [self colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha];
}
/*!
Creates a new color based on the given HSB components.
Note: earlier versions of this method took a hue component as degrees between 0-360,
and saturation and brightness components as percent between 0-100. This method has
now been corrected to take all components in the 0-1 range as in Cocoa.
@param hue the hue component (0.0-1.0)
@param saturation the saturation component (0.0-1.0)
@param brightness the brightness component (0.0-1.0)
@param alpha the opacity component (0.0-1.0)
@return the initialized color
*/
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness alpha:(float)alpha
{
// Clamp values.
hue = MAX(MIN(hue, 1.0), 0.0);
saturation = MAX(MIN(saturation, 1.0), 0.0);
brightness = MAX(MIN(brightness, 1.0), 0.0);
if (saturation === 0.0)
return [CPColor colorWithCalibratedWhite:brightness / 100.0 alpha:alpha];
return [CPColor colorWithCalibratedWhite:brightness 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;
var f = (hue * 360) % 60,
p = (brightness * (1 - saturation)),
q = (brightness * (60 - saturation * f)) / 60,
t = (brightness * (60 - saturation * (60 - f))) / 60,
b = brightness;
switch (FLOOR(hue / 60))
switch (FLOOR(hue * 6))
{
case 0: return [CPColor colorWithCalibratedRed:b green:t blue:p alpha:alpha];
case 1: return [CPColor colorWithCalibratedRed:q green:b blue:p alpha:alpha];
case 2: return [CPColor colorWithCalibratedRed:p green:b blue:t alpha:alpha];
case 3: return [CPColor colorWithCalibratedRed:p green:q blue:b alpha:alpha];
case 4: return [CPColor colorWithCalibratedRed:t green:p blue:b alpha:alpha];
case 5: return [CPColor colorWithCalibratedRed:b green:p blue:q alpha:alpha];
case 0:
case 6:
return [CPColor colorWithCalibratedRed:b green:t blue:p alpha:alpha];
case 1:
return [CPColor colorWithCalibratedRed:q green:b blue:p alpha:alpha];
case 2:
return [CPColor colorWithCalibratedRed:p green:b blue:t alpha:alpha];
case 3:
return [CPColor colorWithCalibratedRed:p green:q blue:b alpha:alpha];
case 4:
return [CPColor colorWithCalibratedRed:t green:p blue:b alpha:alpha];
case 5:
return [CPColor colorWithCalibratedRed:b green:p blue:q alpha:alpha];
}
}
@@ -575,6 +615,9 @@ var cachedBlackColor,
/*!
Returns an array with the HSB values for this color.
The values are expressed as fractions between 0.0-1.0.
The index values are ordered as:
<pre>
<b>Index</b> <b>Component</b>
@@ -621,12 +664,36 @@ var cachedBlackColor,
}
return [
ROUND(hue * 360.0),
ROUND(saturation * 100.0),
ROUND(brightness * 100.0)
hue,
saturation,
brightness
];
}
/*!
Returns the hue component, the H in HSB, of the receiver.
*/
- (float)hueComponent
{
return [self hsbComponents][0];
}
/*!
Returns the saturation component, the S in HSB, of the receiver.
*/
- (float)saturationComponent
{
return [self hsbComponents][1];
}
/*!
Returns the brightness component, the B in HSB, of the receiver.
*/
- (float)brightnessComponent
{
return [self hsbComponents][2];
}
/*!
Returns the CSS representation of this color. The color will
be in one of the following forms:
+2 -2
View File
@@ -576,7 +576,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:_dragColor] forType:aType];
}
- (void)performDragOperation:(id <CPDraggingInfo>)aSender
- (void)performDragOperation:(id /*<CPDraggingInfo>*/)aSender
{
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
pasteboard = [aSender draggingPasteboard],
@@ -615,7 +615,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
return _colorPanel;
}
- (void)performDragOperation:(id <CPDraggingInfo>)aSender
- (void)performDragOperation:(id /*<CPDraggingInfo>*/)aSender
{
var pasteboard = [aSender draggingPasteboard];
+10 -10
View File
@@ -115,12 +115,12 @@
- (id)initView
{
var aFrame = _CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
var aFrame = CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
_pickerView = [[CPView alloc] initWithFrame:aFrame];
[_pickerView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_brightnessSlider = [[CPSlider alloc] initWithFrame:_CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
_brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
[_brightnessSlider setValue:15.0 forThemeAttribute:@"track-width"];
[_brightnessSlider setValue:[CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPColorPicker class]] pathForResource:@"brightness_bar.png"]]] forThemeAttribute:@"track-color"];
@@ -133,7 +133,7 @@
[_brightnessSlider setAction:@selector(brightnessSliderDidChange:)];
[_brightnessSlider setAutoresizingMask:CPViewWidthSizable | CPViewMinYMargin];
_hueSaturationView = [[__CPColorWheel alloc] initWithFrame:_CGRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)];
_hueSaturationView = [[__CPColorWheel alloc] initWithFrame:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)];
[_hueSaturationView setDelegate:self];
[_hueSaturationView setAutoresizingMask:(CPViewWidthSizable | CPViewHeightSizable)];
@@ -158,12 +158,12 @@
brightness = [_brightnessSlider floatValue];
[_hueSaturationView setWheelBrightness:brightness / 100.0];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hue saturation:saturation brightness:100]];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hue / 360.0 saturation:saturation / 100.0 brightness:1]];
var colorPanel = [self colorPanel],
opacity = [colorPanel opacity];
_cachedColor = [CPColor colorWithHue:hue saturation:saturation brightness:brightness alpha:opacity];
_cachedColor = [CPColor colorWithHue:hue / 360.0 saturation:saturation / 100.0 brightness:brightness / 100.0 alpha:opacity];
[[self colorPanel] setColor:_cachedColor];
}
@@ -194,10 +194,10 @@
var hsb = [newColor hsbComponents];
[_hueSaturationView setPositionToColor:newColor];
[_brightnessSlider setFloatValue:hsb[2]];
[_hueSaturationView setWheelBrightness:hsb[2] / 100.0];
[_brightnessSlider setFloatValue:hsb[2] * 100.0];
[_hueSaturationView setWheelBrightness:hsb[2]];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hsb[0] saturation:hsb[1] brightness:100]];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hsb[0] saturation:hsb[1] brightness:1]];
}
- (CPImage)provideNewButtonImage
@@ -366,8 +366,8 @@
{
var hsb = [aColor hsbComponents],
bounds = [self bounds],
angle = [self degreesToRadians:hsb[0]],
distance = (hsb[1] / 100.0) * _radius;
angle = [self degreesToRadians:hsb[0] * 360.0],
distance = hsb[1] * _radius;
[self setAngle:angle distance:distance];
}
+8 -8
View File
@@ -58,13 +58,13 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
return @"colorwell";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"bezel-inset": _CGInsetMakeZero(),
@"bezel-inset": CGInsetMakeZero(),
@"bezel-color": [CPNull null],
@"content-inset": _CGInsetMake(3.0, 3.0, 3.0, 3.0),
@"content-border-inset": _CGInsetMakeZero(),
@"content-inset": CGInsetMake(3.0, 3.0, 3.0, 3.0),
@"content-border-inset": CGInsetMakeZero(),
@"content-border-color": [CPNull null],
};
}
@@ -249,21 +249,21 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
return _CGRectInsetByInset(bounds, contentInset);
return CGRectInsetByInset(bounds, contentInset);
}
- (CGRect)bezelRectForBounds:(CGRect)bounds
{
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
return _CGRectInsetByInset(bounds, bezelInset);
return CGRectInsetByInset(bounds, bezelInset);
}
- (CGRect)contentBorderRectForBounds:(CGRect)bounds
{
var contentBorderInset = [self currentValueForThemeAttribute:@"content-border-inset"];
return _CGRectInsetByInset(bounds, contentBorderInset);
return CGRectInsetByInset(bounds, contentBorderInset);
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
@@ -283,7 +283,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[view setHitTests:NO];
+8 -8
View File
@@ -58,11 +58,11 @@ var CPComboBoxTextSubview = @"text",
return "combobox";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"popup-button-size": _CGSizeMake(21.0, 29.0),
@"border-inset": _CGInsetMake(3.0, 3.0, 3.0, 3.0),
@"popup-button-size": CGSizeMake(21.0, 29.0),
@"border-inset": CGInsetMake(3.0, 3.0, 3.0, 3.0),
};
}
@@ -171,7 +171,7 @@ var CPComboBoxTextSubview = @"text",
#pragma mark Setting a Delegate
- (id < CPComboBoxDelegate >)delegate
- (id /*< CPComboBoxDelegate >*/)delegate
{
return [super delegate];
}
@@ -182,7 +182,7 @@ var CPComboBoxTextSubview = @"text",
protocol, in actual fact it doesn't. Also note that the same
delegate may conform to the NSTextFieldDelegate protocol.
*/
- (void)setDelegate:(id < CPComboBoxDelegate >)aDelegate
- (void)setDelegate:(id /*< CPComboBoxDelegate >*/)aDelegate
{
var delegate = [self delegate];
@@ -231,7 +231,7 @@ var CPComboBoxTextSubview = @"text",
#pragma mark Setting a Data Source
- (id < CPComboBoxDataSource >)dataSource
- (id /*< CPComboBoxDataSource >*/)dataSource
{
if (!_usesDataSource)
[self _dataSourceWarningForMethod:_cmd condition:NO];
@@ -239,7 +239,7 @@ var CPComboBoxTextSubview = @"text",
return _dataSource;
}
- (void)setDataSource:(id < CPComboBoxDataSource >)aSource
- (void)setDataSource:(id /*< CPComboBoxDataSource >*/)aSource
{
if (!_usesDataSource)
[self _dataSourceWarningForMethod:_cmd condition:NO];
@@ -854,7 +854,7 @@ var CPComboBoxTextSubview = @"text",
{
if (aName === "popup-button-view")
{
var view = [[_CPComboBoxPopUpButton alloc] initWithFrame:_CGRectMakeZero() comboBox:self];
var view = [[_CPComboBoxPopUpButton alloc] initWithFrame:CGRectMakeZero() comboBox:self];
return view;
}
+46 -4
View File
@@ -46,7 +46,9 @@ CPHTMLDragAndDropFeature = 8;
CPJavaScriptInnerTextFeature = 9;
CPJavaScriptTextContentFeature = 10;
// In onpaste, oncopy and oncut events, the event has an event.clipboardData from which the current pasteboard contents can be read with event.clipboardData.getData.
CPJavaScriptClipboardEventsFeature = 11;
// window.clipboardData exists and can be read and written to at any time using window.clipboardData.getData/setData.
CPJavaScriptClipboardAccessFeature = 12;
CPJavaScriptCanvasDrawFeature = 13;
CPJavaScriptCanvasTransformFeature = 14;
@@ -76,11 +78,19 @@ CPInputOnInputEventFeature = 30;
CPFileAPIFeature = 31;
/*
When an absolutely positioned div (CPView) with an absolutely positioned canvas in it (CPView with drawRect:) moves things on top of the canvas (subviews) don't redraw correctly. E.g. if you have a bunch of text fields in a CPBox in a sheet which animates in, some of the text fields might not be visible because the CPBox has a canvas at the bottom and the box moved form offscreen to onscreen. This bug is probably very related: https://bugs.webkit.org/show_bug.cgi?id=67203
*/
CPCanvasParentDrawErrorsOnMovementBug = 1 << 0;
// The paste event is only sent if an input or textarea has focus.
CPJavaScriptPasteRequiresEditableTarget = 1 << 1;
// Redirecting the focus of the browser on keydown to an input for Cmd-V or Ctrl-V makes the paste fail.
CPJavaScriptPasteCantRefocus = 1 << 2;
var USER_AGENT = "",
PLATFORM_ENGINE = CPUnknownBrowserEngine,
PLATFORM_FEATURES = [],
@@ -118,6 +128,9 @@ else if (typeof window !== "undefined" && window.attachEvent) // Must follow Ope
// Tested in Internet Explore 8 and 9.
PLATFORM_FEATURES[CPInputSetFontOutsideOfDOM] = NO;
// IE allows free clipboard access.
PLATFORM_FEATURES[CPJavaScriptClipboardAccessFeature] = YES;
}
// WebKit
@@ -129,11 +142,8 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
PLATFORM_FEATURES[CPCSSRGBAFeature] = YES;
PLATFORM_FEATURES[CPHTMLContentEditableFeature] = YES;
if (USER_AGENT.indexOf("Chrome") === -1)
PLATFORM_FEATURES[CPHTMLDragAndDropFeature] = YES;
PLATFORM_FEATURES[CPJavaScriptClipboardEventsFeature] = YES;
PLATFORM_FEATURES[CPJavaScriptClipboardAccessFeature] = YES;
PLATFORM_FEATURES[CPJavaScriptClipboardAccessFeature] = NO;
PLATFORM_FEATURES[CPJavaScriptShadowFeature] = YES;
var versionStart = USER_AGENT.indexOf("AppleWebKit/") + "AppleWebKit/".length,
@@ -159,7 +169,14 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
PLATFORM_FEATURES[CPInput1PxLeftPadding] = YES;
if (USER_AGENT.indexOf("Chrome") === CPNotFound)
{
PLATFORM_FEATURES[CPSOPDisabledFromFileURLs] = YES;
PLATFORM_FEATURES[CPHTMLDragAndDropFeature] = YES;
// https://bugs.webkit.org/show_bug.cgi?id=75891
PLATFORM_BUGS |= CPJavaScriptPasteRequiresEditableTarget;
// https://bugs.webkit.org/show_bug.cgi?id=39689
PLATFORM_BUGS |= CPJavaScriptPasteCantRefocus;
}
// Assume this bug was introduced around Safari 5.1/Chrome 16. This could probably be tighter.
if (majorVersion > 533)
@@ -190,6 +207,17 @@ else if (USER_AGENT.indexOf("Gecko") !== -1) // Must follow KHTML check.
// Some day this might be fixed and should be version prefixed. No known fixed version yet.
PLATFORM_FEATURES[CPInput1PxLeftPadding] = YES;
// This was supposed to be added in Firefox 22, but when testing with the latest beta as of 2013-06-14
// it does not seem to work. It seems to exhibit the CPJavaScriptPasteRequiresEditableTarget problem,
// and in addition doesn't seem to work with our native copy code either.
/*if (version >= 22.0)
{
PLATFORM_FEATURES[CPJavaScriptClipboardEventsFeature] = YES;
// TODO File a bug at https://bugzilla.mozilla.org/. In other browsers, one can return "false" from the
// beforepaste event to indicate a paste should be enabled even that the DOMEvent.target is not editable.
PLATFORM_BUGS |= CPJavaScriptPasteRequiresEditableTarget;
}*/
}
// Feature-specific checks
@@ -323,6 +351,20 @@ function CPBrowserStyleProperty(aProperty)
r = candidates[PLATFORM_STYLE_JS_PROPERTIES['transition']] || nil;
break;
case 'transformorigin':
var candidates = {
'WebkitTransform' : 'WebkitTransformOrigin',
'MozTransform' : 'MozTransformOrigin',
'OTransform' : 'OTransformOrigin',
'msTransform' : 'MSTransformOrigin',
'transform' : 'transformOrigin'
};
r = candidates[PLATFORM_STYLE_JS_PROPERTIES['transform']] || nil;
break;
default:
var prefixes = ["Webkit", "Moz", "O", "ms"],
strippedProperty = aProperty.split('-').join(' '),
+52 -10
View File
@@ -117,11 +117,11 @@ var CPControlBlackColor = [CPColor blackColor];
@"text-color": [CPColor blackColor],
@"font": [CPFont systemFontOfSize:CPFontCurrentSystemSize],
@"text-shadow-color": [CPNull null],
@"text-shadow-offset": _CGSizeMakeZero(),
@"text-shadow-offset": CGSizeMakeZero(),
@"image-position": CPImageLeft,
@"image-scaling": CPScaleToFit,
@"min-size": _CGSizeMakeZero(),
@"max-size": _CGSizeMake(-1.0, -1.0),
@"min-size": CGSizeMakeZero(),
@"max-size": CGSizeMake(-1.0, -1.0),
};
}
@@ -322,11 +322,11 @@ var CPControlBlackColor = [CPColor blackColor];
_previousTrackingLocation = currentLocation;
}
- (void)setState:(int)state
- (void)setState:(CPInteger)state
{
}
- (int)nextState
- (CPInteger)nextState
{
return 0;
}
@@ -530,7 +530,7 @@ var CPControlBlackColor = [CPColor blackColor];
return formattedValue;
}
return (_value === undefined || _value === nil) ? "" : String(_value);
return (_value === undefined || _value === nil) ? @"" : String(_value);
}
/*!
@@ -607,7 +607,7 @@ var CPControlBlackColor = [CPColor blackColor];
if ([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:@{ "CPFieldEditor": [note object] }];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}];
}
- (void)textDidChange:(CPNotification)note
@@ -616,7 +616,7 @@ var CPControlBlackColor = [CPColor blackColor];
if ([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:@{ "CPFieldEditor": [note object] }];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:@{"CPFieldEditor": [note object]}];
}
- (void)textDidEndEditing:(CPNotification)note
@@ -627,7 +627,49 @@ var CPControlBlackColor = [CPColor blackColor];
[self _reverseSetBinding];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:@{ "CPFieldEditor": [note object] }];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[note userInfo]];
}
/*!
@ignore
Return the currentTextMovement needed by the delegate textDidEndEditing
This is going to check the currentEvent of the CPApp
*/
- (unsigned)_currentTextMovement
{
var currentEvent = [CPApp currentEvent],
keyCode = [currentEvent keyCode],
modifierFlags = [currentEvent modifierFlags];
switch (keyCode)
{
case CPEscapeKeyCode:
return CPCancelTextMovement;
case CPLeftArrowKeyCode:
return CPLeftTextMovement;
case CPRightArrowKeyCode:
return CPRightTextMovement;
case CPUpArrowKeyCode:
return CPUpTextMovement;
case CPDownArrowKeyCode:
return CPDownTextMovement;
case CPReturnKeyCode:
return CPReturnTextMovement;
case CPTabKeyCode:
if (modifierFlags & CPShiftKeyMask)
return CPBacktabTextMovement;
return CPTabTextMovement;
default:
return CPOtherTextMovement;
}
}
/*!
@@ -813,7 +855,7 @@ var CPControlBlackColor = [CPColor blackColor];
/*!
Returns the image scaling of the control.
*/
- (CPImageScaling)imageScaling
- (CPUInteger)imageScaling
{
return [self valueForThemeAttribute:@"image-scaling"];
}
+2 -1
View File
@@ -116,7 +116,8 @@ var currentCursor = nil,
- (void)push
{
currentCursor = cursorStack.push(self);
cursorStack.push(self);
currentCursor = self;
}
- (void)set
+691
View File
@@ -0,0 +1,691 @@
/* CPDatePicker.j
* AppKit
*
* Created by Alexandre Wilhelm
* Copyright 2012 <alexandre.wilhelmfr@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPControl.j"
@import "CPFont.j"
@import "CPTextField.j"
@import "_CPDatePickerTextField.j"
@import "_CPDatePickerCalendar.j"
@import <Foundation/CPArray.j>
@import <Foundation/CPObject.j>
@import <Foundation/CPDate.j>
@import <Foundation/CPDateFormatter.j>
@import <Foundation/CPLocale.j>
@import <Foundation/CPTimeZone.j>
@class CPStepper
@class CPApp
@global CPLocaleLanguageCode
@global CPDateFormatterShortStyle
var CPDatePicker_validateProposedDateValue_timeInterval = 1 << 1;
CPSingleDateMode = 0;
CPRangeDateMode = 1;
CPTextFieldAndStepperDatePickerStyle = 0;
CPClockAndCalendarDatePickerStyle = 1;
CPTextFieldDatePickerStyle = 2;
CPHourMinuteDatePickerElementFlag = 0x000c;
CPHourMinuteSecondDatePickerElementFlag = 0x000e;
CPTimeZoneDatePickerElementFlag = 0x0010;
CPYearMonthDatePickerElementFlag = 0x00c0;
CPYearMonthDayDatePickerElementFlag = 0x00e0;
CPEraDatePickerElementFlag = 0x0100;
/*!
@ingroup appkit
This control displays a datepicker in a Cappuccino application
*/
@implementation CPDatePicker : CPControl
{
BOOL _isBordered @accessors(getter=isBordered, setter=setBordered:);
BOOL _isBezeled @accessors(getter=isBezeled, setter=setBezeled:);
BOOL _drawsBackground @accessors(property=drawsBackground);
CPDate _dateValue @accessors(property=dateValue);
CPDate _minDate @accessors(property=minDate);
CPDate _maxDate @accessors(property=maxDate);
CPFont _textFont @accessors(property=textFont);
CPLocale _locale @accessors(property=locale);
//CPCalendar _calendar @accessors(property=calendar);
CPTimeZone _timeZone @accessors(property=timeZone);
id _delegate @accessors(property=delegate);
CPInteger _datePickerElements @accessors(property=datePickerElements);
CPInteger _datePickerMode @accessors(property=datePickerMode);
CPInteger _datePickerStyle @accessors(property=datePickerStyle);
CPInteger _timeInterval @accessors(property=timeInterval);
_CPDatePickerTextField _datePickerTextfield;
_CPDatePickerCalendar _datePickerCalendar;
unsigned _implementedCDatePickerDelegateMethods;
}
#pragma mark -
#pragma mark Theme methods
+ (CPString)defaultThemeClass
{
return @"datePicker";
}
+ (CPDictionary)themeAttributes
{
return @{
@"bezel-color": [CPColor clearColor],
@"border-width" : 1.0,
@"border-color": [CPColor clearColor],
@"content-inset": CGInsetMakeZero(),
@"bezel-inset": CGInsetMakeZero(),
@"datepicker-textfield-bezel-color": [CPColor clearColor],
@"min-size-datepicker-textfield": CGSizeMakeZero(),
@"content-inset-datepicker-textfield": CGInsetMakeZero(),
@"content-inset-datepicker-textfield-separator": CGInsetMakeZero(),
@"separator-content-inset": CGInsetMakeZero(),
@"date-hour-margin": 5.0,
@"stepper-margin": 5.0,
@"bezel-color-calendar": [CPColor clearColor],
@"title-text-color": [CPColor blackColor],
@"title-text-shadow-color": [CPColor clearColor],
@"title-text-shadow-offset": CGSizeMakeZero(),
@"title-font": [CPNull null],
@"weekday-text-color": [CPColor blackColor],
@"weekday-text-shadow-color": [CPColor clearColor],
@"weekday-text-shadow-offset": CGSizeMakeZero(),
@"weekday-font": [CPNull null],
@"arrow-image-left": [CPNull null],
@"arrow-image-right": [CPNull null],
@"arrow-image-left-highlighted": [CPNull null],
@"arrow-image-right-highlighted": [CPNull null],
@"arrow-inset": CGInsetMakeZero(),
@"circle-image": [CPNull null],
@"circle-image-highlighted": [CPNull null],
@"tile-text-color": [CPColor blackColor],
@"tile-text-shadow-color": [CPColor clearColor],
@"tile-text-shadow-offset": CGSizeMakeZero(),
@"tile-font": [CPNull null],
@"size-tile": CGSizeMakeZero(),
@"size-calendar": CGSizeMakeZero(),
@"size-header": CGSizeMakeZero(),
@"min-size-calendar": CGSizeMakeZero(),
@"max-size-calendar": CGSizeMakeZero(),
@"bezel-color-clock": [CPColor clearColor],
@"clock-text-color": [CPColor blackColor],
@"clock-text-shadow-color": [CPColor clearColor],
@"clock-text-shadow-offset": CGSizeMakeZero(),
@"clock-font": [CPNull null],
@"second-hand-image": [CPNull null],
@"hour-hand-image": [CPNull null],
@"middle-hand-image": [CPNull null],
@"minute-hand-image": [CPNull null],
@"size-clock": CGSizeMakeZero(),
@"second-hand-size": CGSizeMakeZero(),
@"hour-hand-size": CGSizeMakeZero(),
@"middle-hand-size": CGSizeMakeZero(),
@"minute-hand-size": CGSizeMakeZero(),
};
}
#pragma mark -
#pragma mark Binding methods
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding == CPValueBinding || theBinding == CPMinValueBinding || theBinding == CPMaxValueBinding)
return [_CPDatePickerValueBinder class];
return [super _binderClassForBinding:theBinding];
}
- (CPString)_replacementKeyPathForBinding:(CPString)aBinding
{
if (aBinding == CPValueBinding)
return @"dateValue";
if (aBinding == CPMinValueBinding)
return @"minDate";
if (aBinding == CPMaxValueBinding)
return @"maxDate";
return [super _replacementKeyPathForBinding:aBinding];
}
#pragma mark -
#pragma mark Init methods
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
_drawsBackground = YES;
_datePickerStyle = CPTextFieldAndStepperDatePickerStyle;
_datePickerMode = CPSingleDateMode;
_datePickerElements = CPYearMonthDayDatePickerElementFlag | CPHourMinuteSecondDatePickerElementFlag;
_timeInterval = 0;
_implementedCDatePickerDelegateMethods = 0;
[self setObjectValue:[CPDate date]];
_minDate = [CPDate distantPast];
_maxDate = [CPDate distantFuture];
[self setBezeled:YES];
[self setBordered:YES];
[self _init];
}
return self
}
- (void)_init
{
if (!_locale)
_locale = [CPLocale currentLocale];
if (!_timeZone)
_timeZone = [CPTimeZone systemTimeZone];
_datePickerTextfield = [[_CPDatePickerTextField alloc] initWithFrame:[self bounds] withDatePicker:self];
[_datePickerTextfield setDateValue:_dateValue];
[self addSubview:_datePickerTextfield];
_datePickerCalendar = [[_CPDatePickerCalendar alloc] initWithFrame:[self bounds] withDatePicker:self];
[_datePickerCalendar setDateValue:_dateValue];
[_datePickerCalendar setHidden:YES];
[self addSubview:_datePickerCalendar];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
#pragma mark -
#pragma mark Delegate methods
/*! Set the delegate of the datePicker
@param aDelegate delegate of the datePicker
*/
- (void)setDelegate:(id)aDelegate
{
_delegate = aDelegate;
_implementedCDatePickerDelegateMethods = 0;
// Look if the delegate implements or not the delegate methods
if ([_delegate respondsToSelector:@selector(datePicker:validateProposedDateValue:timeInterval:)])
_implementedCDatePickerDelegateMethods |= CPDatePicker_validateProposedDateValue_timeInterval;
}
#pragma mark -
#pragma mark Layout method
/*! Layout the subviews
*/
- (void)layoutSubviews
{
[super layoutSubviews];
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
{
[_datePickerTextfield setHidden:NO];
[_datePickerCalendar setHidden:YES];
[_datePickerTextfield setNeedsLayout];
}
else
{
[_datePickerCalendar setHidden:NO];
[_datePickerTextfield setHidden:YES];
[_datePickerCalendar setNeedsLayout];
}
}
#pragma mark -
#pragma mark Setter
/*! Return the objectValue of the datePicker. The objectValue should take the timeZoneEffect
*/
- (id)objectValue
{
// TODO : add timeZone effect. How to do it because js ???
return _dateValue
}
/*! Set the objectValue ofhe datePier. It has to be a CPDate
@param aDateValue the dateValue
*/
- (void)setObjectValue:(CPDate)aValue
{
[self setDateValue:aValue];
}
/* Set the dateValue of the datePicker
@param aDateValue the dateValue
*/
- (void)setDateValue:(CPDate)aDateValue
{
if (aDateValue == nil)
return;
[self _setDateValue:aDateValue timeInterval:_timeInterval];
}
/*! Set the dateValue and the timeInterval. This method checks the min and max date of the datePicker also. It will call the delegate if possible.
@param aDateValue the dateValue
@param aTimeInterval the timeInterval
*/
- (void)_setDateValue:(CPDate)aDateValue timeInterval:(CPTimeInterval)aTimeInterval
{
if (_minDate)
aDateValue = new Date (MAX(aDateValue, _minDate));
if (_maxDate)
aDateValue = new Date (MIN(aDateValue, _maxDate));
aTimeInterval = MAX(MIN(aTimeInterval, [_maxDate timeIntervalSinceDate:aDateValue]), [_minDate timeIntervalSinceDate:aDateValue]);
if ([aDateValue isEqualToDate:_dateValue] && aTimeInterval == _timeInterval)
return;
if (_implementedCDatePickerDelegateMethods & CPDatePicker_validateProposedDateValue_timeInterval)
{
// constrain timeInterval also
var aStartDateRef = function(x){if (typeof x == 'undefined') return aDateValue; aDateValue = x;}
var aTimeIntervalRef = function(x){if (typeof x == 'undefined') return aTimeInterval; aTimeInterval = x;}
[_delegate datePicker:self validateProposedDateValue:aStartDateRef timeInterval:aTimeIntervalRef];
}
[self willChangeValueForKey:@"objectValue"];
[self willChangeValueForKey:@"dateValue"];
_dateValue = aDateValue;
[super setObjectValue:_dateValue];
[self didChangeValueForKey:@"objectValue"];
[self didChangeValueForKey:@"dateValue"];
[self willChangeValueForKey:@"timeInterval"];
_timeInterval = (_datePickerMode == CPSingleDateMode)? 0 : aTimeInterval;
[self didChangeValueForKey:@"timeInterval"];
[self sendAction:[self action] to:[self target]];
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
[_datePickerTextfield setDateValue:_dateValue];
else
[_datePickerCalendar setDateValue:_dateValue];
}
/*! Set the minDate of the datePicker
@param aMinDate the minDate
*/
- (void)setMinDate:(CPDate)aMinDate
{
[self willChangeValueForKey:@"minDate"];
_minDate = aMinDate;
[self didChangeValueForKey:@"minDate"];
[self _setDateValue:_dateValue timeInterval:_timeInterval];
}
/*! Set the maxDate of the datePicker
@param aMaxDate the maxDate
*/
- (void)setMaxDate:(CPDate)aMaxDate
{
[self willChangeValueForKey:@"maxDate"];
_maxDate = aMaxDate;
[self didChangeValueForKey:@"maxDate"];
[self _setDateValue:_dateValue timeInterval:_timeInterval];
}
/*! Set the syle of the datePicker
@param aDatePickerStyle the datePicker style
*/
- (void)setDatePickerStyle:(CPInteger)aDatePickerStyle
{
_datePickerStyle = aDatePickerStyle;
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
/*! Set the elements of the datePicker
@param aDatePickerElements the datePicker elements
*/
- (void)setDatePickerElements:(CPInteger)aDatePickerElements
{
_datePickerElements = aDatePickerElements;
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
/*! Set the mode of the datePicker
@param aDatePickerMode the datePicker mode
*/
- (void)setDatePickerMode:(CPInteger)aDatePickerMode
{
_datePickerMode = aDatePickerMode;
if (_datePickerMode == CPSingleDateMode)
[self _setDateValue:[self dateValue] timeInterval:0];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
/*! Set the timeInterval of the datePicker
@param aTimeInterval the timeInterval of the datePicker
*/
- (void)setTimeInterval:(CPInteger)aTimeInterval
{
if (_datePickerMode == CPSingleDateMode)
return;
[self _setDateValue:[self dateValue] timeInterval:aTimeInterval];
}
/*! Set the locale of the datePicker. This update laso the locale of the formatter.
@param aLocale the locale
*/
- (void)setLocale:(CPLocale)aLocale
{
_locale = aLocale;
if (_formatter)
{
[self willChangeValueForKey:@"locale"];
[_formatter setLocale:_locale];
[self didChangeValueForKey:@"locale"];
}
// This will update the textFields (usefull when changing with a date with pm and am)
[_datePickerTextfield setDateValue:_dateValue];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
/*!
Sets whether the datepicker will have a bezeled border.
@param shouldBeBezeled \c YES means the datepicker will draw a bezeled border
*/
- (void)setBezeled:(BOOL)shouldBeBezeled
{
_isBezeled = shouldBeBezeled;
if (shouldBeBezeled)
[self setThemeState:CPThemeStateBezeled];
else
[self unsetThemeState:CPThemeStateBezeled];
}
/*!
Sets whether the datepicker will have a border drawn. (actually it does nothing)
@param shouldBeBordered \c YES makes the datepicker draw a border
*/
- (void)setBordered:(BOOL)shouldBeBordered
{
_isBordered = shouldBeBordered;
if (shouldBeBordered)
[self setThemeState:CPThemeStateBordered];
else
[self unsetThemeState:CPThemeStateBordered];
}
/*!
Sets the font of the control.
@param aFont
*/
- (void)setTextFont:(CPFont)aFont
{
[self setFont:aFont];
}
/*! Sets the enabled status of the control. Controls that are not enabled can not be used by the user and obtain the CPThemeStateDisabled theme state.
@param a boolean. YES if the control should be enabled, otherwise NO.
*/
- (void)setEnabled:(BOOL)aBoolean
{
[super setEnabled:aBoolean];
[_datePickerTextfield setEnabled:aBoolean];
[_datePickerCalendar setEnabled:aBoolean];
}
/*! Set the background color of the datePicker
@param aColor
*/
- (void)setBackgroundColor:(CPColor)aColor
{
_backgroundColor = aColor;
[self setNeedsLayout];
}
/*! Set the boolean drawsBackgroundColor
@param aBoolean
*/
- (void)setDrawsBackground:(BOOL)aBoolean
{
[self willChangeValueForKey:@"drawsBackground"];
_drawsBackground = aBoolean;
[self didChangeValueForKey:@"drawsBackground"];
[self setNeedsLayout];
}
/*! Set the timeZone
@param aTimeZone
*/
- (void)setTimeZone:(CPTimeZone)aTimeZone
{
[self willChangeValueForKey:@"timeZone"];
_timeZone = aTimeZone;
[self didChangeValueForKey:@"timeZone"];
[self setNeedsLayout];
}
#pragma mark -
#pragma mark First responder methods
/*! Return YES if style is set to CPTextFieldAndStepperDatePickerStyle or CPTextFieldDatePickerStyle
*/
- (BOOL)becomeFirstResponder
{
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
[_datePickerTextfield _selecteTextFieldWithFlags:[[CPApp currentEvent] modifierFlags]];
else
return NO;
return YES;
}
/*! Return YES
*/
- (BOOL)acceptsFirstResponder
{
return YES;
}
/*! Return YES
*/
- (BOOL)resignFirstResponder
{
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
[_datePickerTextfield resignFirstResponder];
return YES;
}
#pragma mark -
#pragma mark getter
/*!
Returns \c YES if the textfield is bezeled.
*/
- (BOOL)isBezeled
{
return [self hasThemeState:CPThemeStateBezeled];
}
/*!
Returns \c YES if the textfield has a border.
*/
- (BOOL)isBordered
{
return [self hasThemeState:CPThemeStateBordered];
}
/*!
Returns the font of the control.
*/
- (CPFont)textFont
{
return [self font];
}
/*! Check if we are in the american format or not. Depending on the locale
*/
- (BOOL)_isAmericanFormat
{
return [[_locale objectForKey:CPLocaleCountryCode] isEqualToString:@"US"];
}
/*! Check if we are in the english format or not. Depending on the locale
*/
- (BOOL)_isEnglishFormat
{
return [[_locale objectForKey:CPLocaleLanguageCode] isEqualToString:@"en"];
}
#pragma mark -
#pragma mark Key event
/*! Key down event
@param anEvent
*/
- (void)keyDown:(CPEvent)anEvent
{
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
[_datePickerTextfield keyDown:anEvent];
}
@end
var CPDatePickerModeKey = @"CPDatePickerModeKey",
CPIntervalKey = @"CPIntervalKey",
CPMinDateKey = @"CPMinDateKey",
CPMaxDateKey = @"CPMaxDateKey",
CPBackgroundColorKey = @"CPBackgroundColorKey",
CPDrawsBackgroundKey = @"CPDrawsBackgroundKey",
CPTextFontKey = @"CPTextFontKey",
CPDatePickerElementsKey = @"CPDatePickerElementsKey",
CPDatePickerStyleKey = @"CPDatePickerStyleKey",
CPLocaleKey = @"CPLocaleKey",
CPBorderedKey = @"CPBorderedKey",
CPDateValueKey = @"CPDateValueKey";
@implementation CPDatePicker (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_textFont = [aCoder decodeObjectForKey:CPTextFontKey];
_minDate = [aCoder decodeObjectForKey:CPMinDateKey] || [CPDate distantPast];
_maxDate = [aCoder decodeObjectForKey:CPMaxDateKey] || [CPDate distantFuture];
_timeInterval = [aCoder decodeDoubleForKey:CPIntervalKey];
_datePickerMode = [aCoder decodeIntForKey:CPDatePickerModeKey];
_datePickerElements = [aCoder decodeIntForKey:CPDatePickerElementsKey];
_datePickerStyle = [aCoder decodeIntForKey:CPDatePickerStyleKey];
_locale = [aCoder decodeObjectForKey:CPLocaleKey];
_dateValue = [aCoder decodeObjectForKey:CPDateValueKey];
_backgroundColor = [aCoder decodeObjectForKey:CPBackgroundColorKey];
_drawsBackground = [aCoder decodeBoolForKey:CPDrawsBackgroundKey];
_isBordered = [aCoder decodeBoolForKey:CPBorderedKey];
[self _init];
}
return self
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeDouble:_timeInterval forKey:CPIntervalKey];
[aCoder encodeInt:_datePickerMode forKey:CPDatePickerModeKey];
[aCoder encodeInt:_datePickerStyle forKey:CPDatePickerStyleKey];
[aCoder encodeInt:_datePickerElements forKey:CPDatePickerElementsKey];
[aCoder encodeObject:_minDate forKey:CPMinDateKey];
[aCoder encodeObject:_maxDate forKey:CPMaxDateKey]
[aCoder encodeObject:_dateValue forKey:CPDateValueKey];;
[aCoder encodeObject:_textFont forKey:CPTextFontKey];
[aCoder encodeObject:_locale forKey:CPLocaleKey];
[aCoder encodeObject:_backgroundColor forKey:CPBackgroundColorKey];
[aCoder encodeObject:_drawsBackground forKey:CPDrawsBackgroundKey];
[aCoder encodeObject:_isBordered forKey:CPBorderedKey];
}
@end
@implementation _CPDatePickerValueBinder : CPBinder
{
}
@end
@implementation CPDate (CPDatePickerAdditions)
- (int)_daysInMonth
{
return 32 - new Date(self.getFullYear(), self.getMonth(), 32).getDate();
}
- (void)_resetToMidnight
{
self.setHours(0);
self.setMinutes(0);
self.setSeconds(0);
self.setMilliseconds(0);
}
- (void)_resetToLastSeconds
{
self.setHours(23);
self.setMinutes(59);
self.setSeconds(59);
self.setMilliseconds(99);
}
@end
File diff suppressed because it is too large Load Diff
+314
View File
@@ -0,0 +1,314 @@
/*
* _CPDatePickerClock.j
* AppKit
*
* Created by Alexandre Wilhelm
* Copyright 2012 <alexandre.wilhelmfr@gmail.com>
*
* 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"
@import "CPTextField.j"
@import "CPImageView.j"
@import "CALayer.j"
@class _CPCibCustomResource
@class CPDatePicker
@global CPHourMinuteSecondDatePickerElementFlag
@global CPTextFieldAndStepperDatePickerStyle
@global CPTextFieldDatePickerStyle
var RADIANS = Math.PI / 180;
@implementation _CPDatePickerClock : CPView
{
BOOL _isEnabled;
CALayer _rootLayer;
CALayer _hourHandLayer;
CALayer _minuteHandLayer;
CALayer _secondHandLayer;
CALayer _middleHandLayer;
CPDatePicker _datePicker;
CPTextField _PMAMTextField;
}
#pragma mark -
#pragma mark Init methods
- (id)initWithFrame:(CGRect)aFrame datePicker:(CPDatePicker)aDatePicker
{
if (self = [super initWithFrame:aFrame])
{
_datePicker = aDatePicker;
_PMAMTextField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-font" inState:CPThemeStateNormal] forThemeAttribute:@"font" inState:CPThemeStateNormal];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-color" inState:CPThemeStateNormal];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-font" inState:CPThemeStateDisabled] forThemeAttribute:@"font" inState:CPThemeStateDisabled];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled];
[self addSubview:_PMAMTextField];
var middleHandSize = [_datePicker valueForThemeAttribute:@"middle-hand-size"],
minuteHandSize = [_datePicker valueForThemeAttribute:@"minute-hand-size"],
hourHandSize = [_datePicker valueForThemeAttribute:@"hour-hand-size"],
secondHandSize = [_datePicker valueForThemeAttribute:@"second-hand-size"];
// We use layer to make the rotation possible
_hourHandLayer = [[HandLayer alloc] initWithSize:hourHandSize];
[_hourHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)];
[_hourHandLayer setAnchorPoint:CGPointMakeZero()];
[_hourHandLayer setPosition:CGPointMake(0.0, 0.0)];
_minuteHandLayer = [[HandLayer alloc] initWithSize:minuteHandSize];
[_minuteHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)];
[_minuteHandLayer setAnchorPoint:CGPointMakeZero()];
[_minuteHandLayer setPosition:CGPointMake(0.0, 0.0)];
_secondHandLayer = [[HandLayer alloc] initWithSize:secondHandSize];
[_secondHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)];
[_secondHandLayer setAnchorPoint:CGPointMakeZero()];
[_secondHandLayer setPosition:CGPointMake(0.0, 0.0)];
_middleHandLayer = [[HandLayer alloc] initWithSize:middleHandSize];
[_middleHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)];
[_middleHandLayer setAnchorPoint:CGPointMakeZero()];
[_middleHandLayer setPosition:CGPointMake(0.0, 0.0)];
_rootLayer = [CALayer layer];
[self setWantsLayer:YES];
[self setLayer:_rootLayer];
[_hourHandLayer setNeedsDisplay];
[_middleHandLayer setNeedsDisplay];
[_secondHandLayer setNeedsDisplay];
[_minuteHandLayer setNeedsDisplay];
[_rootLayer addSublayer:_hourHandLayer];
[_rootLayer addSublayer:_minuteHandLayer];
[_rootLayer addSublayer:_secondHandLayer];
[_rootLayer addSublayer:_middleHandLayer];
[_rootLayer setNeedsDisplay];
}
return self;
}
#pragma mark -
#pragma mark Layout methods
- (void)layoutSubviews
{
if ([_datePicker datePickerStyle] == CPTextFieldAndStepperDatePickerStyle || [_datePicker datePickerStyle] == CPTextFieldDatePickerStyle)
return;
[super layoutSubviews];
var bounds = [self bounds],
dateValue = [[_datePicker dateValue] copy];
[dateValue _dateWithTimeZone:[_datePicker timeZone]];
[self setBackgroundColor:[_datePicker currentValueForThemeAttribute:@"bezel-color-clock"]];
[_middleHandLayer setImage:[_datePicker currentValueForThemeAttribute:@"middle-hand-image"]];
[_hourHandLayer setImage:[_datePicker currentValueForThemeAttribute:@"hour-hand-image"]];
[_minuteHandLayer setImage:[_datePicker currentValueForThemeAttribute:@"minute-hand-image"]];
[_secondHandLayer setImage:[_datePicker currentValueForThemeAttribute:@"second-hand-image"]];
if ([_datePicker _isEnglishFormat])
{
if (dateValue.getHours() > 11)
[_PMAMTextField setStringValue:@"PM"]
else
[_PMAMTextField setStringValue:@"AM"];
[_PMAMTextField sizeToFit];
[_PMAMTextField setFrameOrigin:CGPointMake(bounds.size.width / 2 - [_PMAMTextField frameSize].width / 2, bounds.size.height / 2 + 15)];
[_PMAMTextField setHidden:NO];
}
else
{
[_PMAMTextField setHidden:YES];
}
[_hourHandLayer setRotationRadians:[self _hourPositionRadianForDate:dateValue]];
[_minuteHandLayer setRotationRadians:[self _minutePositionRadianForDate:dateValue]];
[_secondHandLayer setRotationRadians:[self _secondPositionRadianForDate:dateValue]];
[_PMAMTextField setEnabled:_isEnabled];
[_hourHandLayer setEnabled:_isEnabled];
[_middleHandLayer setEnabled:_isEnabled];
[_secondHandLayer setEnabled:_isEnabled];
[_minuteHandLayer setEnabled:_isEnabled];
// Check if we have to display the hand second
if (([_datePicker datePickerElements] & CPHourMinuteSecondDatePickerElementFlag) == CPHourMinuteSecondDatePickerElementFlag)
[_secondHandLayer setHidden:NO];
else
[_secondHandLayer setHidden:YES];
[_rootLayer setNeedsDisplay];
}
#pragma mark -
#pragma mark Accessors
- (float)_hourPositionRadianForDate:(CPDate)aDate
{
var hours = aDate.getHours() + aDate.getMinutes() / 60;
return (360 * hours / 12) * RADIANS;
}
- (float)_secondPositionRadianForDate:(CPDate)aDate
{
return (360 * aDate.getSeconds() / 60) * RADIANS;
}
- (float)_minutePositionRadianForDate:(CPDate)aDate
{
var minutes = aDate.getMinutes() + aDate.getSeconds() / 60;
return (360 * minutes / 60) * RADIANS;
}
- (void)setEnabled:(BOOL)shouldEnable
{
shouldEnable = !!shouldEnable;
if (shouldEnable === _isEnabled)
return;
_isEnabled = shouldEnable;
[self setNeedsLayout];
// FIXME: This is a workaround for an apparent bug in CALayer.
// Without pumping the event loop, the sublayers of _rootLayer
// (the hands) are not redrawn until an event occurs.
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
@end
@implementation HandLayer : CALayer
{
BOOL _isEnabled @accessors(setter=setEnabled:, getter=isEnabled);
CPImage _image;
CALayer _imageLayer;
float _rotationRadians;
}
#pragma mark -
#pragma mark Init methods
- (id)initWithSize:(CGSize)aSize
{
if (self = [super init])
{
_isEnabled = YES;
_imageLayer = [CALayer layer];
_rotationRadians = 0;
[_imageLayer setDelegate:self];
[_imageLayer setBounds:CGRectMake(0.0, 0.0, aSize.width, aSize.height)];
[self addSublayer:_imageLayer];
}
return self;
}
#pragma mark -
#pragma mark Setter Getter methods
/*!
Set the bounds of the layer. The imageLayer will be at the center of this bounds.
*/
- (void)setBounds:(CGRect)aRect
{
[super setBounds:aRect];
[_imageLayer setPosition:CGPointMake(CGRectGetMidX(aRect), CGRectGetMidY(aRect))];
}
- (void)setImage:(CPImage)anImage
{
if (_image === anImage)
return;
if ([anImage isKindOfClass:[_CPCibCustomResource class]])
_image = [anImage imageFromCoder:nil];
else
_image = anImage;
[_imageLayer setNeedsDisplay];
}
- (void)setRotationRadians:(float)radians
{
if (_rotationRadians === radians)
return;
_rotationRadians = radians;
[_imageLayer setAffineTransform:CGAffineTransformScale(
CGAffineTransformMakeRotation(_rotationRadians),
1.0, 1.0)];
}
- (void)setEnabled:(BOOL)shouldEnable
{
shouldEnable = !!shouldEnable;
if (_isEnabled === shouldEnable)
return;
_isEnabled = shouldEnable;
[self setNeedsDisplay];
[_imageLayer setNeedsDisplay];
}
- (void)imageDidLoad:(CPImage)anImage
{
[_imageLayer setNeedsDisplay];
}
- (void)drawLayer:(CALayer)aLayer inContext:(CGContext)aContext
{
if ([_image loadStatus] != CPImageLoadStatusCompleted)
[_image setDelegate:self];
else
CGContextDrawImage(aContext, [aLayer bounds], _image);
}
@end
File diff suppressed because it is too large Load Diff
+11 -25
View File
@@ -244,11 +244,6 @@ var CPDocumentUntitledCount = 0;
{
}
- (CPWindowController)firstEligibleExistingWindowController
{
return nil;
}
// Creating and managing window controllers
/*!
Creates the window controller for this document.
@@ -261,6 +256,7 @@ var CPDocumentUntitledCount = 0;
- (void)makeViewAndWindowControllers
{
var viewCibName = [self viewCibName],
windowCibName = [self windowCibName],
viewController = nil,
windowController = nil;
@@ -268,31 +264,21 @@ var CPDocumentUntitledCount = 0;
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];
// From a cib if we have one.
if ([windowCibName length])
windowController = [[CPWindowController alloc] initWithWindowCibName:windowCibName owner:self];
// If not, create one.
if (!windowController)
// If not you get a standard window capable of displaying multiple documents and view
else if (viewController)
{
var windowCibName = [self windowCibName];
var view = [viewController view],
viewFrame = [view frame];
// From a cib if we have one.
if ([windowCibName length])
windowController = [[CPWindowController alloc] initWithWindowCibName:windowCibName owner:self];
viewFrame.origin = CGPointMake(50, 50);
// If not you get a standard window capable of displaying multiple documents and view
else if (viewController)
{
var view = [viewController view],
viewFrame = [view frame];
var theWindow = [[CPWindow alloc] initWithContentRect:viewFrame styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
viewFrame.origin = CGPointMake(50, 50);
var theWindow = [[CPWindow alloc] initWithContentRect:viewFrame styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
windowController = [[CPWindowController alloc] initWithWindow:theWindow];
}
windowController = [[CPWindowController alloc] initWithWindow:theWindow];
}
if (windowController && viewController)
+35
View File
@@ -253,6 +253,14 @@ var CPSharedDocumentController = nil;
return _documents;
}
/*!
Returns the CPDocument object associated with the main window.
*/
- (CPDocument)currentDocument
{
return [[[CPApp mainWindow] windowController] document];
}
/*!
Adds \c aDocument under the control of the receiver.
@param aDocument the document to add
@@ -271,6 +279,33 @@ var CPSharedDocumentController = nil;
[_documents removeObjectIdenticalTo:aDocument];
}
/*!
Returns the document object whose window controller
owns a specified window.
*/
- (CPDocument)documentForWindow:(CPWindow)aWindow
{
return [[aWindow windowController] document];
}
/*!
Returns a Boolean value that indicates whether the receiver
has any documents with unsaved changes.
*/
- (BOOL)hasEditedDocuments
{
var iter = [_documents objectEnumerator],
obj;
while ((obj = [iter nextObject]) !== nil)
{
if ([obj isDocumentEdited])
return YES;
}
return NO;
}
- (CPString)defaultType
{
return [_documentTypes[0] objectForKey:@"CPBundleTypeName"];
+28 -19
View File
@@ -163,7 +163,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
if (self)
{
_draggedWindow = [[CPWindow alloc] initWithContentRect:_CGRectMakeZero() styleMask:CPBorderlessWindowMask];
_draggedWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessWindowMask];
[_draggedWindow setLevel:CPDraggingWindowLevel];
}
@@ -201,7 +201,12 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
- (void)draggingSourceUpdatedWithGlobalLocation:(CGPoint)aGlobalLocation
{
if (![CPPlatform supportsDragAndDrop])
[_draggedWindow setFrameOrigin:_CGPointMake(aGlobalLocation.x - _draggingOffset.width, aGlobalLocation.y - _draggingOffset.height)];
{
var frame = [_draggedWindow frame];
frame.origin.x = aGlobalLocation.x - _draggingOffset.width;
frame.origin.y = aGlobalLocation.y - _draggingOffset.height;
[_draggedWindow _setFrame:frame display:YES animate:NO constrainWidth:NO constrainHeight:NO];
}
if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_movedTo_)
[_draggingSource draggedImage:[_draggedView image] movedTo:aGlobalLocation];
@@ -265,10 +270,10 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
{
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 (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)
@@ -277,17 +282,17 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
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 (eventLocation.x < CGRectGetMinX(insetBounds))
deltaX = CGRectGetMinX(insetBounds) - eventLocation.x;
else if (eventLocation.x > CGRectGetMaxX(insetBounds))
deltaX = CGRectGetMaxX(insetBounds) - eventLocation.x;
if (deltaX < -insetBounds.size.width)
deltaX = -insetBounds.size.width;
if (deltaX > insetBounds.size.width)
deltaX = insetBounds.size.width;
}
var scrollPoint = _CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY);
var scrollPoint = CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY);
[contentView scrollToPoint:scrollPoint];
[[scrollView _headerView] scrollPoint:scrollPoint];
@@ -365,22 +370,26 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
if (mouseDownWindow)
mouseDownEventLocation = [mouseDownWindow convertBaseToGlobal:mouseDownEventLocation];
_draggingOffset = _CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y);
_draggingOffset = CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y);
}
else
_draggingOffset = _CGSizeMakeZero();
_draggingOffset = CGSizeMakeZero();
if ([CPPlatform isBrowser])
[_draggedWindow setPlatformWindow:[aWindow platformWindow]];
[aView setFrameOrigin:_CGPointMakeZero()];
[aView setFrameOrigin:CGPointMakeZero()];
var mouseLocation = [CPEvent mouseLocation];
var mouseLocation = [CPEvent mouseLocation],
viewSize = [aView frameSize],
startDragLocationX = mouseLocation.x - _draggingOffset.width,
startDragLocationY = mouseLocation.y - _draggingOffset.height,
draggedWindowFrame = CGRectMake(startDragLocationX, startDragLocationY, viewSize.width, viewSize.height);
// 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];
_startDragLocation = CGPointMake(startDragLocationX, startDragLocationY);
[_draggedWindow _setFrame:draggedWindowFrame display:YES animate:NO constrainWidth:NO constrainHeight:NO];
[[_draggedWindow contentView] addSubview:aView];
@@ -429,7 +438,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
var imageSize = [anImage size];
if (!_imageView)
_imageView = [[CPImageView alloc] initWithFrame:_CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)];
_imageView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)];
[_imageView setImage:anImage];
+25 -2
View File
@@ -68,6 +68,11 @@ var _CPEventPeriodicEventPeriod = 0,
float _deltaX;
float _deltaY;
float _deltaZ;
#if PLATFORM(DOM)
BOOL _suppressCappuccinoCut;
BOOL _suppressCappuccinoPaste;
#endif
}
/*!
@@ -235,7 +240,7 @@ var _CPEventPeriodicEventPeriod = 0,
*/
- (CGPoint)locationInWindow
{
return _CGPointMakeCopy(_location);
return CGPointMakeCopy(_location);
}
- (CGPoint)globalLocation
@@ -473,6 +478,24 @@ var _CPEventPeriodicEventPeriod = 0,
return !firstResponderIsText;
}
/*!
Return YES if this event is a part of processing a browser controlled cut or paste event
where the browser will go ahead and do the work of cutting or pasting within the input
element after processing of this event. The implication is that it should not be done by
the CPTextField (or whatever else is controlling the input) since this would result in
nothing being cut (because the field already cut the text out), or a double paste
(because the field pasted as well as the browser).
*/
- (BOOL)_platformIsEffectingCutOrPaste
{
#if PLATFORM(DOM)
return _suppressCappuccinoCut || _suppressCappuccinoPaste;
#else
return NO;
#endif
}
/*!
Generates periodic events every \c aPeriod seconds.
@@ -527,7 +550,7 @@ var _CPEventPeriodicEventPeriod = 0,
function _CPEventFirePeriodEvent()
{
[CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:_CGPointMakeZero() modifierFlags:0 timestamp:[CPEvent currentTimestamp] windowNumber:0 context:nil subtype:0 data1:0 data2:0]];
[CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:CGPointMakeZero() modifierFlags:0 timestamp:[CPEvent currentTimestamp] windowNumber:0 context:nil subtype:0 data1:0 data2:0]];
}
var CPEventClass = [CPEvent class];
+1 -1
View File
@@ -189,7 +189,7 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
return @"CPFV_" + [self UID];
}
- (void)mouseMoved:(id)sommit
- (void)mouseMoved:(CPEvent)sommit
{
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
+9 -7
View File
@@ -37,12 +37,12 @@ CPFontCurrentSystemSize = -1;
// For internal use only by this class and subclasses
_CPFontSystemFacePlaceholder = "_CPFontSystemFacePlaceholder";
var _CPFontCache = {},
_CPSystemFontCache = {},
_CPFontSystemFontFace = CPFontDefaultSystemFontFace,
_CPFontSystemFontSize = 12,
_CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "),
_CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g");
var _CPFontCache = {},
_CPSystemFontCache = {},
_CPFontSystemFontFace = CPFontDefaultSystemFontFace,
_CPFontSystemFontSize = 12,
_CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "),
_CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g");
#define _CPRealFontSize(aSize) (aSize <= 0 ? _CPFontSystemFontSize : aSize)
@@ -181,8 +181,10 @@ following:
{
case CPSmallControlSize:
return _CPFontSystemFontSize - 1;
case CPMiniControlSize:
return _CPFontSystemFontSize - 2;
case CPRegularControlSize:
default:
return _CPFontSystemFontSize;
@@ -206,7 +208,7 @@ following:
var systemSize = String(_CPFontSystemFontSize),
currentSize = String(CPFontCurrentSystemSize);
for (key in _CPSystemFontCache)
for (var key in _CPSystemFontCache)
{
if (_CPSystemFontCache.hasOwnProperty(key) &&
(key.indexOf(systemSize) === 0 || key.indexOf(currentSize) === 0))
+6 -6
View File
@@ -108,13 +108,13 @@ CPGradientDrawsAfterEndingLocation = kCGGradientDrawsAfterEndLocation;
angle = ((angle % 360.0) + 360.0) % 360.0;
if (angle < 90.0)
startPoint = _CGPointMake(_CGRectGetMinX(rect), _CGRectGetMinY(rect));
startPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
else if (angle < 180.0)
startPoint = _CGPointMake(_CGRectGetMaxX(rect), _CGRectGetMinY(rect));
startPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
else if (angle < 270.0)
startPoint = _CGPointMake(_CGRectGetMaxX(rect), _CGRectGetMaxY(rect));
startPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
else
startPoint = _CGPointMake(_CGRectGetMinX(rect), _CGRectGetMaxY(rect));
startPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
// A line segment comes out of the starting point at the given angle, with the first colour
// at the starting point and the last at the end. To do what drawInRect: is supposed to do
@@ -129,9 +129,9 @@ CPGradientDrawsAfterEndingLocation = kCGGradientDrawsAfterEndLocation;
// This simplifies down to (in the first quadrant) rectWidth * cos(a) + rectHeight * sin(a).
var radians = PI * angle / 180.0,
length = ABS(_CGRectGetWidth(rect) * COS(radians)) + ABS(_CGRectGetHeight(rect) * SIN(radians));
length = ABS(CGRectGetWidth(rect) * COS(radians)) + ABS(CGRectGetHeight(rect) * SIN(radians));
endPoint = _CGPointMake(startPoint.x + length * COS(radians),
endPoint = CGPointMake(startPoint.x + length * COS(radians),
startPoint.y + length * SIN(radians));
[self drawFromPoint:startPoint toPoint:endPoint options:CPGradientDrawsBeforeStartingLocation | CPGradientDrawsAfterEndingLocation];
+12 -12
View File
@@ -60,9 +60,9 @@ function CPDrawColorTiledRects(
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(),
var resultRect = CGRectMakeCopy(boundsRect),
slice = CGRectMakeZero(),
remainder = CGRectMakeZero(),
context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(context);
@@ -77,7 +77,7 @@ function CPDrawColorTiledRects(
slice = CGRectIntersection(slice, clipRect);
// Cocoa docs say that only slices that are within the clipRect are actually drawn
if (_CGRectIsEmpty(slice))
if (CGRectIsEmpty(slice))
continue;
var minX,
@@ -88,23 +88,23 @@ function CPDrawColorTiledRects(
if (side == CPMinXEdge || side == CPMaxXEdge)
{
// Make sure we have at least 1 pixel to draw a line
if (_CGRectGetWidth(slice) < 1.0)
if (CGRectGetWidth(slice) < 1.0)
continue;
minX = _CGRectGetMinX(slice) + 0.5;
minX = CGRectGetMinX(slice) + 0.5;
maxX = minX;
minY = _CGRectGetMinY(slice);
maxY = _CGRectGetMaxY(slice);
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)
if (CGRectGetHeight(slice) < 1.0)
continue;
minX = _CGRectGetMinX(slice);
maxX = _CGRectGetMaxX(slice);
minY = _CGRectGetMinY(slice) + 0.5;
minX = CGRectGetMinX(slice);
maxX = CGRectGetMaxX(slice);
minY = CGRectGetMinY(slice) + 0.5;
maxY = minY;
}
+15 -10
View File
@@ -48,8 +48,8 @@ var imagesForNames = { },
AppKitImageForNames = { },
ImageDescriptionFormat = "%s {\n filename: \"%s\",\n size: { width:%f, height:%f }\n}";
AppKitImageForNames[CPImageNameColorPanel] = _CGSizeMake(26.0, 29.0);
AppKitImageForNames[CPImageNameColorPanelHighlighted] = _CGSizeMake(26.0, 29.0);
AppKitImageForNames[CPImageNameColorPanel] = CGSizeMake(26.0, 29.0);
AppKitImageForNames[CPImageNameColorPanelHighlighted] = CGSizeMake(26.0, 29.0);
/*!
Returns a resource image with a relative path and size
@@ -72,7 +72,7 @@ function CPImageInBundle()
if (typeof(arguments[1]) === "number")
{
if (arguments[1] !== nil && arguments[1] !== undefined)
size = _CGSizeMake(arguments[1], arguments[2]);
size = CGSizeMake(arguments[1], arguments[2]);
bundle = arguments[3];
}
@@ -131,24 +131,29 @@ function CPAppKitImage(aFilename, aSize)
- (id)init
{
return [self initByReferencingFile:@"" size:_CGSizeMake(-1, -1)];
return [self initByReferencingFile:@"" size:CGSizeMake(-1, -1)];
}
/*!
Initializes the image, by associating it with a filename. The image
denoted in \c aFilename is not actually loaded. It will
be loaded once needed.
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
*/
- (id)initByReferencingFile:(CPString)aFilename size:(CGSize)aSize
{
// Quietly return nil like in Cocoa, rather than crashing later.
if (aFilename === undefined || aFilename === nil)
return nil;
self = [super init];
if (self)
{
_size = _CGSizeMakeCopy(aSize);
_size = CGSizeMakeCopy(aSize);
_filename = aFilename;
_loadStatus = CPImageLoadStatusInitialized;
}
@@ -180,7 +185,7 @@ function CPAppKitImage(aFilename, aSize)
*/
- (id)initWithContentsOfFile:(CPString)aFilename
{
self = [self initByReferencingFile:aFilename size:_CGSizeMake(-1, -1)];
self = [self initByReferencingFile:aFilename size:CGSizeMake(-1, -1)];
if (self)
[self load];
@@ -247,7 +252,7 @@ function CPAppKitImage(aFilename, aSize)
*/
- (void)setSize:(CGSize)aSize
{
_size = _CGSizeMakeCopy(aSize);
_size = CGSizeMakeCopy(aSize);
}
/*!
@@ -446,7 +451,7 @@ function CPAppKitImage(aFilename, aSize)
// FIXME: IE is wrong on image sizes????
if (!_size || (_size.width == -1 && _size.height == -1))
_size = _CGSizeMake(_image.width, _image.height);
_size = CGSizeMake(_image.width, _image.height);
[[CPNotificationCenter defaultCenter]
postNotificationName:CPImageDidLoadNotification
+39 -46
View File
@@ -87,26 +87,37 @@ var CPImageViewEmptyPlaceholderImage = nil;
if (self)
{
#if PLATFORM(DOM)
_DOMImageElement = document.createElement("img");
_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";
[self _createDOMImageElement];
#endif
}
return self;
}
- (void)_createDOMImageElement
{
#if PLATFORM(DOM)
if (_DOMImageElement)
return;
_DOMImageElement = document.createElement("img");
_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";
}
_DOMImageElement.style.visibility = "hidden";
AppKitTagDOMElement(self, _DOMImageElement);
CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement);
#endif
}
/*!
Returns the view's image.
*/
@@ -138,6 +149,9 @@ var CPImageViewEmptyPlaceholderImage = nil;
var newImage = [self objectValue];
#if PLATFORM(DOM)
if (!_DOMImageElement)
[self _createDOMImageElement];
_DOMImageElement.src = newImage ? [newImage filename] : [CPImageViewEmptyPlaceholderImage filename];
#endif
@@ -253,7 +267,7 @@ var CPImageViewEmptyPlaceholderImage = nil;
[self setNeedsDisplay:YES];
}
- (unsigned)imageScaling
- (CPUInteger)imageScaling
{
return [self currentValueForThemeAttribute:@"image-scaling"];
}
@@ -302,8 +316,8 @@ var CPImageViewEmptyPlaceholderImage = nil;
y = 0.0,
insetWidth = (_hasShadow ? [_shadowView horizontalInset] : 0.0),
insetHeight = (_hasShadow ? [_shadowView verticalInset] : 0.0),
boundsWidth = _CGRectGetWidth(bounds),
boundsHeight = _CGRectGetHeight(bounds),
boundsWidth = CGRectGetWidth(bounds),
boundsHeight = CGRectGetHeight(bounds),
width = boundsWidth - insetWidth,
height = boundsHeight - insetHeight;
@@ -401,10 +415,10 @@ var CPImageViewEmptyPlaceholderImage = nil;
#endif
}
_imageRect = _CGRectMake(x, y, width, height);
_imageRect = CGRectMake(x, y, width, height);
if (_hasShadow)
[_shadowView setFrame:_CGRectMake(x - [_shadowView leftInset], y - [_shadowView topInset], width + insetWidth, height + insetHeight)];
[_shadowView setFrame:CGRectMake(x - [_shadowView leftInset], y - [_shadowView topInset], width + insetWidth, height + insetHeight)];
}
- (void)mouseDown:(CPEvent)anEvent
@@ -488,7 +502,7 @@ var CPImageViewEmptyPlaceholderImage = nil;
[_source setImage:image];
}
- (void)valueForBinding:(CPString)aBinding
- (id)valueForBinding:(CPString)aBinding
{
var image = [_source image];
@@ -517,28 +531,12 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
*/
- (id)initWithCoder:(CPCoder)aCoder
{
#if PLATFORM(DOM)
_DOMImageElement = document.createElement("img");
_DOMImageElement.style.position = "absolute";
_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";
}
if (typeof(appkit_tag_dom_elements) !== "undefined" && !!appkit_tag_dom_elements)
_DOMImageElement.setAttribute("data-cappuccino-view", [self className]);
#endif
self = [super initWithCoder:aCoder];
if (self)
{
#if PLATFORM(DOM)
_DOMElement.appendChild(_DOMImageElement);
[self _createDOMImageElement];
#endif
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
@@ -564,17 +562,12 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
// We do this in order to avoid encoding the _shadowView, which
// should just automatically be created programmatically as needed.
if (_shadowView)
{
var actualSubviews = _subviews;
_subviews = [_subviews copy];
[_subviews removeObjectIdenticalTo:_shadowView];
}
[_shadowView removeFromSuperview];
[super encodeWithCoder:aCoder];
if (_shadowView)
_subviews = actualSubviews;
[self addSubview:_shadowView];
[aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
[aCoder encodeInt:_imageAlignment forKey:CPImageViewImageAlignmentKey];
@@ -585,7 +578,7 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
@end
@implementation CPImage (CahedImage)
@implementation CPImage (CachedImage)
+ (CPImage)cachedImageWithContentsOfFile:(CPString)aFile
{
@@ -601,4 +594,4 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
return image;
}
@end
@end
+5 -1
View File
@@ -257,7 +257,11 @@ var CPBindingOperationAnd = 0,
if (valueTransformer)
aValue = [valueTransformer transformedValue:aValue];
if (aValue === undefined || aValue === nil || aValue === [CPNull null])
// If the value is nil AND the source doesn't respond to setPlaceholderString: then
// we set the value to the placeholder. Otherwise, we do not want to short cut the process
// of setting the placeholder that is based on the fact that the value is nil.
if ((aValue === undefined || aValue === nil || aValue === [CPNull null])
&& ![_source respondsToSelector:@selector(setPlaceholderString:)])
aValue = [options objectForKey:CPNullPlaceholderBindingOption] || nil;
return aValue;
+7 -7
View File
@@ -62,7 +62,7 @@ CPRatingLevelIndicatorStyle = 3;
return "level-indicator";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"bezel-color": [CPNull null],
@@ -122,7 +122,7 @@ CPRatingLevelIndicatorStyle = 3;
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
return [[CPView alloc] initWithFrame:CGRectMakeZero()];
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
@@ -130,11 +130,11 @@ CPRatingLevelIndicatorStyle = 3;
// TODO Put into theme attributes.
var bezelHeight = 18,
segmentHeight = 17,
bounds = _CGRectCreateCopy([self bounds]);
bounds = CGRectCreateCopy([self bounds]);
if (aViewName == "bezel")
{
bounds.origin.y = (_CGRectGetHeight(bounds) - bezelHeight) / 2.0;
bounds.origin.y = (CGRectGetHeight(bounds) - bezelHeight) / 2.0;
bounds.size.height = bezelHeight;
return bounds;
}
@@ -144,13 +144,13 @@ CPRatingLevelIndicatorStyle = 3;
segmentCount = _maxValue - _minValue;
if (segment >= segmentCount)
return _CGRectMakeZero();
return CGRectMakeZero();
var basicSegmentWidth = bounds.size.width / segmentCount,
segmentFrame = CGRectCreateCopy([self bounds]),
spacing = [self valueForThemeAttribute:@"spacing"];
segmentFrame.origin.y = (_CGRectGetHeight(bounds) - bezelHeight) / 2.0;
segmentFrame.origin.y = (CGRectGetHeight(bounds) - bezelHeight) / 2.0;
segmentFrame.origin.x = FLOOR(segment * basicSegmentWidth);
segmentFrame.size.width = (segment == segmentCount - 1) ? bounds.size.width - segmentFrame.origin.x : FLOOR(((segment + 1) * basicSegmentWidth)) - FLOOR((segment * basicSegmentWidth)) - spacing;
segmentFrame.size.height = segmentHeight;
@@ -158,7 +158,7 @@ CPRatingLevelIndicatorStyle = 3;
return segmentFrame;
}
return _CGRectMakeZero();
return CGRectMakeZero();
}
/*!
+42 -15
View File
@@ -68,6 +68,8 @@ var _CPMenuBarVisible = NO,
int _highlightedIndex;
_CPMenuWindow _menuWindow;
CPEvent _lastCloseEvent;
}
// Managing the Menu Bar
@@ -276,7 +278,7 @@ var _CPMenuBarVisible = NO,
@param aMenuItem the item to insert
@param anIndex the index in the menu to insert the item.
*/
- (void)insertItem:(CPMenuItem)aMenuItem atIndex:(unsigned)anIndex
- (void)insertItem:(CPMenuItem)aMenuItem atIndex:(CPUInteger)anIndex
{
[self insertObject:aMenuItem inItemsAtIndex:anIndex];
}
@@ -289,7 +291,7 @@ var _CPMenuBarVisible = NO,
@param anIndex the index location in the menu for the new item
@return the new menu item
*/
- (CPMenuItem)insertItemWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent atIndex:(unsigned)anIndex
- (CPMenuItem)insertItemWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent atIndex:(CPUInteger)anIndex
{
var item = [[CPMenuItem alloc] initWithTitle:aTitle action:anAction keyEquivalent:aKeyEquivalent];
@@ -333,7 +335,7 @@ var _CPMenuBarVisible = NO,
Removes the item at the specified index from the menu
@param anIndex the index of the item to remove
*/
- (void)removeItemAtIndex:(unsigned)anIndex
- (void)removeItemAtIndex:(CPUInteger)anIndex
{
[self removeObjectFromItemsAtIndex:anIndex];
}
@@ -353,7 +355,7 @@ var _CPMenuBarVisible = NO,
while (count--)
[_items[count] setMenu:nil];
_highlightedIndex = CPNotFound;
[self _highlightItemAtIndex:CPNotFound];
// Because we are changing _items directly, be sure to notify KVO
[self willChangeValueForKey:@"items"];
@@ -619,7 +621,7 @@ var _CPMenuBarVisible = NO,
*/
- (void)update
{
if (![self autoenablesItems])
if (!_autoenablesItems)
return;
var items = [self itemArray];
@@ -631,14 +633,24 @@ var _CPMenuBarVisible = NO,
if ([item hasSubmenu])
continue;
var validator = [CPApp targetForAction:[item action] to:[item target] from:item];
// If there are enabled bindings for the item, they override anything else
var binder = [CPBinder getBinding:CPEnabledBinding forObject:item];
if (binder)
{
[binder setValueFor:CPEnabledBinding];
return;
}
var validator = [CPApp targetForAction:[item action] to:[item target] from:item],
shouldBeEnabled = YES;
if (!validator)
{
// If targetForAction: returns nil, it could be that there is no action.
// If there is an action and nil is returned, no valid target could be found.
if ([item action] || [item target])
[item setEnabled:NO];
shouldBeEnabled = NO;
else
{
// Check to see if there is a target binding with an invalid selector
@@ -653,16 +665,18 @@ var _CPMenuBarVisible = NO,
selector = [options valueForKey:CPSelectorNameBindingOption];
if (target && selector && ![target respondsToSelector:CPSelectorFromString(selector)])
[item setEnabled:NO];
shouldBeEnabled = NO;
}
}
}
else if (![validator respondsToSelector:[item action]])
[item setEnabled:NO];
shouldBeEnabled = NO;
else if ([validator respondsToSelector:@selector(validateMenuItem:)])
[item setEnabled:[validator validateMenuItem:item]];
shouldBeEnabled = [validator validateMenuItem:item];
else if ([validator respondsToSelector:@selector(validateUserInterfaceItem:)])
[item setEnabled:[validator validateUserInterfaceItem:item]];
shouldBeEnabled = [validator validateUserInterfaceItem:item];
[item setEnabled:shouldBeEnabled];
}
[[_menuWindow _menuView] tile];
@@ -841,6 +855,9 @@ var _CPMenuBarVisible = NO,
+ (void)popUpContextMenu:(CPMenu)aMenu withEvent:(CPEvent)anEvent forView:(CPView)aView withFont:(CPFont)aFont
{
// This is needed when we are making several rights click
[[_CPMenuManager sharedMenuManager] cancelActiveMenu];
[aMenu _menuWillOpen];
if (!aFont)
@@ -944,6 +961,10 @@ var _CPMenuBarVisible = NO,
- (void)_menuDidClose
{
// Remember which event caused this menu to close, if any. CPPopUpButton uses this to detect
// when a click on the button itself caused the menu to close.
_lastCloseEvent = [CPApp currentEvent];
var delegate = [self delegate];
if ([delegate respondsToSelector:@selector(menuDidClose:)])
@@ -963,7 +984,7 @@ var _CPMenuBarVisible = NO,
{
[CPApp sendEvent:[CPEvent
otherEventWithType:CPAppKitDefined
location:_CGPointMakeZero()
location:CGPointMakeZero()
modifierFlags:0
timestamp:0
windowNumber:0
@@ -1040,7 +1061,7 @@ var _CPMenuBarVisible = NO,
Sends the action of the menu item at the specified index.
@param anIndex the index of the item
*/
- (void)performActionForItemAtIndex:(unsigned)anIndex
- (void)performActionForItemAtIndex:(CPUInteger)anIndex
{
var item = _items[anIndex];
@@ -1143,6 +1164,7 @@ var _CPMenuBarVisible = NO,
return;
[aMenuItem setMenu:self];
[self _highlightItemAtIndex:CPNotFound];
[_items insertObject:aMenuItem atIndex:anIndex];
[[CPNotificationCenter defaultCenter]
@@ -1157,6 +1179,7 @@ var _CPMenuBarVisible = NO,
return;
[[_items objectAtIndex:anIndex] setMenu:nil];
[self _highlightItemAtIndex:CPNotFound];
[_items removeObjectAtIndex:anIndex];
[[CPNotificationCenter defaultCenter]
@@ -1170,7 +1193,8 @@ var _CPMenuBarVisible = NO,
var CPMenuTitleKey = @"CPMenuTitleKey",
CPMenuNameKey = @"CPMenuNameKey",
CPMenuItemsKey = @"CPMenuItemsKey",
CPMenuShowsStateColumnKey = @"CPMenuShowsStateColumnKey";
CPMenuShowsStateColumnKey = @"CPMenuShowsStateColumnKey",
CPMenuAutoEnablesItemsKey = @"CPMenuAutoEnablesItemsKey";
@implementation CPMenu (CPCoding)
@@ -1192,7 +1216,7 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
_showsStateColumn = ![aCoder containsValueForKey:CPMenuShowsStateColumnKey] || [aCoder decodeBoolForKey:CPMenuShowsStateColumnKey];
_autoenablesItems = YES;
_autoenablesItems = ![aCoder containsValueForKey:CPMenuAutoEnablesItemsKey] || [aCoder decodeBoolForKey:CPMenuAutoEnablesItemsKey];
[self setMinimumWidth:0];
}
@@ -1215,6 +1239,9 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
if (!_showsStateColumn)
[aCoder encodeBool:_showsStateColumn forKey:CPMenuShowsStateColumnKey];
if (!_autoenablesItems)
[aCoder encodeBool:_autoenablesItems forKey:CPMenuAutoEnablesItemsKey];
}
@end
+9 -3
View File
@@ -67,6 +67,8 @@
if (self)
{
_constrainsToUsableScreen = NO;
[self setLevel:CPMainMenuWindowLevel];
[self setAutoresizingMask:CPWindowWidthSizable];
@@ -141,6 +143,7 @@
_textColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setTextColor:) withObject:_textColor];
[_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuTextColor:) withObject:_textColor];
}
- (void)setTitleColor:(CPColor)aColor
@@ -161,6 +164,7 @@
_textShadowColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setTextShadowColor:) withObject:_textShadowColor];
[_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuTextShadowColor:) withObject:_textShadowColor];
}
- (void)setTitleShadowColor:(CPColor)aColor
@@ -179,6 +183,8 @@
return;
_highlightColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuHighlightColor:) withObject:_highlightColor];
}
- (void)setHighlightTextColor:(CPColor)aColor
@@ -188,7 +194,7 @@
_highlightTextColor = aColor;
// [_menuItemViews makeObjectsPerformSelector:@selector(setActivateColor:) withObject:_highlightTextColor];
[_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuHighlightTextColor:) withObject:_highlightTextColor];
}
- (void)setHighlightTextShadowColor:(CPColor)aColor
@@ -198,7 +204,7 @@
_highlightTextShadowColor = aColor;
// [_menuItemViews makeObjectsPerformSelector:@selector(setActivateShadowColor:) withObject:_highlightTextShadowColor];
[_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuHighlightTextShadowColor:) withObject:_highlightTextShadowColor];
}
- (void)setMenu:(CPMenu)aMenu
@@ -411,7 +417,7 @@
[super setFrame:aRect display:shouldDisplay animate:shouldAnimate];
if (!_CGSizeEqualToSize(size, aRect.size))
if (!CGSizeEqualToSize(size, aRect.size))
[self tile];
}
+58 -23
View File
@@ -45,6 +45,7 @@ var STICKY_TIME_INTERVAL = 0.4,
@implementation _CPMenuManager: CPObject
{
CPTimeInterval _startTime;
CPEvent _openEvent;
BOOL _mouseWasDragged;
int _scrollingState;
CGPoint _lastGlobalLocation;
@@ -103,6 +104,7 @@ var STICKY_TIME_INTERVAL = 0.4,
CPApp._activeMenu = menu;
_startTime = [anEvent timestamp];
_openEvent = anEvent;
_scrollingState = _CPMenuManagerScrollingStateNone;
_constraintRect = aRect;
@@ -132,6 +134,11 @@ var STICKY_TIME_INTERVAL = 0.4,
[self trackEvent:anEvent];
}
- (void)_trackAgain
{
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPKeyDownMask | CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseDownMask | CPLeftMouseUpMask | CPRightMouseUpMask | CPAppKitDefinedMask | CPScrollWheelMask untilDate:nil inMode:nil dequeue:YES];
}
- (void)trackEvent:(CPEvent)anEvent
{
var type = [anEvent type],
@@ -141,8 +148,6 @@ var STICKY_TIME_INTERVAL = 0.4,
if (type === CPAppKitDefined)
return [self completeTracking];
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPKeyDownMask | CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPRightMouseUpMask | CPAppKitDefinedMask | CPScrollWheelMask untilDate:nil inMode:nil dequeue:YES];
if (type === CPKeyDown)
{
var menu = trackingMenu,
@@ -158,6 +163,7 @@ var STICKY_TIME_INTERVAL = 0.4,
if ([menu numberOfItems])
[self interpretKeyEvent:anEvent forMenu:menu];
[self _trackAgain];
return;
}
@@ -165,7 +171,10 @@ var STICKY_TIME_INTERVAL = 0.4,
var globalLocation = type === CPPeriodic ? _lastGlobalLocation : [anEvent globalLocation];
if (!globalLocation)
{
[self _trackAgain];
return;
}
// Find which menu window the mouse is currently on top of
var activeMenuContainer = [self menuContainerForPoint:globalLocation],
@@ -176,15 +185,35 @@ var STICKY_TIME_INTERVAL = 0.4,
activeItemIndex = activeMenuContainer ? [activeMenuContainer itemIndexAtPoint:menuLocation] : CPNotFound,
activeItem = activeItemIndex !== CPNotFound ? [activeMenu itemAtIndex:activeItemIndex] : nil;
if (_keyBuffer)
{
if (([anEvent timestamp] - _startTime) > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] / 2))
[self selectNextItemBeginningWith:_keyBuffer inMenu:menu clearBuffer:YES];
/*
Click outside the menu structure?
if (type === CPPeriodic)
return;
The event which caused the menu to open is not considered even if it's
technically a click outside of an open menu, since this would mean the same
click which opened the menu could also close it. This is actually common.
E.g. you click on a button and it opens a menu below itself.
*/
if (type === CPLeftMouseDown && _openEvent !== anEvent && (!activeMenuContainer || !CGRectContainsPoint([activeMenuContainer globalFrame], globalLocation)))
{
[self completeTracking];
/*
You can close and interact with a control in a single click. E.g. you can have a menu open,
click on a button outside of it and have the menu immediately close and the button activate,
without having to click once to close the menu and once to activate the button.
Since we normally dequeue the event after tracking it, we'll have to put it back on the stack
in this special case. Note that it's important the event is executed /right now/, since certain
controls such as HTML upload buttons need a native click event at the top of the stack trace
to activate - it's not something we can fake later.
*/
[CPApp sendEvent:anEvent];
return;
}
[self _trackAgain];
// unhighlight when mouse is moved off the menu
if (_lastGlobalLocation && CGRectContainsPoint([activeMenuContainer globalFrame], _lastGlobalLocation)
&& !CGRectContainsPoint([activeMenuContainer globalFrame], globalLocation))
@@ -221,9 +250,9 @@ var STICKY_TIME_INTERVAL = 0.4,
if (_lastMouseOverMenuView != mouseOverMenuView)
{
[mouseOverMenuView mouseExited:anEvent];
[_lastMouseOverMenuView mouseExited:anEvent];
// FIXME: Possibly multiple of these?
[_lastMouseOverMenuView mouseEntered:anEvent];
[mouseOverMenuView mouseEntered:anEvent];
_lastMouseOverMenuView = mouseOverMenuView;
}
@@ -252,7 +281,7 @@ var STICKY_TIME_INTERVAL = 0.4,
_lastMouseOverMenuView = nil;
}
if (activeItemIndex != CPNotFound)
if (activeItemIndex !== CPNotFound)
[activeMenu _highlightItemAtIndex:activeItemIndex];
if (type === CPMouseMoved || type === CPLeftMouseDragged || type === CPLeftMouseDown || type === CPPeriodic)
@@ -378,6 +407,15 @@ var STICKY_TIME_INTERVAL = 0.4,
[menu cancelTracking];
}
- (void)cancelActiveMenu
{
if (CPApp._activeMenu)
{
[self completeTracking];
_menuContainerStack = [];
}
}
- (void)completeTracking
{
var trackingMenu = [self trackingMenu];
@@ -428,8 +466,8 @@ var STICKY_TIME_INTERVAL = 0.4,
{
var menuContainer = _menuContainerStack[index],
menuContainerFrame = [menuContainer globalFrame],
menuContainerMinX = _CGRectGetMinX(menuContainerFrame),
menuContainerMaxX = _CGRectGetMaxX(menuContainerFrame);
menuContainerMinX = CGRectGetMinX(menuContainerFrame),
menuContainerMaxX = CGRectGetMaxX(menuContainerFrame);
// If within the x bounds of this menu container, return it.
if (x < menuContainerMaxX && x >= menuContainerMinX)
@@ -525,6 +563,9 @@ var STICKY_TIME_INTERVAL = 0.4,
}
else if (!(modifierFlags & (CPCommandKeyMask | CPControlKeyMask)))
{
if (([anEvent timestamp] - _startTime) > STICKY_TIME_INTERVAL)
_keyBuffer = nil;
if (!_keyBuffer)
{
_startTime = [anEvent timestamp];
@@ -536,12 +577,12 @@ var STICKY_TIME_INTERVAL = 0.4,
else
_keyBuffer += character;
[self selectNextItemBeginningWith:_keyBuffer inMenu:menu clearBuffer:NO];
_lastGlobalLocation = Nil;
[self selectNextItemBeginningWith:_keyBuffer inMenu:menu];
_lastGlobalLocation = nil;
}
}
- (void)selectNextItemBeginningWith:(CPString)characters inMenu:(CPMenu)menu clearBuffer:(BOOL)shouldClear
- (void)selectNextItemBeginningWith:(CPString)characters inMenu:(CPMenu)menu
{
var iter = [[menu itemArray] objectEnumerator],
obj;
@@ -558,13 +599,7 @@ var STICKY_TIME_INTERVAL = 0.4,
}
}
if (shouldClear)
{
[CPEvent stopPeriodicEvents];
_keyBuffer = Nil;
}
else
_startTime = [CPEvent currentTimestamp];
_startTime = [CPEvent currentTimestamp];
}
- (void)scrollToBeginningOfDocument:(CPMenu)menu
+11 -8
View File
@@ -72,7 +72,8 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2;
+ (void)poolMenuWindow:(_CPMenuWindow)aMenuWindow
{
if (!aMenuWindow || _CPMenuWindowPool.length >= _CPMenuWindowPoolCapacity)
// FIXME :the poolMenuWindow is called too many times somewhere....
if (!aMenuWindow || _CPMenuWindowPool.length >= _CPMenuWindowPoolCapacity || [_CPMenuWindowPool containsObject:aMenuWindow])
return;
_CPMenuWindowPool.push(aMenuWindow);
@@ -80,13 +81,15 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2;
- (id)initWithContentRect:(CGRect)aRect styleMask:(unsigned)aStyleMask
{
_constraintRect = _CGRectMakeZero();
_unconstrainedFrame = _CGRectMakeZero();
_constraintRect = CGRectMakeZero();
_unconstrainedFrame = CGRectMakeZero();
self = [super initWithContentRect:aRect styleMask:CPBorderlessWindowMask];
if (self)
{
_constrainsToUsableScreen = NO;
[self setLevel:CPPopUpMenuWindowLevel];
[self setHasShadow:YES];
[self setShadowStyle:CPMenuWindowShadowStyle];
@@ -207,26 +210,26 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2;
- (CGRect)unconstrainedFrame
{
return _CGRectMakeCopy(_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))];
[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)];
[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);
_unconstrainedFrame = CGRectMakeCopy(aFrame);
var constrainedFrame = CGRectIntersection(_unconstrainedFrame, _constraintRect),
marginInset = [_menuView valueForThemeAttribute:@"menu-window-margin-inset"],
@@ -432,7 +435,7 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2;
return "menu-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"menu-window-more-above-image": [CPNull null],
+3
View File
@@ -166,6 +166,9 @@ var CPMenuItemStringRepresentationDictionary = @{
if (_isEnabled === isEnabled)
return;
if (!isEnabled && [self isHighlighted])
[_menu _highlightItemAtIndex:CPNotFound];
_isEnabled = !!isEnabled;
[_menuItemView setDirty];
+69 -16
View File
@@ -28,13 +28,18 @@
@implementation _CPMenuItemMenuBarView : CPView
{
CPColor _highlightColor @accessors(property=highlightColor);
CPColor _textColor @accessors(property=textColor);
CPColor _textShadowColor @accessors(property=textShadowColor);
CPColor _highlightTextColor @accessors(property=highlightTextColor);
CPColor _highlightTextShadowColor @accessors(property=highlightTextShadowColor);
CPMenuItem _menuItem @accessors(property=menuItem);
CPFont _font;
CPColor _textColor;
CPColor _textShadowColor;
BOOL _isDirty;
BOOL _shouldHighlight;
_CPImageAndTextView _imageAndTextView;
}
@@ -44,12 +49,10 @@
return "menu-item-bar-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"menu-item-selection-color": [CPNull null],
@"menu-item-text-shadow-color": [CPNull null],
@"horizontal-margin": 12.0,
@"horizontal-margin": 9.0,
@"submenu-indicator-margin": 3.0,
@"vertical-margin": 4.0,
};
@@ -81,12 +84,36 @@
return self;
}
- (void)setTextColor:(CPColor)aColor
{
_textColor = aColor;
[self setNeedsLayout];
}
- (void)setTextShadowColor:(CPColor)aColor
{
_textShadowColor = aColor;
[self setNeedsLayout];
}
- (void)setHighlightTextColor:(CPColor)aColor
{
_highlightTextColor = aColor;
[self setNeedsLayout];
}
- (void)setHighlightTextShadowColor:(CPColor)aColor
{
_highlightTextShadowColor = aColor;
[self setNeedsLayout];
}
- (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];
return _textColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-text-color" forClass:_CPMenuView];
}
- (CPColor)textShadowColor
@@ -94,7 +121,28 @@
if (![_menuItem isEnabled])
return [CPColor clearColor];
return _textShadowColor || [CPColor colorWithWhite:1.0 alpha:0.8];
return _textShadowColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-text-shadow-color" forClass:_CPMenuView];
}
- (CPColor)highlightTextColor
{
if (![_menuItem isEnabled])
return [CPColor lightGrayColor];
return _highlightTextColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-highlight-text-color" forClass:_CPMenuView];
}
- (CPColor)highlightTextShadowColor
{
if (![_menuItem isEnabled])
return [CPColor clearColor];
return _highlightTextShadowColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-highlight-text-shadow-color" forClass:_CPMenuView];
}
- (CPColor)highlightColor
{
return _highlightColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-window-background-selected-color" forClass:_CPMenuView];
}
- (void)update
@@ -102,13 +150,11 @@
var x = [self valueForThemeAttribute:@"horizontal-margin"],
height = 0.0;
[_imageAndTextView setText:[_menuItem title]];
[_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 setImage:[_menuItem image]];
[_imageAndTextView sizeToFit];
var imageAndTextViewFrame = [_imageAndTextView frame];
@@ -123,6 +169,7 @@
[self setAutoresizesSubviews:NO];
[self setFrameSize:CGSizeMake(x + [self valueForThemeAttribute:@"horizontal-margin"], height)];
[self setAutoresizesSubviews:YES];
[self setNeedsLayout];
}
- (void)highlight:(BOOL)shouldHighlight
@@ -131,14 +178,20 @@
if (![_menuItem isEnabled])
shouldHighlight = NO;
if (shouldHighlight)
_shouldHighlight = shouldHighlight;
[self setNeedsLayout];
}
- (void)layoutSubviews
{
if (_shouldHighlight)
{
if (![_menuItem _isMenuBarButton])
[self setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-window-background-selected-color" forClass:_CPMenuView]];
[self setBackgroundColor:[self highlightColor]];
[_imageAndTextView setImage:[_menuItem alternateImage] || [_menuItem image]];
[_imageAndTextView setTextColor:[CPColor whiteColor]];
[_imageAndTextView setTextShadowColor:[self valueForThemeAttribute:@"menu-item-text-shadow-color"]];
[_imageAndTextView setTextColor:[self highlightTextColor]];
[_imageAndTextView setTextShadowColor:[self highlightTextShadowColor]];
}
else
{
+6 -1
View File
@@ -45,7 +45,7 @@
return "menu-item-standard-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"submenu-indicator-color": [CPNull null],
@@ -336,6 +336,11 @@
}
}
- (BOOL)isHighlighted
{
return _highlighted;
}
@end
@implementation _CPMenuItemSubmenuIndicatorView : CPView
+32 -3
View File
@@ -34,7 +34,7 @@
@implementation _CPMenuItemView : CPView
{
CPMenuItem _menuItem;
CPView _view;
CPView _view @accessors(property=view, readonly);
CPFont _font;
CPColor _textColor;
@@ -53,7 +53,7 @@
return "menu-item-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{};
}
@@ -112,7 +112,6 @@
_view = menuItemView;
}
}
else if ([_menuItem menu] == [CPApp mainMenu])
{
if (![_view isKindOfClass:[_CPMenuItemMenuBarView class]])
@@ -220,6 +219,36 @@
return [_menuItem isEnabled] ? (_textShadowColor ? _textShadowColor : [CPColor colorWithWhite:1.0 alpha:0.8]) : [CPColor colorWithWhite:0.8 alpha:0.8];
}
- (void)setParentMenuHighlightColor:(CPColor)aColor
{
if ([_view respondsToSelector:@selector(setHighlightColor:)])
[_view setHighlightColor:aColor];
}
- (void)setParentMenuHighlightTextColor:(CPColor)aColor
{
if ([_view respondsToSelector:@selector(setHighlightTextColor:)])
[_view setHighlightTextColor:aColor];
}
- (void)setParentMenuHighlightTextShadowColor:(CPColor)aColor
{
if ([_view respondsToSelector:@selector(setHighlightTextShadowColor:)])
[_view setHighlightTextShadowColor:aColor];
}
- (void)setParentMenuTextColor:(CPColor)aColor
{
if ([_view respondsToSelector:@selector(setTextColor:)])
[_view setTextColor:aColor];
}
- (void)setParentMenuTextShadowColor:(CPColor)aColor
{
if ([_view respondsToSelector:@selector(setTextShadowColor:)])
[_view setTextShadowColor:aColor];
}
@end
@implementation _CPMenuItemArrowView : CPView
+5 -5
View File
@@ -51,7 +51,7 @@
CPCountedSet _observedKeys;
}
+ (id)initialize
+ (void)initialize
{
if (self !== [CPObjectController class])
return;
@@ -572,7 +572,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
}
}
- (void)insertObject:(id)anObject atIndex:(unsigned)anIndex
- (void)insertObject:(id)anObject atIndex:(CPUInteger)anIndex
{
for (var i = 0, count = [_observationProxies count]; i < count; i++)
{
@@ -592,7 +592,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
[super insertObject:anObject atIndex:anIndex];
}
- (void)removeObjectAtIndex:(unsigned)anIndex
- (void)removeObjectAtIndex:(CPUInteger)anIndex
{
var currentObject = [self objectAtIndex:anIndex];
@@ -614,7 +614,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
[super removeObjectAtIndex:anIndex];
}
- (_CPObservableArray)objectsAtIndexes:(CPIndexSet)theIndexes
- (CPArray)objectsAtIndexes:(CPIndexSet)theIndexes
{
return [_CPObservableArray arrayWithArray:[super objectsAtIndexes:theIndexes]];
}
@@ -629,7 +629,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
[self removeObjectAtIndex:[self count]];
}
- (void)replaceObjectAtIndex:(unsigned)anIndex withObject:(id)anObject
- (void)replaceObjectAtIndex:(CPUInteger)anIndex withObject:(id)anObject
{
var currentObject = [self objectAtIndex:anIndex];
+112 -39
View File
@@ -52,6 +52,7 @@ var CPOutlineViewDataSource_outlineView_objectValue_forTableColumn_byItem_
CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 11;
var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1,
CPOutlineViewDelegate_outlineView_viewForTableColumn_item_ = 1 << 26,
CPOutlineViewDelegate_outlineView_didClickTableColumn_ = 1 << 2,
CPOutlineViewDelegate_outlineView_didDragTableColumn_ = 1 << 3,
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 4,
@@ -351,6 +352,10 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
*/
- (void)expandItem:(id)anItem expandChildren:(BOOL)shouldExpandChildren
{
if ([self _delegateRespondsToShouldExpandItem])
if ([_outlineViewDelegate outlineView:self shouldExpandItem:anItem] == NO)
return;
var itemInfo = null;
if (!anItem)
@@ -426,6 +431,10 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
if (!anItem)
return;
if ([self _delegateRespondsToShouldCollapseItem])
if ([_outlineViewDelegate outlineView:self shouldCollapseItem:anItem] == NO)
return;
var itemInfo = _itemInfosForItems[[anItem UID]];
if (!itemInfo)
@@ -709,27 +718,36 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
{
var theItem = [self itemAtRow:aRow];
if (![self isExpandable:theItem] || ![self _shouldShowOutlineDisclosureControlForItem:theItem])
return _CGRectMakeZero();
return CGRectMakeZero();
var dataViewFrame = [self _frameOfOutlineDataViewAtRow:aRow],
disclosureWidth = _CGRectGetWidth([_disclosureControlPrototype frame]),
frame = _CGRectMake(_CGRectGetMinX(dataViewFrame) - disclosureWidth, _CGRectGetMinY(dataViewFrame), disclosureWidth, _CGRectGetHeight(dataViewFrame));
disclosureWidth = CGRectGetWidth([_disclosureControlPrototype frame]),
frame = CGRectMake(CGRectGetMinX(dataViewFrame) - disclosureWidth, CGRectGetMinY(dataViewFrame), disclosureWidth, CGRectGetHeight(dataViewFrame));
return frame;
}
/*!
@ignore
Select or deselect rows, this is overridden because we need to change the color or the outline control.
Select or deselect rows, this is overridden because we need to change the color of the outline control.
*/
- (void)_performSelection:(BOOL)select forRow:(CPInteger)rowIndex context:(id)context
- (void)_setSelectedRowIndexes:(CPIndexSet)rows
{
[super _performSelection:select forRow:rowIndex context:context];
if (_disclosureControlsForRows.length)
{
var indexes = [_selectedRowIndexes copy];
[indexes removeIndexesInRange:CPMakeRange(_disclosureControlsForRows.length, _itemsForRows.length - _disclosureControlsForRows.length)];
[[_disclosureControlsForRows objectsAtIndexes:indexes] makeObjectsPerformSelector:@selector(unsetThemeState:) withObject:CPThemeStateSelected];
}
var control = _disclosureControlsForRows[rowIndex],
selector = select ? @"setThemeState:" : @"unsetThemeState:";
[super _setSelectedRowIndexes:rows];
[control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
if (_disclosureControlsForRows.length)
{
var indexes = [_selectedRowIndexes copy];
[indexes removeIndexesInRange:CPMakeRange(_disclosureControlsForRows.length, _itemsForRows.length - _disclosureControlsForRows.length)];
[[_disclosureControlsForRows objectsAtIndexes:indexes] makeObjectsPerformSelector:@selector(setThemeState:) withObject:CPThemeStateSelected];
}
}
/*!
@@ -871,6 +889,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
var delegateMethods = [
CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ , @selector(outlineView:dataViewForTableColumn:item:),
CPOutlineViewDelegate_outlineView_viewForTableColumn_item_ , @selector(outlineView:viewForTableColumn:item:),
CPOutlineViewDelegate_outlineView_didClickTableColumn_ , @selector(outlineView:didClickTableColumn:),
CPOutlineViewDelegate_outlineView_didDragTableColumn_ , @selector(outlineView:didDragTableColumn:),
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ , @selector(outlineView:heightOfRowByItem:),
@@ -963,6 +982,10 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
name:CPOutlineViewItemDidCollapseNotification
object:self];
[self _updateIsViewBased];
if ([self _delegateRespondsToDataViewForTableColumn])
CPLog.warn("outlineView:dataViewForTableColumn:item: is deprecated. You should use -outlineView:viewForTableColumn:item: where you can request the view with -makeViewWithIdentifier:owner:");
}
- (BOOL)_sendDelegateDeleteKeyPressed
@@ -1055,12 +1078,12 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
@ignore
We need to offset the dataview and add the disclosure triangle.
*/
- (CPView)_dragViewForColumn:(int)theColumnIndex event:(CPEvent)theDragEvent offset:(CGPoint)theDragViewOffset
- (CPView)_dragViewForColumn:(CPInteger)theColumnIndex event:(CPEvent)theDragEvent offset:(CGPoint)theDragViewOffset
{
var dragView = [[_CPColumnDragView alloc] initWithLineColor:[self gridColor]],
tableColumn = [[self tableColumns] objectAtIndex:theColumnIndex],
defaultRowHeight = [self valueForThemeAttribute:@"default-row-height"],
bounds = _CGRectMake(0.0, 0.0, [tableColumn width], _CGRectGetHeight([self exposedRect]) + defaultRowHeight),
bounds = CGRectMake(0.0, 0.0, [tableColumn width], CGRectGetHeight([self exposedRect]) + defaultRowHeight),
columnRect = [self rectOfColumn:theColumnIndex],
headerView = [tableColumn headerView],
row = [_exposedRows firstIndex];
@@ -1074,7 +1097,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
dataViewFrame.origin.x = 0.0;
// Offset by table header height - scroll position
dataViewFrame.origin.y = ( _CGRectGetMinY(dataViewFrame) - _CGRectGetMinY([self exposedRect]) ) + defaultRowHeight;
dataViewFrame.origin.y = (CGRectGetMinY(dataViewFrame) - CGRectGetMinY([self exposedRect])) + defaultRowHeight;
[dataView setFrame:dataViewFrame];
[dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]];
@@ -1098,7 +1121,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
// Add the column header view
var headerFrame = [headerView frame];
headerFrame.origin = _CGPointMakeZero();
headerFrame.origin = CGPointMakeZero();
var columnHeaderView = [[_CPTableColumnHeaderView alloc] initWithFrame:headerFrame];
[columnHeaderView setStringValue:[headerView stringValue]];
@@ -1188,7 +1211,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
/*!
@ignore
*/
- (id)_parentItemForUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex atMouseOffset:(CGPoint)theOffset
- (id)_parentItemForUpperRow:(CPInteger)theUpperRowIndex andLowerRow:(CPInteger)theLowerRowIndex atMouseOffset:(CGPoint)theOffset
{
if (_shouldRetargetItem)
return _retargetedItem;
@@ -1218,7 +1241,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
/*!
@ignore
*/
- (CGRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(CGPoint)theOffset
- (CGRect)_rectForDropHighlightViewBetweenUpperRow:(CPInteger)theUpperRowIndex andLowerRow:(CPInteger)theLowerRowIndex offset:(CGPoint)theOffset
{
// Call super and the update x to reflect the current indentation level
var rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theOffset],
@@ -1304,7 +1327,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
var disclosureControlFrame = [self frameOfOutlineDisclosureControlAtRow:row];
if (_CGRectIsEmpty(disclosureControlFrame))
if (CGRectIsEmpty(disclosureControlFrame))
continue;
var control = [self _dequeueDisclosureControl];
@@ -1361,7 +1384,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
- (void)_toggleFromDisclosureControl:(CPControl)aControl
{
var controlFrame = [aControl frame],
item = [self itemAtRow:[self rowAtPoint:_CGPointMake(_CGRectGetMinX(controlFrame), _CGRectGetMidY(controlFrame))]];
item = [self itemAtRow:[self rowAtPoint:CGPointMake(CGRectGetMinX(controlFrame), CGRectGetMidY(controlFrame))]];
if ([self isItemExpanded:item])
[self collapseItem:item];
@@ -1534,16 +1557,59 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
[super keyDown:anEvent];
}
- (CPView)_sendDelegateViewForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRow
{
return [_outlineViewDelegate outlineView:self viewForTableColumn:aTableColumn item:[self itemAtRow:aRow]];
}
- (CPView)_sendDelegateDataViewForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRow
{
return [_outlineViewDelegate outlineView:self dataViewForTableColumn:aTableColumn item:[self itemAtRow:aRow]];
}
- (BOOL)_dataSourceRespondsToObjectValueForTableColumn
{
return _implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_objectValue_forTableColumn_byItem_;
}
- (BOOL)_delegateRespondsToViewForTableColumn
{
return _implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_viewForTableColumn_item_;
}
- (BOOL)_delegateRespondsToDataViewForTableColumn
{
return _implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_;
}
- (BOOL)_delegateRespondsToShouldExpandItem
{
return _implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldExpandItem_;
}
- (BOOL)_delegateRespondsToShouldCollapseItem
{
return _implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldCollapseItem_;
}
/*!
@ignore
Return YES if the delegate implements outlineView:selectionIndexesForProposedSelection
*/
- (BOOL)_delegateRespondsToSelectionIndexesForProposedSelection
{
return _implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_selectionIndexesForProposedSelection_;
}
/*!
@ignore
Return YES if the delegate implements outlineView:shouldSelectItem:
*/
- (BOOL)_delegateRespondsToShouldSelectRow
{
return _implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_;
}
@end
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
@@ -1741,7 +1807,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard];
}
- (int)_childIndexForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CGPoint)theOffset
- (int)_childIndexForDropOperation:(CPTableViewDropOperation)theDropOperation row:(CPInteger)theRow offset:(CGPoint)theOffset
{
if (_outlineView._shouldRetargetChildIndex)
return _outlineView._retargedChildIndex;
@@ -1765,7 +1831,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return childIndex;
}
- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CGPoint)theOffset
- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(CPInteger)theRow offset:(CGPoint)theOffset
{
if (theDropOperation === CPTableViewDropAbove)
return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset]
@@ -1773,8 +1839,8 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return [_outlineView itemAtRow:theRow];
}
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id < CPDraggingInfo >)theInfo
proposedRow:(int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id /*< CPDraggingInfo >*/)theInfo
proposedRow:(CPInteger)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation
{
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_))
return CPDragOperationNone;
@@ -1793,7 +1859,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex];
}
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id <CPDraggingInfo>)theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id /*<CPDraggingInfo>*/)theInfo row:(CPInteger)theRow dropOperation:(CPTableViewDropOperation)theOperation
{
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_))
return NO;
@@ -1837,7 +1903,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return self;
}
- (BOOL)tableView:(CPTableView)theTableView shouldSelectRow:(int)theRow
- (BOOL)tableView:(CPTableView)theTableView shouldSelectRow:(CPInteger)theRow
{
return SHOULD_SELECT_ITEM(_outlineView, [_outlineView itemAtRow:theRow]);
}
@@ -1847,7 +1913,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return SELECTION_SHOULD_CHANGE(_outlineView);
}
- (BOOL)tableView:(CPTableView)aTableView shouldEditTableColumn:(CPTableColumn)aColumn row:(int)aRow
- (BOOL)tableView:(CPTableView)aTableView shouldEditTableColumn:(CPTableColumn)aColumn row:(CPInteger)aRow
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldEditTableColumn_item_))
return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldEditTableColumn:aColumn item:[_outlineView itemAtRow:aRow]];
@@ -1855,7 +1921,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return NO;
}
- (float)tableView:(CPTableView)theTableView heightOfRow:(int)theRow
- (float)tableView:(CPTableView)theTableView heightOfRow:(CPInteger)theRow
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_heightOfRowByItem_))
return [_outlineView._outlineViewDelegate outlineView:_outlineView heightOfRowByItem:[_outlineView itemAtRow:theRow]];
@@ -1863,7 +1929,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return [theTableView rowHeight];
}
- (void)tableView:(CPTableView)aTableView willDisplayView:(id)aView forTableColumn:(CPTableColumn)aTableColumn row:(int)aRowIndex
- (void)tableView:(CPTableView)aTableView willDisplayView:(id)aView forTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_))
{
@@ -1872,7 +1938,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
}
}
- (BOOL)tableView:(CPTableView)aTableView isGroupRow:(int)aRow
- (BOOL)tableView:(CPTableView)aTableView isGroupRow:(CPInteger)aRow
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_isGroupItem_))
return [_outlineView._outlineViewDelegate outlineView:_outlineView isGroupItem:[_outlineView itemAtRow:aRow]];
@@ -1880,7 +1946,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return NO;
}
- (CPMenu)tableView:(CPTableView)aTableView menuForTableColumn:(CPTableColumn)aTableColumn row:(int)aRow
- (CPMenu)tableView:(CPTableView)aTableView menuForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRow
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_menuForTableColumn_item_))
{
@@ -1893,15 +1959,20 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return [_outlineView menu] || [[_outlineView class] defaultMenu];
}
- (CPView)tableView:(CPTableView)aTableView dataViewForTableColumn:(CPTableColumn)aTableColumn row:(int)aRow
- (CPIndexSet)tableView:(CPTableView)aTableView selectionIndexesForProposedSelection:(CPIndexSet)anIndexSet
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_))
{
var item = [_outlineView itemAtRow:aRow];
return [_outlineView._outlineViewDelegate outlineView:_outlineView dataViewForTableColumn:aTableColumn item:item]
}
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_selectionIndexesForProposedSelection_))
return [_outlineView._outlineViewDelegate outlineView:_outlineView selectionIndexesForProposedSelection:anIndexSet];
return nil;
return anIndexSet;
}
- (BOOL)tableView:(CPTableView)aTableView shouldSelectTableColumn:(CPTableColumn)aTableColumn
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_))
return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldSelectTableColumn:aTableColumn];
return YES;
}
@end
@@ -1921,7 +1992,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return self;
}
- (void)setState:(CPState)aState
- (void)setState:(CPInteger)aState
{
[super setState:aState];
@@ -1936,14 +2007,14 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
{
var bounds = [self bounds],
context = [[CPGraphicsContext currentContext] graphicsPort],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
width = CGRectGetWidth(bounds),
height = CGRectGetHeight(bounds);
CGContextBeginPath(context);
if (_angle)
{
var centre = _CGPointMake(FLOOR(width / 2.0), FLOOR(height / 2.0));
var centre = CGPointMake(FLOOR(width / 2.0), FLOOR(height / 2.0));
CGContextTranslateCTM(context, centre.x, centre.y);
CGContextRotateCTM(context, _angle);
CGContextTranslateCTM(context, -centre.x, -centre.y);
@@ -2007,6 +2078,8 @@ var CPOutlineViewIndentationPerLevelKey = @"CPOutlineViewIndentationPerLevelKey"
[super setDataSource:[[_CPOutlineViewTableViewDataSource alloc] initWithOutlineView:self]];
[super setDelegate:[[_CPOutlineViewTableViewDelegate alloc] initWithOutlineView:self]];
[self _updateIsViewBased];
}
return self;
+11 -4
View File
@@ -191,10 +191,12 @@ var CPPasteboards = nil,
_owners = @{};
_provided = @{};
var count = _types.length;
while (count--)
[_owners setObject:anOwner forKey:_types[count]];
if (anOwner)
{
var count = _types.length;
while (count--)
[_owners setObject:anOwner forKey:_types[count]];
}
if (_nativePasteboard && shouldUpdate)
{
@@ -205,6 +207,7 @@ var CPPasteboards = nil,
_nativePasteboard.declareTypes_(nativeTypes);
_changeCount = _nativePasteboard.changeCount();
}
return ++_changeCount;
}
@@ -243,6 +246,10 @@ var CPPasteboards = nil,
*/
- (void)setString:(CPString)aString forType:(CPString)aType
{
// Putting a non-string on the string pasteboard can lead to strange crashes.
if (aString && aString.isa && ![aString isKindOfClass:CPString])
[CPException raise:CPInvalidArgumentException reason:"CPPasteboard setString:forType: must be called with a string."];
[self setPropertyList:aString forType:aType];
}
+12 -7
View File
@@ -279,7 +279,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
Selects the item at the specified index
@param anIndex the index of the item to select
*/
- (void)setObjectValue:(int)anIndex
- (void)setObjectValue:(id)anIndex
{
var indexOfSelectedItem = [self objectValue];
@@ -344,7 +344,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
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
- (CPMenuItem)itemAtIndex:(CPUInteger)anIndex
{
return [[self menu] itemAtIndex:anIndex];
}
@@ -353,7 +353,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
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
- (CPString)itemTitleAtIndex:(CPUInteger)anIndex
{
return [[[self menu] itemAtIndex:anIndex] title];
}
@@ -667,10 +667,15 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if (![self isEnabled] || ![self numberOfItems])
return;
var menu = [self menu];
// Don't reopen the menu based on the same click which caused it to close, e.g. a click on this button.
if (menu._lastCloseEvent === anEvent)
return;
[self highlight:YES];
var menu = [self menu],
bounds = [self bounds],
var bounds = [self bounds],
minimumWidth = CGRectGetWidth(bounds);
// FIXME: setFont: should set the font on the menu.
@@ -833,7 +838,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
[self _setContentValuesIfNeeded:contentArray];
}
- (void)valueForBinding:(CPString)aBinding
- (id)valueForBinding:(CPString)aBinding
{
return [self _content];
}
@@ -905,7 +910,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
- (void)setValue:(CPArray)aValue forBinding:(CPString)aBinding
{
[super _setContent:aValue];
}
+16 -1
View File
@@ -63,7 +63,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
@outlet CPViewController _contentViewController @accessors(property=contentViewController);
@outlet id _delegate @accessors(getter=delegate);
BOOL _animates @accessors(property=animates);
BOOL _animates @accessors(getter=animates);
int _appearance @accessors(property=appearance);
int _behavior @accessors(getter=behavior);
@@ -153,6 +153,20 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
return [_popoverWindow isVisible];
}
/*!
Set if the popover should animate for open/close actions.
@param shouldAnimate if YES, the popover will be animated.
*/
- (void)setAnimates:(BOOL)shouldAnimate
{
if (_animates == shouldAnimate)
return;
_animates = shouldAnimate;
[_popoverWindow setAnimates:_animates];
}
/*!
Set the behavior of the CPPopover. It can be:
@@ -224,6 +238,7 @@ Set the behavior of the CPPopover. It can be:
_popoverWindow = [[_CPPopoverWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:[self styleMaskForBehavior]];
}
[_popoverWindow setPlatformWindow:[[positioningView window] platformWindow]];
[_popoverWindow setAppearance:_appearance];
[_popoverWindow setAnimates:_animates];
[_popoverWindow setDelegate:self];
+2 -2
View File
@@ -371,7 +371,7 @@ var CPProgressIndicatorSpinningStyleColors = [];
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
return [[CPView alloc] initWithFrame:CGRectMakeZero()];
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
@@ -387,7 +387,7 @@ var CPProgressIndicatorSpinningStyleColors = [];
if (_indeterminate)
barWidth = width;
return _CGRectMake(0, 0, barWidth, [self valueForThemeAttribute:@"default-height"]);
return CGRectMake(0, 0, barWidth, [self valueForThemeAttribute:@"default-height"]);
}
return nil;
+1 -1
View File
@@ -152,7 +152,7 @@ CPRadioImageOffset = 4.0;
[_radioGroup _setSelectedRadio:self];
}
- (void)sendAction:(SEL)anAction to:(id)anObject
- (BOOL)sendAction:(SEL)anAction to:(id)anObject
{
[super sendAction:anAction to:anObject];
+1 -1
View File
@@ -356,7 +356,7 @@ CPDeleteForwardKeyCode = 46;
var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
CPResponderMenuKey = @"CPResponderMenuKey";
@implementation CPResponder (CPCoding)
@implementation CPResponder (CPCoding) <CPCoding>
/*!
Initializes the responder with data from a coder.
+5 -5
View File
@@ -484,7 +484,7 @@
#pragma mark RuleEditor delegate methods
- (int)_queryNumberOfChildrenOfItem:(id)rowItem withRowType:(int)type
- (int)_queryNumberOfChildrenOfItem:(id)rowItem withRowType:(CPRuleEditorRowType)type
{
if (rowItem == nil)
{
@@ -494,7 +494,7 @@
return [[rowItem children] count];
}
- (id)_queryChild:(int)childIndex ofItem:(id)rowItem withRowType:(int)type
- (id)_queryChild:(int)childIndex ofItem:(id)rowItem withRowType:(CPRuleEditorRowType)type
{
if (rowItem == nil)
{
@@ -505,7 +505,7 @@
return [[rowItem children] objectAtIndex:childIndex];
}
- (id)_queryValueForItem:(id)rowItem inRow:(int)rowIndex
- (id)_queryValueForItem:(id)rowItem inRow:(CPInteger)rowIndex
{
return [rowItem displayValue];
}
@@ -516,7 +516,7 @@ var CPPredicateTemplatesKey = @"CPPredicateTemplates";
@implementation CPPredicateEditor (CPCoding)
- (id)initWithCoder:(id)aCoder
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
@@ -531,7 +531,7 @@ var CPPredicateTemplatesKey = @"CPPredicateTemplates";
return self;
}
- (void)encodeWithCoder:(id)aCoder
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_allTemplates forKey:CPPredicateTemplatesKey];
@@ -702,12 +702,12 @@ CPTransformableAttributeType = 1800;
return textField;
}
- (void)_setOptions:(unsigned int)options
- (void)_setOptions:(unsigned)options
{
_predicateOptions = options;
}
- (void)_setModifier:(unsigned int)modifier
- (void)_setModifier:(unsigned)modifier
{
_predicateModifier = modifier;
}
+27 -27
View File
@@ -122,7 +122,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
return @"rule-editor";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"alternating-row-colors": [CPNull null],
@@ -461,7 +461,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
@param row The index of a row in the receiver.
@return The currently chosen items for row @a row.
*/
- (id)criteriaForRow:(int)row
- (id)criteriaForRow:(CPInteger)row
{
var rowcache = [self _rowCacheForIndex:row];
if (rowcache)
@@ -480,7 +480,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
@return The chosen values (strings, views, or menu items) for row row.
@discussion The values returned are the same as those returned from the delegate method -#ruleEditor:displayValueForCriterion:inRow:
*/
- (CPMutableArray)displayValuesForRow:(int)row
- (CPMutableArray)displayValuesForRow:(CPInteger)row
{
var rowcache = [self _rowCacheForIndex:row];
if (rowcache)
@@ -503,7 +503,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
@param rowIndex The index of a row in the receiver.
@return The index of the parent of the row at @a rowIndex. If the row at @a rowIndex is a root row, returns @c -1.
*/
- (int)parentRowForRow:(int)rowIndex
- (int)parentRowForRow:(CPInteger)rowIndex
{
if (rowIndex < 0 || rowIndex >= [self numberOfRows])
[CPException raise:CPRangeException reason:_cmd + @" row " + rowIndex + " is out of range"];
@@ -544,7 +544,7 @@ TODO: implement
@return The type of the row at @a rowIndex.
@warning Raises a @c CPRangeException if rowIndex is less than @c 0 or greater than or equal to the number of rows.
*/
- (CPRuleEditorRowType)rowTypeForRow:(int)rowIndex
- (CPRuleEditorRowType)rowTypeForRow:(CPInteger)rowIndex
{
if (rowIndex < 0 || rowIndex > [self numberOfRows])
[CPException raise:CPRangeException reason:_cmd + @"row " + rowIndex + " is out of range"];
@@ -565,7 +565,7 @@ TODO: implement
@return The immediate subrows of the row at @a rowIndex.
@discussion Rows are numbered starting at @c 0.
*/
- (CPIndexSet)subrowIndexesForRow:(int)rowIndex
- (CPIndexSet)subrowIndexesForRow:(CPInteger)rowIndex
{
var object;
@@ -691,7 +691,7 @@ TODO: implement
@note Currently, @a shouldAnimate has no effect, rows are always animated when calling this method.
@see addRow:
*/
- (void)insertRowAtIndex:(int)rowIndex withType:(unsigned int)rowType asSubrowOfRow:(int)parentRow animate:(BOOL)shouldAnimate
- (void)insertRowAtIndex:(int)rowIndex withType:(unsigned int)rowType asSubrowOfRow:(CPInteger)parentRow animate:(BOOL)shouldAnimate
{
/*
TODO: raise exceptions if parentRow is greater than or equal to rowIndex, or if rowIndex would fall amongst the children of some other parent, or if the nesting mode forbids this configuration.
@@ -1313,7 +1313,7 @@ TODO: implement
return [_boundArrayOwner mutableArrayValueForKey:_boundArrayKeyPath];
}
- (BOOL)_nextUnusedItems:(CPArray)items andValues:(CPArray)values forRow:(int)rowIndex forRowType:(unsigned int)type
- (BOOL)_nextUnusedItems:(CPArray)items andValues:(CPArray)values forRow:(CPInteger)rowIndex forRowType:(unsigned int)type
{
var parentItem = [items lastObject], // if empty items array, this is NULL aka the root item;
childrenCount = [self _queryNumberOfChildrenOfItem:parentItem withRowType:type],
@@ -1375,7 +1375,7 @@ TODO: implement
return YES;
}
- (CPMutableArray)_getItemsAndValuesToAddForRow:(int)rowIndex ofType:(CPRuleEditorRowType)type
- (CPMutableArray)_getItemsAndValuesToAddForRow:(CPInteger)rowIndex ofType:(CPRuleEditorRowType)type
{
//var cachedItemsAndValues = _itemsAndValuesToAddForRowType[type];
//if (cachedItemsAndValues)
@@ -1418,7 +1418,7 @@ TODO: implement
[self insertRowAtIndex:insertIndex withType:type asSubrowOfRow:parentRowIndex animate:YES];
}
- (id)_insertNewRowAtIndex:(int)insertIndex ofType:(CPRuleEditorRowType)rowtype withParentRow:(int)parentRowIndex
- (id)_insertNewRowAtIndex:(int)insertIndex ofType:(CPRuleEditorRowType)rowtype withParentRow:(CPInteger)parentRowIndex
{
var row = [[[self rowClass] alloc] init],
itemsandvalues = [self _getItemsAndValuesToAddForRow:insertIndex ofType:rowtype],
@@ -1520,7 +1520,7 @@ TODO: implement
}
}
- (void)_changedItem:(id)fromItem toItem:(id)toItem inRow:(int)aRow atCriteriaIndex:(int)fromItemIndex
- (void)_changedItem:(id)fromItem toItem:(id)toItem inRow:(CPInteger)aRow atCriteriaIndex:(int)fromItemIndex
{
var criteria = [self criteriaForRow:aRow],
displayValues = [self displayValuesForRow:aRow],
@@ -1684,7 +1684,7 @@ TODO: implement
[super bind:aBinding toObject:observableController withKeyPath:aKeyPath options:options];
}
- (void)unbind:(id)object
- (void)unbind:(CPString)object
{
_rowClass = [_CPRuleEditorRowObject class];
[super unbind:object];
@@ -2005,7 +2005,7 @@ TODO: implement
return [_ruleDelegate ruleEditor:self child:childIndex forCriterion:item withRowType:type];
}
- (id)_queryValueForItem:(id)item inRow:(int)row
- (id)_queryValueForItem:(id)item inRow:(CPInteger)row
{
return [_ruleDelegate ruleEditor:self displayValueForCriterion:item inRow:row];
}
@@ -2026,12 +2026,12 @@ TODO: implement
_alignmentGridWidth = width;
}
- (BOOL)_validateItem:(id)item value:(id)value inRow:(int)row
- (BOOL)_validateItem:(id)item value:(id)value inRow:(CPInteger)row
{
return [self _queryCanSelectItem:item displayValue:value inRow:row];
}
- (BOOL)_queryCanSelectItem:(id)item displayValue:(id)value inRow:(int)row
- (BOOL)_queryCanSelectItem:(id)item displayValue:(id)value inRow:(CPInteger)row
{
return YES;
}
@@ -2128,7 +2128,7 @@ TODO: implement
return YES;
}
- (CPDragOperation)draggingEntered:(id < CPDraggingInfo >)sender
- (CPDragOperation)draggingEntered:(id /*< CPDraggingInfo >*/)sender
{
if ([sender draggingSource] === self)
{
@@ -2158,7 +2158,7 @@ TODO: implement
_subviewIndexOfDropLine = CPNotFound;
}
- (CPDragOperation)draggingUpdated:(id <CPDraggingInfo>)sender
- (CPDragOperation)draggingUpdated:(id /*<CPDraggingInfo>*/)sender
{
var point = [self convertPoint:[sender draggingLocation] fromView:nil],
y = point.y + _sliceHeight / 2,
@@ -2195,12 +2195,12 @@ TODO: implement
return CPDragOperationMove;
}
- (BOOL)prepareForDragOperation:(id < CPDraggingInfo >)sender
- (BOOL)prepareForDragOperation:(id /*< CPDraggingInfo >*/)sender
{
return (_subviewIndexOfDropLine !== CPNotFound);
}
- (BOOL)performDragOperation:(id < CPDraggingInfo >)info
- (BOOL)performDragOperation:(id /*< CPDraggingInfo >*/)info
{
var aboveInsertIndexCount = 0,
object,
@@ -2262,7 +2262,7 @@ TODO: implement
{
}
- (void)_setWindow:(id)window
- (void)_setWindow:(CPWindow)window
{
[super _setWindow:window];
}
@@ -2279,7 +2279,7 @@ TODO: implement
- (void)_postRowCountChangedNotificationOfType:(CPString)notificationName indexes:indexes
{
var userInfo = @{ "indexes": indexes };
var userInfo = indexes === nil ? @{} : @{ "indexes": indexes };
[[CPNotificationCenter defaultCenter] postNotificationName:notificationName object:self userInfo:userInfo];
}
@@ -2325,7 +2325,7 @@ TODO: implement
return YES;
}
- (void)_getAllAvailableItems:(id)items values:(id)values asChildrenOfItem:(id)parentItem inRow:(int)aRow
- (void)_getAllAvailableItems:(id)items values:(id)values asChildrenOfItem:(id)parentItem inRow:(CPInteger)aRow
{
var type,
indexofCriterion,
@@ -2426,7 +2426,7 @@ var CPRuleEditorAlignmentGridWidthKey = @"CPRuleEditorAlignmentGridWidth",
return self;
}
- (void)encodeWithCoder:(id)coder
- (void)encodeWithCoder:(CPCoder)coder
{
[super encodeWithCoder:coder];
@@ -2481,7 +2481,7 @@ var CriteriaKey = @"criteria",
return "<" + [self className] + ">\nsubrows = " + [subrows description] + "\ncriteria = " + [criteria description] + "\ndisplayValues = " + [displayValues description];
}
- (id)initWithCoder:(id)coder
- (id)initWithCoder:(CPCoder)coder
{
self = [super init];
if (self !== nil)
@@ -2495,7 +2495,7 @@ var CriteriaKey = @"criteria",
return self;
}
- (void)encodeWithCoder:(id)coder
- (void)encodeWithCoder:(CPCoder)coder
{
[coder encodeObject:subrows forKey:SubrowsKey];
[coder encodeObject:criteria forKey:CriteriaKey];
@@ -2534,7 +2534,7 @@ var CPBoundArrayKey = @"CPBoundArray";
return self;
}
- (id)initWithCoder:(id)coder
- (id)initWithCoder:(CPCoder)coder
{
if (self = [super init])
boundArray = [coder decodeObjectForKey:CPBoundArrayKey];
@@ -2542,7 +2542,7 @@ var CPBoundArrayKey = @"CPBoundArray";
return self;
}
- (void)encodeWithCoder:(id)coder
- (void)encodeWithCoder:(CPCoder)coder
{
[coder encodeObject:boundArray forKey:CPBoundArrayKey];
}
@@ -86,7 +86,7 @@ else if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
return self;
}
- (id)hitTest:(CGPoint)point
- (CPView)hitTest:(CGPoint)point
{
if (!CGRectContainsPoint([self frame], point) || ![self sliceIsEditable])
return nil;
@@ -100,12 +100,12 @@ else if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
return ![superview isKindOfClass:[_CPRuleEditorViewSlice]] || [superview isEditable];
}
- (BOOL)trackMouse:(CPEvent)theEvent
- (void)trackMouse:(CPEvent)theEvent
{
if (![self sliceIsEditable])
return NO;
return;
return [super trackMouse:theEvent];
[super trackMouse:theEvent];
}
- (CGRect)contentRectForBounds:(CGRect)bounds
+2 -2
View File
@@ -53,8 +53,8 @@
if (select == _selected)
return;
var selector = select ? @"setThemeState:" : @"unsetThemeState:";
[[self subviews] makeObjectsPerformSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelectedDataView];
var selector = select ? @selector(setThemeState:) : @selector(unsetThemeState:);
[[self subviews] makeObjectsPerformSelector:selector withObject:CPThemeStateSelectedDataView];
_selected = select;
}
@@ -522,7 +522,7 @@ var CONTROL_HEIGHT = 16.,
return self;
}
- (id)hitTest:(CGPoint)point
- (CPView)hitTest:(CGPoint)point
{
if (!CGRectContainsPoint([self frame], point))
return nil;
+2 -2
View File
@@ -43,9 +43,9 @@
- (CGRect)visibleFrame
{
#if PLATFORM(DOM)
return _CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight);
return CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight);
#else
return _CGRectMakeZero();
return CGRectMakeZero();
#endif
}
+77 -67
View File
@@ -34,34 +34,44 @@
/*! @ignore */
var _isSystemUsingOverlayScrollers = function()
var _isBrowserUsingOverlayScrollers = function()
{
#if PLATFORM(DOM)
var inner = document.createElement('p'),
outer = document.createElement('div');
/*
Even if the system supports overlay (Lion) scrollers,
the browser (e.g. FireFox *cough*) may not.
inner.style.width = "100%";
inner.style.height = "200px";
To determine if the browser is using overlay scrollbars,
we put a <p> element inside a shorter <div> and set its
overflow to scroll. If the browser is using visible scrollers,
the outer div's clientWidth will less than the offsetWidth, because
clientWidth does not include scrollbars, whereas offsetWidth does.
So if clientWidth === offsetWidth, the scrollers must be overlay.
Even IE gets this right.
*/
var outer = document.createElement('div'),
inner = document.createElement('p');
// position it absolute so it doesn't affect existing DOM elements
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild (inner);
outer.style.overflow = "scroll";
document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2)
w2 = outer.clientWidth;
inner.style.width = "100%";
inner.style.height = "200px";
outer.appendChild(inner);
document.body.removeChild (outer);
document.body.appendChild(outer);
return (w1 - w2 == 0);
var usingOverlayScrollers = outer.clientWidth === outer.offsetWidth;
document.body.removeChild(outer);
return usingOverlayScrollers;
#else
return NO;
#endif
@@ -130,8 +140,8 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
var globalValue = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPScrollersGlobalStyle"];
if (globalValue == nil || globalValue == -1)
CPScrollerStyleGlobal = _isSystemUsingOverlayScrollers() ? CPScrollerStyleOverlay : CPScrollerStyleLegacy
if (globalValue === nil || globalValue === -1)
CPScrollerStyleGlobal = _isBrowserUsingOverlayScrollers() ? CPScrollerStyleOverlay : CPScrollerStyleLegacy
else
CPScrollerStyleGlobal = globalValue;
}
@@ -151,7 +161,7 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
+ (CGSize)contentSizeForFrameSize:(CGSize)frameSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType
{
var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType],
var bounds = [self _insetBounds:CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType],
scrollerWidth = [CPScroller scrollerWidth];
if (hFlag)
@@ -165,10 +175,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
+ (CGSize)frameSizeForContentSize:(CGSize)contentSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType
{
var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) borderType:borderType],
var bounds = [self _insetBounds:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) borderType:borderType],
widthInset = contentSize.width - bounds.size.width,
heightInset = contentSize.height - bounds.size.height,
frameSize = _CGSizeMake(contentSize.width + widthInset, contentSize.height + heightInset),
frameSize = CGSizeMake(contentSize.width + widthInset, contentSize.height + heightInset),
scrollerWidth = [CPScroller scrollerWidth];
if (hFlag)
@@ -186,10 +196,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
{
case CPLineBorder:
case CPBezelBorder:
return _CGRectInset(bounds, 1.0, 1.0);
return CGRectInset(bounds, 1.0, 1.0);
case CPGrooveBorder:
bounds = _CGRectInset(bounds, 2.0, 2.0);
bounds = CGRectInset(bounds, 2.0, 2.0);
++bounds.origin.y;
--bounds.size.height;
return bounds;
@@ -517,8 +527,8 @@ Notifies the delegate when the scroll view has finished scrolling.
{
var bounds = [self _insetBounds];
[self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1), [CPScroller scrollerWidthInStyle:_scrollerStyle])]];
[[self horizontalScroller] setFrameSize:CGSizeMake(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle])];
[self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1), [CPScroller scrollerWidthInStyle:_scrollerStyle])]];
[[self horizontalScroller] setFrameSize:CGSizeMake(CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle])];
}
[self reflectScrolledClipView:_contentView];
@@ -582,8 +592,8 @@ Notifies the delegate when the scroll view has finished scrolling.
{
var bounds = [self _insetBounds];
[self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidthInStyle:_scrollerStyle], MAX(_CGRectGetHeight(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1))]];
[[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidthInStyle:_scrollerStyle], _CGRectGetHeight(bounds))];
[self setVerticalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, [CPScroller scrollerWidthInStyle:_scrollerStyle], MAX(CGRectGetHeight(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1))]];
[[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidthInStyle:_scrollerStyle], CGRectGetHeight(bounds))];
}
[self reflectScrolledClipView:_contentView];
@@ -859,13 +869,13 @@ Notifies the delegate when the scroll view has finished scrolling.
- (CGRect)_cornerViewFrame
{
if (!_cornerView)
return _CGRectMakeZero();
return CGRectMakeZero();
var bounds = [self _insetBounds],
frame = [_cornerView frame];
frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame);
frame.origin.y = _CGRectGetMinY(bounds);
frame.origin.x = CGRectGetMaxX(bounds) - CGRectGetWidth(frame);
frame.origin.y = CGRectGetMinY(bounds);
return frame;
}
@@ -876,14 +886,14 @@ Notifies the delegate when the scroll view has finished scrolling.
var headerView = [self _headerView];
if (!headerView)
return _CGRectMakeZero();
return CGRectMakeZero();
var frame = [self _insetBounds];
frame.size.height = _CGRectGetHeight([headerView frame]);
frame.size.height = CGRectGetHeight([headerView frame]);
if (SHOULD_SHOW_CORNER_VIEW())
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
frame.size.width -= CGRectGetWidth([self _cornerViewFrame]);
return frame;
}
@@ -924,18 +934,18 @@ Notifies the delegate when the scroll view has finished scrolling.
break;
case CPScrollerDecrementPage:
contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
contentBounds.origin.y -= CGRectGetHeight(contentBounds) - _verticalPageScroll;
break;
case CPScrollerIncrementPage:
contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
contentBounds.origin.y += CGRectGetHeight(contentBounds) - _verticalPageScroll;
break;
// We want integral bounds!
case CPScrollerKnobSlot:
case CPScrollerKnob:
default:
contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)));
contentBounds.origin.y = ROUND(value * (CGRectGetHeight(documentFrame) - CGRectGetHeight(contentBounds)));
}
[self _sendDelegateMessages];
@@ -961,18 +971,18 @@ Notifies the delegate when the scroll view has finished scrolling.
break;
case CPScrollerDecrementPage:
contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
contentBounds.origin.x -= CGRectGetWidth(contentBounds) - _horizontalPageScroll;
break;
case CPScrollerIncrementPage:
contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
contentBounds.origin.x += CGRectGetWidth(contentBounds) - _horizontalPageScroll;
break;
// We want integral bounds!
case CPScrollerKnobSlot:
case CPScrollerKnob:
default:
contentBounds.origin.x = ROUND(value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds)));
contentBounds.origin.x = ROUND(value * (CGRectGetWidth(documentFrame) - CGRectGetWidth(contentBounds)));
}
[self _sendDelegateMessages];
@@ -1096,7 +1106,7 @@ Notifies the delegate when the scroll view has finished scrolling.
}
[_contentView setFrame:[self _insetBounds]];
[_headerClipView setFrame:_CGRectMakeZero()];
[_headerClipView setFrame:CGRectMakeZero()];
--_recursionCount;
@@ -1106,12 +1116,12 @@ Notifies the delegate when the scroll view has finished scrolling.
var documentFrame = [documentView frame], // the size of the whole document
contentFrame = [self _insetBounds], // assume it takes up the entire size of the scrollview (no scrollers)
headerClipViewFrame = [self _headerClipViewFrame],
headerClipViewHeight = _CGRectGetHeight(headerClipViewFrame);
headerClipViewHeight = CGRectGetHeight(headerClipViewFrame);
contentFrame.origin.y += headerClipViewHeight;
contentFrame.size.height -= headerClipViewHeight;
var difference = _CGSizeMake(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentFrame), _CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentFrame)),
var difference = CGSizeMake(CGRectGetWidth(documentFrame) - CGRectGetWidth(contentFrame), CGRectGetHeight(documentFrame) - CGRectGetHeight(contentFrame)),
verticalScrollerWidth = [CPScroller scrollerWidthInStyle:[_verticalScroller style]],
horizontalScrollerHeight = [CPScroller scrollerWidthInStyle:[_horizontalScroller style]],
hasVerticalScroll = difference.height > 0.0,
@@ -1162,18 +1172,18 @@ Notifies the delegate when the scroll view has finished scrolling.
if (shouldShowVerticalScroller)
{
var verticalScrollerY =
MAX(_CGRectGetMinY(contentFrame), MAX(_CGRectGetMaxY([self _cornerViewFrame]), _CGRectGetMaxY(headerClipViewFrame)));
MAX(CGRectGetMinY(contentFrame), MAX(CGRectGetMaxY([self _cornerViewFrame]), CGRectGetMaxY(headerClipViewFrame)));
var verticalScrollerHeight = _CGRectGetMaxY(contentFrame) - verticalScrollerY;
var verticalScrollerHeight = CGRectGetMaxY(contentFrame) - verticalScrollerY;
// Make a gap at the bottom of the vertical scroller so that the horizontal and vertical can't overlap.
if (_scrollerStyle === CPScrollerStyleOverlay && hasHorizontalScroll)
verticalScrollerHeight -= horizontalScrollerHeight;
var documentHeight = _CGRectGetHeight(documentFrame);
var documentHeight = CGRectGetHeight(documentFrame);
[_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height];
[_verticalScroller setKnobProportion:documentHeight > 0 ? _CGRectGetHeight(contentFrame) / documentHeight : 1.0];
[_verticalScroller setFrame:_CGRectMake(_CGRectGetMaxX(contentFrame) - overlay, verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)];
[_verticalScroller setKnobProportion:documentHeight > 0 ? CGRectGetHeight(contentFrame) / documentHeight : 1.0];
[_verticalScroller setFrame:CGRectMake(CGRectGetMaxX(contentFrame) - overlay, verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)];
}
else if (wasShowingVerticalScroller)
{
@@ -1183,16 +1193,16 @@ Notifies the delegate when the scroll view has finished scrolling.
if (shouldShowHorizontalScroller)
{
var horizontalScrollerWidth = _CGRectGetWidth(contentFrame);
var horizontalScrollerWidth = CGRectGetWidth(contentFrame);
// Make a gap at the bottom of the vertical scroller so that the horizontal and vertical can't overlap.
if (_scrollerStyle === CPScrollerStyleOverlay && hasVerticalScroll)
horizontalScrollerWidth -= verticalScrollerWidth;
var documentWidth = _CGRectGetWidth(documentFrame);
var documentWidth = CGRectGetWidth(documentFrame);
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
[_horizontalScroller setKnobProportion:documentWidth > 0 ? _CGRectGetWidth(contentFrame) / documentWidth : 1.0];
[_horizontalScroller setFrame:_CGRectMake(_CGRectGetMinX(contentFrame), _CGRectGetMaxY(contentFrame) - overlay, horizontalScrollerWidth, horizontalScrollerHeight)];
[_horizontalScroller setKnobProportion:documentWidth > 0 ? CGRectGetWidth(contentFrame) / documentWidth : 1.0];
[_horizontalScroller setFrame:CGRectMake(CGRectGetMinX(contentFrame), CGRectGetMaxY(contentFrame) - overlay, horizontalScrollerWidth, horizontalScrollerHeight)];
}
else if (wasShowingHorizontalScroller)
{
@@ -1272,7 +1282,7 @@ Notifies the delegate when the scroll view has finished scrolling.
{
case CPLineBorder:
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"border-color"]);
CGContextStrokeRect(context, _CGRectInset(strokeRect, 0.5, 0.5));
CGContextStrokeRect(context, CGRectInset(strokeRect, 0.5, 0.5));
break;
case CPBezelBorder:
@@ -1290,10 +1300,10 @@ Notifies the delegate when the scroll view has finished scrolling.
- (void)_drawGrayBezelInContext:(CGContext)context bounds:(CGRect)aRect
{
var minX = _CGRectGetMinX(aRect),
maxX = _CGRectGetMaxX(aRect),
minY = _CGRectGetMinY(aRect),
maxY = _CGRectGetMaxY(aRect),
var minX = CGRectGetMinX(aRect),
maxX = CGRectGetMaxX(aRect),
minY = CGRectGetMinY(aRect),
maxY = CGRectGetMaxY(aRect),
y = minY + 0.5;
// Slightly darker line on top.
@@ -1324,10 +1334,10 @@ Notifies the delegate when the scroll view has finished scrolling.
- (void)_drawGrooveInContext:(CGContext)context bounds:(CGRect)aRect
{
var minX = _CGRectGetMinX(aRect),
maxX = _CGRectGetMaxX(aRect),
minY = _CGRectGetMinY(aRect),
maxY = _CGRectGetMaxY(aRect);
var minX = CGRectGetMinX(aRect),
maxX = CGRectGetMaxX(aRect),
minY = CGRectGetMinY(aRect),
maxY = CGRectGetMaxY(aRect);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:159.0 / 255.0 alpha:1.0]);
@@ -1357,11 +1367,11 @@ Notifies the delegate when the scroll view has finished scrolling.
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor whiteColor]);
var rect = _CGRectOffset(aRect, 1.0, 1.0);
var rect = CGRectOffset(aRect, 1.0, 1.0);
rect.size.width -= 1.0;
rect.size.height -= 1.0;
CGContextStrokeRect(context, _CGRectInset(rect, 0.5, 0.5));
CGContextStrokeRect(context, CGRectInset(rect, 0.5, 0.5));
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
@@ -1395,29 +1405,29 @@ Notifies the delegate when the scroll view has finished scrolling.
- (void)scrollPageUp:(id)sender
{
var contentBounds = [_contentView bounds];
[self moveByOffset:CGSizeMake(0.0, -(_CGRectGetHeight(contentBounds) - _verticalPageScroll))];
[self moveByOffset:CGSizeMake(0.0, -(CGRectGetHeight(contentBounds) - _verticalPageScroll))];
}
- (void)scrollPageDown:(id)sender
{
var contentBounds = [_contentView bounds];
[self moveByOffset:CGSizeMake(0.0, _CGRectGetHeight(contentBounds) - _verticalPageScroll)];
[self moveByOffset:CGSizeMake(0.0, CGRectGetHeight(contentBounds) - _verticalPageScroll)];
}
- (void)scrollToBeginningOfDocument:(id)sender
{
[_contentView scrollToPoint:_CGPointMakeZero()];
[_headerClipView scrollToPoint:_CGPointMakeZero()];
[_contentView scrollToPoint:CGPointMakeZero()];
[_headerClipView scrollToPoint:CGPointMakeZero()];
}
- (void)scrollToEndOfDocument:(id)sender
{
var contentBounds = [_contentView bounds],
documentFrame = [[self documentView] frame],
scrollPoint = _CGPointMake(0.0, _CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds));
scrollPoint = CGPointMake(0.0, CGRectGetHeight(documentFrame) - CGRectGetHeight(contentBounds));
[_contentView scrollToPoint:scrollPoint];
[_headerClipView scrollToPoint:_CGPointMakeZero()];
[_headerClipView scrollToPoint:CGPointMakeZero()];
}
- (void)moveLeft:(id)sender
+37 -36
View File
@@ -108,7 +108,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
return "scroller";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"scroller-width": 7.0,
@@ -116,11 +116,11 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
@"decrement-line-color": [CPNull null],
@"increment-line-color": [CPNull null],
@"knob-color": [CPNull null],
@"decrement-line-size":_CGSizeMakeZero(),
@"increment-line-size":_CGSizeMakeZero(),
@"track-inset":_CGInsetMakeZero(),
@"knob-inset": _CGInsetMakeZero(),
@"minimum-knob-length":21.0,
@"decrement-line-size": CGSizeMakeZero(),
@"increment-line-size": CGSizeMakeZero(),
@"track-inset": CGInsetMakeZero(),
@"knob-inset": CGInsetMakeZero(),
@"minimum-knob-length": 21.0,
@"track-border-overlay": 9.0
};
}
@@ -182,6 +182,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
_allowFadingOut = YES;
_isMouseOver = NO;
_style = CPScrollerStyleOverlay;
var paramAnimFadeOut = @{
CPViewAnimationTargetKey: self,
CPViewAnimationEffectKey: CPViewAnimationFadeOutEffect,
@@ -194,7 +195,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
// We have to choose an orientation. If for some bizarre reason width === height,
// punt and choose vertical.
[self _setIsVertical:_CGRectGetHeight(aFrame) >= _CGRectGetWidth(aFrame)];
[self _setIsVertical:CGRectGetHeight(aFrame) >= CGRectGetWidth(aFrame)];
}
return self;
@@ -321,7 +322,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
- (CGRect)rectForPart:(CPScrollerPart)aPart
{
if (aPart == CPScrollerNoPart)
return _CGRectMakeZero();
return CGRectMakeZero();
return _partRects[aPart];
}
@@ -391,8 +392,8 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
var knobInset = [self currentValueForThemeAttribute:@"knob-inset"],
trackInset = [self currentValueForThemeAttribute:@"track-inset"],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
width = CGRectGetWidth(bounds),
height = CGRectGetHeight(bounds);
if ([self isVertical])
{
@@ -406,21 +407,21 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
knobHeight = MAX(minimumKnobLength, (slotSize * _knobProportion)),
knobLocation = effectiveDecrementLineHeight + (slotSize - knobHeight) * [self floatValue];
_partRects[CPScrollerDecrementPage] = _CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight);
_partRects[CPScrollerKnob] = _CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight);
_partRects[CPScrollerIncrementPage] = _CGRectMake(0.0, knobLocation + knobHeight, width, height - (knobLocation + knobHeight) - effectiveIncrementLineHeight);
_partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotSize);
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height);
_partRects[CPScrollerDecrementPage] = CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight);
_partRects[CPScrollerKnob] = CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight);
_partRects[CPScrollerIncrementPage] = CGRectMake(0.0, knobLocation + knobHeight, width, height - (knobLocation + knobHeight) - effectiveIncrementLineHeight);
_partRects[CPScrollerKnobSlot] = CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotSize);
_partRects[CPScrollerDecrementLine] = CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.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();
_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);
_partRects[CPScrollerIncrementLine] = CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = CGRectMake(trackInset.left, 0, width - trackInset.left - trackInset.right, height);
}
}
else
@@ -435,21 +436,21 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
knobHeight = height - knobInset.top - knobInset.bottom,
knobLocation = effectiveDecrementLineWidth + (slotSize - knobWidth) * [self floatValue];
_partRects[CPScrollerDecrementPage] = _CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height);
_partRects[CPScrollerKnob] = _CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight);
_partRects[CPScrollerIncrementPage] = _CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - effectiveIncrementLineWidth, height);
_partRects[CPScrollerKnobSlot] = _CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotSize, height - trackInset.top - trackInset.bottom);
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = _CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height);
_partRects[CPScrollerDecrementPage] = CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height);
_partRects[CPScrollerKnob] = CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight);
_partRects[CPScrollerIncrementPage] = CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - effectiveIncrementLineWidth, height);
_partRects[CPScrollerKnobSlot] = CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotSize, height - trackInset.top - trackInset.bottom);
_partRects[CPScrollerDecrementLine] = CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height);
if (width < knobWidth + decrementLineSize.width + incrementLineSize.width + trackInset.left + trackInset.right)
_partRects[CPScrollerKnob] = _CGRectMakeZero();
_partRects[CPScrollerKnob] = CGRectMakeZero();
if (width < decrementLineSize.width + incrementLineSize.width - 2)
{
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = _CGRectMake(0.0, 0.0, width, slotSize);
_partRects[CPScrollerIncrementLine] = CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = CGRectMake(0.0, 0.0, width, slotSize);
}
}
}
@@ -517,7 +518,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
- (CPView)createViewForPart:(CPScrollerPart)aPart
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[view setHitTests:NO];
@@ -531,7 +532,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[view setHitTests:NO];
@@ -606,7 +607,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
{
var knobRect = [self rectForPart:CPScrollerKnob],
knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
remainder = ![self isVertical] ? (_CGRectGetWidth(knobSlotRect) - _CGRectGetWidth(knobRect)) : (_CGRectGetHeight(knobSlotRect) - _CGRectGetHeight(knobRect));
remainder = ![self isVertical] ? (CGRectGetWidth(knobSlotRect) - CGRectGetWidth(knobRect)) : (CGRectGetHeight(knobSlotRect) - CGRectGetHeight(knobRect));
if (remainder <= 0)
[self setFloatValue:0.0];
@@ -660,11 +661,11 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
else if (_trackingPart === CPScrollerDecrementPage || _trackingPart === CPScrollerIncrementPage)
{
var knobRect = [self rectForPart:CPScrollerKnob],
knobWidth = ![self isVertical] ? _CGRectGetWidth(knobRect) : _CGRectGetHeight(knobRect),
knobWidth = ![self isVertical] ? CGRectGetWidth(knobRect) : CGRectGetHeight(knobRect),
knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
remainder = (![self isVertical] ? _CGRectGetWidth(knobSlotRect) : _CGRectGetHeight(knobSlotRect)) - knobWidth;
remainder = (![self isVertical] ? CGRectGetWidth(knobSlotRect) : CGRectGetHeight(knobSlotRect)) - knobWidth;
[self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - _CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - _CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder];
[self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder];
_hitPart = CPScrollerKnob;
+10 -10
View File
@@ -229,22 +229,22 @@ var RECENT_SEARCH_PREFIX = @" ";
- (CGRect)searchTextRectForBounds:(CGRect)rect
{
var leftOffset = 0,
width = _CGRectGetWidth(rect),
width = CGRectGetWidth(rect),
bounds = [self bounds];
if (_searchButton)
{
var searchBounds = [self searchButtonRectForBounds:bounds];
leftOffset = _CGRectGetMaxX(searchBounds) + 2;
leftOffset = CGRectGetMaxX(searchBounds) + 2;
}
if (_cancelButton)
{
var cancelRect = [self cancelButtonRectForBounds:bounds];
width = _CGRectGetMinX(cancelRect) - leftOffset;
width = CGRectGetMinX(cancelRect) - leftOffset;
}
return _CGRectMake(leftOffset, _CGRectGetMinY(rect), width, _CGRectGetHeight(rect));
return CGRectMake(leftOffset, CGRectGetMinY(rect), width, CGRectGetHeight(rect));
}
/*!
@@ -256,7 +256,7 @@ var RECENT_SEARCH_PREFIX = @" ";
{
var size = [[self valueForThemeAttribute:@"image-search"] size] || CGSizeMakeZero();
return _CGRectMake(5, (_CGRectGetHeight(rect) - size.height) / 2, size.width, size.height);
return CGRectMake(5, (CGRectGetHeight(rect) - size.height) / 2, size.width, size.height);
}
/*!
@@ -268,7 +268,7 @@ var RECENT_SEARCH_PREFIX = @" ";
{
var size = [[self valueForThemeAttribute:@"image-cancel"] size] || CGSizeMakeZero();
return _CGRectMake(_CGRectGetWidth(rect) - size.width - 5, (_CGRectGetHeight(rect) - size.width) / 2, size.height, size.height);
return CGRectMake(CGRectGetWidth(rect) - size.width - 5, (CGRectGetHeight(rect) - size.width) / 2, size.height, size.height);
}
// Managing Menu Templates
@@ -458,7 +458,7 @@ var RECENT_SEARCH_PREFIX = @" ";
[self sendAction:[self action] to:[self target]];
}
- (void)sendAction:(SEL)anAction to:(id)anObject
- (BOOL)sendAction:(SEL)anAction to:(id)anObject
{
[super sendAction:anAction to:anObject];
@@ -482,7 +482,7 @@ var RECENT_SEARCH_PREFIX = @" ";
- (CPView)hitTest:(CGPoint)aPoint
{
// Make sure a hit anywhere within the search field returns the search field itself
if (_CGRectContainsPoint([self frame], aPoint))
if (CGRectContainsPoint([self frame], aPoint))
return self;
else
return nil;
@@ -498,7 +498,7 @@ var RECENT_SEARCH_PREFIX = @" ";
var location = [anEvent locationInWindow],
point = [self convertPoint:location fromView:nil];
if (_CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point))
if (CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point))
{
if (_searchMenuTemplate == nil)
{
@@ -510,7 +510,7 @@ var RECENT_SEARCH_PREFIX = @" ";
else
[self _showMenu];
}
else if (_CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point))
else if (CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point))
[_cancelButton mouseDown:anEvent];
else
[super mouseDown:anEvent];
+5 -5
View File
@@ -56,15 +56,15 @@ CPSegmentSwitchTrackingMomentary = 2;
return "segmented-control";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"alignment": CPCenterTextAlignment,
@"vertical-alignment": CPCenterVerticalTextAlignment,
@"image-position": CPImageLeft,
@"image-scaling": CPImageScaleNone,
@"bezel-inset": _CGInsetMakeZero(),
@"content-inset": _CGInsetMakeZero(),
@"bezel-inset": CGInsetMakeZero(),
@"content-inset": CGInsetMakeZero(),
@"left-segment-bezel-color": [CPNull null],
@"right-segment-bezel-color": [CPNull null],
@"center-segment-bezel-color": [CPNull null],
@@ -564,9 +564,9 @@ CPSegmentSwitchTrackingMomentary = 2;
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
if ([aName hasPrefix:@"segment-content"])
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
return [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()];
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
return [[CPView alloc] initWithFrame:CGRectMakeZero()];
}
- (void)layoutSubviews
+2 -2
View File
@@ -47,7 +47,7 @@ CPThemeStateShadowViewHeavy = CPThemeState("shadowview-style-heavy");
return "shadow-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"bezel-color": [CPNull null],
@@ -60,7 +60,7 @@ CPThemeStateShadowViewHeavy = CPThemeState("shadowview-style-heavy");
var shadowView = [CPShadowView new],
inset = [shadowView valueForThemeAttribute:@"content-inset" inState:(aWeight == CPLightShadow) ? CPThemeStateShadowViewLight : CPThemeStateShadowViewHeavy];
return CGRectMake(_CGRectGetMinX(aFrame) - inset.left, _CGRectGetMinY(aFrame) - inset.top, _CGRectGetWidth(aFrame) + inset.left + inset.right, _CGRectGetHeight(aFrame) + inset.top + inset.bottom);
return CGRectMake(CGRectGetMinX(aFrame) - inset.left, CGRectGetMinY(aFrame) - inset.top, CGRectGetWidth(aFrame) + inset.left + inset.right, CGRectGetHeight(aFrame) + inset.top + inset.bottom);
}
+ (id)shadowViewEnclosingView:(CPView)aView
+27 -27
View File
@@ -49,11 +49,11 @@ CPCircularSlider = 1;
return "slider";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"knob-color": [CPNull null],
@"knob-size": _CGSizeMakeZero(),
@"knob-size": CGSizeMakeZero(),
@"track-width": 0.0,
@"track-color": [CPNull null],
};
@@ -162,16 +162,16 @@ CPCircularSlider = 1;
var trackWidth = [self currentValueForThemeAttribute:@"track-width"];
if (trackWidth <= 0)
return _CGRectMakeZero();
return CGRectMakeZero();
if ([self isVertical])
{
bounds.origin.x = (_CGRectGetWidth(bounds) - trackWidth) / 2.0;
bounds.origin.x = (CGRectGetWidth(bounds) - trackWidth) / 2.0;
bounds.size.width = trackWidth;
}
else
{
bounds.origin.y = (_CGRectGetHeight(bounds) - trackWidth) / 2.0;
bounds.origin.y = (CGRectGetHeight(bounds) - trackWidth) / 2.0;
bounds.size.height = trackWidth;
}
}
@@ -184,13 +184,13 @@ CPCircularSlider = 1;
var knobSize = [self currentValueForThemeAttribute:@"knob-size"];
if (knobSize.width <= 0 || knobSize.height <= 0)
return _CGRectMakeZero();
return CGRectMakeZero();
var knobRect = _CGRectMake(0.0, 0.0, knobSize.width, knobSize.height),
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))
if (!trackRect || CGRectIsEmpty(trackRect))
trackRect = bounds;
if ([self hasThemeState:CPThemeStateCircular])
@@ -203,13 +203,13 @@ CPCircularSlider = 1;
}
else if ([self isVertical])
{
knobRect.origin.x = _CGRectGetMidX(trackRect) - knobSize.width / 2.0;
knobRect.origin.y = ((_maxValue - [self doubleValue]) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height);
knobRect.origin.x = CGRectGetMidX(trackRect) - knobSize.width / 2.0;
knobRect.origin.y = ((_maxValue - [self doubleValue]) / (_maxValue - _minValue)) * (CGRectGetHeight(trackRect) - knobSize.height);
}
else
{
knobRect.origin.x = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetWidth(trackRect) - knobSize.width);
knobRect.origin.y = _CGRectGetMidY(trackRect) - knobSize.height / 2.0;
knobRect.origin.x = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (CGRectGetWidth(trackRect) - knobSize.width);
knobRect.origin.y = CGRectGetMidY(trackRect) - knobSize.height / 2.0;
}
return knobRect;
@@ -260,8 +260,8 @@ CPCircularSlider = 1;
{
// Recalculate isVertical.
var bounds = [self bounds],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
width = CGRectGetWidth(bounds),
height = CGRectGetHeight(bounds);
_isVertical = width < height ? 1 : (width > height ? 0 : -1);
@@ -306,55 +306,55 @@ CPCircularSlider = 1;
if ([self hasThemeState:CPThemeStateCircular])
{
var knobWidth = _CGRectGetWidth(knobRect);
var knobWidth = CGRectGetWidth(knobRect);
trackRect.origin.x += knobWidth / 2;
trackRect.size.width -= knobWidth;
var minValue = [self minValue],
dx = aPoint.x - _CGRectGetMidX(trackRect),
dy = aPoint.y - _CGRectGetMidY(trackRect);
dx = aPoint.x - CGRectGetMidX(trackRect),
dy = aPoint.y - CGRectGetMidY(trackRect);
return MAX(0.0, MIN(1.0, 1.0 - (3 * PI_2 - ATAN2(dy, dx)) % PI2 / PI2)) * ([self maxValue] - minValue) + minValue;
}
else if ([self isVertical])
{
var knobHeight = _CGRectGetHeight(knobRect);
var knobHeight = CGRectGetHeight(knobRect);
trackRect.origin.y += knobHeight / 2;
trackRect.size.height -= knobHeight;
var minValue = [self minValue];
return MAX(0.0, MIN(1.0, (_CGRectGetMaxY(trackRect) - aPoint.y) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue;
return MAX(0.0, MIN(1.0, (CGRectGetMaxY(trackRect) - aPoint.y) / CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue;
}
else
{
var knobWidth = _CGRectGetWidth(knobRect);
var knobWidth = CGRectGetWidth(knobRect);
trackRect.origin.x += knobWidth / 2;
trackRect.size.width -= knobWidth;
var minValue = [self minValue];
return MAX(0.0, MIN(1.0, (aPoint.x - _CGRectGetMinX(trackRect)) / _CGRectGetWidth(trackRect))) * ([self maxValue] - minValue) + minValue;
return MAX(0.0, MIN(1.0, (aPoint.x - CGRectGetMinX(trackRect)) / CGRectGetWidth(trackRect))) * ([self maxValue] - minValue) + minValue;
}
}
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
var bounds = [self bounds],
knobRect = [self knobRectForBounds:_CGRectMakeCopy(bounds)];
knobRect = [self knobRectForBounds:CGRectMakeCopy(bounds)];
if (_CGRectContainsPoint(knobRect, aPoint))
_dragOffset = _CGSizeMake(_CGRectGetMidX(knobRect) - aPoint.x, _CGRectGetMidY(knobRect) - aPoint.y);
if (CGRectContainsPoint(knobRect, aPoint))
_dragOffset = CGSizeMake(CGRectGetMidX(knobRect) - aPoint.x, CGRectGetMidY(knobRect) - aPoint.y);
else
{
var trackRect = [self trackRectForBounds:bounds];
if (trackRect && _CGRectContainsPoint(trackRect, aPoint))
if (trackRect && CGRectContainsPoint(trackRect, aPoint))
{
_dragOffset = _CGSizeMakeZero();
_dragOffset = CGSizeMakeZero();
[self setObjectValue:[self _valueAtPoint:aPoint]];
}
@@ -373,7 +373,7 @@ CPCircularSlider = 1;
- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
{
[self setObjectValue:[self _valueAtPoint:_CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
[self setObjectValue:[self _valueAtPoint:CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
return YES;
}
+12 -10
View File
@@ -55,7 +55,6 @@
CPTextField _hexLabel;
CPTextField _hexValue;
CPTextField _hexValue;
CPTextField _redValue;
CPTextField _greenValue;
CPTextField _blueValue;
@@ -146,7 +145,7 @@
[_hueLabel setTextColor:[CPColor blackColor]];
_hueSlider = [[CPSlider alloc] initWithFrame:CGRectMake(15, 143, aFrame.size.width - 70, 20)];
[_hueSlider setMaxValue:359.0];
[_hueSlider setMaxValue:0.999];
[_hueSlider setMinValue:0.0];
[_hueSlider setTarget:self];
[_hueSlider setAction:@selector(sliderChanged:)];
@@ -165,7 +164,7 @@
[_saturationLabel setTextColor:[CPColor blackColor]];
_saturationSlider = [[CPSlider alloc] initWithFrame:CGRectMake(15, 168, aFrame.size.width - 70, 20)];
[_saturationSlider setMaxValue:100.0];
[_saturationSlider setMaxValue:1.0];
[_saturationSlider setMinValue:0.0];
[_saturationSlider setTarget:self];
[_saturationSlider setAction:@selector(sliderChanged:)];
@@ -184,7 +183,7 @@
[_brightnessLabel setTextColor:[CPColor blackColor]];
_brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(15, 194, aFrame.size.width - 70, 20)];
[_brightnessSlider setMaxValue:100.0];
[_brightnessSlider setMaxValue:1.0];
[_brightnessSlider setMinValue:0.0];
[_brightnessSlider setTarget:self];
[_brightnessSlider setAction:@selector(sliderChanged:)];
@@ -282,6 +281,9 @@
- (void)setColor:(CPColor)aColor
{
if (!aColor)
[CPException raise:CPInvalidArgumentException reason:"aColor can't be nil"];
[self updateRGBSliders:aColor];
[self updateHSBSliders:aColor];
[self updateHex:aColor];
@@ -313,9 +315,9 @@
- (void)updateLabels
{
[_hueValue setStringValue:ROUND([_hueSlider floatValue])];
[_saturationValue setStringValue:ROUND([_saturationSlider floatValue])];
[_brightnessValue setStringValue:ROUND([_brightnessSlider floatValue])];
[_hueValue setStringValue:ROUND([_hueSlider floatValue] * 360.0)];
[_saturationValue setStringValue:ROUND([_saturationSlider floatValue] * 100.0)];
[_brightnessValue setStringValue:ROUND([_brightnessSlider floatValue] * 100.0)];
[_redValue setStringValue:ROUND([_redSlider floatValue] * 255)];
[_greenValue setStringValue:ROUND([_greenSlider floatValue] * 255)];
@@ -363,15 +365,15 @@
[self sliderChanged:_blueSlider];
break;
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(value), 360), 0)];
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(value), 360) / 360.0, 0)];
[self sliderChanged:_hueSlider];
break;
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(value), 100) / 100.0, 0)];
[self sliderChanged:_saturationSlider];
break;
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(value), 100) / 100.0, 0)];
[self sliderChanged:_brightnessSlider];
break;
}
+5 -5
View File
@@ -103,7 +103,7 @@ var ShouldSuppressResizeNotifications = 1,
return @"splitview";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"divider-thickness": 1.0,
@@ -334,8 +334,8 @@ var ShouldSuppressResizeNotifications = 1,
}
[self _setupDOMDivider];
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect));
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect));
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], CGRectGetWidth(aRect), CGRectGetHeight(aRect));
#endif
}
@@ -995,7 +995,7 @@ The sum of the views and the sum of the dividers should be equal to the size of
@param unsigned int - The divider index the button bar will be assigned to.
*/
// FIXME Should be renamed to setButtonBar:ofDividerAtIndex:.
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(CPUInteger)dividerIndex
{
if (!aButtonBar)
{
@@ -1110,7 +1110,7 @@ The sum of the views and the sum of the dividers should be equal to the size of
*/
- (void)_restoreFromAutosaveIfNeeded
{
if (_shouldRestoreFromAutosaveUnlessFrameSize && !_CGSizeEqualToSize([self frameSize], _shouldRestoreFromAutosaveUnlessFrameSize))
if (_shouldRestoreFromAutosaveUnlessFrameSize && !CGSizeEqualToSize([self frameSize], _shouldRestoreFromAutosaveUnlessFrameSize))
{
[self _restoreFromAutosave];
}
+11 -11
View File
@@ -55,7 +55,7 @@
*/
+ (CPStepper)stepperWithInitialValue:(float)aValue minValue:(float)aMinValue maxValue:(float)aMaxValue
{
var stepper = [[CPStepper alloc] initWithFrame:_CGRectMakeZero()];
var stepper = [[CPStepper alloc] initWithFrame:CGRectMakeZero()];
[stepper setDoubleValue:aValue];
[stepper setMinValue:aMinValue];
@@ -122,14 +122,14 @@
- (void)_init
{
_buttonUp = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
_buttonUp = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
[_buttonUp setContinuous:_autorepeat];
[_buttonUp setTarget:self];
[_buttonUp setAction:@selector(_buttonDidClick:)];
[_buttonUp setAutoresizingMask:CPViewNotSizable];
[self addSubview:_buttonUp];
_buttonDown = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
_buttonDown = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
[_buttonDown setContinuous:_autorepeat];
[_buttonDown setTarget:self];
[_buttonDown setAction:@selector(_buttonDidClick:)];
@@ -161,8 +161,8 @@
{
var upSize = [self valueForThemeAttribute:@"up-button-size"],
downSize = [self valueForThemeAttribute:@"down-button-size"],
minSize = _CGSizeMake(upSize.width, upSize.height + downSize.height),
frame = _CGRectMakeCopy(aFrame);
minSize = CGSizeMake(upSize.width, upSize.height + downSize.height),
frame = CGRectMakeCopy(aFrame);
frame.size.width = MAX(minSize.width, frame.size.width);
frame.size.height = MAX(minSize.height, frame.size.height);
@@ -175,8 +175,8 @@
var aFrame = [self frame],
upSize = [self valueForThemeAttribute:@"up-button-size"],
downSize = [self valueForThemeAttribute:@"down-button-size"],
upFrame = _CGRectMake(aFrame.size.width - upSize.width, 0, upSize.width, upSize.height),
downFrame = _CGRectMake(aFrame.size.width - downSize.width, upSize.height, downSize.width, downSize.height);
upFrame = CGRectMake(aFrame.size.width - upSize.width, 0, upSize.width, upSize.height),
downFrame = CGRectMake(aFrame.size.width - downSize.width, upSize.height, downSize.width, downSize.height);
[_buttonUp setFrame:upFrame];
[_buttonDown setFrame:downFrame];
@@ -213,7 +213,7 @@
Set the current value of the stepper.
@param aValue a float containing the value
*/
- (void)setDoubleValue:(float)aValue
- (void)setDoubleValue:(double)aValue
{
if (aValue > _maxValue)
[super setDoubleValue:_valueWraps ? _minValue : _maxValue];
@@ -267,13 +267,13 @@
return @"stepper";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"bezel-color-up-button": [CPNull null],
@"bezel-color-down-button": [CPNull null],
@"up-button-size": _CGSizeMakeZero(),
@"down-button-size": _CGSizeMakeZero(),
@"up-button-size": CGSizeMakeZero(),
@"down-button-size": CGSizeMakeZero(),
};
}
+22 -14
View File
@@ -79,11 +79,11 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
{
_selectedIndex = CPNotFound;
_tabs = [[CPSegmentedControl alloc] initWithFrame:_CGRectMake(0, 0, 0, 0)];
_tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[_tabs setHitTests:NO];
var height = [_tabs valueForThemeAttribute:@"default-height"];
[_tabs setFrameSize:_CGSizeMake(0, height)];
[_tabs setFrameSize:CGSizeMake(0, height)];
_box = [[CPBox alloc] initWithFrame:[self bounds]];
[self setBackgroundColor:[CPColor colorWithCalibratedWhite:0.95 alpha:1.0]];
@@ -107,7 +107,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
@param aTabViewItem the item to insert
@param anIndex the index for the item
*/
- (void)insertTabViewItem:(CPTabViewItem)aTabViewItem atIndex:(unsigned)anIndex
- (void)insertTabViewItem:(CPTabViewItem)aTabViewItem atIndex:(CPUInteger)anIndex
{
[_items insertObject:aTabViewItem atIndex:anIndex];
@@ -183,7 +183,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
Returns the CPTabViewItem at the specified index.
@return a tab view item, or nil
*/
- (CPTabViewItem)tabViewItemAtIndex:(unsigned)anIndex
- (CPTabViewItem)tabViewItemAtIndex:(CPUInteger)anIndex
{
return [_items objectAtIndex:anIndex];
}
@@ -270,7 +270,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
Selects the item at the specified index.
@param anIndex the index of the item to display.
*/
- (BOOL)selectTabViewItemAtIndex:(unsigned)anIndex
- (BOOL)selectTabViewItemAtIndex:(CPUInteger)anIndex
{
if (anIndex === _selectedIndex)
return;
@@ -373,11 +373,11 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
else
{
var aFrame = [self frame],
segmentedHeight = _CGRectGetHeight([_tabs frame]),
segmentedHeight = CGRectGetHeight([_tabs frame]),
origin = _type === CPTopTabsBezelBorder ? segmentedHeight / 2 : 0;
[_box setFrame:_CGRectMake(0, origin, _CGRectGetWidth(aFrame),
_CGRectGetHeight(aFrame) - segmentedHeight / 2)];
[_box setFrame:CGRectMake(0, origin, CGRectGetWidth(aFrame),
CGRectGetHeight(aFrame) - segmentedHeight / 2)];
[self _repositionTabs];
}
@@ -447,13 +447,13 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
- (void)_repositionTabs
{
var horizontalCenterOfSelf = _CGRectGetWidth([self bounds]) / 2,
verticalCenterOfTabs = _CGRectGetHeight([_tabs bounds]) / 2;
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
verticalCenterOfTabs = CGRectGetHeight([_tabs bounds]) / 2;
if (_type === CPBottomTabsBezelBorder)
[_tabs setCenter:_CGPointMake(horizontalCenterOfSelf, _CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
[_tabs setCenter:CGPointMake(horizontalCenterOfSelf, CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
else
[_tabs setCenter:_CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
[_tabs setCenter:CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
}
- (void)_setSelectedIndex:(CPNumber)index
@@ -504,8 +504,6 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
_items = [aCoder decodeObjectForKey:CPTabViewItemsKey];
[_items makeObjectsPerformSelector:@selector(_setTabView:) withObject:self];
[self _updateItems];
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
self.selectOnAwake = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
@@ -517,6 +515,10 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
- (void)awakeFromCib
{
// This cannot be run in initWithCoder because it might call selectTabViewItem:, which is
// not safe to call before the views of the tab views items are fully decoded.
[self _updateItems];
if (self.selectOnAwake)
{
[self selectTabViewItem:self.selectOnAwake];
@@ -532,7 +534,13 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
// Don't bother to encode the CPBox. We will recreate it on decode and its content view is already
// stored by the tab view item. Not encoding _box makes the resulting archive smaller and reduces
// the surface for decoding bugs (of which we've had many in tab view).
var subviews = [self subviews];
[_box removeFromSuperview];
[super encodeWithCoder:aCoder];
[self setSubviews:subviews];
[aCoder encodeObject:_items forKey:CPTabViewItemsKey];
+4 -4
View File
@@ -283,7 +283,7 @@ CPTableColumnUserResizingMask = 1 << 1;
*/
- (void)sizeToFit
{
var width = _CGRectGetWidth([_headerView frame]);
var width = CGRectGetWidth([_headerView frame]);
if (width < [self minWidth])
[self setMinWidth:width];
@@ -416,7 +416,7 @@ CPTableColumnUserResizingMask = 1 << 1;
to be invoked with row equal to -1 in cases where no actual row is involved but the table
view needs to get some generic cell info.
*/
- (id)dataViewForRow:(int)aRowIndex
- (id)dataViewForRow:(CPInteger)aRowIndex
{
return [self dataView];
}
@@ -595,7 +595,7 @@ CPTableColumnUserResizingMask = 1 << 1;
@implementation CPTableColumn (Bindings)
+ (id)_binderClassForBinding:(CPString)aBinding
+ (Class)_binderClassForBinding:(CPString)aBinding
{
if (aBinding == CPValueBinding)
return [CPTableColumnValueBinder class];
@@ -828,7 +828,7 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
/*!
@ignore
*/
- (id)dataCellForRow:(int)row
- (id)dataCellForRow:(CPInteger)row
{
[CPException raise:CPUnsupportedMethodException
reason:@"dataCellForRow: is not supported. Use -dataViewForRow:row instead."];
+68 -53
View File
@@ -43,7 +43,7 @@
return @"columnHeader";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"background-color": [CPNull null],
@@ -53,11 +53,11 @@
@"text-color": [CPNull null],
@"font": [CPNull null],
@"text-shadow-color": [CPNull null],
@"text-shadow-offset": CGSizeMakeZero(),
@"text-shadow-offset": CGSizeMakeZero()
};
}
- (void)initWithFrame:(CGRect)frame
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
@@ -69,7 +69,7 @@
- (void)_init
{
_textField = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
_textField = [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()];
[_textField setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
@@ -87,7 +87,7 @@
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 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:@"font"]];
[_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
@@ -229,6 +229,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
CGPoint _previousTrackingLocation;
int _activeColumn;
int _pressedColumn;
int _lastDragDestinationColumnIndex;
BOOL _isResizing;
BOOL _isDragging;
@@ -245,18 +246,19 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
return @"tableHeaderRow";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"background-color": [CPNull null],
@"divider-color": [CPColor grayColor],
@"divider-thickness": 1.0
};
}
- (void)_init
{
_mouseDownLocation = _CGPointMakeZero();
_previousTrackingLocation = _CGPointMakeZero();
_mouseDownLocation = CGPointMakeZero();
_previousTrackingLocation = CGPointMakeZero();
_activeColumn = -1;
_pressedColumn = -1;
@@ -285,13 +287,13 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
return [_tableView columnAtPoint:CGPointMake(aPoint.x, aPoint.y)];
}
- (CGRect)headerRectOfColumn:(int)aColumnIndex
- (CGRect)headerRectOfColumn:(CPInteger)aColumnIndex
{
var headerRect = CGRectMakeCopy([self bounds]),
columnRect = [_tableView rectOfColumn:aColumnIndex];
headerRect.origin.x = _CGRectGetMinX(columnRect);
headerRect.size.width = _CGRectGetWidth(columnRect);
headerRect.origin.x = CGRectGetMinX(columnRect);
headerRect.size.width = CGRectGetWidth(columnRect);
return headerRect;
}
@@ -306,14 +308,14 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
return _drawsColumnLines;
}
- (CGRect)_cursorRectForColumn:(int)column
- (CGRect)_cursorRectForColumn:(CPInteger)column
{
if (column == -1 || !([_tableView._tableColumns[column] resizingMask] & CPTableColumnUserResizingMask))
return _CGRectMakeZero();
return CGRectMakeZero();
var rect = [self headerRectOfColumn:column];
rect.origin.x = _CGRectGetMaxX(rect) - 5;
rect.origin.x = CGRectGetMaxX(rect) - 5;
rect.size.width = 20;
return rect;
@@ -332,7 +334,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
var headerView = [_tableView._tableColumns[column] headerView];
[headerView setThemeState:CPThemeStateHighlighted];
if (_tableView._editingColumn == column)
if (_tableView._editingCellIndex || _tableView._editingColumn == column)
[[self window] makeFirstResponder:_tableView];
}
@@ -353,7 +355,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
currentLocation.x -= 5.0;
var columnIndex = [self columnAtPoint:currentLocation],
shouldResize = [self shouldResizeTableColumn:columnIndex at:_CGPointMake(currentLocation.x + 5.0, currentLocation.y)];
shouldResize = [self shouldResizeTableColumn:columnIndex at:CGPointMake(currentLocation.x + 5.0, currentLocation.y)];
if (type === CPLeftMouseUp)
{
@@ -381,7 +383,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
_mouseDownLocation = currentLocation;
_activeColumn = columnIndex;
[_tableView _sendDelegateDidMouseDownInHeader:columnIndex];
[_tableView _sendDelegateMouseDownInHeaderOfTableColumn:columnIndex];
if (shouldResize)
[self startResizingTableColumn:columnIndex at:currentLocation];
@@ -397,7 +399,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[self continueResizingTableColumn:_activeColumn at:currentLocation];
else
{
if (_activeColumn === columnIndex && _CGRectContainsPoint([self headerRectOfColumn:columnIndex], currentLocation))
if (_activeColumn === columnIndex && CGRectContainsPoint([self headerRectOfColumn:columnIndex], currentLocation))
{
if (_isTrackingColumn && _pressedColumn !== -1)
{
@@ -415,24 +417,25 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (void)startTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (void)startTrackingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
{
_lastDragDestinationColumnIndex = -1;
[self _setPressedColumn:aColumnIndex];
}
- (BOOL)continueTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (BOOL)continueTrackingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
{
if ([self _shouldDragTableColumn:aColumnIndex at:aPoint])
{
var columnRect = [self headerRectOfColumn:aColumnIndex],
offset = _CGPointMakeZero(),
offset = CGPointMakeZero(),
view = [_tableView _dragViewForColumn:aColumnIndex event:[CPApp currentEvent] offset:offset],
viewLocation = _CGPointMakeZero();
viewLocation = CGPointMakeZero();
viewLocation.x = ( _CGRectGetMinX(columnRect) + offset.x ) + ( aPoint.x - _mouseDownLocation.x );
viewLocation.y = _CGRectGetMinY(columnRect) + offset.y;
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]
[self dragView:view at:viewLocation offset:CGSizeMakeZero() event:[CPApp currentEvent]
pasteboard:[CPPasteboard pasteboardWithName:CPDragPboard] source:self slideBack:YES];
return NO;
@@ -441,21 +444,21 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
return YES;
}
- (BOOL)_shouldStopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (BOOL)_shouldStopTrackingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
{
return _isTrackingColumn && _activeColumn === aColumnIndex &&
_CGRectContainsPoint([self headerRectOfColumn:aColumnIndex], aPoint);
CGRectContainsPoint([self headerRectOfColumn:aColumnIndex], aPoint);
}
- (void)stopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (void)stopTrackingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
{
[self _setPressedColumn:CPNotFound];
[self _updateResizeCursor:[CPApp currentEvent]];
}
- (BOOL)_shouldDragTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (BOOL)_shouldDragTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
{
return [_tableView allowsColumnReordering] && ABS(aPoint.x - _mouseDownLocation.x) >= 10.0;
return ABS(aPoint.x - _mouseDownLocation.x) >= 10.0 && [_tableView _sendDelegateShouldReorderColumn:aColumnIndex toColumn:-1];
}
- (CGRect)_headerRectOfLastVisibleColumn
@@ -488,10 +491,10 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
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)));
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);
frame.origin.y = CGRectGetMinY(lastColumnRect);
// Convert the calculated origin back to the window coordinate system
frame.origin = [self convertPoint:frame.origin toView:nil];
@@ -501,11 +504,14 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[dragWindow setFrame:frame];
}
- (void)_moveColumn:(int)aFromIndex toColumn:(int)aToIndex
- (void)_moveColumn:(CPInteger)aFromIndex toColumn:(CPInteger)aToIndex
{
[_tableView moveColumn:aFromIndex toColumn:aToIndex];
_activeColumn = aToIndex;
_pressedColumn = _activeColumn;
if ([_tableView _sendDelegateShouldReorderColumn:aFromIndex toColumn:aToIndex])
{
[_tableView moveColumn:aFromIndex toColumn:aToIndex];
_activeColumn = aToIndex;
_pressedColumn = _activeColumn;
}
}
- (void)draggedView:(CPView)aView beganAt:(CGPoint)aPoint
@@ -530,9 +536,9 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
var hoverPoint = CGPointCreateCopy(aPoint);
if (aPoint.x < _previousTrackingLocation.x)
hoverPoint = _CGPointMake(_CGRectGetMinX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
hoverPoint = CGPointMake(CGRectGetMinX(dragWindowFrame), CGRectGetMinY(dragWindowFrame));
else if (aPoint.x > _previousTrackingLocation.x)
hoverPoint = _CGPointMake(_CGRectGetMaxX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
hoverPoint = CGPointMake(CGRectGetMaxX(dragWindowFrame), CGRectGetMinY(dragWindowFrame));
// Convert the hover point from the global coordinate system to windows' coordinate system
hoverPoint = [[self window] convertGlobalToBase:hoverPoint];
@@ -541,14 +547,21 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
var hoveredColumn = [self columnAtPoint:hoverPoint];
if (hoveredColumn !== -1)
if (hoveredColumn !== _lastDragDestinationColumnIndex && hoveredColumn !== -1)
{
var columnRect = [self headerRectOfColumn:hoveredColumn],
columnCenterPoint = [self convertPoint:CGPointMake(_CGRectGetMidX(columnRect), _CGRectGetMidY(columnRect)) fromView:self];
columnCenterPoint = [self convertPoint:CGPointMake(CGRectGetMidX(columnRect), CGRectGetMidY(columnRect)) fromView:self];
if (hoveredColumn < _activeColumn && hoverPoint.x < columnCenterPoint.x)
{
[self _moveColumn:_activeColumn toColumn:hoveredColumn];
_lastDragDestinationColumnIndex = hoveredColumn;
}
else if (hoveredColumn > _activeColumn && hoverPoint.x > columnCenterPoint.x)
{
[self _moveColumn:_activeColumn toColumn:hoveredColumn];
_lastDragDestinationColumnIndex = hoveredColumn;
}
}
_previousTrackingLocation = aPoint;
@@ -568,7 +581,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[_tableView _enqueueDraggingViews];
}
- (BOOL)shouldResizeTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (BOOL)shouldResizeTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
{
if (_isResizing)
return YES;
@@ -576,10 +589,10 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
if (_isTrackingColumn)
return NO;
return [_tableView allowsColumnResizing] && _CGRectContainsPoint([self _cursorRectForColumn:aColumnIndex], aPoint);
return [_tableView allowsColumnResizing] && CGRectContainsPoint([self _cursorRectForColumn:aColumnIndex], aPoint);
}
- (void)startResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (void)startResizingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
{
_isResizing = YES;
@@ -589,7 +602,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[_tableView setDisableAutomaticResizing:YES];
}
- (void)continueResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (void)continueResizingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex],
newWidth = [tableColumn width] + aPoint.x - _previousTrackingLocation.x;
@@ -609,7 +622,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
}
}
- (void)stopResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (void)stopResizingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
[tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
@@ -632,7 +645,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
mouseOverLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
overColumn = [self columnAtPoint:mouseOverLocation];
if (overColumn >= 0 && _CGRectContainsPoint([self _cursorRectForColumn:overColumn], mouseLocation))
if (overColumn >= 0 && CGRectContainsPoint([self _cursorRectForColumn:overColumn], mouseLocation))
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn],
width = [tableColumn width];
@@ -667,7 +680,8 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
- (void)layoutSubviews
{
var tableColumns = [_tableView tableColumns],
count = [tableColumns count];
count = [tableColumns count],
lineThickness = [self currentValueForThemeAttribute:@"divider-thickness"];
for (var i = 0; i < count; i++)
{
@@ -677,7 +691,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
// Make space for the gridline on the right.
frame.origin.x -= 0.5;
frame.size.width -= 1.0;
frame.size.width -= lineThickness;
frame.size.height -= 0.5;
// Note: we're not adding in intercell spacing here. This setting only affects the regular
// table cell data views, not the header. Verified in Cocoa on March 29th, 2011.
@@ -702,9 +716,10 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
tableColumns = [_tableView tableColumns],
exposedTableColumns = _tableView._exposedColumns,
firstIndex = [exposedTableColumns firstIndex],
exposedRange = CPMakeRange(firstIndex, [exposedTableColumns lastIndex] - firstIndex + 1);
exposedRange = CPMakeRange(firstIndex, [exposedTableColumns lastIndex] - firstIndex + 1),
lineThickness = [self currentValueForThemeAttribute:@"divider-thickness"];
CGContextSetLineWidth(context, 1);
CGContextSetLineWidth(context, lineThickness);
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"divider-color"]);
[exposedColumnIndexes getIndexes:columnsArray maxCount:-1 inIndexRange:exposedRange];
@@ -721,10 +736,10 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
var columnIndex = columnsArray[columnArrayIndex],
columnToStroke = [self headerRectOfColumn:columnIndex];
columnMaxX = _CGRectGetMaxX(columnToStroke);
columnMaxX = CGRectGetMaxX(columnToStroke);
CGContextMoveToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMinY(columnToStroke)));
CGContextAddLineToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMaxY(columnToStroke)) - 1.0);
CGContextMoveToPoint(context, FLOOR(columnMaxX) - 0.5 * lineThickness, ROUND(CGRectGetMinY(columnToStroke)));
CGContextAddLineToPoint(context, FLOOR(columnMaxX) - 0.5 * lineThickness, ROUND(CGRectGetMaxY(columnToStroke)) - 1.0);
}
CGContextClosePath(context);
+1163 -552
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -28,3 +28,14 @@ CPFormFeedCharacter = "\u000c";
CPCarriageReturnCharacter = "\u000d";
CPBackTabCharacter = "\u0019";
CPDeleteCharacter = "\u007f";
CPIllegalTextMovement = 0;
CPOtherTextMovement = 0;
CPReturnTextMovement = 16;
CPTabTextMovement = 17;
CPBacktabTextMovement = 18;
CPLeftTextMovement = 19;
CPRightTextMovement = 20;
CPUpTextMovement = 21;
CPDownTextMovement = 22;
CPCancelTextMovement = 23;
+380 -137
View File
@@ -59,15 +59,22 @@ function CPTextFieldBlurFunction(anEvent, owner, domElement, inputElement, resig
if (owner && domElement != inputElement.parentNode)
return;
if (!resigning && [[owner window] isKeyWindow])
var ownerWindow = [owner window];
if (!resigning && [ownerWindow isKeyWindow])
{
/*
Browsers blur text fields when a click occurs anywhere outside the text field. That is normal for browsers, but in Cocoa the key view retains focus unless the click target accepts first responder. So if we lost focus but were not told to resign and our window is still key, restore focus.
Browsers blur text fields when a click occurs anywhere outside the text field. That is normal for browsers, but in Cocoa the key view retains focus unless the click target accepts first responder. So if we lost focus but were not told to resign and our window is still key, restore focus,
but only if the text field is completely within the browser window. If we restore focus when it
is off screen, the entire body scrolls out of our control.
*/
window.setTimeout(function()
if ([owner _isWithinUsablePlatformRect])
{
inputElement.focus();
}, 0.0);
window.setTimeout(function()
{
inputElement.focus();
}, 0.0);
}
}
CPTextFieldHandleBlur(anEvent, @ref(owner));
@@ -202,16 +209,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return "textfield";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"bezel-inset": _CGInsetMakeZero(),
@"content-inset": _CGInsetMake(1.0, 0.0, 0.0, 0.0),
@"bezel-inset": CGInsetMakeZero(),
@"content-inset": CGInsetMake(1.0, 0.0, 0.0, 0.0),
@"bezel-color": [CPNull null],
};
}
/* @ignore */
#if PLATFORM(DOM)
- (DOMElement)_inputElement
{
@@ -231,7 +237,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return CPTextFieldBlurFunction(
anEvent,
CPTextFieldInputOwner,
CPTextFieldInputOwner._DOMElement,
CPTextFieldInputOwner ? CPTextFieldInputOwner._DOMElement : nil,
CPTextFieldDOMInputElement,
CPTextFieldInputResigning,
@ref(CPTextFieldInputDidBlur));
@@ -245,7 +251,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return;
var cappEvent = [CPEvent keyEventWithType:CPKeyUp
location:_CGPointMakeZero()
location:CGPointMakeZero()
modifierFlags:0
timestamp:[CPEvent currentTimestamp]
windowNumber:[[CPApp keyWindow] windowNumber]
@@ -345,8 +351,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
else
[self unsetThemeState:CPThemeStateEditable];
// We only allow first responder status if the field is editable and enabled.
if (!shouldBeEditable && [[self window] firstResponder] === self)
// We only allow first responder status if the field is enable, and editable or selectable.
if (!(shouldBeEditable && ![self isSelectable]) && [[self window] firstResponder] === self)
[[self window] makeFirstResponder:nil];
if (shouldBeEditable)
@@ -371,7 +377,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{
[super setEnabled:shouldBeEnabled];
// We only allow first responder status if the field is editable and enabled.
// We only allow first responder status if the field is enabled.
if (!shouldBeEnabled && [[self window] firstResponder] === self)
[[self window] makeFirstResponder:nil];
}
@@ -522,35 +528,48 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return _textFieldBackgroundColor;
}
/* @ignore */
/*! @ignore */
- (BOOL)acceptsFirstResponder
{
return [self isEditable] && [self isEnabled];
return [self isEnabled] && ([self isEditable] || [self isSelectable]) && [self _isWithinUsablePlatformRect];
}
/* @ignore */
/*! @ignore */
- (BOOL)becomeFirstResponder
{
if (![self isEnabled])
return NO;
// As long as we are the first responder we need to monitor the key status of our window.
[self _setObserveWindowKeyNotifications:YES];
_isEditing = NO;
if ([[self window] isKeyWindow])
[self _becomeFirstKeyResponder];
if ([[self window] isKeyWindow] && [self isEditable])
return [self _becomeFirstKeyResponder];
return YES;
}
/*!
/*
A text field can be the first responder without necessarily being the focus of keyboard input. For example, it might be the first responder of window A but window B is the main and key window. It's important we don't put a focused input field into a text field in a non-key window, even if that field is the first responder, because the key window might also have a first responder text field which the user will expect to receive keyboard input.
Since a first responder but non-key window text field can't receive input it should not even look like an active text field (Cocoa has a "slightly active" text field look it uses when another window is the key window, but Cappuccino doesn't today.)
It's also possible for a text field to be non-editable but selectable in which case it can also become the first responder -
this is what allows text to be copied from it.
*/
- (void)_becomeFirstKeyResponder
- (BOOL)_becomeFirstKeyResponder
{
// Make sure the text field is visible so the browser will not scroll without the NSScrollView knowing about it.
[self scrollRectToVisible:[self bounds]];
// If the text field is still not completely on screen, refuse to become
// first responder, because the browser will scroll it into view out of our control.
if (![self _isWithinUsablePlatformRect])
return NO;
// A selectable but non-editable text field may be the first responder, but never the
// first key responder (first key responder indicating editability.)
if (![self isEditable])
return NO;
[self setThemeState:CPThemeStateEditing];
@@ -576,11 +595,16 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
switch ([self alignment])
{
case CPCenterTextAlignment: element.style.textAlign = "center";
break;
case CPRightTextAlignment: element.style.textAlign = "right";
break;
default: element.style.textAlign = "left";
case CPCenterTextAlignment:
element.style.textAlign = "center";
break;
case CPRightTextAlignment:
element.style.textAlign = "right";
break;
default:
element.style.textAlign = "left";
}
var contentRect = [self contentRectForBounds:[self bounds]],
@@ -589,31 +613,32 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
switch (verticalAlign)
{
case CPTopVerticalTextAlignment:
var topPoint = _CGRectGetMinY(contentRect) + "px";
var topPoint = CGRectGetMinY(contentRect) + "px";
break;
case CPCenterVerticalTextAlignment:
var topPoint = (_CGRectGetMidY(contentRect) - (lineHeight / 2)) + "px";
var topPoint = (CGRectGetMidY(contentRect) - (lineHeight / 2)) + "px";
break;
case CPBottomVerticalTextAlignment:
var topPoint = (_CGRectGetMaxY(contentRect) - lineHeight) + "px";
var topPoint = (CGRectGetMaxY(contentRect) - lineHeight) + "px";
break;
default:
var topPoint = _CGRectGetMinY(contentRect) + "px";
var topPoint = CGRectGetMinY(contentRect) + "px";
break;
}
element.style.top = topPoint;
var left = _CGRectGetMinX(contentRect);
var left = CGRectGetMinX(contentRect);
// If the browser has a built in left padding, compensate for it. We need the input text to be exactly on top of the original text.
if (CPFeatureIsCompatible(CPInput1PxLeftPadding))
left -= 1;
element.style.left = left + "px";
element.style.width = _CGRectGetWidth(contentRect) + "px";
element.style.width = CGRectGetWidth(contentRect) + "px";
element.style.height = ROUND(lineHeight) + "px";
element.style.lineHeight = ROUND(lineHeight) + "px";
element.style.verticalAlign = "top";
@@ -658,30 +683,34 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}, 0.0);
#endif
return YES;
}
/* @ignore */
/*! @ignore */
- (BOOL)resignFirstResponder
{
#if PLATFORM(DOM)
var element = [self _inputElement],
newValue = element.value,
error = @"";
if (newValue !== _stringValue)
// We might have been the first responder without actually editing.
if (_isEditing && CPTextFieldInputOwner === self)
{
[self _setStringValue:newValue];
}
var element = [self _inputElement],
newValue = element.value,
error = @"";
// If there is a formatter, always give it a chance to reject the resignation,
// even if the value has not changed.
if ([self _valueIsValid:newValue] === NO)
{
element.focus();
return NO;
}
if (newValue !== _stringValue)
{
[self _setStringValue:newValue];
}
// If there is a formatter, always give it a chance to reject the resignation,
// even if the value has not changed.
if ([self _valueIsValid:newValue] === NO)
{
element.focus();
return NO;
}
}
#endif
// When we are no longer the first responder we don't worry about the key status of our window anymore.
@@ -690,10 +719,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[self _resignFirstKeyResponder];
_isEditing = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
if ([self isEditable])
{
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:@{"CPTextMovement": [self _currentTextMovement]}]];
if ([self sendsActionOnEndEditing])
[self sendAction:[self action] to:[self target]];
if ([self sendsActionOnEndEditing])
[self sendAction:[self action] to:[self target]];
}
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
@@ -766,8 +798,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)_windowDidBecomeKey:(CPNotification)aNotification
{
if ([[self window] isKeyWindow] && [[self window] firstResponder] === self)
[self _becomeFirstKeyResponder];
if (!([self isEnabled] && [self isEditable]))
return;
var wind = [self window];
if ([wind isKeyWindow] && [wind firstResponder] === self)
if (![self _becomeFirstKeyResponder])
[wind makeFirstResponder:nil];
}
- (BOOL)_valueIsValid:(CPString)aValue
@@ -802,13 +840,24 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
/*!
Only text fields that can become first responder accepts first mouse.
Only text fields that can become first responder accept first mouse.
*/
- (BOOL)acceptsFirstMouse:(CPEvent)anEvent
{
return [self acceptsFirstResponder];
}
- (void)_didEdit
{
if (!_isEditing)
{
_isEditing = YES;
[self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
}
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
}
- (void)mouseDown:(CPEvent)anEvent
{
// Don't track! (ever?)
@@ -835,7 +884,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)mouseUp:(CPEvent)anEvent
{
if (![self isSelectable] && (![self isEditable] || ![self isEnabled]))
if (![self isEnabled] || !([self isSelectable] || [self isEditable]))
[[self nextResponder] mouseUp:anEvent];
else if ([self isSelectable])
{
@@ -847,13 +896,22 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
CPTextFieldCachedSelectStartFunction = nil
CPTextFieldCachedDragFunction = nil;
}
// TODO clickCount === 2 should select the clicked word.
if ([[CPApp currentEvent] clickCount] === 3)
{
[self selectText:nil];
return;
}
return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
}
}
- (void)mouseDragged:(CPEvent)anEvent
{
if (![self isSelectable] && (![self isEditable] || ![self isEnabled]))
if (![self isEnabled] || !([self isSelectable] || [self isEditable]))
[[self nextResponder] mouseDragged:anEvent];
else if ([self isSelectable])
return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
@@ -861,26 +919,21 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)keyUp:(CPEvent)anEvent
{
#if PLATFORM(DOM)
if (!([self isEnabled] && [self isEditable]))
return;
#if PLATFORM(DOM)
var newValue = [self _inputElement].value;
if (newValue !== _stringValue)
{
[self _setStringValue:newValue];
if (!_isEditing)
{
_isEditing = YES;
[self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
}
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
[self _didEdit];
}
#endif
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
#endif
}
- (void)keyDown:(CPEvent)anEvent
@@ -913,11 +966,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)insertNewline:(id)sender
{
if (!([self isEnabled] && [self isEditable]))
return;
var newValue = [self _inputElement].value;
if (newValue !== _stringValue)
{
[self _setStringValue:newValue];
[self _didEdit];
}
if ([self _valueIsValid:_stringValue])
@@ -930,7 +987,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
if (_isEditing)
{
_isEditing = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:@{"CPTextMovement": [self _currentTextMovement]}]];
}
// If there is no target action, or the sendAction call returns
@@ -956,6 +1013,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)_insertCharacterIgnoringFieldEditor:(CPString)aCharacter
{
if (!([self isEnabled] && [self isEditable]))
return;
#if PLATFORM(DOM)
var oldValue = _stringValue,
@@ -968,13 +1028,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
// NOTE: _stringValue is now the current input element value
if (oldValue !== _stringValue)
{
if (!_isEditing)
{
_isEditing = YES;
[self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
}
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
[self _didEdit];
}
#endif
@@ -1017,7 +1071,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
/*
@ignore
Sets the internal string value without updating the value in the input element.
This should only be invoked when the underlying text element's value has changed.
*/
@@ -1026,8 +1079,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return [self _setStringValue:aValue isNewValue:YES errorDescription:nil];
}
/*
@ignore
/*!
Sets the internal string value without updating the value in the input element.
If there is a formatter and formatting fails, returns NO. Otherwise returns YES.
*/
@@ -1086,10 +1138,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
value = undefined;
[super setObjectValue:value];
_stringValue = (value === nil || value === undefined) ? @"" : String(value);
}
else
_stringValue = formattedString;
}
_stringValue = [self stringValue];
else
_stringValue = [self stringValue];
#if PLATFORM(DOM)
@@ -1169,7 +1224,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
maxSize = [self currentValueForThemeAttribute:@"max-size"],
lineBreakMode = [self lineBreakMode],
text = (_stringValue || @" "),
textSize = _CGSizeMakeCopy(frameSize),
textSize = CGSizeMakeCopy(frameSize),
font = [self currentValueForThemeAttribute:@"font"];
textSize.width -= contentInset.left + contentInset.right;
@@ -1223,22 +1278,29 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)_selectText:(id)sender immediately:(BOOL)immediately
{
// Selecting the text in a field makes it the first responder
if (([self isEditable] || [self isSelectable]))
if ([self isEditable] || [self isSelectable])
{
var wind = [self window];
#if PLATFORM(DOM)
var element = [self _inputElement];
if ([wind firstResponder] === self)
if ([self isEditable])
{
if (immediately)
element.select();
else
window.setTimeout(function() { element.select(); }, 0);
var element = [self _inputElement];
if ([wind firstResponder] === self)
{
if (immediately)
element.select();
else
window.setTimeout(function() { element.select(); }, 0);
}
else if (wind !== nil && [wind makeFirstResponder:self])
[self _selectText:sender immediately:immediately];
}
else
{
[self setSelectedRange:CPMakeRange(0, _stringValue.length)];
}
else if (wind !== nil && [wind makeFirstResponder:self])
[self _selectText:sender immediately:immediately];
#else
// Even if we can't actually select the text we need to preserve the first
// responder side effect.
@@ -1251,36 +1313,70 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)copy:(id)sender
{
if (![CPPlatform isBrowser])
// First write to the Cappuccino clipboard.
var stringToCopy = nil;
if ([self isEditable])
{
var selectedRange = [self selectedRange];
if (selectedRange.length < 1)
return;
var pasteboard = [CPPasteboard generalPasteboard],
stringForPasting = [_stringValue substringWithRange:selectedRange];
stringToCopy = [_stringValue substringWithRange:selectedRange];
}
else
{
// selectedRange won't work if we're displaying our text using a <div>. Instead we have to ask the browser
// what's selected and hope it's right in a Cappuccino context as well.
#if PLATFORM(DOM)
stringToCopy = [[[self window] platformWindow] _selectedText];
#endif
}
[pasteboard declareTypes:[CPStringPboardType] owner:nil];
[pasteboard setString:stringForPasting forType:CPStringPboardType];
var pasteboard = [CPPasteboard generalPasteboard];
[pasteboard declareTypes:[CPStringPboardType] owner:nil];
[pasteboard setString:stringToCopy forType:CPStringPboardType];
if ([CPPlatform isBrowser])
{
// Then also allow the browser to capture the copied text into the system clipboard.
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
}
- (void)cut:(id)sender
{
if (![CPPlatform isBrowser])
if (![self isEnabled])
return;
[self copy:sender];
if (![self isEditable])
return;
if (![[CPApp currentEvent] _platformIsEffectingCutOrPaste])
{
[self copy:sender];
[self deleteBackward:sender];
}
// If we don't have an oninput listener, we won't detect the change made by the cut and need to fake a key up "soon".
else if (!CPFeatureIsCompatible(CPInputOnInputEventFeature))
[CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(keyUp:) userInfo:nil repeats:NO];
else
{
// Allow the browser's standard cut handling. This should also result in the deleteBackward: happening.
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
// If we don't have an oninput listener, we won't detect the change made by the cut and need to fake a key up "soon".
if (!CPFeatureIsCompatible(CPInputOnInputEventFeature))
[CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(keyUp:) userInfo:nil repeats:NO];
}
}
- (void)paste:(id)sender
{
if (![CPPlatform isBrowser])
if (!([self isEnabled] && [self isEditable]))
return;
if (![[CPApp currentEvent] _platformIsEffectingCutOrPaste])
{
var pasteboard = [CPPasteboard generalPasteboard];
@@ -1294,15 +1390,24 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:pasteString];
[self setStringValue:newValue];
[self _didEdit];
[self setSelectedRange:CPMakeRange(selectedRange.location + pasteString.length, 0)];
}
// If we don't have an oninput listener, we won't detect the change made by the cut and need to fake a key up "soon".
else if (!CPFeatureIsCompatible(CPInputOnInputEventFeature))
[CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(keyUp:) userInfo:nil repeats:NO];
else
{
// Allow the browser's standard paste handling.
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
if (!CPFeatureIsCompatible(CPInputOnInputEventFeature))
[CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(keyUp:) userInfo:nil repeats:NO];
}
}
- (CPRange)selectedRange
{
// TODO Need a way to figure out the selected range if we're not using an input. Need
// to get whole document selection and somehow see which part is inside of this text field.
if ([[self window] firstResponder] !== self)
return CPMakeRange(0, 0);
@@ -1346,35 +1451,48 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
#if PLATFORM(DOM)
var inputElement = [self _inputElement];
try
if (![self isEditable])
{
if ([inputElement.selectionStart isKindOfClass:CPNumber])
{
inputElement.selectionStart = aRange.location;
inputElement.selectionEnd = CPMaxRange(aRange);
}
else
{
// browsers which don't support selectionStart/selectionEnd (aka IE).
var theDocument = inputElement.ownerDocument || inputElement.document,
existingRange = theDocument.selection.createRange(),
range = inputElement.createTextRange();
// No input element - selectable text field only.
var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"bezel-view"];
if (range.inRange(existingRange))
if (contentView)
[contentView setSelectedRange:aRange];
}
else
{
// Input element
var inputElement = [self _inputElement];
try
{
if ([inputElement.selectionStart isKindOfClass:CPNumber])
{
range.collapse(true);
range.move('character', aRange.location);
range.moveEnd('character', aRange.length);
range.select();
inputElement.selectionStart = aRange.location;
inputElement.selectionEnd = CPMaxRange(aRange);
}
else
{
// browsers which don't support selectionStart/selectionEnd (aka IE).
var theDocument = inputElement.ownerDocument || inputElement.document,
existingRange = theDocument.selection.createRange(),
range = inputElement.createTextRange();
if (range.inRange(existingRange))
{
range.collapse(true);
range.move('character', aRange.location);
range.moveEnd('character', aRange.length);
range.select();
}
}
}
catch (e)
{
}
}
catch (e)
{
}
#endif
}
@@ -1385,18 +1503,84 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)deleteBackward:(id)sender
{
if (!([self isEnabled] && [self isEditable]))
return;
var selectedRange = [self selectedRange];
if (selectedRange.length < 2)
return;
if (selectedRange.length < 1)
{
if (selectedRange.location < 1)
return;
selectedRange.location += 1;
selectedRange.length -= 1;
// Delete a single element backward from the insertion point if there's no selection.
selectedRange.location -= 1;
selectedRange.length += 1;
}
var newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:""];
[self setStringValue:newValue];
[self setSelectedRange:CPMakeRange(selectedRange.location, 0)];
[self _didEdit];
#if PLATFORM(DOM)
// Since we just performed the deletion manually, we don't need the browser to do anything else.
// (Previously we would allow the event to propagate for the browser to delete 1 character only,
// and we'd delete the rest manually. But this meant that if deleteBackward: was called without
// it being a browser backspace event, 1 character would be left behind.)
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
#endif
}
- (void)delete:(id)sender
{
if (!([self isEnabled] && [self isEditable]))
return;
// delete: only works when there's a selection (as opposed to deleteForward: and deleteBackward:).
var selectedRange = [self selectedRange];
if (selectedRange.length < 1)
return;
var newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:""];
[self setStringValue:newValue];
[self setSelectedRange:CPMakeRange(selectedRange.location, 0)];
[self _didEdit];
#if PLATFORM(DOM)
// Since we just performed the deletion manually, we don't need the browser to do anything else.
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
#endif
}
- (void)deleteForward:(id)sender
{
if (!([self isEnabled] && [self isEditable]))
return;
var selectedRange = [self selectedRange];
if (selectedRange.length < 1)
{
if (selectedRange.location + 1 >= _stringValue.length)
return;
selectedRange.length += 1;
}
var newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:""];
[self setStringValue:newValue];
[self setSelectedRange:CPMakeRange(selectedRange.location, 0)];
[self _didEdit];
#if PLATFORM(DOM)
// Since we just performed the deletion manually, we don't need the browser to do anything else.
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
#endif
}
#pragma mark Setting the Delegate
@@ -1463,14 +1647,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
return _CGRectInsetByInset(bounds, contentInset);
return CGRectInsetByInset(bounds, contentInset);
}
- (CGRect)bezelRectForBounds:(CGRect)bounds
{
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
return _CGRectInsetByInset(bounds, bezelInset);
return CGRectInsetByInset(bounds, bezelInset);
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
@@ -1488,7 +1672,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{
if (aName === "bezel-view")
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[view setHitTests:NO];
@@ -1496,7 +1680,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
else
{
var view = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
var view = [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()];
[view setHitTests:NO];
@@ -1563,6 +1747,65 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
}
#pragma mark Overrides
- (void)viewDidHide
{
[super viewDidHide];
if ([[self window] firstResponder] === self)
[self _resignFirstKeyResponder];
}
- (void)viewDidUnhide
{
[super viewDidUnhide];
if ([self isEditable] && [[self window] firstResponder] === self)
[self _becomeFirstKeyResponder];
}
- (BOOL)validateUserInterfaceItem:(id /*<CPValidatedUserInterfaceItem>*/)anItem
{
var theAction = [anItem action];
if (![self isEditable] && (theAction == @selector(cut:) || theAction == @selector(paste:) || theAction == @selector(delete:)))
return NO;
// FIXME - [self selectedRange] is always empty if we're not an editable field, so we must assume yes here.
if (![self isEditable])
return YES;
if (theAction == @selector(copy:) || theAction == @selector(cut:) || theAction == @selector(delete:))
return [self selectedRange].length;
return YES;
}
#pragma mark Private
- (BOOL)_isWithinUsablePlatformRect
{
// Make sure the text field is completely within the platform window
// so the browser will not scroll it into view.
var wind = [self window];
// If the field is not yet within a window, it can't be first responder
if (!wind)
return NO;
var frame = [self convertRectToBase:[self bounds]],
usableRect = [[wind platformWindow] usableContentFrame];
frame.origin = [wind convertBaseToGlobal:frame.origin];
return (CGRectGetMinX(frame) >= CGRectGetMinX(usableRect) &&
CGRectGetMaxX(frame) <= CGRectGetMaxX(usableRect) &&
CGRectGetMinY(frame) >= CGRectGetMinY(usableRect) &&
CGRectGetMaxY(frame) <= CGRectGetMaxY(usableRect));
}
@end
var secureStringForString = function(aString)
@@ -1640,7 +1883,7 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
@implementation _CPTextFieldValueBinder : CPBinder
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options forBinding:(CPBinder)aBinding
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options forBinding:(CPString)aBinding
{
[super _updatePlaceholdersWithOptions:options];
+30 -23
View File
@@ -404,25 +404,25 @@ function CPThemeStateName(aState)
return name;
}
CPThemeStateNames[0] = "normal";
CPThemeStateNormal = CPThemeStates["normal"] = 0;
CPThemeStateDisabled = CPThemeState("disabled");
CPThemeStateHovered = CPThemeState("hovered");
CPThemeStateHighlighted = CPThemeState("highlighted");
CPThemeStateSelected = CPThemeState("selected");
CPThemeStateTableDataView = CPThemeState("tableDataView");
CPThemeStateSelectedDataView = CPThemeStateSelectedTableDataView = CPThemeState("selectedTableDataView");
CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
CPThemeStateBezeled = CPThemeState("bezeled");
CPThemeStateBordered = CPThemeState("bordered");
CPThemeStateEditable = CPThemeState("editable");
CPThemeStateEditing = CPThemeState("editing");
CPThemeStateVertical = CPThemeState("vertical");
CPThemeStateDefault = CPThemeState("default");
CPThemeStateCircular = CPThemeState("circular");
CPThemeStateAutocompleting = CPThemeState("autocompleting");
CPThemeStateMainWindow = CPThemeState("mainWindow");
CPThemeStateKeyWindow = CPThemeState("keyWindow");
CPThemeStateNames[0] = "normal";
CPThemeStateNormal = CPThemeStates["normal"] = 0;
CPThemeStateDisabled = CPThemeState("disabled");
CPThemeStateHovered = CPThemeState("hovered");
CPThemeStateHighlighted = CPThemeState("highlighted");
CPThemeStateSelected = CPThemeState("selected");
CPThemeStateTableDataView = CPThemeState("tableDataView");
CPThemeStateSelectedDataView = CPThemeState("selectedTableDataView");
CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
CPThemeStateBezeled = CPThemeState("bezeled");
CPThemeStateBordered = CPThemeState("bordered");
CPThemeStateEditable = CPThemeState("editable");
CPThemeStateEditing = CPThemeState("editing");
CPThemeStateVertical = CPThemeState("vertical");
CPThemeStateDefault = CPThemeState("default");
CPThemeStateCircular = CPThemeState("circular");
CPThemeStateAutocompleting = CPThemeState("autocompleting");
CPThemeStateMainWindow = CPThemeState("mainWindow");
CPThemeStateKeyWindow = CPThemeState("keyWindow");
@implementation _CPThemeAttribute : CPObject
{
@@ -431,7 +431,7 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
CPDictionary _values @accessors(readonly, getter=values);
JSObject _cache;
_CPThemeAttribute _parentAttribute;
_CPThemeAttribute _themeDefaultAttribute;
}
- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue
@@ -542,11 +542,18 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
}
if (value === undefined || value === nil)
value = [_parentAttribute valueForState:aState];
value = [_themeDefaultAttribute valueForState:aState];
if (value === undefined || value === nil)
{
value = _defaultValue;
// Class theme attributes cannot use nil because it's a dictionary.
// So transform CPNull into nil.
if (value === [CPNull null])
value = nil;
}
_cache[aState] = value;
return value;
@@ -554,11 +561,11 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
- (void)setParentAttribute:(_CPThemeAttribute)anAttribute
{
if (_parentAttribute === anAttribute)
if (_themeDefaultAttribute === anAttribute)
return;
_cache = { };
_parentAttribute = anAttribute;
_themeDefaultAttribute = anAttribute;
}
- (_CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
Executable → Regular
+61 -45
View File
@@ -20,8 +20,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "../Foundation/CPRange.h"
@import <Foundation/CPCharacterSet.j>
@import <Foundation/CPIndexSet.j>
@import <Foundation/CPTimer.j>
@@ -36,6 +34,8 @@
@import "CPWindow_Constants.j"
@global CPApp
@global CPTextFieldDidFocusNotification
@global CPTextFieldDidBlurNotification
#if PLATFORM(DOM)
@@ -98,9 +98,9 @@ CPTokenFieldDeleteButtonType = 1;
return "tokenfield";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{ @"editor-inset": _CGInsetMakeZero() };
return @{ @"editor-inset": CGInsetMakeZero() };
}
- (id)initWithFrame:(CGRect)frame
@@ -124,7 +124,7 @@ CPTokenFieldDeleteButtonType = 1;
- (void)_init
{
_selectedRange = _CPMakeRange(0, 0);
_selectedRange = CPMakeRange(0, 0);
var frame = [self frame];
@@ -214,7 +214,7 @@ CPTokenFieldDeleteButtonType = 1;
if (delegateApprovedObjectsCount)
location += delegateApprovedObjectsCount;
_selectedRange = _CPMakeRange(location, 0);
_selectedRange = CPMakeRange(location, 0);
[self _inputElement].value = @"";
[self setNeedsLayout];
@@ -234,12 +234,12 @@ CPTokenFieldDeleteButtonType = 1;
if (indexOfToken == CPNotFound)
{
if (!extend)
_selectedRange = _CPMakeRange([[self _tokens] count], 0);
_selectedRange = CPMakeRange([[self _tokens] count], 0);
}
else if (extend)
_selectedRange = CPUnionRange(_selectedRange, _CPMakeRange(indexOfToken, 1));
_selectedRange = CPUnionRange(_selectedRange, CPMakeRange(indexOfToken, 1));
else
_selectedRange = _CPMakeRange(indexOfToken, 1);
_selectedRange = CPMakeRange(indexOfToken, 1);
[self setNeedsLayout];
}
@@ -249,7 +249,7 @@ CPTokenFieldDeleteButtonType = 1;
var indexOfToken = [[self _tokens] indexOfObject:token];
if (CPLocationInRange(indexOfToken, _selectedRange))
_selectedRange = _CPMakeRange(MAX(indexOfToken, _selectedRange.location), MIN(_selectedRange.length, indexOfToken - _selectedRange.location));
_selectedRange = CPMakeRange(MAX(indexOfToken, _selectedRange.location), MIN(_selectedRange.length, indexOfToken - _selectedRange.location));
[self setNeedsLayout];
}
@@ -302,7 +302,7 @@ CPTokenFieldDeleteButtonType = 1;
[self setObjectValue:tokens];
// setObjectValue moves the cursor to the end of the selection. We want it to stay
// where the selected tokens were.
_selectedRange = _CPMakeRange(collapsedSelection, 0);
_selectedRange = CPMakeRange(collapsedSelection, 0);
[self _controlTextDidChange];
}
@@ -332,13 +332,18 @@ CPTokenFieldDeleteButtonType = 1;
[self scrollRectToVisible:[self bounds]];
if ([[self window] isKeyWindow])
[self _becomeFirstKeyResponder];
return [self _becomeFirstKeyResponder];
return YES;
}
- (void)_becomeFirstKeyResponder
- (BOOL)_becomeFirstKeyResponder
{
// If the token field is still not completely on screen, refuse to become
// first responder, because the browser will scroll it into view out of our control.
if (![self _isWithinUsablePlatformRect])
return NO;
[self setThemeState:CPThemeStateEditing];
[self _updatePlaceholderState];
@@ -358,11 +363,16 @@ CPTokenFieldDeleteButtonType = 1;
switch ([self alignment])
{
case CPCenterTextAlignment: element.style.textAlign = "center";
break;
case CPRightTextAlignment: element.style.textAlign = "right";
break;
default: element.style.textAlign = "left";
case CPCenterTextAlignment:
element.style.textAlign = "center";
break;
case CPRightTextAlignment:
element.style.textAlign = "right";
break;
default:
element.style.textAlign = "left";
}
var contentRect = [self contentRectForBounds:[self bounds]];
@@ -384,6 +394,8 @@ CPTokenFieldDeleteButtonType = 1;
element.focus();
CPTokenFieldInputOwner = self;
}, 0.0);
[self textDidFocus:[CPNotification notificationWithName:CPTextFieldDidFocusNotification object:self userInfo:nil]];
}, 0.0);
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
@@ -400,6 +412,8 @@ CPTokenFieldDeleteButtonType = 1;
}
#endif
return YES;
}
- (BOOL)resignFirstResponder
@@ -414,12 +428,14 @@ CPTokenFieldDeleteButtonType = 1;
if (_shouldNotifyTarget)
{
_shouldNotifyTarget = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:@{"CPTextMovement": [self _currentTextMovement]}]];
if ([self sendsActionOnEndEditing])
[self sendAction:[self action] to:[self target]];
}
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
return YES;
}
@@ -481,7 +497,7 @@ CPTokenFieldDeleteButtonType = 1;
- (void)_mouseUpOnToken:(_CPTokenFieldToken)aToken withEvent:(CPEvent)anEvent
{
if (_mouseDownEvent && _CGPointEqualToPoint([_mouseDownEvent locationInWindow], [anEvent locationInWindow]))
if (_mouseDownEvent && CGPointEqualToPoint([_mouseDownEvent locationInWindow], [anEvent locationInWindow]))
{
[self _selectToken:aToken byExtendingSelection:[anEvent modifierFlags] & CPShiftKeyMask];
[[self window] makeFirstResponder:self];
@@ -629,7 +645,7 @@ CPTokenFieldDeleteButtonType = 1;
[[self _tokens] makeObjectsPerformSelector:@selector(setEditable:) withObject:shouldBeEditable];
}
- (void)sendAction:(SEL)anAction to:(id)anObject
- (BOOL)sendAction:(SEL)anAction to:(id)anObject
{
_shouldNotifyTarget = NO;
[super sendAction:anAction to:anObject];
@@ -637,7 +653,7 @@ CPTokenFieldDeleteButtonType = 1;
// Incredible hack to disable supers implementation
// so it cannot change our object value and break the tokenfield
- (void)_setStringValue:(id)aValue
- (BOOL)_setStringValue:(CPString)aValue
{
}
@@ -817,7 +833,7 @@ CPTokenFieldDeleteButtonType = 1;
if (_selectedRange.length)
{
// Place the cursor at the end of the selection and collapse.
_selectedRange.location = _CPMaxRange(_selectedRange);
_selectedRange.location = CPMaxRange(_selectedRange);
_selectedRange.length = 0;
}
else
@@ -838,7 +854,7 @@ CPTokenFieldDeleteButtonType = 1;
- (void)moveRightAndModifySelection:(id)sender
{
if (_CPMaxRange(_selectedRange) < [[self _tokens] count] && [self _editorValue] == "")
if (CPMaxRange(_selectedRange) < [[self _tokens] count] && [self _editorValue] == "")
{
// Leave the selection location in place but include the next token to the right.
_selectedRange.length++;
@@ -917,7 +933,7 @@ CPTokenFieldDeleteButtonType = 1;
// Finish any editing.
[self _autocomplete];
_selectedRange = _CPMakeRange(0, [[self _tokens] count]);
_selectedRange = CPMakeRange(0, [[self _tokens] count]);
[self setNeedsLayout];
}
@@ -1009,7 +1025,7 @@ CPTokenFieldDeleteButtonType = 1;
return;
// Move each token into the right position.
var contentRect = _CGRectMakeCopy([contentView bounds]),
var contentRect = CGRectMakeCopy([contentView bounds]),
contentOrigin = contentRect.origin,
contentSize = contentRect.size,
offset = CGPointMake(contentOrigin.x, contentOrigin.y),
@@ -1026,11 +1042,11 @@ CPTokenFieldDeleteButtonType = 1;
// Get the height of a typical token, or a token token if you will.
[tokenToken sizeToFit];
var tokenHeight = _CGRectGetHeight([tokenToken bounds]);
var tokenHeight = CGRectGetHeight([tokenToken bounds]);
var fitAndFrame = function(width, height)
{
var r = _CGRectMake(0, 0, width, height);
var r = CGRectMake(0, 0, width, height);
if (offset.x + width >= contentSize.width && offset.x > contentOrigin.x)
{
@@ -1043,8 +1059,8 @@ CPTokenFieldDeleteButtonType = 1;
// Make sure the frame fits.
var scrollHeight = offset.y + tokenHeight + CEIL(spaceBetweenTokens.height / 2.0);
if (_CGRectGetHeight([contentView bounds]) < scrollHeight)
[contentView setFrameSize:_CGSizeMake(_CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
if (CGRectGetHeight([contentView bounds]) < scrollHeight)
[contentView setFrameSize:CGSizeMake(CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
offset.x += width + spaceBetweenTokens.width;
@@ -1078,12 +1094,12 @@ CPTokenFieldDeleteButtonType = 1;
// When editing, always scroll to the cursor.
if (_selectedRange.length == 0)
[[_tokenScrollView documentView] scrollPoint:_CGPointMake(0, _inputFrame.origin.y)];
[[_tokenScrollView documentView] scrollPoint:CGPointMake(0, _inputFrame.origin.y)];
};
for (var i = 0, count = [tokens count]; i < count; i++)
{
if (isEditing && !_selectedRange.length && i == _CPMaxRange(_selectedRange))
if (isEditing && !_selectedRange.length && i == CPMaxRange(_selectedRange))
placeEditor(false);
var tokenView = [tokens objectAtIndex:i];
@@ -1104,7 +1120,7 @@ CPTokenFieldDeleteButtonType = 1;
[tokenView setButtonType:_buttonType];
}
if (isEditing && !_selectedRange.length && _CPMaxRange(_selectedRange) >= [tokens count])
if (isEditing && !_selectedRange.length && CPMaxRange(_selectedRange) >= [tokens count])
placeEditor(true);
// Hide the editor if there are selected tokens, but still keep it active
@@ -1125,8 +1141,8 @@ CPTokenFieldDeleteButtonType = 1;
// Trim off any excess height downwards (in case we shrank).
var scrollHeight = offset.y + tokenHeight;
if (_CGRectGetHeight([contentView bounds]) > scrollHeight)
[contentView setFrameSize:_CGSizeMake(_CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
if (CGRectGetHeight([contentView bounds]) > scrollHeight)
[contentView setFrameSize:CGSizeMake(CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
if (_shouldScrollTo !== CPScrollDestinationNone)
{
@@ -1138,7 +1154,7 @@ CPTokenFieldDeleteButtonType = 1;
if (scrollToToken === CPScrollDestinationLeft)
scrollToToken = tokens[_selectedRange.location]
else if (scrollToToken === CPScrollDestinationRight)
scrollToToken = tokens[MAX(0, _CPMaxRange(_selectedRange) - 1)];
scrollToToken = tokens[MAX(0, CPMaxRange(_selectedRange) - 1)];
[self _scrollTokenViewToVisible:scrollToToken];
}
@@ -1151,7 +1167,7 @@ CPTokenFieldDeleteButtonType = 1;
if (!aToken)
return;
return [[_tokenScrollView documentView] scrollPoint:_CGPointMake(0, [aToken frameOrigin].y)];
return [[_tokenScrollView documentView] scrollPoint:CGPointMake(0, [aToken frameOrigin].y)];
}
@end
@@ -1183,7 +1199,7 @@ CPTokenFieldDeleteButtonType = 1;
- (CGPoint)_completionOrigin:(_CPAutocompleteMenu)anAutocompleteMenu
{
var relativeFrame = _inputFrame ? [[_tokenScrollView documentView] convertRect:_inputFrame toView:self ] : [self bounds];
return _CGPointMake(_CGRectGetMinX(relativeFrame), _CGRectGetMaxY(relativeFrame));
return CGPointMake(CGRectGetMinX(relativeFrame), CGRectGetMaxY(relativeFrame));
}
/*!
@@ -1403,7 +1419,7 @@ CPTokenFieldDeleteButtonType = 1;
- (CGSize)_minimumFrameSize
{
var size = _CGSizeMakeZero(),
var size = CGSizeMakeZero(),
minSize = [self currentValueForThemeAttribute:@"min-size"],
contentInset = [self currentValueForThemeAttribute:@"content-inset"];
@@ -1478,7 +1494,7 @@ CPTokenFieldDeleteButtonType = 1;
buttonOffset = [_disclosureButton currentValueForThemeAttribute:@"offset"],
buttonSize = [_disclosureButton currentValueForThemeAttribute:@"min-size"];
[_disclosureButton setFrame:_CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
[_disclosureButton setFrame:CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
break;
case CPTokenFieldDeleteButtonType:
[_deleteButton setEnabled:[self isEditable] && [self isEnabled]];
@@ -1487,7 +1503,7 @@ CPTokenFieldDeleteButtonType = 1;
buttonOffset = [_deleteButton currentValueForThemeAttribute:@"offset"],
buttonSize = [_deleteButton currentValueForThemeAttribute:@"min-size"];
[_deleteButton setFrame:_CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
[_deleteButton setFrame:CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
break;
}
}
@@ -1525,11 +1541,11 @@ CPTokenFieldDeleteButtonType = 1;
{
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
var attributes = [CPButton themeAttributes];
[attributes setObject:_CGPointMake(15, 5) forKey:@"offset"];
[attributes setObject:CGPointMake(15, 5) forKey:@"offset"];
return attributes;
}
@@ -1555,11 +1571,11 @@ CPTokenFieldDeleteButtonType = 1;
{
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
var attributes = [CPButton themeAttributes];
[attributes setObject:_CGPointMake(15, 5) forKey:@"offset"];
[attributes setObject:CGPointMake(15, 5) forKey:@"offset"];
return attributes;
}
+22 -31
View File
@@ -93,7 +93,7 @@ var CPToolbarsByIdentifier = nil,
BOOL _showsBaselineSeparator;
BOOL _allowsUserCustomization;
BOOL _isVisible;
int _sizeMode @accessors(property=sizeMode);
CPToolbarSizeMode _sizeMode @accessors(property=sizeMode);
int _desiredHeight;
id _delegate;
@@ -165,15 +165,6 @@ var CPToolbarsByIdentifier = nil,
return self;
}
/*!
Sets the toolbar's display mode. NOT YET IMPLEMENTED.
*/
- (void)setDisplayMode:(CPToolbarDisplayMode)aDisplayMode
{
}
/*!
Returns the toolbar's identifier
*/
@@ -603,14 +594,14 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
return @"toolbar-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"item-margin": 10.0,
@"extra-item-width": 20.0,
@"extra-item-extra-image": [CPNull null],
@"extra-item-extra-alternate-image": [CPNull null],
@"content-inset": _CGInsetMake(4.0, 4.0, 4.0, 10),
@"content-inset": CGInsetMake(4.0, 4.0, 4.0, 10),
@"regular-size-height": 59.0,
@"small-size-height": 46.0,
@"image-item-separator-color": [CPNull null],
@@ -629,7 +620,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
_labelColor = [CPColor blackColor];
_labelShadowColor = [CPColor colorWithWhite:1.0 alpha:0.75];
_additionalItemsButton = [[CPPopUpButton alloc] initWithFrame:_CGRectMake(0.0, 0.0, 10.0, 15.0) pullsDown:YES];
_additionalItemsButton = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 15.0) pullsDown:YES];
[_additionalItemsButton setBordered:NO];
[_additionalItemsButton setImagePosition:CPImageOnly];
@@ -679,7 +670,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
{
// We begin by recalculating the visible items.
var items = [_toolbar items],
itemsWidth = _CGRectGetWidth([self bounds]),
itemsWidth = CGRectGetWidth([self bounds]),
minWidth = _minWidth,
// FIXME: This should be a CPSet.
invisibleItemsSortedByPriority = [];
@@ -766,7 +757,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
// static width (min==max). This handles the case where the user did setView:
// with a view of a different size than minSize/maxSize
else
[view setFrameSize:_CGSizeMake(minSize.width, height)];
[view setFrameSize:CGSizeMake(minSize.width, height)];
[view setHidden:NO];
}
@@ -801,7 +792,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
remainingSpace += proposedWidth - constrainedWidth;
}
[view setFrameSize:_CGSizeMake(constrainedWidth, height)];
[view setFrameSize:CGSizeMake(constrainedWidth, height)];
}
}
@@ -815,9 +806,9 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
for (; index < count; ++index)
{
var view = [self viewForItem:_visibleItems[index]],
viewWidth = _CGRectGetWidth([view frame]);
viewWidth = CGRectGetWidth([view frame]);
[view setFrame:_CGRectMake(x, y, viewWidth, height)];
[view setFrame:CGRectMake(x, y, viewWidth, height)];
x += viewWidth + [self valueForThemeAttribute:@"item-margin"];
}
@@ -851,7 +842,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
if (needsAdditionalItemsButton)
{
[_additionalItemsButton setFrameOrigin:_CGPointMake(itemsWidth + 5.0, (_CGRectGetHeight([self bounds]) - _CGRectGetHeight([_additionalItemsButton frame])) / 2.0)];
[_additionalItemsButton setFrameOrigin:CGPointMake(itemsWidth + 5.0, (CGRectGetHeight([self bounds]) - CGRectGetHeight([_additionalItemsButton frame])) / 2.0)];
[self addSubview:_additionalItemsButton];
@@ -994,12 +985,12 @@ var LABEL_MARGIN = 2.0;
{
_toolbarItem = aToolbarItem;
_labelField = [[CPTextField alloc] initWithFrame:_CGRectMakeZero()];
_labelField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_labelField setFont:[CPFont systemFontOfSize:11.0]];
[_labelField setTextColor:[self FIXME_labelColor]];
[_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
[_labelField setTextShadowOffset:_CGSizeMake(0.0, 1.0)];
[_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_labelField setAutoresizingMask:CPViewWidthSizable | CPViewMinXMargin];
[self addSubview:_labelField];
@@ -1101,8 +1092,8 @@ var LABEL_MARGIN = 2.0;
[_labelField setHidden:iconOnly];
[_view setHidden:labelOnly];
_minSize = _CGSizeMake(MAX(_labelSize.width, minSize.width), (labelOnly ? 0 : minSize.height) + (iconOnly ? 0 : _labelSize.height + LABEL_MARGIN));
_maxSize = _CGSizeMake(MAX(_labelSize.width, maxSize.width), 100000000.0);
_minSize = CGSizeMake(MAX(_labelSize.width, minSize.width), (labelOnly ? 0 : minSize.height) + (iconOnly ? 0 : _labelSize.height + LABEL_MARGIN));
_maxSize = CGSizeMake(MAX(_labelSize.width, maxSize.width), 100000000.0);
[_toolbar tile];
}
@@ -1116,14 +1107,14 @@ var LABEL_MARGIN = 2.0;
return;
var bounds = [self bounds],
width = _CGRectGetWidth(bounds);
width = CGRectGetWidth(bounds);
if (identifier === CPToolbarSeparatorItemIdentifier)
{
var itemSeparatorColor = [_toolbar valueForThemeAttribute:@"image-item-separator-color"],
itemSeparatorSize = [_toolbar valueForThemeAttribute:@"image-item-separator-size"];
[_view setFrame:_CGRectMake(ROUND((width - itemSeparatorSize.size.width) / 2.0), 0.0, itemSeparatorSize.size.width, _CGRectGetHeight(bounds))];
[_view setFrame:CGRectMake(ROUND((width - itemSeparatorSize.size.width) / 2.0), 0.0, itemSeparatorSize.size.width, CGRectGetHeight(bounds))];
[_view setBackgroundColor:itemSeparatorColor];
return;
@@ -1133,17 +1124,17 @@ var LABEL_MARGIN = 2.0;
var view = _view || _imageView,
itemMaxSize = [_toolbarItem maxSize],
iconOnly = [[_toolbarItem toolbar] displayMode] === CPToolbarDisplayModeIconOnly,
height = _CGRectGetHeight(bounds) - (iconOnly ? 0 : _labelSize.height),
height = CGRectGetHeight(bounds) - (iconOnly ? 0 : _labelSize.height),
viewWidth = MIN(itemMaxSize.width, width),
viewHeight = MIN(itemMaxSize.height, height);
[view setFrame:_CGRectMake(ROUND((width - viewWidth) / 2.0),
[view setFrame:CGRectMake(ROUND((width - viewWidth) / 2.0),
ROUND((height - viewHeight) / 2.0),
viewWidth,
viewHeight)];
// Label is always drawn at the bottom of the view. So if the view is really tall but the icon is tiny, the icon is centred above the label while the label remains on the bottom.
[_labelField setFrameOrigin:_CGPointMake(ROUND((width - _labelSize.width) / 2.0), _CGRectGetHeight(bounds) - _labelSize.height)];
[_labelField setFrameOrigin:CGPointMake(ROUND((width - _labelSize.width) / 2.0), CGRectGetHeight(bounds) - _labelSize.height)];
}
- (void)mouseDown:(CPEvent)anEvent
@@ -1210,7 +1201,7 @@ var LABEL_MARGIN = 2.0;
if (alternateImage)
[_imageView setImage:alternateImage];
[_labelField setTextShadowOffset:_CGSizeMakeZero()];
[_labelField setTextShadowOffset:CGSizeMakeZero()];
}
else
{
@@ -1219,13 +1210,13 @@ var LABEL_MARGIN = 2.0;
if (image)
[_imageView setImage:image];
[_labelField setTextShadowOffset:_CGSizeMake(0.0, 1.0)];
[_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
}
[_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
}
- (void)sendAction:(SEL)anAction to:(id)aSender
- (BOOL)sendAction:(SEL)anAction to:(id)aSender
{
[CPApp sendAction:anAction to:aSender from:_toolbarItem];
}
+396 -115
View File
@@ -43,6 +43,26 @@
@global appkit_tag_dom_elements
#if PLATFORM(DOM)
if (typeof(appkit_tag_dom_elements) !== "undefined" && appkit_tag_dom_elements)
{
AppKitTagDOMElement = function(owner, element)
{
element.setAttribute("data-cappuccino-view", [owner className]);
element.setAttribute("data-cappuccino-uid", [owner UID]);
}
}
else
{
AppKitTagDOMElement = function(owner, element)
{
// By default, do nothing.
}
}
#endif
/*
@global
@group CPViewAutoresizingMasks
@@ -179,6 +199,11 @@ var CPViewFlags = { },
_CPViewFullScreenModeState _fullScreenModeState;
// Zoom Support
BOOL _isScaled;
CGSize _hierarchyScaleSize;
CGSize _scaleSize;
// Layout Support
BOOL _needsLayout;
JSObject _ephemeralSubviews;
@@ -294,8 +319,8 @@ var CPViewFlags = { },
if (self)
{
var width = _CGRectGetWidth(aFrame),
height = _CGRectGetHeight(aFrame);
var width = CGRectGetWidth(aFrame),
height = CGRectGetHeight(aFrame);
_subviews = [];
_registeredDraggedTypes = [CPSet set];
@@ -303,8 +328,8 @@ var CPViewFlags = { },
_tag = -1;
_frame = _CGRectMakeCopy(aFrame);
_bounds = _CGRectMake(0.0, 0.0, width, height);
_frame = CGRectMakeCopy(aFrame);
_bounds = CGRectMake(0.0, 0.0, width, height);
_autoresizingMask = CPViewNotSizable;
_autoresizesSubviews = YES;
@@ -314,15 +339,17 @@ var CPViewFlags = { },
_isHidden = NO;
_hitTests = YES;
_hierarchyScaleSize = CGSizeMake(1.0 , 1.0);
_scaleSize = CGSizeMake(1.0, 1.0);
_isScaled = NO;
#if PLATFORM(DOM)
_DOMElement = DOMElementPrototype.cloneNode(false);
AppKitTagDOMElement(self, _DOMElement);
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(aFrame), _CGRectGetMinY(aFrame));
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(aFrame), CGRectGetMinY(aFrame));
CPDOMDisplayServerSetStyleSize(_DOMElement, width, height);
if (typeof(appkit_tag_dom_elements) !== "undefined" && !!appkit_tag_dom_elements)
_DOMElement.setAttribute("data-cappuccino-view", [self className]);
_DOMImageParts = [];
_DOMImageSizes = [];
#endif
@@ -373,9 +400,9 @@ var CPViewFlags = { },
#if PLATFORM(DOM)
if (_DOMElement.addEventListener)
{
_DOMElement.addEventListener("mouseover", _toolTipFunctionIn, NO);
_DOMElement.addEventListener("keypress", _toolTipFunctionOut, NO);
_DOMElement.addEventListener("mouseout", _toolTipFunctionOut, NO);
_DOMElement.addEventListener("mouseover", _toolTipFunctionIn, YES);
_DOMElement.addEventListener("keypress", _toolTipFunctionOut, YES);
_DOMElement.addEventListener("mouseout", _toolTipFunctionOut, YES);
}
else if (_DOMElement.attachEvent)
{
@@ -400,9 +427,9 @@ var CPViewFlags = { },
#if PLATFORM(DOM)
if (_DOMElement.removeEventListener)
{
_DOMElement.removeEventListener("mouseover", _toolTipFunctionIn, NO);
_DOMElement.removeEventListener("keypress", _toolTipFunctionOut, NO);
_DOMElement.removeEventListener("mouseout", _toolTipFunctionOut, NO);
_DOMElement.removeEventListener("mouseover", _toolTipFunctionIn, YES);
_DOMElement.removeEventListener("keypress", _toolTipFunctionOut, YES);
_DOMElement.removeEventListener("mouseout", _toolTipFunctionOut, YES);
}
else if (_DOMElement.detachEvent)
{
@@ -543,6 +570,13 @@ var CPViewFlags = { },
}
[aSubview setNextResponder:self];
[aSubview _scaleSizeUnitSquareToSize:[self _hierarchyScaleSize]];
// If the subview is not hidden and one of its ancestors is hidden,
// notify the subview that it is now hidden.
if (![aSubview isHidden] && [self isHiddenOrHasHiddenAncestor])
[aSubview _notifyViewDidHide];
[aSubview viewDidMoveToSuperview];
[self didAddSubview:aSubview];
@@ -575,6 +609,12 @@ var CPViewFlags = { },
#if PLATFORM(DOM)
CPDOMDisplayServerRemoveChild(_superview._DOMElement, _DOMElement);
#endif
// If the view is not hidden and one of its ancestors is hidden,
// notify the view that it is now unhidden.
if (!_isHidden && [_superview isHiddenOrHasHiddenAncestor])
[self _notifyViewDidUnhide];
_superview = nil;
[self _setWindow:nil];
@@ -829,7 +869,7 @@ var CPViewFlags = { },
*/
- (void)setFrame:(CGRect)aFrame
{
if (_CGRectEqualToRect(_frame, aFrame))
if (CGRectEqualToRect(_frame, aFrame))
return;
_inhibitFrameAndBoundsChangedNotifications = YES;
@@ -849,17 +889,17 @@ var CPViewFlags = { },
*/
- (CGRect)frame
{
return _CGRectMakeCopy(_frame);
return CGRectMakeCopy(_frame);
}
- (CGPoint)frameOrigin
{
return _CGPointMakeCopy(_frame.origin);
return CGPointMakeCopy(_frame.origin);
}
- (CGSize)frameSize
{
return _CGSizeMakeCopy(_frame.size);
return CGSizeMakeCopy(_frame.size);
}
/*!
@@ -894,7 +934,7 @@ var CPViewFlags = { },
{
var origin = _frame.origin;
if (!aPoint || _CGPointEqualToPoint(origin, aPoint))
if (!aPoint || CGPointEqualToPoint(origin, aPoint))
return;
origin.x = aPoint.x;
@@ -920,18 +960,18 @@ var CPViewFlags = { },
{
var size = _frame.size;
if (!aSize || _CGSizeEqualToSize(size, aSize))
if (!aSize || CGSizeEqualToSize(size, aSize))
return;
var oldSize = _CGSizeMakeCopy(size);
var oldSize = CGSizeMakeCopy(size);
size.width = aSize.width;
size.height = aSize.height;
if (YES)
{
_bounds.size.width = aSize.width;
_bounds.size.height = aSize.height;
_bounds.size.width = aSize.width * 1 / _scaleSize.width;
_bounds.size.height = aSize.height * 1 / _scaleSize.height;
}
if (_layer)
@@ -944,7 +984,7 @@ var CPViewFlags = { },
[self setNeedsDisplay:YES];
#if PLATFORM(DOM)
CPDOMDisplayServerSetStyleSize(_DOMElement, size.width, size.height);
[self _setDisplayServerSetStyleSize:size];
if (_DOMContentsElement)
{
@@ -1053,6 +1093,19 @@ var CPViewFlags = { },
[CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
}
/*!
This method is used to set the width and height of the _DOMElement. It cares about the scale of the view.
When scaling, for instance with a size (0.5, 0.5), the bounds of the view will be multiply by 2. It's why we multiply by the inverse of the scaling.
The view will finally keep the same proportion for the user on the screen.
*/
- (void)_setDisplayServerSetStyleSize:(CGSize)aSize
{
#if PLATFORM(DOM)
var scale = [self scaleSize];
CPDOMDisplayServerSetStyleSize(_DOMElement, aSize.width * 1 / scale.width, aSize.height * 1 / scale.height);
#endif
}
/*!
Sets the receiver's bounds. The bounds define the size and location of the receiver inside it's frame. Posts a
CPViewBoundsDidChangeNotification to the default notification center if the receiver is configured to do so.
@@ -1060,7 +1113,7 @@ var CPViewFlags = { },
*/
- (void)setBounds:(CGRect)bounds
{
if (_CGRectEqualToRect(_bounds, bounds))
if (CGRectEqualToRect(_bounds, bounds))
return;
_inhibitFrameAndBoundsChangedNotifications = YES;
@@ -1080,17 +1133,17 @@ var CPViewFlags = { },
*/
- (CGRect)bounds
{
return _CGRectMakeCopy(_bounds);
return CGRectMakeCopy(_bounds);
}
- (CGPoint)boundsOrigin
{
return _CGPointMakeCopy(_bounds.origin);
return CGPointMakeCopy(_bounds.origin);
}
- (CGSize)boundsSize
{
return _CGSizeMakeCopy(_bounds.size);
return CGSizeMakeCopy(_bounds.size);
}
/*!
@@ -1103,7 +1156,7 @@ var CPViewFlags = { },
{
var origin = _bounds.origin;
if (_CGPointEqualToPoint(origin, aPoint))
if (CGPointEqualToPoint(origin, aPoint))
return;
origin.x = aPoint.x;
@@ -1111,7 +1164,7 @@ var CPViewFlags = { },
if (origin.x != 0 || origin.y != 0)
{
_boundsTransform = _CGAffineTransformMakeTranslation(-origin.x, -origin.y);
_boundsTransform = CGAffineTransformMakeTranslation(-origin.x, -origin.y);
_inverseBoundsTransform = CGAffineTransformInvert(_boundsTransform);
}
else
@@ -1146,12 +1199,12 @@ var CPViewFlags = { },
{
var size = _bounds.size;
if (_CGSizeEqualToSize(size, aSize))
if (CGSizeEqualToSize(size, aSize))
return;
var frameSize = _frame.size;
if (!_CGSizeEqualToSize(size, frameSize))
if (!CGSizeEqualToSize(size, frameSize))
{
var origin = _bounds.origin;
@@ -1162,7 +1215,7 @@ var CPViewFlags = { },
size.width = aSize.width;
size.height = aSize.height;
if (!_CGSizeEqualToSize(size, frameSize))
if (!CGSizeEqualToSize(size, frameSize))
{
var origin = _bounds.origin;
@@ -1187,21 +1240,29 @@ var CPViewFlags = { },
return;
var frame = _superview._frame,
newFrame = _CGRectMakeCopy(_frame),
dX = (_CGRectGetWidth(frame) - aSize.width) /
(((mask & CPViewMinXMargin) ? 1 : 0) + (mask & CPViewWidthSizable ? 1 : 0) + (mask & CPViewMaxXMargin ? 1 : 0)),
dY = (_CGRectGetHeight(frame) - aSize.height) /
((mask & CPViewMinYMargin ? 1 : 0) + (mask & CPViewHeightSizable ? 1 : 0) + (mask & CPViewMaxYMargin ? 1 : 0));
newFrame = CGRectMakeCopy(_frame),
dX = frame.size.width - aSize.width,
dY = frame.size.height - aSize.height,
evenFractionX = 1.0 / ((mask & CPViewMinXMargin ? 1 : 0) + (mask & CPViewWidthSizable ? 1 : 0) + (mask & CPViewMaxXMargin ? 1 : 0)),
evenFractionY = 1.0 / ((mask & CPViewMinYMargin ? 1 : 0) + (mask & CPViewHeightSizable ? 1 : 0) + (mask & CPViewMaxYMargin ? 1 : 0)),
baseX = (mask & CPViewMinXMargin ? _frame.origin.x : 0) +
(mask & CPViewWidthSizable ? _frame.size.width : 0) +
(mask & CPViewMaxXMargin ? aSize.width - _frame.size.width - _frame.origin.x : 0),
baseY = (mask & CPViewMinYMargin ? _frame.origin.y : 0) +
(mask & CPViewHeightSizable ? _frame.size.height : 0) +
(mask & CPViewMaxYMargin ? aSize.height - _frame.size.height - _frame.origin.y : 0);
if (mask & CPViewMinXMargin)
newFrame.origin.x += dX;
newFrame.origin.x += dX * (baseX > 0 ? _frame.origin.x / baseX : evenFractionX);
if (mask & CPViewWidthSizable)
newFrame.size.width += dX;
newFrame.size.width += dX * (baseX > 0 ? _frame.size.width / baseX : evenFractionX);
if (mask & CPViewMinYMargin)
newFrame.origin.y += dY;
newFrame.origin.y += dY * (baseY > 0 ? _frame.origin.y / baseY : evenFractionY);
if (mask & CPViewHeightSizable)
newFrame.size.height += dY;
newFrame.size.height += dY * (baseY > 0 ? _frame.size.height / baseY : evenFractionY);
[self setFrame:newFrame];
}
@@ -1345,6 +1406,7 @@ var CPViewFlags = { },
// FIXME: Should we return to visibility? This breaks in FireFox, Opera, and IE.
// _DOMElement.style.visibility = (_isHidden = aFlag) ? "hidden" : "visible";
_isHidden = aFlag;
#if PLATFORM(DOM)
_DOMElement.style.display = _isHidden ? "none" : "block";
#endif
@@ -1380,6 +1442,7 @@ var CPViewFlags = { },
[self viewDidHide];
var count = [_subviews count];
while (count--)
[_subviews[count] _notifyViewDidHide];
}
@@ -1389,6 +1452,7 @@ var CPViewFlags = { },
[self viewDidUnhide];
var count = [_subviews count];
while (count--)
[_subviews[count] _notifyViewDidUnhide];
}
@@ -1539,15 +1603,42 @@ var CPViewFlags = { },
*/
- (CPView)hitTest:(CGPoint)aPoint
{
if (_isHidden || !_hitTests || !_CGRectContainsPoint(_frame, aPoint))
if (_isHidden || !_hitTests)
return nil;
var frame = _frame,
sizeScale = [self _hierarchyScaleSize];
if (_isScaled)
frame = CGRectApplyAffineTransform(_frame, CGAffineTransformMakeScale([_superview _hierarchyScaleSize].width, [_superview _hierarchyScaleSize].height));
else
frame = CGRectApplyAffineTransform(_frame, CGAffineTransformMakeScale(sizeScale.width, sizeScale.height));
if (!CGRectContainsPoint(frame, aPoint))
return nil;
var view = nil,
i = _subviews.length,
adjustedPoint = _CGPointMake(aPoint.x - _CGRectGetMinX(_frame), aPoint.y - _CGRectGetMinY(_frame));
adjustedPoint = CGPointMake(aPoint.x - CGRectGetMinX(frame), aPoint.y - CGRectGetMinY(frame));
if (_inverseBoundsTransform)
adjustedPoint = _CGPointApplyAffineTransform(adjustedPoint, _inverseBoundsTransform);
{
var affineTransform = CGAffineTransformMakeCopy(_inverseBoundsTransform);
if (_isScaled)
{
affineTransform.tx *= [_superview _hierarchyScaleSize].width;
affineTransform.ty *= [_superview _hierarchyScaleSize].height;
}
else
{
affineTransform.tx *= sizeScale.width;
affineTransform.ty *= sizeScale.height;
}
adjustedPoint = CGPointApplyAffineTransform(adjustedPoint, affineTransform);
}
while (i--)
if (view = [_subviews[i] hitTest:adjustedPoint])
@@ -1868,6 +1959,9 @@ var CPViewFlags = { },
*/
- (CGPoint)convertPoint:(CGPoint)aPoint fromView:(CPView)aView
{
if (aView === self)
return aPoint;
return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(aView, self));
}
@@ -1878,7 +1972,7 @@ var CPViewFlags = { },
*/
- (CGPoint)convertPointFromBase:(CGPoint)aPoint
{
return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(nil, self));
return [self convertPoint:aPoint fromView:nil];
}
/*!
@@ -1889,9 +1983,13 @@ var CPViewFlags = { },
*/
- (CGPoint)convertPoint:(CGPoint)aPoint toView:(CPView)aView
{
if (aView === self)
return aPoint;
return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(self, aView));
}
/*!
Converts the point from the receivers coordinate system to the base coordinate system.
@param aPoint A point specifying a location in the coordinate system of the receiver
@@ -1899,7 +1997,7 @@ var CPViewFlags = { },
*/
- (CGPoint)convertPointToBase:(CGPoint)aPoint
{
return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(self, nil));
return [self convertPoint:aPoint toView:nil];
}
/*!
@@ -1910,6 +2008,9 @@ var CPViewFlags = { },
*/
- (CGSize)convertSize:(CGSize)aSize fromView:(CPView)aView
{
if (aView === self)
return aSize;
return CGSizeApplyAffineTransform(aSize, _CPViewGetTransform(aView, self));
}
@@ -1921,6 +2022,9 @@ var CPViewFlags = { },
*/
- (CGSize)convertSize:(CGSize)aSize toView:(CPView)aView
{
if (aView === self)
return aSize;
return CGSizeApplyAffineTransform(aSize, _CPViewGetTransform(self, aView));
}
@@ -1932,6 +2036,9 @@ var CPViewFlags = { },
*/
- (CGRect)convertRect:(CGRect)aRect fromView:(CPView)aView
{
if (self === aView)
return aRect;
return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(aView, self));
}
@@ -1942,7 +2049,7 @@ var CPViewFlags = { },
*/
- (CGRect)convertRectFromBase:(CGRect)aRect
{
return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(nil, self));
return [self convertRect:aRect fromView:nil];
}
/*!
@@ -1953,6 +2060,9 @@ var CPViewFlags = { },
*/
- (CGRect)convertRect:(CGRect)aRect toView:(CPView)aView
{
if (self === aView)
return aRect;
return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(self, aView));
}
@@ -1963,7 +2073,7 @@ var CPViewFlags = { },
*/
- (CGRect)convertRectToBase:(CGRect)aRect
{
return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(self, nil));
return [self convertRect:aRect toView:nil];
}
/*!
@@ -1986,9 +2096,6 @@ setFrameOrigin:
return;
_postsFrameChangedNotifications = shouldPostFrameChangedNotifications;
if (_postsFrameChangedNotifications)
[CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
}
/*!
@@ -2019,9 +2126,6 @@ setBoundsOrigin:
return;
_postsBoundsChangedNotifications = shouldPostBoundsChangedNotifications;
if (_postsBoundsChangedNotifications)
[CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
}
/*!
@@ -2114,6 +2218,88 @@ setBoundsOrigin:
}
// Scaling
/*!
Scales the receivers coordinate system so that the unit square scales to the specified dimensions.
The bounds of the receiver will change, for instance if the given size is (0.5, 0.5) the width and height of the bounds will be multiply by 2.
You must call setNeedsDisplay: to redraw the view.
@param aSize, the size corresponding the new unit scales
*/
- (void)scaleUnitSquareToSize:(CGSize)aSize
{
if (!aSize)
return;
// Reset the bounds
var bounds = CGRectMakeCopy([self bounds]);
bounds.size.width *= _scaleSize.width;
bounds.size.height *= _scaleSize.height;
[self willChangeValueForKey:@"scaleSize"];
_scaleSize = CGSizeMakeCopy([self scaleSize]);
_scaleSize.height *= aSize.height;
_scaleSize.width *= aSize.width;
[self didChangeValueForKey:@"scaleSize"];
_isScaled = YES;
_hierarchyScaleSize = CGSizeMakeCopy([self _hierarchyScaleSize]);
_hierarchyScaleSize.height *= aSize.height;
_hierarchyScaleSize.width *= aSize.width;
var scaleAffine = CGAffineTransformMakeScale(1.0 / _scaleSize.width, 1.0 / _scaleSize.height),
newBounds = CGRectApplyAffineTransform(CGRectMakeCopy(bounds), scaleAffine);
[self setBounds:newBounds];
[_subviews makeObjectsPerformSelector:@selector(_scaleSizeUnitSquareToSize:) withObject:aSize];
}
/*!
@ignore
Set the _hierarchyScaleSize and call all of the subviews to set their _hierarchyScaleSize
*/
- (void)_scaleSizeUnitSquareToSize:(CGSize)aSize
{
_hierarchyScaleSize = CGSizeMakeCopy([_superview _hierarchyScaleSize]);
if (_isScaled)
{
_hierarchyScaleSize.width *= _scaleSize.width;
_hierarchyScaleSize.height *= _scaleSize.height;
}
[_subviews makeObjectsPerformSelector:@selector(_scaleSizeUnitSquareToSize:) withObject:aSize];
}
/*!
Return the _hierarchyScaleSize, this is a CGSize with the real zoom of the view (depending with his parents)
*/
- (CGSize)_hierarchyScaleSize
{
return _hierarchyScaleSize || CGSizeMake(1.0, 1.0);
}
/*!
Make a zoom in css
*/
- (void)_applyCSSScalingTranformations
{
#if PLATFORM(DOM)
if (_isScaled)
{
var scale = [self scaleSize],
browserPropertyTransform = CPBrowserStyleProperty(@"transform"),
browserPropertyTransformOrigin = CPBrowserStyleProperty(@"transformOrigin");
self._DOMElement.style[browserPropertyTransform] = 'scale(' + scale.width + ', ' + scale.height + ')';
self._DOMElement.style[browserPropertyTransformOrigin] = '0 0';
[self _setDisplayServerSetStyleSize:[self frameSize]];
}
#endif
}
// Displaying
/*!
@@ -2122,7 +2308,10 @@ setBoundsOrigin:
- (void)setNeedsDisplay:(BOOL)aFlag
{
if (aFlag)
{
[self _applyCSSScalingTranformations];
[self setNeedsDisplayInRect:[self bounds]];
}
}
/*!
@@ -2134,20 +2323,20 @@ setBoundsOrigin:
if (!(_viewClassFlags & CPViewHasCustomDrawRect))
return;
if (_CGRectIsEmpty(aRect))
if (CGRectIsEmpty(aRect))
return;
if (_dirtyRect && !_CGRectIsEmpty(_dirtyRect))
if (_dirtyRect && !CGRectIsEmpty(_dirtyRect))
_dirtyRect = CGRectUnion(aRect, _dirtyRect);
else
_dirtyRect = _CGRectMakeCopy(aRect);
_dirtyRect = CGRectMakeCopy(aRect);
_CPDisplayServerAddDisplayObject(self);
}
- (BOOL)needsDisplay
{
return _dirtyRect && !_CGRectIsEmpty(_dirtyRect);
return _dirtyRect && !CGRectIsEmpty(_dirtyRect);
}
/*!
@@ -2215,6 +2404,9 @@ setBoundsOrigin:
var graphicsPort = CGBitmapGraphicsContextCreate();
#if PLATFORM(DOM)
var width = CGRectGetWidth(_frame),
height = CGRectGetHeight(_frame);
_DOMContentsElement = graphicsPort.DOMElement;
_DOMContentsElement.style.zIndex = -100;
@@ -2223,13 +2415,10 @@ setBoundsOrigin:
_DOMContentsElement.style.position = "absolute";
_DOMContentsElement.style.visibility = "visible";
_DOMContentsElement.width = ROUND(_CGRectGetWidth(_frame));
_DOMContentsElement.height = ROUND(_CGRectGetHeight(_frame));
CPDOMDisplayServerSetSize(_DOMContentsElement, width, height);
_DOMContentsElement.style.top = "0px";
_DOMContentsElement.style.left = "0px";
_DOMContentsElement.style.width = ROUND(_CGRectGetWidth(_frame)) + "px";
_DOMContentsElement.style.height = ROUND(_CGRectGetHeight(_frame)) + "px";
CPDOMDisplayServerSetStyleLeftTop(_DOMContentsElement, NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleSize(_DOMContentsElement, width, height);
// The performance implications of this aren't clear, but without this subviews might not be redrawn when this
// view moves.
@@ -2337,7 +2526,7 @@ setBoundsOrigin:
aRect = CGRectIntersection(aRect, _bounds);
// If aRect is empty no scrolling required.
if (_CGRectIsEmpty(aRect))
if (CGRectIsEmpty(aRect))
return NO;
var enclosingClipView = [self _enclosingClipView];
@@ -2360,18 +2549,18 @@ setBoundsOrigin:
if (CGRectContainsRect(documentViewVisibleRect, rectInDocumentView))
return NO;
var scrollPoint = _CGPointMakeCopy(documentViewVisibleRect.origin);
var scrollPoint = CGPointMakeCopy(documentViewVisibleRect.origin);
// One of the following has to be true since our current visible rect didn't contain aRect.
if (_CGRectGetMinX(rectInDocumentView) < _CGRectGetMinX(documentViewVisibleRect))
scrollPoint.x = _CGRectGetMinX(rectInDocumentView);
else if (_CGRectGetMaxX(rectInDocumentView) > _CGRectGetMaxX(documentViewVisibleRect))
scrollPoint.x += _CGRectGetMaxX(rectInDocumentView) - _CGRectGetMaxX(documentViewVisibleRect);
if (CGRectGetMinX(rectInDocumentView) < CGRectGetMinX(documentViewVisibleRect))
scrollPoint.x = CGRectGetMinX(rectInDocumentView);
else if (CGRectGetMaxX(rectInDocumentView) > CGRectGetMaxX(documentViewVisibleRect))
scrollPoint.x += CGRectGetMaxX(rectInDocumentView) - CGRectGetMaxX(documentViewVisibleRect);
if (_CGRectGetMinY(rectInDocumentView) < _CGRectGetMinY(documentViewVisibleRect))
scrollPoint.y = _CGRectGetMinY(rectInDocumentView);
else if (_CGRectGetMaxY(rectInDocumentView) > _CGRectGetMaxY(documentViewVisibleRect))
scrollPoint.y += _CGRectGetMaxY(rectInDocumentView) - _CGRectGetMaxY(documentViewVisibleRect);
if (CGRectGetMinY(rectInDocumentView) < CGRectGetMinY(documentViewVisibleRect))
scrollPoint.y = CGRectGetMinY(rectInDocumentView);
else if (CGRectGetMaxY(rectInDocumentView) > CGRectGetMaxY(documentViewVisibleRect))
scrollPoint.y += CGRectGetMaxY(rectInDocumentView) - CGRectGetMaxY(documentViewVisibleRect);
[enclosingClipView scrollToPoint:scrollPoint];
@@ -2519,14 +2708,18 @@ setBoundsOrigin:
- (CPView)nextValidKeyView
{
var result = [self nextKeyView],
firstResult = result;
resultUID = [result UID],
unsuitableResults = {};
while (result && ![result canBecomeKeyView])
{
unsuitableResults[resultUID] = 1;
result = [result nextKeyView];
// Cycled.
if (result === firstResult)
resultUID = [result UID];
// Did we get back to a key view we already ruled out due to ![result canBecomeKeyView]?
if (unsuitableResults[resultUID])
return nil;
}
@@ -2557,21 +2750,35 @@ setBoundsOrigin:
- (void)_setPreviousKeyView:(CPView)previous
{
if ([previous isEqual:self] || ![[previous window] isEqual:[self window]])
_previousKeyView = nil;
else
_previousKeyView = previous;
if (![previous isEqual:self])
{
var previousWindow = [previous window];
if (!previousWindow || previousWindow === _window)
{
_previousKeyView = previous;
return;
}
}
_previousKeyView = nil;
}
- (void)setNextKeyView:(CPView)next
{
if ([next isEqual:self] || ![[next window] isEqual:[self window]])
_nextKeyView = nil;
else
if (![next isEqual:self])
{
_nextKeyView = next;
[_nextKeyView _setPreviousKeyView:self];
var nextWindow = [next window];
if (!nextWindow || nextWindow === _window)
{
_nextKeyView = next;
[_nextKeyView _setPreviousKeyView:self];
return;
}
}
_nextKeyView = nil;
}
@end
@@ -2638,6 +2845,40 @@ setBoundsOrigin:
@end
@implementation CPView (Scaling)
/*!
Set the zoom of the view. This will call scaleUnitSquareToSize: and setNeedsDisplay:
This method doesn't care about the last zoom you set in the view
@param aSize, the size corresponding the new unit scales
*/
- (void)setScaleSize:(CGSize)aSize
{
if (CGSizeEqualToSize(_scaleSize, aSize))
return;
var size = CGSizeMakeZero(),
scale = CGSizeMakeCopy([self scaleSize]);
size.height = aSize.height / scale.height;
size.width = aSize.width / scale.width;
[self scaleUnitSquareToSize:size];
[self setNeedsDisplay:YES];
}
/*!
Return the scaleSize of the view, this scaleSize is used to scale in css
*/
- (CGSize)scaleSize
{
return _scaleSize || CGSizeMake(1.0, 1.0);
}
@end
@implementation CPView (Theming)
#pragma mark Theme States
@@ -2948,7 +3189,7 @@ setBoundsOrigin:
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
{
return _CGRectMakeZero();
return CGRectMakeZero();
}
- (CPView)layoutEphemeralSubviewNamed:(CPString)aViewName
@@ -3016,7 +3257,10 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
CPViewWindowKey = @"CPViewWindowKey",
CPViewNextKeyViewKey = @"CPViewNextKeyViewKey",
CPViewPreviousKeyViewKey = @"CPViewPreviousKeyViewKey",
CPReuseIdentifierKey = @"CPReuseIdentifierKey";
CPReuseIdentifierKey = @"CPReuseIdentifierKey",
CPViewScaleKey = @"CPViewScaleKey",
CPViewSizeScaleKey = @"CPViewSizeScaleKey",
CPViewIsScaledKey = @"CPViewIsScaledKey";
@implementation CPView (CPCoding)
@@ -3033,6 +3277,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
// a more "elegant" way to do this...?
#if PLATFORM(DOM)
_DOMElement = DOMElementPrototype.cloneNode(false);
AppKitTagDOMElement(self, _DOMElement);
#endif
// Also decode these "early".
@@ -3082,13 +3327,17 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
if (_toolTip)
[self _installToolTipEventHandlers];
_scaleSize = [aCoder containsValueForKey:CPViewScaleKey] ? [aCoder decodeSizeForKey:CPViewScaleKey] : CGSizeMake(1.0, 1.0);
_hierarchyScaleSize = [aCoder containsValueForKey:CPViewSizeScaleKey] ? [aCoder decodeSizeForKey:CPViewSizeScaleKey] : CGSizeMake(1.0, 1.0);
_isScaled = [aCoder containsValueForKey:CPViewIsScaledKey] ? [aCoder decodeBoolForKey:CPViewIsScaledKey] : NO;
// DOM SETUP
#if PLATFORM(DOM)
_DOMImageParts = [];
_DOMImageSizes = [];
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(_frame), _CGRectGetMinY(_frame));
CPDOMDisplayServerSetStyleSize(_DOMElement, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame));
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(_frame), CGRectGetMinY(_frame));
[self _setDisplayServerSetStyleSize:_frame.size];
var index = 0,
count = _subviews.length;
@@ -3211,6 +3460,10 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
if (_identifier)
[aCoder encodeObject:_identifier forKey:CPReuseIdentifierKey];
[aCoder encodeSize:[self scaleSize] forKey:CPViewScaleKey];
[aCoder encodeSize:[self _hierarchyScaleSize] forKey:CPViewSizeScaleKey];
[aCoder encodeBool:_isScaled forKey:CPViewIsScaledKey];
}
@end
@@ -3240,12 +3493,26 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView)
{
var frame = view._frame;
transform.tx += _CGRectGetMinX(frame);
transform.ty += _CGRectGetMinY(frame);
if (view._isScaled)
{
var affineZoom = CGAffineTransformMakeScale(view._scaleSize.width, view._scaleSize.height);
CGAffineTransformConcatTo(transform, affineZoom, transform);
}
transform.tx += CGRectGetMinX(frame);
transform.ty += CGRectGetMinY(frame);
if (view._boundsTransform)
{
_CGAffineTransformConcatTo(transform, view._boundsTransform, transform);
var inverseBoundsTransform = CGAffineTransformMakeCopy(view._boundsTransform);
if (view._isScaled)
{
var affineZoom = CGAffineTransformMakeScale(view._scaleSize.width, view._scaleSize.height);
CGAffineTransformConcatTo(inverseBoundsTransform, affineZoom, inverseBoundsTransform);
}
CGAffineTransformConcatTo(transform, inverseBoundsTransform, transform);
}
view = view._superview;
@@ -3253,50 +3520,64 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView)
// If we hit toView, then we're done.
if (view === toView)
{
return transform;
}
else if (fromView && toView)
{
fromWindow = [fromView window];
toWindow = [toView window];
if (fromWindow && toWindow && fromWindow !== toWindow)
{
sameWindow = NO;
var frame = [fromWindow frame];
transform.tx += _CGRectGetMinX(frame);
transform.ty += _CGRectGetMinY(frame);
}
}
}
// FIXME: For now we can do things this way, but eventually we need to do them the "hard" way.
var view = toView;
var view = toView,
transform2 = CGAffineTransformMakeIdentity();
while (view)
while (view && view != fromView)
{
var frame = view._frame;
var frame = CGRectMakeCopy(view._frame);
transform.tx -= _CGRectGetMinX(frame);
transform.ty -= _CGRectGetMinY(frame);
// FIXME : For now we don't care about rotate transform and so on
if (view._isScaled)
{
transform2.a *= 1 / view._scaleSize.width;
transform2.d *= 1 / view._scaleSize.height;
}
transform2.tx += CGRectGetMinX(frame) * transform2.a;
transform2.ty += CGRectGetMinY(frame) * transform2.d;
if (view._boundsTransform)
{
_CGAffineTransformConcatTo(transform, view._inverseBoundsTransform, transform);
var inverseBoundsTransform = CGAffineTransformMakeIdentity();
inverseBoundsTransform.tx -= view._inverseBoundsTransform.tx * transform2.a;
inverseBoundsTransform.ty -= view._inverseBoundsTransform.ty * transform2.d;
CGAffineTransformConcatTo(transform2, inverseBoundsTransform, transform2);
}
view = view._superview;
}
if (!sameWindow)
{
var frame = [toWindow frame];
transform2.tx = -transform2.tx;
transform2.ty = -transform2.ty;
transform.tx -= _CGRectGetMinX(frame);
transform.ty -= _CGRectGetMinY(frame);
if (view === fromView)
{
// toView is inside of fromView
return transform2;
}
CGAffineTransformConcatTo(transform, transform2, transform);
return transform;
/* var views = [],
view = toView;
@@ -3312,8 +3593,8 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView)
{
var frame = views[index]._frame;
transform.tx -= _CGRectGetMinX(frame);
transform.ty -= _CGRectGetMinY(frame);
transform.tx -= CGRectGetMinX(frame);
transform.ty -= CGRectGetMinY(frame);
}*/
return transform;
+5 -5
View File
@@ -105,7 +105,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
[super startAnimation];
}
- (void)setCurrentProgress:(CPAnimationProgress)progress
- (void)setCurrentProgress:(float)progress
{
[super setCurrentProgress:progress];
@@ -116,7 +116,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
view = [self _targetView:dictionary],
startFrame = [self _startFrame:dictionary],
endFrame = [self _endFrame:dictionary],
differenceFrame = _CGRectMakeZero(),
differenceFrame = CGRectMakeZero(),
value = [super currentValue];
differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x;
@@ -124,7 +124,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
differenceFrame.size.width = endFrame.size.width - startFrame.size.width;
differenceFrame.size.height = endFrame.size.height - startFrame.size.height;
var intermediateFrame = _CGRectMakeZero();
var intermediateFrame = CGRectMakeZero();
intermediateFrame.origin.x = startFrame.origin.x + differenceFrame.origin.x * value;
intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * value;
intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * value;
@@ -140,7 +140,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
[view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * value];
if (progress === 1.0)
[self _targetView:view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
[self _targetView:view setHidden:CGRectIsEmpty(endFrame) || [view alphaValue] === 0.0];
}
}
@@ -161,7 +161,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
else if (effect === CPViewAnimationFadeOutEffect)
[view setAlphaValue:0.0];
[self _targetView:view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
[self _targetView:view setHidden:CGRectIsEmpty(endFrame) || [view alphaValue] === 0.0];
}
[super stopAnimation];
+305 -189
View File
@@ -56,7 +56,10 @@
var CPWindowSaveImage = nil,
CPWindowResizeTime = 0.2,
CPWindowResizeStyleGlobalChangeNotification = @"CPWindowResizeStyleGlobalChangeNotification";
CPWindowResizeStyleGlobalChangeNotification = @"CPWindowResizeStyleGlobalChangeNotification",
CPWindowMinVisibleHorizontalMargin = 40,
CPWindowMinVisibleVerticalMargin = 2;
/*
Keys for which action messages will be sent by default when unhandled, e.g. complete:.
@@ -144,6 +147,7 @@ var CPWindowActionMessageKeys = [
BOOL _hasShadow;
BOOL _isMovableByWindowBackground;
BOOL _isMovable;
BOOL _constrainsToUsableScreen;
unsigned _shadowStyle;
BOOL _showsResizeIndicator;
@@ -226,7 +230,7 @@ var CPWindowActionMessageKeys = [
- (id)init
{
return [self initWithContentRect:_CGRectMakeZero() styleMask:CPTitledWindowMask];
return [self initWithContentRect:CGRectMakeZero() styleMask:CPTitledWindowMask];
}
/*!
@@ -244,7 +248,7 @@ CPTexturedBackgroundWindowMask
@param aStyleMask a style mask
@return the initialized window
*/
- (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask
- (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned)aStyleMask
{
self = [super init];
@@ -253,6 +257,7 @@ CPTexturedBackgroundWindowMask
var windowViewClass = [[self class] _windowViewClassForStyleMask:aStyleMask];
_frame = [windowViewClass frameRectForContentRect:aContentRect];
_constrainsToUsableScreen = YES;
[self _setSharesChromeWithPlatformWindow:![CPPlatform isBrowser]];
@@ -298,19 +303,19 @@ CPTexturedBackgroundWindowMask
[self setLevel:CPNormalWindowLevel];
// Create our border view which is the actual root of our view hierarchy.
_windowView = [[windowViewClass alloc] initWithFrame:_CGRectMake(0.0, 0.0, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)) styleMask:aStyleMask];
_windowView = [[windowViewClass alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)) styleMask:aStyleMask];
[_windowView _setWindow:self];
[_windowView setNextResponder:self];
// Size calculation needs _windowView
_minSize = [self _calculateMinSizeForProposedSize:_CGSizeMake(0.0, 0.0)];
_maxSize = _CGSizeMake(1000000.0, 1000000.0);
_minSize = [self _calculateMinSizeForProposedSize:CGSizeMake(0.0, 0.0)];
_maxSize = CGSizeMake(1000000.0, 1000000.0);
[self setMovableByWindowBackground:aStyleMask & CPHUDBackgroundWindowMask];
// Create a generic content view.
[self setContentView:[[CPView alloc] initWithFrame:_CGRectMakeZero()]];
[self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
_firstResponder = self;
@@ -323,7 +328,7 @@ CPTexturedBackgroundWindowMask
if (![self _sharesChromeWithPlatformWindow])
{
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(_frame), _CGRectGetMinY(_frame));
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(_frame), CGRectGetMinY(_frame));
}
CPDOMDisplayServerSetStyleSize(_DOMElement, 1, 1);
@@ -542,7 +547,7 @@ CPTexturedBackgroundWindowMask
_fullPlatformWindowSession = _CPWindowFullPlatformWindowSessionMake(_windowView, [self contentRectForFrameRect:[self frame]], [self hasShadow], [self level]);
var fullPlatformWindowViewClass = [[self class] _windowViewClassForFullPlatformWindowStyleMask:_styleMask],
windowView = [[fullPlatformWindowViewClass alloc] initWithFrame:_CGRectMakeZero() styleMask:_styleMask];
windowView = [[fullPlatformWindowViewClass alloc] initWithFrame:CGRectMakeZero() styleMask:_styleMask];
[self _setWindowView:windowView];
@@ -628,7 +633,7 @@ CPTexturedBackgroundWindowMask
*/
- (CGRect)frame
{
return _CGRectMakeCopy(_frame);
return CGRectMakeCopy(_frame);
}
/*!
@@ -640,48 +645,54 @@ CPTexturedBackgroundWindowMask
*/
- (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
{
aFrame = _CGRectMakeCopy(aFrame);
[self _setFrame:aFrame display:shouldDisplay animate:shouldAnimate constrainWidth:NO constrainHeight:YES];
}
var value = aFrame.origin.x,
- (void)_setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate constrainWidth:(BOOL)shouldConstrainWidth constrainHeight:(BOOL)shouldConstrainHeight
{
var frame = CGRectMakeCopy(aFrame),
value = frame.origin.x,
delta = value - FLOOR(value);
if (delta)
aFrame.origin.x = value > 0.879 ? CEIL(value) : FLOOR(value);
frame.origin.x = value > 0.879 ? CEIL(value) : FLOOR(value);
value = aFrame.origin.y;
value = frame.origin.y;
delta = value - FLOOR(value);
if (delta)
aFrame.origin.y = value > 0.879 ? CEIL(value) : FLOOR(value);
frame.origin.y = value > 0.879 ? CEIL(value) : FLOOR(value);
value = aFrame.size.width;
value = frame.size.width;
delta = value - FLOOR(value);
if (delta)
aFrame.size.width = value > 0.15 ? CEIL(value) : FLOOR(value);
frame.size.width = value > 0.15 ? CEIL(value) : FLOOR(value);
value = aFrame.size.height;
value = frame.size.height;
delta = value - FLOOR(value);
if (delta)
aFrame.size.height = value > 0.15 ? CEIL(value) : FLOOR(value);
frame.size.height = value > 0.15 ? CEIL(value) : FLOOR(value);
frame = [self _constrainFrame:frame toUsableScreenWidth:shouldConstrainWidth andHeight:shouldConstrainHeight];
if (shouldAnimate)
{
[_frameAnimation stopAnimation];
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:frame];
[_frameAnimation startAnimation];
}
else
{
var origin = _frame.origin,
newOrigin = aFrame.origin,
originMoved = !_CGPointEqualToPoint(origin, newOrigin);
newOrigin = frame.origin,
originMoved = !CGPointEqualToPoint(origin, newOrigin);
if (originMoved)
{
delta = _CGPointMake(newOrigin.x - origin.x, newOrigin.y - origin.y);
delta = CGPointMake(newOrigin.x - origin.x, newOrigin.y - origin.y);
origin.x = newOrigin.x;
origin.y = newOrigin.y;
@@ -692,13 +703,17 @@ CPTexturedBackgroundWindowMask
}
#endif
// reposition sheet
if ([self attachedSheet])
[self _setAttachedSheetFrameOrigin];
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidMoveNotification object:self];
}
var size = _frame.size,
newSize = aFrame.size;
newSize = frame.size;
if (!_CGSizeEqualToSize(size, newSize))
if (!CGSizeEqualToSize(size, newSize))
{
size.width = newSize.width;
size.height = newSize.height;
@@ -720,13 +735,99 @@ CPTexturedBackgroundWindowMask
}
}
/*
Constrain a frame so that the window remains at least partially visible on screen,
moving or resizing the frame as necessary.
*/
- (CGRect)_constrainFrame:(CGRect)aFrame toUsableScreenWidth:(BOOL)constrainWidth andHeight:(BOOL)constrainHeight
{
var frame = CGRectMakeCopy(aFrame);
if (!_constrainsToUsableScreen || !_isVisible)
return frame;
var usableRect = [_platformWindow usableContentFrame];
if (constrainWidth)
{
// First move the frame right to ensure the left side is within the usable rect.
frame.origin.x = MAX(frame.origin.x, usableRect.origin.x);
// Now move the frame left so that the right side is within the usable rect.
var maxX = MIN(CGRectGetMaxX(frame), CGRectGetMaxX(usableRect));
frame.origin.x = maxX - frame.size.width;
// Finally, adjust the left + width to ensure the left side is within the usable rect.
var usableWidth = CGRectGetWidth(usableRect);
if (CGRectGetWidth(frame) > usableWidth)
{
frame.origin.x = CGRectGetMinX(usableRect);
frame.size.width = MAX(usableWidth, _minSize.width);
}
}
if (constrainHeight)
{
// First move the frame down to ensure the top is within the usable rect.
frame.origin.y = MAX(frame.origin.y, usableRect.origin.y);
// Now move the frame up so that the bottom is within the usable rect.
var maxY = MIN(CGRectGetMaxY(frame), CGRectGetMaxY(usableRect));
frame.origin.y = maxY - frame.size.height;
// Finally, adjust the top + height to ensure the top is within the usable rect.
var usableHeight = CGRectGetHeight(usableRect);
if (CGRectGetHeight(frame) > usableHeight)
{
frame.origin.y = CGRectGetMinY(usableRect);
frame.size.height = MAX(usableHeight, _minSize.height);
}
}
return frame;
}
/*
Constrain the origin of a frame such that:
- The window view's minimum resize width is kept onscreen at the left/right of the window.
- The top of the window is kept below the top of the usable content.
- The top of the contentView + CPWindowMinVisibleVerticalMargin is kept above the bottom of the usable content.
*/
- (CGRect)_constrainOriginOfFrame:(CGRect)aFrame
{
var frame = CGRectMakeCopy(aFrame);
if (!_constrainsToUsableScreen || !_isVisible)
return frame;
var usableRect = [_platformWindow usableContentFrame],
minimumSize = [_windowView _minimumResizeSize];
// First constrain x so that at least CPWindowMinVisibleHorizontalMargin is visible on the right
frame.origin.x = MAX(frame.origin.x, CGRectGetMinX(usableRect) + minimumSize.width - CGRectGetWidth(frame));
// Now constrain x so that at least CPWindowMinVisibleHorizontalMargin is visible on the left
frame.origin.x = MIN(frame.origin.x, CGRectGetMaxX(usableRect) - minimumSize.width);
// Now constrain y so that it is below the top of the usable content
frame.origin.y = MAX(frame.origin.y, CGRectGetMinY(usableRect));
// Finally constrain y so that at least CPWindowMinVisibleHorizontalMargin is visible at the bottom
frame.origin.y = MIN(frame.origin.y, CGRectGetMaxY(usableRect) - CGRectGetMinY([_contentView frame]) - CPWindowMinVisibleVerticalMargin);
return frame;
}
- (void)_moveChildWindows:(CGPoint)delta
{
[_childWindows enumerateObjectsUsingBlock:function(childWindow)
{
var origin = [childWindow frame].origin;
[childWindow setFrameOrigin:_CGPointMake(origin.x + delta.x, origin.y + delta.y)];
[childWindow setFrameOrigin:CGPointMake(origin.x + delta.x, origin.y + delta.y)];
}
];
}
@@ -756,11 +857,8 @@ CPTexturedBackgroundWindowMask
*/
- (void)setFrameOrigin:(CGPoint)anOrigin
{
[self setFrame:_CGRectMake(anOrigin.x, anOrigin.y, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)) display:YES animate:NO];
// reposition sheet
if ([self attachedSheet])
[self _setAttachedSheetFrameOrigin];
var frame = [self _constrainOriginOfFrame:CGRectMake(anOrigin.x, anOrigin.y, _frame.size.width, _frame.size.height)];
[self _setFrame:frame display:YES animate:NO constrainWidth:NO constrainHeight:NO];
}
/*!
@@ -769,7 +867,7 @@ CPTexturedBackgroundWindowMask
*/
- (void)setFrameSize:(CGSize)aSize
{
[self setFrame:_CGRectMake(_CGRectGetMinX(_frame), _CGRectGetMinY(_frame), aSize.width, aSize.height) display:YES animate:NO];
[self setFrame:CGRectMake(CGRectGetMinX(_frame), CGRectGetMinY(_frame), aSize.width, aSize.height) display:YES animate:NO];
}
/*!
@@ -785,9 +883,12 @@ CPTexturedBackgroundWindowMask
{
#if PLATFORM(DOM)
// -dw- if a sheet is clicked, the parent window should come up too
if ([self isSheet])
if (_isSheet)
[_parentView orderFront:self];
if (!_isVisible)
[self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES];
[_platformWindow orderFront:self];
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
#endif
@@ -896,6 +997,7 @@ CPTexturedBackgroundWindowMask
[_platformWindow moveWindow:self fromLevel:_level toLevel:aLevel];
_level = aLevel;
[_childWindows makeObjectsPerformSelector:@selector(setLevel:) withObject:_level];
if ([self _sharesChromeWithPlatformWindow])
[_platformWindow setLevel:aLevel];
@@ -931,6 +1033,23 @@ CPTexturedBackgroundWindowMask
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowResizeStyleGlobalChangeNotification object:nil];
}
/*!
If set to NO, platform window (virtual screen) resizes will not attempt to move/resize user windows.
to the usable area.
*/
+ (void)setConstrainWindowsToUsableScreen:(BOOL)shouldConstrain
{
CPWindowConstrainToScreen = shouldConstrain;
}
/*!
Return whether platform window (virtual screen) resizes constrain user windows to the usable area.
*/
+ (BOOL)constrainWindowsToUsableScreen
{
return CPWindowConstrainToScreen;
}
- (void)_didReceiveResizeStyleChange:(CPNotification)aNotification
{
[_windowView setShowsResizeIndicator:_styleMask & CPResizableWindowMask];
@@ -994,7 +1113,7 @@ CPTexturedBackgroundWindowMask
if (_contentView)
[_contentView removeFromSuperview];
var bounds = _CGRectMake(0.0, 0.0, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame));
var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
_contentView = aView;
[_contentView setFrame:[self contentRectForFrameRect:bounds]];
@@ -1061,12 +1180,12 @@ CPTexturedBackgroundWindowMask
*/
- (void)setMinSize:(CGSize)aSize
{
if (_CGSizeEqualToSize(_minSize, aSize))
if (CGSizeEqualToSize(_minSize, aSize))
return;
_minSize = [self _calculateMinSizeForProposedSize:aSize];
var size = _CGSizeMakeCopy([self frame].size),
var size = CGSizeMakeCopy([self frame].size),
needsFrameChange = NO;
if (size.width < _minSize.width)
@@ -1097,9 +1216,9 @@ CPTexturedBackgroundWindowMask
- (CGSize)_calculateMinSizeForProposedSize:(CGSize)proposedSize
{
var contentFrame = [self contentRectForFrameRect:_frame],
minHeight = _CGRectGetHeight(_frame) - _CGRectGetHeight(contentFrame);
minHeight = CGRectGetHeight(_frame) - CGRectGetHeight(contentFrame);
return _CGSizeMake(MAX(proposedSize.width, 0), MAX(proposedSize.height, minHeight));
return CGSizeMake(MAX(proposedSize.width, 0), MAX(proposedSize.height, minHeight));
}
/*!
@@ -1110,12 +1229,12 @@ CPTexturedBackgroundWindowMask
*/
- (void)setMaxSize:(CGSize)aSize
{
if (_CGSizeEqualToSize(_maxSize, aSize))
if (CGSizeEqualToSize(_maxSize, aSize))
return;
_maxSize = _CGSizeMakeCopy(aSize);
_maxSize = CGSizeMakeCopy(aSize);
var size = _CGSizeMakeCopy([self frame].size),
var size = CGSizeMakeCopy([self frame].size),
needsFrameChange = NO;
if (size.width > _maxSize.width)
@@ -1169,7 +1288,7 @@ CPTexturedBackgroundWindowMask
if (_hasShadow && !_shadowView)
{
_shadowView = [[_CPShadowWindowView alloc] initWithFrame:CGRectMakeZero()];
_shadowView = [[_CPShadowWindowView alloc] initWithFrame:CGRectMakeZero()];
[_shadowView setWindowView:_windowView];
[_shadowView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
@@ -1454,8 +1573,6 @@ CPTexturedBackgroundWindowMask
[_windowView setTitle:aTitle];
[_platformWindow _setTitle:_title window:self];
[self _synchronizeMenuBarTitleWithWindowTitle];
}
/*!
@@ -1552,7 +1669,7 @@ CPTexturedBackgroundWindowMask
var size = [self frame].size,
containerSize = [CPPlatform isBrowser] ? [_platformWindow contentBounds].size : [[self screen] visibleFrame].size;
var origin = _CGPointMake((containerSize.width - size.width) / 2.0, (containerSize.height - size.height) / 2.0);
var origin = CGPointMake((containerSize.width - size.width) / 2.0, (containerSize.height - size.height) / 2.0);
if (origin.x < 0.0)
origin.x = 0.0;
@@ -1570,33 +1687,43 @@ CPTexturedBackgroundWindowMask
- (void)sendEvent:(CPEvent)anEvent
{
var type = [anEvent type],
point = [anEvent locationInWindow];
sheet = [self attachedSheet];
// If a sheet is attached events get filtered here.
// It is not clear what events should be passed to the view, perhaps all?
// CPLeftMouseDown is needed for window moving and resizing to work.
// CPMouseMoved is needed for rollover effects on title bar buttons.
var sheet = [self attachedSheet];
if (sheet)
{
switch (type)
{
case CPLeftMouseDown:
// This is needed when a doubleClick occurs when the sheet is closing or opening
if (!_parentWindow)
return;
[_windowView mouseDown:anEvent];
// -dw- if the window is clicked, the sheet should come to front, and become key,
// and the window should be immediately behind
[sheet makeKeyAndOrderFront:self];
break;
case CPMouseMoved:
[_windowView mouseMoved:anEvent];
break;
}
return;
return;
case CPMouseMoved:
// Allow these through to the parent
break;
default:
// Everything else is filtered
return;
}
}
var point = [anEvent locationInWindow];
switch (type)
{
case CPFlagsChanged:
@@ -1717,7 +1844,8 @@ CPTexturedBackgroundWindowMask
case CPMouseMoved:
[_windowView setCursorForLocation:point resizing:NO];
if (!_acceptsMouseMovedEvents)
// Ignore mouse moves for parents of sheets
if (!_acceptsMouseMovedEvents || sheet)
return;
if (!_mouseEnteredStack)
@@ -2234,6 +2362,13 @@ CPTexturedBackgroundWindowMask
*/
- (void)makeMainWindow
{
// Sheets cannot be main. Their parent window becomes main.
if (_isSheet)
{
[_parentView makeMainWindow];
return;
}
if ([CPApp mainWindow] === self || ![self canBecomeMainWindow])
return;
@@ -2248,7 +2383,6 @@ CPTexturedBackgroundWindowMask
{
CPApp._mainWindow = self;
[self _synchronizeMenuBarTitleWithWindowTitle];
[self _synchronizeSaveMenuWithDocumentSaving];
[_windowView noteMainWindowStateChanged];
@@ -2367,7 +2501,7 @@ CPTexturedBackgroundWindowMask
// If this has an owner, dump it!
[[aToolbar _window] setToolbar:nil];
// This is no longer out toolbar.
// This is no longer our toolbar.
[_toolbar _setWindow:nil];
_toolbar = aToolbar;
@@ -2387,7 +2521,7 @@ CPTexturedBackgroundWindowMask
- (void)_noteToolbarChanged
{
var frame = _CGRectMakeCopy([self frame]),
var frame = CGRectMakeCopy([self frame]),
newFrame;
[_windowView noteToolbarChanged];
@@ -2396,7 +2530,7 @@ CPTexturedBackgroundWindowMask
newFrame = [_platformWindow visibleFrame];
else
{
newFrame = _CGRectMakeCopy([self frame]);
newFrame = CGRectMakeCopy([self frame]);
newFrame.origin = frame.origin;
}
@@ -2432,6 +2566,7 @@ CPTexturedBackgroundWindowMask
[childWindow setParentWindow:self];
[childWindow _setChildOrdering:orderingMode];
[childWindow setLevel:[self level]];
if ([self isVisible] && ![childWindow isVisible])
[childWindow orderWindow:orderingMode relativeTo:_windowNumber];
@@ -2489,25 +2624,24 @@ CPTexturedBackgroundWindowMask
return CPWindowResizeTime;
}
/* @ignore */
- (void)_setAttachedSheetFrameOrigin
{
// Position the sheet above the contentRect.
var attachedSheet = [self attachedSheet],
contentRect = [_contentView frame],
sheetFrame = _CGRectMakeCopy([attachedSheet frame]);
sheetFrame = CGRectMakeCopy([attachedSheet frame]);
sheetFrame.origin.y = _CGRectGetMinY(_frame) + _CGRectGetMinY(contentRect);
sheetFrame.origin.x = _CGRectGetMinX(_frame) + FLOOR((_CGRectGetWidth(_frame) - _CGRectGetWidth(sheetFrame)) / 2.0);
sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect);
sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0);
[attachedSheet setFrame:sheetFrame display:YES animate:NO];
}
/* @ignore
/*
Starting point for sheet session, called from CPApplication beginSheet:
*/
- (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate
didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
didEndSelector:(SEL)didEndSelector contextInfo:(id)contextInfo
{
if (_sheetContext)
{
@@ -2516,24 +2650,21 @@ CPTexturedBackgroundWindowMask
return;
}
var sheetFrame = [aSheet frame];
_sheetContext = {
"sheet": aSheet,
"modalDelegate": aModalDelegate,
"endSelector": didEndSelector,
"contextInfo": contextInfo,
"returnCode": -1,
"opened": NO,
"isAttached": YES,
"savedConstrains": aSheet._constrainsToUsableScreen
};
_sheetContext = {"sheet": aSheet, "modalDelegate": aModalDelegate, "endSelector": aDidEndSelector,
"contextInfo": aContextInfo, "frame": _CGRectMakeCopy(sheetFrame), "returnCode": -1,
"opened": NO};
// Sheets are not constrained, they are controlled by their parent
aSheet._constrainsToUsableScreen = NO;
[self _attachSheetWindow];
}
/* @ignore
Called to animate the sheet in. The timer seems to solve a bug where sheets would
be partially animated under certain conditions.
*/
- (void)_attachSheetWindow
{
_sheetContext["isAttached"] = YES;
// it would be ideal to block here and spin an event loop, until attach is complete
// A timer seems to be necessary for the animation to work correctly
[CPTimer scheduledTimerWithTimeInterval:0.0
target:self
selector:@selector(_sheetShouldAnimateIn:)
@@ -2541,7 +2672,7 @@ CPTexturedBackgroundWindowMask
repeats:NO];
}
/* @ignore
/*
Called to end the sheet. Note that orderOut: is needed to animate the sheet out, as in Cocoa.
The sheet isn't completely gone until _cleanupSheetWindow gets called.
*/
@@ -2562,7 +2693,7 @@ CPTexturedBackgroundWindowMask
}
}
/* @ignore
/*
Called to animate the sheet out. If called while animating in, schedules an animate
out at completion
*/
@@ -2570,7 +2701,8 @@ CPTexturedBackgroundWindowMask
{
_sheetContext["isAttached"] = NO;
// it would be ideal to block here and spin the event loop, until attach is complete
// A timer seems to be necessary for the animation to work correctly.
// It would be ideal to block here and spin the event loop, until attach is complete.
[CPTimer scheduledTimerWithTimeInterval:0.0
target:self
selector:@selector(_sheetShouldAnimateOut:)
@@ -2578,27 +2710,26 @@ CPTexturedBackgroundWindowMask
repeats:NO];
}
/* @ignore
/*
Called to cleanup sheet, when we are definitely done with it
*/
- (void)_cleanupSheetWindow
{
var sheet = _sheetContext["sheet"],
lastFrame = _sheetContext["frame"],
deferDidEnd = _sheetContext["deferDidEndSelector"];
[sheet setFrame:lastFrame];
[self _restoreMasksForView:[sheet contentView]];
// if the parent window is modal, the sheet started its own modal session
// If the parent window is modal, the sheet started its own modal session
if (sheet._isModal)
[CPApp stopModal];
// restore the state of window before it was sheetified
[sheet._windowView _enableSheet:NO];
[self _removeClipForSheet:sheet];
// close it
// Restore the state of window before it was sheetified
sheet._isSheet = NO;
[sheet._windowView _enableSheet:NO inWindow:self];
sheet._constrainsToUsableScreen = _sheetContext["savedConstrains"];
// Close it
[sheet orderOut:self];
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
@@ -2610,7 +2741,7 @@ CPTexturedBackgroundWindowMask
returnCode = _sheetContext["returnCode"],
contextInfo = _sheetContext["contextInfo"];
// context must be destroyed, since didEnd might want to attach another sheet
// Context must be destroyed, since didEnd might want to attach another sheet
_sheetContext = nil;
sheet._parentView = nil;
@@ -2638,31 +2769,19 @@ CPTexturedBackgroundWindowMask
repeats:NO];
}
/* @ignore */
- (void)_sheetShouldAnimateIn:(CPTimer)timer
{
// can't open sheet while opening or closing animation is going on
if (_sheetContext["isOpening"] ||
_sheetContext["isClosing"])
// Can't open sheet while opening or closing animation is going on
if (_sheetContext["isOpening"] || _sheetContext["isClosing"])
return;
var sheet = _sheetContext["sheet"],
sheetFrame = [sheet frame],
frame = [self frame];
[self _setUpMasksForView:[sheet contentView]];
var sheet = _sheetContext["sheet"];
sheet._isSheet = YES;
sheet._parentView = self;
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2),
originy = frame.origin.y + [_contentView frame].origin.y,
startFrame = _CGRectMake(originx, originy, sheetFrame.size.width, 0),
endFrame = _CGRectMake(originx, originy, sheetFrame.size.width, sheetFrame.size.height);
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
// if sheet is attached to a modal window, the sheet runs
// If sheet is attached to a modal window, the sheet runs
// as if itself and the parent window are modal
sheet._isModal = NO;
@@ -2672,7 +2791,29 @@ CPTexturedBackgroundWindowMask
sheet._isModal = YES;
}
// The sheet starts hidden just above the top of a clip rect
// TODO : Make properly for the -1 in endY
var sheetFrame = [sheet frame],
sheetShadowFrame = sheet._hasShadow ? [sheet._shadowView frame] : sheetFrame,
frame = [self frame],
originX = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2),
startFrame = CGRectMake(originX, -sheetShadowFrame.size.height, sheetFrame.size.width, sheetFrame.size.height),
endY = -1 + [_windowView bodyOffset] - [[self contentView] frame].origin.y,
endFrame = CGRectMake(originX, endY, sheetFrame.size.width, sheetFrame.size.height);
if (_toolbar && [_windowView showsToolbar] && [self isFullPlatformWindow])
{
endY += [[_toolbar _toolbarView] frameSize].height;
endFrame = CGRectMake(originX, endY, sheetFrame.size.width, sheetFrame.size.height);
}
// Move the sheet offscreen before ordering front so it doesn't appear briefly
[sheet setFrameOrigin:CGPointMake(0, -13000)];
// Because clipping does funny thing with the DOM, we have to orderFront before clipping
[sheet orderFront:self];
[self _clipSheet:sheet];
[sheet setFrame:startFrame display:YES animate:NO];
_sheetContext["opened"] = YES;
@@ -2680,23 +2821,13 @@ CPTexturedBackgroundWindowMask
_sheetContext["isOpening"] = YES;
[sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseOut];
// NOTE: cocoa doesn't make window key until animation is done, but a
// keypress while animating eventually gets to the window. Therefore,
// there must be a runloop specifically designed for sheets?
[sheet makeKeyWindow];
}
/* @ignore */
- (void)_sheetShouldAnimateOut:(CPTimer)timer
{
var sheet = _sheetContext["sheet"],
startFrame = [sheet frame],
endFrame = _CGRectMakeCopy(startFrame);
if (_sheetContext["isOpening"])
{
// allow sheet to be closed while opening, it will close when animate in completes
// Allow sheet to be closed while opening, it will close when animate in completes
_sheetContext["shouldClose"] = YES;
return;
}
@@ -2705,14 +2836,24 @@ CPTexturedBackgroundWindowMask
return;
_sheetContext["opened"] = NO;
_sheetContext["frame"] = startFrame;
_sheetContext["isClosing"] = YES;
// the parent window can be orderedOut to disable the sheet animate out, as in Cocoa
// The parent window can be orderedOut to disable the sheet animate out, as in Cocoa
if ([self isVisible])
{
endFrame.size.height = 0;
[self _setUpMasksForView:[sheet contentView]];
var sheet = _sheetContext["sheet"],
sheetFrame = [sheet frame],
fullHeight = sheet._hasShadow ? [sheet._shadowView frame].size.height : sheetFrame.size.height,
endFrame = CGRectMakeCopy(sheetFrame),
contentOrigin = [self convertBaseToGlobal:[[self contentView] frame].origin];
// Don't constrain sheets, they are controlled by the parent
sheet._constrainsToUsableScreen = NO;
[sheet setFrameOrigin:CGPointMake(sheetFrame.origin.x, sheetFrame.origin.y - contentOrigin.y)];
[self _clipSheet:sheet];
endFrame.origin.y = -fullHeight;
[sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseIn];
}
else
@@ -2721,7 +2862,6 @@ CPTexturedBackgroundWindowMask
}
}
/* @ignore */
- (void)_sheetAnimationDidEnd:(CPTimer)timer
{
var sheet = _sheetContext["sheet"];
@@ -2731,12 +2871,17 @@ CPTexturedBackgroundWindowMask
if (_sheetContext["opened"] === YES)
{
// sheet is open and completely visible
[self _restoreMasksForView:[sheet contentView]];
var sheetFrame = [sheet frame],
sheetOrigin = CGPointMakeCopy(sheetFrame.origin);
[self _removeClipForSheet:sheet];
[sheet setFrameOrigin:CGPointMake(sheetOrigin.x, [sheet frame].origin.y + sheetOrigin.y)];
// we wanted to close the sheet while it animated in, do that now
if (_sheetContext["shouldClose"] === YES)
[self _detachSheetWindow];
else
[sheet makeKeyWindow];
}
else
{
@@ -2745,36 +2890,17 @@ CPTexturedBackgroundWindowMask
}
}
- (void)_setUpMasksForView:(CPView)aView
- (void)_clipSheet:(CPWindow)aSheet
{
var views = [aView subviews];
var clipRect = [_platformWindow contentBounds];
clipRect.origin.y = [self frame].origin.y + [[self contentView] frame].origin.y;
[views addObject:aView];
for (var i = 0, count = [views count]; i < count; i++)
{
var view = [views objectAtIndex:i],
mask = [view autoresizingMask],
maskToAdd = (mask & CPViewMinYMargin) ? 128 : CPViewMinYMargin;
[view setAutoresizingMask:(mask | maskToAdd)];
}
[[_platformWindow layerAtLevel:_level create:NO] clipWindow:aSheet toRect:clipRect];
}
- (void)_restoreMasksForView:(CPView)aView
- (void)_removeClipForSheet:(CPWindow)aSheet
{
var views = [aView subviews];
[views addObject:aView];
for (var i = 0, count = [views count]; i < count; i++)
{
var view = [views objectAtIndex:i],
mask = [view autoresizingMask],
maskToRemove = (mask & 128) ? 128 : CPViewMinYMargin;
[view setAutoresizingMask:(mask & (~ maskToRemove))];
}
[[_platformWindow layerAtLevel:_level create:NO] removeClipForWindow:aSheet];
}
/*!
@@ -3141,11 +3267,11 @@ var keyViewComparator = function(lhs, rhs, context)
{
var lhsBounds = [lhs convertRect:[lhs bounds] toView:nil],
rhsBounds = [rhs convertRect:[rhs bounds] toView:nil],
lhsY = _CGRectGetMinY(lhsBounds),
rhsY = _CGRectGetMinY(rhsBounds),
lhsX = _CGRectGetMinX(lhsBounds),
rhsX = _CGRectGetMinX(rhsBounds),
intersectsVertically = MIN(_CGRectGetMaxY(lhsBounds), _CGRectGetMaxY(rhsBounds)) - MAX(lhsY, rhsY);
lhsY = CGRectGetMinY(lhsBounds),
rhsY = CGRectGetMinY(rhsBounds),
lhsX = CGRectGetMinX(lhsBounds),
rhsX = CGRectGetMinX(rhsBounds),
intersectsVertically = MIN(CGRectGetMaxY(lhsBounds), CGRectGetMaxY(rhsBounds)) - MAX(lhsY, rhsY);
// If two views are "on the same line" (intersect vertically), then rely on the x comparison.
if (intersectsVertically > 0)
@@ -3168,19 +3294,6 @@ var keyViewComparator = function(lhs, rhs, context)
return CPOrderedDescending;
};
@implementation CPWindow (MenuBar)
- (void)_synchronizeMenuBarTitleWithWindowTitle
{
// Windows with Documents automatically update the native window title and the menu bar title.
if (![_windowController document] || ![self isMainWindow])
return;
[CPMenu setMenuBarTitle:_title];
}
@end
@implementation CPWindow (BridgeSupport)
/*
@@ -3191,27 +3304,30 @@ var keyViewComparator = function(lhs, rhs, context)
if ([self isFullPlatformWindow])
return [self setFrame:[_platformWindow visibleFrame]];
if (_autoresizingMask == CPWindowNotSizable)
// If this window is constrainable and we are globally ignoring constraining, ignore the platform resize
if ((_constrainsToUsableScreen && !CPWindowConstrainToScreen) || _autoresizingMask === CPWindowNotSizable)
return;
var frame = [_platformWindow contentBounds],
newFrame = _CGRectMakeCopy(_frame),
dX = (_CGRectGetWidth(frame) - aSize.width) /
newFrame = CGRectMakeCopy(_frame),
dX = (CGRectGetWidth(frame) - aSize.width) /
(((_autoresizingMask & CPWindowMinXMargin) ? 1 : 0) + (_autoresizingMask & CPWindowWidthSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxXMargin ? 1 : 0)),
dY = (_CGRectGetHeight(frame) - aSize.height) /
dY = (CGRectGetHeight(frame) - aSize.height) /
((_autoresizingMask & CPWindowMinYMargin ? 1 : 0) + (_autoresizingMask & CPWindowHeightSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxYMargin ? 1 : 0));
if (_autoresizingMask & CPWindowMinXMargin)
newFrame.origin.x += dX;
if (_autoresizingMask & CPWindowWidthSizable)
newFrame.size.width += dX;
if (_autoresizingMask & CPWindowMinYMargin)
newFrame.origin.y += dY;
if (_autoresizingMask & CPWindowHeightSizable)
newFrame.size.height += dY;
[self setFrame:newFrame];
[self _setFrame:newFrame display:YES animate:NO constrainWidth:YES constrainHeight:YES];
}
/*
@@ -3252,11 +3368,11 @@ var keyViewComparator = function(lhs, rhs, context)
- (CGPoint)convertBaseToPlatformWindow:(CGPoint)aPoint
{
if ([self _sharesChromeWithPlatformWindow])
return _CGPointMakeCopy(aPoint);
return CGPointMakeCopy(aPoint);
var origin = [self frame].origin;
return _CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y);
return CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y);
}
/*!
@@ -3265,11 +3381,11 @@ var keyViewComparator = function(lhs, rhs, context)
- (CGPoint)convertPlatformWindowToBase:(CGPoint)aPoint
{
if ([self _sharesChromeWithPlatformWindow])
return _CGPointMakeCopy(aPoint);
return CGPointMakeCopy(aPoint);
var origin = [self frame].origin;
return _CGPointMake(aPoint.x - origin.x, aPoint.y - origin.y);
return CGPointMake(aPoint.x - origin.x, aPoint.y - origin.y);
}
- (CGPoint)convertScreenToBase:(CGPoint)aPoint
@@ -3345,7 +3461,7 @@ var keyViewComparator = function(lhs, rhs, context)
- (BOOL)containsPoint:(CGPoint)aPoint
{
return _CGRectContainsPoint(_frame, aPoint);
return CGRectContainsPoint(_frame, aPoint);
}
/* aPoint should be global */
@@ -3353,9 +3469,9 @@ var keyViewComparator = function(lhs, rhs, context)
{
// If we are using the new resizing mode, mouse events are valid
// outside the window's frame for non-full platform windows.
var mouseFrame = (!_isFullPlatformWindow && (_styleMask & CPResizableWindowMask) && (CPWindowResizeStyle === CPWindowResizeStyleModern)) ? _CGRectInset(_frame, -_CPWindowViewResizeSlop, -_CPWindowViewResizeSlop) : _frame;
var mouseFrame = (!_isFullPlatformWindow && (_styleMask & CPResizableWindowMask) && (CPWindowResizeStyle === CPWindowResizeStyleModern)) ? CGRectInset(_frame, -_CPWindowViewResizeSlop, -_CPWindowViewResizeSlop) : _frame;
return _CGRectContainsPoint(mouseFrame, aPoint);
return CGRectContainsPoint(mouseFrame, aPoint);
}
@end
@@ -3421,8 +3537,8 @@ var interpolate = function(fromValue, toValue, progress)
{
_window = aWindow;
_targetFrame = _CGRectMakeCopy(aTargetFrame);
_startFrame = _CGRectMakeCopy([_window frame]);
_targetFrame = CGRectMakeCopy(aTargetFrame);
_startFrame = CGRectMakeCopy([_window frame]);
}
return self;
@@ -3444,11 +3560,11 @@ var interpolate = function(fromValue, toValue, progress)
if (value == 1.0)
_window._isAnimating = NO;
var newFrame = _CGRectMake(
interpolate(_CGRectGetMinX(_startFrame), _CGRectGetMinX(_targetFrame), value),
interpolate(_CGRectGetMinY(_startFrame), _CGRectGetMinY(_targetFrame), value),
interpolate(_CGRectGetWidth(_startFrame), _CGRectGetWidth(_targetFrame), value),
interpolate(_CGRectGetHeight(_startFrame), _CGRectGetHeight(_targetFrame), value));
var newFrame = CGRectMake(
interpolate(CGRectGetMinX(_startFrame), CGRectGetMinX(_targetFrame), value),
interpolate(CGRectGetMinY(_startFrame), CGRectGetMinY(_targetFrame), value),
interpolate(CGRectGetWidth(_startFrame), CGRectGetWidth(_targetFrame), value),
interpolate(CGRectGetHeight(_startFrame), CGRectGetHeight(_targetFrame), value));
[_window setFrame:newFrame display:YES animate:NO];
}
+2
View File
@@ -194,3 +194,5 @@ CPStandardWindowShadowStyle = 0;
CPMenuWindowShadowStyle = 1;
CPPanelWindowShadowStyle = 2;
CPCustomWindowShadowStyle = 3;
CPWindowConstrainToScreen = YES;
@@ -32,7 +32,7 @@
return @"bordeless-bridge-window-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"toolbar-background-color": [CPColor grayColor],
+9 -17
View File
@@ -26,7 +26,6 @@
@implementation _CPDocModalWindowView : _CPWindowView
{
CPView _bodyView;
CPView _shadowView;
}
+ (CPString)defaultThemeClass
@@ -34,11 +33,11 @@
return @"doc-modal-window-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"body-color": [CPColor whiteColor],
@"height-shadow": 8,
@"shadow-height": 8,
};
}
@@ -50,7 +49,7 @@
*/
var contentRect = [super contentRectForFrameRect:aFrameRect];
return _CGRectInset(contentRect, 1.0, 1.0);
return CGRectInset(contentRect, 1.0, 1.0);
}
- (id)initWithFrame:(CGRect)aFrame styleMask:(unsigned)aStyleMask
@@ -61,17 +60,13 @@
{
var bounds = [self bounds];
_bodyView = [[CPView alloc] initWithFrame:_CGRectMake(0.0, 0.0, _CGRectGetWidth(bounds), _CGRectGetHeight(bounds))];
_bodyView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), CGRectGetHeight(bounds))];
[_bodyView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_bodyView setHitTests:NO];
[self addSubview:_bodyView];
_shadowView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, _CGRectGetWidth(bounds), [self valueForThemeAttribute:@"height-shadow"])];
[_shadowView setAutoresizingMask:CPViewWidthSizable];
[self addSubview:_shadowView];
}
}
return self;
}
@@ -86,11 +81,6 @@
return [[self class] frameRectForContentRect:aContentRect];
}
- (void)_enableSheet:(BOOL)enable
{
// do nothing, already a sheet
}
- (void)layoutSubviews
{
[super layoutSubviews];
@@ -98,9 +88,11 @@
var bounds = [self bounds];
[_bodyView setBackgroundColor:[self valueForThemeAttribute:@"body-color"]];
}
[_shadowView setFrame:CGRectMake(0,0, _CGRectGetWidth(bounds), [self valueForThemeAttribute:@"height-shadow"])];
[_shadowView setBackgroundColor:[self valueForThemeAttribute:@"attached-sheet-shadow-color"]];
- (int)bodyOffset
{
return [_bodyView frame].origin.y;
}
@end
+11 -9
View File
@@ -127,7 +127,7 @@
- (CGSize)toolbarOffset
{
return _CGSizeMake(0.0, [[self class] titleBarHeight]);
return CGSizeMake(0.0, [[self class] titleBarHeight]);
}
- (void)tile
@@ -136,22 +136,22 @@
var theWindow = [self window],
bounds = [self bounds],
width = _CGRectGetWidth(bounds);
width = CGRectGetWidth(bounds);
[_titleField setFrame:_CGRectMake(20.0, 0, width - 40.0, [self toolbarOffset].height)];
[_titleField setFrame:CGRectMake(20.0, 0, width - 40.0, [self toolbarOffset].height)];
var maxY = [self toolbarMaxY];
if ([_titleField isHidden])
maxY -= ([self toolbarOffset]).height;
var contentRect = _CGRectMake(0.0, maxY, width, _CGRectGetHeight(bounds) - maxY);
var contentRect = CGRectMake(0.0, maxY, width, CGRectGetHeight(bounds) - maxY);
[[theWindow contentView] setFrame:contentRect];
}
- (void)_enableSheet:(BOOL)enable
- (void)_enableSheet:(BOOL)enable inWindow:(CPWindow)parentWindow
{
[super _enableSheet:enable];
// No need to call super, it just deals with the shadow view, which we don't want
[_closeButton setHidden:enable];
[_titleField setHidden:enable];
@@ -164,15 +164,17 @@
if (enable)
dy = -dy;
var newHeight = _CGRectGetMaxY(frame) + dy,
newWidth = _CGRectGetMaxX(frame);
var newHeight = CGRectGetMaxY(frame) + dy,
newWidth = CGRectGetMaxX(frame);
frame.size.height += dy;
[self setFrameSize:_CGSizeMake(newWidth, newHeight)];
[self setFrameSize:CGSizeMake(newWidth, newHeight)];
[self tile];
[theWindow setFrame:frame display:NO animate:NO];
[theWindow setMovableByWindowBackground:!enable];
[self setNeedsLayout];
}
- (void)layoutSubviews
+29 -29
View File
@@ -28,11 +28,7 @@
@global CPPopoverAppearanceMinimal
var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
_CPPopoverWindowViewRadius = 5.0,
_CPPopoverWindowViewStrokeWidth = 1.0,
_CPPopoverWindowViewShadowSize = _CGSizeMake(0, 6),
_CPPopoverWindowViewShadowBlur = 15.0;
var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10);
/*!
@ignore
@@ -54,13 +50,17 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
return @"popover-window-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"background-gradient": [CPNull null],
@"background-gradient-hud": [CPNull null],
@"stroke-color": [CPNull null],
@"stroke-color-hud": [CPNull null],
@"border-radius": 5.0,
@"stroke-width": 1.0,
@"shadow-size": CGSizeMake(0, 6),
@"shadow-blur": 15.0
};
}
@@ -71,7 +71,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
*/
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
var contentRect = _CGRectMakeCopy(aFrameRect),
var contentRect = CGRectMakeCopy(aFrameRect),
modifierX = 16,
modifierY = 19;
@@ -79,7 +79,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
//
// @comment: If we use this, each time we open the popover, the content
// view is reduced a little over and over
// return _CGRectInset(contentRect, modifierX, modifierY);
// return CGRectInset(contentRect, modifierX, modifierY);
contentRect.origin.x += modifierX;
contentRect.origin.y += modifierY;
@@ -96,7 +96,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
*/
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
{
var frameRect = _CGRectMakeCopy(aContentRect),
var frameRect = CGRectMakeCopy(aContentRect),
modifierX = 16,
modifierY = 19;
@@ -104,7 +104,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
// @comment: If we use this, each time we open the popover, the content
//
// view is reduced a little over and over
// return _CGRectOffset(frameRect, modifierX, modifierY);
// return CGRectOffset(frameRect, modifierX, modifierY);
frameRect.origin.x -= modifierX;
frameRect.origin.y -= modifierY;
@@ -124,7 +124,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
_arrowOffsetX = 0.0;
_arrowOffsetY = 0.0;
_appearance = CPPopoverAppearanceMinimal;
_cursorSize = _CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize);
_cursorSize = CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize);
}
return self;
@@ -135,7 +135,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
*/
- (void)hideCursor
{
_cursorSize = _CGSizeMakeZero();
_cursorSize = CGSizeMakeZero();
[self setNeedsDisplay:YES];
}
@@ -144,7 +144,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
*/
- (void)showCursor
{
_cursorSize = _CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize);
_cursorSize = CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize);
[self setNeedsDisplay:YES];
}
@@ -156,15 +156,15 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
[super drawRect:aRect];
var context = [[CPGraphicsContext currentContext] graphicsPort],
radius = _CPPopoverWindowViewRadius,
radius = [self valueForThemeAttribute:@"border-radius"],
arrowWidth = _cursorSize.width,
arrowHeight = _cursorSize.height,
strokeWidth = _CPPopoverWindowViewStrokeWidth,
strokeWidth = [self valueForThemeAttribute:@"stroke-width"],
halfStrokeWidth = strokeWidth / 2.0,
strokeColor,
shadowColor = [[CPColor blackColor] colorWithAlphaComponent:.2],
shadowSize = _CPPopoverWindowViewShadowSize,
shadowBlur = _CPPopoverWindowViewShadowBlur,
shadowSize = [self valueForThemeAttribute:@"shadow-size"],
shadowBlur = [self valueForThemeAttribute:@"shadow-blur"],
gradient,
frame = [self bounds];
@@ -190,19 +190,19 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
CGContextBeginPath(context);
CGContextSetShadowWithColor(context, shadowSize, shadowBlur, shadowColor);
CGContextDrawLinearGradient(context, gradient, _CGPointMake(_CGRectGetMidX(frame), 0.0), _CGPointMake(_CGRectGetMidX(frame), frame.size.height), 0);
CGContextDrawLinearGradient(context, gradient, CGPointMake(CGRectGetMidX(frame), 0.0), CGPointMake(CGRectGetMidX(frame), frame.size.height), 0);
var xMin = _CGRectGetMinX(frame),
xMax = _CGRectGetMaxX(frame),
yMin = _CGRectGetMinY(frame),
yMax = _CGRectGetMaxY(frame),
var xMin = CGRectGetMinX(frame),
xMax = CGRectGetMaxX(frame),
yMin = CGRectGetMinY(frame),
yMax = CGRectGetMaxY(frame),
arrowMinX = CGAlignCoordinate(xMin + radius + strokeWidth),
arrowMaxX = CGAlignCoordinate(xMax - radius - strokeWidth),
arrowMinY = CGAlignCoordinate(yMin + radius + strokeWidth),
arrowMaxY = CGAlignCoordinate(yMax - radius + strokeWidth),
arrowAnchor = _CGPointMakeZero(),
arrowStart = _CGPointMakeZero(),
pt = _CGPointMakeZero();
arrowAnchor = CGPointMakeZero(),
arrowStart = CGPointMakeZero(),
pt = CGPointMakeZero();
// draw!
var path = CGPathCreateMutable();
@@ -237,7 +237,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
pt.y = arrowMaxY - arrowWidth;
pt.x = arrowAnchor.x;
arrowStart = _CGPointMakeCopy(pt);
arrowStart = CGPointMakeCopy(pt);
CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
// top edge -> point
@@ -279,7 +279,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
pt.y = arrowMaxY;
pt.x = arrowAnchor.x;
arrowStart = _CGPointMakeCopy(pt);
arrowStart = CGPointMakeCopy(pt);
CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
// bottom edge -> point
@@ -328,7 +328,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
pt.x = arrowMaxX - arrowWidth;
pt.y = arrowAnchor.y;
arrowStart = _CGPointMakeCopy(pt);
arrowStart = CGPointMakeCopy(pt);
CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
// left edge -> point
@@ -370,7 +370,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10),
pt.x = arrowMaxX;
pt.y = arrowAnchor.y;
arrowStart = _CGPointMakeCopy(pt);
arrowStart = CGPointMakeCopy(pt);
CGPathAddLineToPoint(path, NULL, pt.x, pt.y);
// right edge -> point
+2 -2
View File
@@ -41,7 +41,7 @@
return @"shadow-window-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{};
}
@@ -54,7 +54,7 @@
shadowDistance = [_windowView valueForThemeAttribute:@"shadow-distance"],
shadowInset = [_windowView valueForThemeAttribute:@"shadow-inset"],
size = [_windowView frameSize],
shadowSize = _CGSizeMake(size.width, size.height);
shadowSize = CGSizeMake(size.width, size.height);
// if the shadow would be taller/wider than the window height,
// make it the same as the window height. this allows views to
+80 -46
View File
@@ -29,6 +29,8 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
@implementation _CPTexturedWindowHeadView : CPView
{
BOOL _isSheet @accessors(setter=setSheet:);
_CPWindowView _parentView;
CPView _gradientView;
CPView _solidView;
@@ -39,7 +41,7 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
return @"textured-window-head-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{};
}
@@ -51,10 +53,10 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
if (self)
{
_parentView = parentView;
_gradientView = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
_gradientView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[self addSubview:_gradientView];
_solidView = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
_solidView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[self addSubview:_solidView];
}
@@ -66,12 +68,13 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
[super layoutSubviews];
var gradientHeight = [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView],
bounds = [self bounds];
bounds = [self bounds],
bezelHeadColor = [[CPTheme defaultTheme] valueForAttributeWithName:_isSheet ? @"bezel-head-sheet-color" : @"bezel-head-color" inState:[_parentView themeState] forClass:_CPStandardWindowView];
[_gradientView setFrame:_CGRectMake(0.0, 0.0, _CGRectGetWidth(bounds), gradientHeight)];
[_gradientView setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"bezel-head-color" inState:[_parentView themeState] forClass:_CPStandardWindowView]];
[_gradientView setFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), gradientHeight)];
[_gradientView setBackgroundColor:bezelHeadColor];
[_solidView setFrame:_CGRectMake(0.0, gradientHeight, _CGRectGetWidth(bounds), _CGRectGetHeight(bounds) - gradientHeight)];
[_solidView setFrame:CGRectMake(0.0, gradientHeight, CGRectGetWidth(bounds), CGRectGetHeight(bounds) - gradientHeight)];
[_solidView setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"solid-color" forClass:_CPStandardWindowView]];
}
@@ -79,8 +82,8 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
{
var bounds = [self bounds];
[_gradientView setFrameSize:_CGSizeMake(_CGRectGetWidth(bounds), [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView])];
[_solidView setFrameSize:_CGSizeMake(_CGRectGetWidth(bounds), _CGRectGetHeight(bounds) - [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView])];
[_gradientView setFrameSize:CGSizeMake(CGRectGetWidth(bounds), [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView])];
[_solidView setFrameSize:CGSizeMake(CGRectGetWidth(bounds), CGRectGetHeight(bounds) - [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView])];
}
@end
@@ -97,6 +100,7 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
CPButton _minimizeButton;
BOOL _isDocumentEdited;
BOOL _isSheet;
}
+ (CPString)defaultThemeClass
@@ -104,12 +108,13 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
return @"standard-window-view";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"gradient-height": [CPNull null],
@"solid-color": [CPNull null],
@"bezel-head-color": [CPNull null],
@"bezel-head-sheet-color": [CPNull null],
@"divider-color": [CPColor blackColor],
@"body-color": [CPColor whiteColor],
@"title-bar-height": 32,
@@ -130,7 +135,6 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
The top coordinate has already been adjusted by _CPTitleableWindowView.
*/
var contentRect = [super contentRectForFrameRect:aFrameRect];
contentRect.origin.x += 1;
contentRect.size.width -= 2;
contentRect.size.height -= 1;
@@ -151,34 +155,34 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
var theClass = [self class],
bounds = [self bounds];
_headView = [[_CPTexturedWindowHeadView alloc] initWithFrame:_CGRectMake(0.0, 0.0, _CGRectGetWidth(bounds), [self valueForThemeAttribute:@"title-bar-height"]) windowView:self];
_headView = [[_CPTexturedWindowHeadView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), [self valueForThemeAttribute:@"title-bar-height"]) windowView:self];
[_headView setAutoresizingMask:CPViewWidthSizable];;
[_headView setHitTests:NO];
[self addSubview:_headView positioned:CPWindowBelow relativeTo:_titleField];
_dividerView = [[CPView alloc] initWithFrame:_CGRectMake(0.0, _CGRectGetMaxY([_headView frame]), _CGRectGetWidth(bounds), _CPStandardWindowViewDividerViewHeight)];
_dividerView = [[CPView alloc] initWithFrame:CGRectMake(0.0, CGRectGetMaxY([_headView frame]), CGRectGetWidth(bounds), _CPStandardWindowViewDividerViewHeight)];
[_dividerView setAutoresizingMask:CPViewWidthSizable];
[_dividerView setHitTests:NO];
[self addSubview:_dividerView];
var y = _CGRectGetMaxY([_dividerView frame]);
var y = CGRectGetMinY([_dividerView frame]);
_bodyView = [[CPView alloc] initWithFrame:_CGRectMake(0.0, y, _CGRectGetWidth(bounds), _CGRectGetHeight(bounds) - y)];
_bodyView = [[CPView alloc] initWithFrame:CGRectMake(0.0, y, CGRectGetWidth(bounds), CGRectGetHeight(bounds) - y)];
[_bodyView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_bodyView setHitTests:NO];
[self addSubview:_bodyView];
[self setResizeIndicatorOffset:_CGSizeMake(2.0, 2.0)];
[self setResizeIndicatorOffset:CGSizeMake(2.0, 2.0)];
if (_styleMask & CPClosableWindowMask)
{
_closeButton = [[CPButton alloc] initWithFrame:_CGRectMake(8.0, 8.0, 16.0, 16.0)];
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 8.0, 16.0, 16.0)];
[_closeButton setButtonType:CPMomentaryChangeButton];
[_closeButton setBordered:NO];
@@ -189,7 +193,7 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
if (_styleMask & CPMiniaturizableWindowMask && ![CPPlatform isBrowser])
{
_minimizeButton = [[CPButton alloc] initWithFrame:_CGRectMake(27.0, 7.0, 16.0, 16.0)];
_minimizeButton = [[CPButton alloc] initWithFrame:CGRectMake(27.0, 7.0, 16.0, 16.0)];
[_minimizeButton setButtonType:CPMomentaryChangeButton];
[_minimizeButton setBordered:NO];
@@ -213,7 +217,7 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
- (CGSize)toolbarOffset
{
return _CGSizeMake(0.0, [self valueForThemeAttribute:@"title-bar-height"]);
return CGSizeMake(0.0, [self valueForThemeAttribute:@"title-bar-height"]);
}
- (void)tile
@@ -222,22 +226,26 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
var theWindow = [self window],
bounds = [self bounds],
width = _CGRectGetWidth(bounds),
width = CGRectGetWidth(bounds),
headHeight = [self toolbarMaxY];
[_headView setFrameSize:_CGSizeMake(width, headHeight)];
[_dividerView setFrame:_CGRectMake(0.0, headHeight, width, 1.0)];
var dividerMaxY = 0,
dividerMinY = 0;
if (![_dividerView isHidden])
if (_isSheet && _toolbarView && [self showsToolbar])
{
dividerMinY = _CGRectGetMinY([_dividerView frame]);
dividerMaxY = _CGRectGetMaxY([_dividerView frame]);
headHeight = [_toolbarView frameSize].height;
[_toolbarView setFrameOrigin:CGPointMake(0.0, 0.0)];
}
[_bodyView setFrame:_CGRectMake(0.0, dividerMaxY, width, _CGRectGetHeight(bounds) - dividerMaxY)];
[_headView setFrameSize:CGSizeMake(width, headHeight)];
[_dividerView setFrame:CGRectMake(0.0, headHeight, width, _CPStandardWindowViewDividerViewHeight)];
var dividerMinY = 0,
dividerFrame = [_dividerView frame];
if (![_dividerView isHidden])
dividerMinY = CGRectGetMinY(dividerFrame);
[_bodyView setFrame:CGRectMake(0.0, dividerMinY, width, CGRectGetHeight(bounds) - dividerMinY)];
var leftOffset = 8;
@@ -246,11 +254,10 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
if (_minimizeButton)
leftOffset += 19.0;
[_titleField setFrame:_CGRectMake(leftOffset, 0, width - leftOffset * 2.0, [self valueForThemeAttribute:@"title-bar-height"])];
[_titleField setFrame:CGRectMake(leftOffset, 0, width - leftOffset * 2.0, [self valueForThemeAttribute:@"title-bar-height"])];
var contentRect = _CGRectMake(0.0, dividerMaxY, width, _CGRectGetHeight([_bodyView frame]));
[[theWindow contentView] setFrame:contentRect];
var contentFrame = [_bodyView frame];
[[theWindow contentView] setFrame:CGRectInset(contentFrame, 1.0, 1.0)];
}
/*
@@ -307,43 +314,65 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
- (BOOL)couldBeMoveEvent:(CPEvent)anEvent
{
if (![_headView isHidden])
if (_CGRectContainsPoint([_headView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]))
if (CGRectContainsPoint([_headView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]))
return YES;
return [super couldBeMoveEvent:anEvent];
}
- (void)_enableSheet:(BOOL)enable
- (void)_enableSheet:(BOOL)enable inWindow:(CPWindow)parentWindow
{
[super _enableSheet:enable];
[super _enableSheet:enable inWindow:parentWindow];
_isSheet = enable;
[_headView setSheet:enable];
if (_toolbarView && [self showsToolbar])
{
[_headView setHidden:NO];
[_dividerView setHidden:NO];
}
else
{
[_headView setHidden:enable];
[_dividerView setHidden:enable];
}
[_headView setHidden:enable];
[_dividerView setHidden:enable];
[_closeButton setHidden:enable];
[_minimizeButton setHidden:enable];
[_titleField setHidden:enable];
[[self window] setMovable:!enable];
if (enable)
{
[_bodyView setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"body-color" forClass:_CPDocModalWindowView]];
// Move the shadow view down so it is inside the content border
var shadowFrame = [_sheetShadowView frame];
[_sheetShadowView setFrameOrigin:CGPointMake(shadowFrame.origin.x, shadowFrame.origin.y + 1)];
}
else
[_bodyView setBackgroundColor:[self valueForThemeAttribute:@"body-color"]];
// resize the window
var theWindow = [self window],
frame = [theWindow frame],
dy;
dividerHeight = [_dividerView frame].size.height,
dy = [self toolbarMaxY] + dividerHeight;
if (_toolbarView && [self showsToolbar])
dy = [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView];
if (enable)
dy = -(_CGRectGetHeight([_headView frame]) + _CGRectGetHeight([_dividerView frame]));
else
dy = [self toolbarMaxY] + 1.0;
dy = -dy;
var newHeight = _CGRectGetMaxY(frame) + dy,
newWidth = _CGRectGetMaxX(frame);
var newHeight = CGRectGetHeight(frame) + dy,
newWidth = CGRectGetWidth(frame);
frame.size.height += dy;
[self setFrameSize:_CGSizeMake(newWidth, newHeight)];
[self setFrameSize:CGSizeMake(newWidth, newHeight)];
[self tile];
[theWindow setFrame:frame display:NO animate:NO];
@@ -380,4 +409,9 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
return size;
}
- (int)bodyOffset
{
return [_bodyView frame].origin.y;
}
@end
+6 -1
View File
@@ -95,7 +95,7 @@
// The vertical alignment of the title is set by the theme, so just give it all available space. By default
// the title will vertically centre within.
[_titleField setFrame:_CGRectMake(20.0, 0, width - 40.0, [[self class] titleBarHeight])];
[_titleField setFrame:CGRectMake(20.0, 0, width - 40.0, [[self class] titleBarHeight])];
}
- (void)layoutSubviews
@@ -121,4 +121,9 @@
return size;
}
- (int)bodyOffset
{
return [self contentRectForFrameRect:[self frame]].origin.y;
}
@end
+1 -1
View File
@@ -38,7 +38,7 @@
return @"tooltip";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"stroke-color": [CPColor colorWithHexString:@"E3E3E3"],
+217 -115
View File
@@ -57,7 +57,7 @@ _CPWindowViewResizeSlop = 3;
CGSize _toolbarOffset;
// BOOL _isAnimatingToolbar;
CGRect _resizeFrame;
CGRect _cachedFrame;
int _resizeRegion;
CGPoint _mouseDraggedPoint;
@@ -68,12 +68,12 @@ _CPWindowViewResizeSlop = 3;
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
return _CGRectMakeCopy(aFrameRect);
return CGRectMakeCopy(aFrameRect);
}
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
{
return _CGRectMakeCopy(aContentRect);
return CGRectMakeCopy(aContentRect);
}
+ (CPString)defaultThemeClass
@@ -81,7 +81,7 @@ _CPWindowViewResizeSlop = 3;
return "window";
}
+ (id)themeAttributes
+ (CPDictionary)themeAttributes
{
return @{
@"title-bar-height": 25,
@@ -91,6 +91,7 @@ _CPWindowViewResizeSlop = 3;
@"size-indicator": CGSizeMakeZero(),
@"resize-indicator": [CPNull null],
@"attached-sheet-shadow-color": [CPColor blackColor],
@"shadow-height": 8,
@"close-image-origin": [CPNull null],
@"close-image-size": [CPNull null],
@"close-image": [CPNull null],
@@ -99,7 +100,7 @@ _CPWindowViewResizeSlop = 3;
@"title-text-color": [CPColor blackColor],
@"title-font": [CPFont systemFontOfSize:CPFontCurrentSystemSize],
@"title-text-shadow-color": [CPNull null],
@"title-text-shadow-offset": _CGSizeMakeZero(),
@"title-text-shadow-offset": CGSizeMakeZero(),
@"title-alignment": CPCenterTextAlignment,
@"title-line-break-mode": CPLineBreakByTruncatingTail,
@"title-vertical-alignment": CPTopVerticalTextAlignment,
@@ -113,7 +114,7 @@ _CPWindowViewResizeSlop = 3;
if ([theToolbar isVisible])
{
var toolbarHeight = _CGRectGetHeight([[theToolbar _toolbarView] frame]);
var toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]);
contentRect.origin.y += toolbarHeight;
contentRect.size.height -= toolbarHeight;
@@ -129,7 +130,7 @@ _CPWindowViewResizeSlop = 3;
if ([theToolbar isVisible])
{
var toolbarHeight = _CGRectGetHeight([[theToolbar _toolbarView] frame]);
var toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]);
frameRect.origin.y -= toolbarHeight;
frameRect.size.height += toolbarHeight;
@@ -145,8 +146,8 @@ _CPWindowViewResizeSlop = 3;
if (self)
{
_styleMask = aStyleMask;
_resizeIndicatorOffset = _CGSizeMakeZero();
_toolbarOffset = _CGSizeMakeZero();
_resizeIndicatorOffset = CGSizeMakeZero();
_toolbarOffset = CGSizeMakeZero();
}
return self;
@@ -201,8 +202,8 @@ _CPWindowViewResizeSlop = 3;
{
// Extend the resize frame to the edge of the window frame
var resizeFrame = [_resizeIndicator frame];
resizeFrame.size.width = _CGRectGetWidth(windowFrame) - _CGRectGetMinX(resizeFrame);
resizeFrame.size.height = _CGRectGetHeight(windowFrame) - _CGRectGetMinY(resizeFrame);
resizeFrame.size.width = CGRectGetWidth(windowFrame) - CGRectGetMinX(resizeFrame);
resizeFrame.size.height = CGRectGetHeight(windowFrame) - CGRectGetMinY(resizeFrame);
var localPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
shouldResize = CGRectContainsPoint(resizeFrame, localPoint);
@@ -245,6 +246,8 @@ _CPWindowViewResizeSlop = 3;
rects are the same size. So to save calculations, we can just create
3 rects and move them around to do hit testing. Start with the corners
and then do left/right and top/bottom.
NOTE: If the window is a sheet, the top is never eligible for resizing.
*/
var wind = [self window],
frame = [wind frame],
@@ -252,87 +255,88 @@ _CPWindowViewResizeSlop = 3;
minSize = [wind minSize],
maxSize = [wind maxSize],
isFixedWidth = minSize.width === maxSize.width,
isFixedHeight = minSize.height === maxSize.height;
isFixedHeight = minSize.height === maxSize.height,
isSheet = wind._isSheet;
if (isFixedWidth)
{
rect = _CGRectMake(frame.origin.x - _CPWindowViewResizeSlop,
rect = CGRectMake(frame.origin.x - _CPWindowViewResizeSlop,
frame.origin.y - _CPWindowViewResizeSlop,
frame.size.width + (_CPWindowViewResizeSlop * 2),
_CPWindowViewResizeSlop * 2);
if (_CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionTop;
if (CGRectContainsPoint(rect, aPoint))
return isSheet ? _CPWindowViewResizeRegionNone : _CPWindowViewResizeRegionTop;
rect.origin.y = _CGRectGetMaxY(frame) - _CPWindowViewResizeSlop;
rect.origin.y = CGRectGetMaxY(frame) - _CPWindowViewResizeSlop;
if (_CGRectContainsPoint(rect, aPoint))
if (CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionBottom;
}
else if (isFixedHeight)
{
rect = _CGRectMake(frame.origin.x - _CPWindowViewResizeSlop,
rect = CGRectMake(frame.origin.x - _CPWindowViewResizeSlop,
frame.origin.y - _CPWindowViewResizeSlop,
_CPWindowViewResizeSlop * 2,
frame.size.height + (_CPWindowViewResizeSlop * 2));
if (_CGRectContainsPoint(rect, aPoint))
if (CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionLeft;
rect.origin.x = _CGRectGetMaxX(frame) - _CPWindowViewResizeSlop;
rect.origin.x = CGRectGetMaxX(frame) - _CPWindowViewResizeSlop;
if (_CGRectContainsPoint(rect, aPoint))
if (CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionRight;
}
else
{
rect = _CGRectMake(frame.origin.x - _CPWindowViewResizeSlop,
rect = CGRectMake(frame.origin.x - _CPWindowViewResizeSlop,
frame.origin.y - _CPWindowViewResizeSlop,
_CPWindowViewCornerResizeRectWidth + _CPWindowViewResizeSlop,
_CPWindowViewCornerResizeRectWidth + _CPWindowViewResizeSlop);
if (_CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionTopLeft;
if (CGRectContainsPoint(rect, aPoint))
return isSheet ? _CPWindowViewResizeRegionNone : _CPWindowViewResizeRegionTopLeft;
rect.origin.x = _CGRectGetMaxX(frame) - _CPWindowViewCornerResizeRectWidth;
rect.origin.x = CGRectGetMaxX(frame) - _CPWindowViewCornerResizeRectWidth;
if (_CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionTopRight;
if (CGRectContainsPoint(rect, aPoint))
return isSheet ? _CPWindowViewResizeRegionNone : _CPWindowViewResizeRegionTopRight;
rect.origin.y = _CGRectGetMaxY(frame) - _CPWindowViewCornerResizeRectWidth;
rect.origin.y = CGRectGetMaxY(frame) - _CPWindowViewCornerResizeRectWidth;
if (_CGRectContainsPoint(rect, aPoint))
if (CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionBottomRight;
rect.origin.x = frame.origin.x - _CPWindowViewResizeSlop;
if (_CGRectContainsPoint(rect, aPoint))
if (CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionBottomLeft;
rect = _CGRectMake(rect.origin.x,
rect = CGRectMake(rect.origin.x,
frame.origin.y + _CPWindowViewCornerResizeRectWidth,
_CPWindowViewResizeSlop * 2,
_CGRectGetHeight(frame) - (_CPWindowViewCornerResizeRectWidth * 2));
CGRectGetHeight(frame) - (_CPWindowViewCornerResizeRectWidth * 2));
if (_CGRectContainsPoint(rect, aPoint))
if (CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionLeft;
rect.origin.x = _CGRectGetMaxX(frame) - _CPWindowViewResizeSlop;
rect.origin.x = CGRectGetMaxX(frame) - _CPWindowViewResizeSlop;
if (_CGRectContainsPoint(rect, aPoint))
if (CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionRight;
rect = _CGRectMake(frame.origin.x + _CPWindowViewCornerResizeRectWidth,
rect = CGRectMake(frame.origin.x + _CPWindowViewCornerResizeRectWidth,
frame.origin.y - _CPWindowViewResizeSlop,
_CGRectGetWidth(frame) - (_CPWindowViewCornerResizeRectWidth * 2),
CGRectGetWidth(frame) - (_CPWindowViewCornerResizeRectWidth * 2),
_CPWindowViewResizeSlop * 2);
if (_CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionTop;
if (CGRectContainsPoint(rect, aPoint))
return isSheet ? _CPWindowViewResizeRegionNone : _CPWindowViewResizeRegionTop;
rect.origin.y = _CGRectGetMaxY(frame) - _CPWindowViewResizeSlop;
rect.origin.y = CGRectGetMaxY(frame) - _CPWindowViewResizeSlop;
if (_CGRectContainsPoint(rect, aPoint))
if (CGRectContainsPoint(rect, aPoint))
return _CPWindowViewResizeRegionBottom;
}
@@ -367,9 +371,9 @@ _CPWindowViewResizeSlop = 3;
switch (resizeRegion)
{
case _CPWindowViewResizeRegionTopLeft:
if (minSize && _CGSizeEqualToSize(frameSize, minSize))
if (minSize && CGSizeEqualToSize(frameSize, minSize))
[[CPCursor resizeNorthwestCursor] set];
else if (maxSize && _CGSizeEqualToSize(frameSize, maxSize))
else if (maxSize && CGSizeEqualToSize(frameSize, maxSize))
[[CPCursor resizeSoutheastCursor] set];
else
[[CPCursor resizeNorthwestSoutheastCursor] set];
@@ -380,16 +384,16 @@ _CPWindowViewResizeSlop = 3;
[[CPCursor resizeUpCursor] set];
else if (maxSize && (frameSize.height === maxSize.height))
[[CPCursor resizeDownCursor] set];
else if ([CPMenu menuBarVisible] && (_CGRectGetMinY([theWindow frame]) <= [CPMenu menuBarHeight]))
else if ([CPMenu menuBarVisible] && (CGRectGetMinY([theWindow frame]) <= [CPMenu menuBarHeight]))
[[CPCursor resizeDownCursor] set];
else
[[CPCursor resizeNorthSouthCursor] set];
break;
case _CPWindowViewResizeRegionTopRight:
if (minSize && _CGSizeEqualToSize(frameSize, minSize))
if (minSize && CGSizeEqualToSize(frameSize, minSize))
[[CPCursor resizeNortheastCursor] set];
else if (maxSize && _CGSizeEqualToSize(frameSize, maxSize))
else if (maxSize && CGSizeEqualToSize(frameSize, maxSize))
[[CPCursor resizeSouthwestCursor] set];
else
[[CPCursor resizeNortheastSouthwestCursor] set];
@@ -405,9 +409,9 @@ _CPWindowViewResizeSlop = 3;
break;
case _CPWindowViewResizeRegionBottomRight:
if (minSize && _CGSizeEqualToSize(frameSize, minSize))
if (minSize && CGSizeEqualToSize(frameSize, minSize))
[[CPCursor resizeSoutheastCursor] set];
else if (maxSize && _CGSizeEqualToSize(frameSize, maxSize))
else if (maxSize && CGSizeEqualToSize(frameSize, maxSize))
[[CPCursor resizeNorthwestCursor] set];
else
[[CPCursor resizeNorthwestSoutheastCursor] set];
@@ -423,9 +427,9 @@ _CPWindowViewResizeSlop = 3;
break;
case _CPWindowViewResizeRegionBottomLeft:
if (minSize && _CGSizeEqualToSize(frameSize, minSize))
if (minSize && CGSizeEqualToSize(frameSize, minSize))
[[CPCursor resizeSouthwestCursor] set];
else if (maxSize && _CGSizeEqualToSize(frameSize, maxSize))
else if (maxSize && CGSizeEqualToSize(frameSize, maxSize))
[[CPCursor resizeNortheastCursor] set];
else
[[CPCursor resizeNortheastSouthwestCursor] set];
@@ -450,7 +454,10 @@ _CPWindowViewResizeSlop = 3;
var type = [anEvent type];
if (type === CPLeftMouseUp)
{
_cachedScreenFrame = nil;
return;
}
var location = [anEvent locationInWindow],
theWindow = [self window],
@@ -459,28 +466,31 @@ _CPWindowViewResizeSlop = 3;
if (type === CPLeftMouseDown)
{
_mouseDraggedPoint = _CGPointMakeCopy(globalLocation);
_resizeFrame = _CGRectMakeCopy(frame);
_mouseDraggedPoint = CGPointMake(globalLocation.x, globalLocation.y);
_cachedFrame = CGRectMakeCopy(frame);
_cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
}
else if (type === CPLeftMouseDragged)
{
var deltaX = globalLocation.x - _mouseDraggedPoint.x,
deltaY = globalLocation.y - _mouseDraggedPoint.y,
startX = _CGRectGetMinX(_resizeFrame),
startY = _CGRectGetMinY(_resizeFrame),
startWidth = _CGRectGetWidth(_resizeFrame),
startHeight = _CGRectGetHeight(_resizeFrame),
startX = CGRectGetMinX(_cachedFrame),
startY = CGRectGetMinY(_cachedFrame),
startWidth = CGRectGetWidth(_cachedFrame),
startHeight = CGRectGetHeight(_cachedFrame),
newX,
newY,
newWidth,
newHeight,
platformFrame = [[theWindow platformWindow] usableContentFrame],
resizeMinSize = [self _minimumResizeSize],
minSize = [theWindow minSize],
maxSize = [theWindow maxSize];
minSize = _CGSizeMake(MAX(minSize.width, resizeMinSize.width), MAX(minSize.height, resizeMinSize.height));
minSize = CGSizeMake(MAX(minSize.width, resizeMinSize.width), MAX(minSize.height, resizeMinSize.height));
// If it's a sheet, horizontal resizing is symmetrical, so the movement is effectively doubled
if (theWindow._isSheet)
deltaX *= 2;
// Calculate x and width first
switch (_resizeRegion)
@@ -498,8 +508,24 @@ _CPWindowViewResizeSlop = 3;
else if (deltaX < 0)
deltaX = -MIN(maxSize.width - startWidth, ABS(deltaX));
// When resizing from the left, we change the origin and the width
if (theWindow._isSheet)
deltaX = FLOOR(deltaX / 2);
newX = startX + deltaX;
// Pin the left edge to the usable screen left edge
var pinnedX = MAX(newX, CGRectGetMinX(_cachedScreenFrame));
if (pinnedX !== newX)
{
deltaX += pinnedX - newX;
newX = pinnedX;
}
// When resizing from the left, we change the origin and the width
if (theWindow._isSheet)
deltaX *= 2;
newWidth = startWidth - deltaX;
break;
@@ -516,9 +542,26 @@ _CPWindowViewResizeSlop = 3;
else if (deltaX < 0)
deltaX = -MIN(startWidth - minSize.width, ABS(deltaX));
// When resizing from the right, change only the width
newX = startX;
newWidth = startWidth + deltaX;
if (theWindow._isSheet)
deltaX = FLOOR(deltaX / 2);
// Pin the right edge to the usable screen right edge
var newMaxX = startX + startWidth + deltaX,
pinnedX = MIN(newMaxX, CGRectGetMaxX(_cachedScreenFrame));
if (pinnedX !== newMaxX)
deltaX += pinnedX - newMaxX;
if (theWindow._isSheet)
{
newWidth = startWidth + (deltaX * 2);
newX = startX - FLOOR((newWidth - startWidth) / 2);
}
else
{
newWidth = startWidth + deltaX;
newX = startX;
}
break;
default:
@@ -542,8 +585,18 @@ _CPWindowViewResizeSlop = 3;
else if (deltaY < 0)
deltaY = -MIN(maxSize.height - startHeight, ABS(deltaY));
// When resizing from the top, change the origin and the height
newY = startY + deltaY;
// Pin the top edge to the usable screen top edge
var pinnedY = MAX(newY, CGRectGetMinY(_cachedScreenFrame));
if (pinnedY !== newY)
{
deltaY += pinnedY - newY;
newY = pinnedY;
}
// When resizing from the top, change the origin and the height
newHeight = startHeight - deltaY;
break;
@@ -560,8 +613,16 @@ _CPWindowViewResizeSlop = 3;
else if (deltaY < 0)
deltaY = -MIN(startHeight - minSize.height, ABS(deltaY));
// When resizing from the bottom, change only the height
newY = startY;
// Pin the bottom edge to the usable screen bottom edge
var newMaxY = startY + startHeight + deltaY,
pinnedY = MIN(newMaxY, CGRectGetMaxY(_cachedScreenFrame));
if (pinnedY !== newMaxY)
deltaY += pinnedY - newMaxY;
// When resizing from the bottom, change only the height
newHeight = startHeight + deltaY;
break;
@@ -570,72 +631,71 @@ _CPWindowViewResizeSlop = 3;
newHeight = startHeight;
}
if (theWindow._isSheet && theWindow._parentView && (frame.size.width !== newWidth))
[theWindow._parentView _setAttachedSheetFrameOrigin];
// When resizing, we always constrain to the usable screen.
frame = CGRectMake(newX, newY, newWidth, newHeight);
// Constrain resize to fit within the platform window.
var newFrame = CGRectIntersection(_CGRectMake(newX, newY, newWidth, newHeight), platformFrame);
var constrainedFrame = [theWindow _constrainOriginOfFrame:frame],
dx = constrainedFrame.origin.x - frame.origin.x,
dy = constrainedFrame.origin.y - frame.origin.y;
[theWindow setFrame:newFrame];
// When resizing from the left or top, we adjust the origin and size.
switch (_resizeRegion)
{
case _CPWindowViewResizeRegionBottomLeft:
case _CPWindowViewResizeRegionLeft:
case _CPWindowViewResizeRegionTopLeft:
case _CPWindowViewResizeRegionTop:
case _CPWindowViewResizeRegionTopRight:
frame.origin = constrainedFrame.origin;
frame.size.width -= dx;
frame.size.height -= dy;
}
// When resizing from the right or bottom, we only adjust the size.
switch (_resizeRegion)
{
case _CPWindowViewResizeRegionTopRight:
case _CPWindowViewResizeRegionRight:
case _CPWindowViewResizeRegionBottomRight:
case _CPWindowViewResizeRegionBottom:
frame.size.width += dx;
frame.size.height += dy;
}
[theWindow _setFrame:frame display:YES animate:NO constrainWidth:NO constrainHeight:NO];
[self setCursorForLocation:location resizing:YES];
}
[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 = [[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, minPointY), _CGRectGetMaxY(visibleFrame) - 8.0);
return restrictedPoint;
}
- (void)trackMoveWithEvent:(CPEvent)anEvent
{
if (![[self window] isMovable])
var theWindow = [self window];
if (![theWindow isMovable])
return;
var type = [anEvent type];
if (type === CPLeftMouseUp)
{
_cachedScreenFrame = nil;
return;
}
else if (type === CPLeftMouseDown)
{
_mouseDraggedPoint = [[self window] convertBaseToGlobal:[anEvent locationInWindow]];
_cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
_mouseDraggedPoint = [theWindow convertBaseToGlobal:[anEvent locationInWindow]];
_cachedFrame = CGRectMakeCopy([theWindow frame]);
}
else if (type === CPLeftMouseDragged)
{
var theWindow = [self window],
frame = [theWindow frame],
location = [theWindow convertBaseToGlobal:[anEvent locationInWindow]],
deltaX = location.x - _mouseDraggedPoint.x,
deltaY = location.y - _mouseDraggedPoint.y,
origin = [self _pointWithinScreenFrame:_CGPointMake(frame.origin.x + deltaX,
frame.origin.y + deltaY)];
[theWindow setFrameOrigin:origin];
origin = CGPointMake(_cachedFrame.origin.x + deltaX, _cachedFrame.origin.y + deltaY);
_mouseDraggedPoint = [self _pointWithinScreenFrame:location];
[theWindow setFrameOrigin:origin];
}
[CPApp setTarget:self selector:@selector(trackMoveWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
@@ -646,10 +706,16 @@ _CPWindowViewResizeSlop = 3;
[super setFrameSize:newSize];
// reposition sheet if the parent window resizes or moves
var theWindow = [self window];
var theWindow = [self window],
sheet = [theWindow attachedSheet];
if ([theWindow attachedSheet])
if (sheet)
{
[theWindow _setAttachedSheetFrameOrigin];
[sheet._windowView _adjustShadowViewSize];
}
else if (theWindow && theWindow._isSheet)
[self _adjustShadowViewSize];
}
- (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator
@@ -678,7 +744,7 @@ _CPWindowViewResizeSlop = 3;
- (void)setResizeIndicatorOffset:(CGSize)anOffset
{
if (_CGSizeEqualToSize(_resizeIndicatorOffset, anOffset))
if (CGSizeEqualToSize(_resizeIndicatorOffset, anOffset))
return;
_resizeIndicatorOffset = anOffset;
@@ -689,7 +755,7 @@ _CPWindowViewResizeSlop = 3;
var size = [_resizeIndicator frame].size,
boundsSize = [self frame].size;
[_resizeIndicator setFrameOrigin:_CGPointMake(boundsSize.width - size.width - anOffset.width, boundsSize.height - size.height - anOffset.height)];
[_resizeIndicator setFrameOrigin:CGPointMake(boundsSize.width - size.width - anOffset.width, boundsSize.height - size.height - anOffset.height)];
}
- (CGSize)resizeIndicatorOffset
@@ -707,7 +773,9 @@ _CPWindowViewResizeSlop = 3;
- (BOOL)showsToolbar
{
return YES;
var styleMaskWindow = [[self window] styleMask];
return styleMaskWindow & CPBorderlessWindowMask || styleMaskWindow & CPTitledWindowMask || styleMaskWindow & CPHUDBackgroundWindowMask || styleMaskWindow & CPBorderlessBridgeWindowMask;
}
- (CGSize)toolbarOffset
@@ -725,7 +793,7 @@ _CPWindowViewResizeSlop = 3;
if (!_toolbarView || [_toolbarView isHidden])
return [self toolbarOffset].height;
return _CGRectGetMaxY([_toolbarView frame]);
return CGRectGetMaxY([_toolbarView frame]);
}
- (_CPToolbarView)toolbarView
@@ -737,14 +805,14 @@ _CPWindowViewResizeSlop = 3;
{
var theWindow = [self window],
bounds = [self bounds],
width = _CGRectGetWidth(bounds);
width = CGRectGetWidth(bounds);
if ([[theWindow toolbar] isVisible])
{
var toolbarView = [self toolbarView],
toolbarOffset = [self toolbarOffset];
[toolbarView setFrame:_CGRectMake(toolbarOffset.width, toolbarOffset.height, width, _CGRectGetHeight([toolbarView frame]))];
[toolbarView setFrame:CGRectMake(toolbarOffset.width, toolbarOffset.height, width, CGRectGetHeight([toolbarView frame]))];
}
if ([self showsResizeIndicator])
@@ -752,7 +820,7 @@ _CPWindowViewResizeSlop = 3;
var size = [_resizeIndicator frame].size,
boundsSize = [self bounds].size;
[_resizeIndicator setFrameOrigin:_CGPointMake(boundsSize.width - size.width - _resizeIndicatorOffset.width, boundsSize.height - size.height - _resizeIndicatorOffset.height)];
[_resizeIndicator setFrameOrigin:CGPointMake(boundsSize.width - size.width - _resizeIndicatorOffset.width, boundsSize.height - size.height - _resizeIndicatorOffset.height)];
}
}
@@ -829,22 +897,36 @@ _CPWindowViewResizeSlop = 3;
[self addSubview:_resizeIndicator];
}
- (void)_enableSheet:(BOOL)enable
- (void)_enableSheet:(BOOL)enable inWindow:(CPWindow)parentWindow
{
if (enable)
{
_sheetShadowView = [[CPView alloc] initWithFrame:_CGRectMake(0, 0, _CGRectGetWidth([self bounds]), 8)];
// Clip the shadow view width to the parent's content view
var myWidth = [self bounds].size.width,
shadowWidth = [self _shadowViewWidthForParentWindow:parentWindow],
shadowHeight = [self currentValueForThemeAttribute:@"shadow-height"];
_sheetShadowView = [[CPView alloc] initWithFrame:CGRectMake(FLOOR((myWidth - shadowWidth) / 2), 0, shadowWidth, shadowHeight)];
[_sheetShadowView setAutoresizingMask:CPViewWidthSizable];
[self addSubview:_sheetShadowView];
}
else
{
[_sheetShadowView removeFromSuperview];
_sheetShadowView = nil;
}
[self setNeedsLayout];
}
- (CGRect)_shadowViewWidthForParentWindow:(CPWindow)parentWindow
{
var myWidth = [self bounds].size.width,
parentWidth = [[parentWindow contentView] bounds].size.width;
return MIN(myWidth, parentWidth);
}
- (void)layoutSubviews
{
[super layoutSubviews];
@@ -861,9 +943,29 @@ _CPWindowViewResizeSlop = 3;
}
}
- (void)_adjustShadowViewSize
{
if (!_sheetShadowView)
return;
var myWidth = [self frame].size.width,
shadowFrame = [_sheetShadowView frame],
shadowWidth = [self _shadowViewWidthForParentWindow:_window._parentView];
shadowFrame.origin.x = FLOOR((myWidth - shadowWidth) / 2);
shadowFrame.size.width = shadowWidth;
[_sheetShadowView setFrame:shadowFrame];
}
- (CGSize)_minimumResizeSize
{
return _CGSizeMake(0, _CPWindowViewMinContentHeight);
// Leave at least 4px so there is something visible.
return CGSizeMake(4, _CPWindowViewMinContentHeight);
}
- (int)bodyOffset
{
return [self frame].origin.y;
}
@end
+8 -1
View File
@@ -165,7 +165,14 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
- (BOOL)instantiateCibWithOwner:(id)anOwner topLevelObjects:(CPArray)topLevelObjects
{
return [self instantiateCibWithExternalNameTable:@{ CPCibOwner: anOwner, CPCibTopLevelObjects: topLevelObjects }];
// anOwner can be nil, and we can't store nil in a dictionary. If we leave it out,
// anyone who asks for CPCibOwner will get nil back.
var nameTable = @{ CPCibTopLevelObjects: topLevelObjects };
if (anOwner)
[nameTable setObject:anOwner forKey:CPCibOwner];
return [self instantiateCibWithExternalNameTable:nameTable];
}
@end
+5 -5
View File
@@ -63,8 +63,8 @@ var CPCibOwner = @"CPCibOwner";
+ (CPCib)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable loadDelegate:aDelegate
{
return ([[CPCib alloc]
initWithContentsOfURL:anAbsolutePath
loadDelegate:[[_CPCibLoadDelegate alloc]
initWithContentsOfURL:anAbsolutePath
loadDelegate:[[_CPCibLoadDelegate alloc]
initWithLoadDelegate:aDelegate
externalNameTable:aNameTable]]);
}
@@ -84,9 +84,9 @@ var CPCibOwner = @"CPCibOwner";
- (CPCib)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable loadDelegate:(id)aDelegate
{
return ([[CPCib alloc]
initWithCibNamed:aFileName
bundle:self
loadDelegate:[[_CPCibLoadDelegate alloc]
initWithCibNamed:aFileName
bundle:self
loadDelegate:[[_CPCibLoadDelegate alloc]
initWithLoadDelegate:aDelegate
externalNameTable:aNameTable]]);
}
+83 -29
View File
@@ -31,19 +31,33 @@
@import "CPTheme.j"
@class CPButtonBar
@class CPView
var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
_CPCibCustomResourceResourceNameKey = @"_CPCibCustomResourceResourceNameKey",
_CPCibCustomResourcePropertiesKey = @"_CPCibCustomResourcePropertiesKey";
_CPCibCustomResourcePropertiesKey = @"_CPCibCustomResourcePropertiesKey",
_CPCibCustomResourceTemplateImageMap = nil;
@implementation _CPCibCustomResource : CPObject
{
CPString _className;
CPString _resourceName;
CPDictionary _properties;
CPBundle _bundle;
}
+ (void)initialize
{
if (self !== [_CPCibCustomResource class])
return;
_CPCibCustomResourceTemplateImageMap = @{
"CPAddTemplate": "button-image-plus",
"CPRemoveTemplate": "button-image-minus"
};
}
+ (id)imageResourceWithName:(CPString)aResourceName size:(CGSize)aSize
{
return [[self alloc] initWithClassName:@"CPImage" resourceName:aResourceName properties:@{ @"size": aSize }];
@@ -63,6 +77,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
_className = aClassName;
_resourceName = aResourceName;
_properties = properties;
_bundle = nil;
}
return self;
@@ -77,6 +92,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
_className = [aCoder decodeObjectForKey:_CPCibCustomResourceClassNameKey];
_resourceName = [aCoder decodeObjectForKey:_CPCibCustomResourceResourceNameKey];
_properties = [aCoder decodeObjectForKey:_CPCibCustomResourcePropertiesKey];
_bundle = nil;
}
return self;
@@ -95,44 +111,77 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
(![aCoder respondsToSelector:@selector(awakenCustomResources)] || [aCoder awakenCustomResources]))
if (_className === @"CPImage")
{
if (_resourceName == "CPAddTemplate")
return [[CPTheme defaultTheme] valueForAttributeWithName:@"button-image-plus" forClass:[CPButtonBar class]];
else if (_resourceName == "CPRemoveTemplate")
return [[CPTheme defaultTheme] valueForAttributeWithName:@"button-image-minus" forClass:[CPButtonBar class]];
var templateImage = [_CPCibCustomResourceTemplateImageMap objectForKey:_resourceName];
return [self imageFromBundle:[aCoder bundle]];
if (templateImage)
return [[CPTheme defaultTheme] valueForAttributeWithName:templateImage forClass:[CPButtonBar class]];
else
return [self imageFromCoder:aCoder];
}
return self;
}
- (CPImage)imageFromBundle:(CPBundle)aBundle
{
if (!aBundle)
{
var bundleClass = _properties.valueForKey(@"bundleClass");
if (bundleClass)
{
bundleClass = CPClassFromString(bundleClass);
if (bundleClass)
aBundle = [CPBundle bundleForClass:bundleClass];
}
else
aBundle = [CPBundle mainBundle];
}
return [[CPImage alloc] initWithContentsOfFile:[aBundle pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
}
@end
@implementation _CPCibCustomResource (CPImage)
- (CPBundle)imageBundleWithCoder:(CPCoder)aCoder
{
if (_bundle)
return _bundle;
var bundleIdentifier = [_properties valueForKey:@"bundleIdentifier"];
if (bundleIdentifier)
_bundle = [CPBundle bundleWithIdentifier:bundleIdentifier];
else
{
var bundleClass = [_properties valueForKey:@"bundleClass"];
if (bundleClass)
{
bundleClass = CPClassFromString(bundleClass);
if (bundleClass)
_bundle = [CPBundle bundleForClass:bundleClass];
}
}
if (!_bundle)
{
var framework = [_properties valueForKey:@"framework"];
if (framework)
{
// Get AppKit and hope the framework is in the same directory
var appKit = [CPBundle bundleForClass:[CPView class]],
url = [[appKit bundleURL] URLByDeletingLastPathComponent];
url = [CPURL URLWithString:framework relativeToURL:url];
_bundle = [CPBundle bundleWithURL:url];
}
}
if (!_bundle)
{
if (aCoder)
_bundle = [aCoder bundle];
else
_bundle = [CPBundle mainBundle];
}
return _bundle;
}
- (CPImage)imageFromCoder:(CPCoder)aCoder
{
return [[CPImage alloc] initWithContentsOfFile:[[self imageBundleWithCoder:aCoder] pathForResource:_resourceName] size:[_properties valueForKey:@"size"]];
}
- (CPString)filename
{
return [[CPBundle mainBundle] pathForResource:_resourceName];
return [[self imageBundleWithCoder:nil] pathForResource:_resourceName];
}
- (CGSize)size
@@ -140,6 +189,11 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
return [_properties objectForKey:@"size"];
}
- (BOOL)isSingleImage
{
return YES;
}
- (BOOL)isThreePartImage
{
return NO;
@@ -162,7 +216,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
- (CPString)description
{
var image = [self imageFromBundle:nil];
var image = [self imageFromCoder:nil];
return [image description];
}
+1 -1
View File
@@ -48,7 +48,7 @@
@end
var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
@implementation _CPCibCustomView (CPCoding)
+13 -9
View File
@@ -87,12 +87,17 @@
- (id)_cibInstantiate
{
var windowClass = CPClassFromString([self windowClass]),
theWindow = [[windowClass alloc] initWithContentRect:_windowRect styleMask:_windowStyleMask];
var windowClass = CPClassFromString([self windowClass]);
/* if (!windowClass)
[NSException raise:NSInvalidArgumentException format:@"Unable to locate NSWindow class %@, using NSWindow",_windowClass];
class=[NSWindow class];*/
if (!windowClass)
{
#if DEBUG
CPLog.warn("Unknown class \"%@\" in cib file, using CPWindow instead.", [self windowClass]);
#endif
windowClass = [CPWindow class];
}
var theWindow = [[windowClass alloc] initWithContentRect:_windowRect styleMask:_windowStyleMask];
if (_minSize)
[theWindow setMinSize:_minSize];
@@ -103,12 +108,11 @@
//[result setHidesOnDeactivate:(_wtFlags&0x80000000)?YES:NO];
[theWindow setTitle:_windowTitle];
// FIXME: we can't autoresize yet...
var contentViewAutoresizesSubviews = [_windowView autoresizesSubviews];
[_windowView setAutoresizesSubviews:NO];
[theWindow setContentView:_windowView];
[_windowView setAutoresizesSubviews:YES];
[_windowView setAutoresizesSubviews:contentViewAutoresizesSubviews];
if ([_viewClass isKindOfClass:[CPToolbar class]])
[theWindow setToolbar:_viewClass];
+46 -42
View File
@@ -157,6 +157,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
_sublayers = [];
#if PLATFORM(DOM)
_DOMElement = document.createElement("div");
_DOMElement.style.overflow = "visible";
@@ -167,6 +168,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
_DOMElement.style.zIndex = 0;
_DOMElement.style.width = "0px";
_DOMElement.style.height = "0px";
#endif
}
return self;
@@ -184,7 +186,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
var oldOrigin = _bounds.origin;
_bounds = _CGRectMakeCopy(aBounds);
_bounds = CGRectMakeCopy(aBounds);
if (_hasSublayerTransform)
_CALayerUpdateSublayerTransformForSublayers(self);
@@ -219,7 +221,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
if (CGPointEqualToPoint(_position, aPosition))
return;
_position = _CGPointMakeCopy(aPosition);
_position = CGPointMakeCopy(aPosition);
_CALayerRecalculateGeometry(self, CALayerGeometryPositionMask);
}
@@ -252,7 +254,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
*/
- (void)setAnchorPoint:(CGPoint)anAnchorPoint
{
anAnchorPoint = _CGPointMakeCopy(anAnchorPoint);
anAnchorPoint = CGPointMakeCopy(anAnchorPoint);
anAnchorPoint.x = MIN(1.0, MAX(0.0, anAnchorPoint.x));
anAnchorPoint.y = MIN(1.0, MAX(0.0, anAnchorPoint.y));
@@ -265,7 +267,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
_CALayerUpdateSublayerTransformForSublayers(self);
if (_owningView)
_position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y);
_position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y);
_CALayerRecalculateGeometry(self, CALayerGeometryAnchorPointMask);
}
@@ -287,7 +289,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
if (CGAffineTransformEqualToTransform(_affineTransform, anAffineTransform))
return;
_affineTransform = _CGAffineTransformMakeCopy(anAffineTransform);
_affineTransform = CGAffineTransformMakeCopy(anAffineTransform);
_CALayerRecalculateGeometry(self, CALayerGeometryAffineTransformMask);
}
@@ -311,8 +313,8 @@ var CALayerRegisteredRunLoopUpdates = nil;
var hadSublayerTransform = _hasSublayerTransform;
_sublayerTransform = _CGAffineTransformMakeCopy(anAffineTransform);
_hasSublayerTransform = !_CGAffineTransformIsIdentity(_sublayerTransform);
_sublayerTransform = CGAffineTransformMakeCopy(anAffineTransform);
_hasSublayerTransform = !CGAffineTransformIsIdentity(_sublayerTransform);
if (_hasSublayerTransform)
{
@@ -400,8 +402,8 @@ var CALayerRegisteredRunLoopUpdates = nil;
var bounds = [_superlayer bounds],
frame = [_superlayer convertRect:bounds toLayer:nil];
aFrame.origin.x -= _CGRectGetMinX(frame);
aFrame.origin.y -= _CGRectGetMinY(frame);
aFrame.origin.x -= CGRectGetMinX(frame);
aFrame.origin.y -= CGRectGetMinY(frame);
}
else
aFrame = CGRectMakeCopy(aFrame);
@@ -449,7 +451,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
if (USE_BUFFER && !_contents || !_context)
return;
CGContextClearRect(_context, _CGRectMake(0.0, 0.0, _CGRectGetWidth(_backingStoreFrame), _CGRectGetHeight(_backingStoreFrame)));
CGContextClearRect(_context, CGRectMake(0.0, 0.0, CGRectGetWidth(_backingStoreFrame), CGRectGetHeight(_backingStoreFrame)));
// Recomposite
var transform;
@@ -469,8 +471,8 @@ var CALayerRegisteredRunLoopUpdates = nil;
// Copy so we don't affect the original.
transform = CGAffineTransformCreateCopy(_transformFromLayer);
transform.tx -= _CGRectGetMinX(_backingStoreFrame);
transform.ty -= _CGRectGetMinY(_backingStoreFrame);
transform.tx -= CGRectGetMinX(_backingStoreFrame);
transform.ty -= CGRectGetMinY(_backingStoreFrame);
CGContextSaveGState(_context);
@@ -479,7 +481,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
if (USE_BUFFER)
{
// CGContextDrawImage(_context, _bounds, _contents.context);
_context.drawImage(_contents.buffer, _CGRectGetMinX(_bounds), _CGRectGetMinY(_bounds));//, _CGRectGetWidth(_standardBackingStoreFrame), _CGRectGetHeight(_standardBackingStoreFrame));
_context.drawImage(_contents.buffer, CGRectGetMinX(_bounds), CGRectGetMinY(_bounds));//, CGRectGetWidth(_standardBackingStoreFrame), CGRectGetHeight(_standardBackingStoreFrame));
}
else
[self drawInContext:_context];
@@ -504,13 +506,13 @@ var CALayerRegisteredRunLoopUpdates = nil;
_DOMContentsElement.style.position = "absolute";
_DOMContentsElement.style.visibility = "visible";
_DOMContentsElement.width = ROUND(_CGRectGetWidth(_backingStoreFrame));
_DOMContentsElement.height = ROUND(_CGRectGetHeight(_backingStoreFrame));
_DOMContentsElement.width = ROUND(CGRectGetWidth(_backingStoreFrame));
_DOMContentsElement.height = ROUND(CGRectGetHeight(_backingStoreFrame));
_DOMContentsElement.style.top = "0px";
_DOMContentsElement.style.left = "0px";
_DOMContentsElement.style.width = ROUND(_CGRectGetWidth(_backingStoreFrame)) + "px";
_DOMContentsElement.style.height = ROUND(_CGRectGetHeight(_backingStoreFrame)) + "px";
_DOMContentsElement.style.width = ROUND(CGRectGetWidth(_backingStoreFrame)) + "px";
_DOMContentsElement.style.height = ROUND(CGRectGetHeight(_backingStoreFrame)) + "px";
_DOMElement.appendChild(_DOMContentsElement);
}
@@ -520,7 +522,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
if (_delegateRespondsToDisplayLayerSelector)
return [_delegate displayInLayer:self];
if (_CGRectGetWidth(_backingStoreFrame) == 0.0 || _CGRectGetHeight(_backingStoreFrame) == 0.0)
if (CGRectGetWidth(_backingStoreFrame) == 0.0 || CGRectGetHeight(_backingStoreFrame) == 0.0)
return;
if (!_contents)
@@ -685,7 +687,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
@param aLayer the layer to insert
@param anIndex the index to insert the layer at
*/
- (void)insertSublayer:(CALayer)aLayer atIndex:(unsigned)anIndex
- (void)insertSublayer:(CALayer)aLayer atIndex:(CPUInteger)anIndex
{
if (!aLayer)
return;
@@ -711,10 +713,12 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
[_sublayers insertObject:aLayer atIndex:anIndex];
#if PLATFORM(DOM)
if (anIndex >= _sublayers.length - 1)
_DOMElement.appendChild(DOM(aLayer));
else
_DOMElement.insertBefore(DOM(aLayer), _sublayers[anIndex + 1]._DOMElement);
#endif
aLayer._superlayer = self;
@@ -913,7 +917,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
*/
- (BOOL)containsPoint:(CGPoint)aPoint
{
return _CGRectContainsPoint(_bounds, aPoint);
return CGRectContainsPoint(_bounds, aPoint);
}
/*!
@@ -928,7 +932,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
var point = CGPointApplyAffineTransform(aPoint, _transformToLayer);
if (!_CGRectContainsPoint(_bounds, point))
if (!CGRectContainsPoint(_bounds, point))
return nil;
var layer = nil,
@@ -979,7 +983,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
_owningView = anOwningView;
_bounds.size = CGSizeMakeCopy([_owningView bounds].size);
_position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y);
_position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y);
}
_CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask);
@@ -989,7 +993,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
- (void)_owningViewBoundsChanged
{
_bounds.size = CGSizeMakeCopy([_owningView bounds].size);
_position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y);
_position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y);
_CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask);
}
@@ -1021,8 +1025,8 @@ function _CALayerUpdateSublayerTransformForSublayers(aLayer)
{
var bounds = aLayer._bounds,
anchorPoint = aLayer._anchorPoint,
translateX = _CGRectGetWidth(bounds) * anchorPoint.x,
translateY = _CGRectGetHeight(bounds) * anchorPoint.y;
translateX = CGRectGetWidth(bounds) * anchorPoint.x,
translateY = CGRectGetHeight(bounds) * anchorPoint.y;
aLayer._sublayerTransformForSublayers = CGAffineTransformConcat(
CGAffineTransformMakeTranslation(-translateX, -translateY),
@@ -1041,14 +1045,14 @@ function _CALayerUpdateDOM(aLayer, aMask)
if (aMask & CALayerFrameOriginUpdateMask)
{
DOMElementStyle.top = ROUND(_CGRectGetMinY(frame)) + "px";
DOMElementStyle.left = ROUND(_CGRectGetMinX(frame)) + "px";
DOMElementStyle.top = ROUND(CGRectGetMinY(frame)) + "px";
DOMElementStyle.left = ROUND(CGRectGetMinX(frame)) + "px";
}
if (aMask & CALayerFrameSizeUpdateMask)
{
var width = MAX(0.0, ROUND(_CGRectGetWidth(frame))),
height = MAX(0.0, ROUND(_CGRectGetHeight(frame))),
var width = MAX(0.0, ROUND(CGRectGetWidth(frame))),
height = MAX(0.0, ROUND(CGRectGetHeight(frame))),
DOMContentsElement = aLayer._DOMContentsElement;
DOMElementStyle.width = width + "px";
@@ -1068,24 +1072,24 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
{
var bounds = aLayer._bounds,
superlayer = aLayer._superlayer,
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds),
width = CGRectGetWidth(bounds),
height = CGRectGetHeight(bounds),
position = aLayer._position,
anchorPoint = aLayer._anchorPoint,
affineTransform = aLayer._affineTransform,
backingStoreFrameSize = _CGSizeMakeCopy(aLayer._backingStoreFrame),
backingStoreFrameSize = CGSizeMakeCopy(aLayer._backingStoreFrame),
hasCustomBackingStoreFrame = aLayer._hasCustomBackingStoreFrame;
// Go to anchor, transform, go back to bounds.
aLayer._transformFromLayer = CGAffineTransformConcat(
CGAffineTransformMakeTranslation(-width * anchorPoint.x - _CGRectGetMinX(aLayer._bounds), -height * anchorPoint.y - _CGRectGetMinY(aLayer._bounds)),
CGAffineTransformMakeTranslation(-width * anchorPoint.x - CGRectGetMinX(aLayer._bounds), -height * anchorPoint.y - CGRectGetMinY(aLayer._bounds)),
CGAffineTransformConcat(affineTransform,
CGAffineTransformMakeTranslation(position.x, position.y)));
if (superlayer && superlayer._hasSublayerTransform)
{
// aLayer._transformFromLayer = CGAffineTransformConcat(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers);
_CGAffineTransformConcatTo(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers, aLayer._transformFromLayer);
CGAffineTransformConcatTo(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers, aLayer._transformFromLayer);
}
aLayer._transformToLayer = CGAffineTransformInvert(aLayer._transformFromLayer);
@@ -1101,8 +1105,8 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
var bounds = [superlayer bounds],
frame = [superlayer convertRect:bounds toLayer:nil];
aLayer._standardBackingStoreFrame.origin.x -= _CGRectGetMinX(frame);
aLayer._standardBackingStoreFrame.origin.y -= _CGRectGetMinY(frame);
aLayer._standardBackingStoreFrame.origin.x -= CGRectGetMinX(frame);
aLayer._standardBackingStoreFrame.origin.y -= CGRectGetMinY(frame);
}
// We used to use CGRectIntegral here, but what we actually want, is the largest integral
@@ -1128,13 +1132,13 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
// These values get rounded in the DOM, so don't both updating them if they're
// not going to be different after rounding.
if (ROUND(_CGRectGetMinX(backingStoreFrame)) != ROUND(_CGRectGetMinX(aLayer._backingStoreFrame)) ||
ROUND(_CGRectGetMinY(backingStoreFrame)) != ROUND(_CGRectGetMinY(aLayer._backingStoreFrame)))
if (ROUND(CGRectGetMinX(backingStoreFrame)) != ROUND(CGRectGetMinX(aLayer._backingStoreFrame)) ||
ROUND(CGRectGetMinY(backingStoreFrame)) != ROUND(CGRectGetMinY(aLayer._backingStoreFrame)))
[aLayer registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask];
// Any change in size due to a geometry change is purely due to rounding error.
if ((_CGRectGetWidth(backingStoreFrame) != ROUND(_CGRectGetWidth(aLayer._backingStoreFrame)) ||
_CGRectGetHeight(backingStoreFrame) != ROUND(_CGRectGetHeight(aLayer._backingStoreFrame))))
if ((CGRectGetWidth(backingStoreFrame) != ROUND(CGRectGetWidth(aLayer._backingStoreFrame)) ||
CGRectGetHeight(backingStoreFrame) != ROUND(CGRectGetHeight(aLayer._backingStoreFrame))))
[aLayer registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask];
aLayer._backingStoreFrame = backingStoreFrame;
@@ -1172,7 +1176,7 @@ function _CALayerGetTransform(fromLayer, toLayer)
var transformFromLayer = layer._transformFromLayer;
//transform = CGAffineTransformConcat(transform, layer._transformFromLayer);
_CGAffineTransformConcatTo(transform, transformFromLayer, transform);
CGAffineTransformConcatTo(transform, transformFromLayer, transform);
layer = layer._superlayer;
}
@@ -1197,7 +1201,7 @@ function _CALayerGetTransform(fromLayer, toLayer)
{
var transformToLayer = layers[index]._transformToLayer;
_CGAffineTransformConcatTo(transform, transformToLayer, transform);
CGAffineTransformConcatTo(transform, transformToLayer, transform);
}
return transform;
+1 -1
View File
@@ -75,7 +75,7 @@ var CAMediaNamedTimingFunctions = nil;
return self;
}
- (void)getControlPointAtIndex:(unsigned)anIndex values:(float/*[2]*/)reference
- (void)getControlPointAtIndex:(CPUInteger)anIndex values:(float/*[2]*/)reference
{
if (anIndex == 0)
{

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